• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_vector.h"
17 
18 #include "ecmascript/interpreter/interpreter.h"
19 #include "ecmascript/js_array.h"
20 #include "ecmascript/js_api/js_api_vector_iterator.h"
21 #include "ecmascript/js_handle.h"
22 #include "ecmascript/js_function.h"
23 #include "ecmascript/js_tagged_number.h"
24 #include "ecmascript/js_tagged_value.h"
25 #include "ecmascript/object_factory.h"
26 
27 namespace panda::ecmascript {
28 static const uint32_t MAX_VALUE = 0x7fffffff;
29 static const uint32_t MAX_ARRAY_SIZE = MAX_VALUE - 8;
Add(JSThread * thread,const JSHandle<JSAPIVector> & vector,const JSHandle<JSTaggedValue> & value)30 bool JSAPIVector::Add(JSThread *thread, const JSHandle<JSAPIVector> &vector, const JSHandle<JSTaggedValue> &value)
31 {
32     int32_t length = vector->GetSize();
33     GrowCapacity(thread, vector, length + 1);
34 
35     TaggedArray *elements = TaggedArray::Cast(vector->GetElements().GetTaggedObject());
36     ASSERT(!elements->IsDictionaryMode());
37     elements->Set(thread, length, value);
38     vector->SetLength(++length);
39 
40     return true;
41 }
42 
Insert(JSThread * thread,const JSHandle<JSAPIVector> & vector,const JSHandle<JSTaggedValue> & value,int32_t index)43 void JSAPIVector::Insert(JSThread *thread, const JSHandle<JSAPIVector> &vector,
44                          const JSHandle<JSTaggedValue> &value, int32_t index)
45 {
46     int32_t length = vector->GetSize();
47     if (index < 0 || index > length) {
48         THROW_ERROR(thread, ErrorType::RANGE_ERROR, "the index is out-of-bounds");
49     }
50     GrowCapacity(thread, vector, length + 1);
51 
52     TaggedArray *elements = TaggedArray::Cast(vector->GetElements().GetTaggedObject());
53     ASSERT(!elements->IsDictionaryMode());
54     for (int32_t i = length - 1; i >= index; i--) {
55         elements->Set(thread, i + 1, elements->Get(i));
56     }
57 
58     elements->Set(thread, index, value);
59     vector->SetLength(++length);
60 }
61 
SetLength(JSThread * thread,const JSHandle<JSAPIVector> & vector,uint32_t newSize)62 void JSAPIVector::SetLength(JSThread *thread, const JSHandle<JSAPIVector> &vector, uint32_t newSize)
63 {
64     uint32_t len = static_cast<uint32_t>(vector->GetSize());
65     if (newSize > len) {
66         GrowCapacity(thread, vector, newSize);
67     }
68     vector->SetLength(newSize);
69 }
70 
GetCapacity()71 uint32_t JSAPIVector::GetCapacity()
72 {
73     TaggedArray *elementData = TaggedArray::Cast(GetElements().GetTaggedObject());
74     ASSERT(!elementData->IsDictionaryMode());
75     return elementData->GetLength();
76 }
77 
IncreaseCapacityTo(JSThread * thread,const JSHandle<JSAPIVector> & vector,int32_t newCapacity)78 void JSAPIVector::IncreaseCapacityTo(JSThread *thread, const JSHandle<JSAPIVector> &vector, int32_t newCapacity)
79 {
80     if (newCapacity < 0) {
81         THROW_ERROR(thread, ErrorType::RANGE_ERROR, "An incorrect size was set");
82     }
83 
84     JSHandle<TaggedArray> elementData(thread, vector->GetElements());
85     ASSERT(!elementData->IsDictionaryMode());
86     uint32_t oldCapacity = elementData->GetLength();
87     uint32_t tempCapacity = static_cast<uint32_t>(newCapacity);
88     if (oldCapacity < tempCapacity) {
89         JSHandle<TaggedArray> newElements =
90             thread->GetEcmaVM()->GetFactory()->CopyArray(elementData, oldCapacity, tempCapacity);
91         vector->SetElements(thread, newElements);
92     }
93 }
94 
GetIndexOf(JSThread * thread,const JSHandle<JSAPIVector> & vector,const JSHandle<JSTaggedValue> & obj)95 int32_t JSAPIVector::GetIndexOf(JSThread *thread, const JSHandle<JSAPIVector> &vector,
96                                 const JSHandle<JSTaggedValue> &obj)
97 {
98     return JSAPIVector::GetIndexFrom(thread, vector, obj, 0);
99 }
100 
GetIndexFrom(JSThread * thread,const JSHandle<JSAPIVector> & vector,const JSHandle<JSTaggedValue> & obj,int32_t index)101 int32_t JSAPIVector::GetIndexFrom(JSThread *thread, const JSHandle<JSAPIVector> &vector,
102                                   const JSHandle<JSTaggedValue> &obj, int32_t index)
103 {
104     TaggedArray *elements = TaggedArray::Cast(vector->GetElements().GetTaggedObject());
105     ASSERT(!elements->IsDictionaryMode());
106     int32_t length = vector->GetSize();
107     if (index < 0) {
108         index = 0;
109     } else if (index >= length) {
110         THROW_RANGE_ERROR_AND_RETURN(thread, "no-such-element", -1);
111     }
112 
113     JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
114     for (int32_t i = index; i < length; i++) {
115         value.Update(JSTaggedValue(elements->Get(i)));
116         if (JSTaggedValue::StrictEqual(thread, obj, value))
117             return i;
118     }
119     return -1;
120 }
121 
IsEmpty() const122 bool JSAPIVector::IsEmpty() const
123 {
124     return GetSize() == 0;
125 }
126 
GetLastElement()127 JSTaggedValue JSAPIVector::GetLastElement()
128 {
129     int32_t length = GetSize();
130     if (length == 0) {
131         return JSTaggedValue::Undefined();
132     }
133     TaggedArray *elements = TaggedArray::Cast(GetElements().GetTaggedObject());
134     ASSERT(!elements->IsDictionaryMode());
135     return elements->Get(length - 1);
136 }
137 
GetLastIndexOf(JSThread * thread,const JSHandle<JSAPIVector> & vector,const JSHandle<JSTaggedValue> & obj)138 int32_t JSAPIVector::GetLastIndexOf(JSThread *thread, const JSHandle<JSAPIVector> &vector,
139                                     const JSHandle<JSTaggedValue> &obj)
140 {
141     int32_t index = vector->GetSize() - 1;
142     if (index < 0) {
143         return -1; // vector isEmpty, defalut return -1
144     }
145     return JSAPIVector::GetLastIndexFrom(thread, vector, obj, index);
146 }
147 
GetLastIndexFrom(JSThread * thread,const JSHandle<JSAPIVector> & vector,const JSHandle<JSTaggedValue> & obj,int32_t index)148 int32_t JSAPIVector::GetLastIndexFrom(JSThread *thread, const JSHandle<JSAPIVector> &vector,
149                                       const JSHandle<JSTaggedValue> &obj, int32_t index)
150 {
151     int32_t length = vector->GetSize();
152     if (index >= length) {
153         THROW_RANGE_ERROR_AND_RETURN(thread, "index-out-of-bounds", -1);
154     } else if (index < 0) {
155         index = 0;
156     }
157     TaggedArray *elements = TaggedArray::Cast(vector->GetElements().GetTaggedObject());
158     ASSERT(!elements->IsDictionaryMode());
159     JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
160     for (int32_t i = index; i >= 0; i--) {
161         value.Update(elements->Get(i));
162         if (JSTaggedValue::StrictEqual(thread, obj, value)) {
163             return i;
164         }
165     }
166     return -1;
167 }
168 
Remove(JSThread * thread,const JSHandle<JSAPIVector> & vector,const JSHandle<JSTaggedValue> & obj)169 bool JSAPIVector::Remove(JSThread *thread, const JSHandle<JSAPIVector> &vector, const JSHandle<JSTaggedValue> &obj)
170 {
171     int32_t index = GetIndexOf(thread, vector, obj);
172     int32_t length = vector->GetSize();
173     if (index >= 0) {
174         JSHandle<TaggedArray> elements(thread, vector->GetElements());
175         ASSERT(!elements->IsDictionaryMode());
176         ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
177         factory->RemoveElementByIndex(elements, index, length);
178         length--;
179         vector->SetLength(length);
180         return true;
181     }
182     return false;
183 }
184 
RemoveByIndex(JSThread * thread,const JSHandle<JSAPIVector> & vector,int32_t index)185 JSTaggedValue JSAPIVector::RemoveByIndex(JSThread *thread, const JSHandle<JSAPIVector> &vector, int32_t index)
186 {
187     int32_t length = vector->GetSize();
188     if (index < 0 || index >= length) {
189         THROW_RANGE_ERROR_AND_RETURN(thread, "the index is out-of-bounds", JSTaggedValue::Exception());
190     }
191     TaggedArray *resElements = TaggedArray::Cast(vector->GetElements().GetTaggedObject());
192     ASSERT(!resElements->IsDictionaryMode());
193     JSTaggedValue oldValue = resElements->Get(index);
194 
195     if (index >= 0) {
196         JSHandle<TaggedArray> elements(thread, vector->GetElements());
197         ASSERT(!elements->IsDictionaryMode());
198         ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
199         factory->RemoveElementByIndex(elements, index, length);
200         vector->SetLength(length - 1);
201     }
202     length--;
203     vector->SetLength(length);
204 
205     return oldValue;
206 }
207 
RemoveByRange(JSThread * thread,const JSHandle<JSAPIVector> & vector,int32_t fromIndex,int32_t toIndex)208 JSTaggedValue JSAPIVector::RemoveByRange(JSThread *thread, const JSHandle<JSAPIVector> &vector,
209                                          int32_t fromIndex, int32_t toIndex)
210 {
211     int32_t length = vector->GetSize();
212     if (toIndex <= fromIndex) {
213         THROW_RANGE_ERROR_AND_RETURN(thread, "the fromIndex cannot be less than or equal to toIndex",
214                                      JSTaggedValue::Exception());
215     }
216     if (fromIndex < 0 || fromIndex >= length) {
217         THROW_RANGE_ERROR_AND_RETURN(thread, "the fromIndex or the toIndex is out-of-bounds",
218                                      JSTaggedValue::Exception());
219     }
220 
221     int32_t endIndex = toIndex >= length ? length : toIndex;
222     TaggedArray *elements = TaggedArray::Cast(vector->GetElements().GetTaggedObject());
223     ASSERT(!elements->IsDictionaryMode());
224     int32_t numMoved = length - endIndex;
225     for (int32_t i = 0; i < numMoved; i++) {
226         elements->Set(thread, fromIndex + i, elements->Get(endIndex + i));
227     }
228 
229     int32_t newLength = length - (endIndex - fromIndex);
230     elements->SetLength(newLength);
231     vector->SetLength(newLength);
232     return JSTaggedValue::True();
233 }
234 
SubVector(JSThread * thread,const JSHandle<JSAPIVector> & vector,int32_t fromIndex,int32_t toIndex)235 JSHandle<JSAPIVector> JSAPIVector::SubVector(JSThread *thread, const JSHandle<JSAPIVector> &vector,
236                                              int32_t fromIndex, int32_t toIndex)
237 {
238     int32_t length = vector->GetSize();
239     if (fromIndex < 0 || toIndex < 0 || fromIndex >= length || toIndex >= length) {
240         THROW_RANGE_ERROR_AND_RETURN(thread, "the fromIndex or the toIndex is out-of-bounds",
241                                      JSHandle<JSAPIVector>());
242     }
243     if (toIndex <= fromIndex) {
244         THROW_RANGE_ERROR_AND_RETURN(thread, "the fromIndex cannot be less than or equal to toIndex",
245                                      JSHandle<JSAPIVector>());
246     }
247 
248     int32_t newLength = toIndex - fromIndex;
249     JSHandle<JSAPIVector> subVector = thread->GetEcmaVM()->GetFactory()->NewJSAPIVector(newLength);
250     TaggedArray *elements = TaggedArray::Cast(vector->GetElements().GetTaggedObject());
251 
252     subVector->SetLength(newLength);
253     for (int32_t i = 0; i < newLength; i++) {
254         subVector->Set(thread, i, elements->Get(fromIndex + i));
255     }
256 
257     return subVector;
258 }
259 
ToString(JSThread * thread,const JSHandle<JSAPIVector> & vector)260 JSTaggedValue JSAPIVector::ToString(JSThread *thread, const JSHandle<JSAPIVector> &vector)
261 {
262     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
263     std::u16string sepHandle = std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> {}.from_bytes(",");
264 
265     int32_t length = vector->GetSize();
266     std::u16string concatStr;
267     JSMutableHandle<JSTaggedValue> element(thread, JSTaggedValue::Undefined());
268     for (int32_t k = 0; k < length; k++) {
269         std::u16string nextStr;
270         element.Update(Get(thread, vector, k));
271         if (!element->IsUndefined() && !element->IsNull()) {
272             JSHandle<EcmaString> nextStringHandle = JSTaggedValue::ToString(thread, element);
273             RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
274             nextStr = EcmaStringAccessor(nextStringHandle).ToU16String();
275         }
276         if (k > 0) {
277             concatStr.append(sepHandle);
278             concatStr.append(nextStr);
279             continue;
280         }
281         concatStr.append(nextStr);
282     }
283 
284     char16_t *char16tData = concatStr.data();
285     auto *uint16tData = reinterpret_cast<uint16_t *>(char16tData);
286     uint32_t u16strSize = concatStr.size();
287     return factory->NewFromUtf16Literal(uint16tData, u16strSize).GetTaggedValue();
288 }
289 
ForEach(JSThread * thread,const JSHandle<JSTaggedValue> & thisHandle,const JSHandle<JSTaggedValue> & callbackFn,const JSHandle<JSTaggedValue> & thisArg)290 JSTaggedValue JSAPIVector::ForEach(JSThread *thread, const JSHandle<JSTaggedValue> &thisHandle,
291                                    const JSHandle<JSTaggedValue> &callbackFn,
292                                    const JSHandle<JSTaggedValue> &thisArg)
293 {
294     JSHandle<JSAPIVector> vector = JSHandle<JSAPIVector>::Cast(thisHandle);
295     int32_t length = vector->GetSize();
296     JSTaggedValue key = JSTaggedValue::Undefined();
297     JSMutableHandle<JSTaggedValue> kValue(thread, JSTaggedValue::Undefined());
298     const int32_t argsLength = NUM_MANDATORY_JSFUNC_ARGS;
299     JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
300 
301     for (int32_t k = 0; k < length; k++) {
302         kValue.Update(Get(thread, vector, k));
303         key = JSTaggedValue(k);
304         EcmaRuntimeCallInfo *info =
305             EcmaInterpreter::NewRuntimeCallInfo(thread, callbackFn, thisArg, undefined, argsLength);
306         RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception());
307         info->SetCallArg(kValue.GetTaggedValue(), key, thisHandle.GetTaggedValue());
308         JSTaggedValue funcResult = JSFunction::Call(info);
309         RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, funcResult);
310         if (length != vector->GetSize()) {  // prevent length change
311             length = vector->GetSize();
312         }
313     }
314 
315     return JSTaggedValue::Undefined();
316 }
317 
ReplaceAllElements(JSThread * thread,const JSHandle<JSTaggedValue> & thisHandle,const JSHandle<JSTaggedValue> & callbackFn,const JSHandle<JSTaggedValue> & thisArg)318 JSTaggedValue JSAPIVector::ReplaceAllElements(JSThread *thread, const JSHandle<JSTaggedValue> &thisHandle,
319                                               const JSHandle<JSTaggedValue> &callbackFn,
320                                               const JSHandle<JSTaggedValue> &thisArg)
321 {
322     JSHandle<JSAPIVector> vector = JSHandle<JSAPIVector>::Cast(thisHandle);
323     int32_t length = vector->GetSize();
324     JSTaggedValue key = JSTaggedValue::Undefined();
325     JSMutableHandle<JSTaggedValue> kValue(thread, JSTaggedValue::Undefined());
326     const int32_t argsLength = NUM_MANDATORY_JSFUNC_ARGS;
327     JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
328 
329     for (int32_t k = 0; k < length; k++) {
330         kValue.Update(Get(thread, vector, k));
331         key = JSTaggedValue(k);
332         EcmaRuntimeCallInfo *info =
333             EcmaInterpreter::NewRuntimeCallInfo(thread, callbackFn, thisArg, undefined, argsLength);
334         RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception());
335         info->SetCallArg(kValue.GetTaggedValue(), key, thisHandle.GetTaggedValue());
336         JSTaggedValue funcResult = JSFunction::Call(info);
337         RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, funcResult);
338         if (length != vector->GetSize()) {  // prevent length change
339             length = vector->GetSize();
340         }
341         vector->Set(thread, k, funcResult);
342     }
343 
344     return JSTaggedValue::Undefined();
345 }
346 
GrowCapacity(JSThread * thread,const JSHandle<JSAPIVector> & vector,uint32_t minCapacity)347 void JSAPIVector::GrowCapacity(JSThread *thread, const JSHandle<JSAPIVector> &vector, uint32_t minCapacity)
348 {
349     JSHandle<TaggedArray> elementData(thread, vector->GetElements());
350     ASSERT(!elementData->IsDictionaryMode());
351     uint32_t curCapacity = elementData->GetLength();
352     if (minCapacity > curCapacity) {
353         uint32_t oldCapacity = elementData->GetLength();
354         // 2 : 2 Capacity doubled
355         uint32_t newCapacity = oldCapacity * 2;
356         if (newCapacity < minCapacity)
357             newCapacity = minCapacity;
358 
359         if (newCapacity > MAX_ARRAY_SIZE) {
360             newCapacity = (minCapacity > MAX_ARRAY_SIZE) ? MAX_VALUE : MAX_ARRAY_SIZE;
361         }
362         JSHandle<TaggedArray> newElements =
363             thread->GetEcmaVM()->GetFactory()->CopyArray(elementData, oldCapacity, newCapacity);
364 
365         vector->SetElements(thread, newElements);
366     }
367 }
368 
Get(JSThread * thread,const JSHandle<JSAPIVector> & vector,int32_t index)369 JSTaggedValue JSAPIVector::Get(JSThread *thread, const JSHandle<JSAPIVector> &vector, int32_t index)
370 {
371     int32_t len = vector->GetSize();
372     if (index < 0 || index >= len) {
373         THROW_RANGE_ERROR_AND_RETURN(thread, "the index is out-of-bounds", JSTaggedValue::Exception());
374     }
375 
376     TaggedArray *elements = TaggedArray::Cast(vector->GetElements().GetTaggedObject());
377     return elements->Get(index);
378 }
379 
Set(JSThread * thread,int32_t index,const JSTaggedValue & value)380 JSTaggedValue JSAPIVector::Set(JSThread *thread, int32_t index, const JSTaggedValue &value)
381 {
382     TaggedArray *elements = TaggedArray::Cast(GetElements().GetTaggedObject());
383     elements->Set(thread, index, value);
384     return JSTaggedValue::Undefined();
385 }
386 
Has(const JSTaggedValue & value) const387 bool JSAPIVector::Has(const JSTaggedValue &value) const
388 {
389     TaggedArray *elements = TaggedArray::Cast(GetElements().GetTaggedObject());
390     int32_t length = GetSize();
391     if (length == 0) {
392         return false;
393     }
394 
395     for (int32_t i = 0; i < length; i++) {
396         if (JSTaggedValue::SameValue(elements->Get(i), value)) {
397             return true;
398         }
399     }
400     return false;
401 }
402 
OwnKeys(JSThread * thread,const JSHandle<JSAPIVector> & obj)403 JSHandle<TaggedArray> JSAPIVector::OwnKeys(JSThread *thread, const JSHandle<JSAPIVector> &obj)
404 {
405     int32_t length = obj->GetSize();
406     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
407     JSHandle<TaggedArray> keys = factory->NewTaggedArray(length);
408 
409     for (int32_t i = 0; i < length; i++) {
410         keys->Set(thread, i, JSTaggedValue(i));
411     }
412 
413     return keys;
414 }
415 
GetOwnProperty(JSThread * thread,const JSHandle<JSAPIVector> & obj,const JSHandle<JSTaggedValue> & key)416 bool JSAPIVector::GetOwnProperty(JSThread *thread, const JSHandle<JSAPIVector> &obj,
417                                  const JSHandle<JSTaggedValue> &key)
418 {
419     uint32_t index = 0;
420     if (UNLIKELY(!JSTaggedValue::ToElementIndex(key.GetTaggedValue(), &index))) {
421         THROW_TYPE_ERROR_AND_RETURN(thread, "Can not obtain attributes of no-number type", false);
422     }
423 
424     uint32_t length = static_cast<uint32_t>(obj->GetSize());
425     if (index >= length) {
426         THROW_RANGE_ERROR_AND_RETURN(thread, "GetOwnProperty index out-of-bounds", false);
427     }
428 
429     JSAPIVector::Get(thread, obj, index);
430     RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false);
431     return true;
432 }
433 
TrimToCurrentLength(JSThread * thread,const JSHandle<JSAPIVector> & obj)434 void JSAPIVector::TrimToCurrentLength(JSThread *thread, const JSHandle<JSAPIVector> &obj)
435 {
436     int32_t length = obj->GetSize();
437     uint32_t capacity = obj->GetCapacity();
438     TaggedArray *elements = TaggedArray::Cast(obj->GetElements().GetTaggedObject());
439     ASSERT(!elements->IsDictionaryMode());
440     if (capacity > static_cast<uint32_t>(length)) {
441         elements->Trim(thread, length);
442     }
443 }
444 
Clear(JSThread * thread,const JSHandle<JSAPIVector> & obj)445 void JSAPIVector::Clear(JSThread *thread, const JSHandle<JSAPIVector> &obj)
446 {
447     int length = obj->GetLength();
448     JSHandle<TaggedArray> elements(thread, obj->GetElements());
449     ASSERT(!elements->IsDictionaryMode());
450     for (int i = 0; i <= length; ++i) {
451         elements->Set(thread, i, JSTaggedValue::Hole());
452     }
453     obj->SetLength(0);
454 }
455 
Clone(JSThread * thread,const JSHandle<JSAPIVector> & obj)456 JSHandle<JSAPIVector> JSAPIVector::Clone(JSThread *thread, const JSHandle<JSAPIVector> &obj)
457 {
458     JSHandle<TaggedArray> srcElements(thread, obj->GetElements());
459     auto factory = thread->GetEcmaVM()->GetFactory();
460     JSHandle<JSAPIVector> newVector = factory->NewJSAPIVector(0);
461 
462     int32_t length = obj->GetSize();
463     newVector->SetLength(length);
464 
465     JSHandle<TaggedArray> dstElements = factory->NewAndCopyTaggedArray(srcElements, length, length);
466     newVector->SetElements(thread, dstElements);
467     return newVector;
468 }
469 
GetFirstElement(const JSHandle<JSAPIVector> & vector)470 JSTaggedValue JSAPIVector::GetFirstElement(const JSHandle<JSAPIVector> &vector)
471 {
472     int32_t length = vector->GetSize();
473     if (length == 0) {
474         return JSTaggedValue::Undefined();
475     }
476     TaggedArray *elements = TaggedArray::Cast(vector->GetElements().GetTaggedObject());
477     return elements->Get(0);
478 }
479 
GetIteratorObj(JSThread * thread,const JSHandle<JSAPIVector> & obj)480 JSTaggedValue JSAPIVector::GetIteratorObj(JSThread *thread, const JSHandle<JSAPIVector> &obj)
481 {
482     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
483     JSHandle<JSAPIVectorIterator> iter(factory->NewJSAPIVectorIterator(obj));
484 
485     return iter.GetTaggedValue();
486 }
487 
GetProperty(JSThread * thread,const JSHandle<JSAPIVector> & obj,const JSHandle<JSTaggedValue> & key)488 OperationResult JSAPIVector::GetProperty(JSThread *thread, const JSHandle<JSAPIVector> &obj,
489                                          const JSHandle<JSTaggedValue> &key)
490 {
491     int length = obj->GetSize();
492     int index = key->GetInt();
493     if (index < 0 || index >= length) {
494         THROW_RANGE_ERROR_AND_RETURN(thread, "GetProperty index out-of-bounds",
495                                      OperationResult(thread, JSTaggedValue::Exception(), PropertyMetaData(false)));
496     }
497 
498     return OperationResult(thread, JSAPIVector::Get(thread, obj, index), PropertyMetaData(false));
499 }
500 
SetProperty(JSThread * thread,const JSHandle<JSAPIVector> & obj,const JSHandle<JSTaggedValue> & key,const JSHandle<JSTaggedValue> & value)501 bool JSAPIVector::SetProperty(JSThread *thread, const JSHandle<JSAPIVector> &obj,
502                               const JSHandle<JSTaggedValue> &key,
503                               const JSHandle<JSTaggedValue> &value)
504 {
505     int length = obj->GetSize();
506     int index = key->GetInt();
507     if (index < 0 || index >= length) {
508         return false;
509     }
510 
511     obj->Set(thread, index, value.GetTaggedValue());
512     return true;
513 }
514 } // namespace panda::ecmascript