diff --git a/doc/api/process.md b/doc/api/process.md index cd16dec54062f8..fea9f1f0a3a76d 100644 --- a/doc/api/process.md +++ b/doc/api/process.md @@ -706,14 +706,15 @@ console.log(process.env.test); // => 1 ``` -## process.emitWarning(warning[, name][, ctor]) +## process.emitWarning(warning[, type[, code]][, ctor]) * `warning` {String | Error} The warning to emit. -* `name` {String} When `warning` is a String, `name` is the name to use - for the warning. Default: `Warning`. +* `type` {String} When `warning` is a String, `type` is the name to use + for the *type* of warning being emitted. Default: `Warning`. +* `code` {String} A unique identifier for the warning instance being emitted. * `ctor` {Function} When `warning` is a String, `ctor` is an optional function used to limit the generated stack trace. Default `process.emitWarning` @@ -729,11 +730,16 @@ process.emitWarning('Something happened!'); ``` ```js -// Emit a warning using a string and a name... +// Emit a warning using a string and a type... process.emitWarning('Something Happened!', 'CustomWarning'); // Emits: (node:56338) CustomWarning: Something Happened! ``` +```js +process.emitWarning('Something happened!', 'CustomWarning', 'WARN001'); +// Emits: (node:56338) CustomWarning [WARN001]: Something Happened! +``` + In each of the previous examples, an `Error` object is generated internally by `process.emitWarning()` and passed through to the [`process.on('warning')`][process_warning] event. @@ -742,21 +748,24 @@ In each of the previous examples, an `Error` object is generated internally by process.on('warning', (warning) => { console.warn(warning.name); console.warn(warning.message); + console.warn(warning.code); console.warn(warning.stack); }); ``` If `warning` is passed as an `Error` object, it will be passed through to the -`process.on('warning')` event handler unmodified (and the optional `name` -and `ctor` arguments will be ignored): +`process.on('warning')` event handler unmodified (and the optional `type`, +`code` and `ctor` arguments will be ignored): ```js // Emit a warning using an Error object... const myWarning = new Error('Warning! Something happened!'); +// Use the Error name property to specify the type name myWarning.name = 'CustomWarning'; +myWarning.code = 'WARN001'; process.emitWarning(myWarning); -// Emits: (node:56338) CustomWarning: Warning! Something Happened! +// Emits: (node:56338) CustomWarning [WARN001]: Warning! Something Happened! ``` A `TypeError` is thrown if `warning` is anything other than a string or `Error` @@ -765,7 +774,7 @@ object. Note that while process warnings use `Error` objects, the process warning mechanism is **not** a replacement for normal error handling mechanisms. -The following additional handling is implemented if the warning `name` is +The following additional handling is implemented if the warning `type` is `DeprecationWarning`: * If the `--throw-deprecation` command-line flag is used, the deprecation diff --git a/lib/internal/process/warning.js b/lib/internal/process/warning.js index f98f7f69ddae23..fd9e7e72a40430 100644 --- a/lib/internal/process/warning.js +++ b/lib/internal/process/warning.js @@ -13,26 +13,45 @@ function setupProcessWarnings() { const trace = process.traceProcessWarnings || (isDeprecation && process.traceDeprecation); if (trace && warning.stack) { - console.error(`${prefix}${warning.stack}`); + if (warning.code) { + console.error(`${prefix}[${warning.code}] ${warning.stack}`); + } else { + console.error(`${prefix}${warning.stack}`); + } } else { - var toString = warning.toString; - if (typeof toString !== 'function') - toString = Error.prototype.toString; - console.error(`${prefix}${toString.apply(warning)}`); + const toString = + typeof warning.toString === 'function' ? + warning.toString : Error.prototype.toString; + if (warning.code) { + console.error( + `${prefix}[${warning.code}] ${toString.apply(warning)}`); + } else { + console.error(`${prefix}${toString.apply(warning)}`); + } } }); } // process.emitWarning(error) - // process.emitWarning(str[, name][, ctor]) - process.emitWarning = function(warning, name, ctor) { - if (typeof name === 'function') { - ctor = name; - name = 'Warning'; + // process.emitWarning(str[, type[, code]][, ctor]) + process.emitWarning = function(warning, type, code, ctor) { + if (typeof type === 'function') { + ctor = type; + code = undefined; + type = 'Warning'; } + if (typeof code === 'function') { + ctor = code; + code = undefined; + } + if (code !== undefined && typeof code !== 'string') + throw new TypeError('\'code\' must be a String'); + if (type !== undefined && typeof type !== 'string') + throw new TypeError('\'type\' must be a String'); if (warning === undefined || typeof warning === 'string') { warning = new Error(warning); - warning.name = name || 'Warning'; + warning.name = String(type || 'Warning'); + if (code !== undefined) warning.code = code; Error.captureStackTrace(warning, ctor || process.emitWarning); } if (!(warning instanceof Error)) { diff --git a/test/parallel/test-process-emitwarning.js b/test/parallel/test-process-emitwarning.js index 651bdbd1abc1ed..b7491000014dc5 100644 --- a/test/parallel/test-process-emitwarning.js +++ b/test/parallel/test-process-emitwarning.js @@ -9,18 +9,21 @@ const util = require('util'); process.on('warning', common.mustCall((warning) => { assert(warning); assert(/^(Warning|CustomWarning)/.test(warning.name)); - assert(warning.message, 'A Warning'); -}, 7)); + assert.strictEqual(warning.message, 'A Warning'); + if (warning.code) assert.strictEqual(warning.code, 'CODE001'); +}, 8)); process.emitWarning('A Warning'); process.emitWarning('A Warning', 'CustomWarning'); process.emitWarning('A Warning', CustomWarning); process.emitWarning('A Warning', 'CustomWarning', CustomWarning); +process.emitWarning('A Warning', 'CustomWarning', 'CODE001'); function CustomWarning() { Error.call(this); this.name = 'CustomWarning'; this.message = 'A Warning'; + this.code = 'CODE001'; Error.captureStackTrace(this, CustomWarning); } util.inherits(CustomWarning, Error); @@ -36,6 +39,16 @@ warningThrowToString.toString = function() { }; process.emitWarning(warningThrowToString); -// TypeError is thrown on invalid output +// TypeError is thrown on invalid input assert.throws(() => process.emitWarning(1), TypeError); assert.throws(() => process.emitWarning({}), TypeError); +assert.throws(() => process.emitWarning(true), TypeError); +assert.throws(() => process.emitWarning([]), TypeError); +assert.throws(() => process.emitWarning('', {}), TypeError); +assert.throws(() => process.emitWarning('', '', {}), TypeError); +assert.throws(() => process.emitWarning('', 1), TypeError); +assert.throws(() => process.emitWarning('', '', 1), TypeError); +assert.throws(() => process.emitWarning('', true), TypeError); +assert.throws(() => process.emitWarning('', '', true), TypeError); +assert.throws(() => process.emitWarning('', []), TypeError); +assert.throws(() => process.emitWarning('', '', []), TypeError);