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