From 89e59e067f4576ca0830abf77db4da0a0d0acf01 Mon Sep 17 00:00:00 2001 From: Cameron Little <cameron@camlittle.com> Date: Mon, 13 Mar 2017 09:04:54 -0700 Subject: [PATCH 1/2] test: support multiple warnings in common.checkWarning This allows the common.checkWarning() test method to accept a map of warning names to description(s), to allow testing code that generates multiple types of warnings. --- test/common.js | 42 +++++++++++++++++++++++++++++++++++------- 1 file changed, 35 insertions(+), 7 deletions(-) diff --git a/test/common.js b/test/common.js index 8f19efd900abf7..842abe2aab75ae 100644 --- a/test/common.js +++ b/test/common.js @@ -600,17 +600,45 @@ exports.isAlive = function isAlive(pid) { } }; -exports.expectWarning = function(name, expected) { - if (typeof expected === 'string') - expected = [expected]; - process.on('warning', exports.mustCall((warning) => { +function expectWarning(name, expectedMessages) { + return exports.mustCall((warning) => { assert.strictEqual(warning.name, name); - assert.ok(expected.includes(warning.message), + assert.ok(expectedMessages.includes(warning.message), `unexpected error message: "${warning.message}"`); // Remove a warning message after it is seen so that we guarantee that we // get each message only once. - expected.splice(expected.indexOf(warning.message), 1); - }, expected.length)); + expectedMessages.splice(expectedMessages.indexOf(warning.message), 1); + }, expectedMessages.length); +} + +function expectWarningByName(name, expected) { + if (typeof expected === 'string') { + expected = [expected]; + } + process.on('warning', expectWarning(name, expected)); +} + +function expectWarningByMap(warningMap) { + const catchWarning = {}; + Object.keys(warningMap).forEach((name) => { + let expected = warningMap[name]; + if (typeof expected === 'string') { + expected = [expected]; + } + catchWarning[name] = expectWarning(name, expected); + }); + process.on('warning', (warning) => catchWarning[warning.name](warning)); +} + +// accepts a warning name and description or array of descriptions or a map +// of warning names to description(s) +// ensures a warning is generated for each name/description pair +exports.expectWarning = function(nameOrMap, expected) { + if (typeof nameOrMap === 'string') { + expectWarningByName(nameOrMap, expected); + } else { + expectWarningByMap(nameOrMap); + } }; Object.defineProperty(exports, 'hasIntl', { From 840021c0ef5a01632c1f72cf9ad62ad5417381fc Mon Sep 17 00:00:00 2001 From: Cameron Little <cameron@camlittle.com> Date: Mon, 13 Mar 2017 09:07:06 -0700 Subject: [PATCH 2/2] process: Cast promise rejection reason to string The unhandled promise rejection warning uses a template literal and prints the reason a promise was rejected. If rejecting with a symbol, the symbol failed to convert to a string and the process crashed. Now, symbols are casted to strings and the process does not crash. Fixes: https://github.com/nodejs/node/issues/11637 --- lib/internal/process/promises.js | 2 +- ...est-promises-unhandled-symbol-rejections.js | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 test/parallel/test-promises-unhandled-symbol-rejections.js diff --git a/lib/internal/process/promises.js b/lib/internal/process/promises.js index 0e382d11d5523b..1ba4aa47f575bf 100644 --- a/lib/internal/process/promises.js +++ b/lib/internal/process/promises.js @@ -57,7 +57,7 @@ function setupPromises(scheduleMicrotasks) { function emitWarning(uid, reason) { const warning = new Error('Unhandled promise rejection ' + - `(rejection id: ${uid}): ${reason}`); + `(rejection id: ${uid}): ${String(reason)}`); warning.name = 'UnhandledPromiseRejectionWarning'; warning.id = uid; if (reason instanceof Error) { diff --git a/test/parallel/test-promises-unhandled-symbol-rejections.js b/test/parallel/test-promises-unhandled-symbol-rejections.js new file mode 100644 index 00000000000000..a60a5f2e8aac30 --- /dev/null +++ b/test/parallel/test-promises-unhandled-symbol-rejections.js @@ -0,0 +1,18 @@ +'use strict'; +const common = require('../common'); + +const expectedDeprecationWarning = 'Unhandled promise rejections are ' + + 'deprecated. In the future, promise ' + + 'rejections that are not handled will ' + + 'terminate the Node.js process with a ' + + 'non-zero exit code.'; +const expectedPromiseWarning = 'Unhandled promise rejection (rejection id: ' + + '1): Symbol()'; + +common.expectWarning({ + DeprecationWarning: expectedDeprecationWarning, + UnhandledPromiseRejectionWarning: expectedPromiseWarning, +}); + +// ensure this doesn't crash +Promise.reject(Symbol());