Skip to content

Commit 1e3da65

Browse files
committed
process: move multipleResolves event to EOL
The `multipleResolves` event has been deprecated for several years now. It's time.
1 parent 3f6ad56 commit 1e3da65

9 files changed

+10
-180
lines changed

doc/api/deprecations.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3327,6 +3327,9 @@ the errors used for value type validation.
33273327

33283328
<!-- YAML
33293329
changes:
3330+
- version: REPLACEME
3331+
pr-url: https://github.com/nodejs/node/pull/00000
3332+
description: End-of-Life.
33303333
- version: v18.0.0
33313334
pr-url: https://github.com/nodejs/node/pull/41896
33323335
description: Runtime deprecation.
@@ -3337,10 +3340,10 @@ changes:
33373340
description: Documentation-only deprecation.
33383341
-->
33393342

3340-
Type: Runtime
3343+
Type: End-of-Life
33413344

3342-
This event was deprecated because it did not work with V8 promise combinators
3343-
which diminished its usefulness.
3345+
This event was deprecated and remove because it did not work with V8 promise
3346+
combinators which diminished its usefulness.
33443347

33453348
### DEP0161: `process._getActiveRequests()` and `process._getActiveHandles()`
33463349

doc/api/process.md

Lines changed: 0 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -176,95 +176,6 @@ process, the `message` argument can contain data that JSON is not able
176176
to represent.
177177
See [Advanced serialization for `child_process`][] for more details.
178178

179-
### Event: `'multipleResolves'`
180-
181-
<!-- YAML
182-
added: v10.12.0
183-
deprecated:
184-
- v17.6.0
185-
- v16.15.0
186-
-->
187-
188-
> Stability: 0 - Deprecated
189-
190-
* `type` {string} The resolution type. One of `'resolve'` or `'reject'`.
191-
* `promise` {Promise} The promise that resolved or rejected more than once.
192-
* `value` {any} The value with which the promise was either resolved or
193-
rejected after the original resolve.
194-
195-
The `'multipleResolves'` event is emitted whenever a `Promise` has been either:
196-
197-
* Resolved more than once.
198-
* Rejected more than once.
199-
* Rejected after resolve.
200-
* Resolved after reject.
201-
202-
This is useful for tracking potential errors in an application while using the
203-
`Promise` constructor, as multiple resolutions are silently swallowed. However,
204-
the occurrence of this event does not necessarily indicate an error. For
205-
example, [`Promise.race()`][] can trigger a `'multipleResolves'` event.
206-
207-
Because of the unreliability of the event in cases like the
208-
[`Promise.race()`][] example above it has been deprecated.
209-
210-
```mjs
211-
import process from 'node:process';
212-
213-
process.on('multipleResolves', (type, promise, reason) => {
214-
console.error(type, promise, reason);
215-
setImmediate(() => process.exit(1));
216-
});
217-
218-
async function main() {
219-
try {
220-
return await new Promise((resolve, reject) => {
221-
resolve('First call');
222-
resolve('Swallowed resolve');
223-
reject(new Error('Swallowed reject'));
224-
});
225-
} catch {
226-
throw new Error('Failed');
227-
}
228-
}
229-
230-
main().then(console.log);
231-
// resolve: Promise { 'First call' } 'Swallowed resolve'
232-
// reject: Promise { 'First call' } Error: Swallowed reject
233-
// at Promise (*)
234-
// at new Promise (<anonymous>)
235-
// at main (*)
236-
// First call
237-
```
238-
239-
```cjs
240-
const process = require('node:process');
241-
242-
process.on('multipleResolves', (type, promise, reason) => {
243-
console.error(type, promise, reason);
244-
setImmediate(() => process.exit(1));
245-
});
246-
247-
async function main() {
248-
try {
249-
return await new Promise((resolve, reject) => {
250-
resolve('First call');
251-
resolve('Swallowed resolve');
252-
reject(new Error('Swallowed reject'));
253-
});
254-
} catch {
255-
throw new Error('Failed');
256-
}
257-
}
258-
259-
main().then(console.log);
260-
// resolve: Promise { 'First call' } 'Swallowed resolve'
261-
// reject: Promise { 'First call' } Error: Swallowed reject
262-
// at Promise (*)
263-
// at new Promise (<anonymous>)
264-
// at main (*)
265-
// First call
266-
```
267-
268179
### Event: `'rejectionHandled'`
269180

270181
<!-- YAML
@@ -4603,7 +4514,6 @@ cases:
46034514
[`Error`]: errors.md#class-error
46044515
[`EventEmitter`]: events.md#class-eventemitter
46054516
[`NODE_OPTIONS`]: cli.md#node_optionsoptions
4606-
[`Promise.race()`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/race
46074517
[`Worker`]: worker_threads.md#class-worker
46084518
[`Worker` constructor]: worker_threads.md#new-workerfilename-options
46094519
[`console.error()`]: console.md#consoleerrordata-args

lib/internal/process/promises.js

Lines changed: 4 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -43,27 +43,6 @@ const AsyncContextFrame = require('internal/async_context_frame');
4343
// *Must* match Environment::TickInfo::Fields in src/env.h.
4444
const kHasRejectionToWarn = 1;
4545

46-
// By default true because in cases where process is not a global
47-
// it is not possible to determine if the user has added a listener
48-
// to the process object.
49-
let hasMultipleResolvesListener = true;
50-
51-
if (process.on) {
52-
hasMultipleResolvesListener = process.listenerCount('multipleResolves') !== 0;
53-
54-
process.on('newListener', (eventName) => {
55-
if (eventName === 'multipleResolves') {
56-
hasMultipleResolvesListener = true;
57-
}
58-
});
59-
60-
process.on('removeListener', (eventName) => {
61-
if (eventName === 'multipleResolves') {
62-
hasMultipleResolvesListener = process.listenerCount('multipleResolves') !== 0;
63-
}
64-
});
65-
}
66-
6746
/**
6847
* Errors & Warnings
6948
*/
@@ -192,55 +171,16 @@ function promiseRejectHandler(type, promise, reason) {
192171
handledRejection(promise);
193172
break;
194173
case kPromiseRejectAfterResolved: // 2
195-
if (hasMultipleResolvesListener) {
196-
resolveErrorReject(promise, reason);
197-
}
174+
// Do nothing in this case. Previous we would emit a multipleResolves
175+
// event but that was deprecated then later removed.
198176
break;
199177
case kPromiseResolveAfterResolved: // 3
200-
if (hasMultipleResolvesListener) {
201-
resolveErrorResolve(promise, reason);
202-
}
178+
// Do nothing in this case. Previous we would emit a multipleResolves
179+
// event but that was deprecated then later removed.
203180
break;
204181
}
205182
}
206183

207-
const multipleResolvesDeprecate = deprecate(
208-
() => {},
209-
'The multipleResolves event has been deprecated.',
210-
'DEP0160',
211-
);
212-
213-
/**
214-
* @param {Promise} promise
215-
* @param {Error} reason
216-
*/
217-
function resolveErrorResolve(promise, reason) {
218-
// We have to wrap this in a next tick. Otherwise the error could be caught by
219-
// the executed promise.
220-
process.nextTick(() => {
221-
// Emit the multipleResolves event.
222-
// This is a deprecated event, so we have to check if it's being listened to.
223-
if (process.emit('multipleResolves', 'resolve', promise, reason)) {
224-
// If the event is being listened to, emit a deprecation warning.
225-
multipleResolvesDeprecate();
226-
}
227-
});
228-
}
229-
230-
/**
231-
* @param {Promise} promise
232-
* @param {Error} reason
233-
*/
234-
function resolveErrorReject(promise, reason) {
235-
// We have to wrap this in a next tick. Otherwise the error could be caught by
236-
// the executed promise.
237-
process.nextTick(() => {
238-
if (process.emit('multipleResolves', 'reject', promise, reason)) {
239-
multipleResolvesDeprecate();
240-
}
241-
});
242-
}
243-
244184
/**
245185
* @param {Promise} promise
246186
* @param {PromiseInfo} promiseInfo

test/parallel/test-events-once.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,6 @@ async function stopListeningAfterCatchingError() {
105105
} catch (_e) {
106106
err = _e;
107107
}
108-
process.removeAllListeners('multipleResolves');
109108
strictEqual(err, expected);
110109
strictEqual(ee.listenerCount('error'), 0);
111110
strictEqual(ee.listenerCount('myevent'), 0);

test/parallel/test-promise-swallowed-event.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@ const rejectPromise = new Promise((r) => setTimeout(r, 10, rejection2));
1010
const swallowedResolve = 'Swallowed resolve';
1111
const swallowedResolve2 = 'Foobar';
1212

13-
process.on('multipleResolves', common.mustCall(handler, 4));
14-
1513
const p1 = new Promise((resolve, reject) => {
1614
resolve(resolveMessage);
1715
resolve(swallowedResolve);

test/parallel/test-timers-immediate-promisified.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,6 @@ const setPromiseImmediate = promisify(timers.setImmediate);
1414

1515
assert.strictEqual(setPromiseImmediate, timerPromises.setImmediate);
1616

17-
process.on('multipleResolves', common.mustNotCall());
18-
1917
{
2018
const promise = setPromiseImmediate();
2119
promise.then(common.mustCall((value) => {

test/parallel/test-timers-interval-promisified.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,6 @@ const setPromiseTimeout = promisify(timers.setTimeout);
1414

1515
const { setInterval } = timerPromises;
1616

17-
process.on('multipleResolves', common.mustNotCall());
18-
1917
{
2018
const iterable = setInterval(1, undefined);
2119
const iterator = iterable[Symbol.asyncIterator]();

test/parallel/test-timers-timeout-promisified.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,6 @@ const setPromiseTimeout = promisify(timers.setTimeout);
1414

1515
assert.strictEqual(setPromiseTimeout, timerPromises.setTimeout);
1616

17-
process.on('multipleResolves', common.mustNotCall());
18-
1917
{
2018
const promise = setPromiseTimeout(1);
2119
promise.then(common.mustCall((value) => {

test/parallel/test-warn-multipleResolves.mjs

Lines changed: 0 additions & 14 deletions
This file was deleted.

0 commit comments

Comments
 (0)