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