1use super::*;
4
5pub(crate) fn arr_at(it: &mut Interp, t: Value, a: &[Value]) -> Result<Value, Value> {
7 let items = generic_array_items(it, &t);
8 let n = arg(a, 0).to_number() as i64;
9 let len = items.len() as i64;
10 let idx = if n < 0 { len + n } else { n };
11 if idx >= 0 && idx < len {
12 Ok(items[idx as usize].clone())
13 } else {
14 Ok(Value::Undefined)
15 }
16}
17pub(crate) fn arr_find_last(it: &mut Interp, t: Value, a: &[Value]) -> Result<Value, Value> {
18 let items = generic_array_items(it, &t);
19 let f = arg(a, 0);
20 let this_arg = arg(a, 1);
21 for i in (0..items.len()).rev() {
22 if it
23 .call_value(
24 &f,
25 this_arg.clone(),
26 &[items[i].clone(), Value::Number(i as f64), t.clone()],
27 )?
28 .truthy()
29 {
30 return Ok(items[i].clone());
31 }
32 }
33 Ok(Value::Undefined)
34}
35pub(crate) fn arr_find_last_index(it: &mut Interp, t: Value, a: &[Value]) -> Result<Value, Value> {
36 let items = generic_array_items(it, &t);
37 let f = arg(a, 0);
38 let this_arg = arg(a, 1);
39 for i in (0..items.len()).rev() {
40 if it
41 .call_value(
42 &f,
43 this_arg.clone(),
44 &[items[i].clone(), Value::Number(i as f64), t.clone()],
45 )?
46 .truthy()
47 {
48 return Ok(Value::Number(i as f64));
49 }
50 }
51 Ok(Value::Number(-1.0))
52}
53pub(crate) fn arr_flat_map(it: &mut Interp, t: Value, a: &[Value]) -> Result<Value, Value> {
54 let items = generic_array_items(it, &t);
55 let f = arg(a, 0);
56 let this_arg = arg(a, 1);
57 let mut out: Vec<Value> = Vec::new();
58 for (i, v) in items.iter().enumerate() {
59 let r = it.call_value(
60 &f,
61 this_arg.clone(),
62 &[v.clone(), Value::Number(i as f64), t.clone()],
63 )?;
64 let inner = if let Value::Object(o) = &r {
65 if let ObjKind::Array(items) = &o.borrow().kind {
66 Some(items.clone())
67 } else {
68 None
69 }
70 } else {
71 None
72 };
73 match inner {
74 Some(arr) => out.extend(arr),
75 None => out.push(r),
76 }
77 }
78 Ok(Value::Object(Obj::array(out)))
79}
80pub fn make_iterator(items: Vec<Value>) -> super::super::value::ObjRef {
88 let o = Obj::host("iterator");
89 o.borrow_mut().props.insert("_items".into(), Value::Object(Obj::array(items)));
90 o.borrow_mut().props.insert("_pos".into(), Value::Number(0.0));
91 o
92}
93pub fn iterator_next(_it: &mut Interp, this: Value, _a: &[Value]) -> Result<Value, Value> {
94 if let Value::Object(o) = &this {
95 let items = o.borrow().props.get("_items").cloned();
96 let pos = o
97 .borrow()
98 .props
99 .get("_pos")
100 .map(|v| v.to_number() as usize)
101 .unwrap_or(0);
102 if let Some(Value::Object(arr)) = items {
103 let item = if let ObjKind::Array(v) = &arr.borrow().kind {
104 v.get(pos).cloned()
105 } else {
106 None
107 };
108 if let Some(value) = item {
109 o.borrow_mut().props.insert("_pos".into(), Value::Number((pos + 1) as f64));
110 return Ok(iter_result(value, false));
111 }
112 }
113 }
114 Ok(iter_result(Value::Undefined, true))
115}
116pub fn iterator_self(_it: &mut Interp, this: Value, _a: &[Value]) -> Result<Value, Value> {
117 Ok(this)
118}
119pub(crate) fn iterator_remaining(this: &Value) -> Vec<Value> {
126 if let Value::Object(o) = this {
127 let items = o.borrow().props.get("_items").cloned();
128 let pos = o
129 .borrow()
130 .props
131 .get("_pos")
132 .map(|v| v.to_number() as usize)
133 .unwrap_or(0);
134 if let Some(Value::Object(arr)) = items {
135 let rest: Option<Vec<Value>> = if let ObjKind::Array(v) = &arr.borrow().kind {
136 Some(v.iter().skip(pos).cloned().collect())
137 } else {
138 None
139 };
140 if let Some(rest) = rest {
141 let len = if let ObjKind::Array(v) = &arr.borrow().kind { v.len() } else { pos };
142 o.borrow_mut().props.insert("_pos".into(), Value::Number(len as f64));
143 return rest;
144 }
145 }
146 }
147 Vec::new()
148}
149pub fn iterator_map(it: &mut Interp, this: Value, a: &[Value]) -> Result<Value, Value> {
151 let cb = arg(a, 0);
152 let items = iterator_remaining(&this);
153 let mut out = Vec::with_capacity(items.len());
154 for (i, v) in items.into_iter().enumerate() {
155 out.push(it.call_value(&cb, Value::Undefined, &[v, Value::Number(i as f64)])?);
156 }
157 Ok(Value::Object(make_iterator(out)))
158}
159pub fn iterator_filter(it: &mut Interp, this: Value, a: &[Value]) -> Result<Value, Value> {
161 let cb = arg(a, 0);
162 let items = iterator_remaining(&this);
163 let mut out = Vec::new();
164 for (i, v) in items.into_iter().enumerate() {
165 let keep = it.call_value(&cb, Value::Undefined, &[v.clone(), Value::Number(i as f64)])?;
166 if keep.truthy() {
167 out.push(v);
168 }
169 }
170 Ok(Value::Object(make_iterator(out)))
171}
172pub fn iterator_take(_it: &mut Interp, this: Value, a: &[Value]) -> Result<Value, Value> {
174 let n = arg(a, 0).to_number();
175 let n = if n.is_finite() && n > 0.0 { n as usize } else { 0 };
176 let items = iterator_remaining(&this);
177 Ok(Value::Object(make_iterator(items.into_iter().take(n).collect())))
178}
179pub fn iterator_drop(_it: &mut Interp, this: Value, a: &[Value]) -> Result<Value, Value> {
181 let n = arg(a, 0).to_number();
182 let n = if n.is_finite() && n > 0.0 { n as usize } else { 0 };
183 let items = iterator_remaining(&this);
184 Ok(Value::Object(make_iterator(items.into_iter().skip(n).collect())))
185}
186pub fn iterator_to_array(_it: &mut Interp, this: Value, _a: &[Value]) -> Result<Value, Value> {
188 Ok(Value::Object(Obj::array(iterator_remaining(&this))))
189}
190pub fn iterator_for_each(it: &mut Interp, this: Value, a: &[Value]) -> Result<Value, Value> {
192 let cb = arg(a, 0);
193 let items = iterator_remaining(&this);
194 for (i, v) in items.into_iter().enumerate() {
195 it.call_value(&cb, Value::Undefined, &[v, Value::Number(i as f64)])?;
196 }
197 Ok(Value::Undefined)
198}
199pub fn iterator_flat_map(it: &mut Interp, this: Value, a: &[Value]) -> Result<Value, Value> {
205 let cb = arg(a, 0);
206 let items = iterator_remaining(&this);
207 let mut out = Vec::new();
208 for (i, v) in items.into_iter().enumerate() {
209 let mapped = it.call_value(&cb, Value::Undefined, &[v, Value::Number(i as f64)])?;
210 out.extend(it.iter_to_vec(&mapped));
211 }
212 Ok(Value::Object(make_iterator(out)))
213}
214pub fn iterator_some(it: &mut Interp, this: Value, a: &[Value]) -> Result<Value, Value> {
219 let cb = arg(a, 0);
220 let items = iterator_remaining(&this);
221 for (i, v) in items.into_iter().enumerate() {
222 let r = it.call_value(&cb, Value::Undefined, &[v, Value::Number(i as f64)])?;
223 if r.truthy() {
224 return Ok(Value::Bool(true));
225 }
226 }
227 Ok(Value::Bool(false))
228}
229pub fn iterator_every(it: &mut Interp, this: Value, a: &[Value]) -> Result<Value, Value> {
230 let cb = arg(a, 0);
231 let items = iterator_remaining(&this);
232 for (i, v) in items.into_iter().enumerate() {
233 let r = it.call_value(&cb, Value::Undefined, &[v, Value::Number(i as f64)])?;
234 if !r.truthy() {
235 return Ok(Value::Bool(false));
236 }
237 }
238 Ok(Value::Bool(true))
239}
240pub fn iterator_find(it: &mut Interp, this: Value, a: &[Value]) -> Result<Value, Value> {
241 let cb = arg(a, 0);
242 let items = iterator_remaining(&this);
243 for (i, v) in items.into_iter().enumerate() {
244 let r = it.call_value(&cb, Value::Undefined, &[v.clone(), Value::Number(i as f64)])?;
245 if r.truthy() {
246 return Ok(v);
247 }
248 }
249 Ok(Value::Undefined)
250}
251pub fn iterator_reduce(it: &mut Interp, this: Value, a: &[Value]) -> Result<Value, Value> {
253 let cb = arg(a, 0);
254 let items = iterator_remaining(&this);
255 let mut iter = items.into_iter().enumerate();
256 let mut acc = if a.len() > 1 {
257 arg(a, 1)
258 } else {
259 match iter.next() {
260 Some((_, v)) => v,
261 None => return Err(it.error("Reduce of empty iterator with no initial value")),
262 }
263 };
264 for (i, v) in iter {
265 acc = it.call_value(&cb, Value::Undefined, &[acc, v, Value::Number(i as f64)])?;
266 }
267 Ok(acc)
268}
269pub(crate) fn arr_entries(it: &mut Interp, t: Value, _a: &[Value]) -> Result<Value, Value> {
270 let out: Vec<Value> = generic_array_items(it, &t)
271 .into_iter()
272 .enumerate()
273 .map(|(i, v)| Value::Object(Obj::array(alloc::vec![Value::Number(i as f64), v])))
274 .collect();
275 Ok(Value::Object(make_iterator(out)))
276}
277pub(crate) fn arr_keys(it: &mut Interp, t: Value, _a: &[Value]) -> Result<Value, Value> {
278 let n = generic_array_items(it, &t).len();
279 Ok(Value::Object(make_iterator(
280 (0..n).map(|i| Value::Number(i as f64)).collect(),
281 )))
282}
283pub(crate) fn arr_values(it: &mut Interp, t: Value, _a: &[Value]) -> Result<Value, Value> {
284 let items = generic_array_items(it, &t);
285 Ok(Value::Object(make_iterator(items)))
286}
287pub(crate) fn arr_reduce_right(it: &mut Interp, t: Value, a: &[Value]) -> Result<Value, Value> {
288 let items = generic_array_items(it, &t);
289 let f = arg(a, 0);
290 let (mut acc, start) = if a.len() > 1 {
291 (arg(a, 1), items.len())
292 } else if items.is_empty() {
293 return Err(it.error("Reduce of empty array with no initial value"));
294 } else {
295 (items[items.len() - 1].clone(), items.len() - 1)
296 };
297 for i in (0..start).rev() {
298 acc = it.call_value(
299 &f,
300 Value::Undefined,
301 &[acc, items[i].clone(), Value::Number(i as f64), t.clone()],
302 )?;
303 }
304 Ok(acc)
305}
306
307pub(crate) fn str_at(_it: &mut Interp, t: Value, a: &[Value]) -> Result<Value, Value> {
309 let chars: Vec<char> = this_str(&t).chars().collect();
310 let n = arg(a, 0).to_number() as i64;
311 let len = chars.len() as i64;
312 let idx = if n < 0 { len + n } else { n };
313 if idx >= 0 && idx < len {
314 Ok(Value::str(chars[idx as usize].to_string()))
315 } else {
316 Ok(Value::Undefined)
317 }
318}
319
320pub(crate) fn resolve_maybe_thenable(
328 it: &mut Interp,
329 item: &Value,
330) -> Option<PromiseRc<PromiseRefCell<PromiseState>>> {
331 if let Some(s) = this_promise_state(item) {
332 return Some(s);
333 }
334 let then_fn = if matches!(item, Value::Object(_)) {
339 it.get_property(item, "then").unwrap_or(Value::Undefined)
340 } else {
341 Value::Undefined
342 };
343 let has_then = matches!(&then_fn, Value::Object(f) if f.borrow().is_callable());
344 if has_then {
345 let s = new_pending();
346 it.promise_resolve(&s, item.clone());
347 Some(s)
348 } else {
349 None
350 }
351}
352pub(crate) fn promise_all_settled_static(it: &mut Interp, _t: Value, a: &[Value]) -> Result<Value, Value> {
353 let items = it.iter_to_vec(&arg(a, 0));
354 let result = new_pending();
355 it.run_microtasks();
356 let mut out: Vec<Value> = Vec::new();
357 for item in items {
358 let o = Obj::plain();
359 {
360 let mut b = o.borrow_mut();
361 match resolve_maybe_thenable(it, &item) {
362 Some(s) => {
363 let st = s.borrow();
364 match st.status {
365 PromiseStatus::Rejected => {
366 b.props.insert("status".into(), Value::str("rejected"));
367 b.props.insert("reason".into(), st.value.clone());
368 }
369 _ => {
370 b.props.insert("status".into(), Value::str("fulfilled"));
371 b.props.insert("value".into(), st.value.clone());
372 }
373 }
374 }
375 None => {
376 b.props.insert("status".into(), Value::str("fulfilled"));
377 b.props.insert("value".into(), item.clone());
378 }
379 }
380 }
381 out.push(Value::Object(o));
382 }
383 it.promise_resolve(&result, Value::Object(Obj::array(out)));
384 Ok(Value::Object(Obj::promise(result)))
385}
386pub(crate) fn promise_race_static(it: &mut Interp, _t: Value, a: &[Value]) -> Result<Value, Value> {
387 let items = it.iter_to_vec(&arg(a, 0));
388 let result = new_pending();
389 it.run_microtasks();
390 for item in items {
391 match resolve_maybe_thenable(it, &item) {
392 Some(s) => {
393 let (status, val) = {
394 let b = s.borrow();
395 (b.status, b.value.clone())
396 };
397 match status {
398 PromiseStatus::Fulfilled => {
399 it.promise_resolve(&result, val);
400 return Ok(Value::Object(Obj::promise(result)));
401 }
402 PromiseStatus::Rejected => {
403 it.promise_reject(&result, val);
404 return Ok(Value::Object(Obj::promise(result)));
405 }
406 PromiseStatus::Pending => {}
407 }
408 }
409 None => {
410 it.promise_resolve(&result, item.clone());
411 return Ok(Value::Object(Obj::promise(result)));
412 }
413 }
414 }
415 Ok(Value::Object(Obj::promise(result)))
416}
417pub(crate) fn promise_any_static(it: &mut Interp, _t: Value, a: &[Value]) -> Result<Value, Value> {
422 let items = it.iter_to_vec(&arg(a, 0));
423 let result = new_pending();
424 it.run_microtasks();
425 let mut reasons: Vec<Value> = Vec::new();
426 for item in items {
427 match resolve_maybe_thenable(it, &item) {
428 Some(s) => {
429 let (status, val) = {
430 let b = s.borrow();
431 (b.status, b.value.clone())
432 };
433 match status {
434 PromiseStatus::Fulfilled => {
435 it.promise_resolve(&result, val);
436 return Ok(Value::Object(Obj::promise(result)));
437 }
438 PromiseStatus::Rejected => {
439 reasons.push(val);
440 }
441 PromiseStatus::Pending => {}
442 }
443 }
444 None => {
445 it.promise_resolve(&result, item.clone());
446 return Ok(Value::Object(Obj::promise(result)));
447 }
448 }
449 }
450 let agg = make_aggregate_error(it, reasons, "All promises were rejected");
451 it.promise_reject(&result, agg);
452 Ok(Value::Object(Obj::promise(result)))
453}
454
455pub fn iterator_concat_static(it: &mut Interp, _t: Value, a: &[Value]) -> Result<Value, Value> {
458 let mut combined = Vec::new();
459 for arg_val in a {
460 let items = it.iter_to_vec(arg_val);
461 combined.extend(items);
462 }
463 Ok(Value::Object(make_iterator(combined)))
464}
465
466pub fn iterator_from_static(it: &mut Interp, _t: Value, a: &[Value]) -> Result<Value, Value> {
469 let source = arg(a, 0);
470 let items = it.iter_to_vec(&source);
471 Ok(Value::Object(make_iterator(items)))
472}