diff --git a/doc/api/util.md b/doc/api/util.md index 6a8b30ef7ae1b6..00072745f7e6ce 100644 --- a/doc/api/util.md +++ b/doc/api/util.md @@ -633,22 +633,25 @@ via the `util.inspect.styles` and `util.inspect.colors` properties. The default styles and associated colors are: - * `number` - `yellow` - * `boolean` - `yellow` - * `string` - `green` - * `date` - `magenta` - * `regexp` - `red` - * `null` - `bold` - * `undefined` - `grey` - * `special` - `cyan` (only applied to functions at this time) - * `name` - (no styling) +* `bigint` - `yellow` +* `boolean` - `yellow` +* `date` - `magenta` +* `module` - `underline` +* `name` - (no styling) +* `null` - `bold` +* `number` - `yellow` +* `regexp` - `red` +* `special` - `cyan` (e.g., `Proxies`) +* `string` - `green` +* `symbol` - `green` +* `undefined` - `grey` The predefined color codes are: `white`, `grey`, `black`, `blue`, `cyan`, `green`, `magenta`, `red` and `yellow`. There are also `bold`, `italic`, `underline` and `inverse` codes. Color styling uses ANSI control codes that may not be supported on all -terminals. +terminals. To verify color support use [`tty.hasColors()`][]. ### Custom inspection functions on Objects @@ -2185,6 +2188,7 @@ util.log('Timestamped message.'); [`assert.deepStrictEqual()`]: assert.html#assert_assert_deepstrictequal_actual_expected_message [`console.error()`]: console.html#console_console_error_data_args [`target` and `handler`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy#Terminology +[`tty.hasColors()`]: tty.html#tty_writestream_hascolors_count_env [`util.format()`]: #util_util_format_format_args [`util.inspect()`]: #util_util_inspect_object_options [`util.promisify()`]: #util_util_promisify_original diff --git a/lib/internal/util/inspect.js b/lib/internal/util/inspect.js index e5a8b2ecb6d189..0047f07afb1a66 100644 --- a/lib/internal/util/inspect.js +++ b/lib/internal/util/inspect.js @@ -86,6 +86,8 @@ const { const assert = require('internal/assert'); +const { NativeModule } = require('internal/bootstrap/loaders'); + let hexSlice; const inspectDefaultOptions = Object.seal({ @@ -115,6 +117,9 @@ const strEscapeSequencesReplacerSingle = /[\x00-\x1f\x5c]/g; const keyStrRegExp = /^[a-zA-Z_][a-zA-Z_0-9]*$/; const numberRegExp = /^(0|[1-9][0-9]*)$/; +const coreModuleRegExp = /^ at (?:[^/\\(]+ \(|)((? ${formatValue(ctx, entries[pos + 1], recurseTimes)}`; } - // Sort all entries to have a halfway reliable output (if more entries - // than retrieved ones exist, we can not reliably return the same output). - output = output.sort(); + // Sort all entries to have a halfway reliable output (if more entries than + // retrieved ones exist, we can not reliably return the same output) if the + // output is not sorted anyway. + if (!ctx.sorted) + output = output.sort(); } else { for (; i < maxLength; i++) { const pos = i * 2; diff --git a/test/fixtures/node_modules/node_modules/bar.js b/test/fixtures/node_modules/node_modules/bar.js index 84b74de9d9d8f3..a2aab083b70bf6 100644 --- a/test/fixtures/node_modules/node_modules/bar.js +++ b/test/fixtures/node_modules/node_modules/bar.js @@ -19,6 +19,4 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE // USE OR OTHER DEALINGS IN THE SOFTWARE. -console.error(__filename); -console.error(module.paths.join('\n') + '\n'); throw new Error('Should not ever get here.'); diff --git a/test/parallel/test-util-inspect.js b/test/parallel/test-util-inspect.js index 1de812286a2c28..8d161e8965dbc4 100644 --- a/test/parallel/test-util-inspect.js +++ b/test/parallel/test-util-inspect.js @@ -2306,3 +2306,43 @@ assert.strictEqual( assert.strictEqual(out, expected); } + +{ + // Use a fake stack to verify the expected colored outcome. + const stack = [ + 'TypedError: Wonderful message!', + ' at A. (/test/node_modules/foo/node_modules/bar/baz.js:2:7)', + ' at Module._compile (internal/modules/cjs/loader.js:827:30)', + ' at Fancy (vm.js:697:32)', + // This file is not an actual Node.js core file. + ' at tryModuleLoad (internal/modules/cjs/foo.js:629:12)', + ' at Function.Module._load (internal/modules/cjs/loader.js:621:3)', + // This file is not an actual Node.js core file. + ' at Module.require [as weird/name] (internal/aaaaaa/loader.js:735:19)', + ' at require (internal/modules/cjs/helpers.js:14:16)', + ' at /test/test-util-inspect.js:2239:9', + ' at getActual (assert.js:592:5)' + ]; + const isNodeCoreFile = [ + false, false, true, true, false, true, false, true, false, true + ]; + const err = new TypeError('Wonderful message!'); + err.stack = stack.join('\n'); + util.inspect(err, { colors: true }).split('\n').forEach((line, i) => { + let actual = stack[i].replace(/node_modules\/([a-z]+)/g, (a, m) => { + return `node_modules/\u001b[4m${m}\u001b[24m`; + }); + if (isNodeCoreFile[i]) { + actual = `\u001b[90m${actual}\u001b[39m`; + } + assert.strictEqual(actual, line); + }); +} + +{ + // Cross platform checks. + const err = new Error('foo'); + util.inspect(err, { colors: true }).split('\n').forEach((line, i) => { + assert(i < 2 || line.startsWith('\u001b[90m')); + }); +} diff --git a/test/pseudo-tty/console_colors.js b/test/pseudo-tty/console_colors.js index dd16a0c028dccd..e525bed59c9d4f 100644 --- a/test/pseudo-tty/console_colors.js +++ b/test/pseudo-tty/console_colors.js @@ -1,5 +1,6 @@ 'use strict'; require('../common'); +const vm = require('vm'); // Make this test OS-independent by overriding stdio getColorDepth(). process.stdout.getColorDepth = () => 8; process.stderr.getColorDepth = () => 8; @@ -7,3 +8,15 @@ process.stderr.getColorDepth = () => 8; console.log({ foo: 'bar' }); console.log('%s q', 'string'); console.log('%o with object format param', { foo: 'bar' }); + +console.log( + new Error('test\n at abc (../fixtures/node_modules/bar.js:4:4)\nfoobar') +); + +try { + require('../fixtures/node_modules/node_modules/bar.js'); +} catch (err) { + console.log(err); +} + +vm.runInThisContext('console.log(new Error())'); diff --git a/test/pseudo-tty/console_colors.out b/test/pseudo-tty/console_colors.out index f0ee5e42d60db5..6ee69f645bce3e 100644 --- a/test/pseudo-tty/console_colors.out +++ b/test/pseudo-tty/console_colors.out @@ -1,3 +1,38 @@ { foo: *[32m'bar'*[39m } string q { foo: *[32m'bar'*[39m } with object format param + +Error: test +at abc (../fixtures/node_modules/bar.js:4:4) +foobar +at * (*console_colors.js:*:*) +*[90m at * (internal*:*:*)*[39m +*[90m at *[39m +*[90m at *[39m +*[90m at *[39m +*[90m at *[39m +*[90m at *[39m + +Error: Should not ever get here. +at * (*node_modules*[4m*node_modules*[24m*bar.js:*:*) +*[90m at *[39m +*[90m at *[39m +*[90m at *[39m +*[90m at *[39m +*[90m at *[39m +*[90m at *[39m +at * (*console_colors.js:*:*) +*[90m at *[39m +*[90m at *[39m + +Error +at evalmachine.:*:* +*[90m at Script.runInThisContext (vm.js:*:*)*[39m +*[90m at Object.runInThisContext (vm.js:*:*)*[39m +at * (*console_colors.js:*:*) +*[90m at *[39m +*[90m at *[39m +*[90m at *[39m +*[90m at *[39m +*[90m at *[39m +*[90m at *[39m