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