Skip to main content

pipa/object/
array_obj.rs

1use crate::object::object::JSObject;
2use crate::value::JSValue;
3
4#[repr(C)]
5pub struct JSArrayObject {
6    pub header: JSObject,
7    pub elements: Vec<JSValue>,
8}
9
10impl JSArrayObject {
11    pub fn new() -> Self {
12        let mut header = JSObject::new_array();
13        header.set_dense_array_flag();
14        JSArrayObject {
15            header,
16            elements: Vec::new(),
17        }
18    }
19
20    pub fn with_capacity(capacity: usize) -> Self {
21        let mut header = JSObject::new_array();
22        header.set_dense_array_flag();
23        JSArrayObject {
24            header,
25            elements: Vec::with_capacity(capacity),
26        }
27    }
28
29    pub fn with_length(length: usize) -> Self {
30        let mut header = JSObject::new_array();
31        header.set_dense_array_flag();
32        let elements = if length <= 100_000 {
33            vec![JSValue::undefined(); length]
34        } else {
35            Vec::with_capacity(length)
36        };
37        JSArrayObject { header, elements }
38    }
39
40    pub fn from_elements(elements: Vec<JSValue>) -> Self {
41        let mut header = JSObject::new_array();
42        header.set_dense_array_flag();
43        JSArrayObject { header, elements }
44    }
45
46    #[inline]
47    pub fn get(&self, index: usize) -> Option<JSValue> {
48        self.elements.get(index).copied()
49    }
50
51    #[inline]
52    pub fn set(&mut self, index: usize, value: JSValue) {
53        if index < self.elements.len() {
54            self.elements[index] = value;
55        } else if index == self.elements.len() && index < 100000 {
56            self.elements.push(value);
57        } else if index < 100000 {
58            self.elements.resize(index + 1, JSValue::undefined());
59            self.elements[index] = value;
60        }
61    }
62
63    #[inline]
64    pub fn push(&mut self, value: JSValue) {
65        self.elements.push(value);
66    }
67
68    #[inline]
69    pub fn len(&self) -> usize {
70        self.elements.len()
71    }
72
73    #[inline]
74    pub fn is_empty(&self) -> bool {
75        self.elements.is_empty()
76    }
77
78    pub fn for_each_element(&self, mut f: impl FnMut(&JSValue)) {
79        for value in self.elements.iter() {
80            f(value);
81        }
82    }
83
84    pub fn set_elements(&mut self, elements: Vec<JSValue>) {
85        self.elements = elements;
86    }
87
88    #[inline]
89    pub fn elements(&self) -> &Vec<JSValue> {
90        &self.elements
91    }
92
93    #[inline]
94    pub fn elements_mut(&mut self) -> &mut Vec<JSValue> {
95        &mut self.elements
96    }
97}
98
99#[cfg(test)]
100mod tests {
101    use super::*;
102    use crate::value::JSValue;
103
104    #[test]
105    fn test_array_object_new() {
106        let arr = JSArrayObject::new();
107        assert!(arr.is_empty());
108        assert_eq!(arr.len(), 0);
109        assert!(arr.header.is_array());
110    }
111
112    #[test]
113    fn test_array_object_push_and_get() {
114        let mut arr = JSArrayObject::new();
115        arr.push(JSValue::new_int(1));
116        arr.push(JSValue::new_int(2));
117        arr.push(JSValue::new_int(3));
118
119        assert_eq!(arr.len(), 3);
120        assert_eq!(arr.get(0).unwrap().get_int(), 1);
121        assert_eq!(arr.get(1).unwrap().get_int(), 2);
122        assert_eq!(arr.get(2).unwrap().get_int(), 3);
123        assert!(arr.get(3).is_none());
124    }
125
126    #[test]
127    fn test_array_object_set_existing() {
128        let mut arr = JSArrayObject::from_elements(vec![JSValue::new_int(0); 5]);
129        arr.set(2, JSValue::new_int(99));
130        assert_eq!(arr.get(2).unwrap().get_int(), 99);
131        assert_eq!(arr.len(), 5);
132    }
133
134    #[test]
135    fn test_array_object_set_extends() {
136        let mut arr = JSArrayObject::new();
137        arr.set(3, JSValue::new_int(42));
138        assert_eq!(arr.len(), 4);
139        assert_eq!(arr.get(3).unwrap().get_int(), 42);
140
141        assert!(arr.get(0).unwrap().is_undefined());
142    }
143
144    #[test]
145    fn test_array_object_from_elements() {
146        let arr = JSArrayObject::from_elements(vec![JSValue::new_int(10), JSValue::new_int(20)]);
147        assert_eq!(arr.len(), 2);
148        assert_eq!(arr.get(0).unwrap().get_int(), 10);
149    }
150
151    #[test]
152    fn test_array_object_set_elements() {
153        let mut arr = JSArrayObject::new();
154        arr.push(JSValue::new_int(1));
155        arr.set_elements(vec![JSValue::new_int(99)]);
156        assert_eq!(arr.len(), 1);
157        assert_eq!(arr.get(0).unwrap().get_int(), 99);
158    }
159
160    #[test]
161    fn test_array_object_for_each_element() {
162        let mut arr = JSArrayObject::new();
163        arr.push(JSValue::new_int(10));
164        arr.push(JSValue::new_int(20));
165
166        let mut sum = 0i64;
167        arr.for_each_element(|v| {
168            sum += v.get_int();
169        });
170        assert_eq!(sum, 30);
171    }
172
173    #[test]
174    fn test_array_object_with_capacity() {
175        let arr = JSArrayObject::with_capacity(100);
176        assert_eq!(arr.len(), 0);
177        assert!(arr.elements().capacity() >= 100);
178    }
179
180    #[test]
181    fn test_array_object_elements_accessor() {
182        let mut arr = JSArrayObject::new();
183        arr.push(JSValue::new_int(1));
184        assert_eq!(arr.elements().len(), 1);
185        arr.elements_mut().push(JSValue::new_int(2));
186        assert_eq!(arr.len(), 2);
187    }
188}