Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: invalidate new worker and its dependencies (fix #1873) #1896

Merged
merged 4 commits into from Aug 23, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
18 changes: 18 additions & 0 deletions packages/vite-node/src/client.ts
Expand Up @@ -91,6 +91,24 @@ export class ModuleCacheMap extends Map<string, ModuleCache> {
}
return invalidated
}

/**
* Invalidate dependency modules of the given modules, down to the bottom-level dependencies
*/
invalidateSubDepTree(ids: string[] | Set<string>, invalidated = new Set<string>()) {
for (const _id of ids) {
const id = this.normalizePath(_id)
if (invalidated.has(id))
continue
invalidated.add(id)
const subIds = Array.from(super.entries())
.filter(([,mod]) => mod.importers?.has(id))
.map(([key]) => key)
subIds.length && this.invalidateSubDepTree(subIds, invalidated)
super.delete(id)
}
return invalidated
}
}

export class ViteNodeRunner {
Expand Down
11 changes: 2 additions & 9 deletions packages/web-worker/src/pure.ts
Expand Up @@ -44,7 +44,6 @@ interface InlineWorkerContext {
postMessage: (data: any) => void
self: InlineWorkerContext
global: InlineWorkerContext
invalidates: string[]
importScripts?: any
}

Expand Down Expand Up @@ -95,7 +94,6 @@ export function defineWebWorker() {
public onerror: null | Procedure = null

constructor(url: URL | string) {
const invalidates: string[] = []
const context: InlineWorkerContext = {
onmessage: null,
dispatchEvent: (event: Event) => {
Expand All @@ -113,7 +111,6 @@ export function defineWebWorker() {
get global() {
return context
},
invalidates,
}

this.inside.on('message', (e) => {
Expand All @@ -129,15 +126,11 @@ export function defineWebWorker() {
const id = (url instanceof URL ? url.toString() : url).replace(/^file:\/+/, '/')

const fsPath = toFilePath(id, config.root)
invalidates.push(fsPath)

runner.executeFile(fsPath)
.then(() => {
invalidates.forEach((fsPath) => {
// worker should be new every time
moduleCache.delete(fsPath)
moduleCache.delete(`mock:${fsPath}`)
})
// worker should be new every time, invalidate its sub dependency
sheremet-va marked this conversation as resolved.
Show resolved Hide resolved
moduleCache.invalidateSubDepTree([fsPath, `mock:${fsPath}`])
const q = this.messageQueue
this.messageQueue = null
if (q)
Expand Down
3 changes: 3 additions & 0 deletions test/web-worker/src/selfWorker.ts
@@ -0,0 +1,3 @@
import subSelf from './selfWorkerDep'

self.postMessage(subSelf === self)
1 change: 1 addition & 0 deletions test/web-worker/src/selfWorkerDep.ts
@@ -0,0 +1 @@
export default self
24 changes: 24 additions & 0 deletions test/web-worker/test/init.test.ts
Expand Up @@ -2,6 +2,9 @@ import { expect, it } from 'vitest'

import MyWorker from '../src/worker?worker'
import MyEventListenerWorker from '../src/eventListenerWorker?worker'
import MySelfWorker from '../src/selfWorker?worker'

const sleep = (time: number) => new Promise(resolve => setTimeout(resolve, time))

const testWorker = (worker: Worker) => {
return new Promise<void>((resolve) => {
Expand All @@ -14,6 +17,14 @@ const testWorker = (worker: Worker) => {
})
}

const testSelfWorker = (worker: Worker) => {
return new Promise<boolean>((resolve) => {
worker.onmessage = (e) => {
resolve(e.data)
}
})
}

it('worker exists', async () => {
expect(Worker).toBeDefined()
})
Expand Down Expand Up @@ -42,3 +53,16 @@ it('worker with url', async () => {

await testWorker(new Worker(new URL('../src/worker.ts', url)))
})

it('self injected into worker and its deps should be equal', async () => {
expect.assertions(4)
expect(await testSelfWorker(new MySelfWorker())).toBeTruthy()
// wait for clear worker mod cache
await sleep(500)
expect(await testSelfWorker(new MySelfWorker())).toBeTruthy()

expect(await testSelfWorker(new Worker(new URL('../src/selfWorker.ts', import.meta.url)))).toBeTruthy()
// wait for clear worker mod cache
await sleep(500)
expect(await testSelfWorker(new Worker(new URL('../src/selfWorker.ts', import.meta.url)))).toBeTruthy()
})