From 495db8d7bc03e1e5e48934393fca9c274e50ec75 Mon Sep 17 00:00:00 2001 From: Jeremy Andrews Date: Thu, 15 Jul 2021 03:08:11 -0500 Subject: [PATCH] Issue #1725 - Fix logic in PerformPromiseAllSettled. This function essentially appears to work as written, there was an issue with it returning false too early in some situations that prevented it from working properly. --- js/src/builtin/Promise.cpp | 55 ++++++++++++++++++++------------------ 1 file changed, 29 insertions(+), 26 deletions(-) diff --git a/js/src/builtin/Promise.cpp b/js/src/builtin/Promise.cpp index 8ead6d9e7a..faba010950 100644 --- a/js/src/builtin/Promise.cpp +++ b/js/src/builtin/Promise.cpp @@ -1963,40 +1963,43 @@ PerformPromiseAllSettled(JSContext *cx, JS::ForOfIterator& iterator, HandleObjec RootedValue nextPromise(cx); RootedValue staticResolve(cx); - if (!GetProperty(cx, CVal, cx->names().resolve, &staticResolve)) - return false; - RootedValue staticReject(cx); - if (!GetProperty(cx, CVal, cx->names().reject, &staticReject)) + RootedValue staticReject(cx); + + // Because Promise.allSettled can continue whether the promise is fulfilled or rejected, we + // should only return false if neither condition is true. + + if (!GetProperty(cx, CVal, cx->names().resolve, &staticResolve) && + !GetProperty(cx, CVal, cx->names().reject, &staticReject)) return false; FixedInvokeArgs<1> resolveArgs(cx); resolveArgs[0].set(nextValue); - if (!Call(cx, staticResolve, CVal, resolveArgs, &nextPromise)) - return false; FixedInvokeArgs<1> rejectArgs(cx); rejectArgs[0].set(nextValue); - if (!Call(cx, staticReject, CVal, rejectArgs, &nextPromise)) + if (!Call(cx, staticResolve, CVal, resolveArgs, &nextPromise) && + !Call(cx, staticReject, CVal, rejectArgs, &nextPromise)) return false; - RootedFunction resolveFunc(cx, NewNativeFunction(cx, PromiseAllSettledResolveElementFunction, - 1, nullptr, - gc::AllocKind::FUNCTION_EXTENDED, - GenericObject)); - if (!resolveFunc) - return false; - RootedFunction rejectFunc(cx, NewNativeFunction(cx, PromiseAllSettledRejectElementFunction, - 1, nullptr, - gc::AllocKind::FUNCTION_EXTENDED, - GenericObject)); - if (!rejectFunc) - return false; - - resolveFunc->setExtendedSlot(PromiseAllResolveElementFunctionSlot_Data, dataHolderVal); - resolveFunc->setExtendedSlot(PromiseAllResolveElementFunctionSlot_ElementIndex, - Int32Value(index)); - rejectFunc->setExtendedSlot(PromiseAllResolveElementFunctionSlot_Data, dataHolderVal); - rejectFunc->setExtendedSlot(PromiseAllResolveElementFunctionSlot_ElementIndex, - Int32Value(index)); + + RootedFunction resolveFunc(cx, NewNativeFunction(cx, PromiseAllSettledResolveElementFunction, + 1, nullptr, + gc::AllocKind::FUNCTION_EXTENDED, + GenericObject)); + + RootedFunction rejectFunc(cx, NewNativeFunction(cx, PromiseAllSettledRejectElementFunction, + 1, nullptr, + gc::AllocKind::FUNCTION_EXTENDED, + GenericObject)); + if (!resolveFunc && !rejectFunc) { + return false; + } + + resolveFunc->setExtendedSlot(PromiseAllResolveElementFunctionSlot_Data, dataHolderVal); + resolveFunc->setExtendedSlot(PromiseAllResolveElementFunctionSlot_ElementIndex, + Int32Value(index)); + rejectFunc->setExtendedSlot(PromiseAllResolveElementFunctionSlot_Data, dataHolderVal); + rejectFunc->setExtendedSlot(PromiseAllResolveElementFunctionSlot_ElementIndex, + Int32Value(index)); dataHolder->increaseRemainingCount();