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