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