Skip to main content

atmos/os_lib/js/builtins/
collections.rs

1// 分割: builtins.rs より機械的に移動(2026-07-16 リファクタ フェーズ2)。
2// ロジック不変。可視性のみ pub(crate) へ昇格し、親が pub(crate) use で再エクスポート。
3use super::*;
4
5// ============ Map / Set ============
6
7/// Map/Set のキー等価(SameValueZero 近似: strict_eq + NaN===NaN)。
8pub(crate) fn same_value_zero(a: &Value, b: &Value) -> bool {
9    if let (Value::Number(x), Value::Number(y)) = (a, b) {
10        if x.is_nan() && y.is_nan() {
11            return true;
12        }
13    }
14    a.strict_eq(b)
15}
16
17/// `new Map(iterable)`。以前は各エントリを `key_at` で無条件に読み取っており、
18/// 要素が配列(ペア)でない場合(例: `new Map([1,2,3])`)でも例外を投げず
19/// `key_at` が黙って `undefined` を返すため `{undefined: undefined}` という
20/// 意味のない1エントリだけの `Map` が静かに作られてしまっていた。仕様どおり
21/// 各要素がオブジェクトでなければ `TypeError` を投げる(`Set` はペア要件が
22/// 無いため対象外)。
23pub(crate) fn map_ctor(it: &mut Interp, _t: Value, a: &[Value]) -> Result<Value, Value> {
24    let mut entries: Vec<(Value, Value)> = Vec::new();
25    // new Map([[k,v], ...])
26    if let Some(init) = a.first() {
27        for pair in it.iter_to_vec(init) {
28            if !matches!(pair, Value::Object(_)) {
29                return Err(it.error(alloc::format!(
30                    "Iterator value {} is not an entry object",
31                    pair.to_js_string()
32                )));
33            }
34            let k = key_at(&pair, 0);
35            let v = key_at(&pair, 1);
36            if !entries.iter().any(|(ek, _)| same_value_zero(ek, &k)) {
37                entries.push((k, v));
38            }
39        }
40    }
41    Ok(Value::Object(Obj::map_obj(entries)))
42}
43
44pub(crate) fn set_ctor(it: &mut Interp, _t: Value, a: &[Value]) -> Result<Value, Value> {
45    let mut items: Vec<Value> = Vec::new();
46    if let Some(init) = a.first() {
47        for v in it.iter_to_vec(init) {
48            if !items.iter().any(|x| same_value_zero(x, &v)) {
49                items.push(v);
50            }
51        }
52    }
53    Ok(Value::Object(Obj::set_obj(items)))
54}
55
56/// 配列要素 [i] を取り出す(Map 初期化のペア用)。
57pub(crate) fn key_at(v: &Value, i: usize) -> Value {
58    if let Value::Object(o) = v {
59        if let ObjKind::Array(items) = &o.borrow().kind {
60            return items.get(i).cloned().unwrap_or(Value::Undefined);
61        }
62    }
63    Value::Undefined
64}
65
66// ============ Proxy / Reflect ============
67
68/// `new Proxy(target, handler)`。両者ともオブジェクトが必要。
69pub(crate) fn proxy_ctor(i: &mut Interp, _t: Value, a: &[Value]) -> Result<Value, Value> {
70    let target = match arg(a, 0) {
71        Value::Object(o) => o,
72        _ => return Err(i.error("Cannot create proxy with a non-object as target")),
73    };
74    let handler = match arg(a, 1) {
75        Value::Object(o) => o,
76        _ => return Err(i.error("Cannot create proxy with a non-object as handler")),
77    };
78    Ok(Value::Object(Obj::proxy(target, handler)))
79}
80
81/// Reflect.get(target, key[, receiver])
82pub(crate) fn reflect_get(i: &mut Interp, _t: Value, a: &[Value]) -> Result<Value, Value> {
83    let target = arg(a, 0);
84    let key = arg(a, 1).to_js_string();
85    i.get_property(&target, &key)
86}
87
88/// Reflect.set(target, key, value[, receiver]) → 成否の bool。以前は常に `true` を
89/// 返しており、凍結済みオブジェクトへの書込みが `set_property()` 側で黙殺されていても
90/// 呼び出し元からは成功したように見えていた(`delete`/`Reflect.deleteProperty` が
91/// 失敗時に `false` を返すのと非対称だった)。
92pub(crate) fn reflect_set(i: &mut Interp, _t: Value, a: &[Value]) -> Result<Value, Value> {
93    let target = arg(a, 0);
94    let key = arg(a, 1).to_js_string();
95    let val = arg(a, 2);
96    let blocked = matches!(&target, Value::Object(o) if {
97        let b = o.borrow();
98        // 新規キー追加は sealed/non_extensible でも拒否される(set_property と同じ条件)。
99        (b.frozen) || ((b.sealed || b.non_extensible) && !b.props.contains_key(&key))
100    });
101    i.set_property(&target, &key, val);
102    Ok(Value::Bool(!blocked))
103}
104
105/// Reflect.has(target, key) → bool
106pub(crate) fn reflect_has(i: &mut Interp, _t: Value, a: &[Value]) -> Result<Value, Value> {
107    let target = arg(a, 0);
108    let key = arg(a, 1);
109    i.eval_binary(&super::super::ast::BinaryOp::In, key, target)
110}
111
112/// Reflect.deleteProperty(target, key) → bool。`delete target[key]` と同じ拒否条件
113/// (凍結/封印済みなら失敗)を適用する。以前は `frozen`/`sealed` を一切見ずに常に
114/// 削除・成功させていた(`delete` 演算子側で行った凍結オブジェクト保護と非対称だった)。
115pub(crate) fn reflect_delete_property(_: &mut Interp, _t: Value, a: &[Value]) -> Result<Value, Value> {
116    if let Value::Object(o) = arg(a, 0) {
117        if o.borrow().frozen || o.borrow().sealed {
118            return Ok(Value::Bool(false));
119        }
120        let key = arg(a, 1).to_js_string();
121        let mut b = o.borrow_mut();
122        if let Some(attr) = b.attrs.get(&key) {
123            if !attr.configurable {
124                return Ok(Value::Bool(false));
125            }
126        }
127        b.props.shift_remove(&key);
128        b.accessors.shift_remove(&key);
129        b.attrs.shift_remove(&key);
130        return Ok(Value::Bool(true));
131    }
132    Ok(Value::Bool(false))
133}
134
135/// Reflect.ownKeys(target) → string[]
136pub(crate) fn reflect_own_keys(i: &mut Interp, t: Value, a: &[Value]) -> Result<Value, Value> {
137    object_keys(i, t, a)
138}
139
140/// Reflect.getPrototypeOf(target) → proto | null
141pub(crate) fn reflect_get_prototype_of(it: &mut Interp, _t: Value, a: &[Value]) -> Result<Value, Value> {
142    if let Value::Object(o) = arg(a, 0) {
143        return Ok(super::extra_static::effective_proto(it, &o));
144    }
145    Ok(Value::Null)
146}
147
148/// Reflect.defineProperty(target, key, descriptor) → true(value のみ簡易対応)
149pub(crate) fn reflect_define_property(_: &mut Interp, _t: Value, a: &[Value]) -> Result<Value, Value> {
150    if let Value::Object(o) = arg(a, 0) {
151        let key = arg(a, 1).to_js_string();
152        if let Value::Object(desc) = arg(a, 2) {
153            if let Some(v) = desc.borrow().props.get("value") {
154                o.borrow_mut().props.insert(key, v.clone());
155                return Ok(Value::Bool(true));
156            }
157        }
158    }
159    Ok(Value::Bool(false))
160}
161
162/// Reflect.apply(target, thisArg, argsList)
163// `Reflect.apply`/`Reflect.construct` の `argumentsList` は仕様上
164// `CreateListFromArrayLike`(`length` + 添字プロパティを読む array-like 全般)を
165// 経由するべきだが、以前は `Array`/`Set`/`Map`/`Generator`/文字列以外を無条件で
166// 空 `Vec` にする純関数 `iterable_values` を使っており、`{0:'a',1:'b',length:2}`
167// のような素の array-like(実配列ではない)を渡すと引数が丸ごと消える静かな
168// 破壊バグだった。`array_like_items`(`length` + 添字読み取り)に差し替える。
169pub(crate) fn reflect_apply(i: &mut Interp, _t: Value, a: &[Value]) -> Result<Value, Value> {
170    let func = arg(a, 0);
171    let this = arg(a, 1);
172    let args_val = arg(a, 2);
173    let args = array_like_items(i, &args_val);
174    i.call_value(&func, this, &args)
175}
176
177/// Reflect.construct(target, argsList)
178pub(crate) fn reflect_construct(i: &mut Interp, _t: Value, a: &[Value]) -> Result<Value, Value> {
179    let func = arg(a, 0);
180    let args_val = arg(a, 1);
181    let args = array_like_items(i, &args_val);
182    // 第 3 引数 newTarget(省略時は target)。インスタンスの原型は newTarget.prototype。
183    let new_target = match a.get(2) {
184        Some(nt @ Value::Object(_)) => nt.clone(),
185        _ => func.clone(),
186    };
187    i.construct_with_target(&func, &args, &new_target)
188}
189
190/// `is_map` と key からメソッド Value を返す(interp の get_property から呼ばれる)。
191pub fn mapset_method(is_map: bool, key: &str) -> Value {
192    if is_map {
193        match key {
194            "set" => nv("Map.set", map_set),
195            "get" => nv("Map.get", map_get),
196            "has" => nv("Map.has", map_has),
197            "delete" => nv("Map.delete", map_delete),
198            "clear" => nv("Map.clear", map_clear),
199            "forEach" => nv("Map.forEach", map_for_each),
200            "keys" => nv("Map.keys", map_keys),
201            "values" => nv("Map.values", map_values),
202            "entries" => nv("Map.entries", map_entries),
203            // `Map.prototype[Symbol.iterator]` は仕様上 `entries` の別名(配列と同種の
204            // 見落とし。`for...of` は内部高速経路のため気づかれなかった)。
205            "Symbol(Symbol.iterator)" => nv("[Symbol.iterator]", map_entries),
206            _ => Value::Undefined,
207        }
208    } else {
209        match key {
210            "add" => nv("Set.add", set_add),
211            "has" => nv("Set.has", set_has),
212            "delete" => nv("Set.delete", set_delete),
213            "clear" => nv("Set.clear", set_clear),
214            "forEach" => nv("Set.forEach", set_for_each),
215            "values" => nv("Set.values", set_values),
216            "keys" => nv("Set.values", set_values),
217            // `Set.prototype[Symbol.iterator]` は仕様上 `values` の別名。
218            "Symbol(Symbol.iterator)" => nv("[Symbol.iterator]", set_values),
219            "union" => nv("Set.union", set_union),
220            "intersection" => nv("Set.intersection", set_intersection),
221            "difference" => nv("Set.difference", set_difference),
222            "symmetricDifference" => nv("Set.symmetricDifference", set_symmetric_difference),
223            "isSubsetOf" => nv("Set.isSubsetOf", set_is_subset_of),
224            "isSupersetOf" => nv("Set.isSupersetOf", set_is_superset_of),
225            "isDisjointFrom" => nv("Set.isDisjointFrom", set_is_disjoint_from),
226            _ => Value::Undefined,
227        }
228    }
229}
230
231// `Map`/`Set` の全メソッドが使うこの2つのヘルパも、`this_items`/`this_objref` と同じ
232// 理由(`Proxy` を素通しできない)で `new Proxy(new Map(...), {}).get(k)` 等が
233// 常に失敗するバグだった。
234pub(crate) fn with_map<R>(this: &Value, f: impl FnOnce(&mut Vec<(Value, Value)>) -> R) -> Option<R> {
235    if let Value::Object(o) = this {
236        let o = unwrap_proxy_target(o);
237        let mut b = o.borrow_mut();
238        if let ObjKind::MapObj(e) = &mut b.kind {
239            return Some(f(e));
240        }
241    }
242    None
243}
244pub(crate) fn with_set<R>(this: &Value, f: impl FnOnce(&mut Vec<Value>) -> R) -> Option<R> {
245    if let Value::Object(o) = this {
246        let o = unwrap_proxy_target(o);
247        let mut b = o.borrow_mut();
248        if let ObjKind::SetObj(s) = &mut b.kind {
249            return Some(f(s));
250        }
251    }
252    None
253}
254
255pub(crate) fn map_set(_: &mut Interp, this: Value, a: &[Value]) -> Result<Value, Value> {
256    let k = arg(a, 0);
257    let v = arg(a, 1);
258    with_map(&this, |e| {
259        if let Some(slot) = e.iter_mut().find(|(ek, _)| same_value_zero(ek, &k)) {
260            slot.1 = v.clone();
261        } else {
262            e.push((k.clone(), v.clone()));
263        }
264    });
265    Ok(this) // チェーン可能に this を返す。
266}
267pub(crate) fn map_get(_: &mut Interp, this: Value, a: &[Value]) -> Result<Value, Value> {
268    let k = arg(a, 0);
269    Ok(with_map(&this, |e| {
270        e.iter()
271            .find(|(ek, _)| same_value_zero(ek, &k))
272            .map(|(_, v)| v.clone())
273    })
274    .flatten()
275    .unwrap_or(Value::Undefined))
276}
277pub(crate) fn map_has(_: &mut Interp, this: Value, a: &[Value]) -> Result<Value, Value> {
278    let k = arg(a, 0);
279    Ok(Value::Bool(
280        with_map(&this, |e| e.iter().any(|(ek, _)| same_value_zero(ek, &k))).unwrap_or(false),
281    ))
282}
283pub(crate) fn map_delete(_: &mut Interp, this: Value, a: &[Value]) -> Result<Value, Value> {
284    let k = arg(a, 0);
285    Ok(Value::Bool(
286        with_map(&this, |e| {
287            let before = e.len();
288            e.retain(|(ek, _)| !same_value_zero(ek, &k));
289            e.len() != before
290        })
291        .unwrap_or(false),
292    ))
293}
294pub(crate) fn map_clear(_: &mut Interp, this: Value, _a: &[Value]) -> Result<Value, Value> {
295    with_map(&this, |e| e.clear());
296    Ok(Value::Undefined)
297}
298pub(crate) fn map_keys(_: &mut Interp, this: Value, _a: &[Value]) -> Result<Value, Value> {
299    Ok(Value::Object(make_iterator(
300        with_map(&this, |e| e.iter().map(|(k, _)| k.clone()).collect()).unwrap_or_default(),
301    )))
302}
303pub(crate) fn map_values(_: &mut Interp, this: Value, _a: &[Value]) -> Result<Value, Value> {
304    Ok(Value::Object(make_iterator(
305        with_map(&this, |e| e.iter().map(|(_, v)| v.clone()).collect()).unwrap_or_default(),
306    )))
307}
308pub(crate) fn map_entries(_: &mut Interp, this: Value, _a: &[Value]) -> Result<Value, Value> {
309    let entries = with_map(&this, |e| e.clone()).unwrap_or_default();
310    let arr: Vec<Value> = entries
311        .into_iter()
312        .map(|(k, v)| Value::Object(Obj::array(vec![k, v])))
313        .collect();
314    Ok(Value::Object(make_iterator(arr)))
315}
316/// `Map.prototype.forEach(callback, thisArg)`。以前は `thisArg`(第2引数)を無視して
317/// 常に `undefined` を `this` として呼んでいた(`Array.prototype.forEach` 等と同じ
318/// バグがこちらにもあった)。
319pub(crate) fn map_for_each(it: &mut Interp, this: Value, a: &[Value]) -> Result<Value, Value> {
320    let cb = arg(a, 0);
321    let this_arg = arg(a, 1);
322    let entries = with_map(&this, |e| e.clone()).unwrap_or_default();
323    for (k, v) in entries {
324        it.call_value(&cb, this_arg.clone(), &[v, k, this.clone()])?;
325    }
326    Ok(Value::Undefined)
327}
328
329pub(crate) fn set_add(_: &mut Interp, this: Value, a: &[Value]) -> Result<Value, Value> {
330    let v = arg(a, 0);
331    with_set(&this, |s| {
332        if !s.iter().any(|x| same_value_zero(x, &v)) {
333            s.push(v.clone());
334        }
335    });
336    Ok(this)
337}
338pub(crate) fn set_has(_: &mut Interp, this: Value, a: &[Value]) -> Result<Value, Value> {
339    let v = arg(a, 0);
340    Ok(Value::Bool(
341        with_set(&this, |s| s.iter().any(|x| same_value_zero(x, &v))).unwrap_or(false),
342    ))
343}
344pub(crate) fn set_delete(_: &mut Interp, this: Value, a: &[Value]) -> Result<Value, Value> {
345    let v = arg(a, 0);
346    Ok(Value::Bool(
347        with_set(&this, |s| {
348            let before = s.len();
349            s.retain(|x| !same_value_zero(x, &v));
350            s.len() != before
351        })
352        .unwrap_or(false),
353    ))
354}
355pub(crate) fn set_clear(_: &mut Interp, this: Value, _a: &[Value]) -> Result<Value, Value> {
356    with_set(&this, |s| s.clear());
357    Ok(Value::Undefined)
358}
359pub(crate) fn set_values(_: &mut Interp, this: Value, _a: &[Value]) -> Result<Value, Value> {
360    Ok(Value::Object(make_iterator(
361        with_set(&this, |s| s.clone()).unwrap_or_default(),
362    )))
363}
364/// `Set.prototype.forEach(callback, thisArg)`。`Map.prototype.forEach` と同じ
365/// `thisArg` 無視バグがこちらにもあった。
366pub(crate) fn set_for_each(it: &mut Interp, this: Value, a: &[Value]) -> Result<Value, Value> {
367    let cb = arg(a, 0);
368    let this_arg = arg(a, 1);
369    let items = with_set(&this, |s| s.clone()).unwrap_or_default();
370    for v in items {
371        it.call_value(&cb, this_arg.clone(), &[v.clone(), v, this.clone()])?;
372    }
373    Ok(Value::Undefined)
374}
375
376// ===== New Set Methods(ES2024/2025 Set 演算)=====
377// 仕様上は任意の「set-like」オブジェクト(has/size/keys を持つ)を第2引数に取れるが、
378// この処理系では実用上ほぼ全てのケースをカバーする「別の Set または任意のイテラブル」を
379// 対象とする簡略実装。要素の等価判定は既存の Set/Map と同じ `same_value_zero`。
380// ES2024 の Set 合成メソッド群(`union`/`intersection`/...)は第一引数に「任意の
381// set-like」(`Set` に限らず iterable 全般)を受け付けるべきだが、以前は `&mut Interp`
382// を持たない `iterable_values` にフォールバックしており、`this_items`/`iterable_values`
383// 系の横展開監査で既に修正済みの他の箇所と同型の「Generator を渡すと常に空扱いになる」
384// バグが残っていた(`it.iter_to_vec` を使う完全版に統一して解消)。
385pub(crate) fn other_set_items(it: &mut Interp, v: &Value) -> Vec<Value> {
386    if let Value::Object(o) = v {
387        if let ObjKind::SetObj(s) = &o.borrow().kind {
388            return s.clone();
389        }
390    }
391    it.iter_to_vec(v)
392}
393pub(crate) fn set_union(it: &mut Interp, this: Value, a: &[Value]) -> Result<Value, Value> {
394    let mut out = with_set(&this, |s| s.clone()).unwrap_or_default();
395    for v in other_set_items(it, &arg(a, 0)) {
396        if !out.iter().any(|x| same_value_zero(x, &v)) {
397            out.push(v);
398        }
399    }
400    Ok(Value::Object(Obj::set_obj(out)))
401}
402pub(crate) fn set_intersection(it: &mut Interp, this: Value, a: &[Value]) -> Result<Value, Value> {
403    let other = other_set_items(it, &arg(a, 0));
404    let mine = with_set(&this, |s| s.clone()).unwrap_or_default();
405    let out = mine
406        .into_iter()
407        .filter(|v| other.iter().any(|x| same_value_zero(x, v)))
408        .collect();
409    Ok(Value::Object(Obj::set_obj(out)))
410}
411pub(crate) fn set_difference(it: &mut Interp, this: Value, a: &[Value]) -> Result<Value, Value> {
412    let other = other_set_items(it, &arg(a, 0));
413    let mine = with_set(&this, |s| s.clone()).unwrap_or_default();
414    let out = mine
415        .into_iter()
416        .filter(|v| !other.iter().any(|x| same_value_zero(x, v)))
417        .collect();
418    Ok(Value::Object(Obj::set_obj(out)))
419}
420pub(crate) fn set_symmetric_difference(it: &mut Interp, this: Value, a: &[Value]) -> Result<Value, Value> {
421    let other = other_set_items(it, &arg(a, 0));
422    let mine = with_set(&this, |s| s.clone()).unwrap_or_default();
423    let mut out: Vec<Value> = mine
424        .iter()
425        .filter(|v| !other.iter().any(|x| same_value_zero(x, v)))
426        .cloned()
427        .collect();
428    for v in other {
429        if !mine.iter().any(|x| same_value_zero(x, &v)) {
430            out.push(v);
431        }
432    }
433    Ok(Value::Object(Obj::set_obj(out)))
434}
435pub(crate) fn set_is_subset_of(it: &mut Interp, this: Value, a: &[Value]) -> Result<Value, Value> {
436    let other = other_set_items(it, &arg(a, 0));
437    let mine = with_set(&this, |s| s.clone()).unwrap_or_default();
438    Ok(Value::Bool(
439        mine.iter().all(|v| other.iter().any(|x| same_value_zero(x, v))),
440    ))
441}
442pub(crate) fn set_is_superset_of(it: &mut Interp, this: Value, a: &[Value]) -> Result<Value, Value> {
443    let other = other_set_items(it, &arg(a, 0));
444    let mine = with_set(&this, |s| s.clone()).unwrap_or_default();
445    Ok(Value::Bool(
446        other.iter().all(|v| mine.iter().any(|x| same_value_zero(x, v))),
447    ))
448}
449pub(crate) fn set_is_disjoint_from(it: &mut Interp, this: Value, a: &[Value]) -> Result<Value, Value> {
450    let other = other_set_items(it, &arg(a, 0));
451    let mine = with_set(&this, |s| s.clone()).unwrap_or_default();
452    Ok(Value::Bool(
453        !mine.iter().any(|v| other.iter().any(|x| same_value_zero(x, v))),
454    ))
455}
456