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