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