From f044b21099f1fc01b326006866d4076514e83d5f 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 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). --- 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 c95567c50623..145189d84de2 100644 --- a/lib/internal/process/execution.js +++ b/lib/internal/process/execution.js @@ -138,8 +138,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; @@ -153,6 +157,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 7d4a7aecbcd4..e9f9cc5e891c 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 b975d41a55d9..a0d848b125b7 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 c762d74aedbc..87261c451fff 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 c83f8001d99f..d7a2c3eef06e 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 0c6b9d128c90..a1fa8c6c5b71 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 89a81beb4126..9392ef5cca27 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 2b7e0120b6f9..a744f786ca6d 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 f56f1e4bdca6..7568206d46bd 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 +}