From ea2d429b203ba313718a04416524f1dafba9d954 Mon Sep 17 00:00:00 2001 From: Hiroshi Ogawa Date: Wed, 25 Sep 2024 17:24:02 +0900 Subject: [PATCH] fix(browser): fix dynamic import inside worker (#6569) --- packages/browser/src/node/plugin.ts | 14 ++++++++++++++ test/browser/fixtures/worker/src/basic.test.ts | 11 +++++++++++ .../fixtures/worker/src/worker-dynamic-dep.ts | 1 + test/browser/fixtures/worker/src/worker.ts | 4 ++++ test/browser/fixtures/worker/vitest.config.ts | 17 +++++++++++++++++ test/browser/specs/worker.test.ts | 13 +++++++++++++ 6 files changed, 60 insertions(+) create mode 100644 test/browser/fixtures/worker/src/basic.test.ts create mode 100644 test/browser/fixtures/worker/src/worker-dynamic-dep.ts create mode 100644 test/browser/fixtures/worker/src/worker.ts create mode 100644 test/browser/fixtures/worker/vitest.config.ts create mode 100644 test/browser/specs/worker.test.ts diff --git a/packages/browser/src/node/plugin.ts b/packages/browser/src/node/plugin.ts index 218d60269ae3..fafa27c51a69 100644 --- a/packages/browser/src/node/plugin.ts +++ b/packages/browser/src/node/plugin.ts @@ -368,6 +368,20 @@ export default (browserServer: BrowserServer, base = '/'): Plugin[] => { } }, }, + { + name: 'vitest:browser:worker', + transform(code, id, _options) { + // https://github.com/vitejs/vite/blob/ba56cf43b5480f8519349f7d7fe60718e9af5f1a/packages/vite/src/node/plugins/worker.ts#L46 + if (/(?:\?|&)worker_file&type=\w+(?:&|$)/.test(id)) { + const s = new MagicString(code) + s.prepend('globalThis.__vitest_browser_runner__ = { wrapDynamicImport: f => f() };\n') + return { + code: s.toString(), + map: s.generateMap({ hires: 'boundary' }), + } + } + }, + }, // TODO: remove this when @testing-library/vue supports ESM { name: 'vitest:browser:support-testing-library', diff --git a/test/browser/fixtures/worker/src/basic.test.ts b/test/browser/fixtures/worker/src/basic.test.ts new file mode 100644 index 000000000000..b2976af9420a --- /dev/null +++ b/test/browser/fixtures/worker/src/basic.test.ts @@ -0,0 +1,11 @@ +import { expect, test } from 'vitest' + +test('worker dynamic dep', async () => { + const worker = new Worker(new URL('./worker', import.meta.url), { type: 'module' }); + const data = await new Promise((resolve, reject) => { + worker.addEventListener("message", (e) => resolve(e.data)) + worker.addEventListener("messageerror", (e) => reject(e)) + worker.postMessage("ping"); + }); + expect(data).toMatchInlineSnapshot(`"worker-dynamic-dep-ok"`); +}) diff --git a/test/browser/fixtures/worker/src/worker-dynamic-dep.ts b/test/browser/fixtures/worker/src/worker-dynamic-dep.ts new file mode 100644 index 000000000000..1be160e7b5ca --- /dev/null +++ b/test/browser/fixtures/worker/src/worker-dynamic-dep.ts @@ -0,0 +1 @@ +export default "worker-dynamic-dep-ok" diff --git a/test/browser/fixtures/worker/src/worker.ts b/test/browser/fixtures/worker/src/worker.ts new file mode 100644 index 000000000000..3d61435eafb2 --- /dev/null +++ b/test/browser/fixtures/worker/src/worker.ts @@ -0,0 +1,4 @@ +self.onmessage = async () => { + const mod = await import("./worker-dynamic-dep"); + self.postMessage(mod.default); +} diff --git a/test/browser/fixtures/worker/vitest.config.ts b/test/browser/fixtures/worker/vitest.config.ts new file mode 100644 index 000000000000..c3fe79b6ac9c --- /dev/null +++ b/test/browser/fixtures/worker/vitest.config.ts @@ -0,0 +1,17 @@ +import { fileURLToPath } from 'node:url' +import { defineConfig } from 'vitest/config' + +const provider = process.env.PROVIDER || 'playwright' +const name = + process.env.BROWSER || (provider === 'playwright' ? 'chromium' : 'chrome') + +export default defineConfig({ + cacheDir: fileURLToPath(new URL("./node_modules/.vite", import.meta.url)), + test: { + browser: { + enabled: true, + provider, + name, + }, + }, +}) diff --git a/test/browser/specs/worker.test.ts b/test/browser/specs/worker.test.ts new file mode 100644 index 000000000000..060c4dc4ef83 --- /dev/null +++ b/test/browser/specs/worker.test.ts @@ -0,0 +1,13 @@ +import { expect, test } from 'vitest' +import { runBrowserTests } from './utils' + +test('worker', async () => { + const { ctx } = await runBrowserTests({ + root: './fixtures/worker', + }) + expect(Object.fromEntries(ctx.state.getFiles().map(f => [f.name, f.result.state]))).toMatchInlineSnapshot(` + { + "src/basic.test.ts": "pass", + } + `) +})