Skip to content

Commit 014d1b5

Browse files
committed
adapt changes from #34862
1 parent f362a6a commit 014d1b5

File tree

2 files changed

+45
-13
lines changed

2 files changed

+45
-13
lines changed

lib/internal/process/promises.js

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ const {
55
ArrayPrototypeShift,
66
Error,
77
ObjectPrototypeHasOwnProperty,
8+
SafeMap,
89
SafeWeakMap,
910
} = primordials;
1011

@@ -149,9 +150,10 @@ class PromiseRejectionHandledWarning extends Error {
149150
const maybeUnhandledPromises = new SafeWeakMap();
150151

151152
/**
152-
* @type {Promise[]}
153+
* Using a Mp causes the promise to be referenced at least for one tick.
154+
* @type {Map<Promise, PromiseInfo>}
153155
*/
154-
const pendingUnhandledRejections = [];
156+
let pendingUnhandledRejections = new SafeMap();
155157

156158
/**
157159
* @type {Array<{promise: Promise, warning: Error}>}
@@ -279,21 +281,23 @@ const emitUnhandledRejection = (promise, promiseInfo) => {
279281
* @param {Error} reason
280282
*/
281283
function unhandledRejection(promise, reason) {
282-
maybeUnhandledPromises.set(promise, {
284+
pendingUnhandledRejections.set(promise, {
283285
reason,
284286
uid: ++lastPromiseId,
285287
warned: false,
286288
domain: process.domain,
287289
});
288-
// This causes the promise to be referenced at least for one tick.
289-
ArrayPrototypePush(pendingUnhandledRejections, promise);
290290
setHasRejectionToWarn(true);
291291
}
292292

293293
/**
294294
* @param {Promise} promise
295295
*/
296296
function handledRejection(promise) {
297+
if (pendingUnhandledRejections.has(promise)) {
298+
pendingUnhandledRejections.delete(promise);
299+
return;
300+
}
297301
const promiseInfo = maybeUnhandledPromises.get(promise);
298302
if (promiseInfo !== undefined) {
299303
maybeUnhandledPromises.delete(promise);
@@ -465,16 +469,17 @@ function processPromiseRejections() {
465469
}
466470
}
467471

468-
let len = pendingUnhandledRejections.length;
469472
let needPop = true;
470473
let promiseAsyncId;
471474

472-
while (len--) {
473-
const promise = ArrayPrototypeShift(pendingUnhandledRejections);
474-
const promiseInfo = maybeUnhandledPromises.get(promise);
475-
if (promiseInfo === undefined) {
476-
continue;
477-
}
475+
const pending = pendingUnhandledRejections;
476+
pendingUnhandledRejections = new SafeMap();
477+
478+
for (const { 0: promise, 1: promiseInfo } of pending.entries()) {
479+
pending.delete(promise);
480+
481+
maybeUnhandledPromises.set(promise, promiseInfo);
482+
478483
promiseInfo.warned = true;
479484

480485
// We need to check if async_hooks are enabled
@@ -499,7 +504,7 @@ function processPromiseRejections() {
499504
maybeScheduledTicksOrMicrotasks = true;
500505
}
501506
return maybeScheduledTicksOrMicrotasks ||
502-
pendingUnhandledRejections.length !== 0;
507+
pendingUnhandledRejections.size !== 0;
503508
}
504509

505510
function listenForRejections() {
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
'use strict';
2+
3+
require('../common');
4+
const assert = require('assert');
5+
6+
function delay(time) {
7+
return new Promise((resolve) => {
8+
setTimeout(resolve, time);
9+
});
10+
}
11+
12+
async function test() {
13+
for (let i = 0; i < 100000; i++) {
14+
await new Promise((resolve, reject) => {
15+
reject('value');
16+
})
17+
.then(() => { }, () => { });
18+
}
19+
20+
const time0 = Date.now();
21+
await delay(0);
22+
23+
const diff = Date.now() - time0;
24+
assert.ok(Date.now() - time0 < 500, `Expected less than 500ms, got ${diff}ms`);
25+
}
26+
27+
test();

0 commit comments

Comments
 (0)