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 
93 namespace panda::ecmascript::builtins {
94 enum class KeyType : uint8_t {
95     STRING_TYPE = 0,
96     SYMBOL_TYPE,
97 };
98 
99 class BuiltinsObject : public base::BuiltinsBase {
100 public:
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 
GetObjectFunctions()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
GetObjectPrototypeFunctions()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 
GetFunctionPrototypeProperties()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 
GetFunctionProperties()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 
196 private:
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