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 */ 54ecma_value_t 55ecma_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 */ 79bool 80ecma_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 */ 142bool 143ecma_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 */ 189ecma_value_t 190ecma_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 */ 216bool 217ecma_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 */ 263ecma_value_t 264ecma_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 */ 335ecma_value_t 336ecma_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 */ 406ecma_string_t * 407ecma_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 */ 482ecma_string_t * 483ecma_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 */ 508ecma_value_t 509ecma_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 */ 555ecma_object_t * 556ecma_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 */ 661ecma_value_t 662ecma_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 */ 869ecma_value_t 870ecma_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 */ 918ecma_value_t 919ecma_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 */ 983ecma_collection_t * 984ecma_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