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(thread).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(thread).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(thread, 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(JSThread * thread)69 uint32_t JSAPIVector::GetCapacity(JSThread *thread)
70 {
71 TaggedArray *elementData = TaggedArray::Cast(GetElements(thread).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(thread));
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(thread).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(thread, 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(JSThread * thread)126 JSTaggedValue JSAPIVector::GetLastElement(JSThread *thread)
127 {
128 uint32_t length = GetSize();
129 if (length == 0) {
130 return JSTaggedValue::Undefined();
131 }
132 TaggedArray *elements = TaggedArray::Cast(GetElements(thread).GetTaggedObject());
133 ASSERT(!elements->IsDictionaryMode());
134 return elements->Get(thread, 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(thread).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(thread, 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(thread));
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(thread).GetTaggedObject());
190 ASSERT(!resElements->IsDictionaryMode());
191 JSTaggedValue oldValue = resElements->Get(thread, index);
192
193 if (index >= 0) {
194 JSHandle<TaggedArray> elements(thread, vector->GetElements(thread));
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(thread).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(thread, 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(thread).GetTaggedObject());
248
249 subVector->SetLength(newLength);
250 for (uint32_t i = 0; i < newLength; i++) {
251 subVector->Set(thread, i, elements->Get(thread, 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(thread);
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(thread));
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(thread).GetTaggedObject());
378 return elements->Get(thread, 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(thread).GetTaggedObject());
384 elements->Set(thread, index, value);
385 return JSTaggedValue::Undefined();
386 }
387
Has(JSThread * thread,const JSTaggedValue & value) const388 bool JSAPIVector::Has(JSThread *thread, const JSTaggedValue &value) const
389 {
390 TaggedArray *elements = TaggedArray::Cast(GetElements(thread).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(thread, elements->Get(thread, 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(thread, 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(thread);
436 TaggedArray *elements = TaggedArray::Cast(obj->GetElements(thread).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(thread));
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(thread));
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(JSThread * thread,const JSHandle<JSAPIVector> & vector)468 JSTaggedValue JSAPIVector::GetFirstElement(JSThread *thread, 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(thread).GetTaggedObject());
475 return elements->Get(thread, 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