util: add subclass and null prototype support for errors in inspect · nodejs/node@0f615d4 (original) (raw)
`@@ -643,25 +643,9 @@ function formatRaw(ctx, value, recurseTimes, typedArray) {
`
643
643
`return ctx.stylize(base, 'date');
`
644
644
`}
`
645
645
`} else if (isError(value)) {
`
646
``
`-
// Make error with message first say the error.
`
647
``
`-
base = formatError(value);
`
648
``
`-
// Wrap the error in brackets in case it has no stack trace.
`
649
``
`-
const stackStart = base.indexOf('\n at');
`
650
``
`-
if (stackStart === -1) {
`
651
``
`` -
base = [${base}]
;
``
652
``
`-
}
`
653
``
`-
// The message and the stack have to be indented as well!
`
654
``
`-
if (ctx.indentationLvl !== 0) {
`
655
``
`-
const indentation = ' '.repeat(ctx.indentationLvl);
`
656
``
`` -
base = formatError(value).replace(/\n/g, \n${indentation}
);
``
657
``
`-
}
`
``
646
`+
base = formatError(value, constructor, tag, ctx);
`
658
647
`if (keys.length === 0)
`
659
648
`return base;
`
660
``
-
661
``
`-
if (ctx.compact === false && stackStart !== -1) {
`
662
``
`` -
braces[0] += ${base.slice(stackStart)}
;
``
663
``
`` -
base = [${base.slice(0, stackStart)}]
;
``
664
``
`-
}
`
665
649
`} else if (isAnyArrayBuffer(value)) {
`
666
650
`// Fast path for ArrayBuffer and SharedArrayBuffer.
`
667
651
`// Can't do the same for DataView because it has a non-primitive
`
`@@ -821,6 +805,52 @@ function formatRaw(ctx, value, recurseTimes, typedArray) {
`
821
805
`return res;
`
822
806
`}
`
823
807
``
``
808
`+
function formatError(err, constructor, tag, ctx) {
`
``
809
`+
// TODO(BridgeAR): Always show the error code if present.
`
``
810
`+
let stack = err.stack || errorToString(err);
`
``
811
+
``
812
`+
// A stack trace may contain arbitrary data. Only manipulate the output
`
``
813
`+
// for "regular errors" (errors that "look normal") for now.
`
``
814
`+
const name = err.name || 'Error';
`
``
815
`+
let len = name.length;
`
``
816
`+
if (constructor === null ||
`
``
817
`+
name.endsWith('Error') &&
`
``
818
`+
stack.startsWith(name) &&
`
``
819
`+
(stack.length === len || stack[len] === ':' || stack[len] === '\n')) {
`
``
820
`+
let fallback = 'Error';
`
``
821
`+
if (constructor === null) {
`
``
822
`+
const start = stack.match(/^([A-Z][a-z_ A-Z0-9[]()-]+)(?::|\n {4}at)/) ||
`
``
823
`+
stack.match(/^([a-z_A-Z0-9-]*Error)$/);
`
``
824
`+
fallback = start && start[1] || '';
`
``
825
`+
len = fallback.length;
`
``
826
`+
fallback = fallback || 'Error';
`
``
827
`+
}
`
``
828
`+
const prefix = getPrefix(constructor, tag, fallback).slice(0, -1);
`
``
829
`+
if (name !== prefix) {
`
``
830
`+
if (prefix.includes(name)) {
`
``
831
`+
if (len === 0) {
`
``
832
`` +
stack = ${prefix}: ${stack}
;
``
``
833
`+
} else {
`
``
834
`` +
stack = ${prefix}${stack.slice(len)}
;
``
``
835
`+
}
`
``
836
`+
} else {
`
``
837
`` +
stack = ${prefix} [${name}]${stack.slice(len)}
;
``
``
838
`+
}
`
``
839
`+
}
`
``
840
`+
}
`
``
841
`+
// Wrap the error in brackets in case it has no stack trace.
`
``
842
`+
const stackStart = stack.indexOf('\n at');
`
``
843
`+
if (stackStart === -1) {
`
``
844
`` +
stack = [${stack}]
;
``
``
845
`+
}
`
``
846
`+
// The message and the stack have to be indented as well!
`
``
847
`+
if (ctx.indentationLvl !== 0) {
`
``
848
`+
const indentation = ' '.repeat(ctx.indentationLvl);
`
``
849
`` +
stack = stack.replace(/\n/g, \n${indentation}
);
``
``
850
`+
}
`
``
851
`+
return stack;
`
``
852
`+
}
`
``
853
+
824
854
`function groupArrayElements(ctx, output) {
`
825
855
`let totalLength = 0;
`
826
856
`let maxLength = 0;
`
`@@ -968,10 +998,6 @@ function formatPrimitive(fn, value, ctx) {
`
968
998
`return fn(value.toString(), 'symbol');
`
969
999
`}
`
970
1000
``
971
``
`-
function formatError(value) {
`
972
``
`-
return value.stack || errorToString(value);
`
973
``
`-
}
`
974
``
-
975
1001
`function formatNamespaceObject(ctx, value, recurseTimes, keys) {
`
976
1002
`const output = new Array(keys.length);
`
977
1003
`for (var i = 0; i < keys.length; i++) {
`