• 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_plainarray.h"
17 
18 #include "ecmascript/containers/containers_errors.h"
19 #include "ecmascript/ecma_vm.h"
20 #include "ecmascript/js_api/js_api_plain_array.h"
21 #include "ecmascript/js_iterator.h"
22 #include "ecmascript/object_factory.h"
23 #include "ecmascript/tagged_array-inl.h"
24 
25 namespace panda::ecmascript::containers {
PlainArrayConstructor(EcmaRuntimeCallInfo * argv)26 JSTaggedValue ContainersPlainArray::PlainArrayConstructor(EcmaRuntimeCallInfo *argv)
27 {
28     ASSERT(argv != nullptr);
29     JSThread *thread = argv->GetThread();
30     BUILTINS_API_TRACE(thread, PlainArray, Constructor);
31     [[maybe_unused]] EcmaHandleScope handleScope(thread);
32     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
33     JSHandle<JSTaggedValue> newTarget = GetNewTarget(argv);
34     if (newTarget->IsUndefined()) {
35         JSTaggedValue error =
36             ContainerError::BusinessError(thread, ErrorFlag::IS_NULL_ERROR,
37                                           "The PlainArray's constructor cannot be directly invoked");
38         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
39     }
40     JSHandle<JSTaggedValue> constructor = GetConstructor(argv);
41     JSHandle<JSObject> obj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(constructor), newTarget);
42     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
43     JSHandle<JSAPIPlainArray> plainArray = JSHandle<JSAPIPlainArray>::Cast(obj);
44     JSHandle<TaggedArray> keys =
45         JSAPIPlainArray::CreateSlot(thread, JSAPIPlainArray::DEFAULT_CAPACITY_LENGTH);
46     JSHandle<TaggedArray> values =
47         JSAPIPlainArray::CreateSlot(thread, JSAPIPlainArray::DEFAULT_CAPACITY_LENGTH);
48     plainArray->SetKeys(thread, keys);
49     plainArray->SetValues(thread, values);
50     return obj.GetTaggedValue();
51 }
52 
Add(EcmaRuntimeCallInfo * argv)53 JSTaggedValue ContainersPlainArray::Add(EcmaRuntimeCallInfo *argv)
54 {
55     ASSERT(argv != nullptr);
56     JSThread *thread = argv->GetThread();
57     BUILTINS_API_TRACE(thread, PlainArray, Add);
58     [[maybe_unused]] EcmaHandleScope handleScope(thread);
59     JSHandle<JSTaggedValue> self = GetThis(argv);
60     if (!self->IsJSAPIPlainArray()) {
61         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIPlainArray()) {
62             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
63         } else {
64             JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
65                                                                 "The add method cannot be bound");
66             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
67         }
68     }
69     JSHandle<JSTaggedValue> key(GetCallArg(argv, 0));
70     JSHandle<JSTaggedValue> value(GetCallArg(argv, 1));
71     if (!key->IsInteger()) {
72         JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, key.GetTaggedValue());
73         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
74         CString errorMsg =
75             "The type of \"key\" must be number. Received value is: " + ConvertToString(*result);
76         JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str());
77         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
78     }
79     JSAPIPlainArray::Add(thread, JSHandle<JSAPIPlainArray>::Cast(self), key, value);
80     return JSTaggedValue::True();
81 }
82 
Clear(EcmaRuntimeCallInfo * argv)83 JSTaggedValue ContainersPlainArray::Clear(EcmaRuntimeCallInfo *argv)
84 {
85     ASSERT(argv != nullptr);
86     JSThread *thread = argv->GetThread();
87     BUILTINS_API_TRACE(thread, PlainArray, Clear);
88     [[maybe_unused]] EcmaHandleScope handleScope(thread);
89     JSHandle<JSTaggedValue> self = GetThis(argv);
90     if (!self->IsJSAPIPlainArray()) {
91         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIPlainArray()) {
92             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
93         } else {
94             JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
95                                                                 "The clear method cannot be bound");
96             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
97         }
98     }
99     JSAPIPlainArray *array = JSAPIPlainArray::Cast(self->GetTaggedObject());
100     array->Clear(thread);
101     return JSTaggedValue::True();
102 }
103 
Clone(EcmaRuntimeCallInfo * argv)104 JSTaggedValue ContainersPlainArray::Clone(EcmaRuntimeCallInfo *argv)
105 {
106     ASSERT(argv != nullptr);
107     JSThread *thread = argv->GetThread();
108     BUILTINS_API_TRACE(thread, PlainArray, Clone);
109     [[maybe_unused]] EcmaHandleScope handleScope(thread);
110     JSHandle<JSTaggedValue> self = GetThis(argv);
111     if (!self->IsJSAPIPlainArray()) {
112         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIPlainArray()) {
113             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
114         } else {
115             JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
116                                                                 "The clone method cannot be bound");
117             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
118         }
119     }
120     JSHandle<JSAPIPlainArray> newPlainArray =
121         JSAPIPlainArray::Clone(thread, JSHandle<JSAPIPlainArray>::Cast(self));
122     return newPlainArray.GetTaggedValue();
123 }
124 
Has(EcmaRuntimeCallInfo * argv)125 JSTaggedValue ContainersPlainArray::Has(EcmaRuntimeCallInfo *argv)
126 {
127     ASSERT(argv != nullptr);
128     JSThread *thread = argv->GetThread();
129     BUILTINS_API_TRACE(thread, PlainArray, Has);
130     [[maybe_unused]] EcmaHandleScope handleScope(thread);
131     JSHandle<JSTaggedValue> self = GetThis(argv);
132     if (!self->IsJSAPIPlainArray()) {
133         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIPlainArray()) {
134             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
135         } else {
136             JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
137                                                                 "The has method cannot be bound");
138             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
139         }
140     }
141     JSHandle<JSTaggedValue> value(GetCallArg(argv, 0));
142     if (!value->IsNumber()) {
143         JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, value.GetTaggedValue());
144         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
145         CString errorMsg =
146             "The type of \"key\" must be number. Received value is: " + ConvertToString(*result);
147         JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str());
148         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
149     }
150     JSAPIPlainArray *array = JSAPIPlainArray::Cast(self->GetTaggedObject());
151     int32_t key = value->GetNumber();
152     bool result = array->Has(key);
153     return JSTaggedValue(result);
154 }
155 
Get(EcmaRuntimeCallInfo * argv)156 JSTaggedValue ContainersPlainArray::Get(EcmaRuntimeCallInfo *argv)
157 {
158     ASSERT(argv != nullptr);
159     JSThread *thread = argv->GetThread();
160     BUILTINS_API_TRACE(thread, PlainArray, Get);
161     [[maybe_unused]] EcmaHandleScope handleScope(thread);
162     JSHandle<JSTaggedValue> self = GetThis(argv);
163     if (!self->IsJSAPIPlainArray()) {
164         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIPlainArray()) {
165             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
166         } else {
167             JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
168                                                                 "The get method cannot be bound");
169             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
170         }
171     }
172     JSHandle<JSTaggedValue> key(GetCallArg(argv, 0));
173     if (!key->IsInteger()) {
174         JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, key.GetTaggedValue());
175         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
176         CString errorMsg =
177             "The type of \"key\" must be number. Received value is: " + ConvertToString(*result);
178         JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str());
179         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
180     }
181     JSAPIPlainArray *array = JSAPIPlainArray::Cast(self->GetTaggedObject());
182     JSTaggedValue value = array->Get(key.GetTaggedValue());
183 
184     return value;
185 }
186 
GetIteratorObj(EcmaRuntimeCallInfo * argv)187 JSTaggedValue ContainersPlainArray::GetIteratorObj(EcmaRuntimeCallInfo *argv)
188 {
189     ASSERT(argv != nullptr);
190     JSThread *thread = argv->GetThread();
191     BUILTINS_API_TRACE(thread, PlainArray, GetIteratorObj);
192     [[maybe_unused]] EcmaHandleScope handleScope(thread);
193     JSHandle<JSTaggedValue> self = GetThis(argv);
194     if (!self->IsJSAPIPlainArray()) {
195         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIPlainArray()) {
196             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
197         } else {
198             JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
199                                                                 "The Symbol.iterator method cannot be bound");
200             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
201         }
202     }
203     JSHandle<JSTaggedValue> iter =
204         JSAPIPlainArray::GetIteratorObj(thread, JSHandle<JSAPIPlainArray>::Cast(self), IterationKind::KEY_AND_VALUE);
205     return iter.GetTaggedValue();
206 }
207 
ForEach(EcmaRuntimeCallInfo * argv)208 JSTaggedValue ContainersPlainArray::ForEach(EcmaRuntimeCallInfo *argv)
209 {
210     ASSERT(argv != nullptr);
211     JSThread *thread = argv->GetThread();
212     BUILTINS_API_TRACE(thread, PlainArray, ForEach);
213     JSHandle<JSTaggedValue> thisHandle = GetThis(argv);
214     if (!thisHandle->IsJSAPIPlainArray()) {
215         if (thisHandle->IsJSProxy() && JSHandle<JSProxy>::Cast(thisHandle)->GetTarget().IsJSAPIPlainArray()) {
216             thisHandle = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(thisHandle)->GetTarget());
217         } else {
218             JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
219                                                                 "The forEach method cannot be bound");
220             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
221         }
222     }
223     JSHandle<JSTaggedValue> callbackFnHandle = GetCallArg(argv, 0);
224     if (!callbackFnHandle->IsCallable()) {
225         JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, callbackFnHandle.GetTaggedValue());
226         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
227         CString errorMsg =
228             "The type of \"callbackfn\" must be callable. Received value is: " + ConvertToString(*result);
229         JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str());
230         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
231     }
232     JSHandle<JSTaggedValue> thisArgHandle = GetCallArg(argv, 1);
233     return JSAPIPlainArray::ForEach(thread, thisHandle, callbackFnHandle, thisArgHandle);
234 }
235 
ToString(EcmaRuntimeCallInfo * argv)236 JSTaggedValue ContainersPlainArray::ToString(EcmaRuntimeCallInfo *argv)
237 {
238     ASSERT(argv != nullptr);
239     JSThread *thread = argv->GetThread();
240     BUILTINS_API_TRACE(thread, PlainArray, ToString);
241     JSHandle<JSTaggedValue> self = GetThis(argv);
242     if (!self->IsJSAPIPlainArray()) {
243         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIPlainArray()) {
244             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
245         } else {
246             JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
247                                                                 "The toString method cannot be bound");
248             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
249         }
250     }
251     JSTaggedValue value = JSAPIPlainArray::ToString(thread, JSHandle<JSAPIPlainArray>::Cast(self));
252     return value;
253 }
254 
GetIndexOfKey(EcmaRuntimeCallInfo * argv)255 JSTaggedValue ContainersPlainArray::GetIndexOfKey(EcmaRuntimeCallInfo *argv)
256 {
257     ASSERT(argv != nullptr);
258     JSThread *thread = argv->GetThread();
259     BUILTINS_API_TRACE(thread, PlainArray, GetIndexOfKey);
260     JSHandle<JSTaggedValue> self = GetThis(argv);
261     if (!self->IsJSAPIPlainArray()) {
262         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIPlainArray()) {
263             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
264         } else {
265             JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
266                                                                 "The getIndexOfKey method cannot be bound");
267             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
268         }
269     }
270     JSHandle<JSTaggedValue> value(GetCallArg(argv, 0));
271     if (!value->IsNumber()) {
272         JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, value.GetTaggedValue());
273         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
274         CString errorMsg =
275             "The type of \"key\" must be number. Received value is: " + ConvertToString(*result);
276         JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str());
277         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
278     }
279     JSAPIPlainArray *array = JSAPIPlainArray::Cast(self->GetTaggedObject());
280     int32_t key = value->GetNumber();
281     JSTaggedValue result = array->GetIndexOfKey(key);
282     return result;
283 }
284 
GetIndexOfValue(EcmaRuntimeCallInfo * argv)285 JSTaggedValue ContainersPlainArray::GetIndexOfValue(EcmaRuntimeCallInfo *argv)
286 {
287     ASSERT(argv != nullptr);
288     JSThread *thread = argv->GetThread();
289     BUILTINS_API_TRACE(thread, PlainArray, GetIndexOfValue);
290     JSHandle<JSTaggedValue> self = GetThis(argv);
291     if (!self->IsJSAPIPlainArray()) {
292         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIPlainArray()) {
293             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
294         } else {
295             JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
296                                                                 "The getIndexOfValue method cannot be bound");
297             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
298         }
299     }
300     JSAPIPlainArray *array = JSAPIPlainArray::Cast(self->GetTaggedObject());
301     JSHandle<JSTaggedValue> value(GetCallArg(argv, 0));
302     JSTaggedValue jsValue = array->GetIndexOfValue(value.GetTaggedValue());
303     return jsValue;
304 }
305 
IsEmpty(EcmaRuntimeCallInfo * argv)306 JSTaggedValue ContainersPlainArray::IsEmpty(EcmaRuntimeCallInfo *argv)
307 {
308     ASSERT(argv != nullptr);
309     JSThread *thread = argv->GetThread();
310     BUILTINS_API_TRACE(thread, PlainArray, IsEmpty);
311     JSHandle<JSTaggedValue> self = GetThis(argv);
312     if (!self->IsJSAPIPlainArray()) {
313         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIPlainArray()) {
314             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
315         } else {
316             JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
317                                                                 "The isEmpty method cannot be bound");
318             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
319         }
320     }
321     JSAPIPlainArray *array = JSAPIPlainArray::Cast(self->GetTaggedObject());
322     bool ret = array->IsEmpty();
323     return JSTaggedValue(ret);
324 }
325 
GetKeyAt(EcmaRuntimeCallInfo * argv)326 JSTaggedValue ContainersPlainArray::GetKeyAt(EcmaRuntimeCallInfo *argv)
327 {
328     ASSERT(argv != nullptr);
329     JSThread *thread = argv->GetThread();
330     BUILTINS_API_TRACE(thread, PlainArray, GetKeyAt);
331     JSHandle<JSTaggedValue> self = GetThis(argv);
332     if (!self->IsJSAPIPlainArray()) {
333         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIPlainArray()) {
334             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
335         } else {
336             JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
337                                                                 "The getKeyAt method cannot be bound");
338             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
339         }
340     }
341     JSHandle<JSTaggedValue> value(GetCallArg(argv, 0));
342     if (!value->IsNumber()) {
343         JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, value.GetTaggedValue());
344         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
345         CString errorMsg =
346             "The type of \"index\" must be number. Received value is: " + ConvertToString(*result);
347         JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str());
348         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
349     }
350     JSAPIPlainArray *array = JSAPIPlainArray::Cast(self->GetTaggedObject());
351     int32_t index = value->GetNumber();
352     JSTaggedValue result = array->GetKeyAt(index);
353     return result;
354 }
355 
Remove(EcmaRuntimeCallInfo * argv)356 JSTaggedValue ContainersPlainArray::Remove(EcmaRuntimeCallInfo *argv)
357 {
358     ASSERT(argv != nullptr);
359     JSThread *thread = argv->GetThread();
360     BUILTINS_API_TRACE(thread, PlainArray, Remove);
361     JSHandle<JSTaggedValue> self = GetThis(argv);
362     if (!self->IsJSAPIPlainArray()) {
363         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIPlainArray()) {
364             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
365         } else {
366             JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
367                                                                 "The remove method cannot be bound");
368             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
369         }
370     }
371     JSHandle<JSTaggedValue> key(GetCallArg(argv, 0));
372     if (!key->IsInteger()) {
373         JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, key.GetTaggedValue());
374         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
375         CString errorMsg =
376             "The type of \"key\" must be number. Received value is: " + ConvertToString(*result);
377         JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str());
378         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
379     }
380     JSAPIPlainArray *array = JSAPIPlainArray::Cast(self->GetTaggedObject());
381     JSTaggedValue value = array->Remove(thread, key.GetTaggedValue());
382     return value;
383 }
384 
RemoveAt(EcmaRuntimeCallInfo * argv)385 JSTaggedValue ContainersPlainArray::RemoveAt(EcmaRuntimeCallInfo *argv)
386 {
387     ASSERT(argv != nullptr);
388     JSThread *thread = argv->GetThread();
389     BUILTINS_API_TRACE(thread, PlainArray, RemoveAt);
390     JSHandle<JSTaggedValue> self = GetThis(argv);
391     if (!self->IsJSAPIPlainArray()) {
392         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIPlainArray()) {
393             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
394         } else {
395             JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
396                                                                 "The removeAt method cannot be bound");
397             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
398         }
399     }
400     JSHandle<JSTaggedValue> index(GetCallArg(argv, 0));
401     if (!index->IsInteger()) {
402         JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, index.GetTaggedValue());
403         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
404         CString errorMsg =
405             "The type of \"index\" must be number. Received value is: " + ConvertToString(*result);
406         JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str());
407         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
408     }
409     JSAPIPlainArray *array = JSAPIPlainArray::Cast(self->GetTaggedObject());
410     JSTaggedValue value = array->RemoveAt(thread, index.GetTaggedValue());
411     return value;
412 }
413 
RemoveRangeFrom(EcmaRuntimeCallInfo * argv)414 JSTaggedValue ContainersPlainArray::RemoveRangeFrom(EcmaRuntimeCallInfo *argv)
415 {
416     ASSERT(argv != nullptr);
417     JSThread *thread = argv->GetThread();
418     BUILTINS_API_TRACE(thread, PlainArray, RemoveRangeFrom);
419     JSHandle<JSTaggedValue> self = GetThis(argv);
420     if (!self->IsJSAPIPlainArray()) {
421         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIPlainArray()) {
422             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
423         } else {
424             JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
425                                                                 "The removeRangeFrom method cannot be bound");
426             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
427         }
428     }
429     JSHandle<JSTaggedValue> valueIndex(GetCallArg(argv, 0));
430     JSHandle<JSTaggedValue> valueSize(GetCallArg(argv, 1));
431     if (!valueIndex->IsInteger()) {
432         JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, valueIndex.GetTaggedValue());
433         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
434         CString errorMsg =
435             "The type of \"index\" must be number. Received value is: " + ConvertToString(*result);
436         JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str());
437         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
438     }
439     if (!valueSize->IsInteger()) {
440         JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, valueSize.GetTaggedValue());
441         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
442         CString errorMsg =
443             "The type of \"size\" must be number. Received value is: " + ConvertToString(*result);
444         JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str());
445         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
446     }
447     int32_t index = valueIndex->GetNumber();
448     int32_t size = valueSize->GetNumber();
449     JSAPIPlainArray *array = JSAPIPlainArray::Cast(self->GetTaggedObject());
450     JSTaggedValue value = array->RemoveRangeFrom(thread, index, size);
451     return value;
452 }
453 
SetValueAt(EcmaRuntimeCallInfo * argv)454 JSTaggedValue ContainersPlainArray::SetValueAt(EcmaRuntimeCallInfo *argv)
455 {
456     ASSERT(argv != nullptr);
457     JSThread *thread = argv->GetThread();
458     BUILTINS_API_TRACE(thread, PlainArray, SetValueAt);
459     [[maybe_unused]] EcmaHandleScope handleScope(thread);
460     JSHandle<JSTaggedValue> self = GetThis(argv);
461     if (!self->IsJSAPIPlainArray()) {
462         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIPlainArray()) {
463             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
464         } else {
465             JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
466                                                                 "The setValueAt method cannot be bound");
467             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
468         }
469     }
470     JSHandle<JSTaggedValue> index(GetCallArg(argv, 0));
471     JSHandle<JSTaggedValue> value(GetCallArg(argv, 1));
472     if (!index->IsInteger()) {
473         JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, index.GetTaggedValue());
474         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
475         CString errorMsg =
476             "The type of \"index\" must be number. Received value is: " + ConvertToString(*result);
477         JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str());
478         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
479     }
480     JSAPIPlainArray *array = JSAPIPlainArray::Cast(self->GetTaggedObject());
481     array->SetValueAt(thread, index.GetTaggedValue(), value.GetTaggedValue());
482     return JSTaggedValue::Undefined();
483 }
484 
GetValueAt(EcmaRuntimeCallInfo * argv)485 JSTaggedValue ContainersPlainArray::GetValueAt(EcmaRuntimeCallInfo *argv)
486 {
487     ASSERT(argv != nullptr);
488     JSThread *thread = argv->GetThread();
489     BUILTINS_API_TRACE(thread, PlainArray, GetValueAt);
490     [[maybe_unused]] EcmaHandleScope handleScope(thread);
491     JSHandle<JSTaggedValue> self = GetThis(argv);
492     if (!self->IsJSAPIPlainArray()) {
493         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIPlainArray()) {
494             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
495         } else {
496             JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
497                                                                 "The getValueAt method cannot be bound");
498             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
499         }
500     }
501     JSHandle<JSTaggedValue> idx(GetCallArg(argv, 0));
502     if (!idx->IsInteger()) {
503         JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, idx.GetTaggedValue());
504         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
505         CString errorMsg =
506             "The type of \"index\" must be number. Received value is: " + ConvertToString(*result);
507         JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str());
508         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
509     }
510     JSAPIPlainArray *array = JSAPIPlainArray::Cast(self->GetTaggedObject());
511     int32_t index = idx->GetNumber();
512     JSTaggedValue value = array->GetValueAt(thread, index);
513     return value;
514 }
515 
GetSize(EcmaRuntimeCallInfo * argv)516 JSTaggedValue ContainersPlainArray::GetSize(EcmaRuntimeCallInfo *argv)
517 {
518     ASSERT(argv != nullptr);
519     JSThread *thread = argv->GetThread();
520     BUILTINS_API_TRACE(thread, PlainArray, GetSize);
521     JSHandle<JSTaggedValue> self = GetThis(argv);
522     if (!self->IsJSAPIPlainArray()) {
523         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIPlainArray()) {
524             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
525         } else {
526             JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
527                                                                 "The getSize method cannot be bound");
528             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
529         }
530     }
531     uint32_t length = JSHandle<JSAPIPlainArray>::Cast(self)->GetSize();
532     return JSTaggedValue(length);
533 }
534 } // namespace panda::ecmascript::containers
535