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