Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions packages/vite-dev-server/rolldown.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,7 @@ const webWorkerBuilderConfig = defineConfig({
createEagerWorkerTransformerImportsPlugin(),
createHostViteHelperIsolationPlugin(),
createBuilderGlobalsGuardPlugin(),
createPreloadHelperGuardPlugin(),
...createTransformerPlugins({
copyAssets: false,
guardAggregate: 'node/web-worker-builder.js',
Expand Down Expand Up @@ -582,6 +583,8 @@ function createEagerWorkerTransformerImportsPlugin(): Plugin {
'./asset',
'./clientInjections',
'./define',
'./modulePreloadPolyfill',
'./assetImportMetaUrl',
'./forwardConsole',
]],
// buildEnvironment() loads rolldown lazily, while the static graph imports it as well
Expand Down Expand Up @@ -738,6 +741,54 @@ function createBuilderGlobalsGuardPlugin(): Plugin {
}
}

function createPreloadHelperGuardPlugin(): Plugin {
// `getPreloadCode()` of the build inlines `preload()` into the output with `toString()`, with the
// helper that it calls. The host build of an app may minify the builder, which renames the helper,
// also where `preload()` calls it. So the preload code must declare the helper under its runtime
// name (`.name`), and `preload()` must not call other functions of the bundle.
return {
name: 'guard-preload-helper',
generateBundle(_options, bundle) {
const entry = Object.values(bundle).find(
output => output.type === 'chunk' && output.fileName === 'node/web-worker-builder.js'
)
if (!entry || entry.type !== 'chunk') {
this.error('[guard-preload-helper] Could not find node/web-worker-builder.js entry')
}
const { code } = entry
const helper = /const seen = \{\};const \$\{(\w+)\.name\} = \$\{\1\.toString\(\)\};/.exec(code)?.[1]
if (!helper) {
this.error('[guard-preload-helper] The preload code must declare isCssPreloadUrl under its runtime name')
}
const preload = /const preloadMethodCode = (\w+)\.toString\(\)/.exec(code)?.[1]
const start = preload ? code.indexOf(`\nfunction ${preload}(`) : -1
const end = start < 0 ? -1 : code.indexOf('\n}\n', start)
if (start < 0 || end < 0) {
this.error('[guard-preload-helper] Could not find preload()')
}
const source = code.slice(start, end)
const calls = new Set(
Array.from(source.matchAll(/(?<![\w$.])([A-Za-z_$][\w$]*)\(/g), match => match[1])
)
if (!calls.has(helper)) {
this.error(`[guard-preload-helper] preload() does not call ${helper}()`)
}
for (const name of calls) {
if (
name !== helper &&
name !== preload &&
code.includes(`\nfunction ${name}(`) &&
!source.includes(`function ${name}(`)
) {
this.error(
`[guard-preload-helper] preload() calls ${name}(), which the preload code does not declare`
)
}
}
},
}
}

function createRuntimeNodeEnvGuardPlugin(): Plugin {
// `resolveConfig()` decides `isProduction` from `process.env.NODE_ENV` at runtime, so that the dev
// Web Worker and the build Worker can share the code. Stop the build when the bundle fixes it.
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading