From 2380d90f0a2abf550b1a465d33861d3b769593ec Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Tue, 17 Mar 2020 21:22:57 +0100 Subject: [PATCH] util: mark classes while inspecting them This outlines the basic class setup when inspecting a class. Signed-off-by: Ruben Bridgewater PR-URL: https://github.com/nodejs/node/pull/32332 Fixes: https://github.com/nodejs/node/issues/32270 Reviewed-By: Anna Henningsen Reviewed-By: Anto Aravinth --- lib/internal/util/inspect.js | 37 ++++++++++ test/parallel/test-repl-top-level-await.js | 2 +- test/parallel/test-util-inspect.js | 82 ++++++++++++++++++++++ 3 files changed, 120 insertions(+), 1 deletion(-) diff --git a/lib/internal/util/inspect.js b/lib/internal/util/inspect.js index 7b1e7eca0e61af..37a89a211a4a2d 100644 --- a/lib/internal/util/inspect.js +++ b/lib/internal/util/inspect.js @@ -12,6 +12,7 @@ const { DatePrototypeToString, ErrorPrototypeToString, Float32Array, + FunctionPrototypeToString, JSONStringify, Map, MapPrototype, @@ -170,6 +171,10 @@ const numberRegExp = /^(0|[1-9][0-9]*)$/; const coreModuleRegExp = /^ at (?:[^/\\(]+ \(|)((? { + const inspected = util.inspect(clazz); + assert.strictEqual(inspected, string); + Object.defineProperty(clazz, Symbol.toStringTag, { + value: 'Woohoo' + }); + const parts = inspected.slice(0, -1).split(' '); + const [, name, ...rest] = parts; + rest.unshift('[Woohoo]'); + if (rest.length) { + rest[rest.length - 1] += ']'; + } + assert.strictEqual( + util.inspect(clazz), + ['[class', name, ...rest].join(' ') + ); + if (rest.length) { + rest[rest.length - 1] = rest[rest.length - 1].slice(0, -1); + rest.length = 1; + } + Object.setPrototypeOf(clazz, null); + assert.strictEqual( + util.inspect(clazz), + ['[class', name, ...rest, 'extends [null prototype]]'].join(' ') + ); + Object.defineProperty(clazz, 'name', { value: 'Foo' }); + const res = ['[class', 'Foo', ...rest, 'extends [null prototype]]'].join(' '); + assert.strictEqual(util.inspect(clazz), res); + clazz.foo = true; + assert.strictEqual(util.inspect(clazz), `${res} { foo: true }`); +}); + +// "class" properties should not be detected as "class". +{ + // eslint-disable-next-line space-before-function-paren + let obj = { class () {} }; + assert.strictEqual( + util.inspect(obj), + '{ class: [Function: class] }' + ); + obj = { class: () => {} }; + assert.strictEqual( + util.inspect(obj), + '{ class: [Function: class] }' + ); + obj = { ['class Foo {}']() {} }; + assert.strictEqual( + util.inspect(obj), + "{ 'class Foo {}': [Function: class Foo {}] }" + ); + function Foo() {} + Object.defineProperty(Foo, 'toString', { value: () => 'class Foo {}' }); + assert.strictEqual( + util.inspect(Foo), + '[Function: Foo]' + ); + function fn() {} + Object.defineProperty(fn, 'name', { value: 'class Foo {}' }); + assert.strictEqual( + util.inspect(fn), + '[Function: class Foo {}]' + ); +} + // Verify that throwing in valueOf and toString still produces nice results. [ [new String(55), "[String: '55']"],