• 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