1 /* 2 * Copyright (c) 2021-2022 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_serializer.h" 17 18 #if defined(PANDA_TARGET_IOS) 19 #include <stdlib.h> 20 #elif defined(PANDA_TARGET_MACOS) 21 #include <sys/malloc.h> 22 #else 23 #include <malloc.h> 24 #endif 25 26 #include "ecmascript/base/array_helper.h" 27 #include "ecmascript/base/typed_array_helper-inl.h" 28 #include "ecmascript/base/typed_array_helper.h" 29 #include "ecmascript/global_env.h" 30 #include "ecmascript/js_array.h" 31 #include "ecmascript/js_arraybuffer.h" 32 #include "ecmascript/js_hclass.h" 33 #include "ecmascript/js_regexp.h" 34 #include "ecmascript/js_set.h" 35 #include "ecmascript/js_typed_array.h" 36 #include "ecmascript/linked_hash_table.h" 37 #include "ecmascript/shared_mm/shared_mm.h" 38 39 #include "securec.h" 40 41 namespace panda::ecmascript { 42 using TypedArrayHelper = base::TypedArrayHelper; 43 constexpr size_t INITIAL_CAPACITY = 64; 44 constexpr int CAPACITY_INCREASE_RATE = 2; 45 WriteType(SerializationUID id)46 bool JSSerializer::WriteType(SerializationUID id) 47 { 48 uint8_t rawId = static_cast<uint8_t>(id); 49 return WriteRawData(&rawId, sizeof(rawId)); 50 } 51 InitTransferSet(CUnorderedSet<uintptr_t> transferDataSet)52 void JSSerializer::InitTransferSet(CUnorderedSet<uintptr_t> transferDataSet) 53 { 54 transferDataSet_ = std::move(transferDataSet); 55 } 56 ClearTransferSet()57 void JSSerializer::ClearTransferSet() 58 { 59 transferDataSet_.clear(); 60 } 61 62 // Write JSTaggedValue could be either a pointer to a HeapObject or a value SerializeJSTaggedValue(const JSHandle<JSTaggedValue> & value)63 bool JSSerializer::SerializeJSTaggedValue(const JSHandle<JSTaggedValue> &value) 64 { 65 [[maybe_unused]] EcmaHandleScope scope(thread_); 66 DISALLOW_GARBAGE_COLLECTION; 67 if (!value->IsHeapObject()) { 68 if (!WritePrimitiveValue(value)) { 69 return false; 70 } 71 } else { 72 if (!WriteTaggedObject(value)) { 73 return false; 74 } 75 } 76 return true; 77 } 78 79 // Write JSTaggedValue that is pure value WritePrimitiveValue(const JSHandle<JSTaggedValue> & value)80 bool JSSerializer::WritePrimitiveValue(const JSHandle<JSTaggedValue> &value) 81 { 82 if (value->IsNull()) { 83 return WriteType(SerializationUID::JS_NULL); 84 } 85 if (value->IsUndefined()) { 86 return WriteType(SerializationUID::JS_UNDEFINED); 87 } 88 if (value->IsTrue()) { 89 return WriteType(SerializationUID::JS_TRUE); 90 } 91 if (value->IsFalse()) { 92 return WriteType(SerializationUID::JS_FALSE); 93 } 94 if (value->IsInt()) { 95 return WriteInt(value->GetInt()); 96 } 97 if (value->IsDouble()) { 98 return WriteDouble(value->GetDouble()); 99 } 100 if (value->IsHole()) { 101 return WriteType(SerializationUID::HOLE); 102 } 103 return false; 104 } 105 WriteInt(int32_t value)106 bool JSSerializer::WriteInt(int32_t value) 107 { 108 if (!WriteType(SerializationUID::INT32)) { 109 return false; 110 } 111 if (!WriteRawData(&value, sizeof(value))) { 112 return false; 113 } 114 return true; 115 } 116 WriteDouble(double value)117 bool JSSerializer::WriteDouble(double value) 118 { 119 if (!WriteType(SerializationUID::DOUBLE)) { 120 return false; 121 } 122 if (!WriteRawData(&value, sizeof(value))) { 123 return false; 124 } 125 return true; 126 } 127 WriteBoolean(bool value)128 bool JSSerializer::WriteBoolean(bool value) 129 { 130 if (value) { 131 return WriteType(SerializationUID::C_TRUE); 132 } 133 return WriteType(SerializationUID::C_FALSE); 134 } 135 WriteRawData(const void * data,size_t length)136 bool JSSerializer::WriteRawData(const void *data, size_t length) 137 { 138 if (length <= 0) { 139 return false; 140 } 141 if ((bufferSize_ + length) > bufferCapacity_) { 142 if (!AllocateBuffer(length)) { 143 return false; 144 } 145 } 146 if (memcpy_s(buffer_ + bufferSize_, bufferCapacity_ - bufferSize_, data, length) != EOK) { 147 LOG_FULL(ERROR) << "Failed to memcpy_s Data"; 148 return false; 149 } 150 bufferSize_ += length; 151 return true; 152 } 153 WriteString(const CString & str)154 bool JSSerializer::WriteString(const CString &str) 155 { 156 if (!WriteType(SerializationUID::C_STRING)) { 157 return false; 158 } 159 160 size_t length = str.length() + 1; // 1: '\0' 161 if ((bufferSize_ + length) > bufferCapacity_) { 162 if (!AllocateBuffer(length)) { 163 return false; 164 } 165 } 166 if (memcpy_s(buffer_ + bufferSize_, bufferCapacity_ - bufferSize_, str.c_str(), length) != EOK) { 167 LOG_FULL(ERROR) << "Failed to memcpy_s Data"; 168 return false; 169 } 170 bufferSize_ += length; 171 return true; 172 } 173 AllocateBuffer(size_t bytes)174 bool JSSerializer::AllocateBuffer(size_t bytes) 175 { 176 // Get internal heap size 177 if (sizeLimit_ == 0) { 178 uint64_t heapSize = thread_->GetEcmaVM()->GetJSOptions().GetSerializerBufferSizeLimit(); 179 sizeLimit_ = heapSize; 180 } 181 size_t oldSize = bufferSize_; 182 size_t newSize = oldSize + bytes; 183 if (newSize > sizeLimit_) { 184 return false; 185 } 186 if (bufferCapacity_ == 0) { 187 if (bytes < INITIAL_CAPACITY) { 188 buffer_ = reinterpret_cast<uint8_t *>(malloc(INITIAL_CAPACITY)); 189 if (buffer_ != nullptr) { 190 bufferCapacity_ = INITIAL_CAPACITY; 191 return true; 192 } else { 193 return false; 194 } 195 } else { 196 buffer_ = reinterpret_cast<uint8_t *>(malloc(bytes)); 197 if (buffer_ != nullptr) { 198 bufferCapacity_ = bytes; 199 return true; 200 } else { 201 return false; 202 } 203 } 204 } 205 if (newSize > bufferCapacity_) { 206 if (!ExpandBuffer(newSize)) { 207 return false; 208 } 209 } 210 return true; 211 } 212 ExpandBuffer(size_t requestedSize)213 bool JSSerializer::ExpandBuffer(size_t requestedSize) 214 { 215 size_t newCapacity = bufferCapacity_ * CAPACITY_INCREASE_RATE; 216 newCapacity = std::max(newCapacity, requestedSize); 217 if (newCapacity > sizeLimit_) { 218 return false; 219 } 220 uint8_t *newBuffer = reinterpret_cast<uint8_t *>(malloc(newCapacity)); 221 if (newBuffer == nullptr) { 222 return false; 223 } 224 if (memcpy_s(newBuffer, newCapacity, buffer_, bufferSize_) != EOK) { 225 LOG_FULL(ERROR) << "Failed to memcpy_s Data"; 226 free(newBuffer); 227 return false; 228 } 229 free(buffer_); 230 buffer_ = newBuffer; 231 bufferCapacity_ = newCapacity; 232 return true; 233 } 234 235 // Transfer ownership of buffer, should not use this Serializer after release ReleaseBuffer()236 std::pair<uint8_t *, size_t> JSSerializer::ReleaseBuffer() 237 { 238 auto res = std::make_pair(buffer_, bufferSize_); 239 buffer_ = nullptr; 240 bufferSize_ = 0; 241 bufferCapacity_ = 0; 242 objectId_ = 0; 243 return res; 244 } 245 IsSerialized(uintptr_t addr) const246 bool JSSerializer::IsSerialized(uintptr_t addr) const 247 { 248 if (referenceMap_.find(addr) != referenceMap_.end()) { 249 return true; 250 } 251 return false; 252 } 253 WriteIfSerialized(uintptr_t addr)254 bool JSSerializer::WriteIfSerialized(uintptr_t addr) 255 { 256 auto iter = referenceMap_.find(addr); 257 if (iter == referenceMap_.end()) { 258 return false; 259 } 260 uint64_t id = iter->second; 261 if (!WriteType(SerializationUID::TAGGED_OBJECT_REFERNCE)) { 262 return false; 263 } 264 if (!WriteRawData(&id, sizeof(uint64_t))) { 265 return false; 266 } 267 return true; 268 } 269 270 // Write HeapObject WriteTaggedObject(const JSHandle<JSTaggedValue> & value)271 bool JSSerializer::WriteTaggedObject(const JSHandle<JSTaggedValue> &value) 272 { 273 uintptr_t addr = reinterpret_cast<uintptr_t>(value.GetTaggedValue().GetTaggedObject()); 274 bool serialized = IsSerialized(addr); 275 if (serialized) { 276 return WriteIfSerialized(addr); 277 } 278 referenceMap_.emplace(addr, objectId_); 279 objectId_++; 280 281 TaggedObject *taggedObject = value->GetTaggedObject(); 282 JSType type = taggedObject->GetClass()->GetObjectType(); 283 switch (type) { 284 case JSType::JS_ERROR: 285 case JSType::JS_EVAL_ERROR: 286 case JSType::JS_RANGE_ERROR: 287 case JSType::JS_REFERENCE_ERROR: 288 case JSType::JS_TYPE_ERROR: 289 case JSType::JS_AGGREGATE_ERROR: 290 case JSType::JS_URI_ERROR: 291 case JSType::JS_SYNTAX_ERROR: 292 case JSType::JS_OOM_ERROR: 293 return WriteJSError(value); 294 case JSType::JS_DATE: 295 return WriteJSDate(value); 296 case JSType::JS_ARRAY: 297 return WriteJSArray(value); 298 case JSType::JS_MAP: 299 return WriteJSMap(value); 300 case JSType::JS_SET: 301 return WriteJSSet(value); 302 case JSType::JS_REG_EXP: 303 return WriteJSRegExp(value); 304 case JSType::JS_INT8_ARRAY: 305 return WriteJSTypedArray(value, SerializationUID::JS_INT8_ARRAY); 306 case JSType::JS_UINT8_ARRAY: 307 return WriteJSTypedArray(value, SerializationUID::JS_UINT8_ARRAY); 308 case JSType::JS_UINT8_CLAMPED_ARRAY: 309 return WriteJSTypedArray(value, SerializationUID::JS_UINT8_CLAMPED_ARRAY); 310 case JSType::JS_INT16_ARRAY: 311 return WriteJSTypedArray(value, SerializationUID::JS_INT16_ARRAY); 312 case JSType::JS_UINT16_ARRAY: 313 return WriteJSTypedArray(value, SerializationUID::JS_UINT16_ARRAY); 314 case JSType::JS_INT32_ARRAY: 315 return WriteJSTypedArray(value, SerializationUID::JS_INT32_ARRAY); 316 case JSType::JS_UINT32_ARRAY: 317 return WriteJSTypedArray(value, SerializationUID::JS_UINT32_ARRAY); 318 case JSType::JS_FLOAT32_ARRAY: 319 return WriteJSTypedArray(value, SerializationUID::JS_FLOAT32_ARRAY); 320 case JSType::JS_FLOAT64_ARRAY: 321 return WriteJSTypedArray(value, SerializationUID::JS_FLOAT64_ARRAY); 322 case JSType::JS_BIGINT64_ARRAY: 323 return WriteJSTypedArray(value, SerializationUID::JS_BIGINT64_ARRAY); 324 case JSType::JS_BIGUINT64_ARRAY: 325 return WriteJSTypedArray(value, SerializationUID::JS_BIGUINT64_ARRAY); 326 case JSType::JS_ARRAY_BUFFER: 327 case JSType::JS_SHARED_ARRAY_BUFFER: 328 return WriteJSArrayBuffer(value); 329 case JSType::LINE_STRING: 330 case JSType::CONSTANT_STRING: 331 case JSType::TREE_STRING: 332 return WriteEcmaString(value); 333 case JSType::JS_OBJECT: 334 return WritePlainObject(value); 335 case JSType::JS_ASYNC_FUNCTION: // means CONCURRENT_FUNCTION 336 return WriteJSFunction(value); 337 case JSType::METHOD: 338 return WriteMethod(value); 339 case JSType::TAGGED_ARRAY: 340 return WriteTaggedArray(value); 341 case JSType::BIGINT: 342 return WriteBigInt(value); 343 default: 344 break; 345 } 346 return false; 347 } 348 WriteBigInt(const JSHandle<JSTaggedValue> & value)349 bool JSSerializer::WriteBigInt(const JSHandle<JSTaggedValue> &value) 350 { 351 JSHandle<BigInt> bigInt = JSHandle<BigInt>::Cast(value); 352 if (!WriteType(SerializationUID::BIGINT)) { 353 return false; 354 } 355 uint32_t len = bigInt->GetLength(); 356 if (!WriteInt(len)) { 357 return false; 358 } 359 bool sign = bigInt->GetSign(); 360 if (!WriteBoolean(sign)) { 361 return false; 362 } 363 for (uint32_t i = 0; i < len; i++) { 364 uint32_t val = bigInt->GetDigit(i); 365 if (!WriteInt(val)) { 366 return false; 367 } 368 } 369 return true; 370 } 371 WriteTaggedArray(const JSHandle<JSTaggedValue> & value)372 bool JSSerializer::WriteTaggedArray(const JSHandle<JSTaggedValue> &value) 373 { 374 JSHandle<TaggedArray> taggedArray = JSHandle<TaggedArray>::Cast(value); 375 if (!WriteType(SerializationUID::TAGGED_ARRAY)) { 376 return false; 377 } 378 uint32_t len = taggedArray->GetLength(); 379 if (!WriteInt(len)) { 380 return false; 381 } 382 JSMutableHandle<JSTaggedValue> val(thread_, JSTaggedValue::Undefined()); 383 for (uint32_t i = 0; i < len; i++) { 384 val.Update(taggedArray->Get(i)); 385 if (!SerializeJSTaggedValue(val)) { 386 return false; 387 } 388 } 389 return true; 390 } 391 WriteByteArray(const JSHandle<JSTaggedValue> & value,DataViewType viewType)392 bool JSSerializer::WriteByteArray(const JSHandle<JSTaggedValue> &value, DataViewType viewType) 393 { 394 JSHandle<ByteArray> byteArray = JSHandle<ByteArray>::Cast(value); 395 if (!WriteType(SerializationUID::BYTE_ARRAY)) { 396 return false; 397 } 398 uint32_t arrayLength = byteArray->GetArrayLength(); 399 if (!WriteInt(arrayLength)) { 400 return false; 401 } 402 uint32_t viewTypeIndex = GetDataViewTypeIndex(viewType); 403 if (!WriteInt(viewTypeIndex)) { 404 return false; 405 } 406 JSMutableHandle<JSTaggedValue> val(thread_, JSTaggedValue::Undefined()); 407 for (uint32_t i = 0; i < arrayLength; i++) { 408 val.Update(byteArray->Get(thread_, i, viewType)); 409 if (!SerializeJSTaggedValue(val)) { 410 return false; 411 } 412 } 413 return true; 414 } 415 GetDataViewTypeIndex(const DataViewType viewType)416 uint32_t JSSerializer::GetDataViewTypeIndex(const DataViewType viewType) 417 { 418 uint32_t index = 0; 419 switch (viewType) { 420 case DataViewType::INT8: 421 index = 1; // 1 : DataViewType::INT8 422 break; 423 case DataViewType::UINT8: 424 index = 2; // 2 : DataViewType::UINT8 425 break; 426 case DataViewType::UINT8_CLAMPED: 427 index = 3; // 3 : DataViewType::UINT8_CLAMPED 428 break; 429 case DataViewType::INT16: 430 index = 4; // 4 : DataViewType::INT16 431 break; 432 case DataViewType::UINT16: 433 index = 5; // 5 : DataViewType::UINT16 434 break; 435 case DataViewType::INT32: 436 index = 6; // 6 : DataViewType::INT32 437 break; 438 case DataViewType::UINT32: 439 index = 7; // 7 : DataViewType::UINT32 440 break; 441 case DataViewType::FLOAT32: 442 index = 8; // 8 : DataViewType::FLOAT32 443 break; 444 case DataViewType::FLOAT64: 445 index = 9; // 9 : DataViewType::FLOAT64 446 break; 447 case DataViewType::BIGINT64: 448 index = 10; // 10 : DataViewType::BIGINT64 449 break; 450 case DataViewType::BIGUINT64: 451 index = 11; // 11 : DataViewType::BIGUINT64 452 break; 453 default: 454 LOG_ECMA(FATAL) << "this branch is unreachable"; 455 UNREACHABLE(); 456 } 457 return index; 458 } 459 WriteMethod(const JSHandle<JSTaggedValue> & value)460 bool JSSerializer::WriteMethod(const JSHandle<JSTaggedValue> &value) 461 { 462 JSHandle<Method> method = JSHandle<Method>::Cast(value); 463 if (method->IsNativeWithCallField()) { 464 if (!WriteType(SerializationUID::NATIVE_METHOD)) { 465 return false; 466 } 467 const void *nativeFunc = method->GetNativePointer(); 468 if (!WriteRawData(&nativeFunc, sizeof(uintptr_t))) { 469 return false; 470 } 471 } else { 472 if (!WriteType(SerializationUID::METHOD)) { 473 return false; 474 } 475 const MethodLiteral *methodLiteral = method->GetMethodLiteral(); 476 if (!WriteRawData(&methodLiteral, sizeof(uintptr_t))) { 477 return false; 478 } 479 JSHandle<ConstantPool> constPool(thread_, method->GetConstantPool()); 480 const JSPandaFile *jsPandaFile = constPool->GetJSPandaFile(); 481 if (jsPandaFile == nullptr) { 482 return false; 483 } 484 const CString &desc = jsPandaFile->GetJSPandaFileDesc(); 485 if (!WriteString(desc)) { 486 return false; 487 } 488 } 489 return true; 490 } 491 WriteJSFunction(const JSHandle<JSTaggedValue> & value)492 bool JSSerializer::WriteJSFunction(const JSHandle<JSTaggedValue> &value) 493 { 494 if (!WriteType(SerializationUID::CONCURRENT_FUNCTION)) { 495 return false; 496 } 497 JSHandle<JSFunction> func = JSHandle<JSFunction>::Cast(value); 498 // check concurrent function 499 if (func->GetFunctionKind() != ecmascript::FunctionKind::CONCURRENT_FUNCTION) { 500 LOG_ECMA(ERROR) << "only support serialize concurrent function"; 501 return false; 502 } 503 JSHandle<JSTaggedValue> method(thread_, func->GetMethod()); 504 if (!SerializeJSTaggedValue(method)) { 505 return false; 506 } 507 return true; 508 } 509 WriteJSError(const JSHandle<JSTaggedValue> & value)510 bool JSSerializer::WriteJSError(const JSHandle<JSTaggedValue> &value) 511 { 512 TaggedObject *taggedObject = value->GetTaggedObject(); 513 JSType errorType = taggedObject->GetClass()->GetObjectType(); 514 if (!WriteJSErrorHeader(errorType)) { 515 return false; 516 } 517 auto globalConst = thread_->GlobalConstants(); 518 JSHandle<JSTaggedValue> handleMsg = globalConst->GetHandledMessageString(); 519 JSHandle<JSTaggedValue> msg = JSObject::GetProperty(thread_, value, handleMsg).GetValue(); 520 // Write error message 521 if (!SerializeJSTaggedValue(msg)) { 522 return false; 523 } 524 return true; 525 } 526 WriteJSErrorHeader(JSType type)527 bool JSSerializer::WriteJSErrorHeader(JSType type) 528 { 529 switch (type) { 530 case JSType::JS_ERROR: 531 return WriteType(SerializationUID::JS_ERROR); 532 case JSType::JS_EVAL_ERROR: 533 return WriteType(SerializationUID::EVAL_ERROR); 534 case JSType::JS_RANGE_ERROR: 535 return WriteType(SerializationUID::RANGE_ERROR); 536 case JSType::JS_REFERENCE_ERROR: 537 return WriteType(SerializationUID::REFERENCE_ERROR); 538 case JSType::JS_TYPE_ERROR: 539 return WriteType(SerializationUID::TYPE_ERROR); 540 case JSType::JS_AGGREGATE_ERROR: 541 return WriteType(SerializationUID::AGGREGATE_ERROR); 542 case JSType::JS_URI_ERROR: 543 return WriteType(SerializationUID::URI_ERROR); 544 case JSType::JS_SYNTAX_ERROR: 545 return WriteType(SerializationUID::SYNTAX_ERROR); 546 case JSType::JS_OOM_ERROR: 547 return WriteType(SerializationUID::OOM_ERROR); 548 default: 549 LOG_ECMA(FATAL) << "this branch is unreachable"; 550 UNREACHABLE(); 551 } 552 return false; 553 } 554 WriteJSDate(const JSHandle<JSTaggedValue> & value)555 bool JSSerializer::WriteJSDate(const JSHandle<JSTaggedValue> &value) 556 { 557 JSHandle<JSDate> date = JSHandle<JSDate>::Cast(value); 558 if (!WriteType(SerializationUID::JS_DATE)) { 559 return false; 560 } 561 if (!WritePlainObject(value)) { 562 return false; 563 } 564 double timeValue = date->GetTimeValue().GetDouble(); 565 if (!WriteDouble(timeValue)) { 566 return false; 567 } 568 double localOffset = date->GetLocalOffset().GetDouble(); 569 if (!WriteDouble(localOffset)) { 570 return false; 571 } 572 return true; 573 } 574 WriteJSArray(const JSHandle<JSTaggedValue> & value)575 bool JSSerializer::WriteJSArray(const JSHandle<JSTaggedValue> &value) 576 { 577 JSHandle<JSArray> array = JSHandle<JSArray>::Cast(value); 578 if (!WriteType(SerializationUID::JS_ARRAY)) { 579 return false; 580 } 581 if (!WritePlainObject(value)) { 582 return false; 583 } 584 uint32_t arrayLength = array->GetLength(); 585 if (!WriteInt(arrayLength)) { 586 return false; 587 } 588 return true; 589 } 590 WriteEcmaString(const JSHandle<JSTaggedValue> & value)591 bool JSSerializer::WriteEcmaString(const JSHandle<JSTaggedValue> &value) 592 { 593 JSHandle<EcmaString> strHandle = JSHandle<EcmaString>::Cast(value); 594 auto string = JSHandle<EcmaString>(thread_, EcmaStringAccessor::Flatten(thread_->GetEcmaVM(), strHandle)); 595 if (!WriteType(SerializationUID::ECMASTRING)) { 596 return false; 597 } 598 599 size_t length = EcmaStringAccessor(string).GetLength(); 600 if (!WriteInt(static_cast<int32_t>(length))) { 601 return false; 602 } 603 // skip writeRawData for empty EcmaString 604 if (length == 0) { 605 return true; 606 } 607 608 bool isUtf8 = EcmaStringAccessor(string).IsUtf8(); 609 // write utf encode flag 610 if (!WriteBoolean(isUtf8)) { 611 return false; 612 } 613 if (isUtf8) { 614 const uint8_t *data = EcmaStringAccessor(string).GetDataUtf8(); 615 const uint8_t strEnd = '\0'; 616 if (!WriteRawData(data, length) || !WriteRawData(&strEnd, sizeof(uint8_t))) { 617 return false; 618 } 619 } else { 620 const uint16_t *data = EcmaStringAccessor(string).GetDataUtf16(); 621 if (!WriteRawData(data, length * sizeof(uint16_t))) { 622 return false; 623 } 624 } 625 return true; 626 } 627 WriteJSMap(const JSHandle<JSTaggedValue> & value)628 bool JSSerializer::WriteJSMap(const JSHandle<JSTaggedValue> &value) 629 { 630 JSHandle<JSMap> map = JSHandle<JSMap>::Cast(value); 631 if (!WriteType(SerializationUID::JS_MAP)) { 632 return false; 633 } 634 if (!WritePlainObject(value)) { 635 return false; 636 } 637 uint32_t size = map->GetSize(); 638 if (!WriteInt(static_cast<int32_t>(size))) { 639 return false; 640 } 641 JSMutableHandle<JSTaggedValue> key(thread_, JSTaggedValue::Undefined()); 642 JSMutableHandle<JSTaggedValue> val(thread_, JSTaggedValue::Undefined()); 643 for (uint32_t i = 0; i < size; i++) { 644 key.Update(map->GetKey(i)); 645 if (!SerializeJSTaggedValue(key)) { 646 return false; 647 } 648 val.Update(map->GetValue(i)); 649 if (!SerializeJSTaggedValue(val)) { 650 return false; 651 } 652 } 653 return true; 654 } 655 WriteJSSet(const JSHandle<JSTaggedValue> & value)656 bool JSSerializer::WriteJSSet(const JSHandle<JSTaggedValue> &value) 657 { 658 JSHandle<JSSet> set = JSHandle<JSSet>::Cast(value); 659 if (!WriteType(SerializationUID::JS_SET)) { 660 return false; 661 } 662 if (!WritePlainObject(value)) { 663 return false; 664 } 665 uint32_t size = set->GetSize(); 666 if (!WriteInt(static_cast<int32_t>(size))) { 667 return false; 668 } 669 JSMutableHandle<JSTaggedValue> val(thread_, JSTaggedValue::Undefined()); 670 for (uint32_t i = 0; i < size; i++) { 671 val.Update(set->GetValue(i)); 672 if (!SerializeJSTaggedValue(val)) { 673 return false; 674 } 675 } 676 return true; 677 } 678 WriteJSRegExp(const JSHandle<JSTaggedValue> & value)679 bool JSSerializer::WriteJSRegExp(const JSHandle<JSTaggedValue> &value) 680 { 681 JSHandle<JSRegExp> regExp = JSHandle<JSRegExp>::Cast(value); 682 if (!WriteType(SerializationUID::JS_REG_EXP)) { 683 return false; 684 } 685 if (!WritePlainObject(value)) { 686 return false; 687 } 688 uint32_t bufferSize = regExp->GetLength(); 689 if (!WriteInt(static_cast<int32_t>(bufferSize))) { 690 return false; 691 } 692 // Write Accessor(ByteCodeBuffer) which is a pointer to a dynamic buffer 693 JSHandle<JSTaggedValue> bufferValue(thread_, regExp->GetByteCodeBuffer()); 694 JSHandle<JSNativePointer> np = JSHandle<JSNativePointer>::Cast(bufferValue); 695 void *dynBuffer = np->GetExternalPointer(); 696 if (!WriteRawData(dynBuffer, bufferSize)) { 697 return false; 698 } 699 // Write Accessor(OriginalSource) 700 JSHandle<JSTaggedValue> originalSource(thread_, regExp->GetOriginalSource()); 701 if (!SerializeJSTaggedValue(originalSource)) { 702 return false; 703 } 704 // Write Accessor(OriginalFlags) 705 JSHandle<JSTaggedValue> originalFlags(thread_, regExp->GetOriginalFlags()); 706 if (!SerializeJSTaggedValue(originalFlags)) { 707 return false; 708 } 709 return true; 710 } 711 WriteJSTypedArray(const JSHandle<JSTaggedValue> & value,SerializationUID uId)712 bool JSSerializer::WriteJSTypedArray(const JSHandle<JSTaggedValue> &value, SerializationUID uId) 713 { 714 JSHandle<JSTypedArray> typedArray = JSHandle<JSTypedArray>::Cast(value); 715 if (!WriteType(uId)) { 716 return false; 717 } 718 if (!WritePlainObject(value)) { 719 return false; 720 } 721 [[maybe_unused]] DataViewType viewType = TypedArrayHelper::GetType(typedArray); 722 // Write ACCESSORS(ViewedArrayBuffer) which is a pointer to an ArrayBuffer 723 JSHandle<JSTaggedValue> viewedArrayBufferOrByteArray(thread_, typedArray->GetViewedArrayBufferOrByteArray()); 724 bool isViewedArrayBuffer = false; 725 if (viewedArrayBufferOrByteArray->IsArrayBuffer() || viewedArrayBufferOrByteArray->IsSharedArrayBuffer()) { 726 isViewedArrayBuffer = true; 727 if (!WriteBoolean(isViewedArrayBuffer)) { 728 return false; 729 } 730 if (!SerializeJSTaggedValue(viewedArrayBufferOrByteArray)) { 731 return false; 732 } 733 } else { 734 if (!WriteBoolean(isViewedArrayBuffer)) { 735 return false; 736 } 737 if (!WriteByteArray(viewedArrayBufferOrByteArray, viewType)) { 738 return false; 739 } 740 } 741 742 // Write ACCESSORS(TypedArrayName) 743 JSHandle<JSTaggedValue> typedArrayName(thread_, typedArray->GetTypedArrayName()); 744 if (!SerializeJSTaggedValue(typedArrayName)) { 745 return false; 746 } 747 // Write ACCESSORS(ByteLength) 748 JSTaggedValue byteLength(typedArray->GetByteLength()); 749 if (!WriteRawData(&byteLength, sizeof(JSTaggedValue))) { 750 return false; 751 } 752 // Write ACCESSORS(ByteOffset) 753 JSTaggedValue byteOffset(typedArray->GetByteOffset()); 754 if (!WriteRawData(&byteOffset, sizeof(JSTaggedValue))) { 755 return false; 756 } 757 // Write ACCESSORS(ArrayLength) 758 JSTaggedValue arrayLength(typedArray->GetArrayLength()); 759 if (!WriteRawData(&arrayLength, sizeof(JSTaggedValue))) { 760 return false; 761 } 762 // Write ACCESSORS(ContentType) 763 ContentType contentType = typedArray->GetContentType(); 764 if (!WriteRawData(&contentType, sizeof(ContentType))) { 765 return false; 766 } 767 return true; 768 } 769 WriteJSNativePointer(const JSHandle<JSNativePointer> & nativePtr)770 bool JSSerializer::WriteJSNativePointer(const JSHandle<JSNativePointer> &nativePtr) 771 { 772 uintptr_t externalPtr = reinterpret_cast<uintptr_t>(nativePtr->GetExternalPointer()); 773 if (!WriteRawData(&externalPtr, sizeof(uintptr_t))) { 774 return false; 775 } 776 uintptr_t deleter = reinterpret_cast<uintptr_t>(nativePtr->GetDeleter()); 777 if (!WriteRawData(&deleter, sizeof(uintptr_t))) { 778 return false; 779 } 780 uintptr_t allocatorPtr = reinterpret_cast<uintptr_t>(nativePtr->GetData()); 781 if (!WriteRawData(&allocatorPtr, sizeof(uintptr_t))) { 782 return false; 783 } 784 int32_t bindingSize = static_cast<int32_t>(nativePtr->GetBindingSize()); 785 if (!WriteInt(bindingSize)) { 786 return false; 787 } 788 nativePtr->Detach(); 789 return true; 790 } 791 WriteJSArrayBuffer(const JSHandle<JSTaggedValue> & value)792 bool JSSerializer::WriteJSArrayBuffer(const JSHandle<JSTaggedValue> &value) 793 { 794 JSHandle<JSArrayBuffer> arrayBuffer = JSHandle<JSArrayBuffer>::Cast(value); 795 if (arrayBuffer->IsDetach()) { 796 return false; 797 } 798 bool shared = arrayBuffer->GetShared(); 799 bool transfer = transferDataSet_.find(static_cast<uintptr_t>(value.GetTaggedType())) != transferDataSet_.end(); 800 if (shared && transfer) { 801 LOG_ECMA(ERROR) << "Can't transfer a shared JSArrayBuffer"; 802 return false; 803 } 804 if (shared) { 805 if (!WriteType(SerializationUID::JS_SHARED_ARRAY_BUFFER)) { 806 return false; 807 } 808 } else if (transfer) { 809 if (!WriteType(SerializationUID::JS_TRANSFER_ARRAY_BUFFER)) { 810 return false; 811 } 812 } else { 813 if (!WriteType(SerializationUID::JS_ARRAY_BUFFER)) { 814 return false; 815 } 816 } 817 818 bool withNativeAreaAllocator = arrayBuffer->GetWithNativeAreaAllocator(); 819 if (!WriteBoolean(withNativeAreaAllocator)) { 820 return false; 821 } 822 823 // Write Accessors(ArrayBufferByteLength) 824 uint32_t arrayLength = arrayBuffer->GetArrayBufferByteLength(); 825 if (!WriteInt(arrayLength)) { 826 return false; 827 } 828 829 bool empty = arrayLength == 0; 830 if (!empty) { 831 JSHandle<JSNativePointer> np(thread_, arrayBuffer->GetArrayBufferData()); 832 if (shared) { 833 void *buffer = np->GetExternalPointer(); 834 JSSharedMemoryManager::GetInstance()->CreateOrLoad(&buffer, arrayLength); 835 uint64_t bufferAddr = reinterpret_cast<uint64_t>(buffer); 836 if (!WriteRawData(&bufferAddr, sizeof(uint64_t))) { 837 return false; 838 } 839 } else if (transfer) { 840 // Write Accessors(ArrayBufferData) which is a pointer to a Buffer 841 if (!WriteJSNativePointer(np)) { 842 return false; 843 } 844 arrayBuffer->Detach(thread_, withNativeAreaAllocator); 845 } else { 846 // Write Accessors(ArrayBufferData) which is a pointer to a Buffer 847 void *buffer = np->GetExternalPointer(); 848 if (!WriteRawData(buffer, arrayLength)) { 849 return false; 850 } 851 } 852 } 853 854 // write obj properties 855 if (!WritePlainObject(value)) { 856 return false; 857 } 858 return true; 859 } 860 IsNativeBindingObject(std::vector<JSTaggedValue> keyVector)861 bool JSSerializer::IsNativeBindingObject(std::vector<JSTaggedValue> keyVector) 862 { 863 if (keyVector.size() < 2) { // 2: detachSymbol, attachSymbol 864 return false; 865 } 866 JSHandle<GlobalEnv> env = thread_->GetEcmaVM()->GetGlobalEnv(); 867 JSHandle<JSTaggedValue> detach = env->GetDetachSymbol(); 868 JSHandle<JSTaggedValue> attach = env->GetAttachSymbol(); 869 JSMutableHandle<JSTaggedValue> detachKey(thread_, JSTaggedValue::Undefined()); 870 JSMutableHandle<JSTaggedValue> attachKey(thread_, JSTaggedValue::Undefined()); 871 uint32_t keyLength = keyVector.size(); 872 for (uint32_t i = 0; i < keyLength - 1; i++) { 873 if (keyVector[i].IsSymbol() && keyVector[i + 1].IsSymbol()) { 874 detachKey.Update(keyVector[i]); 875 attachKey.Update(keyVector[i + 1]); 876 if (JSTaggedValue::Equal(thread_, detach, detachKey) || JSTaggedValue::Equal(thread_, attach, attachKey)) { 877 return true; 878 } 879 } 880 } 881 return false; 882 } 883 WritePlainObject(const JSHandle<JSTaggedValue> & objValue)884 bool JSSerializer::WritePlainObject(const JSHandle<JSTaggedValue> &objValue) 885 { 886 JSHandle<JSObject> obj = JSHandle<JSObject>::Cast(objValue); 887 std::vector<JSTaggedValue> keyVector; 888 uint32_t propertiesLength = obj->GetNumberOfKeys(); 889 JSObject::GetAllKeys(obj, keyVector); 890 if (keyVector.size() != propertiesLength) { 891 return false; 892 } 893 894 // Write custom JS obj that only used for carrying native binding functions 895 if (IsNativeBindingObject(keyVector)) { 896 return WriteNativeBindingObject(objValue); 897 } 898 899 // not support native object without detach and attach 900 if (obj->GetNativePointerFieldCount() > 0) { 901 return false; 902 } 903 904 if (!WriteType(SerializationUID::JS_PLAIN_OBJECT)) { 905 return false; 906 } 907 if (!WriteInt(static_cast<int32_t>(propertiesLength))) { 908 return false; 909 } 910 JSMutableHandle<JSTaggedValue> propertyKey(thread_, JSTaggedValue::Undefined()); 911 for (uint32_t i = 0; i < propertiesLength; i++) { 912 if (keyVector.empty()) { 913 return false; 914 } 915 propertyKey.Update(keyVector[i]); 916 if (!SerializeJSTaggedValue(propertyKey)) { 917 return false; 918 } 919 PropertyDescriptor desc(thread_); 920 JSObject::OrdinaryGetOwnProperty(thread_, obj, propertyKey, desc); 921 if (!WriteDesc(desc)) { 922 return false; 923 } 924 } 925 926 uint32_t elementsLength = obj->GetNumberOfElements(); 927 if (!WriteInt(static_cast<int32_t>(elementsLength))) { 928 return false; 929 } 930 keyVector.clear(); 931 JSObject::GetALLElementKeysIntoVector(thread_, obj, keyVector); 932 // Write elements' description attributes and value 933 if (keyVector.size() != elementsLength) { 934 return false; 935 } 936 JSMutableHandle<JSTaggedValue> elementKey(thread_, JSTaggedValue::Undefined()); 937 for (uint32_t i = 0; i < elementsLength; i++) { 938 elementKey.Update(keyVector[i]); 939 if (!SerializeJSTaggedValue(elementKey)) { 940 return false; 941 } 942 PropertyDescriptor desc(thread_); 943 JSObject::OrdinaryGetOwnProperty(thread_, obj, elementKey, desc); 944 if (!WriteDesc(desc)) { 945 return false; 946 } 947 } 948 return true; 949 } 950 WriteNativeBindingObject(const JSHandle<JSTaggedValue> & objValue)951 bool JSSerializer::WriteNativeBindingObject(const JSHandle<JSTaggedValue> &objValue) 952 { 953 JSHandle<JSObject> obj = JSHandle<JSObject>::Cast(objValue); 954 JSHandle<GlobalEnv> env = thread_->GetEcmaVM()->GetGlobalEnv(); 955 JSHandle<JSTaggedValue> detach = env->GetDetachSymbol(); 956 JSHandle<JSTaggedValue> attach = env->GetAttachSymbol(); 957 if (!WriteType(SerializationUID::NATIVE_BINDING_OBJECT)) { 958 return false; 959 } 960 int32_t paramCount = obj->GetNativePointerFieldCount(); 961 void *enginePointer = nullptr; 962 void *objPointer = nullptr; 963 void *hint = nullptr; 964 void *detachData = nullptr; 965 void *attachData = nullptr; 966 if (paramCount == 5) { // 5 : enginePointer, objPointer, hint, detachData, attachData 967 enginePointer = obj->GetNativePointerField(0); 968 objPointer = obj->GetNativePointerField(1); 969 hint = obj->GetNativePointerField(2); // 2 : hint 970 detachData = obj->GetNativePointerField(3); // 3 : detachData 971 attachData = obj->GetNativePointerField(4); // 4 : attachData 972 } 973 // Write custom object's values: AttachFunc*, buffer* 974 JSHandle<JSTaggedValue> detachVal = JSObject::GetProperty(thread_, obj, detach).GetRawValue(); 975 JSHandle<JSTaggedValue> attackVal = JSObject::GetProperty(thread_, obj, attach).GetRawValue(); 976 DetachFunc detachNative = reinterpret_cast<DetachFunc>(JSNativePointer::Cast( 977 detachVal.GetTaggedValue().GetTaggedObject())->GetExternalPointer()); 978 if (detachNative == nullptr) { 979 return false; 980 } 981 void *buffer = detachNative(enginePointer, objPointer, hint, detachData); 982 AttachFunc attachNative = reinterpret_cast<AttachFunc>(JSNativePointer::Cast( 983 attackVal.GetTaggedValue().GetTaggedObject())->GetExternalPointer()); 984 if (!WriteRawData(&attachNative, sizeof(uintptr_t))) { 985 return false; 986 } 987 if (!WriteRawData(&buffer, sizeof(uintptr_t))) { 988 return false; 989 } 990 if (!WriteRawData(&hint, sizeof(uintptr_t))) { 991 return false; 992 } 993 if (!WriteRawData(&attachData, sizeof(uintptr_t))) { 994 return false; 995 } 996 return true; 997 } 998 WriteDesc(const PropertyDescriptor & desc)999 bool JSSerializer::WriteDesc(const PropertyDescriptor &desc) 1000 { 1001 bool isWritable = desc.IsWritable(); 1002 if (!WriteBoolean(isWritable)) { 1003 return false; 1004 } 1005 bool isEnumerable = desc.IsEnumerable(); 1006 if (!WriteBoolean(isEnumerable)) { 1007 return false; 1008 } 1009 bool isConfigurable = desc.IsConfigurable(); 1010 if (!WriteBoolean(isConfigurable)) { 1011 return false; 1012 } 1013 bool hasWritable = desc.HasWritable(); 1014 if (!WriteBoolean(hasWritable)) { 1015 return false; 1016 } 1017 bool hasEnumerable = desc.HasEnumerable(); 1018 if (!WriteBoolean(hasEnumerable)) { 1019 return false; 1020 } 1021 bool hasConfigurable = desc.HasConfigurable(); 1022 if (!WriteBoolean(hasConfigurable)) { 1023 return false; 1024 } 1025 JSHandle<JSTaggedValue> value = desc.GetValue(); 1026 if (!SerializeJSTaggedValue(value)) { 1027 return false; 1028 } 1029 return true; 1030 } 1031 ReadType()1032 SerializationUID JSDeserializer::ReadType() 1033 { 1034 SerializationUID uid; 1035 if (position_ >= end_) { 1036 return SerializationUID::UNKNOWN; 1037 } 1038 uid = static_cast<SerializationUID>(*position_); 1039 if (uid < SerializationUID::UID_BEGIN || uid > SerializationUID::UID_END) { 1040 return SerializationUID::UNKNOWN; 1041 } 1042 position_++; // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) 1043 return uid; 1044 } 1045 ReadInt(int32_t * value)1046 bool JSDeserializer::ReadInt(int32_t *value) 1047 { 1048 size_t len = sizeof(int32_t); 1049 if (len > static_cast<size_t>(end_ - position_)) { 1050 return false; 1051 } 1052 if (memcpy_s(value, len, position_, len) != EOK) { 1053 LOG_ECMA(FATAL) << "this branch is unreachable"; 1054 UNREACHABLE(); 1055 } 1056 position_ += len; 1057 return true; 1058 } 1059 ReadObjectId(uint64_t * objectId)1060 bool JSDeserializer::ReadObjectId(uint64_t *objectId) 1061 { 1062 size_t len = sizeof(uint64_t); 1063 if (len > static_cast<size_t>(end_ - position_)) { 1064 return false; 1065 } 1066 if (memcpy_s(objectId, len, position_, len) != EOK) { 1067 LOG_ECMA(FATAL) << "this branch is unreachable"; 1068 UNREACHABLE(); 1069 } 1070 position_ += len; 1071 return true; 1072 } 1073 ReadDouble(double * value)1074 bool JSDeserializer::ReadDouble(double *value) 1075 { 1076 size_t len = sizeof(double); 1077 if (len > static_cast<size_t>(end_ - position_)) { 1078 return false; 1079 } 1080 if (memcpy_s(value, len, position_, len) != EOK) { 1081 LOG_ECMA(FATAL) << "this branch is unreachable"; 1082 UNREACHABLE(); 1083 } 1084 position_ += len; 1085 return true; 1086 } 1087 ~JSDeserializer()1088 JSDeserializer::~JSDeserializer() 1089 { 1090 referenceMap_.clear(); 1091 } 1092 Deserialize()1093 JSHandle<JSTaggedValue> JSDeserializer::Deserialize() 1094 { 1095 size_t maxSerializerSize = thread_->GetEcmaVM()->GetEcmaParamConfiguration().GetMaxJSSerializerSize(); 1096 uint8_t dataSize = end_ - begin_; 1097 if (dataSize > maxSerializerSize) { 1098 LOG_ECMA(ERROR) << "The Serialization data size exceed limit Size"; 1099 return JSHandle<JSTaggedValue>(); 1100 } 1101 JSHandle<JSTaggedValue> res = DeserializeJSTaggedValue(); 1102 return res; 1103 } 1104 DeserializeJSTaggedValue()1105 JSHandle<JSTaggedValue> JSDeserializer::DeserializeJSTaggedValue() 1106 { 1107 SerializationUID uid = ReadType(); 1108 if (uid == SerializationUID::UNKNOWN) { 1109 return JSHandle<JSTaggedValue>(); 1110 } 1111 switch (uid) { 1112 case SerializationUID::JS_NULL: 1113 return JSHandle<JSTaggedValue>(thread_, JSTaggedValue::Null()); 1114 case SerializationUID::JS_UNDEFINED: 1115 return JSHandle<JSTaggedValue>(thread_, JSTaggedValue::Undefined()); 1116 case SerializationUID::JS_TRUE: 1117 return JSHandle<JSTaggedValue>(thread_, JSTaggedValue::True()); 1118 case SerializationUID::JS_FALSE: 1119 return JSHandle<JSTaggedValue>(thread_, JSTaggedValue::False()); 1120 case SerializationUID::HOLE: 1121 return JSHandle<JSTaggedValue>(thread_, JSTaggedValue::Hole()); 1122 case SerializationUID::INT32: { 1123 int32_t value; 1124 if (!ReadInt(&value)) { 1125 return JSHandle<JSTaggedValue>(); 1126 } 1127 return JSHandle<JSTaggedValue>(thread_, JSTaggedValue(value)); 1128 } 1129 case SerializationUID::DOUBLE: { 1130 double value; 1131 if (!ReadDouble(&value)) { 1132 return JSHandle<JSTaggedValue>(); 1133 } 1134 return JSHandle<JSTaggedValue>(thread_, JSTaggedValue(value)); 1135 } 1136 case SerializationUID::JS_ERROR: 1137 case SerializationUID::EVAL_ERROR: 1138 case SerializationUID::RANGE_ERROR: 1139 case SerializationUID::REFERENCE_ERROR: 1140 case SerializationUID::TYPE_ERROR: 1141 case SerializationUID::AGGREGATE_ERROR: 1142 case SerializationUID::URI_ERROR: 1143 case SerializationUID::SYNTAX_ERROR: 1144 case SerializationUID::OOM_ERROR: 1145 return ReadJSError(uid); 1146 case SerializationUID::JS_DATE: 1147 return ReadJSDate(); 1148 case SerializationUID::JS_PLAIN_OBJECT: 1149 return ReadPlainObject(); 1150 case SerializationUID::NATIVE_BINDING_OBJECT: 1151 return ReadNativeBindingObject(); 1152 case SerializationUID::JS_ARRAY: 1153 return ReadJSArray(); 1154 case SerializationUID::ECMASTRING: 1155 return ReadEcmaString(); 1156 case SerializationUID::JS_MAP: 1157 return ReadJSMap(); 1158 case SerializationUID::JS_SET: 1159 return ReadJSSet(); 1160 case SerializationUID::JS_REG_EXP: 1161 return ReadJSRegExp(); 1162 case SerializationUID::JS_INT8_ARRAY: 1163 return ReadJSTypedArray(SerializationUID::JS_INT8_ARRAY); 1164 case SerializationUID::JS_UINT8_ARRAY: 1165 return ReadJSTypedArray(SerializationUID::JS_UINT8_ARRAY); 1166 case SerializationUID::JS_UINT8_CLAMPED_ARRAY: 1167 return ReadJSTypedArray(SerializationUID::JS_UINT8_CLAMPED_ARRAY); 1168 case SerializationUID::JS_INT16_ARRAY: 1169 return ReadJSTypedArray(SerializationUID::JS_INT16_ARRAY); 1170 case SerializationUID::JS_UINT16_ARRAY: 1171 return ReadJSTypedArray(SerializationUID::JS_UINT16_ARRAY); 1172 case SerializationUID::JS_INT32_ARRAY: 1173 return ReadJSTypedArray(SerializationUID::JS_INT32_ARRAY); 1174 case SerializationUID::JS_UINT32_ARRAY: 1175 return ReadJSTypedArray(SerializationUID::JS_UINT32_ARRAY); 1176 case SerializationUID::JS_FLOAT32_ARRAY: 1177 return ReadJSTypedArray(SerializationUID::JS_FLOAT32_ARRAY); 1178 case SerializationUID::JS_FLOAT64_ARRAY: 1179 return ReadJSTypedArray(SerializationUID::JS_FLOAT64_ARRAY); 1180 case SerializationUID::JS_BIGINT64_ARRAY: 1181 return ReadJSTypedArray(SerializationUID::JS_BIGINT64_ARRAY); 1182 case SerializationUID::JS_BIGUINT64_ARRAY: 1183 return ReadJSTypedArray(SerializationUID::JS_BIGUINT64_ARRAY); 1184 case SerializationUID::JS_ARRAY_BUFFER: 1185 case SerializationUID::JS_SHARED_ARRAY_BUFFER: 1186 case SerializationUID::JS_TRANSFER_ARRAY_BUFFER: 1187 return ReadJSArrayBuffer(uid); 1188 case SerializationUID::TAGGED_OBJECT_REFERNCE: 1189 return ReadReference(); 1190 case SerializationUID::CONCURRENT_FUNCTION: 1191 return ReadJSFunction(); 1192 case SerializationUID::TAGGED_ARRAY: 1193 return ReadTaggedArray(); 1194 case SerializationUID::METHOD: 1195 return ReadMethod(); 1196 case SerializationUID::NATIVE_METHOD: 1197 return ReadNativeMethod(); 1198 case SerializationUID::BIGINT: 1199 return ReadBigInt(); 1200 default: 1201 return JSHandle<JSTaggedValue>(); 1202 } 1203 } 1204 ReadBigInt()1205 JSHandle<JSTaggedValue> JSDeserializer::ReadBigInt() 1206 { 1207 int32_t len = 0; 1208 if (!JudgeType(SerializationUID::INT32) || !ReadInt(&len)) { 1209 return JSHandle<JSTaggedValue>(); 1210 } 1211 bool sign = false; 1212 if (!ReadBoolean(&sign)) { 1213 return JSHandle<JSTaggedValue>(); 1214 } 1215 JSHandle<BigInt> bigInt = factory_->NewBigInt(len); 1216 bigInt->SetSign(sign); 1217 JSHandle<JSTaggedValue> bigIntVal(bigInt); 1218 referenceMap_.emplace(objectId_++, bigIntVal); 1219 for (int32_t i = 0; i < len; i++) { 1220 int32_t val = 0; 1221 if (!JudgeType(SerializationUID::INT32) || !ReadInt(&val)) { 1222 return JSHandle<JSTaggedValue>(); 1223 } 1224 bigInt->SetDigit(i, val); 1225 } 1226 return bigIntVal; 1227 } 1228 ReadTaggedArray()1229 JSHandle<JSTaggedValue> JSDeserializer::ReadTaggedArray() 1230 { 1231 int32_t len = 0; 1232 if (!JudgeType(SerializationUID::INT32) || !ReadInt(&len)) { 1233 return JSHandle<JSTaggedValue>(); 1234 } 1235 JSHandle<TaggedArray> taggedArray = factory_->NewTaggedArray(len); 1236 JSHandle<JSTaggedValue> arrayTag(taggedArray); 1237 referenceMap_.emplace(objectId_++, arrayTag); 1238 for (int32_t i = 0; i < len; i++) { 1239 JSHandle<JSTaggedValue> val = DeserializeJSTaggedValue(); 1240 taggedArray->Set(thread_, i, val.GetTaggedValue()); 1241 } 1242 return arrayTag; 1243 } 1244 ReadByteArray()1245 JSHandle<JSTaggedValue> JSDeserializer::ReadByteArray() 1246 { 1247 int32_t arrayLength = 0; 1248 if (!JudgeType(SerializationUID::INT32) || !ReadInt(&arrayLength)) { 1249 return JSHandle<JSTaggedValue>(); 1250 } 1251 int32_t viewTypeIndex = 0; 1252 if (!JudgeType(SerializationUID::INT32) || !ReadInt(&viewTypeIndex)) { 1253 return JSHandle<JSTaggedValue>(); 1254 } 1255 DataViewType viewType = GetDataViewTypeByIndex(viewTypeIndex); 1256 uint32_t arrayType = TypedArrayHelper::GetSizeFromType(viewType); 1257 JSHandle<ByteArray> byteArray = factory_->NewByteArray(arrayLength, arrayType); 1258 for (int32_t i = 0; i < arrayLength; i++) { 1259 JSHandle<JSTaggedValue> val = DeserializeJSTaggedValue(); 1260 byteArray->Set(thread_, i, viewType, val.GetTaggedType()); 1261 } 1262 return JSHandle<JSTaggedValue>(byteArray); 1263 } 1264 GetDataViewTypeByIndex(uint32_t viewTypeIndex)1265 DataViewType JSDeserializer::GetDataViewTypeByIndex(uint32_t viewTypeIndex) 1266 { 1267 DataViewType viewType; 1268 switch (viewTypeIndex) { 1269 case 1: // 1 : DataViewType::INT8 1270 viewType = DataViewType::INT8; 1271 break; 1272 case 2: // 2 : DataViewType::UINT8 1273 viewType = DataViewType::UINT8; 1274 break; 1275 case 3: // 3 : DataViewType::UINT8_CLAMPED 1276 viewType = DataViewType::UINT8_CLAMPED; 1277 break; 1278 case 4: // 4 : DataViewType::INT16 1279 viewType = DataViewType::INT16; 1280 break; 1281 case 5: // 5 : DataViewType::UINT16 1282 viewType = DataViewType::UINT16; 1283 break; 1284 case 6: // 6 : DataViewType::INT32 1285 viewType = DataViewType::INT32; 1286 break; 1287 case 7: // 7 : DataViewType::UINT32 1288 viewType = DataViewType::UINT32; 1289 break; 1290 case 8: // 8 : DataViewType::FLOAT32 1291 viewType = DataViewType::FLOAT32; 1292 break; 1293 case 9: // 9 : DataViewType::FLOAT64 1294 viewType = DataViewType::FLOAT64; 1295 break; 1296 case 10: // 10 : DataViewType::BIGINT64 1297 viewType = DataViewType::BIGINT64; 1298 break; 1299 case 11: // 11 : DataViewType::BIGUINT64 1300 viewType = DataViewType::BIGUINT64; 1301 break; 1302 default: 1303 LOG_ECMA(FATAL) << "this branch is unreachable"; 1304 UNREACHABLE(); 1305 } 1306 return viewType; 1307 } 1308 ReadMethod()1309 JSHandle<JSTaggedValue> JSDeserializer::ReadMethod() 1310 { 1311 uintptr_t methodLiteral; 1312 if (!ReadNativePointer(&methodLiteral)) { 1313 return JSHandle<JSTaggedValue>(); 1314 } 1315 JSHandle<Method> method = factory_->NewMethod(reinterpret_cast<MethodLiteral *>(methodLiteral)); 1316 JSHandle<JSTaggedValue> methodTag(method); 1317 referenceMap_.emplace(objectId_++, methodTag); 1318 1319 CString desc; 1320 if (!ReadString(&desc)) { 1321 return JSHandle<JSTaggedValue>(); 1322 } 1323 std::shared_ptr<JSPandaFile> jsPandaFile = JSPandaFileManager::GetInstance()->FindJSPandaFile(desc); 1324 if (jsPandaFile == nullptr) { 1325 return JSHandle<JSTaggedValue>(); 1326 } 1327 JSHandle<ConstantPool> constPool = 1328 thread_->GetCurrentEcmaContext()->FindOrCreateConstPool(jsPandaFile.get(), method->GetMethodId()); 1329 method->SetConstantPool(thread_, constPool.GetTaggedValue()); 1330 return methodTag; 1331 } 1332 ReadString(CString * value)1333 bool JSDeserializer::ReadString(CString *value) 1334 { 1335 if (!JudgeType(SerializationUID::C_STRING)) { 1336 return false; 1337 } 1338 1339 *value = reinterpret_cast<char *>(const_cast<uint8_t *>(position_)); 1340 size_t len = value->length() + 1; // 1: '\0' 1341 position_ += len; 1342 return true; 1343 } 1344 ReadNativeMethod()1345 JSHandle<JSTaggedValue> JSDeserializer::ReadNativeMethod() 1346 { 1347 uintptr_t nativeFunc; 1348 if (!ReadNativePointer(&nativeFunc)) { 1349 return JSHandle<JSTaggedValue>(); 1350 } 1351 JSHandle<Method> method = factory_->NewMethodForNativeFunction(reinterpret_cast<void *>(nativeFunc)); 1352 JSHandle<JSTaggedValue> methodTag(method); 1353 referenceMap_.emplace(objectId_++, methodTag); 1354 return methodTag; 1355 } 1356 ReadJSFunction()1357 JSHandle<JSTaggedValue> JSDeserializer::ReadJSFunction() 1358 { 1359 JSHandle<GlobalEnv> env = thread_->GetEcmaVM()->GetGlobalEnv(); 1360 JSHandle<JSFunction> func = factory_->NewJSFunction(env, nullptr, FunctionKind::CONCURRENT_FUNCTION); 1361 JSHandle<JSTaggedValue> funcTag(func); 1362 referenceMap_.emplace(objectId_++, funcTag); 1363 JSHandle<JSTaggedValue> methodVal = DeserializeJSTaggedValue(); 1364 JSHandle<Method> method = JSHandle<Method>::Cast(methodVal); 1365 func->SetMethod(thread_, method); 1366 return funcTag; 1367 } 1368 ReadJSError(SerializationUID uid)1369 JSHandle<JSTaggedValue> JSDeserializer::ReadJSError(SerializationUID uid) 1370 { 1371 base::ErrorType errorType; 1372 switch (uid) { 1373 case SerializationUID::JS_ERROR: 1374 errorType = base::ErrorType::ERROR; 1375 break; 1376 case SerializationUID::EVAL_ERROR: 1377 errorType = base::ErrorType::EVAL_ERROR; 1378 break; 1379 case SerializationUID::RANGE_ERROR: 1380 errorType = base::ErrorType::RANGE_ERROR; 1381 break; 1382 case SerializationUID::REFERENCE_ERROR: 1383 errorType = base::ErrorType::REFERENCE_ERROR; 1384 break; 1385 case SerializationUID::TYPE_ERROR: 1386 errorType = base::ErrorType::TYPE_ERROR; 1387 break; 1388 case SerializationUID::AGGREGATE_ERROR: 1389 errorType = base::ErrorType::AGGREGATE_ERROR; 1390 break; 1391 case SerializationUID::URI_ERROR: 1392 errorType = base::ErrorType::URI_ERROR; 1393 break; 1394 case SerializationUID::SYNTAX_ERROR: 1395 errorType = base::ErrorType::SYNTAX_ERROR; 1396 break; 1397 case SerializationUID::OOM_ERROR: 1398 errorType = base::ErrorType::OOM_ERROR; 1399 break; 1400 default: 1401 LOG_ECMA(FATAL) << "this branch is unreachable"; 1402 UNREACHABLE(); 1403 } 1404 JSHandle<JSTaggedValue> msg = DeserializeJSTaggedValue(); 1405 JSHandle<EcmaString> handleMsg(msg); 1406 JSHandle<JSTaggedValue> errorTag = JSHandle<JSTaggedValue>::Cast(factory_->NewJSError(errorType, handleMsg)); 1407 referenceMap_.emplace(objectId_++, errorTag); 1408 return errorTag; 1409 } 1410 ReadJSDate()1411 JSHandle<JSTaggedValue> JSDeserializer::ReadJSDate() 1412 { 1413 JSHandle<GlobalEnv> env = thread_->GetEcmaVM()->GetGlobalEnv(); 1414 JSHandle<JSFunction> dateFunction(env->GetDateFunction()); 1415 JSHandle<JSDate> date = JSHandle<JSDate>::Cast(factory_->NewJSObjectByConstructor(dateFunction)); 1416 JSHandle<JSTaggedValue> dateTag = JSHandle<JSTaggedValue>::Cast(date); 1417 referenceMap_.emplace(objectId_++, dateTag); 1418 if (!JudgeType(SerializationUID::JS_PLAIN_OBJECT) || !DefinePropertiesAndElements(dateTag)) { 1419 return JSHandle<JSTaggedValue>(); 1420 } 1421 double timeValue = 0.0; 1422 if (!JudgeType(SerializationUID::DOUBLE) || !ReadDouble(&timeValue)) { 1423 return JSHandle<JSTaggedValue>(); 1424 } 1425 date->SetTimeValue(thread_, JSTaggedValue(timeValue)); 1426 double localOffset = 0.0; 1427 if (!JudgeType(SerializationUID::DOUBLE) || !ReadDouble(&localOffset)) { 1428 return JSHandle<JSTaggedValue>(); 1429 } 1430 date->SetLocalOffset(thread_, JSTaggedValue(localOffset)); 1431 return dateTag; 1432 } 1433 ReadJSArray()1434 JSHandle<JSTaggedValue> JSDeserializer::ReadJSArray() 1435 { 1436 JSHandle<JSArray> jsArray = thread_->GetEcmaVM()->GetFactory()->NewJSArray(); 1437 JSHandle<JSTaggedValue> arrayTag = JSHandle<JSTaggedValue>::Cast(jsArray); 1438 referenceMap_.emplace(objectId_++, arrayTag); 1439 if (!JudgeType(SerializationUID::JS_PLAIN_OBJECT) || !DefinePropertiesAndElements(arrayTag)) { 1440 return JSHandle<JSTaggedValue>(); 1441 } 1442 int32_t arrLength; 1443 if (!JudgeType(SerializationUID::INT32) || !ReadInt(&arrLength)) { 1444 return JSHandle<JSTaggedValue>(); 1445 } 1446 jsArray->SetLength(arrLength); 1447 return arrayTag; 1448 } 1449 ReadEcmaString()1450 JSHandle<JSTaggedValue> JSDeserializer::ReadEcmaString() 1451 { 1452 int32_t stringLength; 1453 if (!JudgeType(SerializationUID::INT32) || !ReadInt(&stringLength)) { 1454 return JSHandle<JSTaggedValue>(); 1455 } 1456 if (stringLength == 0) { 1457 JSHandle<JSTaggedValue> emptyString = JSHandle<JSTaggedValue>::Cast(factory_->GetEmptyString()); 1458 referenceMap_.emplace(objectId_++, emptyString); 1459 return emptyString; 1460 } 1461 1462 bool isUtf8 = false; 1463 if (!ReadBoolean(&isUtf8)) { 1464 return JSHandle<JSTaggedValue>(); 1465 } 1466 1467 JSHandle<JSTaggedValue> stringTag; 1468 if (isUtf8) { 1469 uint8_t *string = reinterpret_cast<uint8_t*>(GetBuffer(stringLength + 1)); 1470 if (string == nullptr) { 1471 return JSHandle<JSTaggedValue>(); 1472 } 1473 1474 JSHandle<EcmaString> ecmaString = factory_->NewFromUtf8(string, stringLength); 1475 stringTag = JSHandle<JSTaggedValue>(ecmaString); 1476 referenceMap_.emplace(objectId_++, stringTag); 1477 } else { 1478 uint16_t *string = reinterpret_cast<uint16_t*>(GetBuffer(stringLength * sizeof(uint16_t))); 1479 if (string == nullptr) { 1480 return JSHandle<JSTaggedValue>(); 1481 } 1482 JSHandle<EcmaString> ecmaString = factory_->NewFromUtf16(string, stringLength); 1483 stringTag = JSHandle<JSTaggedValue>(ecmaString); 1484 referenceMap_.emplace(objectId_++, stringTag); 1485 } 1486 return stringTag; 1487 } 1488 ReadPlainObject()1489 JSHandle<JSTaggedValue> JSDeserializer::ReadPlainObject() 1490 { 1491 JSHandle<GlobalEnv> env = thread_->GetEcmaVM()->GetGlobalEnv(); 1492 JSHandle<JSFunction> objFunc(env->GetObjectFunction()); 1493 JSHandle<JSObject> jsObject = thread_->GetEcmaVM()->GetFactory()->NewJSObjectByConstructor(objFunc); 1494 JSHandle<JSTaggedValue> objTag = JSHandle<JSTaggedValue>::Cast(jsObject); 1495 referenceMap_.emplace(objectId_++, objTag); 1496 if (!DefinePropertiesAndElements(objTag)) { 1497 return JSHandle<JSTaggedValue>(); 1498 } 1499 return objTag; 1500 } 1501 ReadNativeBindingObject()1502 JSHandle<JSTaggedValue> JSDeserializer::ReadNativeBindingObject() 1503 { 1504 uintptr_t funcPointer; 1505 if (!ReadNativePointer(&funcPointer)) { 1506 return JSHandle<JSTaggedValue>(); 1507 } 1508 AttachFunc attachFunc = reinterpret_cast<AttachFunc>(funcPointer); 1509 if (attachFunc == nullptr) { 1510 return JSHandle<JSTaggedValue>(); 1511 } 1512 uintptr_t bufferPointer; 1513 if (!ReadNativePointer(&bufferPointer)) { 1514 return JSHandle<JSTaggedValue>(); 1515 } 1516 uintptr_t hint; 1517 if (!ReadNativePointer(&hint)) { 1518 return JSHandle<JSTaggedValue>(); 1519 } 1520 uintptr_t attachData; 1521 if (!ReadNativePointer(&attachData)) { 1522 return JSHandle<JSTaggedValue>(); 1523 } 1524 Local<JSValueRef> attachVal = attachFunc(engine_, reinterpret_cast<void *>(bufferPointer), 1525 reinterpret_cast<void *>(hint), reinterpret_cast<void *>(attachData)); 1526 if (attachVal.IsEmpty()) { 1527 LOG_ECMA(ERROR) << "NativeBindingObject is empty"; 1528 attachVal = JSValueRef::Undefined(thread_->GetEcmaVM()); 1529 } 1530 objectId_++; 1531 return JSNApiHelper::ToJSHandle(attachVal); 1532 } 1533 ReadJSMap()1534 JSHandle<JSTaggedValue> JSDeserializer::ReadJSMap() 1535 { 1536 JSHandle<GlobalEnv> env = thread_->GetEcmaVM()->GetGlobalEnv(); 1537 JSHandle<JSFunction> mapFunction(env->GetBuiltinsMapFunction()); 1538 JSHandle<JSMap> jsMap = JSHandle<JSMap>::Cast(factory_->NewJSObjectByConstructor(mapFunction)); 1539 JSHandle<JSTaggedValue> mapTag = JSHandle<JSTaggedValue>::Cast(jsMap); 1540 referenceMap_.emplace(objectId_++, mapTag); 1541 if (!JudgeType(SerializationUID::JS_PLAIN_OBJECT) || !DefinePropertiesAndElements(mapTag)) { 1542 return JSHandle<JSTaggedValue>(); 1543 } 1544 int32_t size; 1545 if (!JudgeType(SerializationUID::INT32) || !ReadInt(&size)) { 1546 return JSHandle<JSTaggedValue>(); 1547 } 1548 JSHandle<LinkedHashMap> linkedMap = LinkedHashMap::Create(thread_); 1549 jsMap->SetLinkedMap(thread_, linkedMap); 1550 for (int32_t i = 0; i < size; i++) { 1551 JSHandle<JSTaggedValue> key = DeserializeJSTaggedValue(); 1552 if (key.IsEmpty()) { 1553 return JSHandle<JSTaggedValue>(); 1554 } 1555 JSHandle<JSTaggedValue> value = DeserializeJSTaggedValue(); 1556 if (value.IsEmpty()) { 1557 return JSHandle<JSTaggedValue>(); 1558 } 1559 JSMap::Set(thread_, jsMap, key, value); 1560 } 1561 return mapTag; 1562 } 1563 ReadJSSet()1564 JSHandle<JSTaggedValue> JSDeserializer::ReadJSSet() 1565 { 1566 JSHandle<GlobalEnv> env = thread_->GetEcmaVM()->GetGlobalEnv(); 1567 JSHandle<JSFunction> setFunction(env->GetBuiltinsSetFunction()); 1568 JSHandle<JSSet> jsSet = JSHandle<JSSet>::Cast(factory_->NewJSObjectByConstructor(setFunction)); 1569 JSHandle<JSTaggedValue> setTag = JSHandle<JSTaggedValue>::Cast(jsSet); 1570 referenceMap_.emplace(objectId_++, setTag); 1571 if (!JudgeType(SerializationUID::JS_PLAIN_OBJECT) || !DefinePropertiesAndElements(setTag)) { 1572 return JSHandle<JSTaggedValue>(); 1573 } 1574 int32_t size; 1575 if (!JudgeType(SerializationUID::INT32) || !ReadInt(&size)) { 1576 return JSHandle<JSTaggedValue>(); 1577 } 1578 JSHandle<LinkedHashSet> linkedSet = LinkedHashSet::Create(thread_); 1579 jsSet->SetLinkedSet(thread_, linkedSet); 1580 for (int32_t i = 0; i < size; i++) { 1581 JSHandle<JSTaggedValue> key = DeserializeJSTaggedValue(); 1582 if (key.IsEmpty()) { 1583 return JSHandle<JSTaggedValue>(); 1584 } 1585 JSSet::Add(thread_, jsSet, key); 1586 } 1587 return setTag; 1588 } 1589 ReadJSRegExp()1590 JSHandle<JSTaggedValue> JSDeserializer::ReadJSRegExp() 1591 { 1592 JSHandle<GlobalEnv> env = thread_->GetEcmaVM()->GetGlobalEnv(); 1593 JSHandle<JSFunction> regexpFunction(env->GetRegExpFunction()); 1594 JSHandle<JSObject> obj = factory_->NewJSObjectByConstructor(regexpFunction); 1595 JSHandle<JSRegExp> regExp = JSHandle<JSRegExp>::Cast(obj); 1596 JSHandle<JSTaggedValue> regexpTag = JSHandle<JSTaggedValue>::Cast(regExp); 1597 referenceMap_.emplace(objectId_++, regexpTag); 1598 if (!JudgeType(SerializationUID::JS_PLAIN_OBJECT) || !DefinePropertiesAndElements(regexpTag)) { 1599 return JSHandle<JSTaggedValue>(); 1600 } 1601 int32_t bufferSize; 1602 if (!JudgeType(SerializationUID::INT32) || !ReadInt(&bufferSize)) { 1603 return JSHandle<JSTaggedValue>(); 1604 } 1605 void *buffer = GetBuffer(bufferSize); 1606 if (buffer == nullptr) { 1607 return JSHandle<JSTaggedValue>(); 1608 } 1609 factory_->NewJSRegExpByteCodeData(regExp, buffer, bufferSize); 1610 JSHandle<JSTaggedValue> originalSource = DeserializeJSTaggedValue(); 1611 regExp->SetOriginalSource(thread_, originalSource); 1612 JSHandle<JSTaggedValue> originalFlags = DeserializeJSTaggedValue(); 1613 regExp->SetOriginalFlags(thread_, originalFlags); 1614 return regexpTag; 1615 } 1616 ReadJSTypedArray(SerializationUID uid)1617 JSHandle<JSTaggedValue> JSDeserializer::ReadJSTypedArray(SerializationUID uid) 1618 { 1619 JSHandle<GlobalEnv> env = thread_->GetEcmaVM()->GetGlobalEnv(); 1620 JSHandle<JSTaggedValue> target; 1621 JSHandle<JSObject> obj; 1622 JSHandle<JSTaggedValue> objTag; 1623 switch (uid) { 1624 case SerializationUID::JS_INT8_ARRAY: { 1625 target = env->GetInt8ArrayFunction(); 1626 break; 1627 } 1628 case SerializationUID::JS_UINT8_ARRAY: { 1629 target = env->GetUint8ArrayFunction(); 1630 break; 1631 } 1632 case SerializationUID::JS_UINT8_CLAMPED_ARRAY: { 1633 target = env->GetUint8ClampedArrayFunction(); 1634 break; 1635 } 1636 case SerializationUID::JS_INT16_ARRAY: { 1637 target = env->GetInt16ArrayFunction(); 1638 break; 1639 } 1640 case SerializationUID::JS_UINT16_ARRAY: { 1641 target = env->GetUint16ArrayFunction(); 1642 break; 1643 } 1644 case SerializationUID::JS_INT32_ARRAY: { 1645 target = env->GetInt32ArrayFunction(); 1646 break; 1647 } 1648 case SerializationUID::JS_UINT32_ARRAY: { 1649 target = env->GetUint32ArrayFunction(); 1650 break; 1651 } 1652 case SerializationUID::JS_FLOAT32_ARRAY: { 1653 target = env->GetFloat32ArrayFunction(); 1654 break; 1655 } 1656 case SerializationUID::JS_FLOAT64_ARRAY: { 1657 target = env->GetFloat64ArrayFunction(); 1658 break; 1659 } 1660 case SerializationUID::JS_BIGINT64_ARRAY: { 1661 target = env->GetBigInt64ArrayFunction(); 1662 break; 1663 } 1664 case SerializationUID::JS_BIGUINT64_ARRAY: { 1665 target = env->GetBigUint64ArrayFunction(); 1666 break; 1667 } 1668 default: 1669 LOG_ECMA(FATAL) << "this branch is unreachable"; 1670 UNREACHABLE(); 1671 } 1672 JSHandle<JSTypedArray> typedArray = 1673 JSHandle<JSTypedArray>::Cast(factory_->NewJSObjectByConstructor(JSHandle<JSFunction>(target))); 1674 obj = JSHandle<JSObject>::Cast(typedArray); 1675 objTag = JSHandle<JSTaggedValue>::Cast(obj); 1676 referenceMap_.emplace(objectId_++, objTag); 1677 if (!JudgeType(SerializationUID::JS_PLAIN_OBJECT) || !DefinePropertiesAndElements(objTag)) { 1678 return JSHandle<JSTaggedValue>(); 1679 } 1680 1681 bool isViewedArrayBuffer = false; 1682 if (!ReadBoolean(&isViewedArrayBuffer)) { 1683 return JSHandle<JSTaggedValue>(); 1684 } 1685 JSHandle<JSTaggedValue> viewedArrayBufferOrByteArray; 1686 if (isViewedArrayBuffer) { 1687 viewedArrayBufferOrByteArray = DeserializeJSTaggedValue(); 1688 } else { 1689 if (!JudgeType(SerializationUID::BYTE_ARRAY)) { 1690 return JSHandle<JSTaggedValue>(); 1691 } 1692 viewedArrayBufferOrByteArray = ReadByteArray(); 1693 } 1694 if (viewedArrayBufferOrByteArray.IsEmpty()) { 1695 return JSHandle<JSTaggedValue>(); 1696 } 1697 typedArray->SetViewedArrayBufferOrByteArray(thread_, viewedArrayBufferOrByteArray); 1698 1699 JSHandle<JSTaggedValue> typedArrayName = DeserializeJSTaggedValue(); 1700 if (typedArrayName.IsEmpty()) { 1701 return JSHandle<JSTaggedValue>(); 1702 } 1703 typedArray->SetTypedArrayName(thread_, typedArrayName); 1704 1705 JSTaggedValue byteLength; 1706 if (!ReadJSTaggedValue(&byteLength) || !byteLength.IsNumber()) { 1707 return JSHandle<JSTaggedValue>(); 1708 } 1709 typedArray->SetByteLength(byteLength.GetNumber()); 1710 1711 JSTaggedValue byteOffset; 1712 if (!ReadJSTaggedValue(&byteOffset) || !byteOffset.IsNumber()) { 1713 return JSHandle<JSTaggedValue>(); 1714 } 1715 typedArray->SetByteOffset(byteOffset.GetNumber()); 1716 1717 JSTaggedValue arrayLength; 1718 if (!ReadJSTaggedValue(&arrayLength) || !byteOffset.IsNumber()) { 1719 return JSHandle<JSTaggedValue>(); 1720 } 1721 typedArray->SetArrayLength(arrayLength.GetNumber()); 1722 1723 ContentType *contentType = reinterpret_cast<ContentType*>(GetBuffer(sizeof(ContentType))); 1724 if (contentType == nullptr) { 1725 return JSHandle<JSTaggedValue>(); 1726 } 1727 typedArray->SetContentType(*contentType); 1728 return objTag; 1729 } 1730 ReadJSNativePointer()1731 JSHandle<JSTaggedValue> JSDeserializer::ReadJSNativePointer() 1732 { 1733 uintptr_t externalPtr; 1734 if (!ReadNativePointer(&externalPtr)) { 1735 return JSHandle<JSTaggedValue>(); 1736 } 1737 uintptr_t deleter; 1738 if (!ReadNativePointer(&deleter)) { 1739 return JSHandle<JSTaggedValue>(); 1740 } 1741 uintptr_t allocatorPtr; 1742 if (!ReadNativePointer(&allocatorPtr)) { 1743 return JSHandle<JSTaggedValue>(); 1744 } 1745 int32_t bindingSize; 1746 if (!JudgeType(SerializationUID::INT32) || !ReadInt(&bindingSize)) { 1747 return JSHandle<JSTaggedValue>(); 1748 } 1749 JSHandle<JSNativePointer> np = factory_->NewJSNativePointer(ToVoidPtr(externalPtr), 1750 reinterpret_cast<DeleteEntryPoint>(deleter), 1751 ToVoidPtr(allocatorPtr), 1752 false, 1753 bindingSize); 1754 return JSHandle<JSTaggedValue>::Cast(np); 1755 } 1756 ReadJSArrayBuffer(SerializationUID uid)1757 JSHandle<JSTaggedValue> JSDeserializer::ReadJSArrayBuffer(SerializationUID uid) 1758 { 1759 bool withNativeAreaAllocator; 1760 if (!ReadBoolean(&withNativeAreaAllocator)) { 1761 return JSHandle<JSTaggedValue>(); 1762 } 1763 // read access length 1764 int32_t arrayLength; 1765 if (!JudgeType(SerializationUID::INT32) || !ReadInt(&arrayLength)) { 1766 return JSHandle<JSTaggedValue>(); 1767 } 1768 // read access shared 1769 bool shared = (uid == SerializationUID::JS_SHARED_ARRAY_BUFFER); 1770 1771 JSHandle<JSArrayBuffer> arrayBuffer; 1772 if (arrayLength == 0) { 1773 // create an empty arrayBuffer 1774 arrayBuffer = factory_->NewJSArrayBuffer(0); 1775 arrayBuffer->SetShared(shared); 1776 } else { 1777 if (shared) { 1778 uint64_t *bufferAddr = reinterpret_cast<uint64_t*>(GetBuffer(sizeof(uint64_t))); 1779 void *bufferData = ToVoidPtr(*bufferAddr); 1780 arrayBuffer = factory_->NewJSSharedArrayBuffer(bufferData, arrayLength); 1781 } else if (uid == SerializationUID::JS_TRANSFER_ARRAY_BUFFER) { 1782 JSHandle<JSTaggedValue> np = ReadJSNativePointer(); 1783 if (np.IsEmpty()) { 1784 return JSHandle<JSTaggedValue>(); 1785 } 1786 arrayBuffer = factory_->NewJSArrayBuffer(0); 1787 arrayBuffer->Attach(thread_, arrayLength, np.GetTaggedValue(), withNativeAreaAllocator); 1788 } else { 1789 void *fromBuffer = GetBuffer(arrayLength); 1790 if (fromBuffer == nullptr) { 1791 return JSHandle<JSTaggedValue>(); 1792 } 1793 arrayBuffer = factory_->NewJSArrayBuffer(arrayLength); 1794 JSNativePointer* np = JSNativePointer::Cast(arrayBuffer->GetArrayBufferData().GetTaggedObject()); 1795 void *toBuffer = np->GetExternalPointer(); 1796 if (memcpy_s(toBuffer, arrayLength, fromBuffer, arrayLength) != EOK) { 1797 LOG_ECMA(FATAL) << "this branch is unreachable"; 1798 UNREACHABLE(); 1799 } 1800 } 1801 } 1802 1803 arrayBuffer->SetWithNativeAreaAllocator(withNativeAreaAllocator); 1804 JSHandle<JSTaggedValue> arrayBufferTag = JSHandle<JSTaggedValue>::Cast(arrayBuffer); 1805 referenceMap_.emplace(objectId_++, arrayBufferTag); 1806 // read jsarraybuffer properties 1807 if (!JudgeType(SerializationUID::JS_PLAIN_OBJECT) || !DefinePropertiesAndElements(arrayBufferTag)) { 1808 return JSHandle<JSTaggedValue>(); 1809 } 1810 1811 return arrayBufferTag; 1812 } 1813 ReadJSTaggedValue(JSTaggedValue * value)1814 bool JSDeserializer::ReadJSTaggedValue(JSTaggedValue *value) 1815 { 1816 size_t len = sizeof(JSTaggedValue); 1817 if (len > static_cast<size_t>(end_ - position_)) { 1818 return false; 1819 } 1820 if (memcpy_s(value, len, position_, len) != EOK) { 1821 LOG_ECMA(FATAL) << "this branch is unreachable"; 1822 UNREACHABLE(); 1823 } 1824 position_ += len; 1825 return true; 1826 } 1827 ReadNativePointer(uintptr_t * value)1828 bool JSDeserializer::ReadNativePointer(uintptr_t *value) 1829 { 1830 size_t len = sizeof(uintptr_t); 1831 if (len > static_cast<size_t>(end_ - position_)) { 1832 return false; 1833 } 1834 if (memcpy_s(value, len, position_, len) != EOK) { 1835 LOG_ECMA(FATAL) << "this branch is unreachable"; 1836 UNREACHABLE(); 1837 } 1838 position_ += len; 1839 return true; 1840 } 1841 GetBuffer(uint32_t bufferSize)1842 void *JSDeserializer::GetBuffer(uint32_t bufferSize) 1843 { 1844 const uint8_t *buffer = nullptr; 1845 if (bufferSize > static_cast<size_t>(end_ - position_)) { 1846 return nullptr; 1847 } 1848 buffer = position_; 1849 position_ += bufferSize; 1850 uint8_t *retBuffer = const_cast<uint8_t *>(buffer); 1851 return static_cast<void *>(retBuffer); 1852 } 1853 ReadReference()1854 JSHandle<JSTaggedValue> JSDeserializer::ReadReference() 1855 { 1856 uint64_t objId; 1857 if (!ReadObjectId(&objId)) { 1858 return JSHandle<JSTaggedValue>(); 1859 } 1860 auto objIter = referenceMap_.find(objId); 1861 if (objIter == referenceMap_.end()) { 1862 return JSHandle<JSTaggedValue>(); 1863 } 1864 return objIter->second; 1865 } 1866 JudgeType(SerializationUID targetUid)1867 bool JSDeserializer::JudgeType(SerializationUID targetUid) 1868 { 1869 if (ReadType() != targetUid) { 1870 return false; 1871 } 1872 return true; 1873 } 1874 DefinePropertiesAndElements(const JSHandle<JSTaggedValue> & obj)1875 bool JSDeserializer::DefinePropertiesAndElements(const JSHandle<JSTaggedValue> &obj) 1876 { 1877 int32_t propertyLength; 1878 if (!JudgeType(SerializationUID::INT32) || !ReadInt(&propertyLength)) { 1879 return false; 1880 } 1881 for (int32_t i = 0; i < propertyLength; i++) { 1882 JSHandle<JSTaggedValue> key = DeserializeJSTaggedValue(); 1883 if (key.IsEmpty()) { 1884 return false; 1885 } 1886 PropertyDescriptor desc(thread_); 1887 if (!ReadDesc(&desc)) { 1888 return false; 1889 } 1890 if (!JSTaggedValue::DefineOwnProperty(thread_, obj, key, desc)) { 1891 return false; 1892 } 1893 } 1894 1895 int32_t elementLength; 1896 if (!JudgeType(SerializationUID::INT32) || !ReadInt(&elementLength)) { 1897 return false; 1898 } 1899 for (int32_t i = 0; i < elementLength; i++) { 1900 JSHandle<JSTaggedValue> key = DeserializeJSTaggedValue(); 1901 if (key.IsEmpty()) { 1902 return false; 1903 } 1904 PropertyDescriptor desc(thread_); 1905 if (!ReadDesc(&desc)) { 1906 return false; 1907 } 1908 if (!JSTaggedValue::DefineOwnProperty(thread_, obj, key, desc)) { 1909 return false; 1910 } 1911 } 1912 return true; 1913 } 1914 ReadDesc(PropertyDescriptor * desc)1915 bool JSDeserializer::ReadDesc(PropertyDescriptor *desc) 1916 { 1917 bool isWritable = false; 1918 if (!ReadBoolean(&isWritable)) { 1919 return false; 1920 } 1921 bool isEnumerable = false; 1922 if (!ReadBoolean(&isEnumerable)) { 1923 return false; 1924 } 1925 bool isConfigurable = false; 1926 if (!ReadBoolean(&isConfigurable)) { 1927 return false; 1928 } 1929 bool hasWritable = false; 1930 if (!ReadBoolean(&hasWritable)) { 1931 return false; 1932 } 1933 bool hasEnumerable = false; 1934 if (!ReadBoolean(&hasEnumerable)) { 1935 return false; 1936 } 1937 bool hasConfigurable = false; 1938 if (!ReadBoolean(&hasConfigurable)) { 1939 return false; 1940 } 1941 JSHandle<JSTaggedValue> value = DeserializeJSTaggedValue(); 1942 if (value.IsEmpty()) { 1943 return false; 1944 } 1945 desc->SetValue(value); 1946 if (hasWritable) { 1947 desc->SetWritable(isWritable); 1948 } 1949 if (hasEnumerable) { 1950 desc->SetEnumerable(isEnumerable); 1951 } 1952 if (hasConfigurable) { 1953 desc->SetConfigurable(isConfigurable); 1954 } 1955 return true; 1956 } 1957 ReadBoolean(bool * value)1958 bool JSDeserializer::ReadBoolean(bool *value) 1959 { 1960 SerializationUID uid = ReadType(); 1961 if (uid == SerializationUID::C_TRUE) { 1962 *value = true; 1963 return true; 1964 } 1965 if (uid == SerializationUID::C_FALSE) { 1966 *value = false; 1967 return true; 1968 } 1969 return false; 1970 } 1971 WriteValue(JSThread * thread,const JSHandle<JSTaggedValue> & value,const JSHandle<JSTaggedValue> & transfer)1972 bool Serializer::WriteValue( 1973 JSThread *thread, const JSHandle<JSTaggedValue> &value, const JSHandle<JSTaggedValue> &transfer) 1974 { 1975 if (data_ != nullptr) { 1976 return false; 1977 } 1978 data_.reset(new SerializationData); 1979 if (!PrepareTransfer(thread, transfer)) { 1980 return false; 1981 } 1982 if (!valueSerializer_.SerializeJSTaggedValue(value)) { 1983 return false; 1984 } 1985 // clear transfer obj set after serialization 1986 valueSerializer_.ClearTransferSet(); 1987 std::pair<uint8_t*, size_t> pair = valueSerializer_.ReleaseBuffer(); 1988 data_->value_.reset(pair.first); 1989 data_->dataSize_ = pair.second; 1990 return true; 1991 } 1992 Release()1993 std::unique_ptr<SerializationData> Serializer::Release() 1994 { 1995 return std::move(data_); 1996 } 1997 PrepareTransfer(JSThread * thread,const JSHandle<JSTaggedValue> & transfer)1998 bool Serializer::PrepareTransfer(JSThread *thread, const JSHandle<JSTaggedValue> &transfer) 1999 { 2000 if (transfer->IsUndefined()) { 2001 return true; 2002 } 2003 if (!transfer->IsJSArray()) { 2004 return false; 2005 } 2006 int len = base::ArrayHelper::GetArrayLength(thread, transfer); 2007 int k = 0; 2008 CUnorderedSet<uintptr_t> transferDataSet; 2009 while (k < len) { 2010 bool exists = JSTaggedValue::HasProperty(thread, transfer, k); 2011 if (exists) { 2012 JSHandle<JSTaggedValue> element = JSArray::FastGetPropertyByValue(thread, transfer, k); 2013 if (!element->IsArrayBuffer()) { 2014 return false; 2015 } 2016 transferDataSet.insert(static_cast<uintptr_t>(element.GetTaggedType())); 2017 } 2018 k++; 2019 } 2020 valueSerializer_.InitTransferSet(std::move(transferDataSet)); 2021 return true; 2022 } 2023 ReadValue()2024 JSHandle<JSTaggedValue> Deserializer::ReadValue() 2025 { 2026 return valueDeserializer_.Deserialize(); 2027 } 2028 } // namespace panda::ecmascript 2029