• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 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/serializer/value_serializer.h"
17 
18 #include "ecmascript/base/config.h"
19 #include "ecmascript/checkpoint/thread_state_transition.h"
20 #include "ecmascript/base/array_helper.h"
21 
22 namespace panda::ecmascript {
23 
CheckObjectCanSerialize(TaggedObject * object,bool & findSharedObject)24 bool ValueSerializer::CheckObjectCanSerialize(TaggedObject *object, bool &findSharedObject)
25 {
26     JSType type = object->GetClass()->GetObjectType();
27     if (IsInternalJSType(type)) {
28         return true;
29     }
30     switch (type) {
31         case JSType::JS_PRIMITIVE_REF:
32         case JSType::JS_ERROR:
33         case JSType::JS_EVAL_ERROR:
34         case JSType::JS_RANGE_ERROR:
35         case JSType::JS_REFERENCE_ERROR:
36         case JSType::JS_TYPE_ERROR:
37         case JSType::JS_AGGREGATE_ERROR:
38         case JSType::JS_URI_ERROR:
39         case JSType::JS_SYNTAX_ERROR:
40         case JSType::JS_OOM_ERROR:
41         case JSType::JS_TERMINATION_ERROR:
42         case JSType::JS_DATE:
43         case JSType::JS_ARRAY:
44         case JSType::JS_MAP:
45         case JSType::JS_SET:
46         case JSType::JS_REG_EXP:
47         case JSType::JS_INT8_ARRAY:
48         case JSType::JS_UINT8_ARRAY:
49         case JSType::JS_UINT8_CLAMPED_ARRAY:
50         case JSType::JS_INT16_ARRAY:
51         case JSType::JS_UINT16_ARRAY:
52         case JSType::JS_INT32_ARRAY:
53         case JSType::JS_UINT32_ARRAY:
54         case JSType::JS_FLOAT32_ARRAY:
55         case JSType::JS_FLOAT64_ARRAY:
56         case JSType::JS_BIGINT64_ARRAY:
57         case JSType::JS_BIGUINT64_ARRAY:
58         case JSType::JS_ARRAY_BUFFER:
59         case JSType::JS_SHARED_ARRAY_BUFFER:
60         case JSType::LINE_STRING:
61         case JSType::TREE_STRING:
62         case JSType::SLICED_STRING:
63         case JSType::JS_OBJECT:
64         case JSType::JS_ASYNC_FUNCTION:  // means CONCURRENT_FUNCTION
65             return true;
66         case JSType::JS_API_BITVECTOR:
67         case JSType::JS_SHARED_SET:
68         case JSType::JS_SHARED_MAP:
69         case JSType::JS_SENDABLE_ARRAY_BUFFER:
70         case JSType::JS_SHARED_ARRAY:
71         case JSType::JS_SHARED_INT8_ARRAY:
72         case JSType::JS_SHARED_UINT8_ARRAY:
73         case JSType::JS_SHARED_UINT8_CLAMPED_ARRAY:
74         case JSType::JS_SHARED_INT16_ARRAY:
75         case JSType::JS_SHARED_UINT16_ARRAY:
76         case JSType::JS_SHARED_INT32_ARRAY:
77         case JSType::JS_SHARED_UINT32_ARRAY:
78         case JSType::JS_SHARED_FLOAT32_ARRAY:
79         case JSType::JS_SHARED_FLOAT64_ARRAY:
80         case JSType::JS_SHARED_BIGINT64_ARRAY:
81         case JSType::JS_SHARED_BIGUINT64_ARRAY:
82         case JSType::JS_SHARED_OBJECT:
83         case JSType::JS_SHARED_FUNCTION:
84         case JSType::JS_SHARED_ASYNC_FUNCTION: {
85             if (serializeSharedEvent_ > 0) {
86                 return true;
87             }
88             if (defaultCloneShared_ || cloneSharedSet_.find(ToUintPtr(object)) != cloneSharedSet_.end()) {
89                 findSharedObject = true;
90                 serializeSharedEvent_++;
91             }
92             return true;
93         }
94         default:
95             break;
96     }
97     std::string errorMessage = "Serialize don't support object type: " + ConvertToStdString(JSHClass::DumpJSType(type));
98     PrintAndRecordErrorMessage(errorMessage);
99     return false;
100 }
101 
WriteValue(JSThread * thread,const JSHandle<JSTaggedValue> & value,const JSHandle<JSTaggedValue> & transfer,const JSHandle<JSTaggedValue> & cloneList)102 bool ValueSerializer::WriteValue(JSThread *thread,
103                                  const JSHandle<JSTaggedValue> &value,
104                                  const JSHandle<JSTaggedValue> &transfer,
105                                  const JSHandle<JSTaggedValue> &cloneList)
106 {
107     ECMA_BYTRACE_NAME(HITRACE_LEVEL_COMMERCIAL, HITRACE_TAG_ARK, "ValueSerializer::WriteValue", "");
108     ASSERT(!value->IsWeak());
109     if (!defaultTransfer_ && !PrepareTransfer(thread, transfer)) {
110         std::string errorMessage = "Serialize PrepareTransfer fail";
111         PrintAndRecordErrorMessage(errorMessage);
112         data_->SetIncompleteData(true);
113         return false;
114     }
115     if (!defaultCloneShared_ && !PrepareClone(thread, cloneList)) {
116         std::string errorMessage = "Serialize PrepareClone fail";
117         PrintAndRecordErrorMessage(errorMessage);
118         data_->SetIncompleteData(true);
119         return false;
120     }
121     SerializeJSTaggedValue(value.GetTaggedValue());
122     // ThreadNativeScope may trigger moving gc, so PushSerializationRoot must do before native state.
123     // Push share root object to runtime map
124     uint32_t index = data_->GetDataIndex();
125     bool chunkEmpty = sharedObjChunk_->Empty();
126     if (!chunkEmpty) {
127         index = Runtime::GetInstance()->PushSerializationRoot(thread_, std::move(sharedObjChunk_));
128     }
129     {
130         ThreadNativeScope nativeScope(thread);
131         for (auto &entry : detachCallbackInfo_) {
132             auto info = entry.second;
133             DetachFunc detachNative = reinterpret_cast<DetachFunc>(info->detachFunc);
134             if (detachNative == nullptr || entry.first < 0) {
135                 std::string errorMessage = "Serialize don't support NativeBindingObject detachNative is nullptr";
136                 PrintAndRecordErrorMessage(errorMessage);
137                 notSupport_ = true;
138                 break;
139             }
140             void *buffer = detachNative(info->env, info->nativeValue, info->hint, info->detachData);
141             if (info->detachedFinalizer != nullptr) {
142                 data_->AddNativeBindingDetachInfo(info, buffer);
143             }
144             data_->EmitU64(reinterpret_cast<uint64_t>(buffer), static_cast<size_t>(entry.first));
145         }
146     }
147     if (notSupport_) {
148         LOG_ECMA(ERROR) << "ValueSerialize: serialize data is incomplete";
149         data_->SetIncompleteData(true);
150         if (!chunkEmpty) {
151             // If notSupport, serializeRoot should be removed.
152             Runtime::GetInstance()->RemoveSerializationRoot(thread_, index);
153         }
154         return false;
155     }
156     if (!chunkEmpty) {
157         [[maybe_unused]] EcmaHandleScope scope(thread_);
158         JSMutableHandle<JSTaggedValue> strHandle(thread_, JSTaggedValue::Undefined());
159         SerializationChunk *chunk = Runtime::GetInstance()->GetSerializeRootMapValue(thread_, index);
160         size_t size = chunk->Size();
161         for (size_t i = 0; i < size; ++i) {
162             JSTaggedValue val(chunk->Get(i));
163             if (UNLIKELY(val.IsTreeString())) {
164                 strHandle.Update(val);
165                 JSHandle<JSTaggedValue> flattenStr(JSTaggedValue::PublishSharedValue(thread, strHandle));
166                 chunk->Set(i, flattenStr.GetTaggedType());
167             }
168         }
169         data_->SetDataIndex(index);
170     }
171     size_t maxSerializerSize = GetMaxJSSerializerSize(vm_);
172     if (data_->Size() > maxSerializerSize) {
173         std::ostringstream errorMessage;
174         errorMessage << "The serialization data size has exceed limit Size, current size is: " << data_->Size()
175                      << " max size is: " << maxSerializerSize;
176         PrintAndRecordErrorMessage(errorMessage.str());
177         return false;
178     }
179     return true;
180 }
181 
SerializeSharedObj(TaggedObject * object)182 bool ValueSerializer::SerializeSharedObj([[maybe_unused]] TaggedObject *object)
183 {
184     [[maybe_unused]] Region *region = Region::ObjectAddressToRange(object);
185     JSHClass *objClass = object->GetClass();
186     if (g_isEnableCMCGC) {
187         if (objClass->IsString() || objClass->IsMethod() || objClass->IsJSSharedFunction() ||
188             objClass->IsJSSharedAsyncFunction() ||
189             // add shared read only
190             (serializeSharedEvent_ == 0 && object->IsInSharedHeap())) {
191             SerializeSharedObject(object);
192             return true;
193         }
194         return false;
195     } else {
196         if (objClass->IsString() || objClass->IsMethod() || objClass->IsJSSharedFunction() ||
197             objClass->IsJSSharedAsyncFunction() ||
198             region->InSharedReadOnlySpace() || (serializeSharedEvent_ == 0 && region->InSharedHeap())) {
199             SerializeSharedObject(object);
200             return true;
201         }
202         return false;
203     }
204 }
205 
SerializeObjectImpl(TaggedObject * object,bool isWeak)206 void ValueSerializer::SerializeObjectImpl(TaggedObject *object, bool isWeak)
207 {
208     if (notSupport_) {
209         return;
210     }
211     bool cloneSharedObject = false;
212     if (!CheckObjectCanSerialize(object, cloneSharedObject)) {
213         notSupport_ = true;
214         return;
215     }
216     if (isWeak) {
217         data_->WriteEncodeFlag(EncodeFlag::WEAK);
218     }
219     if (SerializeReference(object) || SerializeRootObject(object)) {
220         return;
221     }
222 
223     if (SerializeSharedObj(object)) {
224         return;
225     }
226     JSHClass *objClass = object->GetClass();
227     if (objClass->IsNativeBindingObject()) {
228         SerializeNativeBindingObject(object);
229         return;
230     }
231     if (objClass->IsJSError()) {
232         SerializeJSError(object);
233         return;
234     }
235     bool arrayBufferDeferDetach = false;
236     JSTaggedValue trackInfo;
237     JSTaggedType hashfield = JSTaggedValue::VALUE_ZERO;
238     JSType type = objClass->GetObjectType();
239     SourceTextModule::MutableFields moduleMutableFields;
240     // serialize prologue
241     switch (type) {
242         case JSType::JS_ARRAY_BUFFER: {
243             supportJSNativePointer_ = true;
244             arrayBufferDeferDetach = SerializeJSArrayBufferPrologue(object);
245             break;
246         }
247         case JSType::JS_SHARED_ARRAY_BUFFER: {
248             supportJSNativePointer_ = true;
249             SerializeJSSharedArrayBufferPrologue(object);
250             break;
251         }
252         case JSType::JS_SENDABLE_ARRAY_BUFFER: {
253             supportJSNativePointer_ = true;
254             SerializeJSSendableArrayBufferPrologue(object);
255             break;
256         }
257         case JSType::JS_ARRAY: {
258             JSArray *array = reinterpret_cast<JSArray *>(object);
259             trackInfo = array->GetTrackInfo(thread_);
260             array->SetTrackInfo(thread_, JSTaggedValue::Undefined());
261             break;
262         }
263         case JSType::JS_REG_EXP: {
264             supportJSNativePointer_ = true;
265             SerializeJSRegExpPrologue(reinterpret_cast<JSRegExp *>(object));
266             break;
267         }
268         case JSType::JS_OBJECT: {
269             hashfield = Barriers::GetTaggedValue(thread_, object, JSObject::HASH_OFFSET);
270             Barriers::SetPrimitive<JSTaggedType>(object, JSObject::HASH_OFFSET, JSTaggedValue::VALUE_ZERO);
271             break;
272         }
273         case JSType::SOURCE_TEXT_MODULE_RECORD: {
274             if (!SerializeModuleCNativeObjects(object)) {
275                 notSupport_ = true;
276                 return;
277             }
278             SourceTextModule::StoreAndResetMutableFields(thread_,
279                 JSHandle<SourceTextModule>(thread_, object), moduleMutableFields);
280             break;
281         }
282         default:
283             break;
284     }
285 
286     // serialize object here
287     SerializeTaggedObject<SerializeType::VALUE_SERIALIZE>(object);
288 
289     // serialize epilogue
290     switch (type) {
291         case JSType::JS_ARRAY_BUFFER:
292         case JSType::JS_SHARED_ARRAY_BUFFER:
293         case JSType::JS_SENDABLE_ARRAY_BUFFER:
294         case JSType::JS_REG_EXP:
295             // JSNativePointer supports serialization only during serialize JSArrayBuffer,
296             // JSSharedArrayBuffer and JSRegExp
297             supportJSNativePointer_ = false;
298             break;
299         case JSType::JS_ARRAY: {
300             JSArray *array = reinterpret_cast<JSArray *>(object);
301             array->SetTrackInfo(thread_, trackInfo);
302             break;
303         }
304         case JSType::JS_OBJECT: {
305             if (JSTaggedValue(hashfield).IsHeapObject()) {
306                 Barriers::SetObject<true>(thread_, object, JSObject::HASH_OFFSET, hashfield);
307             } else {
308                 Barriers::SetPrimitive<JSTaggedType>(object, JSObject::HASH_OFFSET, hashfield);
309             }
310             break;
311         }
312         case JSType::SOURCE_TEXT_MODULE_RECORD: {
313             SourceTextModule::RestoreMutableFields(
314                 thread_, JSHandle<SourceTextModule>(thread_, object), moduleMutableFields);
315             break;
316         }
317         default:
318             break;
319     }
320     if (cloneSharedObject) {
321         serializeSharedEvent_--;
322     }
323     if (arrayBufferDeferDetach) {
324         ASSERT(objClass->IsArrayBuffer());
325         JSArrayBuffer *arrayBuffer = reinterpret_cast<JSArrayBuffer *>(object);
326         arrayBuffer->Detach(thread_, arrayBuffer->GetWithNativeAreaAllocator(), true);
327     }
328 }
329 
SerializeJSError(TaggedObject * object)330 void ValueSerializer::SerializeJSError(TaggedObject *object)
331 {
332     [[maybe_unused]] EcmaHandleScope scope(thread_);
333     data_->WriteEncodeFlag(EncodeFlag::JS_ERROR);
334     JSType type = object->GetClass()->GetObjectType();
335     ASSERT(type >= JSType::JS_ERROR_FIRST && type <= JSType::JS_ERROR_LAST);
336     data_->WriteUint8(static_cast<uint8_t>(type));
337     auto globalConst = thread_->GlobalConstants();
338     JSHandle<JSTaggedValue> handleMsg = globalConst->GetHandledMessageString();
339     JSHandle<JSTaggedValue> msg =
340         JSObject::GetProperty(thread_, JSHandle<JSTaggedValue>(thread_, object), handleMsg).GetValue();
341     if (msg->IsString()) {
342         data_->WriteUint8(1); // 1: msg is string
343         // string must be shared
344         SerializeSharedObject(msg->GetTaggedObject());
345     } else {
346         data_->WriteUint8(0); // 0: msg is undefined
347     }
348 }
349 
SerializeNativeBindingObject(TaggedObject * object)350 void ValueSerializer::SerializeNativeBindingObject(TaggedObject *object)
351 {
352     [[maybe_unused]] EcmaHandleScope scope(thread_);
353     JSHandle<GlobalEnv> env = vm_->GetGlobalEnv();
354     JSHandle<JSTaggedValue> nativeBindingSymbol = env->GetNativeBindingSymbol();
355     JSHandle<JSTaggedValue> nativeBindingValue =
356         JSObject::GetProperty(thread_, JSHandle<JSObject>(thread_, object), nativeBindingSymbol).GetRawValue();
357     if (!nativeBindingValue->IsJSNativePointer()) {
358         std::string errorMessage = "Serialize don't support nativeBindingValue is not JSNativePointer";
359         PrintAndRecordErrorMessage(errorMessage);
360         notSupport_ = true;
361         return;
362     }
363     auto info = reinterpret_cast<panda::JSNApi::NativeBindingInfo *>(
364         JSNativePointer::Cast(nativeBindingValue->GetTaggedObject())->GetExternalPointer());
365     if (info == nullptr) {
366         std::string errorMessage = "Serialize don't support NativeBindingInfo is nullptr";
367         PrintAndRecordErrorMessage(errorMessage);
368         notSupport_ = true;
369         return;
370     }
371     void *hint = info->hint;
372     void *attachData = info->attachData;
373     AttachFunc attachNative = reinterpret_cast<AttachFunc>(info->attachFunc);
374     data_->WriteEncodeFlag(EncodeFlag::NATIVE_BINDING_OBJECT);
375     data_->WriteJSTaggedType(reinterpret_cast<JSTaggedType>(attachNative));
376     ssize_t offset = data_->EmitU64(0); // 0 is a placeholder which will be filled later
377     detachCallbackInfo_.push_back({offset, info});
378     data_->WriteJSTaggedType(reinterpret_cast<JSTaggedType>(hint));
379     data_->WriteJSTaggedType(reinterpret_cast<JSTaggedType>(attachData));
380 }
381 
SerializeJSArrayBufferPrologue(TaggedObject * object)382 bool ValueSerializer::SerializeJSArrayBufferPrologue(TaggedObject *object)
383 {
384     ASSERT(object->GetClass()->IsArrayBuffer());
385     JSArrayBuffer *arrayBuffer = reinterpret_cast<JSArrayBuffer *>(object);
386     if (arrayBuffer->IsDetach(thread_)) {
387         std::string errorMessage = "Serialize don't support detached array buffer";
388         PrintAndRecordErrorMessage(errorMessage);
389         notSupport_ = true;
390         return false;
391     }
392     bool transfer = transferDataSet_.find(ToUintPtr(object)) != transferDataSet_.end();
393     bool clone = cloneArrayBufferSet_.find(ToUintPtr(object)) != cloneArrayBufferSet_.end();
394     size_t arrayLength = arrayBuffer->GetArrayBufferByteLength();
395     if (arrayLength > 0) {
396         if (transfer) {
397             if (clone) {
398                 notSupport_ = true;
399                 std::string errorMessage = "Serialize don't support arraybuffer in both transfer list and clone list";
400                 PrintAndRecordErrorMessage(errorMessage);
401                 return false;
402             }
403             data_->WriteEncodeFlag(EncodeFlag::TRANSFER_ARRAY_BUFFER);
404             return true;
405         } else if (clone || !defaultTransfer_) {
406             bool nativeAreaAllocated = arrayBuffer->GetWithNativeAreaAllocator();
407             if (!nativeAreaAllocated) {
408                 std::string errorMessage = "Serialize don't support clone arraybuffer has external allocated buffer, "
409                     "considering transfer it";
410                 PrintAndRecordErrorMessage(errorMessage);
411                 notSupport_ = true;
412                 return false;
413             }
414             data_->WriteEncodeFlag(EncodeFlag::ARRAY_BUFFER);
415             data_->WriteUint32(arrayLength);
416             JSNativePointer *np =
417                 reinterpret_cast<JSNativePointer *>(arrayBuffer->GetArrayBufferData(thread_).GetTaggedObject());
418             data_->WriteRawData(static_cast<uint8_t *>(np->GetExternalPointer()), arrayLength);
419             return false;
420         } else {
421             data_->WriteEncodeFlag(EncodeFlag::TRANSFER_ARRAY_BUFFER);
422             return true;
423         }
424     }
425     return false;
426 }
427 
SerializeJSSharedArrayBufferPrologue(TaggedObject * object)428 void ValueSerializer::SerializeJSSharedArrayBufferPrologue(TaggedObject *object)
429 {
430     ASSERT(object->GetClass()->IsSharedArrayBuffer());
431     JSArrayBuffer *arrayBuffer = reinterpret_cast<JSArrayBuffer *>(object);
432     bool transfer = transferDataSet_.find(ToUintPtr(object)) != transferDataSet_.end();
433     if (arrayBuffer->IsDetach(thread_) || transfer) {
434         std::string errorMessage =  "Serialize don't support detached or transfer shared array buffer";
435         PrintAndRecordErrorMessage(errorMessage);
436         notSupport_ = true;
437         return;
438     }
439     size_t arrayLength = arrayBuffer->GetArrayBufferByteLength();
440     if (arrayLength > 0) {
441         JSNativePointer *np =
442             reinterpret_cast<JSNativePointer *>(arrayBuffer->GetArrayBufferData(thread_).GetTaggedObject());
443         void *buffer = np->GetExternalPointer();
444         if (JSSharedMemoryManager::GetInstance()->CreateOrLoad(&buffer, arrayLength)) {
445             std::string errorMessage =  "Serialize can't find buffer from shared memory pool";
446             PrintAndRecordErrorMessage(errorMessage);
447             notSupport_ = true;
448             return;
449         }
450         data_->WriteEncodeFlag(EncodeFlag::SHARED_ARRAY_BUFFER);
451         data_->insertSharedArrayBuffer(reinterpret_cast<uintptr_t>(buffer));
452     }
453 }
454 
SerializeJSSendableArrayBufferPrologue(TaggedObject * object)455 void ValueSerializer::SerializeJSSendableArrayBufferPrologue(TaggedObject *object)
456 {
457     ASSERT(object->GetClass()->IsSendableArrayBuffer());
458     JSSendableArrayBuffer *arrayBuffer = reinterpret_cast<JSSendableArrayBuffer *>(object);
459     if (arrayBuffer->IsDetach(thread_)) {
460         std::string errorMessage =  "Serialize don't support serialize detached sendable array buffer";
461         PrintAndRecordErrorMessage(errorMessage);
462         notSupport_ = true;
463         return;
464     }
465     size_t arrayLength = arrayBuffer->GetArrayBufferByteLength();
466     if (arrayLength > 0) {
467         bool nativeAreaAllocated = arrayBuffer->GetWithNativeAreaAllocator();
468         if (!nativeAreaAllocated) {
469             std::string errorMessage =  "Serialize don't support clone sendablearraybuffer has external allocated buffer";
470             PrintAndRecordErrorMessage(errorMessage);
471             notSupport_ = true;
472             return;
473         }
474         data_->WriteEncodeFlag(EncodeFlag::SENDABLE_ARRAY_BUFFER);
475         data_->WriteUint32(arrayLength);
476         JSNativePointer *np =
477             reinterpret_cast<JSNativePointer *>(arrayBuffer->GetArrayBufferData(thread_).GetTaggedObject());
478         data_->WriteRawData(static_cast<uint8_t *>(np->GetExternalPointer()), arrayLength);
479     }
480 }
481 
SerializeJSRegExpPrologue(JSRegExp * jsRegExp)482 void ValueSerializer::SerializeJSRegExpPrologue(JSRegExp *jsRegExp)
483 {
484     uint32_t bufferSize = jsRegExp->GetLength();
485     if (bufferSize == 0) {
486         std::string errorMessage =  "Serialize don't support JSRegExp buffer size is 0";
487         PrintAndRecordErrorMessage(errorMessage);
488         notSupport_ = true;
489         return;
490     }
491 
492     data_->WriteEncodeFlag(EncodeFlag::JS_REG_EXP);
493     data_->WriteUint32(bufferSize);
494     JSNativePointer *np = reinterpret_cast<JSNativePointer *>(jsRegExp->GetByteCodeBuffer(thread_).GetTaggedObject());
495     data_->WriteRawData(static_cast<uint8_t *>(np->GetExternalPointer()), bufferSize);
496 }
497 
PrepareTransfer(JSThread * thread,const JSHandle<JSTaggedValue> & transfer)498 bool ValueSerializer::PrepareTransfer(JSThread *thread, const JSHandle<JSTaggedValue> &transfer)
499 {
500     if (transfer->IsUndefined()) {
501         return true;
502     }
503     if (!transfer->IsJSArray()) {
504         return false;
505     }
506     int len = base::ArrayHelper::GetArrayLength(thread, transfer);
507     int k = 0;
508     while (k < len) {
509         bool exists = JSTaggedValue::HasProperty(thread, transfer, k);
510         if (exists) {
511             JSHandle<JSTaggedValue> element = JSArray::FastGetPropertyByValue(thread, transfer, k);
512             if (!element->IsArrayBuffer()) {
513                 return false;
514             }
515             transferDataSet_.insert(static_cast<uintptr_t>(element.GetTaggedType()));
516         }
517         k++;
518     }
519     return true;
520 }
521 
PrepareClone(JSThread * thread,const JSHandle<JSTaggedValue> & cloneList)522 bool ValueSerializer::PrepareClone(JSThread *thread, const JSHandle<JSTaggedValue> &cloneList)
523 {
524     if (cloneList->IsUndefined()) {
525         return true;
526     }
527     if (!cloneList->IsJSArray()) {
528         return false;
529     }
530     int len = base::ArrayHelper::GetArrayLength(thread, cloneList);
531     int index = 0;
532     while (index < len) {
533         bool exists = JSTaggedValue::HasProperty(thread, cloneList, index);
534         if (exists) {
535             JSHandle<JSTaggedValue> element = JSArray::FastGetPropertyByValue(thread, cloneList, index);
536             if (element->IsArrayBuffer()) {
537                 cloneArrayBufferSet_.insert(static_cast<uintptr_t>(element.GetTaggedType()));
538             } else if (element->IsJSShared()) {
539                 cloneSharedSet_.insert(static_cast<uintptr_t>(element.GetTaggedType()));
540             } else {
541                 return false;
542             }
543         }
544         index++;
545     }
546     return true;
547 }
548 
549 // especially process cpp native object in SourceTextModule
SerializeModuleCNativeObjects(TaggedObject * object)550 bool ValueSerializer::SerializeModuleCNativeObjects(TaggedObject *object)
551 {
552     JSHandle<SourceTextModule> module = JSHandle<SourceTextModule>(thread_, object);
553     CString moduleFileName = module->GetEcmaModuleFilenameString();
554     data_->WriteEncodeFlag(EncodeFlag::MODULE_FILE_NAME);
555     if (!moduleFileName.empty()) {
556         data_->WriteUint32(moduleFileName.size());
557         data_->WriteRawData(reinterpret_cast<uint8_t *>(moduleFileName.data()), moduleFileName.size());
558     } else {
559         LOG_ECMA(ERROR) << "ValueSerialize::SerializeModuleCNativeObjects moduleFileName is empty";
560         return false;
561     }
562 
563     CString moduleRecordName = module->GetEcmaModuleRecordNameString();
564     data_->WriteEncodeFlag(EncodeFlag::MODULE_RECORD_NAME);
565     if (!moduleRecordName.empty()) {
566         data_->WriteUint32(moduleRecordName.size());
567         data_->WriteRawData(reinterpret_cast<uint8_t *>(moduleRecordName.data()), moduleRecordName.size());
568     } else {
569         data_->WriteUint32(0);
570     }
571 
572     bool *lazyArray = module->GetLazyImportStatusArray();
573     // ModuleRequests size is equal to lazy array size.
574     JSTaggedValue requests = module->GetModuleRequests(thread_);
575     data_->WriteEncodeFlag(EncodeFlag::MODULE_LAZY_ARRAY);
576     if (lazyArray && requests.IsTaggedArray()) {
577         JSHandle<TaggedArray> moduleRequests(thread_, requests);
578         size_t lazyArraySpaceSize = moduleRequests->GetLength() * sizeof(bool);
579         if (lazyArraySpaceSize != 0) {
580             data_->WriteUint32(lazyArraySpaceSize);
581             data_->WriteRawData(reinterpret_cast<uint8_t *>(lazyArray), lazyArraySpaceSize);
582         } else {
583             data_->WriteUint32(0);
584         }
585     } else {
586         data_->WriteUint32(0);
587     }
588     return true;
589 }
590 }  // namespace panda::ecmascript
591 
592