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/js_api/js_api_bitvector.h" 17 18#include "ecmascript/tagged_array-inl.h" 19#include "ecmascript/shared_objects/concurrent_api_scope.h" 20 21namespace panda::ecmascript { 22using ContainerError = containers::ContainerError; 23using ErrorFlag = containers::ErrorFlag; 24bool JSAPIBitVector::Push( 25 JSThread* thread, const JSHandle<JSAPIBitVector>& bitVector, const JSHandle<JSTaggedValue>& value) 26{ 27 [[maybe_unused]] ConcurrentApiScope<JSAPIBitVector, ModType::WRITE> scope(thread, 28 JSHandle<JSTaggedValue>::Cast(bitVector)); 29 uint32_t length = static_cast<uint32_t>(bitVector->GetLength()); 30 JSHandle<JSNativePointer> np(thread, bitVector->GetNativePointer()); 31 auto elements = reinterpret_cast<std::vector<std::bitset<BIT_SET_LENGTH>>*>(np->GetExternalPointer()); 32 if ((length & TAGGED_VALUE_BIT_OFFSET) == 0) { 33 std::bitset<BIT_SET_LENGTH> increaseSet; 34 if (!value->IsZero()) { 35 increaseSet.set(0); 36 } 37 elements->push_back(increaseSet); 38 } else { 39 SetBit(elements, length, value.GetTaggedValue()); 40 } 41 bitVector->SetLength(++length); 42 return true; 43} 44 45JSTaggedValue JSAPIBitVector::Pop(JSThread* thread, const JSHandle<JSAPIBitVector>& bitVector) 46{ 47 [[maybe_unused]] ConcurrentApiScope<JSAPIBitVector, ModType::WRITE> scope(thread, 48 JSHandle<JSTaggedValue>::Cast(bitVector)); 49 if (bitVector->GetLength() <= 0) { 50 return JSTaggedValue::Undefined(); 51 } 52 uint32_t lastIndex = static_cast<uint32_t>(bitVector->GetLength() - 1); 53 JSHandle<JSNativePointer> np(thread, bitVector->GetNativePointer()); 54 auto elements = reinterpret_cast<std::vector<std::bitset<BIT_SET_LENGTH>>*>(np->GetExternalPointer()); 55 56 JSTaggedValue bit = GetBit(elements, lastIndex); 57 if ((lastIndex & TAGGED_VALUE_BIT_OFFSET) == 0) { 58 elements->pop_back(); 59 } else { 60 SetBit(elements, lastIndex, JSTaggedValue(0)); 61 } 62 bitVector->SetLength(lastIndex); 63 return bit; 64} 65 66JSTaggedValue JSAPIBitVector::Set(JSThread* thread, const uint32_t index, JSTaggedValue value) 67{ 68 uint32_t length = static_cast<uint32_t>(GetLength()); 69 if (index >= length) { 70 std::ostringstream oss; 71 oss << "The value of \"index\" is out of range. It must be >= 0 && <= " << (length - 1) 72 << ". Received value is: " << index; 73 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::RANGE_ERROR, oss.str().c_str()); 74 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 75 } 76 JSNativePointer* np = JSNativePointer::Cast(GetNativePointer().GetTaggedObject()); 77 auto elements = reinterpret_cast<std::vector<std::bitset<BIT_SET_LENGTH>>*>(np->GetExternalPointer()); 78 SetBit(elements, index, value); 79 return JSTaggedValue::Undefined(); 80} 81 82JSTaggedValue JSAPIBitVector::Get(JSThread* thread, const uint32_t index) 83{ 84 uint32_t length = static_cast<uint32_t>(GetLength()); 85 if (index >= length) { 86 std::ostringstream oss; 87 oss << "The value of \"index\" is out of range. It must be >= 0 && <= " << (length - 1) 88 << ". Received value is: " << index; 89 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::RANGE_ERROR, oss.str().c_str()); 90 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 91 } 92 JSNativePointer* np = JSNativePointer::Cast(GetNativePointer().GetTaggedObject()); 93 auto elements = reinterpret_cast<std::vector<std::bitset<BIT_SET_LENGTH>>*>(np->GetExternalPointer()); 94 return GetBit(elements, index); 95} 96 97bool JSAPIBitVector::Has(JSThread* thread, const JSHandle<JSAPIBitVector>& bitVector, 98 const JSHandle<JSTaggedValue>& value, const JSHandle<JSTaggedValue>& start, const JSHandle<JSTaggedValue>& end) 99{ 100 int32_t startIndex = JSTaggedValue::ToInt32(thread, start); 101 int32_t endIndex = JSTaggedValue::ToInt32(thread, end); 102 int32_t length = bitVector->GetLength(); 103 int32_t size = length > endIndex ? endIndex : length; 104 if (endIndex < 0 || endIndex > length) { 105 std::ostringstream oss; 106 oss << "The value of \"toIndex\" is out of range. It must be >= 0 && <= " << length 107 << ". Received value is: " << endIndex; 108 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::RANGE_ERROR, oss.str().c_str()); 109 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, false); 110 } 111 if (startIndex < 0 || startIndex >= size) { 112 std::ostringstream oss; 113 oss << "The value of \"fromIndex\" is out of range. It must be >= 0 && <= " << (size - 1) 114 << ". Received value is: " << startIndex; 115 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::RANGE_ERROR, oss.str().c_str()); 116 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, false); 117 } 118 if (length == 0) { 119 return false; 120 } 121 JSHandle<JSNativePointer> np(thread, bitVector->GetNativePointer()); 122 auto elements = reinterpret_cast<std::vector<std::bitset<BIT_SET_LENGTH>>*>(np->GetExternalPointer()); 123 for (int index = startIndex; index <= endIndex; index++) { 124 std::pair<uint32_t, uint32_t> pair = ComputeElementIdAndBitId(index); 125 uint32_t elementId = pair.first; 126 uint32_t bitId = pair.second; 127 if ((value->IsZero() && (*elements)[elementId].test(bitId) == 0) || 128 (!value->IsZero() && (*elements)[elementId].test(bitId) != 0)) { 129 return true; 130 } 131 } 132 return false; 133} 134 135bool JSAPIBitVector::Has(const JSTaggedValue& value) const 136{ 137 uint32_t length = GetSize(); 138 if (length == 0) { 139 return false; 140 } 141 JSNativePointer* np = JSNativePointer::Cast(GetNativePointer().GetTaggedObject()); 142 auto elements = reinterpret_cast<std::vector<std::bitset<BIT_SET_LENGTH>>*>(np->GetExternalPointer()); 143 for (uint32_t index = 0; index < length; index++) { 144 std::pair<uint32_t, uint32_t> pair = ComputeElementIdAndBitId(index); 145 uint32_t elementId = pair.first; 146 uint32_t bitId = pair.second; 147 if ((value.IsZero() && (*elements)[elementId].test(bitId) == 0) || 148 (!value.IsZero() && (*elements)[elementId].test(bitId) != 0)) { 149 return true; 150 } 151 } 152 return false; 153} 154 155JSTaggedValue JSAPIBitVector::SetBitsByRange(JSThread* thread, const JSHandle<JSAPIBitVector>& bitVector, 156 const JSHandle<JSTaggedValue>& value, const JSHandle<JSTaggedValue>& start, const JSHandle<JSTaggedValue>& end) 157{ 158 [[maybe_unused]] ConcurrentApiScope<JSAPIBitVector, ModType::WRITE> scope(thread, 159 JSHandle<JSTaggedValue>::Cast(bitVector)); 160 int32_t startIndex = JSTaggedValue::ToInt32(thread, start); 161 int32_t endIndex = JSTaggedValue::ToInt32(thread, end); 162 int32_t length = bitVector->GetLength(); 163 int32_t size = length > endIndex ? endIndex : length; 164 if (endIndex < 0 || endIndex > length) { 165 std::ostringstream oss; 166 oss << "The value of \"toIndex\" is out of range. It must be >= 0 && <= " << length 167 << ". Received value is: " << endIndex; 168 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::RANGE_ERROR, oss.str().c_str()); 169 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 170 } 171 if (startIndex < 0 || startIndex >= size) { 172 std::ostringstream oss; 173 oss << "The value of \"fromIndex\" is out of range. It must be >= 0 && <= " << (size - 1) 174 << ". Received value is: " << startIndex; 175 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::RANGE_ERROR, oss.str().c_str()); 176 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 177 } 178 179 JSHandle<JSNativePointer> np(thread, bitVector->GetNativePointer()); 180 auto elements = reinterpret_cast<std::vector<std::bitset<BIT_SET_LENGTH>>*>(np->GetExternalPointer()); 181 for (int32_t index = startIndex; index < endIndex; index++) { 182 SetBit(elements, index, value.GetTaggedValue()); 183 } 184 return JSTaggedValue::Undefined(); 185} 186 187JSTaggedValue JSAPIBitVector::GetBitsByRange(JSThread* thread, const JSHandle<JSAPIBitVector>& bitVector, 188 const JSHandle<JSTaggedValue>& start, const JSHandle<JSTaggedValue>& end) 189{ 190 [[maybe_unused]] ConcurrentApiScope<JSAPIBitVector, ModType::WRITE> scope(thread, 191 JSHandle<JSTaggedValue>::Cast(bitVector)); 192 int32_t startIndex = JSTaggedValue::ToInt32(thread, start); 193 int32_t endIndex = JSTaggedValue::ToInt32(thread, end); 194 int32_t length = bitVector->GetLength(); 195 int32_t size = length > endIndex ? endIndex : length; 196 if (endIndex < 0 || endIndex > length) { 197 std::ostringstream oss; 198 oss << "The value of \"toIndex\" is out of range. It must be >= 0 && <= " << length 199 << ". Received value is: " << endIndex; 200 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::RANGE_ERROR, oss.str().c_str()); 201 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 202 } 203 if (startIndex < 0 || startIndex >= size) { 204 std::ostringstream oss; 205 oss << "The value of \"fromIndex\" is out of range. It must be >= 0 && <= " << (size - 1) 206 << ". Received value is: " << startIndex; 207 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::RANGE_ERROR, oss.str().c_str()); 208 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 209 } 210 int32_t dstLength = endIndex - startIndex; 211 auto factory = thread->GetEcmaVM()->GetFactory(); 212 JSHandle<JSNativePointer> srcNp(thread, bitVector->GetNativePointer()); 213 auto srcElements = reinterpret_cast<std::vector<std::bitset<BIT_SET_LENGTH>>*>(srcNp->GetExternalPointer()); 214 215 JSHandle<JSAPIBitVector> newBitVector = factory->NewJSAPIBitVector(dstLength); 216 JSHandle<JSNativePointer> dstNp(thread, newBitVector->GetNativePointer()); 217 auto dstElements = reinterpret_cast<std::vector<std::bitset<BIT_SET_LENGTH>>*>(dstNp->GetExternalPointer()); 218 219 for (int32_t index = 0; index < dstLength; index++) { 220 JSTaggedValue value = GetBit(srcElements, index + startIndex); 221 SetBit(dstElements, index, value); 222 } 223 newBitVector->SetLength(dstLength); 224 newBitVector->SetNativePointer(thread, dstNp); 225 226 return newBitVector.GetTaggedValue(); 227} 228 229JSTaggedValue JSAPIBitVector::SetAllBits( 230 JSThread* thread, const JSHandle<JSAPIBitVector>& bitVector, const JSHandle<JSTaggedValue>& value) 231{ 232 [[maybe_unused]] ConcurrentApiScope<JSAPIBitVector, ModType::WRITE> scope(thread, 233 JSHandle<JSTaggedValue>::Cast(bitVector)); 234 JSHandle<JSNativePointer> np(thread, bitVector->GetNativePointer()); 235 auto elements = reinterpret_cast<std::vector<std::bitset<BIT_SET_LENGTH>>*>(np->GetExternalPointer()); 236 int size = static_cast<int>(elements->size()); 237 if (value->IsZero()) { 238 for (int index = 0; index < size; index++) { 239 (*elements)[index] = std::bitset<BIT_SET_LENGTH>(0); 240 } 241 } else { 242 for (int index = 0; index < size; index++) { 243 (*elements)[index] = std::bitset<BIT_SET_LENGTH>(UINT64_MAX); 244 } 245 } 246 return JSTaggedValue::Undefined(); 247} 248 249JSTaggedValue JSAPIBitVector::GetBitCountByRange(JSThread* thread, const JSHandle<JSAPIBitVector>& bitVector, 250 const JSHandle<JSTaggedValue>& value, const JSHandle<JSTaggedValue>& start, const JSHandle<JSTaggedValue>& end) 251{ 252 [[maybe_unused]] ConcurrentApiScope<JSAPIBitVector> scope(thread, JSHandle<JSTaggedValue>::Cast(bitVector)); 253 int32_t startIndex = JSTaggedValue::ToInt32(thread, start); 254 int32_t endIndex = JSTaggedValue::ToInt32(thread, end); 255 int32_t length = bitVector->GetLength(); 256 int32_t size = length > endIndex ? endIndex : length; 257 int32_t count = 0; 258 if (endIndex < 0 || endIndex > length) { 259 std::ostringstream oss; 260 oss << "The value of \"toIndex\" is out of range. It must be >= 0 && <= " << length 261 << ". Received value is: " << endIndex; 262 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::RANGE_ERROR, oss.str().c_str()); 263 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 264 } 265 if (startIndex < 0 || startIndex >= size) { 266 std::ostringstream oss; 267 oss << "The value of \"fromIndex\" is out of range. It must be >= 0 && <= " << (size - 1) 268 << ". Received value is: " << startIndex; 269 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::RANGE_ERROR, oss.str().c_str()); 270 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 271 } 272 JSHandle<JSNativePointer> np(thread, bitVector->GetNativePointer()); 273 auto elements = reinterpret_cast<std::vector<std::bitset<BIT_SET_LENGTH>>*>(np->GetExternalPointer()); 274 for (int32_t index = startIndex; index < endIndex; index++) { 275 std::pair<uint32_t, uint32_t> pair = ComputeElementIdAndBitId(index); 276 uint32_t elementId = pair.first; 277 uint32_t bitId = pair.second; 278 if ((value->IsZero() && (*elements)[elementId].test(bitId) == 0) || 279 (!value->IsZero() && (*elements)[elementId].test(bitId) != 0)) { 280 count++; 281 } 282 } 283 return JSTaggedValue(count); 284} 285 286int JSAPIBitVector::GetIndexOf(JSThread* thread, const JSHandle<JSAPIBitVector>& bitVector, 287 const JSHandle<JSTaggedValue>& value, const JSHandle<JSTaggedValue>& start, const JSHandle<JSTaggedValue>& end) 288{ 289 [[maybe_unused]] ConcurrentApiScope<JSAPIBitVector> scope(thread, JSHandle<JSTaggedValue>::Cast(bitVector)); 290 int32_t startIndex = JSTaggedValue::ToInt32(thread, start); 291 int32_t endIndex = JSTaggedValue::ToInt32(thread, end); 292 int32_t length = bitVector->GetLength(); 293 int32_t size = length > endIndex ? endIndex : length; 294 if (endIndex < 0 || endIndex > length) { 295 std::ostringstream oss; 296 oss << "The value of \"toIndex\" is out of range. It must be >= 0 && <= " << length 297 << ". Received value is: " << endIndex; 298 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::RANGE_ERROR, oss.str().c_str()); 299 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, -1); 300 } 301 if (startIndex < 0 || startIndex >= size) { 302 std::ostringstream oss; 303 oss << "The value of \"fromIndex\" is out of range. It must be >= 0 && <= " << (size - 1) 304 << ". Received value is: " << startIndex; 305 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::RANGE_ERROR, oss.str().c_str()); 306 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, -1); 307 } 308 JSHandle<JSNativePointer> np(thread, bitVector->GetNativePointer()); 309 auto elements = reinterpret_cast<std::vector<std::bitset<BIT_SET_LENGTH>>*>(np->GetExternalPointer()); 310 for (int32_t index = startIndex; index < endIndex; index++) { 311 std::pair<uint32_t, uint32_t> pair = ComputeElementIdAndBitId(index); 312 uint32_t elementId = pair.first; 313 uint32_t bitId = pair.second; 314 if ((value->IsZero() && (*elements)[elementId].test(bitId) == 0) || 315 (!value->IsZero() && (*elements)[elementId].test(bitId) != 0)) { 316 return index; 317 } 318 } 319 return -1; 320} 321 322int JSAPIBitVector::GetLastIndexOf(JSThread* thread, const JSHandle<JSAPIBitVector>& bitVector, 323 const JSHandle<JSTaggedValue>& value, const JSHandle<JSTaggedValue>& start, const JSHandle<JSTaggedValue>& end) 324{ 325 [[maybe_unused]] ConcurrentApiScope<JSAPIBitVector> scope(thread, JSHandle<JSTaggedValue>::Cast(bitVector)); 326 int32_t startIndex = JSTaggedValue::ToInt32(thread, start); 327 int32_t endIndex = JSTaggedValue::ToInt32(thread, end); 328 int32_t length = bitVector->GetLength(); 329 int32_t size = length > endIndex ? endIndex : length; 330 if (endIndex < 0 || endIndex > length) { 331 std::ostringstream oss; 332 oss << "The value of \"toIndex\" is out of range. It must be >= 0 && <= " << length 333 << ". Received value is: " << endIndex; 334 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::RANGE_ERROR, oss.str().c_str()); 335 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, -1); 336 } 337 if (startIndex < 0 || startIndex >= size) { 338 std::ostringstream oss; 339 oss << "The value of \"fromIndex\" is out of range. It must be >= 0 && <= " << (size - 1) 340 << ". Received value is: " << startIndex; 341 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::RANGE_ERROR, oss.str().c_str()); 342 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, -1); 343 } 344 JSHandle<JSNativePointer> np(thread, bitVector->GetNativePointer()); 345 auto elements = reinterpret_cast<std::vector<std::bitset<BIT_SET_LENGTH>>*>(np->GetExternalPointer()); 346 for (int32_t index = endIndex - 1; index >= startIndex; index--) { 347 std::pair<uint32_t, uint32_t> pair = ComputeElementIdAndBitId(index); 348 uint32_t elementId = pair.first; 349 uint32_t bitId = pair.second; 350 if ((value->IsZero() && (*elements)[elementId].test(bitId) == 0) || 351 (!value->IsZero() && (*elements)[elementId].test(bitId) != 0)) { 352 return index; 353 } 354 } 355 return -1; 356} 357 358JSTaggedValue JSAPIBitVector::FlipBitByIndex(JSThread* thread, const JSHandle<JSAPIBitVector>& bitVector, int index) 359{ 360 [[maybe_unused]] ConcurrentApiScope<JSAPIBitVector, ModType::WRITE> scope(thread, 361 JSHandle<JSTaggedValue>::Cast(bitVector)); 362 if (index >= bitVector->GetLength()) { 363 std::ostringstream oss; 364 oss << "The value of \"index\" is out of range. It must be >= 0 && <= " << (bitVector->GetLength() - 1) 365 << ". Received value is: " << index; 366 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::RANGE_ERROR, oss.str().c_str()); 367 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 368 } 369 370 JSHandle<JSNativePointer> np(thread, bitVector->GetNativePointer()); 371 auto elements = reinterpret_cast<std::vector<std::bitset<BIT_SET_LENGTH>>*>(np->GetExternalPointer()); 372 373 std::pair<uint32_t, uint32_t> pair = ComputeElementIdAndBitId(index); 374 uint32_t elementId = pair.first; 375 uint32_t bitId = pair.second; 376 (*elements)[elementId].flip(bitId); 377 return JSTaggedValue::Undefined(); 378} 379 380JSTaggedValue JSAPIBitVector::FlipBitsByRange(JSThread* thread, const JSHandle<JSAPIBitVector>& bitVector, 381 const JSHandle<JSTaggedValue>& start, const JSHandle<JSTaggedValue>& end) 382{ 383 [[maybe_unused]] ConcurrentApiScope<JSAPIBitVector, ModType::WRITE> scope(thread, 384 JSHandle<JSTaggedValue>::Cast(bitVector)); 385 int32_t startIndex = JSTaggedValue::ToInt32(thread, start); 386 int32_t endIndex = JSTaggedValue::ToInt32(thread, end); 387 int32_t length = bitVector->GetLength(); 388 int32_t size = length > endIndex ? endIndex : length; 389 if (endIndex < 0 || endIndex > length) { 390 std::ostringstream oss; 391 oss << "The value of \"toIndex\" is out of range. It must be >= 0 && <= " << length 392 << ". Received value is: " << endIndex; 393 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::RANGE_ERROR, oss.str().c_str()); 394 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 395 } 396 if (startIndex < 0 || startIndex >= size) { 397 std::ostringstream oss; 398 oss << "The value of \"fromIndex\" is out of range. It must be >= 0 && <= " << (size - 1) 399 << ". Received value is: " << startIndex; 400 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::RANGE_ERROR, oss.str().c_str()); 401 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); 402 } 403 JSHandle<JSNativePointer> np(thread, bitVector->GetNativePointer()); 404 auto elements = reinterpret_cast<std::vector<std::bitset<BIT_SET_LENGTH>>*>(np->GetExternalPointer()); 405 for (int32_t index = startIndex; index < endIndex; index++) { 406 std::pair<uint32_t, uint32_t> pair = ComputeElementIdAndBitId(index); 407 uint32_t elementId = pair.first; 408 uint32_t bitId = pair.second; 409 (*elements)[elementId].flip(bitId); 410 } 411 return JSTaggedValue::Undefined(); 412} 413 414void JSAPIBitVector::Resize(JSThread* thread, const JSHandle<JSAPIBitVector>& bitVector, int newSize) 415{ 416 if (newSize < 0) { 417 std::ostringstream oss; 418 oss << "The value of \"length\" is out of range. It must be >= 0" << ". Received value is: " << newSize; 419 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::RANGE_ERROR, oss.str().c_str()); 420 THROW_NEW_ERROR_AND_RETURN(thread, error); 421 } 422 [[maybe_unused]] ConcurrentApiScope<JSAPIBitVector, ModType::WRITE> scope(thread, 423 JSHandle<JSTaggedValue>::Cast(bitVector)); 424 int length = bitVector->GetLength(); 425 uint32_t elementsLength = static_cast<uint32_t>((length - 1) / BIT_SET_LENGTH + 1); 426 uint32_t newElementsLength = static_cast<uint32_t>((newSize - 1) / BIT_SET_LENGTH + 1); 427 428 JSHandle<JSNativePointer> np(thread, bitVector->GetNativePointer()); 429 auto elements = reinterpret_cast<std::vector<std::bitset<BIT_SET_LENGTH>>*>(np->GetExternalPointer()); 430 if (elementsLength == newElementsLength && length < newSize) { 431 for (int32_t index = length; index < newSize; index++) { 432 SetBit(elements, index, JSTaggedValue(0)); 433 } 434 } else if (elementsLength < newElementsLength) { 435 std::bitset<JSAPIBitVector::BIT_SET_LENGTH> initBitSet; 436 elements->resize(newElementsLength, initBitSet); 437 } else if (elementsLength > newElementsLength) { 438 elements->resize(newElementsLength); 439 } 440 bitVector->SetLength(newSize); 441} 442 443JSHandle<TaggedArray> JSAPIBitVector::OwnKeys(JSThread* thread, const JSHandle<JSAPIBitVector>& obj) 444{ 445 uint32_t numOfElements = static_cast<uint32_t>(obj->GetLength()); 446 JSHandle<TaggedArray> keyArray = thread->GetEcmaVM()->GetFactory()->NewTaggedArray(numOfElements); 447 448 if (numOfElements > 0) { 449 for (uint32_t i = 0; i < numOfElements; ++i) { 450 auto key = base::NumberHelper::IntToEcmaString(thread, i); 451 keyArray->Set(thread, i, key); 452 } 453 } 454 455 return keyArray; 456} 457 458JSHandle<TaggedArray> JSAPIBitVector::OwnEnumKeys(JSThread* thread, const JSHandle<JSAPIBitVector>& obj) 459{ 460 return OwnKeys(thread, obj); 461} 462 463bool JSAPIBitVector::GetOwnProperty( 464 JSThread* thread, const JSHandle<JSAPIBitVector>& obj, const JSHandle<JSTaggedValue>& key) 465{ 466 uint32_t index = 0; 467 if (UNLIKELY(!JSTaggedValue::ToElementIndex(key.GetTaggedValue(), &index))) { 468 JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, key.GetTaggedValue()); 469 RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false); 470 CString errorMsg = "The type of \"index\" can not obtain attributes of no-number type. Received value is: " + 471 ConvertToString(*result); 472 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str()); 473 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, false); 474 } 475 476 uint32_t length = static_cast<uint32_t>(obj->GetLength()); 477 if (index >= length) { 478 std::ostringstream oss; 479 oss << "The value of \"index\" is out of range. It must be > " << (length - 1) 480 << ". Received value is: " << index; 481 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::RANGE_ERROR, oss.str().c_str()); 482 THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, false); 483 } 484 485 obj->Get(thread, index); 486 RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false); 487 return true; 488} 489 490JSTaggedValue JSAPIBitVector::GetIteratorObj(JSThread* thread, const JSHandle<JSAPIBitVector>& obj) 491{ 492 ObjectFactory* factory = thread->GetEcmaVM()->GetFactory(); 493 JSHandle<JSAPIBitVectorIterator> iter(factory->NewJSAPIBitVectorIterator(obj)); 494 495 return iter.GetTaggedValue(); 496} 497 498OperationResult JSAPIBitVector::GetProperty( 499 JSThread* thread, const JSHandle<JSAPIBitVector>& obj, const JSHandle<JSTaggedValue>& key) 500{ 501 int length = obj->GetLength(); 502 int index = key->GetInt(); 503 if (index < 0 || index >= length) { 504 std::ostringstream oss; 505 oss << "The value of \"index\" is out of range. It must be >= 0 && <= " << (length - 1) 506 << ". Received value is: " << index; 507 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::RANGE_ERROR, oss.str().c_str()); 508 THROW_NEW_ERROR_AND_RETURN_VALUE( 509 thread, error, OperationResult(thread, JSTaggedValue::Exception(), PropertyMetaData(false))); 510 } 511 512 return OperationResult(thread, obj->Get(thread, index), PropertyMetaData(false)); 513} 514bool JSAPIBitVector::SetProperty(JSThread* thread, const JSHandle<JSAPIBitVector>& obj, 515 const JSHandle<JSTaggedValue>& key, const JSHandle<JSTaggedValue>& value) 516{ 517 int length = obj->GetLength(); 518 int index = key->GetInt(); 519 if (index < 0 || index >= length) { 520 return false; 521 } 522 523 obj->Set(thread, index, value.GetTaggedValue()); 524 return true; 525} 526 527} // namespace panda::ecmascript 528