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