Skip to content

Commit ccca547

Browse files
authored
util: runtime deprecate promisify-ing a function returning a Promise
PR-URL: #49609 Fixes: #49607 Reviewed-By: LiviaMedeiros <livia@cirno.name> Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
1 parent 553169f commit ccca547

File tree

3 files changed

+32
-3
lines changed

3 files changed

+32
-3
lines changed

doc/api/deprecations.md

+4-1
Original file line numberDiff line numberDiff line change
@@ -3387,12 +3387,15 @@ Consider using alternatives such as the [`mock`][] helper function.
33873387

33883388
<!-- YAML
33893389
changes:
3390+
- version: REPLACEME
3391+
pr-url: https://github.com/nodejs/node/pull/49609
3392+
description: Runtime deprecation.
33903393
- version: REPLACEME
33913394
pr-url: https://github.com/nodejs/node/pull/49647
33923395
description: Documentation-only deprecation.
33933396
-->
33943397

3395-
Type: Documentation-only
3398+
Type: Runtime
33963399

33973400
Calling [`util.promisify`][] on a function that returns a <Promise> will ignore
33983401
the result of said promise, which can lead to unhandled promise rejections.

lib/internal/util.js

+5-2
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ const {
6363
sleep: _sleep,
6464
toUSVString: _toUSVString,
6565
} = internalBinding('util');
66-
const { isNativeError } = internalBinding('types');
66+
const { isNativeError, isPromise } = internalBinding('types');
6767
const { getOptionValue } = require('internal/options');
6868

6969
const noCrypto = !process.versions.openssl;
@@ -409,7 +409,10 @@ function promisify(original) {
409409
resolve(values[0]);
410410
}
411411
});
412-
ReflectApply(original, this, args);
412+
if (isPromise(ReflectApply(original, this, args))) {
413+
process.emitWarning('Calling promisify on a function that returns a Promise is likely a mistake.',
414+
'DeprecationWarning', 'DEP0174');
415+
}
413416
});
414417
}
415418

test/parallel/test-util-promisify.js

+23
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,29 @@ const vm = require('vm');
77
const { promisify } = require('util');
88
const { customPromisifyArgs } = require('internal/util');
99

10+
{
11+
const warningHandler = common.mustNotCall();
12+
process.on('warning', warningHandler);
13+
function foo() {}
14+
foo.constructor = (async () => {}).constructor;
15+
promisify(foo);
16+
process.off('warning', warningHandler);
17+
}
18+
19+
common.expectWarning(
20+
'DeprecationWarning',
21+
'Calling promisify on a function that returns a Promise is likely a mistake.',
22+
'DEP0174');
23+
promisify(async (callback) => { callback(); })().then(common.mustCall(() => {
24+
// We must add the second `expectWarning` call in the `.then` handler, when
25+
// the first warning has already been triggered.
26+
common.expectWarning(
27+
'DeprecationWarning',
28+
'Calling promisify on a function that returns a Promise is likely a mistake.',
29+
'DEP0174');
30+
promisify(async () => {})().then(common.mustNotCall());
31+
}));
32+
1033
const stat = promisify(fs.stat);
1134

1235
{

0 commit comments

Comments
 (0)