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