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}