diff options
-rw-r--r-- | doc/api/util.md | 8 | ||||
-rw-r--r-- | lib/internal/util/inspect.js | 32 | ||||
-rw-r--r-- | test/parallel/test-util-inspect.js | 33 |
3 files changed, 68 insertions, 5 deletions
diff --git a/doc/api/util.md b/doc/api/util.md index 8c21bef9ae..0b9e477394 100644 --- a/doc/api/util.md +++ b/doc/api/util.md @@ -389,6 +389,9 @@ stream.write('With ES6'); <!-- YAML added: v0.3.0 changes: + - version: REPLACEME + pr-url: https://github.com/nodejs/node/pull/24852 + description: The `getters` option is supported now. - version: v11.4.0 pr-url: https://github.com/nodejs/node/pull/24326 description: The `depth` default changed back to `2`. @@ -468,6 +471,11 @@ changes: of an object and Set and Map entries will be sorted in the returned string. If set to `true` the [default sort][] is going to be used. If set to a function, it is used as a [compare function][]. + * `getters` {boolean|string} If set to `true`, getters are going to be + inspected as well. If set to `'get'` only getters without setter are going + to be inspected. If set to `'set'` only getters having a corresponding + setter are going to be inspected. This might cause side effects depending on + the getter function. **Default:** `false`. * Returns: {string} The representation of passed object The `util.inspect()` method returns a string representation of `object` that is diff --git a/lib/internal/util/inspect.js b/lib/internal/util/inspect.js index 6ec27b9d1d..f7e5507882 100644 --- a/lib/internal/util/inspect.js +++ b/lib/internal/util/inspect.js @@ -99,7 +99,8 @@ const inspectDefaultOptions = Object.seal({ maxArrayLength: 100, breakLength: 60, compact: true, - sorted: false + sorted: false, + getters: false }); const kObjectType = 0; @@ -167,7 +168,8 @@ function inspect(value, opts) { maxArrayLength: inspectDefaultOptions.maxArrayLength, breakLength: inspectDefaultOptions.breakLength, compact: inspectDefaultOptions.compact, - sorted: inspectDefaultOptions.sorted + sorted: inspectDefaultOptions.sorted, + getters: inspectDefaultOptions.getters }; if (arguments.length > 1) { // Legacy... @@ -1131,10 +1133,30 @@ function formatProperty(ctx, value, recurseTimes, key, type) { } ctx.indentationLvl -= diff; } else if (desc.get !== undefined) { - if (desc.set !== undefined) { - str = ctx.stylize('[Getter/Setter]', 'special'); + const label = desc.set !== undefined ? 'Getter/Setter' : 'Getter'; + const s = ctx.stylize; + const sp = 'special'; + if (ctx.getters && (ctx.getters === true || + ctx.getters === 'get' && desc.set === undefined || + ctx.getters === 'set' && desc.set !== undefined)) { + try { + const tmp = value[key]; + ctx.indentationLvl += 2; + if (tmp === null) { + str = `${s(`[${label}:`, sp)} ${s('null', 'null')}${s(']', sp)}`; + } else if (typeof tmp === 'object') { + str = `${s(`[${label}]`, sp)} ${formatValue(ctx, tmp, recurseTimes)}`; + } else { + const primitive = formatPrimitive(s, tmp, ctx); + str = `${s(`[${label}:`, sp)} ${primitive}${s(']', sp)}`; + } + ctx.indentationLvl -= 2; + } catch (err) { + const message = `<Inspection threw (${err.message})>`; + str = `${s(`[${label}:`, sp)} ${message}${s(']', sp)}`; + } } else { - str = ctx.stylize('[Getter]', 'special'); + str = ctx.stylize(`[${label}]`, sp); } } else if (desc.set !== undefined) { str = ctx.stylize('[Setter]', 'special'); diff --git a/test/parallel/test-util-inspect.js b/test/parallel/test-util-inspect.js index c0fc3219ce..20b03d2dd0 100644 --- a/test/parallel/test-util-inspect.js +++ b/test/parallel/test-util-inspect.js @@ -1764,3 +1764,36 @@ assert.strictEqual( }); assert.strictEqual(util.inspect(obj), '[Set: null prototype] { 1, 2 }'); } + +// Check the getter option. +{ + let foo = 1; + const get = { get foo() { return foo; } }; + const getset = { + get foo() { return foo; }, + set foo(val) { foo = val; }, + get inc() { return ++foo; } + }; + const thrower = { get foo() { throw new Error('Oops'); } }; + assert.strictEqual( + inspect(get, { getters: true, colors: true }), + '{ foo: \u001b[36m[Getter:\u001b[39m ' + + '\u001b[33m1\u001b[39m\u001b[36m]\u001b[39m }'); + assert.strictEqual( + inspect(thrower, { getters: true }), + '{ foo: [Getter: <Inspection threw (Oops)>] }'); + assert.strictEqual( + inspect(getset, { getters: true }), + '{ foo: [Getter/Setter: 1], inc: [Getter: 2] }'); + assert.strictEqual( + inspect(getset, { getters: 'get' }), + '{ foo: [Getter/Setter], inc: [Getter: 3] }'); + assert.strictEqual( + inspect(getset, { getters: 'set' }), + '{ foo: [Getter/Setter: 3], inc: [Getter] }'); + getset.foo = new Set([[{ a: true }, 2, {}], 'foobar', { x: 1 }]); + assert.strictEqual( + inspect(getset, { getters: true }), + '{ foo: [Getter/Setter] Set { [ [Object], 2, {} ], ' + + "'foobar', { x: 1 } },\n inc: [Getter: NaN] }"); +} |