* 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 <memory>
#include <thread>
#include "libpandabase/utils/utf.h"
#include "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_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/module/js_module_source_text.h"
#include "ecmascript/object_factory.h"
#include "ecmascript/tests/test_helper.h"
#include "ecmascript/containers/containers_private.h"
#include "ecmascript/containers/containers_treeset.h"
#include "ecmascript/ecma_runtime_call_info.h"
#include "ecmascript/js_api/js_api_tree_set.h"
#include "ecmascript/js_api/js_api_tree_set_iterator.h"
#include "ecmascript/js_handle.h"
#include "ecmascript/js_tagged_value-inl.h"
#include "ecmascript/containers/tests/containers_test_helper.h"
#include "ecmascript/serializer/value_serializer.h"
#include "ecmascript/serializer/base_deserializer.h"
#include "ecmascript/serializer/file_deserializer.h"
#include "ecmascript/serializer/file_serializer.h"
using namespace panda::ecmascript;
using namespace testing::ext;
using namespace panda::ecmascript::builtins;
using namespace panda::ecmascript::containers;
namespace panda::test {
using DeserializeFunc = void (*)(SerializeData* data);
using Clock = std::chrono::high_resolution_clock;
using Duration = std::chrono::duration<uint64_t, std::nano>;
constexpr int32_t INITIALIZE_SIZE = 100;
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);
thread->ManagedCodeBegin();
}
void Destroy()
{
thread->ManagedCodeEnd();
delete scope;
scope = nullptr;
ecmaVm->SetEnableForceGC(false);
thread->ClearException();
JSNApi::DestroyJSVM(ecmaVm);
}
void JSSpecialValueTest(SerializeData* 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());
BaseDeserializer deserializer(thread, data);
JSHandle<JSTaggedValue> retTrue = deserializer.ReadValue();
EXPECT_TRUE(JSTaggedValue::SameValue(thread, jsTrue, retTrue)) << "Not same value for JS_TRUE";
JSHandle<JSTaggedValue> retFalse = deserializer.ReadValue();
EXPECT_TRUE(JSTaggedValue::SameValue(thread, jsFalse, retFalse)) << "Not same value for JS_FALSE";
JSHandle<JSTaggedValue> retUndefined = deserializer.ReadValue();
JSHandle<JSTaggedValue> retNull = deserializer.ReadValue();
JSHandle<JSTaggedValue> retHole = deserializer.ReadValue();
EXPECT_TRUE(JSTaggedValue::SameValue(thread, jsUndefined, retUndefined)) << "Not same value for JS_UNDEFINED";
EXPECT_TRUE(JSTaggedValue::SameValue(thread, jsNull, retNull)) << "Not same value for JS_NULL";
EXPECT_TRUE(JSTaggedValue::SameValue(thread, jsHole, retHole)) << "Not same value for JS_HOLE";
Destroy();
}
void LineStringTest(SerializeData* data)
{
Init();
BaseDeserializer deserializer(thread, data);
JSHandle<JSTaggedValue> res = deserializer.ReadValue();
ecmaVm->CollectGarbage(TriggerGCType::YOUNG_GC);
ecmaVm->CollectGarbage(TriggerGCType::OLD_GC);
EXPECT_FALSE(res.IsEmpty());
EXPECT_TRUE(res->IsLineString());
Destroy();
}
void TreeStringTest(SerializeData* data)
{
Init();
BaseDeserializer deserializer(thread, data);
JSHandle<JSTaggedValue> res = deserializer.ReadValue();
ecmaVm->CollectGarbage(TriggerGCType::YOUNG_GC);
ecmaVm->CollectGarbage(TriggerGCType::OLD_GC);
EXPECT_FALSE(res.IsEmpty());
EXPECT_TRUE(res->IsLineString());
Destroy();
}
void SlicedStringTest(SerializeData* data)
{
Init();
BaseDeserializer deserializer(thread, data);
JSHandle<JSTaggedValue> res = deserializer.ReadValue();
ecmaVm->CollectGarbage(TriggerGCType::YOUNG_GC);
ecmaVm->CollectGarbage(TriggerGCType::OLD_GC);
EXPECT_FALSE(res.IsEmpty());
EXPECT_TRUE(res->IsSlicedString());
Destroy();
}
void JSPlainObjectTest1(SerializeData* data)
{
Init();
BaseDeserializer deserializer(thread, data);
JSHandle<JSTaggedValue> objValue = deserializer.ReadValue();
ecmaVm->CollectGarbage(TriggerGCType::YOUNG_GC);
ecmaVm->CollectGarbage(TriggerGCType::OLD_GC);
JSHandle<JSObject> retObj = JSHandle<JSObject>::Cast(objValue);
EXPECT_FALSE(retObj.IsEmpty());
JSHandle<TaggedArray> array = JSObject::GetOwnPropertyKeys(thread, retObj);
uint32_t length = array->GetLength();
EXPECT_EQ(length, 4U);
double sum = 0.0;
for (uint32_t i = 0; i < length; i++) {
JSHandle<JSTaggedValue> key(thread, array->Get(thread, i));
double a = JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(retObj), key).GetValue()->GetNumber();
sum += a;
}
EXPECT_EQ(sum, 10);
Destroy();
}
void JSPlainObjectTest2(SerializeData* data)
{
Init();
BaseDeserializer deserializer(thread, data);
JSHandle<JSTaggedValue> objValue = deserializer.ReadValue();
ecmaVm->CollectGarbage(TriggerGCType::YOUNG_GC);
ecmaVm->CollectGarbage(TriggerGCType::OLD_GC);
JSHandle<JSObject> retObj = JSHandle<JSObject>::Cast(objValue);
EXPECT_FALSE(retObj.IsEmpty());
JSHandle<TaggedArray> array = JSObject::GetOwnPropertyKeys(thread, retObj);
uint32_t length = array->GetLength();
EXPECT_EQ(length, 10U);
for (uint32_t i = 0; i < length; i++) {
JSHandle<JSTaggedValue> key(thread, array->Get(thread, i));
JSHandle<JSTaggedValue> value =
JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(retObj), key).GetValue();
EXPECT_TRUE(value->GetTaggedObject()->GetClass()->IsJSObject());
}
Destroy();
}
void JSPlainObjectTest3(SerializeData* data)
{
Init();
BaseDeserializer deserializer(thread, data);
JSHandle<JSTaggedValue> objValue = deserializer.ReadValue();
ecmaVm->CollectGarbage(TriggerGCType::YOUNG_GC);
ecmaVm->CollectGarbage(TriggerGCType::OLD_GC);
JSHandle<JSObject> retObj = JSHandle<JSObject>::Cast(objValue);
EXPECT_FALSE(retObj.IsEmpty());
EXPECT_TRUE(retObj->GetClass()->IsDictionaryMode());
JSHandle<TaggedArray> array = JSObject::GetOwnPropertyKeys(thread, retObj);
uint32_t length = array->GetLength();
EXPECT_EQ(length, 1030U);
for (uint32_t i = 0; i < length; i++) {
JSHandle<JSTaggedValue> key(thread, array->Get(thread, i));
JSHandle<JSTaggedValue> value =
JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(retObj), key).GetValue();
EXPECT_TRUE(value->IsInt());
}
Destroy();
}
void JSPlainObjectTest4(SerializeData* data)
{
Init();
ObjectFactory *factory = ecmaVm->GetFactory();
JSHandle<JSTaggedValue> key(factory->NewFromASCII("str1"));
BaseDeserializer deserializer(thread, data);
JSHandle<JSTaggedValue> objValue = deserializer.ReadValue();
ecmaVm->CollectGarbage(TriggerGCType::YOUNG_GC);
ecmaVm->CollectGarbage(TriggerGCType::OLD_GC);
JSHandle<JSObject> retObj = JSHandle<JSObject>::Cast(objValue);
EXPECT_FALSE(retObj.IsEmpty());
JSHandle<JSTaggedValue> value =
JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(retObj), key).GetValue();
EXPECT_TRUE(value->IsTaggedArray());
TaggedArray *array = reinterpret_cast<TaggedArray *>(value->GetTaggedObject());
size_t length = array->GetLength();
EXPECT_EQ(length, 102400U);
for (uint32_t i = 0; i < length; i++) {
EXPECT_TRUE(array->Get(thread, i).IsHole());
}
Destroy();
}
void PrimitiveTest(SerializeData* data)
{
Init();
BaseDeserializer deserializer(thread, data);
JSHandle<JSTaggedValue> objValue = deserializer.ReadValue();
ecmaVm->CollectGarbage(TriggerGCType::YOUNG_GC);
ecmaVm->CollectGarbage(TriggerGCType::OLD_GC);
EXPECT_FALSE(objValue.IsEmpty());
EXPECT_TRUE(objValue->IsJSObject());
Destroy();
}
void JSErrorTest1(SerializeData* data)
{
Init();
BaseDeserializer deserializer(thread, data);
JSHandle<JSTaggedValue> objValue = deserializer.ReadValue();
ecmaVm->CollectGarbage(TriggerGCType::YOUNG_GC);
ecmaVm->CollectGarbage(TriggerGCType::OLD_GC);
EXPECT_FALSE(objValue.IsEmpty());
EXPECT_TRUE(objValue->IsJSError());
Destroy();
}
void JSErrorTest2(SerializeData* data)
{
Init();
BaseDeserializer deserializer(thread, data);
JSHandle<JSTaggedValue> objValue = deserializer.ReadValue();
ecmaVm->CollectGarbage(TriggerGCType::YOUNG_GC);
ecmaVm->CollectGarbage(TriggerGCType::OLD_GC);
JSHandle<JSObject> retObj = JSHandle<JSObject>::Cast(objValue);
EXPECT_FALSE(retObj.IsEmpty());
JSHandle<TaggedArray> array = JSObject::GetOwnPropertyKeys(thread, retObj);
uint32_t length = array->GetLength();
EXPECT_EQ(length, 2U);
for (uint32_t i = 0; i < length; i++) {
JSHandle<JSTaggedValue> key(thread, array->Get(thread, i));
JSHandle<JSTaggedValue> value =
JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(retObj), key).GetValue();
EXPECT_TRUE(value->IsJSError());
}
Destroy();
}
void JSErrorTest3(SerializeData *data)
{
Init();
BaseDeserializer deserializer(thread, data);
JSHandle<JSTaggedValue> objValue = deserializer.ReadValue();
ecmaVm->CollectGarbage(TriggerGCType::YOUNG_GC);
ecmaVm->CollectGarbage(TriggerGCType::OLD_GC);
JSHandle<JSObject> retObj = JSHandle<JSObject>::Cast(objValue);
EXPECT_FALSE(retObj.IsEmpty());
JSHandle<TaggedArray> array = JSObject::GetOwnPropertyKeys(thread, retObj);
uint32_t length = array->GetLength();
EXPECT_EQ(length, 7U);
for (uint32_t i = 0; i < length; i++) {
JSHandle<JSTaggedValue> key(thread, array->Get(thread, i));
JSHandle<JSTaggedValue> value =
JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(retObj), key).GetValue();
EXPECT_TRUE(value->IsJSError());
}
Destroy();
}
void BigIntTest(SerializeData* data)
{
Init();
BaseDeserializer deserializer(thread, data);
JSHandle<JSTaggedValue> objValue = deserializer.ReadValue();
ecmaVm->CollectGarbage(TriggerGCType::YOUNG_GC);
ecmaVm->CollectGarbage(TriggerGCType::OLD_GC);
JSHandle<JSObject> retObj = JSHandle<JSObject>::Cast(objValue);
EXPECT_FALSE(retObj.IsEmpty());
JSHandle<TaggedArray> array = JSObject::GetOwnPropertyKeys(thread, retObj);
uint32_t length = array->GetLength();
EXPECT_EQ(length, 2U);
for (uint32_t i = 0; i < length; i++) {
JSHandle<JSTaggedValue> key(thread, array->Get(thread, i));
JSHandle<JSTaggedValue> value =
JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(retObj), key).GetValue();
EXPECT_TRUE(value->GetTaggedObject()->GetClass()->IsBigInt());
}
Destroy();
}
void NativeBindingObjectTest1(SerializeData* data)
{
Init();
BaseDeserializer deserializer(thread, data);
JSHandle<JSTaggedValue> objValue = deserializer.ReadValue();
ecmaVm->CollectGarbage(TriggerGCType::YOUNG_GC);
ecmaVm->CollectGarbage(TriggerGCType::OLD_GC);
EXPECT_TRUE(objValue->IsUndefined());
Destroy();
}
void NativeBindingObjectTest2(SerializeData* data)
{
Init();
BaseDeserializer deserializer(thread, data);
JSHandle<JSTaggedValue> objValue = deserializer.ReadValue();
ecmaVm->CollectGarbage(TriggerGCType::YOUNG_GC);
ecmaVm->CollectGarbage(TriggerGCType::OLD_GC);
EXPECT_TRUE(objValue->IsJSObject());
JSHandle<JSObject> retObj = JSHandle<JSObject>::Cast(objValue);
JSHandle<TaggedArray> array = JSObject::GetOwnPropertyKeys(thread, retObj);
uint32_t length = array->GetLength();
EXPECT_EQ(length, 2U);
JSHandle<JSTaggedValue> key(thread, array->Get(thread, 0));
JSHandle<JSTaggedValue> value =
JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(retObj), key).GetValue();
EXPECT_TRUE(value->IsUndefined());
Destroy();
}
void JSSetTest(SerializeData* data)
{
Init();
ObjectFactory *factory = ecmaVm->GetFactory();
JSHandle<JSTaggedValue> value1(thread, JSTaggedValue(7));
JSHandle<JSTaggedValue> value2(thread, JSTaggedValue(9));
JSHandle<JSTaggedValue> value3(factory->NewFromASCII("x"));
JSHandle<JSTaggedValue> value4(factory->NewFromASCII("y"));
BaseDeserializer deserializer(thread, data);
JSHandle<JSTaggedValue> setValue = deserializer.ReadValue();
EXPECT_TRUE(!setValue.IsEmpty());
ecmaVm->CollectGarbage(TriggerGCType::YOUNG_GC);
ecmaVm->CollectGarbage(TriggerGCType::OLD_GC);
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);
int sum = 0;
for (uint32_t i = 0; i < propertyLength; i++) {
JSHandle<JSTaggedValue> key(thread, array->Get(thread, i));
double a = JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(retSet), key).GetValue()->GetNumber();
sum += a;
}
EXPECT_EQ(sum, 16);
EXPECT_EQ(retSet->GetSize(thread), 4);
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(SerializeData* data)
{
Init();
BaseDeserializer deserializer(thread, data);
JSHandle<JSTaggedValue> arrayValue = deserializer.ReadValue();
EXPECT_TRUE(!arrayValue.IsEmpty());
ecmaVm->CollectGarbage(TriggerGCType::YOUNG_GC);
ecmaVm->CollectGarbage(TriggerGCType::OLD_GC);
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);
int sum = 0;
for (uint32_t i = 0; i < propertyLength; i++) {
JSHandle<JSTaggedValue> key(thread, keyArray->Get(thread, i));
double a = JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(retArray), key).GetValue()->GetNumber();
sum += a;
}
EXPECT_EQ(sum, 226);
for (int i = 0; i < 20; i++) {
JSHandle<JSTaggedValue> value = JSArray::FastGetPropertyByValue(thread, arrayValue, i);
EXPECT_EQ(i, value.GetTaggedValue().GetInt());
}
Destroy();
}
void EcmaStringTest1(SerializeData* data)
{
Init();
const char *rawStr = "ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss"\
"sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss"\
"sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss"\
"ssssss";
JSHandle<EcmaString> ecmaString = thread->GetEcmaVM()->GetFactory()->NewFromASCII(rawStr);
BaseDeserializer deserializer(thread, data);
JSHandle<JSTaggedValue> res = deserializer.ReadValue();
EXPECT_TRUE(!res.IsEmpty()) << "[Empty] Deserialize ecmaString fail";
EXPECT_TRUE(res->IsString()) << "[NotString] Deserialize ecmaString fail";
ecmaVm->CollectGarbage(TriggerGCType::YOUNG_GC);
ecmaVm->CollectGarbage(TriggerGCType::OLD_GC);
JSHandle<EcmaString> resEcmaString = JSHandle<EcmaString>::Cast(res);
auto ecmaStringCode = EcmaStringAccessor(ecmaString).GetHashcode(thread);
auto resEcmaStringCode = EcmaStringAccessor(resEcmaString).GetHashcode(thread);
EXPECT_TRUE(ecmaStringCode == resEcmaStringCode) << "Not same HashCode";
EXPECT_TRUE(EcmaStringAccessor::StringsAreEqual(thread, *ecmaString, *resEcmaString)) << "Not same EcmaString";
Destroy();
}
void EcmaStringTest2(SerializeData* data)
{
Init();
JSHandle<EcmaString> ecmaString = thread->GetEcmaVM()->GetFactory()->NewFromStdString("你好,世界");
JSHandle<EcmaString> ecmaString1 = thread->GetEcmaVM()->GetFactory()->NewFromStdString("你好,世界");
auto ecmaStringCode1 = EcmaStringAccessor(ecmaString).GetHashcode(thread);
auto ecmaString1Code = EcmaStringAccessor(ecmaString1).GetHashcode(thread);
EXPECT_TRUE(ecmaStringCode1 == ecmaString1Code) << "Not same HashCode";
EXPECT_TRUE(EcmaStringAccessor::StringsAreEqual(thread, *ecmaString, *ecmaString1)) << "Not same EcmaString";
BaseDeserializer deserializer(thread, data);
JSHandle<JSTaggedValue> res = deserializer.ReadValue();
EXPECT_TRUE(!res.IsEmpty()) << "[Empty] Deserialize ecmaString fail";
EXPECT_TRUE(res->IsString()) << "[NotString] Deserialize ecmaString fail";
ecmaVm->CollectGarbage(TriggerGCType::YOUNG_GC);
ecmaVm->CollectGarbage(TriggerGCType::OLD_GC);
JSHandle<EcmaString> resEcmaString = JSHandle<EcmaString>::Cast(res);
auto ecmaStringCode2 = EcmaStringAccessor(ecmaString).GetHashcode(thread);
auto resEcmaStringCode = EcmaStringAccessor(resEcmaString).GetHashcode(thread);
EXPECT_TRUE(ecmaStringCode2 == resEcmaStringCode) << "Not same HashCode";
EXPECT_TRUE(EcmaStringAccessor::StringsAreEqual(thread, *ecmaString, *resEcmaString)) << "Not same EcmaString";
Destroy();
}
void Int32Test(SerializeData* data)
{
Init();
int32_t a = 64;
int32_t min = -2147483648;
int32_t b = -63;
BaseDeserializer deserializer(thread, data);
JSHandle<JSTaggedValue> resA = deserializer.ReadValue();
JSHandle<JSTaggedValue> resMin = deserializer.ReadValue();
JSHandle<JSTaggedValue> resB = deserializer.ReadValue();
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(SerializeData* data)
{
Init();
double a = 3.1415926535;
double b = -3.1415926535;
BaseDeserializer deserializer(thread, data);
JSHandle<JSTaggedValue> resA = deserializer.ReadValue();
JSHandle<JSTaggedValue> resB = deserializer.ReadValue();
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(SerializeData* data)
{
Init();
double tm = 28 * 60 * 60 * 1000;
BaseDeserializer deserializer(thread, data);
JSHandle<JSTaggedValue> res = deserializer.ReadValue();
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(thread) == JSTaggedValue(tm)) << "Not Same Time Value";
Destroy();
}
void JSMapTest(SerializeData* data, const JSHandle<JSMap> &originMap)
{
Init();
BaseDeserializer deserializer(thread, data);
JSHandle<JSTaggedValue> res = deserializer.ReadValue();
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(thread) == resMap->GetSize(thread)) << "the map size Not equal";
uint32_t resSize = static_cast<uint32_t>(resMap->GetSize(thread));
for (uint32_t i = 0; i < resSize; i++) {
JSHandle<JSTaggedValue> resKey(thread, resMap->GetKey(thread, i));
JSHandle<JSTaggedValue> resValue(thread, resMap->GetValue(thread, i));
JSHandle<JSTaggedValue> key(thread, originMap->GetKey(thread, i));
JSHandle<JSTaggedValue> value(thread, originMap->GetValue(thread, i));
JSHandle<EcmaString> resKeyStr = JSHandle<EcmaString>::Cast(resKey);
JSHandle<EcmaString> keyStr = JSHandle<EcmaString>::Cast(key);
EXPECT_TRUE(EcmaStringAccessor::StringsAreEqual(thread, *resKeyStr, *keyStr)) << "Not same map key";
EXPECT_TRUE(JSTaggedValue::ToInt32(thread, resValue) == JSTaggedValue::ToInt32(thread, value))
<< "Not same map value";
}
Destroy();
}
class JSTreeSetTestClass : public base::BuiltinsBase {
public:
static JSTaggedValue TestForEachFunc(EcmaRuntimeCallInfo *argv)
{
JSThread *thread = argv->GetThread();
JSHandle<JSTaggedValue> value = GetCallArg(argv, 0);
JSHandle<JSTaggedValue> key = GetCallArg(argv, 1);
JSHandle<JSAPITreeSet> set(GetCallArg(argv, 2));
EXPECT_EQ(key.GetTaggedValue(), value.GetTaggedValue());
JSAPITreeSet::Delete(thread, set, key);
JSHandle<JSAPITreeSet> jsTreeSet(GetThis(argv));
JSAPITreeSet::Add(thread, jsTreeSet, key);
return JSTaggedValue::Undefined();
}
static JSTaggedValue TestCompareFunction(EcmaRuntimeCallInfo *argv)
{
JSThread *thread = argv->GetThread();
JSHandle<JSTaggedValue> valueX = GetCallArg(argv, 0);
JSHandle<JSTaggedValue> valueY = GetCallArg(argv, 1);
if (valueX->IsString() && valueY->IsString()) {
auto xHandle = JSHandle<EcmaString>(valueX);
auto yHandle = JSHandle<EcmaString>(valueY);
int result = EcmaStringAccessor::Compare(thread->GetEcmaVM(), xHandle, yHandle);
if (result < 0) {
return JSTaggedValue(1);
}
if (result == 0) {
return JSTaggedValue(0);
}
return JSTaggedValue(-1);
}
if (valueX->IsNumber() && valueY->IsString()) {
return JSTaggedValue(1);
}
if (valueX->IsString() && valueY->IsNumber()) {
return JSTaggedValue(-1);
}
ComparisonResult res = ComparisonResult::UNDEFINED;
if (valueX->IsNumber() && valueY->IsNumber()) {
res = JSTaggedValue::StrictNumberCompare(valueY->GetNumber(), valueX->GetNumber());
} else {
res = JSTaggedValue::Compare(thread, valueY, valueX);
}
return res == ComparisonResult::GREAT ?
JSTaggedValue(1) : (res == ComparisonResult::LESS ? JSTaggedValue(-1) : JSTaggedValue(0));
}
};
JSTaggedValue InitializeTreeSetConstructor()
{
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
JSHandle<JSTaggedValue> globalObject = env->GetJSGlobalObject();
JSHandle<JSTaggedValue> key(factory->NewFromASCII("ArkPrivate"));
JSHandle<JSTaggedValue> value =
JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(globalObject), key).GetValue();
auto objCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
objCallInfo->SetFunction(JSTaggedValue::Undefined());
objCallInfo->SetThis(value.GetTaggedValue());
objCallInfo->SetCallArg(0, JSTaggedValue(static_cast<int>(ContainerTag::TreeSet)));
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, objCallInfo);
JSTaggedValue result = ContainersPrivate::Load(objCallInfo);
TestHelper::TearDownFrame(thread, prev);
return result;
}
JSHandle<JSAPITreeSet> CreateJSAPITreeSet(JSTaggedValue compare = JSTaggedValue::Undefined())
{
JSHandle<JSTaggedValue> compareHandle(thread, compare);
JSHandle<JSFunction> newTarget(thread, InitializeTreeSetConstructor());
auto objCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
objCallInfo->SetFunction(newTarget.GetTaggedValue());
objCallInfo->SetNewTarget(newTarget.GetTaggedValue());
objCallInfo->SetThis(JSTaggedValue::Undefined());
objCallInfo->SetCallArg(0, compareHandle.GetTaggedValue());
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, objCallInfo);
JSTaggedValue result = ContainersTreeSet::TreeSetConstructor(objCallInfo);
TestHelper::TearDownFrame(thread, prev);
JSHandle<JSAPITreeSet> set(thread, result);
return set;
}
void JSTreeSetNextTest(const JSHandle<JSAPITreeSet>& tset)
{
constexpr uint32_t nodeNumber = 8;
auto callInfo1 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);
callInfo1->SetFunction(JSTaggedValue::Undefined());
callInfo1->SetThis(tset.GetTaggedValue());
[[maybe_unused]] auto prev1 = TestHelper::SetupFrame(thread, callInfo1);
JSHandle<JSTaggedValue> iterValues(thread, ContainersTreeSet::Values(callInfo1));
TestHelper::TearDownFrame(thread, prev1);
EXPECT_TRUE(iterValues->IsJSAPITreeSetIterator());
{
JSMutableHandle<JSTaggedValue> result(thread, JSTaggedValue::Undefined());
auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);
callInfo->SetFunction(JSTaggedValue::Undefined());
callInfo->SetThis(iterValues.GetTaggedValue());
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
result.Update(JSAPITreeSetIterator::Next(callInfo));
TestHelper::TearDownFrame(thread, prev);
bool isDone = false;
for (int i = 0; !isDone; i++) {
EXPECT_EQ(i, JSIterator::IteratorValue(thread, result)->GetInt());
auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);
callInfo->SetFunction(JSTaggedValue::Undefined());
callInfo->SetThis(iterValues.GetTaggedValue());
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
result.Update(JSAPITreeSetIterator::Next(callInfo));
TestHelper::TearDownFrame(thread, prev);
isDone = JSIterator::IteratorComplete(thread, result);
EXPECT_EQ(i + 1 == nodeNumber, isDone);
}
}
}
void JSTreeSetEntriesTest(const JSHandle<JSAPITreeSet>& tset)
{
auto callInfo2 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);
callInfo2->SetFunction(JSTaggedValue::Undefined());
callInfo2->SetThis(tset.GetTaggedValue());
[[maybe_unused]] auto prev2 = TestHelper::SetupFrame(thread, callInfo2);
JSHandle<JSTaggedValue> iter(thread, ContainersTreeSet::Entries(callInfo2));
TestHelper::TearDownFrame(thread, prev2);
EXPECT_TRUE(iter->IsJSAPITreeSetIterator());
}
void JSTreeSetForeachTest(JSHandle<JSAPITreeSet>& tset)
{
constexpr uint32_t nodeNumber = 8;
constexpr uint32_t step = 2;
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
JSHandle<JSAPITreeSet> dset = CreateJSAPITreeSet();
{
JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
JSHandle<JSFunction> func =
factory->NewJSFunction(env, reinterpret_cast<void *>(JSTreeSetTestClass::TestForEachFunc));
auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);
callInfo->SetFunction(JSTaggedValue::Undefined());
callInfo->SetThis(tset.GetTaggedValue());
callInfo->SetCallArg(0, func.GetTaggedValue());
callInfo->SetCallArg(1, dset.GetTaggedValue());
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
ContainersTreeSet::ForEach(callInfo);
TestHelper::TearDownFrame(thread, prev);
}
EXPECT_EQ(dset->GetSize(thread), nodeNumber / step);
EXPECT_EQ(tset->GetSize(thread), nodeNumber / step);
for (int i = 0; i < nodeNumber; i += step) {
auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
callInfo->SetFunction(JSTaggedValue::Undefined());
callInfo->SetThis(dset.GetTaggedValue());
callInfo->SetCallArg(0, JSTaggedValue(i));
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
JSTaggedValue result = ContainersTreeSet::Has(callInfo);
TestHelper::TearDownFrame(thread, prev);
EXPECT_TRUE(result.IsTrue());
}
JSTreeSetStringTest(tset, dset);
}
void JSTreeSetStringTest(JSHandle<JSAPITreeSet>& tset, JSHandle<JSAPITreeSet>& dset)
{
constexpr uint32_t nodeNumber = 8;
constexpr uint32_t step = 2;
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
std::string myKey("mykey");
for (int i = 0; i < nodeNumber; i++) {
std::string ikey = myKey + std::to_string(i);
key.Update(factory->NewFromStdString(ikey).GetTaggedValue());
auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
callInfo->SetFunction(JSTaggedValue::Undefined());
callInfo->SetThis(tset.GetTaggedValue());
callInfo->SetCallArg(0, key.GetTaggedValue());
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
JSTaggedValue result = ContainersTreeSet::Add(callInfo);
TestHelper::TearDownFrame(thread, prev);
EXPECT_TRUE(result.IsTrue());
EXPECT_EQ(tset->GetSize(thread), nodeNumber / step + i + 1);
}
EXPECT_EQ(tset->GetSize(thread), nodeNumber / step + nodeNumber);
{
JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
JSHandle<JSFunction> func =
factory->NewJSFunction(env, reinterpret_cast<void *>(JSTreeSetTestClass::TestForEachFunc));
auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);
callInfo->SetFunction(JSTaggedValue::Undefined());
callInfo->SetThis(tset.GetTaggedValue());
callInfo->SetCallArg(0, func.GetTaggedValue());
callInfo->SetCallArg(1, dset.GetTaggedValue());
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
ContainersTreeSet::ForEach(callInfo);
TestHelper::TearDownFrame(thread, prev);
}
EXPECT_EQ(dset->GetSize(thread), nodeNumber + step);
EXPECT_EQ(tset->GetSize(thread), nodeNumber - step);
for (int i = 0; i < nodeNumber; i += step) {
std::string ikey = myKey + std::to_string(i);
key.Update(factory->NewFromStdString(ikey).GetTaggedValue());
auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
callInfo->SetFunction(JSTaggedValue::Undefined());
callInfo->SetThis(dset.GetTaggedValue());
callInfo->SetCallArg(0, key.GetTaggedValue());
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
JSTaggedValue result = ContainersTreeSet::Has(callInfo);
TestHelper::TearDownFrame(thread, prev);
EXPECT_TRUE(result.IsTrue());
}
}
void JSTreeSetTest(SerializeData* data)
{
Init();
constexpr uint32_t nodeNumber = 8;
BaseDeserializer deserializer(thread, data);
JSHandle<JSTaggedValue> res = deserializer.ReadValue();
EXPECT_TRUE(!res.IsEmpty()) << "[Empty] Deserialize JSAPITreeSet fail";
EXPECT_TRUE(res->IsJSAPITreeSet()) << "[NotJSAPITreeSet] Deserialize JSAPITreeSet fail";
JSHandle<JSAPITreeSet> tset = JSHandle<JSAPITreeSet>::Cast(res);
EXPECT_TRUE(tset->GetSize(thread) == nodeNumber) << "the treeset size Not equal";
for (int i = 0; i < nodeNumber; i++) {
auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
callInfo->SetFunction(JSTaggedValue::Undefined());
callInfo->SetThis(tset.GetTaggedValue());
callInfo->SetCallArg(0, JSTaggedValue(i));
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
JSTaggedValue result = ContainersTreeSet::Has(callInfo);
TestHelper::TearDownFrame(thread, prev);
EXPECT_TRUE(result.IsTrue());
}
JSTreeSetNextTest(tset);
JSTreeSetEntriesTest(tset);
JSTreeSetForeachTest(tset);
Destroy();
}
void JSSharedArrayBufferTest(SerializeData *data, int32_t byteLength, const char *msg)
{
Init();
BaseDeserializer deserializer(thread, data);
JSHandle<JSTaggedValue> res = deserializer.ReadValue();
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> resBufferData(thread, resJSArrayBuffer->GetArrayBufferData(thread));
JSHandle<JSNativePointer> resNp = JSHandle<JSNativePointer>::Cast(resBufferData);
void *resBuffer = resNp->GetExternalPointer();
ASSERT_NE(resBuffer, nullptr);
if (msg != nullptr) {
if (memcpy_s(resBuffer, byteLength, msg, byteLength) != EOK) {
EXPECT_TRUE(false) << " memcpy error!";
}
}
Destroy();
}
void SerializeMultiNonmovableRegionTest(SerializeData *data)
{
Init();
BaseDeserializer deserializer(thread, data);
JSHandle<JSTaggedValue> res = deserializer.ReadValue();
EXPECT_TRUE(!res.IsEmpty());
EXPECT_TRUE(res->IsJSObject());
JSTaggedValue elements = JSHandle<JSObject>(res)->GetElements(thread);
EXPECT_TRUE(elements.IsTaggedArray());
EXPECT_EQ(JSHandle<TaggedArray>(thread, elements)->GetLength(), 10 * 1024);
JSTaggedValue value = JSHandle<TaggedArray>(thread, elements)->Get(thread, 0);
EXPECT_TRUE(value.IsTaggedArray());
uint32_t length = JSHandle<TaggedArray>(thread, value)->GetLength();
EXPECT_EQ(length, 11 * 1024);
Destroy();
}
void SerializeMultiSharedRegionTest(SerializeData *data)
{
Init();
BaseDeserializer deserializer(thread, data);
JSHandle<JSTaggedValue> res = deserializer.ReadValue();
EXPECT_TRUE(!res.IsEmpty());
EXPECT_TRUE(res->IsJSObject());
JSTaggedValue elements = JSHandle<JSObject>(res)->GetElements(thread);
EXPECT_TRUE(elements.IsTaggedArray());
EXPECT_EQ(JSHandle<TaggedArray>(thread, elements)->GetLength(), 10 * 1024);
JSTaggedValue value = JSHandle<TaggedArray>(thread, elements)->Get(thread, 0);
EXPECT_TRUE(value.IsTaggedArray());
uint32_t length = JSHandle<TaggedArray>(thread, value)->GetLength();
EXPECT_EQ(length, 11 * 1024);
Destroy();
}
void SerializeMultiSharedRegionTest1(SerializeData *data)
{
Init();
BaseDeserializer deserializer(thread, data);
JSHandle<JSTaggedValue> res = deserializer.ReadValue();
EXPECT_TRUE(!res.IsEmpty());
EXPECT_TRUE(res->IsJSObject());
JSTaggedValue elements = JSHandle<JSObject>(res)->GetElements(thread);
EXPECT_TRUE(elements.IsTaggedArray());
EXPECT_EQ(JSHandle<TaggedArray>(thread, elements)->GetLength(), 3 * 1024);
for (int i = 0; i < 5; i++) {
JSTaggedValue value = JSHandle<TaggedArray>(thread, elements)->Get(thread, i);
EXPECT_TRUE(value.IsTaggedArray());
uint32_t length = JSHandle<TaggedArray>(thread, value)->GetLength();
EXPECT_EQ(length, 3 * 1024);
}
Destroy();
}
void SerializeMultiSharedRegionTest2(SerializeData *data)
{
Init();
BaseDeserializer deserializer(thread, data);
JSHandle<JSTaggedValue> res = deserializer.ReadValue();
EXPECT_TRUE(!res.IsEmpty());
EXPECT_TRUE(res->IsJSObject());
JSTaggedValue properties = JSHandle<JSObject>(res)->GetProperties(thread);
EXPECT_TRUE(properties.IsTaggedArray());
EXPECT_EQ(JSHandle<TaggedArray>(thread, properties)->GetLength(), 3 * 1024);
for (int i = 0; i < 5; i++) {
JSTaggedValue value = JSHandle<TaggedArray>(thread, properties)->Get(thread, i);
EXPECT_TRUE(value.IsTaggedArray());
uint32_t length = JSHandle<TaggedArray>(thread, value)->GetLength();
EXPECT_EQ(length, 3 * 1024);
}
JSTaggedValue elements = JSHandle<JSObject>(res)->GetElements(thread);
EXPECT_TRUE(elements.IsTaggedArray());
EXPECT_EQ(JSHandle<TaggedArray>(thread, elements)->GetLength(), 3 * 1024);
for (int i = 0; i < 5; i++) {
JSTaggedValue value = JSHandle<TaggedArray>(thread, elements)->Get(thread, i);
EXPECT_TRUE(value.IsTaggedArray());
uint32_t length = JSHandle<TaggedArray>(thread, value)->GetLength();
EXPECT_EQ(length, 3 * 1024);
}
Destroy();
}
void SerializeOldObjOOMTest(SerializeData *data)
{
if constexpr (G_USE_CMS_GC) {
return;
}
Init();
ecmaVm->SetEnableForceGC(false);
ObjectFactory *factory = ecmaVm->GetFactory();
BaseDeserializer deserializer(thread, data);
if (ecmaVm->GetHeap()->GetHeapLimitSize() >= 448_MB) {
[[maybe_unused]] EcmaHandleScope handleScope(thread);
for (int i = 0; i < 1450; i++) {
[[maybe_unused]] JSHandle<TaggedArray> element =
factory->NewTaggedArray(100 * 1024 / 8, JSTaggedValue::Hole());
[[maybe_unused]] JSHandle<TaggedArray> property =
factory->NewTaggedArray(100 * 1024 / 8, JSTaggedValue::Hole());
}
}
JSHandle<JSTaggedValue> res = deserializer.ReadValue();
EXPECT_TRUE(!res.IsEmpty());
EXPECT_TRUE(res->IsTaggedArray());
Destroy();
}
void SerializeHugeObjOOMTest(SerializeData *data)
{
Init();
ecmaVm->SetEnableForceGC(false);
ObjectFactory *factory = ecmaVm->GetFactory();
BaseDeserializer deserializer(thread, data);
if (ecmaVm->GetHeap()->GetHeapLimitSize() >= 448_MB) {
[[maybe_unused]] EcmaHandleScope handleScope(thread);
for (int i = 0; i < 1450; i++) {
[[maybe_unused]] JSHandle<TaggedArray> element =
factory->NewTaggedArray(100 * 1024 / 8, JSTaggedValue::Hole());
[[maybe_unused]] JSHandle<TaggedArray> property =
factory->NewTaggedArray(100 * 1024 / 8, JSTaggedValue::Hole());
}
}
JSHandle<JSTaggedValue> res = deserializer.ReadValue();
EXPECT_TRUE(!res.IsEmpty());
EXPECT_TRUE(res->IsTaggedArray());
Destroy();
}
void SerializeNonMoveObjOOMTest(SerializeData *data)
{
Init();
ecmaVm->SetEnableForceGC(false);
ObjectFactory *factory = ecmaVm->GetFactory();
BaseDeserializer deserializer(thread, data);
if (ecmaVm->GetHeap()->GetHeapLimitSize() >= 448_MB) {
[[maybe_unused]] EcmaHandleScope handleScope(thread);
for (int i = 0; i < 240; i++) {
[[maybe_unused]] JSHandle<TaggedArray> element =
factory->NewTaggedArray(100 * 1024 / 8, JSTaggedValue::Hole(),
MemSpaceType::NON_MOVABLE);
[[maybe_unused]] JSHandle<TaggedArray> property =
factory->NewTaggedArray(100 * 1024 / 8, JSTaggedValue::Hole(),
MemSpaceType::NON_MOVABLE);
}
}
JSHandle<JSTaggedValue> res = deserializer.ReadValue();
EXPECT_TRUE(!res.IsEmpty());
EXPECT_TRUE(res->IsTaggedArray());
Destroy();
}
void JSSharedSetBasicTest1(SerializeData *data)
{
Init();
BaseDeserializer deserializer(thread, data);
JSHandle<JSTaggedValue> res = deserializer.ReadValue();
EXPECT_TRUE(!res.IsEmpty()) << "[Empty] Deserialize JSSharedSet failed";
EXPECT_TRUE(res->IsJSSharedSet()) << "[NotJSSharedSet] Deserialize JSSharedSet failed";
JSHandle<JSSharedSet> jsSet = JSHandle<JSSharedSet>::Cast(res);
auto size = JSSharedSet::GetSize(thread, jsSet);
EXPECT_TRUE(size == INITIALIZE_SIZE);
JSSharedSet::Clear(thread, jsSet);
Destroy();
}
void JSSharedSetBasicTest2(SerializeData *data)
{
Init();
BaseDeserializer deserializer(thread, data);
JSHandle<JSTaggedValue> res = deserializer.ReadValue();
EXPECT_TRUE(!res.IsEmpty()) << "[Empty] Deserialize JSSharedSet failed";
EXPECT_TRUE(res->IsJSSharedSet()) << "[NotJSSharedSet] Deserialize JSSharedSet failed";
JSHandle<JSSharedSet> jsSet = JSHandle<JSSharedSet>::Cast(res);
auto size = JSSharedSet::GetSize(thread, jsSet);
EXPECT_TRUE(size == INITIALIZE_SIZE);
for (int32_t i = 0; i < size; i++) {
EXPECT_TRUE(JSSharedSet::Has(thread, jsSet, JSTaggedValue(i)));
}
JSSharedSet::Add(thread, jsSet, JSHandle<JSTaggedValue>(thread, JSTaggedValue(INITIALIZE_SIZE)));
bool result = JSSharedSet::Delete(thread, jsSet, JSHandle<JSTaggedValue>(thread, JSTaggedValue(0)));
EXPECT_TRUE(result) << "Delete failed";
Destroy();
}
void JSSharedSetMultiThreadTest1(SerializeData *data)
{
EXPECT_TRUE(data != nullptr);
Init();
BaseDeserializer deserializer(thread, data);
JSHandle<JSTaggedValue> res = deserializer.ReadValue();
EXPECT_TRUE(!res.IsEmpty()) << "[Empty] Deserialize JSSharedSet fail";
EXPECT_TRUE(res->IsJSSharedSet()) << "[NotJSSharedSet] Deserialize JSSharedSet fail";
JSHandle<JSSharedSet> jsSet = JSHandle<JSSharedSet>::Cast(res);
EXPECT_TRUE(JSSharedSet::GetSize(thread, jsSet) == INITIALIZE_SIZE);
for (int i = 0; i < INITIALIZE_SIZE; i++) {
EXPECT_TRUE(JSSharedSet::Has(thread, jsSet, JSTaggedValue(i)));
}
Destroy();
}
void JSSharedMapBasicTest1(SerializeData *data)
{
Init();
BaseDeserializer deserializer(thread, data);
JSHandle<JSTaggedValue> res = deserializer.ReadValue();
EXPECT_TRUE(!res.IsEmpty()) << "[Empty] Deserialize JSSharedMap failed";
EXPECT_TRUE(res->IsJSSharedMap()) << "[NotJSSharedMap] Deserialize JSSharedMap failed";
JSHandle<JSSharedMap> jsMap = JSHandle<JSSharedMap>::Cast(res);
auto size = JSSharedMap::GetSize(thread, jsMap);
EXPECT_TRUE(size == INITIALIZE_SIZE);
JSSharedMap::Clear(thread, jsMap);
Destroy();
}
void JSSharedMapBasicTest2(SerializeData *data)
{
Init();
BaseDeserializer deserializer(thread, data);
JSHandle<JSTaggedValue> res = deserializer.ReadValue();
EXPECT_TRUE(!res.IsEmpty()) << "[Empty] Deserialize JSSharedMap failed";
EXPECT_TRUE(res->IsJSSharedMap()) << "[NotJSSharedMap] Deserialize JSSharedMap failed";
JSHandle<JSSharedMap> jsMap = JSHandle<JSSharedMap>::Cast(res);
auto size = JSSharedMap::GetSize(thread, jsMap);
EXPECT_TRUE(size == INITIALIZE_SIZE);
for (int32_t i = 0; i < size; i++) {
EXPECT_TRUE(JSSharedMap::Has(thread, jsMap, JSTaggedValue(i)));
}
JSSharedMap::Set(thread, jsMap, JSHandle<JSTaggedValue>(thread, JSTaggedValue(INITIALIZE_SIZE)),
JSHandle<JSTaggedValue>(thread, JSTaggedValue(INITIALIZE_SIZE)));
bool result = JSSharedMap::Delete(thread, jsMap, JSHandle<JSTaggedValue>(thread, JSTaggedValue(0)));
EXPECT_TRUE(result) << "Delete failed";
Destroy();
}
void JSRegexpTest(SerializeData *data)
{
Init();
JSHandle<EcmaString> pattern = thread->GetEcmaVM()->GetFactory()->NewFromASCII("key2");
char buffer[] = "1234567";
uint32_t bufferSize = 7;
BaseDeserializer deserializer(thread, data);
JSHandle<JSTaggedValue> res = deserializer.ReadValue();
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(thread));
EXPECT_TRUE(originalSource->IsString());
JSHandle<JSTaggedValue> originalFlags(thread, resJSRegexp->GetOriginalFlags(thread));
EXPECT_TRUE(EcmaStringAccessor::StringsAreEqual(thread, *JSHandle<EcmaString>(originalSource), *pattern));
EXPECT_TRUE(originalFlags->IsInt());
EXPECT_TRUE(originalFlags->GetInt() == 0);
JSHandle<JSTaggedValue> resBufferData(thread, resJSRegexp->GetByteCodeBuffer(thread));
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(SerializeData *data)
{
Init();
JSHandle<JSTaggedValue> originTypedArrayName(thread, thread->GlobalConstants()->GetInt8ArrayString());
BaseDeserializer deserializer(thread, data);
JSHandle<JSTaggedValue> res = deserializer.ReadValue();
EXPECT_TRUE(!res.IsEmpty()) << "[Empty] Deserialize TypedArray fail";
EXPECT_TRUE(res->IsJSInt8Array()) << "[NotJSInt8Array] Deserialize TypedArray fail";
JSHandle<JSTypedArray> resJSInt8Array = JSHandle<JSTypedArray>::Cast(res);
uint32_t byteLength = resJSInt8Array->GetByteLength();
uint32_t byteOffset = resJSInt8Array->GetByteOffset();
uint32_t arrayLength = resJSInt8Array->GetArrayLength();
DataViewType contentType = resJSInt8Array->GetContentType();
JSHandle<JSTaggedValue> viewedArrayBuffer(thread, resJSInt8Array->GetViewedArrayBufferOrByteArray(thread));
EXPECT_EQ(byteLength, 10) << "Not Same ByteLength";
EXPECT_EQ(byteOffset, 0) << "Not Same ByteOffset";
EXPECT_EQ(arrayLength, 10) << "Not Same ArrayLength";
EXPECT_TRUE(contentType == DataViewType::INT8) << "Not Same ContentType";
EXPECT_TRUE(viewedArrayBuffer->IsArrayBuffer());
JSHandle<JSArrayBuffer> resJSArrayBuffer(viewedArrayBuffer);
uint32_t resTaggedLength = resJSArrayBuffer->GetArrayBufferByteLength();
EXPECT_EQ(resTaggedLength, 10) << "Not same viewedBuffer length";
JSHandle<JSTaggedValue> resBufferData(thread, resJSArrayBuffer->GetArrayBufferData(thread));
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(SerializeData *data)
{
Init();
JSHandle<JSTaggedValue> originTypedArrayName(thread, thread->GlobalConstants()->GetInt8ArrayString());
BaseDeserializer deserializer(thread, data);
JSHandle<JSTaggedValue> res = deserializer.ReadValue();
EXPECT_TRUE(!res.IsEmpty()) << "[Empty] Deserialize TypedArray fail";
EXPECT_TRUE(res->IsJSInt8Array()) << "[NotJSInt8Array] Deserialize TypedArray fail";
JSHandle<JSTypedArray> resJSInt8Array = JSHandle<JSTypedArray>::Cast(res);
uint32_t byteLength = resJSInt8Array->GetByteLength();
uint32_t byteOffset = resJSInt8Array->GetByteOffset();
uint32_t arrayLength = resJSInt8Array->GetArrayLength();
DataViewType contentType = resJSInt8Array->GetContentType();
JSHandle<JSTaggedValue> byteArray(thread, resJSInt8Array->GetViewedArrayBufferOrByteArray(thread));
EXPECT_EQ(byteLength, 10) << "Not Same ByteLength";
EXPECT_EQ(byteOffset, 0) << "Not Same ByteOffset";
EXPECT_EQ(arrayLength, 10) << "Not Same ArrayLength";
EXPECT_TRUE(contentType == DataViewType::INT8) << "Not Same ContentType";
EXPECT_TRUE(byteArray->IsByteArray());
JSHandle<ByteArray> resByteArray(byteArray);
uint32_t resTaggedLength = resByteArray->GetArrayLength();
EXPECT_EQ(resTaggedLength, 10) << "Not same viewedBuffer length";
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";
}
Destroy();
}
void SharedObjectTest4(SerializeData* data)
{
Init();
BaseDeserializer deserializer(thread, data);
JSHandle<JSTaggedValue> res = deserializer.ReadValue();
EXPECT_FALSE(res.IsEmpty());
EXPECT_TRUE(res->IsJSSharedObject()) << "[NotJSSharedObject] Deserialize SharedObject fail";
JSHandle<JSObject> sObj = JSHandle<JSObject>::Cast(res);
JSHandle<TaggedArray> array = JSObject::GetOwnPropertyKeys(thread, sObj);
uint32_t length = array->GetLength();
EXPECT_EQ(length, 512U);
for (uint32_t i = 0; i < length; i++) {
JSHandle<JSTaggedValue> key(thread, array->Get(thread, i));
JSHandle<JSTaggedValue> value =
JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(sObj), key).GetValue();
EXPECT_TRUE(value->IsInt());
}
Destroy();
}
void SerializeSharedFunctionTest(SerializeData *data)
{
Init();
BaseDeserializer deserializer(thread, data);
JSHandle<JSTaggedValue> res = deserializer.ReadValue();
EXPECT_TRUE(!res.IsEmpty()) << "[Empty] Deserialize SharedFunction fail";
EXPECT_TRUE(res->IsJSSharedFunction()) << "[NotJSSharedFunction] Deserialize SharedFunction fail";
JSHandle<JSSharedFunction> sFunc = JSHandle<JSSharedFunction>::Cast(res);
EXPECT_TRUE(sFunc->IsCallable());
EXPECT_FALSE(sFunc->GetProtoOrHClass(thread).IsHole());
EXPECT_TRUE(sFunc->GetLexicalEnv(thread).IsTaggedArray());
EXPECT_TRUE(sFunc->GetHomeObject(thread).IsJSSharedObject());
JSHandle<JSSharedObject> sObj(thread, sFunc->GetHomeObject(thread));
Destroy();
}
void SerializeSharedFunctionTest1(SerializeData *data)
{
Init();
BaseDeserializer deserializer(thread, data);
JSHandle<JSTaggedValue> res = deserializer.ReadValue();
EXPECT_TRUE(!res.IsEmpty()) << "[Empty] Deserialize SharedFunction fail";
EXPECT_TRUE(res->IsJSSharedFunction()) << "[NotJSSharedFunction] Deserialize SharedFunction fail";
Destroy();
}
void ObjectWithConcurrentFunctionTest(SerializeData* data)
{
Init();
ObjectFactory *factory = ecmaVm->GetFactory();
BaseDeserializer deserializer(thread, data);
JSHandle<JSTaggedValue> res = deserializer.ReadValue();
ecmaVm->CollectGarbage(TriggerGCType::YOUNG_GC);
ecmaVm->CollectGarbage(TriggerGCType::OLD_GC);
EXPECT_TRUE(!res.IsEmpty()) << "[Empty] Deserialize ObjectWithConcurrentFunction fail";
JSHandle<JSTaggedValue> key1(factory->NewFromASCII("abc"));
OperationResult result1 = JSObject::GetProperty(thread, res, key1);
JSHandle<JSTaggedValue> value1 = result1.GetRawValue();
EXPECT_TRUE(value1->IsString());
JSHandle<JSTaggedValue> key2(factory->NewFromASCII("2"));
OperationResult result2 = JSObject::GetProperty(thread, res, key2);
JSHandle<JSTaggedValue> value2 = result2.GetRawValue();
EXPECT_TRUE(value2->IsJSFunction());
JSHandle<JSTaggedValue> key3(factory->NewFromASCII("key"));
OperationResult result3 = JSObject::GetProperty(thread, res, key3);
JSHandle<JSTaggedValue> value3 = result3.GetRawValue();
EXPECT_TRUE(value3->IsJSFunction());
Destroy();
}
void TransferJSArrayBufferTest1(SerializeData *data, uintptr_t bufferAddrCheck)
{
Init();
BaseDeserializer deserializer(thread, data);
JSHandle<JSTaggedValue> res = deserializer.ReadValue();
ecmaVm->CollectGarbage(TriggerGCType::YOUNG_GC);
ecmaVm->CollectGarbage(TriggerGCType::OLD_GC);
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);
JSHandle<JSTaggedValue> nativePtr(thread, arrBuf->GetArrayBufferData(thread));
EXPECT_TRUE(nativePtr->IsJSNativePointer()) << "[NotJSNativePointer] Deserialize TransferJSArrayBuffer1 fail";
JSHandle<JSNativePointer> np = JSHandle<JSNativePointer>::Cast(nativePtr);
uintptr_t bufferAddr = reinterpret_cast<uintptr_t>(np->GetExternalPointer());
EXPECT_EQ(static_cast<uint64_t>(bufferAddr), static_cast<uint64_t>(bufferAddrCheck));
Destroy();
}
void TransferJSArrayBufferTest2(SerializeData *data, uintptr_t bufferAddrCheck)
{
Init();
BaseDeserializer deserializer(thread, data);
JSHandle<JSTaggedValue> res = deserializer.ReadValue();
ecmaVm->CollectGarbage(TriggerGCType::YOUNG_GC);
ecmaVm->CollectGarbage(TriggerGCType::OLD_GC);
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);
JSHandle<JSTaggedValue> nativePtr(thread, arrBuf->GetArrayBufferData(thread));
EXPECT_TRUE(nativePtr->IsJSNativePointer()) << "[NotJSNativePointer] Deserialize TransferJSArrayBuffer2 fail";
JSHandle<JSNativePointer> np = JSHandle<JSNativePointer>::Cast(nativePtr);
uintptr_t bufferAddr = reinterpret_cast<uintptr_t>(np->GetExternalPointer());
EXPECT_NE(static_cast<uint64_t>(bufferAddr), static_cast<uint64_t>(bufferAddrCheck));
Destroy();
}
void TransferJSArrayBufferTest3(SerializeData *data)
{
Init();
BaseDeserializer deserializer(thread, data);
JSHandle<JSTaggedValue> res = deserializer.ReadValue();
ecmaVm->CollectGarbage(TriggerGCType::YOUNG_GC);
ecmaVm->CollectGarbage(TriggerGCType::OLD_GC);
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(thread));
EXPECT_TRUE(nativePtr->IsUndefined()) << "[NotJSNativePointer] Deserialize TransferJSArrayBuffer3 fail";
Destroy();
}
void TransferJSArrayBufferTest5(SerializeData *data)
{
Init();
BaseDeserializer deserializer(thread, data);
JSHandle<JSTaggedValue> res = deserializer.ReadValue();
ecmaVm->CollectGarbage(TriggerGCType::YOUNG_GC);
ecmaVm->CollectGarbage(TriggerGCType::OLD_GC);
EXPECT_TRUE(!res.IsEmpty()) << "[Empty] Deserialize TransferJSArrayBuffer5 fail";
EXPECT_TRUE(res->IsArrayBuffer()) << "[NotJSArrayBuffer] Deserialize TransferJSArrayBuffer5 fail";
JSHandle<JSArrayBuffer> arrBuf = JSHandle<JSArrayBuffer>::Cast(res);
EXPECT_EQ(arrBuf->GetArrayBufferByteLength(), 5);
JSHandle<JSTaggedValue> nativePtr(thread, arrBuf->GetArrayBufferData(thread));
EXPECT_TRUE(reinterpret_cast<JSNativePointer *>(nativePtr->GetTaggedObject())->GetDeleter());
Destroy();
}
void SerializeCloneListTest1(SerializeData *data)
{
Init();
BaseDeserializer deserializer(thread, data);
JSHandle<JSTaggedValue> res = deserializer.ReadValue();
ecmaVm->CollectGarbage(TriggerGCType::YOUNG_GC);
ecmaVm->CollectGarbage(TriggerGCType::OLD_GC);
EXPECT_TRUE(!res.IsEmpty()) << "[Empty] Deserialize CloneListTest1 fail";
EXPECT_TRUE(res->IsJSShared());
JSType resType = res->GetTaggedObject()->GetClass()->GetObjectType();
EXPECT_EQ(resType, JSType::JS_SHARED_OBJECT);
ObjectFactory *factory = ecmaVm->GetFactory();
JSHandle<JSTaggedValue> key(factory->NewFromASCII("str2str1"));
JSHandle<JSTaggedValue> shareObj =
JSObject::GetProperty(thread, JSHandle<JSObject>(res), key).GetValue();
EXPECT_TRUE(shareObj->IsJSShared());
Destroy();
}
void SerializeCloneListTest2(SerializeData *data)
{
Init();
BaseDeserializer deserializer(thread, data);
JSHandle<JSTaggedValue> res = deserializer.ReadValue();
ecmaVm->CollectGarbage(TriggerGCType::YOUNG_GC);
ecmaVm->CollectGarbage(TriggerGCType::OLD_GC);
EXPECT_TRUE(!res.IsEmpty()) << "[Empty] Deserialize CloneListTest2 fail";
ObjectFactory *factory = ecmaVm->GetFactory();
JSHandle<JSTaggedValue> key(factory->NewFromASCII("shareObj"));
JSHandle<JSTaggedValue> shareObj =
JSObject::GetProperty(thread, JSHandle<JSObject>(res), key).GetValue();
EXPECT_TRUE(shareObj->IsJSShared());
Destroy();
}
void SerializeCloneListTest4(SerializeData *data)
{
Init();
BaseDeserializer deserializer(thread, data);
JSHandle<JSTaggedValue> res = deserializer.ReadValue();
ecmaVm->CollectGarbage(TriggerGCType::YOUNG_GC);
ecmaVm->CollectGarbage(TriggerGCType::OLD_GC);
EXPECT_TRUE(!res.IsEmpty()) << "[Empty] Deserialize CloneListTest4 fail";
Destroy();
}
void ModuleDeserialierTest1(SerializeData* data)
{
Init();
FileDeserializer deserializer(thread, data);
JSHandle<JSTaggedValue> res = deserializer.ReadValue();
ecmaVm->CollectGarbage(TriggerGCType::YOUNG_GC);
ecmaVm->CollectGarbage(TriggerGCType::OLD_GC);
EXPECT_FALSE(res.IsEmpty());
EXPECT_TRUE(res->IsSourceTextModule());
JSHandle<SourceTextModule> module = JSHandle<SourceTextModule>::Cast(res);
EXPECT_EQ(module->GetEcmaModuleFilenameString(), "modules.abc");
EXPECT_EQ(module->GetEcmaModuleRecordNameString(), "a");
EXPECT_EQ(module->GetTypes(), ModuleTypes::ECMA_MODULE);
EXPECT_EQ(module->GetStatus(), ModuleStatus::INSTANTIATED);
JSHandle<TaggedArray> requestedModules(thread, module->GetRequestedModules(thread));
EXPECT_TRUE(requestedModules->Get(thread, 0).IsSourceTextModule());
ObjectFactory *factory = ecmaVm->GetFactory();
JSHandle<JSTaggedValue> val = JSHandle<JSTaggedValue>::Cast(factory->NewFromUtf8("val"));
JSHandle<TaggedArray> importArray(thread, module->GetImportEntries(thread));
JSHandle<ImportEntry> importEntry(thread, importArray->Get(thread, 0));
EXPECT_EQ(importEntry->GetModuleRequestIndex(), 0);
EXPECT_EQ(importEntry->GetImportName(thread), val.GetTaggedValue());
EXPECT_EQ(importEntry->GetLocalName(thread), val.GetTaggedValue());
JSHandle<TaggedArray> localExportEntries(thread, module->GetLocalExportEntries(thread));
JSHandle<LocalExportEntry> localExportEntry(thread, localExportEntries->Get(thread, 0));
EXPECT_EQ(localExportEntry->GetLocalIndex(), 0);
EXPECT_EQ(localExportEntry->GetExportName(thread), val.GetTaggedValue());
EXPECT_EQ(localExportEntry->GetLocalName(thread), val.GetTaggedValue());
JSHandle<TaggedArray> indirectExportEntries(thread, module->GetIndirectExportEntries(thread));
JSHandle<IndirectExportEntry> indirectExportEntry(thread, indirectExportEntries->Get(thread, 0));
EXPECT_EQ(indirectExportEntry->GetModuleRequestIndex(), 0);
EXPECT_EQ(indirectExportEntry->GetExportName(thread), val.GetTaggedValue());
EXPECT_EQ(indirectExportEntry->GetImportName(thread), val.GetTaggedValue());
EXPECT_FALSE(module->IsLazyImportModule(0));
Destroy();
}
void ModuleDeserialierTest2(SerializeData* data)
{
Init();
FileDeserializer deserializer(thread, data);
JSHandle<JSTaggedValue> res = deserializer.ReadValue();
ecmaVm->CollectGarbage(TriggerGCType::YOUNG_GC);
ecmaVm->CollectGarbage(TriggerGCType::OLD_GC);
EXPECT_FALSE(res.IsEmpty());
JSHandle<TaggedArray> deserializedModules = JSHandle<TaggedArray>::Cast(res);
JSTaggedValue value = deserializedModules->Get(thread, 0);
EXPECT_EQ(SourceTextModule::Cast(value.GetTaggedObject())->GetStatus(), ModuleStatus::UNINSTANTIATED);
value = deserializedModules->Get(thread, 1);
EXPECT_EQ(SourceTextModule::Cast(value.GetTaggedObject())->GetStatus(), ModuleStatus::PREINSTANTIATING);
constexpr uint32_t INDEX_2 = 2;
value = deserializedModules->Get(thread, INDEX_2);
EXPECT_EQ(SourceTextModule::Cast(value.GetTaggedObject())->GetStatus(), ModuleStatus::INSTANTIATING);
constexpr uint32_t INDEX_3 = 3;
value = deserializedModules->Get(thread, INDEX_3);
EXPECT_EQ(SourceTextModule::Cast(value.GetTaggedObject())->GetStatus(), ModuleStatus::INSTANTIATED);
constexpr uint32_t INDEX_4 = 4;
value = deserializedModules->Get(thread, INDEX_4);
EXPECT_EQ(SourceTextModule::Cast(value.GetTaggedObject())->GetStatus(), ModuleStatus::INSTANTIATED);
constexpr uint32_t INDEX_5 = 5;
value = deserializedModules->Get(thread, INDEX_5);
EXPECT_EQ(SourceTextModule::Cast(value.GetTaggedObject())->GetStatus(), ModuleStatus::INSTANTIATED);
constexpr uint32_t INDEX_6 = 6;
value = deserializedModules->Get(thread, INDEX_6);
EXPECT_EQ(SourceTextModule::Cast(value.GetTaggedObject())->GetStatus(), ModuleStatus::INSTANTIATED);
constexpr uint32_t INDEX_7 = 7;
value = deserializedModules->Get(thread, INDEX_7);
EXPECT_EQ(SourceTextModule::Cast(value.GetTaggedObject())->GetStatus(), ModuleStatus::INSTANTIATED);
Destroy();
}
void ModuleDeserialierTest3(SerializeData* data)
{
Init();
FileDeserializer deserializer(thread, data);
JSHandle<JSTaggedValue> res = deserializer.ReadValue();
ecmaVm->CollectGarbage(TriggerGCType::YOUNG_GC);
ecmaVm->CollectGarbage(TriggerGCType::OLD_GC);
EXPECT_FALSE(res.IsEmpty());
EXPECT_TRUE(res->IsSourceTextModule());
JSHandle<SourceTextModule> module = JSHandle<SourceTextModule>::Cast(res);
EXPECT_EQ(module->GetEcmaModuleFilenameString(), "modules.abc");
EXPECT_EQ(module->GetStatus(), ModuleStatus::INSTANTIATED);
EXPECT_FALSE(module->IsLazyImportModule(0));
EXPECT_FALSE(module->IsLazyImportModule(1));
EXPECT_TRUE(module->IsLazyImportModule(2));
EXPECT_FALSE(module->IsLazyImportModule(3));
EXPECT_TRUE(module->IsLazyImportModule(4));
Destroy();
}
void ModuleDeserialierTest4(SerializeData* data)
{
Init();
FileDeserializer deserializer(thread, data);
JSHandle<JSTaggedValue> res = deserializer.ReadValue();
ecmaVm->CollectGarbage(TriggerGCType::YOUNG_GC);
ecmaVm->CollectGarbage(TriggerGCType::OLD_GC);
EXPECT_FALSE(res.IsEmpty());
EXPECT_TRUE(res->IsSourceTextModule());
JSHandle<SourceTextModule> module = JSHandle<SourceTextModule>::Cast(res);
EXPECT_EQ(module->GetEcmaModuleFilenameString(), "modules.abc");
EXPECT_EQ(module->GetStatus(), ModuleStatus::INSTANTIATED);
JSHandle<TaggedArray> environmentArray(thread, module->GetEnvironment(thread));
ObjectFactory *objectFactory = ecmaVm->GetFactory();
JSHandle<EcmaString> recordNameHdl = objectFactory->NewFromUtf8("sendable binding recordName");
JSHandle<EcmaString> baseFileNameHdl = objectFactory->NewFromUtf8("sendable binding baseFileNameHdl");
ResolvedRecordIndexBinding *recordIndexBinding =
ResolvedRecordIndexBinding::Cast(environmentArray->Get(thread, 0).GetTaggedObject());
EXPECT_EQ(recordIndexBinding->GetModuleRecord(thread), recordNameHdl.GetTaggedValue());
EXPECT_EQ(recordIndexBinding->GetAbcFileName(thread), baseFileNameHdl.GetTaggedValue());
EXPECT_EQ(recordIndexBinding->GetIndex(), 0);
JSHandle<JSTaggedValue> val = JSHandle<JSTaggedValue>::Cast(objectFactory->NewFromUtf8("val"));
ResolvedRecordBinding *nameBinding =
ResolvedRecordBinding::Cast(environmentArray->Get(thread, 1).GetTaggedObject());
EXPECT_EQ(nameBinding->GetModuleRecord(thread), recordNameHdl.GetTaggedValue());
EXPECT_EQ(nameBinding->GetBindingName(thread), val.GetTaggedValue());
ResolvedBinding *resolvedBinding =
ResolvedBinding::Cast(environmentArray->Get(thread, 2).GetTaggedObject());
JSHandle<SourceTextModule> module1(thread, resolvedBinding->GetModule(thread));
EXPECT_EQ(resolvedBinding->GetBindingName(thread), val.GetTaggedValue());
ResolvedIndexBinding *resolvedIndexBinding =
ResolvedIndexBinding::Cast(environmentArray->Get(thread, 3).GetTaggedObject());
JSHandle<SourceTextModule> module2(thread, resolvedBinding->GetModule(thread));
EXPECT_EQ(resolvedIndexBinding->GetIndex(), 0);
EXPECT_EQ(module1, module2);
EXPECT_EQ(module1->GetEcmaModuleFilenameString(), "modules1.abc");
EXPECT_EQ(module1->GetStatus(), ModuleStatus::INSTANTIATED);
Destroy();
}
void LargeArrayTest(SerializeData* data)
{
Init();
BaseDeserializer deserializer(thread, data);
JSHandle<JSTaggedValue> result = deserializer.ReadValue();
EXPECT_FALSE(result.IsEmpty()) << "Deserialization result should not be empty";
EXPECT_TRUE(result->IsTaggedArray()) << "Deserialized result should be TaggedArray";
JSHandle<TaggedArray> array = JSHandle<TaggedArray>::Cast(result);
EXPECT_EQ(array->GetLength(), 20U);
Destroy();
}
void HugeArrayTest(SerializeData* data)
{
Init();
BaseDeserializer deserializer(thread, data);
JSHandle<JSTaggedValue> result = deserializer.ReadValue();
EXPECT_FALSE(result.IsEmpty()) << "Deserialization result should not be empty";
EXPECT_TRUE(result->IsTaggedArray()) << "Deserialized result should be TaggedArray";
Destroy();
}
void NestedLargeObjectsTest(SerializeData* data)
{
Init();
BaseDeserializer deserializer(thread, data);
JSHandle<JSTaggedValue> result = deserializer.ReadValue();
EXPECT_FALSE(result.IsEmpty()) << "Deserialization result should not be empty";
EXPECT_TRUE(result->IsJSObject()) << "Deserialized result should be JSObject";
for (int i = 0; i < 5; i++) {
std::string keyStr = "nested" + std::to_string(i);
JSHandle<EcmaString> key = ecmaVm->GetFactory()->NewFromASCII(keyStr.c_str());
OperationResult res = JSObject::GetProperty(thread, result, JSHandle<JSTaggedValue>(key));
EXPECT_FALSE(res.GetValue().IsEmpty()) << "Nested object " << i << " should exist";
}
Destroy();
}
void MixedSizeObjectsTest(SerializeData* data)
{
Init();
BaseDeserializer deserializer(thread, data);
JSHandle<JSTaggedValue> result = deserializer.ReadValue();
EXPECT_FALSE(result.IsEmpty()) << "Deserialization result should not be empty";
EXPECT_TRUE(result->IsJSArray()) << "Deserialized result should be JSArray";
Destroy();
}
void SourceTextModuleMutableFieldsTest(SerializeData* data)
{
Init();
FileDeserializer deserializer(thread, data);
JSHandle<JSTaggedValue> res = deserializer.ReadValue();
ecmaVm->CollectGarbage(TriggerGCType::YOUNG_GC);
ecmaVm->CollectGarbage(TriggerGCType::OLD_GC);
EXPECT_FALSE(res.IsEmpty());
EXPECT_TRUE(res->IsSourceTextModule());
JSHandle<SourceTextModule> module = JSHandle<SourceTextModule>::Cast(res);
EXPECT_EQ(module->GetEcmaModuleFilenameString(), "mutable_fields_test.abc");
EXPECT_EQ(module->GetEcmaModuleRecordNameString(), "testRecord");
EXPECT_EQ(module->GetStatus(), ModuleStatus::INSTANTIATED);
EXPECT_EQ(module->GetTypes(), ModuleTypes::ECMA_MODULE);
JSTaggedValue undefined = thread->GlobalConstants()->GetUndefined();
EXPECT_EQ(module->GetNamespace(thread), undefined);
EXPECT_EQ(module->GetNameDictionary(thread), undefined);
EXPECT_EQ(module->GetCycleRoot(thread), module.GetTaggedValue());
EXPECT_EQ(module->GetTopLevelCapability(thread), undefined);
EXPECT_EQ(module->GetAsyncParentModules(thread), undefined);
EXPECT_EQ(module->GetSendableEnv(thread), undefined);
EXPECT_EQ(module->GetException(thread), JSTaggedValue::Hole());
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);
}
void Reset()
{
TestHelper::DestroyEcmaVMWithScope(ecmaVm, scope);
thread = nullptr;
ecmaVm = nullptr;
scope = nullptr;
TestHelper::CreateEcmaVMWithScope(ecmaVm, thread, scope);
}
std::unique_ptr<FileSerializer> CreateModuleSerializer()
{
return std::make_unique<FileSerializer>(thread, FileSerializer::SourceTextModuleFilter);
}
JSThread *thread {nullptr};
EcmaVM *ecmaVm {nullptr};
EcmaHandleScope *scope {nullptr};
EcmaVM *instance {nullptr};
protected:
JSTaggedValue InitializeTreeSetConstructor()
{
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
JSHandle<JSTaggedValue> globalObject = env->GetJSGlobalObject();
JSHandle<JSTaggedValue> key(factory->NewFromASCII("ArkPrivate"));
JSHandle<JSTaggedValue> value =
JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(globalObject), key).GetValue();
auto objCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
objCallInfo->SetFunction(JSTaggedValue::Undefined());
objCallInfo->SetThis(value.GetTaggedValue());
objCallInfo->SetCallArg(0, JSTaggedValue(static_cast<int>(ContainerTag::TreeSet)));
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, objCallInfo);
JSTaggedValue result = ContainersPrivate::Load(objCallInfo);
TestHelper::TearDownFrame(thread, prev);
return result;
}
JSHandle<JSAPITreeSet> CreateJSAPITreeSet(JSTaggedValue compare = JSTaggedValue::Undefined())
{
JSHandle<JSTaggedValue> compareHandle(thread, compare);
JSHandle<JSFunction> newTarget(thread, InitializeTreeSetConstructor());
auto objCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
objCallInfo->SetFunction(newTarget.GetTaggedValue());
objCallInfo->SetNewTarget(newTarget.GetTaggedValue());
objCallInfo->SetThis(JSTaggedValue::Undefined());
objCallInfo->SetCallArg(0, compareHandle.GetTaggedValue());
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, objCallInfo);
JSTaggedValue result = ContainersTreeSet::TreeSetConstructor(objCallInfo);
TestHelper::TearDownFrame(thread, prev);
JSHandle<JSAPITreeSet> set(thread, result);
return set;
}
};
HWTEST_F_L0(JSSerializerTest, SerializeOldObjOOMTest)
{
#if !USE_CMS_GC
ecmaVm->SetEnableForceGC(false);
ObjectFactory *factory = ecmaVm->GetFactory();
JSHandle<TaggedArray> array = factory->NewTaggedArray(80, JSTaggedValue::Hole());
for (int i = 0; i < 80; i++) {
JSHandle<TaggedArray> element =
factory->NewTaggedArray(100 * 1024 / 8, JSTaggedValue::Hole());
array->Set(thread, i, element);
}
ValueSerializer *serializer = new ValueSerializer(thread, false, true);
bool success = serializer->WriteValue(thread, JSHandle<JSTaggedValue>(array),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
EXPECT_TRUE(success);
std::unique_ptr<SerializeData> data = serializer->Release();
JSDeserializerTest jsDeserializerTest;
std::thread t1(&JSDeserializerTest::SerializeOldObjOOMTest, jsDeserializerTest, data.release());
ecmascript::ThreadSuspensionScope scope(thread);
t1.join();
delete serializer;
#endif
};
HWTEST_F_L0(JSSerializerTest, SerializeHugeObjOOMTest)
{
#if !USE_CMS_GC
ObjectFactory *factory = ecmaVm->GetFactory();
JSHandle<TaggedArray> array =
factory->NewTaggedArray(10 * 1024 * 1024 / 8, JSTaggedValue::Hole());
ValueSerializer *serializer = new ValueSerializer(thread, false, true);
bool success = serializer->WriteValue(thread, JSHandle<JSTaggedValue>(array),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
EXPECT_TRUE(success);
std::unique_ptr<SerializeData> data = serializer->Release();
JSDeserializerTest jsDeserializerTest;
std::thread t1(&JSDeserializerTest::SerializeHugeObjOOMTest, jsDeserializerTest, data.release());
ecmascript::ThreadSuspensionScope scope(thread);
t1.join();
delete serializer;
#endif
};
HWTEST_F_L0(JSSerializerTest, SerializeNonMoveObjOOMTest)
{
#if !USE_CMS_GC
ecmaVm->SetEnableForceGC(false);
ObjectFactory *factory = ecmaVm->GetFactory();
JSHandle<TaggedArray> array = factory->NewTaggedArray(80, JSTaggedValue::Hole());
for (int i = 0; i < 80; i++) {
JSHandle<TaggedArray> element =
factory->NewTaggedArray(100 * 1024 / 8, JSTaggedValue::Hole(),
MemSpaceType::NON_MOVABLE);
array->Set(thread, i, element);
}
ValueSerializer *serializer = new ValueSerializer(thread, false, true);
bool success = serializer->WriteValue(thread, JSHandle<JSTaggedValue>(array),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
EXPECT_TRUE(success);
std::unique_ptr<SerializeData> data = serializer->Release();
JSDeserializerTest jsDeserializerTest;
std::thread t1(&JSDeserializerTest::SerializeNonMoveObjOOMTest, jsDeserializerTest, data.release());
ecmascript::ThreadSuspensionScope scope(thread);
t1.join();
delete serializer;
#endif
};
HWTEST_F_L0(JSSerializerTest, SerializeJSSpecialValue)
{
ValueSerializer *serializer = new ValueSerializer(thread);
serializer->SerializeJSTaggedValue(JSTaggedValue::True());
serializer->SerializeJSTaggedValue(JSTaggedValue::False());
serializer->SerializeJSTaggedValue(JSTaggedValue::Undefined());
serializer->SerializeJSTaggedValue(JSTaggedValue::Null());
serializer->SerializeJSTaggedValue(JSTaggedValue::Hole());
std::unique_ptr<SerializeData> data = serializer->Release();
JSDeserializerTest jsDeserializerTest;
std::thread t1(&JSDeserializerTest::JSSpecialValueTest, jsDeserializerTest, data.release());
ecmascript::ThreadSuspensionScope scope(thread);
t1.join();
delete serializer;
};
HWTEST_F_L0(JSSerializerTest, SerializeLineString)
{
ObjectFactory *factory = ecmaVm->GetFactory();
JSHandle<EcmaString> str(factory->NewFromASCII("123"));
ValueSerializer *serializer = new ValueSerializer(thread);
serializer->WriteValue(thread, JSHandle<JSTaggedValue>(str),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
std::unique_ptr<SerializeData> data = serializer->Release();
JSDeserializerTest jsDeserializerTest;
std::thread t1(&JSDeserializerTest::LineStringTest, jsDeserializerTest, data.release());
{
ecmascript::ThreadSuspensionScope suspensionScope(thread);
t1.join();
}
delete serializer;
};
HWTEST_F_L0(JSSerializerTest, SerializeTreeString)
{
ObjectFactory *factory = ecmaVm->GetFactory();
JSHandle<EcmaString> str1(factory->NewFromASCII("123456789"));
JSHandle<EcmaString> str2(factory->NewFromASCII("abcdefghi"));
JSHandle<EcmaString> str3 = JSHandle<EcmaString>(thread, EcmaStringAccessor::Concat(ecmaVm, str1, str2));
EXPECT_TRUE(str3.GetTaggedValue().IsTreeString());
ValueSerializer *serializer = new ValueSerializer(thread);
serializer->WriteValue(thread, JSHandle<JSTaggedValue>(str3),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
std::unique_ptr<SerializeData> data = serializer->Release();
JSDeserializerTest jsDeserializerTest;
std::thread t1(&JSDeserializerTest::TreeStringTest, jsDeserializerTest, data.release());
{
ecmascript::ThreadSuspensionScope suspensionScope(thread);
t1.join();
}
delete serializer;
};
HWTEST_F_L0(JSSerializerTest, SerializeSlicedString)
{
ObjectFactory *factory = ecmaVm->GetFactory();
JSHandle<EcmaString> str1(factory->NewFromASCII("123456789abcedfghijk"));
JSHandle<EcmaString> str2 =
JSHandle<EcmaString>(thread, EcmaStringAccessor::GetSubString(ecmaVm, str1, 2, 13));
EXPECT_TRUE(str2.GetTaggedValue().IsSlicedString());
ValueSerializer *serializer = new ValueSerializer(thread);
serializer->WriteValue(thread, JSHandle<JSTaggedValue>(str2),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
std::unique_ptr<SerializeData> data = serializer->Release();
JSDeserializerTest jsDeserializerTest;
std::thread t1(&JSDeserializerTest::SlicedStringTest, jsDeserializerTest, data.release());
{
ecmascript::ThreadSuspensionScope suspensionScope(thread);
t1.join();
}
delete serializer;
};
HWTEST_F_L0(JSSerializerTest, SerializeJSPlainObject1)
{
ObjectFactory *factory = ecmaVm->GetFactory();
JSHandle<JSObject> obj = 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> value1(thread, JSTaggedValue(1));
JSHandle<JSTaggedValue> value2(thread, JSTaggedValue(2));
JSHandle<JSTaggedValue> value3(thread, JSTaggedValue(3));
JSHandle<JSTaggedValue> value4(thread, JSTaggedValue(4));
JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj), key1, value1);
JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj), key2, value2);
JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj), key3, value3);
JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj), key4, value4);
ValueSerializer *serializer = new ValueSerializer(thread);
serializer->WriteValue(thread, JSHandle<JSTaggedValue>(obj),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
std::unique_ptr<SerializeData> data = serializer->Release();
JSDeserializerTest jsDeserializerTest;
std::thread t1(&JSDeserializerTest::JSPlainObjectTest1, jsDeserializerTest, data.release());
ecmascript::ThreadSuspensionScope scope(thread);
t1.join();
delete serializer;
};
HWTEST_F_L0(JSSerializerTest, SerializeJSPlainObject2)
{
ObjectFactory *factory = ecmaVm->GetFactory();
JSHandle<JSObject> obj = factory->NewEmptyJSObject();
JSHandle<EcmaString> key1(factory->NewFromASCII("str1"));
JSHandle<EcmaString> key2(factory->NewFromASCII("str2"));
for (int i = 0; i < 10; i++) {
JSHandle<JSObject> obj1 = factory->NewEmptyJSObject();
JSHandle<EcmaString> key3(factory->NewFromASCII("str3"));
for (int j = 0; j < 10; j++) {
key3 = JSHandle<EcmaString>(thread, EcmaStringAccessor::Concat(ecmaVm, key3, key1));
JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj1), JSHandle<JSTaggedValue>(key3),
JSHandle<JSTaggedValue>(factory->NewEmptyJSObject()));
}
key2 = JSHandle<EcmaString>(thread, EcmaStringAccessor::Concat(ecmaVm, key2, key1));
JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj), JSHandle<JSTaggedValue>(key2),
JSHandle<JSTaggedValue>(obj1));
}
ValueSerializer *serializer = new ValueSerializer(thread);
serializer->WriteValue(thread, JSHandle<JSTaggedValue>(obj),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
std::unique_ptr<SerializeData> data = serializer->Release();
JSDeserializerTest jsDeserializerTest;
std::thread t1(&JSDeserializerTest::JSPlainObjectTest2, jsDeserializerTest, data.release());
ecmascript::ThreadSuspensionScope scope(thread);
t1.join();
delete serializer;
};
HWTEST_F_L0(JSSerializerTest, SerializeJSPlainObject3)
{
ObjectFactory *factory = ecmaVm->GetFactory();
JSHandle<JSObject> obj = factory->NewEmptyJSObject();
JSHandle<EcmaString> key1(factory->NewFromASCII("str1"));
JSHandle<EcmaString> key2(factory->NewFromASCII("str2"));
JSHandle<JSTaggedValue> value1(thread, JSTaggedValue(1));
for (int i = 0; i < 1030; i++) {
key2 = JSHandle<EcmaString>(thread, EcmaStringAccessor::Concat(ecmaVm, key2, key1));
JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj), JSHandle<JSTaggedValue>(key2), value1);
}
EXPECT_TRUE(obj->GetClass()->IsDictionaryMode());
ValueSerializer *serializer = new ValueSerializer(thread);
serializer->WriteValue(thread, JSHandle<JSTaggedValue>(obj),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
std::unique_ptr<SerializeData> data = serializer->Release();
JSDeserializerTest jsDeserializerTest;
std::thread t1(&JSDeserializerTest::JSPlainObjectTest3, jsDeserializerTest, data.release());
ecmascript::ThreadSuspensionScope scope(thread);
t1.join();
delete serializer;
};
HWTEST_F_L0(JSSerializerTest, SerializeJSPlainObject4)
{
ObjectFactory *factory = ecmaVm->GetFactory();
JSHandle<JSObject> obj = factory->NewEmptyJSObject();
JSHandle<EcmaString> key1(factory->NewFromASCII("str1"));
JSHandle<TaggedArray> taggedArray =
factory->NewTaggedArray(1024 * 100, JSTaggedValue::Hole(), MemSpaceType::OLD_SPACE);
JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj), JSHandle<JSTaggedValue>(key1),
JSHandle<JSTaggedValue>(taggedArray));
ValueSerializer *serializer = new ValueSerializer(thread);
serializer->WriteValue(thread, JSHandle<JSTaggedValue>(obj),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
std::unique_ptr<SerializeData> data = serializer->Release();
JSDeserializerTest jsDeserializerTest;
std::thread t1(&JSDeserializerTest::JSPlainObjectTest4, jsDeserializerTest, data.release());
ecmascript::ThreadSuspensionScope scope(thread);
t1.join();
delete serializer;
};
HWTEST_F_L0(JSSerializerTest, SerializeJSPlainObject5)
{
ObjectFactory *factory = ecmaVm->GetFactory();
JSHandle<JSObject> obj = 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("func"));
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<GlobalEnv> env = ecmaVm->GetGlobalEnv();
JSHandle<JSFunction> function = factory->NewJSFunction(env, nullptr, FunctionKind::NORMAL_FUNCTION);
EXPECT_TRUE(function->IsJSFunction());
JSHandle<JSTaggedValue> value5 = JSHandle<JSTaggedValue>::Cast(function);
JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj), key1, value1);
JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj), key2, value2);
JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj), key3, value3);
JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj), key4, value4);
JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj), key5, value5);
ValueSerializer *serializer = new ValueSerializer(thread);
bool success = serializer->WriteValue(thread, JSHandle<JSTaggedValue>(obj),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
EXPECT_FALSE(success);
std::unique_ptr<SerializeData> data = serializer->Release();
BaseDeserializer deserializer(thread, data.release());
JSHandle<JSTaggedValue> res = deserializer.ReadValue();
EXPECT_TRUE(res.IsEmpty());
delete serializer;
};
HWTEST_F_L0(JSSerializerTest, SerializeJSError1)
{
ObjectFactory *factory = ecmaVm->GetFactory();
JSHandle<EcmaString> msg(factory->NewFromASCII("this is error"));
JSHandle<JSTaggedValue> errorTag =
JSHandle<JSTaggedValue>::Cast(factory->NewJSError(base::ErrorType::ERROR, msg, StackCheck::NO));
ValueSerializer *serializer = new ValueSerializer(thread);
serializer->WriteValue(thread, errorTag, JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
std::unique_ptr<SerializeData> data = serializer->Release();
JSDeserializerTest jsDeserializerTest;
std::thread t1(&JSDeserializerTest::JSErrorTest1, jsDeserializerTest, data.release());
ecmascript::ThreadSuspensionScope scope(thread);
t1.join();
delete serializer;
};
HWTEST_F_L0(JSSerializerTest, SerializeJSError2)
{
ObjectFactory *factory = ecmaVm->GetFactory();
JSHandle<JSObject> obj = factory->NewEmptyJSObject();
JSHandle<EcmaString> key1(factory->NewFromASCII("error1"));
JSHandle<EcmaString> key2(factory->NewFromASCII("error2"));
JSHandle<EcmaString> msg(factory->NewFromASCII("this is error"));
JSHandle<JSTaggedValue> errorTag =
JSHandle<JSTaggedValue>::Cast(factory->NewJSError(base::ErrorType::ERROR, msg, StackCheck::NO));
JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj), JSHandle<JSTaggedValue>(key1), errorTag);
JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj), JSHandle<JSTaggedValue>(key2), errorTag);
ValueSerializer *serializer = new ValueSerializer(thread);
serializer->WriteValue(thread, JSHandle<JSTaggedValue>(obj),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
std::unique_ptr<SerializeData> data = serializer->Release();
JSDeserializerTest jsDeserializerTest;
std::thread t1(&JSDeserializerTest::JSErrorTest2, jsDeserializerTest, data.release());
ecmascript::ThreadSuspensionScope scope(thread);
t1.join();
delete serializer;
};
HWTEST_F_L0(JSSerializerTest, SerializeJSError3)
{
ObjectFactory *factory = ecmaVm->GetFactory();
JSHandle<JSObject> obj = factory->NewEmptyJSObject();
JSHandle<EcmaString> key1(factory->NewFromASCII("error1"));
JSHandle<EcmaString> key2(factory->NewFromASCII("error2"));
JSHandle<EcmaString> key3(factory->NewFromASCII("error3"));
JSHandle<EcmaString> key4(factory->NewFromASCII("error4"));
JSHandle<EcmaString> key5(factory->NewFromASCII("error5"));
JSHandle<EcmaString> key6(factory->NewFromASCII("error6"));
JSHandle<EcmaString> key7(factory->NewFromASCII("error7"));
JSHandle<EcmaString> msg(factory->NewFromASCII("this is error"));
JSHandle<JSTaggedValue> error1 =
JSHandle<JSTaggedValue>::Cast(factory->NewJSError(base::ErrorType::RANGE_ERROR, msg, StackCheck::NO));
JSHandle<JSTaggedValue> error2 =
JSHandle<JSTaggedValue>::Cast(factory->NewJSError(base::ErrorType::REFERENCE_ERROR, msg, StackCheck::NO));
JSHandle<JSTaggedValue> error3 =
JSHandle<JSTaggedValue>::Cast(factory->NewJSError(base::ErrorType::TYPE_ERROR, msg, StackCheck::NO));
JSHandle<JSTaggedValue> error4 =
JSHandle<JSTaggedValue>::Cast(factory->NewJSError(base::ErrorType::URI_ERROR, msg, StackCheck::NO));
JSHandle<JSTaggedValue> error5 =
JSHandle<JSTaggedValue>::Cast(factory->NewJSError(base::ErrorType::SYNTAX_ERROR, msg, StackCheck::NO));
JSHandle<JSTaggedValue> error6 =
JSHandle<JSTaggedValue>::Cast(factory->NewJSError(base::ErrorType::OOM_ERROR, msg, StackCheck::NO));
JSHandle<JSTaggedValue> error7 =
JSHandle<JSTaggedValue>::Cast(factory->NewJSError(base::ErrorType::TERMINATION_ERROR, msg, StackCheck::NO));
JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj), JSHandle<JSTaggedValue>(key1), error1);
JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj), JSHandle<JSTaggedValue>(key2), error2);
JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj), JSHandle<JSTaggedValue>(key3), error3);
JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj), JSHandle<JSTaggedValue>(key4), error4);
JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj), JSHandle<JSTaggedValue>(key5), error5);
JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj), JSHandle<JSTaggedValue>(key6), error6);
JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj), JSHandle<JSTaggedValue>(key7), error7);
ValueSerializer *serializer = new ValueSerializer(thread);
bool success = serializer->WriteValue(thread, JSHandle<JSTaggedValue>(obj),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
EXPECT_TRUE(success);
std::unique_ptr<SerializeData> data = serializer->Release();
JSDeserializerTest jsDeserializerTest;
std::thread t1(&JSDeserializerTest::JSErrorTest3, jsDeserializerTest, data.release());
ecmascript::ThreadSuspensionScope scope(thread);
t1.join();
delete serializer;
}
HWTEST_F_L0(JSSerializerTest, SerializeJSError4)
{
ObjectFactory *factory = ecmaVm->GetFactory();
JSHandle<EcmaString> msg(factory->NewFromASCII("this is error"));
JSHandle<EcmaString> stack(factory->NewFromASCII("this is error stack"));
JSHandle<JSTaggedValue> errorTag =
JSHandle<JSTaggedValue>::Cast(factory->NewJSError(base::ErrorType::ERROR, msg, stack, StackCheck::NO));
ValueSerializer *serializer = new (std::nothrow) ValueSerializer(thread, false, false, true);
if (serializer == nullptr) {
return;
}
serializer->WriteValue(thread, errorTag, JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
std::unique_ptr<SerializeData> data = serializer->Release();
JSDeserializerTest jsDeserializerTest;
std::thread t1(&JSDeserializerTest::JSErrorTest1, jsDeserializerTest, data.release());
ecmascript::ThreadSuspensionScope scope(thread);
t1.join();
delete serializer;
};
HWTEST_F_L0(JSSerializerTest, SerializeJSError5)
{
ObjectFactory *factory = ecmaVm->GetFactory();
JSHandle<JSObject> obj = factory->NewEmptyJSObject();
JSHandle<EcmaString> key1(factory->NewFromASCII("error1"));
JSHandle<EcmaString> key2(factory->NewFromASCII("error2"));
JSHandle<EcmaString> msg(factory->NewFromASCII("this is error"));
JSHandle<EcmaString> stack(factory->NewFromASCII("this is error stack"));
JSHandle<JSTaggedValue> errorTag =
JSHandle<JSTaggedValue>::Cast(factory->NewJSError(base::ErrorType::ERROR, msg, stack, StackCheck::NO));
JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj), JSHandle<JSTaggedValue>(key1), errorTag);
JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj), JSHandle<JSTaggedValue>(key2), errorTag);
ValueSerializer *serializer = new (std::nothrow) ValueSerializer(thread, false, false, true);
if (serializer == nullptr) {
return;
}
serializer->WriteValue(thread, JSHandle<JSTaggedValue>(obj),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
std::unique_ptr<SerializeData> data = serializer->Release();
JSDeserializerTest jsDeserializerTest;
std::thread t1(&JSDeserializerTest::JSErrorTest2, jsDeserializerTest, data.release());
ecmascript::ThreadSuspensionScope scope(thread);
t1.join();
delete serializer;
};
HWTEST_F_L0(JSSerializerTest, SerializeJSError6)
{
ObjectFactory *factory = ecmaVm->GetFactory();
JSHandle<JSObject> obj = factory->NewEmptyJSObject();
JSHandle<EcmaString> key1(factory->NewFromASCII("error1"));
JSHandle<EcmaString> key2(factory->NewFromASCII("error2"));
JSHandle<EcmaString> key3(factory->NewFromASCII("error3"));
JSHandle<EcmaString> key4(factory->NewFromASCII("error4"));
JSHandle<EcmaString> key5(factory->NewFromASCII("error5"));
JSHandle<EcmaString> key6(factory->NewFromASCII("error6"));
JSHandle<EcmaString> key7(factory->NewFromASCII("error7"));
JSHandle<EcmaString> msg(factory->NewFromASCII("this is error"));
JSHandle<EcmaString> stack(factory->NewFromASCII("this is error stack"));
JSHandle<JSTaggedValue> error1 =
JSHandle<JSTaggedValue>::Cast(factory->NewJSError(base::ErrorType::RANGE_ERROR, msg, stack, StackCheck::NO));
JSHandle<JSTaggedValue> error2 =
JSHandle<JSTaggedValue>::Cast(factory->NewJSError(base::ErrorType::REFERENCE_ERROR, msg,
stack, StackCheck::NO));
JSHandle<JSTaggedValue> error3 =
JSHandle<JSTaggedValue>::Cast(factory->NewJSError(base::ErrorType::TYPE_ERROR, msg, stack, StackCheck::NO));
JSHandle<JSTaggedValue> error4 =
JSHandle<JSTaggedValue>::Cast(factory->NewJSError(base::ErrorType::URI_ERROR, msg, stack, StackCheck::NO));
JSHandle<JSTaggedValue> error5 =
JSHandle<JSTaggedValue>::Cast(factory->NewJSError(base::ErrorType::SYNTAX_ERROR, msg, stack, StackCheck::NO));
JSHandle<JSTaggedValue> error6 =
JSHandle<JSTaggedValue>::Cast(factory->NewJSError(base::ErrorType::OOM_ERROR, msg, stack, StackCheck::NO));
JSHandle<JSTaggedValue> error7 =
JSHandle<JSTaggedValue>::Cast(factory->NewJSError(base::ErrorType::TERMINATION_ERROR, msg,
stack, StackCheck::NO));
JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj), JSHandle<JSTaggedValue>(key1), error1);
JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj), JSHandle<JSTaggedValue>(key2), error2);
JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj), JSHandle<JSTaggedValue>(key3), error3);
JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj), JSHandle<JSTaggedValue>(key4), error4);
JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj), JSHandle<JSTaggedValue>(key5), error5);
JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj), JSHandle<JSTaggedValue>(key6), error6);
JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj), JSHandle<JSTaggedValue>(key7), error7);
ValueSerializer *serializer = new (std::nothrow) ValueSerializer(thread, false, false, true);
if (serializer == nullptr) {
return;
}
bool success = serializer->WriteValue(thread, JSHandle<JSTaggedValue>(obj),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
EXPECT_TRUE(success);
std::unique_ptr<SerializeData> data = serializer->Release();
JSDeserializerTest jsDeserializerTest;
std::thread t1(&JSDeserializerTest::JSErrorTest3, jsDeserializerTest, data.release());
ecmascript::ThreadSuspensionScope scope(thread);
t1.join();
delete serializer;
}
HWTEST_F_L0(JSSerializerTest, SerializeBigInt)
{
ObjectFactory *factory = ecmaVm->GetFactory();
JSHandle<JSObject> obj = factory->NewEmptyJSObject();
JSHandle<EcmaString> key1(factory->NewFromASCII("pss"));
JSHandle<EcmaString> key2(factory->NewFromASCII("nativeHeap"));
CString value1 = "365769";
CString value2 = "139900";
JSHandle<BigInt> bigInt1 = BigIntHelper::SetBigInt(thread, value1);
JSHandle<BigInt> bigInt2 = BigIntHelper::SetBigInt(thread, value1);
JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj), JSHandle<JSTaggedValue>(key1),
JSHandle<JSTaggedValue>(bigInt1));
JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj), JSHandle<JSTaggedValue>(key2),
JSHandle<JSTaggedValue>(bigInt2));
ValueSerializer *serializer = new ValueSerializer(thread);
bool success = serializer->WriteValue(thread, JSHandle<JSTaggedValue>(obj),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
EXPECT_TRUE(success) << "Serialize bigInt fail";
std::unique_ptr<SerializeData> data = serializer->Release();
JSDeserializerTest jsDeserializerTest;
std::thread t1(&JSDeserializerTest::BigIntTest, jsDeserializerTest, data.release());
ecmascript::ThreadSuspensionScope scope(thread);
t1.join();
delete serializer;
};
HWTEST_F_L0(JSSerializerTest, SerializePrimitive)
{
ObjectFactory *factory = ecmaVm->GetFactory();
JSHandle<JSObject> obj = factory->NewEmptyJSObject();
JSHandle<EcmaString> keyInt(factory->NewFromASCII("int"));
JSHandle<EcmaString> keyDouble(factory->NewFromASCII("double"));
JSHandle<EcmaString> keyBoolean(factory->NewFromASCII("boolean"));
JSHandle<EcmaString> keyString(factory->NewFromASCII("string"));
int32_t intValue = 42;
double doubleValue = 3.14159;
bool booleanValue = true;
JSHandle<EcmaString> stringValue(factory->NewFromASCII("Hello World"));
JSHandle<JSPrimitiveRef> intPrimitive = factory->NewJSPrimitiveRef(
PrimitiveType::PRIMITIVE_NUMBER, JSHandle<JSTaggedValue>(thread, JSTaggedValue(intValue)));
JSHandle<JSPrimitiveRef> doublePrimitive = factory->NewJSPrimitiveRef(
PrimitiveType::PRIMITIVE_NUMBER, JSHandle<JSTaggedValue>(thread, JSTaggedValue(doubleValue)));
JSHandle<JSPrimitiveRef> booleanPrimitive = factory->NewJSPrimitiveRef(
PrimitiveType::PRIMITIVE_BOOLEAN, JSHandle<JSTaggedValue>(thread, JSTaggedValue(booleanValue)));
JSHandle<JSPrimitiveRef> stringPrimitive = factory->NewJSPrimitiveRef(
PrimitiveType::PRIMITIVE_STRING, JSHandle<JSTaggedValue>(stringValue));
JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj), JSHandle<JSTaggedValue>(keyInt),
JSHandle<JSTaggedValue>(intPrimitive));
JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj), JSHandle<JSTaggedValue>(keyDouble),
JSHandle<JSTaggedValue>(doublePrimitive));
JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj), JSHandle<JSTaggedValue>(keyBoolean),
JSHandle<JSTaggedValue>(booleanPrimitive));
JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj), JSHandle<JSTaggedValue>(keyString),
JSHandle<JSTaggedValue>(stringPrimitive));
ValueSerializer *serializer = new ValueSerializer(thread);
bool success = serializer->WriteValue(thread, JSHandle<JSTaggedValue>(obj),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
EXPECT_TRUE(success) << "Serialize primitive types failed";
std::unique_ptr<SerializeData> data = serializer->Release();
JSDeserializerTest jsDeserializerTest;
std::thread t1(&JSDeserializerTest::PrimitiveTest, jsDeserializerTest, data.release());
ecmascript::ThreadSuspensionScope scope(thread);
t1.join();
delete serializer;
}
static void* Detach(void *param1, void *param2, void *hint, void *detachData)
{
GTEST_LOG_(INFO) << "detach is running";
if (param1 == nullptr && param2 == nullptr) {
GTEST_LOG_(INFO) << "detach: two params is nullptr";
}
if (hint == nullptr && detachData) {
GTEST_LOG_(INFO) << "detach: hint is nullptr";
}
return nullptr;
}
static void* Attach([[maybe_unused]] void *enginePointer, [[maybe_unused]] void *buffer, [[maybe_unused]] void *hint,
[[maybe_unused]] void *attachData)
{
GTEST_LOG_(INFO) << "attach is running";
return nullptr;
}
static void* Attach2([[maybe_unused]] void *enginePointer, [[maybe_unused]] void *buffer, [[maybe_unused]] void *hint,
[[maybe_unused]] void *attachData)
{
GTEST_LOG_(INFO) << "attach2 is running";
EcmaVM *vm = reinterpret_cast<EcmaVM *>(enginePointer);
ObjectFactory *factory = vm->GetFactory();
JSThread *thread = vm->GetJSThread();
ThreadManagedScope scope(thread);
JSHandle<JSTaggedValue> prototype(thread, JSTaggedValue::Undefined());
JSHandle<JSHClass> hclass = factory->NewEcmaHClass(JSObject::SIZE, JSType::JS_OBJECT, prototype);
JSHandle<JSObject> obj = factory->NewJSObject(hclass);
return reinterpret_cast<void *>(obj.GetAddress());
}
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<JSObject> obj1 = factory->NewEmptyJSObject();
JSHandle<JSTaggedValue> key1 = thread->GlobalConstants()->GetHandledNativeBindingSymbol();
JSHandle<JSTaggedValue> key2(factory->NewFromASCII("x"));
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));
JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj1), key1, value1);
JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj1), key2, value2);
obj1->GetClass()->SetIsNativeBindingObject(true);
ValueSerializer *serializer = new ValueSerializer(thread);
bool success = serializer->WriteValue(thread, JSHandle<JSTaggedValue>(obj1),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
EXPECT_TRUE(success) << "Serialize fail";
std::unique_ptr<SerializeData> data = serializer->Release();
JSDeserializerTest jsDeserializerTest;
std::thread t1(&JSDeserializerTest::NativeBindingObjectTest1, jsDeserializerTest, data.release());
ecmascript::ThreadSuspensionScope scope(thread);
t1.join();
delete serializer;
}
HWTEST_F_L0(JSSerializerTest, SerializeNativeBindingObject2)
{
ObjectFactory *factory = ecmaVm->GetFactory();
JSHandle<JSObject> obj1 = factory->NewEmptyJSObject();
JSHandle<JSObject> obj2 = factory->NewEmptyJSObject();
JSHandle<JSTaggedValue> key1 = thread->GlobalConstants()->GetHandledNativeBindingSymbol();
JSHandle<JSTaggedValue> key2(factory->NewFromASCII("x"));
JSHandle<JSTaggedValue> key3(factory->NewFromASCII("xx"));
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));
JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj1), key1, value1);
JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj1), key2, value2);
obj1->GetClass()->SetIsNativeBindingObject(true);
JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj2), key2, JSHandle<JSTaggedValue>(obj1));
JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj2), key3, value3);
ValueSerializer *serializer = new ValueSerializer(thread);
bool success = serializer->WriteValue(thread, JSHandle<JSTaggedValue>(obj2),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
EXPECT_TRUE(success) << "Serialize fail";
std::unique_ptr<SerializeData> data = serializer->Release();
JSDeserializerTest jsDeserializerTest;
std::thread t1(&JSDeserializerTest::NativeBindingObjectTest2, jsDeserializerTest, data.release());
ecmascript::ThreadSuspensionScope scope(thread);
t1.join();
delete serializer;
}
HWTEST_F_L0(JSSerializerTest, SerializeNativeBindingObject3)
{
ObjectFactory *factory = ecmaVm->GetFactory();
JSHandle<JSObject> obj1 = factory->NewEmptyJSObject();
JSHandle<JSTaggedValue> key1 = thread->GlobalConstants()->GetHandledNativeBindingSymbol();
JSHandle<JSTaggedValue> key2(factory->NewFromASCII("x"));
auto info = CreateNativeBindingInfo(reinterpret_cast<void*>(Attach), nullptr);
JSHandle<JSTaggedValue> value1(factory->NewJSNativePointer(reinterpret_cast<void*>(info)));
JSHandle<JSTaggedValue> value2(thread, JSTaggedValue(1));
JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj1), key1, value1);
JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj1), key2, value2);
obj1->GetClass()->SetIsNativeBindingObject(true);
ValueSerializer *serializer = new ValueSerializer(thread);
bool success = serializer->WriteValue(thread, JSHandle<JSTaggedValue>(obj1),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
EXPECT_FALSE(success);
std::unique_ptr<SerializeData> data = serializer->Release();
BaseDeserializer deserializer(thread, data.release());
JSHandle<JSTaggedValue> res = deserializer.ReadValue();
EXPECT_TRUE(res.IsEmpty());
delete serializer;
}
HWTEST_F_L0(JSSerializerTest, SerializeNativeBindingObject4)
{
ObjectFactory *factory = ecmaVm->GetFactory();
JSHandle<JSObject> obj1 = factory->NewEmptyJSObject();
JSHandle<JSTaggedValue> key1 = thread->GlobalConstants()->GetHandledNativeBindingSymbol();
JSHandle<JSTaggedValue> key2(factory->NewFromASCII("x"));
auto info = CreateNativeBindingInfo(reinterpret_cast<void*>(Attach2), reinterpret_cast<void*>(Detach));
JSHandle<JSTaggedValue> value1(factory->NewJSNativePointer(reinterpret_cast<void*>(info)));
JSHandle<JSTaggedValue> value2(thread, JSTaggedValue(1));
JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj1), key1, value1);
JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj1), key2, value2);
obj1->GetClass()->SetIsNativeBindingObject(true);
ValueSerializer *serializer = new ValueSerializer(thread);
bool success = serializer->WriteValue(thread, JSHandle<JSTaggedValue>(obj1),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
EXPECT_TRUE(success) << "Serialize fail";
std::unique_ptr<SerializeData> data = serializer->Release();
BaseDeserializer deserializer(thread, data.release(), ecmaVm);
JSHandle<JSTaggedValue> res = deserializer.ReadValue();
EXPECT_FALSE(res.IsEmpty());
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);
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);
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);
ValueSerializer *serializer = new ValueSerializer(thread);
bool success = serializer->WriteValue(thread, JSHandle<JSTaggedValue>(set),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
EXPECT_TRUE(success) << "Serialize JSSet fail";
std::unique_ptr<SerializeData> data = serializer->Release();
JSDeserializerTest jsDeserializerTest;
std::thread t1(&JSDeserializerTest::JSSetTest, jsDeserializerTest, data.release());
ecmascript::ThreadSuspensionScope scope(thread);
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));
ValueSerializer *serializer = new ValueSerializer(thread);
bool success = serializer->WriteValue(thread, JSHandle<JSTaggedValue>(jsDate),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
EXPECT_TRUE(success) << "Serialize JSDate fail";
std::unique_ptr<SerializeData> data = serializer->Release();
JSDeserializerTest jsDeserializerTest;
std::thread t1(&JSDeserializerTest::JSDateTest, jsDeserializerTest, data.release());
ecmascript::ThreadSuspensionScope scope(thread);
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);
ValueSerializer *serializer = new ValueSerializer(thread);
bool success = serializer->WriteValue(thread, JSHandle<JSTaggedValue>(map),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
EXPECT_TRUE(success) << "Serialize JSMap fail";
std::unique_ptr<SerializeData> data = serializer->Release();
JSDeserializerTest jsDeserializerTest;
std::thread t1(&JSDeserializerTest::JSMapTest, jsDeserializerTest, data.release(), map);
ecmascript::ThreadSuspensionScope scope(thread);
t1.join();
delete serializer;
};
HWTEST_F_L0(JSSerializerTest, SerializeJSTreeSet)
{
constexpr int nodeNumber = 8;
JSHandle<JSAPITreeSet> tset = CreateJSAPITreeSet();
for (int i = 0; i < nodeNumber; i++) {
auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
callInfo->SetFunction(JSTaggedValue::Undefined());
callInfo->SetThis(tset.GetTaggedValue());
callInfo->SetCallArg(0, JSTaggedValue(i));
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
JSTaggedValue result = ContainersTreeSet::Add(callInfo);
TestHelper::TearDownFrame(thread, prev);
EXPECT_TRUE(result.IsTrue());
EXPECT_EQ(tset->GetSize(thread), i + 1);
}
auto callInfo1 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);
callInfo1->SetFunction(JSTaggedValue::Undefined());
callInfo1->SetThis(tset.GetTaggedValue());
[[maybe_unused]] auto prev1 = TestHelper::SetupFrame(thread, callInfo1);
JSHandle<JSTaggedValue> iterValues(thread, ContainersTreeSet::Values(callInfo1));
TestHelper::TearDownFrame(thread, prev1);
EXPECT_TRUE(iterValues->IsJSAPITreeSetIterator());
JSMutableHandle<JSTaggedValue> result(thread, JSTaggedValue::Undefined());
bool isDone = false;
for (int i = 0; !isDone; i++) {
auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);
callInfo->SetFunction(JSTaggedValue::Undefined());
callInfo->SetThis(iterValues.GetTaggedValue());
[[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo);
result.Update(JSAPITreeSetIterator::Next(callInfo));
TestHelper::TearDownFrame(thread, prev);
isDone = JSIterator::IteratorComplete(thread, result);
EXPECT_EQ(i == nodeNumber, isDone);
}
ValueSerializer *serializer = new ValueSerializer(thread);
bool success = serializer->WriteValue(thread, JSHandle<JSTaggedValue>(tset),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
EXPECT_TRUE(success) << "Serialize JSTreeSet fail";
std::unique_ptr<SerializeData> data = serializer->Release();
JSDeserializerTest jsDeserializerTest;
std::thread t1(&JSDeserializerTest::JSTreeSetTest, jsDeserializerTest, data.release());
ecmascript::ThreadSuspensionScope scope(thread);
t1.join();
delete serializer;
};
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");
char buffer[] = "1234567";
uint32_t bufferSize = 7;
factory->NewJSRegExpByteCodeData(jsRegexp, static_cast<void *>(buffer), bufferSize);
jsRegexp->SetOriginalSource(thread, JSHandle<JSTaggedValue>(pattern));
jsRegexp->SetOriginalFlags(thread, JSTaggedValue(0));
ValueSerializer *serializer = new ValueSerializer(thread);
bool success = serializer->WriteValue(thread, JSHandle<JSTaggedValue>(jsRegexp),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
EXPECT_TRUE(success) << "Serialize JSRegExp fail";
std::unique_ptr<SerializeData> data = serializer->Release();
JSDeserializerTest jsDeserializerTest;
std::thread t1(&JSDeserializerTest::JSRegexpTest, jsDeserializerTest, data.release());
ecmascript::ThreadSuspensionScope scope(thread);
t1.join();
delete serializer;
};
HWTEST_F_L0(JSSerializerTest, TestSerializeJSArray)
{
ObjectFactory *factory = ecmaVm->GetFactory();
JSHandle<JSArray> array = factory->NewJSArray();
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);
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);
}
ValueSerializer *serializer = new ValueSerializer(thread);
bool success = serializer->WriteValue(thread, JSHandle<JSTaggedValue>(array),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
EXPECT_TRUE(success) << "Serialize JSArray fail";
std::unique_ptr<SerializeData> data = serializer->Release();
JSDeserializerTest jsDeserializerTest;
std::thread t1(&JSDeserializerTest::JSArrayTest, jsDeserializerTest, data.release());
ecmascript::ThreadSuspensionScope scope(thread);
t1.join();
delete serializer;
};
HWTEST_F_L0(JSSerializerTest, SerializeEcmaString1)
{
const char *rawStr = "ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss"\
"sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss"\
"sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss"\
"ssssss";
JSHandle<EcmaString> ecmaString = thread->GetEcmaVM()->GetFactory()->NewFromASCII(rawStr);
ValueSerializer *serializer = new ValueSerializer(thread);
bool success = serializer->WriteValue(thread, JSHandle<JSTaggedValue>(ecmaString),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
EXPECT_TRUE(success) << "Serialize EcmaString fail";
std::unique_ptr<SerializeData> data = serializer->Release();
JSDeserializerTest jsDeserializerTest;
std::thread t1(&JSDeserializerTest::EcmaStringTest1, jsDeserializerTest, data.release());
ecmascript::ThreadSuspensionScope scope(thread);
t1.join();
delete serializer;
};
HWTEST_F_L0(JSSerializerTest, SerializeEcmaString2)
{
std::string rawStr = "你好,世界";
JSHandle<EcmaString> ecmaString = thread->GetEcmaVM()->GetFactory()->NewFromStdString(rawStr);
ValueSerializer *serializer = new ValueSerializer(thread);
bool success = serializer->WriteValue(thread, JSHandle<JSTaggedValue>(ecmaString),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
EXPECT_TRUE(success) << "Serialize EcmaString fail";
std::unique_ptr<SerializeData> data = serializer->Release();
JSDeserializerTest jsDeserializerTest;
std::thread t1(&JSDeserializerTest::EcmaStringTest2, jsDeserializerTest, data.release());
ecmascript::ThreadSuspensionScope scope(thread);
t1.join();
delete serializer;
};
HWTEST_F_L0(JSSerializerTest, SerializeInt32_t)
{
int32_t a = 64, min = -2147483648, b = -63;
JSTaggedValue aTag(a), minTag(min), bTag(b);
ValueSerializer *serializer = new ValueSerializer(thread);
serializer->SerializeJSTaggedValue(aTag);
serializer->SerializeJSTaggedValue(minTag);
serializer->SerializeJSTaggedValue(bTag);
std::unique_ptr<SerializeData> data = serializer->Release();
JSDeserializerTest jsDeserializerTest;
std::thread t1(&JSDeserializerTest::Int32Test, jsDeserializerTest, data.release());
ecmascript::ThreadSuspensionScope scope(thread);
t1.join();
delete serializer;
};
HWTEST_F_L0(JSSerializerTest, SerializeDouble)
{
double a = 3.1415926535, b = -3.1415926535;
JSTaggedValue aTag(a), bTag(b);
ValueSerializer *serializer = new ValueSerializer(thread);
serializer->SerializeJSTaggedValue(aTag);
serializer->SerializeJSTaggedValue(bTag);
std::unique_ptr<SerializeData> data = serializer->Release();
JSDeserializerTest jsDeserializerTest;
std::thread t1(&JSDeserializerTest::DoubleTest, jsDeserializerTest, data.release());
ecmascript::ThreadSuspensionScope scope(thread);
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, 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(thread) == ecmascript::FunctionKind::CONCURRENT_FUNCTION);
JSHandle<JSFunction> concurrentFunction2 = factory->NewJSFunction(env, nullptr, FunctionKind::CONCURRENT_FUNCTION);
EXPECT_TRUE(concurrentFunction2->IsJSFunction());
EXPECT_TRUE(concurrentFunction2->GetFunctionKind(thread) == 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, value1);
JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj), key5, JSHandle<JSTaggedValue>(concurrentFunction2));
ValueSerializer *serializer = new ValueSerializer(thread);
bool success = serializer->WriteValue(thread, JSHandle<JSTaggedValue>(obj),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
EXPECT_TRUE(success) << "Serialize concurrent function fail";
std::unique_ptr<SerializeData> data = serializer->Release();
JSDeserializerTest jsDeserializerTest;
std::thread t1(&JSDeserializerTest::ObjectWithConcurrentFunctionTest, jsDeserializerTest, data.release());
ecmascript::ThreadSuspensionScope scope(thread);
t1.join();
delete serializer;
};
HWTEST_F_L0(JSSerializerTest, SerializeFunction)
{
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
JSHandle<JSFunction> function = factory->NewJSFunction(env, nullptr, FunctionKind::NORMAL_FUNCTION);
EXPECT_TRUE(function->IsJSFunction());
ValueSerializer *serializer = new ValueSerializer(thread);
bool success = serializer->WriteValue(thread, JSHandle<JSTaggedValue>(function),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
EXPECT_FALSE(success);
std::unique_ptr<SerializeData> data = serializer->Release();
BaseDeserializer deserializer(thread, data.release());
JSHandle<JSTaggedValue> res = deserializer.ReadValue();
EXPECT_TRUE(res.IsEmpty());
delete serializer;
}
HWTEST_F_L0(JSSerializerTest, SerializeApiFunction)
{
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
JSHandle<JSFunction> function = factory->NewNormalJSApiFunction(env, nullptr);
EXPECT_TRUE(function->IsJSApiFunction());
ValueSerializer *serializer = new ValueSerializer(thread);
bool success = serializer->WriteValue(thread, JSHandle<JSTaggedValue>(function),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
EXPECT_FALSE(success);
std::unique_ptr<SerializeData> data = serializer->Release();
BaseDeserializer deserializer(thread, data.release());
JSHandle<JSTaggedValue> res = deserializer.ReadValue();
EXPECT_TRUE(res.IsEmpty());
delete serializer;
}
HWTEST_F_L0(JSSerializerTest, TransferJSArrayBuffer1)
{
ObjectFactory *factory = ecmaVm->GetFactory();
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>(arrBuf);
JSHandle<JSArray> array = factory->NewJSArray();
array->SetArrayLength(thread, 1);
JSArray::FastSetPropertyByValue(thread, JSHandle<JSTaggedValue>(array), 0, arrBufTag);
ValueSerializer *serializer = new ValueSerializer(thread);
bool success = serializer->WriteValue(thread, arrBufTag, JSHandle<JSTaggedValue>(array),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
EXPECT_TRUE(success) << "Serialize transfer JSArrayBuffer fail";
std::unique_ptr<SerializeData> data = serializer->Release();
JSDeserializerTest jsDeserializerTest;
std::thread t1(&JSDeserializerTest::TransferJSArrayBufferTest1,
jsDeserializerTest,
data.release(),
reinterpret_cast<uintptr_t>(buffer));
ecmascript::ThreadSuspensionScope scope(thread);
t1.join();
delete serializer;
EXPECT_TRUE(arrBuf->IsDetach(thread));
};
HWTEST_F_L0(JSSerializerTest, TransferJSArrayBuffer2)
{
ObjectFactory *factory = ecmaVm->GetFactory();
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);
ValueSerializer *serializer = new ValueSerializer(thread);
bool success = serializer->WriteValue(thread, arrBufTag,
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
EXPECT_TRUE(success) << "Serialize not transfer JSArrayBuffer fail";
std::unique_ptr<SerializeData> data = serializer->Release();
JSDeserializerTest jsDeserializerTest;
std::thread t1(&JSDeserializerTest::TransferJSArrayBufferTest2,
jsDeserializerTest,
data.release(),
reinterpret_cast<uintptr_t>(buffer));
ecmascript::ThreadSuspensionScope scope(thread);
t1.join();
delete serializer;
EXPECT_FALSE(arrBuf->IsDetach(thread));
};
HWTEST_F_L0(JSSerializerTest, TransferJSArrayBuffer3)
{
ObjectFactory *factory = ecmaVm->GetFactory();
JSHandle<JSArrayBuffer> arrBuf = factory->NewJSArrayBuffer(0);
JSHandle<JSTaggedValue> arrBufTag = JSHandle<JSTaggedValue>::Cast(arrBuf);
ValueSerializer *serializer = new ValueSerializer(thread);
bool success = serializer->WriteValue(thread, arrBufTag,
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
EXPECT_TRUE(success) << "Serialize empty JSArrayBuffer fail";
std::unique_ptr<SerializeData> data = serializer->Release();
JSDeserializerTest jsDeserializerTest;
std::thread t1(&JSDeserializerTest::TransferJSArrayBufferTest3, jsDeserializerTest, data.release());
ecmascript::ThreadSuspensionScope scope(thread);
t1.join();
delete serializer;
EXPECT_FALSE(arrBuf->IsDetach(thread));
};
HWTEST_F_L0(JSSerializerTest, TransferJSArrayBuffer4)
{
ObjectFactory *factory = ecmaVm->GetFactory();
size_t length = 5;
uint8_t value = 100;
void *buffer = reinterpret_cast<void *>(malloc(length));
if (memset_s(buffer, length, value, length) != EOK) {
LOG_ECMA(FATAL) << "this branch is unreachable";
UNREACHABLE();
}
JSHandle<JSArrayBuffer> arrBuf = factory->NewJSArrayBuffer(buffer, length, nullptr, nullptr);
JSHandle<JSTaggedValue> arrBufTag = JSHandle<JSTaggedValue>::Cast(arrBuf);
ValueSerializer *serializer = new ValueSerializer(thread);
bool res = serializer->WriteValue(thread, arrBufTag,
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
EXPECT_FALSE(res) << "serialize JSArrayBuffer with external native shall not clone it";
free(buffer);
};
void ArrayBufferDeleter([[maybe_unused]] void *env, void *buf, [[maybe_unused]] void *data)
{
free(buf);
}
HWTEST_F_L0(JSSerializerTest, TransferJSArrayBuffer5)
{
ObjectFactory *factory = ecmaVm->GetFactory();
size_t length = 5;
uint8_t value = 100;
void *buffer = reinterpret_cast<void *>(malloc(length));
if (memset_s(buffer, length, value, length) != EOK) {
LOG_ECMA(FATAL) << "this branch is unreachable";
UNREACHABLE();
}
JSHandle<JSArrayBuffer> arrBuf = factory->NewJSArrayBuffer(buffer, length, ArrayBufferDeleter, nullptr);
JSHandle<JSTaggedValue> arrBufTag = JSHandle<JSTaggedValue>::Cast(arrBuf);
ValueSerializer *serializer = new ValueSerializer(thread, true);
bool res = serializer->WriteValue(thread, arrBufTag,
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
EXPECT_TRUE(res) << "serialize JSArrayBuffer with external pointer fail";
EXPECT_TRUE(arrBuf->IsDetach(thread));
std::unique_ptr<SerializeData> data = serializer->Release();
JSDeserializerTest jsDeserializerTest;
std::thread t1(&JSDeserializerTest::TransferJSArrayBufferTest5, jsDeserializerTest, data.release());
ecmascript::ThreadSuspensionScope scope(thread);
t1.join();
delete serializer;
};
HWTEST_F_L0(JSSerializerTest, TransferJSArrayBuffer6)
{
ObjectFactory *factory = ecmaVm->GetFactory();
JSHandle<JSObject> obj = factory->NewEmptyJSObject();
JSHandle<EcmaString> transfer(factory->NewFromASCII("transfer"));
ValueSerializer *serializer = new ValueSerializer(thread);
bool success = serializer->WriteValue(thread, JSHandle<JSTaggedValue>(obj),
JSHandle<JSTaggedValue>(transfer),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
EXPECT_FALSE(success);
std::unique_ptr<SerializeData> data = serializer->Release();
BaseDeserializer deserializer(thread, data.release());
JSHandle<JSTaggedValue> res = deserializer.ReadValue();
EXPECT_TRUE(res.IsEmpty());
delete serializer;
};
HWTEST_F_L0(JSSerializerTest, TransferJSArrayBuffer7)
{
ObjectFactory *factory = ecmaVm->GetFactory();
JSHandle<JSObject> obj = factory->NewEmptyJSObject();
JSHandle<EcmaString> transfer(factory->NewFromASCII("transfer"));
JSHandle<JSArray> array = factory->NewJSArray();
array->SetArrayLength(thread, 1);
JSArray::FastSetPropertyByValue(thread, JSHandle<JSTaggedValue>(array), 0, JSHandle<JSTaggedValue>(transfer));
ValueSerializer *serializer = new ValueSerializer(thread);
bool success = serializer->WriteValue(thread, JSHandle<JSTaggedValue>(obj),
JSHandle<JSTaggedValue>(array),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
EXPECT_FALSE(success);
std::unique_ptr<SerializeData> data = serializer->Release();
BaseDeserializer deserializer(thread, data.release());
JSHandle<JSTaggedValue> res = deserializer.ReadValue();
EXPECT_TRUE(res.IsEmpty());
delete serializer;
};
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(thread));
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";
}
ValueSerializer *serializer = new ValueSerializer(thread);
bool success = serializer->WriteValue(thread, JSHandle<JSTaggedValue>(jsArrayBuffer),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
EXPECT_TRUE(success) << "Serialize JSSharedArrayBuffer fail";
std::unique_ptr<SerializeData> data = serializer->Release();
JSDeserializerTest jsDeserializerTest;
std::string changeStr = "world hello";
std::thread t1(&JSDeserializerTest::JSSharedArrayBufferTest,
jsDeserializerTest, data.release(), 12, changeStr.c_str());
ecmascript::ThreadSuspensionScope scope(thread);
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(thread));
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";
}
ValueSerializer *serializer = new ValueSerializer(thread);
bool success = serializer->WriteValue(thread, JSHandle<JSTaggedValue>(jsArrayBuffer),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
EXPECT_TRUE(success) << "Serialize JSSharedArrayBuffer fail";
std::unique_ptr<SerializeData> data = serializer->Release();
JSDeserializerTest jsDeserializerTest;
std::string changeStr = "world hello";
std::thread t1(&JSDeserializerTest::JSSharedArrayBufferTest,
jsDeserializerTest, data.get(), 12, changeStr.c_str());
{
ecmascript::ThreadSuspensionScope scope(thread);
t1.join();
EXPECT_TRUE(strcmp((char *)buffer, "world hello") == 0) << "Serialize JSArrayBuffer fail";
changeStr = "world hella";
JSDeserializerTest jsDeserializerTest1;
std::thread t2(&JSDeserializerTest::JSSharedArrayBufferTest,
jsDeserializerTest1, data.get(), 12, changeStr.c_str());
t2.join();
EXPECT_TRUE(strcmp((char *)buffer, "world hella") == 0) << "Serialize JSArrayBuffer fail";
changeStr = "world hellb";
JSDeserializerTest jsDeserializerTest2;
std::thread t3(&JSDeserializerTest::JSSharedArrayBufferTest,
jsDeserializerTest2, data.get(), 12, changeStr.c_str());
t3.join();
EXPECT_TRUE(strcmp((char *)buffer, "world hellb") == 0) << "Serialize JSArrayBuffer fail";
}
delete serializer;
data.reset();
EXPECT_TRUE(JSHandle<JSTaggedValue>(jsArrayBuffer)->IsSharedArrayBuffer());
};
HWTEST_F_L0(JSSerializerTest, SerializeJSNativePointer)
{
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
JSHandle<JSNativePointer> np = factory->NewJSNativePointer(nullptr);
ValueSerializer *serializer = new ValueSerializer(thread);
bool success = serializer->WriteValue(thread, JSHandle<JSTaggedValue>(np),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
EXPECT_TRUE(!success);
std::unique_ptr<SerializeData> data = serializer->Release();
EXPECT_TRUE(data->IsIncompleteData());
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++) {
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->SetContentType(DataViewType::INT8);
int8Array->SetArrayLength(arrayLength);
ValueSerializer *serializer = new ValueSerializer(thread);
bool success = serializer->WriteValue(thread, JSHandle<JSTaggedValue>(int8Array),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
EXPECT_TRUE(success) << "Serialize type array fail";
std::unique_ptr<SerializeData> data = serializer->Release();
JSDeserializerTest jsDeserializerTest;
std::thread t1(&JSDeserializerTest::TypedArrayTest1, jsDeserializerTest, data.release());
ecmascript::ThreadSuspensionScope scope(thread);
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;
JSTaggedType val = JSTaggedValue(value).GetRawData();
int byteArrayLength = 10;
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->SetContentType(DataViewType::INT8);
int8Array->SetArrayLength(arrayLength);
ValueSerializer *serializer = new ValueSerializer(thread);
bool success = serializer->WriteValue(thread, JSHandle<JSTaggedValue>(int8Array),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
EXPECT_TRUE(success) << "Serialize type array fail";
std::unique_ptr<SerializeData> data = serializer->Release();
JSDeserializerTest jsDeserializerTest;
std::thread t1(&JSDeserializerTest::TypedArrayTest2, jsDeserializerTest, data.release());
ecmascript::ThreadSuspensionScope scope(thread);
t1.join();
delete serializer;
};
JSHandle<JSObject> CreateEmptySObject(JSThread *thread)
{
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
const GlobalEnvConstants *globalConst = thread->GlobalConstants();
JSHandle<JSTaggedValue> nullHandle = globalConst->GetHandledNull();
JSHandle<LayoutInfo> emptyLayout = factory->CreateSLayoutInfo(0);
JSHandle<JSHClass> hclass = factory->NewSEcmaHClass(JSSharedObject::SIZE, 0, JSType::JS_SHARED_OBJECT, nullHandle,
JSHandle<JSTaggedValue>(emptyLayout));
return factory->NewSharedOldSpaceJSObject(hclass);
}
JSHandle<JSObject> CreateSObject(JSThread *thread)
{
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
const GlobalEnvConstants *globalConst = thread->GlobalConstants();
JSHandle<JSTaggedValue> nullHandle = globalConst->GetHandledNull();
uint32_t index = 0;
PropertyAttributes attributes = PropertyAttributes::Default(false, false, false);
attributes.SetIsInlinedProps(true);
attributes.SetRepresentation(Representation::TAGGED);
uint32_t length = 4;
JSHandle<LayoutInfo> layout = factory->CreateSLayoutInfo(length);
JSHandle<EcmaString> key1(factory->NewFromASCII("str1"));
JSHandle<EcmaString> key2(factory->NewFromASCII("str2"));
while (index < length) {
attributes.SetOffset(index);
attributes.SetIsAccessor(false);
key2 = JSHandle<EcmaString>(thread, EcmaStringAccessor::Concat(thread->GetEcmaVM(), key2, key1));
auto stringTable = thread->GetEcmaVM()->GetEcmaStringTable();
stringTable->GetOrInternString(thread->GetEcmaVM(), *key2);
layout->AddKey(thread, index++, key2.GetTaggedValue(), attributes);
}
JSHandle<JSHClass> hclass = factory->NewSEcmaHClass(JSSharedObject::SIZE, length, JSType::JS_SHARED_OBJECT,
nullHandle, JSHandle<JSTaggedValue>(layout));
JSHandle<JSObject> object = factory->NewSharedOldSpaceJSObject(hclass);
uint32_t fieldIndex = 0;
while (fieldIndex < length) {
JSHandle<JSObject> emptyObject = CreateEmptySObject(thread);
object->SetPropertyInlinedProps(thread, fieldIndex++, emptyObject.GetTaggedValue());
}
return object;
}
JSHandle<JSSharedSet> CreateSSet(JSThread *thread)
{
auto globalEnv = thread->GetEcmaVM()->GetGlobalEnv();
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
JSHandle<JSTaggedValue> proto = globalEnv->GetSharedSetPrototype();
auto emptySLayout = thread->GlobalConstants()->GetHandledEmptySLayoutInfo();
JSHandle<JSHClass> setClass = factory->NewSEcmaHClass(JSSharedSet::SIZE, 0,
JSType::JS_SHARED_SET, proto, emptySLayout);
JSHandle<JSSharedSet> jsSet = JSHandle<JSSharedSet>::Cast(factory->NewSharedOldSpaceJSObjectWithInit(setClass));
JSHandle<LinkedHashSet> linkedSet(
LinkedHashSet::Create(thread, LinkedHashSet::MIN_CAPACITY, MemSpaceKind::SHARED));
jsSet->SetLinkedSet(thread, linkedSet);
jsSet->SetModRecord(0);
return jsSet;
}
JSHandle<JSSharedMap> CreateSMap(JSThread *thread)
{
auto globalEnv = thread->GetEcmaVM()->GetGlobalEnv();
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
JSHandle<JSTaggedValue> proto = globalEnv->GetSharedMapPrototype();
auto emptySLayout = thread->GlobalConstants()->GetHandledEmptySLayoutInfo();
JSHandle<JSHClass> mapClass = factory->NewSEcmaHClass(JSSharedMap::SIZE, 0,
JSType::JS_SHARED_MAP, proto, emptySLayout);
JSHandle<JSSharedMap> jsMap = JSHandle<JSSharedMap>::Cast(factory->NewSharedOldSpaceJSObjectWithInit(mapClass));
JSHandle<LinkedHashMap> linkedMap(
LinkedHashMap::Create(thread, LinkedHashSet::MIN_CAPACITY, MemSpaceKind::SHARED));
jsMap->SetLinkedMap(thread, linkedMap);
jsMap->SetModRecord(0);
return jsMap;
}
HWTEST_F_L0(JSSerializerTest, SerializeCloneListTest1)
{
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
JSHandle<JSObject> shareObj = CreateSObject(thread);
EXPECT_TRUE(shareObj->IsJSShared());
JSHandle<EcmaString> key(factory->NewFromASCII("str2str1"));
JSHandle<JSTaggedValue> shareObj1 =
JSObject::GetProperty(thread, JSHandle<JSObject>(shareObj), JSHandle<JSTaggedValue>(key)).GetValue();
EXPECT_TRUE(shareObj1->IsJSShared());
JSHandle<JSArray> array = factory->NewJSArray();
JSArray::FastSetPropertyByValue(thread, JSHandle<JSTaggedValue>(array), 0, JSHandle<JSTaggedValue>(shareObj));
ValueSerializer *serializer = new ValueSerializer(thread);
bool success = serializer->WriteValue(thread, JSHandle<JSTaggedValue>(shareObj),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()),
JSHandle<JSTaggedValue>(array));
EXPECT_TRUE(success) << "SerializeCloneListTest1: Serialize shared obj fail";
std::unique_ptr<SerializeData> data = serializer->Release();
JSDeserializerTest jsDeserializerTest;
std::thread t1(&JSDeserializerTest::SerializeCloneListTest1, jsDeserializerTest, data.release());
ecmascript::ThreadSuspensionScope scope(thread);
t1.join();
delete serializer;
};
HWTEST_F_L0(JSSerializerTest, SerializeCloneListTest2)
{
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
JSHandle<JSObject> rootObj = factory->NewEmptyJSObject();
JSHandle<JSObject> shareObj = CreateSObject(thread);
JSHandle<JSObject> noShareObj = CreateSObject(thread);
JSHandle<JSTaggedValue> key1(factory->NewFromASCII("shareObj"));
JSHandle<JSTaggedValue> key2(factory->NewFromASCII("noShareObj"));
JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(rootObj), key1, JSHandle<JSTaggedValue>(shareObj));
JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(rootObj), key2, JSHandle<JSTaggedValue>(noShareObj));
JSHandle<JSArray> array = factory->NewJSArray();
JSArray::FastSetPropertyByValue(thread, JSHandle<JSTaggedValue>(array), 0, JSHandle<JSTaggedValue>(shareObj));
ValueSerializer *serializer = new ValueSerializer(thread);
bool success = serializer->WriteValue(thread, JSHandle<JSTaggedValue>(rootObj),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()),
JSHandle<JSTaggedValue>(array));
EXPECT_TRUE(success) << "SerializeCloneListTest2: Serialize shared obj fail";
std::unique_ptr<SerializeData> data = serializer->Release();
JSDeserializerTest jsDeserializerTest;
std::thread t1(&JSDeserializerTest::SerializeCloneListTest2, jsDeserializerTest, data.release());
ecmascript::ThreadSuspensionScope scope(thread);
t1.join();
delete serializer;
};
HWTEST_F_L0(JSSerializerTest, SerializeCloneListTest3)
{
ObjectFactory *factory = ecmaVm->GetFactory();
JSHandle<JSObject> obj = factory->NewEmptyJSObject();
JSHandle<EcmaString> cloneList(factory->NewFromASCII("cloneList"));
ValueSerializer *serializer = new ValueSerializer(thread);
bool success = serializer->WriteValue(thread, JSHandle<JSTaggedValue>(obj),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()),
JSHandle<JSTaggedValue>(cloneList));
EXPECT_FALSE(success);
std::unique_ptr<SerializeData> data = serializer->Release();
BaseDeserializer deserializer(thread, data.release());
JSHandle<JSTaggedValue> res = deserializer.ReadValue();
EXPECT_TRUE(res.IsEmpty());
delete serializer;
};
HWTEST_F_L0(JSSerializerTest, SerializeCloneListTest4)
{
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
JSHandle<JSObject> obj = factory->NewEmptyJSObject();
JSHandle<JSArrayBuffer> arrBuf = factory->NewJSArrayBuffer(0);
JSHandle<JSTaggedValue> arrBufTag = JSHandle<JSTaggedValue>::Cast(arrBuf);
JSHandle<JSArray> array = factory->NewJSArray();
JSArray::FastSetPropertyByValue(thread, JSHandle<JSTaggedValue>(array), 0, arrBufTag);
ValueSerializer *serializer = new ValueSerializer(thread);
bool success = serializer->WriteValue(thread, JSHandle<JSTaggedValue>(obj),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()),
JSHandle<JSTaggedValue>(array));
EXPECT_TRUE(success) << "SerializeCloneListTest4: Serialize shared obj fail";
std::unique_ptr<SerializeData> data = serializer->Release();
JSDeserializerTest jsDeserializerTest;
std::thread t1(&JSDeserializerTest::SerializeCloneListTest4, jsDeserializerTest, data.release());
ecmascript::ThreadSuspensionScope scope(thread);
t1.join();
delete serializer;
};
HWTEST_F_L0(JSSerializerTest, SerializeCloneListTest5)
{
ObjectFactory *factory = ecmaVm->GetFactory();
JSHandle<JSObject> obj = factory->NewEmptyJSObject();
JSHandle<JSObject> obj1 = factory->NewEmptyJSObject();
JSHandle<JSArray> array = factory->NewJSArray();
array->SetArrayLength(thread, 1);
JSArray::FastSetPropertyByValue(thread, JSHandle<JSTaggedValue>(array), 0, JSHandle<JSTaggedValue>(obj1));
ValueSerializer *serializer = new ValueSerializer(thread);
bool success = serializer->WriteValue(thread, JSHandle<JSTaggedValue>(obj),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()),
JSHandle<JSTaggedValue>(array));
EXPECT_FALSE(success);
std::unique_ptr<SerializeData> data = serializer->Release();
BaseDeserializer deserializer(thread, data.release());
JSHandle<JSTaggedValue> res = deserializer.ReadValue();
EXPECT_TRUE(res.IsEmpty());
delete serializer;
};
HWTEST_F_L0(JSSerializerTest, SerializeJSSharedSetBasic1)
{
JSHandle<JSSharedSet> jsSet = CreateSSet(thread);
ValueSerializer *serializer = new ValueSerializer(thread);
bool success = serializer->WriteValue(thread, JSHandle<JSTaggedValue>(jsSet),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
EXPECT_TRUE(success) << "Serialize JSSharedSet failed";
std::unique_ptr<SerializeData> data = serializer->Release();
{
for (int i = 0; i < INITIALIZE_SIZE; i++) {
JSSharedSet::Add(thread, jsSet, JSHandle<JSTaggedValue>(thread, JSTaggedValue(i)));
}
JSDeserializerTest jsDeserializerTest;
std::thread t1(&JSDeserializerTest::JSSharedSetBasicTest1,
jsDeserializerTest, data.get());
ecmascript::ThreadSuspensionScope scope(thread);
t1.join();
EXPECT_TRUE(JSSharedSet::GetSize(thread, jsSet) == 0);
}
{
for (int i = 0; i < INITIALIZE_SIZE; i++) {
JSSharedSet::Add(thread, jsSet, JSHandle<JSTaggedValue>(thread, JSTaggedValue(i)));
}
EXPECT_TRUE(!JSSharedSet::Has(thread, jsSet, JSTaggedValue(INITIALIZE_SIZE)));
JSDeserializerTest jsDeserializerTest;
std::thread t1(&JSDeserializerTest::JSSharedSetBasicTest2,
jsDeserializerTest, data.get());
ecmascript::ThreadSuspensionScope scope(thread);
t1.join();
EXPECT_TRUE(!JSSharedSet::Has(thread, jsSet, JSTaggedValue(0)));
EXPECT_TRUE(JSSharedSet::Has(thread, jsSet, JSTaggedValue(INITIALIZE_SIZE)));
}
delete serializer;
};
HWTEST_F_L0(JSSerializerTest, SerializeMultiThreadJSSharedSet)
{
Reset();
JSHandle<JSSharedSet> jsSet = CreateSSet(thread);
ValueSerializer *serializer = new ValueSerializer(thread);
bool success = serializer->WriteValue(thread, JSHandle<JSTaggedValue>(jsSet),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
EXPECT_TRUE(success) << "Serialize JSSharedSet fail";
std::unique_ptr<SerializeData> data = serializer->Release();
for (int i = 0; i < INITIALIZE_SIZE; i++) {
JSSharedSet::Add(thread, jsSet, JSHandle<JSTaggedValue>(thread, JSTaggedValue(i)));
}
constexpr uint32_t maxNumDeserializers = 10;
JSDeserializerTest jsDeserializerTests[maxNumDeserializers];
std::thread threads[maxNumDeserializers];
for (int32_t i = 0; i < maxNumDeserializers; i++) {
threads[i] = std::thread(&JSDeserializerTest::JSSharedSetMultiThreadTest1,
jsDeserializerTests[i], data.get());
}
ecmascript::ThreadSuspensionScope scope(thread);
for (int i = 0; i < maxNumDeserializers; i++) {
threads[i].join();
}
EXPECT_TRUE(jsSet->GetModRecord() == 0);
delete serializer;
};
HWTEST_F_L0(JSSerializerTest, SerializeJSSharedMapBasic)
{
JSHandle<JSSharedMap> jsMap = CreateSMap(thread);
ValueSerializer *serializer = new ValueSerializer(thread);
bool success = serializer->WriteValue(thread, JSHandle<JSTaggedValue>(jsMap),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
EXPECT_TRUE(success) << "Serialize JSSharedMap failed";
std::unique_ptr<SerializeData> data = serializer->Release();
{
for (int i = 0; i < INITIALIZE_SIZE; i++) {
JSSharedMap::Set(thread, jsMap, JSHandle<JSTaggedValue>(thread, JSTaggedValue(i)),
JSHandle<JSTaggedValue>(thread, JSTaggedValue(i)));
}
JSDeserializerTest jsDeserializerTest;
std::thread t1(&JSDeserializerTest::JSSharedMapBasicTest1,
jsDeserializerTest, data.get());
ecmascript::ThreadSuspensionScope scope(thread);
t1.join();
EXPECT_TRUE(JSSharedMap::GetSize(thread, jsMap) == 0);
}
{
for (int i = 0; i < INITIALIZE_SIZE; i++) {
JSSharedMap::Set(thread, jsMap, JSHandle<JSTaggedValue>(thread, JSTaggedValue(i)),
JSHandle<JSTaggedValue>(thread, JSTaggedValue(i)));
}
EXPECT_TRUE(!JSSharedMap::Has(thread, jsMap, JSTaggedValue(INITIALIZE_SIZE)));
JSDeserializerTest jsDeserializerTest;
std::thread t1(&JSDeserializerTest::JSSharedMapBasicTest2,
jsDeserializerTest, data.get());
ecmascript::ThreadSuspensionScope scope(thread);
t1.join();
EXPECT_TRUE(!JSSharedMap::Has(thread, jsMap, JSTaggedValue(0)));
EXPECT_TRUE(JSSharedMap::Has(thread, jsMap, JSTaggedValue(INITIALIZE_SIZE)));
}
delete serializer;
};
HWTEST_F_L0(JSSerializerTest, SerializeMultiNonmovableRegion)
{
ObjectFactory *factory = ecmaVm->GetFactory();
JSHandle<TaggedArray> array = factory->NewTaggedArray(10 * 1024, JSTaggedValue::Hole(),
MemSpaceType::NON_MOVABLE);
for (int i = 0; i < 5; i++) {
JSHandle<TaggedArray> element = factory->NewTaggedArray((11 + i) * 1024, JSTaggedValue::Hole(),
MemSpaceType::NON_MOVABLE);
array->Set(thread, i, element);
}
JSHandle<JSHClass> hClassHandle(thread->GlobalConstants()->GetHandledObjectClass());
JSHandle<JSObject> object = factory->NewJSObject(hClassHandle);
object->SetElements(thread, array);
ValueSerializer *serializer = new ValueSerializer(thread, false, true);
bool success = serializer->WriteValue(thread, JSHandle<JSTaggedValue>(object),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
EXPECT_TRUE(success);
std::unique_ptr<SerializeData> data = serializer->Release();
JSDeserializerTest jsDeserializerTest;
std::thread t1(&JSDeserializerTest::SerializeMultiNonmovableRegionTest, jsDeserializerTest, data.release());
ecmascript::ThreadSuspensionScope scope(thread);
t1.join();
delete serializer;
};
HWTEST_F_L0(JSSerializerTest, SerializeMultiSharedRegion)
{
ObjectFactory *factory = ecmaVm->GetFactory();
JSHandle<TaggedArray> array = factory->NewSTaggedArray(10 * 1024, JSTaggedValue::Hole());
for (int i = 0; i < 5; i++) {
JSHandle<TaggedArray> element = factory->NewSTaggedArray((11 + i) * 1024, JSTaggedValue::Hole());
array->Set(thread, i, element);
}
JSHandle<JSObject> sobj = CreateEmptySObject(thread);
sobj->SetElements(thread, array);
ValueSerializer *serializer = new ValueSerializer(thread, false, true);
bool success = serializer->WriteValue(thread, JSHandle<JSTaggedValue>(sobj),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
EXPECT_TRUE(success);
std::unique_ptr<SerializeData> data = serializer->Release();
JSDeserializerTest jsDeserializerTest;
std::thread t1(&JSDeserializerTest::SerializeMultiSharedRegionTest, jsDeserializerTest, data.release());
ecmascript::ThreadSuspensionScope scope(thread);
t1.join();
delete serializer;
};
HWTEST_F_L0(JSSerializerTest, SerializeMultiSharedRegion1)
{
ObjectFactory *factory = ecmaVm->GetFactory();
JSHandle<TaggedArray> array = factory->NewTaggedArray(3 * 1024, JSTaggedValue::Hole());
for (int i = 0; i < 5; i++) {
JSHandle<TaggedArray> element = factory->NewTaggedArray(3 * 1024, JSTaggedValue::Hole());
array->Set(thread, i, element);
}
JSHandle<JSObject> obj = factory->NewEmptyJSObject();
obj->SetElements(thread, array);
ValueSerializer *serializer = new ValueSerializer(thread, false, true);
bool success = serializer->WriteValue(thread, JSHandle<JSTaggedValue>(obj),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
EXPECT_TRUE(success);
std::unique_ptr<SerializeData> data = serializer->Release();
JSDeserializerTest jsDeserializerTest;
std::thread t1(&JSDeserializerTest::SerializeMultiSharedRegionTest1, jsDeserializerTest, data.release());
ecmascript::ThreadSuspensionScope scope(thread);
t1.join();
delete serializer;
};
HWTEST_F_L0(JSSerializerTest, SerializeMultiSharedRegion2)
{
ObjectFactory *factory = ecmaVm->GetFactory();
JSHandle<TaggedArray> array = factory->NewTaggedArray(3 * 1024,
JSTaggedValue::Hole());
for (int i = 0; i < 5; i++) {
JSHandle<TaggedArray> element = factory->NewTaggedArray(3 * 1024, JSTaggedValue::Hole());
array->Set(thread, i, element);
}
JSHandle<TaggedArray> array1 = factory->NewTaggedArray(3 * 1024,
JSTaggedValue::Hole(), true);
for (int i = 0; i < 5; i++) {
JSHandle<TaggedArray> element = factory->NewTaggedArray(3 * 1024, JSTaggedValue::Hole(), true);
array1->Set(thread, i, element);
}
JSHandle<JSObject> obj = factory->NewEmptyJSObject();
obj->SetProperties(thread, array);
obj->SetElements(thread, array1);
ValueSerializer *serializer = new ValueSerializer(thread, false, true);
bool success = serializer->WriteValue(thread, JSHandle<JSTaggedValue>(obj),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
EXPECT_TRUE(success);
std::unique_ptr<SerializeData> data = serializer->Release();
JSDeserializerTest jsDeserializerTest;
std::thread t1(&JSDeserializerTest::SerializeMultiSharedRegionTest2, jsDeserializerTest, data.release());
ecmascript::ThreadSuspensionScope scope(thread);
t1.join();
delete serializer;
};
HWTEST_F_L0(JSSerializerTest, SerializeSourceTextModule)
{
auto vm = thread->GetEcmaVM();
ObjectFactory *objectFactory = vm->GetFactory();
JSHandle<SourceTextModule> module = objectFactory->NewSourceTextModule();
CString baseFileName = "modules.abc";
CString recordName = "a";
module->SetEcmaModuleFilenameString(baseFileName);
module->SetEcmaModuleRecordNameString(recordName);
module->SetTypes(ModuleTypes::ECMA_MODULE);
module->SetStatus(ModuleStatus::INSTANTIATED);
JSHandle<JSTaggedValue> val = JSHandle<JSTaggedValue>::Cast(objectFactory->NewFromUtf8("val"));
JSHandle<TaggedArray> requestedModules = objectFactory->NewTaggedArray(2);
module->SetRequestedModules(thread, requestedModules.GetTaggedValue());
JSHandle<SourceTextModule> module1 = objectFactory->NewSourceTextModule();
module1->SetEcmaModuleFilenameString(baseFileName);
requestedModules->Set(thread, 0, module1);
JSHandle<JSTaggedValue> importName = val;
JSHandle<JSTaggedValue> localName = val;
JSHandle<ImportEntry> importEntry1 =
objectFactory->NewImportEntry(0, importName, localName, SharedTypes::UNSENDABLE_MODULE);
SourceTextModule::AddImportEntry(thread, module, importEntry1, 0, 2);
JSHandle<JSTaggedValue> starString = thread->GlobalConstants()->GetHandledStarString();
JSHandle<ImportEntry> importEntry2 =
objectFactory->NewImportEntry(1, starString, localName, SharedTypes::UNSENDABLE_MODULE);
SourceTextModule::AddImportEntry(thread, module, importEntry2, 1, 2);
JSHandle<LocalExportEntry> localExportEntry =
objectFactory->NewLocalExportEntry(val, val, 0, SharedTypes::UNSENDABLE_MODULE);
JSHandle<TaggedArray> localExportEntries = objectFactory->NewTaggedArray(1);
localExportEntries->Set(thread, 0, localExportEntry);
SourceTextModule::AddLocalExportEntry(thread, module, localExportEntry, 0, 1);
JSHandle<IndirectExportEntry> indirectExportEntry =
objectFactory->NewIndirectExportEntry(val, 0, val, SharedTypes::UNSENDABLE_MODULE);
JSHandle<TaggedArray> indirectExportEntries = objectFactory->NewTaggedArray(1);
indirectExportEntries->Set(thread, 0, indirectExportEntry);
module->SetIndirectExportEntries(thread, indirectExportEntries);
auto serializer = CreateModuleSerializer();
bool res = serializer->WriteValue(thread, JSHandle<JSTaggedValue>(module),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
EXPECT_TRUE(res);
std::unique_ptr<SerializeData> data = serializer->Release();
JSDeserializerTest jsDeserializerTest;
std::thread t1(&JSDeserializerTest::ModuleDeserialierTest1, jsDeserializerTest, data.release());
{
ThreadSuspensionScope suspensionScope(thread);
t1.join();
}
};
HWTEST_F_L0(JSSerializerTest, SerializeSourceTextModuleFileNameEmpty)
{
auto vm = thread->GetEcmaVM();
ObjectFactory *objectFactory = vm->GetFactory();
JSHandle<SourceTextModule> module = objectFactory->NewSourceTextModule();
auto serializer = CreateModuleSerializer();
bool res = serializer->WriteValue(thread, JSHandle<JSTaggedValue>(module),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
EXPECT_FALSE(res);
};
HWTEST_F_L0(JSSerializerTest, SerializeSourceTextModuleStatusCheck)
{
auto vm = thread->GetEcmaVM();
ObjectFactory *objectFactory = vm->GetFactory();
JSHandle<TaggedArray> serializerArray = objectFactory->NewTaggedArray(8);
JSHandle<SourceTextModule> module1 = objectFactory->NewSourceTextModule();
CString baseFileName = "modules.abc";
module1->SetEcmaModuleFilenameString(baseFileName);
module1->SetStatus(ModuleStatus::UNINSTANTIATED);
serializerArray->Set(thread, 0, module1);
JSHandle<SourceTextModule> module2 = objectFactory->NewSourceTextModule();
module2->SetEcmaModuleFilenameString(baseFileName);
module2->SetStatus(ModuleStatus::PREINSTANTIATING);
serializerArray->Set(thread, 1, module2);
JSHandle<SourceTextModule> module3 = objectFactory->NewSourceTextModule();
module3->SetEcmaModuleFilenameString(baseFileName);
module3->SetStatus(ModuleStatus::INSTANTIATING);
serializerArray->Set(thread, 2, module3);
JSHandle<SourceTextModule> module4 = objectFactory->NewSourceTextModule();
module4->SetEcmaModuleFilenameString(baseFileName);
module4->SetStatus(ModuleStatus::INSTANTIATED);
serializerArray->Set(thread, 3, module4);
JSHandle<SourceTextModule> module5 = objectFactory->NewSourceTextModule();
module5->SetEcmaModuleFilenameString(baseFileName);
module5->SetStatus(ModuleStatus::EVALUATING);
serializerArray->Set(thread, 4, module5);
JSHandle<SourceTextModule> module6 = objectFactory->NewSourceTextModule();
module6->SetEcmaModuleFilenameString(baseFileName);
module6->SetStatus(ModuleStatus::EVALUATING_ASYNC);
serializerArray->Set(thread, 5, module6);
JSHandle<SourceTextModule> module7 = objectFactory->NewSourceTextModule();
module7->SetEcmaModuleFilenameString(baseFileName);
module7->SetStatus(ModuleStatus::EVALUATED);
serializerArray->Set(thread, 6, module7);
JSHandle<SourceTextModule> module8 = objectFactory->NewSourceTextModule();
module8->SetEcmaModuleFilenameString(baseFileName);
module8->SetStatus(ModuleStatus::ERRORED);
serializerArray->Set(thread, 7, module8);
auto serializer = CreateModuleSerializer();
bool res = serializer->WriteValue(thread, JSHandle<JSTaggedValue>(serializerArray),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
EXPECT_TRUE(res);
std::unique_ptr<SerializeData> data = serializer->Release();
JSDeserializerTest jsDeserializerTest;
std::thread t1(&JSDeserializerTest::ModuleDeserialierTest2, jsDeserializerTest, data.release());
{
ThreadSuspensionScope suspensionScope(thread);
t1.join();
}
};
HWTEST_F_L0(JSSerializerTest, SerializeSourceTextModuleLazy)
{
auto vm = thread->GetEcmaVM();
ObjectFactory *objectFactory = vm->GetFactory();
JSHandle<SourceTextModule> module = objectFactory->NewSourceTextModule();
CString baseFileName = "modules.abc";
module->SetEcmaModuleFilenameString(baseFileName);
module->SetStatus(ModuleStatus::EVALUATED);
bool *lazyImportArray = new bool[5]();
lazyImportArray[0] = 0;
lazyImportArray[1] = 0;
lazyImportArray[2] = 1;
lazyImportArray[3] = 0;
lazyImportArray[4] = 1;
module->SetLazyImportArray(lazyImportArray);
JSHandle<TaggedArray> moduleRequestArray = objectFactory->NewTaggedArray(5);
module->SetModuleRequests(thread, moduleRequestArray);
auto serializer = CreateModuleSerializer();
bool res = serializer->WriteValue(thread, JSHandle<JSTaggedValue>(module),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
EXPECT_TRUE(res);
delete[] lazyImportArray;
std::unique_ptr<SerializeData> data = serializer->Release();
JSDeserializerTest jsDeserializerTest;
std::thread t1(&JSDeserializerTest::ModuleDeserialierTest3, jsDeserializerTest, data.release());
{
ThreadSuspensionScope suspensionScope(thread);
t1.join();
}
};
HWTEST_F_L0(JSSerializerTest, SerializeSourceTextModuleBinding)
{
auto vm = thread->GetEcmaVM();
ObjectFactory *objectFactory = vm->GetFactory();
JSHandle<SourceTextModule> module = objectFactory->NewSourceTextModule();
CString baseFileName = "modules.abc";
module->SetEcmaModuleFilenameString(baseFileName);
module->SetStatus(ModuleStatus::EVALUATED);
JSHandle<TaggedArray> environmentArray = objectFactory->NewTaggedArray(4);
JSHandle<EcmaString> recordNameHdl = objectFactory->NewFromUtf8("sendable binding recordName");
JSHandle<EcmaString> baseFileNameHdl = objectFactory->NewFromUtf8("sendable binding baseFileNameHdl");
JSHandle<ResolvedRecordIndexBinding> recordIndexBinding =
objectFactory->NewSResolvedRecordIndexBindingRecord(recordNameHdl, baseFileNameHdl, 0);
environmentArray->Set(thread, 0, recordIndexBinding.GetTaggedValue());
JSHandle<JSTaggedValue> val = JSHandle<JSTaggedValue>::Cast(objectFactory->NewFromUtf8("val"));
JSHandle<ResolvedRecordBinding> nameBinding =
objectFactory->NewSResolvedRecordBindingRecord(recordNameHdl, val);
environmentArray->Set(thread, 1, nameBinding.GetTaggedValue());
JSHandle<SourceTextModule> module1 = objectFactory->NewSourceTextModule();
CString baseFileName1 = "modules1.abc";
module1->SetEcmaModuleFilenameString(baseFileName1);
module1->SetStatus(ModuleStatus::EVALUATED);
JSHandle<ResolvedBinding> resolvedBinding = objectFactory->NewResolvedBindingRecord(module1, val);
environmentArray->Set(thread, 2, resolvedBinding.GetTaggedValue());
JSHandle<ResolvedIndexBinding> resolvedIndexBinding = objectFactory->NewResolvedIndexBindingRecord(module1, 0);
environmentArray->Set(thread, 3, resolvedIndexBinding.GetTaggedValue());
module->SetEnvironment(thread, environmentArray);
auto serializer = CreateModuleSerializer();
bool res = serializer->WriteValue(thread, JSHandle<JSTaggedValue>(module),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
EXPECT_TRUE(res);
std::unique_ptr<SerializeData> data = serializer->Release();
JSDeserializerTest jsDeserializerTest;
std::thread t1(&JSDeserializerTest::ModuleDeserialierTest4, jsDeserializerTest, data.release());
{
ThreadSuspensionScope suspensionScope(thread);
t1.join();
}
};
HWTEST_F_L0(JSSerializerTest, SerializeJSHClass)
{
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
JSHandle<JSFunction> func = factory->NewJSFunction(env, nullptr, FunctionKind::NORMAL_FUNCTION);
JSHandle<JSHClass> hclass =
factory->NewEcmaHClass(JSObject::SIZE, JSType::JS_OBJECT, env->GetObjectFunctionPrototype());
JSHandle<ProtoChangeMarker> markerHandle = factory->NewProtoChangeMarker();
markerHandle->SetHasChanged(false);
markerHandle->SetNotFoundHasChanged(false);
hclass->SetProtoChangeMarker(thread, markerHandle.GetTaggedValue());
JSHandle<ProtoChangeDetails> protoDetailsHandle = factory->NewProtoChangeDetails();
hclass->SetProtoChangeDetails(thread, protoDetailsHandle);
JSHandle<EnumCache> enumCache = factory->NewEnumCache();
hclass->SetEnumCache(thread, enumCache);
auto dependentInfos = factory->NewTaggedArray(2);
dependentInfos->Set(thread, 0, func.GetTaggedValue());
dependentInfos->Set(thread, 1, func.GetTaggedValue());
hclass->SetDependentInfos(thread, dependentInfos.GetTaggedValue());
auto serializer = CreateModuleSerializer();
bool success = serializer->WriteValue(thread, JSHandle<JSTaggedValue>(hclass),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
EXPECT_TRUE(success) << "Serialize js hclass fail";
std::unique_ptr<SerializeData> data = serializer->Release();
}
HWTEST_F_L0(JSSerializerTest, DeserializeAllObjectTypes)
{
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
JSHandle<JSFunction> objFunction = JSHandle<JSFunction>(env->GetObjectFunction());
JSHandle<JSObject> jsObject = factory->NewJSObjectByConstructor(objFunction);
JSHandle<JSArray> jsArray = factory->NewJSArray();
JSHandle<JSHClass> mapClass = factory->NewEcmaHClass(JSMap::SIZE, JSType::JS_MAP, env->GetMapPrototype());
JSHandle<JSMap> jsMap = JSHandle<JSMap>::Cast(factory->NewJSObjectWithInit(mapClass));
JSHandle<LinkedHashMap> linkedMap(LinkedHashMap::Create(thread));
jsMap->SetLinkedMap(thread, linkedMap);
JSHandle<JSHClass> setClass = factory->NewEcmaHClass(JSSet::SIZE, JSType::JS_SET, env->GetSetPrototype());
JSHandle<JSSet> jsSet = JSHandle<JSSet>::Cast(factory->NewJSObjectWithInit(setClass));
JSHandle<LinkedHashSet> linkedSet(LinkedHashSet::Create(thread));
jsSet->SetLinkedSet(thread, linkedSet);
auto serializer = CreateModuleSerializer();
bool success = serializer->WriteValue(thread, JSHandle<JSTaggedValue>(jsObject),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
EXPECT_TRUE(success) << "Serialize JSObject fail";
success = serializer->WriteValue(thread, JSHandle<JSTaggedValue>(jsArray),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
EXPECT_TRUE(success) << "Serialize JSArray fail";
success = serializer->WriteValue(thread, JSHandle<JSTaggedValue>(jsMap),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
EXPECT_TRUE(success) << "Serialize JSMap fail";
success = serializer->WriteValue(thread, JSHandle<JSTaggedValue>(jsSet),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
EXPECT_TRUE(success) << "Serialize JSSet fail";
std::unique_ptr<SerializeData> data = serializer->Release();
}
HWTEST_F_L0(JSSerializerTest, SerializeLargeArrayForMultipleRegions)
{
ObjectFactory *factory = ecmaVm->GetFactory();
constexpr int numLargeArrays = 20;
JSHandle<TaggedArray> container = factory->NewTaggedArray(numLargeArrays);
for (int i = 0; i < numLargeArrays; i++) {
JSHandle<TaggedArray> largeArray =
factory->NewTaggedArray(100 * 1024 / 8, JSTaggedValue::Hole());
container->Set(thread, i, largeArray.GetTaggedValue());
}
ValueSerializer *serializer = new ValueSerializer(thread);
bool success = serializer->WriteValue(thread,
JSHandle<JSTaggedValue>(container),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
EXPECT_TRUE(success) << "Serialize large array container failed";
std::unique_ptr<SerializeData> data = serializer->Release();
JSDeserializerTest jsDeserializerTest;
std::thread t1(&JSDeserializerTest::LargeArrayTest, jsDeserializerTest, data.release());
ecmascript::ThreadSuspensionScope scope(thread);
t1.join();
delete serializer;
}
HWTEST_F_L0(JSSerializerTest, SerializeHugeObjectForLargeSpace)
{
ObjectFactory *factory = ecmaVm->GetFactory();
JSHandle<TaggedArray> hugeArray =
factory->NewTaggedArray(2000 * 1024 / 8, JSTaggedValue::Hole(), MemSpaceType::OLD_SPACE);
for (uint32_t i = 0; i < 10; i++) {
hugeArray->Set(thread, i, JSTaggedValue(i));
}
ValueSerializer *serializer = new ValueSerializer(thread);
bool success = serializer->WriteValue(thread,
JSHandle<JSTaggedValue>(hugeArray),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
EXPECT_TRUE(success) << "Serialize huge array failed";
std::unique_ptr<SerializeData> data = serializer->Release();
JSDeserializerTest jsDeserializerTest;
std::thread t1(&JSDeserializerTest::HugeArrayTest, jsDeserializerTest, data.release());
ecmascript::ThreadSuspensionScope scope(thread);
t1.join();
delete serializer;
}
HWTEST_F_L0(JSSerializerTest, SerializeNestedLargeObjects)
{
ObjectFactory *factory = ecmaVm->GetFactory();
JSHandle<JSObject> outerObj = factory->NewEmptyJSObject();
constexpr int numNested = 5;
for (int i = 0; i < numNested; i++) {
JSHandle<JSObject> innerObj = factory->NewEmptyJSObject();
JSHandle<TaggedArray> largeArray =
factory->NewTaggedArray(80 * 1024 / 8, JSTaggedValue::Hole());
std::string keyStr = "prop" + std::to_string(i);
JSHandle<EcmaString> key = factory->NewFromASCII(keyStr.c_str());
JSObject::SetProperty(thread,
JSHandle<JSTaggedValue>(innerObj),
JSHandle<JSTaggedValue>(key),
JSHandle<JSTaggedValue>(largeArray));
std::string outerKeyStr = "nested" + std::to_string(i);
JSHandle<EcmaString> outerKey = factory->NewFromASCII(outerKeyStr.c_str());
JSObject::SetProperty(thread,
JSHandle<JSTaggedValue>(outerObj),
JSHandle<JSTaggedValue>(outerKey),
JSHandle<JSTaggedValue>(innerObj));
}
ValueSerializer *serializer = new ValueSerializer(thread);
bool success = serializer->WriteValue(thread,
JSHandle<JSTaggedValue>(outerObj),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
EXPECT_TRUE(success) << "Serialize nested large objects failed";
std::unique_ptr<SerializeData> data = serializer->Release();
JSDeserializerTest jsDeserializerTest;
std::thread t1(&JSDeserializerTest::NestedLargeObjectsTest, jsDeserializerTest, data.release());
ecmascript::ThreadSuspensionScope scope(thread);
t1.join();
delete serializer;
}
HWTEST_F_L0(JSSerializerTest, SerializeMixedSizeObjects)
{
ObjectFactory *factory = ecmaVm->GetFactory();
JSHandle<JSArray> mixedArray = factory->NewJSArray();
mixedArray->SetArrayLength(thread, 4);
JSHandle<JSObject> smallObj = factory->NewEmptyJSObject();
JSArray::FastSetPropertyByValue(thread,
JSHandle<JSTaggedValue>(mixedArray),
0,
JSHandle<JSTaggedValue>(smallObj));
JSHandle<TaggedArray> mediumArray = factory->NewTaggedArray(10 * 1024 / 8);
JSArray::FastSetPropertyByValue(thread,
JSHandle<JSTaggedValue>(mixedArray),
1,
JSHandle<JSTaggedValue>(mediumArray));
JSHandle<TaggedArray> largeArray = factory->NewTaggedArray(100 * 1024 / 8);
JSArray::FastSetPropertyByValue(thread,
JSHandle<JSTaggedValue>(mixedArray),
2,
JSHandle<JSTaggedValue>(largeArray));
JSHandle<JSObject> smallObj2 = factory->NewEmptyJSObject();
JSArray::FastSetPropertyByValue(thread,
JSHandle<JSTaggedValue>(mixedArray),
3,
JSHandle<JSTaggedValue>(smallObj2));
ValueSerializer *serializer = new ValueSerializer(thread);
bool success = serializer->WriteValue(thread,
JSHandle<JSTaggedValue>(mixedArray),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
EXPECT_TRUE(success) << "Serialize mixed size objects failed";
std::unique_ptr<SerializeData> data = serializer->Release();
JSDeserializerTest jsDeserializerTest;
std::thread t1(&JSDeserializerTest::MixedSizeObjectsTest, jsDeserializerTest, data.release());
ecmascript::ThreadSuspensionScope scope(thread);
t1.join();
delete serializer;
}
HWTEST_F_L0(JSSerializerTest, SerializeSourceTextModuleMutableFields)
{
auto vm = thread->GetEcmaVM();
ObjectFactory *objectFactory = vm->GetFactory();
JSHandle<SourceTextModule> module = objectFactory->NewSourceTextModule();
CString baseFileName = "mutable_fields_test.abc";
CString recordName = "testRecord";
module->SetEcmaModuleFilenameString(baseFileName);
module->SetEcmaModuleRecordNameString(recordName);
module->SetTypes(ModuleTypes::ECMA_MODULE);
module->SetStatus(ModuleStatus::INSTANTIATED);
JSTaggedValue undefined = thread->GlobalConstants()->GetUndefined();
JSHandle<JSTaggedValue> promise(thread, JSTaggedValue::Hole());
module->SetTopLevelCapability(thread, promise.GetTaggedValue());
JSHandle<TaggedArray> nameDict = objectFactory->NewTaggedArray(1);
module->SetNameDictionary(thread, nameDict.GetTaggedValue());
module->SetCycleRoot(thread, undefined);
JSHandle<TaggedArray> asyncParents = objectFactory->NewTaggedArray(1);
module->SetAsyncParentModules(thread, asyncParents.GetTaggedValue());
JSHandle<SFunctionEnv> sendableEnv = objectFactory->NewSFunctionEnv(1);
module->SetSendableEnv(thread, sendableEnv.GetTaggedValue());
module->SetException(thread, undefined);
JSHandle<ModuleNamespace> ns = objectFactory->NewModuleNamespace();
module->SetNamespace(thread, ns.GetTaggedValue());
auto serializer = CreateModuleSerializer();
bool res = serializer->WriteValue(thread, JSHandle<JSTaggedValue>(module),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
EXPECT_TRUE(res);
std::unique_ptr<SerializeData> data = serializer->Release();
JSDeserializerTest jsDeserializerTest;
std::thread t1(&JSDeserializerTest::SourceTextModuleMutableFieldsTest, jsDeserializerTest, data.release());
{
ThreadSuspensionScope suspensionScope(thread);
t1.join();
}
}
HWTEST_F_L0(JSSerializerTest, SerializeModuleCNativeObjectsBothNotEmpty)
{
auto vm = thread->GetEcmaVM();
ObjectFactory *objectFactory = vm->GetFactory();
JSHandle<SourceTextModule> module = objectFactory->NewSourceTextModule();
CString baseFileName = "test_module.abc";
CString recordName = "testRecord";
module->SetEcmaModuleFilenameString(baseFileName);
module->SetEcmaModuleRecordNameString(recordName);
module->SetStatus(ModuleStatus::INSTANTIATED);
auto serializer = CreateModuleSerializer();
bool res = serializer->WriteValue(thread, JSHandle<JSTaggedValue>(module),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
EXPECT_TRUE(res);
std::unique_ptr<SerializeData> data = serializer->Release();
}
HWTEST_F_L0(JSSerializerTest, SerializeModuleCNativeObjectsFileNameEmptyRecordNotEmpty)
{
auto vm = thread->GetEcmaVM();
ObjectFactory *objectFactory = vm->GetFactory();
JSHandle<SourceTextModule> module = objectFactory->NewSourceTextModule();
CString recordName = "testRecord";
module->SetEcmaModuleRecordNameString(recordName);
module->SetStatus(ModuleStatus::INSTANTIATED);
auto serializer = CreateModuleSerializer();
bool res = serializer->WriteValue(thread, JSHandle<JSTaggedValue>(module),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
EXPECT_TRUE(res);
std::unique_ptr<SerializeData> data = serializer->Release();
}
HWTEST_F_L0(JSSerializerTest, SerializeModuleCNativeObjectsFileNameNotEmptyRecordEmpty)
{
auto vm = thread->GetEcmaVM();
ObjectFactory *objectFactory = vm->GetFactory();
JSHandle<SourceTextModule> module = objectFactory->NewSourceTextModule();
CString baseFileName = "test_module.abc";
module->SetEcmaModuleFilenameString(baseFileName);
module->SetStatus(ModuleStatus::INSTANTIATED);
auto serializer = CreateModuleSerializer();
bool res = serializer->WriteValue(thread, JSHandle<JSTaggedValue>(module),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
EXPECT_TRUE(res);
std::unique_ptr<SerializeData> data = serializer->Release();
}
HWTEST_F_L0(JSSerializerTest, SerializeModuleCNativeObjectsBothEmpty)
{
auto vm = thread->GetEcmaVM();
ObjectFactory *objectFactory = vm->GetFactory();
JSHandle<SourceTextModule> module = objectFactory->NewSourceTextModule();
module->SetStatus(ModuleStatus::INSTANTIATED);
auto serializer = CreateModuleSerializer();
bool res = serializer->WriteValue(thread, JSHandle<JSTaggedValue>(module),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()),
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
EXPECT_FALSE(res);
}
}