diff options
author | Ruben Bridgewater <ruben@bridgewater.de> | 2019-05-09 09:22:15 +0200 |
---|---|---|
committer | Ruben Bridgewater <ruben@bridgewater.de> | 2019-05-20 14:18:18 +0200 |
commit | 5518664d41b8916dfbe2eca2180d760db632748e (patch) | |
tree | 38b36fd6e4ba56e5a0ef1a0955fc495270675144 /lib | |
parent | 182b48aa777a2c9c453f729c162412b6900b055d (diff) | |
download | android-node-v8-5518664d41b8916dfbe2eca2180d760db632748e.tar.gz android-node-v8-5518664d41b8916dfbe2eca2180d760db632748e.tar.bz2 android-node-v8-5518664d41b8916dfbe2eca2180d760db632748e.zip |
util: if present, fallback to `toString` using the %s formatter
This makes sure that `util.format` uses `String` to stringify an object
in case the object has an own property named `toString` with type
`function`. That way objects that do not have such function are still
inspected using `util.inspect` and the old behavior is preserved as
well.
PR-URL: https://github.com/nodejs/node/pull/27621
Refs: https://github.com/facebook/jest/issues/8443
Reviewed-By: Roman Reiss <me@silverwind.io>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/internal/util/inspect.js | 39 |
1 files changed, 30 insertions, 9 deletions
diff --git a/lib/internal/util/inspect.js b/lib/internal/util/inspect.js index 07757f3fe0..e46a18633c 100644 --- a/lib/internal/util/inspect.js +++ b/lib/internal/util/inspect.js @@ -93,6 +93,10 @@ const { NativeModule } = require('internal/bootstrap/loaders'); let hexSlice; +const builtInObjects = new Set( + Object.getOwnPropertyNames(global).filter((e) => /^([A-Z][a-z]+)+$/.test(e)) +); + const inspectDefaultOptions = Object.seal({ showHidden: false, depth: 2, @@ -1541,16 +1545,33 @@ function formatWithOptions(inspectOptions, ...args) { switch (nextChar) { case 115: // 's' const tempArg = args[++a]; - if (typeof tempArg !== 'string' && - typeof tempArg !== 'function') { - tempStr = inspect(tempArg, { - ...inspectOptions, - compact: 3, - colors: false, - depth: 0 - }); + if (typeof tempArg === 'number') { + tempStr = formatNumber(stylizeNoColor, tempArg); + // eslint-disable-next-line valid-typeof + } else if (typeof tempArg === 'bigint') { + tempStr = `${tempArg}n`; } else { - tempStr = String(tempArg); + let constr; + if (typeof tempArg !== 'object' || + tempArg === null || + typeof tempArg.toString === 'function' && + // A direct own property. + (hasOwnProperty(tempArg, 'toString') || + // A direct own property on the constructor prototype in + // case the constructor is not an built-in object. + (constr = tempArg.constructor) && + !builtInObjects.has(constr.name) && + constr.prototype && + hasOwnProperty(constr.prototype, 'toString'))) { + tempStr = String(tempArg); + } else { + tempStr = inspect(tempArg, { + ...inspectOptions, + compact: 3, + colors: false, + depth: 0 + }); + } } break; case 106: // 'j' |