diff --git a/packages/vite-node/src/client.ts b/packages/vite-node/src/client.ts index 822dc189ac84..2425c34e9791 100644 --- a/packages/vite-node/src/client.ts +++ b/packages/vite-node/src/client.ts @@ -91,6 +91,24 @@ export class ModuleCacheMap extends Map { } return invalidated } + + /** + * Invalidate dependency modules of the given modules, down to the bottom-level dependencies + */ + invalidateSubDepTree(ids: string[] | Set, invalidated = new Set()) { + 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 { diff --git a/packages/web-worker/src/pure.ts b/packages/web-worker/src/pure.ts index 6eaecf38ce7f..da2c6d591ffc 100644 --- a/packages/web-worker/src/pure.ts +++ b/packages/web-worker/src/pure.ts @@ -44,7 +44,6 @@ interface InlineWorkerContext { postMessage: (data: any) => void self: InlineWorkerContext global: InlineWorkerContext - invalidates: string[] importScripts?: any } @@ -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) => { @@ -113,7 +111,6 @@ export function defineWebWorker() { get global() { return context }, - invalidates, } this.inside.on('message', (e) => { @@ -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 + moduleCache.invalidateSubDepTree([fsPath, `mock:${fsPath}`]) const q = this.messageQueue this.messageQueue = null if (q) diff --git a/test/web-worker/src/selfWorker.ts b/test/web-worker/src/selfWorker.ts new file mode 100644 index 000000000000..229e8b38aeeb --- /dev/null +++ b/test/web-worker/src/selfWorker.ts @@ -0,0 +1,3 @@ +import subSelf from './selfWorkerDep' + +self.postMessage(subSelf === self) diff --git a/test/web-worker/src/selfWorkerDep.ts b/test/web-worker/src/selfWorkerDep.ts new file mode 100644 index 000000000000..df83f106c0c7 --- /dev/null +++ b/test/web-worker/src/selfWorkerDep.ts @@ -0,0 +1 @@ +export default self diff --git a/test/web-worker/test/init.test.ts b/test/web-worker/test/init.test.ts index d58f7872674a..a22872f0c9c7 100644 --- a/test/web-worker/test/init.test.ts +++ b/test/web-worker/test/init.test.ts @@ -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((resolve) => { @@ -14,6 +17,14 @@ const testWorker = (worker: Worker) => { }) } +const testSelfWorker = (worker: Worker) => { + return new Promise((resolve) => { + worker.onmessage = (e) => { + resolve(e.data) + } + }) +} + it('worker exists', async () => { expect(Worker).toBeDefined() }) @@ -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() +})