• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/js_function.h"
17 #include "ecmascript/base/builtins_base.h"
18 #include "ecmascript/ecma_string.h"
19 #include "ecmascript/ecma_vm.h"
20 #include "ecmascript/global_env.h"
21 #include "ecmascript/interpreter/interpreter.h"
22 #include "ecmascript/js_handle.h"
23 #include "ecmascript/js_hclass.h"
24 #include "ecmascript/js_object-inl.h"
25 #include "ecmascript/object_factory.h"
26 #include "ecmascript/tagged_array-inl.h"
27 #include "ecmascript/tests/test_helper.h"
28 
29 using namespace panda::ecmascript;
30 
31 using namespace panda::ecmascript::base;
32 
33 namespace panda::test {
34 class JSFunctionTest : public BaseTestWithScope<false> {
35 };
36 
JSObjectCreate(JSThread * thread)37 JSFunction *JSObjectCreate(JSThread *thread)
38 {
39     EcmaVM *ecmaVM = thread->GetEcmaVM();
40     JSHandle<GlobalEnv> globalEnv = ecmaVM->GetGlobalEnv();
41     return globalEnv->GetObjectFunction().GetObject<JSFunction>();
42 }
43 
HWTEST_F_L0(JSFunctionTest,Create)44 HWTEST_F_L0(JSFunctionTest, Create)
45 {
46     EcmaVM *ecmaVM = thread->GetEcmaVM();
47     JSHandle<GlobalEnv> env = ecmaVM->GetGlobalEnv();
48     JSHandle<JSFunction> funHandle = thread->GetEcmaVM()->GetFactory()->NewJSFunction(env);
49     EXPECT_TRUE(*funHandle != nullptr);
50     EXPECT_EQ(funHandle->GetProtoOrHClass(), JSTaggedValue::Hole());
51 
52     JSHandle<LexicalEnv> lexicalEnv = thread->GetEcmaVM()->GetFactory()->NewLexicalEnv(0);
53     funHandle->SetLexicalEnv(thread, lexicalEnv.GetTaggedValue());
54     EXPECT_EQ(funHandle->GetLexicalEnv(), lexicalEnv.GetTaggedValue());
55     EXPECT_TRUE(*lexicalEnv != nullptr);
56 }
HWTEST_F_L0(JSFunctionTest,MakeConstructor)57 HWTEST_F_L0(JSFunctionTest, MakeConstructor)
58 {
59     EcmaVM *ecmaVM = thread->GetEcmaVM();
60     JSHandle<GlobalEnv> env = ecmaVM->GetGlobalEnv();
61     JSHandle<JSFunction> func = thread->GetEcmaVM()->GetFactory()->NewJSFunction(env, static_cast<void *>(nullptr),
62                                                                                  FunctionKind::BASE_CONSTRUCTOR);
63     EXPECT_TRUE(*func != nullptr);
64     JSHandle<JSTaggedValue> funcHandle(func);
65     func->GetJSHClass()->SetExtensible(true);
66 
67     JSHandle<JSObject> nullHandle(thread, JSTaggedValue::Null());
68     JSHandle<JSObject> obj = JSObject::ObjectCreate(thread, nullHandle);
69     JSHandle<JSTaggedValue> objValue(obj);
70 
71     JSFunction::MakeConstructor(thread, func, objValue);
72 
73     JSHandle<JSTaggedValue> constructorKey(
74         thread->GetEcmaVM()->GetFactory()->NewFromASCII("constructor"));
75 
76     JSHandle<JSTaggedValue> protoKey(thread->GetEcmaVM()->GetFactory()->NewFromASCII("prototype"));
77     JSTaggedValue proto = JSObject::GetProperty(thread, funcHandle, protoKey).GetValue().GetTaggedValue();
78     JSTaggedValue constructor =
79         JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(obj), constructorKey).GetValue().GetTaggedValue();
80     EXPECT_EQ(constructor, funcHandle.GetTaggedValue());
81     EXPECT_EQ(proto, obj.GetTaggedValue());
82     EXPECT_EQ(func->GetFunctionKind(), FunctionKind::BASE_CONSTRUCTOR);
83 }
84 
HWTEST_F_L0(JSFunctionTest,OrdinaryHasInstance)85 HWTEST_F_L0(JSFunctionTest, OrdinaryHasInstance)
86 {
87     JSHandle<JSTaggedValue> objFun(thread, JSObjectCreate(thread));
88 
89     JSHandle<JSObject> jsobject =
90         thread->GetEcmaVM()->GetFactory()->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun);
91     JSHandle<JSTaggedValue> obj(thread, jsobject.GetTaggedValue());
92     EXPECT_TRUE(*jsobject != nullptr);
93 
94     EcmaVM *ecmaVM = thread->GetEcmaVM();
95     JSHandle<GlobalEnv> globalEnv = ecmaVM->GetGlobalEnv();
96     JSHandle<JSTaggedValue> constructor = globalEnv->GetObjectFunction();
97     EXPECT_TRUE(ecmascript::JSFunction::OrdinaryHasInstance(thread, constructor, obj));
98 }
99 
TestInvokeInternal(EcmaRuntimeCallInfo * argv)100 JSTaggedValue TestInvokeInternal(EcmaRuntimeCallInfo *argv)
101 {
102     if (argv->GetArgsNumber() == 1 && argv->GetCallArg(0).GetTaggedValue() == JSTaggedValue(1)) {
103         return BuiltinsBase::GetTaggedBoolean(true);
104     } else {
105         return BuiltinsBase::GetTaggedBoolean(false);
106     }
107 }
108 
HWTEST_F_L0(JSFunctionTest,Invoke)109 HWTEST_F_L0(JSFunctionTest, Invoke)
110 {
111     EcmaVM *ecmaVM = thread->GetEcmaVM();
112     JSHandle<GlobalEnv> env = ecmaVM->GetGlobalEnv();
113     JSHandle<JSTaggedValue> hclass(thread, JSObjectCreate(thread));
114     JSHandle<JSTaggedValue> callee(
115         thread->GetEcmaVM()->GetFactory()->NewJSObjectByConstructor(JSHandle<JSFunction>::Cast(hclass), hclass));
116     EXPECT_TRUE(*callee != nullptr);
117 
118     char keyArray[] = "invoked";
119     JSHandle<JSTaggedValue> calleeKey(thread->GetEcmaVM()->GetFactory()->NewFromASCII(&keyArray[0]));
120     JSHandle<JSFunction> calleeFunc =
121         thread->GetEcmaVM()->GetFactory()->NewJSFunction(env, reinterpret_cast<void *>(TestInvokeInternal));
122     calleeFunc->SetCallable(true);
123     JSHandle<JSTaggedValue> calleeValue(calleeFunc);
124     JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(callee), calleeKey, calleeValue);
125     JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
126     EcmaRuntimeCallInfo *info = EcmaInterpreter::NewRuntimeCallInfo(thread, undefined, callee, undefined, 1);
127     info->SetCallArg(JSTaggedValue(1));
128     JSTaggedValue res = JSFunction::Invoke(info, calleeKey);
129 
130     JSTaggedValue ruler = BuiltinsBase::GetTaggedBoolean(true);
131     EXPECT_EQ(res.GetRawData(), ruler.GetRawData());
132 }
133 
HWTEST_F_L0(JSFunctionTest,SetSymbolFunctionName)134 HWTEST_F_L0(JSFunctionTest, SetSymbolFunctionName)
135 {
136     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
137     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
138     JSHandle<JSFunction> jsFunction = factory->NewJSFunction(env);
139     JSHandle<JSSymbol> symbol = factory->NewPublicSymbolWithChar("name");
140     JSHandle<EcmaString> name = factory->NewFromASCII("[name]");
141     JSHandle<JSTaggedValue> prefix(thread, JSTaggedValue::Undefined());
142     JSFunction::SetFunctionName(thread, JSHandle<JSFunctionBase>(jsFunction), JSHandle<JSTaggedValue>(symbol), prefix);
143     JSHandle<JSTaggedValue> functionName =
144         JSFunctionBase::GetFunctionName(thread, JSHandle<JSFunctionBase>(jsFunction));
145     EXPECT_TRUE(functionName->IsString());
146     EXPECT_TRUE(EcmaStringAccessor::StringsAreEqual(*(JSHandle<EcmaString>(functionName)), *name));
147 }
148 }  // namespace panda::test
149