• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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 #include <malloc.h>
19 #include <vector>
20 
21 #include "ecmascript/base/array_helper.h"
22 #include "ecmascript/global_env.h"
23 #include "ecmascript/js_array.h"
24 #include "ecmascript/js_arraybuffer.h"
25 #include "ecmascript/js_hclass.h"
26 #include "ecmascript/js_regexp.h"
27 #include "ecmascript/js_set.h"
28 #include "ecmascript/js_typed_array.h"
29 #include "ecmascript/linked_hash_table-inl.h"
30 #include "libpandabase/mem/mem.h"
31 #include "securec.h"
32 
33 namespace panda::ecmascript {
34 constexpr size_t INITIAL_CAPACITY = 64;
35 constexpr int CAPACITY_INCREASE_RATE = 2;
36 
WriteType(SerializationUID id)37 bool JSSerializer::WriteType(SerializationUID id)
38 {
39     uint8_t rawId = static_cast<uint8_t>(id);
40     return WriteRawData(&rawId, sizeof(rawId));
41 }
42 
43 // Write JSTaggedValue could be either a pointer to a HeapObject or a value
SerializeJSTaggedValue(const JSHandle<JSTaggedValue> & value)44 bool JSSerializer::SerializeJSTaggedValue(const JSHandle<JSTaggedValue> &value)
45 {
46     [[maybe_unused]] EcmaHandleScope scope(thread_);
47     if (!value->IsHeapObject()) {
48         if (!WritePrimitiveValue(value)) {
49             return false;
50         }
51     } else {
52         if (!WriteTaggedObject(value)) {
53             return false;
54         }
55     }
56     return true;
57 }
58 
59 // Write JSTaggedValue that is pure value
WritePrimitiveValue(const JSHandle<JSTaggedValue> & value)60 bool JSSerializer::WritePrimitiveValue(const JSHandle<JSTaggedValue> &value)
61 {
62     if (value->IsNull()) {
63         return WriteType(SerializationUID::JS_NULL);
64     }
65     if (value->IsUndefined()) {
66         return WriteType(SerializationUID::JS_UNDEFINED);
67     }
68     if (value->IsTrue()) {
69         return WriteType(SerializationUID::JS_TRUE);
70     }
71     if (value->IsFalse()) {
72         return WriteType(SerializationUID::JS_FALSE);
73     }
74     if (value->IsInt()) {
75         return WriteInt(value->GetInt());
76     }
77     if (value->IsDouble()) {
78         return WriteDouble(value->GetDouble());
79     }
80     if (value->IsHole()) {
81         return WriteType(SerializationUID::HOLE);
82     }
83     return false;
84 }
85 
WriteInt(int32_t value)86 bool JSSerializer::WriteInt(int32_t value)
87 {
88     size_t oldSize = bufferSize_;
89     if (!WriteType(SerializationUID::INT32)) {
90         return false;
91     }
92     if (!WriteRawData(&value, sizeof(value))) {
93         bufferSize_ = oldSize;
94         return false;
95     }
96     return true;
97 }
98 
WriteDouble(double value)99 bool JSSerializer::WriteDouble(double value)
100 {
101     size_t oldSize = bufferSize_;
102     if (!WriteType(SerializationUID::DOUBLE)) {
103         return false;
104     }
105     if (!WriteRawData(&value, sizeof(value))) {
106         bufferSize_ = oldSize;
107         return false;
108     }
109     return true;
110 }
111 
WriteBoolean(bool value)112 bool JSSerializer::WriteBoolean(bool value)
113 {
114     if (value) {
115         return WriteType(SerializationUID::C_TRUE);
116     }
117     return WriteType(SerializationUID::C_FALSE);
118 }
119 
WriteRawData(const void * data,size_t length)120 bool JSSerializer::WriteRawData(const void *data, size_t length)
121 {
122     if (length <= 0) {
123         return false;
124     }
125     if ((bufferSize_ + length) > bufferCapacity_) {
126         if (!AllocateBuffer(length)) {
127             return false;
128         }
129     }
130     if (memcpy_s(buffer_ + bufferSize_, bufferCapacity_ - bufferSize_, data, length) != EOK) {
131         LOG(ERROR, RUNTIME) << "Failed to memcpy_s Data";
132         return false;
133     }
134     bufferSize_ += length;
135     return true;
136 }
137 
AllocateBuffer(size_t bytes)138 bool JSSerializer::AllocateBuffer(size_t bytes)
139 {
140     // Get internal heap size
141     if (sizeLimit_ == 0) {
142         uint64_t heapSize = thread_->GetEcmaVM()->GetJSOptions().GetInternalMemorySizeLimit();
143         sizeLimit_ = heapSize;
144     }
145     size_t oldSize = bufferSize_;
146     size_t newSize = oldSize + bytes;
147     if (newSize > sizeLimit_) {
148         return false;
149     }
150     if (bufferCapacity_ == 0) {
151         if (bytes < INITIAL_CAPACITY) {
152             buffer_ = reinterpret_cast<uint8_t *>(malloc(INITIAL_CAPACITY));
153             if (buffer_ != nullptr) {
154                 bufferCapacity_ = INITIAL_CAPACITY;
155                 return true;
156             } else {
157                 return false;
158             }
159         } else {
160             buffer_ = reinterpret_cast<uint8_t *>(malloc(bytes));
161             if (buffer_ != nullptr) {
162                 bufferCapacity_ = bytes;
163                 return true;
164             } else {
165                 return false;
166             }
167         }
168     }
169     if (newSize > bufferCapacity_) {
170         if (!ExpandBuffer(newSize)) {
171             return false;
172         }
173     }
174     return true;
175 }
176 
ExpandBuffer(size_t requestedSize)177 bool JSSerializer::ExpandBuffer(size_t requestedSize)
178 {
179     size_t newCapacity = bufferCapacity_ * CAPACITY_INCREASE_RATE;
180     newCapacity = std::max(newCapacity, requestedSize);
181     if (newCapacity > sizeLimit_) {
182         return false;
183     }
184     uint8_t *newBuffer = reinterpret_cast<uint8_t *>(malloc(newCapacity));
185     if (newBuffer == nullptr) {
186         return false;
187     }
188     if (memcpy_s(newBuffer, newCapacity, buffer_, bufferSize_) != EOK) {
189         LOG(ERROR, RUNTIME) << "Failed to memcpy_s Data";
190         free(newBuffer);
191         return false;
192     }
193     free(buffer_);
194     buffer_ = newBuffer;
195     bufferCapacity_ = newCapacity;
196     return true;
197 }
198 
199 // Transfer ownership of buffer, should not use this Serializer after release
ReleaseBuffer()200 std::pair<uint8_t *, size_t> JSSerializer::ReleaseBuffer()
201 {
202     auto res = std::make_pair(buffer_, bufferSize_);
203     buffer_ = nullptr;
204     bufferSize_ = 0;
205     bufferCapacity_ = 0;
206     objectId_ = 0;
207     return res;
208 }
209 
IsSerialized(uintptr_t addr) const210 bool JSSerializer::IsSerialized(uintptr_t addr) const
211 {
212     if (referenceMap_.find(addr) != referenceMap_.end()) {
213         return true;
214     }
215     return false;
216 }
217 
WriteIfSerialized(uintptr_t addr)218 bool JSSerializer::WriteIfSerialized(uintptr_t addr)
219 {
220     size_t oldSize = bufferSize_;
221     auto iter = referenceMap_.find(addr);
222     if (iter == referenceMap_.end()) {
223         return false;
224     }
225     uint64_t id = iter->second;
226     if (!WriteType(SerializationUID::TAGGED_OBJECT_REFERNCE)) {
227         return false;
228     }
229     if (!WriteRawData(&id, sizeof(uint64_t))) {
230         bufferSize_ = oldSize;
231         return false;
232     }
233     return true;
234 }
235 
236 // Write HeapObject
WriteTaggedObject(const JSHandle<JSTaggedValue> & value)237 bool JSSerializer::WriteTaggedObject(const JSHandle<JSTaggedValue> &value)
238 {
239     uintptr_t addr = reinterpret_cast<uintptr_t>(value.GetTaggedValue().GetTaggedObject());
240     bool serialized = IsSerialized(addr);
241     if (serialized) {
242         return WriteIfSerialized(addr);
243     }
244     referenceMap_.insert(std::pair(addr, objectId_));
245     objectId_++;
246 
247     TaggedObject *taggedObject = value->GetTaggedObject();
248     JSType type = taggedObject->GetClass()->GetObjectType();
249     switch (type) {
250         case JSType::JS_ERROR:
251         case JSType::JS_EVAL_ERROR:
252         case JSType::JS_RANGE_ERROR:
253         case JSType::JS_REFERENCE_ERROR:
254         case JSType::JS_TYPE_ERROR:
255         case JSType::JS_URI_ERROR:
256         case JSType::JS_SYNTAX_ERROR:
257             return WriteJSError(value);
258         case JSType::JS_DATE:
259             return WriteJSDate(value);
260         case JSType::JS_ARRAY:
261             return WriteJSArray(value);
262         case JSType::JS_MAP:
263             return WriteJSMap(value);
264         case JSType::JS_SET:
265             return WriteJSSet(value);
266         case JSType::JS_REG_EXP:
267             return WriteJSRegExp(value);
268         case JSType::JS_INT8_ARRAY:
269             return WriteJSTypedArray(value, SerializationUID::JS_INT8_ARRAY);
270         case JSType::JS_UINT8_ARRAY:
271             return WriteJSTypedArray(value, SerializationUID::JS_UINT8_ARRAY);
272         case JSType::JS_UINT8_CLAMPED_ARRAY:
273             return WriteJSTypedArray(value, SerializationUID::JS_UINT8_CLAMPED_ARRAY);
274         case JSType::JS_INT16_ARRAY:
275             return WriteJSTypedArray(value, SerializationUID::JS_INT16_ARRAY);
276         case JSType::JS_UINT16_ARRAY:
277             return WriteJSTypedArray(value, SerializationUID::JS_UINT16_ARRAY);
278         case JSType::JS_INT32_ARRAY:
279             return WriteJSTypedArray(value, SerializationUID::JS_INT32_ARRAY);
280         case JSType::JS_UINT32_ARRAY:
281             return WriteJSTypedArray(value, SerializationUID::JS_UINT32_ARRAY);
282         case JSType::JS_FLOAT32_ARRAY:
283             return WriteJSTypedArray(value, SerializationUID::JS_FLOAT32_ARRAY);
284         case JSType::JS_FLOAT64_ARRAY:
285             return WriteJSTypedArray(value, SerializationUID::JS_FLOAT64_ARRAY);
286         case JSType::JS_ARRAY_BUFFER:
287             return WriteJSArrayBuffer(value);
288         case JSType::STRING:
289             return WriteEcmaString(value);
290         case JSType::JS_OBJECT:
291             return WritePlainObject(value);
292         default:
293             break;
294     }
295     return false;
296 }
297 
WriteJSError(const JSHandle<JSTaggedValue> & value)298 bool JSSerializer::WriteJSError(const JSHandle<JSTaggedValue> &value)
299 {
300     size_t oldSize = bufferSize_;
301     TaggedObject *taggedObject = value->GetTaggedObject();
302     JSType errorType = taggedObject->GetClass()->GetObjectType();
303     if (!WriteJSErrorHeader(errorType)) {
304         return false;
305     }
306     auto globalConst = thread_->GlobalConstants();
307     JSHandle<JSTaggedValue> handleMsg = globalConst->GetHandledMessageString();
308     JSHandle<JSTaggedValue> msg = JSObject::GetProperty(thread_, value, handleMsg).GetValue();
309     // Write error message
310     if (!SerializeJSTaggedValue(msg)) {
311         bufferSize_ = oldSize;
312         return false;
313     }
314     return true;
315 }
316 
WriteJSErrorHeader(JSType type)317 bool JSSerializer::WriteJSErrorHeader(JSType type)
318 {
319     switch (type) {
320         case JSType::JS_ERROR:
321             return WriteType(SerializationUID::JS_ERROR);
322         case JSType::JS_EVAL_ERROR:
323             return WriteType(SerializationUID::EVAL_ERROR);
324         case JSType::JS_RANGE_ERROR:
325             return WriteType(SerializationUID::RANGE_ERROR);
326         case JSType::JS_REFERENCE_ERROR:
327             return WriteType(SerializationUID::REFERENCE_ERROR);
328         case JSType::JS_TYPE_ERROR:
329             return WriteType(SerializationUID::TYPE_ERROR);
330         case JSType::JS_URI_ERROR:
331             return WriteType(SerializationUID::URI_ERROR);
332         case JSType::JS_SYNTAX_ERROR:
333             return WriteType(SerializationUID::SYNTAX_ERROR);
334         default:
335             UNREACHABLE();
336     }
337     return false;
338 }
339 
WriteJSDate(const JSHandle<JSTaggedValue> & value)340 bool JSSerializer::WriteJSDate(const JSHandle<JSTaggedValue> &value)
341 {
342     JSHandle<JSDate> date = JSHandle<JSDate>::Cast(value);
343     size_t oldSize = bufferSize_;
344     if (!WriteType(SerializationUID::JS_DATE)) {
345         return false;
346     }
347     if (!WritePlainObject(value)) {
348         bufferSize_ = oldSize;
349         return false;
350     }
351     double timeValue = date->GetTimeValue().GetDouble();
352     if (!WriteDouble(timeValue)) {
353         bufferSize_ = oldSize;
354         return false;
355     }
356     double localOffset = date->GetLocalOffset().GetDouble();
357     if (!WriteDouble(localOffset)) {
358         bufferSize_ = oldSize;
359         return false;
360     }
361     return true;
362 }
363 
WriteJSArray(const JSHandle<JSTaggedValue> & value)364 bool JSSerializer::WriteJSArray(const JSHandle<JSTaggedValue> &value)
365 {
366     JSHandle<JSArray> array = JSHandle<JSArray>::Cast(value);
367     size_t oldSize = bufferSize_;
368     if (!WriteType(SerializationUID::JS_ARRAY)) {
369         return false;
370     }
371     if (!WritePlainObject(value)) {
372         bufferSize_ = oldSize;
373         return false;
374     }
375     uint32_t arrayLength = static_cast<uint32_t>(array->GetLength().GetInt());
376     if (!WriteInt(arrayLength)) {
377         bufferSize_ = oldSize;
378         return false;
379     }
380     return true;
381 }
382 
WriteEcmaString(const JSHandle<JSTaggedValue> & value)383 bool JSSerializer::WriteEcmaString(const JSHandle<JSTaggedValue> &value)
384 {
385     JSHandle<EcmaString> string = JSHandle<EcmaString>::Cast(value);
386     size_t oldSize = bufferSize_;
387     if (!WriteType(SerializationUID::ECMASTRING)) {
388         return false;
389     }
390     size_t length = string->GetLength();
391     if (!WriteInt(static_cast<int32_t>(length))) {
392         bufferSize_ = oldSize;
393         return false;
394     }
395     // skip writeRawData for empty EcmaString
396     if (length == 0) {
397         return true;
398     }
399     const uint8_t *data = string->GetDataUtf8();
400     const uint8_t strEnd = '\0';
401     if (!WriteRawData(data, length) || !WriteRawData(&strEnd, sizeof(uint8_t))) {
402         bufferSize_ = oldSize;
403         return false;
404     }
405     return true;
406 }
407 
WriteJSMap(const JSHandle<JSTaggedValue> & value)408 bool JSSerializer::WriteJSMap(const JSHandle<JSTaggedValue> &value)
409 {
410     JSHandle<JSMap> map = JSHandle<JSMap>::Cast(value);
411     size_t oldSize = bufferSize_;
412     if (!WriteType(SerializationUID::JS_MAP)) {
413         return false;
414     }
415     if (!WritePlainObject(value)) {
416         bufferSize_ = oldSize;
417         return false;
418     }
419     int size = map->GetSize();
420     if (!WriteInt(size)) {
421         bufferSize_ = oldSize;
422         return false;
423     }
424     for (int i = 0; i < size; i++) {
425         JSHandle<JSTaggedValue> key(thread_, map->GetKey(i));
426         if (!SerializeJSTaggedValue(key)) {
427             bufferSize_ = oldSize;
428             return false;
429         }
430         JSHandle<JSTaggedValue> val(thread_, map->GetValue(i));
431         if (!SerializeJSTaggedValue(val)) {
432             bufferSize_ = oldSize;
433             return false;
434         }
435     }
436     return true;
437 }
438 
WriteJSSet(const JSHandle<JSTaggedValue> & value)439 bool JSSerializer::WriteJSSet(const JSHandle<JSTaggedValue> &value)
440 {
441     JSHandle<JSSet> set = JSHandle<JSSet>::Cast(value);
442     size_t oldSize = bufferSize_;
443     if (!WriteType(SerializationUID::JS_SET)) {
444         return false;
445     }
446     if (!WritePlainObject(value)) {
447         bufferSize_ = oldSize;
448         return false;
449     }
450     int size = set->GetSize();
451     if (!WriteInt(size)) {
452         bufferSize_ = oldSize;
453         return false;
454     }
455     for (int i = 0; i < size; i++) {
456         JSHandle<JSTaggedValue> val(thread_, set->GetValue(i));
457         if (!SerializeJSTaggedValue(val)) {
458             bufferSize_ = oldSize;
459             return false;
460         }
461     }
462     return true;
463 }
464 
WriteJSRegExp(const JSHandle<JSTaggedValue> & value)465 bool JSSerializer::WriteJSRegExp(const JSHandle<JSTaggedValue> &value)
466 {
467     JSHandle<JSRegExp> regExp = JSHandle<JSRegExp>::Cast(value);
468     size_t oldSize = bufferSize_;
469     if (!WriteType(SerializationUID::JS_REG_EXP)) {
470         return false;
471     }
472     if (!WritePlainObject(value)) {
473         bufferSize_ = oldSize;
474         return false;
475     }
476     uint32_t bufferSize = regExp->GetLength();
477     if (!WriteInt(static_cast<int32_t>(bufferSize))) {
478         bufferSize_ = oldSize;
479         return false;
480     }
481     // Write Accessor(ByteCodeBuffer) which is a pointer to a Dynbuffer
482     JSHandle<JSTaggedValue> bufferValue(thread_, regExp->GetByteCodeBuffer());
483     JSHandle<JSNativePointer> np = JSHandle<JSNativePointer>::Cast(bufferValue);
484     void *dynBuffer = np->GetExternalPointer();
485     if (!WriteRawData(dynBuffer, bufferSize)) {
486         bufferSize_ = oldSize;
487         return false;
488     }
489     // Write Accessor(OriginalSource)
490     JSHandle<JSTaggedValue> originalSource(thread_, regExp->GetOriginalSource());
491     if (!SerializeJSTaggedValue(originalSource)) {
492         bufferSize_ = oldSize;
493         return false;
494     }
495     // Write Accessor(OriginalFlags)
496     JSHandle<JSTaggedValue> originalFlags(thread_, regExp->GetOriginalFlags());
497     if (!SerializeJSTaggedValue(originalFlags)) {
498         bufferSize_ = oldSize;
499         return false;
500     }
501     return true;
502 }
503 
WriteJSTypedArray(const JSHandle<JSTaggedValue> & value,SerializationUID uId)504 bool JSSerializer::WriteJSTypedArray(const JSHandle<JSTaggedValue> &value, SerializationUID uId)
505 {
506     JSHandle<JSTypedArray> typedArray = JSHandle<JSTypedArray>::Cast(value);
507     size_t oldSize = bufferSize_;
508     if (!WriteType(uId)) {
509         return false;
510     }
511     if (!WritePlainObject(value)) {
512         bufferSize_ = oldSize;
513         return false;
514     }
515     // Write ACCESSORS(ViewedArrayBuffer) which is a pointer to an ArrayBuffer
516     JSHandle<JSTaggedValue> viewedArrayBuffer(thread_, typedArray->GetViewedArrayBuffer());
517     if (!WriteJSArrayBuffer(viewedArrayBuffer)) {
518         bufferSize_ = oldSize;
519         return false;
520     }
521     // Write ACCESSORS(TypedArrayName)
522     JSHandle<JSTaggedValue> typedArrayName(thread_, typedArray->GetTypedArrayName());
523     if (!SerializeJSTaggedValue(typedArrayName)) {
524         bufferSize_ = oldSize;
525         return false;
526     }
527     // Write ACCESSORS(ByteLength)
528     JSTaggedValue byteLength = typedArray->GetByteLength();
529     if (!WriteRawData(&byteLength, sizeof(JSTaggedValue))) {
530         bufferSize_ = oldSize;
531         return false;
532     }
533     // Write ACCESSORS(ByteOffset)
534     JSTaggedValue byteOffset = typedArray->GetByteOffset();
535     if (!WriteRawData(&byteOffset, sizeof(JSTaggedValue))) {
536         bufferSize_ = oldSize;
537         return false;
538     }
539     // Write ACCESSORS(ArrayLength)
540     JSTaggedValue arrayLength = typedArray->GetArrayLength();
541     if (!WriteRawData(&arrayLength, sizeof(JSTaggedValue))) {
542         bufferSize_ = oldSize;
543         return false;
544     }
545     return true;
546 }
547 
WriteNativeFunctionPointer(const JSHandle<JSTaggedValue> & value)548 bool JSSerializer::WriteNativeFunctionPointer(const JSHandle<JSTaggedValue> &value)
549 {
550     size_t oldSize = bufferSize_;
551     if (!WriteType(SerializationUID::NATIVE_FUNCTION_POINTER)) {
552         return false;
553     }
554     JSTaggedValue pointer = value.GetTaggedValue();
555     if (!WriteRawData(&pointer, sizeof(JSTaggedValue))) {
556         bufferSize_ = oldSize;
557         return false;
558     }
559     return true;
560 }
561 
WriteJSArrayBuffer(const JSHandle<JSTaggedValue> & value)562 bool JSSerializer::WriteJSArrayBuffer(const JSHandle<JSTaggedValue> &value)
563 {
564     size_t oldSize = bufferSize_;
565     JSHandle<JSArrayBuffer> arrayBuffer = JSHandle<JSArrayBuffer>::Cast(value);
566 
567     if (arrayBuffer->IsDetach()) {
568         return false;
569     }
570 
571     if (!WriteType(SerializationUID::JS_ARRAY_BUFFER)) {
572         return false;
573     }
574 
575     // Write Accessors(ArrayBufferByteLength)
576     uint32_t arrayLength = arrayBuffer->GetArrayBufferByteLength();
577     if (!WriteInt(arrayLength)) {
578         bufferSize_ = oldSize;
579         return false;
580     }
581 
582     // write Accessor shared which indicate the C memeory is shared
583     bool shared = arrayBuffer->GetShared();
584     if (!WriteBoolean(shared)) {
585         bufferSize_ = oldSize;
586         return false;
587     }
588 
589     if (shared) {
590         JSHandle<JSNativePointer> np(thread_, arrayBuffer->GetArrayBufferData());
591         void *buffer = np->GetExternalPointer();
592         uint64_t bufferAddr = (uint64_t)buffer;
593         if (!WriteRawData(&bufferAddr, sizeof(uint64_t))) {
594             bufferSize_ = oldSize;
595             return false;
596         }
597     } else {
598         // Write Accessors(ArrayBufferData) which is a pointer to a DynBuffer
599         JSHandle<JSNativePointer> np(thread_, arrayBuffer->GetArrayBufferData());
600         void *buffer = np->GetExternalPointer();
601         if (!WriteRawData(buffer, arrayLength)) {
602             bufferSize_ = oldSize;
603             return false;
604         }
605     }
606 
607     // write obj properties
608     if (!WritePlainObject(value)) {
609         bufferSize_ = oldSize;
610         return false;
611     }
612 
613     return true;
614 }
615 
WritePlainObject(const JSHandle<JSTaggedValue> & objValue)616 bool JSSerializer::WritePlainObject(const JSHandle<JSTaggedValue> &objValue)
617 {
618     JSHandle<JSObject> obj = JSHandle<JSObject>::Cast(objValue);
619     size_t oldSize = bufferSize_;
620     if (!WriteType(SerializationUID::JS_PLAIN_OBJECT)) {
621         return false;
622     }
623     // Get the number of elements stored in obj
624     uint32_t elementsLength = obj->GetNumberOfElements();
625     if (!WriteInt(static_cast<int32_t>(elementsLength))) {
626         bufferSize_ = oldSize;
627         return false;
628     }
629     std::vector<JSTaggedValue> keyVector;
630     JSObject::GetALLElementKeysIntoVector(thread_, obj, keyVector);
631     // Write elements' description attributes and value
632     if (keyVector.size() != elementsLength) {
633         bufferSize_ = oldSize;
634         return false;
635     }
636     for (uint32_t i = 0; i < elementsLength; i++) {
637         JSHandle<JSTaggedValue> key(thread_, keyVector[i]);
638         if (!SerializeJSTaggedValue(key)) {
639             bufferSize_ = oldSize;
640             return false;
641         }
642         PropertyDescriptor desc(thread_);
643         JSObject::OrdinaryGetOwnProperty(thread_, obj, key, desc);
644         if (!WriteDesc(desc)) {
645             bufferSize_ = oldSize;
646             return false;
647         }
648         JSHandle<JSTaggedValue> value = desc.GetValue();
649         if (!SerializeJSTaggedValue(value)) {
650             bufferSize_ = oldSize;
651             return false;
652         }
653     }
654     // Get the number of k-v form properties stored in obj
655     keyVector.clear();
656     uint32_t propertiesLength = obj->GetNumberOfKeys();
657     if (!WriteInt(static_cast<int32_t>(propertiesLength))) {
658         bufferSize_ = oldSize;
659         return false;
660     }
661     JSObject::GetAllKeys(thread_, obj, keyVector);
662     if (keyVector.size() != propertiesLength) {
663         bufferSize_ = oldSize;
664         return false;
665     }
666     // Write keys' description attributes and related values
667     for (uint32_t i = 0; i < propertiesLength; i++) {
668         if (keyVector.empty()) {
669             bufferSize_ = oldSize;
670             return false;
671         }
672         JSHandle<JSTaggedValue> key(thread_, keyVector[i]);
673         if (!SerializeJSTaggedValue(key)) {
674             bufferSize_ = oldSize;
675             return false;
676         }
677         PropertyDescriptor desc(thread_);
678         JSObject::OrdinaryGetOwnProperty(thread_, obj, key, desc);
679         if (!WriteDesc(desc)) {
680             bufferSize_ = oldSize;
681             return false;
682         }
683         JSHandle<JSTaggedValue> value = desc.GetValue();
684         if (!SerializeJSTaggedValue(value)) {
685             bufferSize_ = oldSize;
686             return false;
687         }
688     }
689     return true;
690 }
691 
WriteDesc(const PropertyDescriptor & desc)692 bool JSSerializer::WriteDesc(const PropertyDescriptor &desc)
693 {
694     size_t oldSize = bufferSize_;
695     bool isWritable = desc.IsWritable();
696     if (!WriteBoolean(isWritable)) {
697         bufferSize_ = oldSize;
698         return false;
699     }
700     bool isEnumerable = desc.IsEnumerable();
701     if (!WriteBoolean(isEnumerable)) {
702         bufferSize_ = oldSize;
703         return false;
704     }
705     bool isConfigurable = desc.IsConfigurable();
706     if (!WriteBoolean(isConfigurable)) {
707         bufferSize_ = oldSize;
708         return false;
709     }
710     bool hasWritable = desc.HasWritable();
711     if (!WriteBoolean(hasWritable)) {
712         bufferSize_ = oldSize;
713         return false;
714     }
715     bool hasEnumerable = desc.HasEnumerable();
716     if (!WriteBoolean(hasEnumerable)) {
717         bufferSize_ = oldSize;
718         return false;
719     }
720     bool hasConfigurable = desc.HasConfigurable();
721     if (!WriteBoolean(hasConfigurable)) {
722         bufferSize_ = oldSize;
723         return false;
724     }
725     return true;
726 }
727 
ReadType()728 SerializationUID JSDeserializer::ReadType()
729 {
730     SerializationUID uid;
731     if (position_ >= end_) {
732         return SerializationUID::UNKNOWN;
733     }
734     uid = static_cast<SerializationUID>(*position_);
735     if (uid < SerializationUID::JS_NULL || uid > SerializationUID::NATIVE_FUNCTION_POINTER) {
736         return SerializationUID::UNKNOWN;
737     }
738     position_++;  // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
739     return uid;
740 }
741 
ReadInt(int32_t * value)742 bool JSDeserializer::ReadInt(int32_t *value)
743 {
744     size_t len = sizeof(int32_t);
745     if (len > static_cast<size_t>(end_ - position_)) {
746         return false;
747     }
748     if (memcpy_s(value, len, position_, len) != EOK) {
749         UNREACHABLE();
750     }
751     position_ += len;
752     return true;
753 }
754 
ReadObjectId(uint64_t * objectId)755 bool JSDeserializer::ReadObjectId(uint64_t *objectId)
756 {
757     size_t len = sizeof(uint64_t);
758     if (len > static_cast<size_t>(end_ - position_)) {
759         return false;
760     }
761     if (memcpy_s(objectId, len, position_, len) != EOK) {
762         UNREACHABLE();
763     }
764     position_ += len;
765     return true;
766 }
767 
ReadDouble(double * value)768 bool JSDeserializer::ReadDouble(double *value)
769 {
770     size_t len = sizeof(double);
771     if (len > static_cast<size_t>(end_ - position_)) {
772         return false;
773     }
774     if (memcpy_s(value, len, position_, len) != EOK) {
775         UNREACHABLE();
776     }
777     position_ += len;
778     return true;
779 }
780 
~JSDeserializer()781 JSDeserializer::~JSDeserializer()
782 {
783     free(begin_);
784     begin_ = nullptr;
785 }
786 
DeserializeJSTaggedValue()787 JSHandle<JSTaggedValue> JSDeserializer::DeserializeJSTaggedValue()
788 {
789     SerializationUID uid = ReadType();
790     if (uid == SerializationUID::UNKNOWN) {
791         return JSHandle<JSTaggedValue>();
792     }
793     switch (uid) {
794         case SerializationUID::JS_NULL:
795             return JSHandle<JSTaggedValue>(thread_, JSTaggedValue::Null());
796         case SerializationUID::JS_UNDEFINED:
797             return JSHandle<JSTaggedValue>(thread_, JSTaggedValue::Undefined());
798         case SerializationUID::JS_TRUE:
799             return JSHandle<JSTaggedValue>(thread_, JSTaggedValue::True());
800         case SerializationUID::JS_FALSE:
801             return JSHandle<JSTaggedValue>(thread_, JSTaggedValue::False());
802         case SerializationUID::HOLE:
803             return JSHandle<JSTaggedValue>(thread_, JSTaggedValue::Hole());
804         case SerializationUID::INT32: {
805             int32_t value;
806             if (!ReadInt(&value)) {
807                 return JSHandle<JSTaggedValue>();
808             }
809             return JSHandle<JSTaggedValue>(thread_, JSTaggedValue(value));
810         }
811         case SerializationUID::DOUBLE: {
812             double value;
813             if (!ReadDouble(&value)) {
814                 return JSHandle<JSTaggedValue>();
815             }
816             return JSHandle<JSTaggedValue>(thread_, JSTaggedValue(value));
817         }
818         case SerializationUID::JS_ERROR:
819         case SerializationUID::EVAL_ERROR:
820         case SerializationUID::RANGE_ERROR:
821         case SerializationUID::REFERENCE_ERROR:
822         case SerializationUID::TYPE_ERROR:
823         case SerializationUID::URI_ERROR:
824         case SerializationUID::SYNTAX_ERROR:
825             return ReadJSError(uid);
826         case SerializationUID::JS_DATE:
827             return ReadJSDate();
828         case SerializationUID::JS_PLAIN_OBJECT:
829             return ReadPlainObject();
830         case SerializationUID::JS_ARRAY:
831             return ReadJSArray();
832         case SerializationUID::ECMASTRING:
833             return ReadEcmaString();
834         case SerializationUID::JS_MAP:
835             return ReadJSMap();
836         case SerializationUID::JS_SET:
837             return ReadJSSet();
838         case SerializationUID::JS_REG_EXP:
839             return ReadJSRegExp();
840         case SerializationUID::JS_INT8_ARRAY:
841             return ReadJSTypedArray(SerializationUID::JS_INT8_ARRAY);
842         case SerializationUID::JS_UINT8_ARRAY:
843             return ReadJSTypedArray(SerializationUID::JS_UINT8_ARRAY);
844         case SerializationUID::JS_UINT8_CLAMPED_ARRAY:
845             return ReadJSTypedArray(SerializationUID::JS_UINT8_CLAMPED_ARRAY);
846         case SerializationUID::JS_INT16_ARRAY:
847             return ReadJSTypedArray(SerializationUID::JS_INT16_ARRAY);
848         case SerializationUID::JS_UINT16_ARRAY:
849             return ReadJSTypedArray(SerializationUID::JS_UINT16_ARRAY);
850         case SerializationUID::JS_INT32_ARRAY:
851             return ReadJSTypedArray(SerializationUID::JS_INT32_ARRAY);
852         case SerializationUID::JS_UINT32_ARRAY:
853             return ReadJSTypedArray(SerializationUID::JS_UINT32_ARRAY);
854         case SerializationUID::JS_FLOAT32_ARRAY:
855             return ReadJSTypedArray(SerializationUID::JS_FLOAT32_ARRAY);
856         case SerializationUID::JS_FLOAT64_ARRAY:
857             return ReadJSTypedArray(SerializationUID::JS_FLOAT64_ARRAY);
858         case SerializationUID::NATIVE_FUNCTION_POINTER:
859             return ReadNativeFunctionPointer();
860         case SerializationUID::JS_ARRAY_BUFFER:
861             return ReadJSArrayBuffer();
862         case SerializationUID::TAGGED_OBJECT_REFERNCE:
863             return ReadReference();
864         default:
865             return JSHandle<JSTaggedValue>();
866     }
867 }
868 
ReadJSError(SerializationUID uid)869 JSHandle<JSTaggedValue> JSDeserializer::ReadJSError(SerializationUID uid)
870 {
871     ObjectFactory *factory = thread_->GetEcmaVM()->GetFactory();
872     base::ErrorType errorType;
873     switch (uid) {
874         case SerializationUID::JS_ERROR:
875             errorType = base::ErrorType::ERROR;
876             break;
877         case SerializationUID::EVAL_ERROR:
878             errorType = base::ErrorType::EVAL_ERROR;
879             break;
880         case SerializationUID::RANGE_ERROR:
881             errorType = base::ErrorType::RANGE_ERROR;
882             break;
883         case SerializationUID::REFERENCE_ERROR:
884             errorType = base::ErrorType::REFERENCE_ERROR;
885             break;
886         case SerializationUID::TYPE_ERROR:
887             errorType = base::ErrorType::TYPE_ERROR;
888             break;
889         case SerializationUID::URI_ERROR:
890             errorType = base::ErrorType::URI_ERROR;
891             break;
892         case SerializationUID::SYNTAX_ERROR:
893             errorType = base::ErrorType::URI_ERROR;
894             break;
895         default:
896             UNREACHABLE();
897     }
898     JSHandle<JSTaggedValue> msg = DeserializeJSTaggedValue();
899     JSHandle<EcmaString> handleMsg(msg);
900     JSHandle<JSTaggedValue> errorTag = JSHandle<JSTaggedValue>::Cast(factory->NewJSError(errorType, handleMsg));
901     referenceMap_.insert(std::pair(objectId_++, errorTag));
902     return errorTag;
903 }
904 
ReadJSDate()905 JSHandle<JSTaggedValue> JSDeserializer::ReadJSDate()
906 {
907     ObjectFactory *factory = thread_->GetEcmaVM()->GetFactory();
908     JSHandle<GlobalEnv> env = thread_->GetEcmaVM()->GetGlobalEnv();
909     JSHandle<JSTaggedValue> dateFunction = env->GetDateFunction();
910     JSHandle<JSDate> date =
911         JSHandle<JSDate>::Cast(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(dateFunction), dateFunction));
912     JSHandle<JSTaggedValue> dateTag = JSHandle<JSTaggedValue>::Cast(date);
913     referenceMap_.insert(std::pair(objectId_++, dateTag));
914     if (!JudgeType(SerializationUID::JS_PLAIN_OBJECT) || !DefinePropertiesAndElements(dateTag)) {
915         return JSHandle<JSTaggedValue>();
916     }
917     double timeValue;
918     if (!JudgeType(SerializationUID::DOUBLE) || !ReadDouble(&timeValue)) {
919         return JSHandle<JSTaggedValue>();
920     }
921     date->SetTimeValue(thread_, JSTaggedValue(timeValue));
922     double localOffset;
923     if (!JudgeType(SerializationUID::DOUBLE) || !ReadDouble(&localOffset)) {
924         return JSHandle<JSTaggedValue>();
925     }
926     date->SetLocalOffset(thread_, JSTaggedValue(localOffset));
927     return dateTag;
928 }
929 
ReadJSArray()930 JSHandle<JSTaggedValue> JSDeserializer::ReadJSArray()
931 {
932     JSHandle<JSArray> jsArray = thread_->GetEcmaVM()->GetFactory()->NewJSArray();
933     JSHandle<JSTaggedValue> arrayTag = JSHandle<JSTaggedValue>::Cast(jsArray);
934     referenceMap_.insert(std::pair(objectId_++, arrayTag));
935     if (!JudgeType(SerializationUID::JS_PLAIN_OBJECT) || !DefinePropertiesAndElements(arrayTag)) {
936         return JSHandle<JSTaggedValue>();
937     }
938     int32_t arrLength;
939     if (!JudgeType(SerializationUID::INT32) || !ReadInt(&arrLength)) {
940         return JSHandle<JSTaggedValue>();
941     }
942     jsArray->SetLength(thread_, JSTaggedValue(arrLength));
943     return arrayTag;
944 }
945 
ReadEcmaString()946 JSHandle<JSTaggedValue> JSDeserializer::ReadEcmaString()
947 {
948     int32_t stringLength;
949     if (!JudgeType(SerializationUID::INT32) || !ReadInt(&stringLength)) {
950         return JSHandle<JSTaggedValue>();
951     }
952     ObjectFactory *factory = thread_->GetEcmaVM()->GetFactory();
953     if (stringLength == 0) {
954         JSHandle<JSTaggedValue> emptyString = JSHandle<JSTaggedValue>::Cast(factory->GetEmptyString());
955         referenceMap_.insert(std::pair(objectId_++, emptyString));
956         return emptyString;
957     }
958 
959     uint8_t *string = reinterpret_cast<uint8_t*>(GetBuffer(stringLength + 1));
960     if (string == nullptr) {
961         return JSHandle<JSTaggedValue>();
962     }
963 
964     JSHandle<EcmaString> ecmaString = factory->NewFromUtf8(string, stringLength);
965     JSHandle<JSTaggedValue> stringTag = JSHandle<JSTaggedValue>(ecmaString);
966     referenceMap_.insert(std::pair(objectId_++, stringTag));
967     return stringTag;
968 }
969 
ReadPlainObject()970 JSHandle<JSTaggedValue> JSDeserializer::ReadPlainObject()
971 {
972     JSHandle<GlobalEnv> env = thread_->GetEcmaVM()->GetGlobalEnv();
973     JSHandle<JSTaggedValue> objFunc(thread_, env->GetObjectFunction().GetObject<JSFunction>());
974     JSHandle<JSObject> jsObject =
975         thread_->GetEcmaVM()->GetFactory()->NewJSObjectByConstructor(JSHandle<JSFunction>(objFunc), objFunc);
976     JSHandle<JSTaggedValue> objTag = JSHandle<JSTaggedValue>::Cast(jsObject);
977     referenceMap_.insert(std::pair(objectId_++, objTag));
978     if (!DefinePropertiesAndElements(objTag)) {
979         return JSHandle<JSTaggedValue>();
980     }
981     return objTag;
982 }
983 
ReadJSMap()984 JSHandle<JSTaggedValue> JSDeserializer::ReadJSMap()
985 {
986     ObjectFactory *factory = thread_->GetEcmaVM()->GetFactory();
987     JSHandle<GlobalEnv> env = thread_->GetEcmaVM()->GetGlobalEnv();
988     JSHandle<JSTaggedValue> mapFunction = env->GetBuiltinsMapFunction();
989     JSHandle<JSMap> jsMap =
990         JSHandle<JSMap>::Cast(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(mapFunction), mapFunction));
991     JSHandle<JSTaggedValue> mapTag = JSHandle<JSTaggedValue>::Cast(jsMap);
992     referenceMap_.insert(std::pair(objectId_++, mapTag));
993     if (!JudgeType(SerializationUID::JS_PLAIN_OBJECT) || !DefinePropertiesAndElements(mapTag)) {
994         return JSHandle<JSTaggedValue>();
995     }
996     int32_t size;
997     if (!JudgeType(SerializationUID::INT32) || !ReadInt(&size)) {
998         return JSHandle<JSTaggedValue>();
999     }
1000     JSHandle<LinkedHashMap> linkedMap = LinkedHashMap::Create(thread_);
1001     jsMap->SetLinkedMap(thread_, linkedMap);
1002     for (int32_t i = 0; i < size; i++) {
1003         JSHandle<JSTaggedValue> key = DeserializeJSTaggedValue();
1004         if (key.IsEmpty()) {
1005             return JSHandle<JSTaggedValue>();
1006         }
1007         JSHandle<JSTaggedValue> value = DeserializeJSTaggedValue();
1008         if (value.IsEmpty()) {
1009             return JSHandle<JSTaggedValue>();
1010         }
1011         JSMap::Set(thread_, jsMap, key, value);
1012     }
1013     return mapTag;
1014 }
1015 
ReadJSSet()1016 JSHandle<JSTaggedValue> JSDeserializer::ReadJSSet()
1017 {
1018     ObjectFactory *factory = thread_->GetEcmaVM()->GetFactory();
1019     JSHandle<GlobalEnv> env = thread_->GetEcmaVM()->GetGlobalEnv();
1020     JSHandle<JSTaggedValue> setFunction = env->GetBuiltinsSetFunction();
1021     JSHandle<JSSet> jsSet =
1022         JSHandle<JSSet>::Cast(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(setFunction), setFunction));
1023     JSHandle<JSTaggedValue> setTag = JSHandle<JSTaggedValue>::Cast(jsSet);
1024     referenceMap_.insert(std::pair(objectId_++, setTag));
1025     if (!JudgeType(SerializationUID::JS_PLAIN_OBJECT) || !DefinePropertiesAndElements(setTag)) {
1026         return JSHandle<JSTaggedValue>();
1027     }
1028     int32_t size;
1029     if (!JudgeType(SerializationUID::INT32) || !ReadInt(&size)) {
1030         return JSHandle<JSTaggedValue>();
1031     }
1032     JSHandle<LinkedHashSet> linkedSet = LinkedHashSet::Create(thread_);
1033     jsSet->SetLinkedSet(thread_, linkedSet);
1034     for (int32_t i = 0; i < size; i++) {
1035         JSHandle<JSTaggedValue> key = DeserializeJSTaggedValue();
1036         if (key.IsEmpty()) {
1037             return JSHandle<JSTaggedValue>();
1038         }
1039         JSSet::Add(thread_, jsSet, key);
1040     }
1041     return setTag;
1042 }
1043 
ReadJSRegExp()1044 JSHandle<JSTaggedValue> JSDeserializer::ReadJSRegExp()
1045 {
1046     ObjectFactory *factory = thread_->GetEcmaVM()->GetFactory();
1047     JSHandle<GlobalEnv> env = thread_->GetEcmaVM()->GetGlobalEnv();
1048     JSHandle<JSTaggedValue> regexpFunction = env->GetRegExpFunction();
1049     JSHandle<JSObject> obj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(regexpFunction), regexpFunction);
1050     JSHandle<JSRegExp> regExp = JSHandle<JSRegExp>::Cast(obj);
1051     JSHandle<JSTaggedValue> regexpTag = JSHandle<JSTaggedValue>::Cast(regExp);
1052     referenceMap_.insert(std::pair(objectId_++, regexpTag));
1053     if (!JudgeType(SerializationUID::JS_PLAIN_OBJECT) || !DefinePropertiesAndElements(regexpTag)) {
1054         return JSHandle<JSTaggedValue>();
1055     }
1056     int32_t bufferSize;
1057     if (!JudgeType(SerializationUID::INT32) || !ReadInt(&bufferSize)) {
1058         return JSHandle<JSTaggedValue>();
1059     }
1060     void *buffer = GetBuffer(bufferSize);
1061     if (buffer == nullptr) {
1062         return JSHandle<JSTaggedValue>();
1063     }
1064     factory->NewJSRegExpByteCodeData(regExp, buffer, bufferSize);
1065     JSHandle<JSTaggedValue> originalSource = DeserializeJSTaggedValue();
1066     regExp->SetOriginalSource(thread_, originalSource);
1067     JSHandle<JSTaggedValue> originalFlags = DeserializeJSTaggedValue();
1068     regExp->SetOriginalFlags(thread_, originalFlags);
1069     return regexpTag;
1070 }
1071 
ReadJSTypedArray(SerializationUID uid)1072 JSHandle<JSTaggedValue> JSDeserializer::ReadJSTypedArray(SerializationUID uid)
1073 {
1074     ObjectFactory *factory = thread_->GetEcmaVM()->GetFactory();
1075     JSHandle<GlobalEnv> env = thread_->GetEcmaVM()->GetGlobalEnv();
1076     JSHandle<JSTaggedValue> target;
1077     JSHandle<JSObject> obj;
1078     JSHandle<JSTaggedValue> objTag;
1079     switch (uid) {
1080         case SerializationUID::JS_INT8_ARRAY: {
1081             target = env->GetInt8ArrayFunction();
1082             break;
1083         }
1084         case SerializationUID::JS_UINT8_ARRAY: {
1085             target = env->GetUint8ArrayFunction();
1086             break;
1087         }
1088         case SerializationUID::JS_UINT8_CLAMPED_ARRAY: {
1089             target = env->GetUint8ClampedArrayFunction();
1090             break;
1091         }
1092         case SerializationUID::JS_INT16_ARRAY: {
1093             target = env->GetInt16ArrayFunction();
1094             break;
1095         }
1096         case SerializationUID::JS_UINT16_ARRAY: {
1097             target = env->GetUint16ArrayFunction();
1098             break;
1099         }
1100         case SerializationUID::JS_INT32_ARRAY: {
1101             target = env->GetInt32ArrayFunction();
1102             break;
1103         }
1104         case SerializationUID::JS_UINT32_ARRAY: {
1105             target = env->GetUint32ArrayFunction();
1106             break;
1107         }
1108         case SerializationUID::JS_FLOAT32_ARRAY: {
1109             target = env->GetFloat32ArrayFunction();
1110             break;
1111         }
1112         case SerializationUID::JS_FLOAT64_ARRAY: {
1113             target = env->GetFloat64ArrayFunction();
1114             break;
1115         }
1116         default:
1117             UNREACHABLE();
1118     }
1119     JSHandle<JSTypedArray> typedArray =
1120         JSHandle<JSTypedArray>::Cast(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(target), target));
1121     obj = JSHandle<JSObject>::Cast(typedArray);
1122     objTag = JSHandle<JSTaggedValue>::Cast(obj);
1123     referenceMap_.insert(std::pair(objectId_++, objTag));
1124     if (!JudgeType(SerializationUID::JS_PLAIN_OBJECT) || !DefinePropertiesAndElements(objTag)) {
1125         return JSHandle<JSTaggedValue>();
1126     }
1127 
1128     JSHandle<JSTaggedValue> viewedArrayBuffer = DeserializeJSTaggedValue();
1129     if (viewedArrayBuffer.IsEmpty()) {
1130         return JSHandle<JSTaggedValue>();
1131     }
1132     typedArray->SetViewedArrayBuffer(thread_, viewedArrayBuffer);
1133 
1134     JSHandle<JSTaggedValue> typedArrayName = DeserializeJSTaggedValue();
1135     if (typedArrayName.IsEmpty()) {
1136         return JSHandle<JSTaggedValue>();
1137     }
1138     typedArray->SetTypedArrayName(thread_, typedArrayName);
1139 
1140     JSTaggedValue byteLength;
1141     if (!ReadJSTaggedValue(&byteLength) || !byteLength.IsNumber()) {
1142         return JSHandle<JSTaggedValue>();
1143     }
1144     typedArray->SetByteLength(thread_, byteLength);
1145 
1146     JSTaggedValue byteOffset;
1147     if (!ReadJSTaggedValue(&byteOffset) || !byteOffset.IsNumber()) {
1148         return JSHandle<JSTaggedValue>();
1149     }
1150     typedArray->SetByteOffset(thread_, byteOffset);
1151 
1152     JSTaggedValue arrayLength;
1153     if (!ReadJSTaggedValue(&arrayLength) || !byteOffset.IsNumber()) {
1154         return JSHandle<JSTaggedValue>();
1155     }
1156     typedArray->SetArrayLength(thread_, arrayLength);
1157     return objTag;
1158 }
1159 
ReadNativeFunctionPointer()1160 JSHandle<JSTaggedValue> JSDeserializer::ReadNativeFunctionPointer()
1161 {
1162     JSTaggedValue pointer;
1163     if (!ReadJSTaggedValue(&pointer)) {
1164         return JSHandle<JSTaggedValue>();
1165     }
1166     return JSHandle<JSTaggedValue>(thread_, pointer);
1167 }
1168 
ReadJSArrayBuffer()1169 JSHandle<JSTaggedValue> JSDeserializer::ReadJSArrayBuffer()
1170 {
1171     ObjectFactory *factory = thread_->GetEcmaVM()->GetFactory();
1172     // read access length
1173     int32_t arrayLength;
1174     if (!JudgeType(SerializationUID::INT32) || !ReadInt(&arrayLength)) {
1175         return JSHandle<JSTaggedValue>();
1176     }
1177     // read access shared
1178     bool shared = false;
1179     if (!ReadBoolean(&shared)) {
1180         return JSHandle<JSTaggedValue>();
1181     }
1182     // create jsarraybuffer
1183     JSHandle<JSTaggedValue> arrayBufferTag;
1184     if (shared) {
1185         uint64_t *bufferAddr = (uint64_t*)GetBuffer(sizeof(uint64_t));
1186         void* bufferData = ToVoidPtr(*bufferAddr);
1187         JSHandle<JSArrayBuffer> arrayBuffer = factory->NewJSArrayBuffer(bufferData, arrayLength, nullptr, nullptr);
1188         arrayBufferTag = JSHandle<JSTaggedValue>::Cast(arrayBuffer);
1189         referenceMap_.insert(std::pair(objectId_++, arrayBufferTag));
1190     } else {
1191         void *fromBuffer = GetBuffer(arrayLength);
1192         if (fromBuffer == nullptr) {
1193             return arrayBufferTag;
1194         }
1195         JSHandle<JSArrayBuffer> arrayBuffer = factory->NewJSArrayBuffer(arrayLength);
1196         arrayBufferTag = JSHandle<JSTaggedValue>::Cast(arrayBuffer);
1197         referenceMap_.insert(std::pair(objectId_++, arrayBufferTag));
1198         JSHandle<JSNativePointer> np(thread_, arrayBuffer->GetArrayBufferData());
1199         void *toBuffer = np->GetExternalPointer();
1200         if (memcpy_s(toBuffer, arrayLength, fromBuffer, arrayLength) != EOK) {
1201             UNREACHABLE();
1202         }
1203     }
1204     // read jsarraybuffer properties
1205     if (!JudgeType(SerializationUID::JS_PLAIN_OBJECT) || !DefinePropertiesAndElements(arrayBufferTag)) {
1206         return JSHandle<JSTaggedValue>();
1207     }
1208 
1209     return arrayBufferTag;
1210 }
1211 
ReadJSTaggedValue(JSTaggedValue * value)1212 bool JSDeserializer::ReadJSTaggedValue(JSTaggedValue *value)
1213 {
1214     size_t len = sizeof(JSTaggedValue);
1215     if (len > static_cast<size_t>(end_ - position_)) {
1216         return false;
1217     }
1218     if (memcpy_s(value, len, position_, len) != EOK) {
1219         UNREACHABLE();
1220     }
1221     position_ += len;
1222     return true;
1223 }
1224 
GetBuffer(uint32_t bufferSize)1225 void *JSDeserializer::GetBuffer(uint32_t bufferSize)
1226 {
1227     const uint8_t *buffer = nullptr;
1228     if (bufferSize > static_cast<size_t>(end_ - position_)) {
1229         return nullptr;
1230     }
1231     buffer = position_;
1232     position_ += bufferSize;
1233     uint8_t *retBuffer = const_cast<uint8_t *>(buffer);
1234     return static_cast<void *>(retBuffer);
1235 }
1236 
ReadReference()1237 JSHandle<JSTaggedValue> JSDeserializer::ReadReference()
1238 {
1239     uint64_t objId;
1240     if (!ReadObjectId(&objId)) {
1241         return JSHandle<JSTaggedValue>();
1242     }
1243     auto objIter = referenceMap_.find(objId);
1244     if (objIter == referenceMap_.end()) {
1245         return JSHandle<JSTaggedValue>();
1246     }
1247     return objIter->second;
1248 }
1249 
JudgeType(SerializationUID targetUid)1250 bool JSDeserializer::JudgeType(SerializationUID targetUid)
1251 {
1252     if (ReadType() != targetUid) {
1253         return false;
1254     }
1255     return true;
1256 }
1257 
DefinePropertiesAndElements(const JSHandle<JSTaggedValue> & obj)1258 bool JSDeserializer::DefinePropertiesAndElements(const JSHandle<JSTaggedValue> &obj)
1259 {
1260     int32_t elementLength;
1261     if (!JudgeType(SerializationUID::INT32) || !ReadInt(&elementLength)) {
1262         return false;
1263     }
1264     for (int32_t i = 0; i < elementLength; i++) {
1265         JSHandle<JSTaggedValue> key = DeserializeJSTaggedValue();
1266         if (key.IsEmpty()) {
1267             return false;
1268         }
1269         PropertyDescriptor desc(thread_);
1270         if (!ReadDesc(&desc)) {
1271             return false;
1272         }
1273         JSHandle<JSTaggedValue> value = DeserializeJSTaggedValue();
1274         if (value.IsEmpty()) {
1275             return false;
1276         }
1277         desc.SetValue(value);
1278         if (!JSTaggedValue::DefineOwnProperty(thread_, obj, key, desc)) {
1279             return false;
1280         }
1281     }
1282 
1283     int32_t propertyLength;
1284     if (!JudgeType(SerializationUID::INT32) || !ReadInt(&propertyLength)) {
1285         return false;
1286     }
1287     for (int32_t i = 0; i < propertyLength; i++) {
1288         JSHandle<JSTaggedValue> key = DeserializeJSTaggedValue();
1289         if (key.IsEmpty()) {
1290             return false;
1291         }
1292         PropertyDescriptor desc(thread_);
1293         if (!ReadDesc(&desc)) {
1294             return false;
1295         }
1296         JSHandle<JSTaggedValue> value = DeserializeJSTaggedValue();
1297         if (value.IsEmpty()) {
1298             return false;
1299         }
1300         desc.SetValue(value);
1301         if (!JSTaggedValue::DefineOwnProperty(thread_, obj, key, desc)) {
1302             return false;
1303         }
1304     }
1305     return true;
1306 }
1307 
ReadDesc(PropertyDescriptor * desc)1308 bool JSDeserializer::ReadDesc(PropertyDescriptor *desc)
1309 {
1310     bool isWritable = false;
1311     if (!ReadBoolean(&isWritable)) {
1312         return false;
1313     }
1314     bool isEnumerable = false;
1315     if (!ReadBoolean(&isEnumerable)) {
1316         return false;
1317     }
1318     bool isConfigurable = false;
1319     if (!ReadBoolean(&isConfigurable)) {
1320         return false;
1321     }
1322     bool hasWritable = false;
1323     if (!ReadBoolean(&hasWritable)) {
1324         return false;
1325     }
1326     bool hasEnumerable = false;
1327     if (!ReadBoolean(&hasEnumerable)) {
1328         return false;
1329     }
1330     bool hasConfigurable = false;
1331     if (!ReadBoolean(&hasConfigurable)) {
1332         return false;
1333     }
1334     if (hasWritable) {
1335         desc->SetWritable(isWritable);
1336     }
1337     if (hasEnumerable) {
1338         desc->SetEnumerable(isEnumerable);
1339     }
1340     if (hasConfigurable) {
1341         desc->SetConfigurable(isConfigurable);
1342     }
1343     return true;
1344 }
1345 
ReadBoolean(bool * value)1346 bool JSDeserializer::ReadBoolean(bool *value)
1347 {
1348     SerializationUID uid = ReadType();
1349     if (uid == SerializationUID::C_TRUE) {
1350         *value = true;
1351         return true;
1352     }
1353     if (uid == SerializationUID::C_FALSE) {
1354         *value = false;
1355         return true;
1356     }
1357     return false;
1358 }
1359 
WriteValue(JSThread * thread,const JSHandle<JSTaggedValue> & value,const JSHandle<JSTaggedValue> & transfer)1360 bool Serializer::WriteValue(
1361     JSThread *thread, const JSHandle<JSTaggedValue> &value, const JSHandle<JSTaggedValue> &transfer)
1362 {
1363     if (data_ != nullptr) {
1364         return false;
1365     }
1366     data_.reset(new SerializationData);
1367     if (!PrepareTransfer(thread, transfer)) {
1368         return false;
1369     }
1370     if (!valueSerializer_.SerializeJSTaggedValue(value)) {
1371         return false;
1372     }
1373     if (!FinalizeTransfer(thread, transfer)) {
1374         return false;
1375     }
1376     std::pair<uint8_t*, size_t> pair = valueSerializer_.ReleaseBuffer();
1377     data_->value_.reset(pair.first);
1378     data_->dataSize_ = pair.second;
1379     return true;
1380 }
1381 
Release()1382 std::unique_ptr<SerializationData> Serializer::Release()
1383 {
1384     return std::move(data_);
1385 }
1386 
PrepareTransfer(JSThread * thread,const JSHandle<JSTaggedValue> & transfer)1387 bool Serializer::PrepareTransfer(JSThread *thread, const JSHandle<JSTaggedValue> &transfer)
1388 {
1389     if (transfer->IsUndefined()) {
1390         return true;
1391     }
1392     if (!transfer->IsJSArray()) {
1393         return false;
1394     }
1395     int len = base::ArrayHelper::GetArrayLength(thread, transfer);
1396     int k = 0;
1397     while (k < len) {
1398         bool exists = JSTaggedValue::HasProperty(thread, transfer, k);
1399         if (exists) {
1400             JSHandle<JSTaggedValue> element = JSArray::FastGetPropertyByValue(thread, transfer, k);
1401             if (!element->IsArrayBuffer()) {
1402                 return false;
1403             }
1404             arrayBufferIdxs_.emplace_back(k);
1405         }
1406         k++;
1407     }
1408     return true;
1409 }
1410 
FinalizeTransfer(JSThread * thread,const JSHandle<JSTaggedValue> & transfer)1411 bool Serializer::FinalizeTransfer(JSThread *thread, const JSHandle<JSTaggedValue> &transfer)
1412 {
1413     for (int idx : arrayBufferIdxs_) {
1414         JSHandle<JSTaggedValue> element = JSArray::FastGetPropertyByValue(thread, transfer, idx);
1415         JSArrayBuffer::Cast(element->GetHeapObject())->Detach(thread);
1416     }
1417     return true;
1418 }
1419 
ReadValue()1420 JSHandle<JSTaggedValue> Deserializer::ReadValue()
1421 {
1422     return valueDeserializer_.DeserializeJSTaggedValue();
1423 }
1424 }  // namespace panda::ecmascript
1425