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