From 27a808877e0110e32ea790c08d4527c139829fdb Mon Sep 17 00:00:00 2001 From: Vladimir Sheremet Date: Tue, 30 Aug 2022 10:17:50 +0300 Subject: [PATCH 1/2] fix: don't throw on null error, hide JSON results warning --- packages/vitest/src/integrations/vi.ts | 4 ++-- packages/vitest/src/node/cache/results.ts | 9 ++++++--- packages/vitest/src/node/core.ts | 7 +------ packages/vitest/src/node/state.ts | 11 +++++++++-- packages/vitest/src/utils/base.ts | 18 ++++++++++++++++++ 5 files changed, 36 insertions(+), 13 deletions(-) diff --git a/packages/vitest/src/integrations/vi.ts b/packages/vitest/src/integrations/vi.ts index 086926d24bac..889aa192b5a8 100644 --- a/packages/vitest/src/integrations/vi.ts +++ b/packages/vitest/src/integrations/vi.ts @@ -1,7 +1,7 @@ import type { FakeTimerInstallOpts } from '@sinonjs/fake-timers' import { parseStacktrace } from '../utils/source-map' import type { VitestMocker } from '../runtime/mocker' -import { getWorkerState, resetModules, setTimeout } from '../utils' +import { createSimpleError, getWorkerState, resetModules, setTimeout } from '../utils' import { FakeTimers } from './mock/timers' import type { EnhancedSpy, MaybeMocked, MaybeMockedDeep, MaybePartiallyMocked, MaybePartiallyMockedDeep } from './spy' import { fn, isMockFunction, spies, spyOn } from './spy' @@ -108,7 +108,7 @@ class VitestUtils { fn = fn private getImporter() { - const err = new Error('mock') + const err = createSimpleError('mock', 3) const [,, importer] = parseStacktrace(err, true) return importer.file } diff --git a/packages/vitest/src/node/cache/results.ts b/packages/vitest/src/node/cache/results.ts index d5b784989b87..025c63aea3c9 100644 --- a/packages/vitest/src/node/cache/results.ts +++ b/packages/vitest/src/node/cache/results.ts @@ -34,9 +34,12 @@ export class ResultsCache { if (fs.existsSync(this.cachePath)) { const resultsCache = await fs.promises.readFile(this.cachePath, 'utf8') - const { results, version } = JSON.parse(resultsCache) - this.cache = new Map(results) - this.version = version + try { + const { results, version } = JSON.parse(resultsCache) + this.cache = new Map(results) + this.version = version + } + catch {} } } diff --git a/packages/vitest/src/node/core.ts b/packages/vitest/src/node/core.ts index 595823d147d2..d308868a57c2 100644 --- a/packages/vitest/src/node/core.ts +++ b/packages/vitest/src/node/core.ts @@ -106,12 +106,7 @@ export class Vitest { this.runningPromise = undefined this.cache.results.setConfig(resolved.root, resolved.cache) - try { - await this.cache.results.readFromCache() - } - catch (err) { - this.logger.error(`[vitest] Error, while trying to parse cache in ${this.cache.results.getCachePath()}:`, err) - } + await this.cache.results.readFromCache() } async initCoverageProvider() { diff --git a/packages/vitest/src/node/state.ts b/packages/vitest/src/node/state.ts index 54dc6ea31d40..bb4d1d796367 100644 --- a/packages/vitest/src/node/state.ts +++ b/packages/vitest/src/node/state.ts @@ -1,6 +1,7 @@ import type { ErrorWithDiff, File, Task, TaskResultPack, UserConsoleLog } from '../types' // can't import actual functions from utils, because it's incompatible with @vitest/browsers import type { AggregateError as AggregateErrorPonyfill } from '../utils' +import { createSimpleError } from '../utils' interface CollectingPromise { promise: Promise @@ -24,10 +25,16 @@ export class StateManager { errorsSet = new Set() catchError(err: unknown, type: string): void { + if (err == null) + err = createSimpleError('Unknown "null" error thrown') + if (isAggregateError(err)) - return err.errors.forEach(error => this.catchError(error, type)); + return err.errors.forEach(error => this.catchError(error, type)) + + if (typeof err !== 'object') + err = new Error(String(err)) - (err as ErrorWithDiff).type = type + ;(err as ErrorWithDiff).type = type this.errorsSet.add(err) } diff --git a/packages/vitest/src/utils/base.ts b/packages/vitest/src/utils/base.ts index bfe92430b3de..ca98025f18ff 100644 --- a/packages/vitest/src/utils/base.ts +++ b/packages/vitest/src/utils/base.ts @@ -177,3 +177,21 @@ export function shuffle(array: T[], seed = RealDate.now()): T[] { return array } + +// removes stack trace from error, when we don't really need it +// by default stack trace limit is 100 in vitest, but we might +// create errors just to get the last line of stack trace behind the scenes +export function createSimpleError(message?: string, limit = 0) { + if (!('stackTraceLimit' in Error)) { + const err = new Error(message) + if (limit === 0) + err.stack = '' + return err + } + + const oldLimit = Error.stackTraceLimit + Error.stackTraceLimit = limit + const err = new Error(message) + Error.stackTraceLimit = oldLimit + return err +} From 2fc24f6f41b02bf5c7965062cd333d3faa9cc540 Mon Sep 17 00:00:00 2001 From: Vladimir Sheremet Date: Sun, 4 Sep 2022 10:45:03 +0300 Subject: [PATCH 2/2] refactor: rename createSimpleError -> createErrorWithTraceLimit --- packages/vitest/src/integrations/vi.ts | 5 +++-- packages/vitest/src/node/state.ts | 4 ++-- packages/vitest/src/utils/base.ts | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/packages/vitest/src/integrations/vi.ts b/packages/vitest/src/integrations/vi.ts index 889aa192b5a8..7e13e05c3d23 100644 --- a/packages/vitest/src/integrations/vi.ts +++ b/packages/vitest/src/integrations/vi.ts @@ -1,7 +1,8 @@ import type { FakeTimerInstallOpts } from '@sinonjs/fake-timers' import { parseStacktrace } from '../utils/source-map' import type { VitestMocker } from '../runtime/mocker' -import { createSimpleError, getWorkerState, resetModules, setTimeout } from '../utils' +import { getWorkerState, resetModules, setTimeout } from '../utils' +import { createErrorWithTraceLimit } from '../utils/base' import { FakeTimers } from './mock/timers' import type { EnhancedSpy, MaybeMocked, MaybeMockedDeep, MaybePartiallyMocked, MaybePartiallyMockedDeep } from './spy' import { fn, isMockFunction, spies, spyOn } from './spy' @@ -108,7 +109,7 @@ class VitestUtils { fn = fn private getImporter() { - const err = createSimpleError('mock', 3) + const err = createErrorWithTraceLimit('mock', 3) const [,, importer] = parseStacktrace(err, true) return importer.file } diff --git a/packages/vitest/src/node/state.ts b/packages/vitest/src/node/state.ts index bb4d1d796367..b05adfb8ed1b 100644 --- a/packages/vitest/src/node/state.ts +++ b/packages/vitest/src/node/state.ts @@ -1,7 +1,7 @@ import type { ErrorWithDiff, File, Task, TaskResultPack, UserConsoleLog } from '../types' // can't import actual functions from utils, because it's incompatible with @vitest/browsers import type { AggregateError as AggregateErrorPonyfill } from '../utils' -import { createSimpleError } from '../utils' +import { createErrorWithTraceLimit } from '../utils/base' interface CollectingPromise { promise: Promise @@ -26,7 +26,7 @@ export class StateManager { catchError(err: unknown, type: string): void { if (err == null) - err = createSimpleError('Unknown "null" error thrown') + err = createErrorWithTraceLimit('Unknown "null" error thrown') if (isAggregateError(err)) return err.errors.forEach(error => this.catchError(error, type)) diff --git a/packages/vitest/src/utils/base.ts b/packages/vitest/src/utils/base.ts index ca98025f18ff..fbe5950cda42 100644 --- a/packages/vitest/src/utils/base.ts +++ b/packages/vitest/src/utils/base.ts @@ -181,7 +181,7 @@ export function shuffle(array: T[], seed = RealDate.now()): T[] { // removes stack trace from error, when we don't really need it // by default stack trace limit is 100 in vitest, but we might // create errors just to get the last line of stack trace behind the scenes -export function createSimpleError(message?: string, limit = 0) { +export function createErrorWithTraceLimit(message?: string, limit = 0) { if (!('stackTraceLimit' in Error)) { const err = new Error(message) if (limit === 0)