mirror of
https://github.com/nodejs/node.git
synced 2026-10-14 10:26:26 -04:00
errors: refactor to use more primordials
PR-URL: https://github.com/nodejs/node/pull/35944 Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com> Reviewed-By: Ben Coe <bencoe@gmail.com> Reviewed-By: Rich Trott <rtrott@gmail.com>
This commit is contained in:
1 parent
c723e4cb0b
commit
e6e6070364
2 files changed
+79
-50
No files matched your search
+65
-40
@@ -11,31 +11,49 @@
|
||||
// message may change, the code should not.
|
||||
|
||||
const {
|
||||
ArrayFrom,
|
||||
ArrayIsArray,
|
||||
ArrayPrototypeIncludes,
|
||||
ArrayPrototypeIndexOf,
|
||||
ArrayPrototypeJoin,
|
||||
ArrayPrototypeMap,
|
||||
ArrayPrototypePop,
|
||||
ArrayPrototypePush,
|
||||
ArrayPrototypeSlice,
|
||||
ArrayPrototypeSplice,
|
||||
ArrayPrototypeUnshift,
|
||||
Error,
|
||||
ErrorCaptureStackTrace,
|
||||
ErrorPrototypeToString,
|
||||
JSONStringify,
|
||||
Map,
|
||||
MathAbs,
|
||||
MathMax,
|
||||
Number,
|
||||
NumberIsInteger,
|
||||
ObjectDefineProperty,
|
||||
ObjectKeys,
|
||||
RangeError,
|
||||
ReflectApply,
|
||||
RegExpPrototypeTest,
|
||||
SafeMap,
|
||||
SafeWeakMap,
|
||||
String,
|
||||
StringPrototypeEndsWith,
|
||||
StringPrototypeIncludes,
|
||||
StringPrototypeSlice,
|
||||
StringPrototypeSplit,
|
||||
StringPrototypeStartsWith,
|
||||
StringPrototypeToLowerCase,
|
||||
Symbol,
|
||||
SymbolFor,
|
||||
SyntaxError,
|
||||
TypeError,
|
||||
URIError,
|
||||
WeakMap,
|
||||
} = primordials;
|
||||
|
||||
const isWindows = process.platform === 'win32';
|
||||
|
||||
const messages = new Map();
|
||||
const messages = new SafeMap();
|
||||
const codes = {};
|
||||
|
||||
const classRegExp = /^([A-Z][a-z0-9]*)+$/;
|
||||
@@ -54,7 +72,7 @@ const kTypes = [
|
||||
];
|
||||
|
||||
const MainContextError = Error;
|
||||
const overrideStackTrace = new WeakMap();
|
||||
const overrideStackTrace = new SafeWeakMap();
|
||||
const kNoOverride = Symbol('kNoOverride');
|
||||
const prepareStackTrace = (globalThis, error, trace) => {
|
||||
// API for node internals to override error stack formatting
|
||||
@@ -370,8 +388,8 @@ function getMessage(key, args, self) {
|
||||
if (args.length === 0)
|
||||
return msg;
|
||||
|
||||
args.unshift(msg);
|
||||
return lazyInternalUtilInspect().format.apply(null, args);
|
||||
ArrayPrototypeUnshift(args, msg);
|
||||
return ReflectApply(lazyInternalUtilInspect().format, null, args);
|
||||
}
|
||||
|
||||
let uvBinding;
|
||||
@@ -644,9 +662,9 @@ function addNumericalSeparator(val) {
|
||||
let i = val.length;
|
||||
const start = val[0] === '-' ? 1 : 0;
|
||||
for (; i >= start + 4; i -= 3) {
|
||||
res = `_${val.slice(i - 3, i)}${res}`;
|
||||
res = `_${StringPrototypeSlice(val, i - 3, i)}${res}`;
|
||||
}
|
||||
return `${val.slice(0, i)}${res}`;
|
||||
return `${StringPrototypeSlice(val, 0, i)}${res}`;
|
||||
}
|
||||
|
||||
// Used to enhance the stack that will be picked up by the inspector
|
||||
@@ -681,7 +699,8 @@ const fatalExceptionStackEnhancers = {
|
||||
// ANSI escape sequences is not reliable.
|
||||
if (process.platform === 'win32') {
|
||||
const info = internalBinding('os').getOSInformation();
|
||||
const ver = info[2].split('.').map((a) => +a);
|
||||
const ver = ArrayPrototypeMap(StringPrototypeSplit(info[2], '.'),
|
||||
Number);
|
||||
if (ver[0] !== 10 || ver[2] < 14393) {
|
||||
useColors = false;
|
||||
}
|
||||
@@ -975,11 +994,11 @@ E('ERR_INVALID_ARG_TYPE',
|
||||
}
|
||||
|
||||
let msg = 'The ';
|
||||
if (name.endsWith(' argument')) {
|
||||
if (StringPrototypeEndsWith(name, ' argument')) {
|
||||
// For cases like 'first argument'
|
||||
msg += `${name} `;
|
||||
} else {
|
||||
const type = name.includes('.') ? 'property' : 'argument';
|
||||
const type = StringPrototypeIncludes(name, '.') ? 'property' : 'argument';
|
||||
msg += `"${name}" ${type} `;
|
||||
}
|
||||
msg += 'must be ';
|
||||
@@ -991,31 +1010,31 @@ E('ERR_INVALID_ARG_TYPE',
|
||||
for (const value of expected) {
|
||||
assert(typeof value === 'string',
|
||||
'All expected entries have to be of type string');
|
||||
if (kTypes.includes(value)) {
|
||||
types.push(value.toLowerCase());
|
||||
} else if (classRegExp.test(value)) {
|
||||
instances.push(value);
|
||||
if (ArrayPrototypeIncludes(kTypes, value)) {
|
||||
ArrayPrototypePush(types, StringPrototypeToLowerCase(value));
|
||||
} else if (RegExpPrototypeTest(classRegExp, value)) {
|
||||
ArrayPrototypePush(instances, value);
|
||||
} else {
|
||||
assert(value !== 'object',
|
||||
'The value "object" should be written as "Object"');
|
||||
other.push(value);
|
||||
ArrayPrototypePush(other, value);
|
||||
}
|
||||
}
|
||||
|
||||
// Special handle `object` in case other instances are allowed to outline
|
||||
// the differences between each other.
|
||||
if (instances.length > 0) {
|
||||
const pos = types.indexOf('object');
|
||||
const pos = ArrayPrototypeIndexOf(types, 'object');
|
||||
if (pos !== -1) {
|
||||
types.splice(pos, 1);
|
||||
instances.push('Object');
|
||||
ArrayPrototypeSplice(types, pos, 1);
|
||||
ArrayPrototypePush(instances, 'Object');
|
||||
}
|
||||
}
|
||||
|
||||
if (types.length > 0) {
|
||||
if (types.length > 2) {
|
||||
const last = types.pop();
|
||||
msg += `one of type ${types.join(', ')}, or ${last}`;
|
||||
const last = ArrayPrototypePop(types);
|
||||
msg += `one of type ${ArrayPrototypeJoin(types, ', ')}, or ${last}`;
|
||||
} else if (types.length === 2) {
|
||||
msg += `one of type ${types[0]} or ${types[1]}`;
|
||||
} else {
|
||||
@@ -1027,8 +1046,9 @@ E('ERR_INVALID_ARG_TYPE',
|
||||
|
||||
if (instances.length > 0) {
|
||||
if (instances.length > 2) {
|
||||
const last = instances.pop();
|
||||
msg += `an instance of ${instances.join(', ')}, or ${last}`;
|
||||
const last = ArrayPrototypePop(instances);
|
||||
msg +=
|
||||
`an instance of ${ArrayPrototypeJoin(instances, ', ')}, or ${last}`;
|
||||
} else {
|
||||
msg += `an instance of ${instances[0]}`;
|
||||
if (instances.length === 2) {
|
||||
@@ -1041,12 +1061,12 @@ E('ERR_INVALID_ARG_TYPE',
|
||||
|
||||
if (other.length > 0) {
|
||||
if (other.length > 2) {
|
||||
const last = other.pop();
|
||||
msg += `one of ${other.join(', ')}, or ${last}`;
|
||||
const last = ArrayPrototypePop(other);
|
||||
msg += `one of ${ArrayPrototypeJoin(other, ', ')}, or ${last}`;
|
||||
} else if (other.length === 2) {
|
||||
msg += `one of ${other[0]} or ${other[1]}`;
|
||||
} else {
|
||||
if (other[0].toLowerCase() !== other[0])
|
||||
if (StringPrototypeToLowerCase(other[0]) !== other[0])
|
||||
msg += 'an ';
|
||||
msg += `${other[0]}`;
|
||||
}
|
||||
@@ -1068,7 +1088,7 @@ E('ERR_INVALID_ARG_TYPE',
|
||||
let inspected = lazyInternalUtilInspect()
|
||||
.inspect(actual, { colors: false });
|
||||
if (inspected.length > 25)
|
||||
inspected = `${inspected.slice(0, 25)}...`;
|
||||
inspected = `${StringPrototypeSlice(inspected, 0, 25)}...`;
|
||||
msg += `. Received type ${typeof actual} (${inspected})`;
|
||||
}
|
||||
return msg;
|
||||
@@ -1076,9 +1096,9 @@ E('ERR_INVALID_ARG_TYPE',
|
||||
E('ERR_INVALID_ARG_VALUE', (name, value, reason = 'is invalid') => {
|
||||
let inspected = lazyInternalUtilInspect().inspect(value);
|
||||
if (inspected.length > 128) {
|
||||
inspected = `${inspected.slice(0, 128)}...`;
|
||||
inspected = `${StringPrototypeSlice(inspected, 0, 128)}...`;
|
||||
}
|
||||
const type = name.includes('.') ? 'property' : 'argument';
|
||||
const type = StringPrototypeIncludes(name, '.') ? 'property' : 'argument';
|
||||
return `The ${type} '${name}' ${reason}. Received ${inspected}`;
|
||||
}, TypeError, RangeError);
|
||||
E('ERR_INVALID_ASYNC_ID', 'Invalid %s value: %s', RangeError);
|
||||
@@ -1195,9 +1215,10 @@ E('ERR_MANIFEST_ASSERT_INTEGRITY',
|
||||
moduleURL
|
||||
}" does not match the expected integrity.`;
|
||||
if (realIntegrities.size) {
|
||||
const sri = [...realIntegrities.entries()].map(([alg, dgs]) => {
|
||||
return `${alg}-${dgs}`;
|
||||
}).join(' ');
|
||||
const sri = ArrayPrototypeJoin(
|
||||
ArrayFrom(realIntegrities.entries(), ([alg, dgs]) => `${alg}-${dgs}`),
|
||||
' '
|
||||
);
|
||||
msg += ` Integrities found are: ${sri}`;
|
||||
} else {
|
||||
msg += ' The resource was not found in the policy.';
|
||||
@@ -1225,8 +1246,11 @@ E('ERR_MISSING_ARGS',
|
||||
let msg = 'The ';
|
||||
const len = args.length;
|
||||
const wrap = (a) => `"${a}"`;
|
||||
args = args.map(
|
||||
(a) => (ArrayIsArray(a) ? a.map(wrap).join(' or ') : wrap(a))
|
||||
args = ArrayPrototypeMap(
|
||||
args,
|
||||
(a) => (ArrayIsArray(a) ?
|
||||
ArrayPrototypeJoin(ArrayPrototypeMap(a, wrap), ' or ') :
|
||||
wrap(a))
|
||||
);
|
||||
switch (len) {
|
||||
case 1:
|
||||
@@ -1236,7 +1260,7 @@ E('ERR_MISSING_ARGS',
|
||||
msg += `${args[0]} and ${args[1]} arguments`;
|
||||
break;
|
||||
default:
|
||||
msg += args.slice(0, len - 1).join(', ');
|
||||
msg += ArrayPrototypeJoin(ArrayPrototypeSlice(args, 0, len - 1), ', ');
|
||||
msg += `, and ${args[len - 1]} arguments`;
|
||||
break;
|
||||
}
|
||||
@@ -1299,9 +1323,10 @@ E('ERR_QUIC_INVALID_TLS_SESSION_TICKET',
|
||||
'Invalid TLS session ticket', Error);
|
||||
E('ERR_QUIC_VERSION_NEGOTIATION',
|
||||
(version, requestedVersions, supportedVersions) => {
|
||||
const requestedVersionsString = ArrayPrototypeJoin(requestedVersions, ', ');
|
||||
return 'QUIC session received version negotiation from server. ' +
|
||||
`Version: ${version}. Requested: ${requestedVersions.join(', ')} ` +
|
||||
`Supported: ${supportedVersions.join(', ')}`;
|
||||
`Version: ${version}. Requested: ${requestedVersionsString} ` +
|
||||
`Supported: ${ArrayPrototypeJoin(supportedVersions, ', ')}`;
|
||||
},
|
||||
Error);
|
||||
E('ERR_REQUIRE_ESM',
|
||||
@@ -1447,7 +1472,7 @@ E('ERR_VM_MODULE_STATUS', 'Module status %s', Error);
|
||||
E('ERR_WASI_ALREADY_STARTED', 'WASI instance has already started', Error);
|
||||
E('ERR_WORKER_INIT_FAILED', 'Worker initialization failure: %s', Error);
|
||||
E('ERR_WORKER_INVALID_EXEC_ARGV', (errors, msg = 'invalid execArgv flags') =>
|
||||
`Initiated Worker with ${msg}: ${errors.join(', ')}`,
|
||||
`Initiated Worker with ${msg}: ${ArrayPrototypeJoin(errors, ', ')}`,
|
||||
Error);
|
||||
E('ERR_WORKER_NOT_RUNNING', 'Worker instance not running', Error);
|
||||
E('ERR_WORKER_OUT_OF_MEMORY',
|
||||
@@ -1455,10 +1480,10 @@ E('ERR_WORKER_OUT_OF_MEMORY',
|
||||
E('ERR_WORKER_PATH', (filename) =>
|
||||
'The worker script or module filename must be an absolute path or a ' +
|
||||
'relative path starting with \'./\' or \'../\'.' +
|
||||
(filename.startsWith('file://') ?
|
||||
(StringPrototypeStartsWith(filename, 'file://') ?
|
||||
' Wrap file:// URLs with `new URL`.' : ''
|
||||
) +
|
||||
(filename.startsWith('data:text/javascript') ?
|
||||
(StringPrototypeStartsWith(filename, 'data:text/javascript') ?
|
||||
' Wrap data: URLs with `new URL`.' : ''
|
||||
) +
|
||||
` Received "${filename}"`,
|
||||
|
||||
@@ -2,7 +2,12 @@
|
||||
|
||||
const {
|
||||
ArrayPrototypeIndexOf,
|
||||
Error,
|
||||
ArrayPrototypeJoin,
|
||||
ArrayPrototypeMap,
|
||||
ErrorPrototypeToString,
|
||||
StringPrototypeRepeat,
|
||||
StringPrototypeSlice,
|
||||
StringPrototypeSplit,
|
||||
StringPrototypeStartsWith,
|
||||
} = primordials;
|
||||
|
||||
@@ -21,7 +26,6 @@ const { fileURLToPath } = require('internal/url');
|
||||
|
||||
// Create a prettified stacktrace, inserting context from source maps
|
||||
// if possible.
|
||||
const ErrorToString = Error.prototype.toString; // Capture original toString.
|
||||
const prepareStackTrace = (globalThis, error, trace) => {
|
||||
// API for node internals to override error stack formatting
|
||||
// without interfering with userland code.
|
||||
@@ -36,7 +40,7 @@ const prepareStackTrace = (globalThis, error, trace) => {
|
||||
maybeOverridePrepareStackTrace(globalThis, error, trace);
|
||||
if (globalOverride !== kNoOverride) return globalOverride;
|
||||
|
||||
const errorString = ErrorToString.call(error);
|
||||
const errorString = ErrorPrototypeToString(error);
|
||||
|
||||
if (trace.length === 0) {
|
||||
return errorString;
|
||||
@@ -45,7 +49,7 @@ const prepareStackTrace = (globalThis, error, trace) => {
|
||||
let errorSource = '';
|
||||
let firstLine;
|
||||
let firstColumn;
|
||||
const preparedTrace = trace.map((t, i) => {
|
||||
const preparedTrace = ArrayPrototypeJoin(ArrayPrototypeMap(trace, (t, i) => {
|
||||
if (i === 0) {
|
||||
firstLine = t.getLineNumber();
|
||||
firstColumn = t.getColumnNumber();
|
||||
@@ -88,8 +92,8 @@ const prepareStackTrace = (globalThis, error, trace) => {
|
||||
debug(err.stack);
|
||||
}
|
||||
return str;
|
||||
});
|
||||
return `${errorSource}${errorString}\n at ${preparedTrace.join('')}`;
|
||||
}), '');
|
||||
return `${errorSource}${errorString}\n at ${preparedTrace}`;
|
||||
};
|
||||
|
||||
// Places a snippet of code from where the exception was originally thrown
|
||||
@@ -118,18 +122,18 @@ function getErrorSource(payload, originalSource, firstLine, firstColumn) {
|
||||
}
|
||||
}
|
||||
|
||||
const lines = source.split(/\r?\n/, firstLine);
|
||||
const lines = StringPrototypeSplit(source, /\r?\n/, firstLine);
|
||||
const line = lines[firstLine - 1];
|
||||
if (!line) return exceptionLine;
|
||||
|
||||
// Display ^ in appropriate position, regardless of whether tabs or
|
||||
// spaces are used:
|
||||
let prefix = '';
|
||||
for (const character of line.slice(0, firstColumn)) {
|
||||
for (const character of StringPrototypeSlice(line, 0, firstColumn)) {
|
||||
prefix += (character === '\t') ? '\t' :
|
||||
' '.repeat(getStringWidth(character));
|
||||
StringPrototypeRepeat(' ', getStringWidth(character));
|
||||
}
|
||||
prefix = prefix.slice(0, -1); // The last character is the '^'.
|
||||
prefix = StringPrototypeSlice(prefix, 0, -1); // The last character is '^'.
|
||||
|
||||
exceptionLine =
|
||||
`${originalSourceNoScheme}:${firstLine}\n${line}\n${prefix}^\n\n`;
|
||||
|
||||
Reference in new issue
Block a user