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
35 using namespace panda::ecmascript;
36 using namespace panda::ecmascript::builtins;
37 using BuiltinsBase = panda::ecmascript::base::BuiltinsBase;
38
39 namespace panda::test {
40 using BuiltinsWeakRef = ecmascript::builtins::BuiltinsWeakRef;
41
42 class BuiltinsWeakRefTest : public testing::Test {
43 public:
SetUpTestCase()44 static void SetUpTestCase()
45 {
46 GTEST_LOG_(INFO) << "SetUpTestCase";
47 }
48
TearDownTestCase()49 static void TearDownTestCase()
50 {
51 GTEST_LOG_(INFO) << "TearDownCase";
52 }
53
SetUp()54 void SetUp() override
55 {
56 TestHelper::CreateEcmaVMWithScope(instance, thread, scope);
57 }
58
TearDown()59 void TearDown() override
60 {
61 TestHelper::DestroyEcmaVMWithScope(instance, scope);
62 }
63
64 EcmaVM *instance {nullptr};
65 EcmaHandleScope *scope {nullptr};
66 JSThread *thread {nullptr};
67 };
68
CreateWeakRefConstructor(JSThread * thread,JSTaggedValue target)69 JSTaggedValue CreateWeakRefConstructor(JSThread *thread, JSTaggedValue target)
70 {
71 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
72 JSHandle<JSObject> globalObject(thread, env->GetGlobalObject());
73 JSHandle<JSFunction> weakRef(env->GetBuiltinsWeakRefFunction());
74
75 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue(*weakRef), 6);
76 ecmaRuntimeCallInfo->SetFunction(weakRef.GetTaggedValue());
77 ecmaRuntimeCallInfo->SetThis(globalObject.GetTaggedValue());
78 ecmaRuntimeCallInfo->SetCallArg(0, target);
79
80 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
81 JSTaggedValue result = BuiltinsWeakRef::WeakRefConstructor(ecmaRuntimeCallInfo);
82 TestHelper::TearDownFrame(thread, prev);
83 return result;
84 }
85
86 // new WeakRef(target)
HWTEST_F_L0(BuiltinsWeakRefTest,WeakRefConstructor)87 HWTEST_F_L0(BuiltinsWeakRefTest, WeakRefConstructor)
88 {
89 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
90 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
91 JSHandle<JSTaggedValue> objectFunc(env->GetObjectFunction());
92
93 JSHandle<JSObject> target(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objectFunc), objectFunc));
94
95 JSHandle<JSFunction> weakRef(env->GetBuiltinsWeakRefFunction());
96 JSHandle<JSObject> globalObject(thread, env->GetGlobalObject());
97
98 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, weakRef.GetTaggedValue(), 6);
99 ecmaRuntimeCallInfo->SetFunction(weakRef.GetTaggedValue());
100 ecmaRuntimeCallInfo->SetThis(globalObject.GetTaggedValue());
101 ecmaRuntimeCallInfo->SetCallArg(0, target.GetTaggedValue());
102
103 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
104 JSTaggedValue result = BuiltinsWeakRef::WeakRefConstructor(ecmaRuntimeCallInfo);
105
106 ASSERT_TRUE(result.IsECMAObject());
107 }
108
109 // weakRef.Deref()
HWTEST_F_L0(BuiltinsWeakRefTest,Deref1)110 HWTEST_F_L0(BuiltinsWeakRefTest, Deref1)
111 {
112 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
113 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
114 JSHandle<JSTaggedValue> objectFunc(env->GetObjectFunction());
115
116 JSHandle<JSObject> target(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objectFunc), objectFunc));
117 JSTaggedValue result = CreateWeakRefConstructor(thread, target.GetTaggedValue());
118 JSHandle<JSWeakRef> jsWeakRef(thread, JSWeakRef::Cast(reinterpret_cast<TaggedObject *>(result.GetRawData())));
119 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);
120 ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
121 ecmaRuntimeCallInfo->SetThis(jsWeakRef.GetTaggedValue());
122
123 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
124 TestHelper::TearDownFrame(thread, prev);
125 JSTaggedValue result1 = BuiltinsWeakRef::Deref(ecmaRuntimeCallInfo);
126 ASSERT_EQ(result1, target.GetTaggedValue());
127 }
128
129 // weakRef.Deref()
HWTEST_F_L0(BuiltinsWeakRefTest,Deref2)130 HWTEST_F_L0(BuiltinsWeakRefTest, Deref2)
131 {
132 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
133 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
134 JSHandle<JSTaggedValue> objectFunc(env->GetObjectFunction());
135 JSHandle<JSTaggedValue> formatStyle = thread->GlobalConstants()->GetHandledStyleString();
136 JSHandle<JSTaggedValue> styleKey(factory->NewFromASCII("currency"));
137 JSHandle<JSTaggedValue> styleValue(factory->NewFromASCII("EUR"));
138 JSHandle<JSObject> target(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objectFunc), objectFunc));
139 JSObject::SetProperty(thread, target, formatStyle, styleKey);
140 JSObject::SetProperty(thread, target, styleKey, styleValue);
141
142 JSTaggedValue result = CreateWeakRefConstructor(thread, target.GetTaggedValue());
143 JSHandle<JSWeakRef> jsWeakRef(thread, JSWeakRef::Cast(reinterpret_cast<TaggedObject *>(result.GetRawData())));
144 auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);
145 ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
146 ecmaRuntimeCallInfo->SetThis(jsWeakRef.GetTaggedValue());
147
148 [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
149 TestHelper::TearDownFrame(thread, prev);
150 JSTaggedValue result1 = BuiltinsWeakRef::Deref(ecmaRuntimeCallInfo);
151 ASSERT_EQ(result1, target.GetTaggedValue());
152
153 JSObject::SetProperty(thread, target, styleKey, styleValue);
154 ASSERT_EQ(result1, target.GetTaggedValue());
155 }
156
157 // weakRef.Deref()
HWTEST_F_L0(BuiltinsWeakRefTest,Deref3)158 HWTEST_F_L0(BuiltinsWeakRefTest, Deref3)
159 {
160 EcmaVM *vm = thread->GetEcmaVM();
161 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
162 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
163 JSHandle<JSTaggedValue> objectFunc(env->GetObjectFunction());
164
165 JSTaggedValue target =
166 factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objectFunc), objectFunc).GetTaggedValue();
167 JSTaggedValue result = CreateWeakRefConstructor(thread, target);
168 JSHandle<JSWeakRef> jsWeakRef(thread, JSWeakRef::Cast(reinterpret_cast<TaggedObject *>(result.GetRawData())));
169 JSTaggedValue result2 = JSTaggedValue::Undefined();
170
171 {
172 [[maybe_unused]] EcmaHandleScope handleScope(thread);
173 auto obj =
174 factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objectFunc), objectFunc);
175 target = obj.GetTaggedValue();
176 auto ecmaRuntimeCallInfo1 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);
177 ecmaRuntimeCallInfo1->SetFunction(JSTaggedValue::Undefined());
178 ecmaRuntimeCallInfo1->SetThis(jsWeakRef.GetTaggedValue());
179
180 [[maybe_unused]] auto prev1 = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo1);
181 result2 = BuiltinsWeakRef::Deref(ecmaRuntimeCallInfo1);
182 TestHelper::TearDownFrame(thread, prev1);
183 }
184 vm->CollectGarbage(TriggerGCType::FULL_GC);
185 if (!thread->HasPendingException()) {
186 job::MicroJobQueue::ExecutePendingJob(thread, vm->GetJSThread()->GetCurrentEcmaContext()->GetMicroJobQueue());
187 }
188 vm->SetEnableForceGC(true);
189 ASSERT_TRUE(!result2.IsUndefined());
190 }
191
192 // symbol target
HWTEST_F_L0(BuiltinsWeakRefTest,SymbolTarget)193 HWTEST_F_L0(BuiltinsWeakRefTest, SymbolTarget)
194 {
195 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
196 JSHandle<JSSymbol> symbolTarget = thread->GetEcmaVM()->GetFactory()->NewJSSymbol();
197 JSHandle<JSTaggedValue> target(symbolTarget);
198
199 JSHandle<JSFunction> weakRef(env->GetBuiltinsWeakRefFunction());
200
201 auto ecmaRuntimeCallInfo1 =
202 TestHelper::CreateEcmaRuntimeCallInfo(thread, weakRef.GetTaggedValue(), 6); // 6 means 1 call arg
203 ecmaRuntimeCallInfo1->SetFunction(weakRef.GetTaggedValue());
204 ecmaRuntimeCallInfo1->SetThis(JSTaggedValue::Undefined());
205 ecmaRuntimeCallInfo1->SetCallArg(0, target.GetTaggedValue());
206
207 // constructor
208 [[maybe_unused]] auto prev1 = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo1);
209 JSTaggedValue result1 = BuiltinsWeakRef::WeakRefConstructor(ecmaRuntimeCallInfo1);
210 TestHelper::TearDownFrame(thread, prev1);
211 ASSERT_TRUE(result1.IsECMAObject());
212
213 JSHandle<JSWeakRef> jsWeakRef(thread, JSWeakRef::Cast(reinterpret_cast<TaggedObject *>(result1.GetRawData())));
214 auto ecmaRuntimeCallInfo2 =
215 TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4); // 4 means 0 call arg
216 ecmaRuntimeCallInfo2->SetFunction(JSTaggedValue::Undefined());
217 ecmaRuntimeCallInfo2->SetThis(jsWeakRef.GetTaggedValue());
218
219 // weakRef.Deref()
220 [[maybe_unused]] auto prev2 = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo2);
221 JSTaggedValue result2 = BuiltinsWeakRef::Deref(ecmaRuntimeCallInfo2);
222 TestHelper::TearDownFrame(thread, prev2);
223 ASSERT_EQ(result2, target.GetTaggedValue());
224 }
225 } // namespace panda::test
226