diff --git a/packages/vitest/src/node/plugins/index.ts b/packages/vitest/src/node/plugins/index.ts index aa6a7053a0cc..e3bd385ddf93 100644 --- a/packages/vitest/src/node/plugins/index.ts +++ b/packages/vitest/src/node/plugins/index.ts @@ -14,6 +14,7 @@ import { GlobalSetupPlugin } from './globalSetup' import { CSSEnablerPlugin } from './cssEnabler' import { CoverageTransform } from './coverageTransform' import { MocksPlugin } from './mocks' +import { VitestResolver } from './vitestResolver' export async function VitestPlugin(options: UserConfig = {}, ctx = new Vitest('test')): Promise { const userConfig = deepMerge({}, options) as UserConfig @@ -240,6 +241,7 @@ export async function VitestPlugin(options: UserConfig = {}, ctx = new Vitest('t ? await UIPlugin() : null, MocksPlugin(), + VitestResolver(ctx), ] .filter(notNullish) } diff --git a/packages/vitest/src/node/plugins/vitestResolver.ts b/packages/vitest/src/node/plugins/vitestResolver.ts new file mode 100644 index 000000000000..354d46b10b79 --- /dev/null +++ b/packages/vitest/src/node/plugins/vitestResolver.ts @@ -0,0 +1,19 @@ +import type { Plugin } from 'vite' +import { join } from 'pathe' +import type { Vitest } from '../core' + +export function VitestResolver(ctx: Vitest): Plugin { + return { + name: 'vitest:resolve-root', + enforce: 'pre', + async resolveId(id) { + if (id === 'vitest' || id.startsWith('@vitest/')) { + return this.resolve( + id, + join(ctx.config.root, 'index.html'), + { skipSelf: true }, + ) + } + }, + } +} diff --git a/packages/vitest/src/node/plugins/workspace.ts b/packages/vitest/src/node/plugins/workspace.ts index 91aebe65b8d5..f87556d07d1e 100644 --- a/packages/vitest/src/node/plugins/workspace.ts +++ b/packages/vitest/src/node/plugins/workspace.ts @@ -12,6 +12,7 @@ import { CSSEnablerPlugin } from './cssEnabler' import { EnvReplacerPlugin } from './envReplacer' import { GlobalSetupPlugin } from './globalSetup' import { MocksPlugin } from './mocks' +import { VitestResolver } from './vitestResolver' interface WorkspaceOptions extends UserWorkspaceConfig { root?: string @@ -171,5 +172,6 @@ export function WorkspaceVitestPlugin(project: WorkspaceProject, options: Worksp CoverageTransform(project.ctx), GlobalSetupPlugin(project, project.ctx.logger), MocksPlugin(), + VitestResolver(project.ctx), ] } diff --git a/packages/vitest/src/paths.ts b/packages/vitest/src/paths.ts index 4e72159e632a..9bc74dd12216 100644 --- a/packages/vitest/src/paths.ts +++ b/packages/vitest/src/paths.ts @@ -3,6 +3,3 @@ import { resolve } from 'pathe' export const rootDir = resolve(url.fileURLToPath(import.meta.url), '../../') export const distDir = resolve(url.fileURLToPath(import.meta.url), '../../dist') - -export const entryPath = 'vitest/dist/entry.js' -export const spyPath = 'vitest/dist/spy.js' diff --git a/packages/vitest/src/runtime/execute.ts b/packages/vitest/src/runtime/execute.ts index e717659aff49..bacd3c3b1747 100644 --- a/packages/vitest/src/runtime/execute.ts +++ b/packages/vitest/src/runtime/execute.ts @@ -1,14 +1,13 @@ -import { createRequire } from 'node:module' import { pathToFileURL } from 'node:url' import { ModuleCacheMap, ViteNodeRunner } from 'vite-node/client' import { isInternalRequest, isNodeBuiltin, isPrimitive } from 'vite-node/utils' import type { ViteNodeRunnerOptions } from 'vite-node' -import { normalize, relative } from 'pathe' +import { normalize, relative, resolve } from 'pathe' import { processError } from '@vitest/runner/utils' import type { MockMap } from '../types/mocker' import { getCurrentEnvironment, getWorkerState } from '../utils/global' import type { ContextRPC, ContextTestEnvironment, ResolvedConfig } from '../types' -import { entryPath } from '../paths' +import { distDir } from '../paths' import { VitestMocker } from './mocker' import { rpc } from './rpc' @@ -20,10 +19,7 @@ export interface ExecuteOptions extends ViteNodeRunnerOptions { export async function createVitestExecutor(options: ExecuteOptions) { const runner = new VitestExecutor(options) - await Promise.all([ - runner.executeId('/@vite/env'), - runner.mocker.initializeSpyModule(), - ]) + await runner.executeId('/@vite/env') return runner } @@ -80,10 +76,7 @@ export async function startViteNode(ctx: ContextRPC) { base: config.base, }) - const _require = createRequire(config.root) - const vitestEntry = _require.resolve(entryPath, { paths: [config.root] }) - - const { run } = await import(pathToFileURL(vitestEntry).href) + const { run } = await import(pathToFileURL(resolve(distDir, 'entry.js')).href) _viteNode = { run, executor } diff --git a/packages/vitest/src/runtime/mocker.ts b/packages/vitest/src/runtime/mocker.ts index c8a3ba30f87f..8b818bd8b399 100644 --- a/packages/vitest/src/runtime/mocker.ts +++ b/packages/vitest/src/runtime/mocker.ts @@ -5,7 +5,7 @@ import { isNodeBuiltin } from 'vite-node/utils' import { getWorkerState } from '../utils/global' import { getAllMockableProperties } from '../utils/base' import type { MockFactory, PendingSuiteMock } from '../types/mocker' -import { spyPath } from '../paths' +import { spyOn } from '../integrations/spy' import type { VitestExecutor } from './execute' const filterPublicKeys = ['__esModule', Symbol.asyncIterator, Symbol.hasInstance, Symbol.isConcatSpreadable, Symbol.iterator, Symbol.match, Symbol.matchAll, Symbol.replace, Symbol.search, Symbol.split, Symbol.species, Symbol.toPrimitive, Symbol.toStringTag, Symbol.unscopables] @@ -40,7 +40,6 @@ function isSpecialProp(prop: Key, parentType: string) { export class VitestMocker { private static pendingIds: PendingSuiteMock[] = [] - private spyModule?: typeof import('@vitest/spy') private resolveCache = new Map>() constructor( @@ -63,10 +62,6 @@ export class VitestMocker { return this.executor.options.moduleDirectories || [] } - public async initializeSpyModule() { - this.spyModule = await this.executor.executeId(spyPath) - } - private deleteCachedItem(id: string) { const mockId = this.getMockPath(id) if (this.moduleCache.has(mockId)) @@ -280,10 +275,7 @@ export class VitestMocker { continue if (isFunction) { - const spyModule = this.spyModule - if (!spyModule) - throw new Error('[vitest] `spyModule` is not defined. This is Vitest error. Please open a new issue with reproduction.') - const mock = spyModule.spyOn(newContainer, property).mockImplementation(() => undefined) + const mock = spyOn(newContainer, property).mockImplementation(() => undefined) mock.mockRestore = () => { mock.mockReset() mock.mockImplementation(undefined!)