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