From 0b79231ad7897f03de17940ef16684b63aa217fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ari=20Perkki=C3=B6?= Date: Fri, 25 Sep 2026 11:08:15 +0300 Subject: [PATCH] fix: bind `process` in case global is overwritten (#11343) --- .../runtime/moduleRunner/cachedResolver.ts | 3 +- packages/vitest/src/runtime/rpc.ts | 12 ++--- test/unit/test/stubbed-process.test.ts | 44 ++++++++++++++----- 3 files changed, 43 insertions(+), 16 deletions(-) diff --git a/packages/vitest/src/runtime/moduleRunner/cachedResolver.ts b/packages/vitest/src/runtime/moduleRunner/cachedResolver.ts index 95bae4295..e153ae104 100644 --- a/packages/vitest/src/runtime/moduleRunner/cachedResolver.ts +++ b/packages/vitest/src/runtime/moduleRunner/cachedResolver.ts @@ -4,6 +4,7 @@ import { splitFileAndPostfix } from '@vitest/utils/helpers' import { join, normalize } from 'pathe' import { distDir } from '../../paths' +const platform = process.platform const bareVitestRegexp = /^@?vitest(?:\/|$)/ const normalizedDistDir = normalize(distDir) const relativeIds: Record = {} @@ -23,7 +24,7 @@ export function getCachedVitestImport( state: () => WorkerGlobalState, ): null | { externalize: string; type: 'module' } { if (id.startsWith('/@fs/') || id.startsWith('\\@fs\\')) { - id = id.slice(process.platform === 'win32' ? 5 : 4) + id = id.slice(platform === 'win32' ? 5 : 4) } if (externalizeMap.has(id)) { diff --git a/packages/vitest/src/runtime/rpc.ts b/packages/vitest/src/runtime/rpc.ts index 4306b1483..d464f861c 100644 --- a/packages/vitest/src/runtime/rpc.ts +++ b/packages/vitest/src/runtime/rpc.ts @@ -8,6 +8,8 @@ import { getWorkerState } from './utils' const { get } = Reflect +const globalProcess = globalThis.process + function withSafeTimers(fn: () => void) { const { setTimeout, clearTimeout, nextTick, setImmediate, clearImmediate } = getSafeTimers() @@ -17,7 +19,7 @@ function withSafeTimers(fn: () => void) { const currentSetImmediate = globalThis.setImmediate const currentClearImmediate = globalThis.clearImmediate - const currentNextTick = globalThis.process?.nextTick + const currentNextTick = globalProcess?.nextTick try { globalThis.setTimeout = setTimeout @@ -30,8 +32,8 @@ function withSafeTimers(fn: () => void) { globalThis.clearImmediate = clearImmediate } - if (globalThis.process && nextTick) { - globalThis.process.nextTick = nextTick + if (globalProcess && nextTick) { + globalProcess.nextTick = nextTick } const result = fn() @@ -43,9 +45,9 @@ function withSafeTimers(fn: () => void) { globalThis.setImmediate = currentSetImmediate globalThis.clearImmediate = currentClearImmediate - if (globalThis.process && nextTick) { + if (globalProcess && nextTick) { nextTick(() => { - globalThis.process.nextTick = currentNextTick + globalProcess.nextTick = currentNextTick }) } } diff --git a/test/unit/test/stubbed-process.test.ts b/test/unit/test/stubbed-process.test.ts index 43dbb95ae..bc0520963 100644 --- a/test/unit/test/stubbed-process.test.ts +++ b/test/unit/test/stubbed-process.test.ts @@ -1,17 +1,41 @@ -import { expect, it, vi } from 'vitest' +import { beforeAll, describe, expect, it, onTestFinished, vi } from 'vitest' -vi.stubGlobal('process', { badMock: true }) +describe('undefined process', () => { + // This has to be first test of the file to trigger rpc withSafeTimers race + it('undefined process when importing file outside root', async () => { + const realProcess = globalThis.process -it('should not hang', () => { - expect(1).toBe(1) -}) + onTestFinished(async () => { + globalThis.process = realProcess + }) + + globalThis.process = undefined as any -it('should not crash (#9173)', async () => { - await import('./fixtures/increment') + const mod = await import('../../test-utils/fixtures/external-math') + expect(mod.sum(2, 3)).toBe(5) + }) }) -it('should not hang', () => { - vi.unstubAllGlobals() +describe('stubbed process', () => { + beforeAll(() => { + vi.stubGlobal('process', { badMock: true }) + + return () => { + vi.unstubAllGlobals() + } + }) + + it('should not hang', () => { + expect(1).toBe(1) + }) + + it('should not crash (#9173)', async () => { + await import('./fixtures/increment') + }) + + it('should not hang', () => { + vi.unstubAllGlobals() - process.stdout.write = () => true + process.stdout.write = () => true + }) }) -- 2.51.2