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