From f62a7679a30fb02739e6cba2206fbabe6372a332 Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Sat, 2 Nov 2019 19:13:51 +0100 Subject: [PATCH] util: add Set and map size to inspect output MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds the size of a set and map to the output. This aligns the output with the one from Chromium. PR-URL: https://github.com/nodejs/node/pull/30225 Reviewed-By: Michaƫl Zasso Reviewed-By: Rich Trott --- doc/api/util.md | 8 +-- lib/internal/util/inspect.js | 16 ++---- test/parallel/test-assert-deep.js | 2 +- test/parallel/test-util-inspect.js | 91 +++++++++++++++--------------- 4 files changed, 54 insertions(+), 63 deletions(-) diff --git a/doc/api/util.md b/doc/api/util.md index f4e689a2130bd5..4727cdb88e9678 100644 --- a/doc/api/util.md +++ b/doc/api/util.md @@ -576,7 +576,7 @@ console.log(util.inspect(o, { compact: true, depth: 5, breakLength: 80 })); // 'test', // 'foo' ] ], // 4 ], -// b: Map { 'za' => 1, 'zb' => 'test' } } +// b: Map(2) { 'za' => 1, 'zb' => 'test' } } // Setting `compact` to false changes the output to be more reader friendly. console.log(util.inspect(o, { compact: false, depth: 5, breakLength: 80 })); @@ -597,7 +597,7 @@ console.log(util.inspect(o, { compact: false, depth: 5, breakLength: 80 })); // ], // 4 // ], -// b: Map { +// b: Map(2) { // 'za' => 1, // 'zb' => 'test' // } @@ -639,9 +639,9 @@ const o1 = { c: new Set([2, 3, 1]) }; console.log(inspect(o1, { sorted: true })); -// { a: '`a` comes before `b`', b: [ 2, 3, 1 ], c: Set { 1, 2, 3 } } +// { a: '`a` comes before `b`', b: [ 2, 3, 1 ], c: Set(3) { 1, 2, 3 } } console.log(inspect(o1, { sorted: (a, b) => b.localeCompare(a) })); -// { c: Set { 3, 2, 1 }, b: [ 2, 3, 1 ], a: '`a` comes before `b`' } +// { c: Set(3) { 3, 2, 1 }, b: [ 2, 3, 1 ], a: '`a` comes before `b`' } const o2 = { c: new Set([2, 1, 3]), diff --git a/lib/internal/util/inspect.js b/lib/internal/util/inspect.js index 7a34454bb3b287..5f07afe65fbd6a 100644 --- a/lib/internal/util/inspect.js +++ b/lib/internal/util/inspect.js @@ -773,10 +773,10 @@ function formatRaw(ctx, value, recurseTimes, typedArray) { if (constructor !== null) { if (constructor === tag) tag = ''; - prefix = getPrefix(`${constructor}`, tag, ''); + prefix = getPrefix(`${constructor}(${size})`, tag, ''); formatter = formatSet.bind(null, value, size); } else { - prefix = getPrefix(constructor, tag, 'Set'); + prefix = getPrefix(constructor, tag, `Set(${size})`); formatter = formatSet.bind(null, SetPrototypeValues(value), size); } if (size === 0 && keys.length === 0 && protoProps === undefined) @@ -789,10 +789,10 @@ function formatRaw(ctx, value, recurseTimes, typedArray) { if (constructor !== null) { if (constructor === tag) tag = ''; - prefix = getPrefix(`${constructor}`, tag, ''); + prefix = getPrefix(`${constructor}(${size})`, tag, ''); formatter = formatMap.bind(null, value, size); } else { - prefix = getPrefix(constructor, tag, 'Map'); + prefix = getPrefix(constructor, tag, `Map(${size})`); formatter = formatMap.bind(null, MapPrototypeEntries(value), size); } if (size === 0 && keys.length === 0 && protoProps === undefined) @@ -1432,11 +1432,6 @@ function formatSet(value, size, ctx, ignored, recurseTimes) { output.push(formatValue(ctx, v, recurseTimes)); } ctx.indentationLvl -= 2; - // With `showHidden`, `length` will display as a hidden property for - // arrays. For consistency's sake, do the same for `size`, even though this - // property isn't selected by ObjectGetOwnPropertyNames(). - if (ctx.showHidden) - output.push(`[size]: ${ctx.stylize(`${size}`, 'number')}`); return output; } @@ -1448,9 +1443,6 @@ function formatMap(value, size, ctx, ignored, recurseTimes) { formatValue(ctx, v, recurseTimes)); } ctx.indentationLvl -= 2; - // See comment in formatSet - if (ctx.showHidden) - output.push(`[size]: ${ctx.stylize(`${size}`, 'number')}`); return output; } diff --git a/test/parallel/test-assert-deep.js b/test/parallel/test-assert-deep.js index fcc3765105f57c..f98ab14bffc12d 100644 --- a/test/parallel/test-assert-deep.js +++ b/test/parallel/test-assert-deep.js @@ -524,7 +524,7 @@ assertNotDeepOrStrict( { code: 'ERR_ASSERTION', message: `${defaultMsgStartFull}\n\n` + - " Map {\n+ 1 => 1\n- 1 => '1'\n }" + " Map(1) {\n+ 1 => 1\n- 1 => '1'\n }" } ); } diff --git a/test/parallel/test-util-inspect.js b/test/parallel/test-util-inspect.js index 52d9f893d23614..4a25013355703e 100644 --- a/test/parallel/test-util-inspect.js +++ b/test/parallel/test-util-inspect.js @@ -576,9 +576,9 @@ assert.strictEqual(util.inspect(-5e-324), '-5e-324'); let obj = vm.runInNewContext('(function(){return {}})()', {}); assert.strictEqual(util.inspect(obj), '{}'); obj = vm.runInNewContext('var m=new Map();m.set(1,2);m', {}); - assert.strictEqual(util.inspect(obj), 'Map { 1 => 2 }'); + assert.strictEqual(util.inspect(obj), 'Map(1) { 1 => 2 }'); obj = vm.runInNewContext('var s=new Set();s.add(1);s.add(2);s', {}); - assert.strictEqual(util.inspect(obj), 'Set { 1, 2 }'); + assert.strictEqual(util.inspect(obj), 'Set(2) { 1, 2 }'); obj = vm.runInNewContext('fn=function(){};new Promise(fn,fn)', {}); assert.strictEqual(util.inspect(obj), 'Promise { }'); } @@ -1067,13 +1067,13 @@ if (typeof Symbol !== 'undefined') { // Test Set. { - assert.strictEqual(util.inspect(new Set()), 'Set {}'); - assert.strictEqual(util.inspect(new Set([1, 2, 3])), 'Set { 1, 2, 3 }'); + assert.strictEqual(util.inspect(new Set()), 'Set(0) {}'); + assert.strictEqual(util.inspect(new Set([1, 2, 3])), 'Set(3) { 1, 2, 3 }'); const set = new Set(['foo']); set.bar = 42; assert.strictEqual( util.inspect(set, { showHidden: true }), - "Set { 'foo', [size]: 1, bar: 42 }" + "Set(1) { 'foo', bar: 42 }" ); } @@ -1081,33 +1081,39 @@ if (typeof Symbol !== 'undefined') { { const set = new Set(); set.add(set); - assert.strictEqual(util.inspect(set), ' Set { [Circular *1] }'); + assert.strictEqual(util.inspect(set), ' Set(1) { [Circular *1] }'); } // Test Map. { - assert.strictEqual(util.inspect(new Map()), 'Map {}'); + assert.strictEqual(util.inspect(new Map()), 'Map(0) {}'); assert.strictEqual(util.inspect(new Map([[1, 'a'], [2, 'b'], [3, 'c']])), - "Map { 1 => 'a', 2 => 'b', 3 => 'c' }"); + "Map(3) { 1 => 'a', 2 => 'b', 3 => 'c' }"); const map = new Map([['foo', null]]); map.bar = 42; assert.strictEqual(util.inspect(map, true), - "Map { 'foo' => null, [size]: 1, bar: 42 }"); + "Map(1) { 'foo' => null, bar: 42 }"); } // Test circular Map. { const map = new Map(); map.set(map, 'map'); - assert.strictEqual(inspect(map), " Map { [Circular *1] => 'map' }"); + assert.strictEqual( + inspect(map), + " Map(1) { [Circular *1] => 'map' }" + ); map.set(map, map); assert.strictEqual( inspect(map), - ' Map { [Circular *1] => [Circular *1] }' + ' Map(1) { [Circular *1] => [Circular *1] }' ); map.delete(map); map.set('map', map); - assert.strictEqual(inspect(map), " Map { 'map' => [Circular *1] }"); + assert.strictEqual( + inspect(map), + " Map(1) { 'map' => [Circular *1] }" + ); } // Test multiple circular references. @@ -1273,10 +1279,10 @@ if (typeof Symbol !== 'undefined') { }); checkAlignment(obj, '{', " 'X': null", '}'); - checkAlignment(new Set(bigArray), 'Set {', ' X', '}'); + checkAlignment(new Set(bigArray), 'Set(100) {', ' X', '}'); checkAlignment( new Map(bigArray.map((number) => [number, null])), - 'Map {', ' X => null', '}' + 'Map(100) {', ' X => null', '}' ); } @@ -1296,9 +1302,9 @@ if (typeof Symbol !== 'undefined') { assert.strictEqual(util.inspect(new ArraySubclass(1, 2, 3)), 'ArraySubclass [ 1, 2, 3 ]'); assert.strictEqual(util.inspect(new SetSubclass([1, 2, 3])), - 'SetSubclass [Set] { 1, 2, 3 }'); + 'SetSubclass(3) [Set] { 1, 2, 3 }'); assert.strictEqual(util.inspect(new MapSubclass([['foo', 42]])), - "MapSubclass [Map] { 'foo' => 42 }"); + "MapSubclass(1) [Map] { 'foo' => 42 }"); assert.strictEqual(util.inspect(new PromiseSubclass(() => {})), 'PromiseSubclass [Promise] { }'); assert.strictEqual( @@ -1557,7 +1563,7 @@ util.inspect(process); " 'test',", " 'foo' ] ],", ' 4 ],', - " b: Map { 'za' => 1, 'zb' => 'test' } }", + " b: Map(2) { 'za' => 1, 'zb' => 'test' } }", ].join('\n'); assert.strictEqual(out, expect); @@ -1578,7 +1584,7 @@ util.inspect(process); ' ],', ' 4', ' ],', - ' b: Map {', + ' b: Map(2) {', " 'za' => 1,", " 'zb' => 'test'", ' }', @@ -1658,18 +1664,17 @@ util.inspect(process); let out = util.inspect(map, { compact: false, showHidden: true, depth: 9 }); let expected = [ - 'Map {', + 'Map(2) {', ' Promise {', ' [', ' [', ' 1,', - ' Set {', + ' Set(1) {', ' [', ' 1,', ' 2,', ' [length]: 2', - ' ],', - ' [size]: 1', + ' ]', ' },', ' [length]: 2', ' ],', @@ -1703,8 +1708,7 @@ util.inspect(process); ' }', ' ],', ' [Circular *1]', - ' },', - ' [size]: 2', + ' }', '}' ].join('\n'); @@ -1713,12 +1717,12 @@ util.inspect(process); out = util.inspect(map, { compact: 2, showHidden: true, depth: 9 }); expected = [ - 'Map {', + 'Map(2) {', ' Promise {', ' [', ' [', ' 1,', - ' Set { [ 1, 2, [length]: 2 ], [size]: 1 },', + ' Set(1) { [ 1, 2, [length]: 2 ] },', ' [length]: 2', ' ],', ' [length]: 1', @@ -1739,8 +1743,7 @@ util.inspect(process); ' [buffer]: ArrayBuffer { byteLength: 0, foo: true }', ' ],', ' [Circular *1]', - ' },', - ' [size]: 2', + ' }', '}' ].join('\n'); @@ -1750,14 +1753,13 @@ util.inspect(process); showHidden: true, depth: 9, breakLength: 4, compact: true }); expected = [ - 'Map {', + 'Map(2) {', ' Promise {', ' [ [ 1,', - ' Set {', + ' Set(1) {', ' [ 1,', ' 2,', - ' [length]: 2 ],', - ' [size]: 1 },', + ' [length]: 2 ] },', ' [length]: 2 ],', ' [length]: 1 ] } => Uint8Array [', ' [BYTES_PER_ELEMENT]: 1,', @@ -1779,8 +1781,7 @@ util.inspect(process); ' [buffer]: ArrayBuffer {', ' byteLength: 0,', ' foo: true } ],', - ' [Circular *1] },', - ' [size]: 2 }' + ' [Circular *1] } }' ].join('\n'); assert.strict.equal(out, expected); @@ -1944,8 +1945,8 @@ assert.strictEqual(util.inspect('"\'${a}'), "'\"\\'${a}'"); [[1, 2], '[ 1, 2 ]'], [[, , 5, , , , ], '[ <2 empty items>, 5, <3 empty items> ]'], [{ a: 5 }, '{ a: 5 }'], - [new Set([1, 2]), 'Set { 1, 2 }'], - [new Map([[1, 2]]), 'Map { 1 => 2 }'], + [new Set([1, 2]), 'Set(2) { 1, 2 }'], + [new Map([[1, 2]]), 'Map(1) { 1 => 2 }'], [new Set([1, 2]).entries(), '[Set Entries] { [ 1, 1 ], [ 2, 2 ] }'], [new Map([[1, 2]]).keys(), '[Map Iterator] { 1 }'], [new Date(2000), '1970-01-01T00:00:02.000Z'], @@ -1976,8 +1977,8 @@ assert.strictEqual(util.inspect('"\'${a}'), "'\"\\'${a}'"); // Verify that having no prototype still produces nice results. [ [[1, 3, 4], '[Array: null prototype] [ 1, 3, 4 ]'], - [new Set([1, 2]), '[Set: null prototype] { 1, 2 }'], - [new Map([[1, 2]]), '[Map: null prototype] { 1 => 2 }'], + [new Set([1, 2]), '[Set(2): null prototype] { 1, 2 }'], + [new Map([[1, 2]]), '[Map(1): null prototype] { 1 => 2 }'], [new Promise((resolve) => setTimeout(resolve, 10)), '[Promise: null prototype] { }'], [new WeakSet(), '[WeakSet: null prototype] { }'], @@ -2218,7 +2219,7 @@ assert.strictEqual( value: iterator, configurable: true }); - assert.strictEqual(util.inspect(obj), '[Set: null prototype] { 1, 2 }'); + assert.strictEqual(util.inspect(obj), '[Set(2): null prototype] { 1, 2 }'); Object.defineProperty(obj, Symbol.iterator, { value: true, configurable: true @@ -2230,7 +2231,7 @@ assert.strictEqual( }); assert.strictEqual( util.inspect(obj), - '[Set: null prototype] { 1, 2, size: NaN }' + '[Set(2): null prototype] { 1, 2, size: NaN }' ); } @@ -2263,7 +2264,7 @@ assert.strictEqual( getset.foo = new Set([[{ a: true }, 2, {}], 'foobar', { x: 1 }]); assert.strictEqual( inspect(getset, { getters: true }), - '{\n foo: [Getter/Setter] Set { [ [Object], 2, {} ], ' + + '{\n foo: [Getter/Setter] Set(3) { [ [Object], 2, {} ], ' + "'foobar', { x: 1 } },\n inc: [Getter: NaN]\n}"); } @@ -2654,12 +2655,11 @@ assert.strictEqual( assert.strictEqual( inspect(bar), - 'Bar [Map] { prop: true, prop2: true, abc: true }' + 'Bar(0) [Map] { prop: true, prop2: true, abc: true }' ); assert.strictEqual( inspect(bar, { showHidden: true, getters: true, colors: false }), - 'Bar [Map] {\n' + - ' [size]: 0,\n' + + 'Bar(0) [Map] {\n' + ' prop: true,\n' + ' prop2: true,\n' + ' abc: true,\n' + @@ -2669,8 +2669,7 @@ assert.strictEqual( ); assert.strictEqual( inspect(bar, { showHidden: true, getters: false, colors: true }), - 'Bar [Map] {\n' + - ' [size]: \x1B[33m0\x1B[39m,\n' + + 'Bar(0) [Map] {\n' + ' prop: \x1B[33mtrue\x1B[39m,\n' + ' prop2: \x1B[33mtrue\x1B[39m,\n' + ' abc: \x1B[33mtrue\x1B[39m,\n' +