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