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