@@ -26,9 +26,7 @@ extern operator '[]' macro LoadContextElementNoCell(
2626// together with the errors array. Since all closures for a single Promise.any
2727// call use the same context, we need to store the indices for the individual
2828// closures somewhere else (we put them into the identity hash field of the
29- // closures), and we also need to have a separate marker for when the closure
30- // was called already (we slap the native context onto the closure in that
31- // case to mark it's done). See Promise.all which uses the same approach.
29+ // closures).
3230transitioning macro CreatePromiseAnyRejectElementContext(
3331 implicit context: Context)(capability: PromiseCapability,
3432 nativeContext: NativeContext): PromiseAnyRejectElementContext {
@@ -75,36 +73,30 @@ transitioning javascript builtin PromiseAnyRejectElementClosure(
7573 js-implicit context: Context, receiver: JSAny, target: JSFunction)(
7674 value: JSAny): JSAny {
7775 // 1. Let F be the active function object.
78-
79- // 2. Let alreadyCalled be F.[[AlreadyCalled]].
80-
81- // 3. If alreadyCalled.[[Value]] is true, return undefined.
82-
83- // We use the function's context as the marker to remember whether this
84- // reject element closure was already called. It points to the reject
85- // element context (which is a FunctionContext) until it was called the
86- // first time, in which case we make it point to the native context here
87- // to mark this reject element closure as done.
88- if (IsNativeContext(context)) deferred {
89- return Undefined;
90- }
91-
9276 dcheck(
9377 context.length ==
9478 SmiTag(
9579 PromiseAnyRejectElementContextSlots::kPromiseAnyRejectElementLength));
9680 const context = %RawDownCast<PromiseAnyRejectElementContext>(context);
9781
98- // 4. Set alreadyCalled.[[Value]] to true.
99- const nativeContext = LoadNativeContext(context);
100- target.context = nativeContext;
101-
10282 // 5. Let index be F.[[Index]].
10383 dcheck(kPropertyArrayNoHashSentinel == 0);
10484 const identityHash = LoadJSReceiverIdentityHash(target) otherwise unreachable;
10585 dcheck(ChangeUint32ToWord(identityHash) < kSmiMaxValue);
10686 const index = Signed(ChangeUint32ToWord(identityHash)) - 1;
10787
88+ // 8. Let remainingElementsCount be F.[[RemainingElements]].
89+ let remainingElementsCount = *ContextSlot(
90+ context,
91+ PromiseAnyRejectElementContextSlots::
92+ kPromiseAnyRejectElementRemainingSlot);
93+
94+ // If all promises were already rejected, the remaining count will already be
95+ // 0.
96+ if (remainingElementsCount == 0) deferred {
97+ return Undefined;
98+ }
99+
108100 // 6. Let errors be F.[[Errors]].
109101 let errorsRef:&FixedArray = ContextSlot(
110102 context,
@@ -113,12 +105,6 @@ transitioning javascript builtin PromiseAnyRejectElementClosure(
113105
114106 // 7. Let promiseCapability be F.[[Capability]].
115107
116- // 8. Let remainingElementsCount be F.[[RemainingElements]].
117- let remainingElementsCount = *ContextSlot(
118- context,
119- PromiseAnyRejectElementContextSlots::
120- kPromiseAnyRejectElementRemainingSlot);
121-
122108 // 9. Set errors[index] to x.
123109
124110 // The max computation below is an optimization to avoid excessive allocations
@@ -138,11 +124,22 @@ transitioning javascript builtin PromiseAnyRejectElementClosure(
138124 errors, 0, errors.length_intptr, newCapacity, PromiseHole);
139125 *errorsRef = errors;
140126 }
127+
128+ // 2. Let alreadyCalled be F.[[AlreadyCalled]].
129+ // 3. If alreadyCalled.[[Value]] is true, return undefined.
130+ // 4. Set alreadyCalled.[[Value]] to true.
131+ if (errors.objects[index] != PromiseHole) deferred {
132+ return Undefined;
133+ }
134+
135+ // Make sure that we never see the PromiseHole here as a result.
136+ check(value != PromiseHole);
141137 errors.objects[index] = value;
142138
143139 // 10. Set remainingElementsCount.[[Value]] to
144140 // remainingElementsCount.[[Value]] - 1.
145141 remainingElementsCount = remainingElementsCount - 1;
142+ check(remainingElementsCount >= 0);
146143 *ContextSlot(
147144 context,
148145 PromiseAnyRejectElementContextSlots::
0 commit comments