• 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         CString errorMsg =
182             "The type of \"index\" must be number. 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 
187     JSHandle<JSAPILinkedList> jsAPILinkedList = JSHandle<JSAPILinkedList>::Cast(self);
188     JSTaggedValue result =
189         JSAPILinkedList::Insert(thread, jsAPILinkedList, value, index->GetInt());
190     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
191     return result;
192 }
193 
Clear(EcmaRuntimeCallInfo * argv)194 JSTaggedValue ContainersLinkedList::Clear(EcmaRuntimeCallInfo *argv)
195 {
196     ASSERT(argv != nullptr);
197     JSThread *thread = argv->GetThread();
198     BUILTINS_API_TRACE(thread, LinkedList, Clear);
199     [[maybe_unused]] EcmaHandleScope handleScope(thread);
200     JSHandle<JSTaggedValue> self = GetThis(argv);
201     if (!self->IsJSAPILinkedList()) {
202         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPILinkedList()) {
203             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
204         } else {
205             JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
206                                                                 "The clear method cannot be bound");
207             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
208         }
209     }
210     JSHandle<JSAPILinkedList> jsAPILinkedList = JSHandle<JSAPILinkedList>::Cast(self);
211     jsAPILinkedList->Clear(thread);
212     return JSTaggedValue::Undefined();
213 }
214 
Clone(EcmaRuntimeCallInfo * argv)215 JSTaggedValue ContainersLinkedList::Clone(EcmaRuntimeCallInfo *argv)
216 {
217     ASSERT(argv != nullptr);
218     JSThread *thread = argv->GetThread();
219     BUILTINS_API_TRACE(thread, LinkedList, Clone);
220     [[maybe_unused]] EcmaHandleScope handleScope(thread);
221     JSHandle<JSTaggedValue> self = GetThis(argv);
222 
223     if (!self->IsJSAPILinkedList()) {
224         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPILinkedList()) {
225             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
226         } else {
227             JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
228                                                                 "The clone method cannot be bound");
229             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
230         }
231     }
232     JSHandle<JSAPILinkedList> jsAPILinkedList = JSHandle<JSAPILinkedList>::Cast(self);
233     JSHandle<JSAPILinkedList> newLinkedList = JSAPILinkedList::Clone(thread, jsAPILinkedList);
234     return newLinkedList.GetTaggedValue();
235 }
236 
Has(EcmaRuntimeCallInfo * argv)237 JSTaggedValue ContainersLinkedList::Has(EcmaRuntimeCallInfo *argv)
238 {
239     ASSERT(argv != nullptr);
240     JSThread *thread = argv->GetThread();
241     BUILTINS_API_TRACE(thread, LinkedList, Has);
242     [[maybe_unused]] EcmaHandleScope handleScope(thread);
243     JSHandle<JSTaggedValue> self = GetThis(argv);
244     if (!self->IsJSAPILinkedList()) {
245         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPILinkedList()) {
246             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
247         } else {
248             JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
249                                                                 "The has method cannot be bound");
250             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
251         }
252     }
253     JSHandle<JSAPILinkedList> jsAPILinkedList = JSHandle<JSAPILinkedList>::Cast(self);
254     JSHandle<JSTaggedValue> element = GetCallArg(argv, 0);
255     return GetTaggedBoolean(jsAPILinkedList->Has(element.GetTaggedValue()));
256 }
257 
Get(EcmaRuntimeCallInfo * argv)258 JSTaggedValue ContainersLinkedList::Get(EcmaRuntimeCallInfo *argv)
259 {
260     ASSERT(argv != nullptr);
261     JSThread *thread = argv->GetThread();
262     BUILTINS_API_TRACE(thread, LinkedList, Get);
263     [[maybe_unused]] EcmaHandleScope handleScope(thread);
264     JSHandle<JSTaggedValue> self = GetThis(argv);
265     if (!self->IsJSAPILinkedList()) {
266         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPILinkedList()) {
267             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
268         } else {
269             JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
270                                                                 "The get method cannot be bound");
271             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
272         }
273     }
274     JSHandle<JSAPILinkedList> jsAPILinkedList = JSHandle<JSAPILinkedList>::Cast(self);
275     JSHandle<JSTaggedValue> index = GetCallArg(argv, 0);
276     if (!index->IsInteger()) {
277         JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, index.GetTaggedValue());
278         CString errorMsg =
279             "The type of \"index\" must be number. Received value is: " + ConvertToString(*result);
280         JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str());
281         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
282     }
283     return jsAPILinkedList->Get(index->GetInt());
284 }
285 
GetIndexOf(EcmaRuntimeCallInfo * argv)286 JSTaggedValue ContainersLinkedList::GetIndexOf(EcmaRuntimeCallInfo *argv)
287 {
288     ASSERT(argv != nullptr);
289     JSThread *thread = argv->GetThread();
290     BUILTINS_API_TRACE(thread, LinkedList, GetIndexOf);
291     [[maybe_unused]] EcmaHandleScope handleScope(thread);
292     JSHandle<JSTaggedValue> self = GetThis(argv);
293     if (!self->IsJSAPILinkedList()) {
294         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPILinkedList()) {
295             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
296         } else {
297             JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
298                                                                 "The getIndexOf method cannot be bound");
299             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
300         }
301     }
302     JSHandle<JSAPILinkedList> jsAPILinkedList = JSHandle<JSAPILinkedList>::Cast(self);
303     JSHandle<JSTaggedValue> element = GetCallArg(argv, 0);
304     return jsAPILinkedList->GetIndexOf(element.GetTaggedValue());
305 }
306 
GetLastIndexOf(EcmaRuntimeCallInfo * argv)307 JSTaggedValue ContainersLinkedList::GetLastIndexOf(EcmaRuntimeCallInfo *argv)
308 {
309     ASSERT(argv != nullptr);
310     JSThread *thread = argv->GetThread();
311     BUILTINS_API_TRACE(thread, LinkedList, GetLastIndexOf);
312     [[maybe_unused]] EcmaHandleScope handleScope(thread);
313     JSHandle<JSTaggedValue> self = GetThis(argv);
314     if (!self->IsJSAPILinkedList()) {
315         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPILinkedList()) {
316             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
317         } else {
318             JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
319                                                                 "The getLastIndexOf method cannot be bound");
320             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
321         }
322     }
323     JSHandle<JSAPILinkedList> jsAPILinkedList = JSHandle<JSAPILinkedList>::Cast(self);
324     JSHandle<JSTaggedValue> element(GetCallArg(argv, 0));
325     return jsAPILinkedList->GetLastIndexOf(element.GetTaggedValue());
326 }
327 
RemoveByIndex(EcmaRuntimeCallInfo * argv)328 JSTaggedValue ContainersLinkedList::RemoveByIndex(EcmaRuntimeCallInfo *argv)
329 {
330     ASSERT(argv != nullptr);
331     JSThread *thread = argv->GetThread();
332     BUILTINS_API_TRACE(thread, LinkedList, RemoveByIndex);
333     [[maybe_unused]] EcmaHandleScope handleScope(thread);
334     JSHandle<JSTaggedValue> self = GetThis(argv);
335     if (!self->IsJSAPILinkedList()) {
336         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPILinkedList()) {
337             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
338         } else {
339             JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
340                                                                 "The removeByIndex method cannot be bound");
341             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
342         }
343     }
344     JSHandle<JSTaggedValue> index = GetCallArg(argv, 0);
345     if (!index->IsInteger()) {
346         JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, index.GetTaggedValue());
347         CString errorMsg =
348             "The type of \"index\" must be number. Received value is: " + ConvertToString(*result);
349         JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str());
350         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
351     }
352     JSHandle<JSAPILinkedList> jsAPILinkedList = JSHandle<JSAPILinkedList>::Cast(self);
353     JSTaggedValue nodeData =
354         JSAPILinkedList::RemoveByIndex(thread, jsAPILinkedList, index->GetInt());
355     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
356     return nodeData;
357 }
358 
Remove(EcmaRuntimeCallInfo * argv)359 JSTaggedValue ContainersLinkedList::Remove(EcmaRuntimeCallInfo *argv)
360 {
361     ASSERT(argv != nullptr);
362     JSThread *thread = argv->GetThread();
363     BUILTINS_API_TRACE(thread, LinkedList, Remove);
364     [[maybe_unused]] EcmaHandleScope handleScope(thread);
365     JSHandle<JSTaggedValue> self = GetThis(argv);
366     if (!self->IsJSAPILinkedList()) {
367         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPILinkedList()) {
368             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
369         } else {
370             JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
371                                                                 "The remove method cannot be bound");
372             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
373         }
374     }
375     JSHandle<JSTaggedValue> element = GetCallArg(argv, 0);
376     JSHandle<JSAPILinkedList> jsAPILinkedList = JSHandle<JSAPILinkedList>::Cast(self);
377     return jsAPILinkedList->Remove(thread, element.GetTaggedValue());
378 }
379 
RemoveFirst(EcmaRuntimeCallInfo * argv)380 JSTaggedValue ContainersLinkedList::RemoveFirst(EcmaRuntimeCallInfo *argv)
381 {
382     ASSERT(argv != nullptr);
383     JSThread *thread = argv->GetThread();
384     BUILTINS_API_TRACE(thread, LinkedList, RemoveFirst);
385     [[maybe_unused]] EcmaHandleScope handleScope(thread);
386     JSHandle<JSTaggedValue> self = GetThis(argv);
387     if (!self->IsJSAPILinkedList()) {
388         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPILinkedList()) {
389             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
390         } else {
391             JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
392                                                                 "The removeFirst method cannot be bound");
393             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
394         }
395     }
396     JSHandle<JSAPILinkedList> jsAPILinkedList = JSHandle<JSAPILinkedList>::Cast(self);
397     JSTaggedValue lastValue = JSAPILinkedList::RemoveFirst(thread, jsAPILinkedList);
398     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
399     return lastValue;
400 }
401 
RemoveFirstFound(EcmaRuntimeCallInfo * argv)402 JSTaggedValue ContainersLinkedList::RemoveFirstFound(EcmaRuntimeCallInfo *argv)
403 {
404     ASSERT(argv != nullptr);
405     JSThread *thread = argv->GetThread();
406     BUILTINS_API_TRACE(thread, LinkedList, RemoveFirstFound);
407     [[maybe_unused]] EcmaHandleScope handleScope(thread);
408     JSHandle<JSTaggedValue> self = GetThis(argv);
409     if (!self->IsJSAPILinkedList()) {
410         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPILinkedList()) {
411             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
412         } else {
413             JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
414                                                                 "The removeFirstFound method cannot be bound");
415             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
416         }
417     }
418     JSHandle<JSTaggedValue> element = GetCallArg(argv, 0);
419 
420     JSHandle<JSAPILinkedList> jsAPILinkedList = JSHandle<JSAPILinkedList>::Cast(self);
421     JSTaggedValue result = JSAPILinkedList::RemoveFirstFound(thread, jsAPILinkedList, element.GetTaggedValue());
422     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
423     return result;
424 }
425 
RemoveLast(EcmaRuntimeCallInfo * argv)426 JSTaggedValue ContainersLinkedList::RemoveLast(EcmaRuntimeCallInfo *argv)
427 {
428     ASSERT(argv != nullptr);
429     JSThread *thread = argv->GetThread();
430     BUILTINS_API_TRACE(thread, LinkedList, RemoveLast);
431     [[maybe_unused]] EcmaHandleScope handleScope(thread);
432     JSHandle<JSTaggedValue> self = GetThis(argv);
433     if (!self->IsJSAPILinkedList()) {
434         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPILinkedList()) {
435             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
436         } else {
437             JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
438                                                                 "The removeLast method cannot be bound");
439             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
440         }
441     }
442     JSHandle<JSAPILinkedList> jsAPILinkedList = JSHandle<JSAPILinkedList>::Cast(self);
443     JSTaggedValue lastValue = JSAPILinkedList::RemoveLast(thread, jsAPILinkedList);
444     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
445     return lastValue;
446 }
447 
RemoveLastFound(EcmaRuntimeCallInfo * argv)448 JSTaggedValue ContainersLinkedList::RemoveLastFound(EcmaRuntimeCallInfo *argv)
449 {
450     ASSERT(argv != nullptr);
451     JSThread *thread = argv->GetThread();
452     BUILTINS_API_TRACE(thread, LinkedList, RemoveLastFound);
453     [[maybe_unused]] EcmaHandleScope handleScope(thread);
454     JSHandle<JSTaggedValue> self = GetThis(argv);
455     if (!self->IsJSAPILinkedList()) {
456         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPILinkedList()) {
457             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
458         } else {
459             JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
460                                                                 "The removeLastFound method cannot be bound");
461             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
462         }
463     }
464     JSHandle<JSTaggedValue> element = GetCallArg(argv, 0);
465     JSHandle<JSAPILinkedList> jsAPILinkedList = JSHandle<JSAPILinkedList>::Cast(self);
466     JSTaggedValue result = JSAPILinkedList::RemoveLastFound(thread, jsAPILinkedList, element.GetTaggedValue());
467     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
468     return result;
469 }
470 
Set(EcmaRuntimeCallInfo * argv)471 JSTaggedValue ContainersLinkedList::Set(EcmaRuntimeCallInfo *argv)
472 {
473     ASSERT(argv != nullptr);
474     JSThread *thread = argv->GetThread();
475     BUILTINS_API_TRACE(thread, LinkedList, Set);
476     [[maybe_unused]] EcmaHandleScope handleScope(thread);
477     JSHandle<JSTaggedValue> self = GetThis(argv);
478     if (!self->IsJSAPILinkedList()) {
479         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPILinkedList()) {
480             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
481         } else {
482             JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
483                                                                 "The set method cannot be bound");
484             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
485         }
486     }
487     JSHandle<JSTaggedValue> index = GetCallArg(argv, 0);
488     JSHandle<JSTaggedValue> element = GetCallArg(argv, 1);
489     if (!index->IsInteger()) {
490         JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, index.GetTaggedValue());
491         CString errorMsg =
492             "The type of \"index\" must be number. Received value is: " + ConvertToString(*result);
493         JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str());
494         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
495     }
496     JSHandle<JSAPILinkedList> jsAPILinkedList = JSHandle<JSAPILinkedList>::Cast(self);
497     JSTaggedValue oldValue =
498         JSAPILinkedList::Set(thread, jsAPILinkedList, index->GetInt(), element);
499     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
500     return oldValue;
501 }
502 
ConvertToArray(EcmaRuntimeCallInfo * argv)503 JSTaggedValue ContainersLinkedList::ConvertToArray(EcmaRuntimeCallInfo *argv)
504 {
505     ASSERT(argv != nullptr);
506     JSThread *thread = argv->GetThread();
507     BUILTINS_API_TRACE(thread, LinkedList, ConvertToArray);
508     [[maybe_unused]] EcmaHandleScope handleScope(thread);
509     JSHandle<JSTaggedValue> self = GetThis(argv);
510     if (!self->IsJSAPILinkedList()) {
511         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPILinkedList()) {
512             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
513         } else {
514             JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
515                                                                 "The convertToArray method cannot be bound");
516             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
517         }
518     }
519     JSHandle<JSAPILinkedList> jsAPILinkedList = JSHandle<JSAPILinkedList>::Cast(self);
520     return JSAPILinkedList::ConvertToArray(thread, jsAPILinkedList);
521 }
522 
ForEach(EcmaRuntimeCallInfo * argv)523 JSTaggedValue ContainersLinkedList::ForEach(EcmaRuntimeCallInfo *argv)
524 {
525     ASSERT(argv != nullptr);
526     JSThread *thread = argv->GetThread();
527     BUILTINS_API_TRACE(thread, LinkedList, ForEach);
528     [[maybe_unused]] EcmaHandleScope handleScope(thread);
529     JSHandle<JSTaggedValue> thisHandle = GetThis(argv);
530     if (!thisHandle->IsJSAPILinkedList()) {
531         if (thisHandle->IsJSProxy() && JSHandle<JSProxy>::Cast(thisHandle)->GetTarget().IsJSAPILinkedList()) {
532             thisHandle = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(thisHandle)->GetTarget());
533         } else {
534             JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR,
535                                                                 "The forEach method cannot be bound");
536             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
537         }
538     }
539 
540     JSHandle<JSTaggedValue> callbackFnHandle(GetCallArg(argv, 0));
541     if (!callbackFnHandle->IsCallable()) {
542         JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, callbackFnHandle.GetTaggedValue());
543         CString errorMsg =
544             "The type of \"callbackfn\" must be callable. Received value is: " + ConvertToString(*result);
545         JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str());
546         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
547     }
548 
549     JSHandle<JSTaggedValue> thisArgHandle = GetCallArg(argv, 1);
550     JSHandle<JSAPILinkedList> linkedList = JSHandle<JSAPILinkedList>::Cast(thisHandle);
551     JSHandle<TaggedDoubleList> doubleList(thread, linkedList->GetDoubleList());
552     int length = linkedList->Length();
553 
554     int index = 0;
555     const uint32_t argsLength = 3; // 3: «kValue, k, O»
556     JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
557     int valueNode = TaggedDoubleList::ELEMENTS_START_INDEX;
558     while (index < length) {
559         valueNode = doubleList->GetNextDataIndex(valueNode);
560         JSTaggedValue value = doubleList->GetElement(valueNode);
561         EcmaRuntimeCallInfo *info =
562             EcmaInterpreter::NewRuntimeCallInfo(thread, callbackFnHandle, thisArgHandle, undefined, argsLength);
563         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
564         info->SetCallArg(value, JSTaggedValue(index), thisHandle.GetTaggedValue());
565         JSTaggedValue funcResult = JSFunction::Call(info);
566         RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, funcResult);
567         index++;
568     }
569     return JSTaggedValue::Undefined();
570 }
571 
GetIteratorObj(EcmaRuntimeCallInfo * argv)572 JSTaggedValue ContainersLinkedList::GetIteratorObj(EcmaRuntimeCallInfo *argv)
573 {
574     ASSERT(argv != nullptr);
575     JSThread *thread = argv->GetThread();
576     BUILTINS_API_TRACE(thread, LinkedList, GetIteratorObj);
577     [[maybe_unused]] EcmaHandleScope handleScope(thread);
578     JSHandle<JSTaggedValue> self = GetThis(argv);
579     JSHandle<JSTaggedValue> iter = JSAPILinkedListIterator::CreateLinkedListIterator(thread, self);
580     return iter.GetTaggedValue();
581 }
582 }  // namespace panda::ecmascript::containers
583