1use super::*;
4
5pub(crate) fn object_ctor(_: &mut Interp, _t: Value, _a: &[Value]) -> Result<Value, Value> {
8 Ok(Value::Object(Obj::plain()))
9}
10pub(crate) fn unwrap_proxy_target(o: &super::super::value::ObjRef) -> super::super::value::ObjRef {
15 match &o.borrow().kind {
16 ObjKind::Proxy { target, .. } => unwrap_proxy_target(target),
17 _ => o.clone(),
18 }
19}
20pub fn accessor_only_keys(b: &super::super::value::Obj) -> Vec<String> {
23 b.accessors
24 .keys()
25 .filter(|k| !b.props.contains_key(*k))
26 .cloned()
27 .collect()
28}
29pub(crate) fn is_internal_host(kind: &ObjKind) -> bool {
36 matches!(kind, ObjKind::Host(_))
37}
38pub(crate) fn is_symbol_like_key(k: &str) -> bool {
48 k.starts_with("Symbol(") && k.ends_with(')')
49}
50fn array_index_key(k: &str) -> Option<u32> {
54 if k == "0" {
55 return Some(0);
56 }
57 if k.is_empty() || k.starts_with('0') || !k.bytes().all(|b| b.is_ascii_digit()) {
58 return None;
59 }
60 k.parse::<u32>().ok().filter(|&n| n != u32::MAX)
61}
62pub(crate) fn spec_key_order<T>(items: Vec<(String, T)>) -> Vec<(String, T)> {
68 let mut numeric: Vec<(u32, String, T)> = Vec::new();
69 let mut rest: Vec<(String, T)> = Vec::new();
70 for (k, v) in items {
71 match array_index_key(&k) {
72 Some(n) => numeric.push((n, k, v)),
73 None => rest.push((k, v)),
74 }
75 }
76 numeric.sort_by_key(|(n, _, _)| *n);
77 let mut out: Vec<(String, T)> = numeric.into_iter().map(|(_, k, v)| (k, v)).collect();
78 out.extend(rest);
79 out
80}
81pub(crate) fn object_keys(it: &mut Interp, _t: Value, a: &[Value]) -> Result<Value, Value> {
82 let mut keys = Vec::new();
83 if let Value::Object(o) = arg(a, 0) {
84 let o = unwrap_proxy_target(&o);
85 let b = o.borrow();
86 if let ObjKind::Array(items) = &b.kind {
87 for i in 0..items.len() {
88 keys.push(Value::str(i.to_string()));
89 }
90 } else if let Some(sk) = storage_host_keys(&b.kind) {
91 for k in sk {
92 keys.push(Value::str(k));
93 }
94 } else if let Some(sk) = dataset_host_keys(&b.kind, &it.dom.borrow()) {
95 for k in sk {
96 keys.push(Value::str(k));
97 }
98 } else if is_internal_host(&b.kind) {
99 } else {
101 let mut plain_keys: Vec<(String, ())> = Vec::new();
102 for k in b.props.keys().filter(|k| !is_symbol_like_key(k)) {
103 let attr = b.attrs.get(k).copied().unwrap_or_default();
104 if attr.enumerable {
105 plain_keys.push((k.clone(), ()));
106 }
107 }
108 for k in accessor_only_keys(&b) {
109 let attr = b.attrs.get(&k).copied().unwrap_or_default();
110 if attr.enumerable {
111 plain_keys.push((k, ()));
112 }
113 }
114 for (k, ()) in spec_key_order(plain_keys) {
115 keys.push(Value::str(k));
116 }
117 }
118 }
119 Ok(Value::Object(Obj::array(keys)))
120}
121pub(crate) fn object_values(it: &mut Interp, _t: Value, a: &[Value]) -> Result<Value, Value> {
122 let mut vals = Vec::new();
123 if let Value::Object(o) = arg(a, 0) {
124 let o = unwrap_proxy_target(&o);
125 let (is_array, prop_vals, getters) = {
126 let b = o.borrow();
127 if let ObjKind::Array(items) = &b.kind {
128 (true, items.clone(), Vec::new())
129 } else if let Some(sk) = storage_host_keys(&b.kind) {
130 let tag = if let ObjKind::Host(t) = &b.kind { t.clone() } else { String::new() };
131 let vals: Vec<Value> = sk
132 .iter()
133 .filter_map(|k| storage_map(&tag).lock().get(k).map(|v| Value::str(v.clone())))
134 .collect();
135 (true, vals, Vec::new())
136 } else if let Some(entries) = dataset_host_entries(&b.kind, &it.dom.borrow()) {
137 let vals: Vec<Value> = entries.into_iter().map(|(_, v)| Value::str(v)).collect();
138 (true, vals, Vec::new())
139 } else if is_internal_host(&b.kind) {
140 (false, Vec::new(), Vec::new())
141 } else {
142 let plain_vals: Vec<(String, Value)> = b
143 .props
144 .iter()
145 .filter(|(k, _)| {
146 if is_symbol_like_key(k) { return false; }
147 b.attrs.get(*k).copied().unwrap_or_default().enumerable
148 })
149 .map(|(k, v)| (k.clone(), v.clone()))
150 .collect();
151 let prop_vals: Vec<Value> =
152 spec_key_order(plain_vals).into_iter().map(|(_, v)| v).collect();
153 let getters: Vec<Value> = accessor_only_keys(&b)
154 .into_iter()
155 .filter(|k| b.attrs.get(k).copied().unwrap_or_default().enumerable)
156 .filter_map(|k| b.accessors.get(&k).and_then(|acc| acc.get.clone()))
157 .collect();
158 (false, prop_vals, getters)
159 }
160 };
161 vals = prop_vals;
162 if !is_array {
163 for g in getters {
165 vals.push(it.call_value(&g, Value::Object(o.clone()), &[]).unwrap_or(Value::Undefined));
166 }
167 }
168 }
169 Ok(Value::Object(Obj::array(vals)))
170}
171pub(crate) fn object_entries(it: &mut Interp, _t: Value, a: &[Value]) -> Result<Value, Value> {
172 let mut entries = Vec::new();
173 if let Value::Object(o) = arg(a, 0) {
174 let o = unwrap_proxy_target(&o);
175 let (prop_entries, getters) = {
176 let b = o.borrow();
177 if let Some(sk) = storage_host_keys(&b.kind) {
178 let tag = if let ObjKind::Host(t) = &b.kind { t.clone() } else { String::new() };
179 let entries: Vec<(String, Value)> = sk
180 .into_iter()
181 .filter_map(|k| {
182 storage_map(&tag).lock().get(&k).map(|v| (k, Value::str(v.clone())))
183 })
184 .collect();
185 (entries, Vec::new())
186 } else if let Some(ds) = dataset_host_entries(&b.kind, &it.dom.borrow()) {
187 let entries: Vec<(String, Value)> =
188 ds.into_iter().map(|(k, v)| (k, Value::str(v))).collect();
189 (entries, Vec::new())
190 } else if is_internal_host(&b.kind) {
191 (Vec::new(), Vec::new())
192 } else {
193 let plain_entries: Vec<(String, Value)> = b
194 .props
195 .iter()
196 .filter(|(k, _)| {
197 if is_symbol_like_key(k) { return false; }
198 b.attrs.get(*k).copied().unwrap_or_default().enumerable
199 })
200 .map(|(k, v)| (k.clone(), v.clone()))
201 .collect();
202 let prop_entries: Vec<(String, Value)> = spec_key_order(plain_entries);
203 let getters: Vec<(String, Value)> = accessor_only_keys(&b)
204 .into_iter()
205 .filter(|k| b.attrs.get(k).copied().unwrap_or_default().enumerable)
206 .filter_map(|k| b.accessors.get(&k).and_then(|acc| acc.get.clone()).map(|g| (k, g)))
207 .collect();
208 (prop_entries, getters)
209 }
210 };
211 for (k, v) in prop_entries {
212 entries.push(Value::Object(Obj::array(vec![Value::str(k), v])));
213 }
214 for (k, g) in getters {
215 let v = it.call_value(&g, Value::Object(o.clone()), &[]).unwrap_or(Value::Undefined);
216 entries.push(Value::Object(Obj::array(vec![Value::str(k), v])));
217 }
218 }
219 Ok(Value::Object(Obj::array(entries)))
220}
221pub(crate) fn own_enumerable_entries(it: &mut Interp, s: &super::super::value::ObjRef) -> Vec<(String, Value)> {
226 let s = unwrap_proxy_target(s);
227 let (prop_entries, getters) = {
228 let b = s.borrow();
229 if let ObjKind::Array(items) = &b.kind {
230 return items
231 .iter()
232 .enumerate()
233 .map(|(i, v)| (i.to_string(), v.clone()))
234 .collect();
235 }
236 if let Some(sk) = storage_host_keys(&b.kind) {
237 let tag = if let ObjKind::Host(t) = &b.kind { t.clone() } else { String::new() };
238 return sk
239 .into_iter()
240 .filter_map(|k| storage_map(&tag).lock().get(&k).map(|v| (k, Value::str(v.clone()))))
241 .collect();
242 }
243 if let Some(ds) = dataset_host_entries(&b.kind, &it.dom.borrow()) {
244 return ds.into_iter().map(|(k, v)| (k, Value::str(v))).collect();
245 }
246 if is_internal_host(&b.kind) {
247 return Vec::new();
248 }
249 let plain_entries: Vec<(String, Value)> = b
250 .props
251 .iter()
252 .filter(|(k, _)| {
253 if is_symbol_like_key(k) { return false; }
254 b.attrs.get(*k).copied().unwrap_or_default().enumerable
255 })
256 .map(|(k, v)| (k.clone(), v.clone()))
257 .collect();
258 let prop_entries: Vec<(String, Value)> = spec_key_order(plain_entries);
259 let getters: Vec<(String, Value)> = accessor_only_keys(&b)
260 .into_iter()
261 .filter(|k| b.attrs.get(k).copied().unwrap_or_default().enumerable)
262 .filter_map(|k| b.accessors.get(&k).and_then(|acc| acc.get.clone()).map(|g| (k, g)))
263 .collect();
264 (prop_entries, getters)
265 };
266 let mut out = prop_entries;
267 for (k, g) in getters {
268 let v = it.call_value(&g, Value::Object(s.clone()), &[]).unwrap_or(Value::Undefined);
269 out.push((k, v));
270 }
271 out
272}
273pub(crate) fn object_assign(it: &mut Interp, _t: Value, a: &[Value]) -> Result<Value, Value> {
274 let target = arg(a, 0);
275 if let Value::Object(t) = &target {
276 for src in &a[1.min(a.len())..] {
277 if let Value::Object(s) = src {
278 for (k, v) in own_enumerable_entries(it, s) {
279 t.borrow_mut().props.insert(k, v);
280 }
281 let sym: Vec<(String, Value)> = {
285 let src = unwrap_proxy_target(s);
286 let b = src.borrow();
287 b.props
288 .iter()
289 .filter(|(k, _)| is_symbol_like_key(k) && b.attrs.get(*k).copied().unwrap_or_default().enumerable)
290 .map(|(k, v)| (k.clone(), v.clone()))
291 .collect()
292 };
293 for (k, v) in sym {
294 t.borrow_mut().props.insert(k, v);
295 }
296 }
297 }
298 }
299 Ok(target)
300}
301
302pub(crate) fn array_ctor(_it: &mut Interp, t: Value, a: &[Value]) -> Result<Value, Value> {
305 let sized = a.len() == 1 && matches!(a[0], Value::Number(_));
307 let items = if a.len() == 1 {
308 if let Value::Number(n) = a[0] {
309 if n >= 0.0 && (n as u32 as f64) == n && n <= u32::MAX as f64 {
310 vec![Value::Undefined; n as usize]
311 } else {
312 return Err(Value::Str(alloc::rc::Rc::new(String::from("RangeError: Invalid array length"))));
313 }
314 } else {
315 a.to_vec()
316 }
317 } else {
318 a.to_vec()
319 };
320
321 if let Value::Object(ref o) = t {
322 let is_plain = matches!(o.borrow().kind, ObjKind::Plain);
323 if is_plain {
324 let len = items.len();
325 let mut b = o.borrow_mut();
326 b.kind = ObjKind::Array(items);
327 b.props.insert("length".into(), Value::Number(len as f64));
328 if sized {
329 b.holes = Some(alloc::boxed::Box::new(vec![true; len]));
330 }
331 drop(b);
332 return Ok(t);
333 }
334 }
335
336 let len = items.len();
337 let r = Obj::array(items);
338 if sized {
339 r.borrow_mut().holes = Some(alloc::boxed::Box::new(vec![true; len]));
340 }
341 Ok(Value::Object(r))
342}
343pub(crate) fn array_is_array(_: &mut Interp, _t: Value, a: &[Value]) -> Result<Value, Value> {
350 fn is_array_value(v: &Value) -> bool {
351 match v {
352 Value::Object(o) => {
353 let b = o.borrow();
354 match &b.kind {
355 ObjKind::Array(_) => !b.props.contains_key("_ta_kind"),
356 ObjKind::Proxy { target, .. } => {
357 let target = target.clone();
358 drop(b);
359 is_array_value(&Value::Object(target))
360 }
361 _ => false,
362 }
363 }
364 _ => false,
365 }
366 }
367 Ok(Value::Bool(is_array_value(&arg(a, 0))))
368}
369pub(crate) fn array_from(i: &mut Interp, _t: Value, a: &[Value]) -> Result<Value, Value> {
370 let src = arg(a, 0);
371 let mut items = match &src {
372 Value::Object(o) => {
373 let is_iterable = matches!(
380 &o.borrow().kind,
381 ObjKind::Array(_)
382 | ObjKind::Bytes(_)
383 | ObjKind::SetObj(_)
384 | ObjKind::MapObj(_)
385 | ObjKind::Generator(_)
386 ) || matches!(&o.borrow().kind, ObjKind::Host(t) if t == "iterator");
387 if is_iterable {
388 i.iter_to_vec(&src)
389 } else {
390 let len = o
392 .borrow()
393 .props
394 .get("length")
395 .map(|v| v.to_number() as usize)
396 .unwrap_or(0);
397 (0..len)
398 .map(|idx| {
399 o.borrow()
400 .props
401 .get(&idx.to_string())
402 .cloned()
403 .unwrap_or(Value::Undefined)
404 })
405 .collect()
406 }
407 }
408 Value::Str(s) => s.chars().map(|c| Value::str(c.to_string())).collect(),
409 _ => Vec::new(),
410 };
411 let map_fn = arg(a, 1);
414 let this_arg = arg(a, 2);
415 if matches!(&map_fn, Value::Object(o) if o.borrow().is_callable()) {
416 let mut mapped = Vec::with_capacity(items.len());
417 for (idx, v) in items.into_iter().enumerate() {
418 let r = i.call_value(&map_fn, this_arg.clone(), &[v, Value::Number(idx as f64)])?;
419 mapped.push(r);
420 }
421 items = mapped;
422 }
423 Ok(Value::Object(Obj::array(items)))
424}
425
426pub(crate) fn array_from_async(it: &mut Interp, t: Value, a: &[Value]) -> Result<Value, Value> {
432 let inner = (|| -> Result<Value, Value> {
433 let items = it.iter_to_vec(&arg(a, 0));
434 let map_fn = arg(a, 1);
435 let has_map = matches!(&map_fn, Value::Object(o) if o.borrow().is_callable());
436 let this_arg = arg(a, 2);
437 let mut out = Vec::with_capacity(items.len());
438 for (idx, item) in items.into_iter().enumerate() {
439 let awaited = it.await_value(item)?;
440 let v = if has_map {
441 it.call_value(&map_fn, this_arg.clone(), &[awaited, Value::Number(idx as f64)])?
442 } else {
443 awaited
444 };
445 out.push(v);
446 }
447 Ok(Value::Object(Obj::array(out)))
448 })();
449 let _ = t;
450 match inner {
451 Ok(v) => Ok(resolved_promise(it, v)),
452 Err(e) => Ok(rejected_promise(it, e)),
453 }
454}
455
456pub(crate) fn string_ctor(it: &mut Interp, _t: Value, a: &[Value]) -> Result<Value, Value> {
459 Ok(Value::str(it.to_string_value(arg(a, 0))?))
460}
461pub(crate) fn number_ctor(_: &mut Interp, _t: Value, a: &[Value]) -> Result<Value, Value> {
462 if a.is_empty() {
463 return Ok(Value::Number(0.0));
464 }
465 Ok(Value::Number(arg(a, 0).to_number()))
466}
467pub(crate) fn boolean_ctor(_: &mut Interp, _t: Value, a: &[Value]) -> Result<Value, Value> {
468 Ok(Value::Bool(arg(a, 0).truthy()))
469}
470