···219219220220 const testPath = (e as any).VITEST_TEST_PATH
221221 const testName = (e as any).VITEST_TEST_NAME
222222- const afterEnvTeardown = (e as any).VITEST_AFTER_ENV_TEARDOWN
223222 // testName has testPath inside
224223 if (testPath) {
225224 logger.error(
···238237 )}". It might mean one of the following:`
239238 + '\n- The error was thrown, while Vitest was running this test.'
240239 + '\n- If the error occurred after the test had been completed, this was the last documented test before it was thrown.',
241241- ),
242242- )
243243- }
244244- if (afterEnvTeardown) {
245245- logger.error(
246246- c.red(
247247- 'This error was caught after test environment was torn down. Make sure to cancel any running tasks before test finishes:'
248248- + '\n- cancel timeouts using clearTimeout and clearInterval'
249249- + '\n- wait for promises to resolve using the await keyword',
250240 ),
251241 )
252242 }
···292282 'columnNumber',
293283 'VITEST_TEST_NAME',
294284 'VITEST_TEST_PATH',
295295- 'VITEST_AFTER_ENV_TEARDOWN',
296285 '__vitest_rollup_error__',
297286 ...Object.getOwnPropertyNames(Error.prototype),
298287 ...Object.getOwnPropertyNames(Object.prototype),
···11-import type { ResolvedTestEnvironment } from '../types/environment'
11+import type { Environment } from '../types/environment'
22import type { SerializedConfig } from './config'
33-import type { VitestModuleRunner } from './moduleRunner/moduleRunner'
43import { createRequire } from 'node:module'
54import timers from 'node:timers'
65import timersPromises from 'node:timers/promises'
76import util from 'node:util'
87import { KNOWN_ASSET_TYPES } from '@vitest/utils/constants'
99-import { getSafeTimers } from '@vitest/utils/timers'
1010-import { expect } from '../integrations/chai'
1111-import { resolveSnapshotEnvironment } from '../integrations/snapshot/environments/resolveSnapshotEnvironment'
128import * as VitestIndex from '../public/index'
139import { setupCommonEnv } from './setup-common'
1414-import { getWorkerState } from './utils'
15101611// this should only be used in Node
1712let globalSetup = false
1813export async function setupGlobalEnv(
1914 config: SerializedConfig,
2020- { environment }: ResolvedTestEnvironment,
2121- moduleRunner: VitestModuleRunner,
1515+ environment: Environment,
2216): Promise<void> {
2317 await setupCommonEnv(config)
2418···2721 enumerable: false,
2822 })
29233030- const state = getWorkerState()
3131-3232- if (!state.config.snapshotOptions.snapshotEnvironment) {
3333- state.config.snapshotOptions.snapshotEnvironment
3434- = await resolveSnapshotEnvironment(config, moduleRunner)
3535- }
2424+ VitestIndex.expect.setState({
2525+ environment: environment.name,
2626+ })
36273728 if (globalSetup) {
3829 return
···8273 const { createCustomConsole } = await import('./console')
83748475 globalThis.console = createCustomConsole()
8585-}
8686-8787-export async function withEnv(
8888- { environment }: ResolvedTestEnvironment,
8989- options: Record<string, any>,
9090- fn: () => Promise<void>,
9191-): Promise<void> {
9292- // @ts-expect-error untyped global
9393- globalThis.__vitest_environment__ = environment.name
9494- expect.setState({
9595- environment: environment.name,
9696- })
9797- const env = await environment.setup(globalThis, options)
9898- try {
9999- await fn()
100100- }
101101- finally {
102102- // Run possible setTimeouts, e.g. the onces used by ConsoleLogSpy
103103- const { setTimeout } = getSafeTimers()
104104- await new Promise(resolve => setTimeout(resolve))
105105-106106- await env.teardown(globalThis)
107107- }
10876}
+9-15
packages/vitest/src/runtime/worker.ts
···11-import type { ModuleRunner } from 'vite/module-runner'
21import type { ContextRPC, WorkerGlobalState } from '../types/worker'
32import type { VitestWorker } from './workers/types'
43import { createStackString, parseStacktrace } from '@vitest/utils/source-map'
55-import { loadEnvironment } from '../integrations/env/loader'
64import { setupInspect } from './inspector'
75import { VitestEvaluatedModules } from './moduleRunner/evaluatedModules'
88-import { createRuntimeRpc, rpcDone } from './rpc'
66+import { onCancel, rpcDone } from './rpc'
97108const resolvingModules = new Set<string>()
119const globalListeners = new Set<() => unknown>()
···15131614 const cleanups: (() => void | Promise<void>)[] = [setupInspect(ctx)]
17151818- let environmentLoader: ModuleRunner | undefined
1919-2016 // RPC is used to communicate between worker (be it a thread worker or child process or a custom implementation) and the main thread
2121- const { rpc, onCancel } = createRuntimeRpc(worker)
1717+ const rpc = ctx.rpc
22182319 try {
2420 // do not close the RPC channel so that we can get the error messages sent to the main thread
···2824 }))
2925 })
30263131- const beforeEnvironmentTime = performance.now()
3232- const { environment, loader } = await loadEnvironment(ctx, rpc)
3333- environmentLoader = loader
3434-3527 const state = {
3628 ctx,
3729 // here we create a new one, workers can reassign this if they need to keep it non-isolated
···3931 resolvingModules,
4032 moduleExecutionInfo: new Map(),
4133 config: ctx.config,
4242- onCancel,
4343- environment,
3434+ // this is set later by vm or base
3535+ environment: null!,
4436 durations: {
4545- environment: beforeEnvironmentTime,
3737+ environment: 0,
4638 prepare: prepareStart,
4739 },
4840 rpc,
4141+ onCancel,
4942 onCleanup: listener => globalListeners.add(listener),
5043 providedContext: ctx.providedContext,
5144 onFilterStackTrace(stack) {
···6760 finally {
6861 await rpcDone().catch(() => {})
6962 await Promise.all(cleanups.map(fn => fn())).catch(() => {})
7070- await environmentLoader?.close()
7163 }
7264}
7365···8375 await Promise.all([...globalListeners].map(l => l()))
8476}
85777878+const env = process.env
7979+8680function createImportMetaEnvProxy(): WorkerGlobalState['metaEnv'] {
8781 // packages/vitest/src/node/plugins/index.ts:146
8882 const booleanKeys = ['DEV', 'PROD', 'SSR']
8989- return new Proxy(process.env, {
8383+ return new Proxy(env, {
9084 get(_, key) {
9185 if (typeof key !== 'string') {
9286 return undefined
···3030 </li>
3131 </ul>
3232 </div>
3333- <div v-if="error.VITEST_AFTER_ENV_TEARDOWN" text="sm" font-thin>
3434- This error was caught after test environment was torn down. Make sure to cancel any running tasks before test finishes:<br>
3535- <ul>
3636- <li>
3737- Cancel timeouts using clearTimeout and clearInterval.
3838- </li>
3939- <li>
4040- Wait for promises to resolve using the await keyword.
4141- </li>
4242- </ul>
4343- </div>
4433</template>
+1
packages/vitest/src/integrations/env/jsdom.ts
···77 let userErrorListenerCount = 0
88 function throwUnhandlerError(e: ErrorEvent) {
99 if (userErrorListenerCount === 0 && e.error != null) {
1010+ e.preventDefault()
1011 process.emit('uncaughtException', e.error)
1112 }
1213 }
+3-4
packages/vitest/src/integrations/env/loader.ts
···11import type { BuiltinEnvironment, VitestEnvironment } from '../../node/types/config'
22import type { Environment } from '../../types/environment'
33-import type { ContextRPC, WorkerRPC } from '../../types/worker'
33+import type { WorkerRPC } from '../../types/worker'
44import { readFileSync } from 'node:fs'
55import { isBuiltin } from 'node:module'
66import { pathToFileURL } from 'node:url'
···5454}
55555656export async function loadEnvironment(
5757- ctx: ContextRPC,
5757+ name: string,
5858+ root: string,
5859 rpc: WorkerRPC,
5960): Promise<{ environment: Environment; loader?: ModuleRunner }> {
6060- const name = ctx.environment.name
6161 if (isBuiltinEnvironment(name)) {
6262 return { environment: environments[name] }
6363 }
6464- const root = ctx.config.root
6564 const loader = await createEnvironmentLoader(root, rpc)
6665 const packageId
6766 = name[0] === '.' || name[0] === '/'