• 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/containers/containers_vector.h"
17 
18 #include "ecmascript/base/array_helper.h"
19 #include "ecmascript/js_array.h"
20 #include "ecmascript/js_api/js_api_vector.h"
21 #include "ecmascript/tagged_array-inl.h"
22 
23 namespace panda::ecmascript::containers {
VectorConstructor(EcmaRuntimeCallInfo * argv)24 JSTaggedValue ContainersVector::VectorConstructor(EcmaRuntimeCallInfo *argv)
25 {
26     ASSERT(argv != nullptr);
27     JSThread *thread = argv->GetThread();
28     BUILTINS_API_TRACE(thread, Vector, Constructor);
29     [[maybe_unused]] EcmaHandleScope handleScope(thread);
30 
31     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
32     JSHandle<JSTaggedValue> newTarget = GetNewTarget(argv);
33     if (newTarget->IsUndefined()) {
34         THROW_TYPE_ERROR_AND_RETURN(thread, "new target can't be undefined", JSTaggedValue::Exception());
35     }
36     JSHandle<JSTaggedValue> constructor = GetConstructor(argv);
37     JSHandle<JSAPIVector> obj =
38         JSHandle<JSAPIVector>(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(constructor), newTarget));
39     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
40     JSHandle<TaggedArray> newTaggedArray = factory->NewTaggedArray(JSAPIVector::DEFAULT_CAPACITY_LENGTH);
41     obj->SetElements(thread, newTaggedArray);
42 
43     return obj.GetTaggedValue();
44 }
45 
Add(EcmaRuntimeCallInfo * argv)46 JSTaggedValue ContainersVector::Add(EcmaRuntimeCallInfo *argv)
47 {
48     ASSERT(argv != nullptr);
49     JSThread *thread = argv->GetThread();
50     BUILTINS_API_TRACE(thread, Vector, Add);
51     [[maybe_unused]] EcmaHandleScope handleScope(thread);
52 
53     JSHandle<JSTaggedValue> self = GetThis(argv);
54     if (!self->IsJSAPIVector()) {
55         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIVector()) {
56             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
57         } else {
58             THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPIVector", JSTaggedValue::Exception());
59         }
60     }
61     JSHandle<JSTaggedValue> value(GetCallArg(argv, 0));
62     JSAPIVector::Add(thread, JSHandle<JSAPIVector>::Cast(self), value);
63     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
64 
65     return JSTaggedValue::True();
66 }
67 
Insert(EcmaRuntimeCallInfo * argv)68 JSTaggedValue ContainersVector::Insert(EcmaRuntimeCallInfo *argv)
69 {
70     ASSERT(argv != nullptr);
71     JSThread *thread = argv->GetThread();
72     BUILTINS_API_TRACE(thread, Vector, Insert);
73     [[maybe_unused]] EcmaHandleScope handleScope(thread);
74 
75     JSHandle<JSTaggedValue> self = GetThis(argv);
76     if (!self->IsJSAPIVector()) {
77         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIVector()) {
78             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
79         } else {
80             THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPIVector", JSTaggedValue::Exception());
81         }
82     }
83     JSHandle<JSTaggedValue> value = GetCallArg(argv, 0);
84     JSHandle<JSTaggedValue> index = GetCallArg(argv, 1);
85     if (!index->IsNumber()) {
86         THROW_TYPE_ERROR_AND_RETURN(thread, "The passed in index needs to be number", JSTaggedValue::Exception());
87     }
88     int32_t indexInt = JSTaggedValue::ToInt32(thread, index);
89     JSAPIVector::Insert(thread, JSHandle<JSAPIVector>::Cast(self), value, indexInt);
90     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
91 
92     return JSTaggedValue::Undefined();
93 }
94 
SetLength(EcmaRuntimeCallInfo * argv)95 JSTaggedValue ContainersVector::SetLength(EcmaRuntimeCallInfo *argv)
96 {
97     ASSERT(argv != nullptr);
98     JSThread *thread = argv->GetThread();
99     BUILTINS_API_TRACE(thread, Vector, SetLength);
100     [[maybe_unused]] EcmaHandleScope handleScope(thread);
101 
102     JSHandle<JSTaggedValue> self = GetThis(argv);
103     if (!self->IsJSAPIVector()) {
104         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIVector()) {
105             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
106         } else {
107             THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPIVector", JSTaggedValue::Exception());
108         }
109     }
110     JSHandle<JSTaggedValue> newSize = GetCallArg(argv, 0);
111     if (!newSize->IsNumber()) {
112         THROW_TYPE_ERROR_AND_RETURN(thread, "The passed in parameter needs to be number", JSTaggedValue::Exception());
113     }
114     if (newSize->GetNumber() < 0) {
115         THROW_RANGE_ERROR_AND_RETURN(thread, "An incorrect size was set",  JSTaggedValue::Exception());
116     }
117     JSAPIVector::SetLength(thread, JSHandle<JSAPIVector>::Cast(self), JSTaggedValue::ToUint32(thread, newSize));
118     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
119     return JSTaggedValue::Undefined();
120 }
121 
GetCapacity(EcmaRuntimeCallInfo * argv)122 JSTaggedValue ContainersVector::GetCapacity(EcmaRuntimeCallInfo *argv)
123 {
124     ASSERT(argv != nullptr);
125     JSThread *thread = argv->GetThread();
126     BUILTINS_API_TRACE(thread, Vector, GetCapacity);
127     [[maybe_unused]] EcmaHandleScope handleScope(thread);
128 
129     JSHandle<JSTaggedValue> self = GetThis(argv);
130     if (!self->IsJSAPIVector()) {
131         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIVector()) {
132             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
133         } else {
134             THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPIVector", JSTaggedValue::Exception());
135         }
136     }
137     uint32_t capacity = JSHandle<JSAPIVector>::Cast(self)->GetCapacity();
138     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
139 
140     return JSTaggedValue(capacity);
141 }
142 
IncreaseCapacityTo(EcmaRuntimeCallInfo * argv)143 JSTaggedValue ContainersVector::IncreaseCapacityTo(EcmaRuntimeCallInfo *argv)
144 {
145     ASSERT(argv != nullptr);
146     JSThread *thread = argv->GetThread();
147     BUILTINS_API_TRACE(thread, Vector, IncreaseCapacityTo);
148     [[maybe_unused]] EcmaHandleScope handleScope(thread);
149 
150     JSHandle<JSTaggedValue> self = GetThis(argv);
151     if (!self->IsJSAPIVector()) {
152         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIVector()) {
153             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
154         } else {
155             THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPIVector", JSTaggedValue::Exception());
156         }
157     }
158     JSHandle<JSTaggedValue> newCapacity = GetCallArg(argv, 0);
159     if (!newCapacity->IsNumber()) {
160         THROW_TYPE_ERROR_AND_RETURN(thread, "The passed in parameter needs to be number", JSTaggedValue::Exception());
161     }
162     JSAPIVector::IncreaseCapacityTo(thread,
163                                     JSHandle<JSAPIVector>::Cast(self),
164                                     JSTaggedValue::ToInt32(thread, newCapacity));
165     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
166 
167     return JSTaggedValue::Undefined();
168 }
169 
Get(EcmaRuntimeCallInfo * argv)170 JSTaggedValue ContainersVector::Get(EcmaRuntimeCallInfo *argv)
171 {
172     ASSERT(argv != nullptr);
173     JSThread *thread = argv->GetThread();
174     BUILTINS_API_TRACE(thread, Vector, Get);
175     [[maybe_unused]] EcmaHandleScope handleScope(thread);
176 
177     JSHandle<JSTaggedValue> self = GetThis(argv);
178     if (!self->IsJSAPIVector()) {
179         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIVector()) {
180             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
181         } else {
182             THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPIVector", JSTaggedValue::Exception());
183         }
184     }
185     JSHandle<JSTaggedValue> index = GetCallArg(argv, 0);
186     if (!index->IsNumber()) {
187         THROW_TYPE_ERROR_AND_RETURN(thread, "The passed in index needs to be number", JSTaggedValue::Exception());
188     }
189     int32_t indexInt = JSTaggedValue::ToInt32(thread, index);
190     JSTaggedValue value = JSAPIVector::Get(thread, JSHandle<JSAPIVector>::Cast(self), indexInt);
191     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
192 
193     return value;
194 }
195 
GetIndexOf(EcmaRuntimeCallInfo * argv)196 JSTaggedValue ContainersVector::GetIndexOf(EcmaRuntimeCallInfo *argv)
197 {
198     ASSERT(argv != nullptr);
199     JSThread *thread = argv->GetThread();
200     BUILTINS_API_TRACE(thread, Vector, GetIndexOf);
201     [[maybe_unused]] EcmaHandleScope handleScope(thread);
202 
203     JSHandle<JSTaggedValue> self = GetThis(argv);
204     if (!self->IsJSAPIVector()) {
205         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIVector()) {
206             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
207         } else {
208             THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPIVector", JSTaggedValue::Exception());
209         }
210     }
211     JSHandle<JSTaggedValue> element = GetCallArg(argv, 0);
212     int index = JSAPIVector::GetIndexOf(thread, JSHandle<JSAPIVector>::Cast(self), element);
213     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
214 
215     return JSTaggedValue(index);
216 }
217 
GetIndexFrom(EcmaRuntimeCallInfo * argv)218 JSTaggedValue ContainersVector::GetIndexFrom(EcmaRuntimeCallInfo *argv)
219 {
220     ASSERT(argv != nullptr);
221     JSThread *thread = argv->GetThread();
222     BUILTINS_API_TRACE(thread, Vector, GetIndexFrom);
223     [[maybe_unused]] EcmaHandleScope handleScope(thread);
224 
225     JSHandle<JSTaggedValue> self = GetThis(argv);
226     if (!self->IsJSAPIVector()) {
227         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIVector()) {
228             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
229         } else {
230             THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPIVector", JSTaggedValue::Exception());
231         }
232     }
233     JSHandle<JSTaggedValue> element = GetCallArg(argv, 0);
234     JSHandle<JSTaggedValue> index = GetCallArg(argv, 1);
235     if (!index->IsNumber()) {
236         THROW_TYPE_ERROR_AND_RETURN(thread, "The passed in index needs to be number", JSTaggedValue::Exception());
237     }
238     int32_t indexInt = JSTaggedValue::ToInt32(thread, index);
239     int indexOut = JSAPIVector::GetIndexFrom(thread, JSHandle<JSAPIVector>::Cast(self),
240                                              element, indexInt);
241     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
242 
243     return JSTaggedValue(indexOut);
244 }
245 
IsEmpty(EcmaRuntimeCallInfo * argv)246 JSTaggedValue ContainersVector::IsEmpty(EcmaRuntimeCallInfo *argv)
247 {
248     ASSERT(argv != nullptr);
249     JSThread *thread = argv->GetThread();
250     BUILTINS_API_TRACE(thread, Vector, IsEmpty);
251     [[maybe_unused]] EcmaHandleScope handleScope(thread);
252 
253     JSHandle<JSTaggedValue> self = GetThis(argv);
254     if (!self->IsJSAPIVector()) {
255         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIVector()) {
256             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
257         } else {
258             THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPIVector", JSTaggedValue::Exception());
259         }
260     }
261     bool ret = JSHandle<JSAPIVector>::Cast(self)->IsEmpty();
262 
263     return GetTaggedBoolean(ret);
264 }
265 
GetLastElement(EcmaRuntimeCallInfo * argv)266 JSTaggedValue ContainersVector::GetLastElement(EcmaRuntimeCallInfo *argv)
267 {
268     ASSERT(argv != nullptr);
269     JSThread *thread = argv->GetThread();
270     BUILTINS_API_TRACE(thread, Vector, GetLastElement);
271     [[maybe_unused]] EcmaHandleScope handleScope(thread);
272 
273     JSHandle<JSTaggedValue> self = GetThis(argv);
274     if (!self->IsJSAPIVector()) {
275         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIVector()) {
276             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
277         } else {
278             THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPIVector", JSTaggedValue::Exception());
279         }
280     }
281     JSTaggedValue value = JSHandle<JSAPIVector>::Cast(self)->GetLastElement();
282 
283     return value;
284 }
285 
GetLastIndexOf(EcmaRuntimeCallInfo * argv)286 JSTaggedValue ContainersVector::GetLastIndexOf(EcmaRuntimeCallInfo *argv)
287 {
288     ASSERT(argv != nullptr);
289     JSThread *thread = argv->GetThread();
290     BUILTINS_API_TRACE(thread, Vector, GetLastIndexOf);
291     [[maybe_unused]] EcmaHandleScope handleScope(thread);
292 
293     JSHandle<JSTaggedValue> self = GetThis(argv);
294     if (!self->IsJSAPIVector()) {
295         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIVector()) {
296             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
297         } else {
298             THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPIVector", JSTaggedValue::Exception());
299         }
300     }
301     JSHandle<JSTaggedValue> element = GetCallArg(argv, 0);
302     int index = JSAPIVector::GetLastIndexOf(thread, JSHandle<JSAPIVector>::Cast(self), element);
303     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
304 
305     return JSTaggedValue(index);
306 }
307 
GetLastIndexFrom(EcmaRuntimeCallInfo * argv)308 JSTaggedValue ContainersVector::GetLastIndexFrom(EcmaRuntimeCallInfo *argv)
309 {
310     ASSERT(argv != nullptr);
311     JSThread *thread = argv->GetThread();
312     BUILTINS_API_TRACE(thread, Vector, GetLastIndexFrom);
313     [[maybe_unused]] EcmaHandleScope handleScope(thread);
314 
315     JSHandle<JSTaggedValue> self = GetThis(argv);
316     if (!self->IsJSAPIVector()) {
317         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIVector()) {
318             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
319         } else {
320             THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPIVector", JSTaggedValue::Exception());
321         }
322     }
323     JSHandle<JSTaggedValue> element = GetCallArg(argv, 0);
324     JSHandle<JSTaggedValue> index = GetCallArg(argv, 1);
325     if (!index->IsNumber()) {
326         THROW_TYPE_ERROR_AND_RETURN(thread, "The passed in index needs to be number", JSTaggedValue::Exception());
327     }
328     int32_t indexInt = JSTaggedValue::ToInt32(thread, index);
329     int indexOut = JSAPIVector::GetLastIndexFrom(thread, JSHandle<JSAPIVector>::Cast(self),
330                                                  element, indexInt);
331     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
332     return JSTaggedValue(indexOut);
333 }
334 
Remove(EcmaRuntimeCallInfo * argv)335 JSTaggedValue ContainersVector::Remove(EcmaRuntimeCallInfo *argv)
336 {
337     ASSERT(argv != nullptr);
338     JSThread *thread = argv->GetThread();
339     BUILTINS_API_TRACE(thread, Vector, Remove);
340     [[maybe_unused]] EcmaHandleScope handleScope(thread);
341 
342     JSHandle<JSTaggedValue> self = GetThis(argv);
343 
344     if (!self->IsJSAPIVector()) {
345         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIVector()) {
346             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
347         } else {
348             THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPIVector", JSTaggedValue::Exception());
349         }
350     }
351 
352     JSHandle<JSTaggedValue> element = GetCallArg(argv, 0);
353     bool ret = JSAPIVector::Remove(thread, JSHandle<JSAPIVector>::Cast(self), element);
354     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
355     return GetTaggedBoolean(ret);
356 }
357 
RemoveByIndex(EcmaRuntimeCallInfo * argv)358 JSTaggedValue ContainersVector::RemoveByIndex(EcmaRuntimeCallInfo *argv)
359 {
360     ASSERT(argv != nullptr);
361     JSThread *thread = argv->GetThread();
362     BUILTINS_API_TRACE(thread, Vector, RemoveByIndex);
363     [[maybe_unused]] EcmaHandleScope handleScope(thread);
364 
365     JSHandle<JSTaggedValue> self = GetThis(argv);
366     if (!self->IsJSAPIVector()) {
367         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIVector()) {
368             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
369         } else {
370             THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPIVector", JSTaggedValue::Exception());
371         }
372     }
373     JSHandle<JSTaggedValue> index = GetCallArg(argv, 0);
374     if (!index->IsNumber()) {
375         THROW_TYPE_ERROR_AND_RETURN(thread, "The passed in index needs to be number", JSTaggedValue::Exception());
376     }
377     JSTaggedValue value =
378         JSAPIVector::RemoveByIndex(thread, JSHandle<JSAPIVector>::Cast(self), JSTaggedValue::ToInt32(thread, index));
379     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
380     return value;
381 }
382 
RemoveByRange(EcmaRuntimeCallInfo * argv)383 JSTaggedValue ContainersVector::RemoveByRange(EcmaRuntimeCallInfo *argv)
384 {
385     ASSERT(argv != nullptr);
386     JSThread *thread = argv->GetThread();
387     BUILTINS_API_TRACE(thread, Vector, RemoveByRange);
388     [[maybe_unused]] EcmaHandleScope handleScope(thread);
389 
390     JSHandle<JSTaggedValue> self = GetThis(argv);
391     if (!self->IsJSAPIVector()) {
392         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIVector()) {
393             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
394         } else {
395             THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPIVector", JSTaggedValue::Exception());
396         }
397     }
398     JSHandle<JSTaggedValue> fromIndex = GetCallArg(argv, 0);
399     JSHandle<JSTaggedValue> toIndex = GetCallArg(argv, 1);
400     if (!fromIndex->IsNumber() || !toIndex->IsNumber()) {
401         THROW_TYPE_ERROR_AND_RETURN(thread, "The passed in parameter needs to be number", JSTaggedValue::Exception());
402     }
403 
404     JSAPIVector::RemoveByRange(thread, JSHandle<JSAPIVector>::Cast(self),
405                                JSTaggedValue::ToInt32(thread, fromIndex),
406                                JSTaggedValue::ToInt32(thread, toIndex));
407     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
408     return JSTaggedValue::Undefined();
409 }
410 
Set(EcmaRuntimeCallInfo * argv)411 JSTaggedValue ContainersVector::Set(EcmaRuntimeCallInfo *argv)
412 {
413     ASSERT(argv != nullptr);
414     JSThread *thread = argv->GetThread();
415     BUILTINS_API_TRACE(thread, Vector, Set);
416     [[maybe_unused]] EcmaHandleScope handleScope(thread);
417 
418     JSHandle<JSTaggedValue> self = GetThis(argv);
419     if (!self->IsJSAPIVector()) {
420         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIVector()) {
421             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
422         } else {
423             THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPIVector", JSTaggedValue::Exception());
424         }
425     }
426     JSHandle<JSTaggedValue> index = GetCallArg(argv, 0);
427     JSHandle<JSTaggedValue> element = GetCallArg(argv, 1);
428     if (!index->IsNumber()) {
429         THROW_TYPE_ERROR_AND_RETURN(thread, "The passed in index needs to be number", JSTaggedValue::Exception());
430     }
431 
432     int32_t indexInt = JSTaggedValue::ToInt32(thread, index);
433     int32_t len = static_cast<int>(JSHandle<JSAPIVector>::Cast(self)->GetSize());
434     if (indexInt < 0 || indexInt >= len) {
435         THROW_RANGE_ERROR_AND_RETURN(thread, "the index is out-of-bounds", JSTaggedValue::Exception());
436     }
437     JSTaggedValue value = JSHandle<JSAPIVector>::Cast(self)->Set(thread,
438                                                                  indexInt,
439                                                                  element.GetTaggedValue());
440     return value;
441 }
442 
SubVector(EcmaRuntimeCallInfo * argv)443 JSTaggedValue ContainersVector::SubVector(EcmaRuntimeCallInfo *argv)
444 {
445     ASSERT(argv != nullptr);
446     JSThread *thread = argv->GetThread();
447     BUILTINS_API_TRACE(thread, Vector, SubVector);
448     [[maybe_unused]] EcmaHandleScope handleScope(thread);
449 
450     JSHandle<JSTaggedValue> self = GetThis(argv);
451     if (!self->IsJSAPIVector()) {
452         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIVector()) {
453             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
454         } else {
455             THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPIVector", JSTaggedValue::Exception());
456         }
457     }
458     JSHandle<JSTaggedValue> fromIndex = GetCallArg(argv, 0);
459     JSHandle<JSTaggedValue> toIndex = GetCallArg(argv, 1);
460     if (!fromIndex->IsNumber() || !toIndex->IsNumber()) {
461         THROW_TYPE_ERROR_AND_RETURN(thread, "The passed in parameter needs to be number", JSTaggedValue::Exception());
462     }
463     JSHandle<JSAPIVector> subVector = JSAPIVector::SubVector(thread, JSHandle<JSAPIVector>::Cast(self),
464                                                              JSTaggedValue::ToInt32(thread, fromIndex),
465                                                              JSTaggedValue::ToInt32(thread, toIndex));
466     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
467     return subVector.GetTaggedValue();
468 }
469 
ToString(EcmaRuntimeCallInfo * argv)470 JSTaggedValue ContainersVector::ToString(EcmaRuntimeCallInfo *argv)
471 {
472     ASSERT(argv != nullptr);
473     JSThread *thread = argv->GetThread();
474     BUILTINS_API_TRACE(thread, Vector, ToString);
475     [[maybe_unused]] EcmaHandleScope handleScope(thread);
476 
477     JSHandle<JSTaggedValue> self = GetThis(argv);
478     if (!self->IsJSAPIVector()) {
479         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIVector()) {
480             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
481         } else {
482             THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPIVector", JSTaggedValue::Exception());
483         }
484     }
485 
486     JSTaggedValue value = JSAPIVector::ToString(thread, JSHandle<JSAPIVector>::Cast(self));
487     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
488     return value;
489 }
490 
GetSize(EcmaRuntimeCallInfo * argv)491 JSTaggedValue ContainersVector::GetSize(EcmaRuntimeCallInfo *argv)
492 {
493     ASSERT(argv != nullptr);
494     JSThread *thread = argv->GetThread();
495     BUILTINS_API_TRACE(thread, Vector, GetSize);
496     [[maybe_unused]] EcmaHandleScope handleScope(thread);
497     JSHandle<JSTaggedValue> self = GetThis(argv);
498 
499     if (!self->IsJSAPIVector()) {
500         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIVector()) {
501             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
502         } else {
503             THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPIVector", JSTaggedValue::Exception());
504         }
505     }
506 
507     uint32_t length = JSHandle<JSAPIVector>::Cast(self)->GetSize();
508     return JSTaggedValue(length);
509 }
510 
ForEach(EcmaRuntimeCallInfo * argv)511 JSTaggedValue ContainersVector::ForEach(EcmaRuntimeCallInfo *argv)
512 {
513     ASSERT(argv != nullptr);
514     JSThread *thread = argv->GetThread();
515     BUILTINS_API_TRACE(thread, Vector, ForEach);
516     [[maybe_unused]] EcmaHandleScope handleScope(thread);
517     // Let O be ToObject(this value).
518     JSHandle<JSTaggedValue> thisHandle = GetThis(argv); // JSAPIVector
519 
520     if (!thisHandle->IsJSAPIVector()) {
521         if (thisHandle->IsJSProxy() && JSHandle<JSProxy>::Cast(thisHandle)->GetTarget().IsJSAPIVector()) {
522             thisHandle = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(thisHandle)->GetTarget());
523         } else {
524             THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPIVector", JSTaggedValue::Exception());
525         }
526     }
527     // If IsCallable(callbackfn) is false, throw a TypeError exception.
528     JSHandle<JSTaggedValue> callbackFnHandle = GetCallArg(argv, 0);
529     if (!callbackFnHandle->IsCallable()) {
530         THROW_TYPE_ERROR_AND_RETURN(thread, "the callbackfun is not callable.", JSTaggedValue::Exception());
531     }
532     // If thisArg was supplied, let T be thisArg; else let T be undefined.
533     JSHandle<JSTaggedValue> thisArgHandle = GetCallArg(argv, 1);
534 
535     return JSAPIVector::ForEach(thread, thisHandle, callbackFnHandle, thisArgHandle);
536 }
537 
ReplaceAllElements(EcmaRuntimeCallInfo * argv)538 JSTaggedValue ContainersVector::ReplaceAllElements(EcmaRuntimeCallInfo *argv)
539 {
540     ASSERT(argv != nullptr);
541     JSThread *thread = argv->GetThread();
542     BUILTINS_API_TRACE(thread, Vector, ReplaceAllElements);
543     [[maybe_unused]] EcmaHandleScope handleScope(thread);
544     // Let O be ToObject(this value).
545     JSHandle<JSTaggedValue> thisHandle = GetThis(argv); // JSAPIVector
546     if (!thisHandle->IsJSAPIVector()) {
547         if (thisHandle->IsJSProxy() && JSHandle<JSProxy>::Cast(thisHandle)->GetTarget().IsJSAPIVector()) {
548             thisHandle = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(thisHandle)->GetTarget());
549         } else {
550             THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPIVector", JSTaggedValue::Exception());
551         }
552     }
553 
554     // If IsCallable(callbackfn) is false, throw a TypeError exception.
555     JSHandle<JSTaggedValue> callbackFnHandle = GetCallArg(argv, 0);
556     if (!callbackFnHandle->IsCallable()) {
557         THROW_TYPE_ERROR_AND_RETURN(thread, "the callbackfun is not callable.", JSTaggedValue::Exception());
558     }
559     // If thisArg was supplied, let T be thisArg; else let T be undefined.
560     JSHandle<JSTaggedValue> thisArgHandle = GetCallArg(argv, 1);
561     return JSAPIVector::ReplaceAllElements(thread, thisHandle, callbackFnHandle, thisArgHandle);
562 }
563 
TrimToCurrentLength(EcmaRuntimeCallInfo * argv)564 JSTaggedValue ContainersVector::TrimToCurrentLength(EcmaRuntimeCallInfo *argv)
565 {
566     ASSERT(argv != nullptr);
567     JSThread *thread = argv->GetThread();
568     BUILTINS_API_TRACE(thread, Vector, TrimToCurrentLength);
569     [[maybe_unused]] EcmaHandleScope handleScope(thread);
570     JSHandle<JSTaggedValue> self = GetThis(argv);
571 
572     if (!self->IsJSAPIVector()) {
573         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIVector()) {
574             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
575         } else {
576             THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPIVector", JSTaggedValue::Exception());
577         }
578     }
579 
580     JSAPIVector::TrimToCurrentLength(thread, JSHandle<JSAPIVector>::Cast(self));
581     return JSTaggedValue::True();
582 }
583 
Clear(EcmaRuntimeCallInfo * argv)584 JSTaggedValue ContainersVector::Clear(EcmaRuntimeCallInfo *argv)
585 {
586     ASSERT(argv != nullptr);
587     JSThread *thread = argv->GetThread();
588     BUILTINS_API_TRACE(thread, Vector, Clear);
589     [[maybe_unused]] EcmaHandleScope handleScope(thread);
590     JSHandle<JSTaggedValue> self = GetThis(argv);
591 
592     if (!self->IsJSAPIVector()) {
593         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIVector()) {
594             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
595         } else {
596             THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPIVector", JSTaggedValue::Exception());
597         }
598     }
599 
600     JSAPIVector::Clear(thread, JSHandle<JSAPIVector>::Cast(self));
601 
602     return JSTaggedValue::True();
603 }
604 
Clone(EcmaRuntimeCallInfo * argv)605 JSTaggedValue ContainersVector::Clone(EcmaRuntimeCallInfo *argv)
606 {
607     ASSERT(argv != nullptr);
608     JSThread *thread = argv->GetThread();
609     BUILTINS_API_TRACE(thread, Vector, Clone);
610     [[maybe_unused]] EcmaHandleScope handleScope(thread);
611     JSHandle<JSTaggedValue> self = GetThis(argv);
612 
613     if (!self->IsJSAPIVector()) {
614         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIVector()) {
615             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
616         } else {
617             THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPIVector", JSTaggedValue::Exception());
618         }
619     }
620     JSHandle<JSAPIVector> newVector = JSAPIVector::Clone(thread, JSHandle<JSAPIVector>::Cast(self));
621     return newVector.GetTaggedValue();
622 }
623 
Has(EcmaRuntimeCallInfo * argv)624 JSTaggedValue ContainersVector::Has(EcmaRuntimeCallInfo *argv)
625 {
626     ASSERT(argv != nullptr);
627     JSThread *thread = argv->GetThread();
628     BUILTINS_API_TRACE(thread, Vector, Has);
629     [[maybe_unused]] EcmaHandleScope handleScope(thread);
630     JSHandle<JSTaggedValue> self = GetThis(argv);
631 
632     if (!self->IsJSAPIVector()) {
633         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIVector()) {
634             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
635         } else {
636             THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPIVector", JSTaggedValue::Exception());
637         }
638     }
639 
640     JSHandle<JSTaggedValue> value(GetCallArg(argv, 0));
641     bool isHas = JSHandle<JSAPIVector>::Cast(self)->Has(value.GetTaggedValue());
642     return GetTaggedBoolean(isHas);
643 }
644 
CopyToArray(EcmaRuntimeCallInfo * argv)645 JSTaggedValue ContainersVector::CopyToArray(EcmaRuntimeCallInfo *argv)
646 {
647     ASSERT(argv != nullptr);
648     JSThread *thread = argv->GetThread();
649     BUILTINS_API_TRACE(thread, Vector, CopyToArray);
650     [[maybe_unused]] EcmaHandleScope handleScope(thread);
651     JSHandle<JSTaggedValue> self = GetThis(argv);
652 
653     if (!self->IsJSAPIVector()) {
654         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIVector()) {
655             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
656         } else {
657             THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPIVector", JSTaggedValue::Exception());
658         }
659     }
660     JSHandle<JSTaggedValue> arg0(GetCallArg(argv, 0));
661     if (!arg0->IsJSArray()) {
662         return JSTaggedValue::False();
663     }
664 
665     JSHandle<JSAPIVector> vector = JSHandle<JSAPIVector>::Cast(self);
666     JSHandle<TaggedArray> vectorElements(thread, vector->GetElements());
667     uint32_t vectorLength = static_cast<uint32_t>(vector->GetSize());
668 
669     JSHandle<JSArray> array = JSHandle<JSArray>::Cast(arg0);
670     JSHandle<TaggedArray> arrayElements(thread, array->GetElements());
671     uint32_t arrayLength = array->GetArrayLength();
672     if (vectorLength <= arrayLength) {
673         TaggedArray::CopyTaggedArrayElement(thread, vectorElements, arrayElements, vectorLength);
674         for (uint32_t i = vectorLength; i < arrayLength; i++) {
675             arrayElements->Set(thread, i, JSTaggedValue::Undefined());
676         }
677     } else {
678         ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
679         JSHandle<TaggedArray> newArrayElement = factory->NewAndCopyTaggedArray(vectorElements,
680                                                                                vectorLength, vectorLength);
681         array->SetElements(thread, newArrayElement);
682         array->SetLength(vectorLength);
683     }
684     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
685     return JSTaggedValue::True();
686 }
687 
ConvertToArray(EcmaRuntimeCallInfo * argv)688 JSTaggedValue ContainersVector::ConvertToArray(EcmaRuntimeCallInfo *argv)
689 {
690     ASSERT(argv != nullptr);
691     JSThread *thread = argv->GetThread();
692     BUILTINS_API_TRACE(thread, Vector, ConvertToArray);
693     [[maybe_unused]] EcmaHandleScope handleScope(thread);
694     JSHandle<JSTaggedValue> self = GetThis(argv);
695 
696     if (!self->IsJSAPIVector()) {
697         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIVector()) {
698             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
699         } else {
700             THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPIVector", JSTaggedValue::Exception());
701         }
702     }
703 
704     JSHandle<JSAPIVector> vector = JSHandle<JSAPIVector>::Cast(self);
705     auto factory = thread->GetEcmaVM()->GetFactory();
706     JSHandle<JSArray> array = factory->NewJSArray();
707 
708     uint32_t length = vector->GetSize();
709     array->SetArrayLength(thread, length);
710 
711     JSHandle<TaggedArray> srcElements(thread, vector->GetElements());
712     JSHandle<TaggedArray> dstElements = factory->NewAndCopyTaggedArray(srcElements, length, length);
713 
714     array->SetElements(thread, dstElements);
715     return array.GetTaggedValue();
716 }
717 
GetFirstElement(EcmaRuntimeCallInfo * argv)718 JSTaggedValue ContainersVector::GetFirstElement(EcmaRuntimeCallInfo *argv)
719 {
720     ASSERT(argv != nullptr);
721     JSThread *thread = argv->GetThread();
722     BUILTINS_API_TRACE(thread, Vector, GetFirstElement);
723     [[maybe_unused]] EcmaHandleScope handleScope(thread);
724     JSHandle<JSTaggedValue> self = GetThis(argv);
725 
726     if (!self->IsJSAPIVector()) {
727         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIVector()) {
728             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
729         } else {
730             THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPIVector", JSTaggedValue::Exception());
731         }
732     }
733 
734     JSTaggedValue firstElement = JSAPIVector::GetFirstElement(JSHandle<JSAPIVector>::Cast(self));
735     return firstElement;
736 }
737 
Sort(EcmaRuntimeCallInfo * argv)738 JSTaggedValue ContainersVector::Sort(EcmaRuntimeCallInfo *argv)
739 {
740     ASSERT(argv != nullptr);
741     JSThread *thread = argv->GetThread();
742     BUILTINS_API_TRACE(thread, Vector, Sort);
743     [[maybe_unused]] EcmaHandleScope handleScope(thread);
744 
745     JSHandle<JSTaggedValue> self = GetThis(argv);
746     if (!self->IsJSAPIVector()) {
747         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIVector()) {
748             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
749         } else {
750             THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPIVector", JSTaggedValue::Exception());
751         }
752     }
753     JSHandle<JSTaggedValue> callbackFnHandle = GetCallArg(argv, 0);
754 
755     auto obj = JSHandle<JSAPIVector>::Cast(self);
756     uint32_t length = static_cast<uint32_t>(obj->GetSize());
757     JSHandle<TaggedArray> elements = thread->GetEcmaVM()->GetFactory()->NewTaggedArray(length);
758     elements->Copy(thread, 0, 0, TaggedArray::Cast(obj->GetElements()), length);
759     JSMutableHandle<JSTaggedValue> presentValue(thread, JSTaggedValue::Undefined());
760     JSMutableHandle<JSTaggedValue> middleValue(thread, JSTaggedValue::Undefined());
761     JSMutableHandle<JSTaggedValue> previousValue(thread, JSTaggedValue::Undefined());
762     for (uint32_t i = 1; i < length; i++) {
763         uint32_t beginIndex = 0;
764         uint32_t endIndex = i;
765         presentValue.Update(elements->Get(i));
766         while (beginIndex < endIndex) {
767             uint32_t middleIndex = (beginIndex + endIndex) / 2; // 2 : half
768             middleValue.Update(elements->Get(middleIndex));
769             double compareResult = base::ArrayHelper::SortCompare(thread, callbackFnHandle, middleValue, presentValue);
770             RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
771             if (compareResult > 0) {
772                 endIndex = middleIndex;
773             } else {
774                 beginIndex = middleIndex + 1;
775             }
776         }
777 
778         if (endIndex < i) {
779             for (uint32_t j = i; j > endIndex; j--) {
780                 previousValue.Update(elements->Get(j - 1));
781                 elements->Set(thread, j, previousValue.GetTaggedValue());
782             }
783             elements->Set(thread, endIndex, presentValue.GetTaggedValue());
784         }
785     }
786     obj->SetElements(thread, elements);
787     obj->SetLength(elements->GetLength());
788     return JSTaggedValue::True();
789 }
790 
GetIteratorObj(EcmaRuntimeCallInfo * argv)791 JSTaggedValue ContainersVector::GetIteratorObj(EcmaRuntimeCallInfo *argv)
792 {
793     ASSERT(argv != nullptr);
794     JSThread *thread = argv->GetThread();
795     BUILTINS_API_TRACE(thread, Vector, GetIteratorObj);
796     [[maybe_unused]] EcmaHandleScope handleScope(thread);
797 
798     JSHandle<JSTaggedValue> self = GetThis(argv);
799 
800     if (!self->IsJSAPIVector()) {
801         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIVector()) {
802             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
803         } else {
804             THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPIVector", JSTaggedValue::Exception());
805         }
806     }
807 
808     JSTaggedValue values = JSAPIVector::GetIteratorObj(thread, JSHandle<JSAPIVector>::Cast(self));
809     return values;
810 }
811 } // namespace panda::ecmascript::containers
812