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