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}