1use super::*;
5
6pub(crate) fn func_diag_name(func: &Value) -> String {
8 match func {
9 Value::Object(o) => {
10 let b = o.borrow();
11 b.props
12 .get("name")
13 .map(|v| v.to_js_string())
14 .filter(|n| !n.is_empty())
15 .or_else(|| match &b.kind {
16 ObjKind::Function(fd) if !fd.name.is_empty() => Some(fd.name.clone()),
17 _ => None,
18 })
19 .or_else(|| b.props.get("_diag_name").map(|v| alloc::format!("~{}", v.to_js_string())))
20 .unwrap_or_else(|| String::from("<anonymous>"))
21 }
22 _ => String::from("<anonymous>"),
23 }
24}
25
26impl Interp {
27 pub(crate) fn eval_call(
28 &mut self,
29 callee: &Expression,
30 arguments: &[Expression],
31 optional: bool,
32 scope: &Rc<RefCell<Scope>>,
33 this: &Value,
34 ) -> EvalResult {
35 if matches!(callee, Expression::Super) {
37 let sc = self.super_ctor(scope)?;
38 let args = self.eval_arguments(arguments, scope, this)?;
39 return self.call_value(&sc, this.clone(), &args);
40 }
41 if let Expression::Member {
43 object, property, ..
44 } = callee
45 {
46 if matches!(**object, Expression::Super) {
47 let sp = self.super_proto(scope)?;
48 let f = self.get_property(&sp, property)?;
49 let args = self.eval_arguments(arguments, scope, this)?;
50 return self.call_value(&f, this.clone(), &args);
51 }
52 }
53 let (func, call_this, broke) = self.resolve_callee(callee, scope, this)?;
56 if broke {
57 return Ok(Value::Undefined);
58 }
59 if optional && matches!(func, Value::Undefined | Value::Null) {
60 return Ok(Value::Undefined);
61 }
62 let args = self.eval_arguments(arguments, scope, this)?;
63 let callable = match &func {
67 Value::Object(o) => o.borrow().is_callable(),
68 _ => false,
69 };
70 if !callable {
71 let desc = super::properties::describe_expr(callee);
72 return Err(self.type_error(alloc::format!("{} is not a function", desc)));
73 }
74 self.call_value(&func, call_this, &args)
75 }
76
77 pub(crate) fn resolve_callee(
85 &mut self,
86 callee: &Expression,
87 scope: &Rc<RefCell<Scope>>,
88 this: &Value,
89 ) -> Result<(Value, Value, bool), Value> {
90 match callee {
91 Expression::Member {
92 object,
93 property,
94 optional: mopt,
95 } if !matches!(**object, Expression::Super) => {
96 let (obj, broke) = self.eval_chain_object(object, scope, this)?;
97 if broke {
98 return Ok((Value::Undefined, Value::Undefined, true));
99 }
100 if *mopt && matches!(obj, Value::Undefined | Value::Null) {
101 return Ok((Value::Undefined, Value::Undefined, true));
102 }
103 let f = self.get_property_of_expr(&obj, property, object)?;
104 Ok((f, obj, false))
105 }
106 Expression::Index {
107 object,
108 index,
109 optional: iopt,
110 } => {
111 let (obj, broke) = self.eval_chain_object(object, scope, this)?;
112 if broke {
113 return Ok((Value::Undefined, Value::Undefined, true));
114 }
115 if *iopt && matches!(obj, Value::Undefined | Value::Null) {
116 return Ok((Value::Undefined, Value::Undefined, true));
117 }
118 let key = self.eval(index, scope, this)?;
119 let f = self.get_property(&obj, &to_property_key(&key))?;
120 Ok((f, obj, false))
121 }
122 _ => {
123 let (f, broke) = self.eval_chain_object(callee, scope, this)?;
124 Ok((f, Value::Undefined, broke))
125 }
126 }
127 }
128
129 pub(crate) fn eval_chain_object(
135 &mut self,
136 expr: &Expression,
137 scope: &Rc<RefCell<Scope>>,
138 this: &Value,
139 ) -> Result<(Value, bool), Value> {
140 match expr {
141 Expression::Member {
142 object,
143 property,
144 optional,
145 } => {
146 if matches!(**object, Expression::Super) {
147 let sp = self.super_proto(scope)?;
148 return Ok((self.get_property(&sp, property)?, false));
149 }
150 let (obj, broke) = self.eval_chain_object(object, scope, this)?;
151 if broke {
152 return Ok((Value::Undefined, true));
153 }
154 if *optional && matches!(obj, Value::Undefined | Value::Null) {
155 return Ok((Value::Undefined, true));
156 }
157 Ok((self.get_property(&obj, property)?, false))
158 }
159 Expression::Index {
160 object,
161 index,
162 optional,
163 } => {
164 let (obj, broke) = self.eval_chain_object(object, scope, this)?;
165 if broke {
166 return Ok((Value::Undefined, true));
167 }
168 if *optional && matches!(obj, Value::Undefined | Value::Null) {
169 return Ok((Value::Undefined, true));
170 }
171 let key = self.eval(index, scope, this)?;
172 Ok((self.get_property(&obj, &to_property_key(&key))?, false))
173 }
174 Expression::Call {
175 callee,
176 arguments,
177 optional,
178 } => {
179 let involves_super = matches!(**callee, Expression::Super)
180 || matches!(&**callee, Expression::Member { object, .. } if matches!(**object, Expression::Super));
181 if involves_super {
182 return Ok((self.eval(expr, scope, this)?, false));
183 }
184 let (func, call_this, broke) = self.resolve_callee(callee, scope, this)?;
185 if broke {
186 return Ok((Value::Undefined, true));
187 }
188 if *optional && matches!(func, Value::Undefined | Value::Null) {
189 return Ok((Value::Undefined, true));
190 }
191 let args = self.eval_arguments(arguments, scope, this)?;
192 Ok((self.call_value(&func, call_this, &args)?, false))
193 }
194 _ => Ok((self.eval(expr, scope, this)?, false)),
195 }
196 }
197
198 pub(crate) fn eval_arguments(
200 &mut self,
201 arguments: &[Expression],
202 scope: &Rc<RefCell<Scope>>,
203 this: &Value,
204 ) -> Result<Vec<Value>, Value> {
205 let mut args = Vec::with_capacity(arguments.len());
206 for a in arguments {
207 if let Expression::Spread(inner) = a {
208 let v = self.eval(inner, scope, this)?;
209 let items = self.iter_to_vec(&v);
210 args.extend(items);
211 } else {
212 args.push(self.eval(a, scope, this)?);
213 }
214 }
215 Ok(args)
216 }
217
218 pub(crate) fn eval_new(
219 &mut self,
220 callee: &Expression,
221 arguments: &[Expression],
222 scope: &Rc<RefCell<Scope>>,
223 this: &Value,
224 ) -> EvalResult {
225 let func = self.eval(callee, scope, this)?;
226 let args = self.eval_arguments(arguments, scope, this)?;
227 let proxy = match &func {
229 Value::Object(o) => match &o.borrow().kind {
230 ObjKind::Proxy { target, handler } => Some((target.clone(), handler.clone())),
231 _ => None,
232 },
233 _ => None,
234 };
235 if let Some((target, handler)) = proxy {
236 let trap = handler.borrow().props.get("construct").cloned();
237 if let Some(trap) =
238 trap.filter(|t| matches!(t, Value::Object(f) if f.borrow().is_callable()))
239 {
240 let arg_arr = Value::Object(Obj::array(args.clone()));
241 let targs = [
242 Value::Object(target),
243 arg_arr,
244 Value::Object(handler.clone()),
245 ];
246 return self.call_value(&trap, Value::Object(handler), &targs);
247 }
248 return self.construct_object(&Value::Object(target), &args);
249 }
250 self.construct_object(&func, &args)
251 }
252
253 pub fn construct_value(&mut self, func: &Value, args: &[Value]) -> EvalResult {
255 self.construct_object(func, args)
256 }
257
258 pub(crate) fn construct_object(&mut self, func: &Value, args: &[Value]) -> EvalResult {
259 self.construct_with_target(func, args, func)
260 }
261
262 pub(crate) fn construct_with_target(&mut self, func: &Value, args: &[Value], new_target: &Value) -> EvalResult {
265 if let Value::Object(fo) = func {
271 let bound = match &fo.borrow().kind {
272 ObjKind::Bound { target, bound_args, .. } => Some((target.clone(), bound_args.clone())),
273 _ => None,
274 };
275 if let Some((target, mut all)) = bound {
276 all.extend_from_slice(args);
277 let nt = match (new_target, func) {
278 (Value::Object(a), Value::Object(b)) if Rc::ptr_eq(a, b) => target.clone(),
279 _ => new_target.clone(),
280 };
281 return self.construct_with_target(&target, &all, &nt);
282 }
283 }
284 if let Some(proto) = self.element_class_proto(new_target) {
286 let (idx, fresh) = self.ce_construct_target(new_target, proto)?;
287 let inst = Value::Object(Obj::dom(idx));
288 if fresh {
289 self.ce_stack.push((idx, new_target.clone()));
290 }
291 self.pending_new_target = Some(new_target.clone());
292 let ret = self.call_value(func, inst.clone(), args);
293 if fresh {
294 self.ce_stack.pop();
295 }
296 return match ret? {
297 r @ Value::Object(_) => Ok(r),
298 _ => Ok(inst),
299 };
300 }
301 let inst_obj = Obj::plain();
303 if let Value::Object(fo) = new_target {
304 if let Some(Value::Object(p)) = fo.borrow().props.get("prototype") {
305 inst_obj.borrow_mut().proto = Some(p.clone());
306 }
307 }
308 let inst = Value::Object(inst_obj);
309 self.pending_new_target = Some(new_target.clone());
315 let ret = self.call_value(func, inst.clone(), args)?;
316 match ret {
317 Value::Object(_) => Ok(ret),
318 _ => Ok(inst),
319 }
320 }
321
322 pub fn call_value(&mut self, func: &Value, this: Value, args: &[Value]) -> EvalResult {
324 self.depth += 1;
325 let sp = super::current_sp();
329 if sp < self.stack_limit.0.saturating_sub(super::JS_STACK_MARGIN) || sp > self.stack_limit.1 {
330 self.stack_limit = super::js_stack_window();
331 }
332 let used = self.stack_limit.1.saturating_sub(sp);
333 if self.depth > self.max_depth || sp < self.stack_limit.0 {
334 static N: core::sync::atomic::AtomicUsize = core::sync::atomic::AtomicUsize::new(0);
335 if N.fetch_add(1, core::sync::atomic::Ordering::Relaxed) < 5 {
336 let top: Vec<&str> = self.call_names.iter().rev().take(16).map(|s| s.as_str()).collect();
337 crate::warn!(
338 "[JSPROF] call stack exceeded thread={:?} depth={} stack={}KB (steps={}) top={:?}",
339 crate::kernel::scheduler::get_current_process_name(),
340 self.depth,
341 used / 1024,
342 self.steps,
343 top
344 );
345 }
346 self.depth -= 1;
347 return Err(self.range_error("Maximum call stack size exceeded"));
348 }
349 let name = func_diag_name(func);
351 self.call_names.push(name);
352 self.tmp_bodies.push(match func { Value::Object(o) => match &o.borrow().kind { ObjKind::Function(fd) => Some(fd.body.clone()), _ => None }, _ => None }); if crate::os_lib::js::cycle_gc::should_collect() {
355 let _ = crate::os_lib::js::cycle_gc::maybe_collect();
356 }
357 let result = self.call_value_inner(func, this, args);
358 self.process_ce_reactions();
359 self.call_names.pop();
360 self.tmp_bodies.pop(); self.depth -= 1;
362 result
363 }
364
365 pub fn call_listener(
373 &mut self,
374 func: &Value,
375 this: Value,
376 args: &[Value],
377 context: &str,
378 ) -> bool {
379 match self.call_value(func, this, args) {
380 Ok(_) => true,
381 Err(thrown) => {
382 self.report_uncaught(context, &thrown);
383 false
384 }
385 }
386 }
387
388 pub fn report_uncaught(&mut self, context: &str, thrown: &Value) {
390 let mut repr = thrown.to_js_string();
391 if repr == "[object Object]" {
394 repr = alloc::format!("[object Object] {}", describe_thrown(thrown, 3));
395 }
396 let line = crate::os_lib::js::uncaught::format_uncaught(context, &repr);
397 crate::warn!("[JS] {}", line);
398 self.out.push_str(&line);
399 self.out.push('\n');
400 }
401
402 pub fn dispatch_event_in_interp(
406 &mut self,
407 node_idx: usize,
408 event_type: &str,
409 extra: &[(String, Value)],
410 ) -> (bool, bool) {
411 let path = {
413 let dom = self.dom.borrow();
414 let mut path = alloc::vec![node_idx];
415 let mut cur = node_idx;
416 let mut guard = 0;
417 while let Some(p) = dom.nodes.get(cur).and_then(|n| n.parent) {
418 path.push(p);
419 cur = p;
420 guard += 1;
421 if guard > dom.nodes.len() {
422 break;
423 }
424 }
425 path
426 };
427 let any = path
428 .iter()
429 .any(|&n| self.dom.borrow().has_listener_on(n, event_type));
430 let doc_has_listener = {
437 let doc_opt = self.global.borrow().vars.get("document").cloned();
438 doc_opt
439 .and_then(|d| super::super::builtins::event_target_listeners(&d))
440 .and_then(|listeners| listeners.borrow().props.get(event_type).cloned())
441 .is_some_and(|arr| match arr {
442 Value::Object(o) => matches!(&o.borrow().kind, ObjKind::Array(items) if !items.is_empty()),
443 _ => false,
444 })
445 };
446 let on_attr_name = alloc::format!("on{}", event_type);
447 let has_on_handler = path.iter().any(|&n| {
455 if self.dom.borrow().get_on_handler(n, &on_attr_name).is_some() {
456 return true;
457 }
458 self.dom.borrow().get_attr(n, &on_attr_name).is_some()
459 });
460 if !any && !doc_has_listener && !has_on_handler {
461 return (false, false);
462 }
463
464 let bubbles = extra
471 .iter()
472 .find(|(k, _)| k == "bubbles")
473 .map(|(_, v)| v.truthy())
474 .unwrap_or(true);
475 let composed: Vec<Value> = path.iter().map(|&n| Value::Object(Obj::dom(n))).collect();
476 let target = Value::Object(Obj::dom(node_idx));
477 let ev = Obj::plain();
478 {
479 let mut e = ev.borrow_mut();
480 e.props.insert(String::from("type"), Value::str(event_type));
481 e.props.insert(String::from("target"), target.clone());
482 e.props.insert(String::from("bubbles"), Value::Bool(true));
483 e.props.insert(String::from("cancelable"), Value::Bool(true));
489 e.props.insert(String::from("isTrusted"), Value::Bool(false));
495 e.props
496 .insert(String::from("eventPhase"), Value::Number(0.0));
497 e.props
498 .insert(String::from("defaultPrevented"), Value::Bool(false));
499 e.props.insert(
502 String::from("timeStamp"),
503 Value::Number(super::super::builtins::next_perf_timestamp()),
504 );
505 e.props.insert(String::from("returnValue"), Value::Bool(true));
508 e.props.insert(String::from("cancelBubble"), Value::Bool(false));
509 e.props.insert(String::from("srcElement"), target.clone());
510 e.props.insert(
511 String::from("_composedPath"),
512 Value::Object(Obj::array(composed)),
513 );
514 for (k, v) in extra {
515 e.props.insert(k.clone(), v.clone());
516 }
517 e.props.insert(
518 String::from("preventDefault"),
519 Value::Object(Obj::native("preventDefault", |_, this, _| {
520 if let Value::Object(o) = &this {
521 let cancelable = o
522 .borrow()
523 .props
524 .get("cancelable")
525 .map(|v| v.truthy())
526 .unwrap_or(true);
527 if cancelable {
528 let mut b = o.borrow_mut();
529 b.props
530 .insert(String::from("defaultPrevented"), Value::Bool(true));
531 b.props.insert(String::from("returnValue"), Value::Bool(false));
535 }
536 }
537 Ok(Value::Undefined)
538 })),
539 );
540 e.props.insert(
541 String::from("stopPropagation"),
542 Value::Object(Obj::native("stopPropagation", |_, this, _| {
543 if let Value::Object(o) = &this {
544 let mut b = o.borrow_mut();
545 b.props
546 .insert(String::from("_stop"), Value::Bool(true));
547 b.props.insert(String::from("cancelBubble"), Value::Bool(true));
550 }
551 Ok(Value::Undefined)
552 })),
553 );
554 e.props.insert(
555 String::from("stopImmediatePropagation"),
556 Value::Object(Obj::native("stopImmediatePropagation", |_, this, _| {
557 if let Value::Object(o) = &this {
558 let mut b = o.borrow_mut();
559 b.props.insert(String::from("_stop"), Value::Bool(true));
560 b.props
561 .insert(String::from("_stopImmediate"), Value::Bool(true));
562 b.props.insert(String::from("cancelBubble"), Value::Bool(true));
563 }
564 Ok(Value::Undefined)
565 })),
566 );
567 e.props.insert(
568 String::from("composedPath"),
569 Value::Object(Obj::native("composedPath", |_, this, _| {
570 if let Value::Object(o) = &this {
571 if let Some(p) = o.borrow().props.get("_composedPath") {
572 return Ok(p.clone());
573 }
574 }
575 Ok(Value::Object(Obj::array(Vec::new())))
576 })),
577 );
578 }
579
580 let mut steps: Vec<(usize, bool, f64)> = Vec::new();
581 for &n in path.iter().skip(1).rev() {
582 steps.push((n, true, 1.0));
583 }
584 steps.push((node_idx, true, 2.0));
585 steps.push((node_idx, false, 2.0));
586 if bubbles {
587 for &n in path.iter().skip(1) {
588 steps.push((n, false, 3.0));
589 }
590 }
591
592 let mut fired = false;
593 let mut to_remove: Vec<u64> = Vec::new();
594 let mut propagation_stopped = false;
595 let (doc_cap_fired, doc_cap_stopped) = self.fire_document_listeners(&ev, event_type, true);
603 if doc_cap_fired {
604 fired = true;
605 }
606 if doc_cap_stopped {
607 propagation_stopped = true;
608 }
609 if !propagation_stopped {
610 'outer: for (n, want_capture, phase) in steps {
611 let listeners = self
612 .dom
613 .borrow()
614 .listeners_phase(n, event_type, want_capture);
615 let on_attr_name = alloc::format!("on{}", event_type);
616 let node_this = Value::Object(Obj::dom(n));
617 {
620 let mut e = ev.borrow_mut();
621 e.props.insert(String::from("currentTarget"), Value::Object(Obj::dom(n)));
622 e.props.insert(String::from("eventPhase"), Value::Number(phase));
623 }
624 if !want_capture {
625 let on_handler = self
628 .dom
629 .borrow()
630 .get_on_handler(n, &on_attr_name)
631 .filter(|v| !matches!(v, Value::Undefined | Value::Null))
632 .or_else(|| self.dom.borrow().get_attr(n, &on_attr_name).map(Value::str));
633 if let Some(h) = on_handler {
634 match h {
635 Value::Object(_) => {
636 let ctx = alloc::format!("on{} handler", event_type);
637 self.call_listener(
638 &h,
639 node_this.clone(),
640 &[Value::Object(ev.clone())],
641 &ctx,
642 );
643 fired = true;
644 }
645 Value::Str(code) if !code.is_empty() => {
646 if let Err(thrown) = self.eval_source(&code) {
647 let ctx = alloc::format!("on{} attribute", event_type);
648 self.report_uncaught(&ctx, &thrown);
649 }
650 fired = true;
651 }
652 _ => {}
653 }
654 }
655 }
656 if listeners.is_empty() {
657 continue;
658 }
659 {
660 let mut e = ev.borrow_mut();
661 e.props
662 .insert(String::from("currentTarget"), Value::Object(Obj::dom(n)));
663 e.props
664 .insert(String::from("eventPhase"), Value::Number(phase));
665 }
666 let node_this = Value::Object(Obj::dom(n));
667 for (func, once, id) in listeners {
668 let ctx = alloc::format!("{} listener", event_type);
669 self.call_listener(
670 &func,
671 node_this.clone(),
672 &[Value::Object(ev.clone())],
673 &ctx,
674 );
675 fired = true;
676 if once {
677 to_remove.push(id);
678 }
679 if ev
680 .borrow()
681 .props
682 .get("_stopImmediate")
683 .map(|v| v.truthy())
684 .unwrap_or(false)
685 {
686 propagation_stopped = true;
687 break 'outer;
688 }
689 }
690 if ev
691 .borrow()
692 .props
693 .get("_stop")
694 .map(|v| v.truthy())
695 .unwrap_or(false)
696 {
697 propagation_stopped = true;
698 break 'outer;
699 }
700 }
701 }
702 if !to_remove.is_empty() {
703 let mut dom = self.dom.borrow_mut();
704 for id in to_remove {
705 dom.remove_listener_by_id(id);
706 }
707 }
708 if bubbles && !propagation_stopped {
718 let (doc_bub_fired, _) = self.fire_document_listeners(&ev, event_type, false);
719 if doc_bub_fired {
720 fired = true;
721 }
722 }
723 let default_prevented = ev
724 .borrow()
725 .props
726 .get("defaultPrevented")
727 .map(|v| v.truthy())
728 .unwrap_or(false);
729 (fired, default_prevented)
730 }
731
732 fn fire_document_listeners(
742 &mut self,
743 ev: &super::super::value::ObjRef,
744 event_type: &str,
745 want_capture: bool,
746 ) -> (bool, bool) {
747 let mut fired = false;
748 let doc_opt = {
753 let g = self.global.borrow();
754 g.vars.get("document").cloned()
755 };
756 let Some(Value::Object(doc)) = doc_opt else {
757 return (false, false);
758 };
759 let doc_val = Value::Object(doc);
760 let Some(listeners) = super::super::builtins::event_target_listeners(&doc_val) else {
761 return (false, false);
762 };
763 let cbs: alloc::vec::Vec<Value> = match listeners.borrow().props.get(event_type) {
764 Some(Value::Object(arr)) => match &arr.borrow().kind {
765 ObjKind::Array(items) => items.clone(),
766 _ => alloc::vec::Vec::new(),
767 },
768 _ => alloc::vec::Vec::new(),
769 };
770 let matching: alloc::vec::Vec<Value> = cbs
771 .into_iter()
772 .filter(|entry| super::super::builtins::event_target_listener_capture(entry) == want_capture)
773 .collect();
774 if matching.is_empty() {
775 return (false, false);
776 }
777 {
778 let mut e = ev.borrow_mut();
779 e.props.insert(String::from("currentTarget"), doc_val.clone());
780 e.props
781 .insert(String::from("eventPhase"), Value::Number(if want_capture { 1.0 } else { 3.0 }));
782 }
783 for entry in matching {
784 if super::super::builtins::event_target_listener_aborted(&entry) {
785 continue;
786 }
787 let cb = super::super::builtins::event_target_listener_cb(&entry);
788 let once = super::super::builtins::event_target_listener_once(&entry);
789 let ctx = alloc::format!("{} listener (document)", event_type);
790 self.call_listener(&cb, doc_val.clone(), &[Value::Object(ev.clone())], &ctx);
791 fired = true;
792 if once {
793 if let Some(Value::Object(arr)) = listeners.borrow().props.get(event_type).cloned() {
794 if let ObjKind::Array(items) = &mut arr.borrow_mut().kind {
795 items.retain(|v| match (&super::super::builtins::event_target_listener_cb(v), &cb) {
796 (Value::Object(x), Value::Object(y)) => !Rc::ptr_eq(x, y),
797 _ => true,
798 });
799 }
800 }
801 }
802 if ev
803 .borrow()
804 .props
805 .get("_stopImmediate")
806 .map(|v| v.truthy())
807 .unwrap_or(false)
808 {
809 return (fired, true);
810 }
811 }
812 let stopped = ev.borrow().props.get("_stop").map(|v| v.truthy()).unwrap_or(false);
813 (fired, stopped)
814 }
815
816 pub(crate) fn call_value_inner(&mut self, func: &Value, this: Value, args: &[Value]) -> EvalResult {
817 let obj = match func {
818 Value::Object(o) => o.clone(),
819 _ => {
822 let d = alloc::format!("{}", func.to_js_string());
823 return Err(self.throw(alloc::format!("not a function: {}", d)));
826 }
827 };
828 let proxy = match &obj.borrow().kind {
830 ObjKind::Proxy { target, handler } => Some((target.clone(), handler.clone())),
831 _ => None,
832 };
833 if let Some((target, handler)) = proxy {
834 let trap = handler.borrow().props.get("apply").cloned();
835 if let Some(trap) =
836 trap.filter(|t| matches!(t, Value::Object(f) if f.borrow().is_callable()))
837 {
838 let arg_arr = Value::Object(Obj::array(args.to_vec()));
839 let targs = [Value::Object(target), this, arg_arr];
840 return self.call_value(&trap, Value::Object(handler), &targs);
841 }
842 return self.call_value(&Value::Object(target), this, args);
843 }
844 let bound = match &obj.borrow().kind {
848 ObjKind::Bound {
849 target,
850 bound_this,
851 bound_args,
852 } => Some((target.clone(), bound_this.clone(), bound_args.clone())),
853 _ => None,
854 };
855 if let Some((target, bound_this, bound_args)) = bound {
856 let mut combined = bound_args;
857 combined.extend_from_slice(args);
858 return self.call_value(&target, bound_this, &combined);
859 }
860 let kind = {
862 let b = obj.borrow();
863 match &b.kind {
864 ObjKind::Function(fd) => CallKind::User(fd.clone()),
865 ObjKind::Native { func, .. } => CallKind::Native(*func),
866 ObjKind::Resolver { state, reject } => CallKind::Resolver(state.clone(), *reject),
867 other => {
870 let kind_name = match other {
871 ObjKind::Array(_) => "array",
872 ObjKind::Plain => "object",
873 ObjKind::DomElement(_) => "dom element",
874 ObjKind::Host(_) => "host object",
875 _ => "other",
876 };
877 return Err(self.throw(alloc::format!(
878 "not a function: {} (呼べない種別)",
879 kind_name
880 )));
881 }
882 }
883 };
884 match kind {
885 CallKind::Native(f) => f(self, this, args),
886 CallKind::Resolver(state, reject) => {
887 let arg = args.first().cloned().unwrap_or(Value::Undefined);
888 if reject {
889 self.promise_reject(&state, arg);
890 } else {
891 self.promise_resolve(&state, arg);
892 }
893 Ok(Value::Undefined)
894 }
895 CallKind::User(fd) => {
896 let nt = self.pending_new_target.take().unwrap_or(Value::Undefined);
902 let pushed = !fd.is_arrow;
903 if pushed {
904 self.new_target_stack.push(nt);
905 }
906 let result = self.call_user_function(fd, this, args, func.clone());
907 if pushed {
908 self.new_target_stack.pop();
909 }
910 result
911 }
912 }
913 }
914
915 pub(crate) fn call_user_function(
916 &mut self,
917 fd: FunctionData,
918 this: Value,
919 args: &[Value],
920 callee: Value,
921 ) -> EvalResult {
922 let this = if !fd.is_arrow && !fd.body.strict && matches!(this, Value::Undefined | Value::Null) {
926 self.global.borrow().vars.get("window").cloned().unwrap_or(Value::Undefined)
927 } else {
928 this
929 };
930 {
931 let call_scope = Scope::child(fd.closure.clone());
932 for (i, p) in fd.params.iter().enumerate() {
933 if p.is_rest {
934 let rest_args: Vec<Value> =
936 args.get(i..).map(|s| s.to_vec()).unwrap_or_default();
937 self.bind_pattern(
938 &p.pattern,
939 Value::Object(Obj::array(rest_args)),
940 &call_scope,
941 &this,
942 )?;
943 break;
944 }
945 let mut v = args.get(i).cloned().unwrap_or(Value::Undefined);
946 if matches!(v, Value::Undefined) {
948 if let Some(def) = &p.default {
949 v = self.eval(def, &call_scope, &this)?;
950 }
951 }
952 self.bind_pattern(&p.pattern, v, &call_scope, &this)?;
953 }
954 let use_this = if fd.is_arrow {
955 fd.bound_this
956 .as_ref()
957 .map(|b| (**b).clone())
958 .unwrap_or(Value::Undefined)
959 } else {
960 this
961 };
962 if fd.is_generator {
963 return Ok(Value::Object(Obj::generator(GenState {
967 func: fd.clone(),
968 args: args.to_vec(),
969 this: use_this,
970 sent: Vec::new(),
971 started: false,
972 done: false,
973 returned: Value::Undefined,
974 })));
975 }
976 let stmts = fd.body.stmts();
977 if !fd.is_arrow && fd.body.uses_arguments(&stmts) {
986 let arguments_obj = Obj::array(args.to_vec());
987 arguments_obj.borrow_mut().props.insert("callee".into(), callee);
988 scope_declare(&call_scope, "arguments", Value::Object(arguments_obj));
989 }
990 if fd.is_async {
991 let outcome = self.exec_statements(&stmts, &call_scope, &use_this);
994 let pstate = Rc::new(RefCell::new(PromiseState::pending()));
995 match outcome {
996 Ok(Completion::Return(v)) => self.promise_resolve(&pstate, v),
997 Ok(_) => self.promise_resolve(&pstate, Value::Undefined),
998 Err(e) => {
999 if self.aborted {
1000 return Err(e);
1001 }
1002 self.promise_reject(&pstate, e);
1003 }
1004 }
1005 return Ok(Value::Object(Obj::promise(pstate)));
1006 }
1007 match self.exec_statements(&stmts, &call_scope, &use_this)? {
1008 Completion::Return(v) => Ok(v),
1009 _ => Ok(Value::Undefined),
1010 }
1011 }
1012 }
1013
1014 }
1017
1018pub(crate) fn describe_thrown(v: &Value, depth: u32) -> String {
1020 match v {
1021 Value::Object(o) => {
1022 if depth == 0 {
1023 return String::from("{…}");
1024 }
1025 let b = o.borrow();
1026 if let ObjKind::Array(items) = &b.kind {
1027 let parts: Vec<String> = items.iter().take(4).map(|x| describe_thrown(x, depth - 1)).collect();
1028 return alloc::format!("[{}]", parts.join(", "));
1029 }
1030 let parts: Vec<String> = b
1031 .props
1032 .iter()
1033 .take(8)
1034 .map(|(k, x)| alloc::format!("{}={}", k, describe_thrown(x, depth - 1)))
1035 .collect();
1036 alloc::format!("{{{}}}", parts.join(", "))
1037 }
1038 other => other.to_js_string().chars().take(300).collect(),
1039 }
1040}