From 99d89544a899938e52036114cb6613563f9d4390 Mon Sep 17 00:00:00 2001 From: IWANABETHATGUY Date: Fri, 13 Sep 2024 17:19:31 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20worker=20import=20meta?= =?UTF-8?q?=20url?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/node/plugins/workerImportMetaUrl.ts | 144 ++++++++++-------- 1 file changed, 77 insertions(+), 67 deletions(-) diff --git a/packages/vite/src/node/plugins/workerImportMetaUrl.ts b/packages/vite/src/node/plugins/workerImportMetaUrl.ts index bd86a747c20fa7..e416705cb8d33a 100644 --- a/packages/vite/src/node/plugins/workerImportMetaUrl.ts +++ b/packages/vite/src/node/plugins/workerImportMetaUrl.ts @@ -1,6 +1,6 @@ import path from 'node:path' import MagicString from 'magic-string' -import type { RollupError } from 'rolldown' +import type { RolldownPlugin, RollupError } from 'rolldown' import { stripLiteral } from 'strip-literal' import type { ResolvedConfig } from '../config' import type { Plugin } from '../plugin' @@ -103,7 +103,9 @@ function isIncludeWorkerImportMetaUrl(code: string): boolean { return false } -export function workerImportMetaUrlPlugin(config: ResolvedConfig): Plugin { +export function workerImportMetaUrlPlugin( + config: ResolvedConfig, +): RolldownPlugin { const isBuild = config.command === 'build' let workerResolver: ResolveFn @@ -127,79 +129,87 @@ export function workerImportMetaUrlPlugin(config: ResolvedConfig): Plugin { // } // }, - async transform(code, id, options) { - if (!options?.ssr && isIncludeWorkerImportMetaUrl(code)) { - let s: MagicString | undefined - const cleanString = stripLiteral(code) - const workerImportMetaUrlRE = - /\bnew\s+(?:Worker|SharedWorker)\s*\(\s*(new\s+URL\s*\(\s*('[^']+'|"[^"]+"|`[^`]+`)\s*,\s*import\.meta\.url\s*\))/dg - - let match: RegExpExecArray | null - while ((match = workerImportMetaUrlRE.exec(cleanString))) { - const [[, endIndex], [expStart, expEnd], [urlStart, urlEnd]] = - match.indices! - - const rawUrl = code.slice(urlStart, urlEnd) - - // potential dynamic template string - if (rawUrl[0] === '`' && rawUrl.includes('${')) { - this.error( - `\`new URL(url, import.meta.url)\` is not supported in dynamic template string.`, - expStart, - ) - } + transform: { + filter: { + code: { + include: [/(?:new Worker|new SharedWorker)/], + }, + }, + async handler(code, id, options) { + // @ts-expect-error TODO: RolldownPlugin compatible + if (!options?.ssr && isIncludeWorkerImportMetaUrl(code)) { + let s: MagicString | undefined + const cleanString = stripLiteral(code) + const workerImportMetaUrlRE = + /\bnew\s+(?:Worker|SharedWorker)\s*\(\s*(new\s+URL\s*\(\s*('[^']+'|"[^"]+"|`[^`]+`)\s*,\s*import\.meta\.url\s*\))/dg + + let match: RegExpExecArray | null + while ((match = workerImportMetaUrlRE.exec(cleanString))) { + const [[, endIndex], [expStart, expEnd], [urlStart, urlEnd]] = + match.indices! + + const rawUrl = code.slice(urlStart, urlEnd) + + // potential dynamic template string + if (rawUrl[0] === '`' && rawUrl.includes('${')) { + this.error( + `\`new URL(url, import.meta.url)\` is not supported in dynamic template string.`, + expStart, + ) + } - s ||= new MagicString(code) - const workerType = getWorkerType(code, cleanString, endIndex) - const url = rawUrl.slice(1, -1) - let file: string | undefined - if (url[0] === '.') { - file = path.resolve(path.dirname(id), url) - file = tryFsResolve(file, fsResolveOptions) ?? file - } else { - workerResolver ??= config.createResolver({ - extensions: [], - tryIndex: false, - preferRelative: true, - }) - file = await workerResolver(url, id) - file ??= - url[0] === '/' - ? slash(path.join(config.publicDir, url)) - : slash(path.resolve(path.dirname(id), url)) - } + s ||= new MagicString(code) + const workerType = getWorkerType(code, cleanString, endIndex) + const url = rawUrl.slice(1, -1) + let file: string | undefined + if (url[0] === '.') { + file = path.resolve(path.dirname(id), url) + file = tryFsResolve(file, fsResolveOptions) ?? file + } else { + workerResolver ??= config.createResolver({ + extensions: [], + tryIndex: false, + preferRelative: true, + }) + file = await workerResolver(url, id) + file ??= + url[0] === '/' + ? slash(path.join(config.publicDir, url)) + : slash(path.resolve(path.dirname(id), url)) + } - if ( - isBuild && - config.isWorker && - config.bundleChain.at(-1) === cleanUrl(file) - ) { - s.update(expStart, expEnd, 'self.location.href') - } else { - let builtUrl: string - if (isBuild) { - builtUrl = await workerFileToUrl(config, file) + if ( + isBuild && + config.isWorker && + config.bundleChain.at(-1) === cleanUrl(file) + ) { + s.update(expStart, expEnd, 'self.location.href') } else { - builtUrl = await fileToUrl(cleanUrl(file), config, this) - builtUrl = injectQuery( - builtUrl, - `${WORKER_FILE_ID}&type=${workerType}`, + let builtUrl: string + if (isBuild) { + builtUrl = await workerFileToUrl(config, file) + } else { + builtUrl = await fileToUrl(cleanUrl(file), config, this) + builtUrl = injectQuery( + builtUrl, + `${WORKER_FILE_ID}&type=${workerType}`, + ) + } + s.update( + expStart, + expEnd, + `new URL(/* @vite-ignore */ ${JSON.stringify(builtUrl)}, import.meta.url)`, ) } - s.update( - expStart, - expEnd, - `new URL(/* @vite-ignore */ ${JSON.stringify(builtUrl)}, import.meta.url)`, - ) } - } - if (s) { - return transformStableResult(s, id, config) - } + if (s) { + return transformStableResult(s, id, config) + } - return null - } + return null + } + }, }, } }