Skip to content

Commit

Permalink
util: use a shared symbol for util.inspect.custom
Browse files Browse the repository at this point in the history
Define `util.inspect.custom` as
`Symbol.for("nodejs.util.inspect.custom")` rather than
`Symbol("util.inspect.custom")`. This allows `inspect` hooks to
easily/safely be defined in non-Node.js environments.

Fixes: #20821
Refs: #22684

PR-URL: #20857
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Tiancheng "Timothy" Gu <timothygu99@gmail.com>
Reviewed-By: Sakthipriyan Vairamani <thechargingvolcano@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Michaël Zasso <targos@protonmail.com>
Reviewed-By: John-David Dalton <john.david.dalton@gmail.com>
  • Loading branch information
chocolateboy authored and targos committed Sep 15, 2018
1 parent 16210ca commit dadd6e1
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 15 deletions.
46 changes: 40 additions & 6 deletions doc/api/util.md
Original file line number Diff line number Diff line change
Expand Up @@ -574,9 +574,10 @@ terminals.

<!-- type=misc -->

Objects may also define their own `[util.inspect.custom](depth, opts)` function
that `util.inspect()` will invoke and use the result of when inspecting the
object:
Objects may also define their own
[`[util.inspect.custom](depth, opts)`][util.inspect.custom] function,
which `util.inspect()` will invoke and use the result of when inspecting
the object:

```js
const util = require('util');
Expand Down Expand Up @@ -628,10 +629,41 @@ util.inspect(obj);
### util.inspect.custom
<!-- YAML
added: v6.6.0
changes:
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/20857
description: This is now defined as a shared symbol.
-->

* {symbol} that can be used to declare custom inspect functions, see
[Custom inspection functions on Objects][].
* {symbol} that can be used to declare custom inspect functions.

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')`.

```js
const inspect = Symbol.for('nodejs.util.inspect.custom');

class Password {
constructor(value) {
this.value = value;
}

toString() {
return 'xxxxxxxx';
}

[inspect]() {
return `Password <${this.toString()}>`;
}
}

const password = new Password('r0sebud');
console.log(password);
// Prints Password <xxxxxxxx>
```

See [Custom inspection functions on Objects][] for more details.

### util.inspect.defaultOptions
<!-- YAML
Expand Down Expand Up @@ -2076,7 +2108,6 @@ Deprecated predecessor of `console.log`.
[`Array.isArray()`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray
[`ArrayBuffer`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer
[`ArrayBuffer.isView()`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer/isView
[async function]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function
[`assert.deepStrictEqual()`]: assert.html#assert_assert_deepstrictequal_actual_expected_message
[`Buffer.isBuffer()`]: buffer.html#buffer_class_method_buffer_isbuffer_obj
[`console.error()`]: console.html#console_console_error_data_args
Expand Down Expand Up @@ -2118,6 +2149,9 @@ Deprecated predecessor of `console.log`.
[Module Namespace Object]: https://tc39.github.io/ecma262/#sec-module-namespace-exotic-objects
[WHATWG Encoding Standard]: https://encoding.spec.whatwg.org/
[Common System Errors]: errors.html#errors_common_system_errors
[async function]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function
[constructor]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/constructor
[global symbol registry]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/for
[list of deprecated APIS]: deprecations.html#deprecations_list_of_deprecated_apis
[semantically incompatible]: https://github.com/nodejs/node/issues/4179
[util.inspect.custom]: #util_util_inspect_custom
2 changes: 1 addition & 1 deletion lib/internal/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -400,7 +400,7 @@ module.exports = {

// Symbol used to provide a custom inspect function for an object as an
// alternative to using 'inspect'
customInspectSymbol: Symbol('util.inspect.custom'),
customInspectSymbol: Symbol.for('nodejs.util.inspect.custom'),

// Used by the buffer module to capture an internal reference to the
// default isEncoding implementation, just in case userland overrides it.
Expand Down
2 changes: 1 addition & 1 deletion test/parallel/test-assert.js
Original file line number Diff line number Diff line change
Expand Up @@ -603,7 +603,7 @@ assert.throws(
'+ {}\n' +
'- {\n' +
"- loop: 'forever',\n" +
'- [Symbol(util.inspect.custom)]: [Function]\n' +
'- [Symbol(nodejs.util.inspect.custom)]: [Function]\n' +
'- }'
});

Expand Down
8 changes: 4 additions & 4 deletions test/parallel/test-console.js
Original file line number Diff line number Diff line change
Expand Up @@ -214,11 +214,11 @@ for (const expected of expectedStrings) {
}

assert.strictEqual(strings.shift(),
"{ foo: 'bar',\n [Symbol(util.inspect.custom)]: " +
'[Function: [util.inspect.custom]] }\n');
"{ foo: 'bar',\n [Symbol(nodejs.util.inspect.custom)]: " +
'[Function: [nodejs.util.inspect.custom]] }\n');
assert.strictEqual(strings.shift(),
"{ foo: 'bar',\n [Symbol(util.inspect.custom)]: " +
'[Function: [util.inspect.custom]] }\n');
"{ foo: 'bar',\n [Symbol(nodejs.util.inspect.custom)]: " +
'[Function: [nodejs.util.inspect.custom]] }\n');
assert.ok(strings.shift().includes('foo: [Object]'));
assert.strictEqual(strings.shift().includes('baz'), false);
assert.strictEqual(strings.shift(), 'inspect inspect\n');
Expand Down
20 changes: 17 additions & 3 deletions test/parallel/test-util-inspect.js
Original file line number Diff line number Diff line change
Expand Up @@ -627,7 +627,7 @@ assert.strictEqual(util.inspect(Object.create(Date.prototype)), 'Date {}');
{
const x = { [util.inspect.custom]: util.inspect };
assert(util.inspect(x).includes(
'[Symbol(util.inspect.custom)]:\n { [Function: inspect]'));
'[Symbol(nodejs.util.inspect.custom)]:\n { [Function: inspect]'));
}

// `util.inspect` should display the escaped value of a key.
Expand Down Expand Up @@ -758,12 +758,26 @@ util.inspect({ hasOwnProperty: null });
};

util.inspect(subject, { customInspectOptions: true });

// util.inspect.custom is a shared symbol which can be accessed as
// Symbol.for("nodejs.util.inspect.custom").
const inspect = Symbol.for('nodejs.util.inspect.custom');

subject[inspect] = () => ({ baz: 'quux' });

assert.strictEqual(util.inspect(subject), '{ baz: \'quux\' }');

subject[inspect] = (depth, opts) => {
assert.strictEqual(opts.customInspectOptions, true);
};

util.inspect(subject, { customInspectOptions: true });
}

{
// Returning `this` from a custom inspection function works.
const subject = { a: 123, [util.inspect.custom]() { return this; } };
const UIC = 'util.inspect.custom';
const UIC = 'nodejs.util.inspect.custom';
assert.strictEqual(util.inspect(subject),
`{ a: 123,\n [Symbol(${UIC})]: [Function: [${UIC}]] }`);
}
Expand Down Expand Up @@ -1188,7 +1202,7 @@ util.inspect(process);
const obj = { [util.inspect.custom]: 'fhqwhgads' };
assert.strictEqual(
util.inspect(obj),
"{ [Symbol(util.inspect.custom)]: 'fhqwhgads' }"
"{ [Symbol(nodejs.util.inspect.custom)]: 'fhqwhgads' }"
);
}

Expand Down

0 comments on commit dadd6e1

Please sign in to comment.