1 /* Copyright JS Foundation and other contributors, http://js.foundation
2 *
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 "ecma-array-object.h"
17 #include "ecma-builtins.h"
18 #include "ecma-builtin-function-prototype.h"
19 #include "ecma-iterator-object.h"
20 #include "ecma-builtin-helpers.h"
21 #include "ecma-builtin-object.h"
22 #include "ecma-exceptions.h"
23 #include "ecma-function-object.h"
24 #include "ecma-gc.h"
25 #include "ecma-proxy-object.h"
26 #include "jcontext.h"
27
28 #if ENABLED (JERRY_ES2015_BUILTIN_REFLECT)
29
30 #define ECMA_BUILTINS_INTERNAL
31 #include "ecma-builtins-internal.h"
32
33 /**
34 * This object has a custom dispatch function.
35 */
36 #define BUILTIN_CUSTOM_DISPATCH
37
38 /**
39 * List of built-in routine identifiers.
40 */
41 enum
42 {
43 ECMA_REFLECT_OBJECT_ROUTINE_START = ECMA_BUILTIN_ID__COUNT - 1,
44 ECMA_REFLECT_OBJECT_GET, /* ECMA-262 v6, 26.1.6 */
45 ECMA_REFLECT_OBJECT_SET, /* ECMA-262 v6, 26.1.13 */
46 ECMA_REFLECT_OBJECT_HAS, /* ECMA-262 v6, 26.1.9 */
47 ECMA_REFLECT_OBJECT_DELETE_PROPERTY, /* ECMA-262 v6, 26.1.4 */
48 ECMA_REFLECT_OBJECT_CONSTRUCT, /* ECMA-262, 26.1.2 */
49 ECMA_REFLECT_OBJECT_OWN_KEYS, /* ECMA-262 v6, 26.1.11 */
50 ECMA_REFLECT_OBJECT_GET_PROTOTYPE_OF, /* ECMA-262 v6, 26.1.8 */
51 ECMA_REFLECT_OBJECT_SET_PROTOTYPE_OF, /* ECMA-262 v6, 26.1.14 */
52 ECMA_REFLECT_OBJECT_APPLY, /* ECMA-262 v6, 26.1.1 */
53 ECMA_REFLECT_OBJECT_DEFINE_PROPERTY, /* ECMA-262 v6, 26.1.3 */
54 ECMA_REFLECT_OBJECT_GET_OWN_PROPERTY_DESCRIPTOR, /* ECMA-262 v6, 26.1.7 */
55 ECMA_REFLECT_OBJECT_IS_EXTENSIBLE, /* ECMA-262 v6, 26.1.10 */
56 ECMA_REFLECT_OBJECT_PREVENT_EXTENSIONS, /* ECMA-262 v6, 26.1.12 */
57 };
58
59 #define BUILTIN_INC_HEADER_NAME "ecma-builtin-reflect.inc.h"
60 #define BUILTIN_UNDERSCORED_ID reflect
61 #include "ecma-builtin-internal-routines-template.inc.h"
62
63 /** \addtogroup ecma ECMA
64 * @{
65 *
66 * \addtogroup ecmabuiltins
67 * @{
68 *
69 * \addtogroup object ECMA Reflect object built-in
70 * @{
71 */
72
73 /**
74 * Dispatcher for the built-in's routines.
75 *
76 * @return ecma value
77 * Returned value must be freed with ecma_free_value.
78 */
79 ecma_value_t
ecma_builtin_reflect_dispatch_routine(uint16_t builtin_routine_id,ecma_value_t this_arg,const ecma_value_t arguments_list[],ecma_length_t arguments_number)80 ecma_builtin_reflect_dispatch_routine (uint16_t builtin_routine_id, /**< built-in wide routine
81 * identifier */
82 ecma_value_t this_arg, /**< 'this' argument value */
83 const ecma_value_t arguments_list[], /**< list of arguments
84 * passed to routine */
85 ecma_length_t arguments_number) /**< length of arguments' list */
86 {
87 JERRY_UNUSED (this_arg);
88 JERRY_UNUSED (arguments_number);
89
90 if (builtin_routine_id < ECMA_REFLECT_OBJECT_CONSTRUCT)
91 {
92 /* 1. */
93 if (arguments_number == 0 || !ecma_is_value_object (arguments_list[0]))
94 {
95 return ecma_raise_type_error (ECMA_ERR_MSG ("Argument is not an Object."));
96 }
97
98 /* 2. */
99 ecma_string_t *name_str_p = ecma_op_to_prop_name (((arguments_number > 1) ? arguments_list[1]
100 : ECMA_VALUE_UNDEFINED));
101
102 /* 3. */
103 if (name_str_p == NULL)
104 {
105 return ECMA_VALUE_ERROR;
106 }
107
108 ecma_value_t ret_value;
109 ecma_object_t *target_p = ecma_get_object_from_value (arguments_list[0]);
110 switch (builtin_routine_id)
111 {
112 case ECMA_REFLECT_OBJECT_GET:
113 {
114 ecma_value_t receiver = arguments_list[0];
115
116 /* 4. */
117 if (arguments_number > 2)
118 {
119 receiver = arguments_list[2];
120 }
121
122 ret_value = ecma_op_object_get_with_receiver (target_p, name_str_p, receiver);
123 break;
124 }
125
126 case ECMA_REFLECT_OBJECT_HAS:
127 {
128 ret_value = ecma_op_object_has_property (target_p, name_str_p);
129 break;
130 }
131
132 case ECMA_REFLECT_OBJECT_DELETE_PROPERTY:
133 {
134 ret_value = ecma_op_object_delete (target_p, name_str_p, false);
135 break;
136 }
137
138 default:
139 {
140 JERRY_ASSERT (builtin_routine_id == ECMA_REFLECT_OBJECT_SET);
141
142 ecma_value_t receiver = arguments_list[0];
143
144 if (arguments_number > 3)
145 {
146 receiver = arguments_list[3];
147 }
148
149 ret_value = ecma_op_object_put_with_receiver (target_p, name_str_p, arguments_list[2], receiver, false);
150 break;
151 }
152 }
153
154 ecma_deref_ecma_string (name_str_p);
155 return ret_value;
156 }
157
158 if (builtin_routine_id == ECMA_REFLECT_OBJECT_OWN_KEYS)
159 {
160 /* 1. */
161 if (arguments_number == 0 || !ecma_is_value_object (arguments_list[0]))
162 {
163 return ecma_raise_type_error (ECMA_ERR_MSG ("Argument is not an Object."));
164 }
165
166 ecma_object_t *target_p = ecma_get_object_from_value (arguments_list[0]);
167
168 /* 2. 3. */
169 return ecma_builtin_helper_object_get_properties (target_p, ECMA_LIST_SYMBOLS);
170 }
171
172 if (builtin_routine_id == ECMA_REFLECT_OBJECT_CONSTRUCT)
173 {
174 /* 1. */
175 if (arguments_number < 1 || !ecma_is_constructor (arguments_list[0]))
176 {
177 return ecma_raise_type_error (ECMA_ERR_MSG ("Target is not a constructor"));
178 }
179
180 ecma_object_t *target_p = ecma_get_object_from_value (arguments_list[0]);
181
182 /* 2. */
183 ecma_object_t *new_target_p = target_p;
184
185 if (arguments_number > 2)
186 {
187 /* 3. */
188 if (!ecma_is_constructor (arguments_list[2]))
189 {
190 return ecma_raise_type_error (ECMA_ERR_MSG ("Target is not a constructor"));
191 }
192
193 new_target_p = ecma_get_object_from_value (arguments_list[2]);
194 }
195
196 /* 4. */
197 if (arguments_number < 2)
198 {
199 return ecma_raise_type_error (ECMA_ERR_MSG ("Reflect.construct requires the second argument be an object"));
200 }
201
202 ecma_collection_t *coll_p = ecma_op_create_list_from_array_like (arguments_list[1], false);
203
204 if (coll_p == NULL)
205 {
206 return ECMA_VALUE_ERROR;
207 }
208
209 ecma_value_t ret_value = ecma_op_function_construct (target_p,
210 new_target_p,
211 coll_p->buffer_p,
212 coll_p->item_count);
213
214 ecma_collection_free (coll_p);
215 return ret_value;
216 }
217
218 if (!ecma_is_value_object (arguments_list[0]))
219 {
220 return ecma_raise_type_error (ECMA_ERR_MSG ("Argument is not an Object."));
221 }
222
223 switch (builtin_routine_id)
224 {
225 case ECMA_REFLECT_OBJECT_GET_PROTOTYPE_OF:
226 {
227 return ecma_builtin_object_object_get_prototype_of (ecma_get_object_from_value (arguments_list[0]));
228 }
229 case ECMA_REFLECT_OBJECT_SET_PROTOTYPE_OF:
230 {
231 if (!ecma_is_value_object (arguments_list[1]) && !ecma_is_value_null (arguments_list[1]))
232 {
233 return ecma_raise_type_error (ECMA_ERR_MSG ("proto is neither Object nor Null."));
234 }
235
236 ecma_object_t *obj_p = ecma_get_object_from_value (arguments_list[0]);
237 ecma_value_t status;
238
239 #if ENABLED (JERRY_ES2015_BUILTIN_PROXY)
240 if (ECMA_OBJECT_IS_PROXY (obj_p))
241 {
242 status = ecma_proxy_object_set_prototype_of (obj_p, arguments_list[1]);
243 }
244 else
245 #endif /* ENABLED (JERRY_ES2015_BUILTIN_PROXY) */
246 {
247 status = ecma_op_ordinary_object_set_prototype_of (obj_p, arguments_list[1]);
248 }
249
250 return status;
251 }
252 case ECMA_REFLECT_OBJECT_APPLY:
253 {
254 if (!ecma_op_is_callable (arguments_list[0]))
255 {
256 return ecma_raise_type_error (ECMA_ERR_MSG ("Argument 'this' is not a function."));
257 }
258
259 ecma_object_t *func_obj_p = ecma_get_object_from_value (arguments_list[0]);
260 return ecma_builtin_function_prototype_object_apply (func_obj_p, arguments_list[1], arguments_list[2]);
261 }
262 case ECMA_REFLECT_OBJECT_DEFINE_PROPERTY:
263 {
264 ecma_object_t *obj_p = ecma_get_object_from_value (arguments_list[0]);
265 ecma_string_t *name_str_p = ecma_op_to_prop_name (arguments_list[1]);
266
267 if (name_str_p == NULL)
268 {
269 return ECMA_VALUE_ERROR;
270 }
271
272 ecma_property_descriptor_t prop_desc;
273 ecma_value_t conv_result = ecma_op_to_property_descriptor (arguments_list[2], &prop_desc);
274
275 if (ECMA_IS_VALUE_ERROR (conv_result))
276 {
277 ecma_deref_ecma_string (name_str_p);
278 return conv_result;
279 }
280
281 ecma_value_t result = ecma_op_object_define_own_property (obj_p,
282 name_str_p,
283 &prop_desc);
284
285 ecma_deref_ecma_string (name_str_p);
286 ecma_free_property_descriptor (&prop_desc);
287
288 if (ECMA_IS_VALUE_ERROR (result))
289 {
290 return result;
291 }
292
293 bool boolean_result = ecma_op_to_boolean (result);
294
295 return ecma_make_boolean_value (boolean_result);
296 }
297 case ECMA_REFLECT_OBJECT_GET_OWN_PROPERTY_DESCRIPTOR:
298 {
299 ecma_object_t *obj_p = ecma_get_object_from_value (arguments_list[0]);
300 ecma_string_t *name_str_p = ecma_op_to_prop_name (arguments_list[1]);
301
302 if (name_str_p == NULL)
303 {
304 return ECMA_VALUE_ERROR;
305 }
306
307 ecma_value_t ret_val = ecma_builtin_object_object_get_own_property_descriptor (obj_p, name_str_p);
308 ecma_deref_ecma_string (name_str_p);
309 return ret_val;
310 }
311 case ECMA_REFLECT_OBJECT_IS_EXTENSIBLE:
312 {
313 ecma_object_t *obj_p = ecma_get_object_from_value (arguments_list[0]);
314 return ecma_builtin_object_object_is_extensible (obj_p);
315 }
316 default:
317 {
318 JERRY_ASSERT (builtin_routine_id == ECMA_REFLECT_OBJECT_PREVENT_EXTENSIONS);
319 ecma_object_t *obj_p = ecma_get_object_from_value (arguments_list[0]);
320
321 #if ENABLED (JERRY_ES2015_BUILTIN_PROXY)
322 if (ECMA_OBJECT_IS_PROXY (obj_p))
323 {
324 return ecma_proxy_object_prevent_extensions (obj_p);
325 }
326 #endif /* !ENABLED (JERRY_ES2015_BUILTIN_PROXY) */
327
328 ecma_op_ordinary_object_prevent_extensions (obj_p);
329
330 return ECMA_VALUE_TRUE;
331 }
332 }
333 } /* ecma_builtin_reflect_dispatch_routine */
334
335 /**
336 * @}
337 * @}
338 * @}
339 */
340
341 #endif /* ENABLED (JERRY_ES2015_BUILTIN_REFLECT) */
342