From dc2d4757d6720073404d353492dd9a26e888f94a Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Tue, 2 Apr 2019 07:56:14 +0200 Subject: [PATCH 1/4] util: highlight stack frames Using `util.inspect` on errors is going to highlight userland and node_module stack frames from now on. This is done by marking Node.js core frames grey and frames that contain `node_modules` in their path yellow. That way it's easy to grasp what frames belong to what code. --- doc/api/util.md | 19 ++++----- lib/internal/util/inspect.js | 37 ++++++++++++++++- .../fixtures/node_modules/node_modules/bar.js | 2 - test/parallel/test-util-inspect.js | 40 +++++++++++++++++++ test/pseudo-tty/console_colors.js | 13 ++++++ test/pseudo-tty/console_colors.out | 36 +++++++++++++++++ 6 files changed, 134 insertions(+), 13 deletions(-) diff --git a/doc/api/util.md b/doc/api/util.md index 6a8b30ef7ae1b6..7bc01f5c9bc695 100644 --- a/doc/api/util.md +++ b/doc/api/util.md @@ -633,15 +633,16 @@ 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) +* `number` - `yellow` +* `boolean` - `yellow` +* `string` - `green` +* `date` - `magenta` +* `module` - `underline` +* `regexp` - `red` +* `null` - `bold` +* `undefined` - `grey` +* `special` - `cyan` (only applied to functions at this time) +* `name` - (no styling) The predefined color codes are: `white`, `grey`, `black`, `blue`, `cyan`, `green`, `magenta`, `red` and `yellow`. There are also `bold`, `italic`, diff --git a/lib/internal/util/inspect.js b/lib/internal/util/inspect.js index e5a8b2ecb6d189..e2115b3f68d048 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 (?:[^/\\(]+ \(|)((? (/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..b6b5a0a870dc3c 100644 --- a/test/pseudo-tty/console_colors.out +++ b/test/pseudo-tty/console_colors.out @@ -1,3 +1,39 @@ { 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 +*[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 +*[90m at *[39m +at * (*console_colors.js:*:*) +*[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 From 84447261f4cfe490483d03e016e77ad6367f61ad Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Tue, 2 Apr 2019 07:59:44 +0200 Subject: [PATCH 2/4] util: only sort weak entries once This makes sure weak entries are only sorted once, while using the sorted option. --- lib/internal/util/inspect.js | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/lib/internal/util/inspect.js b/lib/internal/util/inspect.js index e2115b3f68d048..ff8f102535db0a 100644 --- a/lib/internal/util/inspect.js +++ b/lib/internal/util/inspect.js @@ -1227,9 +1227,10 @@ function formatSetIterInner(ctx, recurseTimes, entries, state) { output[i] = formatValue(ctx, entries[i], recurseTimes); } ctx.indentationLvl -= 2; - if (state === kWeak) { + if (state === kWeak && !ctx.sorted) { // Sort all entries to have a halfway reliable output (if more entries than - // retrieved ones exist, we can not reliably return the same output). + // retrieved ones exist, we can not reliably return the same output) if the + // output is not sorted anyway. output = output.sort(); } const remaining = entries.length - maxLength; @@ -1254,9 +1255,11 @@ function formatMapIterInner(ctx, recurseTimes, entries, state) { output[i] = `${formatValue(ctx, entries[pos], recurseTimes)}` + ` => ${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; From 634e694c15cd43062d2a0207203a68fc576926ea Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Tue, 2 Apr 2019 23:52:15 +0200 Subject: [PATCH 3/4] doc: update util colors This updates the customization of colors for `util.inspect`. A couple entries were missing and this also adds a reference to check for colors. --- doc/api/util.md | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/doc/api/util.md b/doc/api/util.md index 7bc01f5c9bc695..00072745f7e6ce 100644 --- a/doc/api/util.md +++ b/doc/api/util.md @@ -633,23 +633,25 @@ via the `util.inspect.styles` and `util.inspect.colors` properties. The default styles and associated colors are: -* `number` - `yellow` +* `bigint` - `yellow` * `boolean` - `yellow` -* `string` - `green` * `date` - `magenta` * `module` - `underline` -* `regexp` - `red` +* `name` - (no styling) * `null` - `bold` +* `number` - `yellow` +* `regexp` - `red` +* `special` - `cyan` (e.g., `Proxies`) +* `string` - `green` +* `symbol` - `green` * `undefined` - `grey` -* `special` - `cyan` (only applied to functions at this time) -* `name` - (no styling) 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 @@ -2186,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 From 8723c922707a5fdfe4259cbef97ab79324ec46e6 Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Wed, 10 Apr 2019 01:45:44 +0200 Subject: [PATCH 4/4] fixup! util: highlight stack frames --- lib/internal/util/inspect.js | 2 +- test/pseudo-tty/console_colors.out | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/internal/util/inspect.js b/lib/internal/util/inspect.js index ff8f102535db0a..0047f07afb1a66 100644 --- a/lib/internal/util/inspect.js +++ b/lib/internal/util/inspect.js @@ -901,8 +901,8 @@ function formatError(err, constructor, tag, ctx) { } newStack += pos === 0 ? line : line.slice(pos); } - stack = newStack; } + stack = newStack; } // The message and the stack have to be indented as well! if (ctx.indentationLvl !== 0) { diff --git a/test/pseudo-tty/console_colors.out b/test/pseudo-tty/console_colors.out index b6b5a0a870dc3c..6ee69f645bce3e 100644 --- a/test/pseudo-tty/console_colors.out +++ b/test/pseudo-tty/console_colors.out @@ -12,7 +12,6 @@ at * (*console_colors.js:*:*) *[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:*:*) @@ -22,9 +21,9 @@ at * (*node_modules*[4m*node_modules*[24m*bar.js:*:*) *[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.:*:*