Skip to content

Commit

Permalink
feat: 🎸 worker import meta url
Browse files Browse the repository at this point in the history
  • Loading branch information
IWANABETHATGUY committed Sep 13, 2024
1 parent 4478f31 commit da4b528
Showing 1 changed file with 77 additions and 67 deletions.
144 changes: 77 additions & 67 deletions packages/vite/src/node/plugins/workerImportMetaUrl.ts
Original file line number Diff line number Diff line change
@@ -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'
Expand Down Expand Up @@ -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

Expand All @@ -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
}
},
},
}
}

0 comments on commit da4b528

Please sign in to comment.