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_OBJECT_H
17#define ECMASCRIPT_BUILTINS_BUILTINS_OBJECT_H
18
19#include "ecmascript/base/builtins_base.h"
20#include "ecmascript/ecma_runtime_call_info.h"
21#include "ecmascript/js_handle.h"
22#include "ecmascript/js_hclass.h"
23
24// List of functions in Object, excluding the '@@' properties.
25// V(name, func, length, stubIndex)
26// where BuiltinsObject::func refers to the native implementation of Object[name].
27//       kungfu::BuiltinsStubCSigns::stubIndex refers to the builtin stub index, or INVALID if no stub available.
28
29#define BUILTIN_OBJECT_FUNCTIONS(V)                                                                 \
30    /* Object.assign ( target, ...sources ) */                                                      \
31    V("assign",                   Assign,                   2, ObjectAssign)                        \
32    /* Object.create ( O, Properties ) */                                                           \
33    V("create",                   Create,                   2, ObjectCreate)                        \
34    /* Object.defineProperties ( O, Properties ) */                                                 \
35    V("defineProperties",         DefineProperties,         2, INVALID)                             \
36    /* Object.defineProperty ( O, P, Attributes ) */                                                \
37    V("defineProperty",           DefineProperty,           3, INVALID)                             \
38    /* Object.entries ( O ) */                                                                      \
39    V("entries",                  Entries,                  1, ObjectEntries)                       \
40    /* Object.freeze ( O ) */                                                                       \
41    V("freeze",                   Freeze,                   1, INVALID)                             \
42    /* Object.fromEntries ( iterable ) */                                                           \
43    V("fromEntries",              FromEntries,              1, INVALID)                             \
44    /* Object.getOwnPropertyDescriptor ( O, P ) */                                                  \
45    V("getOwnPropertyDescriptor", GetOwnPropertyDescriptor, 2, INVALID)                             \
46    /* Object.getOwnPropertyDescriptors ( O ) */                                                    \
47    V("getOwnPropertyDescriptors", GetOwnPropertyDescriptors, 1, ObjectGetOwnPropertyDescriptors)   \
48    /* Object.getOwnPropertyNames ( O ) */                                                          \
49    V("getOwnPropertyNames",      GetOwnPropertyNames,      1, ObjectGetOwnPropertyNames)           \
50    /* Object.getOwnPropertySymbols ( O ) */                                                        \
51    V("getOwnPropertySymbols",    GetOwnPropertySymbols,    1, ObjectGetOwnPropertySymbols)         \
52    /* Object.getPrototypeOf ( O ) */                                                               \
53    V("getPrototypeOf",           GetPrototypeOf,           1, ObjectGetPrototypeOf)                \
54    /* Object.hasOwn ( O, P ) */                                                                    \
55    V("hasOwn",                   HasOwn,                   2, INVALID)                             \
56    /* Object.is ( value1, value2 ) */                                                              \
57    V("is",                       Is,                       2, ObjectIs)                             \
58    /* Object.isExtensible ( O ) */                                                                 \
59    V("isExtensible",             IsExtensible,             1, INVALID)                             \
60    /* Object.isFrozen ( O ) */                                                                     \
61    V("isFrozen",                 IsFrozen,                 1, ObjectIsFrozen)                      \
62    /* Object.isSealed ( O ) */                                                                     \
63    V("isSealed",                 IsSealed,                 1, ObjectIsSealed)                      \
64    /* Object.keys ( O ) */                                                                         \
65    V("keys",                     Keys,                     1, ObjectKeys)                          \
66    /* Object.preventExtensions ( O ) */                                                            \
67    V("preventExtensions",        PreventExtensions,        1, INVALID)                             \
68    /* Object.seal ( O ) */                                                                         \
69    V("seal",                     Seal,                     1, INVALID)                             \
70    /* Object.setPrototypeOf ( O, proto ) */                                                        \
71    V("setPrototypeOf",           SetPrototypeOf,           2, ObjectSetPrototypeOf)                \
72    /* Object.values ( O ) */                                                                       \
73    V("values",                   Values,                   1, INVALID)
74
75// List of functions in Object.prototype, excluding the constructor and '@@' properties.
76// V(name, func, length, stubIndex)
77// where BuiltinsObject::func refers to the native implementation of Object.prototype[name].
78#define BUILTIN_OBJECT_PROTOTYPE_FUNCTIONS(V)                                       \
79    V("createRealm",          CreateRealm,          0, INVALID)                     \
80    /* Object.prototype.hasOwnProperty ( V ) */                                     \
81    V("hasOwnProperty",       HasOwnProperty,       1, ObjectHasOwnProperty)        \
82    /* Object.prototype.isPrototypeOf ( V ) */                                      \
83    V("isPrototypeOf",        IsPrototypeOf,        1, ObjectIsPrototypeOf)         \
84    /* Object.prototype.propertyIsEnumerable ( V ) */                               \
85    V("propertyIsEnumerable", PropertyIsEnumerable, 1, INVALID)                     \
86    /* Object.prototype.toLocaleString ( [ reserved1 [ , reserved2 ] ] ) */         \
87    V("toLocaleString",       ToLocaleString,       0, INVALID)                     \
88    /* Object.prototype.toString ( ) */                                             \
89    V("toString",             ToString,             0, ObjectToString)              \
90    /* Object.prototype.valueOf ( ) */                                              \
91    V("valueOf",              ValueOf,              0, INVALID)
92
93namespace panda::ecmascript::builtins {
94enum class KeyType : uint8_t {
95    STRING_TYPE = 0,
96    SYMBOL_TYPE,
97};
98
99class BuiltinsObject : public base::BuiltinsBase {
100public:
101    // 19.1.1.1Object ( [ value ] )
102    static JSTaggedValue ObjectConstructor(EcmaRuntimeCallInfo *argv);
103
104    // 19.1.2.1Object.assign ( target, ...sources )
105    static JSTaggedValue Assign(EcmaRuntimeCallInfo *argv);
106    // 19.1.2.2Object.create ( O [ , Properties ] )
107    static JSTaggedValue Create(EcmaRuntimeCallInfo *argv);
108    // 19.1.2.3Object.defineProperties ( O, Properties )
109    static JSTaggedValue DefineProperties(EcmaRuntimeCallInfo *argv);
110    // 19.1.2.4Object.defineProperty ( O, P, Attributes )
111    static JSTaggedValue DefineProperty(EcmaRuntimeCallInfo *argv);
112    // 19.1.2.5Object.freeze ( O )
113    static JSTaggedValue Freeze(EcmaRuntimeCallInfo *argv);
114    // 19.1.2.6Object.getOwnPropertyDescriptor ( O, P )
115    static JSTaggedValue GetOwnPropertyDescriptor(EcmaRuntimeCallInfo *argv);
116    // 19.1.2.7Object.getOwnPropertyNames ( O )
117    static JSTaggedValue GetOwnPropertyNames(EcmaRuntimeCallInfo *argv);
118    // 19.1.2.8Object.getOwnPropertySymbols ( O )
119    static JSTaggedValue GetOwnPropertySymbols(EcmaRuntimeCallInfo *argv);
120    // 19.1.2.9Object.getPrototypeOf ( O )
121    static JSTaggedValue GetPrototypeOf(EcmaRuntimeCallInfo *argv);
122    // 19.1.2.10Object.is ( value1, value2 )
123    static JSTaggedValue Is(EcmaRuntimeCallInfo *argv);
124    // 19.1.2.11Object.isExtensible ( O )
125    static JSTaggedValue IsExtensible(EcmaRuntimeCallInfo *argv);
126    // 19.1.2.12Object.isFrozen ( O )
127    static JSTaggedValue IsFrozen(EcmaRuntimeCallInfo *argv);
128    // 19.1.2.13Object.isSealed ( O )
129    static JSTaggedValue IsSealed(EcmaRuntimeCallInfo *argv);
130    // 19.1.2.14 Object.keys(O)
131    static JSTaggedValue Keys(EcmaRuntimeCallInfo *argv);
132    // 20.1.2.22 Object.values(O)
133    static JSTaggedValue Values(EcmaRuntimeCallInfo *argv);
134    // 19.1.2.15 Object.preventExtensions(O)
135    static JSTaggedValue PreventExtensions(EcmaRuntimeCallInfo *argv);
136    // 19.1.2.17 Object.seal(O)
137    static JSTaggedValue Seal(EcmaRuntimeCallInfo *argv);
138    // 19.1.2.18 Object.setPrototypeOf(O, proto)
139    static JSTaggedValue SetPrototypeOf(EcmaRuntimeCallInfo *argv);
140
141    static JSTaggedValue GetOwnPropertyDescriptors(EcmaRuntimeCallInfo *argv);
142
143    // 19.1.3.2 Object.prototype.hasOwnProperty(V)
144    static JSTaggedValue HasOwnProperty(EcmaRuntimeCallInfo *argv);
145    static JSTaggedValue HasOwnPropertyInternal(JSThread *thread, JSHandle<JSTaggedValue> thisValue,
146                                                JSHandle<JSTaggedValue> prop);
147    // 19.1.3.3 Object.prototype.isPrototypeOf(V)
148    static JSTaggedValue IsPrototypeOf(EcmaRuntimeCallInfo *argv);
149    // 19.1.3.4 Object.prototype.propertyIsEnumerable(V)
150    static JSTaggedValue PropertyIsEnumerable(EcmaRuntimeCallInfo *argv);
151    // 19.1.3.5 Object.prototype.toLocaleString([reserved1[, reserved2]])
152    static JSTaggedValue ToLocaleString(EcmaRuntimeCallInfo *argv);
153    // 19.1.3.6 Object.prototype.toString()
154    static JSTaggedValue ToString(EcmaRuntimeCallInfo *argv);
155    // 19.1.3.7 Object.prototype.valueOf()
156    static JSTaggedValue ValueOf(EcmaRuntimeCallInfo *argv);
157
158    static JSTaggedValue CreateRealm(EcmaRuntimeCallInfo *argv);
159    // 20.1.2.5 Object.entries ( O )
160    static JSTaggedValue Entries(EcmaRuntimeCallInfo *argv);
161    // 20.1.2.7 Object.fromEntries ( iterable )
162    static JSTaggedValue FromEntries(EcmaRuntimeCallInfo *argv);
163    // B.2.2.1 Object.prototype.__proto__
164    static JSTaggedValue ProtoGetter(EcmaRuntimeCallInfo *argv);
165    static JSTaggedValue ProtoSetter(EcmaRuntimeCallInfo *argv);
166
167    // 20.1.2.7.1 CreateDataPropertyOnObject Functions
168    static JSTaggedValue CreateDataPropertyOnObjectFunctions(EcmaRuntimeCallInfo *argv);
169    // 20.1.2.13 Object.hasOwn ( O, P )
170    static JSTaggedValue HasOwn(EcmaRuntimeCallInfo *argv);
171
172    static Span<const base::BuiltinFunctionEntry> GetObjectFunctions()
173    {
174        return Span<const base::BuiltinFunctionEntry>(OBJECT_FUNCTIONS);
175    }
176
177    // Excluding the constructor and '@@' internal properties
178    static Span<const base::BuiltinFunctionEntry> GetObjectPrototypeFunctions()
179    {
180        return Span<const base::BuiltinFunctionEntry>(OBJECT_PROTOTYPE_FUNCTIONS);
181    }
182
183    static JSTaggedValue AssignTaggedValue(JSThread *thread, const JSHandle<JSTaggedValue> &source,
184                                           const JSHandle<JSObject> &toAssign);
185
186    static Span<const std::pair<std::string_view, bool>> GetFunctionPrototypeProperties()
187    {
188        return Span<const std::pair<std::string_view, bool>>(OBJECT_PROTOTYPE_PROPERTIES);
189    }
190
191    static Span<const std::pair<std::string_view, bool>> GetFunctionProperties()
192    {
193        return Span<const std::pair<std::string_view, bool>>(OBJECT_PROPERTIES);
194    }
195
196private:
197#define BUILTIN_OBJECT_FUNCTION_ENTRY(name, func, length, id) \
198    base::BuiltinFunctionEntry::Create(name, BuiltinsObject::func, length, kungfu::BuiltinsStubCSigns::id),
199
200    static constexpr std::array OBJECT_FUNCTIONS = {
201        BUILTIN_OBJECT_FUNCTIONS(BUILTIN_OBJECT_FUNCTION_ENTRY)
202    };
203    static constexpr std::array OBJECT_PROTOTYPE_FUNCTIONS = {
204        BUILTIN_OBJECT_PROTOTYPE_FUNCTIONS(BUILTIN_OBJECT_FUNCTION_ENTRY)
205    };
206#undef BUILTIN_OBJECT_FUNCTION_ENTRY
207
208#define OBJECT_PROPERTIES_PAIR(name, func, length, id) \
209    std::pair<std::string_view, bool>(name, false),
210
211    static constexpr std::array OBJECT_PROTOTYPE_PROPERTIES = {
212        std::pair<std::string_view, bool>("constructor", false),
213        BUILTIN_OBJECT_PROTOTYPE_FUNCTIONS(OBJECT_PROPERTIES_PAIR)
214        std::pair<std::string_view, bool>("__proto__", true),
215    };
216
217    static constexpr std::array OBJECT_PROPERTIES = {
218        std::pair<std::string_view, bool>("length", false),
219        std::pair<std::string_view, bool>("name", false),
220        std::pair<std::string_view, bool>("prototype", false),
221        BUILTIN_OBJECT_FUNCTIONS(OBJECT_PROPERTIES_PAIR)
222
223    };
224#undef OBJECT_PROPERTIES_PAIR
225
226    static JSTaggedValue ObjectDefineProperties(JSThread *thread, const JSHandle<JSTaggedValue> &obj,
227                                                const JSHandle<JSTaggedValue> &prop);
228    static JSTaggedValue GetOwnPropertyKeys(JSThread *thread, const JSHandle<JSTaggedValue> &obj, const KeyType &type);
229    static JSTaggedValue GetBuiltinObjectToString(JSThread *thread, const JSHandle<JSObject> &object);
230};
231}  // namespace panda::ecmascript::builtins
232#endif  // ECMASCRIPT_BUILTINS_BUILTINS_OBJECT_H
233