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 /**
17 * Implementation of ECMA-defined conversion routines
18 */
19
20 #include <math.h>
21
22 #include "ecma-alloc.h"
23 #include "ecma-boolean-object.h"
24 #include "ecma-conversion.h"
25 #include "ecma-exceptions.h"
26 #include "ecma-function-object.h"
27 #include "ecma-gc.h"
28 #include "ecma-globals.h"
29 #include "ecma-helpers.h"
30 #include "ecma-number-object.h"
31 #include "ecma-objects.h"
32 #include "ecma-objects-general.h"
33 #include "ecma-string-object.h"
34 #include "ecma-symbol-object.h"
35 #include "ecma-try-catch-macro.h"
36 #include "jrt-libc-includes.h"
37
38 /** \addtogroup ecma ECMA
39 * @{
40 *
41 * \addtogroup ecmaconversion ECMA conversion routines
42 * @{
43 */
44
45 /**
46 * CheckObjectCoercible operation.
47 *
48 * See also:
49 * ECMA-262 v5, 9.10
50 *
51 * @return ecma value
52 * Returned value must be freed with ecma_free_value
53 */
54 ecma_value_t
ecma_op_check_object_coercible(ecma_value_t value)55 ecma_op_check_object_coercible (ecma_value_t value) /**< ecma value */
56 {
57 ecma_check_value_type_is_spec_defined (value);
58
59 if (ecma_is_value_undefined (value)
60 || ecma_is_value_null (value))
61 {
62 return ecma_raise_type_error (ECMA_ERR_MSG ("Argument cannot be converted to an object."));
63 }
64 else
65 {
66 return ECMA_VALUE_EMPTY;
67 }
68 } /* ecma_op_check_object_coercible */
69
70 /**
71 * SameValue operation.
72 *
73 * See also:
74 * ECMA-262 v5, 9.12
75 *
76 * @return true - if the value are same according to ECMA-defined SameValue algorithm,
77 * false - otherwise
78 */
79 bool
ecma_op_same_value(ecma_value_t x,ecma_value_t y)80 ecma_op_same_value (ecma_value_t x, /**< ecma value */
81 ecma_value_t y) /**< ecma value */
82 {
83 if (x == y)
84 {
85 return true;
86 }
87
88 ecma_type_t type_of_x = ecma_get_value_type_field (x);
89
90 if (type_of_x != ecma_get_value_type_field (y)
91 || type_of_x == ECMA_TYPE_DIRECT)
92 {
93 return false;
94 }
95
96 if (ecma_is_value_number (x))
97 {
98 ecma_number_t x_num = ecma_get_number_from_value (x);
99 ecma_number_t y_num = ecma_get_number_from_value (y);
100
101 bool is_x_nan = ecma_number_is_nan (x_num);
102 bool is_y_nan = ecma_number_is_nan (y_num);
103
104 if (is_x_nan || is_y_nan)
105 {
106 return is_x_nan && is_y_nan;
107 }
108
109 if (ecma_number_is_zero (x_num)
110 && ecma_number_is_zero (y_num)
111 && ecma_number_is_negative (x_num) != ecma_number_is_negative (y_num))
112 {
113 return false;
114 }
115
116 return (x_num == y_num);
117 }
118
119 if (ecma_is_value_string (x))
120 {
121 ecma_string_t *x_str_p = ecma_get_string_from_value (x);
122 ecma_string_t *y_str_p = ecma_get_string_from_value (y);
123
124 return ecma_compare_ecma_strings (x_str_p, y_str_p);
125 }
126
127 JERRY_ASSERT (ecma_is_value_object (x) || ECMA_ASSERT_VALUE_IS_SYMBOL (x));
128
129 return false;
130 } /* ecma_op_same_value */
131
132 #if ENABLED (JERRY_ES2015_BUILTIN_MAP)
133 /**
134 * SameValueZero operation.
135 *
136 * See also:
137 * ECMA-262 v6, 7.2.10
138 *
139 * @return true - if the value are same according to ECMA-defined SameValueZero algorithm,
140 * false - otherwise
141 */
142 bool
ecma_op_same_value_zero(ecma_value_t x,ecma_value_t y)143 ecma_op_same_value_zero (ecma_value_t x, /**< ecma value */
144 ecma_value_t y) /**< ecma value */
145 {
146 if (ecma_is_value_number (x) && ecma_is_value_number (y))
147 {
148 ecma_number_t x_num = ecma_get_number_from_value (x);
149 ecma_number_t y_num = ecma_get_number_from_value (y);
150
151 bool is_x_nan = ecma_number_is_nan (x_num);
152 bool is_y_nan = ecma_number_is_nan (y_num);
153
154 if (is_x_nan || is_y_nan)
155 {
156 /*
157 * If both are NaN
158 * return true;
159 * else
160 * one of the numbers is NaN, and another - is not
161 * return false;
162 */
163 return (is_x_nan && is_y_nan);
164 }
165
166 if (ecma_number_is_zero (x_num)
167 && ecma_number_is_zero (y_num)
168 && ecma_number_is_negative (x_num) != ecma_number_is_negative (y_num))
169 {
170 return true;
171 }
172
173 return (x_num == y_num);
174 }
175
176 return ecma_op_same_value (x, y);
177 } /* ecma_op_same_value_zero */
178 #endif /* ENABLED (JERRY_ES2015_BUILTIN_MAP) */
179
180 /**
181 * ToPrimitive operation.
182 *
183 * See also:
184 * ECMA-262 v5, 9.1
185 *
186 * @return ecma value
187 * Returned value must be freed with ecma_free_value
188 */
189 ecma_value_t
ecma_op_to_primitive(ecma_value_t value,ecma_preferred_type_hint_t preferred_type)190 ecma_op_to_primitive (ecma_value_t value, /**< ecma value */
191 ecma_preferred_type_hint_t preferred_type) /**< preferred type hint */
192 {
193 ecma_check_value_type_is_spec_defined (value);
194
195 if (ecma_is_value_object (value))
196 {
197 ecma_object_t *obj_p = ecma_get_object_from_value (value);
198
199 return ecma_op_object_default_value (obj_p, preferred_type);
200 }
201 else
202 {
203 return ecma_copy_value (value);
204 }
205 } /* ecma_op_to_primitive */
206
207 /**
208 * ToBoolean operation. Cannot throw an exception.
209 *
210 * See also:
211 * ECMA-262 v5, 9.2
212 *
213 * @return true - if the logical value is true
214 * false - otherwise
215 */
216 bool
ecma_op_to_boolean(ecma_value_t value)217 ecma_op_to_boolean (ecma_value_t value) /**< ecma value */
218 {
219 ecma_check_value_type_is_spec_defined (value);
220
221 if (ecma_is_value_simple (value))
222 {
223 JERRY_ASSERT (ecma_is_value_boolean (value)
224 || ecma_is_value_undefined (value)
225 || ecma_is_value_null (value));
226
227 return ecma_is_value_true (value);
228 }
229
230 if (ecma_is_value_integer_number (value))
231 {
232 return (value != ecma_make_integer_value (0));
233 }
234
235 if (ecma_is_value_float_number (value))
236 {
237 ecma_number_t num = ecma_get_float_from_value (value);
238
239 return (!ecma_number_is_nan (num) && !ecma_number_is_zero (num));
240 }
241
242 if (ecma_is_value_string (value))
243 {
244 ecma_string_t *str_p = ecma_get_string_from_value (value);
245
246 return !ecma_string_is_empty (str_p);
247 }
248
249 JERRY_ASSERT (ecma_is_value_object (value) || ECMA_ASSERT_VALUE_IS_SYMBOL (value));
250
251 return true;
252 } /* ecma_op_to_boolean */
253
254 /**
255 * ToNumber operation.
256 *
257 * See also:
258 * ECMA-262 v5, 9.3
259 *
260 * @return ecma value
261 * Returned value must be freed with ecma_free_value
262 */
263 ecma_value_t
ecma_op_to_number(ecma_value_t value)264 ecma_op_to_number (ecma_value_t value) /**< ecma value */
265 {
266 ecma_check_value_type_is_spec_defined (value);
267
268 if (ecma_is_value_integer_number (value))
269 {
270 return value;
271 }
272
273 if (ecma_is_value_float_number (value))
274 {
275 return ecma_copy_value (value);
276 }
277
278 if (ecma_is_value_string (value))
279 {
280 ecma_string_t *str_p = ecma_get_string_from_value (value);
281 return ecma_make_number_value (ecma_string_to_number (str_p));
282 }
283 #if ENABLED (JERRY_ES2015)
284 if (ecma_is_value_symbol (value))
285 {
286 return ecma_raise_type_error (ECMA_ERR_MSG ("Cannot convert a Symbol value to a number."));
287 }
288 #endif /* ENABLED (JERRY_ES2015) */
289
290 if (ecma_is_value_object (value))
291 {
292 ecma_value_t primitive_value = ecma_op_to_primitive (value, ECMA_PREFERRED_TYPE_NUMBER);
293
294 if (ECMA_IS_VALUE_ERROR (primitive_value))
295 {
296 return primitive_value;
297 }
298
299 ecma_value_t ret_value = ecma_op_to_number (primitive_value);
300 ecma_fast_free_value (primitive_value);
301 return ret_value;
302 }
303
304 if (ecma_is_value_undefined (value))
305 {
306 return ecma_make_nan_value ();
307 }
308
309 ecma_integer_value_t num = 0;
310
311 if (ecma_is_value_null (value))
312 {
313 num = 0;
314 }
315 else
316 {
317 JERRY_ASSERT (ecma_is_value_boolean (value));
318
319 num = ecma_is_value_true (value) ? 1 : 0;
320 }
321
322 return ecma_make_integer_value (num);
323 } /* ecma_op_to_number */
324
325 /**
326 * Helper to get the number contained in an ecma value.
327 *
328 * See also:
329 * ECMA-262 v5, 9.3
330 *
331 * @return ECMA_VALUE_EMPTY if successful
332 * conversion error otherwise
333 * Returned value must be freed with ecma_free_value
334 */
335 ecma_value_t
ecma_get_number(ecma_value_t value,ecma_number_t * number_p)336 ecma_get_number (ecma_value_t value, /**< ecma value*/
337 ecma_number_t *number_p) /**< [out] ecma number */
338 {
339 if (ecma_is_value_integer_number (value))
340 {
341 *number_p = ecma_get_integer_from_value (value);
342 return ECMA_VALUE_EMPTY;
343 }
344
345 if (ecma_is_value_float_number (value))
346 {
347 *number_p = ecma_get_float_from_value (value);
348 return ECMA_VALUE_EMPTY;
349 }
350
351 if (ecma_is_value_string (value))
352 {
353 ecma_string_t *str_p = ecma_get_string_from_value (value);
354 *number_p = ecma_string_to_number (str_p);
355 return ECMA_VALUE_EMPTY;
356 }
357
358 if (ecma_is_value_object (value))
359 {
360 ecma_value_t primitive_value = ecma_op_to_primitive (value, ECMA_PREFERRED_TYPE_NUMBER);
361
362 if (ECMA_IS_VALUE_ERROR (primitive_value))
363 {
364 return primitive_value;
365 }
366
367 ecma_value_t ret_value = ecma_get_number (primitive_value, number_p);
368 ecma_fast_free_value (primitive_value);
369 return ret_value;
370 }
371
372 if (ecma_is_value_undefined (value))
373 {
374 *number_p = ecma_number_make_nan ();
375 return ECMA_VALUE_EMPTY;
376 }
377
378 if (ecma_is_value_null (value))
379 {
380 *number_p = 0;
381 return ECMA_VALUE_EMPTY;
382 }
383
384 #if ENABLED (JERRY_ES2015)
385 if (ecma_is_value_symbol (value))
386 {
387 return ecma_raise_type_error (ECMA_ERR_MSG ("Cannot convert a Symbol value to a number."));
388 }
389 #endif /* ENABLED (JERRY_ES2015) */
390
391 JERRY_ASSERT (ecma_is_value_boolean (value));
392
393 *number_p = ecma_is_value_true (value) ? 1 : 0;
394 return ECMA_VALUE_EMPTY;
395 } /* ecma_get_number */
396
397 /**
398 * ToString operation.
399 *
400 * See also:
401 * ECMA-262 v5, 9.8
402 *
403 * @return NULL - if the conversion fails
404 * pointer to the string descriptor - otherwise
405 */
406 ecma_string_t *
ecma_op_to_string(ecma_value_t value)407 ecma_op_to_string (ecma_value_t value) /**< ecma value */
408 {
409 ecma_check_value_type_is_spec_defined (value);
410
411 if (JERRY_UNLIKELY (ecma_is_value_object (value)))
412 {
413 ecma_value_t prim_value = ecma_op_to_primitive (value, ECMA_PREFERRED_TYPE_STRING);
414
415 if (ECMA_IS_VALUE_ERROR (prim_value))
416 {
417 return NULL;
418 }
419
420 ecma_string_t *ret_string_p = ecma_op_to_string (prim_value);
421
422 ecma_free_value (prim_value);
423
424 return ret_string_p;
425 }
426
427 if (ecma_is_value_string (value))
428 {
429 ecma_string_t *res_p = ecma_get_string_from_value (value);
430 ecma_ref_ecma_string (res_p);
431 return res_p;
432 }
433 else if (ecma_is_value_integer_number (value))
434 {
435 ecma_integer_value_t num = ecma_get_integer_from_value (value);
436
437 if (num < 0)
438 {
439 return ecma_new_ecma_string_from_number ((ecma_number_t) num);
440 }
441 else
442 {
443 return ecma_new_ecma_string_from_uint32 ((uint32_t) num);
444 }
445 }
446 else if (ecma_is_value_float_number (value))
447 {
448 ecma_number_t num = ecma_get_float_from_value (value);
449 return ecma_new_ecma_string_from_number (num);
450 }
451 else if (ecma_is_value_undefined (value))
452 {
453 return ecma_get_magic_string (LIT_MAGIC_STRING_UNDEFINED);
454 }
455 else if (ecma_is_value_null (value))
456 {
457 return ecma_get_magic_string (LIT_MAGIC_STRING_NULL);
458 }
459 #if ENABLED (JERRY_ES2015)
460 else if (ecma_is_value_symbol (value))
461 {
462 ecma_raise_type_error (ECMA_ERR_MSG ("Cannot convert a Symbol value to a string."));
463 return NULL;
464 }
465 #endif /* ENABLED (JERRY_ES2015) */
466 JERRY_ASSERT (ecma_is_value_boolean (value));
467
468 if (ecma_is_value_true (value))
469 {
470 return ecma_get_magic_string (LIT_MAGIC_STRING_TRUE);
471 }
472
473 return ecma_get_magic_string (LIT_MAGIC_STRING_FALSE);
474 } /* ecma_op_to_string */
475
476 /**
477 * ToPropertyName operation.
478 *
479 * @return NULL - if the conversion fails
480 * ecma-string - otherwise
481 */
482 ecma_string_t *
ecma_op_to_prop_name(ecma_value_t value)483 ecma_op_to_prop_name (ecma_value_t value) /**< ecma value */
484 {
485 ecma_check_value_type_is_spec_defined (value);
486
487 #if ENABLED (JERRY_ES2015)
488 if (ecma_is_value_symbol (value))
489 {
490 ecma_string_t *symbol_p = ecma_get_symbol_from_value (value);
491 ecma_ref_ecma_string (symbol_p);
492 return symbol_p;
493 }
494 #endif /* ENABLED (JERRY_ES2015) */
495
496 return ecma_op_to_string (value);
497 } /* ecma_op_to_prop_name */
498
499 /**
500 * ToObject operation.
501 *
502 * See also:
503 * ECMA-262 v5, 9.9
504 *
505 * @return ecma value
506 * Returned value must be freed with ecma_free_value
507 */
508 ecma_value_t
ecma_op_to_object(ecma_value_t value)509 ecma_op_to_object (ecma_value_t value) /**< ecma value */
510 {
511 ecma_check_value_type_is_spec_defined (value);
512
513 if (ecma_is_value_number (value))
514 {
515 return ecma_op_create_number_object (value);
516 }
517 else if (ecma_is_value_string (value))
518 {
519 return ecma_op_create_string_object (&value, 1);
520 }
521 else if (ecma_is_value_object (value))
522 {
523 return ecma_copy_value (value);
524 }
525 #if ENABLED (JERRY_ES2015)
526 else if (ecma_is_value_symbol (value))
527 {
528 return ecma_op_create_symbol_object (value);
529 }
530 #endif /* ENABLED (JERRY_ES2015) */
531 else
532 {
533 if (ecma_is_value_undefined (value)
534 || ecma_is_value_null (value))
535 {
536 return ecma_raise_type_error (ECMA_ERR_MSG ("Argument cannot be converted to an object."));
537 }
538 else
539 {
540 JERRY_ASSERT (ecma_is_value_boolean (value));
541
542 return ecma_op_create_boolean_object (value);
543 }
544 }
545 } /* ecma_op_to_object */
546
547 /**
548 * FromPropertyDescriptor operation.
549 *
550 * See also:
551 * ECMA-262 v5, 8.10.4
552 *
553 * @return constructed object
554 */
555 ecma_object_t *
ecma_op_from_property_descriptor(const ecma_property_descriptor_t * src_prop_desc_p)556 ecma_op_from_property_descriptor (const ecma_property_descriptor_t *src_prop_desc_p) /**< property descriptor */
557 {
558 /* 2. */
559 ecma_object_t *obj_p = ecma_op_create_object_object_noarg ();
560
561 ecma_value_t completion;
562 ecma_property_descriptor_t prop_desc = ecma_make_empty_property_descriptor ();
563 {
564 prop_desc.flags = (ECMA_PROP_IS_VALUE_DEFINED
565 | ECMA_PROP_IS_WRITABLE_DEFINED
566 | ECMA_PROP_IS_WRITABLE
567 | ECMA_PROP_IS_ENUMERABLE_DEFINED
568 | ECMA_PROP_IS_ENUMERABLE
569 | ECMA_PROP_IS_CONFIGURABLE_DEFINED
570 | ECMA_PROP_IS_CONFIGURABLE);
571 }
572
573 /* 3. */
574 if (src_prop_desc_p->flags & (ECMA_PROP_IS_VALUE_DEFINED | ECMA_PROP_IS_WRITABLE_DEFINED))
575 {
576 JERRY_ASSERT ((prop_desc.flags & (ECMA_PROP_IS_VALUE_DEFINED | ECMA_PROP_IS_WRITABLE_DEFINED))
577 == (ECMA_PROP_IS_VALUE_DEFINED | ECMA_PROP_IS_WRITABLE_DEFINED));
578
579 /* a. */
580 prop_desc.value = src_prop_desc_p->value;
581
582 completion = ecma_op_object_define_own_property (obj_p,
583 ecma_get_magic_string (LIT_MAGIC_STRING_VALUE),
584 &prop_desc);
585 JERRY_ASSERT (ecma_is_value_true (completion));
586
587 /* b. */
588 prop_desc.value = ecma_make_boolean_value (src_prop_desc_p->flags & ECMA_PROP_IS_WRITABLE);
589
590 completion = ecma_op_object_define_own_property (obj_p,
591 ecma_get_magic_string (LIT_MAGIC_STRING_WRITABLE),
592 &prop_desc);
593 JERRY_ASSERT (ecma_is_value_true (completion));
594 }
595 else
596 {
597 #if !ENABLED (JERRY_ES2015)
598 JERRY_ASSERT (src_prop_desc_p->flags & (ECMA_PROP_IS_GET_DEFINED | ECMA_PROP_IS_SET_DEFINED));
599 #else /* ENABLED (JERRY_ES2015) */
600 if (src_prop_desc_p->flags & (ECMA_PROP_IS_GET_DEFINED | ECMA_PROP_IS_SET_DEFINED))
601 #endif /* ENABLED (JERRY_ES2015) */
602 {
603 /* a. */
604 if (src_prop_desc_p->get_p == NULL)
605 {
606 prop_desc.value = ECMA_VALUE_UNDEFINED;
607 }
608 else
609 {
610 prop_desc.value = ecma_make_object_value (src_prop_desc_p->get_p);
611 }
612
613 completion = ecma_op_object_define_own_property (obj_p,
614 ecma_get_magic_string (LIT_MAGIC_STRING_GET),
615 &prop_desc);
616 JERRY_ASSERT (ecma_is_value_true (completion));
617
618 /* b. */
619 if (src_prop_desc_p->set_p == NULL)
620 {
621 prop_desc.value = ECMA_VALUE_UNDEFINED;
622 }
623 else
624 {
625 prop_desc.value = ecma_make_object_value (src_prop_desc_p->set_p);
626 }
627
628 completion = ecma_op_object_define_own_property (obj_p,
629 ecma_get_magic_string (LIT_MAGIC_STRING_SET),
630 &prop_desc);
631 JERRY_ASSERT (ecma_is_value_true (completion));
632 }
633 }
634
635 prop_desc.value = ecma_make_boolean_value (src_prop_desc_p->flags & ECMA_PROP_IS_ENUMERABLE);
636
637 completion = ecma_op_object_define_own_property (obj_p,
638 ecma_get_magic_string (LIT_MAGIC_STRING_ENUMERABLE),
639 &prop_desc);
640 JERRY_ASSERT (ecma_is_value_true (completion));
641
642 prop_desc.value = ecma_make_boolean_value (src_prop_desc_p->flags & ECMA_PROP_IS_CONFIGURABLE);
643
644 completion = ecma_op_object_define_own_property (obj_p,
645 ecma_get_magic_string (LIT_MAGIC_STRING_CONFIGURABLE),
646 &prop_desc);
647 JERRY_ASSERT (ecma_is_value_true (completion));
648
649 return obj_p;
650 } /* ecma_op_from_property_descriptor */
651
652 /**
653 * ToPropertyDescriptor operation.
654 *
655 * See also:
656 * ECMA-262 v5, 8.10.5
657 *
658 * @return ecma value
659 * Returned value must be freed with ecma_free_value
660 */
661 ecma_value_t
ecma_op_to_property_descriptor(ecma_value_t obj_value,ecma_property_descriptor_t * out_prop_desc_p)662 ecma_op_to_property_descriptor (ecma_value_t obj_value, /**< object value */
663 ecma_property_descriptor_t *out_prop_desc_p) /**< [out] filled property descriptor
664 if return value is normal
665 empty completion value */
666 {
667 ecma_value_t ret_value = ECMA_VALUE_EMPTY;
668
669 /* 1. */
670 if (!ecma_is_value_object (obj_value))
671 {
672 ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("Expected an object."));
673 }
674 else
675 {
676 ecma_object_t *obj_p = ecma_get_object_from_value (obj_value);
677
678 /* 2. */
679 ecma_property_descriptor_t prop_desc = ecma_make_empty_property_descriptor ();
680
681 /* 3. */
682 ECMA_TRY_CATCH (enumerable_prop_value,
683 ecma_op_object_find (obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_ENUMERABLE)),
684 ret_value);
685
686 if (ecma_is_value_found (enumerable_prop_value))
687 {
688 uint32_t is_enumerable = (ecma_op_to_boolean (enumerable_prop_value) ? ECMA_PROP_IS_ENUMERABLE
689 : ECMA_PROP_NO_OPTS);
690
691 prop_desc.flags |= (uint16_t) (ECMA_PROP_IS_ENUMERABLE_DEFINED | is_enumerable);
692 }
693
694 ECMA_FINALIZE (enumerable_prop_value);
695
696 if (!ECMA_IS_VALUE_ERROR (ret_value))
697 {
698 JERRY_ASSERT (ecma_is_value_empty (ret_value));
699
700 /* 4. */
701 ECMA_TRY_CATCH (configurable_prop_value,
702 ecma_op_object_find (obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_CONFIGURABLE)),
703 ret_value);
704
705 if (ecma_is_value_found (configurable_prop_value))
706 {
707 uint32_t is_configurable = (ecma_op_to_boolean (configurable_prop_value) ? ECMA_PROP_IS_CONFIGURABLE
708 : ECMA_PROP_NO_OPTS);
709
710 prop_desc.flags |= (uint16_t) (ECMA_PROP_IS_CONFIGURABLE_DEFINED | is_configurable);
711 }
712
713 ECMA_FINALIZE (configurable_prop_value);
714 }
715
716 if (!ECMA_IS_VALUE_ERROR (ret_value))
717 {
718 JERRY_ASSERT (ecma_is_value_empty (ret_value));
719
720 /* 5. */
721 ECMA_TRY_CATCH (value_prop_value,
722 ecma_op_object_find (obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_VALUE)),
723 ret_value);
724
725 if (ecma_is_value_found (value_prop_value))
726 {
727 prop_desc.flags |= ECMA_PROP_IS_VALUE_DEFINED;
728 prop_desc.value = ecma_copy_value (value_prop_value);
729 }
730
731 ECMA_FINALIZE (value_prop_value);
732 }
733
734 if (!ECMA_IS_VALUE_ERROR (ret_value))
735 {
736 JERRY_ASSERT (ecma_is_value_empty (ret_value));
737
738 /* 6. */
739 ECMA_TRY_CATCH (writable_prop_value,
740 ecma_op_object_find (obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_WRITABLE)),
741 ret_value);
742
743 if (ecma_is_value_found (writable_prop_value))
744 {
745 uint32_t is_writable = (ecma_op_to_boolean (writable_prop_value) ? ECMA_PROP_IS_WRITABLE
746 : ECMA_PROP_NO_OPTS);
747
748 prop_desc.flags |= (uint16_t) (ECMA_PROP_IS_WRITABLE_DEFINED | is_writable);
749 }
750
751 ECMA_FINALIZE (writable_prop_value);
752 }
753
754 if (!ECMA_IS_VALUE_ERROR (ret_value))
755 {
756 JERRY_ASSERT (ecma_is_value_empty (ret_value));
757
758 /* 7. */
759 ECMA_TRY_CATCH (get_prop_value,
760 ecma_op_object_find (obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_GET)),
761 ret_value);
762
763 if (ecma_is_value_found (get_prop_value))
764 {
765 if (!ecma_op_is_callable (get_prop_value)
766 && !ecma_is_value_undefined (get_prop_value))
767 {
768 ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("Expected a function."));
769 }
770 else
771 {
772 prop_desc.flags |= ECMA_PROP_IS_GET_DEFINED;
773
774 if (ecma_is_value_undefined (get_prop_value))
775 {
776 prop_desc.get_p = NULL;
777 }
778 else
779 {
780 JERRY_ASSERT (ecma_is_value_object (get_prop_value));
781
782 ecma_object_t *get_p = ecma_get_object_from_value (get_prop_value);
783 ecma_ref_object (get_p);
784
785 prop_desc.get_p = get_p;
786 }
787 }
788 }
789
790 ECMA_FINALIZE (get_prop_value);
791 }
792
793 if (!ECMA_IS_VALUE_ERROR (ret_value))
794 {
795 JERRY_ASSERT (ecma_is_value_empty (ret_value));
796
797 /* 8. */
798 ECMA_TRY_CATCH (set_prop_value,
799 ecma_op_object_find (obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_SET)),
800 ret_value);
801
802 if (ecma_is_value_found (set_prop_value))
803 {
804 if (!ecma_op_is_callable (set_prop_value)
805 && !ecma_is_value_undefined (set_prop_value))
806 {
807 ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("Expected a function."));
808 }
809 else
810 {
811 prop_desc.flags |= ECMA_PROP_IS_SET_DEFINED;
812
813 if (ecma_is_value_undefined (set_prop_value))
814 {
815 prop_desc.set_p = NULL;
816 }
817 else
818 {
819 JERRY_ASSERT (ecma_is_value_object (set_prop_value));
820
821 ecma_object_t *set_p = ecma_get_object_from_value (set_prop_value);
822 ecma_ref_object (set_p);
823
824 prop_desc.set_p = set_p;
825 }
826 }
827 }
828
829 ECMA_FINALIZE (set_prop_value);
830 }
831
832 if (!ECMA_IS_VALUE_ERROR (ret_value))
833 {
834 JERRY_ASSERT (ecma_is_value_empty (ret_value));
835
836 /* 9. */
837 if ((prop_desc.flags & (ECMA_PROP_IS_VALUE_DEFINED | ECMA_PROP_IS_WRITABLE_DEFINED))
838 && (prop_desc.flags & (ECMA_PROP_IS_GET_DEFINED | ECMA_PROP_IS_SET_DEFINED)))
839 {
840 ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("Accessors cannot be writable."));
841 }
842 }
843
844 if (!ECMA_IS_VALUE_ERROR (ret_value))
845 {
846 JERRY_ASSERT (ecma_is_value_empty (ret_value));
847 }
848 else
849 {
850 ecma_free_property_descriptor (&prop_desc);
851 }
852
853 *out_prop_desc_p = prop_desc;
854 }
855
856 return ret_value;
857 } /* ecma_op_to_property_descriptor */
858
859 /**
860 * ToInteger operation.
861 *
862 * See also:
863 * ECMA-262 v5, 9.4
864 * ECMA-262 v6, 7.1.4
865 *
866 * @return ECMA_VALUE_EMPTY if successful
867 * conversion error otherwise
868 */
869 ecma_value_t
ecma_op_to_integer(ecma_value_t value,ecma_number_t * number_p)870 ecma_op_to_integer (ecma_value_t value, /**< ecma value */
871 ecma_number_t *number_p) /**< [out] ecma number */
872 {
873 if (ECMA_IS_VALUE_ERROR (value))
874 {
875 return value;
876 }
877
878 /* 1 */
879 ecma_value_t to_number = ecma_get_number (value, number_p);
880
881 /* 2 */
882 if (ECMA_IS_VALUE_ERROR (to_number))
883 {
884 return to_number;
885 }
886
887 ecma_number_t number = *number_p;
888
889 /* 3 */
890 if (ecma_number_is_nan (number))
891 {
892 *number_p = ECMA_NUMBER_ZERO;
893 return ECMA_VALUE_EMPTY;
894 }
895
896 /* 4 */
897 if (ecma_number_is_zero (number) || ecma_number_is_infinity (number))
898 {
899 return ECMA_VALUE_EMPTY;
900 }
901
902 ecma_number_t floor_fabs = floor (fabs (number));
903
904 /* 5 */
905 *number_p = ecma_number_is_negative (number) ? -floor_fabs : floor_fabs;
906 return ECMA_VALUE_EMPTY;
907 } /* ecma_op_to_integer */
908
909 /**
910 * ToLength operation.
911 *
912 * See also:
913 * ECMA-262 v6, 7.1.15
914 *
915 * @return ECMA_VALUE_EMPTY if successful
916 * conversion error otherwise
917 */
918 ecma_value_t
ecma_op_to_length(ecma_value_t value,uint32_t * length)919 ecma_op_to_length (ecma_value_t value, /**< ecma value */
920 uint32_t *length) /**< [out] ecma number */
921 {
922 /* 1 */
923 if (ECMA_IS_VALUE_ERROR (value))
924 {
925 return value;
926 }
927
928 #if ENABLED (JERRY_ES2015)
929 /* 2 */
930 ecma_number_t num;
931 ecma_value_t length_num = ecma_op_to_integer (value, &num);
932
933 /* 3 */
934 if (ECMA_IS_VALUE_ERROR (length_num))
935 {
936 return length_num;
937 }
938
939 /* 4 */
940 if (num <= 0.0f)
941 {
942 *length = 0;
943 return ECMA_VALUE_EMPTY;
944 }
945
946 /* 5 */
947 if (num >= (ecma_number_t) UINT32_MAX)
948 {
949 *length = UINT32_MAX;
950 return ECMA_VALUE_EMPTY;
951 }
952
953 /* 6 */
954 *length = (uint32_t) num;
955 return ECMA_VALUE_EMPTY;
956 #else /* !ENABLED (JERRY_ES2015) */
957 /* In the case of ES5, ToLength(ES6) operation is the same as ToUint32(ES5) */
958 ecma_number_t num;
959 ecma_value_t to_number = ecma_get_number (value, &num);
960
961 /* 2 */
962 if (ECMA_IS_VALUE_ERROR (to_number))
963 {
964 return to_number;
965 }
966
967 *length = ecma_number_to_uint32 (num);
968 return ECMA_VALUE_EMPTY;
969 #endif /* ENABLED (JERRY_ES2015) */
970 } /* ecma_op_to_length */
971
972 #if ENABLED (JERRY_ES2015)
973 /**
974 * CreateListFromArrayLike operation.
975 * Different types are not handled yet.
976 *
977 * See also:
978 * ECMA-262 v6, 7.3.17
979 *
980 * @return ecma_collection_t if successful
981 * NULL otherwise
982 */
983 ecma_collection_t *
ecma_op_create_list_from_array_like(ecma_value_t arr,bool prop_names_only)984 ecma_op_create_list_from_array_like (ecma_value_t arr, /**< array value */
985 bool prop_names_only) /**< true - accept only property names
986 false - otherwise */
987 {
988 /* 1. */
989 JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (arr));
990
991 /* 3. */
992 if (!ecma_is_value_object (arr))
993 {
994 ecma_raise_type_error (ECMA_ERR_MSG ("Argument is not an Object."));
995 return NULL;
996 }
997 ecma_object_t *obj_p = ecma_get_object_from_value (arr);
998
999 /* 4. 5. */
1000 ecma_length_t len;
1001 if (ECMA_IS_VALUE_ERROR (ecma_op_object_get_length (obj_p, &len)))
1002 {
1003 return NULL;
1004 }
1005
1006 /* 6. */
1007 ecma_collection_t *list_ptr = ecma_new_collection ();
1008
1009 /* 7. 8. */
1010 for (uint32_t idx = 0; idx < len; idx++)
1011 {
1012 ecma_value_t next = ecma_op_object_get_by_uint32_index (obj_p, idx);
1013 if (ECMA_IS_VALUE_ERROR (next))
1014 {
1015 ecma_collection_free (list_ptr);
1016 return NULL;
1017 }
1018
1019 if (prop_names_only
1020 && !ecma_is_value_prop_name (next))
1021 {
1022 ecma_free_value (next);
1023 ecma_collection_free (list_ptr);
1024 ecma_raise_type_error (ECMA_ERR_MSG ("Property name is neither Symbol nor String."));
1025 return NULL;
1026 }
1027
1028 ecma_collection_push_back (list_ptr, next);
1029 }
1030
1031 /* 9. */
1032 return list_ptr;
1033 } /* ecma_op_create_list_from_array_like */
1034 #endif /* ENABLED (JERRY_ES2015) */
1035
1036 /**
1037 * @}
1038 * @}
1039 */
1040