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