From a9f518c901459e42afc76871dab9867967e9fa23 Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Mon, 15 Apr 2019 20:10:17 +0200 Subject: [PATCH] process: inspect error in case of a fatal exception MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This makes sure that errors that shut down the application are inspected with `util.inspect()`. That makes sure that all extra properties on the error will be visible and also that the stack trace is highlighted (Node.js internal frames will be grey and node modules are underlined). PR-URL: https://github.com/nodejs/node/pull/27243 Reviewed-By: Anna Henningsen Reviewed-By: Michaƫl Zasso Reviewed-By: Rich Trott --- lib/internal/process/execution.js | 7 ++++++- test/message/assert_throws_stack.out | 18 +++++++++++++++++- test/message/error_exit.out | 8 +++++++- test/message/if-error-has-good-stack.out | 18 +++++++++++++++++- test/message/stack_overflow.out | 2 +- test/message/throw_custom_error.out | 2 +- test/message/throw_in_line_with_tabs.out | 2 +- test/message/throw_non_error.out | 2 +- test/parallel/test-error-reporting.js | 2 +- test/pseudo-tty/test-fatal-error.js | 10 ++++++++++ test/pseudo-tty/test-fatal-error.out | 14 ++++++++++++++ 11 files changed, 76 insertions(+), 9 deletions(-) create mode 100644 test/pseudo-tty/test-fatal-error.js create mode 100644 test/pseudo-tty/test-fatal-error.out diff --git a/lib/internal/process/execution.js b/lib/internal/process/execution.js index 5eda7541c8e..227c1c2149c 100644 --- a/lib/internal/process/execution.js +++ b/lib/internal/process/execution.js @@ -142,8 +142,12 @@ function createFatalException() { if (exceptionHandlerState.captureFn !== null) { exceptionHandlerState.captureFn(er); } else if (!process.emit('uncaughtException', er, type)) { - // If someone handled it, then great. otherwise, die in C++ land + // If someone handled it, then great. Otherwise, die in C++ land // since that means that we'll exit the process, emit the 'exit' event. + const { inspect } = require('internal/util/inspect'); + const colors = internalBinding('util').guessHandleType(2) === 'TTY' && + require('internal/tty').hasColors() || + inspect.defaultOptions.colors; try { if (!process._exiting) { process._exiting = true; @@ -157,6 +161,7 @@ function createFatalException() { const { kExpandStackSymbol } = require('internal/util'); if (typeof er[kExpandStackSymbol] === 'function') er[kExpandStackSymbol](); + er.stack = inspect(er, { colors }); } catch { // Nothing to be done about it at this point. } diff --git a/test/message/assert_throws_stack.out b/test/message/assert_throws_stack.out index 7d4a7aecbcd..e9f9cc5e891 100644 --- a/test/message/assert_throws_stack.out +++ b/test/message/assert_throws_stack.out @@ -15,4 +15,20 @@ AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal: at * at * at * - at * + at * { + generatedMessage: true, + code: 'ERR_ASSERTION', + actual: Error: foo + at assert.throws.bar (*assert_throws_stack.js:*) + at getActual (assert.js:*) + at Function.throws (assert.js:*) + at Object. (*assert_throws_stack.js:*:*) + at * + at * + at * + at * + at * + at *, + expected: [Object], + operator: 'throws' +} diff --git a/test/message/error_exit.out b/test/message/error_exit.out index b975d41a55d..a0d848b125b 100644 --- a/test/message/error_exit.out +++ b/test/message/error_exit.out @@ -13,4 +13,10 @@ AssertionError [ERR_ASSERTION]: Expected values to be strictly equal: at Module.load (internal/modules/cjs/loader.js:*:*) at Function.Module._load (internal/modules/cjs/loader.js:*:*) at Function.Module.runMain (internal/modules/cjs/loader.js:*:*) - at internal/main/run_main_module.js:*:* + at internal/main/run_main_module.js:*:* { + generatedMessage: true, + code: 'ERR_ASSERTION', + actual: 1, + expected: 2, + operator: 'strictEqual' +} diff --git a/test/message/if-error-has-good-stack.out b/test/message/if-error-has-good-stack.out index c762d74aedb..87261c451ff 100644 --- a/test/message/if-error-has-good-stack.out +++ b/test/message/if-error-has-good-stack.out @@ -16,4 +16,20 @@ AssertionError [ERR_ASSERTION]: ifError got unwanted exception: test error at Module.load (internal/modules/cjs/loader.js:*:*) at Function.Module._load (internal/modules/cjs/loader.js:*:*) at Function.Module.runMain (internal/modules/cjs/loader.js:*:*) - at internal/main/run_main_module.js:*:* + at internal/main/run_main_module.js:*:* { + generatedMessage: false, + code: 'ERR_ASSERTION', + actual: Error: test error + at c (*if-error-has-good-stack.js:*:*) + at b (*if-error-has-good-stack.js:*:*) + at a (*if-error-has-good-stack.js:*:*) + at Object. (*if-error-has-good-stack.js:*:*) + at Module._compile (internal/modules/cjs/loader.js:*:*) + at Object.Module._extensions..js (internal/modules/cjs/loader.js:*:*) + at Module.load (internal/modules/cjs/loader.js:*:*) + at Function.Module._load (internal/modules/cjs/loader.js:*:*) + at Function.Module.runMain (internal/modules/cjs/loader.js:*:*) + at internal/main/run_main_module.js:*:* + expected: null, + operator: 'ifError' +} diff --git a/test/message/stack_overflow.out b/test/message/stack_overflow.out index c83f8001d99..d7a2c3eef06 100644 --- a/test/message/stack_overflow.out +++ b/test/message/stack_overflow.out @@ -3,4 +3,4 @@ before JSON.stringify(array); ^ -RangeError: Maximum call stack size exceeded +[RangeError: Maximum call stack size exceeded] diff --git a/test/message/throw_custom_error.out b/test/message/throw_custom_error.out index 0c6b9d128c9..a1fa8c6c5b7 100644 --- a/test/message/throw_custom_error.out +++ b/test/message/throw_custom_error.out @@ -1,4 +1,4 @@ *test*message*throw_custom_error.js:* throw ({ name: 'MyCustomError', message: 'This is a custom message' }); ^ -MyCustomError: This is a custom message +{ name: 'MyCustomError', message: 'This is a custom message' } diff --git a/test/message/throw_in_line_with_tabs.out b/test/message/throw_in_line_with_tabs.out index 89a81beb412..9392ef5cca2 100644 --- a/test/message/throw_in_line_with_tabs.out +++ b/test/message/throw_in_line_with_tabs.out @@ -2,4 +2,4 @@ before *test*message*throw_in_line_with_tabs.js:* throw ({ foo: 'bar' }); ^ -[object Object] +{ foo: 'bar' } diff --git a/test/message/throw_non_error.out b/test/message/throw_non_error.out index 2b7e0120b6f..a744f786ca6 100644 --- a/test/message/throw_non_error.out +++ b/test/message/throw_non_error.out @@ -1,4 +1,4 @@ *test*message*throw_non_error.js:* throw ({ foo: 'bar' }); ^ -[object Object] +{ foo: 'bar' } diff --git a/test/parallel/test-error-reporting.js b/test/parallel/test-error-reporting.js index f56f1e4bdca..7568206d46b 100644 --- a/test/parallel/test-error-reporting.js +++ b/test/parallel/test-error-reporting.js @@ -77,5 +77,5 @@ errExec('throws_error6.js', common.mustCall((err, stdout, stderr) => { // Object that throws in toString() doesn't print garbage errExec('throws_error7.js', common.mustCall((err, stdout, stderr) => { - assert.ok(/ (*test-fatal-error.js:*) +*[90m at *(internal*loader.js:*:*)*[39m +*[90m at *(internal*loader.js:*:*)*[39m +*[90m at *(internal*loader.js:*:*)*[39m +*[90m at *(internal*loader.js:*:*)*[39m +*[90m at *[39m +*[90m at *[39m { + bla: *[33mtrue*[39m +}