mirror of
https://github.com/vitest-dev/vitest.git
synced 2026-01-25 16:48:18 +00:00
94 lines
2.8 KiB
TypeScript
94 lines
2.8 KiB
TypeScript
import type { WorkerGlobalState } from 'vitest'
|
|
import type { CloneOption } from './types'
|
|
import ponyfillStructuredClone from '@ungap/structured-clone'
|
|
import createDebug from 'debug'
|
|
|
|
export const debug: createDebug.Debugger = createDebug('vitest:web-worker')
|
|
|
|
export function getWorkerState(): WorkerGlobalState {
|
|
// @ts-expect-error untyped global
|
|
return globalThis.__vitest_worker__
|
|
}
|
|
|
|
export function assertGlobalExists(name: string): void {
|
|
if (!(name in globalThis)) {
|
|
throw new Error(
|
|
`[@vitest/web-worker] Cannot initiate a custom Web Worker. "${name}" is not supported in this environment. Please, consider using jsdom or happy-dom environment.`,
|
|
)
|
|
}
|
|
}
|
|
|
|
function createClonedMessageEvent(
|
|
data: any,
|
|
transferOrOptions: StructuredSerializeOptions | Transferable[] | undefined,
|
|
clone: CloneOption,
|
|
) {
|
|
const transfer = Array.isArray(transferOrOptions)
|
|
? transferOrOptions
|
|
: transferOrOptions?.transfer
|
|
|
|
debug('clone worker message %o', data)
|
|
const origin = typeof location === 'undefined' ? undefined : location.origin
|
|
|
|
if (typeof structuredClone === 'function' && clone === 'native') {
|
|
debug('create message event, using native structured clone')
|
|
return new MessageEvent('message', {
|
|
data: structuredClone(data, { transfer }),
|
|
origin,
|
|
})
|
|
}
|
|
if (clone !== 'none') {
|
|
debug('create message event, using polyfilled structured clone')
|
|
if (transfer?.length) {
|
|
console.warn(
|
|
'[@vitest/web-worker] `structuredClone` is not supported in this environment. '
|
|
+ 'Falling back to polyfill, your transferable options will be lost. '
|
|
+ 'Set `VITEST_WEB_WORKER_CLONE` environmental variable to "none", if you don\'t want to loose it,'
|
|
+ 'or update to Node 17+.',
|
|
)
|
|
}
|
|
return new MessageEvent('message', {
|
|
data: ponyfillStructuredClone(data, { lossy: true } as any),
|
|
origin,
|
|
})
|
|
}
|
|
debug('create message event without cloning an object')
|
|
return new MessageEvent('message', {
|
|
data,
|
|
origin,
|
|
})
|
|
}
|
|
|
|
export function createMessageEvent(
|
|
data: any,
|
|
transferOrOptions: StructuredSerializeOptions | Transferable[] | undefined,
|
|
clone: CloneOption,
|
|
): MessageEvent {
|
|
try {
|
|
return createClonedMessageEvent(data, transferOrOptions, clone)
|
|
}
|
|
catch (error) {
|
|
debug('failed to clone message, dispatch "messageerror" event: %o', error)
|
|
return new MessageEvent('messageerror', {
|
|
data: error,
|
|
})
|
|
}
|
|
}
|
|
|
|
function stripProtocol(url: string | URL) {
|
|
return url.toString().replace(/^file:\/+/, '/')
|
|
}
|
|
|
|
export function getFileIdFromUrl(url: URL | string): string {
|
|
if (typeof self === 'undefined') {
|
|
return stripProtocol(url)
|
|
}
|
|
if (!(url instanceof URL)) {
|
|
url = new URL(url, self.location.origin)
|
|
}
|
|
if (url.protocol === 'http:' || url.protocol === 'https:') {
|
|
return url.pathname
|
|
}
|
|
return stripProtocol(url)
|
|
}
|