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