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