| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 7e6b77b commit 7703f11
3 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -14,8 +14,6 @@ const { | |||
| 14 | 14 | promiseRejectEvents: { | |
| 15 | 15 | kPromiseRejectWithNoHandler, | |
| 16 | 16 | kPromiseHandlerAddedAfterReject, | |
| 17 | - kPromiseRejectAfterResolved, | ||
| 18 | - kPromiseResolveAfterResolved, | ||
| 19 | 17 | }, | |
| 20 | 18 | setPromiseRejectCallback, | |
| 21 | 19 | } = internalBinding('task_queue'); | |
@@ -161,21 +159,15 @@ function promiseRejectHandler(type, promise, reason) { | |||
| 161 | 159 | if (unhandledRejectionsMode === undefined) { | |
| 162 | 160 | unhandledRejectionsMode = getUnhandledRejectionsMode(); | |
| 163 | 161 | } | |
| 162 | + // kPromiseRejectAfterResolved and kPromiseResolveAfterResolved are | ||
| 163 | + // filtered out in C++ (src/node_task_queue.cc) and never reach JS. | ||
| 164 | 164 | switch (type) { | |
| 165 | 165 | case kPromiseRejectWithNoHandler: // 0 | |
| 166 | 166 | unhandledRejection(promise, reason); | |
| 167 | 167 | break; | |
| 168 | 168 | case kPromiseHandlerAddedAfterReject: // 1 | |
| 169 | 169 | handledRejection(promise); | |
| 170 | 170 | break; | |
| 171 | - case kPromiseRejectAfterResolved: // 2 | ||
| 172 | - // Do nothing in this case. Previous we would emit a multipleResolves | ||
| 173 | - // event but that was deprecated then later removed. | ||
| 174 | - break; | ||
| 175 | - case kPromiseResolveAfterResolved: // 3 | ||
| 176 | - // Do nothing in this case. Previous we would emit a multipleResolves | ||
| 177 | - // event but that was deprecated then later removed. | ||
| 178 | - break; | ||
| 179 | 171 | } | |
| 180 | 172 | } | |
| 181 | 173 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -53,7 +53,11 @@ void PromiseRejectCallback(PromiseRejectMessage message) { | |||
| 53 | 53 | ||
| 54 | 54 | Environment* env = Environment::GetCurrent(isolate); | |
| 55 | 55 | ||
| 56 | - if (env == nullptr || !env->can_call_into_js()) return; | ||
| 56 | + if (env == nullptr || !env->can_call_into_js() || | ||
| 57 | + event != kPromiseRejectWithNoHandler && | ||
| 58 | + event != kPromiseHandlerAddedAfterReject) { | ||
| 59 | + return; | ||
| 60 | + } | ||
| 57 | 61 | ||
| 58 | 62 | Local<Function> callback = env->promise_reject_callback(); | |
| 59 | 63 | // The promise is rejected before JS land calls SetPromiseRejectCallback | |
@@ -77,10 +81,6 @@ void PromiseRejectCallback(PromiseRejectMessage message) { | |||
| 77 | 81 | "rejections", | |
| 78 | 82 | "unhandled", unhandledRejections, | |
| 79 | 83 | "handledAfter", rejectionsHandledAfter); | |
| 80 | - } else if (event == kPromiseResolveAfterResolved) { | ||
| 81 | - value = message.GetValue(); | ||
| 82 | - } else if (event == kPromiseRejectAfterResolved) { | ||
| 83 | - value = message.GetValue(); | ||
| 84 | 84 | } else { | |
| 85 | 85 | return; | |
| 86 | 86 | } | |
@@ -173,8 +173,6 @@ static void Initialize(Local<Object> target, | |||
| 173 | 173 | Local<Object> events = Object::New(isolate); | |
| 174 | 174 | NODE_DEFINE_CONSTANT(events, kPromiseRejectWithNoHandler); | |
| 175 | 175 | NODE_DEFINE_CONSTANT(events, kPromiseHandlerAddedAfterReject); | |
| 176 | - NODE_DEFINE_CONSTANT(events, kPromiseResolveAfterResolved); | ||
| 177 | - NODE_DEFINE_CONSTANT(events, kPromiseRejectAfterResolved); | ||
| 178 | 176 | ||
| 179 | 177 | target->Set(env->context(), | |
| 180 | 178 | FIXED_ONE_BYTE_STRING(isolate, "promiseRejectEvents"), | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,24 @@ | |||
| 1 | + // Flags: --max-old-space-size=64 | ||
| 2 | + 'use strict'; | ||
| 3 | + | ||
| 4 | + // Regression test for https://github.com/nodejs/node/issues/51452 | ||
| 5 | + // When Promise.race() settles, V8 fires kPromiseResolveAfterResolved / | ||
| 6 | + // kPromiseRejectAfterResolved for each "losing" promise. Before this fix, | ||
| 7 | + // the C++ PromiseRejectCallback crossed into JS for these no-op events, | ||
| 8 | + // accumulating references and causing OOM in tight async loops. | ||
| 9 | + // With --max-old-space-size=64, this test would crash before completing | ||
| 10 | + // if the leak is present. | ||
| 11 | + | ||
| 12 | + const common = require('../common'); | ||
| 13 | + | ||
| 14 | + async function main() { | ||
| 15 | + for (let i = 0; i < 100_000; i++) { | ||
| 16 | + await Promise.race([ | ||
| 17 | + Promise.resolve(1), | ||
| 18 | + Promise.resolve(2), | ||
| 19 | + Promise.resolve(3), | ||
| 20 | + ]); | ||
| 21 | + } | ||
| 22 | + } | ||
| 23 | + | ||
| 24 | + main().then(common.mustCall()); | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments