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_weak_ref.h"
174514f5e3Sopenharmony_ci
184514f5e3Sopenharmony_ci#include "ecmascript/base/builtins_base.h"
194514f5e3Sopenharmony_ci#include "ecmascript/ecma_vm.h"
204514f5e3Sopenharmony_ci#include "ecmascript/ecma_runtime_call_info.h"
214514f5e3Sopenharmony_ci#include "ecmascript/global_env.h"
224514f5e3Sopenharmony_ci#include "ecmascript/jobs/micro_job_queue.h"
234514f5e3Sopenharmony_ci#include "ecmascript/js_weak_ref.h"
244514f5e3Sopenharmony_ci#include "ecmascript/js_array.h"
254514f5e3Sopenharmony_ci#include "ecmascript/js_handle.h"
264514f5e3Sopenharmony_ci#include "ecmascript/js_hclass.h"
274514f5e3Sopenharmony_ci#include "ecmascript/js_object-inl.h"
284514f5e3Sopenharmony_ci#include "ecmascript/js_tagged_value.h"
294514f5e3Sopenharmony_ci#include "ecmascript/js_thread.h"
304514f5e3Sopenharmony_ci#include "ecmascript/object_factory.h"
314514f5e3Sopenharmony_ci#include "ecmascript/tests/test_helper.h"
324514f5e3Sopenharmony_ci#include "ecmascript/tagged_array-inl.h"
334514f5e3Sopenharmony_ci
344514f5e3Sopenharmony_ci
354514f5e3Sopenharmony_ciusing namespace panda::ecmascript;
364514f5e3Sopenharmony_ciusing namespace panda::ecmascript::builtins;
374514f5e3Sopenharmony_ciusing BuiltinsBase = panda::ecmascript::base::BuiltinsBase;
384514f5e3Sopenharmony_ci
394514f5e3Sopenharmony_cinamespace panda::test {
404514f5e3Sopenharmony_ciusing BuiltinsWeakRef = ecmascript::builtins::BuiltinsWeakRef;
414514f5e3Sopenharmony_ci
424514f5e3Sopenharmony_ciclass BuiltinsWeakRefTest : public BaseTestWithScope<false> {
434514f5e3Sopenharmony_ci};
444514f5e3Sopenharmony_ci
454514f5e3Sopenharmony_ciJSTaggedValue CreateWeakRefConstructor(JSThread *thread, JSTaggedValue target)
464514f5e3Sopenharmony_ci{
474514f5e3Sopenharmony_ci    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
484514f5e3Sopenharmony_ci    JSHandle<JSObject> globalObject(thread, env->GetGlobalObject());
494514f5e3Sopenharmony_ci    JSHandle<JSFunction> weakRef(env->GetBuiltinsWeakRefFunction());
504514f5e3Sopenharmony_ci
514514f5e3Sopenharmony_ci    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue(*weakRef), 6);
524514f5e3Sopenharmony_ci    ecmaRuntimeCallInfo->SetFunction(weakRef.GetTaggedValue());
534514f5e3Sopenharmony_ci    ecmaRuntimeCallInfo->SetThis(globalObject.GetTaggedValue());
544514f5e3Sopenharmony_ci    ecmaRuntimeCallInfo->SetCallArg(0, target);
554514f5e3Sopenharmony_ci
564514f5e3Sopenharmony_ci    [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
574514f5e3Sopenharmony_ci    JSTaggedValue result = BuiltinsWeakRef::WeakRefConstructor(ecmaRuntimeCallInfo);
584514f5e3Sopenharmony_ci    TestHelper::TearDownFrame(thread, prev);
594514f5e3Sopenharmony_ci    return result;
604514f5e3Sopenharmony_ci}
614514f5e3Sopenharmony_ci
624514f5e3Sopenharmony_ci// new WeakRef(target)
634514f5e3Sopenharmony_ciHWTEST_F_L0(BuiltinsWeakRefTest, WeakRefConstructor)
644514f5e3Sopenharmony_ci{
654514f5e3Sopenharmony_ci    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
664514f5e3Sopenharmony_ci    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
674514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> objectFunc(env->GetObjectFunction());
684514f5e3Sopenharmony_ci
694514f5e3Sopenharmony_ci    JSHandle<JSObject> target(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objectFunc), objectFunc));
704514f5e3Sopenharmony_ci
714514f5e3Sopenharmony_ci    JSHandle<JSFunction> weakRef(env->GetBuiltinsWeakRefFunction());
724514f5e3Sopenharmony_ci    JSHandle<JSObject> globalObject(thread, env->GetGlobalObject());
734514f5e3Sopenharmony_ci
744514f5e3Sopenharmony_ci    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, weakRef.GetTaggedValue(), 6);
754514f5e3Sopenharmony_ci    ecmaRuntimeCallInfo->SetFunction(weakRef.GetTaggedValue());
764514f5e3Sopenharmony_ci    ecmaRuntimeCallInfo->SetThis(globalObject.GetTaggedValue());
774514f5e3Sopenharmony_ci    ecmaRuntimeCallInfo->SetCallArg(0, target.GetTaggedValue());
784514f5e3Sopenharmony_ci
794514f5e3Sopenharmony_ci    [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
804514f5e3Sopenharmony_ci    JSTaggedValue result = BuiltinsWeakRef::WeakRefConstructor(ecmaRuntimeCallInfo);
814514f5e3Sopenharmony_ci
824514f5e3Sopenharmony_ci    ASSERT_TRUE(result.IsECMAObject());
834514f5e3Sopenharmony_ci}
844514f5e3Sopenharmony_ci
854514f5e3Sopenharmony_ci// weakRef.Deref()
864514f5e3Sopenharmony_ciHWTEST_F_L0(BuiltinsWeakRefTest, Deref1)
874514f5e3Sopenharmony_ci{
884514f5e3Sopenharmony_ci    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
894514f5e3Sopenharmony_ci    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
904514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> objectFunc(env->GetObjectFunction());
914514f5e3Sopenharmony_ci
924514f5e3Sopenharmony_ci    JSHandle<JSObject> target(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objectFunc), objectFunc));
934514f5e3Sopenharmony_ci    JSTaggedValue result = CreateWeakRefConstructor(thread, target.GetTaggedValue());
944514f5e3Sopenharmony_ci    JSHandle<JSWeakRef> jsWeakRef(thread, JSWeakRef::Cast(reinterpret_cast<TaggedObject *>(result.GetRawData())));
954514f5e3Sopenharmony_ci    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);
964514f5e3Sopenharmony_ci    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
974514f5e3Sopenharmony_ci    ecmaRuntimeCallInfo->SetThis(jsWeakRef.GetTaggedValue());
984514f5e3Sopenharmony_ci
994514f5e3Sopenharmony_ci    [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
1004514f5e3Sopenharmony_ci    TestHelper::TearDownFrame(thread, prev);
1014514f5e3Sopenharmony_ci    JSTaggedValue result1 = BuiltinsWeakRef::Deref(ecmaRuntimeCallInfo);
1024514f5e3Sopenharmony_ci    ASSERT_EQ(result1, target.GetTaggedValue());
1034514f5e3Sopenharmony_ci}
1044514f5e3Sopenharmony_ci
1054514f5e3Sopenharmony_ci// weakRef.Deref()
1064514f5e3Sopenharmony_ciHWTEST_F_L0(BuiltinsWeakRefTest, Deref2)
1074514f5e3Sopenharmony_ci{
1084514f5e3Sopenharmony_ci    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
1094514f5e3Sopenharmony_ci    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1104514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> objectFunc(env->GetObjectFunction());
1114514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> formatStyle = thread->GlobalConstants()->GetHandledStyleString();
1124514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> styleKey(factory->NewFromASCII("currency"));
1134514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> styleValue(factory->NewFromASCII("EUR"));
1144514f5e3Sopenharmony_ci    JSHandle<JSObject> target(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objectFunc), objectFunc));
1154514f5e3Sopenharmony_ci    JSObject::SetProperty(thread, target, formatStyle, styleKey);
1164514f5e3Sopenharmony_ci    JSObject::SetProperty(thread, target, styleKey, styleValue);
1174514f5e3Sopenharmony_ci
1184514f5e3Sopenharmony_ci    JSTaggedValue result = CreateWeakRefConstructor(thread, target.GetTaggedValue());
1194514f5e3Sopenharmony_ci    JSHandle<JSWeakRef> jsWeakRef(thread, JSWeakRef::Cast(reinterpret_cast<TaggedObject *>(result.GetRawData())));
1204514f5e3Sopenharmony_ci    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);
1214514f5e3Sopenharmony_ci    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
1224514f5e3Sopenharmony_ci    ecmaRuntimeCallInfo->SetThis(jsWeakRef.GetTaggedValue());
1234514f5e3Sopenharmony_ci
1244514f5e3Sopenharmony_ci    [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
1254514f5e3Sopenharmony_ci    TestHelper::TearDownFrame(thread, prev);
1264514f5e3Sopenharmony_ci    JSTaggedValue result1 = BuiltinsWeakRef::Deref(ecmaRuntimeCallInfo);
1274514f5e3Sopenharmony_ci    ASSERT_EQ(result1, target.GetTaggedValue());
1284514f5e3Sopenharmony_ci
1294514f5e3Sopenharmony_ci    JSObject::SetProperty(thread, target, styleKey, styleValue);
1304514f5e3Sopenharmony_ci    ASSERT_EQ(result1, target.GetTaggedValue());
1314514f5e3Sopenharmony_ci}
1324514f5e3Sopenharmony_ci
1334514f5e3Sopenharmony_ci// weakRef.Deref()
1344514f5e3Sopenharmony_ciHWTEST_F_L0(BuiltinsWeakRefTest, Deref3)
1354514f5e3Sopenharmony_ci{
1364514f5e3Sopenharmony_ci    EcmaVM *vm = thread->GetEcmaVM();
1374514f5e3Sopenharmony_ci    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
1384514f5e3Sopenharmony_ci    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1394514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> objectFunc(env->GetObjectFunction());
1404514f5e3Sopenharmony_ci
1414514f5e3Sopenharmony_ci    JSTaggedValue target =
1424514f5e3Sopenharmony_ci	    factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objectFunc), objectFunc).GetTaggedValue();
1434514f5e3Sopenharmony_ci    JSTaggedValue result = CreateWeakRefConstructor(thread, target);
1444514f5e3Sopenharmony_ci    JSHandle<JSWeakRef> jsWeakRef(thread, JSWeakRef::Cast(reinterpret_cast<TaggedObject *>(result.GetRawData())));
1454514f5e3Sopenharmony_ci    JSTaggedValue result2 = JSTaggedValue::Undefined();
1464514f5e3Sopenharmony_ci
1474514f5e3Sopenharmony_ci    {
1484514f5e3Sopenharmony_ci        [[maybe_unused]] EcmaHandleScope handleScope(thread);
1494514f5e3Sopenharmony_ci        auto obj =
1504514f5e3Sopenharmony_ci	        factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objectFunc), objectFunc);
1514514f5e3Sopenharmony_ci        target = obj.GetTaggedValue();
1524514f5e3Sopenharmony_ci        auto ecmaRuntimeCallInfo1 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);
1534514f5e3Sopenharmony_ci        ecmaRuntimeCallInfo1->SetFunction(JSTaggedValue::Undefined());
1544514f5e3Sopenharmony_ci        ecmaRuntimeCallInfo1->SetThis(jsWeakRef.GetTaggedValue());
1554514f5e3Sopenharmony_ci
1564514f5e3Sopenharmony_ci        [[maybe_unused]] auto prev1 = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo1);
1574514f5e3Sopenharmony_ci        result2 = BuiltinsWeakRef::Deref(ecmaRuntimeCallInfo1);
1584514f5e3Sopenharmony_ci        TestHelper::TearDownFrame(thread, prev1);
1594514f5e3Sopenharmony_ci    }
1604514f5e3Sopenharmony_ci    vm->CollectGarbage(TriggerGCType::FULL_GC);
1614514f5e3Sopenharmony_ci    if (!thread->HasPendingException()) {
1624514f5e3Sopenharmony_ci        job::MicroJobQueue::ExecutePendingJob(thread, vm->GetJSThread()->GetCurrentEcmaContext()->GetMicroJobQueue());
1634514f5e3Sopenharmony_ci    }
1644514f5e3Sopenharmony_ci    vm->SetEnableForceGC(true);
1654514f5e3Sopenharmony_ci    ASSERT_TRUE(!result2.IsUndefined());
1664514f5e3Sopenharmony_ci}
1674514f5e3Sopenharmony_ci
1684514f5e3Sopenharmony_ci// symbol target
1694514f5e3Sopenharmony_ciHWTEST_F_L0(BuiltinsWeakRefTest, SymbolTarget)
1704514f5e3Sopenharmony_ci{
1714514f5e3Sopenharmony_ci    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
1724514f5e3Sopenharmony_ci    JSHandle<JSSymbol> symbolTarget = thread->GetEcmaVM()->GetFactory()->NewJSSymbol();
1734514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> target(symbolTarget);
1744514f5e3Sopenharmony_ci
1754514f5e3Sopenharmony_ci    JSHandle<JSFunction> weakRef(env->GetBuiltinsWeakRefFunction());
1764514f5e3Sopenharmony_ci
1774514f5e3Sopenharmony_ci    auto ecmaRuntimeCallInfo1 =
1784514f5e3Sopenharmony_ci        TestHelper::CreateEcmaRuntimeCallInfo(thread, weakRef.GetTaggedValue(), 6); // 6 means 1 call arg
1794514f5e3Sopenharmony_ci    ecmaRuntimeCallInfo1->SetFunction(weakRef.GetTaggedValue());
1804514f5e3Sopenharmony_ci    ecmaRuntimeCallInfo1->SetThis(JSTaggedValue::Undefined());
1814514f5e3Sopenharmony_ci    ecmaRuntimeCallInfo1->SetCallArg(0, target.GetTaggedValue());
1824514f5e3Sopenharmony_ci
1834514f5e3Sopenharmony_ci    // constructor
1844514f5e3Sopenharmony_ci    [[maybe_unused]] auto prev1 = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo1);
1854514f5e3Sopenharmony_ci    JSTaggedValue result1 = BuiltinsWeakRef::WeakRefConstructor(ecmaRuntimeCallInfo1);
1864514f5e3Sopenharmony_ci    TestHelper::TearDownFrame(thread, prev1);
1874514f5e3Sopenharmony_ci    ASSERT_TRUE(result1.IsECMAObject());
1884514f5e3Sopenharmony_ci
1894514f5e3Sopenharmony_ci    JSHandle<JSWeakRef> jsWeakRef(thread, JSWeakRef::Cast(reinterpret_cast<TaggedObject *>(result1.GetRawData())));
1904514f5e3Sopenharmony_ci    auto ecmaRuntimeCallInfo2 =
1914514f5e3Sopenharmony_ci        TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4); // 4 means 0 call arg
1924514f5e3Sopenharmony_ci    ecmaRuntimeCallInfo2->SetFunction(JSTaggedValue::Undefined());
1934514f5e3Sopenharmony_ci    ecmaRuntimeCallInfo2->SetThis(jsWeakRef.GetTaggedValue());
1944514f5e3Sopenharmony_ci
1954514f5e3Sopenharmony_ci    // weakRef.Deref()
1964514f5e3Sopenharmony_ci    [[maybe_unused]] auto prev2 = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo2);
1974514f5e3Sopenharmony_ci    JSTaggedValue result2 = BuiltinsWeakRef::Deref(ecmaRuntimeCallInfo2);
1984514f5e3Sopenharmony_ci    TestHelper::TearDownFrame(thread, prev2);
1994514f5e3Sopenharmony_ci    ASSERT_EQ(result2, target.GetTaggedValue());
2004514f5e3Sopenharmony_ci}
2014514f5e3Sopenharmony_ci}  // namespace panda::test
202