mirror of
https://github.com/denoland/deno.git
synced 2025-03-03 09:31:22 -05:00
fix(cli/js/error_stack): Expose Error.captureStackTrace (#5254)
This commit is contained in:
parent
ce246d8d85
commit
49c7077401
4 changed files with 56 additions and 41 deletions
|
@ -214,51 +214,47 @@ function evaluateCallSite(callSite: CallSite): CallSiteEval {
|
|||
};
|
||||
}
|
||||
|
||||
function prepareStackTrace(
|
||||
error: Error,
|
||||
structuredStackTrace: CallSite[]
|
||||
): string {
|
||||
function prepareStackTrace(error: Error, callSites: CallSite[]): string {
|
||||
const mappedCallSites = callSites.map(
|
||||
(callSite): CallSite => {
|
||||
const fileName = callSite.getFileName();
|
||||
const lineNumber = callSite.getLineNumber();
|
||||
const columnNumber = callSite.getColumnNumber();
|
||||
if (fileName && lineNumber != null && columnNumber != null) {
|
||||
return patchCallSite(
|
||||
callSite,
|
||||
applySourceMap({
|
||||
fileName,
|
||||
lineNumber,
|
||||
columnNumber,
|
||||
})
|
||||
);
|
||||
}
|
||||
return callSite;
|
||||
}
|
||||
);
|
||||
Object.defineProperties(error, {
|
||||
__callSiteEvals: { value: [] },
|
||||
__formattedFrames: { value: [] },
|
||||
__callSiteEvals: { value: [], configurable: true },
|
||||
__formattedFrames: { value: [], configurable: true },
|
||||
});
|
||||
const errorString =
|
||||
`${error.name}: ${error.message}\n` +
|
||||
structuredStackTrace
|
||||
.map(
|
||||
(callSite): CallSite => {
|
||||
const fileName = callSite.getFileName();
|
||||
const lineNumber = callSite.getLineNumber();
|
||||
const columnNumber = callSite.getColumnNumber();
|
||||
if (fileName && lineNumber != null && columnNumber != null) {
|
||||
return patchCallSite(
|
||||
callSite,
|
||||
applySourceMap({
|
||||
fileName,
|
||||
lineNumber,
|
||||
columnNumber,
|
||||
})
|
||||
);
|
||||
}
|
||||
return callSite;
|
||||
}
|
||||
)
|
||||
.map((callSite): string => {
|
||||
// @ts-expect-error
|
||||
error.__callSiteEvals.push(Object.freeze(evaluateCallSite(callSite)));
|
||||
const isInternal =
|
||||
callSite.getFileName()?.startsWith("$deno$") ?? false;
|
||||
const string = callSiteToString(callSite, isInternal);
|
||||
// @ts-expect-error
|
||||
error.__formattedFrames.push(string);
|
||||
return ` at ${colors.stripColor(string)}`;
|
||||
})
|
||||
.join("\n");
|
||||
for (const callSite of mappedCallSites) {
|
||||
// @ts-expect-error
|
||||
error.__callSiteEvals.push(Object.freeze(evaluateCallSite(callSite)));
|
||||
const isInternal = callSite.getFileName()?.startsWith("$deno$") ?? false;
|
||||
// @ts-expect-error
|
||||
error.__formattedFrames.push(callSiteToString(callSite, isInternal));
|
||||
}
|
||||
// @ts-expect-error
|
||||
Object.freeze(error.__callSiteEvals);
|
||||
// @ts-expect-error
|
||||
Object.freeze(error.__formattedFrames);
|
||||
return errorString;
|
||||
return (
|
||||
`${error.name}: ${error.message}\n` +
|
||||
// @ts-expect-error
|
||||
error.__formattedFrames
|
||||
.map((s: string) => ` at ${colors.stripColor(s)}`)
|
||||
.join("\n")
|
||||
);
|
||||
}
|
||||
|
||||
// @internal
|
||||
|
|
8
cli/js/lib.deno.shared_globals.d.ts
vendored
8
cli/js/lib.deno.shared_globals.d.ts
vendored
|
@ -1481,3 +1481,11 @@ declare const AbortSignal: {
|
|||
prototype: AbortSignal;
|
||||
new (): AbortSignal;
|
||||
};
|
||||
|
||||
interface ErrorConstructor {
|
||||
/** See https://v8.dev/docs/stack-trace-api#stack-trace-collection-for-custom-exceptions. */
|
||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||
captureStackTrace(error: Object, constructor?: Function): void;
|
||||
// TODO(nayeemrmn): Support `Error.prepareStackTrace()`. We currently use this
|
||||
// internally in a way that makes it unavailable for users.
|
||||
}
|
||||
|
|
|
@ -948,7 +948,6 @@ export class Console {
|
|||
name: "Trace",
|
||||
message,
|
||||
};
|
||||
// @ts-expect-error
|
||||
Error.captureStackTrace(err, this.trace);
|
||||
this.error((err as Error).stack);
|
||||
};
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
||||
import { unitTest, assert } from "./test_util.ts";
|
||||
import { assert, assertEquals, unitTest } from "./test_util.ts";
|
||||
|
||||
// @ts-expect-error TypeScript (as of 3.7) does not support indexing namespaces by symbol
|
||||
const { setPrepareStackTrace } = Deno[Deno.internal];
|
||||
|
@ -96,6 +96,18 @@ unitTest(function prepareStackTrace(): void {
|
|||
assert(result.includes(".ts:"), "should remap to something in 'js/'");
|
||||
});
|
||||
|
||||
unitTest(function captureStackTrace(): void {
|
||||
function foo(): void {
|
||||
const error = new Error();
|
||||
const stack1 = error.stack!;
|
||||
Error.captureStackTrace(error, foo);
|
||||
const stack2 = error.stack!;
|
||||
// stack2 should be stack1 without the first frame.
|
||||
assertEquals(stack2, stack1.replace(/(?<=^[^\n]*\n)[^\n]*\n/, ""));
|
||||
}
|
||||
foo();
|
||||
});
|
||||
|
||||
unitTest(function applySourceMap(): void {
|
||||
const result = Deno.applySourceMap({
|
||||
fileName: "CLI_SNAPSHOT.js",
|
||||
|
|
Loading…
Add table
Reference in a new issue