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