1425bb815Sopenharmony_ci/* Copyright JS Foundation and other contributors, http://js.foundation
2425bb815Sopenharmony_ci *
3425bb815Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4425bb815Sopenharmony_ci * you may not use this file except in compliance with the License.
5425bb815Sopenharmony_ci * You may obtain a copy of the License at
6425bb815Sopenharmony_ci *
7425bb815Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8425bb815Sopenharmony_ci *
9425bb815Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10425bb815Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS
11425bb815Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12425bb815Sopenharmony_ci * See the License for the specific language governing permissions and
13425bb815Sopenharmony_ci * limitations under the License.
14425bb815Sopenharmony_ci */
15425bb815Sopenharmony_ci
16425bb815Sopenharmony_ci#include "ecma-array-object.h"
17425bb815Sopenharmony_ci#include "ecma-builtins.h"
18425bb815Sopenharmony_ci#include "ecma-builtin-function-prototype.h"
19425bb815Sopenharmony_ci#include "ecma-iterator-object.h"
20425bb815Sopenharmony_ci#include "ecma-builtin-helpers.h"
21425bb815Sopenharmony_ci#include "ecma-builtin-object.h"
22425bb815Sopenharmony_ci#include "ecma-exceptions.h"
23425bb815Sopenharmony_ci#include "ecma-function-object.h"
24425bb815Sopenharmony_ci#include "ecma-gc.h"
25425bb815Sopenharmony_ci#include "ecma-proxy-object.h"
26425bb815Sopenharmony_ci#include "jcontext.h"
27425bb815Sopenharmony_ci
28425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015_BUILTIN_REFLECT)
29425bb815Sopenharmony_ci
30425bb815Sopenharmony_ci#define ECMA_BUILTINS_INTERNAL
31425bb815Sopenharmony_ci#include "ecma-builtins-internal.h"
32425bb815Sopenharmony_ci
33425bb815Sopenharmony_ci/**
34425bb815Sopenharmony_ci * This object has a custom dispatch function.
35425bb815Sopenharmony_ci */
36425bb815Sopenharmony_ci#define BUILTIN_CUSTOM_DISPATCH
37425bb815Sopenharmony_ci
38425bb815Sopenharmony_ci/**
39425bb815Sopenharmony_ci * List of built-in routine identifiers.
40425bb815Sopenharmony_ci */
41425bb815Sopenharmony_cienum
42425bb815Sopenharmony_ci{
43425bb815Sopenharmony_ci  ECMA_REFLECT_OBJECT_ROUTINE_START = ECMA_BUILTIN_ID__COUNT - 1,
44425bb815Sopenharmony_ci  ECMA_REFLECT_OBJECT_GET, /* ECMA-262 v6, 26.1.6 */
45425bb815Sopenharmony_ci  ECMA_REFLECT_OBJECT_SET, /* ECMA-262 v6, 26.1.13 */
46425bb815Sopenharmony_ci  ECMA_REFLECT_OBJECT_HAS, /* ECMA-262 v6, 26.1.9 */
47425bb815Sopenharmony_ci  ECMA_REFLECT_OBJECT_DELETE_PROPERTY, /* ECMA-262 v6, 26.1.4 */
48425bb815Sopenharmony_ci  ECMA_REFLECT_OBJECT_CONSTRUCT, /* ECMA-262, 26.1.2 */
49425bb815Sopenharmony_ci  ECMA_REFLECT_OBJECT_OWN_KEYS, /* ECMA-262 v6, 26.1.11 */
50425bb815Sopenharmony_ci  ECMA_REFLECT_OBJECT_GET_PROTOTYPE_OF, /* ECMA-262 v6, 26.1.8 */
51425bb815Sopenharmony_ci  ECMA_REFLECT_OBJECT_SET_PROTOTYPE_OF, /* ECMA-262 v6, 26.1.14 */
52425bb815Sopenharmony_ci  ECMA_REFLECT_OBJECT_APPLY, /* ECMA-262 v6, 26.1.1 */
53425bb815Sopenharmony_ci  ECMA_REFLECT_OBJECT_DEFINE_PROPERTY, /* ECMA-262 v6, 26.1.3 */
54425bb815Sopenharmony_ci  ECMA_REFLECT_OBJECT_GET_OWN_PROPERTY_DESCRIPTOR, /* ECMA-262 v6, 26.1.7 */
55425bb815Sopenharmony_ci  ECMA_REFLECT_OBJECT_IS_EXTENSIBLE, /* ECMA-262 v6, 26.1.10 */
56425bb815Sopenharmony_ci  ECMA_REFLECT_OBJECT_PREVENT_EXTENSIONS, /* ECMA-262 v6, 26.1.12 */
57425bb815Sopenharmony_ci};
58425bb815Sopenharmony_ci
59425bb815Sopenharmony_ci#define BUILTIN_INC_HEADER_NAME "ecma-builtin-reflect.inc.h"
60425bb815Sopenharmony_ci#define BUILTIN_UNDERSCORED_ID reflect
61425bb815Sopenharmony_ci#include "ecma-builtin-internal-routines-template.inc.h"
62425bb815Sopenharmony_ci
63425bb815Sopenharmony_ci/** \addtogroup ecma ECMA
64425bb815Sopenharmony_ci * @{
65425bb815Sopenharmony_ci *
66425bb815Sopenharmony_ci * \addtogroup ecmabuiltins
67425bb815Sopenharmony_ci * @{
68425bb815Sopenharmony_ci *
69425bb815Sopenharmony_ci * \addtogroup object ECMA Reflect object built-in
70425bb815Sopenharmony_ci * @{
71425bb815Sopenharmony_ci */
72425bb815Sopenharmony_ci
73425bb815Sopenharmony_ci/**
74425bb815Sopenharmony_ci * Dispatcher for the built-in's routines.
75425bb815Sopenharmony_ci *
76425bb815Sopenharmony_ci * @return ecma value
77425bb815Sopenharmony_ci *         Returned value must be freed with ecma_free_value.
78425bb815Sopenharmony_ci */
79425bb815Sopenharmony_ciecma_value_t
80425bb815Sopenharmony_ciecma_builtin_reflect_dispatch_routine (uint16_t builtin_routine_id, /**< built-in wide routine
81425bb815Sopenharmony_ci                                                                     *   identifier */
82425bb815Sopenharmony_ci                                       ecma_value_t this_arg, /**< 'this' argument value */
83425bb815Sopenharmony_ci                                       const ecma_value_t arguments_list[], /**< list of arguments
84425bb815Sopenharmony_ci                                                                             *   passed to routine */
85425bb815Sopenharmony_ci                                       ecma_length_t arguments_number) /**< length of arguments' list */
86425bb815Sopenharmony_ci{
87425bb815Sopenharmony_ci  JERRY_UNUSED (this_arg);
88425bb815Sopenharmony_ci  JERRY_UNUSED (arguments_number);
89425bb815Sopenharmony_ci
90425bb815Sopenharmony_ci  if (builtin_routine_id < ECMA_REFLECT_OBJECT_CONSTRUCT)
91425bb815Sopenharmony_ci  {
92425bb815Sopenharmony_ci    /* 1. */
93425bb815Sopenharmony_ci    if (arguments_number == 0 || !ecma_is_value_object (arguments_list[0]))
94425bb815Sopenharmony_ci    {
95425bb815Sopenharmony_ci      return ecma_raise_type_error (ECMA_ERR_MSG ("Argument is not an Object."));
96425bb815Sopenharmony_ci    }
97425bb815Sopenharmony_ci
98425bb815Sopenharmony_ci    /* 2. */
99425bb815Sopenharmony_ci    ecma_string_t *name_str_p = ecma_op_to_prop_name (((arguments_number > 1) ? arguments_list[1]
100425bb815Sopenharmony_ci                                                                              : ECMA_VALUE_UNDEFINED));
101425bb815Sopenharmony_ci
102425bb815Sopenharmony_ci    /* 3. */
103425bb815Sopenharmony_ci    if (name_str_p == NULL)
104425bb815Sopenharmony_ci    {
105425bb815Sopenharmony_ci      return ECMA_VALUE_ERROR;
106425bb815Sopenharmony_ci    }
107425bb815Sopenharmony_ci
108425bb815Sopenharmony_ci    ecma_value_t ret_value;
109425bb815Sopenharmony_ci    ecma_object_t *target_p = ecma_get_object_from_value (arguments_list[0]);
110425bb815Sopenharmony_ci    switch (builtin_routine_id)
111425bb815Sopenharmony_ci    {
112425bb815Sopenharmony_ci      case ECMA_REFLECT_OBJECT_GET:
113425bb815Sopenharmony_ci      {
114425bb815Sopenharmony_ci        ecma_value_t receiver = arguments_list[0];
115425bb815Sopenharmony_ci
116425bb815Sopenharmony_ci        /* 4. */
117425bb815Sopenharmony_ci        if (arguments_number > 2)
118425bb815Sopenharmony_ci        {
119425bb815Sopenharmony_ci          receiver = arguments_list[2];
120425bb815Sopenharmony_ci        }
121425bb815Sopenharmony_ci
122425bb815Sopenharmony_ci        ret_value = ecma_op_object_get_with_receiver (target_p, name_str_p, receiver);
123425bb815Sopenharmony_ci        break;
124425bb815Sopenharmony_ci      }
125425bb815Sopenharmony_ci
126425bb815Sopenharmony_ci      case ECMA_REFLECT_OBJECT_HAS:
127425bb815Sopenharmony_ci      {
128425bb815Sopenharmony_ci        ret_value = ecma_op_object_has_property (target_p, name_str_p);
129425bb815Sopenharmony_ci        break;
130425bb815Sopenharmony_ci      }
131425bb815Sopenharmony_ci
132425bb815Sopenharmony_ci      case ECMA_REFLECT_OBJECT_DELETE_PROPERTY:
133425bb815Sopenharmony_ci      {
134425bb815Sopenharmony_ci        ret_value = ecma_op_object_delete (target_p, name_str_p, false);
135425bb815Sopenharmony_ci        break;
136425bb815Sopenharmony_ci      }
137425bb815Sopenharmony_ci
138425bb815Sopenharmony_ci      default:
139425bb815Sopenharmony_ci      {
140425bb815Sopenharmony_ci        JERRY_ASSERT (builtin_routine_id == ECMA_REFLECT_OBJECT_SET);
141425bb815Sopenharmony_ci
142425bb815Sopenharmony_ci        ecma_value_t receiver = arguments_list[0];
143425bb815Sopenharmony_ci
144425bb815Sopenharmony_ci        if (arguments_number > 3)
145425bb815Sopenharmony_ci        {
146425bb815Sopenharmony_ci          receiver = arguments_list[3];
147425bb815Sopenharmony_ci        }
148425bb815Sopenharmony_ci
149425bb815Sopenharmony_ci        ret_value = ecma_op_object_put_with_receiver (target_p, name_str_p, arguments_list[2], receiver, false);
150425bb815Sopenharmony_ci        break;
151425bb815Sopenharmony_ci      }
152425bb815Sopenharmony_ci    }
153425bb815Sopenharmony_ci
154425bb815Sopenharmony_ci    ecma_deref_ecma_string (name_str_p);
155425bb815Sopenharmony_ci    return ret_value;
156425bb815Sopenharmony_ci  }
157425bb815Sopenharmony_ci
158425bb815Sopenharmony_ci  if (builtin_routine_id == ECMA_REFLECT_OBJECT_OWN_KEYS)
159425bb815Sopenharmony_ci  {
160425bb815Sopenharmony_ci    /* 1. */
161425bb815Sopenharmony_ci    if (arguments_number == 0 || !ecma_is_value_object (arguments_list[0]))
162425bb815Sopenharmony_ci    {
163425bb815Sopenharmony_ci      return ecma_raise_type_error (ECMA_ERR_MSG ("Argument is not an Object."));
164425bb815Sopenharmony_ci    }
165425bb815Sopenharmony_ci
166425bb815Sopenharmony_ci    ecma_object_t *target_p = ecma_get_object_from_value (arguments_list[0]);
167425bb815Sopenharmony_ci
168425bb815Sopenharmony_ci    /* 2. 3. */
169425bb815Sopenharmony_ci    return ecma_builtin_helper_object_get_properties (target_p, ECMA_LIST_SYMBOLS);
170425bb815Sopenharmony_ci  }
171425bb815Sopenharmony_ci
172425bb815Sopenharmony_ci  if (builtin_routine_id == ECMA_REFLECT_OBJECT_CONSTRUCT)
173425bb815Sopenharmony_ci  {
174425bb815Sopenharmony_ci    /* 1. */
175425bb815Sopenharmony_ci    if (arguments_number < 1 || !ecma_is_constructor (arguments_list[0]))
176425bb815Sopenharmony_ci    {
177425bb815Sopenharmony_ci      return ecma_raise_type_error (ECMA_ERR_MSG ("Target is not a constructor"));
178425bb815Sopenharmony_ci    }
179425bb815Sopenharmony_ci
180425bb815Sopenharmony_ci    ecma_object_t *target_p = ecma_get_object_from_value (arguments_list[0]);
181425bb815Sopenharmony_ci
182425bb815Sopenharmony_ci    /* 2. */
183425bb815Sopenharmony_ci    ecma_object_t *new_target_p = target_p;
184425bb815Sopenharmony_ci
185425bb815Sopenharmony_ci    if (arguments_number > 2)
186425bb815Sopenharmony_ci    {
187425bb815Sopenharmony_ci      /* 3. */
188425bb815Sopenharmony_ci      if (!ecma_is_constructor (arguments_list[2]))
189425bb815Sopenharmony_ci      {
190425bb815Sopenharmony_ci        return ecma_raise_type_error (ECMA_ERR_MSG ("Target is not a constructor"));
191425bb815Sopenharmony_ci      }
192425bb815Sopenharmony_ci
193425bb815Sopenharmony_ci      new_target_p = ecma_get_object_from_value (arguments_list[2]);
194425bb815Sopenharmony_ci    }
195425bb815Sopenharmony_ci
196425bb815Sopenharmony_ci    /* 4. */
197425bb815Sopenharmony_ci    if (arguments_number < 2)
198425bb815Sopenharmony_ci    {
199425bb815Sopenharmony_ci      return ecma_raise_type_error (ECMA_ERR_MSG ("Reflect.construct requires the second argument be an object"));
200425bb815Sopenharmony_ci    }
201425bb815Sopenharmony_ci
202425bb815Sopenharmony_ci    ecma_collection_t *coll_p = ecma_op_create_list_from_array_like (arguments_list[1], false);
203425bb815Sopenharmony_ci
204425bb815Sopenharmony_ci    if (coll_p == NULL)
205425bb815Sopenharmony_ci    {
206425bb815Sopenharmony_ci      return ECMA_VALUE_ERROR;
207425bb815Sopenharmony_ci    }
208425bb815Sopenharmony_ci
209425bb815Sopenharmony_ci    ecma_value_t ret_value = ecma_op_function_construct (target_p,
210425bb815Sopenharmony_ci                                                         new_target_p,
211425bb815Sopenharmony_ci                                                         coll_p->buffer_p,
212425bb815Sopenharmony_ci                                                         coll_p->item_count);
213425bb815Sopenharmony_ci
214425bb815Sopenharmony_ci    ecma_collection_free (coll_p);
215425bb815Sopenharmony_ci    return ret_value;
216425bb815Sopenharmony_ci  }
217425bb815Sopenharmony_ci
218425bb815Sopenharmony_ci  if (!ecma_is_value_object (arguments_list[0]))
219425bb815Sopenharmony_ci  {
220425bb815Sopenharmony_ci    return ecma_raise_type_error (ECMA_ERR_MSG ("Argument is not an Object."));
221425bb815Sopenharmony_ci  }
222425bb815Sopenharmony_ci
223425bb815Sopenharmony_ci  switch (builtin_routine_id)
224425bb815Sopenharmony_ci  {
225425bb815Sopenharmony_ci    case ECMA_REFLECT_OBJECT_GET_PROTOTYPE_OF:
226425bb815Sopenharmony_ci    {
227425bb815Sopenharmony_ci      return ecma_builtin_object_object_get_prototype_of (ecma_get_object_from_value (arguments_list[0]));
228425bb815Sopenharmony_ci    }
229425bb815Sopenharmony_ci    case ECMA_REFLECT_OBJECT_SET_PROTOTYPE_OF:
230425bb815Sopenharmony_ci    {
231425bb815Sopenharmony_ci      if (!ecma_is_value_object (arguments_list[1]) && !ecma_is_value_null (arguments_list[1]))
232425bb815Sopenharmony_ci      {
233425bb815Sopenharmony_ci        return ecma_raise_type_error (ECMA_ERR_MSG ("proto is neither Object nor Null."));
234425bb815Sopenharmony_ci      }
235425bb815Sopenharmony_ci
236425bb815Sopenharmony_ci      ecma_object_t *obj_p = ecma_get_object_from_value (arguments_list[0]);
237425bb815Sopenharmony_ci      ecma_value_t status;
238425bb815Sopenharmony_ci
239425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015_BUILTIN_PROXY)
240425bb815Sopenharmony_ci      if (ECMA_OBJECT_IS_PROXY (obj_p))
241425bb815Sopenharmony_ci      {
242425bb815Sopenharmony_ci        status = ecma_proxy_object_set_prototype_of (obj_p, arguments_list[1]);
243425bb815Sopenharmony_ci      }
244425bb815Sopenharmony_ci      else
245425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015_BUILTIN_PROXY) */
246425bb815Sopenharmony_ci      {
247425bb815Sopenharmony_ci        status = ecma_op_ordinary_object_set_prototype_of (obj_p, arguments_list[1]);
248425bb815Sopenharmony_ci      }
249425bb815Sopenharmony_ci
250425bb815Sopenharmony_ci      return status;
251425bb815Sopenharmony_ci    }
252425bb815Sopenharmony_ci    case ECMA_REFLECT_OBJECT_APPLY:
253425bb815Sopenharmony_ci    {
254425bb815Sopenharmony_ci      if (!ecma_op_is_callable (arguments_list[0]))
255425bb815Sopenharmony_ci      {
256425bb815Sopenharmony_ci        return ecma_raise_type_error (ECMA_ERR_MSG ("Argument 'this' is not a function."));
257425bb815Sopenharmony_ci      }
258425bb815Sopenharmony_ci
259425bb815Sopenharmony_ci      ecma_object_t *func_obj_p = ecma_get_object_from_value (arguments_list[0]);
260425bb815Sopenharmony_ci      return ecma_builtin_function_prototype_object_apply (func_obj_p, arguments_list[1], arguments_list[2]);
261425bb815Sopenharmony_ci    }
262425bb815Sopenharmony_ci    case ECMA_REFLECT_OBJECT_DEFINE_PROPERTY:
263425bb815Sopenharmony_ci    {
264425bb815Sopenharmony_ci      ecma_object_t *obj_p = ecma_get_object_from_value (arguments_list[0]);
265425bb815Sopenharmony_ci      ecma_string_t *name_str_p = ecma_op_to_prop_name (arguments_list[1]);
266425bb815Sopenharmony_ci
267425bb815Sopenharmony_ci      if (name_str_p == NULL)
268425bb815Sopenharmony_ci      {
269425bb815Sopenharmony_ci        return ECMA_VALUE_ERROR;
270425bb815Sopenharmony_ci      }
271425bb815Sopenharmony_ci
272425bb815Sopenharmony_ci      ecma_property_descriptor_t prop_desc;
273425bb815Sopenharmony_ci      ecma_value_t conv_result = ecma_op_to_property_descriptor (arguments_list[2], &prop_desc);
274425bb815Sopenharmony_ci
275425bb815Sopenharmony_ci      if (ECMA_IS_VALUE_ERROR (conv_result))
276425bb815Sopenharmony_ci      {
277425bb815Sopenharmony_ci        ecma_deref_ecma_string (name_str_p);
278425bb815Sopenharmony_ci        return conv_result;
279425bb815Sopenharmony_ci      }
280425bb815Sopenharmony_ci
281425bb815Sopenharmony_ci      ecma_value_t result = ecma_op_object_define_own_property (obj_p,
282425bb815Sopenharmony_ci                                                                name_str_p,
283425bb815Sopenharmony_ci                                                                &prop_desc);
284425bb815Sopenharmony_ci
285425bb815Sopenharmony_ci      ecma_deref_ecma_string (name_str_p);
286425bb815Sopenharmony_ci      ecma_free_property_descriptor (&prop_desc);
287425bb815Sopenharmony_ci
288425bb815Sopenharmony_ci      if (ECMA_IS_VALUE_ERROR (result))
289425bb815Sopenharmony_ci      {
290425bb815Sopenharmony_ci        return result;
291425bb815Sopenharmony_ci      }
292425bb815Sopenharmony_ci
293425bb815Sopenharmony_ci      bool boolean_result = ecma_op_to_boolean (result);
294425bb815Sopenharmony_ci
295425bb815Sopenharmony_ci      return ecma_make_boolean_value (boolean_result);
296425bb815Sopenharmony_ci    }
297425bb815Sopenharmony_ci    case ECMA_REFLECT_OBJECT_GET_OWN_PROPERTY_DESCRIPTOR:
298425bb815Sopenharmony_ci    {
299425bb815Sopenharmony_ci      ecma_object_t *obj_p = ecma_get_object_from_value (arguments_list[0]);
300425bb815Sopenharmony_ci      ecma_string_t *name_str_p = ecma_op_to_prop_name (arguments_list[1]);
301425bb815Sopenharmony_ci
302425bb815Sopenharmony_ci      if (name_str_p == NULL)
303425bb815Sopenharmony_ci      {
304425bb815Sopenharmony_ci        return ECMA_VALUE_ERROR;
305425bb815Sopenharmony_ci      }
306425bb815Sopenharmony_ci
307425bb815Sopenharmony_ci      ecma_value_t ret_val = ecma_builtin_object_object_get_own_property_descriptor (obj_p, name_str_p);
308425bb815Sopenharmony_ci      ecma_deref_ecma_string (name_str_p);
309425bb815Sopenharmony_ci      return ret_val;
310425bb815Sopenharmony_ci    }
311425bb815Sopenharmony_ci    case ECMA_REFLECT_OBJECT_IS_EXTENSIBLE:
312425bb815Sopenharmony_ci    {
313425bb815Sopenharmony_ci      ecma_object_t *obj_p = ecma_get_object_from_value (arguments_list[0]);
314425bb815Sopenharmony_ci      return ecma_builtin_object_object_is_extensible (obj_p);
315425bb815Sopenharmony_ci    }
316425bb815Sopenharmony_ci    default:
317425bb815Sopenharmony_ci    {
318425bb815Sopenharmony_ci      JERRY_ASSERT (builtin_routine_id == ECMA_REFLECT_OBJECT_PREVENT_EXTENSIONS);
319425bb815Sopenharmony_ci      ecma_object_t *obj_p = ecma_get_object_from_value (arguments_list[0]);
320425bb815Sopenharmony_ci
321425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015_BUILTIN_PROXY)
322425bb815Sopenharmony_ci      if (ECMA_OBJECT_IS_PROXY (obj_p))
323425bb815Sopenharmony_ci      {
324425bb815Sopenharmony_ci        return ecma_proxy_object_prevent_extensions (obj_p);
325425bb815Sopenharmony_ci      }
326425bb815Sopenharmony_ci#endif /* !ENABLED (JERRY_ES2015_BUILTIN_PROXY) */
327425bb815Sopenharmony_ci
328425bb815Sopenharmony_ci      ecma_op_ordinary_object_prevent_extensions (obj_p);
329425bb815Sopenharmony_ci
330425bb815Sopenharmony_ci      return ECMA_VALUE_TRUE;
331425bb815Sopenharmony_ci    }
332425bb815Sopenharmony_ci  }
333425bb815Sopenharmony_ci} /* ecma_builtin_reflect_dispatch_routine */
334425bb815Sopenharmony_ci
335425bb815Sopenharmony_ci/**
336425bb815Sopenharmony_ci * @}
337425bb815Sopenharmony_ci * @}
338425bb815Sopenharmony_ci * @}
339425bb815Sopenharmony_ci */
340425bb815Sopenharmony_ci
341425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015_BUILTIN_REFLECT) */
342