1 /*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "ecmascript/js_api/js_api_arraylist.h"
17
18 #include "ecmascript/containers/containers_errors.h"
19 #include "ecmascript/interpreter/interpreter.h"
20 #include "ecmascript/js_iterator.h"
21 #include "ecmascript/js_function.h"
22 #include "ecmascript/js_api/js_api_arraylist_iterator.h"
23 #include "ecmascript/js_function.h"
24 #include "ecmascript/js_iterator.h"
25 #include "ecmascript/js_tagged_value.h"
26 #include "ecmascript/object_factory.h"
27
28 namespace panda::ecmascript {
29 using ContainerError = containers::ContainerError;
30 using ErrorFlag = containers::ErrorFlag;
Add(JSThread * thread,const JSHandle<JSAPIArrayList> & arrayList,const JSHandle<JSTaggedValue> & value)31 bool JSAPIArrayList::Add(JSThread *thread, const JSHandle<JSAPIArrayList> &arrayList,
32 const JSHandle<JSTaggedValue> &value)
33 {
34 uint32_t length = arrayList->GetLength().GetArrayLength();
35 JSHandle<TaggedArray> elements = GrowCapacity(thread, arrayList, length + 1);
36
37 ASSERT(!elements->IsDictionaryMode());
38 elements->Set(thread, length, value);
39 arrayList->SetLength(thread, JSTaggedValue(++length));
40 return true;
41 }
42
Insert(JSThread * thread,const JSHandle<JSAPIArrayList> & arrayList,const JSHandle<JSTaggedValue> & value,const int & index)43 void JSAPIArrayList::Insert(JSThread *thread, const JSHandle<JSAPIArrayList> &arrayList,
44 const JSHandle<JSTaggedValue> &value, const int &index)
45 {
46 int length = arrayList->GetLength().GetInt();
47 if (index < 0 || index > length) {
48 std::ostringstream oss;
49 oss << "The value of \"index\" is out of range. It must be >= 0 && <= " << length
50 << ". Received value is: " << index;
51 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::RANGE_ERROR, oss.str().c_str());
52 THROW_NEW_ERROR_AND_RETURN(thread, error);
53 }
54 JSHandle<TaggedArray> elements = GrowCapacity(thread, arrayList, length + 1);
55 ASSERT(!elements->IsDictionaryMode());
56 for (int i = length - 1; i >= index; --i) {
57 elements->Set(thread, i + 1, elements->Get(i));
58 }
59 elements->Set(thread, index, value);
60 arrayList->SetLength(thread, JSTaggedValue(++length));
61 }
62
Clear(JSThread * thread,const JSHandle<JSAPIArrayList> & arrayList)63 void JSAPIArrayList::Clear(JSThread *thread, const JSHandle<JSAPIArrayList> &arrayList)
64 {
65 if (!arrayList.IsEmpty()) {
66 int length = arrayList->GetLength().GetInt();
67 JSHandle<TaggedArray> elements(thread, arrayList->GetElements());
68 ASSERT(!elements->IsDictionaryMode());
69 for (int i = 0; i <= length; ++i) {
70 elements->Set(thread, i, JSTaggedValue::Hole());
71 }
72 arrayList->SetLength(thread, JSTaggedValue(0));
73 }
74 }
75
Clone(JSThread * thread,const JSHandle<JSAPIArrayList> & obj)76 JSHandle<JSAPIArrayList> JSAPIArrayList::Clone(JSThread *thread, const JSHandle<JSAPIArrayList> &obj)
77 {
78 JSHandle<TaggedArray> srcElements(thread, obj->GetElements());
79 ASSERT(!srcElements->IsDictionaryMode());
80
81 uint32_t length = obj->GetSize();
82 auto factory = thread->GetEcmaVM()->GetFactory();
83 JSHandle<JSAPIArrayList> newArrayList = factory->NewJSAPIArrayList(0);
84 newArrayList->SetLength(thread, JSTaggedValue(length));
85
86 JSHandle<TaggedArray> dstElements = factory->NewAndCopyTaggedArray(srcElements, length, length);
87 newArrayList->SetElements(thread, dstElements);
88 return newArrayList;
89 }
90
GetCapacity(JSThread * thread,const JSHandle<JSAPIArrayList> & obj)91 uint32_t JSAPIArrayList::GetCapacity(JSThread *thread, const JSHandle<JSAPIArrayList> &obj)
92 {
93 JSHandle<TaggedArray> elements(thread, obj->GetElements());
94 ASSERT(!elements->IsDictionaryMode());
95 uint32_t capacity = elements->GetLength();
96 return capacity;
97 }
98
IncreaseCapacityTo(JSThread * thread,const JSHandle<JSAPIArrayList> & arrayList,int capacity)99 void JSAPIArrayList::IncreaseCapacityTo(JSThread *thread, const JSHandle<JSAPIArrayList> &arrayList,
100 int capacity)
101 {
102 JSHandle<TaggedArray> elementData(thread, arrayList->GetElements());
103 ASSERT(!elementData->IsDictionaryMode());
104 int length = arrayList->GetLength().GetInt();
105 int oldElementLength = static_cast<int>(elementData->GetLength());
106 if (oldElementLength != capacity && length < capacity) {
107 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
108 JSHandle<TaggedArray> newElements = factory->NewAndCopyTaggedArray(elementData,
109 static_cast<uint32_t>(capacity), static_cast<uint32_t>(length));
110 arrayList->SetElements(thread, newElements);
111 }
112 }
113
TrimToCurrentLength(JSThread * thread,const JSHandle<JSAPIArrayList> & arrayList)114 void JSAPIArrayList::TrimToCurrentLength(JSThread *thread, const JSHandle<JSAPIArrayList> &arrayList)
115 {
116 uint32_t length = arrayList->GetLength().GetArrayLength();
117 uint32_t capacity = JSAPIArrayList::GetCapacity(thread, arrayList);
118 JSHandle<TaggedArray> elements(thread, arrayList->GetElements());
119 ASSERT(!elements->IsDictionaryMode());
120 if (capacity > length) {
121 elements->Trim(thread, length);
122 }
123 }
124
Get(JSThread * thread,const uint32_t index)125 JSTaggedValue JSAPIArrayList::Get(JSThread *thread, const uint32_t index)
126 {
127 if (index >= GetLength().GetArrayLength()) {
128 std::ostringstream oss;
129 oss << "The value of \"index\" is out of range. It must be >= 0 && <= "
130 << (GetLength().GetArrayLength() - 1) << ". Received value is: " << index;
131 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::RANGE_ERROR, oss.str().c_str());
132 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
133 }
134
135 TaggedArray *elements = TaggedArray::Cast(GetElements().GetTaggedObject());
136 return elements->Get(index);
137 }
138
IsEmpty(const JSHandle<JSAPIArrayList> & arrayList)139 bool JSAPIArrayList::IsEmpty(const JSHandle<JSAPIArrayList> &arrayList)
140 {
141 return arrayList->GetSize() == 0;
142 }
143
GetIndexOf(JSThread * thread,const JSHandle<JSAPIArrayList> & arrayList,const JSHandle<JSTaggedValue> & value)144 int JSAPIArrayList::GetIndexOf(JSThread *thread, const JSHandle<JSAPIArrayList> &arrayList,
145 const JSHandle<JSTaggedValue> &value)
146 {
147 JSHandle<TaggedArray> elements(thread, arrayList->GetElements());
148 ASSERT(!elements->IsDictionaryMode());
149 uint32_t length = arrayList->GetLength().GetArrayLength();
150 JSTaggedValue targetValue = value.GetTaggedValue();
151 for (uint32_t i = 0; i < length; ++i) {
152 if (JSTaggedValue::StrictEqual(targetValue, elements->Get(i))) {
153 return i;
154 }
155 }
156 return -1;
157 }
158
GetLastIndexOf(JSThread * thread,const JSHandle<JSAPIArrayList> & arrayList,const JSHandle<JSTaggedValue> & value)159 int JSAPIArrayList::GetLastIndexOf(JSThread *thread, const JSHandle<JSAPIArrayList> &arrayList,
160 const JSHandle<JSTaggedValue> &value)
161 {
162 JSHandle<TaggedArray> elements(thread, arrayList->GetElements());
163 ASSERT(!elements->IsDictionaryMode());
164 JSTaggedValue targetValue = value.GetTaggedValue();
165 int length = arrayList->GetLength().GetInt();
166 for (int i = length - 1; i >= 0; --i) {
167 if (JSTaggedValue::StrictEqual(targetValue, elements->Get(i))) {
168 return i;
169 }
170 }
171 return -1;
172 }
173
RemoveByIndex(JSThread * thread,const JSHandle<JSAPIArrayList> & arrayList,int index)174 JSTaggedValue JSAPIArrayList::RemoveByIndex(JSThread *thread, const JSHandle<JSAPIArrayList> &arrayList, int index)
175 {
176 int length = arrayList->GetLength().GetInt();
177 if (index < 0 || index >= length) {
178 std::ostringstream oss;
179 oss << "The value of \"index\" is out of range. It must be >= 0 && <= " << (length - 1)
180 << ". Received value is: " << index;
181 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::RANGE_ERROR, oss.str().c_str());
182 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
183 }
184
185 TaggedArray *resElements = TaggedArray::Cast(arrayList->GetElements().GetTaggedObject());
186 JSTaggedValue oldValue = resElements->Get(index);
187
188 if (index >= 0) {
189 JSHandle<TaggedArray> elements(thread, arrayList->GetElements());
190 ASSERT(!elements->IsDictionaryMode());
191 TaggedArray::RemoveElementByIndex(thread, elements, index, length);
192 arrayList->SetLength(thread, JSTaggedValue(length - 1));
193 }
194
195 return oldValue;
196 }
197
Remove(JSThread * thread,const JSHandle<JSAPIArrayList> & arrayList,const JSHandle<JSTaggedValue> & value)198 bool JSAPIArrayList::Remove(JSThread *thread, const JSHandle<JSAPIArrayList> &arrayList,
199 const JSHandle<JSTaggedValue> &value)
200 {
201 int index = GetIndexOf(thread, arrayList, value);
202 uint32_t length = arrayList->GetSize();
203 if (index >= 0) {
204 JSHandle<TaggedArray> elements(thread, arrayList->GetElements());
205 ASSERT(!elements->IsDictionaryMode());
206 TaggedArray::RemoveElementByIndex(thread, elements, index, length);
207 arrayList->SetLength(thread, JSTaggedValue(length - 1));
208 return true;
209 }
210 return false;
211 }
212
RemoveByRange(JSThread * thread,const JSHandle<JSAPIArrayList> & arrayList,const JSHandle<JSTaggedValue> & value1,const JSHandle<JSTaggedValue> & value2)213 JSTaggedValue JSAPIArrayList::RemoveByRange(JSThread *thread, const JSHandle<JSAPIArrayList> &arrayList,
214 const JSHandle<JSTaggedValue> &value1,
215 const JSHandle<JSTaggedValue> &value2)
216 {
217 int32_t startIndex = JSTaggedValue::ToInt32(thread, value1);
218 int32_t endIndex = JSTaggedValue::ToInt32(thread, value2);
219 int32_t length = arrayList->GetLength().GetInt();
220 int32_t size = length > endIndex ? endIndex : length;
221 if (startIndex < 0 || startIndex >= size) {
222 std::ostringstream oss;
223 oss << "The value of \"fromIndex\" is out of range. It must be >= 0 && <= " << (size - 1)
224 << ". Received value is: " << startIndex;
225 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::RANGE_ERROR, oss.str().c_str());
226 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
227 }
228 if (endIndex <= startIndex || endIndex < 0 || endIndex > length) {
229 std::ostringstream oss;
230 oss << "The value of \"toIndex\" is out of range. It must be >= 0 && <= " << length
231 << ". Received value is: " << endIndex;
232 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::RANGE_ERROR, oss.str().c_str());
233 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
234 }
235
236 int32_t toIndex = endIndex >= length ? length : endIndex;
237
238 JSHandle<TaggedArray> elements(thread, arrayList->GetElements());
239 ASSERT(!elements->IsDictionaryMode());
240 int32_t numMoved = length - toIndex;
241
242 for (int32_t i = 0; i < numMoved; i++) {
243 elements->Set(thread, startIndex + i, elements->Get(static_cast<uint32_t>(endIndex + i)));
244 }
245 int32_t newLength = length - (endIndex - startIndex);
246 arrayList->SetLength(thread, JSTaggedValue(newLength));
247 elements->SetLength(newLength);
248 return JSTaggedValue::Undefined();
249 }
250
ReplaceAllElements(JSThread * thread,const JSHandle<JSTaggedValue> & thisHandle,const JSHandle<JSTaggedValue> & callbackFn,const JSHandle<JSTaggedValue> & thisArg)251 JSTaggedValue JSAPIArrayList::ReplaceAllElements(JSThread *thread, const JSHandle<JSTaggedValue> &thisHandle,
252 const JSHandle<JSTaggedValue> &callbackFn,
253 const JSHandle<JSTaggedValue> &thisArg)
254 {
255 JSHandle<JSAPIArrayList> arrayList = JSHandle<JSAPIArrayList>::Cast(thisHandle);
256 uint32_t length = arrayList->GetSize();
257 JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
258 JSMutableHandle<JSTaggedValue> kValue(thread, JSTaggedValue::Undefined());
259 const int32_t argsLength = 3;
260 JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
261 for (uint32_t k = 0; k < length; k++) {
262 kValue.Update(arrayList->Get(thread, k));
263 key.Update(JSTaggedValue(k));
264 EcmaRuntimeCallInfo *info =
265 EcmaInterpreter::NewRuntimeCallInfo(thread, callbackFn, thisArg, undefined, argsLength);
266 RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception());
267 info->SetCallArg(kValue.GetTaggedValue(), key.GetTaggedValue(), thisHandle.GetTaggedValue());
268 JSTaggedValue funcResult = JSFunction::Call(info);
269 RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, funcResult);
270
271 arrayList->Set(thread, k, funcResult);
272 }
273
274 return JSTaggedValue::Undefined();
275 }
276
Set(JSThread * thread,const uint32_t index,JSTaggedValue value)277 JSTaggedValue JSAPIArrayList::Set(JSThread *thread, const uint32_t index, JSTaggedValue value)
278 {
279 if (index >= GetLength().GetArrayLength()) {
280 std::ostringstream oss;
281 oss << "The value of \"index\" is out of range. It must be >= 0 && <= "
282 << (GetLength().GetArrayLength() - 1) << ". Received value is: " << index;
283 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::RANGE_ERROR, oss.str().c_str());
284 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
285 }
286
287 TaggedArray *elements = TaggedArray::Cast(GetElements().GetTaggedObject());
288 elements->Set(thread, index, value);
289 return JSTaggedValue::Undefined();
290 }
291
SubArrayList(JSThread * thread,const JSHandle<JSAPIArrayList> & arrayList,const JSHandle<JSTaggedValue> & value1,const JSHandle<JSTaggedValue> & value2)292 JSTaggedValue JSAPIArrayList::SubArrayList(JSThread *thread, const JSHandle<JSAPIArrayList> &arrayList,
293 const JSHandle<JSTaggedValue> &value1,
294 const JSHandle<JSTaggedValue> &value2)
295 {
296 int length = arrayList->GetLength().GetInt();
297 int fromIndex = JSTaggedValue::ToInt32(thread, value1);
298 int toIndex = JSTaggedValue::ToInt32(thread, value2);
299 int32_t size = length > toIndex ? toIndex : length;
300 if (fromIndex < 0 || fromIndex >= size) {
301 std::ostringstream oss;
302 oss << "The value of \"fromIndex\" is out of range. It must be >= 0 && <= " << (size - 1)
303 << ". Received value is: " << fromIndex;
304 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::RANGE_ERROR, oss.str().c_str());
305 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
306 }
307 if (toIndex <= fromIndex || toIndex < 0 || toIndex > length) {
308 std::ostringstream oss;
309 oss << "The value of \"toIndex\" is out of range. It must be >= 0 && <= " << length
310 << ". Received value is: " << toIndex;
311 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::RANGE_ERROR, oss.str().c_str());
312 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
313 }
314
315 int endIndex = toIndex >= length - 1 ? length - 1 : toIndex;
316 int newLength = toIndex == length ? length - fromIndex : endIndex - fromIndex;
317 JSHandle<JSAPIArrayList> subArrayList = thread->GetEcmaVM()->GetFactory()->NewJSAPIArrayList(newLength);
318 if (newLength == 0) {
319 return subArrayList.GetTaggedValue();
320 }
321 JSHandle<TaggedArray> elements(thread, arrayList->GetElements());
322 ASSERT(!elements->IsDictionaryMode());
323 subArrayList->SetLength(thread, JSTaggedValue(newLength));
324
325 for (int i = 0; i < newLength; i++) {
326 subArrayList->Set(thread, i, elements->Get(fromIndex + i));
327 }
328
329 return subArrayList.GetTaggedValue();
330 }
331
ForEach(JSThread * thread,const JSHandle<JSTaggedValue> & thisHandle,const JSHandle<JSTaggedValue> & callbackFn,const JSHandle<JSTaggedValue> & thisArg)332 JSTaggedValue JSAPIArrayList::ForEach(JSThread *thread, const JSHandle<JSTaggedValue> &thisHandle,
333 const JSHandle<JSTaggedValue> &callbackFn,
334 const JSHandle<JSTaggedValue> &thisArg)
335 {
336 JSHandle<JSAPIArrayList> arrayList = JSHandle<JSAPIArrayList>::Cast(thisHandle);
337 uint32_t length = arrayList->GetSize();
338 JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
339 JSMutableHandle<JSTaggedValue> kValue(thread, JSTaggedValue::Undefined());
340 const int32_t argsLength = 3;
341 JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
342 for (uint32_t k = 0; k < length; k++) {
343 kValue.Update(arrayList->Get(thread, k));
344 key.Update(JSTaggedValue(k));
345 EcmaRuntimeCallInfo *info =
346 EcmaInterpreter::NewRuntimeCallInfo(thread, callbackFn, thisArg, undefined, argsLength);
347 RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception());
348 info->SetCallArg(kValue.GetTaggedValue(), key.GetTaggedValue(), thisHandle.GetTaggedValue());
349 JSTaggedValue funcResult = JSFunction::Call(info);
350 RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, funcResult);
351 if (length != arrayList->GetSize()) {
352 length = arrayList->GetSize();
353 }
354 }
355
356 return JSTaggedValue::Undefined();
357 }
358
GrowCapacity(const JSThread * thread,const JSHandle<JSAPIArrayList> & obj,uint32_t capacity)359 JSHandle<TaggedArray> JSAPIArrayList::GrowCapacity(const JSThread *thread, const JSHandle<JSAPIArrayList> &obj,
360 uint32_t capacity)
361 {
362 JSHandle<TaggedArray> oldElements(thread, obj->GetElements());
363 ASSERT(!oldElements->IsDictionaryMode());
364 uint32_t oldCapacity = oldElements->GetLength();
365 if (capacity < oldCapacity) {
366 return oldElements;
367 }
368 uint32_t newCapacity = ComputeCapacity(capacity);
369 JSHandle<TaggedArray> newElements =
370 thread->GetEcmaVM()->GetFactory()->CopyArray(oldElements, oldCapacity, newCapacity);
371
372 obj->SetElements(thread, newElements);
373 return newElements;
374 }
375
Has(const JSTaggedValue value) const376 bool JSAPIArrayList::Has(const JSTaggedValue value) const
377 {
378 TaggedArray *elements = TaggedArray::Cast(GetElements().GetTaggedObject());
379 uint32_t length = GetSize();
380 if (length == 0) {
381 return false;
382 }
383
384 for (uint32_t i = 0; i < length; i++) {
385 if (JSTaggedValue::SameValue(elements->Get(i), value)) {
386 return true;
387 }
388 }
389 return false;
390 }
391
OwnKeys(JSThread * thread,const JSHandle<JSAPIArrayList> & obj)392 JSHandle<TaggedArray> JSAPIArrayList::OwnKeys(JSThread *thread, const JSHandle<JSAPIArrayList> &obj)
393 {
394 return JSObject::GetOwnPropertyKeys(thread, JSHandle<JSObject>::Cast(obj));
395 }
396
OwnEnumKeys(JSThread * thread,const JSHandle<JSAPIArrayList> & obj)397 JSHandle<TaggedArray> JSAPIArrayList::OwnEnumKeys(JSThread *thread, const JSHandle<JSAPIArrayList> &obj)
398 {
399 return JSObject::GetOwnEnumPropertyKeys(thread, JSHandle<JSObject>::Cast(obj));
400 }
401
GetOwnProperty(JSThread * thread,const JSHandle<JSAPIArrayList> & obj,const JSHandle<JSTaggedValue> & key)402 bool JSAPIArrayList::GetOwnProperty(JSThread *thread, const JSHandle<JSAPIArrayList> &obj,
403 const JSHandle<JSTaggedValue> &key)
404 {
405 uint32_t index = 0;
406 if (UNLIKELY(!JSTaggedValue::ToElementIndex(key.GetTaggedValue(), &index))) {
407 JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, key.GetTaggedValue());
408 RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false);
409 CString errorMsg =
410 "The type of \"index\" can not obtain attributes of no-number type. Received value is: "
411 + ConvertToString(*result);
412 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str());
413 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, false);
414 }
415
416 uint32_t length = obj->GetLength().GetArrayLength();
417 if (index >= length) {
418 std::ostringstream oss;
419 oss << "The value of \"index\" is out of range. It must be > " << (length - 1)
420 << ". Received value is: " << index;
421 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::RANGE_ERROR, oss.str().c_str());
422 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, false);
423 }
424
425 obj->Get(thread, index);
426 RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false);
427 return true;
428 }
429
GetIteratorObj(JSThread * thread,const JSHandle<JSAPIArrayList> & obj)430 JSTaggedValue JSAPIArrayList::GetIteratorObj(JSThread *thread, const JSHandle<JSAPIArrayList> &obj)
431 {
432 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
433 JSHandle<JSAPIArrayListIterator> iter(factory->NewJSAPIArrayListIterator(obj));
434
435 return iter.GetTaggedValue();
436 }
437
GetProperty(JSThread * thread,const JSHandle<JSAPIArrayList> & obj,const JSHandle<JSTaggedValue> & key)438 OperationResult JSAPIArrayList::GetProperty(JSThread *thread, const JSHandle<JSAPIArrayList> &obj,
439 const JSHandle<JSTaggedValue> &key)
440 {
441 int length = obj->GetLength().GetInt();
442 int index = key->GetInt();
443 if (index < 0 || index >= length) {
444 std::ostringstream oss;
445 oss << "The value of \"index\" is out of range. It must be >= 0 && <= " << (length - 1)
446 << ". Received value is: " << index;
447 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::RANGE_ERROR, oss.str().c_str());
448 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error,
449 OperationResult(thread, JSTaggedValue::Exception(), PropertyMetaData(false)));
450 }
451
452 return OperationResult(thread, obj->Get(thread, index), PropertyMetaData(false));
453 }
454
SetProperty(JSThread * thread,const JSHandle<JSAPIArrayList> & obj,const JSHandle<JSTaggedValue> & key,const JSHandle<JSTaggedValue> & value)455 bool JSAPIArrayList::SetProperty(JSThread *thread, const JSHandle<JSAPIArrayList> &obj,
456 const JSHandle<JSTaggedValue> &key,
457 const JSHandle<JSTaggedValue> &value)
458 {
459 int length = obj->GetLength().GetInt();
460 int index = key->GetInt();
461 if (index < 0 || index >= length) {
462 return false;
463 }
464
465 obj->Set(thread, index, value.GetTaggedValue());
466 return true;
467 }
468 } // namespace panda::ecmascript
469