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