Skip to content

Commit 83ab9a4

Browse files
authored
fix: keep per-file isolation in vm pools when maxWorkers is 1 (#10743)
1 parent 3feefd9 commit 83ab9a4

2 files changed

Lines changed: 36 additions & 2 deletions

File tree

packages/vitest/src/node/pool.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -431,8 +431,12 @@ function groupSpecs(specs: TestSpecification[], environments: WeakMap<TestSpecif
431431
throw new Error(`Projects "${last}" and "${spec.project.name}" have different 'maxWorkers' but same 'sequence.groupOrder'.\nProvide unique 'sequence.groupOrder' for them.`)
432432
}
433433

434-
// Non-isolated single worker can receive all files at once
435-
if (isolate === false && maxWorkers === 1) {
434+
// Non-isolated single worker can receive all files at once.
435+
// vm pools are excluded: their `isolate: false` comes from config
436+
// resolution rather than the user, because their isolation is a fresh VM
437+
// context per run request — batching files into a single run request
438+
// would share one context across all of them.
439+
if (isolate === false && maxWorkers === 1 && spec.pool !== 'vmThreads' && spec.pool !== 'vmForks') {
436440
const previous = groups[order].specs[0]?.[0]
437441

438442
if (previous && previous.project.name === spec.project.name && isEqualEnvironments(spec, previous)) {

test/e2e/test/vm-threads.test.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,36 @@ test('importing files in restricted fs works correctly', async () => {
1616
expect(exitCode).toBe(0)
1717
})
1818

19+
// vm pools resolve `isolate` to false (isolation comes from a fresh VM
20+
// context per run request), which used to trigger the "single non-isolated
21+
// worker receives all files at once" batching with `maxWorkers: 1` — all
22+
// files then shared one VM context and leaked state into each other
23+
test.for(['vmThreads', 'vmForks'] as const)(
24+
'%s keeps per-file isolation when maxWorkers is 1',
25+
async (pool) => {
26+
// each file both expects a clean context and pollutes it, so the test
27+
// does not depend on the file execution order
28+
const pollutingTest = `
29+
import { expect, test } from 'vitest'
30+
31+
test('does not see state from other test files', () => {
32+
expect(globalThis.__isolation_leak__).toBeUndefined()
33+
globalThis.__isolation_leak__ = import.meta.url
34+
})
35+
`
36+
const { stderr, exitCode } = await runInlineTests({
37+
'a.test.js': pollutingTest,
38+
'b.test.js': pollutingTest,
39+
}, {
40+
pool,
41+
maxWorkers: 1,
42+
})
43+
44+
expect(stderr).toBe('')
45+
expect(exitCode).toBe(0)
46+
},
47+
)
48+
1949
// The module-sync condition was added in Node 22.12/20.19 when require(esm)
2050
// was unflagged. The fix uses the _resolveFilename conditions option which
2151
// is only available on Node 22.12+. Node 20 is unfixable and reaches EOL

0 commit comments

Comments
 (0)
Sponsor
SponsoredKunjungi sekarang
Promo