atmos/os_lib/js/interp/
promise_loop.rs1use super::*;
5
6impl Interp {
7 pub fn promise_resolve(&mut self, state: &Rc<RefCell<PromiseState>>, value: Value) {
9 if state.borrow().status != PromiseStatus::Pending {
10 return;
11 }
12 if let Value::Object(o) = &value {
14 let inner = match &o.borrow().kind {
15 ObjKind::PromiseObj(s) => Some(s.clone()),
16 _ => None,
17 };
18 if let Some(inner) = inner {
19 let on_f = Value::Object(Obj::resolver(state.clone(), false));
20 let on_r = Value::Object(Obj::resolver(state.clone(), true));
21 self.promise_then(&inner, Some(on_f), Some(on_r));
22 return;
23 }
24 }
25 if matches!(&value, Value::Object(_)) {
33 let then_fn = self.get_property(&value, "then").unwrap_or(Value::Undefined);
39 if matches!(&then_fn, Value::Object(f) if f.borrow().is_callable()) {
40 let on_f = Value::Object(Obj::resolver(state.clone(), false));
41 let on_r = Value::Object(Obj::resolver(state.clone(), true));
42 if let Err(e) = self.call_value(&then_fn, value.clone(), &[on_f, on_r]) {
43 self.promise_reject(state, e);
45 }
46 return;
47 }
48 }
49 let reactions = {
50 let mut b = state.borrow_mut();
51 b.status = PromiseStatus::Fulfilled;
52 b.value = value.clone();
53 core::mem::take(&mut b.reactions)
54 };
55 for r in &reactions {
56 self.schedule_reaction(r, value.clone(), true);
57 }
58 }
59
60 pub fn promise_reject(&mut self, state: &Rc<RefCell<PromiseState>>, reason: Value) {
62 if state.borrow().status != PromiseStatus::Pending {
63 return;
64 }
65 let reactions = {
66 let mut b = state.borrow_mut();
67 b.status = PromiseStatus::Rejected;
68 b.value = reason.clone();
69 core::mem::take(&mut b.reactions)
70 };
71 for r in &reactions {
72 self.schedule_reaction(r, reason.clone(), false);
73 }
74 }
75
76 pub fn promise_then(
78 &mut self,
79 state: &Rc<RefCell<PromiseState>>,
80 on_fulfilled: Option<Value>,
81 on_rejected: Option<Value>,
82 ) -> Value {
83 let result = Rc::new(RefCell::new(PromiseState::pending()));
84 let reaction = Reaction {
85 on_fulfilled,
86 on_rejected,
87 result: result.clone(),
88 };
89 let status = state.borrow().status;
90 match status {
91 PromiseStatus::Pending => state.borrow_mut().reactions.push(reaction),
92 PromiseStatus::Fulfilled => {
93 let v = state.borrow().value.clone();
94 self.schedule_reaction(&reaction, v, true);
95 }
96 PromiseStatus::Rejected => {
97 let v = state.borrow().value.clone();
98 self.schedule_reaction(&reaction, v, false);
99 }
100 }
101 Value::Object(Obj::promise(result))
102 }
103
104 pub(crate) fn schedule_reaction(&self, reaction: &Reaction, value: Value, is_fulfill: bool) {
105 let handler = if is_fulfill {
106 reaction.on_fulfilled.clone()
107 } else {
108 reaction.on_rejected.clone()
109 };
110 self.microtasks.borrow_mut().push_back(Job {
111 handler,
112 arg: value,
113 is_fulfill,
114 result: reaction.result.clone(),
115 });
116 }
117
118 pub(crate) fn run_one_microtask(&mut self) -> bool {
120 let job = self.microtasks.borrow_mut().pop_front();
121 let job = match job {
122 Some(j) => j,
123 None => return false,
124 };
125 match job.handler {
126 Some(h) => match self.call_value(&h, Value::Undefined, &[job.arg]) {
127 Ok(v) => self.promise_resolve(&job.result, v),
128 Err(e) => {
129 if !self.aborted {
130 self.promise_reject(&job.result, e);
131 }
132 }
133 },
134 None => {
135 if job.is_fulfill {
136 self.promise_resolve(&job.result, job.arg);
137 } else {
138 self.promise_reject(&job.result, job.arg);
139 }
140 }
141 }
142 true
143 }
144
145 pub fn run_microtasks(&mut self) {
147 while !self.aborted && self.run_one_microtask() {}
148 }
149
150 pub(crate) fn timer_now(&self) -> u64 {
153 crate::kernel::timer::get_system_time_ms().wrapping_add(self.clock_skew.get())
154 }
155
156 pub(crate) fn run_timer(&mut self, force: bool) -> bool {
160 let now = self.timer_now();
161 let task = {
162 let mut q = self.macrotasks.borrow_mut();
163 let idx = q
164 .iter()
165 .enumerate()
166 .filter(|(_, t)| force || t.due_ms <= now)
167 .min_by_key(|(i, t)| (t.due_ms, *i))
168 .map(|(i, _)| i);
169 idx.and_then(|i| q.remove(i))
170 };
171 let Some(t) = task else { return false };
172 if force && t.due_ms > now {
173 self.clock_skew.set(self.clock_skew.get().wrapping_add(t.due_ms - now));
175 }
176 if let Some(p) = t.period_ms {
177 let mut next = t.clone();
178 next.due_ms = t.due_ms.max(now).wrapping_add(p.max(1));
179 self.macrotasks.borrow_mut().push_back(next);
180 }
181 let ctx = if t.period_ms.is_some() { "setInterval callback" } else { "setTimeout callback" };
182 self.call_listener(&t.cb, Value::Undefined, &t.args, ctx);
183 true
184 }
185
186 pub(crate) fn run_one_macrotask(&mut self) -> bool {
188 self.run_timer(false)
189 }
190
191 pub fn has_due_timer(&self) -> bool {
193 let now = self.timer_now();
194 self.macrotasks.borrow().iter().any(|t| t.due_ms <= now)
195 }
196
197 pub fn run_event_loop_for(&mut self, budget_ms: u64) {
200 let start = crate::kernel::timer::get_system_time_ms();
201 loop {
202 self.run_microtasks();
203 if self.aborted {
204 break;
205 }
206 if crate::kernel::timer::get_system_time_ms().wrapping_sub(start) > budget_ms {
207 break;
208 }
209 if !self.run_timer(false) {
210 break;
211 }
212 }
213 }
214
215 pub fn run_event_loop(&mut self) {
217 self.run_event_loop_for(300);
218 }
219
220 pub(crate) fn chain_suppressed(&mut self, prev: Option<Value>, new_err: Value) -> Value {
225 let Some(suppressed) = prev else {
226 return new_err;
227 };
228 let Some(ctor) = scope_get(&self.global, "SuppressedError") else {
229 return new_err;
230 };
231 self.call_value(&ctor, Value::Undefined, &[new_err.clone(), suppressed, Value::str("")])
232 .unwrap_or(new_err)
233 }
234
235 pub(crate) fn await_value(&mut self, v: Value) -> EvalResult {
236 let state = match &v {
237 Value::Object(o) => match &o.borrow().kind {
238 ObjKind::PromiseObj(s) => Some(s.clone()),
239 _ => None,
240 },
241 _ => None,
242 };
243 let state = match state {
250 Some(s) => s,
251 None => {
252 let new_state = Rc::new(RefCell::new(PromiseState::pending()));
253 self.promise_resolve(&new_state, v);
254 new_state
255 }
256 };
257 loop {
258 let status = state.borrow().status;
259 match status {
260 PromiseStatus::Fulfilled => return Ok(state.borrow().value.clone()),
261 PromiseStatus::Rejected => return Err(state.borrow().value.clone()),
262 PromiseStatus::Pending => {
263 if self.aborted {
264 return Err(Value::Undefined);
265 }
266 let has_micro = self.run_one_microtask();
269 let has_macro = !has_micro && self.run_timer(true);
270 if !has_micro && !has_macro {
271 return Ok(Value::Undefined);
272 }
273 }
274 }
275 }
276 }
277
278}