use crate::{
ecmascript::{Agent, OrdinaryObject, PromiseReaction, Value, new_promise_reaction_job},
engine::{NoGcScope, bindable_handle},
heap::{CompactionLists, HeapMarkAndSweep, WorkQueues},
};
#[derive(Debug, Clone, Default)]
pub(crate) struct PromiseHeapData<'a> {
pub(crate) object_index: Option<OrdinaryObject<'a>>,
pub(crate) promise_state: PromiseState<'a>,
}
bindable_handle!(PromiseHeapData);
#[derive(Debug, Clone)]
pub(crate) enum PromiseState<'a> {
Pending {
fulfill_reactions: Option<PromiseReactions<'a>>,
reject_reactions: Option<PromiseReactions<'a>>,
is_resolved: bool,
},
Fulfilled {
promise_result: Value<'a>,
},
Rejected {
promise_result: Value<'a>,
is_handled: bool,
},
}
impl Default for PromiseState<'_> {
fn default() -> Self {
Self::Pending {
fulfill_reactions: None,
reject_reactions: None,
is_resolved: false,
}
}
}
#[derive(Debug, Clone)]
pub(crate) enum PromiseReactions<'a> {
One(PromiseReaction<'a>),
Many(Vec<PromiseReaction<'a>>),
}
impl PromiseReactions<'_> {
pub(crate) fn trigger(&self, agent: &mut Agent, argument: Value, gc: NoGcScope) {
match self {
PromiseReactions::One(reaction) => {
let job = new_promise_reaction_job(agent, *reaction, argument, gc);
agent.host_hooks.enqueue_promise_job(job);
}
PromiseReactions::Many(vec) => {
for reaction in vec {
let job = new_promise_reaction_job(agent, *reaction, argument, gc);
agent.host_hooks.enqueue_promise_job(job);
}
}
};
}
}
impl HeapMarkAndSweep for PromiseReactions<'static> {
fn mark_values(&self, queues: &mut WorkQueues) {
match self {
PromiseReactions::One(reaction) => reaction.mark_values(queues),
PromiseReactions::Many(reactions) => reactions
.iter()
.for_each(|reaction| reaction.mark_values(queues)),
}
}
fn sweep_values(&mut self, compactions: &CompactionLists) {
match self {
PromiseReactions::One(reaction) => reaction.sweep_values(compactions),
PromiseReactions::Many(reactions) => reactions
.iter_mut()
.for_each(|reaction| reaction.sweep_values(compactions)),
}
}
}
impl HeapMarkAndSweep for PromiseHeapData<'static> {
fn mark_values(&self, queues: &mut WorkQueues) {
let Self {
object_index,
promise_state,
} = self;
object_index.mark_values(queues);
promise_state.mark_values(queues);
}
fn sweep_values(&mut self, compactions: &CompactionLists) {
let Self {
object_index,
promise_state,
} = self;
object_index.sweep_values(compactions);
promise_state.sweep_values(compactions);
}
}
impl HeapMarkAndSweep for PromiseState<'static> {
fn mark_values(&self, queues: &mut WorkQueues) {
match self {
PromiseState::Pending {
fulfill_reactions,
reject_reactions,
is_resolved: _,
} => {
fulfill_reactions.mark_values(queues);
reject_reactions.mark_values(queues);
}
PromiseState::Fulfilled { promise_result }
| PromiseState::Rejected {
promise_result,
is_handled: _,
} => {
promise_result.mark_values(queues);
}
}
}
fn sweep_values(&mut self, compactions: &CompactionLists) {
match self {
PromiseState::Pending {
fulfill_reactions,
reject_reactions,
is_resolved: _,
} => {
fulfill_reactions.sweep_values(compactions);
reject_reactions.sweep_values(compactions);
}
PromiseState::Fulfilled { promise_result }
| PromiseState::Rejected {
promise_result,
is_handled: _,
} => {
promise_result.sweep_values(compactions);
}
}
}
}