1use super::*;
4
5pub(crate) static TIMER_ID: AtomicU64 = AtomicU64::new(1);
8
9fn delay_arg(v: &Value) -> u64 {
11 let d = v.to_number();
12 if d.is_finite() && d > 0.0 {
13 d as u64
14 } else {
15 0
16 }
17}
18
19fn push_timer(it: &mut Interp, a: &[Value], period: bool) -> Result<Value, Value> {
20 if let Some(cb) = callable_or_none(arg(a, 0)) {
21 let extra: Vec<Value> = if a.len() > 2 { a[2..].to_vec() } else { Vec::new() };
22 let id = TIMER_ID.fetch_add(1, Ordering::Relaxed);
23 let delay = delay_arg(&arg(a, 1));
24 let period_ms = period.then(|| delay.max(1));
26 let due_ms = it.timer_now().wrapping_add(period_ms.unwrap_or(delay));
27 it.macrotasks.borrow_mut().push_back(crate::os_lib::js::interp::TimerTask { cb, args: extra, id, due_ms, period_ms });
28 return Ok(Value::Number(id as f64));
29 }
30 Ok(Value::Number(0.0))
31}
32
33pub(crate) fn set_timeout(it: &mut Interp, _t: Value, a: &[Value]) -> Result<Value, Value> {
35 push_timer(it, a, false)
36}
37
38pub(crate) fn set_interval(it: &mut Interp, _t: Value, a: &[Value]) -> Result<Value, Value> {
41 push_timer(it, a, true)
42}
43
44pub(crate) fn clear_interval(it: &mut Interp, _t: Value, a: &[Value]) -> Result<Value, Value> {
45 clear_timeout(it, Value::Undefined, a)
46}
47
48pub(crate) fn clear_timeout(it: &mut Interp, _t: Value, a: &[Value]) -> Result<Value, Value> {
49 let id = arg(a, 0).to_number() as u64;
50 it.macrotasks.borrow_mut().retain(|t| t.id != id);
51 Ok(Value::Undefined)
52}
53
54pub(crate) static RAF_TS: AtomicU64 = AtomicU64::new(0);
56
57pub(crate) fn request_animation_frame(it: &mut Interp, _t: Value, a: &[Value]) -> Result<Value, Value> {
60 if let Some(cb) = callable_or_none(arg(a, 0)) {
61 let ts = RAF_TS.fetch_add(16, Ordering::Relaxed) as f64;
62 let id = TIMER_ID.fetch_add(1, Ordering::Relaxed);
63 let due_ms = it.timer_now().wrapping_add(16);
64 it.macrotasks.borrow_mut().push_back(crate::os_lib::js::interp::TimerTask {
65 cb,
66 args: alloc::vec![Value::Number(ts)],
67 id,
68 due_ms,
69 period_ms: None,
70 });
71 return Ok(Value::Number(id as f64));
72 }
73 Ok(Value::Number(0.0))
74}
75
76pub(crate) fn queue_microtask(it: &mut Interp, _t: Value, a: &[Value]) -> Result<Value, Value> {
77 if let Some(cb) = callable_or_none(arg(a, 0)) {
78 let result = new_pending();
79 it.microtasks.borrow_mut().push_back(Job {
80 handler: Some(cb),
81 arg: Value::Undefined,
82 is_fulfill: true,
83 result,
84 });
85 }
86 Ok(Value::Undefined)
87}
88
89pub fn generator_method(key: &str) -> Value {
93 match key {
94 "next" => nv("Generator.next", gen_next),
95 "return" => nv("Generator.return", gen_return),
96 "throw" => nv("Generator.throw", gen_throw),
97 "map" => nv("Iterator.map", iter_help_map),
103 "filter" => nv("Iterator.filter", iter_help_filter),
104 "take" => nv("Iterator.take", iter_help_take),
105 "drop" => nv("Iterator.drop", iter_help_drop),
106 "flatMap" => nv("Iterator.flatMap", iter_help_flat_map),
107 "toArray" => nv("Iterator.toArray", iter_help_to_array),
108 "forEach" => nv("Iterator.forEach", iter_help_for_each),
109 "some" => nv("Iterator.some", iter_help_some),
110 "every" => nv("Iterator.every", iter_help_every),
111 "find" => nv("Iterator.find", iter_help_find),
112 "reduce" => nv("Iterator.reduce", iter_help_reduce),
113 _ => Value::Undefined,
114 }
115}
116
117pub(crate) fn iter_help_drain(it: &mut Interp, this: &Value) -> Vec<Value> {
118 it.iter_to_vec(this)
119}
120
121pub(crate) fn attach_iterator_helpers(obj: &super::super::value::ObjRef) {
134 let mut b = obj.borrow_mut();
135 b.props.insert("map".into(), nv("Iterator.map", iter_help_map));
136 b.props.insert("filter".into(), nv("Iterator.filter", iter_help_filter));
137 b.props.insert("take".into(), nv("Iterator.take", iter_help_take));
138 b.props.insert("drop".into(), nv("Iterator.drop", iter_help_drop));
139 b.props.insert("flatMap".into(), nv("Iterator.flatMap", iter_help_flat_map));
140 b.props.insert("toArray".into(), nv("Iterator.toArray", iter_help_to_array));
141 b.props.insert("forEach".into(), nv("Iterator.forEach", iter_help_for_each));
142 b.props.insert("some".into(), nv("Iterator.some", iter_help_some));
143 b.props.insert("every".into(), nv("Iterator.every", iter_help_every));
144 b.props.insert("find".into(), nv("Iterator.find", iter_help_find));
145 b.props.insert("reduce".into(), nv("Iterator.reduce", iter_help_reduce));
146}
147
148pub(crate) fn iterator_from(it: &mut Interp, _t: Value, a: &[Value]) -> Result<Value, Value> {
149 let source = arg(a, 0);
150 let items = it.iter_to_vec(&source);
151 let obj = Obj::array(items);
152 attach_iterator_helpers(&obj);
153 Ok(Value::Object(obj))
154}
155
156pub(crate) fn iterator_range(_it: &mut Interp, _t: Value, a: &[Value]) -> Result<Value, Value> {
158 let start = arg(a, 0).to_number();
159 let end = arg(a, 1).to_number();
160 if start.is_nan() || end.is_nan() {
161 return Err(Value::str("RangeError: start and end must be numbers"));
162 }
163 let step = if a.len() > 2 && !matches!(a[2], Value::Undefined) {
164 a[2].to_number()
165 } else if start <= end {
166 1.0
167 } else {
168 -1.0
169 };
170 if step == 0.0 || step.is_nan() {
171 return Err(Value::str("RangeError: step cannot be zero or NaN"));
172 }
173
174 let mut items = Vec::new();
175 let mut current = start;
176 if step > 0.0 {
177 while current < end {
178 items.push(Value::Number(current));
179 current += step;
180 }
181 } else {
182 while current > end {
183 items.push(Value::Number(current));
184 current += step;
185 }
186 }
187
188 let obj = Obj::array(items);
189 attach_iterator_helpers(&obj);
190 Ok(Value::Object(obj))
191}
192pub(crate) fn iter_help_map(it: &mut Interp, this: Value, a: &[Value]) -> Result<Value, Value> {
193 let cb = arg(a, 0);
194 let items = iter_help_drain(it, &this);
195 let mut out = Vec::with_capacity(items.len());
196 for (idx, v) in items.into_iter().enumerate() {
197 out.push(it.call_value(&cb, Value::Undefined, &[v, Value::Number(idx as f64)])?);
198 }
199 let obj = Obj::array(out);
200 attach_iterator_helpers(&obj);
201 Ok(Value::Object(obj))
202}
203pub(crate) fn iter_help_filter(it: &mut Interp, this: Value, a: &[Value]) -> Result<Value, Value> {
204 let cb = arg(a, 0);
205 let items = iter_help_drain(it, &this);
206 let mut out = Vec::new();
207 for (idx, v) in items.into_iter().enumerate() {
208 if it
209 .call_value(&cb, Value::Undefined, &[v.clone(), Value::Number(idx as f64)])?
210 .truthy()
211 {
212 out.push(v);
213 }
214 }
215 let obj = Obj::array(out);
216 attach_iterator_helpers(&obj);
217 Ok(Value::Object(obj))
218}
219pub(crate) fn iter_help_take(it: &mut Interp, this: Value, a: &[Value]) -> Result<Value, Value> {
220 let n = arg(a, 0).to_number().max(0.0) as usize;
221 let items = iter_help_drain(it, &this);
222 let obj = Obj::array(items.into_iter().take(n).collect());
223 attach_iterator_helpers(&obj);
224 Ok(Value::Object(obj))
225}
226pub(crate) fn iter_help_drop(it: &mut Interp, this: Value, a: &[Value]) -> Result<Value, Value> {
227 let n = arg(a, 0).to_number().max(0.0) as usize;
228 let items = iter_help_drain(it, &this);
229 let obj = Obj::array(items.into_iter().skip(n).collect());
230 attach_iterator_helpers(&obj);
231 Ok(Value::Object(obj))
232}
233pub(crate) fn iter_help_flat_map(it: &mut Interp, this: Value, a: &[Value]) -> Result<Value, Value> {
234 let cb = arg(a, 0);
235 let items = iter_help_drain(it, &this);
236 let mut out = Vec::new();
237 for (idx, v) in items.into_iter().enumerate() {
238 let mapped = it.call_value(&cb, Value::Undefined, &[v, Value::Number(idx as f64)])?;
239 out.extend(it.iter_to_vec(&mapped));
240 }
241 let obj = Obj::array(out);
242 attach_iterator_helpers(&obj);
243 Ok(Value::Object(obj))
244}
245pub(crate) fn iter_help_to_array(it: &mut Interp, this: Value, _a: &[Value]) -> Result<Value, Value> {
246 Ok(Value::Object(Obj::array(iter_help_drain(it, &this))))
247}
248pub(crate) fn iter_help_for_each(it: &mut Interp, this: Value, a: &[Value]) -> Result<Value, Value> {
249 let cb = arg(a, 0);
250 let items = iter_help_drain(it, &this);
251 for (idx, v) in items.into_iter().enumerate() {
252 it.call_value(&cb, Value::Undefined, &[v, Value::Number(idx as f64)])?;
253 }
254 Ok(Value::Undefined)
255}
256pub(crate) fn iter_help_some(it: &mut Interp, this: Value, a: &[Value]) -> Result<Value, Value> {
257 let cb = arg(a, 0);
258 let items = iter_help_drain(it, &this);
259 for (idx, v) in items.into_iter().enumerate() {
260 if it
261 .call_value(&cb, Value::Undefined, &[v, Value::Number(idx as f64)])?
262 .truthy()
263 {
264 return Ok(Value::Bool(true));
265 }
266 }
267 Ok(Value::Bool(false))
268}
269pub(crate) fn iter_help_every(it: &mut Interp, this: Value, a: &[Value]) -> Result<Value, Value> {
270 let cb = arg(a, 0);
271 let items = iter_help_drain(it, &this);
272 for (idx, v) in items.into_iter().enumerate() {
273 if !it
274 .call_value(&cb, Value::Undefined, &[v, Value::Number(idx as f64)])?
275 .truthy()
276 {
277 return Ok(Value::Bool(false));
278 }
279 }
280 Ok(Value::Bool(true))
281}
282pub(crate) fn iter_help_find(it: &mut Interp, this: Value, a: &[Value]) -> Result<Value, Value> {
283 let cb = arg(a, 0);
284 let items = iter_help_drain(it, &this);
285 for (idx, v) in items.into_iter().enumerate() {
286 if it
287 .call_value(&cb, Value::Undefined, &[v.clone(), Value::Number(idx as f64)])?
288 .truthy()
289 {
290 return Ok(v);
291 }
292 }
293 Ok(Value::Undefined)
294}
295pub(crate) fn iter_help_reduce(it: &mut Interp, this: Value, a: &[Value]) -> Result<Value, Value> {
296 let cb = arg(a, 0);
297 let items = iter_help_drain(it, &this);
298 let mut iter = items.into_iter().enumerate();
299 let mut acc = if a.len() > 1 {
300 arg(a, 1)
301 } else {
302 match iter.next() {
303 Some((_, v)) => v,
304 None => {
305 return Err(it.error(String::from("Reduce of empty iterator with no initial value")))
306 }
307 }
308 };
309 for (idx, v) in iter {
310 acc = it.call_value(&cb, Value::Undefined, &[acc, v, Value::Number(idx as f64)])?;
311 }
312 Ok(acc)
313}
314
315pub(crate) fn gen_state(this: &Value) -> Option<PromiseRc<PromiseRefCell<GenState>>> {
316 if let Value::Object(o) = this {
317 let o = unwrap_proxy_target(o);
318 let b = o.borrow();
319 if let ObjKind::Generator(g) = &b.kind {
320 return Some(g.clone());
321 }
322 }
323 None
324}
325
326pub(crate) fn iter_result(value: Value, done: bool) -> Value {
327 let res = Obj::plain();
328 res.borrow_mut().props.insert("value".into(), value);
329 res.borrow_mut()
330 .props
331 .insert("done".into(), Value::Bool(done));
332 Value::Object(res)
333}
334
335pub(crate) fn gen_next(i: &mut Interp, this: Value, a: &[Value]) -> Result<Value, Value> {
343 if let Some(g) = gen_state(&this) {
344 let is_async = g.borrow().func.is_async;
345 let sent = arg(a, 0);
346 let result = i.generator_resume(&g, sent);
347 if is_async {
348 return Ok(match result {
349 Ok((value, done)) => resolved_promise(i, iter_result(value, done)),
350 Err(e) => rejected_promise(i, e),
351 });
352 }
353 let (value, done) = result?;
354 return Ok(iter_result(value, done));
355 }
356 Ok(iter_result(Value::Undefined, true))
357}
358
359pub(crate) fn gen_self_iterator(_: &mut Interp, this: Value, _a: &[Value]) -> Result<Value, Value> {
366 Ok(this)
367}
368
369pub fn gen_self_iterator_fn() -> Value {
370 nv("Generator[Symbol.iterator]", gen_self_iterator)
371}
372
373pub(crate) fn gen_return(i: &mut Interp, this: Value, a: &[Value]) -> Result<Value, Value> {
374 let v = arg(a, 0);
375 if let Some(g) = gen_state(&this) {
376 let is_async = g.borrow().func.is_async;
377 let result = i.generator_return(&g, v.clone());
378 if is_async {
379 return Ok(match result {
380 Ok((value, done)) => resolved_promise(i, iter_result(value, done)),
381 Err(e) => rejected_promise(i, e),
382 });
383 }
384 let (value, done) = result?;
385 return Ok(iter_result(value, done));
386 }
387 Ok(iter_result(v, true))
388}
389pub(crate) fn gen_throw(i: &mut Interp, this: Value, a: &[Value]) -> Result<Value, Value> {
393 let err = arg(a, 0);
394 if let Some(g) = gen_state(&this) {
395 let (value, done) = i.generator_throw(&g, err)?;
396 return Ok(iter_result(value, done));
397 }
398 Err(err)
400}
401