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