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 #ifndef ECMASCRIPT_BUILTINS_BUILTINS_FUNCTION_H
17 #define ECMASCRIPT_BUILTINS_BUILTINS_FUNCTION_H
18 
19 #include "ecmascript/base/builtins_base.h"
20 #include "ecmascript/js_tagged_value-inl.h"
21 
22 #define BUILTIN_FUNCTION_PROTOTYPE_FUNCTIONS(V)                                     \
23     /* Function.prototype.apply ( thisArg, argArray ) */                            \
24     V("apply",           FunctionPrototypeApply,      2, FunctionPrototypeApply)    \
25     /* Function.prototype.bind ( thisArg , ...args) */                              \
26     V("bind",            FunctionPrototypeBind,       1, FunctionPrototypeBind)     \
27     /* Function.prototype.call (thisArg , ...args) */                               \
28     V("call",            FunctionPrototypeCall,       1, FunctionPrototypeCall)
29 
30 namespace panda::ecmascript::builtins {
31 using BuiltinsPropertyConfig = base::BuiltinsPropertyConfig;
32 class BuiltinsFunction : public base::BuiltinsBase {
33 public:
34     // ecma 19.2.1 Function (p1, p2, ... , pn, body)
35     static JSTaggedValue FunctionConstructor(EcmaRuntimeCallInfo *argv);
36 
37     // ecma 19.2.3 The Function prototype object is itself a built-in function object.
38     static JSTaggedValue FunctionPrototypeInvokeSelf(EcmaRuntimeCallInfo *argv);
39 
40     // ecma 19.2.3.1 Function.prototype.apply (thisArg, argArray)
41     static JSTaggedValue FunctionPrototypeApply(EcmaRuntimeCallInfo *argv);
42     static JSTaggedValue FunctionPrototypeApplyInternal(JSThread *thread, JSHandle<JSTaggedValue> func,
43                                                         JSHandle<JSTaggedValue> thisArg,
44                                                         JSHandle<JSTaggedValue> arrayObj);
45 
46     // ecma 19.2.3.2 Function.prototype.bind (thisArg , ...args)
47     static JSTaggedValue FunctionPrototypeBind(EcmaRuntimeCallInfo *argv);
48     static JSTaggedValue FunctionPrototypeBindInternal(JSThread *thread, JSHandle<JSTaggedValue> target,
49                                                        JSHandle<JSTaggedValue> thisArg,
50                                                        JSHandle<TaggedArray> argsArray);
51 
52     // ecma 19.2.3.3 Function.prototype.call (thisArg , ...args)
53     static JSTaggedValue FunctionPrototypeCall(EcmaRuntimeCallInfo *argv);
54 
55     // ecma 19.2.3.5 Function.prototype.toString ()
56     static JSTaggedValue FunctionPrototypeToString(EcmaRuntimeCallInfo *argv);
57 
58     // ecma 19.2.3.6 Function.prototype[@@hasInstance] (V)
59     static JSTaggedValue FunctionPrototypeHasInstance(EcmaRuntimeCallInfo *argv);
60 
GetFunctionPrototypeProperties()61     static Span<const BuiltinsPropertyConfig> GetFunctionPrototypeProperties()
62     {
63         return Span<const BuiltinsPropertyConfig>(FUNCTION_PROTOTYPE_PROPERTIES);
64     }
65 
GetFunctionProperties()66     static Span<const BuiltinsPropertyConfig> GetFunctionProperties()
67     {
68         return Span<const BuiltinsPropertyConfig>(FUNCTION_PROPERTIES);
69     }
70 
GetFunctionPrototypeFunctions()71     static Span<const base::BuiltinFunctionEntry> GetFunctionPrototypeFunctions()
72     {
73         return Span<const base::BuiltinFunctionEntry>(FUNCTION_PROTOTYPE_FUNCTIONS);
74     }
75 private:
76     static constexpr std::array FUNCTION_PROTOTYPE_PROPERTIES = {
77         BuiltinsPropertyConfig("length", false, false, false, true),
78         BuiltinsPropertyConfig("name", false, false, false, true),
79         BuiltinsPropertyConfig("constructor", false, true, false, true),
80         BuiltinsPropertyConfig("caller", true, false, false, true),
81         BuiltinsPropertyConfig("arguments", true, false, false, true),
82         BuiltinsPropertyConfig("apply", false, true, false, true),
83         BuiltinsPropertyConfig("bind", false, true, false, true),
84         BuiltinsPropertyConfig("call", false, true, false, true),
85         BuiltinsPropertyConfig("toString", false, true, false, true),
86         BuiltinsPropertyConfig("[Symbol.hasInstance]", false, false, false, false),
87     };
88 
89     static constexpr std::array FUNCTION_PROPERTIES = {
90         BuiltinsPropertyConfig("length", false, false, false, true),
91         BuiltinsPropertyConfig("name", false, false, false, true),
92         BuiltinsPropertyConfig("prototype", false, false, false, false),
93     };
94 
95 #define BUILTIN_FUNCTION_FUNCTION_ENTRY(name, func, length, id) \
96     base::BuiltinFunctionEntry::Create(name, BuiltinsFunction::func, length, kungfu::BuiltinsStubCSigns::id),
97 
98     static constexpr std::array FUNCTION_PROTOTYPE_FUNCTIONS = {
99         BUILTIN_FUNCTION_PROTOTYPE_FUNCTIONS(BUILTIN_FUNCTION_FUNCTION_ENTRY)
100     };
101 #undef BUILTIN_FUNCTION_FUNCTION_ENTRY
102 };
103 }  // namespace panda::ecmascript::builtins
104 #endif  // ECMASCRIPT_BUILTINS_BUILTINS_FUNCTION_H
105