Skip to content

Commit 5b9e46b

Browse files
BridgeARdanielleadams
authored andcommitted
util: pass through the inspect function to custom inspect functions
This allows to use more portable custom inspect functions. Fixes: #35956 Signed-off-by: Ruben Bridgewater <[email protected]> PR-URL: #41019 Reviewed-By: Michaël Zasso <[email protected]>
1 parent 71772d2 commit 5b9e46b

File tree

3 files changed

+35
-16
lines changed

3 files changed

+35
-16
lines changed

doc/api/util.md

+24-11
Original file line numberDiff line numberDiff line change
@@ -577,7 +577,7 @@ changes:
577577
codes. Colors are customizable. See [Customizing `util.inspect` colors][].
578578
**Default:** `false`.
579579
* `customInspect` {boolean} If `false`,
580-
`[util.inspect.custom](depth, opts)` functions are not invoked.
580+
`[util.inspect.custom](depth, opts, inspect)` functions are not invoked.
581581
**Default:** `true`.
582582
* `showProxy` {boolean} If `true`, `Proxy` inspection includes
583583
the [`target` and `handler`][] objects. **Default:** `false`.
@@ -872,10 +872,18 @@ ignored, if not supported.
872872

873873
<!-- type=misc -->
874874

875+
<!-- YAML
876+
added: v0.1.97
877+
changes:
878+
- version: REPLACEME
879+
pr-url: https://github.com/nodejs/node/pull/41019
880+
description: The inspect argument is added for more interoperability.
881+
-->
882+
875883
Objects may also define their own
876-
[`[util.inspect.custom](depth, opts)`][util.inspect.custom] function,
884+
[`[util.inspect.custom](depth, opts, inspect)`][util.inspect.custom] function,
877885
which `util.inspect()` will invoke and use the result of when inspecting
878-
the object:
886+
the object.
879887

880888
```js
881889
const util = require('util');
@@ -885,7 +893,7 @@ class Box {
885893
this.value = value;
886894
}
887895

888-
[util.inspect.custom](depth, options) {
896+
[util.inspect.custom](depth, options, inspect) {
889897
if (depth < 0) {
890898
return options.stylize('[Box]', 'special');
891899
}
@@ -896,8 +904,8 @@ class Box {
896904

897905
// Five space padding because that's the size of "Box< ".
898906
const padding = ' '.repeat(5);
899-
const inner = util.inspect(this.value, newOptions)
900-
.replace(/\n/g, `\n${padding}`);
907+
const inner = inspect(this.value, newOptions)
908+
.replace(/\n/g, `\n${padding}`);
901909
return `${options.stylize('Box', 'special')}< ${inner} >`;
902910
}
903911
}
@@ -908,9 +916,9 @@ util.inspect(box);
908916
// Returns: "Box< true >"
909917
```
910918

911-
Custom `[util.inspect.custom](depth, opts)` functions typically return a string
912-
but may return a value of any type that will be formatted accordingly by
913-
`util.inspect()`.
919+
Custom `[util.inspect.custom](depth, opts, inspect)` functions typically return
920+
a string but may return a value of any type that will be formatted accordingly
921+
by `util.inspect()`.
914922

915923
```js
916924
const util = require('util');
@@ -940,8 +948,13 @@ In addition to being accessible through `util.inspect.custom`, this
940948
symbol is [registered globally][global symbol registry] and can be
941949
accessed in any environment as `Symbol.for('nodejs.util.inspect.custom')`.
942950

951+
Using this allows code to be written in a portable fashion, so that the custom
952+
inspect function is used in an Node.js environment and ignored in the browser.
953+
The `util.inspect()` function itself is passed as third argument to the custom
954+
inspect function to allow further portability.
955+
943956
```js
944-
const inspect = Symbol.for('nodejs.util.inspect.custom');
957+
const customInspectSymbol = Symbol.for('nodejs.util.inspect.custom');
945958

946959
class Password {
947960
constructor(value) {
@@ -952,7 +965,7 @@ class Password {
952965
return 'xxxxxxxx';
953966
}
954967

955-
[inspect]() {
968+
[customInspectSymbol](depth, inspectOptions, inspect) {
956969
return `Password <${this.toString()}>`;
957970
}
958971
}

lib/internal/util/inspect.js

+7-2
Original file line numberDiff line numberDiff line change
@@ -778,7 +778,12 @@ function formatValue(ctx, value, recurseTimes, typedArray) {
778778
const isCrossContext =
779779
proxy !== undefined || !(context instanceof Object);
780780
const ret = FunctionPrototypeCall(
781-
maybeCustom, context, depth, getUserOptions(ctx, isCrossContext));
781+
maybeCustom,
782+
context,
783+
depth,
784+
getUserOptions(ctx, isCrossContext),
785+
inspect
786+
);
782787
// If the custom inspection method returned `this`, don't go into
783788
// infinite recursion.
784789
if (ret !== context) {
@@ -1143,7 +1148,7 @@ function getClassBase(value, constructor, tag) {
11431148

11441149
function getFunctionBase(value, constructor, tag) {
11451150
const stringified = FunctionPrototypeToString(value);
1146-
if (stringified.slice(0, 5) === 'class' && stringified.endsWith('}')) {
1151+
if (stringified.startsWith('class') && stringified.endsWith('}')) {
11471152
const slice = stringified.slice(5, -1);
11481153
const bracketIndex = slice.indexOf('{');
11491154
if (bracketIndex !== -1 &&

test/parallel/test-util-inspect.js

+4-3
Original file line numberDiff line numberDiff line change
@@ -974,7 +974,7 @@ util.inspect({ hasOwnProperty: null });
974974

975975
assert.strictEqual(util.inspect(subject), "{ foo: 'bar' }");
976976

977-
subject[util.inspect.custom] = common.mustCall((depth, opts) => {
977+
subject[util.inspect.custom] = common.mustCall((depth, opts, inspect) => {
978978
const clone = { ...opts };
979979
// This might change at some point but for now we keep the stylize function.
980980
// The function should either be documented or an alternative should be
@@ -984,12 +984,13 @@ util.inspect({ hasOwnProperty: null });
984984
assert.strictEqual(opts.budget, undefined);
985985
assert.strictEqual(opts.indentationLvl, undefined);
986986
assert.strictEqual(opts.showHidden, false);
987+
assert.strictEqual(inspect, util.inspect);
987988
assert.deepStrictEqual(
988-
new Set(Object.keys(util.inspect.defaultOptions).concat(['stylize'])),
989+
new Set(Object.keys(inspect.defaultOptions).concat(['stylize'])),
989990
new Set(Object.keys(opts))
990991
);
991992
opts.showHidden = true;
992-
return { [util.inspect.custom]: common.mustCall((depth, opts2) => {
993+
return { [inspect.custom]: common.mustCall((depth, opts2) => {
993994
assert.deepStrictEqual(clone, opts2);
994995
}) };
995996
});

0 commit comments

Comments
 (0)