1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#[cfg(test)]
mod tests;
use crate::{
builtins::{
object::{internal_methods_trait::ObjectInternalMethods, Object},
property::Property,
value::{to_value, ResultValue, Value, ValueData},
},
exec::Interpreter,
syntax::ast::node::{FormalParameter, Node},
};
use gc::{custom_trace, Gc};
use gc_derive::{Finalize, Trace};
use std::fmt::{self, Debug};
use std::ops::Deref;
pub type NativeFunctionData = fn(&Value, &[Value], &mut Interpreter) -> ResultValue;
#[derive(Trace, Finalize, Debug, Clone)]
pub enum Function {
NativeFunc(NativeFunction),
RegularFunc(RegularFunction),
}
#[derive(Trace, Finalize, Debug, Clone)]
pub struct RegularFunction {
pub object: Object,
pub node: Node,
pub args: Vec<Node>,
}
impl RegularFunction {
#[allow(clippy::cast_possible_wrap)]
pub fn new(node: Node, f_args: Vec<FormalParameter>) -> Self {
let mut args = vec![];
for i in f_args {
let node = if let Some(init) = &i.init {
init.deref().clone()
} else {
Node::Local(i.name.clone())
};
args.push(node);
}
let mut object = Object::default();
object.properties.insert(
"arguments".to_string(),
Property::default().value(Gc::new(ValueData::Integer(args.len() as i32))),
);
Self { object, node, args }
}
}
#[derive(Finalize, Clone)]
pub struct NativeFunction {
pub object: Object,
pub data: NativeFunctionData,
}
impl NativeFunction {
pub fn new(data: NativeFunctionData) -> Self {
let object = Object::default();
Self { object, data }
}
}
impl Debug for NativeFunction {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{{")?;
for (key, val) in self.object.properties.iter() {
write!(
f,
"{}: {}",
key,
val.value
.as_ref()
.unwrap_or(&Gc::new(ValueData::Undefined))
.clone()
)?;
}
write!(f, "}}")
}
}
unsafe impl gc::Trace for NativeFunction {
custom_trace!(this, mark(&this.object));
}
pub fn _create() -> Value {
let function: Object = Object::default();
to_value(function)
}
pub fn init(global: &Value) {
let global_ptr = global;
global_ptr.set_field_slice("Function", _create());
}
pub fn create_unmapped_arguments_object(arguments_list: Vec<Value>) -> Value {
let len = arguments_list.len();
let mut obj = Object::default();
obj.set_internal_slot("ParameterMap", Gc::new(ValueData::Undefined));
let mut length = Property::default();
length = length.writable(true).value(to_value(len));
obj.define_own_property("length".to_string(), length);
let mut index: usize = 0;
while index < len {
let val = arguments_list.get(index).expect("Could not get argument");
let mut prop = Property::default();
prop = prop
.value(val.clone())
.enumerable(true)
.writable(true)
.configurable(true);
obj.properties.insert(index.to_string(), prop);
index += 1;
}
to_value(obj)
}