diff --git a/doc/api/deprecations.md b/doc/api/deprecations.md index 6cd51421935..9e386b1bd9e 100644 --- a/doc/api/deprecations.md +++ b/doc/api/deprecations.md @@ -703,7 +703,7 @@ Type: Runtime ### DEP0079: Custom inspection function on Objects via .inspect() -Type: Documentation-only +Type: Runtime Using a property named `inspect` on an object to specify a custom inspection function for [`util.inspect()`][] is deprecated. Use [`util.inspect.custom`][] diff --git a/doc/api/util.md b/doc/api/util.md index d790319862c..43f26e934d8 100644 --- a/doc/api/util.md +++ b/doc/api/util.md @@ -112,6 +112,7 @@ environment variable. For example: `NODE_DEBUG=fs,net,tls`. added: v0.8.0 changes: - version: REPLACEME + pr-url: https://github.com/nodejs/node/pull/16393 description: Deprecation warnings are only emitted once for each code. --> diff --git a/lib/util.js b/lib/util.js index 6d041fdf425..baace30469a 100644 --- a/lib/util.js +++ b/lib/util.js @@ -428,14 +428,23 @@ function formatValue(ctx, value, recurseTimes, ln) { // Provide a hook for user-specified inspect functions. // Check that value is an object with an inspect function on it if (ctx.customInspect) { - const maybeCustomInspect = value[customInspectSymbol] || value.inspect; + let maybeCustom = value[customInspectSymbol]; - if (typeof maybeCustomInspect === 'function' && + if (!maybeCustom && value.inspect !== exports.inspect && + typeof value.inspect === 'function') { + maybeCustom = deprecate( + value.inspect, + 'Custom inspection function on Objects via .inspect() is deprecated', + 'DEP0079' + ); + } + + if (typeof maybeCustom === 'function' && // Filter out the util module, its inspect function is special - maybeCustomInspect !== exports.inspect && + maybeCustom !== exports.inspect && // Also filter out any prototype objects using the circular check. !(value.constructor && value.constructor.prototype === value)) { - const ret = maybeCustomInspect.call(value, recurseTimes, ctx); + const ret = maybeCustom.call(value, recurseTimes, ctx); // If the custom inspection method returned `this`, don't go into // infinite recursion. diff --git a/test/parallel/test-util-inspect-deprecated.js b/test/parallel/test-util-inspect-deprecated.js new file mode 100644 index 00000000000..adabb066970 --- /dev/null +++ b/test/parallel/test-util-inspect-deprecated.js @@ -0,0 +1,18 @@ +'use strict'; +const common = require('../common'); + +// Test that deprecation warning for custom inspection via the `.inspect()` +// property (on the target object) is emitted once and only once. + +const util = require('util'); + +{ + const target = { inspect: () => 'Fhqwhgads' }; + // `common.expectWarning` will expect the warning exactly one time only + common.expectWarning( + 'DeprecationWarning', + 'Custom inspection function on Objects via .inspect() is deprecated' + ); + util.inspect(target); // should emit deprecation warning + util.inspect(target); // should not emit deprecation warning +} diff --git a/test/parallel/test-util-inspect.js b/test/parallel/test-util-inspect.js index 2804ca4fb1e..edd097ee7a5 100644 --- a/test/parallel/test-util-inspect.js +++ b/test/parallel/test-util-inspect.js @@ -1150,3 +1150,9 @@ if (typeof Symbol !== 'undefined') { } assert.doesNotThrow(() => util.inspect(process)); + +// Setting custom inspect property to a non-function should do nothing. +{ + const obj = { inspect: 'fhqwhgads' }; + assert.strictEqual(util.inspect(obj), "{ inspect: 'fhqwhgads' }"); +}