diff options
author | Ruben Bridgewater <ruben@bridgewater.de> | 2019-04-02 07:56:14 +0200 |
---|---|---|
committer | Ruben Bridgewater <ruben@bridgewater.de> | 2019-04-15 17:30:50 +0200 |
commit | 1940114ac323695c758f21a00394b958a68d8428 (patch) | |
tree | ac64cc180479672da3eb6dfee02642fde784cbd0 /lib/internal/util/inspect.js | |
parent | 693401d0ddd752e5fa47b882e56e252c42c94c0e (diff) | |
download | android-node-v8-1940114ac323695c758f21a00394b958a68d8428.tar.gz android-node-v8-1940114ac323695c758f21a00394b958a68d8428.tar.bz2 android-node-v8-1940114ac323695c758f21a00394b958a68d8428.zip |
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.
PR-URL: https://github.com/nodejs/node/pull/27052
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: James M Snell <jasnell@gmail.com>
Diffstat (limited to 'lib/internal/util/inspect.js')
-rw-r--r-- | lib/internal/util/inspect.js | 37 |
1 files changed, 35 insertions, 2 deletions
diff --git a/lib/internal/util/inspect.js b/lib/internal/util/inspect.js index a31ee5b8eb..08f627db88 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 (?:[^/\\(]+ \(|)((?<![/\\]).+)\.js:\d+:\d+\)?$/; +const nodeModulesRegExp = /[/\\]node_modules[/\\](.+?)(?=[/\\])/g; + const readableRegExps = {}; const kMinLineLength = 16; @@ -253,7 +258,8 @@ inspect.styles = Object.assign(Object.create(null), { symbol: 'green', date: 'magenta', // "name": intentionally not styling - regexp: 'red' + regexp: 'red', + module: 'underline' }); function addQuotes(str, quotes) { @@ -838,10 +844,37 @@ function formatError(err, constructor, tag, ctx) { } } } + // Ignore the error message if it's contained in the stack. + let pos = err.message && stack.indexOf(err.message) || -1; + if (pos !== -1) + pos += err.message.length; // Wrap the error in brackets in case it has no stack trace. - const stackStart = stack.indexOf('\n at'); + const stackStart = stack.indexOf('\n at', pos); if (stackStart === -1) { stack = `[${stack}]`; + } else if (ctx.colors) { + // Highlight userland code and node modules. + let newStack = stack.slice(0, stackStart); + const lines = stack.slice(stackStart + 1).split('\n'); + for (const line of lines) { + const core = line.match(coreModuleRegExp); + if (core !== null && NativeModule.exists(core[1])) { + newStack += `\n${ctx.stylize(line, 'undefined')}`; + } else { + // This adds underscores to all node_modules to quickly identify them. + let nodeModule; + newStack += '\n'; + let pos = 0; + while (nodeModule = nodeModulesRegExp.exec(line)) { + // '/node_modules/'.length === 14 + newStack += line.slice(pos, nodeModule.index + 14); + newStack += ctx.stylize(nodeModule[1], 'module'); + pos = nodeModule.index + nodeModule[0].length; + } + newStack += pos === 0 ? line : line.slice(pos); + } + } + stack = newStack; } // The message and the stack have to be indented as well! if (ctx.indentationLvl !== 0) { |