mirror of
https://github.com/nodejs/node.git
synced 2026-10-14 10:26:26 -04:00
util: pass through the inspect function to custom inspect functions
This allows to use more portable custom inspect functions. Fixes: https://github.com/nodejs/node/issues/35956 Signed-off-by: Ruben Bridgewater <ruben@bridgewater.de> PR-URL: https://github.com/nodejs/node/pull/41019 Reviewed-By: Michaël Zasso <targos@protonmail.com>
This commit is contained in:
1 parent
73fe15bf24
commit
4569674e39
3 files changed
+35
-16
No files matched your search
+24
-11
@@ -579,7 +579,7 @@ changes:
|
||||
codes. Colors are customizable. See [Customizing `util.inspect` colors][].
|
||||
**Default:** `false`.
|
||||
* `customInspect` {boolean} If `false`,
|
||||
`[util.inspect.custom](depth, opts)` functions are not invoked.
|
||||
`[util.inspect.custom](depth, opts, inspect)` functions are not invoked.
|
||||
**Default:** `true`.
|
||||
* `showProxy` {boolean} If `true`, `Proxy` inspection includes
|
||||
the [`target` and `handler`][] objects. **Default:** `false`.
|
||||
@@ -874,10 +874,18 @@ ignored, if not supported.
|
||||
|
||||
<!-- type=misc -->
|
||||
|
||||
<!-- YAML
|
||||
added: v0.1.97
|
||||
changes:
|
||||
- version: REPLACEME
|
||||
pr-url: https://github.com/nodejs/node/pull/41019
|
||||
description: The inspect argument is added for more interoperability.
|
||||
-->
|
||||
|
||||
Objects may also define their own
|
||||
[`[util.inspect.custom](depth, opts)`][util.inspect.custom] function,
|
||||
[`[util.inspect.custom](depth, opts, inspect)`][util.inspect.custom] function,
|
||||
which `util.inspect()` will invoke and use the result of when inspecting
|
||||
the object:
|
||||
the object.
|
||||
|
||||
```js
|
||||
const util = require('util');
|
||||
@@ -887,7 +895,7 @@ class Box {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
[util.inspect.custom](depth, options) {
|
||||
[util.inspect.custom](depth, options, inspect) {
|
||||
if (depth < 0) {
|
||||
return options.stylize('[Box]', 'special');
|
||||
}
|
||||
@@ -898,8 +906,8 @@ class Box {
|
||||
|
||||
// Five space padding because that's the size of "Box< ".
|
||||
const padding = ' '.repeat(5);
|
||||
const inner = util.inspect(this.value, newOptions)
|
||||
.replace(/\n/g, `\n${padding}`);
|
||||
const inner = inspect(this.value, newOptions)
|
||||
.replace(/\n/g, `\n${padding}`);
|
||||
return `${options.stylize('Box', 'special')}< ${inner} >`;
|
||||
}
|
||||
}
|
||||
@@ -910,9 +918,9 @@ util.inspect(box);
|
||||
// Returns: "Box< true >"
|
||||
```
|
||||
|
||||
Custom `[util.inspect.custom](depth, opts)` functions typically return a string
|
||||
but may return a value of any type that will be formatted accordingly by
|
||||
`util.inspect()`.
|
||||
Custom `[util.inspect.custom](depth, opts, inspect)` functions typically return
|
||||
a string but may return a value of any type that will be formatted accordingly
|
||||
by `util.inspect()`.
|
||||
|
||||
```js
|
||||
const util = require('util');
|
||||
@@ -942,8 +950,13 @@ In addition to being accessible through `util.inspect.custom`, this
|
||||
symbol is [registered globally][global symbol registry] and can be
|
||||
accessed in any environment as `Symbol.for('nodejs.util.inspect.custom')`.
|
||||
|
||||
Using this allows code to be written in a portable fashion, so that the custom
|
||||
inspect function is used in an Node.js environment and ignored in the browser.
|
||||
The `util.inspect()` function itself is passed as third argument to the custom
|
||||
inspect function to allow further portability.
|
||||
|
||||
```js
|
||||
const inspect = Symbol.for('nodejs.util.inspect.custom');
|
||||
const customInspectSymbol = Symbol.for('nodejs.util.inspect.custom');
|
||||
|
||||
class Password {
|
||||
constructor(value) {
|
||||
@@ -954,7 +967,7 @@ class Password {
|
||||
return 'xxxxxxxx';
|
||||
}
|
||||
|
||||
[inspect]() {
|
||||
[customInspectSymbol](depth, inspectOptions, inspect) {
|
||||
return `Password <${this.toString()}>`;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -778,7 +778,12 @@ function formatValue(ctx, value, recurseTimes, typedArray) {
|
||||
const isCrossContext =
|
||||
proxy !== undefined || !(context instanceof Object);
|
||||
const ret = FunctionPrototypeCall(
|
||||
maybeCustom, context, depth, getUserOptions(ctx, isCrossContext));
|
||||
maybeCustom,
|
||||
context,
|
||||
depth,
|
||||
getUserOptions(ctx, isCrossContext),
|
||||
inspect
|
||||
);
|
||||
// If the custom inspection method returned `this`, don't go into
|
||||
// infinite recursion.
|
||||
if (ret !== context) {
|
||||
@@ -1143,7 +1148,7 @@ function getClassBase(value, constructor, tag) {
|
||||
|
||||
function getFunctionBase(value, constructor, tag) {
|
||||
const stringified = FunctionPrototypeToString(value);
|
||||
if (stringified.slice(0, 5) === 'class' && stringified.endsWith('}')) {
|
||||
if (stringified.startsWith('class') && stringified.endsWith('}')) {
|
||||
const slice = stringified.slice(5, -1);
|
||||
const bracketIndex = slice.indexOf('{');
|
||||
if (bracketIndex !== -1 &&
|
||||
|
||||
@@ -974,7 +974,7 @@ util.inspect({ hasOwnProperty: null });
|
||||
|
||||
assert.strictEqual(util.inspect(subject), "{ foo: 'bar' }");
|
||||
|
||||
subject[util.inspect.custom] = common.mustCall((depth, opts) => {
|
||||
subject[util.inspect.custom] = common.mustCall((depth, opts, inspect) => {
|
||||
const clone = { ...opts };
|
||||
// This might change at some point but for now we keep the stylize function.
|
||||
// The function should either be documented or an alternative should be
|
||||
@@ -984,12 +984,13 @@ util.inspect({ hasOwnProperty: null });
|
||||
assert.strictEqual(opts.budget, undefined);
|
||||
assert.strictEqual(opts.indentationLvl, undefined);
|
||||
assert.strictEqual(opts.showHidden, false);
|
||||
assert.strictEqual(inspect, util.inspect);
|
||||
assert.deepStrictEqual(
|
||||
new Set(Object.keys(util.inspect.defaultOptions).concat(['stylize'])),
|
||||
new Set(Object.keys(inspect.defaultOptions).concat(['stylize'])),
|
||||
new Set(Object.keys(opts))
|
||||
);
|
||||
opts.showHidden = true;
|
||||
return { [util.inspect.custom]: common.mustCall((depth, opts2) => {
|
||||
return { [inspect.custom]: common.mustCall((depth, opts2) => {
|
||||
assert.deepStrictEqual(clone, opts2);
|
||||
}) };
|
||||
});
|
||||
|
||||
Reference in new issue
Block a user