Skip to content

Commit 9d27359

Browse files
committed
Add Promise All Settled Record
1 parent cf2e8ea commit 9d27359

File tree

8 files changed

+251
-7
lines changed

8 files changed

+251
-7
lines changed

nova_vm/src/ecmascript/builtins/control_abstraction_objects/promise_objects/promise_abstract_operations.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
44

55
pub(crate) mod promise_all_record;
6+
pub(crate) mod promise_all_settled_record;
67
pub mod promise_capability_records;
78
pub(crate) mod promise_finally_functions;
89
pub(crate) mod promise_jobs;
Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
// This Source Code Form is subject to the terms of the Mozilla Public
2+
// License, v. 2.0. If a copy of the MPL was not distributed with this
3+
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
4+
5+
use crate::{
6+
ecmascript::{
7+
builtins::{
8+
Array, promise::Promise,
9+
promise_objects::promise_abstract_operations::promise_capability_records::PromiseCapability,
10+
},
11+
execution::Agent,
12+
types::{IntoValue, Value},
13+
},
14+
engine::{
15+
context::{Bindable, GcScope, NoGcScope, bindable_handle},
16+
rootable::{HeapRootData, HeapRootRef, Rootable},
17+
},
18+
heap::{
19+
CompactionLists, CreateHeapData, Heap, HeapMarkAndSweep, WorkQueues, indexes::BaseIndex,
20+
},
21+
};
22+
23+
#[derive(Debug, Clone, Copy)]
24+
pub struct PromiseAllSettledRecord<'a> {
25+
pub(crate) remaining_elements_count: u32,
26+
pub(crate) result_array: Array<'a>,
27+
pub(crate) promise: Promise<'a>,
28+
}
29+
30+
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
31+
#[repr(transparent)]
32+
pub struct PromiseAllSettled<'a>(BaseIndex<'a, PromiseAllSettledRecord<'static>>);
33+
34+
impl<'a> PromiseAllSettled<'a> {
35+
pub(crate) fn on_promise_fulfilled(
36+
self,
37+
agent: &mut Agent,
38+
index: u32,
39+
value: Value<'a>,
40+
gc: GcScope<'a, '_>,
41+
) {
42+
let promise_all = self.bind(gc.nogc());
43+
let value = value.bind(gc.nogc());
44+
45+
let result_array = promise_all.get_result_array(agent, gc.nogc());
46+
47+
let elements = result_array.as_mut_slice(agent);
48+
elements[index as usize] = Some(value.unbind());
49+
50+
let data = promise_all.get_mut(agent);
51+
52+
// i. Set remainingElementsCount.[[Value]] to remainingElementsCount.[[Value]] - 1.
53+
data.remaining_elements_count = data.remaining_elements_count.saturating_sub(1);
54+
55+
//ii. If remainingElementsCount.[[Value]] = 0, then
56+
if data.remaining_elements_count == 0 {
57+
// 1. Let valuesArray be CreateArrayFromList(values).
58+
// 2. Perform ? Call(resultCapability.[[Resolve]], undefined, « valuesArray »).
59+
let capability = PromiseCapability::from_promise(data.promise, true);
60+
capability.resolve(agent, result_array.into_value().unbind(), gc);
61+
}
62+
}
63+
64+
pub(crate) fn on_promise_rejected(
65+
self,
66+
agent: &mut Agent,
67+
value: Value<'a>,
68+
gc: NoGcScope<'a, '_>,
69+
) {
70+
let value = value.bind(gc);
71+
let promise_all = self.bind(gc);
72+
let data = promise_all.get_mut(agent);
73+
74+
let capability = PromiseCapability::from_promise(data.promise, true);
75+
capability.reject(agent, value.unbind(), gc);
76+
}
77+
78+
pub(crate) fn get_result_array(self, agent: &Agent, gc: NoGcScope<'a, '_>) -> Array<'a> {
79+
let data = self.get(agent);
80+
data.result_array.bind(gc).unbind()
81+
}
82+
83+
pub(crate) const fn get_index(self) -> usize {
84+
self.0.into_index()
85+
}
86+
87+
pub fn get(self, agent: &Agent) -> &PromiseAllSettledRecord<'a> {
88+
agent
89+
.heap
90+
.promise_all_settled_records
91+
.get(self.get_index())
92+
.expect("PromiseAllSettledRecord not found")
93+
}
94+
95+
pub fn get_mut(self, agent: &mut Agent) -> &mut PromiseAllSettledRecord<'static> {
96+
agent
97+
.heap
98+
.promise_all_settled_records
99+
.get_mut(self.get_index())
100+
.expect("PromiseAllSettledRecord not found")
101+
}
102+
103+
pub(crate) const fn _def() -> Self {
104+
Self(BaseIndex::from_u32_index(0))
105+
}
106+
}
107+
108+
impl AsRef<[PromiseAllSettledRecord<'static>]> for Agent {
109+
fn as_ref(&self) -> &[PromiseAllSettledRecord<'static>] {
110+
&self.heap.promise_all_settled_records
111+
}
112+
}
113+
114+
impl AsMut<[PromiseAllSettledRecord<'static>]> for Agent {
115+
fn as_mut(&mut self) -> &mut [PromiseAllSettledRecord<'static>] {
116+
&mut self.heap.promise_all_settled_records
117+
}
118+
}
119+
120+
impl HeapMarkAndSweep for PromiseAllSettledRecord<'static> {
121+
fn mark_values(&self, queues: &mut WorkQueues) {
122+
let Self {
123+
remaining_elements_count: _,
124+
result_array,
125+
promise,
126+
} = self;
127+
result_array.mark_values(queues);
128+
promise.mark_values(queues);
129+
}
130+
131+
fn sweep_values(&mut self, compactions: &CompactionLists) {
132+
let Self {
133+
remaining_elements_count: _,
134+
result_array,
135+
promise,
136+
} = self;
137+
result_array.sweep_values(compactions);
138+
promise.sweep_values(compactions);
139+
}
140+
}
141+
142+
impl Rootable for PromiseAllSettled<'_> {
143+
type RootRepr = HeapRootRef;
144+
145+
fn to_root_repr(value: Self) -> Result<Self::RootRepr, HeapRootData> {
146+
Err(HeapRootData::PromiseAllSettled(value.unbind()))
147+
}
148+
149+
fn from_root_repr(value: &Self::RootRepr) -> Result<Self, HeapRootRef> {
150+
Err(*value)
151+
}
152+
153+
fn from_heap_ref(heap_ref: HeapRootRef) -> Self::RootRepr {
154+
heap_ref
155+
}
156+
157+
fn from_heap_data(heap_data: HeapRootData) -> Option<Self> {
158+
match heap_data {
159+
HeapRootData::PromiseAllSettled(object) => Some(object),
160+
_ => None,
161+
}
162+
}
163+
}
164+
165+
impl HeapMarkAndSweep for PromiseAllSettled<'static> {
166+
fn mark_values(&self, queues: &mut WorkQueues) {
167+
queues.promise_all_settled_records.push(*self);
168+
}
169+
170+
fn sweep_values(&mut self, compactions: &CompactionLists) {
171+
compactions
172+
.promise_all_settled_records
173+
.shift_index(&mut self.0);
174+
}
175+
}
176+
177+
bindable_handle!(PromiseAllSettledRecord);
178+
bindable_handle!(PromiseAllSettled);
179+
180+
impl<'a> CreateHeapData<PromiseAllSettledRecord<'a>, PromiseAllSettled<'a>> for Heap {
181+
fn create(&mut self, data: PromiseAllSettledRecord<'a>) -> PromiseAllSettled<'a> {
182+
self.promise_all_settled_records.push(data.unbind());
183+
self.alloc_counter += core::mem::size_of::<PromiseAllSettledRecord<'static>>();
184+
PromiseAllSettled(BaseIndex::last_t(&self.promise_all_settled_records))
185+
}
186+
}

nova_vm/src/ecmascript/types/language/object.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5017,6 +5017,7 @@ impl TryFrom<HeapRootData> for Object<'_> {
50175017
HeapRootData::AwaitReaction(_)
50185018
| HeapRootData::PromiseReaction(_)
50195019
| HeapRootData::PromiseAll(_)
5020+
| HeapRootData::PromiseAllSettled(_)
50205021
| HeapRootData::Executable(_)
50215022
| HeapRootData::Realm(_)
50225023
| HeapRootData::Script(_)

nova_vm/src/ecmascript/types/language/value.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1517,6 +1517,7 @@ impl Rootable for Value<'_> {
15171517
| HeapRootData::AwaitReaction(_)
15181518
| HeapRootData::PromiseReaction(_)
15191519
| HeapRootData::PromiseAll(_)
1520+
| HeapRootData::PromiseAllSettled(_)
15201521
| HeapRootData::DeclarativeEnvironment(_)
15211522
| HeapRootData::FunctionEnvironment(_)
15221523
| HeapRootData::GlobalEnvironment(_)

nova_vm/src/engine/rootable.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ use crate::{
7070
primitive_objects::PrimitiveObject,
7171
promise::Promise,
7272
promise_objects::promise_abstract_operations::{
73-
promise_all_record::PromiseAll,
73+
promise_all_record::PromiseAll, promise_all_settled_record::PromiseAllSettled,
7474
promise_finally_functions::BuiltinPromiseFinallyFunction,
7575
promise_reaction_records::PromiseReaction,
7676
promise_resolving_functions::BuiltinPromiseResolvingFunction,
@@ -148,7 +148,7 @@ pub mod private {
148148
primitive_objects::PrimitiveObject,
149149
promise::Promise,
150150
promise_objects::promise_abstract_operations::{
151-
promise_all_record::PromiseAll,
151+
promise_all_record::PromiseAll, promise_all_settled_record::PromiseAllSettled,
152152
promise_finally_functions::BuiltinPromiseFinallyFunction,
153153
promise_reaction_records::PromiseReaction,
154154
promise_resolving_functions::BuiltinPromiseResolvingFunction,
@@ -215,6 +215,7 @@ pub mod private {
215215
impl RootableSealed for Promise<'_> {}
216216
impl RootableSealed for PromiseReaction<'_> {}
217217
impl RootableSealed for PromiseAll<'_> {}
218+
impl RootableSealed for PromiseAllSettled<'_> {}
218219
impl RootableSealed for PropertyKey<'_> {}
219220
impl RootableSealed for Proxy<'_> {}
220221
impl RootableSealed for Realm<'_> {}
@@ -557,6 +558,7 @@ pub enum HeapRootData {
557558
AwaitReaction(AwaitReaction<'static>),
558559
PromiseReaction(PromiseReaction<'static>),
559560
PromiseAll(PromiseAll<'static>),
561+
PromiseAllSettled(PromiseAllSettled<'static>),
560562
Realm(Realm<'static>),
561563
Script(Script<'static>),
562564
SourceTextModule(SourceTextModule<'static>),
@@ -792,6 +794,9 @@ impl HeapMarkAndSweep for HeapRootData {
792794
HeapRootData::AwaitReaction(await_reaction) => await_reaction.mark_values(queues),
793795
HeapRootData::PromiseReaction(promise_reaction) => promise_reaction.mark_values(queues),
794796
HeapRootData::PromiseAll(promise_all) => promise_all.mark_values(queues),
797+
HeapRootData::PromiseAllSettled(promise_all_settled) => {
798+
promise_all_settled.mark_values(queues)
799+
}
795800
HeapRootData::Realm(realm) => realm.mark_values(queues),
796801
HeapRootData::Script(script) => script.mark_values(queues),
797802
HeapRootData::SourceCode(source_code) => source_code.mark_values(queues),
@@ -922,6 +927,9 @@ impl HeapMarkAndSweep for HeapRootData {
922927
promise_reaction.sweep_values(compactions)
923928
}
924929
HeapRootData::PromiseAll(promise_all) => promise_all.sweep_values(compactions),
930+
HeapRootData::PromiseAllSettled(promise_all_settled) => {
931+
promise_all_settled.sweep_values(compactions)
932+
}
925933
HeapRootData::Realm(realm) => realm.sweep_values(compactions),
926934
HeapRootData::Script(script) => script.sweep_values(compactions),
927935
HeapRootData::SourceCode(source_code) => source_code.sweep_values(compactions),

nova_vm/src/heap.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,11 @@ use crate::{
7979
},
8080
primitive_objects::PrimitiveObjectHeapData,
8181
promise::data::PromiseHeapData,
82-
promise_objects::promise_abstract_operations::promise_all_record::PromiseAllRecord,
83-
promise_objects::promise_abstract_operations::promise_finally_functions::PromiseFinallyFunctionHeapData,
82+
promise_objects::promise_abstract_operations::{
83+
promise_all_record::PromiseAllRecord,
84+
promise_all_settled_record::PromiseAllSettledRecord,
85+
promise_finally_functions::PromiseFinallyFunctionHeapData,
86+
},
8487
proxy::data::ProxyHeapData,
8588
text_processing::string_objects::string_iterator_objects::StringIteratorHeapData,
8689
},
@@ -175,6 +178,7 @@ pub(crate) struct Heap {
175178
pub(crate) proxies: Vec<Option<ProxyHeapData<'static>>>,
176179
pub(crate) realms: Vec<Option<RealmRecord<'static>>>,
177180
pub(crate) promise_all_records: Vec<PromiseAllRecord<'static>>,
181+
pub(crate) promise_all_settled_records: Vec<PromiseAllSettledRecord<'static>>,
178182
#[cfg(feature = "regexp")]
179183
pub(crate) regexps: Vec<Option<RegExpHeapData<'static>>>,
180184
#[cfg(feature = "regexp")]
@@ -328,6 +332,7 @@ impl Heap {
328332
promise_finally_functions: Vec::with_capacity(0),
329333
promises: Vec::with_capacity(0),
330334
promise_all_records: Vec::with_capacity(0),
335+
promise_all_settled_records: Vec::with_capacity(0),
331336
proxies: Vec::with_capacity(0),
332337
realms: Vec::with_capacity(1),
333338
#[cfg(feature = "regexp")]

nova_vm/src/heap/heap_bits.rs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,10 @@ use crate::ecmascript::{
5656
ordinary::{caches::PropertyLookupCache, shape::ObjectShape},
5757
primitive_objects::PrimitiveObject,
5858
promise::Promise,
59-
promise_objects::promise_abstract_operations::promise_all_record::PromiseAll,
60-
promise_objects::promise_abstract_operations::promise_finally_functions::BuiltinPromiseFinallyFunction,
59+
promise_objects::promise_abstract_operations::{
60+
promise_all_record::PromiseAll, promise_all_settled_record::PromiseAllSettled,
61+
promise_finally_functions::BuiltinPromiseFinallyFunction,
62+
},
6163
proxy::Proxy,
6264
text_processing::string_objects::string_iterator_objects::StringIterator,
6365
},
@@ -142,6 +144,7 @@ pub struct HeapBits {
142144
pub promise_finally_functions: Box<[bool]>,
143145
pub promises: Box<[bool]>,
144146
pub promise_all_records: Box<[bool]>,
147+
pub promise_all_settled_records: Box<[bool]>,
145148
pub proxies: Box<[bool]>,
146149
pub realms: Box<[bool]>,
147150
#[cfg(feature = "regexp")]
@@ -234,6 +237,7 @@ pub(crate) struct WorkQueues {
234237
pub promise_resolving_functions: Vec<BuiltinPromiseResolvingFunction<'static>>,
235238
pub promise_finally_functions: Vec<BuiltinPromiseFinallyFunction<'static>>,
236239
pub promise_all_records: Vec<PromiseAll<'static>>,
240+
pub promise_all_settled_records: Vec<PromiseAllSettled<'static>>,
237241
pub proxies: Vec<Proxy<'static>>,
238242
pub realms: Vec<Realm<'static>>,
239243
#[cfg(feature = "regexp")]
@@ -326,6 +330,7 @@ impl HeapBits {
326330
let private_environments = vec![false; heap.environments.private.len()];
327331
let promises = vec![false; heap.promises.len()];
328332
let promise_all_records = vec![false; heap.promise_all_records.len()];
333+
let promise_all_settled_records = vec![false; heap.promise_all_settled_records.len()];
329334
let proxies = vec![false; heap.proxies.len()];
330335
let realms = vec![false; heap.realms.len()];
331336
#[cfg(feature = "regexp")]
@@ -415,6 +420,7 @@ impl HeapBits {
415420
private_environments: private_environments.into_boxed_slice(),
416421
promises: promises.into_boxed_slice(),
417422
promise_all_records: promise_all_records.into_boxed_slice(),
423+
promise_all_settled_records: promise_all_settled_records.into_boxed_slice(),
418424
proxies: proxies.into_boxed_slice(),
419425
realms: realms.into_boxed_slice(),
420426
#[cfg(feature = "regexp")]
@@ -512,6 +518,9 @@ impl WorkQueues {
512518
promise_finally_functions: Vec::with_capacity(heap.promise_finally_functions.len() / 4),
513519
promises: Vec::with_capacity(heap.promises.len() / 4),
514520
promise_all_records: Vec::with_capacity(heap.promise_all_records.len() / 4),
521+
promise_all_settled_records: Vec::with_capacity(
522+
heap.promise_all_settled_records.len() / 4,
523+
),
515524
proxies: Vec::with_capacity(heap.proxies.len() / 4),
516525
realms: Vec::with_capacity(heap.realms.len() / 4),
517526
#[cfg(feature = "regexp")]
@@ -607,6 +616,7 @@ impl WorkQueues {
607616
promise_resolving_functions,
608617
promise_finally_functions,
609618
promise_all_records,
619+
promise_all_settled_records,
610620
proxies,
611621
realms,
612622
#[cfg(feature = "regexp")]
@@ -717,6 +727,7 @@ impl WorkQueues {
717727
&& promise_resolving_functions.is_empty()
718728
&& promise_finally_functions.is_empty()
719729
&& promise_all_records.is_empty()
730+
&& promise_all_settled_records.is_empty()
720731
&& promises.is_empty()
721732
&& proxies.is_empty()
722733
&& realms.is_empty()
@@ -1072,6 +1083,7 @@ pub(crate) struct CompactionLists {
10721083
pub promise_finally_functions: CompactionList,
10731084
pub promises: CompactionList,
10741085
pub promise_all_records: CompactionList,
1086+
pub promise_all_settled_records: CompactionList,
10751087
pub proxies: CompactionList,
10761088
pub realms: CompactionList,
10771089
#[cfg(feature = "regexp")]
@@ -1180,6 +1192,9 @@ impl CompactionLists {
11801192
),
11811193
promises: CompactionList::from_mark_bits(&bits.promises),
11821194
promise_all_records: CompactionList::from_mark_bits(&bits.promise_all_records),
1195+
promise_all_settled_records: CompactionList::from_mark_bits(
1196+
&bits.promise_all_settled_records,
1197+
),
11831198
#[cfg(feature = "regexp")]
11841199
regexps: CompactionList::from_mark_bits(&bits.regexps),
11851200
#[cfg(feature = "regexp")]

0 commit comments

Comments
 (0)