Skip to content

Commit

Permalink
fixup: add more tests, fix edge case, rework output
Browse files Browse the repository at this point in the history
Signed-off-by: Ruben Bridgewater <ruben@bridgewater.de>
  • Loading branch information
BridgeAR committed Mar 18, 2020
1 parent 12294e4 commit 5fb30dc
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 28 deletions.
17 changes: 11 additions & 6 deletions lib/internal/util/inspect.js
Original file line number Diff line number Diff line change
Expand Up @@ -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)) {
Expand Down Expand Up @@ -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];
Expand Down Expand Up @@ -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}`;
Expand Down
2 changes: 1 addition & 1 deletion test/parallel/test-repl-top-level-await.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 {}; }'],
Expand Down
50 changes: 29 additions & 21 deletions test/parallel/test-util-inspect.js
Original file line number Diff line number Diff line change
Expand Up @@ -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(' ')
);
});

Expand Down

0 comments on commit 5fb30dc

Please sign in to comment.