Skip to content

Commit dd20e68

Browse files
committed
process: add optional detail to process emitWarning
Adds a new method signature variant for process.emitWarning() that accepts an options object. The options object may include a new `detail` option that allows additional detail text to be associated with the warning. By default, this additional text will be printed to stderr along with the warning, and included on the Warning Error object using the `.detail` property. e.g. ```js process.emitWarning('A message',{code: 'WARNING123', detail: 'This is additional detail' }); // Emits: // (node{pid}) [WARNING123] Warning: A message // This is additional detail ``` PR-URL: #12725 Reviewed-By: Colin Ihrig <[email protected]>
1 parent 23fc082 commit dd20e68

File tree

3 files changed

+107
-36
lines changed

3 files changed

+107
-36
lines changed

‎doc/api/process.md‎

Lines changed: 51 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -637,6 +637,52 @@ process's [`ChildProcess.disconnect()`][].
637637
If the Node.js process was not spawned with an IPC channel,
638638
`process.disconnect()` will be `undefined`.
639639

640+
## process.emitWarning(warning[, options])
641+
<!-- YAML
642+
added: REPLACEME
643+
-->
644+
645+
*`warning`{string|Error} The warning to emit.
646+
*`options`{Object}
647+
*`type`{string} When `warning` is a String, `type` is the name to use
648+
for the *type* of warning being emitted. Default: `Warning`.
649+
*`code`{string} A unique identifier for the warning instance being emitted.
650+
*`ctor`{Function} When `warning` is a String, `ctor` is an optional
651+
function used to limit the generated stack trace. Default
652+
`process.emitWarning`
653+
*`detail`{string} Additional text to include with the error.
654+
655+
The `process.emitWarning()` method can be used to emit custom or application
656+
specific process warnings. These can be listened for by adding a handler to the
657+
[`process.on('warning')`][process_warning] event.
658+
659+
```js
660+
// Emit a warning with a code and additional detail.
661+
process.emitWarning('Something happened!',{
662+
code:'MY_WARNING',
663+
detail:'This is some additional information'
664+
});
665+
// Emits:
666+
// (node:56338) [MY_WARNING] Warning: Something happened!
667+
// This is some additional information
668+
```
669+
670+
In this example, an `Error` object is generated internally by
671+
`process.emitWarning()` and passed through to the
672+
[`process.on('warning')`][process_warning] event.
673+
674+
```js
675+
process.on('warning', (warning) =>{
676+
console.warn(warning.name); // 'Warning'
677+
console.warn(warning.message); // 'Something happened!'
678+
console.warn(warning.code); // 'MY_WARNING'
679+
console.warn(warning.stack); // Stack trace
680+
console.warn(warning.detail); // 'This is some additional information'
681+
});
682+
```
683+
684+
If `warning` is passed as an `Error` object, the `options` argument is ignored.
685+
640686
## process.emitWarning(warning[, type[, code]][, ctor])
641687
<!-- YAML
642688
added: v6.0.0
@@ -655,13 +701,13 @@ specific process warnings. These can be listened for by adding a handler to the
655701
[`process.on('warning')`][process_warning] event.
656702

657703
```js
658-
// Emit a warning using a string...
704+
// Emit a warning using a string.
659705
process.emitWarning('Something happened!');
660706
// Emits: (node: 56338) Warning: Something happened!
661707
```
662708

663709
```js
664-
// Emit a warning using a string and a type...
710+
// Emit a warning using a string and a type.
665711
process.emitWarning('Something Happened!', 'CustomWarning');
666712
// Emits: (node:56338) CustomWarning: Something Happened!
667713
```
@@ -689,14 +735,14 @@ If `warning` is passed as an `Error` object, it will be passed through to the
689735
`code` and `ctor` arguments will be ignored):
690736

691737
```js
692-
// Emit a warning using an Error object...
693-
constmyWarning=newError('Warning! Something happened!');
738+
// Emit a warning using an Error object.
739+
constmyWarning=newError('Something happened!');
694740
// Use the Error name property to specify the type name
695741
myWarning.name='CustomWarning';
696742
myWarning.code='WARN001';
697743

698744
process.emitWarning(myWarning);
699-
// Emits: (node:56338) [WARN001] CustomWarning: Warning! Something happened!
745+
// Emits: (node:56338) [WARN001] CustomWarning: Something happened!
700746
```
701747

702748
A `TypeError` is thrown if `warning` is anything other than a string or `Error`

‎lib/internal/process/warning.js‎

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -90,30 +90,37 @@ function setupProcessWarnings(){
9090
if(isDeprecation&&process.noDeprecation)return;
9191
consttrace=process.traceProcessWarnings||
9292
(isDeprecation&&process.traceDeprecation);
93+
letmsg=`${prefix}`;
94+
if(warning.code)
95+
msg+=`[${warning.code}] `;
9396
if(trace&&warning.stack){
94-
if(warning.code){
95-
output(`${prefix}[${warning.code}] ${warning.stack}`);
96-
}else{
97-
output(`${prefix}${warning.stack}`);
98-
}
97+
msg+=`${warning.stack}`;
9998
}else{
10099
consttoString=
101100
typeofwarning.toString==='function' ?
102101
warning.toString : Error.prototype.toString;
103-
if(warning.code){
104-
output(`${prefix}[${warning.code}] ${toString.apply(warning)}`);
105-
}else{
106-
output(`${prefix}${toString.apply(warning)}`);
107-
}
102+
msg+=`${toString.apply(warning)}`;
108103
}
104+
if(typeofwarning.detail==='string'){
105+
msg+=`\n${warning.detail}`;
106+
}
107+
output(msg);
109108
});
110109
}
111110

112111
// process.emitWarning(error)
113112
// process.emitWarning(str[, type[, code]][, ctor])
113+
// process.emitWarning(str[, options])
114114
process.emitWarning=function(warning,type,code,ctor){
115115
consterrors=lazyErrors();
116-
if(typeoftype==='function'){
116+
vardetail;
117+
if(type!==null&&typeoftype==='object'&&!Array.isArray(type)){
118+
ctor=type.ctor;
119+
code=type.code;
120+
if(typeoftype.detail==='string')
121+
detail=type.detail;
122+
type=type.type||'Warning';
123+
}elseif(typeoftype==='function'){
117124
ctor=type;
118125
code=undefined;
119126
type='Warning';
@@ -130,6 +137,7 @@ function setupProcessWarnings(){
130137
warning=newError(warning);
131138
warning.name=String(type||'Warning');
132139
if(code!==undefined)warning.code=code;
140+
if(detail!==undefined)warning.detail=detail;
133141
Error.captureStackTrace(warning,ctor||process.emitWarning);
134142
}
135143
if(!(warninginstanceofError)){

‎test/parallel/test-process-emitwarning.js‎

Lines changed: 37 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,30 +4,48 @@
44

55
constcommon=require('../common');
66
constassert=require('assert');
7-
constutil=require('util');
7+
8+
consttestMsg='A Warning';
9+
consttestCode='CODE001';
10+
consttestDetail='Some detail';
11+
consttestType='CustomWarning';
812

913
process.on('warning',common.mustCall((warning)=>{
1014
assert(warning);
1115
assert(/^(Warning|CustomWarning)/.test(warning.name));
12-
assert.strictEqual(warning.message,'A Warning');
13-
if(warning.code)assert.strictEqual(warning.code,'CODE001');
14-
},8));
15-
16-
process.emitWarning('A Warning');
17-
process.emitWarning('A Warning','CustomWarning');
18-
process.emitWarning('A Warning',CustomWarning);
19-
process.emitWarning('A Warning','CustomWarning',CustomWarning);
20-
process.emitWarning('A Warning','CustomWarning','CODE001');
21-
22-
functionCustomWarning(){
23-
Error.call(this);
24-
this.name='CustomWarning';
25-
this.message='A Warning';
26-
this.code='CODE001';
27-
Error.captureStackTrace(this,CustomWarning);
16+
assert.strictEqual(warning.message,testMsg);
17+
if(warning.code)assert.strictEqual(warning.code,testCode);
18+
if(warning.detail)assert.strictEqual(warning.detail,testDetail);
19+
},15));
20+
21+
classCustomWarningextendsError{
22+
constructor(){
23+
super();
24+
this.name=testType;
25+
this.message=testMsg;
26+
this.code=testCode;
27+
Error.captureStackTrace(this,CustomWarning);
28+
}
2829
}
29-
util.inherits(CustomWarning,Error);
30-
process.emitWarning(newCustomWarning());
30+
31+
[
32+
[testMsg],
33+
[testMsg,testType],
34+
[testMsg,CustomWarning],
35+
[testMsg,testType,CustomWarning],
36+
[testMsg,testType,testCode],
37+
[testMsg,{type: testType}],
38+
[testMsg,{type: testType,code: testCode}],
39+
[testMsg,{type: testType,code: testCode,detail: testDetail}],
40+
[newCustomWarning()],
41+
// detail will be ignored for the following. No errors thrown
42+
[testMsg,{type: testType,code: testCode,detail: true}],
43+
[testMsg,{type: testType,code: testCode,detail: []}],
44+
[testMsg,{type: testType,code: testCode,detail: null}],
45+
[testMsg,{type: testType,code: testCode,detail: 1}]
46+
].forEach((i)=>{
47+
assert.doesNotThrow(()=>process.emitWarning.apply(null,i));
48+
});
3149

3250
constwarningNoToString=newCustomWarning();
3351
warningNoToString.toString=null;
@@ -47,7 +65,6 @@ assert.throws(() => process.emitWarning(1), expectedError);
4765
assert.throws(()=>process.emitWarning({}),expectedError);
4866
assert.throws(()=>process.emitWarning(true),expectedError);
4967
assert.throws(()=>process.emitWarning([]),expectedError);
50-
assert.throws(()=>process.emitWarning('',{}),expectedError);
5168
assert.throws(()=>process.emitWarning('','',{}),expectedError);
5269
assert.throws(()=>process.emitWarning('',1),expectedError);
5370
assert.throws(()=>process.emitWarning('','',1),expectedError);

0 commit comments

Comments
(0)