Skip to content

Commit 7768114

Browse files
committed
fix: fix capturePrintError logger duplicate event handlers
1 parent 3912554 commit 7768114

File tree

2 files changed

+59
-46
lines changed

2 files changed

+59
-46
lines changed

packages/vitest/src/node/error.ts

Lines changed: 57 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import type { ErrorWithDiff, ParsedStack } from '@vitest/utils'
22
import type { Vitest } from './core'
3-
import type { ErrorOptions } from './logger'
3+
import type { ErrorOptions, Logger } from './logger'
44
import type { TestProject } from './project'
55
/* eslint-disable prefer-template */
6+
import { Console } from 'node:console'
67
import { existsSync, readFileSync } from 'node:fs'
78
import { Writable } from 'node:stream'
89
import { stripVTControlCharacters } from 'node:util'
@@ -12,22 +13,24 @@ import c from 'tinyrainbow'
1213
import { TypeCheckError } from '../typecheck/typechecker'
1314
import {
1415
lineSplitRE,
16+
parseErrorStacktrace,
1517
positionToOffset,
1618
} from '../utils/source-map'
17-
import { Logger } from './logger'
1819
import { F_POINTER } from './reporters/renderers/figures'
1920
import { divider, truncateString } from './reporters/renderers/utils'
2021

22+
type ErrorLogger = Pick<Logger, 'error' | 'highlight'>
23+
2124
interface PrintErrorOptions {
25+
logger: ErrorLogger
2226
type?: string
23-
logger: Logger
2427
showCodeFrame?: boolean
2528
printProperties?: boolean
2629
screenshotPaths?: string[]
2730
parseErrorStacktrace: (error: ErrorWithDiff) => ParsedStack[]
2831
}
2932

30-
export interface PrintErrorResult {
33+
interface PrintErrorResult {
3134
nearest?: ParsedStack
3235
}
3336

@@ -44,15 +47,52 @@ export function capturePrintError(
4447
callback()
4548
},
4649
})
47-
const logger = new Logger(ctx, writable, writable)
48-
const result = logger.printError(error, {
49-
showCodeFrame: false,
50+
const console = new Console(writable)
51+
const logger: ErrorLogger = {
52+
error: console.error.bind(console),
53+
highlight: ctx.logger.highlight.bind(ctx.logger),
54+
}
55+
const result = printError(error, ctx, logger, {
5056
...options,
57+
showCodeFrame: false,
5158
})
5259
return { nearest: result?.nearest, output }
5360
}
5461

5562
export function printError(
63+
error: unknown,
64+
ctx: Vitest,
65+
logger: ErrorLogger,
66+
options: ErrorOptions,
67+
) {
68+
const project = options.project
69+
?? ctx.coreWorkspaceProject
70+
?? ctx.projects[0]
71+
return printErrorInner(error, project, {
72+
logger,
73+
type: options.type,
74+
showCodeFrame: options.showCodeFrame,
75+
screenshotPaths: options.screenshotPaths,
76+
printProperties: options.verbose,
77+
parseErrorStacktrace(error) {
78+
// browser stack trace needs to be processed differently,
79+
// so there is a separate method for that
80+
if (options.task?.file.pool === 'browser' && project.browser) {
81+
return project.browser.parseErrorStacktrace(error, {
82+
ignoreStackEntries: options.fullStack ? [] : undefined,
83+
})
84+
}
85+
86+
// node.js stack trace already has correct source map locations
87+
return parseErrorStacktrace(error, {
88+
frameFilter: project.config.onStackTrace,
89+
ignoreStackEntries: options.fullStack ? [] : undefined,
90+
})
91+
},
92+
})
93+
}
94+
95+
function printErrorInner(
5696
error: unknown,
5797
project: TestProject | undefined,
5898
options: PrintErrorOptions,
@@ -129,7 +169,7 @@ export function printError(
129169

130170
// E.g. AssertionError from assert does not set showDiff but has both actual and expected properties
131171
if (e.diff) {
132-
displayDiff(e.diff, logger.console)
172+
displayDiff(e.diff, logger)
133173
}
134174

135175
// if the error provide the frame
@@ -193,7 +233,7 @@ export function printError(
193233

194234
if (typeof e.cause === 'object' && e.cause && 'name' in e.cause) {
195235
(e.cause as any).name = `Caused by: ${(e.cause as any).name}`
196-
printError(e.cause, project, {
236+
printErrorInner(e.cause, project, {
197237
showCodeFrame: false,
198238
logger: options.logger,
199239
parseErrorStacktrace: options.parseErrorStacktrace,
@@ -251,7 +291,7 @@ const esmErrors = [
251291
'Unexpected token \'export\'',
252292
]
253293

254-
function handleImportOutsideModuleError(stack: string, logger: Logger) {
294+
function handleImportOutsideModuleError(stack: string, logger: ErrorLogger) {
255295
if (!esmErrors.some(e => stack.includes(e))) {
256296
return
257297
}
@@ -274,7 +314,7 @@ function handleImportOutsideModuleError(stack: string, logger: Logger) {
274314
}
275315

276316
function printModuleWarningForPackage(
277-
logger: Logger,
317+
logger: ErrorLogger,
278318
path: string,
279319
name: string,
280320
) {
@@ -305,7 +345,7 @@ function printModuleWarningForPackage(
305345
)
306346
}
307347

308-
function printModuleWarningForSourceCode(logger: Logger, path: string) {
348+
function printModuleWarningForSourceCode(logger: ErrorLogger, path: string) {
309349
logger.error(
310350
c.yellow(
311351
`Module ${path} seems to be an ES Module but shipped in a CommonJS package. `
@@ -314,13 +354,13 @@ function printModuleWarningForSourceCode(logger: Logger, path: string) {
314354
)
315355
}
316356

317-
export function displayDiff(diff: string | undefined, console: Console) {
357+
function displayDiff(diff: string | undefined, logger: ErrorLogger) {
318358
if (diff) {
319-
console.error(`\n${diff}\n`)
359+
logger.error(`\n${diff}\n`)
320360
}
321361
}
322362

323-
function printErrorMessage(error: ErrorWithDiff, logger: Logger) {
363+
function printErrorMessage(error: ErrorWithDiff, logger: ErrorLogger) {
324364
const errorName = error.name || error.nameStr || 'Unknown Error'
325365
if (!error.message) {
326366
logger.error(error)
@@ -335,8 +375,8 @@ function printErrorMessage(error: ErrorWithDiff, logger: Logger) {
335375
}
336376
}
337377

338-
export function printStack(
339-
logger: Logger,
378+
function printStack(
379+
logger: ErrorLogger,
340380
project: TestProject,
341381
stack: ParsedStack[],
342382
highlight: ParsedStack | undefined,

packages/vitest/src/node/logger.ts

Lines changed: 2 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,9 @@ import type { ErrorWithDiff } from '@vitest/utils'
33
import type { Writable } from 'node:stream'
44
import type { TypeCheckError } from '../typecheck/typechecker'
55
import type { Vitest } from './core'
6-
import type { PrintErrorResult } from './error'
76
import type { TestProject } from './project'
87
import { Console } from 'node:console'
98
import { toArray } from '@vitest/utils'
10-
import { parseErrorStacktrace } from '@vitest/utils/source-map'
119
import c from 'tinyrainbow'
1210
import { highlightCode } from '../utils/colors'
1311
import { printError } from './error'
@@ -106,33 +104,8 @@ export class Logger {
106104
this.console.log(`${CURSOR_TO_START}${ERASE_DOWN}${log}`)
107105
}
108106

109-
printError(err: unknown, options: ErrorOptions = {}): PrintErrorResult | undefined {
110-
const { fullStack = false, type } = options
111-
const project = options.project
112-
?? this.ctx.coreWorkspaceProject
113-
?? this.ctx.projects[0]
114-
return printError(err, project, {
115-
type,
116-
showCodeFrame: options.showCodeFrame ?? true,
117-
logger: this,
118-
printProperties: options.verbose,
119-
screenshotPaths: options.screenshotPaths,
120-
parseErrorStacktrace: (error) => {
121-
// browser stack trace needs to be processed differently,
122-
// so there is a separate method for that
123-
if (options.task?.file.pool === 'browser' && project.browser) {
124-
return project.browser.parseErrorStacktrace(error, {
125-
ignoreStackEntries: fullStack ? [] : undefined,
126-
})
127-
}
128-
129-
// node.js stack trace already has correct source map locations
130-
return parseErrorStacktrace(error, {
131-
frameFilter: project.config.onStackTrace,
132-
ignoreStackEntries: fullStack ? [] : undefined,
133-
})
134-
},
135-
})
107+
printError(err: unknown, options: ErrorOptions = {}) {
108+
printError(err, this.ctx, this, options)
136109
}
137110

138111
clearHighlightCache(filename?: string) {

0 commit comments

Comments
 (0)