Skip to content

Commit c81121c

Browse files
committed
Move data to PromiseGroup
1 parent 7b39527 commit c81121c

File tree

3 files changed

+224
-123
lines changed

3 files changed

+224
-123
lines changed

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

Lines changed: 169 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,95 +1,191 @@
11
use crate::{
22
ecmascript::{
3-
builtins::promise_objects::promise_abstract_operations::{
4-
promise_all_record::PromiseAllRecord,
5-
promise_all_settled_record::PromiseAllSettledRecord,
3+
builtins::{
4+
Array, promise::Promise,
5+
promise_objects::promise_abstract_operations::promise_capability_records::PromiseCapability,
66
},
77
execution::Agent,
8-
types::Value,
8+
types::{BUILTIN_STRING_MEMORY, IntoValue, OrdinaryObject, Value},
99
},
1010
engine::{
11-
context::{Bindable, GcScope, bindable_handle},
11+
context::{Bindable, GcScope, NoGcScope, bindable_handle},
1212
rootable::{HeapRootData, HeapRootRef, Rootable},
1313
},
1414
heap::{
15-
CompactionLists, CreateHeapData, Heap, HeapMarkAndSweep, WorkQueues, indexes::BaseIndex,
15+
CompactionLists, CreateHeapData, Heap, HeapMarkAndSweep, ObjectEntry, WorkQueues,
16+
indexes::BaseIndex,
1617
},
1718
};
1819

1920
#[derive(Debug, Clone, Copy)]
20-
pub enum PromiseGroupRecord<'a> {
21-
PromiseAll(PromiseAllRecord<'a>),
22-
PromiseAllSettled(PromiseAllSettledRecord<'a>),
21+
pub enum PromiseGroupType {
22+
PromiseAll,
23+
PromiseAllSettled,
24+
}
25+
26+
#[derive(Debug, Clone, Copy)]
27+
pub struct PromiseGroupRecord<'a> {
28+
pub(crate) promise_group_type: PromiseGroupType,
29+
pub(crate) remaining_elements_count: u32,
30+
pub(crate) result_array: Array<'a>,
31+
pub(crate) promise: Promise<'a>,
2332
}
2433

2534
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
2635
#[repr(transparent)]
2736
pub struct PromiseGroup<'a>(BaseIndex<'a, PromiseGroupRecord<'static>>);
2837

2938
impl<'a> PromiseGroup<'a> {
30-
pub(crate) fn on_promise_fulfilled(
39+
pub(crate) fn on_promise_all_fulfilled(
3140
self,
3241
agent: &mut Agent,
3342
index: u32,
3443
value: Value<'a>,
35-
mut gc: GcScope<'a, '_>,
44+
gc: GcScope<'a, '_>,
3645
) {
46+
let promise_all = self.bind(gc.nogc());
3747
let value = value.bind(gc.nogc());
38-
let promise_group = self.bind(gc.nogc());
39-
40-
let promise_group = promise_group.get_mut(agent);
41-
match promise_group {
42-
PromiseGroupRecord::PromiseAll(promise_all) => {
43-
// i. Set remainingElementsCount.[[Value]] to remainingElementsCount.[[Value]] - 1.
44-
promise_all.remaining_elements_count =
45-
promise_all.remaining_elements_count.saturating_sub(1);
46-
promise_all.on_promise_fulfilled(agent, index, value.unbind(), gc.reborrow());
47-
}
48-
PromiseGroupRecord::PromiseAllSettled(promise_all_settled) => {
49-
// 13. Set remainingElementsCount.[[Value]] to remainingElementsCount.[[Value]] - 1.
50-
promise_all_settled.remaining_elements_count = promise_all_settled
51-
.remaining_elements_count
52-
.saturating_sub(1);
53-
promise_all_settled.on_promise_fulfilled(
54-
agent,
55-
index,
56-
value.unbind(),
57-
gc.reborrow(),
58-
);
59-
}
60-
};
61-
}
62-
63-
pub(crate) fn on_promise_rejected(
48+
49+
let result_array = promise_all.get_result_array(agent, gc.nogc());
50+
51+
let elements = result_array.as_mut_slice(agent);
52+
elements[index as usize] = Some(value.unbind());
53+
54+
let data = promise_all.get_mut(agent);
55+
56+
// i. Set remainingElementsCount.[[Value]] to remainingElementsCount.[[Value]] - 1.
57+
data.remaining_elements_count = data.remaining_elements_count.saturating_sub(1);
58+
59+
//ii. If remainingElementsCount.[[Value]] = 0, then
60+
if data.remaining_elements_count == 0 {
61+
// 1. Let valuesArray be CreateArrayFromList(values).
62+
// 2. Perform ? Call(resultCapability.[[Resolve]], undefined, « valuesArray »).
63+
let capability = PromiseCapability::from_promise(data.promise, true);
64+
capability.resolve(agent, result_array.into_value().unbind(), gc);
65+
}
66+
}
67+
68+
pub(crate) fn on_promise_all_rejected(
69+
self,
70+
agent: &mut Agent,
71+
value: Value<'a>,
72+
gc: NoGcScope<'a, '_>,
73+
) {
74+
let value = value.bind(gc);
75+
let promise_all = self.bind(gc);
76+
let data = promise_all.get_mut(agent);
77+
78+
let capability = PromiseCapability::from_promise(data.promise, true);
79+
capability.reject(agent, value.unbind(), gc);
80+
}
81+
82+
pub(crate) fn on_promise_all_settled_fulfilled(
6483
self,
6584
agent: &mut Agent,
6685
index: u32,
6786
value: Value<'a>,
68-
mut gc: GcScope<'a, '_>,
87+
gc: GcScope<'a, '_>,
6988
) {
89+
let promise_all = self.bind(gc.nogc());
7090
let value = value.bind(gc.nogc());
71-
let promise_group = self.bind(gc.nogc());
72-
73-
let promise_group = promise_group.get_mut(agent);
74-
match promise_group {
75-
PromiseGroupRecord::PromiseAll(promise_all) => {
76-
promise_all.on_promise_rejected(agent, value.unbind(), gc.nogc())
77-
}
78-
PromiseGroupRecord::PromiseAllSettled(promise_all_settled) => {
79-
// 13. Set remainingElementsCount.[[Value]] to remainingElementsCount.[[Value]] - 1.
80-
promise_all_settled.remaining_elements_count = promise_all_settled
81-
.remaining_elements_count
82-
.saturating_sub(1);
83-
promise_all_settled.on_promise_rejected(
84-
agent,
85-
index,
86-
value.unbind(),
87-
gc.reborrow(),
88-
);
89-
}
91+
92+
let result_array = promise_all.get_result_array(agent, gc.nogc());
93+
94+
// Let obj be OrdinaryObjectCreate(%Object.prototype%).
95+
// 10. Perform ! CreateDataPropertyOrThrow(obj, "status", "fulfilled").
96+
// 11. Perform ! CreateDataPropertyOrThrow(obj, "value", x).
97+
let obj = OrdinaryObject::create_object(
98+
agent,
99+
Some(
100+
agent
101+
.current_realm_record()
102+
.intrinsics()
103+
.object_prototype()
104+
.into(),
105+
),
106+
&[
107+
ObjectEntry::new_data_entry(
108+
BUILTIN_STRING_MEMORY.status.into(),
109+
BUILTIN_STRING_MEMORY.fulfilled.into(),
110+
),
111+
ObjectEntry::new_data_entry(BUILTIN_STRING_MEMORY.value.into(), value.unbind()),
112+
],
113+
)
114+
.bind(gc.nogc());
115+
116+
let elements = result_array.as_mut_slice(agent);
117+
elements[index as usize] = Some(obj.unbind().into_value());
118+
119+
let data = promise_all.get_mut(agent);
120+
121+
// 13. Set remainingElementsCount.[[Value]] to remainingElementsCount.[[Value]] - 1.
122+
data.remaining_elements_count = data.remaining_elements_count.saturating_sub(1);
123+
124+
// 14. If remainingElementsCount.[[Value]] = 0, then
125+
if data.remaining_elements_count == 0 {
126+
// a. Let valuesArray be CreateArrayFromList(values).
127+
// b. Return ? Call(promiseCapability.[[Resolve]], undefined, « valuesArray »).
128+
let capability = PromiseCapability::from_promise(data.promise, true);
129+
capability.resolve(agent, result_array.into_value().unbind(), gc);
90130
}
91131
}
92132

133+
pub(crate) fn on_promise_all_settled_rejected(
134+
self,
135+
agent: &mut Agent,
136+
index: u32,
137+
value: Value<'a>,
138+
gc: GcScope<'a, '_>,
139+
) {
140+
let promise_all = self.bind(gc.nogc());
141+
let value = value.bind(gc.nogc());
142+
143+
let result_array = promise_all.get_result_array(agent, gc.nogc());
144+
145+
// Let obj be OrdinaryObjectCreate(%Object.prototype%).
146+
// 10. Perform ! CreateDataPropertyOrThrow(obj, "status", "rejected").
147+
// 11. Perform ! CreateDataPropertyOrThrow(obj, "reason", x).
148+
let obj = OrdinaryObject::create_object(
149+
agent,
150+
Some(
151+
agent
152+
.current_realm_record()
153+
.intrinsics()
154+
.object_prototype()
155+
.into(),
156+
),
157+
&[
158+
ObjectEntry::new_data_entry(
159+
BUILTIN_STRING_MEMORY.status.into(),
160+
BUILTIN_STRING_MEMORY.rejected.into(),
161+
),
162+
ObjectEntry::new_data_entry(BUILTIN_STRING_MEMORY.reason.into(), value.unbind()),
163+
],
164+
)
165+
.bind(gc.nogc());
166+
167+
let elements = result_array.as_mut_slice(agent);
168+
elements[index as usize] = Some(obj.unbind().into_value());
169+
170+
let data = promise_all.get_mut(agent);
171+
172+
// 13. Set remainingElementsCount.[[Value]] to remainingElementsCount.[[Value]] - 1.
173+
data.remaining_elements_count = data.remaining_elements_count.saturating_sub(1);
174+
175+
// 14. If remainingElementsCount.[[Value]] = 0, then
176+
if data.remaining_elements_count == 0 {
177+
// a. Let valuesArray be CreateArrayFromList(values).
178+
// b. Return ? Call(promiseCapability.[[Resolve]], undefined, « valuesArray »).
179+
let capability = PromiseCapability::from_promise(data.promise, true);
180+
capability.resolve(agent, result_array.into_value().unbind(), gc);
181+
}
182+
}
183+
184+
pub(crate) fn get_result_array(self, agent: &Agent, gc: NoGcScope<'a, '_>) -> Array<'a> {
185+
let data = self.get(agent);
186+
data.result_array.bind(gc).unbind()
187+
}
188+
93189
pub(crate) const fn get_index(self) -> usize {
94190
self.0.into_index()
95191
}
@@ -129,21 +225,25 @@ impl AsMut<[PromiseGroupRecord<'static>]> for Agent {
129225

130226
impl HeapMarkAndSweep for PromiseGroupRecord<'static> {
131227
fn mark_values(&self, queues: &mut WorkQueues) {
132-
match self {
133-
PromiseGroupRecord::PromiseAll(promise_all) => promise_all.mark_values(queues),
134-
PromiseGroupRecord::PromiseAllSettled(promise_all_settled) => {
135-
promise_all_settled.mark_values(queues)
136-
}
137-
}
228+
let Self {
229+
promise_group_type: _,
230+
remaining_elements_count: _,
231+
result_array,
232+
promise,
233+
} = self;
234+
result_array.mark_values(queues);
235+
promise.mark_values(queues);
138236
}
139237

140238
fn sweep_values(&mut self, compactions: &CompactionLists) {
141-
match self {
142-
PromiseGroupRecord::PromiseAll(promise_all) => promise_all.sweep_values(compactions),
143-
PromiseGroupRecord::PromiseAllSettled(promise_all_settled) => {
144-
promise_all_settled.sweep_values(compactions)
145-
}
146-
}
239+
let Self {
240+
promise_group_type: _,
241+
remaining_elements_count: _,
242+
result_array,
243+
promise,
244+
} = self;
245+
result_array.sweep_values(compactions);
246+
promise.sweep_values(compactions);
147247
}
148248
}
149249

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

Lines changed: 41 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,10 @@ use crate::{
1212
},
1313
operations_on_objects::{call_function, get_function_realm},
1414
},
15-
builtins::{ArgumentsList, promise::Promise},
15+
builtins::{
16+
ArgumentsList, promise::Promise,
17+
promise_objects::promise_abstract_operations::promise_group_record::PromiseGroupType,
18+
},
1619
execution::{
1720
Agent, JsResult,
1821
agent::{InnerJob, Job, JsError},
@@ -289,23 +292,43 @@ impl PromiseReactionJob {
289292
index,
290293
} => {
291294
let reaction_type = agent[reaction].reaction_type;
292-
match reaction_type {
293-
PromiseReactionType::Fulfill => {
294-
promise_group.on_promise_fulfilled(
295-
agent,
296-
index,
297-
argument.unbind(),
298-
gc.reborrow(),
299-
);
300-
}
301-
PromiseReactionType::Reject => {
302-
promise_group.on_promise_rejected(
303-
agent,
304-
index,
305-
argument.unbind(),
306-
gc.reborrow(),
307-
);
308-
}
295+
let record = promise_group.get(agent);
296+
match record.promise_group_type {
297+
PromiseGroupType::PromiseAll => match reaction_type {
298+
PromiseReactionType::Fulfill => {
299+
promise_group.on_promise_all_fulfilled(
300+
agent,
301+
index,
302+
argument.unbind(),
303+
gc.reborrow(),
304+
);
305+
}
306+
PromiseReactionType::Reject => {
307+
promise_group.on_promise_all_rejected(
308+
agent,
309+
argument.unbind(),
310+
gc.nogc(),
311+
);
312+
}
313+
},
314+
PromiseGroupType::PromiseAllSettled => match reaction_type {
315+
PromiseReactionType::Fulfill => {
316+
promise_group.on_promise_all_settled_fulfilled(
317+
agent,
318+
index,
319+
argument.unbind(),
320+
gc.reborrow(),
321+
);
322+
}
323+
PromiseReactionType::Reject => {
324+
promise_group.on_promise_all_settled_rejected(
325+
agent,
326+
index,
327+
argument.unbind(),
328+
gc.reborrow(),
329+
);
330+
}
331+
},
309332
}
310333
return Ok(());
311334
}

0 commit comments

Comments
 (0)