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 }
282 }
283 }
284 Ok(target)
285}
286
287pub(crate) fn array_ctor(_: &mut Interp, _t: Value, a: &[Value]) -> Result<Value, Value> {
290 if a.len() == 1 {
292 if let Value::Number(n) = a[0] {
293 return Ok(Value::Object(Obj::array(vec![
294 Value::Undefined;
295 n as usize
296 ])));
297 }
298 }
299 Ok(Value::Object(Obj::array(a.to_vec())))
300}
301pub(crate) fn array_is_array(_: &mut Interp, _t: Value, a: &[Value]) -> Result<Value, Value> {
308 fn is_array_value(v: &Value) -> bool {
309 match v {
310 Value::Object(o) => {
311 let b = o.borrow();
312 match &b.kind {
313 ObjKind::Array(_) => !b.props.contains_key("_ta_kind"),
314 ObjKind::Proxy { target, .. } => {
315 let target = target.clone();
316 drop(b);
317 is_array_value(&Value::Object(target))
318 }
319 _ => false,
320 }
321 }
322 _ => false,
323 }
324 }
325 Ok(Value::Bool(is_array_value(&arg(a, 0))))
326}
327pub(crate) fn array_from(i: &mut Interp, _t: Value, a: &[Value]) -> Result<Value, Value> {
328 let src = arg(a, 0);
329 let mut items = match &src {
330 Value::Object(o) => {
331 let is_iterable = matches!(
338 &o.borrow().kind,
339 ObjKind::Array(_)
340 | ObjKind::SetObj(_)
341 | ObjKind::MapObj(_)
342 | ObjKind::Generator(_)
343 ) || matches!(&o.borrow().kind, ObjKind::Host(t) if t == "iterator");
344 if is_iterable {
345 i.iter_to_vec(&src)
346 } else {
347 let len = o
349 .borrow()
350 .props
351 .get("length")
352 .map(|v| v.to_number() as usize)
353 .unwrap_or(0);
354 (0..len)
355 .map(|idx| {
356 o.borrow()
357 .props
358 .get(&idx.to_string())
359 .cloned()
360 .unwrap_or(Value::Undefined)
361 })
362 .collect()
363 }
364 }
365 Value::Str(s) => s.chars().map(|c| Value::str(c.to_string())).collect(),
366 _ => Vec::new(),
367 };
368 let map_fn = arg(a, 1);
371 let this_arg = arg(a, 2);
372 if matches!(&map_fn, Value::Object(o) if o.borrow().is_callable()) {
373 let mut mapped = Vec::with_capacity(items.len());
374 for (idx, v) in items.into_iter().enumerate() {
375 let r = i.call_value(&map_fn, this_arg.clone(), &[v, Value::Number(idx as f64)])?;
376 mapped.push(r);
377 }
378 items = mapped;
379 }
380 Ok(Value::Object(Obj::array(items)))
381}
382
383pub(crate) fn array_from_async(it: &mut Interp, t: Value, a: &[Value]) -> Result<Value, Value> {
389 let inner = (|| -> Result<Value, Value> {
390 let items = it.iter_to_vec(&arg(a, 0));
391 let map_fn = arg(a, 1);
392 let has_map = matches!(&map_fn, Value::Object(o) if o.borrow().is_callable());
393 let this_arg = arg(a, 2);
394 let mut out = Vec::with_capacity(items.len());
395 for (idx, item) in items.into_iter().enumerate() {
396 let awaited = it.await_value(item)?;
397 let v = if has_map {
398 it.call_value(&map_fn, this_arg.clone(), &[awaited, Value::Number(idx as f64)])?
399 } else {
400 awaited
401 };
402 out.push(v);
403 }
404 Ok(Value::Object(Obj::array(out)))
405 })();
406 let _ = t;
407 match inner {
408 Ok(v) => Ok(resolved_promise(it, v)),
409 Err(e) => Ok(rejected_promise(it, e)),
410 }
411}
412
413pub(crate) fn string_ctor(_: &mut Interp, _t: Value, a: &[Value]) -> Result<Value, Value> {
416 Ok(Value::str(arg(a, 0).to_js_string()))
417}
418pub(crate) fn number_ctor(_: &mut Interp, _t: Value, a: &[Value]) -> Result<Value, Value> {
419 if a.is_empty() {
420 return Ok(Value::Number(0.0));
421 }
422 Ok(Value::Number(arg(a, 0).to_number()))
423}
424pub(crate) fn boolean_ctor(_: &mut Interp, _t: Value, a: &[Value]) -> Result<Value, Value> {
425 Ok(Value::Bool(arg(a, 0).truthy()))
426}
427