1 /*
2  * Copyright (c) 2023 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_shared_object.h"
17 #include "ecmascript/ecma_vm.h"
18 #include "ecmascript/global_env.h"
19 #include "ecmascript/js_handle.h"
20 #include "ecmascript/js_tagged_value.h"
21 #include "ecmascript/tests/test_helper.h"
22 
23 using namespace panda::ecmascript;
24 
25 namespace panda::test {
26 using BuiltinsSharedObject = ecmascript::builtins::BuiltinsSharedObject;
27 
28 class BuiltinsSharedObjectTest : public BaseTestWithScope<false> {
29 };
30 
HWTEST_F_L0(BuiltinsSharedObjectTest, SharedObjectConstructor)31 HWTEST_F_L0(BuiltinsSharedObjectTest, SharedObjectConstructor)
32 {
33     auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
34     JSTaggedValue result = BuiltinsSharedObject::SharedObjectConstructor(ecmaRuntimeCallInfo);
35     ASSERT_EQ(result.GetRawData(), JSTaggedValue::Exception().GetRawData());
36 }
37 
HWTEST_F_L0(BuiltinsSharedObjectTest, SharedObject)38 HWTEST_F_L0(BuiltinsSharedObjectTest, SharedObject)
39 {
40     DISALLOW_GARBAGE_COLLECTION;
41     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
42     auto globalConst = thread->GlobalConstants();
43     auto sharedObjectPrototype = env->GetSObjectFunctionPrototype();
44     JSHClass *hclass = sharedObjectPrototype->GetTaggedObject()->GetClass();
45     ASSERT_FALSE(hclass->IsExtensible());
46     ASSERT_FALSE(hclass->IsConstructor());
47     ASSERT_FALSE(hclass->IsCallable());
48     ASSERT_TRUE(hclass->IsJSSharedObject());
49     ASSERT_TRUE(hclass->GetProto().IsNull());
50 
51     // SharedObject
52     PropertyDescriptor desc(thread);
53     JSHandle<JSTaggedValue> constructorKey = globalConst->GetHandledConstructorString();
54     JSObject::GetOwnProperty(thread, JSHandle<JSObject>(sharedObjectPrototype), constructorKey, desc);
55     auto ctor = desc.GetValue();
56     ASSERT_EQ(ctor.GetTaggedValue(), env->GetSObjectFunction().GetTaggedValue());
57     JSHClass *ctorHClass = ctor->GetTaggedObject()->GetClass();
58     ASSERT_FALSE(ctorHClass->IsExtensible());
59     ASSERT_TRUE(ctorHClass->IsConstructor());
60     ASSERT_TRUE(ctorHClass->IsCallable());
61     ASSERT_TRUE(ctorHClass->IsJSSharedFunction());
62 
63     // SharedFunction.prototype
64     auto proto = ctorHClass->GetProto();
65     ASSERT_EQ(proto, env->GetSFunctionPrototype().GetTaggedValue());
66     ASSERT_TRUE(proto.IsJSSharedFunction());
67     JSHClass *protoHClass = proto.GetTaggedObject()->GetClass();
68     ASSERT_FALSE(protoHClass->IsExtensible());
69     ASSERT_FALSE(protoHClass->IsConstructor());
70     ASSERT_TRUE(protoHClass->IsCallable());
71 
72     // SharedObject.prototype
73     auto sObjProto = protoHClass->GetProto();
74     ASSERT_EQ(sObjProto, sharedObjectPrototype.GetTaggedValue());
75     ASSERT_TRUE(sObjProto.IsJSSharedObject());
76     JSHClass *sObjProtoHClass = sObjProto.GetTaggedObject()->GetClass();
77     ASSERT_FALSE(sObjProtoHClass->IsExtensible());
78     ASSERT_FALSE(sObjProtoHClass->IsConstructor());
79     ASSERT_FALSE(sObjProtoHClass->IsCallable());
80 }
81 
HWTEST_F_L0(BuiltinsSharedObjectTest, SharedFunction)82 HWTEST_F_L0(BuiltinsSharedObjectTest, SharedFunction)
83 {
84     DISALLOW_GARBAGE_COLLECTION;
85     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
86     auto globalConst = thread->GlobalConstants();
87     auto sFunctionPrototype = env->GetSFunctionPrototype();
88     // SharedFunction
89     PropertyDescriptor desc(thread);
90     JSHandle<JSTaggedValue> constructorKey = globalConst->GetHandledConstructorString();
91     JSObject::GetOwnProperty(thread, JSHandle<JSObject>(sFunctionPrototype), constructorKey, desc);
92     auto ctor = desc.GetValue();
93     ASSERT_EQ(ctor.GetTaggedValue(), env->GetSFunctionFunction().GetTaggedValue());
94     JSHClass *ctorHClass = ctor->GetTaggedObject()->GetClass();
95     ASSERT_FALSE(ctorHClass->IsExtensible());
96     ASSERT_TRUE(ctorHClass->IsConstructor());
97     ASSERT_TRUE(ctorHClass->IsCallable());
98     ASSERT_TRUE(ctorHClass->IsJSSharedFunction());
99 
100     JSHandle<JSHClass> normalFunctionClass(env->GetSFunctionClassWithoutProto());
101     ASSERT_FALSE(normalFunctionClass->IsExtensible());
102     ASSERT_FALSE(normalFunctionClass->IsConstructor());
103     ASSERT_TRUE(ctorHClass->IsCallable());
104     ASSERT_TRUE(ctorHClass->IsJSSharedFunction());
105 }
106 
HWTEST_F_L0(BuiltinsSharedObjectTest, SharedBuiltinsMethod)107 HWTEST_F_L0(BuiltinsSharedObjectTest, SharedBuiltinsMethod)
108 {
109     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
110     auto factory = thread->GetEcmaVM()->GetFactory();
111     auto sFunctionPrototype = env->GetSFunctionPrototype();
112     auto callStr = factory->NewFromASCII("call");
113     PropertyDescriptor desc(thread);
114     JSObject::GetOwnProperty(thread, JSHandle<JSObject>(sFunctionPrototype), JSHandle<JSTaggedValue>(callStr), desc);
115     auto method = desc.GetValue();
116     JSHClass *hclass = method->GetTaggedObject()->GetClass();
117     ASSERT_FALSE(hclass->IsExtensible());
118     ASSERT_TRUE(!hclass->IsConstructor());
119     ASSERT_TRUE(hclass->IsCallable());
120     ASSERT_TRUE(hclass->IsJSSharedFunction());
121 }
122 
HWTEST_F_L0(BuiltinsSharedObjectTest, SendableMethod)123 HWTEST_F_L0(BuiltinsSharedObjectTest, SendableMethod)
124 {
125     // Mock create sendable function
126     auto factory = thread->GetEcmaVM()->GetFactory();
127     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
128 
129     uint32_t methodOffset = 100;
130     MethodLiteral *methodLiteral = new MethodLiteral(EntityId(methodOffset));
131     methodLiteral->SetIsShared(true);
132     JSHandle<Method> method = factory->NewSMethod(methodLiteral);
133     method->SetFunctionKind(FunctionKind::BASE_CONSTRUCTOR);
134     JSHandle<JSFunction> func = factory->NewJSSendableFunction(method);
135     ASSERT_TRUE(Method::Cast(func->GetMethod())->IsSendableMethod());
136 
137     uint32_t methodOffset1 = 101;
138     MethodLiteral *methodLiteral1 = new MethodLiteral(EntityId(methodOffset1));
139     JSHandle<Method> method1 = factory->NewSMethod(methodLiteral1);
140     method1->SetIsSendable(true);
141     JSHandle<JSFunction> func1 = factory->NewSFunctionByHClass(
142         method1, JSHandle<JSHClass>::Cast(env->GetSFunctionClassWithoutProto()));
143     ASSERT_TRUE(Method::Cast(func1->GetMethod())->IsSendableMethod());
144 }
145 }  // namespace panda::test
146