14514f5e3Sopenharmony_ci/*
24514f5e3Sopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd.
34514f5e3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
44514f5e3Sopenharmony_ci * you may not use this file except in compliance with the License.
54514f5e3Sopenharmony_ci * You may obtain a copy of the License at
64514f5e3Sopenharmony_ci *
74514f5e3Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
84514f5e3Sopenharmony_ci *
94514f5e3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
104514f5e3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
114514f5e3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
124514f5e3Sopenharmony_ci * See the License for the specific language governing permissions and
134514f5e3Sopenharmony_ci * limitations under the License.
144514f5e3Sopenharmony_ci */
154514f5e3Sopenharmony_ci
164514f5e3Sopenharmony_ci#include "ecmascript/builtins/builtins_finalization_registry.h"
174514f5e3Sopenharmony_ci#include "ecmascript/ecma_vm.h"
184514f5e3Sopenharmony_ci#include "ecmascript/global_env.h"
194514f5e3Sopenharmony_ci#include "ecmascript/jobs/micro_job_queue.h"
204514f5e3Sopenharmony_ci#include "ecmascript/js_array.h"
214514f5e3Sopenharmony_ci#include "ecmascript/js_array_iterator.h"
224514f5e3Sopenharmony_ci#include "ecmascript/js_finalization_registry.h"
234514f5e3Sopenharmony_ci#include "ecmascript/js_handle.h"
244514f5e3Sopenharmony_ci#include "ecmascript/js_hclass.h"
254514f5e3Sopenharmony_ci#include "ecmascript/js_object-inl.h"
264514f5e3Sopenharmony_ci#include "ecmascript/js_tagged_value.h"
274514f5e3Sopenharmony_ci#include "ecmascript/js_tagged_value-inl.h"
284514f5e3Sopenharmony_ci#include "ecmascript/js_thread.h"
294514f5e3Sopenharmony_ci
304514f5e3Sopenharmony_ci#include "ecmascript/object_factory.h"
314514f5e3Sopenharmony_ci#include "ecmascript/object_operator.h"
324514f5e3Sopenharmony_ci#include "ecmascript/tests/test_helper.h"
334514f5e3Sopenharmony_ci
344514f5e3Sopenharmony_ciusing namespace panda::ecmascript;
354514f5e3Sopenharmony_ciusing namespace panda::ecmascript::builtins;
364514f5e3Sopenharmony_ciusing BuiltinsBase = panda::ecmascript::base::BuiltinsBase;
374514f5e3Sopenharmony_cistatic int testValue = 0;
384514f5e3Sopenharmony_ci
394514f5e3Sopenharmony_cinamespace panda::test {
404514f5e3Sopenharmony_ciclass BuiltinsFinalizationRegistryTest : public BaseTestWithScope<false> {
414514f5e3Sopenharmony_cipublic:
424514f5e3Sopenharmony_ci    class TestClass : public base::BuiltinsBase {
434514f5e3Sopenharmony_ci    public:
444514f5e3Sopenharmony_ci        static JSTaggedValue cleanupCallback()
454514f5e3Sopenharmony_ci        {
464514f5e3Sopenharmony_ci            ++testValue;
474514f5e3Sopenharmony_ci            return JSTaggedValue::Undefined();
484514f5e3Sopenharmony_ci        }
494514f5e3Sopenharmony_ci    };
504514f5e3Sopenharmony_ci};
514514f5e3Sopenharmony_ci
524514f5e3Sopenharmony_ciJSTaggedValue CreateFinalizationRegistryConstructor(JSThread *thread)
534514f5e3Sopenharmony_ci{
544514f5e3Sopenharmony_ci    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
554514f5e3Sopenharmony_ci    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
564514f5e3Sopenharmony_ci
574514f5e3Sopenharmony_ci    JSHandle<JSFunction> finalizationRegistry(env->GetBuiltinsFinalizationRegistryFunction());
584514f5e3Sopenharmony_ci    JSHandle<JSFunction> handleFunc = factory->NewJSFunction(
594514f5e3Sopenharmony_ci        env, reinterpret_cast<void *>(BuiltinsFinalizationRegistryTest::TestClass::cleanupCallback));
604514f5e3Sopenharmony_ci
614514f5e3Sopenharmony_ci    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue(*finalizationRegistry), 6);
624514f5e3Sopenharmony_ci    ecmaRuntimeCallInfo->SetFunction(finalizationRegistry.GetTaggedValue());
634514f5e3Sopenharmony_ci    ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
644514f5e3Sopenharmony_ci    ecmaRuntimeCallInfo->SetCallArg(0, handleFunc.GetTaggedValue());
654514f5e3Sopenharmony_ci
664514f5e3Sopenharmony_ci    [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
674514f5e3Sopenharmony_ci    JSTaggedValue res = BuiltinsFinalizationRegistry::FinalizationRegistryConstructor(ecmaRuntimeCallInfo);
684514f5e3Sopenharmony_ci    TestHelper::TearDownFrame(thread, prev);
694514f5e3Sopenharmony_ci    return res;
704514f5e3Sopenharmony_ci}
714514f5e3Sopenharmony_ci
724514f5e3Sopenharmony_ci// new FinalizationRegistry (cleanupCallback)
734514f5e3Sopenharmony_ciHWTEST_F_L0(BuiltinsFinalizationRegistryTest, FinalizationRegistryConstructor)
744514f5e3Sopenharmony_ci{
754514f5e3Sopenharmony_ci    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
764514f5e3Sopenharmony_ci    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
774514f5e3Sopenharmony_ci
784514f5e3Sopenharmony_ci    JSHandle<JSFunction> finalizationRegistry(env->GetBuiltinsFinalizationRegistryFunction());
794514f5e3Sopenharmony_ci    JSHandle<JSFunction> handleFunc = factory->NewJSFunction(env, reinterpret_cast<void *>(TestClass::cleanupCallback));
804514f5e3Sopenharmony_ci
814514f5e3Sopenharmony_ci    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue(*finalizationRegistry), 6);
824514f5e3Sopenharmony_ci    ecmaRuntimeCallInfo->SetFunction(finalizationRegistry.GetTaggedValue());
834514f5e3Sopenharmony_ci    ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
844514f5e3Sopenharmony_ci    ecmaRuntimeCallInfo->SetCallArg(0, handleFunc.GetTaggedValue());
854514f5e3Sopenharmony_ci
864514f5e3Sopenharmony_ci    [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
874514f5e3Sopenharmony_ci    JSTaggedValue result = BuiltinsFinalizationRegistry::FinalizationRegistryConstructor(ecmaRuntimeCallInfo);
884514f5e3Sopenharmony_ci    ASSERT_TRUE(result.IsECMAObject());
894514f5e3Sopenharmony_ci}
904514f5e3Sopenharmony_ci
914514f5e3Sopenharmony_civoid KeyValueCommon(JSThread* thread, JSHandle<JSTaggedValue>& target)
924514f5e3Sopenharmony_ci{
934514f5e3Sopenharmony_ci    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
944514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> key(factory->NewFromASCII("1"));
954514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> value(thread, JSTaggedValue(1));
964514f5e3Sopenharmony_ci    JSObject::SetProperty(thread, target, key, value);
974514f5e3Sopenharmony_ci}
984514f5e3Sopenharmony_ci
994514f5e3Sopenharmony_ciJSHandle<JSFinalizationRegistry> Common(JSThread* thread)
1004514f5e3Sopenharmony_ci{
1014514f5e3Sopenharmony_ci    JSTaggedValue result = CreateFinalizationRegistryConstructor(thread);
1024514f5e3Sopenharmony_ci    JSHandle<JSFinalizationRegistry> jsfinalizationRegistry(thread, result);
1034514f5e3Sopenharmony_ci    return jsfinalizationRegistry;
1044514f5e3Sopenharmony_ci}
1054514f5e3Sopenharmony_ci
1064514f5e3Sopenharmony_civoid RegisterUnRegisterCommon(JSThread *thread, JSHandle<JSFinalizationRegistry> &jsfinalizationRegistry,
1074514f5e3Sopenharmony_ci                              std::vector<JSTaggedValue> &args, int32_t maxArg, bool unRegister = false)
1084514f5e3Sopenharmony_ci{
1094514f5e3Sopenharmony_ci    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), maxArg);
1104514f5e3Sopenharmony_ci    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
1114514f5e3Sopenharmony_ci    ecmaRuntimeCallInfo->SetThis(jsfinalizationRegistry.GetTaggedValue());
1124514f5e3Sopenharmony_ci    for (size_t i = 0; i < args.size(); i++) {
1134514f5e3Sopenharmony_ci        ecmaRuntimeCallInfo->SetCallArg(i, args[i]);
1144514f5e3Sopenharmony_ci    }
1154514f5e3Sopenharmony_ci
1164514f5e3Sopenharmony_ci    [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
1174514f5e3Sopenharmony_ci    if (unRegister) {
1184514f5e3Sopenharmony_ci        BuiltinsFinalizationRegistry::Unregister(ecmaRuntimeCallInfo);
1194514f5e3Sopenharmony_ci    } else {
1204514f5e3Sopenharmony_ci        BuiltinsFinalizationRegistry::Register(ecmaRuntimeCallInfo);
1214514f5e3Sopenharmony_ci    }
1224514f5e3Sopenharmony_ci    TestHelper::TearDownFrame(thread, prev);
1234514f5e3Sopenharmony_ci}
1244514f5e3Sopenharmony_ci
1254514f5e3Sopenharmony_ci// finalizationRegistry.Register(target, heldValue)
1264514f5e3Sopenharmony_ciHWTEST_F_L0(BuiltinsFinalizationRegistryTest, Register0)
1274514f5e3Sopenharmony_ci{
1284514f5e3Sopenharmony_ci    testValue = 0;
1294514f5e3Sopenharmony_ci    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1304514f5e3Sopenharmony_ci    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
1314514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> objectFunc = env->GetObjectFunction();
1324514f5e3Sopenharmony_ci
1334514f5e3Sopenharmony_ci    auto jsfinalizationRegistry = Common(thread);
1344514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> target(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objectFunc), objectFunc));
1354514f5e3Sopenharmony_ci    KeyValueCommon(thread, target);
1364514f5e3Sopenharmony_ci
1374514f5e3Sopenharmony_ci    std::vector<JSTaggedValue> args{target.GetTaggedValue(), JSTaggedValue(10)};
1384514f5e3Sopenharmony_ci
1394514f5e3Sopenharmony_ci    RegisterUnRegisterCommon(thread, jsfinalizationRegistry, args, 8);
1404514f5e3Sopenharmony_ci    ASSERT_EQ(testValue, 0);
1414514f5e3Sopenharmony_ci}
1424514f5e3Sopenharmony_ci
1434514f5e3Sopenharmony_ci// finalizationRegistry.Register(target, heldValue [ , unregisterToken ])
1444514f5e3Sopenharmony_ciHWTEST_F_L0(BuiltinsFinalizationRegistryTest, Register1)
1454514f5e3Sopenharmony_ci{
1464514f5e3Sopenharmony_ci    testValue = 0;
1474514f5e3Sopenharmony_ci    auto jsfinalizationRegistry = Common(thread);
1484514f5e3Sopenharmony_ci    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1494514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> objectFunc = thread->GetEcmaVM()->GetGlobalEnv()->GetObjectFunction();
1504514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> target(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objectFunc), objectFunc));
1514514f5e3Sopenharmony_ci    KeyValueCommon(thread, target);
1524514f5e3Sopenharmony_ci    std::vector<JSTaggedValue> args{target.GetTaggedValue(), JSTaggedValue(10), target.GetTaggedValue()};
1534514f5e3Sopenharmony_ci    RegisterUnRegisterCommon(thread, jsfinalizationRegistry, args, 10);
1544514f5e3Sopenharmony_ci    ASSERT_EQ(testValue, 0);
1554514f5e3Sopenharmony_ci}
1564514f5e3Sopenharmony_ci
1574514f5e3Sopenharmony_ci// finalizationRegistry.Register(target, heldValue [ , unregisterToken ])
1584514f5e3Sopenharmony_ciHWTEST_F_L0(BuiltinsFinalizationRegistryTest, Register2)
1594514f5e3Sopenharmony_ci{
1604514f5e3Sopenharmony_ci    testValue = 0;
1614514f5e3Sopenharmony_ci    EcmaVM *vm = thread->GetEcmaVM();
1624514f5e3Sopenharmony_ci    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1634514f5e3Sopenharmony_ci    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
1644514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> objectFunc = env->GetObjectFunction();
1654514f5e3Sopenharmony_ci
1664514f5e3Sopenharmony_ci    auto jsfinalizationRegistry = Common(thread);
1674514f5e3Sopenharmony_ci    vm->SetEnableForceGC(false);
1684514f5e3Sopenharmony_ci    JSTaggedValue target = JSTaggedValue::Undefined();
1694514f5e3Sopenharmony_ci    {
1704514f5e3Sopenharmony_ci        [[maybe_unused]] EcmaHandleScope handleScope(thread);
1714514f5e3Sopenharmony_ci        auto obj =
1724514f5e3Sopenharmony_ci            factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objectFunc), objectFunc);
1734514f5e3Sopenharmony_ci        target = obj.GetTaggedValue();
1744514f5e3Sopenharmony_ci        std::vector<JSTaggedValue> args{target, JSTaggedValue(10), target};
1754514f5e3Sopenharmony_ci        RegisterUnRegisterCommon(thread, jsfinalizationRegistry, args, 10);
1764514f5e3Sopenharmony_ci    }
1774514f5e3Sopenharmony_ci    vm->CollectGarbage(TriggerGCType::FULL_GC);
1784514f5e3Sopenharmony_ci    if (!thread->HasPendingException()) {
1794514f5e3Sopenharmony_ci        job::MicroJobQueue::ExecutePendingJob(thread, vm->GetJSThread()->GetCurrentEcmaContext()->GetMicroJobQueue());
1804514f5e3Sopenharmony_ci    }
1814514f5e3Sopenharmony_ci    vm->SetEnableForceGC(true);
1824514f5e3Sopenharmony_ci    ASSERT_EQ(testValue, 1);
1834514f5e3Sopenharmony_ci}
1844514f5e3Sopenharmony_ci
1854514f5e3Sopenharmony_ci// finalizationRegistry.Register(target, heldValue [ , unregisterToken ])
1864514f5e3Sopenharmony_ciHWTEST_F_L0(BuiltinsFinalizationRegistryTest, Register3)
1874514f5e3Sopenharmony_ci{
1884514f5e3Sopenharmony_ci    testValue = 0;
1894514f5e3Sopenharmony_ci    EcmaVM *vm = thread->GetEcmaVM();
1904514f5e3Sopenharmony_ci    auto jsfinalizationRegistry = Common(thread);
1914514f5e3Sopenharmony_ci
1924514f5e3Sopenharmony_ci    vm->SetEnableForceGC(false);
1934514f5e3Sopenharmony_ci    JSTaggedValue target = JSTaggedValue::Undefined();
1944514f5e3Sopenharmony_ci    JSTaggedValue target1 = JSTaggedValue::Undefined();
1954514f5e3Sopenharmony_ci    {
1964514f5e3Sopenharmony_ci        ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1974514f5e3Sopenharmony_ci        JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
1984514f5e3Sopenharmony_ci        JSHandle<JSTaggedValue> objectFunc = env->GetObjectFunction();
1994514f5e3Sopenharmony_ci        [[maybe_unused]] EcmaHandleScope handleScope(thread);
2004514f5e3Sopenharmony_ci        auto obj =
2014514f5e3Sopenharmony_ci            factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objectFunc), objectFunc);
2024514f5e3Sopenharmony_ci        auto obj1 =
2034514f5e3Sopenharmony_ci            factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objectFunc), objectFunc);
2044514f5e3Sopenharmony_ci        target = obj.GetTaggedValue();
2054514f5e3Sopenharmony_ci
2064514f5e3Sopenharmony_ci        std::vector<JSTaggedValue> args{target, JSTaggedValue(10), target};
2074514f5e3Sopenharmony_ci        RegisterUnRegisterCommon(thread, jsfinalizationRegistry, args, 10);
2084514f5e3Sopenharmony_ci
2094514f5e3Sopenharmony_ci        target1 = obj1.GetTaggedValue();
2104514f5e3Sopenharmony_ci        std::vector<JSTaggedValue> args1{target1, JSTaggedValue(10), target1};
2114514f5e3Sopenharmony_ci        RegisterUnRegisterCommon(thread, jsfinalizationRegistry, args, 10);
2124514f5e3Sopenharmony_ci    }
2134514f5e3Sopenharmony_ci    vm->CollectGarbage(TriggerGCType::FULL_GC);
2144514f5e3Sopenharmony_ci    if (!thread->HasPendingException()) {
2154514f5e3Sopenharmony_ci        job::MicroJobQueue::ExecutePendingJob(thread, vm->GetJSThread()->GetCurrentEcmaContext()->GetMicroJobQueue());
2164514f5e3Sopenharmony_ci    }
2174514f5e3Sopenharmony_ci    vm->SetEnableForceGC(true);
2184514f5e3Sopenharmony_ci    ASSERT_EQ(testValue, 2);
2194514f5e3Sopenharmony_ci}
2204514f5e3Sopenharmony_ci
2214514f5e3Sopenharmony_ci// finalizationRegistry.Register(target, heldValue [ , unregisterToken ])
2224514f5e3Sopenharmony_ciHWTEST_F_L0(BuiltinsFinalizationRegistryTest, Register4)
2234514f5e3Sopenharmony_ci{
2244514f5e3Sopenharmony_ci    testValue = 0;
2254514f5e3Sopenharmony_ci    EcmaVM *vm = thread->GetEcmaVM();
2264514f5e3Sopenharmony_ci    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
2274514f5e3Sopenharmony_ci    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
2284514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> objectFunc = env->GetObjectFunction();
2294514f5e3Sopenharmony_ci
2304514f5e3Sopenharmony_ci    auto jsfinalizationRegistry = Common(thread);
2314514f5e3Sopenharmony_ci    auto jsfinalizationRegistry1 = Common(thread);
2324514f5e3Sopenharmony_ci    vm->SetEnableForceGC(false);
2334514f5e3Sopenharmony_ci    JSTaggedValue target = JSTaggedValue::Undefined();
2344514f5e3Sopenharmony_ci    JSTaggedValue target1 = JSTaggedValue::Undefined();
2354514f5e3Sopenharmony_ci    {
2364514f5e3Sopenharmony_ci        [[maybe_unused]] EcmaHandleScope handleScope(thread);
2374514f5e3Sopenharmony_ci        auto obj =
2384514f5e3Sopenharmony_ci            factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objectFunc), objectFunc);
2394514f5e3Sopenharmony_ci        auto obj1 =
2404514f5e3Sopenharmony_ci            factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objectFunc), objectFunc);
2414514f5e3Sopenharmony_ci        target = obj.GetTaggedValue();
2424514f5e3Sopenharmony_ci        target1 = obj1.GetTaggedValue();
2434514f5e3Sopenharmony_ci
2444514f5e3Sopenharmony_ci        std::vector<JSTaggedValue> args{target, JSTaggedValue(10), target};
2454514f5e3Sopenharmony_ci        RegisterUnRegisterCommon(thread, jsfinalizationRegistry, args, 10);
2464514f5e3Sopenharmony_ci
2474514f5e3Sopenharmony_ci        std::vector<JSTaggedValue> args1{target1, JSTaggedValue(10), target1};
2484514f5e3Sopenharmony_ci        RegisterUnRegisterCommon(thread, jsfinalizationRegistry1, args, 10);
2494514f5e3Sopenharmony_ci    }
2504514f5e3Sopenharmony_ci    vm->CollectGarbage(TriggerGCType::FULL_GC);
2514514f5e3Sopenharmony_ci    if (!thread->HasPendingException()) {
2524514f5e3Sopenharmony_ci        job::MicroJobQueue::ExecutePendingJob(thread, vm->GetJSThread()->GetCurrentEcmaContext()->GetMicroJobQueue());
2534514f5e3Sopenharmony_ci    }
2544514f5e3Sopenharmony_ci    vm->SetEnableForceGC(true);
2554514f5e3Sopenharmony_ci    ASSERT_EQ(testValue, 2);
2564514f5e3Sopenharmony_ci}
2574514f5e3Sopenharmony_ci
2584514f5e3Sopenharmony_ci// finalizationRegistry.Register(target, heldValue [ , unregisterToken ])
2594514f5e3Sopenharmony_ciHWTEST_F_L0(BuiltinsFinalizationRegistryTest, Register5)
2604514f5e3Sopenharmony_ci{
2614514f5e3Sopenharmony_ci    testValue = 0;
2624514f5e3Sopenharmony_ci    EcmaVM *vm = thread->GetEcmaVM();
2634514f5e3Sopenharmony_ci    auto jsfinalizationRegistry = Common(thread);
2644514f5e3Sopenharmony_ci    vm->SetEnableForceGC(false);
2654514f5e3Sopenharmony_ci    JSTaggedValue target = JSTaggedValue::Undefined();
2664514f5e3Sopenharmony_ci    JSTaggedValue target1 = JSTaggedValue::Undefined();
2674514f5e3Sopenharmony_ci    {
2684514f5e3Sopenharmony_ci        ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
2694514f5e3Sopenharmony_ci        JSHandle<JSTaggedValue> objectFunc = thread->GetEcmaVM()->GetGlobalEnv()->GetObjectFunction();
2704514f5e3Sopenharmony_ci        [[maybe_unused]] EcmaHandleScope handleScope(thread);
2714514f5e3Sopenharmony_ci        auto obj =
2724514f5e3Sopenharmony_ci            factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objectFunc), objectFunc);
2734514f5e3Sopenharmony_ci        auto obj1 =
2744514f5e3Sopenharmony_ci            factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objectFunc), objectFunc);
2754514f5e3Sopenharmony_ci        target = obj.GetTaggedValue();
2764514f5e3Sopenharmony_ci        target1 = obj1.GetTaggedValue();
2774514f5e3Sopenharmony_ci
2784514f5e3Sopenharmony_ci        std::vector<JSTaggedValue> args{target, JSTaggedValue(10), target};
2794514f5e3Sopenharmony_ci        RegisterUnRegisterCommon(thread, jsfinalizationRegistry, args, 10);
2804514f5e3Sopenharmony_ci
2814514f5e3Sopenharmony_ci        std::vector<JSTaggedValue> args1{target1, JSTaggedValue(10), target};
2824514f5e3Sopenharmony_ci        RegisterUnRegisterCommon(thread, jsfinalizationRegistry, args, 10);
2834514f5e3Sopenharmony_ci    }
2844514f5e3Sopenharmony_ci    vm->CollectGarbage(TriggerGCType::FULL_GC);
2854514f5e3Sopenharmony_ci    if (!thread->HasPendingException()) {
2864514f5e3Sopenharmony_ci        job::MicroJobQueue::ExecutePendingJob(thread, vm->GetJSThread()->GetCurrentEcmaContext()->GetMicroJobQueue());
2874514f5e3Sopenharmony_ci    }
2884514f5e3Sopenharmony_ci    vm->SetEnableForceGC(true);
2894514f5e3Sopenharmony_ci    ASSERT_EQ(testValue, 2);
2904514f5e3Sopenharmony_ci}
2914514f5e3Sopenharmony_ci
2924514f5e3Sopenharmony_ci// finalizationRegistry.Unregister(unregisterToken ])
2934514f5e3Sopenharmony_ciHWTEST_F_L0(BuiltinsFinalizationRegistryTest, Unregister1)
2944514f5e3Sopenharmony_ci{
2954514f5e3Sopenharmony_ci    testValue = 0;
2964514f5e3Sopenharmony_ci    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
2974514f5e3Sopenharmony_ci    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
2984514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> objectFunc = env->GetObjectFunction();
2994514f5e3Sopenharmony_ci
3004514f5e3Sopenharmony_ci    auto jsfinalizationRegistry = Common(thread);
3014514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> target(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objectFunc), objectFunc));
3024514f5e3Sopenharmony_ci    KeyValueCommon(thread, target);
3034514f5e3Sopenharmony_ci
3044514f5e3Sopenharmony_ci    std::vector<JSTaggedValue> args{target.GetTaggedValue(), JSTaggedValue(10), target.GetTaggedValue()};
3054514f5e3Sopenharmony_ci    RegisterUnRegisterCommon(thread, jsfinalizationRegistry, args, 10);
3064514f5e3Sopenharmony_ci
3074514f5e3Sopenharmony_ci    std::vector<JSTaggedValue> args1{target.GetTaggedValue()};
3084514f5e3Sopenharmony_ci    RegisterUnRegisterCommon(thread, jsfinalizationRegistry, args1, 6, true);
3094514f5e3Sopenharmony_ci    ASSERT_EQ(testValue, 0);
3104514f5e3Sopenharmony_ci}
3114514f5e3Sopenharmony_ci
3124514f5e3Sopenharmony_ciHWTEST_F_L0(BuiltinsFinalizationRegistryTest, Unregister2)
3134514f5e3Sopenharmony_ci{
3144514f5e3Sopenharmony_ci    testValue = 0;
3154514f5e3Sopenharmony_ci    EcmaVM *vm = thread->GetEcmaVM();
3164514f5e3Sopenharmony_ci    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
3174514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> objectFunc = thread->GetEcmaVM()->GetGlobalEnv()->GetObjectFunction();
3184514f5e3Sopenharmony_ci
3194514f5e3Sopenharmony_ci    auto jsfinalizationRegistry = Common(thread);
3204514f5e3Sopenharmony_ci    vm->SetEnableForceGC(false);
3214514f5e3Sopenharmony_ci    JSTaggedValue target = JSTaggedValue::Undefined();
3224514f5e3Sopenharmony_ci    {
3234514f5e3Sopenharmony_ci        [[maybe_unused]] EcmaHandleScope handleScope(thread);
3244514f5e3Sopenharmony_ci        auto obj =
3254514f5e3Sopenharmony_ci            factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objectFunc), objectFunc);
3264514f5e3Sopenharmony_ci        target = obj.GetTaggedValue();
3274514f5e3Sopenharmony_ci
3284514f5e3Sopenharmony_ci        std::vector<JSTaggedValue> args{target, JSTaggedValue(10), target};
3294514f5e3Sopenharmony_ci        RegisterUnRegisterCommon(thread, jsfinalizationRegistry, args, 10);
3304514f5e3Sopenharmony_ci
3314514f5e3Sopenharmony_ci        std::vector<JSTaggedValue> args1{target};
3324514f5e3Sopenharmony_ci        RegisterUnRegisterCommon(thread, jsfinalizationRegistry, args1, 6, true);
3334514f5e3Sopenharmony_ci    }
3344514f5e3Sopenharmony_ci    vm->CollectGarbage(TriggerGCType::FULL_GC);
3354514f5e3Sopenharmony_ci    if (!thread->HasPendingException()) {
3364514f5e3Sopenharmony_ci        job::MicroJobQueue::ExecutePendingJob(thread, vm->GetJSThread()->GetCurrentEcmaContext()->GetMicroJobQueue());
3374514f5e3Sopenharmony_ci    }
3384514f5e3Sopenharmony_ci    vm->SetEnableForceGC(true);
3394514f5e3Sopenharmony_ci    ASSERT_EQ(testValue, 0);
3404514f5e3Sopenharmony_ci}
3414514f5e3Sopenharmony_ci
3424514f5e3Sopenharmony_ci// finalizationRegistry.Register(target, heldValue [ , unregisterToken ]) target and unregisterToken Symbol
3434514f5e3Sopenharmony_ciHWTEST_F_L0(BuiltinsFinalizationRegistryTest, RegisterTargetSymbol)
3444514f5e3Sopenharmony_ci{
3454514f5e3Sopenharmony_ci    testValue = 0;
3464514f5e3Sopenharmony_ci    EcmaVM *vm = thread->GetEcmaVM();
3474514f5e3Sopenharmony_ci
3484514f5e3Sopenharmony_ci    auto jsfinalizationRegistry = Common(thread);
3494514f5e3Sopenharmony_ci
3504514f5e3Sopenharmony_ci    vm->SetEnableForceGC(false);
3514514f5e3Sopenharmony_ci    JSTaggedValue target = JSTaggedValue::Undefined();
3524514f5e3Sopenharmony_ci    JSTaggedValue target1 = JSTaggedValue::Undefined();
3534514f5e3Sopenharmony_ci    {
3544514f5e3Sopenharmony_ci        [[maybe_unused]] EcmaHandleScope handleScope(thread);
3554514f5e3Sopenharmony_ci        JSHandle<JSSymbol> symbol1 = thread->GetEcmaVM()->GetFactory()->NewJSSymbol();
3564514f5e3Sopenharmony_ci        JSHandle<JSSymbol> symbol2 = thread->GetEcmaVM()->GetFactory()->NewJSSymbol();
3574514f5e3Sopenharmony_ci        target = symbol1.GetTaggedValue();
3584514f5e3Sopenharmony_ci        target1 = symbol2.GetTaggedValue();
3594514f5e3Sopenharmony_ci        std::vector<JSTaggedValue> args{target, JSTaggedValue(10), target};
3604514f5e3Sopenharmony_ci        RegisterUnRegisterCommon(thread, jsfinalizationRegistry, args, 10);
3614514f5e3Sopenharmony_ci
3624514f5e3Sopenharmony_ci        std::vector<JSTaggedValue> args1{target1, JSTaggedValue(10), target1};
3634514f5e3Sopenharmony_ci        RegisterUnRegisterCommon(thread, jsfinalizationRegistry, args1, 10);
3644514f5e3Sopenharmony_ci    }
3654514f5e3Sopenharmony_ci    vm->CollectGarbage(TriggerGCType::FULL_GC);
3664514f5e3Sopenharmony_ci    if (!thread->HasPendingException()) {
3674514f5e3Sopenharmony_ci        job::MicroJobQueue::ExecutePendingJob(thread, vm->GetJSThread()->GetCurrentEcmaContext()->GetMicroJobQueue());
3684514f5e3Sopenharmony_ci    }
3694514f5e3Sopenharmony_ci    vm->SetEnableForceGC(true);
3704514f5e3Sopenharmony_ci    ASSERT_EQ(testValue, 2);
3714514f5e3Sopenharmony_ci}
3724514f5e3Sopenharmony_ci
3734514f5e3Sopenharmony_ci// finalizationRegistry.Unregister(unregisterToken) unregisterToken Symbol
3744514f5e3Sopenharmony_ciHWTEST_F_L0(BuiltinsFinalizationRegistryTest, UnregisterTokenSymbol)
3754514f5e3Sopenharmony_ci{
3764514f5e3Sopenharmony_ci    testValue = 0;
3774514f5e3Sopenharmony_ci    EcmaVM *vm = thread->GetEcmaVM();
3784514f5e3Sopenharmony_ci
3794514f5e3Sopenharmony_ci    auto jsfinalizationRegistry = Common(thread);
3804514f5e3Sopenharmony_ci    vm->SetEnableForceGC(false);
3814514f5e3Sopenharmony_ci    JSTaggedValue target = JSTaggedValue::Undefined();
3824514f5e3Sopenharmony_ci    {
3834514f5e3Sopenharmony_ci        [[maybe_unused]] EcmaHandleScope handleScope(thread);
3844514f5e3Sopenharmony_ci        JSHandle<JSSymbol> symbol = thread->GetEcmaVM()->GetFactory()->NewJSSymbol();
3854514f5e3Sopenharmony_ci        target = symbol.GetTaggedValue();
3864514f5e3Sopenharmony_ci
3874514f5e3Sopenharmony_ci        std::vector<JSTaggedValue> args{target, JSTaggedValue(10), target};
3884514f5e3Sopenharmony_ci        RegisterUnRegisterCommon(thread, jsfinalizationRegistry, args, 10);
3894514f5e3Sopenharmony_ci
3904514f5e3Sopenharmony_ci        std::vector<JSTaggedValue> args1{target};
3914514f5e3Sopenharmony_ci        RegisterUnRegisterCommon(thread, jsfinalizationRegistry, args1, 6, true);
3924514f5e3Sopenharmony_ci    }
3934514f5e3Sopenharmony_ci    vm->CollectGarbage(TriggerGCType::FULL_GC);
3944514f5e3Sopenharmony_ci    if (!thread->HasPendingException()) {
3954514f5e3Sopenharmony_ci        job::MicroJobQueue::ExecutePendingJob(thread, vm->GetJSThread()->GetCurrentEcmaContext()->GetMicroJobQueue());
3964514f5e3Sopenharmony_ci    }
3974514f5e3Sopenharmony_ci    vm->SetEnableForceGC(true);
3984514f5e3Sopenharmony_ci    ASSERT_EQ(testValue, 0);
3994514f5e3Sopenharmony_ci}
4004514f5e3Sopenharmony_ci}  // namespace panda::test
401