Skip to content

Commit 2687dbb

Browse files
authored
fix(worker): prevent inject esm in classic workers (#14918)
1 parent e49ef02 commit 2687dbb

File tree

10 files changed

+80
-11
lines changed

10 files changed

+80
-11
lines changed

.prettierignore

-1
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,4 @@ pnpm-workspace.yaml
88
playground/tsconfig-json-load-error/has-error/tsconfig.json
99
playground/html/invalid.html
1010
playground/html/valid.html
11-
playground/worker/classic-worker.js
1211
playground/external/public/[email protected]

packages/vite/src/client/client.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -642,7 +642,7 @@ export function injectQuery(url: string, queryToInject: string): string {
642642
}
643643

644644
// can't use pathname from URL since it may be relative like ../
645-
const pathname = url.replace(/#.*$/, '').replace(/\?.*$/, '')
645+
const pathname = url.replace(/[?#].*$/s, '')
646646
const { search, hash } = new URL(url, 'http://vitejs.dev')
647647

648648
return `${pathname}?${queryToInject}${search ? `&` + search.slice(1) : ''}${

packages/vite/src/node/plugins/importAnalysis.ts

+31-5
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ import { throwOutdatedRequest } from './optimizedDeps'
5959
import { isCSSRequest, isDirectCSSRequest } from './css'
6060
import { browserExternalId } from './resolve'
6161
import { serializeDefine } from './define'
62+
import { WORKER_FILE_ID } from './worker'
6263

6364
const debug = createDebugger('vite:import-analysis')
6465

@@ -685,12 +686,17 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin {
685686
const acceptedUrls = mergeAcceptedUrls(orderedAcceptedUrls)
686687
const acceptedExports = mergeAcceptedUrls(orderedAcceptedExports)
687688

688-
if (hasEnv) {
689+
// While we always expect to work with ESM, a classic worker is the only
690+
// case where it's not ESM and we need to avoid injecting ESM-specific code
691+
const isClassicWorker =
692+
importer.includes(WORKER_FILE_ID) && importer.includes('type=classic')
693+
694+
if (hasEnv && !isClassicWorker) {
689695
// inject import.meta.env
690696
str().prepend(getEnv(ssr))
691697
}
692698

693-
if (hasHMR && !ssr) {
699+
if (hasHMR && !ssr && !isClassicWorker) {
694700
debugHmr?.(
695701
`${
696702
isSelfAccepting
@@ -712,9 +718,13 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin {
712718
}
713719

714720
if (needQueryInjectHelper) {
715-
str().prepend(
716-
`import { injectQuery as __vite__injectQuery } from "${clientPublicPath}";`,
717-
)
721+
if (isClassicWorker) {
722+
str().append('\n' + __vite__injectQuery.toString())
723+
} else {
724+
str().prepend(
725+
`import { injectQuery as __vite__injectQuery } from "${clientPublicPath}";`,
726+
)
727+
}
718728
}
719729

720730
// normalize and rewrite accepted urls
@@ -1009,3 +1019,19 @@ export function transformCjsImport(
10091019
return lines.join('; ')
10101020
}
10111021
}
1022+
1023+
// Copied from `client/client.ts`. Only needed so we can inline inject this function for classic workers.
1024+
function __vite__injectQuery(url: string, queryToInject: string): string {
1025+
// skip urls that won't be handled by vite
1026+
if (url[0] !== '.' && url[0] !== '/') {
1027+
return url
1028+
}
1029+
1030+
// can't use pathname from URL since it may be relative like ../
1031+
const pathname = url.replace(/[?#].*$/s, '')
1032+
const { search, hash } = new URL(url, 'http://vitejs.dev')
1033+
1034+
return `${pathname}?${queryToInject}${search ? `&` + search.slice(1) : ''}${
1035+
hash || ''
1036+
}`
1037+
}

playground/worker/__tests__/es/es-worker.spec.ts

+4
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,10 @@ test('classic worker', async () => {
173173
'A classic',
174174
true,
175175
)
176+
await untilUpdated(
177+
() => page.textContent('.classic-worker-import'),
178+
'[success] classic-esm',
179+
)
176180
await untilUpdated(
177181
() => page.textContent('.classic-shared-worker'),
178182
'A classic',

playground/worker/__tests__/iife/iife-worker.spec.ts

+4
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,10 @@ test('module worker', async () => {
136136

137137
test('classic worker', async () => {
138138
await untilUpdated(() => page.textContent('.classic-worker'), 'A classic')
139+
await untilUpdated(
140+
() => page.textContent('.classic-worker-import'),
141+
'[success] classic-esm',
142+
)
139143
await untilUpdated(
140144
() => page.textContent('.classic-shared-worker'),
141145
'A classic',

playground/worker/__tests__/relative-base/relative-base-worker.spec.ts

+4
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,10 @@ test.runIf(isBuild)('classic worker', async () => {
122122
'A classic',
123123
true,
124124
)
125+
await untilUpdated(
126+
() => page.textContent('.classic-worker-import'),
127+
'[success] classic-esm',
128+
)
125129
await untilUpdated(
126130
() => page.textContent('.classic-shared-worker'),
127131
'A classic',

playground/worker/classic-esm.js

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export const msg = '[success] classic-esm'

playground/worker/classic-worker.js

+23-3
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,29 @@ if (base.endsWith('.js') || base === `/worker-entries`) base = '' // for dev
33

44
importScripts(`${base}/classic.js`)
55

6-
self.addEventListener('message', () => {
7-
self.postMessage(self.constant)
6+
self.addEventListener('message', async (e) => {
7+
switch (e.data) {
8+
case 'ping': {
9+
self.postMessage({
10+
message: e.data,
11+
result: self.constant,
12+
})
13+
break
14+
}
15+
case 'test-import': {
16+
// Vite may inject imports to handle this dynamic import, make sure
17+
// it still works in classic workers.
18+
// NOTE: this test only works in dev.
19+
const importPath = `${base}/classic-esm.js`
20+
const { msg } = await import(/* @vite-ignore */ importPath)
21+
self.postMessage({
22+
message: e.data,
23+
result: msg,
24+
})
25+
break
26+
}
27+
}
828
})
929

1030
// for sourcemap
11-
console.log("classic-worker.js")
31+
console.log('classic-worker.js')

playground/worker/index.html

+1
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ <h2 class="format-iife">format iife:</h2>
125125
<span class="classname">.classic-worker</span>
126126
</p>
127127
<code class="classic-worker"></code>
128+
<code class="classic-worker-import"></code>
128129

129130
<p>
130131
new SharedWorker(new URL('./classic-shared-worker.js', import.meta.url), {

playground/worker/worker/main-classic.js

+11-1
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,19 @@ let classicWorker = new Worker(
1212
classicWorker = new Worker(new URL('../classic-worker.js', import.meta.url))
1313

1414
classicWorker.addEventListener('message', ({ data }) => {
15-
text('.classic-worker', JSON.stringify(data))
15+
switch (data.message) {
16+
case 'ping': {
17+
text('.classic-worker', data.result)
18+
break
19+
}
20+
case 'test-import': {
21+
text('.classic-worker-import', data.result)
22+
break
23+
}
24+
}
1625
})
1726
classicWorker.postMessage('ping')
27+
classicWorker.postMessage('test-import')
1828

1929
// prettier-ignore
2030
// test trailing comma

0 commit comments

Comments
 (0)