Skip to content

Commit 202e27f

Browse files
authored
fix(runner): don't fail collection when accessing error.stack throws (#10839)
1 parent 41f551b commit 202e27f

5 files changed

Lines changed: 51 additions & 9 deletions

File tree

packages/vitest/src/runtime/runner/artifact.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ export async function recordArtifact<Artifact extends TestArtifact>(task: Test,
4343

4444
const stack = findTestFileStackTrace(
4545
task.file.filepath,
46-
new Error('STACK_TRACE').stack!,
46+
new Error('STACK_TRACE'),
4747
)
4848

4949
if (stack) {

packages/vitest/src/runtime/runner/suite.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -436,8 +436,7 @@ function createSuiteCollector(
436436
}
437437

438438
if (runner.config.includeTaskLocation) {
439-
const error = stackTraceError.stack!
440-
const stack = findTestFileStackTrace(currentTestFilepath, error)
439+
const stack = findTestFileStackTrace(currentTestFilepath, stackTraceError)
441440
if (stack) {
442441
task.location = {
443442
line: stack.line,
@@ -523,7 +522,7 @@ function createSuiteCollector(
523522
if (runner && includeLocation && runner.config.includeTaskLocation) {
524523
const limit = Error.stackTraceLimit
525524
Error.stackTraceLimit = 15
526-
const error = new Error('stacktrace').stack!
525+
const error = new Error('stacktrace')
527526
Error.stackTraceLimit = limit
528527
const stack = findTestFileStackTrace(currentTestFilepath, error)
529528
if (stack) {
Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,25 @@
11
import type { ParsedStack } from '@vitest/utils'
22
import { parseSingleStack } from '@vitest/utils/source-map'
33

4-
export function findTestFileStackTrace(testFilePath: string, error: string): ParsedStack | undefined {
4+
export function findTestFileStackTrace(testFilePath: string, error: Error): ParsedStack | undefined {
5+
let stack: string | undefined
6+
try {
7+
stack = error.stack
8+
}
9+
catch {
10+
// accessing `.stack` runs `Error.prepareStackTrace`, which can throw
11+
// if the test froze `Object.prototype` (see vitest-dev/vscode#798)
12+
return undefined
13+
}
14+
if (!stack) {
15+
return undefined
16+
}
517
// first line is the error message
6-
const lines = error.split('\n').slice(1)
18+
const lines = stack.split('\n').slice(1)
719
for (const line of lines) {
8-
const stack = parseSingleStack(line)
9-
if (stack && stack.file === testFilePath) {
10-
return stack
20+
const parsed = parseSingleStack(line)
21+
if (parsed && parsed.file === testFilePath) {
22+
return parsed
1123
}
1224
}
1325
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { describe, expect, test } from 'vitest'
2+
3+
Object.freeze(Object.prototype)
4+
5+
describe('with frozen Object.prototype', () => {
6+
test('collects and runs', () => {
7+
expect(1 + 1).toBe(2)
8+
})
9+
})
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { resolve } from 'pathe'
2+
import { expect, test } from 'vitest'
3+
import { runVitest } from '../../test-utils'
4+
5+
const root = resolve(__dirname, '..', 'fixtures', 'frozen-object-prototype')
6+
7+
test('collects tests with includeTaskLocation when the test froze Object.prototype', async () => {
8+
const { stderr, ctx } = await runVitest({
9+
root,
10+
includeTaskLocation: true,
11+
})
12+
13+
expect(stderr).not.toContain('Cannot assign to read only property')
14+
15+
const files = ctx!.state.getFiles()
16+
expect(files).toHaveLength(1)
17+
expect(files[0].result?.state).toBe('pass')
18+
19+
const tests = files[0].tasks.flatMap(suite => suite.type === 'suite' ? suite.tasks : [suite])
20+
expect(tests).toHaveLength(1)
21+
expect(tests[0].result?.state).toBe('pass')
22+
})

0 commit comments

Comments
 (0)
Sponsor
SponsoredKunjungi sekarang
Promo