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