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-alloc.h" 17#include "ecma-builtins.h" 18#include "ecma-exceptions.h" 19#include "ecma-gc.h" 20#include "ecma-globals.h" 21#include "ecma-helpers.h" 22#include "ecma-objects.h" 23#include "jcontext.h" 24#include "jrt-bit-fields.h" 25 26#define ECMA_BUILTINS_INTERNAL 27#include "ecma-builtins-internal.h" 28 29/** \addtogroup ecma ECMA 30 * @{ 31 * 32 * \addtogroup ecmabuiltins 33 * @{ 34 */ 35 36static void ecma_instantiate_builtin (ecma_builtin_id_t id); 37 38/** 39 * Helper definition for ecma_builtin_property_list_references. 40 */ 41typedef const ecma_builtin_property_descriptor_t *ecma_builtin_property_list_reference_t; 42 43/** 44 * Definition of built-in dispatch routine function pointer. 45 */ 46typedef ecma_value_t (*ecma_builtin_dispatch_routine_t) (uint16_t builtin_routine_id, 47 ecma_value_t this_arg, 48 const ecma_value_t arguments_list[], 49 ecma_length_t arguments_number); 50/** 51 * Definition of built-in dispatch call function pointer. 52 */ 53typedef ecma_value_t (*ecma_builtin_dispatch_call_t) (const ecma_value_t arguments_list[], 54 ecma_length_t arguments_number); 55/** 56 * Definition of a builtin descriptor which contains the builtin object's: 57 * - prototype objects's id (13-bits) 58 * - type (3-bits) 59 * 60 * Layout: 61 * 62 * |----------------------|---------------| 63 * prototype_id(13) obj_type(3) 64 */ 65typedef uint16_t ecma_builtin_descriptor_t; 66 67/** 68 * Bitshift index for get the prototype object's id from a builtin descriptor 69 */ 70#define ECMA_BUILTIN_PROTOTYPE_ID_SHIFT 3 71 72/** 73 * Bitmask for get the object's type from a builtin descriptor 74 */ 75#define ECMA_BUILTIN_OBJECT_TYPE_MASK ((1 << ECMA_BUILTIN_PROTOTYPE_ID_SHIFT) - 1) 76 77/** 78 * Create a builtin descriptor value 79 */ 80#define ECMA_MAKE_BUILTIN_DESCRIPTOR(type, proto_id) \ 81 (((proto_id) << ECMA_BUILTIN_PROTOTYPE_ID_SHIFT) | (type)) 82 83/** 84 * List of the built-in descriptors. 85 */ 86static const ecma_builtin_descriptor_t ecma_builtin_descriptors[] = 87{ 88/** @cond doxygen_suppress */ 89#define BUILTIN(a, b, c, d, e) 90#define BUILTIN_ROUTINE(builtin_id, \ 91 object_type, \ 92 object_prototype_builtin_id, \ 93 is_extensible, \ 94 lowercase_name) \ 95 ECMA_MAKE_BUILTIN_DESCRIPTOR (object_type, object_prototype_builtin_id), 96#include "ecma-builtins.inc.h" 97#undef BUILTIN 98#undef BUILTIN_ROUTINE 99#define BUILTIN_ROUTINE(a, b, c, d, e) 100#define BUILTIN(builtin_id, \ 101 object_type, \ 102 object_prototype_builtin_id, \ 103 is_extensible, \ 104 lowercase_name) \ 105 ECMA_MAKE_BUILTIN_DESCRIPTOR (object_type, object_prototype_builtin_id), 106#include "ecma-builtins.inc.h" 107#undef BUILTIN 108#undef BUILTIN_ROUTINE 109/** @endcond */ 110}; 111 112#ifndef JERRY_NDEBUG 113/** @cond doxygen_suppress */ 114enum 115{ 116 ECMA_BUILTIN_EXTENSIBLE_CHECK = 117#define BUILTIN(a, b, c, d, e) 118#define BUILTIN_ROUTINE(builtin_id, \ 119 object_type, \ 120 object_prototype_builtin_id, \ 121 is_extensible, \ 122 lowercase_name) \ 123 (is_extensible != 0 || builtin_id == ECMA_BUILTIN_ID_TYPE_ERROR_THROWER) && 124#include "ecma-builtins.inc.h" 125#undef BUILTIN 126#undef BUILTIN_ROUTINE 127#define BUILTIN_ROUTINE(a, b, c, d, e) 128#define BUILTIN(builtin_id, \ 129 object_type, \ 130 object_prototype_builtin_id, \ 131 is_extensible, \ 132 lowercase_name) \ 133 (is_extensible != 0 || builtin_id == ECMA_BUILTIN_ID_TYPE_ERROR_THROWER) && 134#include "ecma-builtins.inc.h" 135#undef BUILTIN 136#undef BUILTIN_ROUTINE 137 true 138}; 139/** @endcond */ 140 141/** 142 * All the builtin object must be extensible except the ThrowTypeError object. 143 */ 144JERRY_STATIC_ASSERT (ECMA_BUILTIN_EXTENSIBLE_CHECK == true, 145 ecma_builtin_must_be_extensible_except_the_builtin_thorw_type_error_object); 146#endif /* !JERRY_NDEBUG */ 147 148/** 149 * List of the built-in routines. 150 */ 151static const ecma_builtin_dispatch_routine_t ecma_builtin_routines[] = 152{ 153/** @cond doxygen_suppress */ 154#define BUILTIN(a, b, c, d, e) 155#define BUILTIN_ROUTINE(builtin_id, \ 156 object_type, \ 157 object_prototype_builtin_id, \ 158 is_extensible, \ 159 lowercase_name) \ 160 ecma_builtin_ ## lowercase_name ## _dispatch_routine, 161#include "ecma-builtins.inc.h" 162#undef BUILTIN 163#undef BUILTIN_ROUTINE 164#define BUILTIN_ROUTINE(a, b, c, d, e) 165#define BUILTIN(builtin_id, \ 166 object_type, \ 167 object_prototype_builtin_id, \ 168 is_extensible, \ 169 lowercase_name) \ 170 ecma_builtin_ ## lowercase_name ## _dispatch_routine, 171#include "ecma-builtins.inc.h" 172#undef BUILTIN 173#undef BUILTIN_ROUTINE 174/** @endcond */ 175}; 176 177/** 178 * List of the built-in call functions. 179 */ 180static const ecma_builtin_dispatch_call_t ecma_builtin_call_functions[] = 181{ 182/** @cond doxygen_suppress */ 183#define BUILTIN(a, b, c, d, e) 184#define BUILTIN_ROUTINE(builtin_id, \ 185 object_type, \ 186 object_prototype_builtin_id, \ 187 is_extensible, \ 188 lowercase_name) \ 189 ecma_builtin_ ## lowercase_name ## _dispatch_call, 190#include "ecma-builtins.inc.h" 191#undef BUILTIN_ROUTINE 192#undef BUILTIN 193/** @endcond */ 194}; 195 196/** 197 * List of the built-in construct functions. 198 */ 199static const ecma_builtin_dispatch_call_t ecma_builtin_construct_functions[] = 200{ 201/** @cond doxygen_suppress */ 202#define BUILTIN(a, b, c, d, e) 203#define BUILTIN_ROUTINE(builtin_id, \ 204 object_type, \ 205 object_prototype_builtin_id, \ 206 is_extensible, \ 207 lowercase_name) \ 208 ecma_builtin_ ## lowercase_name ## _dispatch_construct, 209#include "ecma-builtins.inc.h" 210#undef BUILTIN_ROUTINE 211#undef BUILTIN 212/** @endcond */ 213}; 214 215/** 216 * Property descriptor lists for all built-ins. 217 */ 218static const ecma_builtin_property_list_reference_t ecma_builtin_property_list_references[] = 219{ 220/** @cond doxygen_suppress */ 221#define BUILTIN(a, b, c, d, e) 222#define BUILTIN_ROUTINE(builtin_id, \ 223 object_type, \ 224 object_prototype_builtin_id, \ 225 is_extensible, \ 226 lowercase_name) \ 227 ecma_builtin_ ## lowercase_name ## _property_descriptor_list, 228#include "ecma-builtins.inc.h" 229#undef BUILTIN 230#undef BUILTIN_ROUTINE 231#define BUILTIN_ROUTINE(a, b, c, d, e) 232#define BUILTIN(builtin_id, \ 233 object_type, \ 234 object_prototype_builtin_id, \ 235 is_extensible, \ 236 lowercase_name) \ 237 ecma_builtin_ ## lowercase_name ## _property_descriptor_list, 238#include "ecma-builtins.inc.h" 239#undef BUILTIN_ROUTINE 240#undef BUILTIN 241/** @endcond */ 242}; 243 244/** 245 * Get the number of properties of a built-in object. 246 * 247 * @return the number of properties 248 */ 249static size_t 250ecma_builtin_get_property_count (ecma_builtin_id_t builtin_id) /**< built-in ID */ 251{ 252 JERRY_ASSERT (builtin_id < ECMA_BUILTIN_ID__COUNT); 253 const ecma_builtin_property_descriptor_t *property_list_p = ecma_builtin_property_list_references[builtin_id]; 254 255 const ecma_builtin_property_descriptor_t *curr_property_p = property_list_p; 256 257 while (curr_property_p->magic_string_id != LIT_MAGIC_STRING__COUNT) 258 { 259 curr_property_p++; 260 } 261 262 return (size_t) (curr_property_p - property_list_p); 263} /* ecma_builtin_get_property_count */ 264 265/** 266 * Check if passed object is the instance of specified built-in. 267 * 268 * @return true - if the object is instance of the specified built-in 269 * false - otherwise 270 */ 271bool 272ecma_builtin_is (ecma_object_t *obj_p, /**< pointer to an object */ 273 ecma_builtin_id_t builtin_id) /**< id of built-in to check on */ 274{ 275 JERRY_ASSERT (obj_p != NULL && !ecma_is_lexical_environment (obj_p)); 276 JERRY_ASSERT (builtin_id < ECMA_BUILTIN_ID__COUNT); 277 278 /* If a built-in object is not instantiated, its value is NULL, 279 hence it cannot be equal to a valid object. */ 280 jmem_cpointer_t builtin_cp = JERRY_CONTEXT (ecma_builtin_objects)[builtin_id]; 281 282 return (builtin_cp != JMEM_CP_NULL && (obj_p == ECMA_GET_NON_NULL_POINTER (ecma_object_t, builtin_cp))); 283} /* ecma_builtin_is */ 284 285/** 286 * Get reference to specified built-in object 287 * 288 * Note: 289 * Does not increase the reference counter. 290 * 291 * @return pointer to the object's instance 292 */ 293ecma_object_t * 294ecma_builtin_get (ecma_builtin_id_t builtin_id) /**< id of built-in to check on */ 295{ 296 JERRY_ASSERT (builtin_id < ECMA_BUILTIN_ID__COUNT); 297 298 if (JERRY_UNLIKELY (JERRY_CONTEXT (ecma_builtin_objects)[builtin_id] == JMEM_CP_NULL)) 299 { 300 ecma_instantiate_builtin (builtin_id); 301 } 302 303 return ECMA_GET_NON_NULL_POINTER (ecma_object_t, JERRY_CONTEXT (ecma_builtin_objects)[builtin_id]); 304} /* ecma_builtin_get */ 305 306/** 307 * Get reference to the global object 308 * 309 * Note: 310 * Does not increase the reference counter. 311 * 312 * @return pointer to the global object 313 */ 314inline ecma_object_t * JERRY_ATTR_ALWAYS_INLINE 315ecma_builtin_get_global (void) 316{ 317 JERRY_ASSERT (JERRY_CONTEXT (ecma_builtin_objects)[ECMA_BUILTIN_ID_GLOBAL] != JMEM_CP_NULL); 318 319 return ECMA_GET_NON_NULL_POINTER (ecma_object_t, JERRY_CONTEXT (ecma_builtin_objects)[ECMA_BUILTIN_ID_GLOBAL]); 320} /* ecma_builtin_get_global */ 321 322/** 323 * Checks whether the given function is a built-in routine 324 * 325 * @return true - if the function object is a built-in routine 326 * false - otherwise 327 */ 328inline bool JERRY_ATTR_ALWAYS_INLINE 329ecma_builtin_function_is_routine (ecma_object_t *func_obj_p) /**< function object */ 330{ 331 JERRY_ASSERT (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_FUNCTION); 332 JERRY_ASSERT (ecma_get_object_is_builtin (func_obj_p)); 333 334 ecma_extended_object_t *ext_func_obj_p = (ecma_extended_object_t *) func_obj_p; 335 return (ext_func_obj_p->u.built_in.routine_id >= ECMA_BUILTIN_ID__COUNT); 336} /* ecma_builtin_function_is_routine */ 337 338/** 339 * Instantiate specified ECMA built-in object 340 */ 341static void 342ecma_instantiate_builtin (ecma_builtin_id_t obj_builtin_id) /**< built-in id */ 343{ 344 JERRY_ASSERT (obj_builtin_id < ECMA_BUILTIN_ID__COUNT); 345 JERRY_ASSERT (JERRY_CONTEXT (ecma_builtin_objects)[obj_builtin_id] == JMEM_CP_NULL); 346 347 ecma_builtin_descriptor_t builtin_desc = ecma_builtin_descriptors[obj_builtin_id]; 348 ecma_builtin_id_t object_prototype_builtin_id = (ecma_builtin_id_t) (builtin_desc >> ECMA_BUILTIN_PROTOTYPE_ID_SHIFT); 349 350 ecma_object_t *prototype_obj_p; 351 352 /* cppcheck-suppress arrayIndexOutOfBoundsCond */ 353 if (JERRY_UNLIKELY (object_prototype_builtin_id == ECMA_BUILTIN_ID__COUNT)) 354 { 355 prototype_obj_p = NULL; 356 } 357 else 358 { 359 if (JERRY_CONTEXT (ecma_builtin_objects)[object_prototype_builtin_id] == JMEM_CP_NULL) 360 { 361 ecma_instantiate_builtin (object_prototype_builtin_id); 362 } 363 prototype_obj_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, 364 JERRY_CONTEXT (ecma_builtin_objects)[object_prototype_builtin_id]); 365 JERRY_ASSERT (prototype_obj_p != NULL); 366 } 367 368 ecma_object_type_t obj_type = (ecma_object_type_t) (builtin_desc & ECMA_BUILTIN_OBJECT_TYPE_MASK); 369 370 bool is_extended_built_in = (obj_type == ECMA_OBJECT_TYPE_CLASS 371 || obj_type == ECMA_OBJECT_TYPE_ARRAY); 372 373 size_t ext_object_size = (is_extended_built_in ? sizeof (ecma_extended_built_in_object_t) 374 : sizeof (ecma_extended_object_t)); 375 376 size_t property_count = ecma_builtin_get_property_count (obj_builtin_id); 377 378 if (property_count > 32) 379 { 380 /* Only 64 extra properties supported at the moment. 381 * This can be extended to 256 later. */ 382 JERRY_ASSERT (property_count <= (32 + 64)); 383 384 ext_object_size += sizeof (uint32_t) * 2; 385 } 386 387 ecma_object_t *obj_p = ecma_create_object (prototype_obj_p, ext_object_size, obj_type); 388 389 if (JERRY_UNLIKELY (obj_builtin_id == ECMA_BUILTIN_ID_TYPE_ERROR_THROWER)) 390 { 391 ecma_op_ordinary_object_prevent_extensions (obj_p); 392 } 393 else 394 { 395 ecma_op_ordinary_object_set_extensible (obj_p); 396 } 397 398 /* 399 * [[Class]] property of built-in object is not stored explicitly. 400 * 401 * See also: ecma_object_get_class_name 402 */ 403 404 ecma_set_object_is_builtin (obj_p); 405 ecma_built_in_props_t *built_in_props_p; 406 407 if (is_extended_built_in) 408 { 409 built_in_props_p = &((ecma_extended_built_in_object_t *) obj_p)->built_in; 410 } 411 else 412 { 413 built_in_props_p = &((ecma_extended_object_t *) obj_p)->u.built_in; 414 } 415 416 built_in_props_p->id = (uint8_t) obj_builtin_id; 417 built_in_props_p->routine_id = (uint16_t) obj_builtin_id; 418 built_in_props_p->u.instantiated_bitset[0] = 0; 419 420 if (property_count > 32) 421 { 422 built_in_props_p->length_and_bitset_size = 1 << ECMA_BUILT_IN_BITSET_SHIFT; 423 424 uint32_t *instantiated_bitset_p = built_in_props_p->u.instantiated_bitset; 425 instantiated_bitset_p[1] = 0; 426 instantiated_bitset_p[2] = 0; 427 } 428 else 429 { 430 built_in_props_p->length_and_bitset_size = 0; 431 } 432 433 /** Initializing [[PrimitiveValue]] properties of built-in prototype objects */ 434 switch (obj_builtin_id) 435 { 436#if ENABLED (JERRY_BUILTIN_ARRAY) 437 case ECMA_BUILTIN_ID_ARRAY_PROTOTYPE: 438 { 439 JERRY_ASSERT (obj_type == ECMA_OBJECT_TYPE_ARRAY); 440 ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) obj_p; 441 442 ext_object_p->u.array.length = 0; 443 ext_object_p->u.array.u.length_prop = ECMA_PROPERTY_FLAG_WRITABLE | ECMA_PROPERTY_TYPE_VIRTUAL; 444 break; 445 } 446#endif /* ENABLED (JERRY_BUILTIN_ARRAY) */ 447 448#if !ENABLED (JERRY_ES2015) 449#if ENABLED (JERRY_BUILTIN_STRING) 450 case ECMA_BUILTIN_ID_STRING_PROTOTYPE: 451 { 452 JERRY_ASSERT (obj_type == ECMA_OBJECT_TYPE_CLASS); 453 ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) obj_p; 454 455 ext_object_p->u.class_prop.class_id = LIT_MAGIC_STRING_STRING_UL; 456 ext_object_p->u.class_prop.u.value = ecma_make_magic_string_value (LIT_MAGIC_STRING__EMPTY); 457 break; 458 } 459#endif /* ENABLED (JERRY_BUILTIN_STRING) */ 460 461#if ENABLED (JERRY_BUILTIN_NUMBER) 462 case ECMA_BUILTIN_ID_NUMBER_PROTOTYPE: 463 { 464 JERRY_ASSERT (obj_type == ECMA_OBJECT_TYPE_CLASS); 465 ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) obj_p; 466 467 ext_object_p->u.class_prop.class_id = LIT_MAGIC_STRING_NUMBER_UL; 468 ext_object_p->u.class_prop.u.value = ecma_make_integer_value (0); 469 break; 470 } 471#endif /* ENABLED (JERRY_BUILTIN_NUMBER) */ 472 473#if ENABLED (JERRY_BUILTIN_BOOLEAN) 474 case ECMA_BUILTIN_ID_BOOLEAN_PROTOTYPE: 475 { 476 JERRY_ASSERT (obj_type == ECMA_OBJECT_TYPE_CLASS); 477 ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) obj_p; 478 479 ext_object_p->u.class_prop.class_id = LIT_MAGIC_STRING_BOOLEAN_UL; 480 ext_object_p->u.class_prop.u.value = ECMA_VALUE_FALSE; 481 break; 482 } 483#endif /* ENABLED (JERRY_BUILTIN_BOOLEAN) */ 484 485#if ENABLED (JERRY_BUILTIN_DATE) 486 case ECMA_BUILTIN_ID_DATE_PROTOTYPE: 487 { 488 JERRY_ASSERT (obj_type == ECMA_OBJECT_TYPE_CLASS); 489 ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) obj_p; 490 491 ext_object_p->u.class_prop.class_id = LIT_MAGIC_STRING_DATE_UL; 492 493 ecma_number_t *prim_prop_num_value_p = ecma_alloc_number (); 494 *prim_prop_num_value_p = ecma_number_make_nan (); 495 ECMA_SET_INTERNAL_VALUE_POINTER (ext_object_p->u.class_prop.u.value, prim_prop_num_value_p); 496 break; 497 } 498#endif /* ENABLED (JERRY_BUILTIN_DATE) */ 499 500#if ENABLED (JERRY_BUILTIN_REGEXP) 501 case ECMA_BUILTIN_ID_REGEXP_PROTOTYPE: 502 { 503 JERRY_ASSERT (obj_type == ECMA_OBJECT_TYPE_CLASS); 504 ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) obj_p; 505 506 ext_object_p->u.class_prop.class_id = LIT_MAGIC_STRING_REGEXP_UL; 507 508 re_compiled_code_t *bc_p = re_compile_bytecode (ecma_get_magic_string (LIT_MAGIC_STRING_EMPTY_NON_CAPTURE_GROUP), 509 RE_FLAG_EMPTY); 510 511 JERRY_ASSERT (bc_p != NULL); 512 513 ECMA_SET_INTERNAL_VALUE_POINTER (ext_object_p->u.class_prop.u.value, bc_p); 514 515 break; 516 } 517#endif /* ENABLED (JERRY_BUILTIN_REGEXP) */ 518#endif /* !ENABLED (JERRY_ES2015) */ 519 default: 520 { 521 JERRY_ASSERT (obj_type != ECMA_OBJECT_TYPE_CLASS); 522 break; 523 } 524 } 525 526 ECMA_SET_NON_NULL_POINTER (JERRY_CONTEXT (ecma_builtin_objects)[obj_builtin_id], obj_p); 527} /* ecma_instantiate_builtin */ 528 529/** 530 * Finalize ECMA built-in objects 531 */ 532void 533ecma_finalize_builtins (void) 534{ 535 for (ecma_builtin_id_t id = (ecma_builtin_id_t) 0; 536 id < ECMA_BUILTIN_ID__COUNT; 537 id = (ecma_builtin_id_t) (id + 1)) 538 { 539 if (JERRY_CONTEXT (ecma_builtin_objects)[id] != JMEM_CP_NULL) 540 { 541 ecma_object_t *obj_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, JERRY_CONTEXT (ecma_builtin_objects)[id]); 542 ecma_deref_object (obj_p); 543 544#if ENABLED (JERRY_ES2015) 545 /* Note: In ES2015 a function object may contain tagged template literal collection. Whenever 546 this function is assigned to a builtin function or function routine during the GC it may cause unresolvable 547 circle since one part of the circle is a weak reference (marked by GC) and the other part is hard reference 548 (reference count). In this case when the function which contains the tagged template literal collection 549 is getting GC marked the arrays in the collection are still holding weak references to properties/prototypes 550 which prevents these objects from getting freed. Releasing the property list and the prototype reference 551 manually eliminates the existence of the unresolvable circle described above. */ 552 ecma_gc_free_properties (obj_p); 553 obj_p->u1.property_list_cp = JMEM_CP_NULL; 554 obj_p->u2.prototype_cp = JMEM_CP_NULL; 555#endif /* ENABLED (JERRY_ES2015) */ 556 557 JERRY_CONTEXT (ecma_builtin_objects)[id] = JMEM_CP_NULL; 558 } 559 } 560} /* ecma_finalize_builtins */ 561 562/** 563 * Construct a Function object for specified built-in routine 564 * 565 * See also: ECMA-262 v5, 15 566 * 567 * @return pointer to constructed Function object 568 */ 569static ecma_object_t * 570ecma_builtin_make_function_object_for_routine (ecma_builtin_id_t builtin_id, /**< identifier of built-in object */ 571 uint16_t routine_id, /**< builtin-wide identifier of the built-in 572 * object's routine property */ 573 uint16_t name_id, /**< magic string id of 'name' property */ 574 uint8_t length_prop_value) /**< value of 'length' property */ 575{ 576 JERRY_ASSERT (length_prop_value < (1 << ECMA_BUILT_IN_BITSET_SHIFT)); 577 578 ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE); 579 580 size_t ext_object_size = sizeof (ecma_extended_object_t); 581 582 ecma_object_t *func_obj_p = ecma_create_object (prototype_obj_p, 583 ext_object_size, 584 ECMA_OBJECT_TYPE_FUNCTION); 585 586 ecma_set_object_is_builtin (func_obj_p); 587 588 JERRY_ASSERT (routine_id >= ECMA_BUILTIN_ID__COUNT); 589 590 ecma_extended_object_t *ext_func_obj_p = (ecma_extended_object_t *) func_obj_p; 591 ext_func_obj_p->u.built_in.id = (uint8_t) builtin_id; 592 ext_func_obj_p->u.built_in.routine_id = routine_id; 593 ext_func_obj_p->u.built_in.u.builtin_routine.name = name_id; 594 ext_func_obj_p->u.built_in.u.builtin_routine.bitset = 0; 595 596 ext_func_obj_p->u.built_in.length_and_bitset_size = length_prop_value; 597 598 return func_obj_p; 599} /* ecma_builtin_make_function_object_for_routine */ 600 601/** 602 * Construct a Function object for specified built-in accessor getter 603 * 604 * @return pointer to constructed accessor getter Function object 605 */ 606static ecma_object_t * 607ecma_builtin_make_function_object_for_getter_accessor (ecma_builtin_id_t builtin_id, /**< id of built-in object */ 608 uint16_t routine_id, /**< builtin-wide id of the built-in 609 * object's routine property */ 610 uint16_t name_id) /**< magic string id of 'name' property */ 611{ 612 return ecma_builtin_make_function_object_for_routine (builtin_id, routine_id, name_id, 0); 613} /* ecma_builtin_make_function_object_for_getter_accessor */ 614 615/** 616 * Construct a Function object for specified built-in accessor setter 617 * 618 * @return pointer to constructed accessor getter Function object 619 */ 620static ecma_object_t * 621ecma_builtin_make_function_object_for_setter_accessor (ecma_builtin_id_t builtin_id, /**< id of built-in object */ 622 uint16_t routine_id, /**< builtin-wide id of the built-in 623 * object's routine property */ 624 uint16_t name_id) /**< magic string id of 'name' property */ 625{ 626 return ecma_builtin_make_function_object_for_routine (builtin_id, routine_id, name_id, 1); 627} /* ecma_builtin_make_function_object_for_setter_accessor */ 628 629/** 630 * Lazy instantiation of builtin routine property of builtin object 631 * 632 * If the property is not instantiated yet, instantiate the property and 633 * return pointer to the instantiated property. 634 * 635 * @return pointer property, if one was instantiated, 636 * NULL - otherwise. 637 */ 638ecma_property_t * 639ecma_builtin_routine_try_to_instantiate_property (ecma_object_t *object_p, /**< object */ 640 ecma_string_t *string_p) /**< property's name */ 641{ 642 JERRY_ASSERT (ecma_get_object_is_builtin (object_p)); 643 JERRY_ASSERT (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_FUNCTION); 644 JERRY_ASSERT (ecma_builtin_function_is_routine (object_p)); 645 646 if (ecma_string_is_length (string_p)) 647 { 648 /* 649 * Lazy instantiation of 'length' property 650 */ 651 652 ecma_property_t *len_prop_p; 653 ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) object_p; 654#if ENABLED (JERRY_ES2015) 655 uint16_t *bitset_p = &ext_func_p->u.built_in.u.builtin_routine.bitset; 656 if (*bitset_p & (1u << 0)) 657 { 658 /* length property was already instantiated */ 659 return NULL; 660 } 661 /* We mark that the property was lazily instantiated, 662 * as it is configurable and so can be deleted (ECMA-262 v6, 19.2.4.1) */ 663 *bitset_p |= (1u << 0); 664 ecma_property_value_t *len_prop_value_p = ecma_create_named_data_property (object_p, 665 string_p, 666 ECMA_PROPERTY_FLAG_CONFIGURABLE, 667 &len_prop_p); 668#else /* !ENABLED (JERRY_ES2015) */ 669 /* We don't need to mark that the property was already lazy instantiated, 670 * as it is non-configurable and so can't be deleted (ECMA-262 v5, 13.2.5) */ 671 ecma_property_value_t *len_prop_value_p = ecma_create_named_data_property (object_p, 672 string_p, 673 ECMA_PROPERTY_FIXED, 674 &len_prop_p); 675#endif /* ENABLED (JERRY_ES2015) */ 676 677 uint8_t length = ext_func_p->u.built_in.length_and_bitset_size; 678 JERRY_ASSERT (length < (1 << ECMA_BUILT_IN_BITSET_SHIFT)); 679 680 len_prop_value_p->value = ecma_make_integer_value (length); 681 682 return len_prop_p; 683 } 684 685 return NULL; 686} /* ecma_builtin_routine_try_to_instantiate_property */ 687 688/** 689 * If the property's name is one of built-in properties of the object 690 * that is not instantiated yet, instantiate the property and 691 * return pointer to the instantiated property. 692 * 693 * @return pointer property, if one was instantiated, 694 * NULL - otherwise. 695 */ 696ecma_property_t * 697ecma_builtin_try_to_instantiate_property (ecma_object_t *object_p, /**< object */ 698 ecma_string_t *string_p) /**< property's name */ 699{ 700 JERRY_ASSERT (ecma_get_object_is_builtin (object_p)); 701 702 lit_magic_string_id_t magic_string_id = ecma_get_string_magic (string_p); 703 704#if ENABLED (JERRY_ES2015) 705 if (JERRY_UNLIKELY (ecma_prop_name_is_symbol (string_p))) 706 { 707 if (string_p->u.hash & ECMA_GLOBAL_SYMBOL_FLAG) 708 { 709 magic_string_id = (string_p->u.hash >> ECMA_GLOBAL_SYMBOL_SHIFT); 710 } 711 } 712#endif /* ENABLED (JERRY_ES2015) */ 713 714 if (magic_string_id == LIT_MAGIC_STRING__COUNT) 715 { 716 return NULL; 717 } 718 719 ecma_built_in_props_t *built_in_props_p; 720 ecma_object_type_t object_type = ecma_get_object_type (object_p); 721 JERRY_ASSERT (object_type != ECMA_OBJECT_TYPE_FUNCTION || !ecma_builtin_function_is_routine (object_p)); 722 723 if (object_type == ECMA_OBJECT_TYPE_CLASS || object_type == ECMA_OBJECT_TYPE_ARRAY) 724 { 725 built_in_props_p = &((ecma_extended_built_in_object_t *) object_p)->built_in; 726 } 727 else 728 { 729 built_in_props_p = &((ecma_extended_object_t *) object_p)->u.built_in; 730 } 731 732 ecma_builtin_id_t builtin_id = (ecma_builtin_id_t) built_in_props_p->id; 733 734 JERRY_ASSERT (builtin_id < ECMA_BUILTIN_ID__COUNT); 735 JERRY_ASSERT (ecma_builtin_is (object_p, builtin_id)); 736 737 const ecma_builtin_property_descriptor_t *property_list_p = ecma_builtin_property_list_references[builtin_id]; 738 739 const ecma_builtin_property_descriptor_t *curr_property_p = property_list_p; 740 741 while (curr_property_p->magic_string_id != magic_string_id) 742 { 743 if (curr_property_p->magic_string_id == LIT_MAGIC_STRING__COUNT) 744 { 745 return NULL; 746 } 747 curr_property_p++; 748 } 749 750 uint32_t index = (uint32_t) (curr_property_p - property_list_p); 751 752 uint32_t *bitset_p = built_in_props_p->u.instantiated_bitset + (index >> 5); 753 754 uint32_t bit_for_index = (uint32_t) (1u << (index & 0x1f)); 755 756 if (*bitset_p & bit_for_index) 757 { 758 /* This property was instantiated before. */ 759 return NULL; 760 } 761 762 *bitset_p |= bit_for_index; 763 764 ecma_value_t value = ECMA_VALUE_EMPTY; 765 bool is_accessor = false; 766 ecma_object_t *getter_p = NULL; 767 ecma_object_t *setter_p = NULL; 768 769 switch (curr_property_p->type) 770 { 771 case ECMA_BUILTIN_PROPERTY_SIMPLE: 772 { 773 value = curr_property_p->value; 774 break; 775 } 776 case ECMA_BUILTIN_PROPERTY_NUMBER: 777 { 778 ecma_number_t num = 0.0; 779 780 if (curr_property_p->value < ECMA_BUILTIN_NUMBER_MAX) 781 { 782 num = curr_property_p->value; 783 } 784 else if (curr_property_p->value < ECMA_BUILTIN_NUMBER_NAN) 785 { 786 static const ecma_number_t builtin_number_list[] = 787 { 788 ECMA_NUMBER_MAX_VALUE, 789 ECMA_NUMBER_MIN_VALUE, 790#if ENABLED (JERRY_ES2015) 791 ECMA_NUMBER_EPSILON, 792 ECMA_NUMBER_MAX_SAFE_INTEGER, 793 ECMA_NUMBER_MIN_SAFE_INTEGER, 794#endif /* ENABLED (JERRY_ES2015) */ 795 ECMA_NUMBER_E, 796 ECMA_NUMBER_PI, 797 ECMA_NUMBER_LN10, 798 ECMA_NUMBER_LN2, 799 ECMA_NUMBER_LOG2E, 800 ECMA_NUMBER_LOG10E, 801 ECMA_NUMBER_SQRT2, 802 ECMA_NUMBER_SQRT_1_2, 803 }; 804 805 num = builtin_number_list[curr_property_p->value - ECMA_BUILTIN_NUMBER_MAX]; 806 } 807 else 808 { 809 switch (curr_property_p->value) 810 { 811 case ECMA_BUILTIN_NUMBER_POSITIVE_INFINITY: 812 { 813 num = ecma_number_make_infinity (false); 814 break; 815 } 816 case ECMA_BUILTIN_NUMBER_NEGATIVE_INFINITY: 817 { 818 num = ecma_number_make_infinity (true); 819 break; 820 } 821 default: 822 { 823 JERRY_ASSERT (curr_property_p->value == ECMA_BUILTIN_NUMBER_NAN); 824 825 num = ecma_number_make_nan (); 826 break; 827 } 828 } 829 } 830 831 value = ecma_make_number_value (num); 832 break; 833 } 834 case ECMA_BUILTIN_PROPERTY_STRING: 835 { 836 value = ecma_make_magic_string_value ((lit_magic_string_id_t) curr_property_p->value); 837 break; 838 } 839#if ENABLED (JERRY_ES2015) 840 case ECMA_BUILTIN_PROPERTY_SYMBOL: 841 { 842 ecma_stringbuilder_t builder = ecma_stringbuilder_create_raw ((lit_utf8_byte_t *) "Symbol.", 7); 843 844 lit_magic_string_id_t symbol_desc_id = (lit_magic_string_id_t) curr_property_p->value; 845 846 ecma_stringbuilder_append_magic (&builder, symbol_desc_id); 847 848 ecma_value_t symbol_desc_value = ecma_make_string_value (ecma_stringbuilder_finalize (&builder)); 849 850 ecma_string_t *symbol_p = ecma_new_symbol_from_descriptor_string (symbol_desc_value); 851 lit_magic_string_id_t symbol_id = (lit_magic_string_id_t) curr_property_p->magic_string_id; 852 symbol_p->u.hash = (uint16_t) ((symbol_id << ECMA_GLOBAL_SYMBOL_SHIFT) | ECMA_GLOBAL_SYMBOL_FLAG); 853 854 value = ecma_make_symbol_value (symbol_p); 855 break; 856 } 857 case ECMA_BUILTIN_PROPERTY_INTRINSIC_PROPERTY: 858 { 859 value = ecma_op_object_get_by_magic_id (ecma_builtin_get (ECMA_BUILTIN_ID_INTRINSIC_OBJECT), 860 (lit_magic_string_id_t) curr_property_p->value); 861 break; 862 } 863 case ECMA_BUILTIN_PROPERTY_ACCESSOR_BUILTIN_FUNCTION: 864 { 865 is_accessor = true; 866 uint16_t getter_id = ECMA_ACCESSOR_READ_WRITE_GET_GETTER_ID (curr_property_p->value); 867 uint16_t setter_id = ECMA_ACCESSOR_READ_WRITE_GET_SETTER_ID (curr_property_p->value); 868 getter_p = ecma_builtin_get (getter_id); 869 setter_p = ecma_builtin_get (setter_id); 870 ecma_ref_object (getter_p); 871 ecma_ref_object (setter_p); 872 break; 873 } 874#endif /* ENABLED (JERRY_ES2015) */ 875 case ECMA_BUILTIN_PROPERTY_OBJECT: 876 { 877 ecma_object_t *builtin_object_p = ecma_builtin_get ((ecma_builtin_id_t) curr_property_p->value); 878 ecma_ref_object (builtin_object_p); 879 value = ecma_make_object_value (builtin_object_p); 880 break; 881 } 882 case ECMA_BUILTIN_PROPERTY_ROUTINE: 883 { 884 ecma_object_t *func_obj_p; 885 func_obj_p = ecma_builtin_make_function_object_for_routine (builtin_id, 886 ECMA_GET_ROUTINE_ID (curr_property_p->value), 887 curr_property_p->magic_string_id, 888 ECMA_GET_ROUTINE_LENGTH (curr_property_p->value)); 889 value = ecma_make_object_value (func_obj_p); 890 break; 891 } 892 case ECMA_BUILTIN_PROPERTY_ACCESSOR_READ_WRITE: 893 { 894 is_accessor = true; 895 uint16_t getter_id = ECMA_ACCESSOR_READ_WRITE_GET_GETTER_ID (curr_property_p->value); 896 uint16_t setter_id = ECMA_ACCESSOR_READ_WRITE_GET_SETTER_ID (curr_property_p->value); 897 getter_p = ecma_builtin_make_function_object_for_getter_accessor (builtin_id, 898 getter_id, 899 curr_property_p->magic_string_id); 900 setter_p = ecma_builtin_make_function_object_for_setter_accessor (builtin_id, 901 setter_id, 902 curr_property_p->magic_string_id); 903 break; 904 } 905 default: 906 { 907 JERRY_ASSERT (curr_property_p->type == ECMA_BUILTIN_PROPERTY_ACCESSOR_READ_ONLY); 908 909 is_accessor = true; 910 getter_p = ecma_builtin_make_function_object_for_getter_accessor (builtin_id, 911 curr_property_p->value, 912 curr_property_p->magic_string_id); 913 break; 914 } 915 } 916 917 ecma_property_t *prop_p; 918 919 if (is_accessor) 920 { 921 ecma_create_named_accessor_property (object_p, 922 string_p, 923 getter_p, 924 setter_p, 925 curr_property_p->attributes, 926 &prop_p); 927 928 if (setter_p) 929 { 930 ecma_deref_object (setter_p); 931 } 932 if (getter_p) 933 { 934 ecma_deref_object (getter_p); 935 } 936 } 937 else 938 { 939 ecma_property_value_t *prop_value_p = ecma_create_named_data_property (object_p, 940 string_p, 941 curr_property_p->attributes, 942 &prop_p); 943 prop_value_p->value = value; 944 945 /* Reference count of objects must be decreased. */ 946 if (ecma_is_value_object (value)) 947 { 948 ecma_free_value (value); 949 } 950 } 951 952 return prop_p; 953} /* ecma_builtin_try_to_instantiate_property */ 954 955/** 956 * List names of a built-in function's lazy instantiated properties 957 * 958 * See also: 959 * ecma_builtin_routine_try_to_instantiate_property 960 */ 961void 962ecma_builtin_routine_list_lazy_property_names (ecma_object_t *object_p, /**< a built-in object */ 963 uint32_t opts, /**< listing options using flags 964 * from ecma_list_properties_options_t */ 965 ecma_collection_t *main_collection_p, /**< 'main' collection */ 966 ecma_collection_t *non_enum_collection_p) /**< skipped 'non-enumerable' 967 * collection */ 968{ 969 JERRY_ASSERT (ecma_get_object_is_builtin (object_p)); 970 JERRY_ASSERT (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_FUNCTION); 971 JERRY_ASSERT (ecma_builtin_function_is_routine (object_p)); 972 973 const bool separate_enumerable = (opts & ECMA_LIST_ENUMERABLE) != 0; 974 const bool is_array_indices_only = (opts & ECMA_LIST_ARRAY_INDICES) != 0; 975 976 ecma_collection_t *for_enumerable_p = main_collection_p; 977 JERRY_UNUSED (for_enumerable_p); 978 979 ecma_collection_t *for_non_enumerable_p = separate_enumerable ? non_enum_collection_p : main_collection_p; 980 981 if (!is_array_indices_only) 982 { 983#if ENABLED (JERRY_ES2015) 984 ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) object_p; 985 if (!(ext_func_p->u.built_in.u.builtin_routine.bitset & (1u << 0))) 986 { 987 /* Unintialized 'length' property is non-enumerable (ECMA-262 v6, 19.2.4.1) */ 988 ecma_collection_push_back (for_non_enumerable_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_LENGTH)); 989 } 990#else /* !ENABLED (JERRY_ES2015) */ 991 /* 'length' property is non-enumerable (ECMA-262 v5, 15) */ 992 ecma_collection_push_back (for_non_enumerable_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_LENGTH)); 993#endif /* ENABLED (JERRY_ES2015) */ 994 } 995} /* ecma_builtin_routine_list_lazy_property_names */ 996 997/** 998 * List names of a built-in object's lazy instantiated properties 999 * 1000 * See also: 1001 * ecma_builtin_try_to_instantiate_property 1002 */ 1003void 1004ecma_builtin_list_lazy_property_names (ecma_object_t *object_p, /**< a built-in object */ 1005 uint32_t opts, /**< listing options using flags 1006 * from ecma_list_properties_options_t */ 1007 ecma_collection_t *main_collection_p, /**< 'main' collection */ 1008 ecma_collection_t *non_enum_collection_p) /**< skipped 'non-enumerable' 1009 * collection */ 1010{ 1011 JERRY_ASSERT (ecma_get_object_is_builtin (object_p)); 1012 JERRY_ASSERT (ecma_get_object_type (object_p) != ECMA_OBJECT_TYPE_FUNCTION 1013 || !ecma_builtin_function_is_routine (object_p)); 1014 1015 const bool separate_enumerable = (opts & ECMA_LIST_ENUMERABLE) != 0; 1016 const bool is_array_indices_only = (opts & ECMA_LIST_ARRAY_INDICES) != 0; 1017 1018 ecma_built_in_props_t *built_in_props_p; 1019 ecma_object_type_t object_type = ecma_get_object_type (object_p); 1020 1021 if (object_type == ECMA_OBJECT_TYPE_CLASS || object_type == ECMA_OBJECT_TYPE_ARRAY) 1022 { 1023 built_in_props_p = &((ecma_extended_built_in_object_t *) object_p)->built_in; 1024 } 1025 else 1026 { 1027 built_in_props_p = &((ecma_extended_object_t *) object_p)->u.built_in; 1028 } 1029 1030 ecma_builtin_id_t builtin_id = (ecma_builtin_id_t) built_in_props_p->id; 1031 1032 JERRY_ASSERT (builtin_id < ECMA_BUILTIN_ID__COUNT); 1033 JERRY_ASSERT (ecma_builtin_is (object_p, builtin_id)); 1034 1035 const ecma_builtin_property_descriptor_t *curr_property_p = ecma_builtin_property_list_references[builtin_id]; 1036 1037 ecma_length_t index = 0; 1038 uint32_t *bitset_p = built_in_props_p->u.instantiated_bitset; 1039 1040 ecma_collection_t *for_non_enumerable_p = (separate_enumerable ? non_enum_collection_p 1041 : main_collection_p); 1042 1043 while (curr_property_p->magic_string_id != LIT_MAGIC_STRING__COUNT) 1044 { 1045 if (index == 32) 1046 { 1047 bitset_p++; 1048 index = 0; 1049 } 1050 1051#if ENABLED (JERRY_ES2015) 1052 /* Builtin symbol properties are internal magic strings which must not be listed */ 1053 if (curr_property_p->magic_string_id > LIT_NON_INTERNAL_MAGIC_STRING__COUNT) 1054 { 1055 curr_property_p++; 1056 continue; 1057 } 1058#endif /* ENABLED (JERRY_ES2015) */ 1059 1060 ecma_string_t *name_p = ecma_get_magic_string ((lit_magic_string_id_t) curr_property_p->magic_string_id); 1061 1062 if (is_array_indices_only && ecma_string_get_array_index (name_p) == ECMA_STRING_NOT_ARRAY_INDEX) 1063 { 1064 curr_property_p++; 1065 continue; 1066 } 1067 1068 uint32_t bit_for_index = (uint32_t) 1u << index; 1069 1070 if (!(*bitset_p & bit_for_index) || ecma_op_ordinary_object_has_own_property (object_p, name_p)) 1071 { 1072 ecma_value_t name = ecma_make_magic_string_value ((lit_magic_string_id_t) curr_property_p->magic_string_id); 1073 1074#if ENABLED (JERRY_ES2015) 1075 if (curr_property_p->attributes & ECMA_PROPERTY_FLAG_ENUMERABLE) 1076 { 1077 ecma_collection_push_back (main_collection_p, name); 1078 } 1079 else 1080#endif /* ENABLED (JERRY_ES2015) */ 1081 { 1082 ecma_collection_push_back (for_non_enumerable_p, name); 1083 } 1084 } 1085 1086 curr_property_p++; 1087 index++; 1088 } 1089} /* ecma_builtin_list_lazy_property_names */ 1090 1091/** 1092 * Dispatcher of built-in routines 1093 * 1094 * @return ecma value 1095 * Returned value must be freed with ecma_free_value. 1096 */ 1097static ecma_value_t 1098ecma_builtin_dispatch_routine (ecma_extended_object_t *func_obj_p, /**< builtin object */ 1099 ecma_value_t this_arg_value, /**< 'this' argument value */ 1100 const ecma_value_t *arguments_list_p, /**< list of arguments passed to routine */ 1101 ecma_length_t arguments_list_len) /**< length of arguments' list */ 1102{ 1103 JERRY_ASSERT (ecma_builtin_function_is_routine ((ecma_object_t *) func_obj_p)); 1104 1105 ecma_value_t padded_arguments_list_p[3] = { ECMA_VALUE_UNDEFINED, ECMA_VALUE_UNDEFINED, ECMA_VALUE_UNDEFINED }; 1106 1107 if (arguments_list_len <= 2) 1108 { 1109 switch (arguments_list_len) 1110 { 1111 case 2: 1112 { 1113 padded_arguments_list_p[1] = arguments_list_p[1]; 1114 /* FALLTHRU */ 1115 } 1116 case 1: 1117 { 1118 padded_arguments_list_p[0] = arguments_list_p[0]; 1119 break; 1120 } 1121 default: 1122 { 1123 JERRY_ASSERT (arguments_list_len == 0); 1124 } 1125 } 1126 1127 arguments_list_p = padded_arguments_list_p; 1128 } 1129 1130 return ecma_builtin_routines[func_obj_p->u.built_in.id] (func_obj_p->u.built_in.routine_id, 1131 this_arg_value, 1132 arguments_list_p, 1133 arguments_list_len); 1134} /* ecma_builtin_dispatch_routine */ 1135 1136/** 1137 * Handle calling [[Call]] of built-in object 1138 * 1139 * @return ecma value 1140 */ 1141ecma_value_t 1142ecma_builtin_dispatch_call (ecma_object_t *obj_p, /**< built-in object */ 1143 ecma_value_t this_arg_value, /**< 'this' argument value */ 1144 const ecma_value_t *arguments_list_p, /**< arguments list */ 1145 ecma_length_t arguments_list_len) /**< arguments list length */ 1146{ 1147 JERRY_ASSERT (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_FUNCTION); 1148 JERRY_ASSERT (ecma_get_object_is_builtin (obj_p)); 1149 1150 ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) obj_p; 1151 1152 if (ecma_builtin_function_is_routine (obj_p)) 1153 { 1154 return ecma_builtin_dispatch_routine (ext_obj_p, 1155 this_arg_value, 1156 arguments_list_p, 1157 arguments_list_len); 1158 } 1159 1160 ecma_builtin_id_t builtin_object_id = ext_obj_p->u.built_in.id; 1161 JERRY_ASSERT (builtin_object_id < sizeof (ecma_builtin_call_functions) / sizeof (ecma_builtin_dispatch_call_t)); 1162 return ecma_builtin_call_functions[builtin_object_id] (arguments_list_p, arguments_list_len); 1163} /* ecma_builtin_dispatch_call */ 1164 1165/** 1166 * Handle calling [[Construct]] of built-in object 1167 * 1168 * @return ecma value 1169 */ 1170ecma_value_t 1171ecma_builtin_dispatch_construct (ecma_object_t *obj_p, /**< built-in object */ 1172 ecma_object_t *new_target_p, /**< new target */ 1173 const ecma_value_t *arguments_list_p, /**< arguments list */ 1174 ecma_length_t arguments_list_len) /**< arguments list length */ 1175{ 1176 JERRY_ASSERT (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_FUNCTION); 1177 JERRY_ASSERT (ecma_get_object_is_builtin (obj_p)); 1178 1179 if (ecma_builtin_function_is_routine (obj_p)) 1180 { 1181 return ecma_raise_type_error (ECMA_ERR_MSG ("Built-in routines have no constructor.")); 1182 } 1183 1184 ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) obj_p; 1185 ecma_builtin_id_t builtin_object_id = ext_obj_p->u.built_in.id; 1186 JERRY_ASSERT (builtin_object_id < sizeof (ecma_builtin_construct_functions) / sizeof (ecma_builtin_dispatch_call_t)); 1187 1188#if ENABLED (JERRY_ES2015) 1189 ecma_object_t *old_new_target = JERRY_CONTEXT (current_new_target); 1190 JERRY_CONTEXT (current_new_target) = new_target_p; 1191#else /* !ENABLED (JERRY_ES2015) */ 1192 JERRY_UNUSED (new_target_p); 1193#endif /* ENABLED (JERRY_ES2015) */ 1194 1195 ecma_value_t ret_value = ecma_builtin_construct_functions[builtin_object_id] (arguments_list_p, arguments_list_len); 1196 1197#if ENABLED (JERRY_ES2015) 1198 JERRY_CONTEXT (current_new_target) = old_new_target; 1199#endif /* ENABLED (JERRY_ES2015) */ 1200 1201 return ret_value; 1202} /* ecma_builtin_dispatch_construct */ 1203 1204/** 1205 * @} 1206 * @} 1207 */ 1208