• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 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_bitvector.h"
17 
18 #include "ecmascript/containers/containers_errors.h"
19 #include "ecmascript/js_api/js_api_bitvector.h"
20 #include "ecmascript/object_factory-inl.h"
21 namespace panda::ecmascript::containers {
BitVectorConstructor(EcmaRuntimeCallInfo * argv)22 JSTaggedValue ContainersBitVector::BitVectorConstructor(EcmaRuntimeCallInfo* argv)
23 {
24     ASSERT(argv);
25     JSThread* thread = argv->GetThread();
26     BUILTINS_API_TRACE(thread, BitVector, Constructor);
27     [[maybe_unused]] EcmaHandleScope handleScope(thread);
28 
29     ObjectFactory* factory = thread->GetEcmaVM()->GetFactory();
30     JSHandle<JSTaggedValue> newTarget = GetNewTarget(argv);
31     if (newTarget->IsUndefined()) {
32         JSTaggedValue error = ContainerError::BusinessError(
33             thread, ErrorFlag::IS_NULL_ERROR, "The BitVector's constructor cannot be directly invoked.");
34         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
35     }
36     JSHandle<JSTaggedValue> constructor = GetConstructor(argv);
37     ASSERT(constructor->IsJSSharedFunction() && constructor.GetTaggedValue().IsInSharedHeap());
38     JSHandle<JSAPIBitVector> obj =
39         JSHandle<JSAPIBitVector>(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(constructor), newTarget));
40     ASSERT(obj.GetTaggedValue().IsInSharedHeap());
41     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
42 
43     JSHandle<JSTaggedValue> length = GetCallArg(argv, 0);
44     if (!length->IsInteger()) {
45         JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, length);
46         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
47         CString errorMsg = "The type of \"length\" must be integer. Received value is: " + ConvertToString(*result);
48         JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str());
49         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
50     }
51 
52     auto* newBitSetVector = new std::vector<std::bitset<JSAPIBitVector::BIT_SET_LENGTH>>();
53     if (!length->IsZero()) {
54         int32_t capacity = std::max(0, (length->GetInt() / JSAPIBitVector::BIT_SET_LENGTH) + 1);
55 
56         std::bitset<JSAPIBitVector::BIT_SET_LENGTH> initBitSet;
57         newBitSetVector->resize(capacity, initBitSet);
58     }
59     JSHandle<JSNativePointer> pointer = factory->NewSJSNativePointer(newBitSetVector,
60                                                                      ContainersBitVector::FreeBitsetVectorPointer,
61                                                                      newBitSetVector);
62     obj->SetNativePointer(thread, pointer);
63     obj->SetLength(std::max(0, length->GetInt()));
64     return obj.GetTaggedValue();
65 }
66 
Push(EcmaRuntimeCallInfo * argv)67 JSTaggedValue ContainersBitVector::Push(EcmaRuntimeCallInfo* argv)
68 {
69     BUILTINS_API_TRACE(argv->GetThread(), BitVector, Push);
70     JSThread* thread = argv->GetThread();
71     [[maybe_unused]] EcmaHandleScope handleScope(thread);
72     JSHandle<JSTaggedValue> self = GetThis(argv);
73 
74     if (!self->IsJSAPIBitVector()) {
75         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIBitVector()) {
76             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
77         } else {
78             JSTaggedValue error =
79                 ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR, "The push method cannot be bound");
80             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
81         }
82     }
83 
84     JSHandle<JSTaggedValue> value = GetCallArg(argv, 0);
85     return GetTaggedBoolean(JSAPIBitVector::Push(thread, JSHandle<JSAPIBitVector>::Cast(self), value));
86 }
87 
Pop(EcmaRuntimeCallInfo * argv)88 JSTaggedValue ContainersBitVector::Pop(EcmaRuntimeCallInfo* argv)
89 {
90     BUILTINS_API_TRACE(argv->GetThread(), BitVector, Pop);
91     JSThread* thread = argv->GetThread();
92     [[maybe_unused]] EcmaHandleScope handleScope(thread);
93     JSHandle<JSTaggedValue> self = GetThis(argv);
94 
95     if (!self->IsJSAPIBitVector()) {
96         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIBitVector()) {
97             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
98         } else {
99             JSTaggedValue error =
100                 ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR, "The pop method cannot be bound");
101             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
102         }
103     }
104 
105     return JSHandle<JSAPIBitVector>::Cast(self)->Pop(thread, JSHandle<JSAPIBitVector>::Cast(self));
106 }
107 
Has(EcmaRuntimeCallInfo * argv)108 JSTaggedValue ContainersBitVector::Has(EcmaRuntimeCallInfo* argv)
109 {
110     ASSERT(argv);
111     BUILTINS_API_TRACE(argv->GetThread(), BitVector, Has);
112     JSThread* thread = argv->GetThread();
113     [[maybe_unused]] EcmaHandleScope handleScope(thread);
114     JSHandle<JSTaggedValue> self = GetThis(argv);
115 
116     if (!self->IsJSAPIBitVector()) {
117         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIBitVector()) {
118             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
119         } else {
120             JSTaggedValue error = ContainerError::BusinessError(thread, BIND_ERROR, "The has method cannot be bound");
121             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
122         }
123     }
124 
125     JSHandle<JSTaggedValue> value = GetCallArg(argv, 0);
126     JSHandle<JSTaggedValue> startIndex = GetCallArg(argv, 1);
127     JSHandle<JSTaggedValue> endIndex = GetCallArg(argv, 2); // 2 means the third arg
128     if (!startIndex->IsInteger()) {
129         JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, startIndex);
130         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
131         CString errorMsg = "The type of \"fromIndex\" must be integer. Received value is: " + ConvertToString(*result);
132         JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str());
133         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
134     }
135     if (!endIndex->IsInteger()) {
136         JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, endIndex);
137         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
138         CString errorMsg = "The type of \"toIndex\" must be integer. Received value is: " + ConvertToString(*result);
139         JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str());
140         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
141     }
142     bool isHas = JSHandle<JSAPIBitVector>::Cast(self)->Has(
143         thread, JSHandle<JSAPIBitVector>::Cast(self), value, startIndex, endIndex);
144 
145     return GetTaggedBoolean(isHas);
146 }
147 
SetBitsByRange(EcmaRuntimeCallInfo * argv)148 JSTaggedValue ContainersBitVector::SetBitsByRange(EcmaRuntimeCallInfo* argv)
149 {
150     ASSERT(argv);
151     BUILTINS_API_TRACE(argv->GetThread(), BitVector, SetBitsByRange);
152     JSThread* thread = argv->GetThread();
153     [[maybe_unused]] EcmaHandleScope handleScope(thread);
154     JSHandle<JSTaggedValue> self = GetThis(argv);
155 
156     if (!self->IsJSAPIBitVector()) {
157         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIBitVector()) {
158             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
159         } else {
160             JSTaggedValue error =
161                 ContainerError::BusinessError(thread, BIND_ERROR, "The setBitsByRange method cannot be bound");
162             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
163         }
164     }
165 
166     JSHandle<JSTaggedValue> value = GetCallArg(argv, 0);
167     JSHandle<JSTaggedValue> startIndex = GetCallArg(argv, 1);
168     JSHandle<JSTaggedValue> endIndex = GetCallArg(argv, 2); // 2 means the third arg
169     if (!startIndex->IsInteger()) {
170         JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, startIndex);
171         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
172         CString errorMsg = "The type of \"fromIndex\" must be integer. Received value is: " + ConvertToString(*result);
173         JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str());
174         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
175     }
176     if (!endIndex->IsInteger()) {
177         JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, endIndex);
178         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
179         CString errorMsg = "The type of \"toIndex\" must be integer. Received value is: " + ConvertToString(*result);
180         JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str());
181         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
182     }
183     JSHandle<JSAPIBitVector>::Cast(self)->SetBitsByRange(
184         thread, JSHandle<JSAPIBitVector>::Cast(self), value, startIndex, endIndex);
185     return JSTaggedValue::Undefined();
186 }
187 
GetBitsByRange(EcmaRuntimeCallInfo * argv)188 JSTaggedValue ContainersBitVector::GetBitsByRange(EcmaRuntimeCallInfo* argv)
189 {
190     ASSERT(argv);
191     BUILTINS_API_TRACE(argv->GetThread(), BitVector, GetBitsByRange);
192     JSThread* thread = argv->GetThread();
193     [[maybe_unused]] EcmaHandleScope handleScope(thread);
194     JSHandle<JSTaggedValue> self = GetThis(argv);
195 
196     if (!self->IsJSAPIBitVector()) {
197         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIBitVector()) {
198             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
199         } else {
200             JSTaggedValue error =
201                 ContainerError::BusinessError(thread, BIND_ERROR, "The getBitsByRange method cannot be bound");
202             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
203         }
204     }
205 
206     JSHandle<JSTaggedValue> startIndex = GetCallArg(argv, 0);
207     JSHandle<JSTaggedValue> endIndex = GetCallArg(argv, 1);
208     if (!startIndex->IsInteger()) {
209         JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, startIndex);
210         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
211         CString errorMsg = "The type of \"fromIndex\" must be integer. Received value is: " + ConvertToString(*result);
212         JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str());
213         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
214     }
215     if (!endIndex->IsInteger()) {
216         JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, endIndex);
217         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
218         CString errorMsg = "The type of \"toIndex\" must be integer. Received value is: " + ConvertToString(*result);
219         JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str());
220         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
221     }
222     return JSHandle<JSAPIBitVector>::Cast(self)->GetBitsByRange(
223         thread, JSHandle<JSAPIBitVector>::Cast(self), startIndex, endIndex);
224 }
225 
Resize(EcmaRuntimeCallInfo * argv)226 JSTaggedValue ContainersBitVector::Resize(EcmaRuntimeCallInfo* argv)
227 {
228     ASSERT(argv);
229     BUILTINS_API_TRACE(argv->GetThread(), BitVector, Resize);
230     JSThread* thread = argv->GetThread();
231     [[maybe_unused]] EcmaHandleScope handleScope(thread);
232     JSHandle<JSTaggedValue> self = GetThis(argv);
233 
234     if (!self->IsJSAPIBitVector()) {
235         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIBitVector()) {
236             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
237         } else {
238             JSTaggedValue error =
239                 ContainerError::BusinessError(thread, BIND_ERROR, "The resize method cannot be bound");
240             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
241         }
242     }
243     JSHandle<JSTaggedValue> size = GetCallArg(argv, 0);
244     if (!size->IsInteger()) {
245         JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, size);
246         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
247         CString errorMsg = "The type of \"size\" must be integer. Received value is: " + ConvertToString(*result);
248         JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str());
249         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
250     }
251     JSHandle<JSAPIBitVector>::Cast(self)->Resize(
252         thread, JSHandle<JSAPIBitVector>::Cast(self), JSTaggedValue::ToUint32(thread, size));
253     return JSTaggedValue::Undefined();
254 }
255 
SetAllBits(EcmaRuntimeCallInfo * argv)256 JSTaggedValue ContainersBitVector::SetAllBits(EcmaRuntimeCallInfo* argv)
257 {
258     BUILTINS_API_TRACE(argv->GetThread(), BitVector, SetAllBits);
259     JSThread* thread = argv->GetThread();
260     [[maybe_unused]] EcmaHandleScope handleScope(thread);
261     JSHandle<JSTaggedValue> self = GetThis(argv);
262 
263     if (!self->IsJSAPIBitVector()) {
264         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIBitVector()) {
265             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
266         } else {
267             JSTaggedValue error =
268                 ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR, "The setAllBits method cannot be bound");
269             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
270         }
271     }
272 
273     JSHandle<JSTaggedValue> value = GetCallArg(argv, 0);
274     JSHandle<JSAPIBitVector>::Cast(self)->SetAllBits(thread, JSHandle<JSAPIBitVector>::Cast(self), value);
275     return JSTaggedValue::Undefined();
276 }
277 
GetBitCountByRange(EcmaRuntimeCallInfo * argv)278 JSTaggedValue ContainersBitVector::GetBitCountByRange(EcmaRuntimeCallInfo* argv)
279 {
280     ASSERT(argv);
281     BUILTINS_API_TRACE(argv->GetThread(), BitVector, GetBitCountByRange);
282     JSThread* thread = argv->GetThread();
283     [[maybe_unused]] EcmaHandleScope handleScope(thread);
284     JSHandle<JSTaggedValue> self = GetThis(argv);
285 
286     if (!self->IsJSAPIBitVector()) {
287         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIBitVector()) {
288             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
289         } else {
290             JSTaggedValue error =
291                 ContainerError::BusinessError(thread, BIND_ERROR, "The getBitCountByRange method cannot be bound");
292             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
293         }
294     }
295 
296     JSHandle<JSTaggedValue> value = GetCallArg(argv, 0);
297     JSHandle<JSTaggedValue> startIndex = GetCallArg(argv, 1);
298     JSHandle<JSTaggedValue> endIndex = GetCallArg(argv, 2); // 2 means the third arg
299     if (!startIndex->IsInteger()) {
300         JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, startIndex);
301         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
302         CString errorMsg = "The type of \"fromIndex\" must be integer. Received value is: " + ConvertToString(*result);
303         JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str());
304         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
305     }
306     if (!endIndex->IsInteger()) {
307         JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, endIndex);
308         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
309         CString errorMsg = "The type of \"toIndex\" must be integer. Received value is: " + ConvertToString(*result);
310         JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str());
311         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
312     }
313     return JSHandle<JSAPIBitVector>::Cast(self)->GetBitCountByRange(
314         thread, JSHandle<JSAPIBitVector>::Cast(self), value, startIndex, endIndex);
315 }
316 
GetIndexOf(EcmaRuntimeCallInfo * argv)317 JSTaggedValue ContainersBitVector::GetIndexOf(EcmaRuntimeCallInfo* argv)
318 {
319     ASSERT(argv);
320     BUILTINS_API_TRACE(argv->GetThread(), BitVector, GetIndexOf);
321     JSThread* thread = argv->GetThread();
322     [[maybe_unused]] EcmaHandleScope handleScope(thread);
323     JSHandle<JSTaggedValue> self = GetThis(argv);
324 
325     if (!self->IsJSAPIBitVector()) {
326         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIBitVector()) {
327             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
328         } else {
329             JSTaggedValue error =
330                 ContainerError::BusinessError(thread, BIND_ERROR, "The getIndexOf method cannot be bound");
331             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
332         }
333     }
334 
335     JSHandle<JSTaggedValue> value = GetCallArg(argv, 0);
336     JSHandle<JSTaggedValue> startIndex = GetCallArg(argv, 1);
337     JSHandle<JSTaggedValue> endIndex = GetCallArg(argv, 2); // 2 means the third arg
338     if (!startIndex->IsInteger()) {
339         JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, startIndex);
340         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
341         CString errorMsg = "The type of \"fromIndex\" must be integer. Received value is: " + ConvertToString(*result);
342         JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str());
343         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
344     }
345     if (!endIndex->IsInteger()) {
346         JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, endIndex);
347         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
348         CString errorMsg = "The type of \"toIndex\" must be integer. 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 
353     return JSTaggedValue(
354         JSAPIBitVector::GetIndexOf(thread, JSHandle<JSAPIBitVector>::Cast(self), value, startIndex, endIndex));
355 }
356 
GetLastIndexOf(EcmaRuntimeCallInfo * argv)357 JSTaggedValue ContainersBitVector::GetLastIndexOf(EcmaRuntimeCallInfo* argv)
358 {
359     ASSERT(argv);
360     BUILTINS_API_TRACE(argv->GetThread(), BitVector, GetLastIndexOf);
361     JSThread* thread = argv->GetThread();
362     [[maybe_unused]] EcmaHandleScope handleScope(thread);
363     JSHandle<JSTaggedValue> self = GetThis(argv);
364 
365     if (!self->IsJSAPIBitVector()) {
366         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIBitVector()) {
367             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
368         } else {
369             JSTaggedValue error =
370                 ContainerError::BusinessError(thread, BIND_ERROR, "The getLastIndexOf method cannot be bound");
371             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
372         }
373     }
374 
375     JSHandle<JSTaggedValue> value = GetCallArg(argv, 0);
376     JSHandle<JSTaggedValue> startIndex = GetCallArg(argv, 1);
377     JSHandle<JSTaggedValue> endIndex = GetCallArg(argv, 2); // 2 means the third arg
378     if (!startIndex->IsInteger()) {
379         JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, startIndex);
380         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
381         CString errorMsg = "The type of \"fromIndex\" must be integer. Received value is: " + ConvertToString(*result);
382         JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str());
383         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
384     }
385     if (!endIndex->IsInteger()) {
386         JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, endIndex);
387         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
388         CString errorMsg = "The type of \"toIndex\" must be integer. Received value is: " + ConvertToString(*result);
389         JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str());
390         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
391     }
392     return JSTaggedValue(
393         JSAPIBitVector::GetLastIndexOf(thread, JSHandle<JSAPIBitVector>::Cast(self), value, startIndex, endIndex));
394 }
395 
FlipBitByIndex(EcmaRuntimeCallInfo * argv)396 JSTaggedValue ContainersBitVector::FlipBitByIndex(EcmaRuntimeCallInfo* argv)
397 {
398     ASSERT(argv);
399     BUILTINS_API_TRACE(argv->GetThread(), BitVector, FlipBitByIndex);
400     JSThread* thread = argv->GetThread();
401     [[maybe_unused]] EcmaHandleScope handleScope(thread);
402     JSHandle<JSTaggedValue> self = GetThis(argv);
403 
404     if (!self->IsJSAPIBitVector()) {
405         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIBitVector()) {
406             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
407         } else {
408             JSTaggedValue error =
409                 ContainerError::BusinessError(thread, BIND_ERROR, "The flipBitByIndex method cannot be bound");
410             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
411         }
412     }
413     JSHandle<JSTaggedValue> value = GetCallArg(argv, 0);
414     if (!value->IsInteger()) {
415         JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, value);
416         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
417         CString errorMsg = "The type of \"index\" must be integer. Received value is: " + ConvertToString(*result);
418         JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str());
419         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
420     }
421 
422     JSAPIBitVector::FlipBitByIndex(
423         thread, JSHandle<JSAPIBitVector>::Cast(self), JSTaggedValue::ToUint32(thread, value));
424     return JSTaggedValue::Undefined();
425 }
426 
FlipBitsByRange(EcmaRuntimeCallInfo * argv)427 JSTaggedValue ContainersBitVector::FlipBitsByRange(EcmaRuntimeCallInfo* argv)
428 {
429     ASSERT(argv);
430     BUILTINS_API_TRACE(argv->GetThread(), BitVector, FlipBitsByRange);
431     JSThread* thread = argv->GetThread();
432     [[maybe_unused]] EcmaHandleScope handleScope(thread);
433     JSHandle<JSTaggedValue> self = GetThis(argv);
434 
435     if (!self->IsJSAPIBitVector()) {
436         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIBitVector()) {
437             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
438         } else {
439             JSTaggedValue error =
440                 ContainerError::BusinessError(thread, BIND_ERROR, "The flipBitsByRange method cannot be bound");
441             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
442         }
443     }
444     JSHandle<JSTaggedValue> startIndex = GetCallArg(argv, 0);
445     JSHandle<JSTaggedValue> endIndex = GetCallArg(argv, 1);
446     if (!startIndex->IsInteger()) {
447         JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, startIndex);
448         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
449         CString errorMsg = "The type of \"fromIndex\" must be integer. Received value is: " + ConvertToString(*result);
450         JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str());
451         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
452     }
453     if (!endIndex->IsInteger()) {
454         JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, endIndex);
455         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
456         CString errorMsg = "The type of \"toIndex\" must be integer. Received value is: " + ConvertToString(*result);
457         JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str());
458         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
459     }
460     JSHandle<JSAPIBitVector>::Cast(self)->FlipBitsByRange(
461         thread, JSHandle<JSAPIBitVector>::Cast(self), startIndex, endIndex);
462     return JSTaggedValue::Undefined();
463 }
464 
GetSize(EcmaRuntimeCallInfo * argv)465 JSTaggedValue ContainersBitVector::GetSize(EcmaRuntimeCallInfo* argv)
466 {
467     ASSERT(argv);
468     BUILTINS_API_TRACE(argv->GetThread(), BitVector, GetSize);
469     JSThread* thread = argv->GetThread();
470     [[maybe_unused]] EcmaHandleScope handleScope(thread);
471     JSHandle<JSTaggedValue> self = GetThis(argv);
472 
473     if (!self->IsJSAPIBitVector()) {
474         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIBitVector()) {
475             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
476         } else {
477             JSTaggedValue error =
478                 ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR, "The getSize method cannot be bound");
479             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
480         }
481     }
482 
483     return JSTaggedValue(JSHandle<JSAPIBitVector>::Cast(self)->GetSize());
484 }
485 
GetIteratorObj(EcmaRuntimeCallInfo * argv)486 JSTaggedValue ContainersBitVector::GetIteratorObj(EcmaRuntimeCallInfo* argv)
487 {
488     ASSERT(argv);
489     BUILTINS_API_TRACE(argv->GetThread(), BitVector, GetIteratorObj);
490     JSThread* thread = argv->GetThread();
491     [[maybe_unused]] EcmaHandleScope handleScope(thread);
492 
493     JSHandle<JSTaggedValue> self = GetThis(argv);
494 
495     if (!self->IsJSAPIBitVector()) {
496         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget().IsJSAPIBitVector()) {
497             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget());
498         } else {
499             JSTaggedValue error = ContainerError::BusinessError(
500                 thread, ErrorFlag::BIND_ERROR, "The Symbol.iterator method cannot be bound");
501             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
502         }
503     }
504 
505     JSTaggedValue values = JSAPIBitVector::GetIteratorObj(thread, JSHandle<JSAPIBitVector>::Cast(self));
506 
507     return values;
508 }
509 
FreeBitsetVectorPointer(void * env,void * pointer,void * data)510 void ContainersBitVector::FreeBitsetVectorPointer([[maybe_unused]] void *env, void *pointer,
511                                                   [[maybe_unused]] void *data)
512 {
513     if (pointer == nullptr) {
514         return;
515     }
516     auto bitsetVector = reinterpret_cast<std::vector<std::bitset<JSAPIBitVector::BIT_SET_LENGTH>> *>(pointer);
517     delete bitsetVector;
518 }
519 } // namespace panda::ecmascript::containers
520