From 866d008f400efe93508532bd666ab4718219b3a4 Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Mon, 22 Apr 2019 06:13:16 +0200 Subject: [PATCH 1/2] util: improve `Symbol.toStringTag` handling Only special handle `Symbol.toStringTag` if the property is not enumerable or not the own property of the inspected object. --- lib/internal/util/inspect.js | 9 ++++++++- test/parallel/test-util-inspect.js | 16 ++++++++++++++-- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/lib/internal/util/inspect.js b/lib/internal/util/inspect.js index db54e232aa8a5b..d20c7b93c92ceb 100644 --- a/lib/internal/util/inspect.js +++ b/lib/internal/util/inspect.js @@ -574,8 +574,15 @@ function formatRaw(ctx, value, recurseTimes, typedArray) { const constructor = getConstructorName(value, ctx); let tag = value[Symbol.toStringTag]; - if (typeof tag !== 'string') + // Only list the tag in case it's non-enumerable / not an own property. + // Otherwise we'd print this twice. + if (typeof tag !== 'string' || + tag !== '' && + (ctx.showHidden ? hasOwnProperty : propertyIsEnumerable)( + value, Symbol.toStringTag + )) { tag = ''; + } let base = ''; let formatter = getEmptyFormatArray; let braces; diff --git a/test/parallel/test-util-inspect.js b/test/parallel/test-util-inspect.js index c1b6e3f98d4480..737f86b30ff8e0 100644 --- a/test/parallel/test-util-inspect.js +++ b/test/parallel/test-util-inspect.js @@ -1264,8 +1264,20 @@ util.inspect(process); { // @@toStringTag - assert.strictEqual(util.inspect({ [Symbol.toStringTag]: 'a' }), - "Object [a] { [Symbol(Symbol.toStringTag)]: 'a' }"); + const obj = { [Symbol.toStringTag]: 'a' }; + assert.strictEqual( + util.inspect(obj), + "{ [Symbol(Symbol.toStringTag)]: 'a' }" + ); + Object.defineProperty(obj, Symbol.toStringTag, { + value: 'a', + enumerable: false + }); + assert.strictEqual(util.inspect(obj), 'Object [a] {}'); + assert.strictEqual( + util.inspect(obj, { showHidden: true }), + "{ [Symbol(Symbol.toStringTag)]: 'a' }" + ); class Foo { constructor() { From d6d6624e8887799d620aea8a4f81bf21c163e2e8 Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Mon, 22 Apr 2019 04:21:02 +0200 Subject: [PATCH 2/2] util: rename setIteratorBraces to getIteratorBraces The function is actually a getter, not a setter. --- lib/internal/util/inspect.js | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/lib/internal/util/inspect.js b/lib/internal/util/inspect.js index d20c7b93c92ceb..4def103f42adeb 100644 --- a/lib/internal/util/inspect.js +++ b/lib/internal/util/inspect.js @@ -560,15 +560,6 @@ function formatValue(ctx, value, recurseTimes, typedArray) { return formatRaw(ctx, value, recurseTimes, typedArray); } -function setIteratorBraces(type, tag) { - if (tag !== `${type} Iterator`) { - if (tag !== '') - tag += '] ['; - tag += `${type} Iterator`; - } - return [`[${tag}] {`, '}']; -} - function formatRaw(ctx, value, recurseTimes, typedArray) { let keys; @@ -630,11 +621,11 @@ function formatRaw(ctx, value, recurseTimes, typedArray) { extrasType = kArrayExtrasType; } else if (isMapIterator(value)) { keys = getKeys(value, ctx.showHidden); - braces = setIteratorBraces('Map', tag); + braces = getIteratorBraces('Map', tag); formatter = formatIterator; } else if (isSetIterator(value)) { keys = getKeys(value, ctx.showHidden); - braces = setIteratorBraces('Set', tag); + braces = getIteratorBraces('Set', tag); formatter = formatIterator; } else { noIterator = true; @@ -754,10 +745,10 @@ function formatRaw(ctx, value, recurseTimes, typedArray) { } } if (isMapIterator(value)) { - braces = setIteratorBraces('Map', tag); + braces = getIteratorBraces('Map', tag); formatter = formatIterator; } else if (isSetIterator(value)) { - braces = setIteratorBraces('Set', tag); + braces = getIteratorBraces('Set', tag); formatter = formatIterator; // Handle other regular objects again. } else if (keys.length === 0) { @@ -818,6 +809,15 @@ function formatRaw(ctx, value, recurseTimes, typedArray) { return res; } +function getIteratorBraces(type, tag) { + if (tag !== `${type} Iterator`) { + if (tag !== '') + tag += '] ['; + tag += `${type} Iterator`; + } + return [`[${tag}] {`, '}']; +} + function formatError(err, constructor, tag, ctx) { // TODO(BridgeAR): Always show the error code if present. let stack = err.stack || ErrorPrototype.toString(err);