• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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