util: fix inspection of class instance prototypes
To achieve this, some internal custom inspect functions had to be changed. They relied upon the former behavior. Signed-off-by: Ruben Bridgewater <ruben@bridgewater.de> PR-URL: https://github.com/nodejs/node/pull/33449 Fixes: https://github.com/nodejs/node/issues/33419 Reviewed-By: Anto Aravinth <anto.aravinth.cse@gmail.com> Reviewed-By: Michaël Zasso <targos@protonmail.com> Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
This commit is contained in:
parent
2f00ca42bf
commit
e24731cb70
@ -514,54 +514,53 @@ function makeTextDecoderJS() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Mix in some shared properties.
|
// Mix in some shared properties.
|
||||||
{
|
ObjectDefineProperties(
|
||||||
ObjectDefineProperties(
|
TextDecoder.prototype,
|
||||||
TextDecoder.prototype,
|
ObjectGetOwnPropertyDescriptors({
|
||||||
ObjectGetOwnPropertyDescriptors({
|
get encoding() {
|
||||||
get encoding() {
|
validateDecoder(this);
|
||||||
validateDecoder(this);
|
return this[kEncoding];
|
||||||
return this[kEncoding];
|
},
|
||||||
},
|
|
||||||
|
|
||||||
get fatal() {
|
get fatal() {
|
||||||
validateDecoder(this);
|
validateDecoder(this);
|
||||||
return (this[kFlags] & CONVERTER_FLAGS_FATAL) === CONVERTER_FLAGS_FATAL;
|
return (this[kFlags] & CONVERTER_FLAGS_FATAL) === CONVERTER_FLAGS_FATAL;
|
||||||
},
|
},
|
||||||
|
|
||||||
get ignoreBOM() {
|
get ignoreBOM() {
|
||||||
validateDecoder(this);
|
validateDecoder(this);
|
||||||
return (this[kFlags] & CONVERTER_FLAGS_IGNORE_BOM) ===
|
return (this[kFlags] & CONVERTER_FLAGS_IGNORE_BOM) ===
|
||||||
CONVERTER_FLAGS_IGNORE_BOM;
|
CONVERTER_FLAGS_IGNORE_BOM;
|
||||||
},
|
},
|
||||||
|
|
||||||
[inspect](depth, opts) {
|
[inspect](depth, opts) {
|
||||||
validateDecoder(this);
|
validateDecoder(this);
|
||||||
if (typeof depth === 'number' && depth < 0)
|
if (typeof depth === 'number' && depth < 0)
|
||||||
return this;
|
return this;
|
||||||
const ctor = getConstructorOf(this);
|
const constructor = getConstructorOf(this) || TextDecoder;
|
||||||
const obj = ObjectCreate({
|
const obj = ObjectCreate({ constructor });
|
||||||
constructor: ctor === null ? TextDecoder : ctor
|
obj.encoding = this.encoding;
|
||||||
});
|
obj.fatal = this.fatal;
|
||||||
obj.encoding = this.encoding;
|
obj.ignoreBOM = this.ignoreBOM;
|
||||||
obj.fatal = this.fatal;
|
if (opts.showHidden) {
|
||||||
obj.ignoreBOM = this.ignoreBOM;
|
obj[kFlags] = this[kFlags];
|
||||||
if (opts.showHidden) {
|
obj[kHandle] = this[kHandle];
|
||||||
obj[kFlags] = this[kFlags];
|
|
||||||
obj[kHandle] = this[kHandle];
|
|
||||||
}
|
|
||||||
// Lazy to avoid circular dependency
|
|
||||||
return require('internal/util/inspect').inspect(obj, opts);
|
|
||||||
}
|
}
|
||||||
}));
|
// Lazy to avoid circular dependency
|
||||||
ObjectDefineProperties(TextDecoder.prototype, {
|
const { inspect } = require('internal/util/inspect');
|
||||||
decode: { enumerable: true },
|
return `${constructor.name} ${inspect(obj)}`;
|
||||||
[inspect]: { enumerable: false },
|
|
||||||
[SymbolToStringTag]: {
|
|
||||||
configurable: true,
|
|
||||||
value: 'TextDecoder'
|
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
}
|
);
|
||||||
|
|
||||||
|
ObjectDefineProperties(TextDecoder.prototype, {
|
||||||
|
decode: { enumerable: true },
|
||||||
|
[inspect]: { enumerable: false },
|
||||||
|
[SymbolToStringTag]: {
|
||||||
|
configurable: true,
|
||||||
|
value: 'TextDecoder'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
getEncodingFromLabel,
|
getEncodingFromLabel,
|
||||||
|
@ -358,11 +358,8 @@ class URL {
|
|||||||
if (typeof depth === 'number' && depth < 0)
|
if (typeof depth === 'number' && depth < 0)
|
||||||
return this;
|
return this;
|
||||||
|
|
||||||
const ctor = getConstructorOf(this);
|
const constructor = getConstructorOf(this) || URL;
|
||||||
|
const obj = ObjectCreate({ constructor });
|
||||||
const obj = ObjectCreate({
|
|
||||||
constructor: ctor === null ? URL : ctor
|
|
||||||
});
|
|
||||||
|
|
||||||
obj.href = this.href;
|
obj.href = this.href;
|
||||||
obj.origin = this.origin;
|
obj.origin = this.origin;
|
||||||
@ -383,7 +380,7 @@ class URL {
|
|||||||
obj[context] = this[context];
|
obj[context] = this[context];
|
||||||
}
|
}
|
||||||
|
|
||||||
return inspect(obj, opts);
|
return `${constructor.name} ${inspect(obj, opts)}`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -498,7 +498,8 @@ function getConstructorName(obj, ctx, recurseTimes, protoProps) {
|
|||||||
const descriptor = ObjectGetOwnPropertyDescriptor(obj, 'constructor');
|
const descriptor = ObjectGetOwnPropertyDescriptor(obj, 'constructor');
|
||||||
if (descriptor !== undefined &&
|
if (descriptor !== undefined &&
|
||||||
typeof descriptor.value === 'function' &&
|
typeof descriptor.value === 'function' &&
|
||||||
descriptor.value.name !== '') {
|
descriptor.value.name !== '' &&
|
||||||
|
tmp instanceof descriptor.value) {
|
||||||
if (protoProps !== undefined &&
|
if (protoProps !== undefined &&
|
||||||
(firstProto !== obj ||
|
(firstProto !== obj ||
|
||||||
!builtInObjects.has(descriptor.value.name))) {
|
!builtInObjects.has(descriptor.value.name))) {
|
||||||
|
@ -5,6 +5,8 @@ const {
|
|||||||
ArrayIsArray,
|
ArrayIsArray,
|
||||||
ObjectCreate,
|
ObjectCreate,
|
||||||
ObjectDefineProperty,
|
ObjectDefineProperty,
|
||||||
|
ObjectGetPrototypeOf,
|
||||||
|
ObjectSetPrototypeOf,
|
||||||
SafePromise,
|
SafePromise,
|
||||||
Symbol,
|
Symbol,
|
||||||
WeakMap,
|
WeakMap,
|
||||||
@ -223,17 +225,27 @@ class Module {
|
|||||||
}
|
}
|
||||||
|
|
||||||
[customInspectSymbol](depth, options) {
|
[customInspectSymbol](depth, options) {
|
||||||
let ctor = getConstructorOf(this);
|
if (this[kWrap] === undefined) {
|
||||||
ctor = ctor === null ? Module : ctor;
|
throw new ERR_VM_MODULE_NOT_MODULE();
|
||||||
|
}
|
||||||
if (typeof depth === 'number' && depth < 0)
|
if (typeof depth === 'number' && depth < 0)
|
||||||
return options.stylize(`[${ctor.name}]`, 'special');
|
return this;
|
||||||
|
|
||||||
const o = ObjectCreate({ constructor: ctor });
|
const constructor = getConstructorOf(this) || Module;
|
||||||
|
const o = ObjectCreate({ constructor });
|
||||||
o.status = this.status;
|
o.status = this.status;
|
||||||
o.identifier = this.identifier;
|
o.identifier = this.identifier;
|
||||||
o.context = this.context;
|
o.context = this.context;
|
||||||
return require('internal/util/inspect').inspect(o, options);
|
|
||||||
|
ObjectSetPrototypeOf(o, ObjectGetPrototypeOf(this));
|
||||||
|
ObjectDefineProperty(o, Symbol.toStringTag, {
|
||||||
|
value: constructor.name,
|
||||||
|
configurable: true
|
||||||
|
});
|
||||||
|
|
||||||
|
// Lazy to avoid circular dependency
|
||||||
|
const { inspect } = require('internal/util/inspect');
|
||||||
|
return inspect(o, { ...options, customInspect: false });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -266,7 +266,7 @@ assert.strictEqual(
|
|||||||
' func: <ref *1> [Function: func] {\n' +
|
' func: <ref *1> [Function: func] {\n' +
|
||||||
' [length]: 0,\n' +
|
' [length]: 0,\n' +
|
||||||
' [name]: \'func\',\n' +
|
' [name]: \'func\',\n' +
|
||||||
' [prototype]: func { [constructor]: [Circular *1] }\n' +
|
' [prototype]: { [constructor]: [Circular *1] }\n' +
|
||||||
' }\n' +
|
' }\n' +
|
||||||
'}');
|
'}');
|
||||||
assert.strictEqual(
|
assert.strictEqual(
|
||||||
@ -279,7 +279,7 @@ assert.strictEqual(
|
|||||||
' a: <ref *1> [Function: a] {\n' +
|
' a: <ref *1> [Function: a] {\n' +
|
||||||
' [length]: 0,\n' +
|
' [length]: 0,\n' +
|
||||||
' [name]: \'a\',\n' +
|
' [name]: \'a\',\n' +
|
||||||
' [prototype]: a { [constructor]: [Circular *1] }\n' +
|
' [prototype]: { [constructor]: [Circular *1] }\n' +
|
||||||
' }\n' +
|
' }\n' +
|
||||||
' },\n' +
|
' },\n' +
|
||||||
' [length]: 1\n' +
|
' [length]: 1\n' +
|
||||||
@ -294,7 +294,7 @@ assert.strictEqual(
|
|||||||
' func: <ref *1> [Function: func] {\n' +
|
' func: <ref *1> [Function: func] {\n' +
|
||||||
' [length]: 0,\n' +
|
' [length]: 0,\n' +
|
||||||
' [name]: \'func\',\n' +
|
' [name]: \'func\',\n' +
|
||||||
' [prototype]: func { [constructor]: [Circular *1] }\n' +
|
' [prototype]: { [constructor]: [Circular *1] }\n' +
|
||||||
' }\n' +
|
' }\n' +
|
||||||
' }\n' +
|
' }\n' +
|
||||||
'}');
|
'}');
|
||||||
@ -306,7 +306,7 @@ assert.strictEqual(
|
|||||||
' func: <ref *1> [Function: func] {\n' +
|
' func: <ref *1> [Function: func] {\n' +
|
||||||
' [length]: 0,\n' +
|
' [length]: 0,\n' +
|
||||||
' [name]: \'func\',\n' +
|
' [name]: \'func\',\n' +
|
||||||
' [prototype]: func { [constructor]: [Circular *1] }\n' +
|
' [prototype]: { [constructor]: [Circular *1] }\n' +
|
||||||
' }\n' +
|
' }\n' +
|
||||||
'} {\n' +
|
'} {\n' +
|
||||||
' foo: \'bar\',\n' +
|
' foo: \'bar\',\n' +
|
||||||
@ -314,7 +314,7 @@ assert.strictEqual(
|
|||||||
' func: <ref *1> [Function: func] {\n' +
|
' func: <ref *1> [Function: func] {\n' +
|
||||||
' [length]: 0,\n' +
|
' [length]: 0,\n' +
|
||||||
' [name]: \'func\',\n' +
|
' [name]: \'func\',\n' +
|
||||||
' [prototype]: func { [constructor]: [Circular *1] }\n' +
|
' [prototype]: { [constructor]: [Circular *1] }\n' +
|
||||||
' }\n' +
|
' }\n' +
|
||||||
'}');
|
'}');
|
||||||
assert.strictEqual(
|
assert.strictEqual(
|
||||||
@ -325,7 +325,7 @@ assert.strictEqual(
|
|||||||
' func: <ref *1> [Function: func] {\n' +
|
' func: <ref *1> [Function: func] {\n' +
|
||||||
' [length]: 0,\n' +
|
' [length]: 0,\n' +
|
||||||
' [name]: \'func\',\n' +
|
' [name]: \'func\',\n' +
|
||||||
' [prototype]: func { [constructor]: [Circular *1] }\n' +
|
' [prototype]: { [constructor]: [Circular *1] }\n' +
|
||||||
' }\n' +
|
' }\n' +
|
||||||
'} %o');
|
'} %o');
|
||||||
|
|
||||||
|
@ -2827,6 +2827,37 @@ assert.strictEqual(
|
|||||||
'{ \x1B[2mabc: \x1B[33mtrue\x1B[39m\x1B[22m, ' +
|
'{ \x1B[2mabc: \x1B[33mtrue\x1B[39m\x1B[22m, ' +
|
||||||
'\x1B[2mdef: \x1B[33m5\x1B[39m\x1B[22m }'
|
'\x1B[2mdef: \x1B[33m5\x1B[39m\x1B[22m }'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
assert.strictEqual(
|
||||||
|
inspect(Object.getPrototypeOf(bar), { showHidden: true, getters: true }),
|
||||||
|
'<ref *1> Foo [Map] {\n' +
|
||||||
|
' [constructor]: [class Bar extends Foo] {\n' +
|
||||||
|
' [length]: 0,\n' +
|
||||||
|
' [prototype]: [Circular *1],\n' +
|
||||||
|
" [name]: 'Bar',\n" +
|
||||||
|
' [Symbol(Symbol.species)]: [Getter: <Inspection threw ' +
|
||||||
|
"(Symbol.prototype.toString requires that 'this' be a Symbol)>]\n" +
|
||||||
|
' },\n' +
|
||||||
|
" [xyz]: [Getter: 'YES!'],\n" +
|
||||||
|
' [Symbol(nodejs.util.inspect.custom)]: ' +
|
||||||
|
'[Function: [nodejs.util.inspect.custom]] {\n' +
|
||||||
|
' [length]: 0,\n' +
|
||||||
|
" [name]: '[nodejs.util.inspect.custom]'\n" +
|
||||||
|
' },\n' +
|
||||||
|
' [abc]: [Getter: true],\n' +
|
||||||
|
' [def]: [Getter/Setter: false]\n' +
|
||||||
|
' }'
|
||||||
|
);
|
||||||
|
|
||||||
|
assert.strictEqual(
|
||||||
|
inspect(Object.getPrototypeOf(bar)),
|
||||||
|
'Foo [Map] {}'
|
||||||
|
);
|
||||||
|
|
||||||
|
assert.strictEqual(
|
||||||
|
inspect(Object.getPrototypeOf(new Foo())),
|
||||||
|
'Map {}'
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test changing util.inspect.colors colors and aliases.
|
// Test changing util.inspect.colors colors and aliases.
|
||||||
|
@ -83,9 +83,12 @@ const util = require('util');
|
|||||||
|
|
||||||
assert.strictEqual(util.inspect(m, { depth: -1 }), '[SourceTextModule]');
|
assert.strictEqual(util.inspect(m, { depth: -1 }), '[SourceTextModule]');
|
||||||
|
|
||||||
assert.strictEqual(
|
assert.throws(
|
||||||
m[util.inspect.custom].call(Object.create(null)),
|
() => m[util.inspect.custom].call(Object.create(null)),
|
||||||
'Module { status: undefined, identifier: undefined, context: undefined }',
|
{
|
||||||
|
code: 'ERR_VM_MODULE_NOT_MODULE',
|
||||||
|
message: 'Provided module is not an instance of Module'
|
||||||
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,6 +85,7 @@ if (common.hasIntl) {
|
|||||||
assert.strictEqual(dec.encoding, 'utf-8');
|
assert.strictEqual(dec.encoding, 'utf-8');
|
||||||
assert.strictEqual(dec.fatal, false);
|
assert.strictEqual(dec.fatal, false);
|
||||||
assert.strictEqual(dec.ignoreBOM, false);
|
assert.strictEqual(dec.ignoreBOM, false);
|
||||||
|
assert.strictEqual(dec[Symbol.toStringTag], 'TextDecoder');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test TextDecoder, UTF-16le
|
// Test TextDecoder, UTF-16le
|
||||||
@ -125,10 +126,7 @@ if (common.hasIntl) {
|
|||||||
' [Symbol(flags)]: 4,\n' +
|
' [Symbol(flags)]: 4,\n' +
|
||||||
' [Symbol(handle)]: StringDecoder {\n' +
|
' [Symbol(handle)]: StringDecoder {\n' +
|
||||||
" encoding: 'utf8',\n" +
|
" encoding: 'utf8',\n" +
|
||||||
' [Symbol(kNativeDecoder)]: <Buffer 00 00 00 00 00 00 01>,\n' +
|
' [Symbol(kNativeDecoder)]: <Buffer 00 00 00 00 00 00 01>\n' +
|
||||||
' lastChar: [Getter],\n' +
|
|
||||||
' lastNeed: [Getter],\n' +
|
|
||||||
' lastTotal: [Getter]\n' +
|
|
||||||
' }\n' +
|
' }\n' +
|
||||||
'}'
|
'}'
|
||||||
);
|
);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user