electron/patches/v8/cherry-pick-8ff63d378f2c.patch

127 lines
5.6 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Shu-yu Guo <syg@chromium.org>
Date: Wed, 2 Aug 2023 17:41:03 -0700
Subject: Merged: [builtins] Clear FixedArray slot in Promise builtins
Fixed: chromium:1468943
(cherry picked from commit a84849ed718932b94dc877bb44a2d38eb8a0aef9)
Change-Id: Ia2b181c373c15bd1840e2a1572c0e930cddcd788
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4753495
Commit-Queue: Adam Klein <adamk@chromium.org>
Reviewed-by: Adam Klein <adamk@chromium.org>
Auto-Submit: Shu-yu Guo <syg@chromium.org>
Cr-Commit-Position: refs/branch-heads/11.6@{#28}
Cr-Branched-From: e29c028f391389a7a60ee37097e3ca9e396d6fa4-refs/heads/11.6.189@{#3}
Cr-Branched-From: 95cbef20e2aa556a1ea75431a48b36c4de6b9934-refs/heads/main@{#88340}
diff --git a/src/builtins/promise-all-element-closure.tq b/src/builtins/promise-all-element-closure.tq
index db3fb0134cf5bf0065174153171ef44a726a6fff..036e3c7b7473eae98f39a6da4472e826420086c8 100644
--- a/src/builtins/promise-all-element-closure.tq
+++ b/src/builtins/promise-all-element-closure.tq
@@ -175,11 +175,22 @@ transitioning macro PromiseAllResolveElementClosure<F: type>(
*NativeContextSlot(
nativeContext, ContextSlot::JS_ARRAY_PACKED_ELEMENTS_MAP_INDEX);
- // If resolve and reject handlers close over values to keep track of whether
- // an input promise is already settled, mark the values array as COW before
- // letting it escape to user code.
- if (hasResolveAndRejectClosures) MakeFixedArrayCOW(values);
-
+ // After this point, values escapes to user code.
+ //
+ // If resolve and reject handlers close over values to keep track of
+ // whether an input promise is already settled, mark the values array as
+ // COW. The original values array is still needed to guard against resolve
+ // or reject being called multiple times for an element.
+ //
+ // Otherwise, clear the slot.
+ if (hasResolveAndRejectClosures) {
+ MakeFixedArrayCOW(values);
+ } else {
+ *ContextSlot(
+ promiseContext,
+ PromiseAllResolveElementContextSlots::
+ kPromiseAllResolveElementValuesSlot) = kEmptyFixedArray;
+ }
const valuesArray = NewJSArray(arrayMap, values);
Call(promiseContext, resolve, Undefined, valuesArray);
}
diff --git a/src/builtins/promise-all.tq b/src/builtins/promise-all.tq
index 4d131abb44b7593d3e361d1d2f971380ee91850c..7205279526fa9edd93f154feb9694c22cae68606 100644
--- a/src/builtins/promise-all.tq
+++ b/src/builtins/promise-all.tq
@@ -278,15 +278,16 @@ Reject(JSAny) {
check(remainingElementsCount >= 0);
+ const valuesRef:&FixedArray = ContextSlot(
+ resolveElementContext,
+ PromiseAllResolveElementContextSlots::
+ kPromiseAllResolveElementValuesSlot);
+ const values = *valuesRef;
+
if (remainingElementsCount > 0) {
// Pre-allocate the backing store for the {values} to the desired
// capacity. We may already have elements in "values" - this happens
// when the Thenable calls the resolve callback immediately.
- const valuesRef:&FixedArray = ContextSlot(
- resolveElementContext,
- PromiseAllResolveElementContextSlots::
- kPromiseAllResolveElementValuesSlot);
- const values = *valuesRef;
// 'index' is a 1-based index and incremented after every Promise. Later we
// use 'values' as a 0-based array, so capacity 'index - 1' is enough.
const newCapacity = SmiUntag(index) - 1;
@@ -301,19 +302,23 @@ Reject(JSAny) {
// Let valuesArray be CreateArrayFromList(values).
// Perform ? Call(resultCapability.[[Resolve]], undefined,
// « valuesArray »).
-
- const values: FixedArray = *ContextSlot(
- resolveElementContext,
- PromiseAllResolveElementContextSlots::
- kPromiseAllResolveElementValuesSlot);
const arrayMap =
*NativeContextSlot(
nativeContext, ContextSlot::JS_ARRAY_PACKED_ELEMENTS_MAP_INDEX);
+ // After this point, values escapes to user code.
+ //
// If resolve and reject handlers close over values to keep track of
// whether an input promise is already settled, mark the values array as
- // COW before letting it escape to user code.
- if (hasResolveAndRejectClosures) MakeFixedArrayCOW(values);
+ // COW. The original values array is still needed to guard against resolve
+ // or reject being called multiple times for an element.
+ //
+ // Otherwise, clear the slot.
+ if (hasResolveAndRejectClosures) {
+ MakeFixedArrayCOW(values);
+ } else {
+ *valuesRef = kEmptyFixedArray;
+ }
const valuesArray = NewJSArray(arrayMap, values);
Call(nativeContext, UnsafeCast<JSAny>(resolve), Undefined, valuesArray);
diff --git a/src/builtins/promise-any.tq b/src/builtins/promise-any.tq
index 7e707e649f11bc946a6d1173180d7293fe94d8ce..45bafac0e6b09143b69b21a7292f9ed6b9c46239 100644
--- a/src/builtins/promise-any.tq
+++ b/src/builtins/promise-any.tq
@@ -313,10 +313,14 @@ Reject(JSAny) {
// We may already have elements in "errors" - this happens when the
// Thenable calls the reject callback immediately.
- const errors: FixedArray = *ContextSlot(
+ const errorsRef:&FixedArray = ContextSlot(
rejectElementContext,
PromiseAnyRejectElementContextSlots::
kPromiseAnyRejectElementErrorsSlot);
+ const errors: FixedArray = *errorsRef;
+
+ // After this point, errors escapes to user code. Clear the slot.
+ *errorsRef = kEmptyFixedArray;
check(errors.length == index - 1);
const error = ConstructAggregateError(errors);