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
23using namespace panda::ecmascript;
24
25namespace panda::test {
26using BuiltinsSharedObject = ecmascript::builtins::BuiltinsSharedObject;
27
28class BuiltinsSharedObjectTest : public BaseTestWithScope<false> {
29};
30
31HWTEST_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
38HWTEST_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
82HWTEST_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
107HWTEST_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
123HWTEST_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