From f4f9cde3e70508c1fe8a34f3dec3782c4e6d095d Mon Sep 17 00:00:00 2001 From: Zoltan Herczeg Date: Fri, 7 Aug 2020 14:32:46 +0200 Subject: [PATCH] Fix evaluation order for binary operators (#4114) Furthermore fix toBoolean for BigInts as well. JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com --- jerry-core/ecma/base/ecma-helpers-number.c | 2 +- .../ecma-builtin-array-prototype.c | 2 +- .../ecma/builtin-objects/ecma-builtin-date.c | 2 +- .../builtin-objects/ecma-builtin-global.c | 2 +- .../builtin-objects/ecma-builtin-helpers.c | 2 +- .../ecma-builtin-string-prototype.c | 2 +- .../ecma-builtin-typedarray-prototype.c | 10 +- .../typedarray/ecma-builtin-typedarray.c | 2 +- jerry-core/ecma/operations/ecma-bigint.c | 40 ++++++ jerry-core/ecma/operations/ecma-bigint.h | 1 + jerry-core/ecma/operations/ecma-conversion.c | 38 +++-- jerry-core/ecma/operations/ecma-conversion.h | 11 +- .../ecma/operations/ecma-dataview-object.c | 2 +- jerry-core/ecma/operations/ecma-objects.c | 2 +- .../ecma/operations/ecma-regexp-object.c | 2 +- .../ecma/operations/ecma-try-catch-macro.h | 2 +- .../ecma/operations/ecma-typedarray-object.c | 4 +- jerry-core/vm/opcodes-ecma-arithmetics.c | 131 ++++++------------ jerry-core/vm/opcodes-ecma-bitwise.c | 77 ++++------ tests/jerry/es.next/arithmetics-3.js | 37 +++++ tests/jerry/es.next/bigint4.js | 6 + tests/test262-esnext-excludelist.xml | 14 -- 22 files changed, 211 insertions(+), 180 deletions(-) create mode 100644 tests/jerry/es.next/arithmetics-3.js diff --git a/jerry-core/ecma/base/ecma-helpers-number.c b/jerry-core/ecma/base/ecma-helpers-number.c index b3d968f3b..9ebcbbe09 100644 --- a/jerry-core/ecma/base/ecma-helpers-number.c +++ b/jerry-core/ecma/base/ecma-helpers-number.c @@ -765,7 +765,7 @@ ecma_number_parse_int (const lit_utf8_byte_t *string_buff, /**< routine's first /* 6. */ ecma_number_t radix_num; - radix = ecma_get_number (radix, &radix_num); + radix = ecma_op_to_numeric (radix, &radix_num, ECMA_TO_NUMERIC_NO_OPTS); if (!ecma_is_value_empty (radix)) { diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype.c b/jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype.c index 80e8f2b05..f21df35c2 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype.c @@ -1070,7 +1070,7 @@ ecma_builtin_array_prototype_object_sort_compare_helper (ecma_value_t lhs, /**< { ecma_number_t ret_num; - if (ECMA_IS_VALUE_ERROR (ecma_get_number (call_value, &ret_num))) + if (ECMA_IS_VALUE_ERROR (ecma_op_to_numeric (call_value, &ret_num, ECMA_TO_NUMERIC_NO_OPTS))) { ecma_free_value (call_value); return ECMA_VALUE_ERROR; diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-date.c b/jerry-core/ecma/builtin-objects/ecma-builtin-date.c index f452be54e..edd5da054 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-date.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-date.c @@ -213,7 +213,7 @@ ecma_date_construct_helper (const ecma_value_t *args, /**< arguments passed to t /* 1-7. */ for (uint32_t i = 0; i < args_len; i++) { - ecma_value_t status = ecma_get_number (args[i], date_nums + i); + ecma_value_t status = ecma_op_to_numeric (args[i], date_nums + i, ECMA_TO_NUMERIC_NO_OPTS); if (ECMA_IS_VALUE_ERROR (status)) { diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-global.c b/jerry-core/ecma/builtin-objects/ecma-builtin-global.c index 326996073..c010ebca5 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-global.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-global.c @@ -612,7 +612,7 @@ ecma_builtin_global_dispatch_routine (uint16_t builtin_routine_id, /**< built-in { ecma_number_t arg_num; - routine_arg_1 = ecma_get_number (routine_arg_1, &arg_num); + routine_arg_1 = ecma_op_to_numeric (routine_arg_1, &arg_num, ECMA_TO_NUMERIC_NO_OPTS); if (!ecma_is_value_empty (routine_arg_1)) { diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-helpers.c b/jerry-core/ecma/builtin-objects/ecma-builtin-helpers.c index 76606fac9..92eb514be 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-helpers.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-helpers.c @@ -539,7 +539,7 @@ ecma_builtin_helper_string_prototype_object_index_of (ecma_string_t *original_st else { #endif /* ENABLED (JERRY_ESNEXT) */ - ret_value = ecma_get_number (arg2, &pos_num); + ret_value = ecma_op_to_numeric (arg2, &pos_num, ECMA_TO_NUMERIC_NO_OPTS); #if ENABLED (JERRY_ESNEXT) } #endif /* ENABLED (JERRY_ESNEXT) */ diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-string-prototype.c b/jerry-core/ecma/builtin-objects/ecma-builtin-string-prototype.c index e95486b52..4d1647649 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-string-prototype.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-string-prototype.c @@ -784,7 +784,7 @@ ecma_builtin_string_prototype_object_split (ecma_value_t this_value, /**< this a { /* ECMA-262 v11, 21.1.3.20 6 */ ecma_number_t num; - if (ECMA_IS_VALUE_ERROR (ecma_get_number (limit_value, &num))) + if (ECMA_IS_VALUE_ERROR (ecma_op_to_numeric (limit_value, &num, ECMA_TO_NUMERIC_NO_OPTS))) { goto cleanup_string; } diff --git a/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray-prototype.c b/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray-prototype.c index aab818f1a..45f63a008 100644 --- a/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray-prototype.c +++ b/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray-prototype.c @@ -429,7 +429,7 @@ ecma_builtin_typedarray_prototype_map (ecma_value_t this_arg, /**< this argument } ecma_number_t mapped_num; - if (ECMA_IS_VALUE_ERROR (ecma_get_number (mapped_value, &mapped_num))) + if (ECMA_IS_VALUE_ERROR (ecma_op_to_numeric (mapped_value, &mapped_num, ECMA_TO_NUMERIC_NO_OPTS))) { ecma_free_value (mapped_value); ecma_free_value (current_index); @@ -949,7 +949,7 @@ ecma_builtin_typedarray_prototype_set (ecma_value_t this_arg, /**< this argument ecma_number_t elem_num; - if (ECMA_IS_VALUE_ERROR (ecma_get_number (elem, &elem_num))) + if (ECMA_IS_VALUE_ERROR (ecma_op_to_numeric (elem, &elem_num, ECMA_TO_NUMERIC_NO_OPTS))) { ecma_free_value (elem); ecma_deref_object (source_obj_p); @@ -1059,7 +1059,7 @@ ecma_builtin_typedarray_prototype_join (ecma_value_t this_arg, /**< this argumen ecma_number_t length_number; - if (ECMA_IS_VALUE_ERROR (ecma_get_number (length_value, &length_number))) + if (ECMA_IS_VALUE_ERROR (ecma_op_to_numeric (length_value, &length_number, ECMA_TO_NUMERIC_NO_OPTS))) { ecma_free_value (length_value); ecma_free_value (obj_value); @@ -1234,7 +1234,7 @@ ecma_builtin_typedarray_prototype_fill (ecma_value_t this_arg, /**< this argumen } ecma_number_t value_num; - ecma_value_t ret_value = ecma_get_number (value, &value_num); + ecma_value_t ret_value = ecma_op_to_numeric (value, &value_num, ECMA_TO_NUMERIC_NO_OPTS); if (!ecma_is_value_empty (ret_value)) { @@ -1355,7 +1355,7 @@ ecma_builtin_typedarray_prototype_sort_compare_helper (ecma_value_t lhs, /**< le } ecma_number_t ret_num; - ecma_value_t number_result = ecma_get_number (call_value, &ret_num); + ecma_value_t number_result = ecma_op_to_numeric (call_value, &ret_num, ECMA_TO_NUMERIC_NO_OPTS); ecma_free_value (call_value); diff --git a/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray.c b/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray.c index dafe2277a..f27197d43 100644 --- a/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray.c +++ b/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray.c @@ -165,7 +165,7 @@ ecma_builtin_typedarray_of (ecma_value_t this_arg, /**< 'this' argument */ while (k < arguments_list_len) { ecma_number_t num; - ecma_value_t next_val = ecma_get_number (arguments_list_p[k], &num); + ecma_value_t next_val = ecma_op_to_numeric (arguments_list_p[k], &num, ECMA_TO_NUMERIC_NO_OPTS); if (ECMA_IS_VALUE_ERROR (next_val)) { diff --git a/jerry-core/ecma/operations/ecma-bigint.c b/jerry-core/ecma/operations/ecma-bigint.c index 8cbc84479..77a689d43 100644 --- a/jerry-core/ecma/operations/ecma-bigint.c +++ b/jerry-core/ecma/operations/ecma-bigint.c @@ -468,6 +468,46 @@ ecma_bigint_to_bigint (ecma_value_t value, /**< any value */ return result; } /* ecma_bigint_to_bigint */ +/** + * Returns with a BigInt if the value is BigInt, + * or the value is object, and its default value is BigInt + * + * @return ecma BigInt value or ECMA_VALUE_ERROR + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_bigint_get_bigint (ecma_value_t value, /**< any value */ + bool *free_result_p) /**< [out] result should be freed */ +{ + *free_result_p = false; + + if (ecma_is_value_bigint (value)) + { + return value; + } + + if (ecma_is_value_object (value)) + { + ecma_object_t *object_p = ecma_get_object_from_value (value); + ecma_value_t default_value = ecma_op_object_default_value (object_p, ECMA_PREFERRED_TYPE_NUMBER); + + if (ECMA_IS_VALUE_ERROR (default_value)) + { + return default_value; + } + + if (ecma_is_value_bigint (default_value)) + { + *free_result_p = (default_value != ECMA_BIGINT_ZERO); + return default_value; + } + + ecma_free_value (default_value); + } + + return ecma_raise_type_error (ECMA_ERR_MSG ("Cannot convert a BigInt value to a number")); +} /* ecma_bigint_get_bigint */ + /** * Create BigInt value from uint64 digits * diff --git a/jerry-core/ecma/operations/ecma-bigint.h b/jerry-core/ecma/operations/ecma-bigint.h index 014189f43..c05e96db9 100644 --- a/jerry-core/ecma/operations/ecma-bigint.h +++ b/jerry-core/ecma/operations/ecma-bigint.h @@ -43,6 +43,7 @@ ecma_value_t ecma_bigint_parse_string (const lit_utf8_byte_t *string_p, lit_utf8 ecma_value_t ecma_bigint_parse_string_value (ecma_value_t string, uint32_t options); ecma_string_t *ecma_bigint_to_string (ecma_value_t value, ecma_bigint_digit_t radix); ecma_value_t ecma_bigint_to_bigint (ecma_value_t value, bool allow_numbers); +ecma_value_t ecma_bigint_get_bigint (ecma_value_t value, bool *free_result_p); ecma_value_t ecma_bigint_create_from_digits (const uint64_t *digits_p, uint32_t size, bool sign); uint32_t ecma_bigint_get_size_in_digits (ecma_value_t value); void ecma_bigint_get_digits_and_sign (ecma_value_t value, uint64_t *digits_p, uint32_t size, bool *sign_p); diff --git a/jerry-core/ecma/operations/ecma-conversion.c b/jerry-core/ecma/operations/ecma-conversion.c index 9e010ea4c..ae7a66763 100644 --- a/jerry-core/ecma/operations/ecma-conversion.c +++ b/jerry-core/ecma/operations/ecma-conversion.c @@ -247,6 +247,13 @@ ecma_op_to_boolean (ecma_value_t value) /**< ecma value */ return !ecma_string_is_empty (str_p); } +#if ENABLED (JERRY_BUILTIN_BIGINT) + if (ecma_is_value_bigint (value)) + { + return value != ECMA_BIGINT_ZERO; + } +#endif /* ENABLED (JERRY_BUILTIN_BIGINT) */ + JERRY_ASSERT (ecma_is_value_object (value) || ECMA_CHECK_SYMBOL_IN_ASSERT (value)); return true; @@ -330,19 +337,22 @@ ecma_op_to_number (ecma_value_t value) /**< ecma value */ } /* ecma_op_to_number */ /** - * Helper to get the number contained in an ecma value. + * Helper to get the numeric value of an ecma value * * See also: - * ECMA-262 v5, 9.3 + * ECMA-262 v11, 7.1.3 * - * @return ECMA_VALUE_EMPTY if successful - * conversion error otherwise + * @return ECMA_VALUE_EMPTY if converted to number, BigInt if + * converted to BigInt, and conversion error otherwise * Returned value must be freed with ecma_free_value */ ecma_value_t -ecma_get_number (ecma_value_t value, /**< ecma value*/ - ecma_number_t *number_p) /**< [out] ecma number */ +ecma_op_to_numeric (ecma_value_t value, /**< ecma value */ + ecma_number_t *number_p, /**< [out] ecma number */ + ecma_to_numeric_options_t options) /**< option bits */ { + JERRY_UNUSED (options); + if (ecma_is_value_integer_number (value)) { *number_p = ecma_get_integer_from_value (value); @@ -396,27 +406,31 @@ ecma_get_number (ecma_value_t value, /**< ecma value*/ #if ENABLED (JERRY_BUILTIN_BIGINT) if (ecma_is_value_bigint (value)) { + if (options & ECMA_TO_NUMERIC_ALLOW_BIGINT) + { + return ecma_copy_value (value); + } return ecma_raise_type_error (ECMA_ERR_MSG ("Cannot convert a BigInt value to a number")); } #endif /* ENABLED (JERRY_BUILTIN_BIGINT) */ JERRY_ASSERT (ecma_is_value_object (value)); - ecma_object_t *obj_p = ecma_get_object_from_value (value); + ecma_object_t *object_p = ecma_get_object_from_value (value); - ecma_value_t def_value = ecma_op_object_default_value (obj_p, ECMA_PREFERRED_TYPE_NUMBER); + ecma_value_t def_value = ecma_op_object_default_value (object_p, ECMA_PREFERRED_TYPE_NUMBER); if (ECMA_IS_VALUE_ERROR (def_value)) { return def_value; } - ecma_value_t ret_value = ecma_get_number (def_value, number_p); + ecma_value_t ret_value = ecma_op_to_numeric (def_value, number_p, options); ecma_fast_free_value (def_value); return ret_value; -} /* ecma_get_number */ +} /* ecma_op_to_numeric */ /** * ToString operation. @@ -935,7 +949,7 @@ ecma_op_to_integer (ecma_value_t value, /**< ecma value */ } /* 1 */ - ecma_value_t to_number = ecma_get_number (value, number_p); + ecma_value_t to_number = ecma_op_to_numeric (value, number_p, ECMA_TO_NUMERIC_NO_OPTS); /* 2 */ if (ECMA_IS_VALUE_ERROR (to_number)) @@ -1015,7 +1029,7 @@ ecma_op_to_length (ecma_value_t value, /**< ecma value */ #else /* !ENABLED (JERRY_ESNEXT) */ /* In the case of ES5, ToLength(ES6) operation is the same as ToUint32(ES5) */ ecma_number_t num; - ecma_value_t to_number = ecma_get_number (value, &num); + ecma_value_t to_number = ecma_op_to_numeric (value, &num, ECMA_TO_NUMERIC_NO_OPTS); /* 2 */ if (ECMA_IS_VALUE_ERROR (to_number)) diff --git a/jerry-core/ecma/operations/ecma-conversion.h b/jerry-core/ecma/operations/ecma-conversion.h index dbceefa6e..634efc4e7 100644 --- a/jerry-core/ecma/operations/ecma-conversion.h +++ b/jerry-core/ecma/operations/ecma-conversion.h @@ -37,6 +37,15 @@ typedef enum ECMA_PREFERRED_TYPE_STRING /**< String */ } ecma_preferred_type_hint_t; +/** + * Option bits for ecma_op_to_numeric. + */ +typedef enum +{ + ECMA_TO_NUMERIC_NO_OPTS = 0, /**< no options (same as toNumber operation) */ + ECMA_TO_NUMERIC_ALLOW_BIGINT = (1 << 0), /**< allow BigInt values */ +} ecma_to_numeric_options_t; + ecma_value_t ecma_op_check_object_coercible (ecma_value_t value); bool ecma_op_same_value (ecma_value_t x, ecma_value_t y); #if ENABLED (JERRY_BUILTIN_MAP) @@ -45,7 +54,7 @@ bool ecma_op_same_value_zero (ecma_value_t x, ecma_value_t y); ecma_value_t ecma_op_to_primitive (ecma_value_t value, ecma_preferred_type_hint_t preferred_type); bool ecma_op_to_boolean (ecma_value_t value); ecma_value_t ecma_op_to_number (ecma_value_t value); -ecma_value_t ecma_get_number (ecma_value_t value, ecma_number_t *number_p); +ecma_value_t ecma_op_to_numeric (ecma_value_t value, ecma_number_t *number_p, ecma_to_numeric_options_t options); ecma_string_t *ecma_op_to_string (ecma_value_t value); ecma_string_t *ecma_op_to_property_key (ecma_value_t value); ecma_value_t ecma_op_to_object (ecma_value_t value); diff --git a/jerry-core/ecma/operations/ecma-dataview-object.c b/jerry-core/ecma/operations/ecma-dataview-object.c index 52b078655..9898c3596 100644 --- a/jerry-core/ecma/operations/ecma-dataview-object.c +++ b/jerry-core/ecma/operations/ecma-dataview-object.c @@ -71,7 +71,7 @@ ecma_op_dataview_create (const ecma_value_t *arguments_list_p, /**< arguments li if (arguments_list_len > 1) { ecma_number_t number_offset, offset_num; - if (ECMA_IS_VALUE_ERROR (ecma_get_number (arguments_list_p[1], &number_offset))) + if (ECMA_IS_VALUE_ERROR (ecma_op_to_numeric (arguments_list_p[1], &number_offset, ECMA_TO_NUMERIC_NO_OPTS))) { return ECMA_VALUE_ERROR; } diff --git a/jerry-core/ecma/operations/ecma-objects.c b/jerry-core/ecma/operations/ecma-objects.c index 86fd4a4de..a110f30c3 100644 --- a/jerry-core/ecma/operations/ecma-objects.c +++ b/jerry-core/ecma/operations/ecma-objects.c @@ -1231,7 +1231,7 @@ ecma_op_object_put_with_receiver (ecma_object_t *object_p, /**< the object */ if (array_index != ECMA_STRING_NOT_ARRAY_INDEX) { ecma_number_t num_var; - ecma_value_t error = ecma_get_number (value, &num_var); + ecma_value_t error = ecma_op_to_numeric (value, &num_var, ECMA_TO_NUMERIC_NO_OPTS); if (ECMA_IS_VALUE_ERROR (error)) { diff --git a/jerry-core/ecma/operations/ecma-regexp-object.c b/jerry-core/ecma/operations/ecma-regexp-object.c index 160fb51ae..a645025d2 100644 --- a/jerry-core/ecma/operations/ecma-regexp-object.c +++ b/jerry-core/ecma/operations/ecma-regexp-object.c @@ -2207,7 +2207,7 @@ ecma_regexp_split_helper (ecma_value_t this_arg, /**< this value */ { /* ECMA-262 v11, 21.2.5.13 13 */ ecma_number_t num; - if (ECMA_IS_VALUE_ERROR (ecma_get_number (limit_arg, &num))) + if (ECMA_IS_VALUE_ERROR (ecma_op_to_numeric (limit_arg, &num, ECMA_TO_NUMERIC_NO_OPTS))) { goto cleanup_splitter; } diff --git a/jerry-core/ecma/operations/ecma-try-catch-macro.h b/jerry-core/ecma/operations/ecma-try-catch-macro.h index 0198f059a..c2fe8fb07 100644 --- a/jerry-core/ecma/operations/ecma-try-catch-macro.h +++ b/jerry-core/ecma/operations/ecma-try-catch-macro.h @@ -32,7 +32,7 @@ #define ECMA_OP_TO_NUMBER_TRY_CATCH(num_var, value, return_value) \ JERRY_ASSERT (return_value == ECMA_VALUE_EMPTY); \ ecma_number_t num_var; \ - return_value = ecma_get_number (value, &num_var); \ + return_value = ecma_op_to_numeric (value, &num_var, ECMA_TO_NUMERIC_NO_OPTS); \ \ if (JERRY_LIKELY (ecma_is_value_empty (return_value))) \ { diff --git a/jerry-core/ecma/operations/ecma-typedarray-object.c b/jerry-core/ecma/operations/ecma-typedarray-object.c index a57f7af0b..4d42fd2d5 100644 --- a/jerry-core/ecma/operations/ecma-typedarray-object.c +++ b/jerry-core/ecma/operations/ecma-typedarray-object.c @@ -720,7 +720,7 @@ ecma_op_typedarray_from_helper (ecma_value_t this_val, /**< this_arg for the abo } ecma_number_t num_var; - ecma_value_t mapped_number = ecma_get_number (mapped_value, &num_var); + ecma_value_t mapped_number = ecma_op_to_numeric (mapped_value, &num_var, ECMA_TO_NUMERIC_NO_OPTS); ecma_free_value (mapped_value); if (ECMA_IS_VALUE_ERROR (mapped_number)) @@ -1357,7 +1357,7 @@ ecma_op_typedarray_define_index_prop (ecma_object_t *obj_p, /**< a TypedArray ob if (property_desc_p->flags & ECMA_PROP_IS_VALUE_DEFINED) { ecma_number_t num_var; - ecma_value_t error = ecma_get_number (property_desc_p->value, &num_var); + ecma_value_t error = ecma_op_to_numeric (property_desc_p->value, &num_var, ECMA_TO_NUMERIC_NO_OPTS); if (ECMA_IS_VALUE_ERROR (error)) { diff --git a/jerry-core/vm/opcodes-ecma-arithmetics.c b/jerry-core/vm/opcodes-ecma-arithmetics.c index 2248ceb2b..e0e7f76b6 100644 --- a/jerry-core/vm/opcodes-ecma-arithmetics.c +++ b/jerry-core/vm/opcodes-ecma-arithmetics.c @@ -47,46 +47,21 @@ do_number_arithmetic (number_arithmetic_op op, /**< number arithmetic operation ecma_value_t left_value, /**< left value */ ecma_value_t right_value) /**< right value */ { - bool free_left_value = false; - bool free_right_value = false; + ecma_number_t left_number; + left_value = ecma_op_to_numeric (left_value, &left_number, ECMA_TO_NUMERIC_ALLOW_BIGINT); - if (ecma_is_value_object (left_value)) + if (ECMA_IS_VALUE_ERROR (left_value)) { - ecma_object_t *obj_p = ecma_get_object_from_value (left_value); - left_value = ecma_op_object_default_value (obj_p, ECMA_PREFERRED_TYPE_NUMBER); - free_left_value = true; - - if (ECMA_IS_VALUE_ERROR (left_value)) - { - return left_value; - } - } - - if (ecma_is_value_object (right_value)) - { - ecma_object_t *obj_p = ecma_get_object_from_value (right_value); - right_value = ecma_op_object_default_value (obj_p, ECMA_PREFERRED_TYPE_NUMBER); - free_right_value = true; - - if (ECMA_IS_VALUE_ERROR (right_value)) - { - if (free_left_value) - { - ecma_free_value (left_value); - } - return right_value; - } + return left_value; } ecma_value_t ret_value = ECMA_VALUE_EMPTY; #if ENABLED (JERRY_BUILTIN_BIGINT) - if (JERRY_LIKELY (!ecma_is_value_bigint (left_value)) - || JERRY_LIKELY (!ecma_is_value_bigint (right_value))) + if (JERRY_LIKELY (!ecma_is_value_bigint (left_value))) { #endif /* ENABLED (JERRY_BUILTIN_BIGINT) */ - ECMA_OP_TO_NUMBER_TRY_CATCH (num_left, left_value, ret_value); - ECMA_OP_TO_NUMBER_TRY_CATCH (num_right, right_value, ret_value); + ECMA_OP_TO_NUMBER_TRY_CATCH (right_number, right_value, ret_value); ecma_number_t result = ECMA_NUMBER_ZERO; @@ -94,28 +69,28 @@ do_number_arithmetic (number_arithmetic_op op, /**< number arithmetic operation { case NUMBER_ARITHMETIC_SUBTRACTION: { - result = num_left - num_right; + result = left_number - right_number; break; } case NUMBER_ARITHMETIC_MULTIPLICATION: { - result = num_left * num_right; + result = left_number * right_number; break; } case NUMBER_ARITHMETIC_DIVISION: { - result = num_left / num_right; + result = left_number / right_number; break; } case NUMBER_ARITHMETIC_REMAINDER: { - result = ecma_op_number_remainder (num_left, num_right); + result = ecma_op_number_remainder (left_number, right_number); break; } #if ENABLED (JERRY_ESNEXT) case NUMBER_ARITHMETIC_EXPONENTIATION: { - result = ecma_number_pow (num_left, num_right); + result = ecma_number_pow (left_number, right_number); break; } #endif /* ENABLED (JERRY_ESNEXT) */ @@ -123,12 +98,20 @@ do_number_arithmetic (number_arithmetic_op op, /**< number arithmetic operation ret_value = ecma_make_number_value (result); - ECMA_OP_TO_NUMBER_FINALIZE (num_right); - ECMA_OP_TO_NUMBER_FINALIZE (num_left); + ECMA_OP_TO_NUMBER_FINALIZE (right_number); #if ENABLED (JERRY_BUILTIN_BIGINT) } else { + bool free_right_value; + right_value = ecma_bigint_get_bigint (right_value, &free_right_value); + + if (ECMA_IS_VALUE_ERROR (right_value)) + { + ecma_free_value (left_value); + return right_value; + } + switch (op) { case NUMBER_ARITHMETIC_SUBTRACTION: @@ -157,19 +140,14 @@ do_number_arithmetic (number_arithmetic_op op, /**< number arithmetic operation break; } } + + ecma_free_value (left_value); + if (free_right_value) + { + ecma_free_value (right_value); + } } #endif /* ENABLED (JERRY_BUILTIN_BIGINT) */ - - if (free_left_value) - { - ecma_free_value (left_value); - } - - if (free_right_value) - { - ecma_free_value (right_value); - } - return ret_value; } /* do_number_arithmetic */ @@ -300,60 +278,41 @@ ecma_value_t opfunc_unary_operation (ecma_value_t left_value, /**< left value */ bool is_plus) /**< unary plus flag */ { - bool free_left_value = false; + ecma_number_t left_number; + left_value = ecma_op_to_numeric (left_value, &left_number, ECMA_TO_NUMERIC_ALLOW_BIGINT); - if (ecma_is_value_object (left_value)) + if (ECMA_IS_VALUE_ERROR (left_value)) { - ecma_object_t *obj_p = ecma_get_object_from_value (left_value); - left_value = ecma_op_object_default_value (obj_p, ECMA_PREFERRED_TYPE_NUMBER); - free_left_value = true; - - if (ECMA_IS_VALUE_ERROR (left_value)) - { - return left_value; - } + return left_value; } - ecma_value_t ret_value = ECMA_VALUE_EMPTY; - #if ENABLED (JERRY_BUILTIN_BIGINT) if (JERRY_LIKELY (!ecma_is_value_bigint (left_value))) { -#endif /* ENABLED (JERRY_BUILTIN_BIGINT) */ - ECMA_OP_TO_NUMBER_TRY_CATCH (num_var_value, - left_value, - ret_value); + return ecma_make_number_value (is_plus ? left_number : -left_number); + } - ret_value = ecma_make_number_value (is_plus ? num_var_value : -num_var_value); + ecma_value_t ret_value; - ECMA_OP_TO_NUMBER_FINALIZE (num_var_value); - -#if ENABLED (JERRY_BUILTIN_BIGINT) + if (is_plus) + { + ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("Unary operation plus is not allowed for BigInt numbers")); } else { - if (is_plus) - { - ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("Unary operation plus is not allowed for BigInt numbers")); - } - else - { - ret_value = left_value; + ret_value = left_value; - if (left_value != ECMA_BIGINT_ZERO) - { - ret_value = ecma_bigint_negate (ecma_get_extended_primitive_from_value (left_value)); - } + if (left_value != ECMA_BIGINT_ZERO) + { + ret_value = ecma_bigint_negate (ecma_get_extended_primitive_from_value (left_value)); } } -#endif /* ENABLED (JERRY_BUILTIN_BIGINT) */ - - if (free_left_value) - { - ecma_free_value (left_value); - } + ecma_free_value (left_value); return ret_value; +#else /* !ENABLED (JERRY_BUILTIN_BIGINT) */ + return ecma_make_number_value (is_plus ? left_number : -left_number); +#endif /* ENABLED (JERRY_BUILTIN_BIGINT) */ } /* opfunc_unary_operation */ /** diff --git a/jerry-core/vm/opcodes-ecma-bitwise.c b/jerry-core/vm/opcodes-ecma-bitwise.c index 138b2008f..b289f197b 100644 --- a/jerry-core/vm/opcodes-ecma-bitwise.c +++ b/jerry-core/vm/opcodes-ecma-bitwise.c @@ -48,83 +48,58 @@ do_number_bitwise_logic (number_bitwise_logic_op op, /**< number bitwise logic o JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (left_value) && !ECMA_IS_VALUE_ERROR (right_value)); - bool free_left_value = false; - bool free_right_value = false; + ecma_number_t left_number; + left_value = ecma_op_to_numeric (left_value, &left_number, ECMA_TO_NUMERIC_ALLOW_BIGINT); - if (ecma_is_value_object (left_value)) + if (ECMA_IS_VALUE_ERROR (left_value)) { - ecma_object_t *obj_p = ecma_get_object_from_value (left_value); - left_value = ecma_op_object_default_value (obj_p, ECMA_PREFERRED_TYPE_NUMBER); - free_left_value = true; - - if (ECMA_IS_VALUE_ERROR (left_value)) - { - return left_value; - } - } - - if (ecma_is_value_object (right_value)) - { - ecma_object_t *obj_p = ecma_get_object_from_value (right_value); - right_value = ecma_op_object_default_value (obj_p, ECMA_PREFERRED_TYPE_NUMBER); - free_right_value = true; - - if (ECMA_IS_VALUE_ERROR (right_value)) - { - if (free_left_value) - { - ecma_free_value (left_value); - } - return right_value; - } + return left_value; } ecma_value_t ret_value = ECMA_VALUE_EMPTY; #if ENABLED (JERRY_BUILTIN_BIGINT) - if (JERRY_LIKELY (!ecma_is_value_bigint (left_value)) - || JERRY_LIKELY (!ecma_is_value_bigint (right_value))) + if (JERRY_LIKELY (!ecma_is_value_bigint (left_value))) { #endif /* ENABLED (JERRY_BUILTIN_BIGINT) */ - ECMA_OP_TO_NUMBER_TRY_CATCH (num_left, left_value, ret_value); - ECMA_OP_TO_NUMBER_TRY_CATCH (num_right, right_value, ret_value); + ECMA_OP_TO_NUMBER_TRY_CATCH (right_number, right_value, ret_value); ecma_number_t result = ECMA_NUMBER_ZERO; - uint32_t right_uint32 = ecma_number_to_uint32 (num_right); + uint32_t right_uint32 = ecma_number_to_uint32 (right_number); switch (op) { case NUMBER_BITWISE_LOGIC_AND: { - uint32_t left_uint32 = ecma_number_to_uint32 (num_left); + uint32_t left_uint32 = ecma_number_to_uint32 (left_number); result = (ecma_number_t) ((int32_t) (left_uint32 & right_uint32)); break; } case NUMBER_BITWISE_LOGIC_OR: { - uint32_t left_uint32 = ecma_number_to_uint32 (num_left); + uint32_t left_uint32 = ecma_number_to_uint32 (left_number); result = (ecma_number_t) ((int32_t) (left_uint32 | right_uint32)); break; } case NUMBER_BITWISE_LOGIC_XOR: { - uint32_t left_uint32 = ecma_number_to_uint32 (num_left); + uint32_t left_uint32 = ecma_number_to_uint32 (left_number); result = (ecma_number_t) ((int32_t) (left_uint32 ^ right_uint32)); break; } case NUMBER_BITWISE_SHIFT_LEFT: { - result = (ecma_number_t) (ecma_number_to_int32 (num_left) << (right_uint32 & 0x1F)); + result = (ecma_number_t) (ecma_number_to_int32 (left_number) << (right_uint32 & 0x1F)); break; } case NUMBER_BITWISE_SHIFT_RIGHT: { - result = (ecma_number_t) (ecma_number_to_int32 (num_left) >> (right_uint32 & 0x1F)); + result = (ecma_number_t) (ecma_number_to_int32 (left_number) >> (right_uint32 & 0x1F)); break; } case NUMBER_BITWISE_SHIFT_URIGHT: { - uint32_t left_uint32 = ecma_number_to_uint32 (num_left); + uint32_t left_uint32 = ecma_number_to_uint32 (left_number); result = (ecma_number_t) (left_uint32 >> (right_uint32 & 0x1F)); break; } @@ -138,11 +113,19 @@ do_number_bitwise_logic (number_bitwise_logic_op op, /**< number bitwise logic o ret_value = ecma_make_number_value (result); ECMA_OP_TO_NUMBER_FINALIZE (num_right); - ECMA_OP_TO_NUMBER_FINALIZE (num_left); #if ENABLED (JERRY_BUILTIN_BIGINT) } else { + bool free_right_value; + right_value = ecma_bigint_get_bigint (right_value, &free_right_value); + + if (ECMA_IS_VALUE_ERROR (right_value)) + { + ecma_free_value (left_value); + return right_value; + } + switch (op) { case NUMBER_BITWISE_LOGIC_AND: @@ -176,19 +159,15 @@ do_number_bitwise_logic (number_bitwise_logic_op op, /**< number bitwise logic o break; } } + + ecma_free_value (left_value); + if (free_right_value) + { + ecma_free_value (right_value); + } } #endif /* ENABLED (JERRY_BUILTIN_BIGINT) */ - if (free_left_value) - { - ecma_free_value (left_value); - } - - if (free_right_value) - { - ecma_free_value (right_value); - } - return ret_value; } /* do_number_bitwise_logic */ diff --git a/tests/jerry/es.next/arithmetics-3.js b/tests/jerry/es.next/arithmetics-3.js new file mode 100644 index 000000000..d3228dfef --- /dev/null +++ b/tests/jerry/es.next/arithmetics-3.js @@ -0,0 +1,37 @@ +// Copyright JS Foundation and other contributors, http://js.foundation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +var o1 = { valueOf() { return Symbol() } } +var o2 = { valueOf() { throw "Should not reach here" } } + +function check_type_error(code) { + try { + eval(code) + assert(false) + } catch (e) { + assert(e instanceof TypeError) + } +} + +check_type_error("o1 - o2") +check_type_error("o1 * o2") +check_type_error("o1 / o2") +check_type_error("o1 % o2") +check_type_error("o1 ** o2") +check_type_error("o1 | o2") +check_type_error("o1 & o2") +check_type_error("o1 ^ o2") +check_type_error("o1 << o2") +check_type_error("o1 >> o2") +check_type_error("o1 >>> o2") diff --git a/tests/jerry/es.next/bigint4.js b/tests/jerry/es.next/bigint4.js index ef1a0e14d..4c334e59a 100644 --- a/tests/jerry/es.next/bigint4.js +++ b/tests/jerry/es.next/bigint4.js @@ -13,6 +13,12 @@ * limitations under the License. */ +/* Boolean. */ + +assert(!BigInt("0") === true) +assert(!BigInt("1") === false) +assert(!BigInt("-1") === false) + /* Strict equal. */ assert(BigInt("0") === BigInt("0")) diff --git a/tests/test262-esnext-excludelist.xml b/tests/test262-esnext-excludelist.xml index 9ada3426e..03870dee8 100644 --- a/tests/test262-esnext-excludelist.xml +++ b/tests/test262-esnext-excludelist.xml @@ -6682,7 +6682,6 @@ - @@ -10468,17 +10467,4 @@ - - - - - - - - - - - - -