• 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 namespace panda::ecmascript::containers {
BitVectorConstructor(EcmaRuntimeCallInfo * argv)21 JSTaggedValue ContainersBitVector::BitVectorConstructor(EcmaRuntimeCallInfo* argv)
22 {
23     ASSERT(argv);
24     JSThread* thread = argv->GetThread();
25     BUILTINS_API_TRACE(thread, BitVector, Constructor);
26     [[maybe_unused]] EcmaHandleScope handleScope(thread);
27 
28     ObjectFactory* factory = thread->GetEcmaVM()->GetFactory();
29     JSHandle<JSTaggedValue> newTarget = GetNewTarget(argv);
30     if (newTarget->IsUndefined()) {
31         JSTaggedValue error = ContainerError::BusinessError(
32             thread, ErrorFlag::IS_NULL_ERROR, "The BitVector's constructor cannot be directly invoked.");
33         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
34     }
35     JSHandle<JSTaggedValue> constructor = GetConstructor(argv);
36     ASSERT(constructor->IsJSSharedFunction() && constructor.GetTaggedValue().IsInSharedHeap());
37     JSHandle<JSAPIBitVector> obj =
38         JSHandle<JSAPIBitVector>(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(constructor), newTarget));
39     ASSERT(obj.GetTaggedValue().IsInSharedHeap());
40     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
41 
42     JSHandle<JSTaggedValue> length = GetCallArg(argv, 0);
43     if (!length->IsInteger()) {
44         JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, length);
45         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
46         CString errorMsg =
47             "The type of \"length\" must be integer. Received value is: " + ConvertToString(thread, *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(thread).IsJSAPIBitVector()) {
76             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget(thread));
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(thread).IsJSAPIBitVector()) {
97             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget(thread));
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(thread).IsJSAPIBitVector()) {
118             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget(thread));
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 =
132             "The type of \"fromIndex\" must be integer. Received value is: " + ConvertToString(thread, *result);
133         JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str());
134         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
135     }
136     if (!endIndex->IsInteger()) {
137         JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, endIndex);
138         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
139         CString errorMsg =
140             "The type of \"toIndex\" must be integer. Received value is: " + ConvertToString(thread, *result);
141         JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str());
142         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
143     }
144     bool isHas = JSHandle<JSAPIBitVector>::Cast(self)->Has(
145         thread, JSHandle<JSAPIBitVector>::Cast(self), value, startIndex, endIndex);
146 
147     return GetTaggedBoolean(isHas);
148 }
149 
SetBitsByRange(EcmaRuntimeCallInfo * argv)150 JSTaggedValue ContainersBitVector::SetBitsByRange(EcmaRuntimeCallInfo* argv)
151 {
152     ASSERT(argv);
153     BUILTINS_API_TRACE(argv->GetThread(), BitVector, SetBitsByRange);
154     JSThread* thread = argv->GetThread();
155     [[maybe_unused]] EcmaHandleScope handleScope(thread);
156     JSHandle<JSTaggedValue> self = GetThis(argv);
157 
158     if (!self->IsJSAPIBitVector()) {
159         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget(thread).IsJSAPIBitVector()) {
160             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget(thread));
161         } else {
162             JSTaggedValue error =
163                 ContainerError::BusinessError(thread, BIND_ERROR, "The setBitsByRange method cannot be bound");
164             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
165         }
166     }
167 
168     JSHandle<JSTaggedValue> value = GetCallArg(argv, 0);
169     JSHandle<JSTaggedValue> startIndex = GetCallArg(argv, 1);
170     JSHandle<JSTaggedValue> endIndex = GetCallArg(argv, 2); // 2 means the third arg
171     if (!startIndex->IsInteger()) {
172         JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, startIndex);
173         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
174         CString errorMsg =
175             "The type of \"fromIndex\" must be integer. Received value is: " + ConvertToString(thread, *result);
176         JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str());
177         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
178     }
179     if (!endIndex->IsInteger()) {
180         JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, endIndex);
181         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
182         CString errorMsg =
183             "The type of \"toIndex\" must be integer. Received value is: " + ConvertToString(thread, *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     JSHandle<JSAPIBitVector>::Cast(self)->SetBitsByRange(
188         thread, JSHandle<JSAPIBitVector>::Cast(self), value, startIndex, endIndex);
189     return JSTaggedValue::Undefined();
190 }
191 
GetBitsByRange(EcmaRuntimeCallInfo * argv)192 JSTaggedValue ContainersBitVector::GetBitsByRange(EcmaRuntimeCallInfo* argv)
193 {
194     ASSERT(argv);
195     BUILTINS_API_TRACE(argv->GetThread(), BitVector, GetBitsByRange);
196     JSThread* thread = argv->GetThread();
197     [[maybe_unused]] EcmaHandleScope handleScope(thread);
198     JSHandle<JSTaggedValue> self = GetThis(argv);
199 
200     if (!self->IsJSAPIBitVector()) {
201         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget(thread).IsJSAPIBitVector()) {
202             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget(thread));
203         } else {
204             JSTaggedValue error =
205                 ContainerError::BusinessError(thread, BIND_ERROR, "The getBitsByRange method cannot be bound");
206             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
207         }
208     }
209 
210     JSHandle<JSTaggedValue> startIndex = GetCallArg(argv, 0);
211     JSHandle<JSTaggedValue> endIndex = GetCallArg(argv, 1);
212     if (!startIndex->IsInteger()) {
213         JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, startIndex);
214         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
215         CString errorMsg =
216             "The type of \"fromIndex\" must be integer. Received value is: " + ConvertToString(thread, *result);
217         JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str());
218         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
219     }
220     if (!endIndex->IsInteger()) {
221         JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, endIndex);
222         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
223         CString errorMsg =
224             "The type of \"toIndex\" must be integer. Received value is: " + ConvertToString(thread, *result);
225         JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str());
226         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
227     }
228     return JSHandle<JSAPIBitVector>::Cast(self)->GetBitsByRange(
229         thread, JSHandle<JSAPIBitVector>::Cast(self), startIndex, endIndex);
230 }
231 
Resize(EcmaRuntimeCallInfo * argv)232 JSTaggedValue ContainersBitVector::Resize(EcmaRuntimeCallInfo* argv)
233 {
234     ASSERT(argv);
235     BUILTINS_API_TRACE(argv->GetThread(), BitVector, Resize);
236     JSThread* thread = argv->GetThread();
237     [[maybe_unused]] EcmaHandleScope handleScope(thread);
238     JSHandle<JSTaggedValue> self = GetThis(argv);
239 
240     if (!self->IsJSAPIBitVector()) {
241         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget(thread).IsJSAPIBitVector()) {
242             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget(thread));
243         } else {
244             JSTaggedValue error =
245                 ContainerError::BusinessError(thread, BIND_ERROR, "The resize method cannot be bound");
246             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
247         }
248     }
249     JSHandle<JSTaggedValue> size = GetCallArg(argv, 0);
250     if (!size->IsInteger()) {
251         JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, size);
252         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
253         CString errorMsg =
254             "The type of \"size\" must be integer. Received value is: " + ConvertToString(thread, *result);
255         JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str());
256         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
257     }
258     JSHandle<JSAPIBitVector>::Cast(self)->Resize(
259         thread, JSHandle<JSAPIBitVector>::Cast(self), JSTaggedValue::ToUint32(thread, size));
260     return JSTaggedValue::Undefined();
261 }
262 
SetAllBits(EcmaRuntimeCallInfo * argv)263 JSTaggedValue ContainersBitVector::SetAllBits(EcmaRuntimeCallInfo* argv)
264 {
265     BUILTINS_API_TRACE(argv->GetThread(), BitVector, SetAllBits);
266     JSThread* thread = argv->GetThread();
267     [[maybe_unused]] EcmaHandleScope handleScope(thread);
268     JSHandle<JSTaggedValue> self = GetThis(argv);
269 
270     if (!self->IsJSAPIBitVector()) {
271         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget(thread).IsJSAPIBitVector()) {
272             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget(thread));
273         } else {
274             JSTaggedValue error =
275                 ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR, "The setAllBits method cannot be bound");
276             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
277         }
278     }
279 
280     JSHandle<JSTaggedValue> value = GetCallArg(argv, 0);
281     JSHandle<JSAPIBitVector>::Cast(self)->SetAllBits(thread, JSHandle<JSAPIBitVector>::Cast(self), value);
282     return JSTaggedValue::Undefined();
283 }
284 
GetBitCountByRange(EcmaRuntimeCallInfo * argv)285 JSTaggedValue ContainersBitVector::GetBitCountByRange(EcmaRuntimeCallInfo* argv)
286 {
287     ASSERT(argv);
288     BUILTINS_API_TRACE(argv->GetThread(), BitVector, GetBitCountByRange);
289     JSThread* thread = argv->GetThread();
290     [[maybe_unused]] EcmaHandleScope handleScope(thread);
291     JSHandle<JSTaggedValue> self = GetThis(argv);
292 
293     if (!self->IsJSAPIBitVector()) {
294         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget(thread).IsJSAPIBitVector()) {
295             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget(thread));
296         } else {
297             JSTaggedValue error =
298                 ContainerError::BusinessError(thread, BIND_ERROR, "The getBitCountByRange method cannot be bound");
299             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
300         }
301     }
302 
303     JSHandle<JSTaggedValue> value = GetCallArg(argv, 0);
304     JSHandle<JSTaggedValue> startIndex = GetCallArg(argv, 1);
305     JSHandle<JSTaggedValue> endIndex = GetCallArg(argv, 2); // 2 means the third arg
306     if (!startIndex->IsInteger()) {
307         JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, startIndex);
308         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
309         CString errorMsg =
310             "The type of \"fromIndex\" must be integer. Received value is: " + ConvertToString(thread, *result);
311         JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str());
312         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
313     }
314     if (!endIndex->IsInteger()) {
315         JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, endIndex);
316         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
317         CString errorMsg =
318             "The type of \"toIndex\" must be integer. Received value is: " + ConvertToString(thread, *result);
319         JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str());
320         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
321     }
322     return JSHandle<JSAPIBitVector>::Cast(self)->GetBitCountByRange(
323         thread, JSHandle<JSAPIBitVector>::Cast(self), value, startIndex, endIndex);
324 }
325 
GetIndexOf(EcmaRuntimeCallInfo * argv)326 JSTaggedValue ContainersBitVector::GetIndexOf(EcmaRuntimeCallInfo* argv)
327 {
328     ASSERT(argv);
329     BUILTINS_API_TRACE(argv->GetThread(), BitVector, GetIndexOf);
330     JSThread* thread = argv->GetThread();
331     [[maybe_unused]] EcmaHandleScope handleScope(thread);
332     JSHandle<JSTaggedValue> self = GetThis(argv);
333 
334     if (!self->IsJSAPIBitVector()) {
335         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget(thread).IsJSAPIBitVector()) {
336             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget(thread));
337         } else {
338             JSTaggedValue error =
339                 ContainerError::BusinessError(thread, BIND_ERROR, "The getIndexOf method cannot be bound");
340             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
341         }
342     }
343 
344     JSHandle<JSTaggedValue> value = GetCallArg(argv, 0);
345     JSHandle<JSTaggedValue> startIndex = GetCallArg(argv, 1);
346     JSHandle<JSTaggedValue> endIndex = GetCallArg(argv, 2); // 2 means the third arg
347     if (!startIndex->IsInteger()) {
348         JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, startIndex);
349         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
350         CString errorMsg =
351             "The type of \"fromIndex\" must be integer. Received value is: " + ConvertToString(thread, *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     if (!endIndex->IsInteger()) {
356         JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, endIndex);
357         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
358         CString errorMsg =
359             "The type of \"toIndex\" must be integer. Received value is: " + ConvertToString(thread, *result);
360         JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str());
361         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
362     }
363 
364     return JSTaggedValue(
365         JSAPIBitVector::GetIndexOf(thread, JSHandle<JSAPIBitVector>::Cast(self), value, startIndex, endIndex));
366 }
367 
GetLastIndexOf(EcmaRuntimeCallInfo * argv)368 JSTaggedValue ContainersBitVector::GetLastIndexOf(EcmaRuntimeCallInfo* argv)
369 {
370     ASSERT(argv);
371     BUILTINS_API_TRACE(argv->GetThread(), BitVector, GetLastIndexOf);
372     JSThread* thread = argv->GetThread();
373     [[maybe_unused]] EcmaHandleScope handleScope(thread);
374     JSHandle<JSTaggedValue> self = GetThis(argv);
375 
376     if (!self->IsJSAPIBitVector()) {
377         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget(thread).IsJSAPIBitVector()) {
378             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget(thread));
379         } else {
380             JSTaggedValue error =
381                 ContainerError::BusinessError(thread, BIND_ERROR, "The getLastIndexOf method cannot be bound");
382             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
383         }
384     }
385 
386     JSHandle<JSTaggedValue> value = GetCallArg(argv, 0);
387     JSHandle<JSTaggedValue> startIndex = GetCallArg(argv, 1);
388     JSHandle<JSTaggedValue> endIndex = GetCallArg(argv, 2); // 2 means the third arg
389     if (!startIndex->IsInteger()) {
390         JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, startIndex);
391         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
392         CString errorMsg =
393             "The type of \"fromIndex\" must be integer. Received value is: " + ConvertToString(thread, *result);
394         JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str());
395         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
396     }
397     if (!endIndex->IsInteger()) {
398         JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, endIndex);
399         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
400         CString errorMsg =
401             "The type of \"toIndex\" must be integer. Received value is: " + ConvertToString(thread, *result);
402         JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str());
403         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
404     }
405     return JSTaggedValue(
406         JSAPIBitVector::GetLastIndexOf(thread, JSHandle<JSAPIBitVector>::Cast(self), value, startIndex, endIndex));
407 }
408 
FlipBitByIndex(EcmaRuntimeCallInfo * argv)409 JSTaggedValue ContainersBitVector::FlipBitByIndex(EcmaRuntimeCallInfo* argv)
410 {
411     ASSERT(argv);
412     BUILTINS_API_TRACE(argv->GetThread(), BitVector, FlipBitByIndex);
413     JSThread* thread = argv->GetThread();
414     [[maybe_unused]] EcmaHandleScope handleScope(thread);
415     JSHandle<JSTaggedValue> self = GetThis(argv);
416 
417     if (!self->IsJSAPIBitVector()) {
418         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget(thread).IsJSAPIBitVector()) {
419             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget(thread));
420         } else {
421             JSTaggedValue error =
422                 ContainerError::BusinessError(thread, BIND_ERROR, "The flipBitByIndex method cannot be bound");
423             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
424         }
425     }
426     JSHandle<JSTaggedValue> value = GetCallArg(argv, 0);
427     if (!value->IsInteger()) {
428         JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, value);
429         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
430         CString errorMsg =
431             "The type of \"index\" must be integer. Received value is: " + ConvertToString(thread, *result);
432         JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str());
433         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
434     }
435 
436     JSAPIBitVector::FlipBitByIndex(
437         thread, JSHandle<JSAPIBitVector>::Cast(self), JSTaggedValue::ToUint32(thread, value));
438     return JSTaggedValue::Undefined();
439 }
440 
FlipBitsByRange(EcmaRuntimeCallInfo * argv)441 JSTaggedValue ContainersBitVector::FlipBitsByRange(EcmaRuntimeCallInfo* argv)
442 {
443     ASSERT(argv);
444     BUILTINS_API_TRACE(argv->GetThread(), BitVector, FlipBitsByRange);
445     JSThread* thread = argv->GetThread();
446     [[maybe_unused]] EcmaHandleScope handleScope(thread);
447     JSHandle<JSTaggedValue> self = GetThis(argv);
448 
449     if (!self->IsJSAPIBitVector()) {
450         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget(thread).IsJSAPIBitVector()) {
451             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget(thread));
452         } else {
453             JSTaggedValue error =
454                 ContainerError::BusinessError(thread, BIND_ERROR, "The flipBitsByRange method cannot be bound");
455             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
456         }
457     }
458     JSHandle<JSTaggedValue> startIndex = GetCallArg(argv, 0);
459     JSHandle<JSTaggedValue> endIndex = GetCallArg(argv, 1);
460     if (!startIndex->IsInteger()) {
461         JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, startIndex);
462         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
463         CString errorMsg =
464             "The type of \"fromIndex\" must be integer. Received value is: " + ConvertToString(thread, *result);
465         JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str());
466         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
467     }
468     if (!endIndex->IsInteger()) {
469         JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, endIndex);
470         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
471         CString errorMsg =
472             "The type of \"toIndex\" must be integer. Received value is: " + ConvertToString(thread, *result);
473         JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str());
474         THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
475     }
476     JSHandle<JSAPIBitVector>::Cast(self)->FlipBitsByRange(
477         thread, JSHandle<JSAPIBitVector>::Cast(self), startIndex, endIndex);
478     return JSTaggedValue::Undefined();
479 }
480 
GetSize(EcmaRuntimeCallInfo * argv)481 JSTaggedValue ContainersBitVector::GetSize(EcmaRuntimeCallInfo* argv)
482 {
483     ASSERT(argv);
484     BUILTINS_API_TRACE(argv->GetThread(), BitVector, GetSize);
485     JSThread* thread = argv->GetThread();
486     [[maybe_unused]] EcmaHandleScope handleScope(thread);
487     JSHandle<JSTaggedValue> self = GetThis(argv);
488 
489     if (!self->IsJSAPIBitVector()) {
490         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget(thread).IsJSAPIBitVector()) {
491             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget(thread));
492         } else {
493             JSTaggedValue error =
494                 ContainerError::BusinessError(thread, ErrorFlag::BIND_ERROR, "The getSize method cannot be bound");
495             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
496         }
497     }
498 
499     return JSTaggedValue(JSHandle<JSAPIBitVector>::Cast(self)->GetSize());
500 }
501 
GetIteratorObj(EcmaRuntimeCallInfo * argv)502 JSTaggedValue ContainersBitVector::GetIteratorObj(EcmaRuntimeCallInfo* argv)
503 {
504     ASSERT(argv);
505     BUILTINS_API_TRACE(argv->GetThread(), BitVector, GetIteratorObj);
506     JSThread* thread = argv->GetThread();
507     [[maybe_unused]] EcmaHandleScope handleScope(thread);
508 
509     JSHandle<JSTaggedValue> self = GetThis(argv);
510 
511     if (!self->IsJSAPIBitVector()) {
512         if (self->IsJSProxy() && JSHandle<JSProxy>::Cast(self)->GetTarget(thread).IsJSAPIBitVector()) {
513             self = JSHandle<JSTaggedValue>(thread, JSHandle<JSProxy>::Cast(self)->GetTarget(thread));
514         } else {
515             JSTaggedValue error = ContainerError::BusinessError(
516                 thread, ErrorFlag::BIND_ERROR, "The Symbol.iterator method cannot be bound");
517             THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception());
518         }
519     }
520 
521     JSTaggedValue values = JSAPIBitVector::GetIteratorObj(thread, JSHandle<JSAPIBitVector>::Cast(self));
522 
523     return values;
524 }
525 
FreeBitsetVectorPointer(void * env,void * pointer,void * data)526 void ContainersBitVector::FreeBitsetVectorPointer([[maybe_unused]] void *env, void *pointer,
527                                                   [[maybe_unused]] void *data)
528 {
529     if (pointer == nullptr) {
530         return;
531     }
532     auto bitsetVector = reinterpret_cast<std::vector<std::bitset<JSAPIBitVector::BIT_SET_LENGTH>> *>(pointer);
533     delete bitsetVector;
534 }
535 } // namespace panda::ecmascript::containers
536