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 */
69 ecma_object_t *
ecma_op_new_array_object(ecma_length_t length)70 ecma_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 */
102 inline bool JERRY_ATTR_ALWAYS_INLINE
ecma_op_object_is_fast_array(ecma_object_t * object_p)103 ecma_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 */
115 inline bool JERRY_ATTR_ALWAYS_INLINE
ecma_op_array_is_fast_array(ecma_extended_object_t * array_p)116 ecma_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 */
129 ecma_object_t *
ecma_op_new_fast_array_object(ecma_length_t length)130 ecma_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 */
165 void
ecma_fast_array_convert_to_normal(ecma_object_t * object_p)166 ecma_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 */
235 bool
ecma_fast_array_set_property(ecma_object_t * object_p,uint32_t index,ecma_value_t value)236 ecma_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 */
309 inline uint32_t JERRY_ATTR_ALWAYS_INLINE
ecma_fast_array_get_hole_count(ecma_object_t * obj_p)310 ecma_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 */
322 ecma_value_t *
ecma_fast_array_extend(ecma_object_t * object_p,uint32_t new_length)323 ecma_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 */
369 void
ecma_array_object_delete_property(ecma_object_t * object_p,ecma_string_t * property_name_p,ecma_property_value_t * prop_value_p)370 ecma_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 */
408 uint32_t
ecma_delete_fast_array_properties(ecma_object_t * object_p,uint32_t new_length)409 ecma_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 */
473 static void
ecma_fast_array_set_length(ecma_object_t * object_p,uint32_t new_length)474 ecma_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 */
513 ecma_collection_t *
ecma_fast_array_get_property_names(ecma_object_t * object_p,uint32_t opts)514 ecma_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 */
579 ecma_value_t
ecma_op_create_array_object(const ecma_value_t * arguments_list_p,ecma_length_t arguments_list_len,bool is_treat_single_arg_as_length)580 ecma_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 */
678 ecma_value_t
ecma_op_array_species_create(ecma_object_t * original_array_p,ecma_length_t length)679 ecma_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 */
769 ecma_value_t
ecma_op_create_array_iterator(ecma_object_t * obj_p,ecma_array_iterator_type_t type)770 ecma_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 */
789 static uint32_t
ecma_delete_array_properties(ecma_object_t * object_p,uint32_t new_length,uint32_t old_length)790 ecma_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 */
947 ecma_value_t
ecma_op_array_object_set_length(ecma_object_t * object_p,ecma_value_t new_value,uint32_t flags)948 ecma_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 */
1069 ecma_value_t
ecma_op_array_object_define_own_property(ecma_object_t * object_p,ecma_string_t * property_name_p,const ecma_property_descriptor_t * property_desc_p)1070 ecma_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 */
1191 extern inline uint32_t JERRY_ATTR_ALWAYS_INLINE
ecma_array_get_length(ecma_object_t * array_p)1192 ecma_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 */
1204 void
ecma_op_array_list_lazy_property_names(ecma_object_t * obj_p,uint32_t opts,ecma_collection_t * main_collection_p,ecma_collection_t * non_enum_collection_p)1205 ecma_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