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