/* * Copyright (c) 2021-2022 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include <thread> #include "assembler/assembly-emitter.h" #include "assembler/assembly-parser.h" #include "libpandabase/utils/utf.h" #include "libpandafile/class_data_accessor-inl.h" #include "ecmascript/builtins/builtins_arraybuffer.h" #include "ecmascript/ecma_vm.h" #include "ecmascript/global_env.h" #include "ecmascript/js_array.h" #include "ecmascript/js_arraybuffer.h" #include "ecmascript/js_hclass.h" #include "ecmascript/js_regexp.h" #include "ecmascript/js_serializer.h" #include "ecmascript/js_set.h" #include "ecmascript/js_thread.h" #include "ecmascript/js_typed_array.h" #include "ecmascript/jspandafile/js_pandafile.h" #include "ecmascript/jspandafile/js_pandafile_manager.h" #include "ecmascript/linked_hash_table.h" #include "ecmascript/mem/c_containers.h" #include "ecmascript/object_factory.h" #include "ecmascript/tests/test_helper.h" using namespace panda::ecmascript; using namespace testing::ext; using namespace panda::ecmascript::builtins; namespace panda::test { class JSDeserializerTest { public: JSDeserializerTest() : ecmaVm(nullptr), scope(nullptr), thread(nullptr) {} void Init() { JSRuntimeOptions options; options.SetEnableForceGC(true); ecmaVm = JSNApi::CreateEcmaVM(options); ecmaVm->SetEnableForceGC(true); EXPECT_TRUE(ecmaVm != nullptr) << "Cannot create Runtime"; thread = ecmaVm->GetJSThread(); scope = new EcmaHandleScope(thread); } void Destroy() { delete scope; scope = nullptr; ecmaVm->SetEnableForceGC(false); thread->ClearException(); JSNApi::DestroyJSVM(ecmaVm); } void JSSpecialValueTest(std::pair<uint8_t *, size_t> data) { Init(); JSHandle<JSTaggedValue> jsTrue(thread, JSTaggedValue::True()); JSHandle<JSTaggedValue> jsFalse(thread, JSTaggedValue::False()); JSHandle<JSTaggedValue> jsUndefined(thread, JSTaggedValue::Undefined()); JSHandle<JSTaggedValue> jsNull(thread, JSTaggedValue::Null()); JSHandle<JSTaggedValue> jsHole(thread, JSTaggedValue::Hole()); JSDeserializer deserializer(thread, data.first, data.second); JSHandle<JSTaggedValue> retTrue = deserializer.Deserialize(); EXPECT_TRUE(JSTaggedValue::SameValue(jsTrue, retTrue)) << "Not same value for JS_TRUE"; JSHandle<JSTaggedValue> retFalse = deserializer.Deserialize(); EXPECT_TRUE(JSTaggedValue::SameValue(jsFalse, retFalse)) << "Not same value for JS_FALSE"; JSHandle<JSTaggedValue> retUndefined = deserializer.Deserialize(); JSHandle<JSTaggedValue> retNull = deserializer.Deserialize(); JSHandle<JSTaggedValue> retHole = deserializer.Deserialize(); EXPECT_TRUE(JSTaggedValue::SameValue(jsUndefined, retUndefined)) << "Not same value for JS_UNDEFINED"; EXPECT_TRUE(JSTaggedValue::SameValue(jsNull, retNull)) << "Not same value for JS_NULL"; EXPECT_TRUE(JSTaggedValue::SameValue(jsHole, retHole)) << "Not same value for JS_HOLE"; Destroy(); } void JSPlainObjectTest1(std::pair<uint8_t *, size_t> data) { Init(); JSDeserializer deserializer(thread, data.first, data.second); JSHandle<JSTaggedValue> objValue1 = deserializer.Deserialize(); JSHandle<JSTaggedValue> objValue2 = deserializer.Deserialize(); JSHandle<JSObject> retObj1 = JSHandle<JSObject>::Cast(objValue1); JSHandle<JSObject> retObj2 = JSHandle<JSObject>::Cast(objValue2); EXPECT_FALSE(retObj1.IsEmpty()); EXPECT_FALSE(retObj2.IsEmpty()); JSHandle<TaggedArray> array1 = JSObject::GetOwnPropertyKeys(thread, retObj1); uint32_t length1 = array1->GetLength(); EXPECT_EQ(length1, 4U); // 4 : test case double sum1 = 0.0; for (uint32_t i = 0; i < length1; i++) { JSHandle<JSTaggedValue> key(thread, array1->Get(i)); double a = JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(retObj1), key).GetValue()->GetNumber(); sum1 += a; } EXPECT_EQ(sum1, 10); // 10 : test case JSHandle<TaggedArray> array2 = JSObject::GetOwnPropertyKeys(thread, retObj2); uint32_t length2 = array2->GetLength(); EXPECT_EQ(length2, 4U); // 4 : test case double sum2 = 0.0; for (uint32_t i = 0; i < length2; i++) { JSHandle<JSTaggedValue> key(thread, array2->Get(i)); double a = JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(retObj2), key).GetValue()->GetNumber(); sum2 += a; } EXPECT_EQ(sum2, 26); // 26 : test case Destroy(); } void JSPlainObjectTest2(std::pair<uint8_t *, size_t> data) { Init(); ObjectFactory *factory = ecmaVm->GetFactory(); JSDeserializer deserializer(thread, data.first, data.second); JSHandle<JSTaggedValue> objValue1 = deserializer.Deserialize(); JSHandle<JSTaggedValue> key1(factory->NewFromASCII("detectResultItems")); JSHandle<JSTaggedValue> key2(factory->NewFromASCII("adviceId")); OperationResult result = JSObject::GetProperty(thread, objValue1, key1); JSHandle<JSTaggedValue> value1 = result.GetRawValue(); EXPECT_TRUE(value1->IsJSArray()); JSHandle<JSTaggedValue> value2 = JSArray::FastGetPropertyByValue(thread, value1, 0); JSHandle<JSObject> obj = JSHandle<JSObject>::Cast(value2); bool res = JSObject::HasProperty(thread, obj, key2); EXPECT_TRUE(res); OperationResult result1 = JSObject::GetProperty(thread, value2, key2); JSHandle<JSTaggedValue> value3 = result1.GetRawValue(); JSHandle<JSTaggedValue> value4 = JSHandle<JSTaggedValue>::Cast(factory->GetEmptyString()); EXPECT_EQ(value3, value4); Destroy(); } void JSPlainObjectTest3(std::pair<uint8_t *, size_t> data) { Init(); JSDeserializer deserializer(thread, data.first, data.second); JSHandle<JSTaggedValue> objValue = deserializer.Deserialize(); JSHandle<JSObject> retObj = JSHandle<JSObject>::Cast(objValue); EXPECT_FALSE(retObj.IsEmpty()); std::vector<JSTaggedValue> keyVector; JSObject::GetAllKeysForSerialization(retObj, keyVector); EXPECT_EQ(keyVector.size(), 2U); // 2 : test case ObjectFactory *factory = ecmaVm->GetFactory(); JSHandle<JSTaggedValue> key(factory->NewFromASCII("y")); int value = JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(retObj), key).GetValue()->GetInt(); EXPECT_EQ(value, 10U); // 10 : test case Destroy(); } void NativeBindingObjectTest1(std::pair<uint8_t *, size_t> data) { Init(); JSDeserializer deserializer(thread, data.first, data.second); [[maybe_unused]] JSHandle<JSTaggedValue> objValue1 = deserializer.Deserialize(); JSHandle<JSTaggedValue> objValue2 = deserializer.Deserialize(); [[maybe_unused]] JSHandle<JSTaggedValue> objValue3 = deserializer.Deserialize(); JSHandle<JSObject> retObj2 = JSHandle<JSObject>::Cast(objValue2); EXPECT_FALSE(retObj2.IsEmpty()); JSHandle<TaggedArray> array2 = JSObject::GetOwnPropertyKeys(thread, retObj2); uint32_t length2 = array2->GetLength(); EXPECT_EQ(length2, 6U); // 6 : test case Destroy(); } void NativeBindingObjectTest2(std::pair<uint8_t *, size_t> data) { Init(); ObjectFactory *factory = ecmaVm->GetFactory(); JSDeserializer deserializer(thread, data.first, data.second); JSHandle<JSTaggedValue> objValue1 = deserializer.Deserialize(); [[maybe_unused]] JSHandle<JSTaggedValue> objValue2 = deserializer.Deserialize(); JSHandle<JSObject> retObj1 = JSHandle<JSObject>::Cast(objValue1); EXPECT_FALSE(retObj1.IsEmpty()); JSHandle<TaggedArray> array1 = JSObject::GetOwnPropertyKeys(thread, retObj1); uint32_t length1 = array1->GetLength(); EXPECT_EQ(length1, 4U); // 4 : test case JSHandle<JSTaggedValue> key1(factory->NewFromASCII("abc")); JSHandle<JSTaggedValue> key2(factory->NewFromASCII("8")); JSHandle<JSTaggedValue> value1(thread, JSTaggedValue(6)); // 6 : test case JSHandle<JSTaggedValue> value2 = JSHandle<JSTaggedValue>::Cast(factory->GetEmptyString()); OperationResult res1 = JSObject::GetProperty(thread, objValue1, key1); JSHandle<JSTaggedValue> resValue1 = res1.GetRawValue(); EXPECT_EQ(resValue1, value1); OperationResult res2 = JSObject::GetProperty(thread, objValue1, key2); JSHandle<JSTaggedValue> resValue2 = res2.GetRawValue(); EXPECT_EQ(resValue2, value2); Destroy(); } void NativeBindingObjectTest3(std::pair<uint8_t *, size_t> data) { Init(); ObjectFactory *factory = ecmaVm->GetFactory(); JSDeserializer deserializer(thread, data.first, data.second); [[maybe_unused]] JSHandle<JSTaggedValue> objValue1 = deserializer.Deserialize(); JSHandle<JSTaggedValue> objValue2 = deserializer.Deserialize(); JSHandle<JSTaggedValue> key1(factory->NewFromASCII("root1")); JSHandle<JSTaggedValue> key2(factory->NewFromASCII("root2")); JSHandle<JSTaggedValue> key3(factory->NewFromASCII("root3")); JSHandle<JSTaggedValue> key4(factory->NewFromASCII("name")); JSHandle<JSTaggedValue> key5(factory->NewFromASCII("version")); JSHandle<JSTaggedValue> key6(factory->NewFromASCII("product")); JSHandle<JSTaggedValue> key7(factory->NewFromASCII("os")); JSHandle<JSTaggedValue> key8(factory->NewFromASCII("system")); JSHandle<JSTaggedValue> value1(factory->NewFromASCII("")); OperationResult res1 = JSObject::GetProperty(thread, objValue2, key1); JSHandle<JSTaggedValue> resValue1 = res1.GetRawValue(); EXPECT_EQ(resValue1, value1); OperationResult res2 = JSObject::GetProperty(thread, objValue2, key2); JSHandle<JSTaggedValue> resValue2 = res2.GetRawValue(); EXPECT_EQ(resValue2, value1); OperationResult res3 = JSObject::GetProperty(thread, objValue2, key3); JSHandle<JSTaggedValue> resValue3 = res3.GetRawValue(); EXPECT_EQ(resValue3, value1); OperationResult res4 = JSObject::GetProperty(thread, objValue2, key4); JSHandle<JSTaggedValue> resValue4 = res4.GetRawValue(); EXPECT_EQ(resValue4, value1); OperationResult res5 = JSObject::GetProperty(thread, objValue2, key5); JSHandle<JSTaggedValue> resValue5 = res5.GetRawValue(); EXPECT_EQ(resValue5, value1); OperationResult res6 = JSObject::GetProperty(thread, objValue2, key6); JSHandle<JSTaggedValue> resValue6 = res6.GetRawValue(); EXPECT_EQ(resValue6, value1); OperationResult res7 = JSObject::GetProperty(thread, objValue2, key7); JSHandle<JSTaggedValue> resValue7 = res7.GetRawValue(); EXPECT_EQ(resValue7, value1); OperationResult res8 = JSObject::GetProperty(thread, objValue2, key8); JSHandle<JSTaggedValue> resValue8 = res8.GetRawValue(); EXPECT_EQ(resValue8, value1); Destroy(); } void DescriptionTest(std::pair<uint8_t *, size_t> data) { Init(); ObjectFactory *factory = ecmaVm->GetFactory(); JSHandle<JSTaggedValue> key1(factory->NewFromASCII("x")); JSHandle<JSTaggedValue> key2(thread->GetEcmaVM()->GetFactory()->NewFromASCII("y")); JSHandle<JSTaggedValue> value1(thread, JSTaggedValue(1)); JSHandle<JSTaggedValue> value2(thread, JSTaggedValue(2)); // 2 : test case JSDeserializer deserializer(thread, data.first, data.second); JSHandle<JSTaggedValue> objValue = deserializer.Deserialize(); JSHandle<JSObject> retObj = JSHandle<JSObject>::Cast(objValue); PropertyDescriptor desc3(thread); PropertyDescriptor desc4(thread); JSHandle<TaggedArray> array1 = JSObject::GetOwnPropertyKeys(thread, retObj); JSHandle<JSTaggedValue> retKey1(thread, array1->Get(0)); JSHandle<JSTaggedValue> retKey2(thread, array1->Get(1)); JSObject::GetOwnProperty(thread, retObj, retKey1, desc3); JSObject::GetOwnProperty(thread, retObj, retKey2, desc4); EXPECT_EQ(key1.GetTaggedValue().GetRawData(), retKey1.GetTaggedValue().GetRawData()); EXPECT_EQ(desc3.GetValue().GetTaggedValue().GetRawData(), value1.GetTaggedValue().GetRawData()); EXPECT_TRUE(desc3.IsWritable()); EXPECT_FALSE(desc3.IsEnumerable()); EXPECT_TRUE(desc3.IsConfigurable()); EXPECT_EQ(desc4.GetValue().GetTaggedValue().GetRawData(), value2.GetTaggedValue().GetRawData()); EXPECT_FALSE(desc4.IsWritable()); EXPECT_TRUE(desc4.IsEnumerable()); EXPECT_FALSE(desc4.IsConfigurable()); Destroy(); } void JSSetTest(std::pair<uint8_t *, size_t> data) { Init(); ObjectFactory *factory = ecmaVm->GetFactory(); JSHandle<JSTaggedValue> value1(thread, JSTaggedValue(7)); // 7 : test case JSHandle<JSTaggedValue> value2(thread, JSTaggedValue(9)); // 9 : test case JSHandle<JSTaggedValue> value3(factory->NewFromASCII("x")); JSHandle<JSTaggedValue> value4(factory->NewFromASCII("y")); JSDeserializer deserializer(thread, data.first, data.second); JSHandle<JSTaggedValue> setValue = deserializer.Deserialize(); EXPECT_TRUE(!setValue.IsEmpty()); JSHandle<JSSet> retSet = JSHandle<JSSet>::Cast(setValue); JSHandle<TaggedArray> array = JSObject::GetOwnPropertyKeys(thread, JSHandle<JSObject>::Cast(retSet)); uint32_t propertyLength = array->GetLength(); EXPECT_EQ(propertyLength, 2U); // 2 : test case int sum = 0; for (uint32_t i = 0; i < propertyLength; i++) { JSHandle<JSTaggedValue> key(thread, array->Get(i)); double a = JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(retSet), key).GetValue()->GetNumber(); sum += a; } EXPECT_EQ(sum, 16); // 16 : test case EXPECT_EQ(retSet->GetSize(), 4); // 4 : test case EXPECT_TRUE(retSet->Has(thread, value1.GetTaggedValue())); EXPECT_TRUE(retSet->Has(thread, value2.GetTaggedValue())); EXPECT_TRUE(retSet->Has(thread, value3.GetTaggedValue())); EXPECT_TRUE(retSet->Has(thread, value4.GetTaggedValue())); Destroy(); } void JSArrayTest(std::pair<uint8_t *, size_t> data) { Init(); JSDeserializer deserializer(thread, data.first, data.second); JSHandle<JSTaggedValue> arrayValue = deserializer.Deserialize(); EXPECT_TRUE(!arrayValue.IsEmpty()); JSHandle<JSArray> retArray = JSHandle<JSArray>::Cast(arrayValue); JSHandle<TaggedArray> keyArray = JSObject::GetOwnPropertyKeys(thread, JSHandle<JSObject>(retArray)); uint32_t propertyLength = keyArray->GetLength(); EXPECT_EQ(propertyLength, 23U); // 23 : test case int sum = 0; for (uint32_t i = 0; i < propertyLength; i++) { JSHandle<JSTaggedValue> key(thread, keyArray->Get(i)); double a = JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(retArray), key).GetValue()->GetNumber(); sum += a; } EXPECT_EQ(sum, 226); // 226 : test case // test get value from array for (int i = 0; i < 20; i++) { // 20 : test case JSHandle<JSTaggedValue> value = JSArray::FastGetPropertyByValue(thread, arrayValue, i); EXPECT_EQ(i, value.GetTaggedValue().GetInt()); } Destroy(); } void ObjectsPropertyReferenceTest(std::pair<uint8_t *, size_t> data) { Init(); JSDeserializer deserializer(thread, data.first, data.second); JSHandle<JSTaggedValue> objValue1 = deserializer.Deserialize(); JSHandle<JSTaggedValue> objValue2 = deserializer.Deserialize(); EXPECT_TRUE(!objValue1.IsEmpty()) << "[Empty] Deserialize obj1 fail"; EXPECT_TRUE(!objValue2.IsEmpty()) << "[Empty] Deserialize obj2 fail"; Destroy(); } void EcmaStringTest1(std::pair<uint8_t *, size_t> data) { Init(); const char *rawStr = "this is a test ecmaString"; JSHandle<EcmaString> ecmaString = thread->GetEcmaVM()->GetFactory()->NewFromASCII(rawStr); JSDeserializer deserializer(thread, data.first, data.second); JSHandle<JSTaggedValue> res = deserializer.Deserialize(); EXPECT_TRUE(!res.IsEmpty()) << "[Empty] Deserialize ecmaString fail"; EXPECT_TRUE(res->IsString()) << "[NotString] Deserialize ecmaString fail"; JSHandle<EcmaString> resEcmaString = JSHandle<EcmaString>::Cast(res); auto ecmaStringCode = EcmaStringAccessor(ecmaString).GetHashcode(); auto resEcmaStringCode = EcmaStringAccessor(resEcmaString).GetHashcode(); EXPECT_TRUE(ecmaStringCode == resEcmaStringCode) << "Not same HashCode"; EXPECT_TRUE(EcmaStringAccessor::StringsAreEqual(*ecmaString, *resEcmaString)) << "Not same EcmaString"; Destroy(); } void EcmaStringTest2(std::pair<uint8_t *, size_t> data) { Init(); const char *rawStr = "ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss"\ "sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss"\ "sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss"\ "ssssss"; JSHandle<EcmaString> ecmaString = thread->GetEcmaVM()->GetFactory()->NewFromASCII(rawStr); JSDeserializer deserializer(thread, data.first, data.second); JSHandle<JSTaggedValue> res = deserializer.Deserialize(); EXPECT_TRUE(!res.IsEmpty()) << "[Empty] Deserialize ecmaString fail"; EXPECT_TRUE(res->IsString()) << "[NotString] Deserialize ecmaString fail"; JSHandle<EcmaString> resEcmaString = JSHandle<EcmaString>::Cast(res); auto ecmaStringCode = EcmaStringAccessor(ecmaString).GetHashcode(); auto resEcmaStringCode = EcmaStringAccessor(resEcmaString).GetHashcode(); EXPECT_TRUE(ecmaStringCode == resEcmaStringCode) << "Not same HashCode"; EXPECT_TRUE(EcmaStringAccessor::StringsAreEqual(*ecmaString, *resEcmaString)) << "Not same EcmaString"; Destroy(); } void EcmaStringTest3(std::pair<uint8_t *, size_t> data) { Init(); JSHandle<EcmaString> ecmaString = thread->GetEcmaVM()->GetFactory()->GetEmptyString(); JSDeserializer deserializer(thread, data.first, data.second); JSHandle<JSTaggedValue> res = deserializer.Deserialize(); EXPECT_TRUE(res->IsString()) << "[NotString] Deserialize ecmaString fail"; JSHandle<EcmaString> resEcmaString = JSHandle<EcmaString>::Cast(res); auto ecmaStringCode = EcmaStringAccessor(ecmaString).GetHashcode(); auto resEcmaStringCode = EcmaStringAccessor(resEcmaString).GetHashcode(); EXPECT_TRUE(ecmaStringCode == resEcmaStringCode) << "Not same HashCode"; EXPECT_TRUE(EcmaStringAccessor::StringsAreEqual(*ecmaString, *resEcmaString)) << "Not same EcmaString"; Destroy(); } void EcmaStringTest4(std::pair<uint8_t *, size_t> data) { Init(); JSHandle<EcmaString> ecmaString = thread->GetEcmaVM()->GetFactory()->NewFromStdString("ä½ å¥½ï¼Œä¸–ç•Œ"); JSHandle<EcmaString> ecmaString1 = thread->GetEcmaVM()->GetFactory()->NewFromStdString("ä½ å¥½ï¼Œä¸–ç•Œ"); auto ecmaStringCode1 = EcmaStringAccessor(ecmaString).GetHashcode(); auto ecmaString1Code = EcmaStringAccessor(ecmaString1).GetHashcode(); EXPECT_TRUE(ecmaStringCode1 == ecmaString1Code) << "Not same HashCode"; EXPECT_TRUE(EcmaStringAccessor::StringsAreEqual(*ecmaString, *ecmaString1)) << "Not same EcmaString"; JSDeserializer deserializer(thread, data.first, data.second); JSHandle<JSTaggedValue> res = deserializer.Deserialize(); EXPECT_TRUE(!res.IsEmpty()) << "[Empty] Deserialize ecmaString fail"; EXPECT_TRUE(res->IsString()) << "[NotString] Deserialize ecmaString fail"; JSHandle<EcmaString> resEcmaString = JSHandle<EcmaString>::Cast(res); auto ecmaStringCode2 = EcmaStringAccessor(ecmaString).GetHashcode(); auto resEcmaStringCode = EcmaStringAccessor(resEcmaString).GetHashcode(); EXPECT_TRUE(ecmaStringCode2 == resEcmaStringCode) << "Not same HashCode"; EXPECT_TRUE(EcmaStringAccessor::StringsAreEqual(*ecmaString, *resEcmaString)) << "Not same EcmaString"; Destroy(); } void Int32Test(std::pair<uint8_t *, size_t> data) { Init(); int32_t a = 64; int32_t min = -2147483648; int32_t b = -63; JSDeserializer deserializer(thread, data.first, data.second); JSHandle<JSTaggedValue> resA = deserializer.Deserialize(); JSHandle<JSTaggedValue> resMin = deserializer.Deserialize(); JSHandle<JSTaggedValue> resB = deserializer.Deserialize(); EXPECT_TRUE(!resA.IsEmpty() && !resMin.IsEmpty() && !resB.IsEmpty()) << "[Empty] Deserialize Int32 fail"; EXPECT_TRUE(resA->IsInt() && resMin->IsInt() && resB->IsInt()) << "[NotInt] Deserialize Int32 fail"; EXPECT_TRUE(JSTaggedValue::ToInt32(thread, resA) == a) << "Not Same Value"; EXPECT_TRUE(JSTaggedValue::ToInt32(thread, resMin) == min) << "Not Same Value"; EXPECT_TRUE(JSTaggedValue::ToInt32(thread, resB) == b) << "Not Same Value"; Destroy(); } void DoubleTest(std::pair<uint8_t *, size_t> data) { Init(); double a = 3.1415926535; double b = -3.1415926535; JSDeserializer deserializer(thread, data.first, data.second); JSHandle<JSTaggedValue> resA = deserializer.Deserialize(); JSHandle<JSTaggedValue> resB = deserializer.Deserialize(); EXPECT_TRUE(!resA.IsEmpty() && !resB.IsEmpty()) << "[Empty] Deserialize double fail"; EXPECT_TRUE(resA->IsDouble() && resB->IsDouble()) << "[NotInt] Deserialize double fail"; EXPECT_TRUE(resA->GetDouble() == a) << "Not Same Value"; EXPECT_TRUE(resB->GetDouble() == b) << "Not Same Value"; Destroy(); } void JSDateTest(std::pair<uint8_t *, size_t> data) { Init(); double tm = 28 * 60 * 60 * 1000; // 28 * 60 * 60 * 1000 : test case JSDeserializer deserializer(thread, data.first, data.second); JSHandle<JSTaggedValue> res = deserializer.Deserialize(); EXPECT_TRUE(!res.IsEmpty()) << "[Empty] Deserialize JSDate fail"; EXPECT_TRUE(res->IsDate()) << "[NotJSDate] Deserialize JSDate fail"; JSHandle<JSDate> resDate = JSHandle<JSDate>(res); EXPECT_TRUE(resDate->GetTimeValue() == JSTaggedValue(tm)) << "Not Same Time Value"; Destroy(); } void JSMapTest(std::pair<uint8_t *, size_t> data, const JSHandle<JSMap> &originMap) { Init(); JSDeserializer deserializer(thread, data.first, data.second); JSHandle<JSTaggedValue> res = deserializer.Deserialize(); EXPECT_TRUE(!res.IsEmpty()) << "[Empty] Deserialize JSMap fail"; EXPECT_TRUE(res->IsJSMap()) << "[NotJSMap] Deserialize JSMap fail"; JSHandle<JSMap> resMap = JSHandle<JSMap>::Cast(res); EXPECT_TRUE(originMap->GetSize() == resMap->GetSize()) << "the map size Not equal"; uint32_t resSize = static_cast<uint32_t>(resMap->GetSize()); for (uint32_t i = 0; i < resSize; i++) { JSHandle<JSTaggedValue> resKey(thread, resMap->GetKey(i)); JSHandle<JSTaggedValue> resValue(thread, resMap->GetValue(i)); JSHandle<JSTaggedValue> key(thread, originMap->GetKey(i)); JSHandle<JSTaggedValue> value(thread, originMap->GetValue(i)); JSHandle<EcmaString> resKeyStr = JSHandle<EcmaString>::Cast(resKey); JSHandle<EcmaString> keyStr = JSHandle<EcmaString>::Cast(key); EXPECT_TRUE(EcmaStringAccessor::StringsAreEqual(*resKeyStr, *keyStr)) << "Not same map key"; EXPECT_TRUE(JSTaggedValue::ToInt32(thread, resValue) == JSTaggedValue::ToInt32(thread, value)) << "Not same map value"; } Destroy(); } void JSArrayBufferTest(std::pair<uint8_t *, size_t> data, const JSHandle<JSArrayBuffer> &originArrayBuffer, int32_t byteLength, const char *msg) { Init(); JSDeserializer deserializer(thread, data.first, data.second); JSHandle<JSTaggedValue> res = deserializer.Deserialize(); EXPECT_TRUE(!res.IsEmpty()) << "[Empty] Deserialize JSArrayBuffer fail"; EXPECT_TRUE(res->IsArrayBuffer()) << "[NotJSArrayBuffer] Deserialize JSArrayBuffer fail"; JSHandle<JSArrayBuffer> resJSArrayBuffer = JSHandle<JSArrayBuffer>::Cast(res); int32_t resByteLength = static_cast<int32_t>(resJSArrayBuffer->GetArrayBufferByteLength()); EXPECT_TRUE(resByteLength == byteLength) << "Not Same ByteLength"; // 10 : test case JSHandle<JSTaggedValue> bufferData(thread, originArrayBuffer->GetArrayBufferData()); auto np = JSHandle<JSNativePointer>::Cast(bufferData); void *buffer = np->GetExternalPointer(); ASSERT_NE(buffer, nullptr); JSHandle<JSTaggedValue> resBufferData(thread, resJSArrayBuffer->GetArrayBufferData()); JSHandle<JSNativePointer> resNp = JSHandle<JSNativePointer>::Cast(resBufferData); void *resBuffer = resNp->GetExternalPointer(); ASSERT_NE(resBuffer, nullptr); for (int32_t i = 0; i < resByteLength; i++) { EXPECT_TRUE(static_cast<char *>(resBuffer)[i] == static_cast<char *>(buffer)[i]) << "Not Same Buffer"; } if (msg != nullptr) { if (memcpy_s(resBuffer, byteLength, msg, byteLength) != EOK) { EXPECT_TRUE(false) << " memcpy error!"; } } Destroy(); } void JSSharedArrayBufferTest(std::pair<uint8_t *, size_t> data, const JSHandle<JSArrayBuffer> &originArrayBuffer, int32_t byteLength, const char *msg) { Init(); JSDeserializer deserializer(thread, data.first, data.second); JSHandle<JSTaggedValue> res = deserializer.Deserialize(); EXPECT_TRUE(!res.IsEmpty()) << "[Empty] Deserialize JSArrayBuffer fail"; EXPECT_TRUE(res->IsSharedArrayBuffer()) << "[NotJSArrayBuffer] Deserialize JSArrayBuffer fail"; JSHandle<JSArrayBuffer> resJSArrayBuffer = JSHandle<JSArrayBuffer>::Cast(res); int32_t resByteLength = static_cast<int32_t>(resJSArrayBuffer->GetArrayBufferByteLength()); EXPECT_TRUE(resByteLength == byteLength) << "Not Same ByteLength"; JSHandle<JSTaggedValue> bufferData(thread, originArrayBuffer->GetArrayBufferData()); auto np = JSHandle<JSNativePointer>::Cast(bufferData); void *buffer = np->GetExternalPointer(); ASSERT_NE(buffer, nullptr); JSHandle<JSTaggedValue> resBufferData(thread, resJSArrayBuffer->GetArrayBufferData()); JSHandle<JSNativePointer> resNp = JSHandle<JSNativePointer>::Cast(resBufferData); void *resBuffer = resNp->GetExternalPointer(); ASSERT_NE(resBuffer, nullptr); EXPECT_TRUE((uint64_t)buffer == (uint64_t)resBuffer) << "Not Same pointer!"; for (int32_t i = 0; i < resByteLength; i++) { EXPECT_TRUE(static_cast<char *>(resBuffer)[i] == static_cast<char *>(buffer)[i]) << "Not Same Buffer"; } if (msg != nullptr) { if (memcpy_s(resBuffer, byteLength, msg, byteLength) != EOK) { EXPECT_TRUE(false) << " memcpy error!"; } } Destroy(); } void JSSharedArrayBufferTest1(std::pair<uint8_t *, size_t> data, int32_t byteLength, const char *msg) { Init(); JSDeserializer deserializer(thread, data.first, data.second); JSHandle<JSTaggedValue> res = deserializer.Deserialize(); EXPECT_TRUE(!res.IsEmpty()) << "[Empty] Deserialize JSArrayBuffer fail"; EXPECT_TRUE(res->IsSharedArrayBuffer()) << "[NotJSArrayBuffer] Deserialize JSArrayBuffer fail"; JSHandle<JSArrayBuffer> resJSArrayBuffer = JSHandle<JSArrayBuffer>::Cast(res); JSHandle<JSTaggedValue> resBufferData(thread, resJSArrayBuffer->GetArrayBufferData()); JSHandle<JSNativePointer> resNp = JSHandle<JSNativePointer>::Cast(resBufferData); void *resBuffer = resNp->GetExternalPointer(); if (msg != nullptr) { if (memcpy_s(resBuffer, byteLength, msg, byteLength) != EOK) { EXPECT_TRUE(false) << " memcpy error!"; } } Destroy(); } void JSRegexpTest(std::pair<uint8_t *, size_t> data) { Init(); JSHandle<EcmaString> pattern = thread->GetEcmaVM()->GetFactory()->NewFromASCII("key2"); JSHandle<EcmaString> flags = thread->GetEcmaVM()->GetFactory()->NewFromASCII("i"); char buffer[] = "1234567"; // use char buffer to simulate byteCodeBuffer uint32_t bufferSize = 7; JSDeserializer deserializer(thread, data.first, data.second); JSHandle<JSTaggedValue> res = deserializer.Deserialize(); EXPECT_TRUE(!res.IsEmpty()) << "[Empty] Deserialize JSRegExp fail"; EXPECT_TRUE(res->IsJSRegExp()) << "[NotJSRegexp] Deserialize JSRegExp fail"; JSHandle<JSRegExp> resJSRegexp(res); uint32_t resBufferSize = resJSRegexp->GetLength(); EXPECT_TRUE(resBufferSize == bufferSize) << "Not Same Length"; JSHandle<JSTaggedValue> originalSource(thread, resJSRegexp->GetOriginalSource()); EXPECT_TRUE(originalSource->IsString()); JSHandle<JSTaggedValue> originalFlags(thread, resJSRegexp->GetOriginalFlags()); EXPECT_TRUE(originalFlags->IsString()); EXPECT_TRUE(EcmaStringAccessor::StringsAreEqual(*JSHandle<EcmaString>(originalSource), *pattern)); EXPECT_TRUE(EcmaStringAccessor::StringsAreEqual(*JSHandle<EcmaString>(originalFlags), *flags)); JSHandle<JSTaggedValue> resBufferData(thread, resJSRegexp->GetByteCodeBuffer()); JSHandle<JSNativePointer> resNp = JSHandle<JSNativePointer>::Cast(resBufferData); void *resBuffer = resNp->GetExternalPointer(); ASSERT_NE(resBuffer, nullptr); for (uint32_t i = 0; i < resBufferSize; i++) { EXPECT_TRUE(static_cast<char *>(resBuffer)[i] == buffer[i]) << "Not Same ByteCode"; } Destroy(); } void TypedArrayTest1(std::pair<uint8_t *, size_t> data) { Init(); JSHandle<JSTaggedValue> originTypedArrayName(thread, thread->GlobalConstants()->GetInt8ArrayString()); JSDeserializer deserializer(thread, data.first, data.second); JSHandle<JSTaggedValue> res = deserializer.Deserialize(); EXPECT_TRUE(!res.IsEmpty()) << "[Empty] Deserialize TypedArray fail"; EXPECT_TRUE(res->IsJSInt8Array()) << "[NotJSInt8Array] Deserialize TypedArray fail"; JSHandle<JSTypedArray> resJSInt8Array = JSHandle<JSTypedArray>::Cast(res); JSHandle<JSTaggedValue> typedArrayName(thread, resJSInt8Array->GetTypedArrayName()); uint32_t byteLength = resJSInt8Array->GetByteLength(); uint32_t byteOffset = resJSInt8Array->GetByteOffset(); uint32_t arrayLength = resJSInt8Array->GetArrayLength(); ContentType contentType = resJSInt8Array->GetContentType(); JSHandle<JSTaggedValue> viewedArrayBuffer(thread, resJSInt8Array->GetViewedArrayBufferOrByteArray()); EXPECT_TRUE(typedArrayName->IsString()); EXPECT_TRUE(EcmaStringAccessor::StringsAreEqual(*JSHandle<EcmaString>(typedArrayName), *JSHandle<EcmaString>(originTypedArrayName))); EXPECT_EQ(byteLength, 10) << "Not Same ByteLength"; // 10: bufferLength EXPECT_EQ(byteOffset, 0) << "Not Same ByteOffset"; EXPECT_EQ(arrayLength, 10) << "Not Same ArrayLength"; // 10: arrayLength EXPECT_TRUE(contentType == ContentType::Number) << "Not Same ContentType"; // check arrayBuffer EXPECT_TRUE(viewedArrayBuffer->IsArrayBuffer()); JSHandle<JSArrayBuffer> resJSArrayBuffer(viewedArrayBuffer); uint32_t resTaggedLength = resJSArrayBuffer->GetArrayBufferByteLength(); EXPECT_EQ(resTaggedLength, 10) << "Not same viewedBuffer length"; // 10: bufferLength JSHandle<JSTaggedValue> resBufferData(thread, resJSArrayBuffer->GetArrayBufferData()); JSHandle<JSNativePointer> resNp = JSHandle<JSNativePointer>::Cast(resBufferData); void *resBuffer = resNp->GetExternalPointer(); for (uint32_t i = 0; i < resTaggedLength; i++) { EXPECT_EQ(static_cast<uint8_t *>(resBuffer)[i], i) << "Not same viewedBuffer"; } Destroy(); } void TypedArrayTest2(std::pair<uint8_t *, size_t> data) { Init(); JSHandle<JSTaggedValue> originTypedArrayName(thread, thread->GlobalConstants()->GetInt8ArrayString()); JSDeserializer deserializer(thread, data.first, data.second); JSHandle<JSTaggedValue> res = deserializer.Deserialize(); EXPECT_TRUE(!res.IsEmpty()) << "[Empty] Deserialize TypedArray fail"; EXPECT_TRUE(res->IsJSInt8Array()) << "[NotJSInt8Array] Deserialize TypedArray fail"; JSHandle<JSTypedArray> resJSInt8Array = JSHandle<JSTypedArray>::Cast(res); JSHandle<JSTaggedValue> typedArrayName(thread, resJSInt8Array->GetTypedArrayName()); uint32_t byteLength = resJSInt8Array->GetByteLength(); uint32_t byteOffset = resJSInt8Array->GetByteOffset(); uint32_t arrayLength = resJSInt8Array->GetArrayLength(); ContentType contentType = resJSInt8Array->GetContentType(); JSHandle<JSTaggedValue> byteArray(thread, resJSInt8Array->GetViewedArrayBufferOrByteArray()); EXPECT_TRUE(typedArrayName->IsString()); EXPECT_TRUE(EcmaStringAccessor::StringsAreEqual(*JSHandle<EcmaString>(typedArrayName), *JSHandle<EcmaString>(originTypedArrayName))); EXPECT_EQ(byteLength, 10) << "Not Same ByteLength"; // 10: bufferLength EXPECT_EQ(byteOffset, 0) << "Not Same ByteOffset"; EXPECT_EQ(arrayLength, 10) << "Not Same ArrayLength"; // 10: arrayLength EXPECT_TRUE(contentType == ContentType::Number) << "Not Same ContentType"; // check byteArray EXPECT_TRUE(byteArray->IsByteArray()); JSHandle<ByteArray> resByteArray(byteArray); uint32_t resTaggedLength = resByteArray->GetArrayLength(); EXPECT_EQ(resTaggedLength, 10) << "Not same viewedBuffer length"; // 10: bufferLength uint32_t resElementSize = resByteArray->GetByteLength(); EXPECT_EQ(resElementSize, 1) << "Not same byteArray size"; for (uint32_t i = 0; i < resTaggedLength; i++) { JSHandle<JSTaggedValue> taggedVal(thread, resByteArray->Get(thread, i, DataViewType::UINT8)); int32_t byteArrayVal = JSTaggedValue::ToInt32(thread, taggedVal); EXPECT_EQ(byteArrayVal, 255) << "Not same byteArray value"; // 255: value in byteArray } Destroy(); } void TaggedArrayTest(std::pair<uint8_t *, size_t> data) { Init(); JSDeserializer deserializer(thread, data.first, data.second); JSHandle<JSTaggedValue> res = deserializer.Deserialize(); EXPECT_TRUE(!res.IsEmpty()) << "[Empty] Deserialize TaggedArray fail"; EXPECT_TRUE(res.GetTaggedValue().IsTaggedArray()) << "[NotTaggedArray] Deserialize TaggedArray fail"; // check taggedArray JSHandle<TaggedArray> taggedArray = JSHandle<TaggedArray>::Cast(res); EXPECT_EQ(taggedArray->GetLength(), 4U); // 4 : test case EcmaString *str11 = reinterpret_cast<EcmaString *>(taggedArray->Get(0).GetTaggedObject()); EcmaString *str22 = reinterpret_cast<EcmaString *>(taggedArray->Get(1).GetTaggedObject()); EXPECT_EQ(std::strcmp(EcmaStringAccessor(str11).ToCString().c_str(), "str11"), 0); EXPECT_EQ(std::strcmp(EcmaStringAccessor(str22).ToCString().c_str(), "str22"), 0); EXPECT_TRUE(taggedArray->Get(2).IsUndefined()); // 2: the second index Destroy(); } void MethodTest(std::pair<uint8_t *, size_t> data) { Init(); JSDeserializer deserializer(thread, data.first, data.second); JSHandle<JSTaggedValue> res = deserializer.Deserialize(); EXPECT_TRUE(!res.IsEmpty()) << "[Empty] Deserialize Method fail"; EXPECT_TRUE(res.GetTaggedValue().IsMethod()) << "[NotMethod] Deserialize Method fail"; JSHandle<Method> method = JSHandle<Method>::Cast(res); EXPECT_TRUE(method->IsNativeWithCallField()); Destroy(); } void MethodTest1(std::pair<uint8_t *, size_t> data) { Init(); JSDeserializer deserializer(thread, data.first, data.second); JSHandle<JSTaggedValue> res = deserializer.Deserialize(); EXPECT_TRUE(!res.IsEmpty()) << "[Empty] Deserialize Method fail"; EXPECT_TRUE(res.GetTaggedValue().IsMethod()) << "[NotMethod] Deserialize Method fail"; JSHandle<Method> method = JSHandle<Method>::Cast(res); EXPECT_FALSE(method->IsNativeWithCallField()); JSHandle<ConstantPool> constpool(thread, method->GetConstantPool()); EXPECT_EQ(constpool->GetLength(), 6U); EXPECT_EQ(constpool->GetCacheLength(), 4U); const JSPandaFile *jsPandaFile = constpool->GetJSPandaFile(); EXPECT_TRUE(jsPandaFile != nullptr); const CString &desc = jsPandaFile->GetJSPandaFileDesc(); EXPECT_EQ(desc, "test.pa"); Destroy(); } void AOTMethodTest(std::pair<uint8_t *, size_t> data) { Init(); JSDeserializer deserializer(thread, data.first, data.second); JSHandle<JSTaggedValue> res = deserializer.Deserialize(); EXPECT_TRUE(!res.IsEmpty()) << "[Empty] Deserialize Method fail"; EXPECT_TRUE(res.GetTaggedValue().IsMethod()) << "[NotMethod] Deserialize Method fail"; JSHandle<Method> method = JSHandle<Method>::Cast(res); EXPECT_FALSE(method->IsNativeWithCallField()); EXPECT_TRUE(method->IsAotWithCallField()); EXPECT_TRUE(method->IsFastCall()); uintptr_t codeEntry = method->GetCodeEntryOrLiteral(); EXPECT_EQ(codeEntry, 0x1234); Destroy(); } void ConcurrentFunctionTest(std::pair<uint8_t *, size_t> data) { Init(); JSDeserializer deserializer(thread, data.first, data.second); JSHandle<JSTaggedValue> res = deserializer.Deserialize(); EXPECT_TRUE(!res.IsEmpty()) << "[Empty] Deserialize ConcurrentFunction fail"; EXPECT_TRUE(res->IsJSFunction()) << "[NotJSFunction] Deserialize ConcurrentFunction fail"; Destroy(); } void BigIntTest(std::pair<uint8_t *, size_t> data) { Init(); JSDeserializer deserialzier(thread, data.first, data.second); JSHandle<JSTaggedValue> res1 = deserialzier.Deserialize(); JSHandle<JSTaggedValue> res2 = deserialzier.Deserialize(); JSHandle<JSTaggedValue> res3 = deserialzier.Deserialize(); JSHandle<JSTaggedValue> res4 = deserialzier.Deserialize(); JSHandle<JSTaggedValue> res5 = deserialzier.Deserialize(); JSHandle<JSTaggedValue> res6 = deserialzier.Deserialize(); JSHandle<JSTaggedValue> res7 = deserialzier.Deserialize(); JSHandle<JSTaggedValue> res8 = deserialzier.Deserialize(); JSHandle<JSTaggedValue> res9 = deserialzier.Deserialize(); JSHandle<JSTaggedValue> res10 = deserialzier.Deserialize(); JSHandle<JSTaggedValue> res11 = deserialzier.Deserialize(); JSHandle<JSTaggedValue> res12 = deserialzier.Deserialize(); JSHandle<JSTaggedValue> res13 = deserialzier.Deserialize(); JSHandle<JSTaggedValue> res14 = deserialzier.Deserialize(); EXPECT_TRUE(!res1.IsEmpty() && !res14.IsEmpty()) << "[Empty] Deserialize BigInt fail"; EXPECT_TRUE(res3->IsBigInt() && res12->IsBigInt()) << "[NotBigInt] Deserialize BigInt fail"; CString str1 = "100000000000000000000000000000000000000000000000000000"; // Binary: 2 ^ 53 CString str2 = "111111111111111111111111111111111111111111111111111111"; // Binary: 2 ^ 54 - 1 CString str3 = "-9007199254740991012345"; CString str4 = "1234567890987654321"; // Decimal JSHandle<BigInt> bigInt1 = BigIntHelper::SetBigInt(thread, str1); JSHandle<BigInt> bigInt2 = BigIntHelper::SetBigInt(thread, str2); JSHandle<BigInt> bigInt3 = BigIntHelper::SetBigInt(thread, str3); JSHandle<BigInt> bigInt4 = BigInt::Uint32ToBigInt(thread, 0); // 0 : test case JSHandle<BigInt> bigInt5 = BigIntHelper::SetBigInt(thread, str4, BigInt::DECIMAL); JSHandle<BigInt> bigInt6 = BigInt::Uint64ToBigInt(thread, ULLONG_MAX); JSHandle<BigInt> bigInt7 = BigInt::Uint64ToBigInt(thread, UINT_MAX); JSHandle<BigInt> bigInt8 = BigInt::Uint32ToBigInt(thread, std::numeric_limits<uint32_t>::max()); JSHandle<BigInt> bigInt9 = BigInt::Uint32ToBigInt(thread, std::numeric_limits<uint32_t>::min()); JSHandle<BigInt> bigInt10 = BigInt::Int64ToBigInt(thread, LLONG_MAX); JSHandle<BigInt> bigInt11 = BigInt::Int64ToBigInt(thread, LLONG_MIN); JSHandle<BigInt> bigInt12 = BigInt::Int64ToBigInt(thread, INT_MAX); JSHandle<BigInt> bigInt13 = BigInt::Int64ToBigInt(thread, INT_MIN); JSHandle<BigInt> bigInt14 = BigInt::Int32ToBigInt(thread, -1); // -1 : test case EXPECT_TRUE(BigInt::Equal(res1.GetTaggedValue(), bigInt1.GetTaggedValue())) << "Not Same BigInt"; EXPECT_TRUE(BigInt::Equal(res2.GetTaggedValue(), bigInt2.GetTaggedValue())) << "Not Same BigInt"; EXPECT_TRUE(BigInt::Equal(res3.GetTaggedValue(), bigInt3.GetTaggedValue())) << "Not Same BigInt"; EXPECT_TRUE(BigInt::Equal(res4.GetTaggedValue(), bigInt4.GetTaggedValue())) << "Not Same BigInt"; EXPECT_TRUE(BigInt::Equal(res5.GetTaggedValue(), bigInt5.GetTaggedValue())) << "Not Same BigInt"; EXPECT_TRUE(BigInt::Equal(res6.GetTaggedValue(), bigInt6.GetTaggedValue())) << "Not Same BigInt"; EXPECT_TRUE(BigInt::Equal(res7.GetTaggedValue(), bigInt7.GetTaggedValue())) << "Not Same BigInt"; EXPECT_TRUE(BigInt::Equal(res8.GetTaggedValue(), bigInt8.GetTaggedValue())) << "Not Same BigInt"; EXPECT_TRUE(BigInt::Equal(res9.GetTaggedValue(), bigInt9.GetTaggedValue())) << "Not Same BigInt"; EXPECT_TRUE(BigInt::Equal(res10.GetTaggedValue(), bigInt10.GetTaggedValue())) << "Not Same BigInt"; EXPECT_TRUE(BigInt::Equal(res11.GetTaggedValue(), bigInt11.GetTaggedValue())) << "Not Same BigInt"; EXPECT_TRUE(BigInt::Equal(res12.GetTaggedValue(), bigInt12.GetTaggedValue())) << "Not Same BigInt"; EXPECT_TRUE(BigInt::Equal(res13.GetTaggedValue(), bigInt13.GetTaggedValue())) << "Not Same BigInt"; EXPECT_TRUE(BigInt::Equal(res14.GetTaggedValue(), bigInt14.GetTaggedValue())) << "Not Same BigInt"; Destroy(); } void ObjectWithConcurrentFunctionTest(std::pair<uint8_t *, size_t> data) { Init(); ObjectFactory *factory = ecmaVm->GetFactory(); JSDeserializer deserializer(thread, data.first, data.second); JSHandle<JSTaggedValue> res = deserializer.Deserialize(); EXPECT_TRUE(!res.IsEmpty()) << "[Empty] Deserialize ObjectWithConcurrentFunction fail"; EXPECT_TRUE(res->IsObject()) << "[NotObjectWithConcurrentFunction] Deserialize ObjectWithConcurrentFunction fail"; JSHandle<JSTaggedValue> key1(factory->NewFromASCII("2")); OperationResult result1 = JSObject::GetProperty(thread, res, key1); JSHandle<JSTaggedValue> value1 = result1.GetRawValue(); EXPECT_TRUE(value1->IsJSFunction()); JSHandle<JSTaggedValue> key2(factory->NewFromASCII("abc")); OperationResult result2 = JSObject::GetProperty(thread, res, key2); JSHandle<JSTaggedValue> value2 = result2.GetRawValue(); EXPECT_TRUE(value2->IsString()); JSHandle<JSTaggedValue> key3(factory->NewFromASCII("4")); OperationResult result3 = JSObject::GetProperty(thread, res, key3); JSHandle<JSTaggedValue> value3 = result3.GetRawValue(); EXPECT_TRUE(value3->IsJSFunction()); JSHandle<JSTaggedValue> key4(factory->NewFromASCII("key")); OperationResult result4 = JSObject::GetProperty(thread, res, key4); JSHandle<JSTaggedValue> value4 = result4.GetRawValue(); EXPECT_TRUE(value4->IsString()); Destroy(); } void TransferJSArrayBufferTest1(std::pair<uint8_t *, size_t> data, uintptr_t bufferAddrCheck) { Init(); JSDeserializer deserializer(thread, data.first, data.second); JSHandle<JSTaggedValue> res = deserializer.Deserialize(); EXPECT_TRUE(!res.IsEmpty()) << "[Empty] Deserialize TransferJSArrayBuffer1 fail"; EXPECT_TRUE(res->IsArrayBuffer()) << "[NotJSArrayBuffer] Deserialize TransferJSArrayBuffer1 fail"; JSHandle<JSArrayBuffer> arrBuf = JSHandle<JSArrayBuffer>::Cast(res); EXPECT_EQ(arrBuf->GetArrayBufferByteLength(), 5); // 5: bufferLength JSHandle<JSTaggedValue> nativePtr(thread, arrBuf->GetArrayBufferData()); EXPECT_TRUE(nativePtr->IsJSNativePointer()) << "[NotJSNativePointer] Deserialize TransferJSArrayBuffer1 fail"; JSHandle<JSNativePointer> np = JSHandle<JSNativePointer>::Cast(nativePtr); uintptr_t bufferAddr = reinterpret_cast<uintptr_t>(np->GetExternalPointer()); // The deserialized C buffer pointer shall be same to the original one EXPECT_EQ(static_cast<uint64_t>(bufferAddr), static_cast<uint64_t>(bufferAddrCheck)); Destroy(); } void TransferJSArrayBufferTest2(std::pair<uint8_t *, size_t> data, uintptr_t bufferAddrCheck) { Init(); JSDeserializer deserializer(thread, data.first, data.second); JSHandle<JSTaggedValue> res = deserializer.Deserialize(); EXPECT_TRUE(!res.IsEmpty()) << "[Empty] Deserialize TransferJSArrayBuffer2 fail"; EXPECT_TRUE(res->IsArrayBuffer()) << "[NotJSArrayBuffer] Deserialize TransferJSArrayBuffer2 fail"; JSHandle<JSArrayBuffer> arrBuf = JSHandle<JSArrayBuffer>::Cast(res); EXPECT_EQ(arrBuf->GetArrayBufferByteLength(), 5); // 5: bufferLength JSHandle<JSTaggedValue> nativePtr(thread, arrBuf->GetArrayBufferData()); EXPECT_TRUE(nativePtr->IsJSNativePointer()) << "[NotJSNativePointer] Deserialize TransferJSArrayBuffer2 fail"; JSHandle<JSNativePointer> np = JSHandle<JSNativePointer>::Cast(nativePtr); uintptr_t bufferAddr = reinterpret_cast<uintptr_t>(np->GetExternalPointer()); // The deserialized C buffer pointer shall be different to the original one EXPECT_NE(static_cast<uint64_t>(bufferAddr), static_cast<uint64_t>(bufferAddrCheck)); Destroy(); } void TransferJSArrayBufferTest3(std::pair<uint8_t *, size_t> data) { Init(); JSDeserializer deserializer(thread, data.first, data.second); JSHandle<JSTaggedValue> res = deserializer.Deserialize(); EXPECT_TRUE(!res.IsEmpty()) << "[Empty] Deserialize TransferJSArrayBuffer3 fail"; EXPECT_TRUE(res->IsArrayBuffer()) << "[NotJSArrayBuffer] Deserialize TransferJSArrayBuffer3 fail"; JSHandle<JSArrayBuffer> arrBuf = JSHandle<JSArrayBuffer>::Cast(res); EXPECT_EQ(arrBuf->GetArrayBufferByteLength(), 0); JSHandle<JSTaggedValue> nativePtr(thread, arrBuf->GetArrayBufferData()); EXPECT_TRUE(nativePtr->IsUndefined()) << "[NotJSNativePointer] Deserialize TransferJSArrayBuffer3 fail"; Destroy(); } void TransferJSArrayBufferTest4(std::pair<uint8_t *, size_t> data, uintptr_t bufferAddrCheck) { Init(); JSDeserializer deserializer(thread, data.first, data.second); JSHandle<JSTaggedValue> res = deserializer.Deserialize(); EXPECT_TRUE(!res.IsEmpty()) << "[Empty] Deserialize TransferJSArrayBuffer4 fail"; EXPECT_TRUE(res->IsArrayBuffer()) << "[NotJSArrayBuffer] Deserialize TransferJSArrayBuffer4 fail"; JSHandle<JSArrayBuffer> arrBuf = JSHandle<JSArrayBuffer>::Cast(res); EXPECT_EQ(arrBuf->GetArrayBufferByteLength(), 5); // 5: bufferLength JSHandle<JSTaggedValue> nativePtr(thread, arrBuf->GetArrayBufferData()); EXPECT_TRUE(nativePtr->IsJSNativePointer()) << "[NotJSNativePointer] Deserialize TransferJSArrayBuffer4 fail"; JSHandle<JSNativePointer> np = JSHandle<JSNativePointer>::Cast(nativePtr); uintptr_t bufferAddr = reinterpret_cast<uintptr_t>(np->GetExternalPointer()); // The deserialized C buffer pointer shall be same to the original one EXPECT_EQ(static_cast<uint64_t>(bufferAddr), static_cast<uint64_t>(bufferAddrCheck)); Destroy(); } void TransferJSArrayBufferTest5(std::pair<uint8_t *, size_t> data, uintptr_t bufferAddrCheck) { Init(); JSDeserializer deserializer(thread, data.first, data.second); JSHandle<JSTaggedValue> res = deserializer.Deserialize(); EXPECT_TRUE(!res.IsEmpty()) << "[Empty] Deserialize TransferJSArrayBuffer5 fail"; EXPECT_TRUE(res->IsJSInt8Array()) << "[NotJSArrayBuffer] Deserialize TransferJSArrayBuffer5 fail"; JSHandle<JSTypedArray> resJSInt8Array = JSHandle<JSTypedArray>::Cast(res); JSHandle<JSTaggedValue> typedArrayName(thread, resJSInt8Array->GetTypedArrayName()); uint32_t byteLength = resJSInt8Array->GetByteLength(); uint32_t byteOffset = resJSInt8Array->GetByteOffset(); uint32_t arrayLength = resJSInt8Array->GetArrayLength(); ContentType contentType = resJSInt8Array->GetContentType(); JSHandle<JSTaggedValue> viewedArrayBuffer(thread, resJSInt8Array->GetViewedArrayBufferOrByteArray()); EXPECT_EQ(byteLength, 10) << "Not Same ByteLength"; // 10: bufferLength EXPECT_EQ(byteOffset, 0) << "Not Same ByteOffset"; EXPECT_EQ(arrayLength, 10) << "Not Same ArrayLength"; // 10: arrayLength EXPECT_TRUE(contentType == ContentType::Number) << "Not Same ContentType"; // check arrayBuffer EXPECT_TRUE(viewedArrayBuffer->IsArrayBuffer()); JSHandle<JSArrayBuffer> resJSArrayBuffer(viewedArrayBuffer); uint32_t resTaggedLength = resJSArrayBuffer->GetArrayBufferByteLength(); EXPECT_EQ(resTaggedLength, 10) << "Not same viewedBuffer length"; // 10: bufferLength JSHandle<JSTaggedValue> resBufferData(thread, resJSArrayBuffer->GetArrayBufferData()); JSHandle<JSNativePointer> resNp = JSHandle<JSNativePointer>::Cast(resBufferData); void *resBuffer = resNp->GetExternalPointer(); for (uint32_t i = 0; i < resTaggedLength; i++) { EXPECT_EQ(static_cast<uint8_t *>(resBuffer)[i], i) << "Not same viewedBuffer"; } JSHandle<JSTaggedValue> nativePtr(thread, resJSArrayBuffer->GetArrayBufferData()); EXPECT_TRUE(nativePtr->IsJSNativePointer()) << "[NotJSNativePointer] Deserialize TransferJSArrayBuffer5 fail"; JSHandle<JSNativePointer> np = JSHandle<JSNativePointer>::Cast(nativePtr); uintptr_t bufferAddr = reinterpret_cast<uintptr_t>(np->GetExternalPointer()); // The deserialized C buffer pointer shall be same to the original one EXPECT_EQ(static_cast<uint64_t>(bufferAddr), static_cast<uint64_t>(bufferAddrCheck)); Destroy(); } private: EcmaVM *ecmaVm = nullptr; EcmaHandleScope *scope = nullptr; JSThread *thread = nullptr; }; class JSSerializerTest : public testing::Test { public: static void SetUpTestCase() { GTEST_LOG_(INFO) << "SetUpTestCase"; } static void TearDownTestCase() { GTEST_LOG_(INFO) << "TearDownCase"; } void SetUp() override { TestHelper::CreateEcmaVMWithScope(ecmaVm, thread, scope); } void TearDown() override { TestHelper::DestroyEcmaVMWithScope(ecmaVm, scope); } JSThread *thread {nullptr}; EcmaVM *ecmaVm {nullptr}; EcmaHandleScope *scope {nullptr}; }; HWTEST_F_L0(JSSerializerTest, SerializeJSSpecialValue) { JSSerializer *serializer = new JSSerializer(thread); JSHandle<JSTaggedValue> jsTrue(thread, JSTaggedValue::True()); JSHandle<JSTaggedValue> jsFalse(thread, JSTaggedValue::False()); JSHandle<JSTaggedValue> jsUndefined(thread, JSTaggedValue::Undefined()); JSHandle<JSTaggedValue> jsNull(thread, JSTaggedValue::Null()); JSHandle<JSTaggedValue> jsHole(thread, JSTaggedValue::Hole()); serializer->SerializeJSTaggedValue(jsTrue); serializer->SerializeJSTaggedValue(jsFalse); serializer->SerializeJSTaggedValue(jsUndefined); serializer->SerializeJSTaggedValue(jsNull); serializer->SerializeJSTaggedValue(jsHole); std::pair<uint8_t *, size_t> data = serializer->ReleaseBuffer(); JSDeserializerTest jsDeserializerTest; std::thread t1(&JSDeserializerTest::JSSpecialValueTest, jsDeserializerTest, data); t1.join(); delete serializer; }; HWTEST_F_L0(JSSerializerTest, SerializeJSPlainObject1) { ObjectFactory *factory = ecmaVm->GetFactory(); JSHandle<JSObject> obj1 = factory->NewEmptyJSObject(); JSHandle<JSObject> obj2 = factory->NewEmptyJSObject(); JSHandle<JSTaggedValue> key1(factory->NewFromASCII("2")); JSHandle<JSTaggedValue> key2(factory->NewFromASCII("3")); JSHandle<JSTaggedValue> key3(factory->NewFromASCII("x")); JSHandle<JSTaggedValue> key4(factory->NewFromASCII("y")); JSHandle<JSTaggedValue> key5(factory->NewFromASCII("a")); JSHandle<JSTaggedValue> key6(factory->NewFromASCII("b")); JSHandle<JSTaggedValue> key7(factory->NewFromASCII("5")); JSHandle<JSTaggedValue> key8(factory->NewFromASCII("6")); JSHandle<JSTaggedValue> value1(thread, JSTaggedValue(1)); JSHandle<JSTaggedValue> value2(thread, JSTaggedValue(2)); JSHandle<JSTaggedValue> value3(thread, JSTaggedValue(3)); JSHandle<JSTaggedValue> value4(thread, JSTaggedValue(4)); JSHandle<JSTaggedValue> value5(thread, JSTaggedValue(5)); JSHandle<JSTaggedValue> value6(thread, JSTaggedValue(6)); JSHandle<JSTaggedValue> value7(thread, JSTaggedValue(7)); JSHandle<JSTaggedValue> value8(thread, JSTaggedValue(8)); JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj1), key1, value1); JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj1), key2, value2); JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj1), key3, value3); JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj1), key4, value4); JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj2), key5, value5); JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj2), key6, value6); JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj2), key7, value7); JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj2), key8, value8); JSSerializer *serializer = new JSSerializer(thread); bool success1 = serializer->SerializeJSTaggedValue(JSHandle<JSTaggedValue>::Cast(obj1)); bool success2 = serializer->SerializeJSTaggedValue(JSHandle<JSTaggedValue>::Cast(obj2)); EXPECT_TRUE(success1); EXPECT_TRUE(success2); std::pair<uint8_t *, size_t> data = serializer->ReleaseBuffer(); JSDeserializerTest jsDeserializerTest; std::thread t1(&JSDeserializerTest::JSPlainObjectTest1, jsDeserializerTest, data); t1.join(); delete serializer; }; HWTEST_F_L0(JSSerializerTest, SerializeJSPlainObject2) { ObjectFactory *factory = ecmaVm->GetFactory(); JSHandle<JSObject> obj1 = factory->NewEmptyJSObject(); JSHandle<JSObject> obj2 = factory->NewEmptyJSObject(); JSHandle<JSTaggedValue> key1(factory->NewFromASCII("diagnosisItem")); JSHandle<JSTaggedValue> key2(factory->NewFromASCII("detectStatus")); JSHandle<JSTaggedValue> key3(factory->NewFromASCII("detectResultItems")); JSHandle<JSTaggedValue> key4(factory->NewFromASCII("faultId")); JSHandle<JSTaggedValue> key5(factory->NewFromASCII("faultContent")); JSHandle<JSTaggedValue> key6(factory->NewFromASCII("faultContentParams")); JSHandle<JSTaggedValue> key7(factory->NewFromASCII("adviceId")); JSHandle<JSTaggedValue> key8(factory->NewFromASCII("adviceContent")); JSHandle<JSTaggedValue> key9(factory->NewFromASCII("adviceContentParams")); JSHandle<JSTaggedValue> value1 = JSHandle<JSTaggedValue>::Cast(factory->NewFromASCII("VoiceDetect1")); JSHandle<JSTaggedValue> value2(thread, JSTaggedValue(1)); JSHandle<JSTaggedValue> value3 = JSHandle<JSTaggedValue>::Cast(factory->NewJSArray()); JSHandle<JSTaggedValue> value4 = JSHandle<JSTaggedValue>::Cast(factory->NewFromASCII("80000001")); JSHandle<JSTaggedValue> value5 = JSHandle<JSTaggedValue>::Cast(factory->GetEmptyString()); JSHandle<JSTaggedValue> value6 = JSHandle<JSTaggedValue>::Cast(factory->NewJSArray()); JSHandle<JSTaggedValue> value7 = JSHandle<JSTaggedValue>::Cast(factory->GetEmptyString()); JSHandle<JSTaggedValue> value8 = JSHandle<JSTaggedValue>::Cast(factory->GetEmptyString()); JSHandle<JSTaggedValue> value9 = JSHandle<JSTaggedValue>::Cast(factory->NewJSArray()); JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj2), key4, value4); JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj2), key5, value5); JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj2), key6, value6); JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj2), key7, value7); JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj2), key8, value8); JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj2), key9, value9); JSArray::FastSetPropertyByValue(thread, value3, 0, JSHandle<JSTaggedValue>(obj2)); JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj1), key1, value1); JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj1), key2, value2); JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj1), key3, value3); JSSerializer *serializer = new JSSerializer(thread); bool success1 = serializer->SerializeJSTaggedValue(JSHandle<JSTaggedValue>::Cast(obj1)); EXPECT_TRUE(success1); std::pair<uint8_t *, size_t> data = serializer->ReleaseBuffer(); JSDeserializerTest jsDeserializerTest; std::thread t1(&JSDeserializerTest::JSPlainObjectTest2, jsDeserializerTest, data); t1.join(); delete serializer; }; HWTEST_F_L0(JSSerializerTest, SerializeJSPlainObject3) { ObjectFactory *factory = ecmaVm->GetFactory(); const uint32_t numOfProps = 2; JSHandle<LayoutInfo> layout = factory->CreateLayoutInfo(numOfProps); JSHandle<JSTaggedValue> key0(factory->NewFromASCII("x")); PropertyAttributes attributes0 = PropertyAttributes::Default(); attributes0.SetIsInlinedProps(true); attributes0.SetRepresentation(Representation::NONE); attributes0.SetOffset(0); layout->AddKey(thread, 0, key0.GetTaggedValue(), attributes0); JSHandle<JSTaggedValue> key1(factory->NewFromASCII("y")); PropertyAttributes attributes1 = PropertyAttributes::Default(); attributes1.SetIsInlinedProps(true); attributes1.SetRepresentation(Representation::NONE); attributes1.SetOffset(1); layout->AddKey(thread, 1, key1.GetTaggedValue(), attributes1); JSHandle<JSHClass> hclass = factory->NewEcmaHClass(JSObject::SIZE, JSType::JS_OBJECT, numOfProps); hclass->SetLayout(thread, layout); hclass->SetNumberOfProps(numOfProps); hclass->SetTS(true); JSHandle<JSObject> obj = factory->NewJSObject(hclass); JSHandle<JSTaggedValue> value1(thread, JSTaggedValue(10)); JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj), key1, value1); JSSerializer *serializer = new JSSerializer(thread); bool success = serializer->SerializeJSTaggedValue(JSHandle<JSTaggedValue>::Cast(obj)); EXPECT_TRUE(success); std::pair<uint8_t *, size_t> data = serializer->ReleaseBuffer(); JSDeserializerTest jsDeserializerTest; std::thread t1(&JSDeserializerTest::JSPlainObjectTest3, jsDeserializerTest, data); t1.join(); delete serializer; } static void* detach(void *param1, void *param2, void *hint) { GTEST_LOG_(INFO) << "detach is running"; if (param1 == nullptr && param2 == nullptr) { GTEST_LOG_(INFO) << "detach: two params is nullptr"; } if (hint == nullptr) { GTEST_LOG_(INFO) << "detach: hint is nullptr"; } return nullptr; } static void* attach([[maybe_unused]] void *enginePointer, [[maybe_unused]] void *buffer, [[maybe_unused]] void *hint) { GTEST_LOG_(INFO) << "attach is running"; return nullptr; } static panda::JSNApi::NativeBindingInfo* CreateNativeBindingInfo(void* attach, void* detach) { GTEST_LOG_(INFO) << "CreateNativeBindingInfo"; auto info = panda::JSNApi::NativeBindingInfo::CreateNewInstance(); info->attachFunc = attach; info->detachFunc = detach; return info; } HWTEST_F_L0(JSSerializerTest, SerializeNativeBindingObject1) { ObjectFactory *factory = ecmaVm->GetFactory(); JSHandle<GlobalEnv> env = ecmaVm->GetGlobalEnv(); JSHandle<JSObject> obj1 = factory->NewEmptyJSObject(); JSHandle<JSObject> obj2 = factory->NewEmptyJSObject(); JSHandle<JSObject> obj3 = factory->NewEmptyJSObject(); JSHandle<JSTaggedValue> key1 = env->GetNativeBindingSymbol(); JSHandle<JSTaggedValue> key2(factory->NewFromASCII("x")); JSHandle<JSTaggedValue> key3(factory->NewFromASCII("y")); JSHandle<JSTaggedValue> key4(factory->NewFromASCII("a")); JSHandle<JSTaggedValue> key5(factory->NewFromASCII("b")); JSHandle<JSTaggedValue> key6(factory->NewFromASCII("5")); JSHandle<JSTaggedValue> key7(factory->NewFromASCII("6")); auto info = CreateNativeBindingInfo(reinterpret_cast<void*>(attach), reinterpret_cast<void*>(detach)); JSHandle<JSTaggedValue> value1(factory->NewJSNativePointer(reinterpret_cast<void*>(info))); JSHandle<JSTaggedValue> value2(thread, JSTaggedValue(1)); JSHandle<JSTaggedValue> value3(thread, JSTaggedValue(2)); JSHandle<JSTaggedValue> value4(thread, JSTaggedValue(3)); JSHandle<JSTaggedValue> value5(thread, JSTaggedValue(4)); JSHandle<JSTaggedValue> value6(thread, JSTaggedValue(5)); JSHandle<JSTaggedValue> value7(thread, JSTaggedValue(6)); JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj1), key1, value1); JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj2), key2, value2); JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj2), key3, value3); JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj2), key4, value4); JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj2), key5, value5); JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj2), key6, value6); JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj2), key7, value7); JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj3), key1, value1); JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj3), key2, value2); JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj3), key3, value3); JSSerializer *serializer = new JSSerializer(thread); bool success1 = serializer->SerializeJSTaggedValue(JSHandle<JSTaggedValue>::Cast(obj1)); bool success2 = serializer->SerializeJSTaggedValue(JSHandle<JSTaggedValue>::Cast(obj2)); bool success3 = serializer->SerializeJSTaggedValue(JSHandle<JSTaggedValue>::Cast(obj3)); EXPECT_TRUE(success1); EXPECT_TRUE(success2); EXPECT_TRUE(success3); std::pair<uint8_t *, size_t> data = serializer->ReleaseBuffer(); JSDeserializerTest jsDeserializerTest; std::thread t1(&JSDeserializerTest::NativeBindingObjectTest1, jsDeserializerTest, data); t1.join(); delete serializer; } // not support native object without detach and attach HWTEST_F_L0(JSSerializerTest, SerializeNativeBindingObject2) { ObjectFactory *factory = ecmaVm->GetFactory(); JSHandle<GlobalEnv> env = ecmaVm->GetGlobalEnv(); JSHandle<JSObject> obj1 = factory->NewEmptyJSObject(); JSHandle<JSObject> obj2 = factory->NewEmptyJSObject(); JSHandle<JSTaggedValue> key1(factory->NewFromASCII("abc")); JSHandle<JSTaggedValue> key2(factory->NewFromASCII("xyz")); JSHandle<JSTaggedValue> key3(factory->NewFromASCII("6")); JSHandle<JSTaggedValue> key4(factory->NewFromASCII("8")); JSHandle<JSTaggedValue> key5 = env->GetNativeBindingSymbol(); JSHandle<JSTaggedValue> value1(thread, JSTaggedValue(6)); JSHandle<JSTaggedValue> value2 = JSHandle<JSTaggedValue>::Cast(factory->NewFromASCII("VALUE")); JSHandle<JSTaggedValue> value3 = JSHandle<JSTaggedValue>::Cast(factory->NewJSArray()); JSHandle<JSTaggedValue> value4 = JSHandle<JSTaggedValue>::Cast(factory->GetEmptyString()); JSHandle<JSTaggedValue> value5(thread, JSTaggedValue::Undefined()); JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj1), key1, value1); JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj1), key2, value2); JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj1), key3, value3); JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj1), key4, value4); JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj2), key5, value5); JSSerializer *serializer = new JSSerializer(thread); bool success1 = serializer->SerializeJSTaggedValue(JSHandle<JSTaggedValue>::Cast(obj1)); bool success2 = serializer->SerializeJSTaggedValue(JSHandle<JSTaggedValue>::Cast(obj2)); EXPECT_TRUE(success1); EXPECT_FALSE(success2); std::pair<uint8_t *, size_t> data = serializer->ReleaseBuffer(); JSDeserializerTest jsDeserializerTest; std::thread t1(&JSDeserializerTest::NativeBindingObjectTest2, jsDeserializerTest, data); t1.join(); delete serializer; } HWTEST_F_L0(JSSerializerTest, SerializeNativeBindingObject3) { ObjectFactory *factory = ecmaVm->GetFactory(); JSHandle<GlobalEnv> env = ecmaVm->GetGlobalEnv(); JSHandle<JSObject> obj1 = factory->NewEmptyJSObject(); JSHandle<JSObject> obj2 = factory->NewEmptyJSObject(); JSHandle<JSTaggedValue> key1 = env->GetNativeBindingSymbol(); JSHandle<JSTaggedValue> key2(factory->NewFromASCII("root1")); JSHandle<JSTaggedValue> key3(factory->NewFromASCII("root2")); JSHandle<JSTaggedValue> key4(factory->NewFromASCII("root3")); JSHandle<JSTaggedValue> key5(factory->NewFromASCII("name")); JSHandle<JSTaggedValue> key6(factory->NewFromASCII("version")); JSHandle<JSTaggedValue> key7(factory->NewFromASCII("product")); JSHandle<JSTaggedValue> key8(factory->NewFromASCII("os")); JSHandle<JSTaggedValue> key9(factory->NewFromASCII("system")); auto info = CreateNativeBindingInfo(reinterpret_cast<void*>(attach), reinterpret_cast<void*>(detach)); JSHandle<JSTaggedValue> value1(factory->NewJSNativePointer(reinterpret_cast<void*>(info))); JSHandle<JSTaggedValue> value2(factory->NewFromASCII("")); JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj1), key1, value1); JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj2), key2, value2); JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj2), key3, value2); JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj2), key4, value2); JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj2), key5, value2); JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj2), key6, value2); JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj2), key7, value2); JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj2), key8, value2); JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj2), key9, value2); JSSerializer *serializer = new JSSerializer(thread); bool success1 = serializer->SerializeJSTaggedValue(JSHandle<JSTaggedValue>::Cast(obj1)); bool success2 = serializer->SerializeJSTaggedValue(JSHandle<JSTaggedValue>::Cast(obj2)); EXPECT_TRUE(success1); EXPECT_TRUE(success2); std::pair<uint8_t *, size_t> data = serializer->ReleaseBuffer(); JSDeserializerTest jsDeserializerTest; std::thread t1(&JSDeserializerTest::NativeBindingObjectTest3, jsDeserializerTest, data); t1.join(); delete serializer; } HWTEST_F_L0(JSSerializerTest, TestSerializeDescription) { ObjectFactory *factory = ecmaVm->GetFactory(); JSHandle<JSObject> obj = factory->NewEmptyJSObject(); JSHandle<JSTaggedValue> key1(factory->NewFromASCII("x")); JSHandle<JSTaggedValue> key2(thread->GetEcmaVM()->GetFactory()->NewFromASCII("y")); PropertyDescriptor desc1(thread); JSHandle<JSTaggedValue> value1(thread, JSTaggedValue(1)); desc1.SetValue(value1); desc1.SetWritable(true); desc1.SetEnumerable(false); desc1.SetConfigurable(true); JSObject::DefineOwnProperty(thread, obj, key1, desc1); PropertyDescriptor desc2(thread); JSHandle<JSTaggedValue> value2(thread, JSTaggedValue(2)); desc2.SetValue(value2); desc2.SetWritable(false); desc2.SetEnumerable(true); desc2.SetConfigurable(false); JSObject::DefineOwnProperty(thread, obj, key2, desc2); JSSerializer *serializer = new JSSerializer(thread); bool success = serializer->SerializeJSTaggedValue(JSHandle<JSTaggedValue>::Cast(obj)); EXPECT_TRUE(success); std::pair<uint8_t *, size_t> data = serializer->ReleaseBuffer(); JSDeserializerTest jsDeserializerTest; std::thread t1(&JSDeserializerTest::DescriptionTest, jsDeserializerTest, data); t1.join(); delete serializer; }; HWTEST_F_L0(JSSerializerTest, TestSerializeJSSet) { ObjectFactory *factory = ecmaVm->GetFactory(); JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv(); JSHandle<JSTaggedValue> constructor = env->GetBuiltinsSetFunction(); JSHandle<JSSet> set = JSHandle<JSSet>::Cast(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(constructor), constructor)); JSHandle<LinkedHashSet> linkedSet = LinkedHashSet::Create(thread); set->SetLinkedSet(thread, linkedSet); // set property to set JSHandle<JSTaggedValue> value1(thread, JSTaggedValue(7)); JSHandle<JSTaggedValue> value2(thread, JSTaggedValue(9)); JSHandle<JSTaggedValue> value3(factory->NewFromASCII("x")); JSHandle<JSTaggedValue> value4(factory->NewFromASCII("y")); JSSet::Add(thread, set, value1); JSSet::Add(thread, set, value2); JSSet::Add(thread, set, value3); JSSet::Add(thread, set, value4); // set property to object JSHandle<JSTaggedValue> key1(factory->NewFromASCII("5")); JSHandle<JSTaggedValue> key2(factory->NewFromASCII("6")); JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(set), key1, value1); JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(set), key2, value2); JSSerializer *serializer = new JSSerializer(thread); bool success = serializer->SerializeJSTaggedValue(JSHandle<JSTaggedValue>::Cast(set)); EXPECT_TRUE(success); std::pair<uint8_t *, size_t> data = serializer->ReleaseBuffer(); JSDeserializerTest jsDeserializerTest; std::thread t1(&JSDeserializerTest::JSSetTest, jsDeserializerTest, data); t1.join(); delete serializer; }; HWTEST_F_L0(JSSerializerTest, TestSerializeJSArray) { ObjectFactory *factory = ecmaVm->GetFactory(); JSHandle<JSArray> array = factory->NewJSArray(); // set property to object JSHandle<JSTaggedValue> key1(factory->NewFromASCII("abasd")); JSHandle<JSTaggedValue> key2(factory->NewFromASCII("qweqwedasd")); JSHandle<JSTaggedValue> value1(thread, JSTaggedValue(7)); JSHandle<JSTaggedValue> value2(thread, JSTaggedValue(9)); JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(array), key1, value1); JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(array), key2, value2); // set value to array array->SetArrayLength(thread, 20); for (int i = 0; i < 20; i++) { JSHandle<JSTaggedValue> data(thread, JSTaggedValue(i)); JSArray::FastSetPropertyByValue(thread, JSHandle<JSTaggedValue>::Cast(array), i, data); } JSSerializer *serializer = new JSSerializer(thread); bool success = serializer->SerializeJSTaggedValue(JSHandle<JSTaggedValue>::Cast(array)); EXPECT_TRUE(success); std::pair<uint8_t *, size_t> data = serializer->ReleaseBuffer(); JSDeserializerTest jsDeserializerTest; std::thread t1(&JSDeserializerTest::JSArrayTest, jsDeserializerTest, data); t1.join(); delete serializer; }; // Test the situation that Objects' properties stores values that reference with each other HWTEST_F_L0(JSSerializerTest, TestObjectsPropertyReference) { ObjectFactory *factory = ecmaVm->GetFactory(); JSHandle<JSObject> obj1 = factory->NewEmptyJSObject(); JSHandle<JSObject> obj2 = factory->NewEmptyJSObject(); [[maybe_unused]] JSHandle<JSObject> obj3 = factory->NewEmptyJSObject(); JSHandle<JSTaggedValue> key1(factory->NewFromASCII("abc")); JSHandle<JSTaggedValue> key2(factory->NewFromASCII("def")); JSHandle<JSTaggedValue> key3(factory->NewFromASCII("dgsdgf")); JSHandle<JSTaggedValue> key4(factory->NewFromASCII("qwjhrf")); JSHandle<JSTaggedValue> value3(thread, JSTaggedValue(10)); JSHandle<JSTaggedValue> value4(thread, JSTaggedValue(5)); // set property to obj1 JSObject::SetProperty(thread, JSHandle<JSTaggedValue>::Cast(obj1), key1, JSHandle<JSTaggedValue>::Cast(obj2)); JSObject::SetProperty(thread, JSHandle<JSTaggedValue>::Cast(obj1), key3, value3); // set property to obj2 JSObject::SetProperty(thread, JSHandle<JSTaggedValue>::Cast(obj2), key2, JSHandle<JSTaggedValue>::Cast(obj1)); JSObject::SetProperty(thread, JSHandle<JSTaggedValue>::Cast(obj2), key4, value4); JSSerializer *serializer = new JSSerializer(thread); bool success1 = serializer->SerializeJSTaggedValue(JSHandle<JSTaggedValue>::Cast(obj1)); bool success2 = serializer->SerializeJSTaggedValue(JSHandle<JSTaggedValue>::Cast(obj2)); EXPECT_TRUE(success1) << "Serialize obj1 fail"; EXPECT_TRUE(success2) << "Serialize obj2 fail"; std::pair<uint8_t *, size_t> data = serializer->ReleaseBuffer(); JSDeserializerTest jsDeserializerTest; std::thread t1(&JSDeserializerTest::ObjectsPropertyReferenceTest, jsDeserializerTest, data); t1.join(); delete serializer; }; HWTEST_F_L0(JSSerializerTest, SerializeEcmaString1) { const char *rawStr = "this is a test ecmaString"; JSHandle<EcmaString> ecmaString = thread->GetEcmaVM()->GetFactory()->NewFromASCII(rawStr); JSSerializer *serializer = new JSSerializer(thread); bool success = serializer->SerializeJSTaggedValue(JSHandle<JSTaggedValue>(ecmaString)); EXPECT_TRUE(success) << "Serialize EcmaString fail"; std::pair<uint8_t *, size_t> data = serializer->ReleaseBuffer(); JSDeserializerTest jsDeserializerTest; std::thread t1(&JSDeserializerTest::EcmaStringTest1, jsDeserializerTest, data); t1.join(); delete serializer; }; HWTEST_F_L0(JSSerializerTest, SerializeEcmaString2) { const char *rawStr = "ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss"\ "sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss"\ "sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss"\ "ssssss"; JSHandle<EcmaString> ecmaString = thread->GetEcmaVM()->GetFactory()->NewFromASCII(rawStr); JSSerializer *serializer = new JSSerializer(thread); bool success = serializer->SerializeJSTaggedValue(JSHandle<JSTaggedValue>(ecmaString)); EXPECT_TRUE(success) << "Serialize EcmaString fail"; std::pair<uint8_t *, size_t> data = serializer->ReleaseBuffer(); JSDeserializerTest jsDeserializerTest; std::thread t1(&JSDeserializerTest::EcmaStringTest2, jsDeserializerTest, data); t1.join(); delete serializer; }; HWTEST_F_L0(JSSerializerTest, SerializeEcmaString3) { JSHandle<EcmaString> ecmaString = thread->GetEcmaVM()->GetFactory()->GetEmptyString(); JSSerializer *serializer = new JSSerializer(thread); bool success = serializer->SerializeJSTaggedValue(JSHandle<JSTaggedValue>(ecmaString)); EXPECT_TRUE(success) << "Serialize EcmaString fail"; std::pair<uint8_t *, size_t> data = serializer->ReleaseBuffer(); JSDeserializerTest jsDeserializerTest; std::thread t1(&JSDeserializerTest::EcmaStringTest3, jsDeserializerTest, data); t1.join(); delete serializer; }; // Test EcmaString contains Chinese Text HWTEST_F_L0(JSSerializerTest, SerializeEcmaString4) { std::string rawStr = "ä½ å¥½ï¼Œä¸–ç•Œ"; JSHandle<EcmaString> ecmaString = thread->GetEcmaVM()->GetFactory()->NewFromStdString(rawStr); JSSerializer *serializer = new JSSerializer(thread); bool success = serializer->SerializeJSTaggedValue(JSHandle<JSTaggedValue>(ecmaString)); EXPECT_TRUE(success) << "Serialize EcmaString fail"; std::pair<uint8_t *, size_t> data = serializer->ReleaseBuffer(); JSDeserializerTest jsDeserializerTest; std::thread t1(&JSDeserializerTest::EcmaStringTest4, jsDeserializerTest, data); t1.join(); delete serializer; }; HWTEST_F_L0(JSSerializerTest, SerializeInt32_t) { JSSerializer *serializer = new JSSerializer(thread); int32_t a = 64, min = -2147483648, b = -63; JSTaggedValue aTag(a), minTag(min), bTag(b); bool success1 = serializer->SerializeJSTaggedValue(JSHandle<JSTaggedValue>(thread, aTag)); bool success2 = serializer->SerializeJSTaggedValue(JSHandle<JSTaggedValue>(thread, minTag)); bool success3 = serializer->SerializeJSTaggedValue(JSHandle<JSTaggedValue>(thread, bTag)); EXPECT_TRUE(success1 && success2 && success3) << "Serialize Int32 fail"; std::pair<uint8_t *, size_t> data = serializer->ReleaseBuffer(); JSDeserializerTest jsDeserializerTest; std::thread t1(&JSDeserializerTest::Int32Test, jsDeserializerTest, data); t1.join(); delete serializer; }; HWTEST_F_L0(JSSerializerTest, SerializeDouble) { JSSerializer *serializer = new JSSerializer(thread); double a = 3.1415926535, b = -3.1415926535; JSTaggedValue aTag(a), bTag(b); bool success1 = serializer->SerializeJSTaggedValue(JSHandle<JSTaggedValue>(thread, aTag)); bool success2 = serializer->SerializeJSTaggedValue(JSHandle<JSTaggedValue>(thread, bTag)); EXPECT_TRUE(success1 && success2) << "Serialize Double fail"; std::pair<uint8_t *, size_t> data = serializer->ReleaseBuffer(); JSDeserializerTest jsDeserializerTest; std::thread t1(&JSDeserializerTest::DoubleTest, jsDeserializerTest, data); t1.join(); delete serializer; }; JSDate *JSDateCreate(EcmaVM *ecmaVM) { ObjectFactory *factory = ecmaVM->GetFactory(); JSHandle<GlobalEnv> globalEnv = ecmaVM->GetGlobalEnv(); JSHandle<JSTaggedValue> dateFunction = globalEnv->GetDateFunction(); JSHandle<JSDate> dateObject = JSHandle<JSDate>::Cast(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(dateFunction), dateFunction)); return *dateObject; } HWTEST_F_L0(JSSerializerTest, SerializeDate) { double tm = 28 * 60 * 60 * 1000; JSHandle<JSDate> jsDate(thread, JSDateCreate(ecmaVm)); jsDate->SetTimeValue(thread, JSTaggedValue(tm)); JSSerializer *serializer = new JSSerializer(thread); bool success = serializer->SerializeJSTaggedValue(JSHandle<JSTaggedValue>::Cast(jsDate)); EXPECT_TRUE(success) << "Serialize JSDate fail"; std::pair<uint8_t *, size_t> data = serializer->ReleaseBuffer(); JSDeserializerTest jsDeserializerTest; std::thread t1(&JSDeserializerTest::JSDateTest, jsDeserializerTest, data); t1.join(); delete serializer; }; JSMap *CreateMap(JSThread *thread) { ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv(); JSHandle<JSTaggedValue> constructor = env->GetBuiltinsMapFunction(); JSHandle<JSMap> map = JSHandle<JSMap>::Cast(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(constructor), constructor)); JSHandle<LinkedHashMap> linkedMap = LinkedHashMap::Create(thread); map->SetLinkedMap(thread, linkedMap); return *map; } HWTEST_F_L0(JSSerializerTest, SerializeJSMap) { JSHandle<JSMap> map(thread, CreateMap(thread)); ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle<JSTaggedValue> key1(factory->NewFromASCII("3")); JSHandle<JSTaggedValue> value1(thread, JSTaggedValue(12345)); JSMap::Set(thread, map, key1, value1); JSHandle<JSTaggedValue> key2(factory->NewFromASCII("key1")); JSHandle<JSTaggedValue> value2(thread, JSTaggedValue(34567)); JSMap::Set(thread, map, key2, value2); JSSerializer *serializer = new JSSerializer(thread); bool success = serializer->SerializeJSTaggedValue(JSHandle<JSTaggedValue>::Cast(map)); EXPECT_TRUE(success) << "Serialize JSMap fail"; std::pair<uint8_t *, size_t> data = serializer->ReleaseBuffer(); JSDeserializerTest jsDeserializerTest; std::thread t1(&JSDeserializerTest::JSMapTest, jsDeserializerTest, data, map); t1.join(); delete serializer; }; JSArrayBuffer *CreateJSArrayBuffer(JSThread *thread) { ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv(); JSHandle<JSTaggedValue> target = env->GetArrayBufferFunction(); JSHandle<JSArrayBuffer> jsArrayBuffer = JSHandle<JSArrayBuffer>::Cast(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(target), target)); return *jsArrayBuffer; } HWTEST_F_L0(JSSerializerTest, SerializeJSArrayBuffer) { JSHandle<JSArrayBuffer> jsArrayBuffer(thread, CreateJSArrayBuffer(thread)); int32_t byteLength = 10; thread->GetEcmaVM()->GetFactory()->NewJSArrayBufferData(jsArrayBuffer, byteLength); jsArrayBuffer->SetArrayBufferByteLength(byteLength); JSHandle<JSTaggedValue> obj = JSHandle<JSTaggedValue>(jsArrayBuffer); JSHandle<JSTaggedValue> number(thread, JSTaggedValue(7)); BuiltinsArrayBuffer::SetValueInBuffer(thread, obj.GetTaggedValue(), 1, DataViewType::UINT8, number, true); number = JSHandle<JSTaggedValue>(thread, JSTaggedValue(17)); BuiltinsArrayBuffer::SetValueInBuffer(thread, obj.GetTaggedValue(), 3, DataViewType::UINT8, // 3:index number, true); JSSerializer *serializer = new JSSerializer(thread); bool success = serializer->SerializeJSTaggedValue(JSHandle<JSTaggedValue>::Cast(jsArrayBuffer)); EXPECT_TRUE(success) << "Serialize JSArrayBuffer fail"; std::pair<uint8_t *, size_t> data = serializer->ReleaseBuffer(); JSDeserializerTest jsDeserializerTest; std::thread t1(&JSDeserializerTest::JSArrayBufferTest, jsDeserializerTest, data, jsArrayBuffer, 10, nullptr); t1.join(); delete serializer; }; HWTEST_F_L0(JSSerializerTest, SerializeJSArrayBufferShared) { std::string msg = "hello world"; uint32_t msgBufferLen = msg.length() + 1U; char* msgBuffer = new char[msgBufferLen] { 0 }; if (memcpy_s(msgBuffer, msgBufferLen, msg.c_str(), msgBufferLen) != EOK) { delete[] msgBuffer; EXPECT_TRUE(false) << " memcpy error"; } ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle<JSArrayBuffer> jsArrayBuffer = factory->NewJSArrayBuffer(msgBuffer, msgBufferLen, nullptr, nullptr); JSSerializer *serializer = new JSSerializer(thread); bool success = serializer->SerializeJSTaggedValue(JSHandle<JSTaggedValue>::Cast(jsArrayBuffer)); EXPECT_TRUE(success) << "Serialize JSArrayBuffer fail"; std::pair<uint8_t *, size_t> data = serializer->ReleaseBuffer(); JSDeserializerTest jsDeserializerTest; std::thread t1(&JSDeserializerTest::JSArrayBufferTest, jsDeserializerTest, data, jsArrayBuffer, 12, nullptr); t1.join(); delete serializer; delete[] msgBuffer; }; HWTEST_F_L0(JSSerializerTest, SerializeJSArrayBufferShared2) { std::string msg = "hello world"; int msgBufferLen = static_cast<int>(msg.length()) + 1; ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle<JSArrayBuffer> jsArrayBuffer = factory->NewJSSharedArrayBuffer(msgBufferLen); JSHandle<JSTaggedValue> BufferData(thread, jsArrayBuffer->GetArrayBufferData()); JSHandle<JSNativePointer> resNp = JSHandle<JSNativePointer>::Cast(BufferData); void *Buffer = resNp->GetExternalPointer(); if (memcpy_s(Buffer, msgBufferLen, msg.c_str(), msgBufferLen) != EOK) { EXPECT_TRUE(false) << " memcpy error"; } JSSerializer *serializer = new JSSerializer(thread); bool success = serializer->SerializeJSTaggedValue(JSHandle<JSTaggedValue>::Cast(jsArrayBuffer)); EXPECT_TRUE(success) << "Serialize JSArrayBuffer fail"; std::pair<uint8_t *, size_t> data = serializer->ReleaseBuffer(); JSDeserializerTest jsDeserializerTest; std::string changeStr = "world hello"; std::thread t1(&JSDeserializerTest::JSSharedArrayBufferTest, jsDeserializerTest, data, jsArrayBuffer, 12, changeStr.c_str()); t1.join(); EXPECT_TRUE(strcmp((char *)Buffer, "world hello") == 0) << "Serialize JSArrayBuffer fail"; delete serializer; }; HWTEST_F_L0(JSSerializerTest, SerializeJSArrayBufferShared3) { std::string msg = "hello world"; int msgBufferLen = static_cast<int>(msg.length()) + 1; ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle<JSArrayBuffer> jsArrayBuffer = factory->NewJSSharedArrayBuffer(msgBufferLen); JSHandle<JSTaggedValue> BufferData(thread, jsArrayBuffer->GetArrayBufferData()); JSHandle<JSNativePointer> resNp = JSHandle<JSNativePointer>::Cast(BufferData); void *Buffer = resNp->GetExternalPointer(); if (memcpy_s(Buffer, msgBufferLen, msg.c_str(), msgBufferLen) != EOK) { EXPECT_TRUE(false) << " memcpy error"; } JSSerializer *serializer = new JSSerializer(thread); bool success = serializer->SerializeJSTaggedValue(JSHandle<JSTaggedValue>::Cast(jsArrayBuffer)); EXPECT_TRUE(success) << "Serialize JSArrayBuffer fail"; std::pair<uint8_t *, size_t> data = serializer->ReleaseBuffer(); JSDeserializerTest jsDeserializerTest; std::string changeStr = "aaaaaaaaaa"; std::thread t1(&JSDeserializerTest::JSSharedArrayBufferTest1, jsDeserializerTest, data, 5, changeStr.c_str()); t1.join(); EXPECT_TRUE(strcmp((char *)Buffer, "aaaaa world") == 0) << "Serialize JSArrayBuffer fail"; JSSerializer *serializer2 = new JSSerializer(thread); bool success2 = serializer2->SerializeJSTaggedValue(JSHandle<JSTaggedValue>::Cast(jsArrayBuffer)); EXPECT_TRUE(success2) << "Serialize JSArrayBuffer fail"; std::pair<uint8_t *, size_t> data2 = serializer2->ReleaseBuffer(); JSDeserializerTest jsDeserializerTest2; std::string changeStr2 = "bbbbbbbbbbb"; std::thread t2(&JSDeserializerTest::JSSharedArrayBufferTest1, jsDeserializerTest2, data2, 6, changeStr2.c_str()); t2.join(); EXPECT_TRUE(strcmp((char *)Buffer, "bbbbbbworld") == 0) << "Serialize JSArrayBuffer fail"; delete serializer; delete serializer2; }; HWTEST_F_L0(JSSerializerTest, SerializeJSRegExp) { ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv(); JSHandle<JSTaggedValue> target = env->GetRegExpFunction(); JSHandle<JSRegExp> jsRegexp = JSHandle<JSRegExp>::Cast(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(target), target)); JSHandle<EcmaString> pattern = thread->GetEcmaVM()->GetFactory()->NewFromASCII("key2"); JSHandle<EcmaString> flags = thread->GetEcmaVM()->GetFactory()->NewFromASCII("i"); char buffer[] = "1234567"; // use char to simulate bytecode uint32_t bufferSize = 7; factory->NewJSRegExpByteCodeData(jsRegexp, static_cast<void *>(buffer), bufferSize); jsRegexp->SetOriginalSource(thread, JSHandle<JSTaggedValue>(pattern)); jsRegexp->SetOriginalFlags(thread, JSHandle<JSTaggedValue>(flags)); JSSerializer *serializer = new JSSerializer(thread); bool success = serializer->SerializeJSTaggedValue(JSHandle<JSTaggedValue>::Cast(jsRegexp)); EXPECT_TRUE(success) << "Serialize JSRegExp fail"; std::pair<uint8_t *, size_t> data = serializer->ReleaseBuffer(); JSDeserializerTest jsDeserializerTest; std::thread t1(&JSDeserializerTest::JSRegexpTest, jsDeserializerTest, data); t1.join(); delete serializer; }; JSArrayBuffer *CreateTestJSArrayBuffer(JSThread *thread) { JSHandle<JSArrayBuffer> jsArrayBuffer(thread, CreateJSArrayBuffer(thread)); int32_t byteLength = 10; thread->GetEcmaVM()->GetFactory()->NewJSArrayBufferData(jsArrayBuffer, byteLength); jsArrayBuffer->SetArrayBufferByteLength(byteLength); JSHandle<JSTaggedValue> obj = JSHandle<JSTaggedValue>(jsArrayBuffer); JSMutableHandle<JSTaggedValue> number(thread, JSTaggedValue::Undefined()); for (int i = 0; i < 10; i++) { // 10: arrayLength number.Update(JSTaggedValue(i)); BuiltinsArrayBuffer::SetValueInBuffer(thread, obj.GetTaggedValue(), i, DataViewType::UINT8, number, true); } return *jsArrayBuffer; } HWTEST_F_L0(JSSerializerTest, SerializeJSTypedArray1) { ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv(); JSHandle<JSTaggedValue> target = env->GetInt8ArrayFunction(); JSHandle<JSTypedArray> int8Array = JSHandle<JSTypedArray>::Cast(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(target), target)); JSHandle<JSTaggedValue> viewedArrayBuffer(thread, CreateTestJSArrayBuffer(thread)); int8Array->SetViewedArrayBufferOrByteArray(thread, viewedArrayBuffer); int byteLength = 10; int byteOffset = 0; int arrayLength = (byteLength - byteOffset) / (sizeof(int8_t)); int8Array->SetByteLength(byteLength); int8Array->SetByteOffset(byteOffset); int8Array->SetTypedArrayName(thread, thread->GlobalConstants()->GetInt8ArrayString()); int8Array->SetArrayLength(arrayLength); int8Array->SetContentType(ContentType::Number); JSSerializer *serializer = new JSSerializer(thread); bool success = serializer->SerializeJSTaggedValue(JSHandle<JSTaggedValue>::Cast(int8Array)); EXPECT_TRUE(success); std::pair<uint8_t *, size_t> data = serializer->ReleaseBuffer(); JSDeserializerTest jsDeserializerTest; std::thread t1(&JSDeserializerTest::TypedArrayTest1, jsDeserializerTest, data); t1.join(); delete serializer; }; HWTEST_F_L0(JSSerializerTest, SerializeJSTypedArray2) { ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv(); JSHandle<JSTaggedValue> target = env->GetInt8ArrayFunction(); JSHandle<JSTypedArray> int8Array = JSHandle<JSTypedArray>::Cast(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(target), target)); uint8_t value = 255; // 255 : test case JSTaggedType val = JSTaggedValue(value).GetRawData(); int byteArrayLength = 10; // 10: arrayLength JSHandle<ByteArray> byteArray = factory->NewByteArray(byteArrayLength, sizeof(value)); for (int i = 0; i < byteArrayLength; i++) { byteArray->Set(thread, i, DataViewType::UINT8, val); } int8Array->SetViewedArrayBufferOrByteArray(thread, byteArray); int byteLength = 10; int byteOffset = 0; int arrayLength = (byteLength - byteOffset) / (sizeof(int8_t)); int8Array->SetByteLength(byteLength); int8Array->SetByteOffset(byteOffset); int8Array->SetTypedArrayName(thread, thread->GlobalConstants()->GetInt8ArrayString()); int8Array->SetArrayLength(arrayLength); int8Array->SetContentType(ContentType::Number); JSSerializer *serializer = new JSSerializer(thread); bool success = serializer->SerializeJSTaggedValue(JSHandle<JSTaggedValue>::Cast(int8Array)); EXPECT_TRUE(success); std::pair<uint8_t *, size_t> data = serializer->ReleaseBuffer(); JSDeserializerTest jsDeserializerTest; std::thread t1(&JSDeserializerTest::TypedArrayTest2, jsDeserializerTest, data); t1.join(); delete serializer; }; HWTEST_F_L0(JSSerializerTest, SerializeTaggedArray) { ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle<TaggedArray> taggedArray(factory->NewTaggedArray(4)); JSHandle<EcmaString> str1 = factory->NewFromASCII("str11"); JSHandle<EcmaString> str2 = factory->NewFromASCII("str22"); // set value to the taggedarray taggedArray->Set(thread, 0, str1.GetTaggedValue()); taggedArray->Set(thread, 1, str2.GetTaggedValue()); taggedArray->Set(thread, 2, JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined())); JSSerializer *serializer = new JSSerializer(thread); bool success = serializer->SerializeJSTaggedValue(JSHandle<JSTaggedValue>::Cast(taggedArray)); EXPECT_TRUE(success); std::pair<uint8_t *, size_t> data = serializer->ReleaseBuffer(); JSDeserializerTest jsDeserializerTest; std::thread t1(&JSDeserializerTest::TaggedArrayTest, jsDeserializerTest, data); t1.join(); delete serializer; }; std::shared_ptr<JSPandaFile> CreateJSPandaFile(const char *source, const CString filename, uint32_t *methodOffset) { pandasm::Parser parser; const std::string fn = "SRC.pa"; // test file name : "SRC.pa" auto res = parser.Parse(source, fn); std::unique_ptr<const panda_file::File> pfPtr = pandasm::AsmEmitter::Emit(res.Value()); JSPandaFileManager *pfManager = JSPandaFileManager::GetInstance(); std::shared_ptr<JSPandaFile> pf = pfManager->NewJSPandaFile(pfPtr.release(), filename); const panda_file::File *file = pf->GetPandaFile(); const uint8_t *typeDesc = utf::CStringAsMutf8("L_GLOBAL;"); panda_file::File::EntityId classId = file->GetClassId(typeDesc); EXPECT_TRUE(classId.IsValid()); panda_file::ClassDataAccessor cda(*file, classId); cda.EnumerateMethods([&](panda_file::MethodDataAccessor &mda) { *methodOffset = mda.GetMethodId().GetOffset(); }); return pf; } static void TestFunc() { return; } HWTEST_F_L0(JSSerializerTest, SerializeMethod1) { ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle<Method> method = factory->NewMethodForNativeFunction(reinterpret_cast<void*>(TestFunc)); EXPECT_TRUE(method.GetTaggedValue().IsMethod()); JSSerializer *serializer = new JSSerializer(thread); bool success = serializer->SerializeJSTaggedValue(JSHandle<JSTaggedValue>::Cast(method)); EXPECT_TRUE(success); std::pair<uint8_t *, size_t> data = serializer->ReleaseBuffer(); JSDeserializerTest jsDeserializerTest; std::thread t1(&JSDeserializerTest::MethodTest, jsDeserializerTest, data); t1.join(); delete serializer; }; HWTEST_F_L0(JSSerializerTest, SerializeMethod2) { ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); const char *source = R"( .function void foo() { lda.str "helloworld" returnundefined } )"; const CString fileName = "test.pa"; uint32_t methodOffset = 0; std::shared_ptr<JSPandaFile> pf = CreateJSPandaFile(source, fileName, &methodOffset); MethodLiteral *methodLiteral = new MethodLiteral(EntityId(methodOffset)); JSHandle<Method> method = factory->NewMethod(methodLiteral); EXPECT_TRUE(method.GetTaggedValue().IsMethod()); JSPandaFileManager::GetInstance()->AddJSPandaFileVm(thread->GetEcmaVM(), pf); EXPECT_TRUE(pf != nullptr); JSHandle<ConstantPool> constPool = factory->NewConstantPool(4); constPool->SetJSPandaFile(pf.get()); EXPECT_TRUE(constPool.GetTaggedValue().IsConstantPool()); method->SetConstantPool(thread, constPool.GetTaggedValue()); JSSerializer *serializer = new JSSerializer(thread); bool success = serializer->SerializeJSTaggedValue(JSHandle<JSTaggedValue>::Cast(method)); EXPECT_TRUE(success); std::pair<uint8_t *, size_t> data = serializer->ReleaseBuffer(); JSDeserializerTest jsDeserializerTest; std::thread t1(&JSDeserializerTest::MethodTest1, jsDeserializerTest, data); t1.join(); delete serializer; }; HWTEST_F_L0(JSSerializerTest, SerializeAOTMethod) { ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); const char *source = R"( .function void foo() { lda.str "hello aot" returnundefined } )"; const CString fileName = "test_aot_method.pa"; uint32_t methodOffset = 0; std::shared_ptr<JSPandaFile> pf = CreateJSPandaFile(source, fileName, &methodOffset); MethodLiteral *methodLiteral = new MethodLiteral(EntityId(methodOffset)); methodLiteral->SetAotCodeBit(true); methodLiteral->SetIsFastCall(true); pf->SetMethodLiteralToMap(methodLiteral); JSHandle<Method> method = factory->NewMethod(methodLiteral); EXPECT_TRUE(method.GetTaggedValue().IsMethod()); JSPandaFileManager::GetInstance()->AddJSPandaFileVm(thread->GetEcmaVM(), pf); EXPECT_TRUE(pf != nullptr); JSHandle<ConstantPool> constPool = factory->NewConstantPool(4); constPool->SetJSPandaFile(pf.get()); EXPECT_TRUE(constPool.GetTaggedValue().IsConstantPool()); method->SetConstantPool(thread, constPool.GetTaggedValue()); uintptr_t codeEntry = 0x1234; method->SetCodeEntryAndMarkAOT(codeEntry); JSSerializer *serializer = new JSSerializer(thread); bool success = serializer->SerializeJSTaggedValue(JSHandle<JSTaggedValue>::Cast(method)); EXPECT_TRUE(success); std::pair<uint8_t *, size_t> data = serializer->ReleaseBuffer(); JSDeserializerTest jsDeserializerTest; std::thread t1(&JSDeserializerTest::AOTMethodTest, jsDeserializerTest, data); t1.join(); delete serializer; }; // support concurrent function HWTEST_F_L0(JSSerializerTest, SerializeConcurrentFunction) { ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv(); JSHandle<JSFunction> concurrentFunction = factory->NewJSFunction(env, nullptr, FunctionKind::CONCURRENT_FUNCTION); EXPECT_TRUE(concurrentFunction->IsJSFunction()); EXPECT_TRUE(concurrentFunction->GetFunctionKind() == ecmascript::FunctionKind::CONCURRENT_FUNCTION); JSSerializer *serializer = new JSSerializer(thread); bool success = serializer->SerializeJSTaggedValue(JSHandle<JSTaggedValue>::Cast(concurrentFunction)); EXPECT_TRUE(success); std::pair<uint8_t *, size_t> data = serializer->ReleaseBuffer(); JSDeserializerTest jsDeserializerTest; std::thread t1(&JSDeserializerTest::ConcurrentFunctionTest, jsDeserializerTest, data); t1.join(); delete serializer; }; HWTEST_F_L0(JSSerializerTest, SerializeBigInt) { CString str1 = "100000000000000000000000000000000000000000000000000000"; // Binary: 2 ^ 53 CString str2 = "111111111111111111111111111111111111111111111111111111"; // Binary: 2 ^ 54 - 1 CString str3 = "-9007199254740991012345"; CString str4 = "1234567890987654321"; // Decimal JSHandle<BigInt> bigInt1 = BigIntHelper::SetBigInt(thread, str1); JSHandle<BigInt> bigInt2 = BigIntHelper::SetBigInt(thread, str2); JSHandle<BigInt> bigInt3 = BigIntHelper::SetBigInt(thread, str3); JSHandle<BigInt> bigInt4 = BigInt::Uint32ToBigInt(thread, 0); // 0 : test case JSHandle<BigInt> bigInt5 = BigIntHelper::SetBigInt(thread, str4, BigInt::DECIMAL); JSHandle<BigInt> bigInt6 = BigInt::Uint64ToBigInt(thread, ULLONG_MAX); JSHandle<BigInt> bigInt7 = BigInt::Uint64ToBigInt(thread, UINT_MAX); JSHandle<BigInt> bigInt8 = BigInt::Uint32ToBigInt(thread, std::numeric_limits<uint32_t>::max()); JSHandle<BigInt> bigInt9 = BigInt::Uint32ToBigInt(thread, std::numeric_limits<uint32_t>::min()); JSHandle<BigInt> bigInt10 = BigInt::Int64ToBigInt(thread, LLONG_MAX); JSHandle<BigInt> bigInt11 = BigInt::Int64ToBigInt(thread, LLONG_MIN); JSHandle<BigInt> bigInt12 = BigInt::Int64ToBigInt(thread, INT_MAX); JSHandle<BigInt> bigInt13 = BigInt::Int64ToBigInt(thread, INT_MIN); JSHandle<BigInt> bigInt14 = BigInt::Int32ToBigInt(thread, -1); // -1 : test case JSSerializer *serializer = new JSSerializer(thread); bool success1 = serializer->SerializeJSTaggedValue(JSHandle<JSTaggedValue>::Cast(bigInt1)); bool success2 = serializer->SerializeJSTaggedValue(JSHandle<JSTaggedValue>::Cast(bigInt2)); bool success3 = serializer->SerializeJSTaggedValue(JSHandle<JSTaggedValue>::Cast(bigInt3)); bool success4 = serializer->SerializeJSTaggedValue(JSHandle<JSTaggedValue>::Cast(bigInt4)); bool success5 = serializer->SerializeJSTaggedValue(JSHandle<JSTaggedValue>::Cast(bigInt5)); bool success6 = serializer->SerializeJSTaggedValue(JSHandle<JSTaggedValue>::Cast(bigInt6)); bool success7 = serializer->SerializeJSTaggedValue(JSHandle<JSTaggedValue>::Cast(bigInt7)); bool success8 = serializer->SerializeJSTaggedValue(JSHandle<JSTaggedValue>::Cast(bigInt8)); bool success9 = serializer->SerializeJSTaggedValue(JSHandle<JSTaggedValue>::Cast(bigInt9)); bool success10 = serializer->SerializeJSTaggedValue(JSHandle<JSTaggedValue>::Cast(bigInt10)); bool success11 = serializer->SerializeJSTaggedValue(JSHandle<JSTaggedValue>::Cast(bigInt11)); bool success12 = serializer->SerializeJSTaggedValue(JSHandle<JSTaggedValue>::Cast(bigInt12)); bool success13 = serializer->SerializeJSTaggedValue(JSHandle<JSTaggedValue>::Cast(bigInt13)); bool success14 = serializer->SerializeJSTaggedValue(JSHandle<JSTaggedValue>::Cast(bigInt14)); EXPECT_TRUE(success1); EXPECT_TRUE(success2); EXPECT_TRUE(success3); EXPECT_TRUE(success4); EXPECT_TRUE(success5); EXPECT_TRUE(success6); EXPECT_TRUE(success7); EXPECT_TRUE(success8); EXPECT_TRUE(success9); EXPECT_TRUE(success10); EXPECT_TRUE(success11); EXPECT_TRUE(success12); EXPECT_TRUE(success13); EXPECT_TRUE(success14); std::pair<uint8_t *, size_t> data = serializer->ReleaseBuffer(); JSDeserializerTest jsDeserializerTest; std::thread t1(&JSDeserializerTest::BigIntTest, jsDeserializerTest, data); t1.join(); delete serializer; } HWTEST_F_L0(JSSerializerTest, SerializeObjectWithConcurrentFunction) { ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv(); JSHandle<JSFunction> concurrentFunction1 = factory->NewJSFunction(env, nullptr, FunctionKind::CONCURRENT_FUNCTION); EXPECT_TRUE(concurrentFunction1->IsJSFunction()); EXPECT_TRUE(concurrentFunction1->GetFunctionKind() == ecmascript::FunctionKind::CONCURRENT_FUNCTION); JSHandle<JSFunction> concurrentFunction2 = factory->NewJSFunction(env, nullptr, FunctionKind::CONCURRENT_FUNCTION); EXPECT_TRUE(concurrentFunction2->IsJSFunction()); EXPECT_TRUE(concurrentFunction2->GetFunctionKind() == ecmascript::FunctionKind::CONCURRENT_FUNCTION); JSHandle<JSTaggedValue> key1(factory->NewFromASCII("1")); JSHandle<JSTaggedValue> key2(factory->NewFromASCII("2")); JSHandle<JSTaggedValue> key3(factory->NewFromASCII("abc")); JSHandle<JSTaggedValue> key4(factory->NewFromASCII("4")); JSHandle<JSTaggedValue> key5(factory->NewFromASCII("key")); JSHandle<JSTaggedValue> value1(thread, JSTaggedValue(12345)); JSHandle<JSTaggedValue> value2(factory->NewFromASCII("def")); JSHandle<JSTaggedValue> value3(factory->NewFromASCII("value")); JSHandle<JSObject> obj = factory->NewEmptyJSObject(); JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj), key1, value1); JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj), key2, JSHandle<JSTaggedValue>(concurrentFunction1)); JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj), key3, value2); JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj), key4, JSHandle<JSTaggedValue>(concurrentFunction2)); JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj), key5, value3); JSSerializer *serializer = new JSSerializer(thread); bool success = serializer->SerializeJSTaggedValue(JSHandle<JSTaggedValue>(obj)); EXPECT_TRUE(success); std::pair<uint8_t *, size_t> data = serializer->ReleaseBuffer(); JSDeserializerTest jsDeserializerTest; std::thread t1(&JSDeserializerTest::ObjectWithConcurrentFunctionTest, jsDeserializerTest, data); t1.join(); delete serializer; }; // not support function HWTEST_F_L0(JSSerializerTest, SerializeFunction) { JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv(); JSHandle<JSTaggedValue> function = env->GetFunctionFunction(); EXPECT_TRUE(function->IsJSFunction()); JSSerializer *serializer = new JSSerializer(thread); bool success = serializer->SerializeJSTaggedValue(JSHandle<JSTaggedValue>(function)); EXPECT_FALSE(success); std::pair<uint8_t *, size_t> data = serializer->ReleaseBuffer(); JSDeserializer deserializer(thread, data.first, data.second); JSHandle<JSTaggedValue> ret = deserializer.Deserialize(); EXPECT_TRUE(ret.IsEmpty()); delete serializer; } // not support symbol HWTEST_F_L0(JSSerializerTest, SerializeSymbolWithProperty) { ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle<JSSymbol> jsSymbol = factory->NewJSSymbol(); JSHandle<JSTaggedValue> key1(factory->NewFromASCII("2")); JSHandle<JSTaggedValue> key2(factory->NewFromASCII("x")); JSHandle<JSTaggedValue> value1(thread, JSTaggedValue(1)); JSHandle<JSTaggedValue> value2(thread, JSTaggedValue(8)); JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(jsSymbol), key1, value1); JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(jsSymbol), key2, value2); JSSerializer *serializer = new JSSerializer(thread); bool success = serializer->SerializeJSTaggedValue(JSHandle<JSTaggedValue>(jsSymbol)); EXPECT_FALSE(success); std::pair<uint8_t *, size_t> data = serializer->ReleaseBuffer(); JSDeserializer deserializer(thread, data.first, data.second); JSHandle<JSTaggedValue> ret = deserializer.Deserialize(); EXPECT_TRUE(ret.IsEmpty()); delete serializer; }; // Test transfer JSArrayBuffer HWTEST_F_L0(JSSerializerTest, TransferJSArrayBuffer1) { ObjectFactory *factory = ecmaVm->GetFactory(); // create a JSArrayBuffer size_t length = 5; uint8_t value = 100; void *buffer = ecmaVm->GetNativeAreaAllocator()->AllocateBuffer(length); if (memset_s(buffer, length, value, length) != EOK) { LOG_ECMA(FATAL) << "this branch is unreachable"; UNREACHABLE(); } JSHandle<JSArrayBuffer> arrBuf = factory->NewJSArrayBuffer(buffer, length, NativeAreaAllocator::FreeBufferFunc, ecmaVm->GetNativeAreaAllocator()); JSHandle<JSTaggedValue> arrBufTag = JSHandle<JSTaggedValue>::Cast(arrBuf); CUnorderedSet<uintptr_t> transferDataSet; uintptr_t addr = static_cast<uintptr_t>(arrBufTag.GetTaggedType()); transferDataSet.insert(addr); JSSerializer *serializer = new JSSerializer(thread); serializer->InitTransferSet(transferDataSet); bool success = serializer->SerializeJSTaggedValue(arrBufTag); EXPECT_TRUE(success); std::pair<uint8_t *, size_t> data = serializer->ReleaseBuffer(); JSDeserializerTest jsDeserializerTest; std::thread t1(&JSDeserializerTest::TransferJSArrayBufferTest1, jsDeserializerTest, data, reinterpret_cast<uintptr_t>(buffer)); t1.join(); delete serializer; // test if detached EXPECT_TRUE(arrBuf->IsDetach()); }; // Test serialize JSArrayBuffer that not transfer HWTEST_F_L0(JSSerializerTest, TransferJSArrayBuffer2) { ObjectFactory *factory = ecmaVm->GetFactory(); // create a JSArrayBuffer size_t length = 5; uint8_t value = 100; void *buffer = ecmaVm->GetNativeAreaAllocator()->AllocateBuffer(length); if (memset_s(buffer, length, value, length) != EOK) { LOG_ECMA(FATAL) << "this branch is unreachable"; UNREACHABLE(); } JSHandle<JSArrayBuffer> arrBuf = factory->NewJSArrayBuffer(buffer, length, NativeAreaAllocator::FreeBufferFunc, ecmaVm->GetNativeAreaAllocator()); JSHandle<JSTaggedValue> arrBufTag = JSHandle<JSTaggedValue>::Cast(arrBuf); JSSerializer *serializer = new JSSerializer(thread); bool success = serializer->SerializeJSTaggedValue(arrBufTag); EXPECT_TRUE(success); std::pair<uint8_t *, size_t> data = serializer->ReleaseBuffer(); JSDeserializerTest jsDeserializerTest; std::thread t1(&JSDeserializerTest::TransferJSArrayBufferTest2, jsDeserializerTest, data, reinterpret_cast<uintptr_t>(buffer)); t1.join(); delete serializer; // test if detached EXPECT_FALSE(arrBuf->IsDetach()); }; // Test serialize an empty JSArrayBuffer HWTEST_F_L0(JSSerializerTest, TransferJSArrayBuffer3) { ObjectFactory *factory = ecmaVm->GetFactory(); // create a JSArrayBuffer JSHandle<JSArrayBuffer> arrBuf = factory->NewJSArrayBuffer(0); JSHandle<JSTaggedValue> arrBufTag = JSHandle<JSTaggedValue>::Cast(arrBuf); JSSerializer *serializer = new JSSerializer(thread); bool success = serializer->SerializeJSTaggedValue(arrBufTag); EXPECT_TRUE(success); std::pair<uint8_t *, size_t> data = serializer->ReleaseBuffer(); JSDeserializerTest jsDeserializerTest; std::thread t1(&JSDeserializerTest::TransferJSArrayBufferTest3, jsDeserializerTest, data); t1.join(); delete serializer; // test if detached EXPECT_FALSE(arrBuf->IsDetach()); }; // Test default transfer JSArrayBuffer HWTEST_F_L0(JSSerializerTest, TransferJSArrayBuffer4) { ObjectFactory *factory = ecmaVm->GetFactory(); // create a JSArrayBuffer size_t length = 5; uint8_t value = 100; void *buffer = ecmaVm->GetNativeAreaAllocator()->AllocateBuffer(length); if (memset_s(buffer, length, value, length) != EOK) { LOG_ECMA(FATAL) << "this branch is unreachable"; UNREACHABLE(); } JSHandle<JSArrayBuffer> arrBuf = factory->NewJSArrayBuffer(buffer, length, NativeAreaAllocator::FreeBufferFunc, ecmaVm->GetNativeAreaAllocator()); JSHandle<JSTaggedValue> arrBufTag = JSHandle<JSTaggedValue>::Cast(arrBuf); JSSerializer *serializer = new JSSerializer(thread); serializer->SetDefaultTransfer(); bool success = serializer->SerializeJSTaggedValue(arrBufTag); EXPECT_TRUE(success); std::pair<uint8_t *, size_t> data = serializer->ReleaseBuffer(); JSDeserializerTest jsDeserializerTest; std::thread t1(&JSDeserializerTest::TransferJSArrayBufferTest4, jsDeserializerTest, data, reinterpret_cast<uintptr_t>(buffer)); t1.join(); delete serializer; // test if detached EXPECT_TRUE(arrBuf->IsDetach()); } // Test JSArrayBuffer transfer mixed with other properties in a typedArray HWTEST_F_L0(JSSerializerTest, TransferJSArrayBufferInTypedArray) { ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv(); JSHandle<JSTaggedValue> target = env->GetInt8ArrayFunction(); JSHandle<JSTypedArray> int8Array = JSHandle<JSTypedArray>::Cast(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(target), target)); JSHandle<JSArrayBuffer> arrBuffer(thread, CreateTestJSArrayBuffer(thread)); JSHandle<JSNativePointer> np = JSHandle<JSNativePointer>::Cast(JSHandle<JSTaggedValue>(thread, arrBuffer->GetArrayBufferData())); // c buffer ptr uintptr_t buffer = reinterpret_cast<uintptr_t>(np->GetExternalPointer()); int8Array->SetViewedArrayBufferOrByteArray(thread, JSHandle<JSTaggedValue>(arrBuffer)); int byteLength = 10; int byteOffset = 0; int arrayLength = (byteLength - byteOffset) / (sizeof(int8_t)); int8Array->SetByteLength(byteLength); int8Array->SetByteOffset(byteOffset); int8Array->SetTypedArrayName(thread, thread->GlobalConstants()->GetInt8ArrayString()); int8Array->SetArrayLength(arrayLength); int8Array->SetContentType(ContentType::Number); CUnorderedSet<uintptr_t> transferDataSet; uintptr_t addr = static_cast<uintptr_t>(arrBuffer.GetTaggedType()); transferDataSet.insert(addr); JSSerializer *serializer = new JSSerializer(thread); serializer->InitTransferSet(transferDataSet); bool success = serializer->SerializeJSTaggedValue(JSHandle<JSTaggedValue>::Cast(int8Array)); EXPECT_TRUE(success); std::pair<uint8_t *, size_t> data = serializer->ReleaseBuffer(); JSDeserializerTest jsDeserializerTest; std::thread t1(&JSDeserializerTest::TransferJSArrayBufferTest5, jsDeserializerTest, data, buffer); t1.join(); delete serializer; // test if detached EXPECT_TRUE(arrBuffer->IsDetach()); }; } // namespace panda::test