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