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 */ 41enum 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 */ 79ecma_value_t 80ecma_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