From 5fb30dcabfc6e9d6bf7ae8d76d1da25599b6a5b3 Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Wed, 18 Mar 2020 20:16:14 +0100 Subject: [PATCH] fixup: add more tests, fix edge case, rework output Signed-off-by: Ruben Bridgewater --- lib/internal/util/inspect.js | 17 +++++--- test/parallel/test-repl-top-level-await.js | 2 +- test/parallel/test-util-inspect.js | 50 +++++++++++++--------- 3 files changed, 41 insertions(+), 28 deletions(-) diff --git a/lib/internal/util/inspect.js b/lib/internal/util/inspect.js index ea81c85ec36b2d..9969771ada1e92 100644 --- a/lib/internal/util/inspect.js +++ b/lib/internal/util/inspect.js @@ -863,10 +863,7 @@ function formatRaw(ctx, value, recurseTimes, typedArray) { return `${braces[0]}}`; } } else if (typeof value === 'function') { - const matches = FunctionPrototypeToString(value).match(classRegExp); - base = matches ? - getClassBase(matches[1], value, constructor, tag) : - getFunctionBase(value, constructor, tag); + base = getFunctionBase(value, constructor, tag); if (keys.length === 0 && protoProps === undefined) return ctx.stylize(base, 'special'); } else if (isRegExp(value)) { @@ -1060,7 +1057,6 @@ function getBoxedBase(value, ctx, keys, constructor, tag) { } function getClassBase(string, value, constructor, tag) { - string = string.replace(stripCommentsRegExp, ''); const parts = string.split(/\s+/); if (parts[1] === 'extends') { parts[3] = parts[2]; @@ -1090,10 +1086,19 @@ function getClassBase(string, value, constructor, tag) { if (superClass !== undefined) { base += ` extends ${superClass}`; } - return `${base} {}`; + return `[${base}]`; } function getFunctionBase(value, constructor, tag) { + const stringified = FunctionPrototypeToString(value); + if (stringified.slice(0, 5) === 'class') { + const match = stringified + .replace(stripCommentsRegExp, ' ') + .match(classRegExp); + if (match !== null) { + return getClassBase(match[1], value, constructor, tag); + } + } let type = 'Function'; if (isGeneratorFunction(value)) { type = `Generator${type}`; diff --git a/test/parallel/test-repl-top-level-await.js b/test/parallel/test-repl-top-level-await.js index b6e75d1b1e5cb3..018d8707009ad9 100644 --- a/test/parallel/test-repl-top-level-await.js +++ b/test/parallel/test-repl-top-level-await.js @@ -116,7 +116,7 @@ async function ordinaryTests() { ['await 0; function foo() {}'], ['foo', '[Function: foo]'], ['class Foo {}; await 1;', '1'], - ['Foo', 'class Foo {}'], + ['Foo', '[class Foo]'], ['if (await true) { function bar() {}; }'], ['bar', '[Function: bar]'], ['if (await true) { class Bar {}; }'], diff --git a/test/parallel/test-util-inspect.js b/test/parallel/test-util-inspect.js index 44d04d17fbaea9..84770c23122031 100644 --- a/test/parallel/test-util-inspect.js +++ b/test/parallel/test-util-inspect.js @@ -1952,50 +1952,58 @@ assert.strictEqual(util.inspect('"\'${a}'), "'\"\\'${a}'"); // Verify that classes are properly inspected. [ + /* eslint-disable spaced-comment, no-multi-spaces, brace-style */ // The whitespace is intentional. - // eslint-disable-next-line no-multi-spaces - [class { }, 'class (anonymous) {}'], - [class extends Error { log() {} }, 'class (anonymous) extends Error {}'], - [class A { constructor(a) { this.a = a; } log() { return this.a; } }], + [class { }, '[class (anonymous)]'], + [class extends Error { log() {} }, '[class (anonymous) extends Error]'], + [class A { constructor(a) { this.a = a; } log() { return this.a; } }, + '[class A]'], [class - // Random comments are part of the stringified result - äß extends TypeError {}, 'class äß extends TypeError {}'], - // The whitespace and new line is intended! - // eslint-disable-next-line no-multi-spaces - [class X extends Error - // eslint-disable-next-line brace-style - {}, 'class X extends Error {}'] + // Random { // comments /* */ are part of the toString() result + /* eslint-disable-next-line space-before-blocks */ + äß/**/extends/*{*/TypeError{}, '[class äß extends TypeError]'], + /* The whitespace and new line is intended! */ + // Foobar !!! + [class X extends /****/ Error + // More comments + {}, '[class X extends Error]'] + /* eslint-enable spaced-comment, no-multi-spaces, brace-style */ ].forEach(([clazz, string]) => { - if (string === undefined) - string = Function.prototype.toString.call(clazz).split(/\s+/).join(' '); - const open = string.indexOf('{'); const inspected = util.inspect(clazz); - assert.strictEqual(inspected, `${string.slice(0, open + 1)}}`); + assert.strictEqual(inspected, string); Object.defineProperty(clazz, Symbol.toStringTag, { value: 'Woohoo' }); - const parts = inspected.split(' '); - parts.pop(); + 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, '[Woohoo]', ...rest, '{}'].join(' ') + ['[class', name, ...rest].join(' ') ); Object.setPrototypeOf(clazz, null); assert.strictEqual( util.inspect(clazz), - ['class', name, '[null prototype] [Woohoo]', ...rest, '{}'].join(' ') + ['[class', name, '[null prototype]', ...rest].join(' ') ); Object.defineProperty(clazz, 'name', { value: 'Foo' }); const newName = name === '(anonymous)' ? 'Foo' : `${name} [Foo]`; assert.strictEqual( util.inspect(clazz), - ['class', newName, '[null prototype] [Woohoo]', ...rest, '{}'].join(' ') + ['[class', newName, '[null prototype]', ...rest].join(' ') ); Object.setPrototypeOf(clazz, Number.prototype); assert.strictEqual( util.inspect(clazz), - ['class', newName, '[Number] [Woohoo]', ...rest, '{}'].join(' ') + ['[class', newName, '[Number]', ...rest].join(' ') + ); + clazz.foo = true; + assert.strictEqual( + util.inspect(clazz), + ['[class', newName, '[Number]', ...rest, '{ foo: true }'].join(' ') ); });