1use super::*;
5
6impl Interp {
7 pub(crate) fn tick(&mut self) -> bool {
9 self.steps += 1;
10 if self.steps > self.max_steps {
11 self.aborted = true;
12 return true;
13 }
14 false
15 }
16
17 pub fn error(&self, msg: impl Into<String>) -> Value {
19 self.throw(msg)
20 }
21
22 pub fn type_error(&self, msg: impl Into<String>) -> Value {
28 let err = self.throw(msg);
29 if let Value::Object(o) = &err {
30 let msg_str = o.borrow().props.get("message").map(|v| v.to_js_string()).unwrap_or_default();
31 o.borrow_mut().props.insert(
32 String::from("stack"),
33 Value::str(super::super::builtins::build_error_stack("TypeError", &msg_str)),
34 );
35 o.borrow_mut().props.insert(String::from("name"), Value::str("TypeError"));
36 if let Some(Value::Object(ctor)) = self.global.borrow().vars.get("TypeError") {
37 if let Some(Value::Object(proto)) = ctor.borrow().props.get("prototype") {
38 o.borrow_mut().proto = Some(proto.clone());
39 }
40 }
41 }
42 err
43 }
44
45 pub(crate) fn throw(&self, msg: impl Into<String>) -> Value {
46 let o = Obj::plain();
48 let msg: String = msg.into();
49 let mut stack_str = if msg.is_empty() {
58 String::from("Error")
59 } else {
60 alloc::format!("Error: {msg}")
61 };
62 for name in self.call_names.iter().rev().take(12) {
63 stack_str.push_str("\n at ");
64 stack_str.push_str(name);
65 }
66 o.borrow_mut().props.insert(String::from("stack"), Value::str(stack_str));
67 o.borrow_mut()
68 .props
69 .insert(String::from("message"), Value::str(msg));
70 o.borrow_mut()
71 .props
72 .insert(String::from("name"), Value::str("Error"));
73 if let Some(Value::Object(ctor)) = self.global.borrow().vars.get("Error") {
77 if let Some(Value::Object(proto)) = ctor.borrow().props.get("prototype") {
78 o.borrow_mut().proto = Some(proto.clone());
79 }
80 }
81 Value::Object(o)
82 }
83
84 pub(crate) fn eval_source(&mut self, source: &str) -> Result<Value, Value> {
90 let mut parser = Parser::new(Lexer::new(source));
91 let program = parser.parse_program();
92 let errors = parser.error_count();
96 if errors > 0 {
97 crate::warn!("[JS] eval(): {} syntax error(s) recovered", errors);
98 for e in parser.errors().iter().take(3) {
99 crate::warn!("[JS] eval() SyntaxError: {}", e.message);
100 }
101 }
102 let scope = self.global.clone();
103 match self.exec_statements(&program.body, &scope, &Value::Undefined) {
104 Ok(Completion::Normal(v)) | Ok(Completion::Return(v)) => Ok(v),
105 Ok(_) => Ok(Value::Undefined),
106 Err(thrown) => Err(thrown),
107 }
108 }
109
110 pub(crate) fn exec_statements(
111 &mut self,
112 stmts: &[Statement],
113 scope: &Rc<RefCell<Scope>>,
114 this: &Value,
115 ) -> Result<Completion, Value> {
116 for s in stmts {
118 let fdecl = match s {
119 Statement::FunctionDeclaration { .. } => Some(s),
120 Statement::ExportDecl { declaration, .. }
121 if matches!(**declaration, Statement::FunctionDeclaration { .. }) =>
122 {
123 Some(&**declaration)
124 }
125 _ => None,
126 };
127 if let Some(Statement::FunctionDeclaration {
128 name,
129 params,
130 body,
131 is_async,
132 is_generator,
133 }) = fdecl
134 {
135 let f = self.make_function(
136 Some(name.clone()),
137 params.clone(),
138 body.clone(),
139 false,
140 *is_async,
141 *is_generator,
142 scope,
143 this,
144 );
145 scope_declare(scope, name, f);
146 }
147 }
148 let mut disposables: Vec<(Value, bool)> = Vec::new();
155 let mut last = Value::Undefined;
156 let mut outcome: Result<Completion, Value> = Ok(Completion::Normal(Value::Undefined));
157 for s in stmts {
158 if let Statement::VarDeclaration { kind, decls } = s {
159 if matches!(kind, VarKind::Using | VarKind::AwaitUsing) {
160 let is_await = matches!(kind, VarKind::AwaitUsing);
161 let mut bind_err = None;
162 for (pat, init) in decls {
163 let v = match init {
164 Some(e) => match self.eval(e, scope, this) {
165 Ok(v) => v,
166 Err(e) => {
167 bind_err = Some(e);
168 break;
169 }
170 },
171 None => Value::Undefined,
172 };
173 if let Err(e) = self.bind_pattern(pat, v.clone(), scope, this) {
174 bind_err = Some(e);
175 break;
176 }
177 if !matches!(v, Value::Undefined | Value::Null) {
178 disposables.push((v, is_await));
179 }
180 }
181 if let Some(e) = bind_err {
182 outcome = Err(e);
183 break;
184 }
185 last = Value::Undefined;
186 continue;
187 }
188 }
189 match self.exec_stmt(s, scope, this) {
190 Ok(Completion::Normal(v)) => last = v,
191 Ok(other) => {
192 outcome = Ok(other);
193 break;
194 }
195 Err(e) => {
196 outcome = Err(e);
197 break;
198 }
199 }
200 }
201 if disposables.is_empty() {
202 return match outcome {
203 Ok(Completion::Normal(_)) => Ok(Completion::Normal(last)),
204 other => other,
205 };
206 }
207 let mut pending_err: Option<Value> = match &outcome {
212 Err(e) => Some(e.clone()),
213 _ => None,
214 };
215 for (resource, is_await) in disposables.into_iter().rev() {
216 let key = if is_await {
217 "Symbol(Symbol.asyncDispose)"
218 } else {
219 "Symbol(Symbol.dispose)"
220 };
221 let method = match self.get_property(&resource, key) {
222 Ok(m) => m,
223 Err(e) => {
224 pending_err = Some(self.chain_suppressed(pending_err, e));
225 continue;
226 }
227 };
228 if matches!(method, Value::Undefined | Value::Null) {
229 continue;
230 }
231 let call_result = self.call_value(&method, resource, &[]);
232 let dispose_result = match call_result {
233 Ok(v) if is_await => self.await_value(v),
234 other => other,
235 };
236 if let Err(e) = dispose_result {
237 pending_err = Some(self.chain_suppressed(pending_err, e));
238 }
239 }
240 if let Some(e) = pending_err {
241 return Err(e);
242 }
243 match outcome {
244 Ok(Completion::Normal(_)) => Ok(Completion::Normal(last)),
245 other => other,
246 }
247 }
248
249 pub(crate) fn exec_stmt(
250 &mut self,
251 stmt: &Statement,
252 scope: &Rc<RefCell<Scope>>,
253 this: &Value,
254 ) -> Result<Completion, Value> {
255 if self.tick() {
256 return Err(Value::Undefined);
257 }
258 match stmt {
259 Statement::Empty => Ok(Completion::Normal(Value::Undefined)),
260 Statement::Expression(e) => {
261 let v = self.eval(e, scope, this)?;
262 Ok(Completion::Normal(v))
263 }
264 Statement::VarDeclaration { decls, .. } => {
265 for (pat, init) in decls {
266 let v = match init {
267 Some(e) => self.eval(e, scope, this)?,
268 None => Value::Undefined,
269 };
270 if let Pattern::Identifier(name) = pat {
276 infer_function_name(&v, name);
277 }
278 self.bind_pattern(pat, v, scope, this)?;
279 }
280 Ok(Completion::Normal(Value::Undefined))
281 }
282 Statement::Block(body) => {
283 self.exec_statements(body, scope, this)
285 }
286 Statement::FunctionDeclaration { .. } => {
287 Ok(Completion::Normal(Value::Undefined))
289 }
290 Statement::If {
291 test,
292 consequent,
293 alternate,
294 } => {
295 if self.eval(test, scope, this)?.truthy() {
296 self.exec_stmt(consequent, scope, this)
297 } else if let Some(alt) = alternate {
298 self.exec_stmt(alt, scope, this)
299 } else {
300 Ok(Completion::Normal(Value::Undefined))
301 }
302 }
303 Statement::While { test, body } => {
304 let own_label = self.pending_label.take();
305 while self.eval(test, scope, this)?.truthy() {
306 if self.tick() {
307 return Err(Value::Undefined);
308 }
309 match self.exec_stmt(body, scope, this)? {
310 Completion::Break(lbl) if lbl.is_none() || lbl == own_label => break,
311 Completion::Break(lbl) => return Ok(Completion::Break(lbl)),
312 Completion::Continue(lbl) if lbl.is_none() || lbl == own_label => {}
313 Completion::Continue(lbl) => return Ok(Completion::Continue(lbl)),
314 Completion::Normal(_) => {}
315 ret @ Completion::Return(_) => return Ok(ret),
316 }
317 }
318 Ok(Completion::Normal(Value::Undefined))
319 }
320 Statement::DoWhile { body, test } => {
321 let own_label = self.pending_label.take();
322 loop {
323 if self.tick() {
324 return Err(Value::Undefined);
325 }
326 match self.exec_stmt(body, scope, this)? {
327 Completion::Break(lbl) if lbl.is_none() || lbl == own_label => break,
328 Completion::Break(lbl) => return Ok(Completion::Break(lbl)),
329 Completion::Continue(lbl) if lbl.is_none() || lbl == own_label => {}
330 Completion::Continue(lbl) => return Ok(Completion::Continue(lbl)),
331 Completion::Normal(_) => {}
332 ret @ Completion::Return(_) => return Ok(ret),
333 }
334 if !self.eval(test, scope, this)?.truthy() {
335 break;
336 }
337 }
338 Ok(Completion::Normal(Value::Undefined))
339 }
340 Statement::For {
341 init,
342 test,
343 update,
344 body,
345 } => {
346 let own_label = self.pending_label.take();
347 let is_let_like = matches!(
355 init.as_deref(),
356 Some(Statement::VarDeclaration {
357 kind: VarKind::Let | VarKind::Const,
358 ..
359 })
360 );
361 let mut loop_scope = if is_let_like {
362 Scope::child(scope.clone())
363 } else {
364 scope.clone()
365 };
366 if let Some(init) = init {
367 self.exec_stmt(init, &loop_scope, this)?;
368 }
369 let let_names: Vec<String> = if is_let_like {
370 loop_scope.borrow().vars.keys().cloned().collect()
371 } else {
372 Vec::new()
373 };
374 loop {
375 if let Some(t) = test {
376 if !self.eval(t, &loop_scope, this)?.truthy() {
377 break;
378 }
379 }
380 if self.tick() {
381 return Err(Value::Undefined);
382 }
383 match self.exec_stmt(body, &loop_scope, this)? {
384 Completion::Break(lbl) if lbl.is_none() || lbl == own_label => break,
385 Completion::Break(lbl) => return Ok(Completion::Break(lbl)),
386 Completion::Continue(lbl) if lbl.is_none() || lbl == own_label => {}
387 Completion::Continue(lbl) => return Ok(Completion::Continue(lbl)),
388 Completion::Normal(_) => {}
389 ret @ Completion::Return(_) => return Ok(ret),
390 }
391 if is_let_like {
392 let next_scope = Scope::child(scope.clone());
393 for name in &let_names {
394 let v = scope_get(&loop_scope, name).unwrap_or(Value::Undefined);
395 next_scope.borrow_mut().vars.insert(name.clone(), v);
396 }
397 loop_scope = next_scope;
398 }
399 if let Some(u) = update {
400 self.eval(u, &loop_scope, this)?;
401 }
402 }
403 Ok(Completion::Normal(Value::Undefined))
404 }
405 Statement::ForIn {
406 decl_kind,
407 pattern,
408 object,
409 body,
410 of,
411 is_await,
412 } => {
413 let own_label = self.pending_label.take();
414 let is_let_like = matches!(decl_kind, Some(VarKind::Let) | Some(VarKind::Const));
419 let obj = self.eval(object, scope, this)?;
420 if *of && *is_await {
424 let async_iter_method =
425 self.get_property(&obj, "Symbol(Symbol.asyncIterator)")?;
426 if !matches!(async_iter_method, Value::Undefined | Value::Null) {
427 let iterator = self.call_value(&async_iter_method, obj, &[])?;
428 loop {
429 if self.tick() {
430 return Err(Value::Undefined);
431 }
432 let next_fn = self.get_property(&iterator, "next")?;
433 let result = self.call_value(&next_fn, iterator.clone(), &[])?;
434 let awaited = self.await_value(result)?;
435 let done = self.get_property(&awaited, "done")?.truthy();
436 if done {
437 break;
438 }
439 let value = self.get_property(&awaited, "value")?;
440 let iter_scope = if is_let_like { Scope::child(scope.clone()) } else { scope.clone() };
441 self.bind_pattern(pattern, value, &iter_scope, this)?;
442 match self.exec_stmt(body, &iter_scope, this)? {
443 Completion::Break(lbl) if lbl.is_none() || lbl == own_label => {
444 break
445 }
446 Completion::Break(lbl) => return Ok(Completion::Break(lbl)),
447 Completion::Continue(lbl)
448 if lbl.is_none() || lbl == own_label => {}
449 Completion::Continue(lbl) => return Ok(Completion::Continue(lbl)),
450 Completion::Normal(_) => {}
451 ret @ Completion::Return(_) => return Ok(ret),
452 }
453 }
454 return Ok(Completion::Normal(Value::Undefined));
455 }
456 let items = self.iterate_values(&obj, true);
457 for item in items {
458 if self.tick() {
459 return Err(Value::Undefined);
460 }
461 let awaited = self.await_value(item)?;
462 let iter_scope = if is_let_like { Scope::child(scope.clone()) } else { scope.clone() };
463 self.bind_pattern(pattern, awaited, &iter_scope, this)?;
464 match self.exec_stmt(body, &iter_scope, this)? {
465 Completion::Break(lbl) if lbl.is_none() || lbl == own_label => break,
466 Completion::Break(lbl) => return Ok(Completion::Break(lbl)),
467 Completion::Continue(lbl) if lbl.is_none() || lbl == own_label => {}
468 Completion::Continue(lbl) => return Ok(Completion::Continue(lbl)),
469 Completion::Normal(_) => {}
470 ret @ Completion::Return(_) => return Ok(ret),
471 }
472 }
473 return Ok(Completion::Normal(Value::Undefined));
474 }
475 let items = self.iterate_values(&obj, *of);
476 for item in items {
477 if self.tick() {
478 return Err(Value::Undefined);
479 }
480 let iter_scope = if is_let_like { Scope::child(scope.clone()) } else { scope.clone() };
481 self.bind_pattern(pattern, item, &iter_scope, this)?;
482 match self.exec_stmt(body, &iter_scope, this)? {
483 Completion::Break(lbl) if lbl.is_none() || lbl == own_label => break,
484 Completion::Break(lbl) => return Ok(Completion::Break(lbl)),
485 Completion::Continue(lbl) if lbl.is_none() || lbl == own_label => {}
486 Completion::Continue(lbl) => return Ok(Completion::Continue(lbl)),
487 Completion::Normal(_) => {}
488 ret @ Completion::Return(_) => return Ok(ret),
489 }
490 }
491 Ok(Completion::Normal(Value::Undefined))
492 }
493 Statement::Return(e) => {
494 let v = match e {
495 Some(e) => self.eval(e, scope, this)?,
496 None => Value::Undefined,
497 };
498 Ok(Completion::Return(v))
499 }
500 Statement::Break(label) => Ok(Completion::Break(label.clone())),
501 Statement::Continue(label) => Ok(Completion::Continue(label.clone())),
502 Statement::Labeled(label, inner) => {
503 self.pending_label = Some(label.clone());
506 match self.exec_stmt(inner, scope, this)? {
507 Completion::Break(Some(lbl)) if lbl == *label => {
510 Ok(Completion::Normal(Value::Undefined))
511 }
512 other => Ok(other),
513 }
514 }
515 Statement::Switch {
516 discriminant,
517 cases,
518 } => {
519 let d = self.eval(discriminant, scope, this)?;
520 let mut start = None;
522 for (i, c) in cases.iter().enumerate() {
523 if let Some(test) = &c.test {
524 let tv = self.eval(test, scope, this)?;
525 if d.strict_eq(&tv) {
526 start = Some(i);
527 break;
528 }
529 }
530 }
531 if start.is_none() {
532 start = cases.iter().position(|c| c.test.is_none());
533 }
534 if let Some(s) = start {
535 for c in &cases[s..] {
536 match self.exec_statements(&c.body, scope, this)? {
537 Completion::Break(None) => {
541 return Ok(Completion::Normal(Value::Undefined))
542 }
543 Completion::Normal(_) => {} other => return Ok(other), }
546 }
547 }
548 Ok(Completion::Normal(Value::Undefined))
549 }
550 Statement::Throw(e) => {
551 let v = self.eval(e, scope, this)?;
552 Err(v)
553 }
554 Statement::Try {
555 block,
556 catch_param,
557 catch_block,
558 finally_block,
559 } => {
560 let result = self.exec_statements(block, scope, this);
561 let after_catch = match result {
562 Err(thrown) if !self.aborted && !self.is_suspending() && !self.is_gen_returning() => {
564 if let Some(cb) = catch_block {
565 if let Some(p) = catch_param {
566 self.bind_pattern(p, thrown, scope, this)?;
567 }
568 self.exec_statements(cb, scope, this)
569 } else {
570 Err(thrown)
571 }
572 }
573 other => other,
574 };
575 if self.is_suspending() {
577 return after_catch;
578 }
579 if let Some(fb) = finally_block {
580 let fin = self.exec_statements(fb, scope, this)?;
582 if let Completion::Return(_) | Completion::Break(_) | Completion::Continue(_) = fin {
583 if let Some(r) = &mut self.gen_replay {
584 r.returning = None;
585 }
586 return Ok(fin);
587 }
588 }
589 after_catch
590 }
591 Statement::Import {
592 source,
593 default,
594 namespace,
595 named,
596 side_effect_only,
597 } => {
598 let exports = self.load_module(source)?;
599 if !side_effect_only {
600 let exp = exports.borrow();
601 if let Some(local) = default {
602 let v = exp.get("default").cloned().unwrap_or(Value::Undefined);
603 scope_declare(scope, local, v);
604 }
605 if let Some(ns) = namespace {
606 let o = Obj::plain();
608 {
609 let mut ob = o.borrow_mut();
610 for (k, v) in exp.iter() {
611 ob.props.insert(k.clone(), v.clone());
612 }
613 }
614 scope_declare(scope, ns, Value::Object(o));
615 }
616 for (orig, local) in named {
617 let v = exp.get(orig).cloned().unwrap_or(Value::Undefined);
618 scope_declare(scope, local, v);
619 }
620 }
621 Ok(Completion::Normal(Value::Undefined))
622 }
623 Statement::ExportDefault(expr) => {
624 let v = self.eval(expr, scope, this)?;
625 self.record_export(scope, "default", v);
626 Ok(Completion::Normal(Value::Undefined))
627 }
628 Statement::ExportDecl { declaration, names } => {
629 let c = self.exec_stmt(declaration, scope, this)?;
630 for name in names {
632 let v = scope_get(scope, name).unwrap_or(Value::Undefined);
633 self.record_export(scope, name, v);
634 }
635 Ok(c)
636 }
637 Statement::ExportNamed { specifiers, source } => {
638 match source {
639 Some(src) => {
641 let exports = self.load_module(src)?;
642 let exp = exports.borrow();
643 for (orig, public) in specifiers {
644 let v = exp.get(orig).cloned().unwrap_or(Value::Undefined);
645 self.record_export(scope, public, v);
646 }
647 }
648 None => {
650 for (local, public) in specifiers {
651 let v = scope_get(scope, local).unwrap_or(Value::Undefined);
652 self.record_export(scope, public, v);
653 }
654 }
655 }
656 Ok(Completion::Normal(Value::Undefined))
657 }
658 Statement::ExportAll { source } => {
659 let exports = self.load_module(source)?;
660 let exp = exports.borrow();
661 for (k, v) in exp.iter() {
662 if k != "default" {
664 self.record_export(scope, k, v.clone());
665 }
666 }
667 Ok(Completion::Normal(Value::Undefined))
668 }
669 }
670 }
671
672 pub(crate) fn record_export(&mut self, scope: &Rc<RefCell<Scope>>, name: &str, val: Value) {
675 if let Some(Value::Object(o)) = scope_get(scope, MODULE_EXPORTS_KEY) {
677 o.borrow_mut().props.insert(String::from(name), val);
678 }
679 }
680
681 pub(crate) fn load_module(
684 &mut self,
685 specifier: &str,
686 ) -> Result<Rc<RefCell<BTreeMap<String, Value>>>, Value> {
687 if let Some(rec) = self.modules.borrow().get(specifier) {
689 if let Some(ex) = &rec.exports {
690 return Ok(ex.clone());
691 }
692 }
693 let source = match self.modules.borrow().get(specifier) {
695 Some(rec) => rec.source.clone(),
696 None => {
697 let empty = Rc::new(RefCell::new(BTreeMap::new()));
698 return Ok(empty);
699 }
700 };
701 let exports = Rc::new(RefCell::new(BTreeMap::new()));
703 if let Some(rec) = self.modules.borrow_mut().get_mut(specifier) {
704 rec.exports = Some(exports.clone());
705 }
706 let module_scope = Scope::child(self.global.clone());
709 let collector = Obj::plain();
710 scope_declare(
711 &module_scope,
712 MODULE_EXPORTS_KEY,
713 Value::Object(collector.clone()),
714 );
715 let program = Parser::new(Lexer::new(&source)).parse_program();
716 let _ = self.exec_statements(&program.body, &module_scope, &Value::Undefined)?;
717 {
719 let cb = collector.borrow();
720 let mut ex = exports.borrow_mut();
721 for (k, v) in cb.props.iter() {
722 ex.insert(k.clone(), v.clone());
723 }
724 }
725 Ok(exports)
726 }
727
728}