···169169export function wildcardPatternToRegExp(pattern: string): RegExp {
170170 return new RegExp(`^${pattern.split('*').map(escapeRegExp).join('.*')}$`, 'i')
171171}
172172+173173+// port from nanoid
174174+// https://github.com/ai/nanoid
175175+const urlAlphabet
176176+ = 'useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict'
177177+export function nanoid(size = 21) {
178178+ let id = ''
179179+ let i = size
180180+ while (i--) id += urlAlphabet[(Math.random() * 64) | 0]
181181+ return id
182182+}
+7-1
packages/vitest/src/integrations/env/loader.ts
···11+import { readFileSync } from 'node:fs'
12import { normalize, resolve } from 'pathe'
23import { ViteNodeRunner } from 'vite-node/client'
34import type { ViteNodeRunnerOptions } from 'vite-node'
···2627 return environments[name]
2728 const loader = await createEnvironmentLoader({
2829 root: ctx.config.root,
2929- fetchModule: id => rpc.fetch(id, 'ssr'),
3030+ fetchModule: async (id) => {
3131+ const result = await rpc.fetch(id, 'ssr')
3232+ if (result.id)
3333+ return { code: readFileSync(result.id, 'utf-8') }
3434+ return result
3535+ },
3036 resolveId: (id, importer) => rpc.resolveId(id, importer, 'ssr'),
3137 })
3238 const root = loader.root
+30-2
packages/vitest/src/node/pools/rpc.ts
···11+import { mkdir, writeFile } from 'node:fs/promises'
12import type { RawSourceMap } from 'vite-node'
33+import { join } from 'pathe'
24import type { RuntimeRPC } from '../../types'
35import type { WorkspaceProject } from '../workspace'
66+77+const created = new Set()
88+const promises = new Map<string, Promise<void>>()
49510export function createMethodsRPC(project: WorkspaceProject): RuntimeRPC {
611 const ctx = project.ctx
···2025 const r = await project.vitenode.transformRequest(id)
2126 return r?.map as RawSourceMap | undefined
2227 },
2323- fetch(id, transformMode) {
2424- return project.vitenode.fetchModule(id, transformMode)
2828+ async fetch(id, transformMode) {
2929+ const result = await project.vitenode.fetchResult(id, transformMode)
3030+ const code = result.code
3131+ if (result.externalize)
3232+ return result
3333+ if ('id' in result)
3434+ return { id: result.id as string }
3535+3636+ if (!code)
3737+ throw new Error(`Failed to fetch module ${id}`)
3838+3939+ const dir = join(project.tmpDir, transformMode)
4040+ const tmp = join(dir, id.replace(/[/\\?%*:|"<>]/g, '_').replace('\0', '__x00__'))
4141+ if (promises.has(tmp)) {
4242+ await promises.get(tmp)
4343+ return { id: tmp }
4444+ }
4545+ if (!created.has(dir)) {
4646+ await mkdir(dir, { recursive: true })
4747+ created.add(dir)
4848+ }
4949+ promises.set(tmp, writeFile(tmp, code, 'utf-8').finally(() => promises.delete(tmp)))
5050+ await promises.get(tmp)
5151+ Object.assign(result, { id: tmp })
5252+ return { id: tmp }
2553 },
2654 resolveId(id, importer, transformMode) {
2755 return project.vitenode.resolveId(id, importer, transformMode)