• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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