lib: stop using prepareStackTrace
PR-URL: https://github.com/nodejs/node/pull/29777 Reviewed-By: Ben Coe <bencoe@gmail.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
This commit is contained in:
parent
48a1f75a90
commit
70c2444155
@ -23,13 +23,16 @@
|
|||||||
const { Object, ObjectPrototype } = primordials;
|
const { Object, ObjectPrototype } = primordials;
|
||||||
|
|
||||||
const { Buffer } = require('buffer');
|
const { Buffer } = require('buffer');
|
||||||
const { codes: {
|
const {
|
||||||
ERR_AMBIGUOUS_ARGUMENT,
|
codes: {
|
||||||
ERR_INVALID_ARG_TYPE,
|
ERR_AMBIGUOUS_ARGUMENT,
|
||||||
ERR_INVALID_ARG_VALUE,
|
ERR_INVALID_ARG_TYPE,
|
||||||
ERR_INVALID_RETURN_VALUE,
|
ERR_INVALID_ARG_VALUE,
|
||||||
ERR_MISSING_ARGS
|
ERR_INVALID_RETURN_VALUE,
|
||||||
} } = require('internal/errors');
|
ERR_MISSING_ARGS,
|
||||||
|
},
|
||||||
|
overrideStackTrace,
|
||||||
|
} = require('internal/errors');
|
||||||
const AssertionError = require('internal/assert/assertion_error');
|
const AssertionError = require('internal/assert/assertion_error');
|
||||||
const { openSync, closeSync, readSync } = require('fs');
|
const { openSync, closeSync, readSync } = require('fs');
|
||||||
const { inspect } = require('internal/util/inspect');
|
const { inspect } = require('internal/util/inspect');
|
||||||
@ -262,10 +265,8 @@ function getErrMessage(message, fn) {
|
|||||||
Error.captureStackTrace(err, fn);
|
Error.captureStackTrace(err, fn);
|
||||||
Error.stackTraceLimit = tmpLimit;
|
Error.stackTraceLimit = tmpLimit;
|
||||||
|
|
||||||
const tmpPrepare = Error.prepareStackTrace;
|
overrideStackTrace.set(err, (_, stack) => stack);
|
||||||
Error.prepareStackTrace = (_, stack) => stack;
|
|
||||||
const call = err.stack[0];
|
const call = err.stack[0];
|
||||||
Error.prepareStackTrace = tmpPrepare;
|
|
||||||
|
|
||||||
const filename = call.getFileName();
|
const filename = call.getFileName();
|
||||||
const line = call.getLineNumber() - 1;
|
const line = call.getLineNumber() - 1;
|
||||||
|
@ -21,9 +21,18 @@ const { kMaxLength } = internalBinding('buffer');
|
|||||||
|
|
||||||
const MainContextError = Error;
|
const MainContextError = Error;
|
||||||
const ErrorToString = Error.prototype.toString;
|
const ErrorToString = Error.prototype.toString;
|
||||||
// Polyfill of V8's Error.prepareStackTrace API.
|
const overrideStackTrace = new WeakMap();
|
||||||
// https://crbug.com/v8/7848
|
|
||||||
const prepareStackTrace = (globalThis, error, trace) => {
|
const prepareStackTrace = (globalThis, error, trace) => {
|
||||||
|
// API for node internals to override error stack formatting
|
||||||
|
// without interfering with userland code.
|
||||||
|
if (overrideStackTrace.has(error)) {
|
||||||
|
const f = overrideStackTrace.get(error);
|
||||||
|
overrideStackTrace.delete(error);
|
||||||
|
return f(error, trace);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Polyfill of V8's Error.prepareStackTrace API.
|
||||||
|
// https://crbug.com/v8/7848
|
||||||
// `globalThis` is the global that contains the constructor which
|
// `globalThis` is the global that contains the constructor which
|
||||||
// created `error`.
|
// created `error`.
|
||||||
if (typeof globalThis.Error.prepareStackTrace === 'function') {
|
if (typeof globalThis.Error.prepareStackTrace === 'function') {
|
||||||
@ -36,6 +45,11 @@ const prepareStackTrace = (globalThis, error, trace) => {
|
|||||||
return MainContextError.prepareStackTrace(error, trace);
|
return MainContextError.prepareStackTrace(error, trace);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Normal error formatting:
|
||||||
|
//
|
||||||
|
// Error: Message
|
||||||
|
// at function (file)
|
||||||
|
// at file
|
||||||
const errorString = ErrorToString.call(error);
|
const errorString = ErrorToString.call(error);
|
||||||
if (trace.length === 0) {
|
if (trace.length === 0) {
|
||||||
return errorString;
|
return errorString;
|
||||||
@ -680,6 +694,7 @@ module.exports = {
|
|||||||
// This is exported only to facilitate testing.
|
// This is exported only to facilitate testing.
|
||||||
E,
|
E,
|
||||||
prepareStackTrace,
|
prepareStackTrace,
|
||||||
|
overrideStackTrace,
|
||||||
kEnhanceStackBeforeInspector,
|
kEnhanceStackBeforeInspector,
|
||||||
fatalExceptionStackEnhancers
|
fatalExceptionStackEnhancers
|
||||||
};
|
};
|
||||||
|
@ -7,7 +7,8 @@ const {
|
|||||||
ERR_NO_CRYPTO,
|
ERR_NO_CRYPTO,
|
||||||
ERR_UNKNOWN_SIGNAL
|
ERR_UNKNOWN_SIGNAL
|
||||||
},
|
},
|
||||||
uvErrmapGet
|
uvErrmapGet,
|
||||||
|
overrideStackTrace,
|
||||||
} = require('internal/errors');
|
} = require('internal/errors');
|
||||||
const { signals } = internalBinding('constants').os;
|
const { signals } = internalBinding('constants').os;
|
||||||
const {
|
const {
|
||||||
@ -338,15 +339,13 @@ function isInsideNodeModules() {
|
|||||||
// side-effect-free. Since this is currently only used for a deprecated API,
|
// side-effect-free. Since this is currently only used for a deprecated API,
|
||||||
// the perf implications should be okay.
|
// the perf implications should be okay.
|
||||||
getStructuredStack = runInNewContext(`(function() {
|
getStructuredStack = runInNewContext(`(function() {
|
||||||
Error.prepareStackTrace = function(err, trace) {
|
|
||||||
return trace;
|
|
||||||
};
|
|
||||||
Error.stackTraceLimit = Infinity;
|
Error.stackTraceLimit = Infinity;
|
||||||
|
|
||||||
return function structuredStack() {
|
return function structuredStack() {
|
||||||
return new Error().stack;
|
const e = new Error();
|
||||||
|
overrideStackTrace.set(e, (err, trace) => trace);
|
||||||
|
return e.stack;
|
||||||
};
|
};
|
||||||
})()`, {}, { filename: 'structured-stack' });
|
})()`, { overrideStackTrace }, { filename: 'structured-stack' });
|
||||||
}
|
}
|
||||||
|
|
||||||
const stack = getStructuredStack();
|
const stack = getStructuredStack();
|
||||||
|
64
lib/repl.js
64
lib/repl.js
@ -69,12 +69,15 @@ const CJSModule = require('internal/modules/cjs/loader').Module;
|
|||||||
const domain = require('domain');
|
const domain = require('domain');
|
||||||
const debug = require('internal/util/debuglog').debuglog('repl');
|
const debug = require('internal/util/debuglog').debuglog('repl');
|
||||||
const {
|
const {
|
||||||
ERR_CANNOT_WATCH_SIGINT,
|
codes: {
|
||||||
ERR_INVALID_ARG_TYPE,
|
ERR_CANNOT_WATCH_SIGINT,
|
||||||
ERR_INVALID_REPL_EVAL_CONFIG,
|
ERR_INVALID_ARG_TYPE,
|
||||||
ERR_INVALID_REPL_INPUT,
|
ERR_INVALID_REPL_EVAL_CONFIG,
|
||||||
ERR_SCRIPT_EXECUTION_INTERRUPTED
|
ERR_INVALID_REPL_INPUT,
|
||||||
} = require('internal/errors').codes;
|
ERR_SCRIPT_EXECUTION_INTERRUPTED,
|
||||||
|
},
|
||||||
|
overrideStackTrace,
|
||||||
|
} = require('internal/errors');
|
||||||
const { sendInspectorCommand } = require('internal/util/inspector');
|
const { sendInspectorCommand } = require('internal/util/inspector');
|
||||||
const experimentalREPLAwait = require('internal/options').getOptionValue(
|
const experimentalREPLAwait = require('internal/options').getOptionValue(
|
||||||
'--experimental-repl-await'
|
'--experimental-repl-await'
|
||||||
@ -473,10 +476,29 @@ function REPLServer(prompt,
|
|||||||
let errStack = '';
|
let errStack = '';
|
||||||
|
|
||||||
if (typeof e === 'object' && e !== null) {
|
if (typeof e === 'object' && e !== null) {
|
||||||
const pstrace = Error.prepareStackTrace;
|
overrideStackTrace.set(e, (error, stackFrames) => {
|
||||||
Error.prepareStackTrace = prepareStackTrace(pstrace);
|
let frames;
|
||||||
|
if (typeof stackFrames === 'object') {
|
||||||
|
// Search from the bottom of the call stack to
|
||||||
|
// find the first frame with a null function name
|
||||||
|
const idx = stackFrames
|
||||||
|
.reverse()
|
||||||
|
.findIndex((frame) => frame.getFunctionName() === null);
|
||||||
|
// If found, get rid of it and everything below it
|
||||||
|
frames = stackFrames.splice(idx + 1);
|
||||||
|
} else {
|
||||||
|
frames = stackFrames;
|
||||||
|
}
|
||||||
|
// FIXME(devsnek): this is inconsistent with the checks
|
||||||
|
// that the real prepareStackTrace dispatch uses in
|
||||||
|
// lib/internal/errors.js.
|
||||||
|
if (typeof Error.prepareStackTrace === 'function') {
|
||||||
|
return Error.prepareStackTrace(error, frames);
|
||||||
|
}
|
||||||
|
frames.push(error);
|
||||||
|
return frames.reverse().join('\n at ');
|
||||||
|
});
|
||||||
decorateErrorStack(e);
|
decorateErrorStack(e);
|
||||||
Error.prepareStackTrace = pstrace;
|
|
||||||
|
|
||||||
if (e.domainThrown) {
|
if (e.domainThrown) {
|
||||||
delete e.domain;
|
delete e.domain;
|
||||||
@ -590,30 +612,6 @@ function REPLServer(prompt,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function filterInternalStackFrames(structuredStack) {
|
|
||||||
// Search from the bottom of the call stack to
|
|
||||||
// find the first frame with a null function name
|
|
||||||
if (typeof structuredStack !== 'object')
|
|
||||||
return structuredStack;
|
|
||||||
const idx = structuredStack.reverse().findIndex(
|
|
||||||
(frame) => frame.getFunctionName() === null);
|
|
||||||
|
|
||||||
// If found, get rid of it and everything below it
|
|
||||||
structuredStack = structuredStack.splice(idx + 1);
|
|
||||||
return structuredStack;
|
|
||||||
}
|
|
||||||
|
|
||||||
function prepareStackTrace(fn) {
|
|
||||||
return (error, stackFrames) => {
|
|
||||||
const frames = filterInternalStackFrames(stackFrames);
|
|
||||||
if (fn) {
|
|
||||||
return fn(error, frames);
|
|
||||||
}
|
|
||||||
frames.push(error);
|
|
||||||
return frames.reverse().join('\n at ');
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function _parseREPLKeyword(keyword, rest) {
|
function _parseREPLKeyword(keyword, rest) {
|
||||||
const cmd = this.commands[keyword];
|
const cmd = this.commands[keyword];
|
||||||
if (cmd) {
|
if (cmd) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user