summaryrefslogtreecommitdiff
path: root/lib/util.js
diff options
context:
space:
mode:
authorRuben Bridgewater <ruben@bridgewater.de>2018-04-13 15:56:37 +0200
committerRuben Bridgewater <ruben@bridgewater.de>2018-04-20 00:02:45 +0200
commitad1d1057f9362558fcc76b603458374f5f5a31c5 (patch)
treed301e016bcaee9ee80d9a0379c9c7f506013d122 /lib/util.js
parent94596560c2556fae614ef237ed0ff2f749b14651 (diff)
downloadandroid-node-v8-ad1d1057f9362558fcc76b603458374f5f5a31c5.tar.gz
android-node-v8-ad1d1057f9362558fcc76b603458374f5f5a31c5.tar.bz2
android-node-v8-ad1d1057f9362558fcc76b603458374f5f5a31c5.zip
util: improve inspect performance
This improves a slow code part in `util.inspect` by directly retrieving the `Symbol.toStringTag` and by optimizing some code paths. PR-URL: https://github.com/nodejs/node/pull/20009 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Yuta Hiroto <hello@hiroppy.me> Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com>
Diffstat (limited to 'lib/util.js')
-rw-r--r--lib/util.js74
1 files changed, 53 insertions, 21 deletions
diff --git a/lib/util.js b/lib/util.js
index 762461402e..91404d254d 100644
--- a/lib/util.js
+++ b/lib/util.js
@@ -72,7 +72,6 @@ const {
customInspectSymbol,
deprecate,
getSystemErrorName: internalErrorName,
- getIdentificationOf,
isError,
promisify,
join,
@@ -396,6 +395,35 @@ function stylizeNoColor(str, styleType) {
return str;
}
+function getConstructorName(obj) {
+ while (obj) {
+ const descriptor = Object.getOwnPropertyDescriptor(obj, 'constructor');
+ if (descriptor !== undefined &&
+ typeof descriptor.value === 'function' &&
+ descriptor.value.name !== '') {
+ return descriptor.value.name;
+ }
+
+ obj = Object.getPrototypeOf(obj);
+ }
+
+ return '';
+}
+
+function getPrefix(constructor, tag) {
+ if (constructor !== '') {
+ if (tag !== '' && constructor !== tag) {
+ return `${constructor} [${tag}] `;
+ }
+ return `${constructor} `;
+ }
+
+ if (tag !== '')
+ return `[${tag}] `;
+
+ return '';
+}
+
function formatValue(ctx, value, recurseTimes, ln) {
// Primitive types cannot have properties
if (typeof value !== 'object' && typeof value !== 'function') {
@@ -475,15 +503,10 @@ function formatValue(ctx, value, recurseTimes, ln) {
const keyLength = keys.length + symbols.length;
- const { constructor, tag } = getIdentificationOf(value);
- let prefix = '';
- if (constructor && tag && constructor !== tag)
- prefix = `${constructor} [${tag}] `;
- else if (constructor)
- prefix = `${constructor} `;
- else if (tag)
- prefix = `[${tag}] `;
-
+ const constructor = getConstructorName(value);
+ let tag = value[Symbol.toStringTag];
+ if (typeof tag !== 'string')
+ tag = '';
let base = '';
let formatter = formatObject;
let braces;
@@ -496,22 +519,25 @@ function formatValue(ctx, value, recurseTimes, ln) {
noIterator = false;
if (Array.isArray(value)) {
// Only set the constructor for non ordinary ("Array [...]") arrays.
+ const prefix = getPrefix(constructor, tag);
braces = [`${prefix === 'Array ' ? '' : prefix}[`, ']'];
if (value.length === 0 && keyLength === 0)
return `${braces[0]}]`;
formatter = formatArray;
} else if (isSet(value)) {
+ const prefix = getPrefix(constructor, tag);
if (value.size === 0 && keyLength === 0)
return `${prefix}{}`;
braces = [`${prefix}{`, '}'];
formatter = formatSet;
} else if (isMap(value)) {
+ const prefix = getPrefix(constructor, tag);
if (value.size === 0 && keyLength === 0)
return `${prefix}{}`;
braces = [`${prefix}{`, '}'];
formatter = formatMap;
} else if (isTypedArray(value)) {
- braces = [`${prefix}[`, ']'];
+ braces = [`${getPrefix(constructor, tag)}[`, ']'];
formatter = formatTypedArray;
} else if (isMapIterator(value)) {
braces = [`[${tag}] {`, '}'];
@@ -543,11 +569,16 @@ function formatValue(ctx, value, recurseTimes, ln) {
}
if (noIterator) {
braces = ['{', '}'];
- if (prefix === 'Object ') {
+ if (constructor === 'Object') {
if (isArgumentsObject(value)) {
braces[0] = '[Arguments] {';
if (keyLength === 0)
return '[Arguments] {}';
+ } else if (tag !== '') {
+ braces[0] = `${getPrefix(constructor, tag)}{`;
+ if (keyLength === 0) {
+ return `${braces[0]}}`;
+ }
} else if (keyLength === 0) {
return '{}';
}
@@ -579,27 +610,28 @@ function formatValue(ctx, value, recurseTimes, ln) {
// Fast path for ArrayBuffer and SharedArrayBuffer.
// Can't do the same for DataView because it has a non-primitive
// .buffer property that we need to recurse for.
+ const prefix = getPrefix(constructor, tag);
if (keyLength === 0)
return prefix +
`{ byteLength: ${formatNumber(ctx.stylize, value.byteLength)} }`;
braces[0] = `${prefix}{`;
keys.unshift('byteLength');
} else if (isDataView(value)) {
- braces[0] = `${prefix}{`;
+ braces[0] = `${getPrefix(constructor, tag)}{`;
// .buffer goes last, it's not a primitive like the others.
keys.unshift('byteLength', 'byteOffset', 'buffer');
} else if (isPromise(value)) {
- braces[0] = `${prefix}{`;
+ braces[0] = `${getPrefix(constructor, tag)}{`;
formatter = formatPromise;
} else if (isWeakSet(value)) {
- braces[0] = `${prefix}{`;
+ braces[0] = `${getPrefix(constructor, tag)}{`;
if (ctx.showHidden) {
formatter = formatWeakSet;
} else {
extra = '[items unknown]';
}
} else if (isWeakMap(value)) {
- braces[0] = `${prefix}{`;
+ braces[0] = `${getPrefix(constructor, tag)}{`;
if (ctx.showHidden) {
formatter = formatWeakMap;
} else {
@@ -638,9 +670,9 @@ function formatValue(ctx, value, recurseTimes, ln) {
} else if (keyLength === 0) {
if (isExternal(value))
return ctx.stylize('[External]', 'special');
- return `${prefix}{}`;
+ return `${getPrefix(constructor, tag)}{}`;
} else {
- braces[0] = `${prefix}{`;
+ braces[0] = `${getPrefix(constructor, tag)}{`;
}
}
}
@@ -675,8 +707,8 @@ function formatNumber(fn, value) {
function formatPrimitive(fn, value, ctx) {
if (typeof value === 'string') {
if (ctx.compact === false &&
- value.length > MIN_LINE_LENGTH &&
- ctx.indentationLvl + value.length > ctx.breakLength) {
+ ctx.indentationLvl + value.length > ctx.breakLength &&
+ value.length > MIN_LINE_LENGTH) {
// eslint-disable-next-line max-len
const minLineLength = Math.max(ctx.breakLength - ctx.indentationLvl, MIN_LINE_LENGTH);
// eslint-disable-next-line max-len
@@ -695,9 +727,9 @@ function formatPrimitive(fn, value, ctx) {
// eslint-disable-next-line max-len, node-core/no-unescaped-regexp-dot
readableRegExps[divisor] = new RegExp(`(.|\\n){1,${divisor}}(\\s|$)|(\\n|.)+?(\\s|$)`, 'gm');
}
- const indent = ' '.repeat(ctx.indentationLvl);
const matches = value.match(readableRegExps[divisor]);
if (matches.length > 1) {
+ const indent = ' '.repeat(ctx.indentationLvl);
res += `${fn(strEscape(matches[0]), 'string')} +\n`;
for (var i = 1; i < matches.length - 1; i++) {
res += `${indent} ${fn(strEscape(matches[i]), 'string')} +\n`;