process: add optional code to warnings + type checking

Add the ability to assign an optional code to process warnings +
add additional type checking to ensure that names and codes can
only be strings.

PR-URL: https://github.com/nodejs/node/pull/10116
Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com>
Reviewed-By: Michal Zasso <targos@protonmail.com>
Reviewed-By: Fedor Indutny <fedor.indutny@gmail.com>
This commit is contained in:
James M Snell 2016-12-04 09:30:53 -08:00
parent 60d77bd514
commit 5e1f32fd94
3 changed files with 63 additions and 22 deletions

View File

@ -706,14 +706,15 @@ console.log(process.env.test);
// => 1 // => 1
``` ```
## process.emitWarning(warning[, name][, ctor]) ## process.emitWarning(warning[, type[, code]][, ctor])
<!-- YAML <!-- YAML
added: v6.0.0 added: v6.0.0
--> -->
* `warning` {String | Error} The warning to emit. * `warning` {String | Error} The warning to emit.
* `name` {String} When `warning` is a String, `name` is the name to use * `type` {String} When `warning` is a String, `type` is the name to use
for the warning. Default: `Warning`. 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 * `ctor` {Function} When `warning` is a String, `ctor` is an optional
function used to limit the generated stack trace. Default function used to limit the generated stack trace. Default
`process.emitWarning` `process.emitWarning`
@ -729,11 +730,16 @@ process.emitWarning('Something happened!');
``` ```
```js ```js
// Emit a warning using a string and a name... // Emit a warning using a string and a type...
process.emitWarning('Something Happened!', 'CustomWarning'); process.emitWarning('Something Happened!', 'CustomWarning');
// Emits: (node:56338) CustomWarning: Something Happened! // 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 In each of the previous examples, an `Error` object is generated internally by
`process.emitWarning()` and passed through to the `process.emitWarning()` and passed through to the
[`process.on('warning')`][process_warning] event. [`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) => { process.on('warning', (warning) => {
console.warn(warning.name); console.warn(warning.name);
console.warn(warning.message); console.warn(warning.message);
console.warn(warning.code);
console.warn(warning.stack); console.warn(warning.stack);
}); });
``` ```
If `warning` is passed as an `Error` object, it will be passed through to the 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` `process.on('warning')` event handler unmodified (and the optional `type`,
and `ctor` arguments will be ignored): `code` and `ctor` arguments will be ignored):
```js ```js
// Emit a warning using an Error object... // Emit a warning using an Error object...
const myWarning = new Error('Warning! Something happened!'); const myWarning = new Error('Warning! Something happened!');
// Use the Error name property to specify the type name
myWarning.name = 'CustomWarning'; myWarning.name = 'CustomWarning';
myWarning.code = 'WARN001';
process.emitWarning(myWarning); 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` 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 Note that while process warnings use `Error` objects, the process warning
mechanism is **not** a replacement for normal error handling mechanisms. 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`: `DeprecationWarning`:
* If the `--throw-deprecation` command-line flag is used, the deprecation * If the `--throw-deprecation` command-line flag is used, the deprecation

View File

@ -13,26 +13,45 @@ function setupProcessWarnings() {
const trace = process.traceProcessWarnings || const trace = process.traceProcessWarnings ||
(isDeprecation && process.traceDeprecation); (isDeprecation && process.traceDeprecation);
if (trace && warning.stack) { 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 { } else {
var toString = warning.toString; const toString =
if (typeof toString !== 'function') typeof warning.toString === 'function' ?
toString = Error.prototype.toString; warning.toString : Error.prototype.toString;
console.error(`${prefix}${toString.apply(warning)}`); if (warning.code) {
console.error(
`${prefix}[${warning.code}] ${toString.apply(warning)}`);
} else {
console.error(`${prefix}${toString.apply(warning)}`);
}
} }
}); });
} }
// process.emitWarning(error) // process.emitWarning(error)
// process.emitWarning(str[, name][, ctor]) // process.emitWarning(str[, type[, code]][, ctor])
process.emitWarning = function(warning, name, ctor) { process.emitWarning = function(warning, type, code, ctor) {
if (typeof name === 'function') { if (typeof type === 'function') {
ctor = name; ctor = type;
name = 'Warning'; 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') { if (warning === undefined || typeof warning === 'string') {
warning = new Error(warning); 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); Error.captureStackTrace(warning, ctor || process.emitWarning);
} }
if (!(warning instanceof Error)) { if (!(warning instanceof Error)) {

View File

@ -9,18 +9,21 @@ const util = require('util');
process.on('warning', common.mustCall((warning) => { process.on('warning', common.mustCall((warning) => {
assert(warning); assert(warning);
assert(/^(Warning|CustomWarning)/.test(warning.name)); assert(/^(Warning|CustomWarning)/.test(warning.name));
assert(warning.message, 'A Warning'); assert.strictEqual(warning.message, 'A Warning');
}, 7)); if (warning.code) assert.strictEqual(warning.code, 'CODE001');
}, 8));
process.emitWarning('A Warning'); process.emitWarning('A Warning');
process.emitWarning('A Warning', 'CustomWarning'); process.emitWarning('A Warning', 'CustomWarning');
process.emitWarning('A Warning', CustomWarning); process.emitWarning('A Warning', CustomWarning);
process.emitWarning('A Warning', 'CustomWarning', CustomWarning); process.emitWarning('A Warning', 'CustomWarning', CustomWarning);
process.emitWarning('A Warning', 'CustomWarning', 'CODE001');
function CustomWarning() { function CustomWarning() {
Error.call(this); Error.call(this);
this.name = 'CustomWarning'; this.name = 'CustomWarning';
this.message = 'A Warning'; this.message = 'A Warning';
this.code = 'CODE001';
Error.captureStackTrace(this, CustomWarning); Error.captureStackTrace(this, CustomWarning);
} }
util.inherits(CustomWarning, Error); util.inherits(CustomWarning, Error);
@ -36,6 +39,16 @@ warningThrowToString.toString = function() {
}; };
process.emitWarning(warningThrowToString); 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(1), TypeError);
assert.throws(() => process.emitWarning({}), 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);