boa/syntax/ast/node/new/
mod.rs1use crate::{
2 builtins::iterable,
3 exec::Executable,
4 gc::{Finalize, Trace},
5 syntax::ast::node::{Call, Node},
6 value::JsValue,
7 BoaProfiler, Context, JsResult,
8};
9use std::fmt;
10
11#[cfg(feature = "deser")]
12use serde::{Deserialize, Serialize};
13
14#[cfg(test)]
15mod tests;
16
17#[cfg_attr(feature = "deser", derive(Serialize, Deserialize))]
33#[derive(Clone, Debug, Trace, Finalize, PartialEq)]
34pub struct New {
35 call: Call,
36}
37
38impl New {
39 pub fn expr(&self) -> &Node {
41 self.call.expr()
42 }
43
44 pub fn args(&self) -> &[Node] {
46 self.call.args()
47 }
48}
49
50impl Executable for New {
51 fn run(&self, context: &mut Context) -> JsResult<JsValue> {
52 let _timer = BoaProfiler::global().start_event("New", "exec");
53
54 let func_object = self.expr().run(context)?;
55 let mut v_args = Vec::with_capacity(self.args().len());
56 for arg in self.args() {
57 if let Node::Spread(ref x) = arg {
58 let val = x.run(context)?;
59 let iterator_record = iterable::get_iterator(&val, context)?;
60 loop {
61 let next = iterator_record.next(context)?;
62 if next.done {
63 break;
64 }
65 let next_value = next.value;
66 v_args.push(next_value);
67 }
68 break; } else {
70 v_args.push(arg.run(context)?);
71 }
72 }
73
74 match func_object {
75 JsValue::Object(ref object) => {
76 object.construct(&v_args, &object.clone().into(), context)
77 }
78 _ => context
79 .throw_type_error(format!("{} is not a constructor", self.expr().to_string(),)),
80 }
81 }
82}
83
84impl From<Call> for New {
85 fn from(call: Call) -> Self {
86 Self { call }
87 }
88}
89
90impl fmt::Display for New {
91 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
92 write!(f, "new {}", self.call)
93 }
94}
95
96impl From<New> for Node {
97 fn from(new: New) -> Self {
98 Self::New(new)
99 }
100}