1/* 2 * Copyright (c) 2021 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16#include "ecmascript/builtins/builtins_weak_ref.h" 17 18#include "ecmascript/base/builtins_base.h" 19#include "ecmascript/ecma_vm.h" 20#include "ecmascript/ecma_runtime_call_info.h" 21#include "ecmascript/global_env.h" 22#include "ecmascript/jobs/micro_job_queue.h" 23#include "ecmascript/js_weak_ref.h" 24#include "ecmascript/js_array.h" 25#include "ecmascript/js_handle.h" 26#include "ecmascript/js_hclass.h" 27#include "ecmascript/js_object-inl.h" 28#include "ecmascript/js_tagged_value.h" 29#include "ecmascript/js_thread.h" 30#include "ecmascript/object_factory.h" 31#include "ecmascript/tests/test_helper.h" 32#include "ecmascript/tagged_array-inl.h" 33 34 35using namespace panda::ecmascript; 36using namespace panda::ecmascript::builtins; 37using BuiltinsBase = panda::ecmascript::base::BuiltinsBase; 38 39namespace panda::test { 40using BuiltinsWeakRef = ecmascript::builtins::BuiltinsWeakRef; 41 42class BuiltinsWeakRefTest : public BaseTestWithScope<false> { 43}; 44 45JSTaggedValue CreateWeakRefConstructor(JSThread *thread, JSTaggedValue target) 46{ 47 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv(); 48 JSHandle<JSObject> globalObject(thread, env->GetGlobalObject()); 49 JSHandle<JSFunction> weakRef(env->GetBuiltinsWeakRefFunction()); 50 51 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue(*weakRef), 6); 52 ecmaRuntimeCallInfo->SetFunction(weakRef.GetTaggedValue()); 53 ecmaRuntimeCallInfo->SetThis(globalObject.GetTaggedValue()); 54 ecmaRuntimeCallInfo->SetCallArg(0, target); 55 56 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo); 57 JSTaggedValue result = BuiltinsWeakRef::WeakRefConstructor(ecmaRuntimeCallInfo); 58 TestHelper::TearDownFrame(thread, prev); 59 return result; 60} 61 62// new WeakRef(target) 63HWTEST_F_L0(BuiltinsWeakRefTest, WeakRefConstructor) 64{ 65 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv(); 66 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 67 JSHandle<JSTaggedValue> objectFunc(env->GetObjectFunction()); 68 69 JSHandle<JSObject> target(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objectFunc), objectFunc)); 70 71 JSHandle<JSFunction> weakRef(env->GetBuiltinsWeakRefFunction()); 72 JSHandle<JSObject> globalObject(thread, env->GetGlobalObject()); 73 74 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, weakRef.GetTaggedValue(), 6); 75 ecmaRuntimeCallInfo->SetFunction(weakRef.GetTaggedValue()); 76 ecmaRuntimeCallInfo->SetThis(globalObject.GetTaggedValue()); 77 ecmaRuntimeCallInfo->SetCallArg(0, target.GetTaggedValue()); 78 79 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo); 80 JSTaggedValue result = BuiltinsWeakRef::WeakRefConstructor(ecmaRuntimeCallInfo); 81 82 ASSERT_TRUE(result.IsECMAObject()); 83} 84 85// weakRef.Deref() 86HWTEST_F_L0(BuiltinsWeakRefTest, Deref1) 87{ 88 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv(); 89 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 90 JSHandle<JSTaggedValue> objectFunc(env->GetObjectFunction()); 91 92 JSHandle<JSObject> target(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objectFunc), objectFunc)); 93 JSTaggedValue result = CreateWeakRefConstructor(thread, target.GetTaggedValue()); 94 JSHandle<JSWeakRef> jsWeakRef(thread, JSWeakRef::Cast(reinterpret_cast<TaggedObject *>(result.GetRawData()))); 95 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4); 96 ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined()); 97 ecmaRuntimeCallInfo->SetThis(jsWeakRef.GetTaggedValue()); 98 99 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo); 100 TestHelper::TearDownFrame(thread, prev); 101 JSTaggedValue result1 = BuiltinsWeakRef::Deref(ecmaRuntimeCallInfo); 102 ASSERT_EQ(result1, target.GetTaggedValue()); 103} 104 105// weakRef.Deref() 106HWTEST_F_L0(BuiltinsWeakRefTest, Deref2) 107{ 108 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv(); 109 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 110 JSHandle<JSTaggedValue> objectFunc(env->GetObjectFunction()); 111 JSHandle<JSTaggedValue> formatStyle = thread->GlobalConstants()->GetHandledStyleString(); 112 JSHandle<JSTaggedValue> styleKey(factory->NewFromASCII("currency")); 113 JSHandle<JSTaggedValue> styleValue(factory->NewFromASCII("EUR")); 114 JSHandle<JSObject> target(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objectFunc), objectFunc)); 115 JSObject::SetProperty(thread, target, formatStyle, styleKey); 116 JSObject::SetProperty(thread, target, styleKey, styleValue); 117 118 JSTaggedValue result = CreateWeakRefConstructor(thread, target.GetTaggedValue()); 119 JSHandle<JSWeakRef> jsWeakRef(thread, JSWeakRef::Cast(reinterpret_cast<TaggedObject *>(result.GetRawData()))); 120 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4); 121 ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined()); 122 ecmaRuntimeCallInfo->SetThis(jsWeakRef.GetTaggedValue()); 123 124 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo); 125 TestHelper::TearDownFrame(thread, prev); 126 JSTaggedValue result1 = BuiltinsWeakRef::Deref(ecmaRuntimeCallInfo); 127 ASSERT_EQ(result1, target.GetTaggedValue()); 128 129 JSObject::SetProperty(thread, target, styleKey, styleValue); 130 ASSERT_EQ(result1, target.GetTaggedValue()); 131} 132 133// weakRef.Deref() 134HWTEST_F_L0(BuiltinsWeakRefTest, Deref3) 135{ 136 EcmaVM *vm = thread->GetEcmaVM(); 137 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv(); 138 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 139 JSHandle<JSTaggedValue> objectFunc(env->GetObjectFunction()); 140 141 JSTaggedValue target = 142 factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objectFunc), objectFunc).GetTaggedValue(); 143 JSTaggedValue result = CreateWeakRefConstructor(thread, target); 144 JSHandle<JSWeakRef> jsWeakRef(thread, JSWeakRef::Cast(reinterpret_cast<TaggedObject *>(result.GetRawData()))); 145 JSTaggedValue result2 = JSTaggedValue::Undefined(); 146 147 { 148 [[maybe_unused]] EcmaHandleScope handleScope(thread); 149 auto obj = 150 factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objectFunc), objectFunc); 151 target = obj.GetTaggedValue(); 152 auto ecmaRuntimeCallInfo1 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4); 153 ecmaRuntimeCallInfo1->SetFunction(JSTaggedValue::Undefined()); 154 ecmaRuntimeCallInfo1->SetThis(jsWeakRef.GetTaggedValue()); 155 156 [[maybe_unused]] auto prev1 = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo1); 157 result2 = BuiltinsWeakRef::Deref(ecmaRuntimeCallInfo1); 158 TestHelper::TearDownFrame(thread, prev1); 159 } 160 vm->CollectGarbage(TriggerGCType::FULL_GC); 161 if (!thread->HasPendingException()) { 162 job::MicroJobQueue::ExecutePendingJob(thread, vm->GetJSThread()->GetCurrentEcmaContext()->GetMicroJobQueue()); 163 } 164 vm->SetEnableForceGC(true); 165 ASSERT_TRUE(!result2.IsUndefined()); 166} 167 168// symbol target 169HWTEST_F_L0(BuiltinsWeakRefTest, SymbolTarget) 170{ 171 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv(); 172 JSHandle<JSSymbol> symbolTarget = thread->GetEcmaVM()->GetFactory()->NewJSSymbol(); 173 JSHandle<JSTaggedValue> target(symbolTarget); 174 175 JSHandle<JSFunction> weakRef(env->GetBuiltinsWeakRefFunction()); 176 177 auto ecmaRuntimeCallInfo1 = 178 TestHelper::CreateEcmaRuntimeCallInfo(thread, weakRef.GetTaggedValue(), 6); // 6 means 1 call arg 179 ecmaRuntimeCallInfo1->SetFunction(weakRef.GetTaggedValue()); 180 ecmaRuntimeCallInfo1->SetThis(JSTaggedValue::Undefined()); 181 ecmaRuntimeCallInfo1->SetCallArg(0, target.GetTaggedValue()); 182 183 // constructor 184 [[maybe_unused]] auto prev1 = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo1); 185 JSTaggedValue result1 = BuiltinsWeakRef::WeakRefConstructor(ecmaRuntimeCallInfo1); 186 TestHelper::TearDownFrame(thread, prev1); 187 ASSERT_TRUE(result1.IsECMAObject()); 188 189 JSHandle<JSWeakRef> jsWeakRef(thread, JSWeakRef::Cast(reinterpret_cast<TaggedObject *>(result1.GetRawData()))); 190 auto ecmaRuntimeCallInfo2 = 191 TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4); // 4 means 0 call arg 192 ecmaRuntimeCallInfo2->SetFunction(JSTaggedValue::Undefined()); 193 ecmaRuntimeCallInfo2->SetThis(jsWeakRef.GetTaggedValue()); 194 195 // weakRef.Deref() 196 [[maybe_unused]] auto prev2 = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo2); 197 JSTaggedValue result2 = BuiltinsWeakRef::Deref(ecmaRuntimeCallInfo2); 198 TestHelper::TearDownFrame(thread, prev2); 199 ASSERT_EQ(result2, target.GetTaggedValue()); 200} 201} // namespace panda::test 202