diff options
author | Ruben Bridgewater <ruben@bridgewater.de> | 2018-04-13 15:56:37 +0200 |
---|---|---|
committer | Ruben Bridgewater <ruben@bridgewater.de> | 2018-04-20 00:02:45 +0200 |
commit | ad1d1057f9362558fcc76b603458374f5f5a31c5 (patch) | |
tree | d301e016bcaee9ee80d9a0379c9c7f506013d122 /lib/util.js | |
parent | 94596560c2556fae614ef237ed0ff2f749b14651 (diff) | |
download | android-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.js | 74 |
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`; |