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_linked_list.h"
17
18 #include "ecmascript/containers/containers_errors.h"
19 #include "ecmascript/interpreter/interpreter.h"
20 #include "ecmascript/js_api/js_api_linked_list.h"
21 #include "ecmascript/js_api/js_api_linked_list_iterator.h"
22 #include "ecmascript/js_function.h"
23
24 namespace panda::ecmascript::containers {
LinkedListConstructor(EcmaRuntimeCallInfo * argv)25 JSTaggedValue ContainersLinkedList::LinkedListConstructor(EcmaRuntimeCallInfo *argv)
26 {
27 ASSERT(argv != nullptr);
28 JSThread *thread = argv->GetThread();
29 BUILTINS_API_TRACE(thread, LinkedList, Constructor);
30 [[maybe_unused]] EcmaHandleScope handleScope(thread);
31 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
32 JSHandle<JSTaggedValue> newTarget = GetNewTarget(argv);
33 if (newTarget->IsUndefined()) {
34 JSTaggedValue error =
35 ContainerError::BusinessError(thread, ErrorFlag::IS_NULL_ERROR,
36 "The LinkedList's constructor cannot be directly invoked");
37 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
38 }
39 JSHandle<JSTaggedValue> constructor = GetConstructor(argv);
40 JSHandle<JSObject> obj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(constructor), newTarget);
41 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
42 JSHandle<JSAPILinkedList> linkedList = JSHandle<JSAPILinkedList>::Cast(obj);
43 JSTaggedValue doubleList = TaggedDoubleList::Create(thread);
44 linkedList->SetDoubleList(thread, doubleList);
45 return linkedList.GetTaggedValue();
46 }
47
Add(EcmaRuntimeCallInfo * argv)48 JSTaggedValue ContainersLinkedList::Add(EcmaRuntimeCallInfo *argv)
49 {
50 ASSERT(argv != nullptr);
51 JSThread *thread = argv->GetThread();
52 BUILTINS_API_TRACE(thread, LinkedList, Add);
53 [[maybe_unused]] EcmaHandleScope handleScope(thread);
54 JSHandle<JSTaggedValue> self = GetThis(argv);
55 if (!self->IsJSAPILinkedList()) {
56 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPILinkedList()) {
57 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
58 } else {
59 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
60 "The add method cannot be bound");
61 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
62 }
63 }
64
65 JSHandle<JSTaggedValue> value = GetCallArg(argv, 0);
66 JSHandle<JSAPILinkedList> jsAPILinkedList = JSHandle<JSAPILinkedList>::Cast(self);
67 JSAPILinkedList::Add(thread, jsAPILinkedList, value);
68 return JSTaggedValue::True();
69 }
70
AddFirst(EcmaRuntimeCallInfo * argv)71 JSTaggedValue ContainersLinkedList::AddFirst(EcmaRuntimeCallInfo *argv)
72 {
73 ASSERT(argv != nullptr);
74 JSThread *thread = argv->GetThread();
75 BUILTINS_API_TRACE(thread, LinkedList, AddFirst);
76 [[maybe_unused]] EcmaHandleScope handleScope(thread);
77 JSHandle<JSTaggedValue> self = GetThis(argv);
78 if (!self->IsJSAPILinkedList()) {
79 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPILinkedList()) {
80 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
81 } else {
82 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
83 "The addFirst method cannot be bound");
84 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
85 }
86 }
87
88 JSHandle<JSTaggedValue> value = GetCallArg(argv, 0);
89 JSHandle<JSAPILinkedList> jsAPILinkedList = JSHandle<JSAPILinkedList>::Cast(self);
90 JSAPILinkedList::AddFirst(thread, jsAPILinkedList, value);
91 return JSTaggedValue::True();
92 }
93
GetFirst(EcmaRuntimeCallInfo * argv)94 JSTaggedValue ContainersLinkedList::GetFirst(EcmaRuntimeCallInfo *argv)
95 {
96 ASSERT(argv != nullptr);
97 JSThread *thread = argv->GetThread();
98 BUILTINS_API_TRACE(thread, LinkedList, GetFirst);
99 [[maybe_unused]] EcmaHandleScope handleScope(thread);
100 JSHandle<JSTaggedValue> self = GetThis(argv);
101 if (!self->IsJSAPILinkedList()) {
102 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPILinkedList()) {
103 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
104 } else {
105 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
106 "The getFirst method cannot be bound");
107 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
108 }
109 }
110 JSHandle<JSAPILinkedList> jsAPILinkedList = JSHandle<JSAPILinkedList>::Cast(self);
111 return jsAPILinkedList->GetFirst();
112 }
113
GetLast(EcmaRuntimeCallInfo * argv)114 JSTaggedValue ContainersLinkedList::GetLast(EcmaRuntimeCallInfo *argv)
115 {
116 ASSERT(argv != nullptr);
117 JSThread *thread = argv->GetThread();
118 BUILTINS_API_TRACE(thread, LinkedList, GetLast);
119 [[maybe_unused]] EcmaHandleScope handleScope(thread);
120 JSHandle<JSTaggedValue> self = GetThis(argv);
121 if (!self->IsJSAPILinkedList()) {
122 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPILinkedList()) {
123 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
124 } else {
125 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
126 "The getLast method cannot be bound");
127 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
128 }
129 }
130 JSHandle<JSAPILinkedList> jsAPILinkedList = JSHandle<JSAPILinkedList>::Cast(self);
131 return jsAPILinkedList->GetLast();
132 }
133
Length(EcmaRuntimeCallInfo * argv)134 JSTaggedValue ContainersLinkedList::Length(EcmaRuntimeCallInfo *argv)
135 {
136 ASSERT(argv != nullptr);
137 JSThread *thread = argv->GetThread();
138 BUILTINS_API_TRACE(thread, LinkedList, Length);
139 [[maybe_unused]] EcmaHandleScope handleScope(thread);
140 JSHandle<JSTaggedValue> self = GetThis(argv);
141 if (!self->IsJSAPILinkedList()) {
142 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPILinkedList()) {
143 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
144 } else {
145 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
146 "The getLength method cannot be bound");
147 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
148 }
149 }
150 JSHandle<JSAPILinkedList> jsAPILinkedList = JSHandle<JSAPILinkedList>::Cast(self);
151 return JSTaggedValue(jsAPILinkedList->Length());
152 }
153
Insert(EcmaRuntimeCallInfo * argv)154 JSTaggedValue ContainersLinkedList::Insert(EcmaRuntimeCallInfo *argv)
155 {
156 ASSERT(argv != nullptr);
157 JSThread *thread = argv->GetThread();
158 BUILTINS_API_TRACE(thread, LinkedList, Insert);
159 [[maybe_unused]] EcmaHandleScope handleScope(thread);
160 JSHandle<JSTaggedValue> self = GetThis(argv);
161
162 if (!self->IsJSAPILinkedList()) {
163 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPILinkedList()) {
164 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
165 } else {
166 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
167 "The insert method cannot be bound");
168 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
169 }
170 }
171
172 JSHandle<JSTaggedValue> value = GetCallArg(argv, 1);
173 JSHandle<JSTaggedValue> index = GetCallArg(argv, 0);
174
175 if (index->IsDouble()) {
176 index = JSHandle<JSTaggedValue>(thread, JSTaggedValue::TryCastDoubleToInt32(index->GetDouble()));
177 }
178 if (!index->IsInt()) {
179 JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, index.GetTaggedValue());
180 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
181 CString errorMsg =
182 "The type of \"index\" must be small integer. Received value is: " + ConvertToString(*result);
183 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str());
184 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
185 }
186 JSHandle<JSAPILinkedList> jsAPILinkedList = JSHandle<JSAPILinkedList>::Cast(self);
187 JSTaggedValue result =
188 JSAPILinkedList::Insert(thread, jsAPILinkedList, value, index->GetInt());
189 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
190 return result;
191 }
192
Clear(EcmaRuntimeCallInfo * argv)193 JSTaggedValue ContainersLinkedList::Clear(EcmaRuntimeCallInfo *argv)
194 {
195 ASSERT(argv != nullptr);
196 JSThread *thread = argv->GetThread();
197 BUILTINS_API_TRACE(thread, LinkedList, Clear);
198 [[maybe_unused]] EcmaHandleScope handleScope(thread);
199 JSHandle<JSTaggedValue> self = GetThis(argv);
200 if (!self->IsJSAPILinkedList()) {
201 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPILinkedList()) {
202 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
203 } else {
204 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
205 "The clear method cannot be bound");
206 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
207 }
208 }
209 JSHandle<JSAPILinkedList> jsAPILinkedList = JSHandle<JSAPILinkedList>::Cast(self);
210 jsAPILinkedList->Clear(thread);
211 return JSTaggedValue::Undefined();
212 }
213
Clone(EcmaRuntimeCallInfo * argv)214 JSTaggedValue ContainersLinkedList::Clone(EcmaRuntimeCallInfo *argv)
215 {
216 ASSERT(argv != nullptr);
217 JSThread *thread = argv->GetThread();
218 BUILTINS_API_TRACE(thread, LinkedList, Clone);
219 [[maybe_unused]] EcmaHandleScope handleScope(thread);
220 JSHandle<JSTaggedValue> self = GetThis(argv);
221
222 if (!self->IsJSAPILinkedList()) {
223 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPILinkedList()) {
224 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
225 } else {
226 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
227 "The clone method cannot be bound");
228 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
229 }
230 }
231 JSHandle<JSAPILinkedList> jsAPILinkedList = JSHandle<JSAPILinkedList>::Cast(self);
232 JSHandle<JSAPILinkedList> newLinkedList = JSAPILinkedList::Clone(thread, jsAPILinkedList);
233 return newLinkedList.GetTaggedValue();
234 }
235
Has(EcmaRuntimeCallInfo * argv)236 JSTaggedValue ContainersLinkedList::Has(EcmaRuntimeCallInfo *argv)
237 {
238 ASSERT(argv != nullptr);
239 JSThread *thread = argv->GetThread();
240 BUILTINS_API_TRACE(thread, LinkedList, Has);
241 [[maybe_unused]] EcmaHandleScope handleScope(thread);
242 JSHandle<JSTaggedValue> self = GetThis(argv);
243 if (!self->IsJSAPILinkedList()) {
244 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPILinkedList()) {
245 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
246 } else {
247 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
248 "The has method cannot be bound");
249 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
250 }
251 }
252 JSHandle<JSAPILinkedList> jsAPILinkedList = JSHandle<JSAPILinkedList>::Cast(self);
253 JSHandle<JSTaggedValue> element = GetCallArg(argv, 0);
254 return GetTaggedBoolean(jsAPILinkedList->Has(element.GetTaggedValue()));
255 }
256
Get(EcmaRuntimeCallInfo * argv)257 JSTaggedValue ContainersLinkedList::Get(EcmaRuntimeCallInfo *argv)
258 {
259 ASSERT(argv != nullptr);
260 JSThread *thread = argv->GetThread();
261 BUILTINS_API_TRACE(thread, LinkedList, Get);
262 [[maybe_unused]] EcmaHandleScope handleScope(thread);
263 JSHandle<JSTaggedValue> self = GetThis(argv);
264 if (!self->IsJSAPILinkedList()) {
265 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPILinkedList()) {
266 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
267 } else {
268 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
269 "The get method cannot be bound");
270 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
271 }
272 }
273 JSHandle<JSAPILinkedList> jsAPILinkedList = JSHandle<JSAPILinkedList>::Cast(self);
274 JSHandle<JSTaggedValue> index = GetCallArg(argv, 0);
275 if (index->IsDouble()) {
276 index = JSHandle<JSTaggedValue>(thread, JSTaggedValue::TryCastDoubleToInt32(index->GetDouble()));
277 }
278 if (!index->IsInt()) {
279 JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, index.GetTaggedValue());
280 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
281 CString errorMsg =
282 "The type of \"index\" must be small integer. Received value is: " + ConvertToString(*result);
283 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str());
284 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
285 }
286 return jsAPILinkedList->Get(index->GetInt());
287 }
288
GetIndexOf(EcmaRuntimeCallInfo * argv)289 JSTaggedValue ContainersLinkedList::GetIndexOf(EcmaRuntimeCallInfo *argv)
290 {
291 ASSERT(argv != nullptr);
292 JSThread *thread = argv->GetThread();
293 BUILTINS_API_TRACE(thread, LinkedList, GetIndexOf);
294 [[maybe_unused]] EcmaHandleScope handleScope(thread);
295 JSHandle<JSTaggedValue> self = GetThis(argv);
296 if (!self->IsJSAPILinkedList()) {
297 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPILinkedList()) {
298 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
299 } else {
300 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
301 "The getIndexOf method cannot be bound");
302 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
303 }
304 }
305 JSHandle<JSAPILinkedList> jsAPILinkedList = JSHandle<JSAPILinkedList>::Cast(self);
306 JSHandle<JSTaggedValue> element = GetCallArg(argv, 0);
307 return jsAPILinkedList->GetIndexOf(element.GetTaggedValue());
308 }
309
GetLastIndexOf(EcmaRuntimeCallInfo * argv)310 JSTaggedValue ContainersLinkedList::GetLastIndexOf(EcmaRuntimeCallInfo *argv)
311 {
312 ASSERT(argv != nullptr);
313 JSThread *thread = argv->GetThread();
314 BUILTINS_API_TRACE(thread, LinkedList, GetLastIndexOf);
315 [[maybe_unused]] EcmaHandleScope handleScope(thread);
316 JSHandle<JSTaggedValue> self = GetThis(argv);
317 if (!self->IsJSAPILinkedList()) {
318 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPILinkedList()) {
319 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
320 } else {
321 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
322 "The getLastIndexOf method cannot be bound");
323 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
324 }
325 }
326 JSHandle<JSAPILinkedList> jsAPILinkedList = JSHandle<JSAPILinkedList>::Cast(self);
327 JSHandle<JSTaggedValue> element(GetCallArg(argv, 0));
328 return jsAPILinkedList->GetLastIndexOf(element.GetTaggedValue());
329 }
330
RemoveByIndex(EcmaRuntimeCallInfo * argv)331 JSTaggedValue ContainersLinkedList::RemoveByIndex(EcmaRuntimeCallInfo *argv)
332 {
333 ASSERT(argv != nullptr);
334 JSThread *thread = argv->GetThread();
335 BUILTINS_API_TRACE(thread, LinkedList, RemoveByIndex);
336 [[maybe_unused]] EcmaHandleScope handleScope(thread);
337 JSHandle<JSTaggedValue> self = GetThis(argv);
338 if (!self->IsJSAPILinkedList()) {
339 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPILinkedList()) {
340 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
341 } else {
342 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
343 "The removeByIndex method cannot be bound");
344 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
345 }
346 }
347 JSHandle<JSTaggedValue> index = GetCallArg(argv, 0);
348 if (index->IsDouble()) {
349 index = JSHandle<JSTaggedValue>(thread, JSTaggedValue::TryCastDoubleToInt32(index->GetDouble()));
350 }
351 if (!index->IsInt()) {
352 JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, index.GetTaggedValue());
353 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
354 CString errorMsg =
355 "The type of \"index\" must be small integer. Received value is: " + ConvertToString(*result);
356 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str());
357 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
358 }
359 JSHandle<JSAPILinkedList> jsAPILinkedList = JSHandle<JSAPILinkedList>::Cast(self);
360 JSTaggedValue nodeData =
361 JSAPILinkedList::RemoveByIndex(thread, jsAPILinkedList, index->GetInt());
362 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
363 return nodeData;
364 }
365
Remove(EcmaRuntimeCallInfo * argv)366 JSTaggedValue ContainersLinkedList::Remove(EcmaRuntimeCallInfo *argv)
367 {
368 ASSERT(argv != nullptr);
369 JSThread *thread = argv->GetThread();
370 BUILTINS_API_TRACE(thread, LinkedList, Remove);
371 [[maybe_unused]] EcmaHandleScope handleScope(thread);
372 JSHandle<JSTaggedValue> self = GetThis(argv);
373 if (!self->IsJSAPILinkedList()) {
374 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPILinkedList()) {
375 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
376 } else {
377 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
378 "The remove method cannot be bound");
379 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
380 }
381 }
382 JSHandle<JSTaggedValue> element = GetCallArg(argv, 0);
383 JSHandle<JSAPILinkedList> jsAPILinkedList = JSHandle<JSAPILinkedList>::Cast(self);
384 return jsAPILinkedList->Remove(thread, element.GetTaggedValue());
385 }
386
RemoveFirst(EcmaRuntimeCallInfo * argv)387 JSTaggedValue ContainersLinkedList::RemoveFirst(EcmaRuntimeCallInfo *argv)
388 {
389 ASSERT(argv != nullptr);
390 JSThread *thread = argv->GetThread();
391 BUILTINS_API_TRACE(thread, LinkedList, RemoveFirst);
392 [[maybe_unused]] EcmaHandleScope handleScope(thread);
393 JSHandle<JSTaggedValue> self = GetThis(argv);
394 if (!self->IsJSAPILinkedList()) {
395 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPILinkedList()) {
396 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
397 } else {
398 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
399 "The removeFirst method cannot be bound");
400 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
401 }
402 }
403 JSHandle<JSAPILinkedList> jsAPILinkedList = JSHandle<JSAPILinkedList>::Cast(self);
404 JSTaggedValue lastValue = JSAPILinkedList::RemoveFirst(thread, jsAPILinkedList);
405 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
406 return lastValue;
407 }
408
RemoveFirstFound(EcmaRuntimeCallInfo * argv)409 JSTaggedValue ContainersLinkedList::RemoveFirstFound(EcmaRuntimeCallInfo *argv)
410 {
411 ASSERT(argv != nullptr);
412 JSThread *thread = argv->GetThread();
413 BUILTINS_API_TRACE(thread, LinkedList, RemoveFirstFound);
414 [[maybe_unused]] EcmaHandleScope handleScope(thread);
415 JSHandle<JSTaggedValue> self = GetThis(argv);
416 if (!self->IsJSAPILinkedList()) {
417 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPILinkedList()) {
418 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
419 } else {
420 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
421 "The removeFirstFound method cannot be bound");
422 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
423 }
424 }
425 JSHandle<JSTaggedValue> element = GetCallArg(argv, 0);
426
427 JSHandle<JSAPILinkedList> jsAPILinkedList = JSHandle<JSAPILinkedList>::Cast(self);
428 JSTaggedValue result = JSAPILinkedList::RemoveFirstFound(thread, jsAPILinkedList, element.GetTaggedValue());
429 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
430 return result;
431 }
432
RemoveLast(EcmaRuntimeCallInfo * argv)433 JSTaggedValue ContainersLinkedList::RemoveLast(EcmaRuntimeCallInfo *argv)
434 {
435 ASSERT(argv != nullptr);
436 JSThread *thread = argv->GetThread();
437 BUILTINS_API_TRACE(thread, LinkedList, RemoveLast);
438 [[maybe_unused]] EcmaHandleScope handleScope(thread);
439 JSHandle<JSTaggedValue> self = GetThis(argv);
440 if (!self->IsJSAPILinkedList()) {
441 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPILinkedList()) {
442 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
443 } else {
444 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
445 "The removeLast method cannot be bound");
446 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
447 }
448 }
449 JSHandle<JSAPILinkedList> jsAPILinkedList = JSHandle<JSAPILinkedList>::Cast(self);
450 JSTaggedValue lastValue = JSAPILinkedList::RemoveLast(thread, jsAPILinkedList);
451 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
452 return lastValue;
453 }
454
RemoveLastFound(EcmaRuntimeCallInfo * argv)455 JSTaggedValue ContainersLinkedList::RemoveLastFound(EcmaRuntimeCallInfo *argv)
456 {
457 ASSERT(argv != nullptr);
458 JSThread *thread = argv->GetThread();
459 BUILTINS_API_TRACE(thread, LinkedList, RemoveLastFound);
460 [[maybe_unused]] EcmaHandleScope handleScope(thread);
461 JSHandle<JSTaggedValue> self = GetThis(argv);
462 if (!self->IsJSAPILinkedList()) {
463 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPILinkedList()) {
464 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
465 } else {
466 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
467 "The removeLastFound method cannot be bound");
468 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
469 }
470 }
471 JSHandle<JSTaggedValue> element = GetCallArg(argv, 0);
472 JSHandle<JSAPILinkedList> jsAPILinkedList = JSHandle<JSAPILinkedList>::Cast(self);
473 JSTaggedValue result = JSAPILinkedList::RemoveLastFound(thread, jsAPILinkedList, element.GetTaggedValue());
474 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
475 return result;
476 }
477
Set(EcmaRuntimeCallInfo * argv)478 JSTaggedValue ContainersLinkedList::Set(EcmaRuntimeCallInfo *argv)
479 {
480 ASSERT(argv != nullptr);
481 JSThread *thread = argv->GetThread();
482 BUILTINS_API_TRACE(thread, LinkedList, Set);
483 [[maybe_unused]] EcmaHandleScope handleScope(thread);
484 JSHandle<JSTaggedValue> self = GetThis(argv);
485 if (!self->IsJSAPILinkedList()) {
486 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPILinkedList()) {
487 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
488 } else {
489 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
490 "The set 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> element = 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 JSHandle<JSAPILinkedList> jsAPILinkedList = JSHandle<JSAPILinkedList>::Cast(self);
508 JSTaggedValue oldValue =
509 JSAPILinkedList::Set(thread, jsAPILinkedList, index->GetInt(), element);
510 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
511 return oldValue;
512 }
513
ConvertToArray(EcmaRuntimeCallInfo * argv)514 JSTaggedValue ContainersLinkedList::ConvertToArray(EcmaRuntimeCallInfo *argv)
515 {
516 ASSERT(argv != nullptr);
517 JSThread *thread = argv->GetThread();
518 BUILTINS_API_TRACE(thread, LinkedList, ConvertToArray);
519 [[maybe_unused]] EcmaHandleScope handleScope(thread);
520 JSHandle<JSTaggedValue> self = GetThis(argv);
521 if (!self->IsJSAPILinkedList()) {
522 if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPILinkedList()) {
523 self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
524 } else {
525 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
526 "The convertToArray method cannot be bound");
527 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
528 }
529 }
530 JSHandle<JSAPILinkedList> jsAPILinkedList = JSHandle<JSAPILinkedList>::Cast(self);
531 return JSAPILinkedList::ConvertToArray(thread, jsAPILinkedList);
532 }
533
ForEach(EcmaRuntimeCallInfo * argv)534 JSTaggedValue ContainersLinkedList::ForEach(EcmaRuntimeCallInfo *argv)
535 {
536 ASSERT(argv != nullptr);
537 JSThread *thread = argv->GetThread();
538 BUILTINS_API_TRACE(thread, LinkedList, ForEach);
539 [[maybe_unused]] EcmaHandleScope handleScope(thread);
540 JSHandle<JSTaggedValue> thisHandle = GetThis(argv);
541 if (!thisHandle->IsJSAPILinkedList()) {
542 if (thisHandle->IsJSProxy() && JSHandle<JSProxy>::Cast(thisHandle)->GetTarget().IsJSAPILinkedList()) {
543 thisHandle = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(thisHandle)->GetTarget());
544 } else {
545 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
546 "The forEach method cannot be bound");
547 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
548 }
549 }
550
551 JSHandle<JSTaggedValue> callbackFnHandle(GetCallArg(argv, 0));
552 if (!callbackFnHandle->IsCallable()) {
553 JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, callbackFnHandle.GetTaggedValue());
554 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
555 CString errorMsg =
556 "The type of \"callbackfn\" must be callable. Received value is: " + ConvertToString(*result);
557 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str());
558 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
559 }
560
561 JSHandle<JSTaggedValue> thisArgHandle = GetCallArg(argv, 1);
562 JSHandle<JSAPILinkedList> linkedList = JSHandle<JSAPILinkedList>::Cast(thisHandle);
563 JSHandle<TaggedDoubleList> doubleList(thread, linkedList->GetDoubleList());
564 uint32_t length = linkedList->Length();
565
566 uint32_t index = 0;
567 const uint32_t argsLength = 3; // 3: «kValue, k, O»
568 JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
569 int valueNode = TaggedDoubleList::ELEMENTS_START_INDEX;
570 while (index < length) {
571 valueNode = doubleList->GetNextDataIndex(valueNode);
572 JSTaggedValue value = doubleList->GetElement(valueNode);
573 EcmaRuntimeCallInfo *info =
574 EcmaInterpreter::NewRuntimeCallInfo(thread, callbackFnHandle, thisArgHandle, undefined, argsLength);
575 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
576 info->SetCallArg(value, JSTaggedValue(index), thisHandle.GetTaggedValue());
577 JSTaggedValue funcResult = JSFunction::Call(info);
578 RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, funcResult);
579 index++;
580 }
581 return JSTaggedValue::Undefined();
582 }
583
GetIteratorObj(EcmaRuntimeCallInfo * argv)584 JSTaggedValue ContainersLinkedList::GetIteratorObj(EcmaRuntimeCallInfo *argv)
585 {
586 ASSERT(argv != nullptr);
587 JSThread *thread = argv->GetThread();
588 BUILTINS_API_TRACE(thread, LinkedList, GetIteratorObj);
589 [[maybe_unused]] EcmaHandleScope handleScope(thread);
590 JSHandle<JSTaggedValue> self = GetThis(argv);
591 JSHandle<JSTaggedValue> iter = JSAPILinkedListIterator::CreateLinkedListIterator(thread, self);
592 return iter.GetTaggedValue();
593 }
594 } // namespace panda::ecmascript::containers
595