Skip to main content

atmos/os_lib/js/interp/
eval_expr.rs

1// 分割: interp.rs の `impl Interp` から機械的に移動(2026-07-16 リファクタ フェーズ5)。
2// ロジック不変。メソッド可視性のみ pub(crate) へ昇格(別モジュールの impl Interp
3// からの self 呼び出しのため)。impl ブロックは型 Interp に自動で結合する。
4use super::*;
5
6impl Interp {
7    pub fn eval(
8        &mut self,
9        expr: &Expression,
10        scope: &Rc<RefCell<Scope>>,
11        this: &Value,
12    ) -> EvalResult {
13        if self.tick() {
14            return Err(Value::Undefined);
15        }
16        match expr {
17            Expression::Number(n) => Ok(Value::Number(*n)),
18            Expression::BigIntLit(s) => match super::super::bigint::BigInt::parse_str(s) {
19                Some(b) => Ok(Value::bigint(b)),
20                None => Err(self.throw(format!("Invalid BigInt literal: {}", s))),
21            },
22            Expression::Str(s) => Ok(Value::str(s.clone())),
23            Expression::Bool(b) => Ok(Value::Bool(*b)),
24            Expression::Null => Ok(Value::Null),
25            Expression::Undefined => Ok(Value::Undefined),
26            Expression::This => Ok(this.clone()),
27            Expression::TemplateLiteral { quasis, exprs } => {
28                // quasis[i] の直後に exprs[i](あれば)を評価して文字列化し挟み込む。
29                // quasis は常に exprs より1つ多い(先頭と末尾は必ず quasi)。
30                let mut s = String::new();
31                for (i, q) in quasis.iter().enumerate() {
32                    s.push_str(q);
33                    if let Some(e) = exprs.get(i) {
34                        let v = self.eval(e, scope, this)?;
35                        s.push_str(&v.to_js_string());
36                    }
37                }
38                Ok(Value::str(s))
39            }
40            Expression::TaggedTemplate {
41                tag,
42                quasis,
43                raw,
44                exprs,
45            } => {
46                let (func, call_this, broke) = self.resolve_callee(tag, scope, this)?;
47                if broke {
48                    return Ok(Value::Undefined);
49                }
50                let strings = Obj::array(quasis.iter().map(|s| Value::str(s.clone())).collect());
51                let raw_arr = Obj::array(raw.iter().map(|s| Value::str(s.clone())).collect());
52                strings
53                    .borrow_mut()
54                    .props
55                    .insert(String::from("raw"), Value::Object(raw_arr));
56                let mut args = Vec::with_capacity(exprs.len() + 1);
57                args.push(Value::Object(strings));
58                for e in exprs {
59                    args.push(self.eval(e, scope, this)?);
60                }
61                self.call_value(&func, call_this, &args)
62            }
63            Expression::Identifier(name) => match scope_get(scope, name) {
64                Some(v) => Ok(v),
65                // 【2026-09-05】スコープに無ければ `window` のプロパティを見る。
66                //
67                // ブラウザでは `window.x = 1` の後に素の `x` で読める
68                // (グローバルオブジェクトのプロパティ=グローバル変数)。
69                // この処理系は `window` を普通のオブジェクトとして持ち、
70                // グローバル変数とは別管理なので、`window.$ = ...` が
71                // 素の `$` から見えなかった。
72                //
73                // jQuery 1.8.2 は最後に `a.jQuery = a.$ = p`(`a` は window)
74                // として自分を公開する。そのため **jQuery は完走するのに
75                // `$ is not defined`** になり、ページの JS が全滅していた。
76                None => {
77                    if let Some(Value::Object(w)) = scope_get(scope, "window") {
78                        let found = w.borrow().props.get(name).cloned();
79                        if let Some(v) = found {
80                            return Ok(v);
81                        }
82                    }
83                    Err(self.throw(format!("{} is not defined", name)))
84                }
85            },
86            Expression::Array(items) => {
87                let mut vals = Vec::with_capacity(items.len());
88                for it in items {
89                    if let Expression::Spread(inner) = it {
90                        let v = self.eval(inner, scope, this)?;
91                        let items = self.iter_to_vec(&v);
92                        vals.extend(items);
93                    } else {
94                        vals.push(self.eval(it, scope, this)?);
95                    }
96                }
97                Ok(Value::Object(Obj::array(vals)))
98            }
99            Expression::Object(props) => {
100                let o = Obj::plain();
101                for p in props {
102                    if p.key == OBJECT_SPREAD_KEY {
103                        // {...src}: src の自身プロパティ(配列なら数値インデックス)をコピー。
104                        let src = self.eval(&p.value, scope, this)?;
105                        if let Value::Object(so) = &src {
106                            let (kind_is_array, items, prop_entries, getters) = {
107                                let b = so.borrow();
108                                match &b.kind {
109                                    ObjKind::Array(items) => {
110                                        (true, items.clone(), Vec::new(), Vec::new())
111                                    }
112                                    // `Host`(DOM プロキシ/`make_iterator()` 等の内部実装専用
113                                    // 種別)は列挙可能な own プロパティを持たない。
114                                    ObjKind::Host(_) => (false, Vec::new(), Vec::new(), Vec::new()),
115                                    _ => {
116                                        let plain_entries: Vec<(String, Value)> = b
117                                            .props
118                                            .iter()
119                                            .filter(|(k, _)| {
120                                                if super::super::builtins::is_symbol_like_key(k) { return false; }
121                                                b.attrs.get(*k).copied().unwrap_or_default().enumerable
122                                            })
123                                            .map(|(k, v)| (k.clone(), v.clone()))
124                                            .collect();
125                                        let prop_entries: Vec<(String, Value)> =
126                                            super::super::builtins::spec_key_order(plain_entries);
127                                        // accessors(getter/setter 限定プロパティ)専用マップも
128                                        // 見ておらず `{...{get x(){return 1;}}}` が `x` を
129                                        // 一切コピーしないバグだった(`in`/`Object.keys`/
130                                        // `JSON.stringify` 等と同種)。spread はディスクリプタ
131                                        // ではなく getter の呼出結果を通常の値プロパティとして
132                                        // コピーする(仕様どおり)。
133                                        let getters: Vec<(String, Value)> =
134                                            super::super::builtins::accessor_only_keys(&b)
135                                                .into_iter()
136                                                .filter(|k| b.attrs.get(k).copied().unwrap_or_default().enumerable)
137                                                .filter_map(|k| {
138                                                    b.accessors
139                                                        .get(&k)
140                                                        .and_then(|acc| acc.get.clone())
141                                                        .map(|g| (k, g))
142                                                })
143                                                .collect();
144                                        (false, Vec::new(), prop_entries, getters)
145                                    }
146                                }
147                            };
148                            if kind_is_array {
149                                for (i, v) in items.iter().enumerate() {
150                                    o.borrow_mut().props.insert(format!("{}", i), v.clone());
151                                }
152                            } else {
153                                for (k, v) in prop_entries {
154                                    o.borrow_mut().props.insert(k, v);
155                                }
156                                for (k, g) in getters {
157                                    let v = self.call_value(&g, src.clone(), &[])?;
158                                    o.borrow_mut().props.insert(k, v);
159                                }
160                            }
161                        }
162                        continue;
163                    }
164                    let key = if let Some(ce) = &p.computed {
165                        to_property_key(&self.eval(ce, scope, this)?)
166                    } else {
167                        p.key.clone()
168                    };
169                    // `{get x(){...}}`/`{set x(v){...}}`: 通常の props ではなく accessors へ
170                    // 登録する。同一キーに get/set 両方が別々の Property として現れる場合は
171                    // マージする(`{get x(){...}, set x(v){...}}`)。
172                    if let Some(is_getter) = p.accessor {
173                        let f = self.eval(&p.value, scope, this)?;
174                        let mut b = o.borrow_mut();
175                        let entry = b
176                            .accessors
177                            .entry(key)
178                            .or_insert(Accessor { get: None, set: None });
179                        if is_getter {
180                            entry.get = Some(f);
181                        } else {
182                            entry.set = Some(f);
183                        }
184                        continue;
185                    }
186                    let v = self.eval(&p.value, scope, this)?;
187                    // `{ __proto__: proto }`(算出キーでない場合。Annex B.3.1)は通常の own
188                    // プロパティではなくオブジェクトの [[Prototype]] を設定する特別な構文。
189                    // 以前は単なる `"__proto__"` という名前の普通のプロパティとして格納
190                    // されてしまい、`Object.keys`/`for-in` に無関係な `__proto__` キーが
191                    // 漏れ出す上、実際のプロトタイプ連鎖には一切反映されなかった。
192                    if p.computed.is_none() && key == "__proto__" {
193                        match v {
194                            Value::Object(proto) => o.borrow_mut().proto = Some(proto),
195                            Value::Null => o.borrow_mut().proto = None,
196                            _ => {}
197                        }
198                        continue;
199                    }
200                    // NamedEvaluation(ES2015): `{foo: function(){}}`/`{foo: () => {}}` の
201                    // ように無名関数式をプロパティ値にする場合も、変数宣言と同様キー名を
202                    // `.name` として継承する(`infer_function_name` は既に名前を持つ関数は
203                    // 上書きしないため、メソッド短縮記法 `{foo(){}}` 等は影響を受けない)。
204                    infer_function_name(&v, &key);
205                    o.borrow_mut().props.insert(key, v);
206                }
207                Ok(Value::Object(o))
208            }
209            Expression::Spread(inner) => self.eval(inner, scope, this),
210            Expression::Class {
211                name,
212                superclass,
213                members,
214            } => self.eval_class(name, superclass, members, scope, this),
215            Expression::Super => {
216                // 単独 super は基底プロトタイプを返す(通常は super.x / super() で使う)。
217                self.super_proto(scope)
218            }
219            Expression::NewTarget => {
220                Ok(self.new_target_stack.last().cloned().unwrap_or(Value::Undefined))
221            }
222            Expression::Sequence(items) => {
223                let mut last = Value::Undefined;
224                for item in items {
225                    last = self.eval(item, scope, this)?;
226                }
227                Ok(last)
228            }
229            Expression::Regex(pattern, flags) => {
230                let re = super::super::regex::Regex::new(pattern, flags);
231                Ok(Value::Object(Obj::regexp(super::super::regex::RegExpData {
232                    re,
233                    last_index: 0,
234                })))
235            }
236            Expression::Await(inner) => {
237                let v = self.eval(inner, scope, this)?;
238                self.await_value(v)
239            }
240            Expression::Yield { argument, delegate } => {
241                let v = match argument {
242                    Some(e) => self.eval(e, scope, this)?,
243                    None => Value::Undefined,
244                };
245                if *delegate {
246                    // yield* iterable: 各要素を順に yield する(個々が 1 yield 点)。
247                    // yield* 式自体の値は委譲先の return 値(配列等では undefined)。
248                    let items = self.iter_to_vec(&v);
249                    for item in items {
250                        self.do_yield(item)?;
251                    }
252                    Ok(Value::Undefined)
253                } else {
254                    self.do_yield(v)
255                }
256            }
257            Expression::Function {
258                name,
259                params,
260                body,
261                is_arrow,
262                is_async,
263                is_generator,
264            } => {
265                // 名前付き関数式(`(function f(){ ... f ... })()`)は仕様上、
266                // 自身の名前を関数本体からのみ参照可能な内側スコープへ束縛
267                // すべきだが、これが丸ごと未対応で、本体内から自身の名前を
268                // 参照すると(外側スコープに同名の変数が無い限り)
269                // ReferenceError になっていた(`var g = function(){...g...}`
270                // という外側の変数代入経由の回避策は動くが、無名関数の
271                // 自己再帰イディオム本来の書き方が使えなかった)。関数
272                // *宣言*(`Statement::FunctionDeclaration` の巻き上げ)は
273                // この特殊束縛の対象外(宣言の名前は仕様上ただの外側スコープ
274                // 変数)のため、`make_function` 自体は変更せずこの式評価
275                // 経路だけで包みスコープを作る。
276                if !*is_arrow {
277                    if let Some(n) = name {
278                        if !n.is_empty() {
279                            let wrapper = Scope::child(scope.clone());
280                            let f = self.make_function(
281                                Some(n.clone()),
282                                params.clone(),
283                                body.clone(),
284                                *is_arrow,
285                                *is_async,
286                                *is_generator,
287                                &wrapper,
288                                this,
289                            );
290                            scope_declare(&wrapper, n, f.clone());
291                            return Ok(f);
292                        }
293                    }
294                }
295                Ok(self.make_function(
296                    name.clone(),
297                    params.clone(),
298                    body.clone(),
299                    *is_arrow,
300                    *is_async,
301                    *is_generator,
302                    scope,
303                    this,
304                ))
305            }
306            Expression::Unary { op, expr } => self.eval_unary(op, expr, scope, this),
307            Expression::Update { op, prefix, target } => {
308                self.eval_update(op, *prefix, target, scope, this)
309            }
310            Expression::Binary { op, left, right } => {
311                // プライベートフィールドのブランドチェック `#x in obj`(ES2022)が
312                // 丸ごと未対応だった。レキサは `#x` を(`this.#x`/`class C { #x }` と
313                // 同様)そのまま識別子テキストの一部として読むため、左辺を素朴に
314                // 通常の変数参照として評価すると `#x is not defined` で必ず例外に
315                // なっていた。`in` 演算子の左辺が `#` で始まる識別子の場合は変数評価を
316                // 行わず、右辺オブジェクトが(プライベートフィールドが実体としては
317                // 通常の `#` 付きキー名の own プロパティとして格納されている前提で)
318                // そのキーを直接持つかどうかで判定する。
319                if matches!(op, BinaryOp::In) {
320                    if let Expression::Identifier(name) = &**left {
321                        if name.starts_with('#') {
322                            let robj = self.eval(right, scope, this)?;
323                            let present = matches!(&robj, Value::Object(o) if o.borrow().props.contains_key(name));
324                            return Ok(Value::Bool(present));
325                        }
326                    }
327                }
328                let l = self.eval(left, scope, this)?;
329                let r = self.eval(right, scope, this)?;
330                self.eval_binary(op, l, r)
331            }
332            Expression::Logical { op, left, right } => {
333                let l = self.eval(left, scope, this)?;
334                match op {
335                    LogicalOp::And => {
336                        if l.truthy() {
337                            self.eval(right, scope, this)
338                        } else {
339                            Ok(l)
340                        }
341                    }
342                    LogicalOp::Or => {
343                        if l.truthy() {
344                            Ok(l)
345                        } else {
346                            self.eval(right, scope, this)
347                        }
348                    }
349                    LogicalOp::Nullish => match l {
350                        Value::Undefined | Value::Null => self.eval(right, scope, this),
351                        _ => Ok(l),
352                    },
353                }
354            }
355            Expression::Conditional {
356                test,
357                consequent,
358                alternate,
359            } => {
360                if self.eval(test, scope, this)?.truthy() {
361                    self.eval(consequent, scope, this)
362                } else {
363                    self.eval(alternate, scope, this)
364                }
365            }
366            Expression::Assign { op, target, value } => {
367                self.eval_assign(op, target, value, scope, this)
368            }
369            Expression::Member {
370                object,
371                property,
372                optional,
373            } => {
374                if matches!(**object, Expression::Super) {
375                    let sp = self.super_proto(scope)?;
376                    return self.get_property(&sp, property);
377                }
378                let (obj, broke) = self.eval_chain_object(object, scope, this)?;
379                if broke {
380                    return Ok(Value::Undefined);
381                }
382                if *optional && matches!(obj, Value::Undefined | Value::Null) {
383                    return Ok(Value::Undefined);
384                }
385                self.get_property(&obj, property)
386            }
387            Expression::Index { object, index, optional } => {
388                let (obj, broke) = self.eval_chain_object(object, scope, this)?;
389                if broke {
390                    return Ok(Value::Undefined);
391                }
392                if *optional && matches!(obj, Value::Undefined | Value::Null) {
393                    return Ok(Value::Undefined);
394                }
395                let key = self.eval(index, scope, this)?;
396                let key_str = to_property_key(&key);
397                self.get_property(&obj, &key_str)
398            }
399            Expression::Call {
400                callee,
401                arguments,
402                optional,
403            } => self.eval_call(callee, arguments, *optional, scope, this),
404            Expression::New { callee, arguments } => self.eval_new(callee, arguments, scope, this),
405        }
406    }
407
408    pub(crate) fn make_function(
409        &self,
410        name: Option<String>,
411        params: Vec<Param>,
412        body: Vec<Statement>,
413        is_arrow: bool,
414        is_async: bool,
415        is_generator: bool,
416        scope: &Rc<RefCell<Scope>>,
417        this: &Value,
418    ) -> Value {
419        let fd = FunctionData {
420            name: name.unwrap_or_default(),
421            params,
422            body: Rc::new(body),
423            closure: scope.clone(),
424            is_arrow,
425            is_async,
426            is_generator,
427            bound_this: if is_arrow {
428                Some(Box::new(this.clone()))
429            } else {
430                None
431            },
432        };
433        let func_obj = Obj::function(fd);
434        // 通常の関数(アロー関数を除く)は仕様どおり `.prototype`(`constructor` プロパティ
435        // 付き)を自動生成する。`new Foo()` はこれを起点にインスタンスの proto を設定する
436        // (`construct_object` 参照)ため、これが無いと `instanceof` が常に false になり、
437        // 従来型の `Foo.prototype.method = ...` によるメソッド共有パターンも機能しない。
438        // アロー関数は仕様上そもそも `new` できず `.prototype` を持たない。
439        if !is_arrow {
440            let proto = Obj::plain();
441            proto
442                .borrow_mut()
443                .props
444                .insert(String::from("constructor"), Value::Object(func_obj.clone()));
445            func_obj
446                .borrow_mut()
447                .props
448                .insert(String::from("prototype"), Value::Object(proto));
449        }
450        Value::Object(func_obj)
451    }
452
453    /// 分割代入パターンへ値を束縛する(var 宣言・引数・for-of 共通)。
454    pub(crate) fn bind_pattern(
455        &mut self,
456        pat: &Pattern,
457        value: Value,
458        scope: &Rc<RefCell<Scope>>,
459        this: &Value,
460    ) -> Result<(), Value> {
461        match pat {
462            Pattern::Identifier(name) => {
463                scope_declare(scope, name, value);
464                Ok(())
465            }
466            Pattern::Expr(target) => self.assign_to(target, value, scope, this),
467            Pattern::Object(props) => {
468                let mut consumed: Vec<String> = Vec::new();
469                for p in props {
470                    if p.is_rest {
471                        // rest: 未消費の自身プロパティを新オブジェクトへ集める。
472                        let rest = Obj::plain();
473                        if let Value::Object(o) = &value {
474                            let (kind_is_array, items, prop_entries, getters) = {
475                                let b = o.borrow();
476                                match &b.kind {
477                                    ObjKind::Array(items) => {
478                                        (true, items.clone(), Vec::new(), Vec::new())
479                                    }
480                                    ObjKind::Host(_) => (false, Vec::new(), Vec::new(), Vec::new()),
481                                    _ => {
482                                        let prop_entries: Vec<(String, Value)> = b
483                                            .props
484                                            .iter()
485                                            .map(|(k, v)| (k.clone(), v.clone()))
486                                            .collect();
487                                        // オブジェクトスプレッドと同じ accessors 見落とし
488                                        // バグが分割代入の rest(`const {a, ...rest} = o`)
489                                        // にもあった。
490                                        let getters: Vec<(String, Value)> =
491                                            super::super::builtins::accessor_only_keys(&b)
492                                                .into_iter()
493                                                .filter_map(|k| {
494                                                    b.accessors
495                                                        .get(&k)
496                                                        .and_then(|acc| acc.get.clone())
497                                                        .map(|g| (k, g))
498                                                })
499                                                .collect();
500                                        (false, Vec::new(), prop_entries, getters)
501                                    }
502                                }
503                            };
504                            if kind_is_array {
505                                for (i, v) in items.iter().enumerate() {
506                                    let k = format!("{}", i);
507                                    if !consumed.contains(&k) {
508                                        rest.borrow_mut().props.insert(k, v.clone());
509                                    }
510                                }
511                            } else {
512                                for (k, v) in prop_entries {
513                                    if !consumed.contains(&k) {
514                                        rest.borrow_mut().props.insert(k, v);
515                                    }
516                                }
517                                for (k, g) in getters {
518                                    if !consumed.contains(&k) {
519                                        let v = self.call_value(&g, value.clone(), &[])?;
520                                        rest.borrow_mut().props.insert(k, v);
521                                    }
522                                }
523                            }
524                        }
525                        self.bind_pattern(&p.value, Value::Object(rest), scope, this)?;
526                        continue;
527                    }
528                    // 算出プロパティ名 `{[expr]: target}`(以前は非対応でパーサ側が
529                    // 丸ごと落としていたバグの続き)。束縛時に評価してキーを得る。
530                    let key = match &p.computed_key {
531                        Some(ce) => to_property_key(&self.eval(ce, scope, this)?),
532                        None => p.key.clone(),
533                    };
534                    consumed.push(key.clone());
535                    let mut v = self.get_property(&value, &key)?;
536                    if matches!(v, Value::Undefined) {
537                        if let Some(def) = &p.default {
538                            v = self.eval(def, scope, this)?;
539                        }
540                    }
541                    self.bind_pattern(&p.value, v, scope, this)?;
542                }
543                Ok(())
544            }
545            Pattern::Array(elems) => {
546                let items = iterable_values(&value);
547                for (i, el) in elems.iter().enumerate() {
548                    if el.is_rest {
549                        let rest: Vec<Value> =
550                            items.get(i..).map(|s| s.to_vec()).unwrap_or_default();
551                        if let Some(p) = &el.pattern {
552                            self.bind_pattern(p, Value::Object(Obj::array(rest)), scope, this)?;
553                        }
554                        break;
555                    }
556                    let p = match &el.pattern {
557                        Some(p) => p,
558                        None => continue,
559                    }; // 穴
560                    let mut v = items.get(i).cloned().unwrap_or(Value::Undefined);
561                    if matches!(v, Value::Undefined) {
562                        if let Some(def) = &el.default {
563                            v = self.eval(def, scope, this)?;
564                        }
565                    }
566                    self.bind_pattern(p, v, scope, this)?;
567                }
568                Ok(())
569            }
570        }
571    }
572
573    /// `class` を評価し、コンストラクタ関数(prototype・静的メンバ・super 連携付き)を返す。
574    pub(crate) fn eval_class(
575        &mut self,
576        name: &Option<String>,
577        superclass: &Option<Box<Expression>>,
578        members: &[ClassMember],
579        scope: &Rc<RefCell<Scope>>,
580        this: &Value,
581    ) -> EvalResult {
582        let superclass_val = match superclass {
583            Some(e) => Some(self.eval(e, scope, this)?),
584            None => None,
585        };
586        // プロトタイプ(インスタンスメソッド置き場)。継承時は基底 prototype を proto に。
587        let proto = Obj::plain();
588        if let Some(sv) = &superclass_val {
589            if let Ok(Value::Object(sp)) = self.get_property(sv, "prototype") {
590                proto.borrow_mut().proto = Some(sp);
591            }
592        }
593        // メソッドの closure に __superclass__ / クラス名を持たせる。
594        let class_scope = Scope::child(scope.clone());
595        if let Some(sv) = &superclass_val {
596            scope_declare(&class_scope, "__superclass__", sv.clone());
597        }
598
599        // インスタンスフィールド宣言(`x = expr;` / `#x = expr;`)はメソッドではなく、
600        // コンストラクタ本体の先頭(super() 呼び出しがあればその直後)で
601        // `this.x = expr;` として実行する必要がある。ここでは初期化式だけ集めておき、
602        // 後でコンストラクタ(ユーザー定義 or デフォルト)の body に差し込む。
603        let mut ctor_params: Vec<Param> = Vec::new();
604        let mut ctor_body: Option<Vec<Statement>> = None;
605        let mut instance_field_inits: Vec<(String, Option<Expression>)> = Vec::new();
606        let mut statics: Vec<(String, Value)> = Vec::new();
607        // static な get/set アクセサ(key, is_getter, function)。コンストラクタ obj が
608        // 出来上がった後でその accessors へ登録する。
609        let mut static_accessors: Vec<(String, bool, Value)> = Vec::new();
610        // `static { ... }`(ES2022)。コンストラクタ obj が出来上がった後、それを `this` として
611        // 順番に実行する(フィールド初期化と同様、宣言順で実行するのが仕様)。
612        let mut static_blocks: Vec<Vec<Statement>> = Vec::new();
613        for m in members {
614            if m.kind == MethodKind::StaticBlock {
615                static_blocks.push(m.body.clone());
616                continue;
617            }
618            if m.kind == MethodKind::Field {
619                if m.is_static {
620                    // static フィールドはクラス定義時に一度だけ評価し、コンストラクタ
621                    // オブジェクト自身のプロパティにする(static メソッドと同じ扱い)。
622                    let v = match &m.field_init {
623                        Some(e) => self.eval(e, &class_scope, this)?,
624                        None => Value::Undefined,
625                    };
626                    statics.push((m.key.clone(), v));
627                } else {
628                    instance_field_inits.push((m.key.clone(), m.field_init.clone()));
629                }
630                continue;
631            }
632            if !m.is_static && m.kind == MethodKind::Constructor {
633                // コンストラクタは function 化を後段(フィールド初期化の差し込み後)に回す。
634                ctor_params = m.params.clone();
635                ctor_body = Some(m.body.clone());
636                continue;
637            }
638            // 算出メソッド名 `[expr](){}`(`[Symbol.iterator]` 等)はクラス定義時に評価する。
639            let key = match &m.computed_key {
640                Some(ce) => to_property_key(&self.eval(ce, &class_scope, this)?),
641                None => m.key.clone(),
642            };
643            if matches!(m.kind, MethodKind::Getter | MethodKind::Setter) {
644                let f = self.make_function(
645                    Some(key.clone()),
646                    m.params.clone(),
647                    m.body.clone(),
648                    false,
649                    false,
650                    false,
651                    &class_scope,
652                    this,
653                );
654                let is_getter = m.kind == MethodKind::Getter;
655                if m.is_static {
656                    static_accessors.push((key, is_getter, f));
657                } else {
658                    let mut b = proto.borrow_mut();
659                    let entry = b
660                        .accessors
661                        .entry(key)
662                        .or_insert(Accessor { get: None, set: None });
663                    if is_getter {
664                        entry.get = Some(f);
665                    } else {
666                        entry.set = Some(f);
667                    }
668                }
669                continue;
670            }
671            let f = self.make_function(
672                Some(key.clone()),
673                m.params.clone(),
674                m.body.clone(),
675                false,
676                m.is_async,
677                m.is_generator,
678                &class_scope,
679                this,
680            );
681            if m.is_static {
682                statics.push((key, f));
683            } else {
684                proto.borrow_mut().props.insert(key.clone(), f);
685                proto.borrow_mut().attrs.insert(
686                    key,
687                    super::super::value::PropertyAttributes {
688                        writable: true,
689                        configurable: true,
690                        enumerable: false,
691                    },
692                );
693            }
694        }
695
696        // インスタンスフィールド初期化文(`this.key = init;`)を組み立てる。
697        let field_stmts: Vec<Statement> = instance_field_inits
698            .into_iter()
699            .map(|(key, init)| {
700                Statement::Expression(Expression::Assign {
701                    op: String::from("="),
702                    target: Box::new(Expression::Member {
703                        object: Box::new(Expression::This),
704                        property: key,
705                        optional: false,
706                    }),
707                    value: Box::new(init.unwrap_or(Expression::Undefined)),
708                })
709            })
710            .collect();
711
712        // コンストラクタ本体を確定: ユーザー定義があればフィールド初期化を先頭に差し込み、
713        // 無ければデフォルト(継承時は super(...arguments) の後にフィールド初期化)。
714        let (final_params, final_body): (Vec<Param>, Vec<Statement>) = match ctor_body {
715            Some(user_body) => {
716                let mut body = field_stmts;
717                body.extend(user_body);
718                (ctor_params, body)
719            }
720            None => {
721                let mut body: Vec<Statement> = Vec::new();
722                if superclass_val.is_some() {
723                    body.push(Statement::Expression(Expression::Call {
724                        callee: Box::new(Expression::Super),
725                        arguments: alloc::vec![Expression::Spread(Box::new(
726                            Expression::Identifier(String::from("arguments"))
727                        ))],
728                        optional: false,
729                    }));
730                }
731                body.extend(field_stmts);
732                (Vec::new(), body)
733            }
734        };
735        let ctor = self.make_function(
736            name.clone(),
737            final_params,
738            final_body,
739            false,
740            false,
741            false,
742            &class_scope,
743            this,
744        );
745
746        if let Value::Object(co) = &ctor {
747            co.borrow_mut()
748                .props
749                .insert(String::from("prototype"), Value::Object(proto.clone()));
750            if let Some(sv) = &superclass_val {
751                co.borrow_mut()
752                    .props
753                    .insert(String::from("__superclass__"), sv.clone());
754                // 静的メソッドの継承: コンストラクタ obj の proto を基底コンストラクタに。
755                if let Value::Object(sc) = sv {
756                    co.borrow_mut().proto = Some(sc.clone());
757                }
758            }
759            for (k, v) in statics {
760                co.borrow_mut().props.insert(k, v);
761            }
762            for (k, is_getter, f) in static_accessors {
763                let mut b = co.borrow_mut();
764                let entry = b
765                    .accessors
766                    .entry(k)
767                    .or_insert(Accessor { get: None, set: None });
768                if is_getter {
769                    entry.get = Some(f);
770                } else {
771                    entry.set = Some(f);
772                }
773            }
774            proto
775                .borrow_mut()
776                .props
777                .insert(String::from("constructor"), ctor.clone());
778            proto.borrow_mut().attrs.insert(
779                String::from("constructor"),
780                super::super::value::PropertyAttributes {
781                    writable: true,
782                    configurable: true,
783                    enumerable: false,
784                },
785            );
786        }
787        // クラス名を class_scope に束縛(メソッド内から自身を参照可能に)。
788        // `static { ... }` ブロックの中からもクラス自身を参照できるよう、実行前に束縛する。
789        if let Some(n) = &name {
790            scope_declare(&class_scope, n, ctor.clone());
791        }
792        // `static { ... }` を宣言順に、`this` をコンストラクタ自身として実行する。
793        for block in static_blocks {
794            self.exec_statements(&block, &class_scope, &ctor)?;
795        }
796        Ok(ctor)
797    }
798
799    /// 現在のスコープから基底クラスのコンストラクタを取得。
800    pub(crate) fn super_ctor(&mut self, scope: &Rc<RefCell<Scope>>) -> EvalResult {
801        match scope_get(scope, "__superclass__") {
802            Some(v) => Ok(v),
803            None => Err(self.throw("'super' keyword unexpected here")),
804        }
805    }
806    /// 基底クラスの prototype を取得。
807    pub(crate) fn super_proto(&mut self, scope: &Rc<RefCell<Scope>>) -> EvalResult {
808        let sc = self.super_ctor(scope)?;
809        self.get_property(&sc, "prototype")
810    }
811
812    // ============ Promise / マイクロタスク ============
813
814}