From 94b7b0168db6e2e4336290038d345674e3b9b28b Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Sat, 30 Dec 2017 02:14:13 +0100 Subject: [PATCH 1/7] streams: add custom inspect to BufferList Currently inspecting the BufferList can result a maximum call stack size error. Adding a individual inspect function prevents this. --- lib/internal/streams/BufferList.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/internal/streams/BufferList.js b/lib/internal/streams/BufferList.js index 23d5a8a2db0eb7..3a86860a182a8b 100644 --- a/lib/internal/streams/BufferList.js +++ b/lib/internal/streams/BufferList.js @@ -1,6 +1,7 @@ 'use strict'; const { Buffer } = require('buffer'); +const { customInspectSymbol } = require('internal/util'); function copyBuffer(src, target, offset) { Buffer.prototype.copy.call(src, target, offset); @@ -73,4 +74,8 @@ module.exports = class BufferList { } return ret; } + + [customInspectSymbol]() { + return `${this.constructor.name} { length: ${this.length} }`; + } }; From 2d845cf6baa24c4d77cbd2384a5eb7e77322e0d2 Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Thu, 28 Dec 2017 23:40:30 +0100 Subject: [PATCH 2/7] util: change util.inspect depth default The current default is not ideal in most use cases. Therefore it is changed to showing unlimited depth in case util.inspect is called directly. The default is kept as before for console.log and similar. Using console.dir will now show a depth of up to five and console.assert / console.trace will show a unlimited depth. --- lib/repl.js | 5 +++-- lib/util.js | 2 +- test/parallel/test-util-inspect-proxy.js | 16 +++++++++------ test/parallel/test-util-inspect.js | 26 ++++++++++++------------ 4 files changed, 27 insertions(+), 22 deletions(-) diff --git a/lib/repl.js b/lib/repl.js index 98fd78eacaa5e5..937e8edcd2a7c3 100644 --- a/lib/repl.js +++ b/lib/repl.js @@ -104,8 +104,9 @@ function hasOwnProperty(obj, prop) { // Can overridden with custom print functions, such as `probe` or `eyes.js`. // This is the default "writer" value if none is passed in the REPL options. const writer = exports.writer = (obj) => util.inspect(obj, writer.options); -writer.options = - Object.assign({}, util.inspect.defaultOptions, { showProxy: true }); +writer.options = Object.assign({}, + util.inspect.defaultOptions, + { showProxy: true, depth: 2 }); exports._builtinLibs = internalModule.builtinLibs; diff --git a/lib/util.js b/lib/util.js index e0cdc2c28f84d9..ad5285360a8d8f 100644 --- a/lib/util.js +++ b/lib/util.js @@ -64,7 +64,7 @@ const { const inspectDefaultOptions = Object.seal({ showHidden: false, - depth: 2, + depth: null, colors: false, customInspect: true, showProxy: false, diff --git a/test/parallel/test-util-inspect-proxy.js b/test/parallel/test-util-inspect-proxy.js index 63527986b1cbf1..8c762854993af5 100644 --- a/test/parallel/test-util-inspect-proxy.js +++ b/test/parallel/test-util-inspect-proxy.js @@ -48,13 +48,17 @@ const expected1 = 'Proxy [ {}, {} ]'; const expected2 = 'Proxy [ Proxy [ {}, {} ], {} ]'; const expected3 = 'Proxy [ Proxy [ Proxy [ {}, {} ], {} ], Proxy [ {}, {} ] ]'; const expected4 = 'Proxy [ Proxy [ {}, {} ], Proxy [ Proxy [ {}, {} ], {} ] ]'; -const expected5 = 'Proxy [ Proxy [ Proxy [ Proxy [Array], {} ],' + +const expected5 = 'Proxy [ Proxy [ Proxy [ Proxy [ {}, {} ], {} ],' + ' Proxy [ {}, {} ] ],\n Proxy [ Proxy [ {}, {} ]' + - ', Proxy [ Proxy [Array], {} ] ] ]'; -const expected6 = 'Proxy [ Proxy [ Proxy [ Proxy [Array], Proxy [Array]' + - ' ],\n Proxy [ Proxy [Array], Proxy [Array] ] ],\n' + - ' Proxy [ Proxy [ Proxy [Array], Proxy [Array] ],\n' + - ' Proxy [ Proxy [Array], Proxy [Array] ] ] ]'; + ', Proxy [ Proxy [ {}, {} ], {} ] ] ]'; +const expected6 = 'Proxy [ Proxy [ Proxy [ Proxy [ Proxy [ {}, {} ], {} ], ' + + 'Proxy [ {}, {} ] ],\n' + + ' Proxy [ Proxy [ {}, {} ], ' + + 'Proxy [ Proxy [ {}, {} ], {} ] ] ],\n' + + ' Proxy [ Proxy [ Proxy [ Proxy [ {}, {} ], {} ], ' + + 'Proxy [ {}, {} ] ],\n' + + ' Proxy [ Proxy [ {}, {} ], ' + + 'Proxy [ Proxy [ {}, {} ], {} ] ] ] ]'; assert.strictEqual( util.inspect(proxy1, { showProxy: true, depth: null }), expected1); diff --git a/test/parallel/test-util-inspect.js b/test/parallel/test-util-inspect.js index 335ba09bd7f288..35e85f6fdd478e 100644 --- a/test/parallel/test-util-inspect.js +++ b/test/parallel/test-util-inspect.js @@ -68,7 +68,7 @@ assert.strictEqual(util.inspect({ a: 1, b: 2 }), '{ a: 1, b: 2 }'); assert.strictEqual(util.inspect({ 'a': {} }), '{ a: {} }'); assert.strictEqual(util.inspect({ 'a': { 'b': 2 } }), '{ a: { b: 2 } }'); assert.strictEqual(util.inspect({ 'a': { 'b': { 'c': { 'd': 2 } } } }), - '{ a: { b: { c: [Object] } } }'); + '{ a: { b: { c: { d: 2 } } } }'); assert.strictEqual( util.inspect({ 'a': { 'b': { 'c': { 'd': 2 } } } }, false, null), '{ a: { b: { c: { d: 2 } } } }'); @@ -106,7 +106,7 @@ assert.strictEqual(util.inspect((new JSStream())._externalStream), assert.strictEqual(util.inspect({ a: regexp }, false, 0), '{ a: /regexp/ }'); } -assert(/Object/.test( +assert(!/Object/.test( util.inspect({ a: { a: { a: { a: {} } } } }, undefined, undefined, true) )); assert(!/Object/.test( @@ -1012,15 +1012,15 @@ if (typeof Symbol !== 'undefined') { // Empty and circular before depth { const arr = [[[[]]]]; - assert.strictEqual(util.inspect(arr), '[ [ [ [] ] ] ]'); + assert.strictEqual(util.inspect(arr, { depth: 2 }), '[ [ [ [] ] ] ]'); arr[0][0][0][0] = []; - assert.strictEqual(util.inspect(arr), '[ [ [ [Array] ] ] ]'); + assert.strictEqual(util.inspect(arr, { depth: 2 }), '[ [ [ [Array] ] ] ]'); arr[0][0][0] = {}; - assert.strictEqual(util.inspect(arr), '[ [ [ {} ] ] ]'); + assert.strictEqual(util.inspect(arr, { depth: 2 }), '[ [ [ {} ] ] ]'); arr[0][0][0] = { a: 2 }; - assert.strictEqual(util.inspect(arr), '[ [ [ [Object] ] ] ]'); + assert.strictEqual(util.inspect(arr, { depth: 2 }), '[ [ [ [Object] ] ] ]'); arr[0][0][0] = arr; - assert.strictEqual(util.inspect(arr), '[ [ [ [Circular] ] ] ]'); + assert.strictEqual(util.inspect(arr, { depth: 2 }), '[ [ [ [Circular] ] ] ]'); } // Corner cases. @@ -1117,22 +1117,22 @@ if (typeof Symbol !== 'undefined') { assert(!/1 more item/.test(util.inspect(arr))); util.inspect.defaultOptions.maxArrayLength = oldOptions.maxArrayLength; assert(/1 more item/.test(util.inspect(arr))); - util.inspect.defaultOptions.depth = null; - assert(!/Object/.test(util.inspect(obj))); - util.inspect.defaultOptions.depth = oldOptions.depth; + util.inspect.defaultOptions.depth = 2; assert(/Object/.test(util.inspect(obj))); + util.inspect.defaultOptions.depth = oldOptions.depth; + assert(!/Object/.test(util.inspect(obj))); assert.strictEqual( JSON.stringify(util.inspect.defaultOptions), JSON.stringify(oldOptions) ); // Set multiple options through object assignment - util.inspect.defaultOptions = { maxArrayLength: null, depth: null }; + util.inspect.defaultOptions = { maxArrayLength: null, depth: 2 }; assert(!/1 more item/.test(util.inspect(arr))); - assert(!/Object/.test(util.inspect(obj))); + assert(/Object/.test(util.inspect(obj))); util.inspect.defaultOptions = oldOptions; assert(/1 more item/.test(util.inspect(arr))); - assert(/Object/.test(util.inspect(obj))); + assert(!/Object/.test(util.inspect(obj))); assert.strictEqual( JSON.stringify(util.inspect.defaultOptions), JSON.stringify(oldOptions) From 27217675765f05f3d30203953030e1b7d72a6af1 Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Thu, 28 Dec 2017 23:44:24 +0100 Subject: [PATCH 3/7] util: improve setting default options Object.assign is currently very slow. Using Object.keys is much faster in v8 6.3. --- lib/util.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/util.js b/lib/util.js index ad5285360a8d8f..64719d597d7dd7 100644 --- a/lib/util.js +++ b/lib/util.js @@ -317,7 +317,9 @@ Object.defineProperty(inspect, 'defaultOptions', { if (options === null || typeof options !== 'object') { throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'options', 'Object'); } - Object.assign(inspectDefaultOptions, options); + const keys = Object.keys(options); + for (var i = 0; i < keys.length; i++) + inspectDefaultOptions[keys[i]] = options[keys[i]]; return inspectDefaultOptions; } }); From 606f06cc97e55175f123960634dec4910c43b23f Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Tue, 2 Jan 2018 02:02:17 +0100 Subject: [PATCH 4/7] fixup address comments --- lib/internal/streams/BufferList.js | 4 +++- lib/util.js | 5 +---- test/parallel/test-stream-buffer-list.js | 8 ++++++++ 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/lib/internal/streams/BufferList.js b/lib/internal/streams/BufferList.js index 3a86860a182a8b..4a25d4ab4e060d 100644 --- a/lib/internal/streams/BufferList.js +++ b/lib/internal/streams/BufferList.js @@ -2,6 +2,7 @@ const { Buffer } = require('buffer'); const { customInspectSymbol } = require('internal/util'); +const util = require('util'); function copyBuffer(src, target, offset) { Buffer.prototype.copy.call(src, target, offset); @@ -76,6 +77,7 @@ module.exports = class BufferList { } [customInspectSymbol]() { - return `${this.constructor.name} { length: ${this.length} }`; + const obj = util.inspect({ length: this.length }); + return `${this.constructor.name} ${obj}`; } }; diff --git a/lib/util.js b/lib/util.js index 64719d597d7dd7..9d1739f786fbbf 100644 --- a/lib/util.js +++ b/lib/util.js @@ -317,10 +317,7 @@ Object.defineProperty(inspect, 'defaultOptions', { if (options === null || typeof options !== 'object') { throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'options', 'Object'); } - const keys = Object.keys(options); - for (var i = 0; i < keys.length; i++) - inspectDefaultOptions[keys[i]] = options[keys[i]]; - return inspectDefaultOptions; + return _extend(inspectDefaultOptions, options); } }); diff --git a/test/parallel/test-stream-buffer-list.js b/test/parallel/test-stream-buffer-list.js index ddbff452de4be9..87c9d2a2bb50ce 100644 --- a/test/parallel/test-stream-buffer-list.js +++ b/test/parallel/test-stream-buffer-list.js @@ -3,6 +3,7 @@ require('../common'); const assert = require('assert'); const BufferList = require('internal/streams/BufferList'); +const util = require('util'); // Test empty buffer list. const emptyList = new BufferList(); @@ -25,3 +26,10 @@ assert.strictEqual(list.join(','), 'foo'); const shifted = list.shift(); assert.strictEqual(shifted, 'foo'); assert.deepStrictEqual(list, new BufferList()); + +const tmp = util.inspect.defaultOptions.colors; +util.inspect.defaultOptions = { colors: true }; +assert.strictEqual( + util.inspect(list), + 'BufferList { length: \u001b[33m0\u001b[39m }'); +util.inspect.defaultOptions = { colors: tmp }; From 3ca34ca06e365f05afb2b27257492d13fc23e352 Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Wed, 3 Jan 2018 16:24:54 +0100 Subject: [PATCH 5/7] fixup update documentation --- doc/api/util.md | 33 ++++++++++++++++++++++-------- lib/internal/streams/BufferList.js | 3 +-- 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/doc/api/util.md b/doc/api/util.md index a2d3c71bb633a8..99f0cf3c98243b 100644 --- a/doc/api/util.md +++ b/doc/api/util.md @@ -327,6 +327,9 @@ stream.write('With ES6');