process: delay throwing an error using `throwDeprecation`

This makes sure all warnings that were triggered before a deprecation
warning during the same tick are properly handled and logged.

It also guarantees that users can not catch the error anymore.

Fixes: https://github.com/nodejs/node/issues/17871

PR-URL: https://github.com/nodejs/node/pull/32312
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Michaël Zasso <targos@protonmail.com>
pull/32312/merge
Ruben Bridgewater 2020-03-17 02:17:10 +01:00
parent 5d06a374ea
commit 49745cdef0
2 changed files with 15 additions and 5 deletions

View File

@ -126,8 +126,13 @@ function emitWarning(warning, type, code, ctor) {
if (warning.name === 'DeprecationWarning') {
if (process.noDeprecation)
return;
if (process.throwDeprecation)
throw warning;
if (process.throwDeprecation) {
// Delay throwing the error to guarantee that all former warnings were
// properly logged.
return process.nextTick(() => {
throw warning;
});
}
}
process.nextTick(doEmitWarning, warning);
}

View File

@ -38,9 +38,14 @@ function test4() {
// process.emitWarning will throw when process.throwDeprecation is true
// and type is `DeprecationWarning`.
process.throwDeprecation = true;
assert.throws(
() => process.emitWarning('test', 'DeprecationWarning'),
/^DeprecationWarning: test$/);
process.once('uncaughtException', (err) => {
assert.match(err.toString(), /^DeprecationWarning: test$/);
});
try {
process.emitWarning('test', 'DeprecationWarning');
} catch {
assert.fail('Unreachable');
}
process.throwDeprecation = false;
setImmediate(test5);
}