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
30namespace panda::ecmascript::builtins {
31using BuiltinsPropertyConfig = base::BuiltinsPropertyConfig;
32class BuiltinsFunction : public base::BuiltinsBase {
33public:
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
61    static Span<const BuiltinsPropertyConfig> GetFunctionPrototypeProperties()
62    {
63        return Span<const BuiltinsPropertyConfig>(FUNCTION_PROTOTYPE_PROPERTIES);
64    }
65
66    static Span<const BuiltinsPropertyConfig> GetFunctionProperties()
67    {
68        return Span<const BuiltinsPropertyConfig>(FUNCTION_PROPERTIES);
69    }
70
71    static Span<const base::BuiltinFunctionEntry> GetFunctionPrototypeFunctions()
72    {
73        return Span<const base::BuiltinFunctionEntry>(FUNCTION_PROTOTYPE_FUNCTIONS);
74    }
75private:
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