• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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