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
36 static void ecma_instantiate_builtin (ecma_builtin_id_t id);
37
38 /**
39 * Helper definition for ecma_builtin_property_list_references.
40 */
41 typedef const ecma_builtin_property_descriptor_t *ecma_builtin_property_list_reference_t;
42
43 /**
44 * Definition of built-in dispatch routine function pointer.
45 */
46 typedef 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 */
53 typedef 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 */
65 typedef 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 */
86 static 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 */
114 enum
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 */
144 JERRY_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 */
151 static 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 */
180 static 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 */
199 static 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 */
218 static 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 */
249 static size_t
ecma_builtin_get_property_count(ecma_builtin_id_t builtin_id)250 ecma_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 */
271 bool
ecma_builtin_is(ecma_object_t * obj_p,ecma_builtin_id_t builtin_id)272 ecma_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 */
293 ecma_object_t *
ecma_builtin_get(ecma_builtin_id_t builtin_id)294 ecma_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 */
314 inline ecma_object_t * JERRY_ATTR_ALWAYS_INLINE
ecma_builtin_get_global(void)315 ecma_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 */
328 inline bool JERRY_ATTR_ALWAYS_INLINE
ecma_builtin_function_is_routine(ecma_object_t * func_obj_p)329 ecma_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 */
341 static void
ecma_instantiate_builtin(ecma_builtin_id_t obj_builtin_id)342 ecma_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 */
532 void
ecma_finalize_builtins(void)533 ecma_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 */
569 static ecma_object_t *
ecma_builtin_make_function_object_for_routine(ecma_builtin_id_t builtin_id,uint16_t routine_id,uint16_t name_id,uint8_t length_prop_value)570 ecma_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 */
606 static ecma_object_t *
ecma_builtin_make_function_object_for_getter_accessor(ecma_builtin_id_t builtin_id,uint16_t routine_id,uint16_t name_id)607 ecma_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 */
620 static ecma_object_t *
ecma_builtin_make_function_object_for_setter_accessor(ecma_builtin_id_t builtin_id,uint16_t routine_id,uint16_t name_id)621 ecma_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 */
638 ecma_property_t *
ecma_builtin_routine_try_to_instantiate_property(ecma_object_t * object_p,ecma_string_t * string_p)639 ecma_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 */
696 ecma_property_t *
ecma_builtin_try_to_instantiate_property(ecma_object_t * object_p,ecma_string_t * string_p)697 ecma_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 */
961 void
ecma_builtin_routine_list_lazy_property_names(ecma_object_t * object_p,uint32_t opts,ecma_collection_t * main_collection_p,ecma_collection_t * non_enum_collection_p)962 ecma_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 */
1003 void
ecma_builtin_list_lazy_property_names(ecma_object_t * object_p,uint32_t opts,ecma_collection_t * main_collection_p,ecma_collection_t * non_enum_collection_p)1004 ecma_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 */
1097 static ecma_value_t
ecma_builtin_dispatch_routine(ecma_extended_object_t * func_obj_p,ecma_value_t this_arg_value,const ecma_value_t * arguments_list_p,ecma_length_t arguments_list_len)1098 ecma_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 */
1141 ecma_value_t
ecma_builtin_dispatch_call(ecma_object_t * obj_p,ecma_value_t this_arg_value,const ecma_value_t * arguments_list_p,ecma_length_t arguments_list_len)1142 ecma_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 */
1170 ecma_value_t
ecma_builtin_dispatch_construct(ecma_object_t * obj_p,ecma_object_t * new_target_p,const ecma_value_t * arguments_list_p,ecma_length_t arguments_list_len)1171 ecma_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