mirror of
https://github.com/stablyai/orca.git
synced 2026-11-13 09:27:29 +00:00
95 lines
3.1 KiB
JavaScript
95 lines
3.1 KiB
JavaScript
import { readFileSync, statSync } from 'node:fs'
|
|
import { dirname, join, relative, resolve } from 'node:path'
|
|
|
|
// vitest-shared-worker-file-reset.mjs undoes mocks, timers, stubs, env and cwd after each file.
|
|
// These can't be undone between files, so a file that uses them keeps its own worker.
|
|
const ISOLATION_REQUIRING_API = new RegExp(
|
|
[
|
|
// Opt-out for a file whose state leaks in ways the reset cannot see.
|
|
String.raw`@orca-isolated-worker\b`,
|
|
String.raw`\bvi\.(?:doMock|unmock|doUnmock|resetModules)\(`,
|
|
String.raw`@vitest-environment\s+(?!node\b)`,
|
|
String.raw`\bglobalThis(?:\.\w+|\[[^\]]+\])\s*=[^=]`,
|
|
String.raw`\bObject\.defineProperty\(\s*(?:globalThis|process|navigator|window|document)\b`
|
|
].join('|')
|
|
)
|
|
const IMPORT_SPECIFIER = /(?:\bfrom\s*|\bimport\s*\(\s*|\bimport\s+)['"]([^'"]+)['"]/g
|
|
const SOURCE_EXTENSIONS = ['.ts', '.tsx', '.mts', '.mjs', '.js']
|
|
|
|
function isFile(path) {
|
|
try {
|
|
return statSync(path).isFile()
|
|
} catch {
|
|
return false
|
|
}
|
|
}
|
|
|
|
function resolveLocal(fromFile, specifier, aliases) {
|
|
let base = null
|
|
if (specifier.startsWith('./') || specifier.startsWith('../')) {
|
|
base = resolve(dirname(fromFile), specifier)
|
|
} else {
|
|
const alias = aliases.find(({ find }) => specifier === find || specifier.startsWith(`${find}/`))
|
|
if (!alias) {
|
|
return null
|
|
}
|
|
base = join(alias.replacement, specifier.slice(alias.find.length))
|
|
}
|
|
const stem = base.replace(/\.[cm]?jsx?$/, '')
|
|
const candidates = [
|
|
base,
|
|
...SOURCE_EXTENSIONS.map((extension) => stem + extension),
|
|
...SOURCE_EXTENSIONS.map((extension) => join(base, `index${extension}`))
|
|
]
|
|
return (
|
|
candidates.find(
|
|
(candidate) => !/[\\/]node_modules[\\/]/.test(candidate) && isFile(candidate)
|
|
) ?? null
|
|
)
|
|
}
|
|
|
|
/**
|
|
* Returns the test files (root-relative, forward slashes) that can share a worker's module cache.
|
|
* Only the test file and the test-support files it imports are scanned, not production modules.
|
|
*/
|
|
export function filesSafeToShareWorker(root, files, aliases = []) {
|
|
const sources = new Map()
|
|
const read = (file) => {
|
|
let source = sources.get(file)
|
|
if (source === undefined) {
|
|
source = readFileSync(file, 'utf8')
|
|
sources.set(file, source)
|
|
}
|
|
return source
|
|
}
|
|
const isTestSupport = (file) => /\bfrom\s+['"]vitest['"]/.test(read(file))
|
|
const memo = new Map()
|
|
const visiting = new Set()
|
|
const requiresIsolation = (file) => {
|
|
const known = memo.get(file)
|
|
if (known !== undefined) {
|
|
return known
|
|
}
|
|
if (visiting.has(file)) {
|
|
return false
|
|
}
|
|
visiting.add(file)
|
|
const source = read(file)
|
|
let result = ISOLATION_REQUIRING_API.test(source)
|
|
for (const match of result ? [] : source.matchAll(IMPORT_SPECIFIER)) {
|
|
const target = resolveLocal(file, match[1], aliases)
|
|
if (target && isTestSupport(target) && requiresIsolation(target)) {
|
|
result = true
|
|
break
|
|
}
|
|
}
|
|
visiting.delete(file)
|
|
memo.set(file, result)
|
|
return result
|
|
}
|
|
return files
|
|
.map((file) => resolve(root, file))
|
|
.filter((file) => isFile(file) && !requiresIsolation(file))
|
|
.map((file) => relative(root, file).replaceAll('\\', '/'))
|
|
}
|