• 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/global_env_constants-inl.h"
19 #include "ecmascript/interpreter/interpreter.h"
20 #include "ecmascript/js_array.h"
21 #include "ecmascript/js_api/js_api_vector_iterator.h"
22 #include "ecmascript/js_handle.h"
23 #include "ecmascript/js_function.h"
24 #include "ecmascript/js_tagged_number.h"
25 #include "ecmascript/js_tagged_value.h"
26 #include "ecmascript/object_factory.h"
27 
28 namespace panda::ecmascript {
29 static const uint32_t MAX_VALUE = 0x7fffffff;
30 static const uint32_t MAX_ARRAY_SIZE = MAX_VALUE - 8;
Add(JSThread * thread,const JSHandle<JSAPIVector> & vector,const JSHandle<JSTaggedValue> & value)31 bool JSAPIVector::Add(JSThread *thread, const JSHandle<JSAPIVector> &vector, const JSHandle<JSTaggedValue> &value)
32 {
33     uint32_t length = vector->GetSize();
34     GrowCapacity(thread, vector, length + 1);
35 
36     TaggedArray *elements = TaggedArray::Cast(vector->GetElements().GetTaggedObject());
37     ASSERT(!elements->IsDictionaryMode());
38     elements->Set(thread, length, value);
39     vector->SetLength(++length);
40 
41     return true;
42 }
43 
Insert(JSThread * thread,const JSHandle<JSAPIVector> & vector,const JSHandle<JSTaggedValue> & value,int32_t index)44 void JSAPIVector::Insert(JSThread *thread, const JSHandle<JSAPIVector> &vector,
45                          const JSHandle<JSTaggedValue> &value, int32_t index)
46 {
47     uint32_t length = vector->GetSize();
48     if (index < 0 || index > static_cast<int32_t>(length)) {
49         THROW_ERROR(thread, ErrorType::RANGE_ERROR, "the index is out-of-bounds");
50     }
51     GrowCapacity(thread, vector, length + 1);
52 
53     TaggedArray *elements = TaggedArray::Cast(vector->GetElements().GetTaggedObject());
54     ASSERT(!elements->IsDictionaryMode());
55     for (int32_t i = static_cast<int32_t>(length) - 1; i >= index; i--) {
56         elements->Set(thread, i + 1, elements->Get(i));
57     }
58 
59     elements->Set(thread, index, value);
60     vector->SetLength(++length);
61 }
62 
SetLength(JSThread * thread,const JSHandle<JSAPIVector> & vector,uint32_t newSize)63 void JSAPIVector::SetLength(JSThread *thread, const JSHandle<JSAPIVector> &vector, uint32_t newSize)
64 {
65     uint32_t len = vector->GetSize();
66     if (newSize > len) {
67         GrowCapacity(thread, vector, newSize);
68     }
69     vector->SetLength(newSize);
70 }
71 
GetCapacity()72 uint32_t JSAPIVector::GetCapacity()
73 {
74     TaggedArray *elementData = TaggedArray::Cast(GetElements().GetTaggedObject());
75     ASSERT(!elementData->IsDictionaryMode());
76     return elementData->GetLength();
77 }
78 
IncreaseCapacityTo(JSThread * thread,const JSHandle<JSAPIVector> & vector,int32_t newCapacity)79 void JSAPIVector::IncreaseCapacityTo(JSThread *thread, const JSHandle<JSAPIVector> &vector, int32_t newCapacity)
80 {
81     if (newCapacity < 0) {
82         THROW_ERROR(thread, ErrorType::RANGE_ERROR, "An incorrect size was set");
83     }
84 
85     JSHandle<TaggedArray> elementData(thread, vector->GetElements());
86     ASSERT(!elementData->IsDictionaryMode());
87     uint32_t oldCapacity = elementData->GetLength();
88     uint32_t tempCapacity = static_cast<uint32_t>(newCapacity);
89     if (oldCapacity < tempCapacity) {
90         JSHandle<TaggedArray> newElements =
91             thread->GetEcmaVM()->GetFactory()->CopyArray(elementData, oldCapacity, tempCapacity);
92         vector->SetElements(thread, newElements);
93     }
94 }
95 
GetIndexOf(JSThread * thread,const JSHandle<JSAPIVector> & vector,const JSHandle<JSTaggedValue> & obj)96 int32_t JSAPIVector::GetIndexOf(JSThread *thread, const JSHandle<JSAPIVector> &vector,
97                                 const JSHandle<JSTaggedValue> &obj)
98 {
99     return JSAPIVector::GetIndexFrom(thread, vector, obj, 0);
100 }
101 
GetIndexFrom(JSThread * thread,const JSHandle<JSAPIVector> & vector,const JSHandle<JSTaggedValue> & obj,int32_t index)102 int32_t JSAPIVector::GetIndexFrom(JSThread *thread, const JSHandle<JSAPIVector> &vector,
103                                   const JSHandle<JSTaggedValue> &obj, int32_t index)
104 {
105     TaggedArray *elements = TaggedArray::Cast(vector->GetElements().GetTaggedObject());
106     ASSERT(!elements->IsDictionaryMode());
107     uint32_t length = vector->GetSize();
108     if (index < 0) {
109         index = 0;
110     } else if (index >= static_cast<int32_t>(length)) {
111         THROW_RANGE_ERROR_AND_RETURN(thread, "no-such-element", -1);
112     }
113 
114     JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
115     for (uint32_t i = static_cast<uint32_t>(index); i < length; i++) {
116         value.Update(JSTaggedValue(elements->Get(i)));
117         if (JSTaggedValue::StrictEqual(thread, obj, value)) {
118             return i;
119         }
120     }
121     return -1;
122 }
123 
IsEmpty() const124 bool JSAPIVector::IsEmpty() const
125 {
126     return GetSize() == 0;
127 }
128 
GetLastElement()129 JSTaggedValue JSAPIVector::GetLastElement()
130 {
131     uint32_t length = GetSize();
132     if (length == 0) {
133         return JSTaggedValue::Undefined();
134     }
135     TaggedArray *elements = TaggedArray::Cast(GetElements().GetTaggedObject());
136     ASSERT(!elements->IsDictionaryMode());
137     return elements->Get(length - 1);
138 }
139 
GetLastIndexOf(JSThread * thread,const JSHandle<JSAPIVector> & vector,const JSHandle<JSTaggedValue> & obj)140 int32_t JSAPIVector::GetLastIndexOf(JSThread *thread, const JSHandle<JSAPIVector> &vector,
141                                     const JSHandle<JSTaggedValue> &obj)
142 {
143     int32_t index = static_cast<int32_t>(vector->GetSize()) - 1;
144     if (index < 0) {
145         return -1; // vector isEmpty, defalut return -1
146     }
147     return JSAPIVector::GetLastIndexFrom(thread, vector, obj, index);
148 }
149 
GetLastIndexFrom(JSThread * thread,const JSHandle<JSAPIVector> & vector,const JSHandle<JSTaggedValue> & obj,int32_t index)150 int32_t JSAPIVector::GetLastIndexFrom(JSThread *thread, const JSHandle<JSAPIVector> &vector,
151                                       const JSHandle<JSTaggedValue> &obj, int32_t index)
152 {
153     uint32_t length = vector->GetSize();
154     if (index >= static_cast<int32_t>(length)) {
155         THROW_RANGE_ERROR_AND_RETURN(thread, "index-out-of-bounds", -1);
156     } else if (index < 0) {
157         index = 0;
158     }
159     TaggedArray *elements = TaggedArray::Cast(vector->GetElements().GetTaggedObject());
160     ASSERT(!elements->IsDictionaryMode());
161     JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined());
162     for (int32_t i = index; i >= 0; i--) {
163         value.Update(elements->Get(i));
164         if (JSTaggedValue::StrictEqual(thread, obj, value)) {
165             return i;
166         }
167     }
168     return -1;
169 }
170 
Remove(JSThread * thread,const JSHandle<JSAPIVector> & vector,const JSHandle<JSTaggedValue> & obj)171 bool JSAPIVector::Remove(JSThread *thread, const JSHandle<JSAPIVector> &vector, const JSHandle<JSTaggedValue> &obj)
172 {
173     int32_t index = GetIndexOf(thread, vector, obj);
174     uint32_t length = vector->GetSize();
175     if (index >= 0) {
176         JSHandle<TaggedArray> elements(thread, vector->GetElements());
177         ASSERT(!elements->IsDictionaryMode());
178         TaggedArray::RemoveElementByIndex(thread, elements, index, length);
179         length--;
180         vector->SetLength(length);
181         return true;
182     }
183     return false;
184 }
185 
RemoveByIndex(JSThread * thread,const JSHandle<JSAPIVector> & vector,int32_t index)186 JSTaggedValue JSAPIVector::RemoveByIndex(JSThread *thread, const JSHandle<JSAPIVector> &vector, int32_t index)
187 {
188     uint32_t length = vector->GetSize();
189     if (index < 0 || index >= static_cast<int32_t>(length)) {
190         THROW_RANGE_ERROR_AND_RETURN(thread, "the index is out-of-bounds", JSTaggedValue::Exception());
191     }
192     TaggedArray *resElements = TaggedArray::Cast(vector->GetElements().GetTaggedObject());
193     ASSERT(!resElements->IsDictionaryMode());
194     JSTaggedValue oldValue = resElements->Get(index);
195 
196     if (index >= 0) {
197         JSHandle<TaggedArray> elements(thread, vector->GetElements());
198         ASSERT(!elements->IsDictionaryMode());
199         TaggedArray::RemoveElementByIndex(thread, elements, index, length);
200         vector->SetLength(length - 1);
201     }
202     length--;
203     vector->SetLength(length);
204     return oldValue;
205 }
206 
RemoveByRange(JSThread * thread,const JSHandle<JSAPIVector> & vector,int32_t fromIndex,int32_t toIndex)207 JSTaggedValue JSAPIVector::RemoveByRange(JSThread *thread, const JSHandle<JSAPIVector> &vector,
208                                          int32_t fromIndex, int32_t toIndex)
209 {
210     int32_t length = static_cast<int32_t>(vector->GetSize());
211     if (toIndex <= fromIndex) {
212         THROW_RANGE_ERROR_AND_RETURN(thread, "the fromIndex cannot be less than or equal to toIndex",
213                                      JSTaggedValue::Exception());
214     }
215     if (fromIndex < 0 || fromIndex >= length) {
216         THROW_RANGE_ERROR_AND_RETURN(thread, "the fromIndex or the toIndex is out-of-bounds",
217                                      JSTaggedValue::Exception());
218     }
219 
220     int32_t endIndex = toIndex >= length ? length : toIndex;
221     TaggedArray *elements = TaggedArray::Cast(vector->GetElements().GetTaggedObject());
222     ASSERT(!elements->IsDictionaryMode());
223     int32_t numMoved = length - endIndex;
224     for (int32_t i = 0; i < numMoved; i++) {
225         elements->Set(thread, fromIndex + i, elements->Get(endIndex + i));
226     }
227 
228     int32_t newLength = length - (endIndex - fromIndex);
229     elements->SetLength(newLength);
230     vector->SetLength(newLength);
231     return JSTaggedValue::True();
232 }
233 
SubVector(JSThread * thread,const JSHandle<JSAPIVector> & vector,int32_t fromIndex,int32_t toIndex)234 JSHandle<JSAPIVector> JSAPIVector::SubVector(JSThread *thread, const JSHandle<JSAPIVector> &vector,
235                                              int32_t fromIndex, int32_t toIndex)
236 {
237     int32_t length = static_cast<int32_t>(vector->GetSize());
238     if (fromIndex < 0 || toIndex < 0 ||
239         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     uint32_t newLength = static_cast<uint32_t>(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 (uint32_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     uint32_t length = vector->GetSize();
266     std::u16string concatStr;
267     JSMutableHandle<JSTaggedValue> element(thread, JSTaggedValue::Undefined());
268     for (uint32_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     uint32_t length = vector->GetSize();
296     JSTaggedValue key = JSTaggedValue::Undefined();
297     JSMutableHandle<JSTaggedValue> kValue(thread, JSTaggedValue::Undefined());
298     const uint32_t argsLength = NUM_MANDATORY_JSFUNC_ARGS;
299     JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
300 
301     for (uint32_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     uint32_t length = vector->GetSize();
324     JSTaggedValue key = JSTaggedValue::Undefined();
325     JSMutableHandle<JSTaggedValue> kValue(thread, JSTaggedValue::Undefined());
326     const uint32_t argsLength = NUM_MANDATORY_JSFUNC_ARGS;
327     JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
328 
329     for (uint32_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             if (k >= length) {
341                 break;
342             }
343         }
344         vector->Set(thread, k, funcResult);
345     }
346 
347     return JSTaggedValue::Undefined();
348 }
349 
GrowCapacity(JSThread * thread,const JSHandle<JSAPIVector> & vector,uint32_t minCapacity)350 void JSAPIVector::GrowCapacity(JSThread *thread, const JSHandle<JSAPIVector> &vector, uint32_t minCapacity)
351 {
352     JSHandle<TaggedArray> elementData(thread, vector->GetElements());
353     ASSERT(!elementData->IsDictionaryMode());
354     uint32_t curCapacity = elementData->GetLength();
355     if (minCapacity > curCapacity) {
356         uint32_t oldCapacity = elementData->GetLength();
357         // 2 : 2 Capacity doubled
358         uint32_t newCapacity = oldCapacity * 2;
359         if (newCapacity < minCapacity) {
360             newCapacity = minCapacity;
361         }
362 
363         if (newCapacity > MAX_ARRAY_SIZE) {
364             newCapacity = (minCapacity > MAX_ARRAY_SIZE) ? MAX_VALUE : MAX_ARRAY_SIZE;
365         }
366         JSHandle<TaggedArray> newElements =
367             thread->GetEcmaVM()->GetFactory()->CopyArray(elementData, oldCapacity, newCapacity);
368 
369         vector->SetElements(thread, newElements);
370     }
371 }
372 
Get(JSThread * thread,const JSHandle<JSAPIVector> & vector,int32_t index)373 JSTaggedValue JSAPIVector::Get(JSThread *thread, const JSHandle<JSAPIVector> &vector, int32_t index)
374 {
375     uint32_t len = vector->GetSize();
376     if (index < 0 || index >= static_cast<int32_t>(len)) {
377         THROW_RANGE_ERROR_AND_RETURN(thread, "the index is out-of-bounds", JSTaggedValue::Exception());
378     }
379 
380     TaggedArray *elements = TaggedArray::Cast(vector->GetElements().GetTaggedObject());
381     return elements->Get(index);
382 }
383 
Set(JSThread * thread,int32_t index,const JSTaggedValue & value)384 JSTaggedValue JSAPIVector::Set(JSThread *thread, int32_t index, const JSTaggedValue &value)
385 {
386     TaggedArray *elements = TaggedArray::Cast(GetElements().GetTaggedObject());
387     elements->Set(thread, index, value);
388     return JSTaggedValue::Undefined();
389 }
390 
Has(const JSTaggedValue & value) const391 bool JSAPIVector::Has(const JSTaggedValue &value) const
392 {
393     TaggedArray *elements = TaggedArray::Cast(GetElements().GetTaggedObject());
394     uint32_t length = GetSize();
395     if (length == 0) {
396         return false;
397     }
398 
399     for (uint32_t i = 0; i < length; i++) {
400         if (JSTaggedValue::SameValue(elements->Get(i), value)) {
401             return true;
402         }
403     }
404     return false;
405 }
406 
OwnKeys(JSThread * thread,const JSHandle<JSAPIVector> & obj)407 JSHandle<TaggedArray> JSAPIVector::OwnKeys(JSThread *thread, const JSHandle<JSAPIVector> &obj)
408 {
409     return JSObject::GetOwnPropertyKeys(thread, JSHandle<JSObject>::Cast(obj));
410 }
411 
OwnEnumKeys(JSThread * thread,const JSHandle<JSAPIVector> & obj)412 JSHandle<TaggedArray> JSAPIVector::OwnEnumKeys(JSThread *thread, const JSHandle<JSAPIVector> &obj)
413 {
414     return JSObject::GetOwnEnumPropertyKeys(thread, JSHandle<JSObject>::Cast(obj));
415 }
416 
GetOwnProperty(JSThread * thread,const JSHandle<JSAPIVector> & obj,const JSHandle<JSTaggedValue> & key)417 bool JSAPIVector::GetOwnProperty(JSThread *thread, const JSHandle<JSAPIVector> &obj,
418                                  const JSHandle<JSTaggedValue> &key)
419 {
420     uint32_t index = 0;
421     if (UNLIKELY(!JSTaggedValue::ToElementIndex(key.GetTaggedValue(), &index))) {
422         THROW_TYPE_ERROR_AND_RETURN(thread, "Can not obtain attributes of no-number type", false);
423     }
424 
425     uint32_t length = obj->GetSize();
426     if (index >= length) {
427         THROW_RANGE_ERROR_AND_RETURN(thread, "GetOwnProperty index out-of-bounds", false);
428     }
429 
430     JSAPIVector::Get(thread, obj, index);
431     RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false);
432     return true;
433 }
434 
TrimToCurrentLength(JSThread * thread,const JSHandle<JSAPIVector> & obj)435 void JSAPIVector::TrimToCurrentLength(JSThread *thread, const JSHandle<JSAPIVector> &obj)
436 {
437     uint32_t length = obj->GetSize();
438     uint32_t capacity = obj->GetCapacity();
439     TaggedArray *elements = TaggedArray::Cast(obj->GetElements().GetTaggedObject());
440     ASSERT(!elements->IsDictionaryMode());
441     if (capacity > length) {
442         elements->Trim(thread, length);
443     }
444 }
445 
Clear(JSThread * thread,const JSHandle<JSAPIVector> & obj)446 void JSAPIVector::Clear(JSThread *thread, const JSHandle<JSAPIVector> &obj)
447 {
448     uint32_t length = obj->GetLength();
449     JSHandle<TaggedArray> elements(thread, obj->GetElements());
450     ASSERT(!elements->IsDictionaryMode());
451     for (uint32_t i = 0; i < length; ++i) {
452         elements->Set(thread, i, JSTaggedValue::Hole());
453     }
454     obj->SetLength(0);
455 }
456 
Clone(JSThread * thread,const JSHandle<JSAPIVector> & obj)457 JSHandle<JSAPIVector> JSAPIVector::Clone(JSThread *thread, const JSHandle<JSAPIVector> &obj)
458 {
459     JSHandle<TaggedArray> srcElements(thread, obj->GetElements());
460     auto factory = thread->GetEcmaVM()->GetFactory();
461     JSHandle<JSAPIVector> newVector = factory->NewJSAPIVector(0);
462 
463     uint32_t length = obj->GetSize();
464     newVector->SetLength(length);
465 
466     JSHandle<TaggedArray> dstElements = factory->NewAndCopyTaggedArray(srcElements, length, length);
467     newVector->SetElements(thread, dstElements);
468     return newVector;
469 }
470 
GetFirstElement(const JSHandle<JSAPIVector> & vector)471 JSTaggedValue JSAPIVector::GetFirstElement(const JSHandle<JSAPIVector> &vector)
472 {
473     uint32_t length = vector->GetSize();
474     if (length == 0) {
475         return JSTaggedValue::Undefined();
476     }
477     TaggedArray *elements = TaggedArray::Cast(vector->GetElements().GetTaggedObject());
478     return elements->Get(0);
479 }
480 
GetIteratorObj(JSThread * thread,const JSHandle<JSAPIVector> & obj)481 JSTaggedValue JSAPIVector::GetIteratorObj(JSThread *thread, const JSHandle<JSAPIVector> &obj)
482 {
483     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
484     JSHandle<JSAPIVectorIterator> iter(factory->NewJSAPIVectorIterator(obj));
485 
486     return iter.GetTaggedValue();
487 }
488 
GetProperty(JSThread * thread,const JSHandle<JSAPIVector> & obj,const JSHandle<JSTaggedValue> & key)489 OperationResult JSAPIVector::GetProperty(JSThread *thread, const JSHandle<JSAPIVector> &obj,
490                                          const JSHandle<JSTaggedValue> &key)
491 {
492     uint32_t length = obj->GetSize();
493     int index = key->GetInt();
494     if (index < 0 || index >= static_cast<int>(length)) {
495         THROW_RANGE_ERROR_AND_RETURN(thread, "GetProperty index out-of-bounds",
496                                      OperationResult(thread, JSTaggedValue::Exception(), PropertyMetaData(false)));
497     }
498 
499     return OperationResult(thread, JSAPIVector::Get(thread, obj, index), PropertyMetaData(false));
500 }
501 
SetProperty(JSThread * thread,const JSHandle<JSAPIVector> & obj,const JSHandle<JSTaggedValue> & key,const JSHandle<JSTaggedValue> & value)502 bool JSAPIVector::SetProperty(JSThread *thread, const JSHandle<JSAPIVector> &obj,
503                               const JSHandle<JSTaggedValue> &key,
504                               const JSHandle<JSTaggedValue> &value)
505 {
506     uint32_t length = obj->GetSize();
507     int index = key->GetInt();
508     if (index < 0 || index >= static_cast<int>(length)) {
509         return false;
510     }
511 
512     obj->Set(thread, index, value.GetTaggedValue());
513     return true;
514 }
515 } // namespace panda::ecmascript
516