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