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(_: &mut Interp, _t: Value, a: &[Value]) -> Result<Value, Value> {
142    if let Value::Object(o) = arg(a, 0) {
143        return Ok(match o.borrow().proto.clone() {
144            Some(p) => Value::Object(p),
145            None => Value::Null,
146        });
147    }
148    Ok(Value::Null)
149}
150
151/// Reflect.defineProperty(target, key, descriptor) → true(value のみ簡易対応)
152pub(crate) fn reflect_define_property(_: &mut Interp, _t: Value, a: &[Value]) -> Result<Value, Value> {
153    if let Value::Object(o) = arg(a, 0) {
154        let key = arg(a, 1).to_js_string();
155        if let Value::Object(desc) = arg(a, 2) {
156            if let Some(v) = desc.borrow().props.get("value") {
157                o.borrow_mut().props.insert(key, v.clone());
158                return Ok(Value::Bool(true));
159            }
160        }
161    }
162    Ok(Value::Bool(false))
163}
164
165/// Reflect.apply(target, thisArg, argsList)
166// `Reflect.apply`/`Reflect.construct` の `argumentsList` は仕様上
167// `CreateListFromArrayLike`(`length` + 添字プロパティを読む array-like 全般)を
168// 経由するべきだが、以前は `Array`/`Set`/`Map`/`Generator`/文字列以外を無条件で
169// 空 `Vec` にする純関数 `iterable_values` を使っており、`{0:'a',1:'b',length:2}`
170// のような素の array-like(実配列ではない)を渡すと引数が丸ごと消える静かな
171// 破壊バグだった。`array_like_items`(`length` + 添字読み取り)に差し替える。
172pub(crate) fn reflect_apply(i: &mut Interp, _t: Value, a: &[Value]) -> Result<Value, Value> {
173    let func = arg(a, 0);
174    let this = arg(a, 1);
175    let args_val = arg(a, 2);
176    let args = array_like_items(i, &args_val);
177    i.call_value(&func, this, &args)
178}
179
180/// Reflect.construct(target, argsList)
181pub(crate) fn reflect_construct(i: &mut Interp, _t: Value, a: &[Value]) -> Result<Value, Value> {
182    let func = arg(a, 0);
183    let args_val = arg(a, 1);
184    let args = array_like_items(i, &args_val);
185    i.construct_value(&func, &args)
186}
187
188/// `is_map` と key からメソッド Value を返す(interp の get_property から呼ばれる)。
189pub fn mapset_method(is_map: bool, key: &str) -> Value {
190    if is_map {
191        match key {
192            "set" => nv("Map.set", map_set),
193            "get" => nv("Map.get", map_get),
194            "has" => nv("Map.has", map_has),
195            "delete" => nv("Map.delete", map_delete),
196            "clear" => nv("Map.clear", map_clear),
197            "forEach" => nv("Map.forEach", map_for_each),
198            "keys" => nv("Map.keys", map_keys),
199            "values" => nv("Map.values", map_values),
200            "entries" => nv("Map.entries", map_entries),
201            // `Map.prototype[Symbol.iterator]` は仕様上 `entries` の別名(配列と同種の
202            // 見落とし。`for...of` は内部高速経路のため気づかれなかった)。
203            "Symbol(Symbol.iterator)" => nv("[Symbol.iterator]", map_entries),
204            _ => Value::Undefined,
205        }
206    } else {
207        match key {
208            "add" => nv("Set.add", set_add),
209            "has" => nv("Set.has", set_has),
210            "delete" => nv("Set.delete", set_delete),
211            "clear" => nv("Set.clear", set_clear),
212            "forEach" => nv("Set.forEach", set_for_each),
213            "values" => nv("Set.values", set_values),
214            "keys" => nv("Set.values", set_values),
215            // `Set.prototype[Symbol.iterator]` は仕様上 `values` の別名。
216            "Symbol(Symbol.iterator)" => nv("[Symbol.iterator]", set_values),
217            "union" => nv("Set.union", set_union),
218            "intersection" => nv("Set.intersection", set_intersection),
219            "difference" => nv("Set.difference", set_difference),
220            "symmetricDifference" => nv("Set.symmetricDifference", set_symmetric_difference),
221            "isSubsetOf" => nv("Set.isSubsetOf", set_is_subset_of),
222            "isSupersetOf" => nv("Set.isSupersetOf", set_is_superset_of),
223            "isDisjointFrom" => nv("Set.isDisjointFrom", set_is_disjoint_from),
224            _ => Value::Undefined,
225        }
226    }
227}
228
229// `Map`/`Set` の全メソッドが使うこの2つのヘルパも、`this_items`/`this_objref` と同じ
230// 理由(`Proxy` を素通しできない)で `new Proxy(new Map(...), {}).get(k)` 等が
231// 常に失敗するバグだった。
232pub(crate) fn with_map<R>(this: &Value, f: impl FnOnce(&mut Vec<(Value, Value)>) -> R) -> Option<R> {
233    if let Value::Object(o) = this {
234        let o = unwrap_proxy_target(o);
235        let mut b = o.borrow_mut();
236        if let ObjKind::MapObj(e) = &mut b.kind {
237            return Some(f(e));
238        }
239    }
240    None
241}
242pub(crate) fn with_set<R>(this: &Value, f: impl FnOnce(&mut Vec<Value>) -> R) -> Option<R> {
243    if let Value::Object(o) = this {
244        let o = unwrap_proxy_target(o);
245        let mut b = o.borrow_mut();
246        if let ObjKind::SetObj(s) = &mut b.kind {
247            return Some(f(s));
248        }
249    }
250    None
251}
252
253pub(crate) fn map_set(_: &mut Interp, this: Value, a: &[Value]) -> Result<Value, Value> {
254    let k = arg(a, 0);
255    let v = arg(a, 1);
256    with_map(&this, |e| {
257        if let Some(slot) = e.iter_mut().find(|(ek, _)| same_value_zero(ek, &k)) {
258            slot.1 = v.clone();
259        } else {
260            e.push((k.clone(), v.clone()));
261        }
262    });
263    Ok(this) // チェーン可能に this を返す。
264}
265pub(crate) fn map_get(_: &mut Interp, this: Value, a: &[Value]) -> Result<Value, Value> {
266    let k = arg(a, 0);
267    Ok(with_map(&this, |e| {
268        e.iter()
269            .find(|(ek, _)| same_value_zero(ek, &k))
270            .map(|(_, v)| v.clone())
271    })
272    .flatten()
273    .unwrap_or(Value::Undefined))
274}
275pub(crate) fn map_has(_: &mut Interp, this: Value, a: &[Value]) -> Result<Value, Value> {
276    let k = arg(a, 0);
277    Ok(Value::Bool(
278        with_map(&this, |e| e.iter().any(|(ek, _)| same_value_zero(ek, &k))).unwrap_or(false),
279    ))
280}
281pub(crate) fn map_delete(_: &mut Interp, this: Value, a: &[Value]) -> Result<Value, Value> {
282    let k = arg(a, 0);
283    Ok(Value::Bool(
284        with_map(&this, |e| {
285            let before = e.len();
286            e.retain(|(ek, _)| !same_value_zero(ek, &k));
287            e.len() != before
288        })
289        .unwrap_or(false),
290    ))
291}
292pub(crate) fn map_clear(_: &mut Interp, this: Value, _a: &[Value]) -> Result<Value, Value> {
293    with_map(&this, |e| e.clear());
294    Ok(Value::Undefined)
295}
296pub(crate) fn map_keys(_: &mut Interp, this: Value, _a: &[Value]) -> Result<Value, Value> {
297    Ok(Value::Object(make_iterator(
298        with_map(&this, |e| e.iter().map(|(k, _)| k.clone()).collect()).unwrap_or_default(),
299    )))
300}
301pub(crate) fn map_values(_: &mut Interp, this: Value, _a: &[Value]) -> Result<Value, Value> {
302    Ok(Value::Object(make_iterator(
303        with_map(&this, |e| e.iter().map(|(_, v)| v.clone()).collect()).unwrap_or_default(),
304    )))
305}
306pub(crate) fn map_entries(_: &mut Interp, this: Value, _a: &[Value]) -> Result<Value, Value> {
307    let entries = with_map(&this, |e| e.clone()).unwrap_or_default();
308    let arr: Vec<Value> = entries
309        .into_iter()
310        .map(|(k, v)| Value::Object(Obj::array(vec![k, v])))
311        .collect();
312    Ok(Value::Object(make_iterator(arr)))
313}
314/// `Map.prototype.forEach(callback, thisArg)`。以前は `thisArg`(第2引数)を無視して
315/// 常に `undefined` を `this` として呼んでいた(`Array.prototype.forEach` 等と同じ
316/// バグがこちらにもあった)。
317pub(crate) fn map_for_each(it: &mut Interp, this: Value, a: &[Value]) -> Result<Value, Value> {
318    let cb = arg(a, 0);
319    let this_arg = arg(a, 1);
320    let entries = with_map(&this, |e| e.clone()).unwrap_or_default();
321    for (k, v) in entries {
322        it.call_value(&cb, this_arg.clone(), &[v, k, this.clone()])?;
323    }
324    Ok(Value::Undefined)
325}
326
327pub(crate) fn set_add(_: &mut Interp, this: Value, a: &[Value]) -> Result<Value, Value> {
328    let v = arg(a, 0);
329    with_set(&this, |s| {
330        if !s.iter().any(|x| same_value_zero(x, &v)) {
331            s.push(v.clone());
332        }
333    });
334    Ok(this)
335}
336pub(crate) fn set_has(_: &mut Interp, this: Value, a: &[Value]) -> Result<Value, Value> {
337    let v = arg(a, 0);
338    Ok(Value::Bool(
339        with_set(&this, |s| s.iter().any(|x| same_value_zero(x, &v))).unwrap_or(false),
340    ))
341}
342pub(crate) fn set_delete(_: &mut Interp, this: Value, a: &[Value]) -> Result<Value, Value> {
343    let v = arg(a, 0);
344    Ok(Value::Bool(
345        with_set(&this, |s| {
346            let before = s.len();
347            s.retain(|x| !same_value_zero(x, &v));
348            s.len() != before
349        })
350        .unwrap_or(false),
351    ))
352}
353pub(crate) fn set_clear(_: &mut Interp, this: Value, _a: &[Value]) -> Result<Value, Value> {
354    with_set(&this, |s| s.clear());
355    Ok(Value::Undefined)
356}
357pub(crate) fn set_values(_: &mut Interp, this: Value, _a: &[Value]) -> Result<Value, Value> {
358    Ok(Value::Object(make_iterator(
359        with_set(&this, |s| s.clone()).unwrap_or_default(),
360    )))
361}
362/// `Set.prototype.forEach(callback, thisArg)`。`Map.prototype.forEach` と同じ
363/// `thisArg` 無視バグがこちらにもあった。
364pub(crate) fn set_for_each(it: &mut Interp, this: Value, a: &[Value]) -> Result<Value, Value> {
365    let cb = arg(a, 0);
366    let this_arg = arg(a, 1);
367    let items = with_set(&this, |s| s.clone()).unwrap_or_default();
368    for v in items {
369        it.call_value(&cb, this_arg.clone(), &[v.clone(), v, this.clone()])?;
370    }
371    Ok(Value::Undefined)
372}
373
374// ===== New Set Methods(ES2024/2025 Set 演算)=====
375// 仕様上は任意の「set-like」オブジェクト(has/size/keys を持つ)を第2引数に取れるが、
376// この処理系では実用上ほぼ全てのケースをカバーする「別の Set または任意のイテラブル」を
377// 対象とする簡略実装。要素の等価判定は既存の Set/Map と同じ `same_value_zero`。
378// ES2024 の Set 合成メソッド群(`union`/`intersection`/...)は第一引数に「任意の
379// set-like」(`Set` に限らず iterable 全般)を受け付けるべきだが、以前は `&mut Interp`
380// を持たない `iterable_values` にフォールバックしており、`this_items`/`iterable_values`
381// 系の横展開監査で既に修正済みの他の箇所と同型の「Generator を渡すと常に空扱いになる」
382// バグが残っていた(`it.iter_to_vec` を使う完全版に統一して解消)。
383pub(crate) fn other_set_items(it: &mut Interp, v: &Value) -> Vec<Value> {
384    if let Value::Object(o) = v {
385        if let ObjKind::SetObj(s) = &o.borrow().kind {
386            return s.clone();
387        }
388    }
389    it.iter_to_vec(v)
390}
391pub(crate) fn set_union(it: &mut Interp, this: Value, a: &[Value]) -> Result<Value, Value> {
392    let mut out = with_set(&this, |s| s.clone()).unwrap_or_default();
393    for v in other_set_items(it, &arg(a, 0)) {
394        if !out.iter().any(|x| same_value_zero(x, &v)) {
395            out.push(v);
396        }
397    }
398    Ok(Value::Object(Obj::set_obj(out)))
399}
400pub(crate) fn set_intersection(it: &mut Interp, this: Value, a: &[Value]) -> Result<Value, Value> {
401    let other = other_set_items(it, &arg(a, 0));
402    let mine = with_set(&this, |s| s.clone()).unwrap_or_default();
403    let out = mine
404        .into_iter()
405        .filter(|v| other.iter().any(|x| same_value_zero(x, v)))
406        .collect();
407    Ok(Value::Object(Obj::set_obj(out)))
408}
409pub(crate) fn set_difference(it: &mut Interp, this: Value, a: &[Value]) -> Result<Value, Value> {
410    let other = other_set_items(it, &arg(a, 0));
411    let mine = with_set(&this, |s| s.clone()).unwrap_or_default();
412    let out = mine
413        .into_iter()
414        .filter(|v| !other.iter().any(|x| same_value_zero(x, v)))
415        .collect();
416    Ok(Value::Object(Obj::set_obj(out)))
417}
418pub(crate) fn set_symmetric_difference(it: &mut Interp, this: Value, a: &[Value]) -> Result<Value, Value> {
419    let other = other_set_items(it, &arg(a, 0));
420    let mine = with_set(&this, |s| s.clone()).unwrap_or_default();
421    let mut out: Vec<Value> = mine
422        .iter()
423        .filter(|v| !other.iter().any(|x| same_value_zero(x, v)))
424        .cloned()
425        .collect();
426    for v in other {
427        if !mine.iter().any(|x| same_value_zero(x, &v)) {
428            out.push(v);
429        }
430    }
431    Ok(Value::Object(Obj::set_obj(out)))
432}
433pub(crate) fn set_is_subset_of(it: &mut Interp, this: Value, a: &[Value]) -> Result<Value, Value> {
434    let other = other_set_items(it, &arg(a, 0));
435    let mine = with_set(&this, |s| s.clone()).unwrap_or_default();
436    Ok(Value::Bool(
437        mine.iter().all(|v| other.iter().any(|x| same_value_zero(x, v))),
438    ))
439}
440pub(crate) fn set_is_superset_of(it: &mut Interp, this: Value, a: &[Value]) -> Result<Value, Value> {
441    let other = other_set_items(it, &arg(a, 0));
442    let mine = with_set(&this, |s| s.clone()).unwrap_or_default();
443    Ok(Value::Bool(
444        other.iter().all(|v| mine.iter().any(|x| same_value_zero(x, v))),
445    ))
446}
447pub(crate) fn set_is_disjoint_from(it: &mut Interp, this: Value, a: &[Value]) -> Result<Value, Value> {
448    let other = other_set_items(it, &arg(a, 0));
449    let mine = with_set(&this, |s| s.clone()).unwrap_or_default();
450    Ok(Value::Bool(
451        !mine.iter().any(|v| other.iter().any(|x| same_value_zero(x, v))),
452    ))
453}
454