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