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}