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 int32_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 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
192 factory->RemoveElementByIndex(elements, index, length);
193 arrayList->SetLength(thread, JSTaggedValue(length - 1));
194 }
195
196 return oldValue;
197 }
198
Remove(JSThread * thread,const JSHandle<JSAPIArrayList> & arrayList,const JSHandle<JSTaggedValue> & value)199 bool JSAPIArrayList::Remove(JSThread *thread, const JSHandle<JSAPIArrayList> &arrayList,
200 const JSHandle<JSTaggedValue> &value)
201 {
202 int index = GetIndexOf(thread, arrayList, value);
203 int length = arrayList->GetSize();
204 if (index >= 0) {
205 JSHandle<TaggedArray> elements(thread, arrayList->GetElements());
206 ASSERT(!elements->IsDictionaryMode());
207 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
208 factory->RemoveElementByIndex(elements, index, length);
209 arrayList->SetLength(thread, JSTaggedValue(length - 1));
210 return true;
211 }
212 return false;
213 }
214
RemoveByRange(JSThread * thread,const JSHandle<JSAPIArrayList> & arrayList,const JSHandle<JSTaggedValue> & value1,const JSHandle<JSTaggedValue> & value2)215 JSTaggedValue JSAPIArrayList::RemoveByRange(JSThread *thread, const JSHandle<JSAPIArrayList> &arrayList,
216 const JSHandle<JSTaggedValue> &value1,
217 const JSHandle<JSTaggedValue> &value2)
218 {
219 int32_t startIndex = JSTaggedValue::ToInt32(thread, value1);
220 int32_t endIndex = JSTaggedValue::ToInt32(thread, value2);
221 int32_t length = arrayList->GetLength().GetInt();
222 int32_t size = length > endIndex ? endIndex : length;
223 if (startIndex < 0 || startIndex >= size) {
224 std::ostringstream oss;
225 oss << "The value of \"fromIndex\" is out of range. It must be >= 0 && <= " << (size - 1)
226 << ". Received value is: " << startIndex;
227 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::RANGE_ERROR, oss.str().c_str());
228 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
229 }
230 if (endIndex <= startIndex || endIndex < 0 || endIndex > length) {
231 std::ostringstream oss;
232 oss << "The value of \"toIndex\" is out of range. It must be >= 0 && <= " << length
233 << ". Received value is: " << endIndex;
234 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::RANGE_ERROR, oss.str().c_str());
235 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
236 }
237
238 int32_t toIndex = endIndex >= length ? length : endIndex;
239
240 JSHandle<TaggedArray> elements(thread, arrayList->GetElements());
241 ASSERT(!elements->IsDictionaryMode());
242 int32_t numMoved = length - toIndex;
243
244 for (int32_t i = 0; i < numMoved; i++) {
245 elements->Set(thread, startIndex + i, elements->Get(static_cast<uint32_t>(endIndex + i)));
246 }
247 int32_t newLength = length - (endIndex - startIndex);
248 arrayList->SetLength(thread, JSTaggedValue(newLength));
249 elements->SetLength(newLength);
250 return JSTaggedValue::Undefined();
251 }
252
ReplaceAllElements(JSThread * thread,const JSHandle<JSTaggedValue> & thisHandle,const JSHandle<JSTaggedValue> & callbackFn,const JSHandle<JSTaggedValue> & thisArg)253 JSTaggedValue JSAPIArrayList::ReplaceAllElements(JSThread *thread, const JSHandle<JSTaggedValue> &thisHandle,
254 const JSHandle<JSTaggedValue> &callbackFn,
255 const JSHandle<JSTaggedValue> &thisArg)
256 {
257 JSHandle<JSAPIArrayList> arrayList = JSHandle<JSAPIArrayList>::Cast(thisHandle);
258 uint32_t length = static_cast<uint32_t>(arrayList->GetSize());
259 JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
260 JSMutableHandle<JSTaggedValue> kValue(thread, JSTaggedValue::Undefined());
261 const int32_t argsLength = 3;
262 JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
263 for (uint32_t k = 0; k < length; k++) {
264 kValue.Update(arrayList->Get(thread, k));
265 key.Update(JSTaggedValue(k));
266 EcmaRuntimeCallInfo *info =
267 EcmaInterpreter::NewRuntimeCallInfo(thread, callbackFn, thisArg, undefined, argsLength);
268 RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception());
269 info->SetCallArg(kValue.GetTaggedValue(), key.GetTaggedValue(), thisHandle.GetTaggedValue());
270 JSTaggedValue funcResult = JSFunction::Call(info);
271 RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, funcResult);
272
273 arrayList->Set(thread, k, funcResult);
274 }
275
276 return JSTaggedValue::Undefined();
277 }
278
Set(JSThread * thread,const uint32_t index,JSTaggedValue value)279 JSTaggedValue JSAPIArrayList::Set(JSThread *thread, const uint32_t index, JSTaggedValue value)
280 {
281 if (index >= GetLength().GetArrayLength()) {
282 std::ostringstream oss;
283 oss << "The value of \"index\" is out of range. It must be >= 0 && <= "
284 << (GetLength().GetArrayLength() - 1) << ". Received value is: " << index;
285 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::RANGE_ERROR, oss.str().c_str());
286 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
287 }
288
289 TaggedArray *elements = TaggedArray::Cast(GetElements().GetTaggedObject());
290 elements->Set(thread, index, value);
291 return JSTaggedValue::Undefined();
292 }
293
SubArrayList(JSThread * thread,const JSHandle<JSAPIArrayList> & arrayList,const JSHandle<JSTaggedValue> & value1,const JSHandle<JSTaggedValue> & value2)294 JSTaggedValue JSAPIArrayList::SubArrayList(JSThread *thread, const JSHandle<JSAPIArrayList> &arrayList,
295 const JSHandle<JSTaggedValue> &value1,
296 const JSHandle<JSTaggedValue> &value2)
297 {
298 int length = arrayList->GetLength().GetInt();
299 int fromIndex = JSTaggedValue::ToInt32(thread, value1);
300 int toIndex = JSTaggedValue::ToInt32(thread, value2);
301 int32_t size = length > toIndex ? toIndex : length;
302 if (fromIndex < 0 || fromIndex >= size) {
303 std::ostringstream oss;
304 oss << "The value of \"fromIndex\" is out of range. It must be >= 0 && <= " << (size - 1)
305 << ". Received value is: " << fromIndex;
306 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::RANGE_ERROR, oss.str().c_str());
307 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
308 }
309 if (toIndex <= fromIndex || toIndex < 0 || toIndex > length) {
310 std::ostringstream oss;
311 oss << "The value of \"toIndex\" is out of range. It must be >= 0 && <= " << length
312 << ". Received value is: " << toIndex;
313 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::RANGE_ERROR, oss.str().c_str());
314 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
315 }
316
317 int endIndex = toIndex >= length - 1 ? length - 1 : toIndex;
318 int newLength = toIndex == length ? length - fromIndex : endIndex - fromIndex;
319 JSHandle<JSAPIArrayList> subArrayList = thread->GetEcmaVM()->GetFactory()->NewJSAPIArrayList(newLength);
320 if (newLength == 0) {
321 return subArrayList.GetTaggedValue();
322 }
323 JSHandle<TaggedArray> elements(thread, arrayList->GetElements());
324 ASSERT(!elements->IsDictionaryMode());
325 subArrayList->SetLength(thread, JSTaggedValue(newLength));
326
327 for (int i = 0; i < newLength; i++) {
328 subArrayList->Set(thread, i, elements->Get(fromIndex + i));
329 }
330
331 return subArrayList.GetTaggedValue();
332 }
333
ForEach(JSThread * thread,const JSHandle<JSTaggedValue> & thisHandle,const JSHandle<JSTaggedValue> & callbackFn,const JSHandle<JSTaggedValue> & thisArg)334 JSTaggedValue JSAPIArrayList::ForEach(JSThread *thread, const JSHandle<JSTaggedValue> &thisHandle,
335 const JSHandle<JSTaggedValue> &callbackFn,
336 const JSHandle<JSTaggedValue> &thisArg)
337 {
338 JSHandle<JSAPIArrayList> arrayList = JSHandle<JSAPIArrayList>::Cast(thisHandle);
339 uint32_t length = static_cast<uint32_t>(arrayList->GetSize());
340 JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
341 JSMutableHandle<JSTaggedValue> kValue(thread, JSTaggedValue::Undefined());
342 const int32_t argsLength = 3;
343 JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
344 for (uint32_t k = 0; k < length; k++) {
345 kValue.Update(arrayList->Get(thread, k));
346 key.Update(JSTaggedValue(k));
347 EcmaRuntimeCallInfo *info =
348 EcmaInterpreter::NewRuntimeCallInfo(thread, callbackFn, thisArg, undefined, argsLength);
349 RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception());
350 info->SetCallArg(kValue.GetTaggedValue(), key.GetTaggedValue(), thisHandle.GetTaggedValue());
351 JSTaggedValue funcResult = JSFunction::Call(info);
352 RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, funcResult);
353 if (static_cast<int>(length) != arrayList->GetSize()) {
354 length = static_cast<uint32_t>(arrayList->GetSize());
355 }
356 }
357
358 return JSTaggedValue::Undefined();
359 }
360
GrowCapacity(const JSThread * thread,const JSHandle<JSAPIArrayList> & obj,uint32_t capacity)361 JSHandle<TaggedArray> JSAPIArrayList::GrowCapacity(const JSThread *thread, const JSHandle<JSAPIArrayList> &obj,
362 uint32_t capacity)
363 {
364 JSHandle<TaggedArray> oldElements(thread, obj->GetElements());
365 ASSERT(!oldElements->IsDictionaryMode());
366 uint32_t oldCapacity = oldElements->GetLength();
367 if (capacity < oldCapacity) {
368 return oldElements;
369 }
370 uint32_t newCapacity = ComputeCapacity(capacity);
371 JSHandle<TaggedArray> newElements =
372 thread->GetEcmaVM()->GetFactory()->CopyArray(oldElements, oldCapacity, newCapacity);
373
374 obj->SetElements(thread, newElements);
375 return newElements;
376 }
377
Has(const JSTaggedValue value) const378 bool JSAPIArrayList::Has(const JSTaggedValue value) const
379 {
380 TaggedArray *elements = TaggedArray::Cast(GetElements().GetTaggedObject());
381 int32_t length = GetSize();
382 if (length == 0) {
383 return false;
384 }
385
386 for (int32_t i = 0; i < length; i++) {
387 if (JSTaggedValue::SameValue(elements->Get(i), value)) {
388 return true;
389 }
390 }
391 return false;
392 }
393
OwnKeys(JSThread * thread,const JSHandle<JSAPIArrayList> & obj)394 JSHandle<TaggedArray> JSAPIArrayList::OwnKeys(JSThread *thread, const JSHandle<JSAPIArrayList> &obj)
395 {
396 uint32_t length = obj->GetLength().GetArrayLength();
397 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
398 JSHandle<TaggedArray> keys = factory->NewTaggedArray(length);
399
400 for (uint32_t i = 0; i < length; i++) {
401 keys->Set(thread, i, JSTaggedValue(i));
402 }
403
404 return keys;
405 }
406
GetOwnProperty(JSThread * thread,const JSHandle<JSAPIArrayList> & obj,const JSHandle<JSTaggedValue> & key)407 bool JSAPIArrayList::GetOwnProperty(JSThread *thread, const JSHandle<JSAPIArrayList> &obj,
408 const JSHandle<JSTaggedValue> &key)
409 {
410 uint32_t index = 0;
411 if (UNLIKELY(!JSTaggedValue::ToElementIndex(key.GetTaggedValue(), &index))) {
412 JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, key.GetTaggedValue());
413 CString errorMsg =
414 "The type of \"index\" can not obtain attributes of no-number type. Received value is: "
415 + ConvertToString(*result);
416 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str());
417 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, false);
418 }
419
420 uint32_t length = obj->GetLength().GetArrayLength();
421 if (index >= length) {
422 std::ostringstream oss;
423 oss << "The value of \"index\" is out of range. It must be > " << (length - 1)
424 << ". Received value is: " << index;
425 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::RANGE_ERROR, oss.str().c_str());
426 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, false);
427 }
428
429 obj->Get(thread, index);
430 RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false);
431 return true;
432 }
433
GetIteratorObj(JSThread * thread,const JSHandle<JSAPIArrayList> & obj)434 JSTaggedValue JSAPIArrayList::GetIteratorObj(JSThread *thread, const JSHandle<JSAPIArrayList> &obj)
435 {
436 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
437 JSHandle<JSAPIArrayListIterator> iter(factory->NewJSAPIArrayListIterator(obj));
438
439 return iter.GetTaggedValue();
440 }
441
GetProperty(JSThread * thread,const JSHandle<JSAPIArrayList> & obj,const JSHandle<JSTaggedValue> & key)442 OperationResult JSAPIArrayList::GetProperty(JSThread *thread, const JSHandle<JSAPIArrayList> &obj,
443 const JSHandle<JSTaggedValue> &key)
444 {
445 int length = obj->GetLength().GetInt();
446 int index = key->GetInt();
447 if (index < 0 || index >= length) {
448 std::ostringstream oss;
449 oss << "The value of \"index\" is out of range. It must be >= 0 && <= " << (length - 1)
450 << ". Received value is: " << index;
451 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::RANGE_ERROR, oss.str().c_str());
452 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error,
453 OperationResult(thread, JSTaggedValue::Exception(), PropertyMetaData(false)));
454 }
455
456 return OperationResult(thread, obj->Get(thread, index), PropertyMetaData(false));
457 }
458
SetProperty(JSThread * thread,const JSHandle<JSAPIArrayList> & obj,const JSHandle<JSTaggedValue> & key,const JSHandle<JSTaggedValue> & value)459 bool JSAPIArrayList::SetProperty(JSThread *thread, const JSHandle<JSAPIArrayList> &obj,
460 const JSHandle<JSTaggedValue> &key,
461 const JSHandle<JSTaggedValue> &value)
462 {
463 int length = obj->GetLength().GetInt();
464 int index = key->GetInt();
465 if (index < 0 || index >= length) {
466 return false;
467 }
468
469 obj->Set(thread, index, value.GetTaggedValue());
470 return true;
471 }
472 } // namespace panda::ecmascript
473