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-array-object.h"
18#include "ecma-iterator-object.h"
19#include "ecma-builtin-helpers.h"
20#include "ecma-builtins.h"
21#include "ecma-exceptions.h"
22#include "ecma-gc.h"
23#include "ecma-globals.h"
24#include "ecma-property-hashmap.h"
25#include "ecma-helpers.h"
26#include "ecma-number-arithmetic.h"
27#include "ecma-objects.h"
28#include "ecma-objects-general.h"
29#include "ecma-function-object.h"
30
31/** \addtogroup ecma ECMA
32 * @{
33 *
34 * \addtogroup ecmaarrayobject ECMA Array object related routines
35 * @{
36 */
37
38#if ENABLED (JERRY_CPOINTER_32_BIT)
39/**
40 * Maximum length of the array length to allocate fast mode access for it
41 * e.g. new Array(5000) is constructed as fast mode access array,
42 * but new Array(50000000) is consturcted as normal property list based array
43 */
44#define ECMA_FAST_ARRAY_MAX_INITIAL_LENGTH (1 << 17)
45#else /* ENABLED (JERRY_CPOINTER_32_BIT) */
46/**
47 * Maximum length of the array length to allocate fast mode access for it
48 * e.g. new Array(5000) is constructed as fast mode access array,
49 * but new Array(50000000) is consturcted as normal property list based array
50 */
51#define ECMA_FAST_ARRAY_MAX_INITIAL_LENGTH (1 << 13)
52#endif /* ENABLED (JERRY_CPOINTER_32_BIT) */
53
54/**
55 * Property name type flag for array indices.
56 */
57#define ECMA_FAST_ARRAY_UINT32_DIRECT_STRING_PROP_TYPE 0x80
58
59/**
60 * Property attribute for the array 'length' virtual property to indicate fast access mode array
61 */
62#define ECMA_FAST_ARRAY_FLAG (ECMA_DIRECT_STRING_MAGIC << ECMA_PROPERTY_NAME_TYPE_SHIFT)
63
64/**
65 * Allocate a new array object with the given length
66 *
67 * @return pointer to the constructed array object
68 */
69ecma_object_t *
70ecma_op_new_array_object (ecma_length_t length) /**< length of the new array */
71{
72#if ENABLED (JERRY_BUILTIN_ARRAY)
73  ecma_object_t *array_prototype_object_p = ecma_builtin_get (ECMA_BUILTIN_ID_ARRAY_PROTOTYPE);
74#else /* !ENABLED (JERRY_BUILTIN_ARRAY) */
75  ecma_object_t *array_prototype_object_p = ecma_builtin_get (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE);
76#endif /* ENABLED (JERRY_BUILTIN_ARRAY) */
77
78  ecma_object_t *object_p = ecma_create_object (array_prototype_object_p,
79                                                sizeof (ecma_extended_object_t),
80                                                ECMA_OBJECT_TYPE_ARRAY);
81
82  /*
83   * [[Class]] property is not stored explicitly for objects of ECMA_OBJECT_TYPE_ARRAY type.
84   *
85   * See also: ecma_object_get_class_name
86   */
87
88  ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) object_p;
89  ext_obj_p->u.array.length = length;
90  ext_obj_p->u.array.u.hole_count = 0;
91  ext_obj_p->u.array.u.length_prop = ECMA_PROPERTY_FLAG_WRITABLE | ECMA_PROPERTY_TYPE_VIRTUAL;
92
93  return object_p;
94} /* ecma_op_new_array_object */
95
96/**
97 * Check whether the given object is fast-access mode array
98 *
99 * @return true - if the object is fast-access mode array
100 *         false, otherwise
101 */
102inline bool JERRY_ATTR_ALWAYS_INLINE
103ecma_op_object_is_fast_array (ecma_object_t *object_p) /**< ecma-object */
104{
105  return (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_ARRAY &&
106          ecma_op_array_is_fast_array ((ecma_extended_object_t *) object_p));
107} /* ecma_op_object_is_fast_array */
108
109/**
110 * Check whether the given array object is fast-access mode array
111 *
112 * @return true - if the array object is fast-access mode array
113 *         false, otherwise
114 */
115inline bool JERRY_ATTR_ALWAYS_INLINE
116ecma_op_array_is_fast_array (ecma_extended_object_t *array_p) /**< ecma-array-object */
117{
118  JERRY_ASSERT (ecma_get_object_type ((ecma_object_t *) array_p) == ECMA_OBJECT_TYPE_ARRAY);
119
120  return array_p->u.array.u.length_prop & ECMA_FAST_ARRAY_FLAG;
121} /* ecma_op_array_is_fast_array */
122
123/**
124 * Allocate a new fast access mode array object with the given length
125 *
126 * @return NULL - if the allocation of the underlying buffer failed
127 *         pointer to the constructed fast access mode array object otherwise
128 */
129ecma_object_t *
130ecma_op_new_fast_array_object (ecma_length_t length) /**< length of the new fast access mode array */
131{
132  const uint32_t aligned_length = ECMA_FAST_ARRAY_ALIGN_LENGTH (length);
133  ecma_value_t *values_p = NULL;
134
135  if (length != 0)
136  {
137    values_p = (ecma_value_t *) jmem_heap_alloc_block_null_on_error (aligned_length * sizeof (ecma_value_t));
138
139    if (JERRY_UNLIKELY (values_p == NULL))
140    {
141      return NULL;
142    }
143  }
144
145  ecma_object_t *object_p = ecma_op_new_array_object (length);
146  ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) object_p;
147
148  ext_obj_p->u.array.u.length_prop = (uint8_t) (ext_obj_p->u.array.u.length_prop | ECMA_FAST_ARRAY_FLAG);
149  ext_obj_p->u.array.u.hole_count += length * ECMA_FAST_ARRAY_HOLE_ONE;
150
151  JERRY_ASSERT (object_p->u1.property_list_cp == JMEM_CP_NULL);
152
153  for (uint32_t i = 0; i < aligned_length; i++)
154  {
155    values_p[i] = ECMA_VALUE_ARRAY_HOLE;
156  }
157
158  ECMA_SET_POINTER (object_p->u1.property_list_cp, values_p);
159  return object_p;
160} /* ecma_op_new_fast_array_object */
161
162/**
163 * Converts a fast access mode array back to a normal property list based array
164 */
165void
166ecma_fast_array_convert_to_normal (ecma_object_t *object_p) /**< fast access mode array object */
167{
168  JERRY_ASSERT (ecma_op_object_is_fast_array (object_p));
169
170  ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) object_p;
171
172  if (object_p->u1.property_list_cp == JMEM_CP_NULL)
173  {
174    ext_obj_p->u.array.u.length_prop = (uint8_t) (ext_obj_p->u.array.u.length_prop & ~ECMA_FAST_ARRAY_FLAG);
175    return;
176  }
177
178  uint32_t length = ext_obj_p->u.array.length;
179  const uint32_t aligned_length = ECMA_FAST_ARRAY_ALIGN_LENGTH (length);
180  ecma_value_t *values_p = ECMA_GET_NON_NULL_POINTER (ecma_value_t, object_p->u1.property_list_cp);
181
182  ecma_ref_object (object_p);
183
184  ecma_property_pair_t *property_pair_p = NULL;
185  jmem_cpointer_t next_property_pair_cp = JMEM_CP_NULL;
186
187  uint32_t prop_index = 1;
188  int32_t index = (int32_t) (length - 1);
189
190  while (index >= 0)
191  {
192    if (ecma_is_value_array_hole (values_p[index]))
193    {
194      index--;
195      continue;
196    }
197
198    if (prop_index == 1)
199    {
200      property_pair_p = ecma_alloc_property_pair ();
201      property_pair_p->header.next_property_cp = next_property_pair_cp;
202      property_pair_p->names_cp[0] = LIT_INTERNAL_MAGIC_STRING_DELETED;
203      property_pair_p->header.types[0] = ECMA_PROPERTY_TYPE_DELETED;
204      ECMA_SET_NON_NULL_POINTER (next_property_pair_cp, property_pair_p);
205    }
206
207    JERRY_ASSERT (index <= ECMA_DIRECT_STRING_MAX_IMM);
208
209    property_pair_p->names_cp[prop_index] = (jmem_cpointer_t) index;
210    property_pair_p->header.types[prop_index] = (ecma_property_t) (ECMA_PROPERTY_TYPE_NAMEDDATA
211                                                                   | ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE
212                                                                   | ECMA_FAST_ARRAY_UINT32_DIRECT_STRING_PROP_TYPE);
213
214    property_pair_p->values[prop_index].value = values_p[index];
215
216    index--;
217    prop_index = !prop_index;
218  }
219
220  ext_obj_p->u.array.u.length_prop = (uint8_t) (ext_obj_p->u.array.u.length_prop & ~ECMA_FAST_ARRAY_FLAG);
221  jmem_heap_free_block (values_p, aligned_length * sizeof (ecma_value_t));
222  ECMA_SET_POINTER (object_p->u1.property_list_cp, property_pair_p);
223
224  ecma_deref_object (object_p);
225} /* ecma_fast_array_convert_to_normal */
226
227/**
228 * [[Put]] operation for a fast access mode array
229 *
230 * @return false - If the property name is not array index, or the requested index to be set
231 *                 would result too much array hole in the underlying buffer. The these cases
232 *                 the array is converted back to normal property list based array.
233 *         true - If the indexed property can be set with/without resizing the underlying buffer.
234 */
235bool
236ecma_fast_array_set_property (ecma_object_t *object_p, /**< fast access mode array object */
237                              uint32_t index, /**< property name index */
238                              ecma_value_t value) /**< value to be set */
239{
240  JERRY_ASSERT (ecma_op_object_is_fast_array (object_p));
241  ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) object_p;
242  uint32_t old_length = ext_obj_p->u.array.length;
243
244  ecma_value_t *values_p;
245
246  if (JERRY_LIKELY (index < old_length))
247  {
248    JERRY_ASSERT (object_p->u1.property_list_cp != JMEM_CP_NULL);
249
250    values_p = ECMA_GET_NON_NULL_POINTER (ecma_value_t, object_p->u1.property_list_cp);
251
252    if (ecma_is_value_array_hole (values_p[index]))
253    {
254      ext_obj_p->u.array.u.hole_count -= ECMA_FAST_ARRAY_HOLE_ONE;
255    }
256    else
257    {
258      ecma_free_value_if_not_object (values_p[index]);
259    }
260
261    values_p[index] = ecma_copy_value_if_not_object (value);
262
263    return true;
264  }
265
266  uint32_t old_holes = ext_obj_p->u.array.u.hole_count;
267  uint32_t new_holes = index - old_length;
268
269  if (JERRY_UNLIKELY (new_holes > ECMA_FAST_ARRAY_MAX_NEW_HOLES_COUNT
270                      || ((old_holes >> ECMA_FAST_ARRAY_HOLE_SHIFT) + new_holes) > ECMA_FAST_ARRAY_MAX_HOLE_COUNT))
271  {
272    ecma_fast_array_convert_to_normal (object_p);
273
274    return false;
275  }
276
277  uint32_t new_length = index + 1;
278
279  JERRY_ASSERT (new_length < UINT32_MAX);
280
281  const uint32_t aligned_length = ECMA_FAST_ARRAY_ALIGN_LENGTH (old_length);
282
283  if (JERRY_LIKELY (index < aligned_length))
284  {
285    JERRY_ASSERT (object_p->u1.property_list_cp != JMEM_CP_NULL);
286
287    values_p = ECMA_GET_NON_NULL_POINTER (ecma_value_t, object_p->u1.property_list_cp);
288    /* This area is filled with ECMA_VALUE_ARRAY_HOLE, but not counted in u.array.u.hole_count */
289    JERRY_ASSERT (ecma_is_value_array_hole (values_p[index]));
290    ext_obj_p->u.array.u.hole_count += new_holes * ECMA_FAST_ARRAY_HOLE_ONE;
291    ext_obj_p->u.array.length = new_length;
292  }
293  else
294  {
295    values_p = ecma_fast_array_extend (object_p, new_length);
296    ext_obj_p->u.array.u.hole_count -= ECMA_FAST_ARRAY_HOLE_ONE;
297  }
298
299  values_p[index] = ecma_copy_value_if_not_object (value);
300
301  return true;
302} /* ecma_fast_array_set_property */
303
304/**
305 * Get the number of array holes in a fast access array object
306 *
307 * @return number of array holes in a fast access array object
308 */
309inline uint32_t JERRY_ATTR_ALWAYS_INLINE
310ecma_fast_array_get_hole_count (ecma_object_t *obj_p) /**< fast access mode array object */
311{
312  JERRY_ASSERT (ecma_op_object_is_fast_array (obj_p));
313
314  return ((ecma_extended_object_t *) obj_p)->u.array.u.hole_count >> ECMA_FAST_ARRAY_HOLE_SHIFT;
315} /* ecma_fast_array_get_hole_count */
316
317/**
318 * Extend the underlying buffer of a fast mode access array for the given new length
319 *
320 * @return pointer to the extended underlying buffer
321 */
322ecma_value_t *
323ecma_fast_array_extend (ecma_object_t *object_p, /**< fast access mode array object */
324                        uint32_t new_length) /**< new length of the fast access mode array */
325{
326  JERRY_ASSERT (ecma_op_object_is_fast_array (object_p));
327  ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) object_p;
328  uint32_t old_length = ext_obj_p->u.array.length;
329
330  JERRY_ASSERT (old_length < new_length);
331
332  ecma_ref_object (object_p);
333
334  ecma_value_t *new_values_p;
335  const uint32_t old_length_aligned = ECMA_FAST_ARRAY_ALIGN_LENGTH (old_length);
336  const uint32_t new_length_aligned = ECMA_FAST_ARRAY_ALIGN_LENGTH (new_length);
337
338  if (object_p->u1.property_list_cp == JMEM_CP_NULL)
339  {
340    new_values_p = jmem_heap_alloc_block (new_length_aligned * sizeof (ecma_value_t));
341  }
342  else
343  {
344    ecma_value_t *values_p = ECMA_GET_NON_NULL_POINTER (ecma_value_t, object_p->u1.property_list_cp);
345    new_values_p = (ecma_value_t *) jmem_heap_realloc_block (values_p,
346                                                             old_length_aligned * sizeof (ecma_value_t),
347                                                             new_length_aligned * sizeof (ecma_value_t));
348  }
349
350  for (uint32_t i = old_length; i < new_length_aligned; i++)
351  {
352    new_values_p[i] = ECMA_VALUE_ARRAY_HOLE;
353  }
354
355  ext_obj_p->u.array.u.hole_count += (new_length - old_length) * ECMA_FAST_ARRAY_HOLE_ONE;
356  ext_obj_p->u.array.length = new_length;
357
358  ECMA_SET_NON_NULL_POINTER (object_p->u1.property_list_cp, new_values_p);
359
360  ecma_deref_object (object_p);
361  return new_values_p;
362} /* ecma_fast_array_extend */
363
364/**
365 * Delete the array object's property referenced by its value pointer.
366 *
367 * Note: specified property must be owned by specified object.
368 */
369void
370ecma_array_object_delete_property (ecma_object_t *object_p, /**< object */
371                                   ecma_string_t *property_name_p, /**< property name */
372                                   ecma_property_value_t *prop_value_p) /**< property value reference */
373{
374  JERRY_ASSERT (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_ARRAY);
375  ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) object_p;
376
377  if (!ecma_op_object_is_fast_array (object_p))
378  {
379    ecma_delete_property (object_p, prop_value_p);
380    return;
381  }
382
383  JERRY_ASSERT (object_p->u1.property_list_cp != JMEM_CP_NULL);
384
385  uint32_t index = ecma_string_get_array_index (property_name_p);
386
387  JERRY_ASSERT (index != ECMA_STRING_NOT_ARRAY_INDEX);
388  JERRY_ASSERT (index < ext_obj_p->u.array.length);
389
390  ecma_value_t *values_p = ECMA_GET_NON_NULL_POINTER (ecma_value_t, object_p->u1.property_list_cp);
391
392  if (ecma_is_value_array_hole (values_p[index]))
393  {
394    return;
395  }
396
397  ecma_free_value_if_not_object (values_p[index]);
398
399  values_p[index] = ECMA_VALUE_ARRAY_HOLE;
400  ext_obj_p->u.array.u.hole_count += ECMA_FAST_ARRAY_HOLE_ONE;
401} /* ecma_array_object_delete_property */
402
403/**
404 * Low level delete of fast access mode array items
405 *
406 * @return the updated value of new_length
407 */
408uint32_t
409ecma_delete_fast_array_properties (ecma_object_t *object_p, /**< fast access mode array */
410                                   uint32_t new_length) /**< new length of the fast access mode array */
411{
412  JERRY_ASSERT (ecma_op_object_is_fast_array (object_p));
413
414  ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) object_p;
415
416  ecma_ref_object (object_p);
417  ecma_value_t *values_p = ECMA_GET_NON_NULL_POINTER (ecma_value_t, object_p->u1.property_list_cp);
418
419  uint32_t old_length = ext_obj_p->u.array.length;
420  const uint32_t old_aligned_length = ECMA_FAST_ARRAY_ALIGN_LENGTH (old_length);
421  JERRY_ASSERT (new_length < old_length);
422
423  for (uint32_t i = new_length; i < old_length; i++)
424  {
425    if (ecma_is_value_array_hole (values_p[i]))
426    {
427      ext_obj_p->u.array.u.hole_count -= ECMA_FAST_ARRAY_HOLE_ONE;
428    }
429    else
430    {
431      ecma_free_value_if_not_object (values_p[i]);
432    }
433  }
434
435  jmem_cpointer_t new_property_list_cp;
436
437  if (new_length == 0)
438  {
439    jmem_heap_free_block (values_p, old_aligned_length * sizeof (ecma_value_t));
440    new_property_list_cp = JMEM_CP_NULL;
441  }
442  else
443  {
444    const uint32_t new_aligned_length = ECMA_FAST_ARRAY_ALIGN_LENGTH (new_length);
445
446    ecma_value_t *new_values_p;
447    new_values_p = (ecma_value_t *) jmem_heap_realloc_block (values_p,
448                                                             old_aligned_length * sizeof (ecma_value_t),
449                                                             new_aligned_length * sizeof (ecma_value_t));
450
451    for (uint32_t i = new_length; i < new_aligned_length; i++)
452    {
453      new_values_p[i] = ECMA_VALUE_ARRAY_HOLE;
454    }
455
456    ECMA_SET_NON_NULL_POINTER (new_property_list_cp, new_values_p);
457  }
458
459  ext_obj_p->u.array.length = new_length;
460  object_p->u1.property_list_cp = new_property_list_cp;
461
462  ecma_deref_object (object_p);
463
464  return new_length;
465} /* ecma_delete_fast_array_properties */
466
467/**
468 * Update the length of a fast access mode array to a new length
469 *
470 * Note: if the new length would result too much array hole in the underlying arraybuffer
471 *       the array is converted back to normal property list based array
472 */
473static void
474ecma_fast_array_set_length (ecma_object_t *object_p, /**< fast access mode array object */
475                            uint32_t new_length) /**< new length of the fast access mode array object*/
476{
477  JERRY_ASSERT (ecma_op_object_is_fast_array (object_p));
478
479  ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) object_p;
480  uint32_t old_length = ext_obj_p->u.array.length;
481
482  JERRY_ASSERT (new_length >= old_length);
483
484  if (new_length == old_length)
485  {
486    return;
487  }
488
489  uint32_t old_holes = ext_obj_p->u.array.u.hole_count;
490  uint32_t new_holes = new_length - old_length;
491
492  if (JERRY_UNLIKELY (new_holes > ECMA_FAST_ARRAY_MAX_NEW_HOLES_COUNT
493                      || ((old_holes >> ECMA_FAST_ARRAY_HOLE_SHIFT) + new_holes) > ECMA_FAST_ARRAY_MAX_HOLE_COUNT))
494  {
495    ecma_fast_array_convert_to_normal (object_p);
496  }
497  else
498  {
499    ecma_fast_array_extend (object_p, new_length);
500  }
501
502  return;
503} /* ecma_fast_array_set_length */
504
505/**
506 * Get collection of property names of a fast access mode array object
507 *
508 * Note: Since the fast array object only contains indexed, enumerable, writable, configurable properties
509 *       we can return a collection of non-array hole array indices
510 *
511 * @return collection of strings - property names
512 */
513ecma_collection_t *
514ecma_fast_array_get_property_names (ecma_object_t *object_p, /**< fast access mode array object */
515                                    uint32_t opts) /**< any combination of ecma_list_properties_options_t values */
516{
517  JERRY_ASSERT (ecma_op_object_is_fast_array (object_p));
518
519  ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) object_p;
520  ecma_collection_t *ret_p = ecma_new_collection ();
521
522#if ENABLED (JERRY_ES2015)
523  if (opts & ECMA_LIST_SYMBOLS_ONLY)
524  {
525    return ret_p;
526  }
527#endif /* ENABLED (JERRY_ES2015) */
528
529  uint32_t length = ext_obj_p->u.array.length;
530
531  bool append_length = (!(opts & ECMA_LIST_ENUMERABLE) && !(opts & ECMA_LIST_ARRAY_INDICES));
532
533  if (length == 0)
534  {
535    if (append_length)
536    {
537      ecma_collection_push_back (ret_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_LENGTH));
538    }
539
540    return ret_p;
541  }
542
543  ecma_value_t *values_p = ECMA_GET_NON_NULL_POINTER (ecma_value_t, object_p->u1.property_list_cp);
544
545  for (uint32_t i = 0; i < length; i++)
546  {
547    if (ecma_is_value_array_hole (values_p[i]))
548    {
549      continue;
550    }
551
552    ecma_string_t *index_str_p = ecma_new_ecma_string_from_uint32 (i);
553
554    ecma_collection_push_back (ret_p, ecma_make_string_value (index_str_p));
555  }
556
557  if (append_length)
558  {
559    ecma_collection_push_back (ret_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_LENGTH));
560  }
561
562  if (opts & ECMA_LIST_CONVERT_FAST_ARRAYS)
563  {
564    ecma_fast_array_convert_to_normal (object_p);
565  }
566
567  return ret_p;
568} /* ecma_fast_array_get_property_names */
569
570/**
571 * Array object creation operation.
572 *
573 * See also: ECMA-262 v5, 15.4.2.1
574 *           ECMA-262 v5, 15.4.2.2
575 *
576 * @return ecma value
577 *         Returned value must be freed with ecma_free_value
578 */
579ecma_value_t
580ecma_op_create_array_object (const ecma_value_t *arguments_list_p, /**< list of arguments that
581                                                                    *   are passed to Array constructor */
582                             ecma_length_t arguments_list_len, /**< length of the arguments' list */
583                             bool is_treat_single_arg_as_length) /**< if the value is true,
584                                                                  *   arguments_list_len is 1
585                                                                  *   and single argument is Number,
586                                                                  *   then treat the single argument
587                                                                  *   as new Array's length rather
588                                                                  *   than as single item of the Array */
589{
590  JERRY_ASSERT (arguments_list_len == 0
591                || arguments_list_p != NULL);
592
593  uint32_t length;
594  const ecma_value_t *array_items_p;
595  ecma_length_t array_items_count;
596
597  if (is_treat_single_arg_as_length
598      && arguments_list_len == 1
599      && ecma_is_value_number (arguments_list_p[0]))
600  {
601    ecma_number_t num = ecma_get_number_from_value (arguments_list_p[0]);
602    uint32_t num_uint32 = ecma_number_to_uint32 (num);
603
604    if (num != ((ecma_number_t) num_uint32))
605    {
606      return ecma_raise_range_error (ECMA_ERR_MSG ("Invalid array length."));
607    }
608    else
609    {
610      length = num_uint32;
611      array_items_p = NULL;
612      array_items_count = 0;
613    }
614
615    if (length > ECMA_FAST_ARRAY_MAX_INITIAL_LENGTH)
616    {
617      return ecma_make_object_value (ecma_op_new_array_object (length));
618    }
619
620    ecma_object_t *object_p = ecma_op_new_fast_array_object (length);
621
622    if (object_p == NULL)
623    {
624      return ecma_make_object_value (ecma_op_new_array_object (length));
625    }
626
627    JERRY_ASSERT (ecma_op_object_is_fast_array (object_p));
628
629    return ecma_make_object_value (object_p);
630  }
631  else
632  {
633    length = arguments_list_len;
634    array_items_p = arguments_list_p;
635    array_items_count = arguments_list_len;
636  }
637
638  ecma_object_t *object_p = ecma_op_new_fast_array_object (length);
639
640  /* At this point we were not able to allocate a length * sizeof (ecma_value_t) amount of memory,
641     so we can terminate the engine since converting it into normal property list based array
642     would consume more memory. */
643  if (object_p == NULL)
644  {
645    jerry_fatal (ERR_OUT_OF_MEMORY);
646  }
647
648  if (length == 0)
649  {
650    return ecma_make_object_value (object_p);
651  }
652
653  ecma_value_t *values_p = ECMA_GET_NON_NULL_POINTER (ecma_value_t, object_p->u1.property_list_cp);
654  ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) object_p;
655
656  for (uint32_t index = 0;
657       index < array_items_count;
658       index++)
659  {
660    JERRY_ASSERT (!ecma_is_value_array_hole (array_items_p[index]));
661    values_p[index] = ecma_copy_value_if_not_object (array_items_p[index]);
662  }
663
664  ext_obj_p->u.array.u.hole_count -= ECMA_FAST_ARRAY_HOLE_ONE * array_items_count;
665
666  return ecma_make_object_value (object_p);
667} /* ecma_op_create_array_object */
668
669#if ENABLED (JERRY_ES2015)
670/**
671 * Array object creation with custom prototype.
672 *
673 * See also: ECMA-262 v6, 9.4.2.3
674 *
675 * @return ecma value
676 *         Returned value must be freed with ecma_free_value
677 */
678ecma_value_t
679ecma_op_array_species_create (ecma_object_t *original_array_p, /**< The object from whom the new array object
680                                                                *   is being created */
681                              ecma_length_t length) /**< length of the array */
682{
683  ecma_value_t constructor = ECMA_VALUE_UNDEFINED;
684  ecma_value_t original_array = ecma_make_object_value (original_array_p);
685
686  ecma_value_t is_array = ecma_is_value_array (original_array);
687
688  if (ECMA_IS_VALUE_ERROR (is_array))
689  {
690    return is_array;
691  }
692
693  if (ecma_is_value_true (is_array))
694  {
695    constructor = ecma_op_object_get_by_magic_id (original_array_p, LIT_MAGIC_STRING_CONSTRUCTOR);
696    if (ECMA_IS_VALUE_ERROR (constructor))
697    {
698      return constructor;
699    }
700
701    if (ecma_is_constructor (constructor)
702        && ecma_get_object_from_value (constructor) == ecma_builtin_get (ECMA_BUILTIN_ID_ARRAY))
703    {
704      ecma_free_value (constructor);
705      constructor = ECMA_VALUE_UNDEFINED;
706    }
707    else if (ecma_is_value_object (constructor))
708    {
709      ecma_object_t *ctor_object_p = ecma_get_object_from_value (constructor);
710      constructor = ecma_op_object_get_by_symbol_id (ctor_object_p, LIT_GLOBAL_SYMBOL_SPECIES);
711      ecma_deref_object (ctor_object_p);
712
713      if (ECMA_IS_VALUE_ERROR (constructor))
714      {
715        return constructor;
716      }
717
718      if (ecma_is_value_null (constructor))
719      {
720        constructor = ECMA_VALUE_UNDEFINED;
721      }
722    }
723  }
724
725  if (ecma_is_value_undefined (constructor))
726  {
727    ecma_value_t length_val = ecma_make_uint32_value (length);
728    ecma_value_t new_array = ecma_op_create_array_object (&length_val, 1, true);
729    ecma_free_value (length_val);
730
731    return new_array;
732  }
733
734  if (!ecma_is_constructor (constructor))
735  {
736    ecma_free_value (constructor);
737    return ecma_raise_type_error (ECMA_ERR_MSG ("Invalid species constructor"));
738  }
739
740  ecma_value_t len_val = ecma_make_uint32_value (length);
741  ecma_object_t *ctor_object_p = ecma_get_object_from_value (constructor);
742  ecma_value_t ret_val = ecma_op_function_construct (ctor_object_p,
743                                                     ctor_object_p,
744                                                     &len_val,
745                                                     1);
746
747  ecma_deref_object (ctor_object_p);
748  ecma_free_value (len_val);
749  return ret_val;
750} /* ecma_op_array_species_create */
751
752/**
753 * CreateArrayIterator Abstract Operation
754 *
755 * See also:
756 *          ECMA-262 v6, 22.1.5.1
757 *
758 * Referenced by:
759 *          ECMA-262 v6, 22.1.3.4
760 *          ECMA-262 v6, 22.1.3.13
761 *          ECMA-262 v6, 22.1.3.29
762 *          ECMA-262 v6, 22.1.3.30
763 *
764 * Note:
765 *      Returned value must be freed with ecma_free_value.
766 *
767 * @return array iterator object
768 */
769ecma_value_t
770ecma_op_create_array_iterator (ecma_object_t *obj_p, /**< array object */
771                               ecma_array_iterator_type_t type) /**< array iterator type */
772{
773  ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_ARRAY_ITERATOR_PROTOTYPE);
774
775  return ecma_op_create_iterator_object (ecma_make_object_value (obj_p),
776                                         prototype_obj_p,
777                                         ECMA_PSEUDO_ARRAY_ITERATOR,
778                                         (uint8_t) type);
779} /* ecma_op_create_array_iterator */
780#endif /* ENABLED (JERRY_ES2015) */
781
782/**
783 * Low level delete of array items from new_length to old_length
784 *
785 * Note: new_length must be less than old_length
786 *
787 * @return the updated value of new_length
788 */
789static uint32_t
790ecma_delete_array_properties (ecma_object_t *object_p, /**< object */
791                              uint32_t new_length, /**< new length */
792                              uint32_t old_length) /**< old length */
793{
794  JERRY_ASSERT (new_length < old_length);
795  JERRY_ASSERT (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_ARRAY);
796
797  if (ecma_op_object_is_fast_array (object_p))
798  {
799    return ecma_delete_fast_array_properties (object_p, new_length);
800  }
801
802  /* First the minimum value of new_length is updated. */
803  jmem_cpointer_t current_prop_cp = object_p->u1.property_list_cp;
804
805  if (current_prop_cp == JMEM_CP_NULL)
806  {
807    return new_length;
808  }
809
810  ecma_property_header_t *current_prop_p;
811
812#if ENABLED (JERRY_PROPRETY_HASHMAP)
813  current_prop_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, current_prop_cp);
814
815  if (current_prop_p->types[0] == ECMA_PROPERTY_TYPE_HASHMAP)
816  {
817    current_prop_cp = current_prop_p->next_property_cp;
818  }
819#endif /* ENABLED (JERRY_PROPRETY_HASHMAP) */
820
821  while (current_prop_cp != JMEM_CP_NULL)
822  {
823    current_prop_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, current_prop_cp);
824    JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (current_prop_p));
825
826    ecma_property_pair_t *prop_pair_p = (ecma_property_pair_t *) current_prop_p;
827
828    for (int i = 0; i < ECMA_PROPERTY_PAIR_ITEM_COUNT; i++)
829    {
830      if (ECMA_PROPERTY_IS_NAMED_PROPERTY (current_prop_p->types[i])
831          && !ecma_is_property_configurable (current_prop_p->types[i]))
832      {
833        uint32_t index = ecma_string_get_property_index (current_prop_p->types[i],
834                                                         prop_pair_p->names_cp[i]);
835
836        if (index < old_length && index >= new_length)
837        {
838          JERRY_ASSERT (index != ECMA_STRING_NOT_ARRAY_INDEX);
839
840          new_length = index + 1;
841
842          if (new_length == old_length)
843          {
844            /* Early return. */
845            return new_length;
846          }
847        }
848      }
849    }
850
851    current_prop_cp = current_prop_p->next_property_cp;
852  }
853
854  /* Second all properties between new_length and old_length are deleted. */
855  current_prop_cp = object_p->u1.property_list_cp;
856  ecma_property_header_t *prev_prop_p = NULL;
857
858#if ENABLED (JERRY_PROPRETY_HASHMAP)
859  JERRY_ASSERT (current_prop_cp != JMEM_CP_NULL);
860
861  ecma_property_hashmap_delete_status hashmap_status = ECMA_PROPERTY_HASHMAP_DELETE_NO_HASHMAP;
862  current_prop_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, current_prop_cp);
863
864  if (current_prop_p->types[0] == ECMA_PROPERTY_TYPE_HASHMAP)
865  {
866    prev_prop_p = current_prop_p;
867    current_prop_cp = current_prop_p->next_property_cp;
868    hashmap_status = ECMA_PROPERTY_HASHMAP_DELETE_HAS_HASHMAP;
869  }
870#endif /* ENABLED (JERRY_PROPRETY_HASHMAP) */
871
872  while (current_prop_cp != JMEM_CP_NULL)
873  {
874    current_prop_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, current_prop_cp);
875
876    JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (current_prop_p));
877    ecma_property_pair_t *prop_pair_p = (ecma_property_pair_t *) current_prop_p;
878
879    for (int i = 0; i < ECMA_PROPERTY_PAIR_ITEM_COUNT; i++)
880    {
881      if (ECMA_PROPERTY_IS_NAMED_PROPERTY (current_prop_p->types[i])
882          && ecma_is_property_configurable (current_prop_p->types[i]))
883      {
884        uint32_t index = ecma_string_get_property_index (current_prop_p->types[i],
885                                                         prop_pair_p->names_cp[i]);
886
887        if (index < old_length && index >= new_length)
888        {
889          JERRY_ASSERT (index != ECMA_STRING_NOT_ARRAY_INDEX);
890
891#if ENABLED (JERRY_PROPRETY_HASHMAP)
892          if (hashmap_status == ECMA_PROPERTY_HASHMAP_DELETE_HAS_HASHMAP)
893          {
894            hashmap_status = ecma_property_hashmap_delete (object_p,
895                                                           prop_pair_p->names_cp[i],
896                                                           current_prop_p->types + i);
897          }
898#endif /* ENABLED (JERRY_PROPRETY_HASHMAP) */
899
900          ecma_free_property (object_p, prop_pair_p->names_cp[i], current_prop_p->types + i);
901          current_prop_p->types[i] = ECMA_PROPERTY_TYPE_DELETED;
902          prop_pair_p->names_cp[i] = LIT_INTERNAL_MAGIC_STRING_DELETED;
903        }
904      }
905    }
906
907    if (current_prop_p->types[0] == ECMA_PROPERTY_TYPE_DELETED
908        && current_prop_p->types[1] == ECMA_PROPERTY_TYPE_DELETED)
909    {
910      if (prev_prop_p == NULL)
911      {
912        object_p->u1.property_list_cp = current_prop_p->next_property_cp;
913      }
914      else
915      {
916        prev_prop_p->next_property_cp = current_prop_p->next_property_cp;
917      }
918
919      jmem_cpointer_t next_prop_cp = current_prop_p->next_property_cp;
920      ecma_dealloc_property_pair ((ecma_property_pair_t *) current_prop_p);
921      current_prop_cp = next_prop_cp;
922    }
923    else
924    {
925      prev_prop_p = current_prop_p;
926      current_prop_cp = current_prop_p->next_property_cp;
927    }
928  }
929
930#if ENABLED (JERRY_PROPRETY_HASHMAP)
931  if (hashmap_status == ECMA_PROPERTY_HASHMAP_DELETE_RECREATE_HASHMAP)
932  {
933    ecma_property_hashmap_free (object_p);
934    ecma_property_hashmap_create (object_p);
935  }
936#endif /* ENABLED (JERRY_PROPRETY_HASHMAP) */
937
938  return new_length;
939} /* ecma_delete_array_properties */
940
941/**
942 * Update the length of an array to a new length
943 *
944 * @return ecma value
945 *         Returned value must be freed with ecma_free_value
946 */
947ecma_value_t
948ecma_op_array_object_set_length (ecma_object_t *object_p, /**< the array object */
949                                 ecma_value_t new_value, /**< new length value */
950                                 uint32_t flags) /**< configuration options */
951{
952  bool is_throw = (flags & ECMA_ARRAY_OBJECT_SET_LENGTH_FLAG_IS_THROW);
953
954  ecma_value_t completion = ecma_op_to_number (new_value);
955
956  if (ECMA_IS_VALUE_ERROR (completion))
957  {
958    return completion;
959  }
960
961  JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (completion)
962                && ecma_is_value_number (completion));
963
964  ecma_number_t new_len_num = ecma_get_number_from_value (completion);
965
966  ecma_free_value (completion);
967
968  if (ecma_is_value_object (new_value))
969  {
970    ecma_value_t compared_num_val = ecma_op_to_number (new_value);
971
972    if (ECMA_IS_VALUE_ERROR (compared_num_val))
973    {
974      return compared_num_val;
975    }
976
977    new_len_num = ecma_get_number_from_value (compared_num_val);
978    ecma_free_value (compared_num_val);
979  }
980
981  uint32_t new_len_uint32 = ecma_number_to_uint32 (new_len_num);
982
983  if (((ecma_number_t) new_len_uint32) != new_len_num)
984  {
985    return ecma_raise_range_error (ECMA_ERR_MSG ("Invalid array length."));
986  }
987
988  if (flags & ECMA_ARRAY_OBJECT_SET_LENGTH_FLAG_REJECT)
989  {
990    return ecma_reject (is_throw);
991  }
992
993  ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p;
994
995  uint32_t old_len_uint32 = ext_object_p->u.array.length;
996
997  if (new_len_num == old_len_uint32)
998  {
999    /* Only the writable flag must be updated. */
1000    if (flags & ECMA_ARRAY_OBJECT_SET_LENGTH_FLAG_WRITABLE_DEFINED)
1001    {
1002      if (!(flags & ECMA_ARRAY_OBJECT_SET_LENGTH_FLAG_WRITABLE))
1003      {
1004        uint8_t new_prop_value = (uint8_t) (ext_object_p->u.array.u.length_prop & ~ECMA_PROPERTY_FLAG_WRITABLE);
1005        ext_object_p->u.array.u.length_prop = new_prop_value;
1006      }
1007      else if (!ecma_is_property_writable (ext_object_p->u.array.u.length_prop))
1008      {
1009        return ecma_reject (is_throw);
1010      }
1011    }
1012    return ECMA_VALUE_TRUE;
1013  }
1014  else if (!ecma_is_property_writable (ext_object_p->u.array.u.length_prop))
1015  {
1016    return ecma_reject (is_throw);
1017  }
1018
1019  uint32_t current_len_uint32 = new_len_uint32;
1020
1021  if (new_len_uint32 < old_len_uint32)
1022  {
1023    current_len_uint32 = ecma_delete_array_properties (object_p, new_len_uint32, old_len_uint32);
1024  }
1025  else if (ecma_op_object_is_fast_array (object_p))
1026  {
1027    ecma_fast_array_set_length (object_p, new_len_uint32);
1028  }
1029
1030  ext_object_p->u.array.length = current_len_uint32;
1031
1032  if ((flags & ECMA_ARRAY_OBJECT_SET_LENGTH_FLAG_WRITABLE_DEFINED)
1033      && !(flags & ECMA_ARRAY_OBJECT_SET_LENGTH_FLAG_WRITABLE))
1034  {
1035    uint8_t new_prop_value = (uint8_t) (ext_object_p->u.array.u.length_prop & ~ECMA_PROPERTY_FLAG_WRITABLE);
1036    ext_object_p->u.array.u.length_prop = new_prop_value;
1037  }
1038
1039  if (current_len_uint32 == new_len_uint32)
1040  {
1041    return ECMA_VALUE_TRUE;
1042  }
1043  return ecma_reject (is_throw);
1044} /* ecma_op_array_object_set_length */
1045
1046/**
1047 * Property descriptor bitset for fast array data properties.
1048 * If the property desciptor fields contains all the flags below
1049 * attempt to stay fast access array during [[DefineOwnProperty]] operation.
1050 */
1051#define ECMA_FAST_ARRAY_DATA_PROP_FLAGS (ECMA_PROP_IS_VALUE_DEFINED \
1052                                         | ECMA_PROP_IS_ENUMERABLE_DEFINED \
1053                                         | ECMA_PROP_IS_ENUMERABLE \
1054                                         | ECMA_PROP_IS_CONFIGURABLE_DEFINED \
1055                                         | ECMA_PROP_IS_CONFIGURABLE \
1056                                         | ECMA_PROP_IS_WRITABLE_DEFINED \
1057                                         | ECMA_PROP_IS_WRITABLE)
1058
1059/**
1060 * [[DefineOwnProperty]] ecma array object's operation
1061 *
1062 * See also:
1063 *          ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8
1064 *          ECMA-262 v5, 15.4.5.1
1065 *
1066 * @return ecma value
1067 *         Returned value must be freed with ecma_free_value
1068 */
1069ecma_value_t
1070ecma_op_array_object_define_own_property (ecma_object_t *object_p, /**< the array object */
1071                                          ecma_string_t *property_name_p, /**< property name */
1072                                          const ecma_property_descriptor_t *property_desc_p) /**< property descriptor */
1073{
1074  if (ecma_string_is_length (property_name_p))
1075  {
1076    JERRY_ASSERT ((property_desc_p->flags & ECMA_PROP_IS_CONFIGURABLE_DEFINED)
1077                  || !(property_desc_p->flags & ECMA_PROP_IS_CONFIGURABLE));
1078    JERRY_ASSERT ((property_desc_p->flags & ECMA_PROP_IS_ENUMERABLE_DEFINED)
1079                  || !(property_desc_p->flags & ECMA_PROP_IS_ENUMERABLE));
1080    JERRY_ASSERT ((property_desc_p->flags & ECMA_PROP_IS_WRITABLE_DEFINED)
1081                  || !(property_desc_p->flags & ECMA_PROP_IS_WRITABLE));
1082
1083    uint32_t flags = 0;
1084
1085    if (property_desc_p->flags & ECMA_PROP_IS_THROW)
1086    {
1087      flags |= ECMA_ARRAY_OBJECT_SET_LENGTH_FLAG_IS_THROW;
1088    }
1089
1090    /* Only the writable and data properties can be modified. */
1091    if (property_desc_p->flags & (ECMA_PROP_IS_CONFIGURABLE
1092                                  | ECMA_PROP_IS_ENUMERABLE
1093                                  | ECMA_PROP_IS_GET_DEFINED
1094                                  | ECMA_PROP_IS_SET_DEFINED))
1095    {
1096      flags |= ECMA_ARRAY_OBJECT_SET_LENGTH_FLAG_REJECT;
1097    }
1098
1099    if (property_desc_p->flags & ECMA_PROP_IS_WRITABLE_DEFINED)
1100    {
1101      flags |= ECMA_ARRAY_OBJECT_SET_LENGTH_FLAG_WRITABLE_DEFINED;
1102    }
1103
1104    if (property_desc_p->flags & ECMA_PROP_IS_WRITABLE)
1105    {
1106      flags |= ECMA_ARRAY_OBJECT_SET_LENGTH_FLAG_WRITABLE;
1107    }
1108
1109    if (property_desc_p->flags & ECMA_PROP_IS_VALUE_DEFINED)
1110    {
1111      return ecma_op_array_object_set_length (object_p, property_desc_p->value, flags);
1112    }
1113
1114    ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p;
1115    ecma_value_t length_value = ecma_make_uint32_value (ext_object_p->u.array.length);
1116
1117    ecma_value_t result = ecma_op_array_object_set_length (object_p, length_value, flags);
1118
1119    ecma_fast_free_value (length_value);
1120    return result;
1121  }
1122
1123  ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p;
1124
1125  if (ecma_op_object_is_fast_array (object_p))
1126  {
1127    if ((property_desc_p->flags & ECMA_FAST_ARRAY_DATA_PROP_FLAGS) == ECMA_FAST_ARRAY_DATA_PROP_FLAGS)
1128    {
1129      uint32_t index = ecma_string_get_array_index (property_name_p);
1130
1131      if (JERRY_UNLIKELY (index == ECMA_STRING_NOT_ARRAY_INDEX))
1132      {
1133        ecma_fast_array_convert_to_normal (object_p);
1134      }
1135      else if (ecma_fast_array_set_property (object_p, index, property_desc_p->value))
1136      {
1137        return ECMA_VALUE_TRUE;
1138      }
1139
1140      JERRY_ASSERT (!ecma_op_array_is_fast_array (ext_object_p));
1141    }
1142    else
1143    {
1144      ecma_fast_array_convert_to_normal (object_p);
1145    }
1146  }
1147
1148  JERRY_ASSERT (!ecma_op_object_is_fast_array (object_p));
1149  uint32_t index = ecma_string_get_array_index (property_name_p);
1150
1151  if (index == ECMA_STRING_NOT_ARRAY_INDEX)
1152  {
1153    return ecma_op_general_object_define_own_property (object_p, property_name_p, property_desc_p);
1154  }
1155
1156  bool update_length = (index >= ext_object_p->u.array.length);
1157
1158  if (update_length && !ecma_is_property_writable (ext_object_p->u.array.u.length_prop))
1159  {
1160    return ecma_reject (property_desc_p->flags & ECMA_PROP_IS_THROW);
1161  }
1162
1163  ecma_property_descriptor_t prop_desc;
1164
1165  prop_desc = *property_desc_p;
1166  prop_desc.flags &= (uint16_t) ~ECMA_PROP_IS_THROW;
1167
1168  ecma_value_t completition = ecma_op_general_object_define_own_property (object_p,
1169                                                                          property_name_p,
1170                                                                          &prop_desc);
1171  JERRY_ASSERT (ecma_is_value_boolean (completition));
1172
1173  if (ecma_is_value_false (completition))
1174  {
1175    return ecma_reject (property_desc_p->flags & ECMA_PROP_IS_THROW);
1176  }
1177
1178  if (update_length)
1179  {
1180    ext_object_p->u.array.length = index + 1;
1181  }
1182
1183  return ECMA_VALUE_TRUE;
1184} /* ecma_op_array_object_define_own_property */
1185
1186/**
1187 * Get the length of the an array object
1188 *
1189 * @return the array length
1190 */
1191extern inline uint32_t JERRY_ATTR_ALWAYS_INLINE
1192ecma_array_get_length (ecma_object_t *array_p) /**< array object */
1193{
1194  JERRY_ASSERT (ecma_get_object_type (array_p) == ECMA_OBJECT_TYPE_ARRAY);
1195
1196  return ((ecma_extended_object_t *) array_p)->u.array.length;
1197} /* ecma_array_get_length */
1198
1199/**
1200 * List names of a String object's lazy instantiated properties
1201 *
1202 * @return string values collection
1203 */
1204void
1205ecma_op_array_list_lazy_property_names (ecma_object_t *obj_p, /**< a String object */
1206                                        uint32_t opts, /**< listing options using flags
1207                                                        *   from ecma_list_properties_options_t */
1208                                        ecma_collection_t *main_collection_p, /**< 'main'  collection */
1209                                        ecma_collection_t *non_enum_collection_p) /**< skipped
1210                                                                                   *   'non-enumerable'
1211                                                                                   *   collection */
1212{
1213  JERRY_ASSERT (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_ARRAY);
1214
1215  ecma_collection_t *for_non_enumerable_p = (opts & ECMA_LIST_ENUMERABLE) ? non_enum_collection_p : main_collection_p;
1216
1217  if ((opts & ECMA_LIST_ARRAY_INDICES) == 0)
1218  {
1219    ecma_collection_push_back (for_non_enumerable_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_LENGTH));
1220  }
1221} /* ecma_op_array_list_lazy_property_names */
1222
1223/**
1224 * @}
1225 * @}
1226 */
1227