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