From cfd69d3b709137abe207efbcaa7af6c5c470e592 Mon Sep 17 00:00:00 2001 From: Zoltan Herczeg Date: Mon, 3 Aug 2020 13:46:34 +0200 Subject: [PATCH] Implement relational operators for BigInts (#4087) Improve BigInt constructor 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 | 4 +- jerry-core/ecma/base/ecma-helpers-value.c | 19 +- jerry-core/ecma/base/ecma-helpers.h | 17 +- .../builtin-objects/ecma-builtin-bigint.c | 31 +- jerry-core/ecma/operations/ecma-big-uint.c | 2 +- jerry-core/ecma/operations/ecma-bigint.c | 458 +++++++++++++++++- jerry-core/ecma/operations/ecma-bigint.h | 11 +- jerry-core/ecma/operations/ecma-comparison.c | 268 +++++++--- jerry-core/ecma/operations/ecma-conversion.c | 4 +- tests/jerry/es.next/bigint3.js | 56 +++ tests/jerry/es.next/bigint4.js | 177 +++++++ tests/test262-esnext-excludelist.xml | 6 - 12 files changed, 941 insertions(+), 112 deletions(-) create mode 100644 tests/jerry/es.next/bigint3.js create mode 100644 tests/jerry/es.next/bigint4.js diff --git a/jerry-core/ecma/base/ecma-helpers-number.c b/jerry-core/ecma/base/ecma-helpers-number.c index cd1d23613..b3d968f3b 100644 --- a/jerry-core/ecma/base/ecma-helpers-number.c +++ b/jerry-core/ecma/base/ecma-helpers-number.c @@ -68,7 +68,7 @@ ecma_number_pack (bool sign, /**< sign */ /** * Unpacking sign, fraction and biased exponent from ecma-number */ -static void +void ecma_number_unpack (ecma_number_t num, /**< ecma-number */ bool *sign_p, /**< [out] sign (optional) */ uint32_t *biased_exp_p, /**< [out] biased exponent (optional) */ @@ -131,7 +131,7 @@ ecma_number_pack (bool sign, /**< sign */ /** * Unpacking sign, fraction and biased exponent from ecma-number */ -static void +void ecma_number_unpack (ecma_number_t num, /**< ecma-number */ bool *sign_p, /**< [out] sign (optional) */ uint32_t *biased_exp_p, /**< [out] biased exponent (optional) */ diff --git a/jerry-core/ecma/base/ecma-helpers-value.c b/jerry-core/ecma/base/ecma-helpers-value.c index 8cd97d426..e6e955f90 100644 --- a/jerry-core/ecma/base/ecma-helpers-value.c +++ b/jerry-core/ecma/base/ecma-helpers-value.c @@ -417,29 +417,14 @@ ecma_is_value_error_reference (ecma_value_t value) /**< ecma value */ void ecma_check_value_type_is_spec_defined (ecma_value_t value) /**< ecma value */ { -#if ENABLED (JERRY_ESNEXT) -#define ECMA_CHECK_IS_VALUE_SYMBOL(value) ecma_is_value_symbol(value) -#else /* !ENABLED (JERRY_ESNEXT) */ -#define ECMA_CHECK_IS_VALUE_SYMBOL(value) false -#endif /* ENABLED (JERRY_ESNEXT) */ - -#if ENABLED (JERRY_BUILTIN_BIGINT) -#define ECMA_CHECK_IS_VALUE_BIGINT(value) ecma_is_value_bigint(value) -#else /* !ENABLED (JERRY_BUILTIN_BIGINT) */ -#define ECMA_CHECK_IS_VALUE_BIGINT(value) false -#endif /* ENABLED (JERRY_BUILTIN_BIGINT) */ - JERRY_ASSERT (ecma_is_value_undefined (value) || ecma_is_value_null (value) || ecma_is_value_boolean (value) || ecma_is_value_number (value) || ecma_is_value_string (value) - || ECMA_CHECK_IS_VALUE_SYMBOL (value) - || ECMA_CHECK_IS_VALUE_BIGINT (value) + || ECMA_CHECK_SYMBOL_IN_ASSERT (value) + || ECMA_CHECK_BIGINT_IN_ASSERT (value) || ecma_is_value_object (value)); - -#undef ECMA_CHECK_IS_VALUE_SYMBOL -#undef ECMA_CHECK_IS_VALUE_BIGINT } /* ecma_check_value_type_is_spec_defined */ /** diff --git a/jerry-core/ecma/base/ecma-helpers.h b/jerry-core/ecma/base/ecma-helpers.h index 728f7f29b..e75529c69 100644 --- a/jerry-core/ecma/base/ecma-helpers.h +++ b/jerry-core/ecma/base/ecma-helpers.h @@ -196,14 +196,26 @@ typedef enum /** * JERRY_ASSERT compatible macro for checking whether the given ecma-value is symbol */ -#define ECMA_ASSERT_VALUE_IS_SYMBOL(value) (ecma_is_value_symbol ((value))) +#define ECMA_CHECK_SYMBOL_IN_ASSERT(value) (ecma_is_value_symbol ((value))) #else /* !ENABLED (JERRY_ESNEXT) */ /** * JERRY_ASSERT compatible macro for checking whether the given ecma-value is symbol */ -#define ECMA_ASSERT_VALUE_IS_SYMBOL(value) (false) +#define ECMA_CHECK_SYMBOL_IN_ASSERT(value) (false) #endif /* ENABLED (JERRY_ESNEXT) */ +#if ENABLED (JERRY_BUILTIN_BIGINT) +/** + * JERRY_ASSERT compatible macro for checking whether the given ecma-value is bigint + */ +#define ECMA_CHECK_BIGINT_IN_ASSERT(value) ecma_is_value_bigint(value) +#else /* !ENABLED (JERRY_BUILTIN_BIGINT) */ +/** + * JERRY_ASSERT compatible macro for checking whether the given ecma-value is bigint + */ +#define ECMA_CHECK_BIGINT_IN_ASSERT(value) false +#endif /* ENABLED (JERRY_BUILTIN_BIGINT) */ + /** * Check whether the given type is ECMA_OBJECT_TYPE_PROXY * @@ -414,6 +426,7 @@ ecma_string_t *ecma_stringbuilder_finalize (ecma_stringbuilder_t *builder_p); void ecma_stringbuilder_destroy (ecma_stringbuilder_t *builder_p); /* ecma-helpers-number.c */ +void ecma_number_unpack (ecma_number_t num, bool *sign_p, uint32_t *biased_exp_p, uint64_t *fraction_p); ecma_number_t ecma_number_make_nan (void); ecma_number_t ecma_number_make_infinity (bool sign); bool ecma_number_is_nan (ecma_number_t num); diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-bigint.c b/jerry-core/ecma/builtin-objects/ecma-builtin-bigint.c index 343805fac..fcc06bfe4 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-bigint.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-bigint.c @@ -51,20 +51,37 @@ ecma_builtin_bigint_dispatch_call (const ecma_value_t *arguments_list_p, /**< ar JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); ecma_value_t value = (arguments_list_len == 0) ? ECMA_VALUE_UNDEFINED : arguments_list_p[0]; + bool free_value = false; - if (!ecma_is_value_string (value)) + if (ecma_is_value_object (value)) { - return ecma_raise_type_error (ECMA_ERR_MSG ("TODO: Only strings are supported now")); + ecma_object_t *obj_p = ecma_get_object_from_value (value); + value = ecma_op_object_default_value (obj_p, ECMA_PREFERRED_TYPE_NUMBER); + free_value = true; + + if (ECMA_IS_VALUE_ERROR (value)) + { + return value; + } } - ecma_string_t *string_p = ecma_get_string_from_value (value); + ecma_value_t ret_value = ECMA_VALUE_EMPTY; - ECMA_STRING_TO_UTF8_STRING (string_p, string_buffer_p, string_buffer_size); + if (ecma_is_value_number (value)) + { + ret_value = ecma_bigint_number_to_bigint (ecma_get_number_from_value (value)); + } + else + { + ret_value = ecma_bigint_to_bigint (value); + } - ecma_value_t result = ecma_bigint_parse_string (string_buffer_p, string_buffer_size); + if (free_value) + { + ecma_free_value (value); + } - ECMA_FINALIZE_UTF8_STRING (string_buffer_p, string_buffer_size); - return result; + return ret_value; } /* ecma_builtin_bigint_dispatch_call */ /** diff --git a/jerry-core/ecma/operations/ecma-big-uint.c b/jerry-core/ecma/operations/ecma-big-uint.c index 81158f83a..a6023a07c 100644 --- a/jerry-core/ecma/operations/ecma-big-uint.c +++ b/jerry-core/ecma/operations/ecma-big-uint.c @@ -99,7 +99,7 @@ ecma_big_uint_extend (ecma_extended_primitive_t *value_p, /**< BigInt value */ /** * Compare two BigUInt numbers * - * return -1, if value1 < value2, 0 if they are equal, and 1 otherwise + * return -1, if left value < right value, 0 if they are equal, and 1 otherwise */ int ecma_big_uint_compare (ecma_extended_primitive_t *left_value_p, /**< left BigUInt value */ diff --git a/jerry-core/ecma/operations/ecma-bigint.c b/jerry-core/ecma/operations/ecma-bigint.c index 207f6fdaa..6d446b94a 100644 --- a/jerry-core/ecma/operations/ecma-bigint.c +++ b/jerry-core/ecma/operations/ecma-bigint.c @@ -41,7 +41,9 @@ ecma_bigint_raise_memory_error (void) */ ecma_value_t ecma_bigint_parse_string (const lit_utf8_byte_t *string_p, /**< string represenation of the BigInt */ - lit_utf8_size_t size) /**< string size */ + lit_utf8_size_t size, /**< string size */ + bool throw_syntax_error) /**< true, if syntax errors should be thrown + * otherwise ECMA_VALUE_FALSE is returned on syntax error */ { ecma_bigint_digit_t radix = 10; uint32_t sign = 0; @@ -77,6 +79,10 @@ ecma_bigint_parse_string (const lit_utf8_byte_t *string_p, /**< string represena } else if (size == 0) { + if (!throw_syntax_error) + { + return ECMA_VALUE_FALSE; + } return ecma_raise_syntax_error (ECMA_ERR_MSG ("BigInt cannot be constructed from empty string")); } @@ -119,6 +125,11 @@ ecma_bigint_parse_string (const lit_utf8_byte_t *string_p, /**< string represena { ecma_deref_bigint (result_p); } + + if (!throw_syntax_error) + { + return ECMA_VALUE_FALSE; + } return ecma_raise_syntax_error (ECMA_ERR_MSG ("String cannot be converted to BigInt value")); } @@ -141,6 +152,26 @@ ecma_bigint_parse_string (const lit_utf8_byte_t *string_p, /**< string represena return ecma_make_extended_primitive_value (result_p, ECMA_TYPE_BIGINT); } /* ecma_bigint_parse_string */ +/** + * Parse a string value and create a BigInt value + * + * @return ecma BigInt value or ECMA_VALUE_ERROR + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_bigint_parse_string_value (ecma_value_t string, /**< ecma string */ + bool throw_syntax_error) /**< true, if syntax errors should be thrown + * otherwise ECMA_VALUE_FALSE is returned on syntax error */ +{ + JERRY_ASSERT (ecma_is_value_string (string)); + + ECMA_STRING_TO_UTF8_STRING (ecma_get_string_from_value (string), string_buffer_p, string_buffer_size); + ecma_value_t result = ecma_bigint_parse_string (string_buffer_p, string_buffer_size, throw_syntax_error); + ECMA_FINALIZE_UTF8_STRING (string_buffer_p, string_buffer_size); + + return result; +} /* ecma_bigint_parse_string_value */ + /** * Create a string representation for a BigInt value * @@ -183,6 +214,431 @@ ecma_bigint_to_string (ecma_value_t value, /**< BigInt value */ return string_p; } /* ecma_bigint_to_string */ +/** + * Get the size of zero digits from the result of ecma_bigint_number_to_digits + */ +#define ECMA_BIGINT_NUMBER_TO_DIGITS_GET_ZERO_SIZE(value) \ + (((value) & 0xffff) * (uint32_t) sizeof (ecma_bigint_digit_t)) + +/** + * Get the number of digits from the result of ecma_bigint_number_to_digits + */ +#define ECMA_BIGINT_NUMBER_TO_DIGITS_GET_DIGITS(value) ((value) >> 20) + +/** + * Get the size of digits from the result of ecma_bigint_number_to_digits + */ +#define ECMA_BIGINT_NUMBER_TO_DIGITS_GET_DIGITS_SIZE(value) \ + (ECMA_BIGINT_NUMBER_TO_DIGITS_GET_DIGITS (value) * (uint32_t) sizeof (ecma_bigint_digit_t)) + +/** + * Set number of digits in the result of ecma_bigint_number_to_digits + */ +#define ECMA_BIGINT_NUMBER_TO_DIGITS_SET_DIGITS(value) ((uint32_t) (value) << 20) + +/** + * This flag is set when the number passed to ecma_bigint_number_to_digits has fraction part + */ +#define ECMA_BIGINT_NUMBER_TO_DIGITS_HAS_FRACTION 0x10000 + +/** + * Convert a number to maximum of 3 digits and left shift + * + * @return packed value, ECMA_BIGINT_NUMBER_TO_DIGITS* macros can be used to decode it + */ +static uint32_t +ecma_bigint_number_to_digits (ecma_number_t number, /**< ecma number */ + ecma_bigint_digit_t *digits_p) /**< [out] BigInt digits */ +{ + uint32_t biased_exp; + uint64_t fraction; + + ecma_number_unpack (number, NULL, &biased_exp, &fraction); + + if (biased_exp == 0) + { + /* Number is zero. */ + return ECMA_BIGINT_NUMBER_TO_DIGITS_SET_DIGITS (0); + } + + if (biased_exp < ((1 << (ECMA_NUMBER_BIASED_EXP_WIDTH - 1)) - 1)) + { + /* Number is less than 1. */ + return ECMA_BIGINT_NUMBER_TO_DIGITS_SET_DIGITS (0) | ECMA_BIGINT_NUMBER_TO_DIGITS_HAS_FRACTION; + } + + biased_exp -= ((1 << (ECMA_NUMBER_BIASED_EXP_WIDTH - 1)) - 1); + fraction |= ((uint64_t) 1) << ECMA_NUMBER_FRACTION_WIDTH; + + if (biased_exp <= ECMA_NUMBER_FRACTION_WIDTH) + { + uint32_t has_fraction = 0; + + if (biased_exp < ECMA_NUMBER_FRACTION_WIDTH + && (fraction << (biased_exp + ((8 * sizeof (uint64_t)) - ECMA_NUMBER_FRACTION_WIDTH))) != 0) + { + has_fraction |= ECMA_BIGINT_NUMBER_TO_DIGITS_HAS_FRACTION; + } + + fraction >>= ECMA_NUMBER_FRACTION_WIDTH - biased_exp; + digits_p[0] = (ecma_bigint_digit_t) fraction; + +#if ENABLED (JERRY_NUMBER_TYPE_FLOAT64) + digits_p[1] = (ecma_bigint_digit_t) (fraction >> (8 * sizeof (ecma_bigint_digit_t))); + return ECMA_BIGINT_NUMBER_TO_DIGITS_SET_DIGITS (digits_p[1] == 0 ? 1 : 2) | has_fraction; +#else /* !ENABLED (JERRY_NUMBER_TYPE_FLOAT64) */ + return ECMA_BIGINT_NUMBER_TO_DIGITS_SET_DIGITS (1) | has_fraction; +#endif /* ENABLED (JERRY_NUMBER_TYPE_FLOAT64) */ + } + + digits_p[0] = (ecma_bigint_digit_t) fraction; +#if ENABLED (JERRY_NUMBER_TYPE_FLOAT64) + digits_p[1] = (ecma_bigint_digit_t) (fraction >> (8 * sizeof (ecma_bigint_digit_t))); +#endif /* ENABLED (JERRY_NUMBER_TYPE_FLOAT64) */ + + biased_exp -= ECMA_NUMBER_FRACTION_WIDTH; + + uint32_t shift_left = biased_exp & ((8 * sizeof (ecma_bigint_digit_t)) - 1); + biased_exp = biased_exp >> ECMA_BIGINT_DIGIT_SHIFT; + + if (shift_left == 0) + { +#if ENABLED (JERRY_NUMBER_TYPE_FLOAT64) + return biased_exp | ECMA_BIGINT_NUMBER_TO_DIGITS_SET_DIGITS (2); +#else /* !ENABLED (JERRY_NUMBER_TYPE_FLOAT64) */ + return biased_exp | ECMA_BIGINT_NUMBER_TO_DIGITS_SET_DIGITS (1); +#endif /* ENABLED (JERRY_NUMBER_TYPE_FLOAT64) */ + } + + uint32_t shift_right = (1 << ECMA_BIGINT_DIGIT_SHIFT) - shift_left; + +#if ENABLED (JERRY_NUMBER_TYPE_FLOAT64) + digits_p[2] = digits_p[1] >> shift_right; + digits_p[1] = (digits_p[1] << shift_left) | (digits_p[0] >> shift_right); + digits_p[0] <<= shift_left; + + return biased_exp | ECMA_BIGINT_NUMBER_TO_DIGITS_SET_DIGITS (digits_p[2] == 0 ? 2 : 3); +#else /* !ENABLED (JERRY_NUMBER_TYPE_FLOAT64) */ + digits_p[1] = digits_p[0] >> shift_right; + digits_p[0] <<= shift_left; + + return biased_exp | ECMA_BIGINT_NUMBER_TO_DIGITS_SET_DIGITS (digits_p[1] == 0 ? 1 : 2); +#endif /* ENABLED (JERRY_NUMBER_TYPE_FLOAT64) */ +} /* ecma_bigint_number_to_digits */ + +/** + * Convert an ecma number to BigInt value + * + * See also: + * ECMA-262 v11, 20.2.1.1.1 + * + * @return ecma BigInt value or ECMA_VALUE_ERROR + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_bigint_number_to_bigint (ecma_number_t number) /**< ecma number */ +{ + if (ecma_number_is_nan (number) || ecma_number_is_infinity (number)) + { + return ecma_raise_range_error (ECMA_ERR_MSG ("Infinity or NaN cannot be converted to BigInt")); + } + + ecma_bigint_digit_t digits[3]; + uint32_t result = ecma_bigint_number_to_digits (number, digits); + + JERRY_ASSERT (ECMA_BIGINT_NUMBER_TO_DIGITS_GET_DIGITS (result) == 0 + || digits[ECMA_BIGINT_NUMBER_TO_DIGITS_GET_DIGITS (result) - 1] > 0); + + if (result & ECMA_BIGINT_NUMBER_TO_DIGITS_HAS_FRACTION) + { + return ecma_raise_range_error (ECMA_ERR_MSG ("Only integer numbers can be converted to BigInt")); + } + + uint32_t digits_size = ECMA_BIGINT_NUMBER_TO_DIGITS_GET_DIGITS_SIZE (result); + uint32_t zero_size = ECMA_BIGINT_NUMBER_TO_DIGITS_GET_ZERO_SIZE (result); + + ecma_extended_primitive_t *result_p = ecma_bigint_create (digits_size + zero_size); + + if (JERRY_UNLIKELY (result_p == NULL)) + { + return ecma_bigint_raise_memory_error (); + } + + if (digits_size > 0) + { + uint8_t *data_p = (uint8_t *) ECMA_BIGINT_GET_DIGITS (result_p, 0); + memset (data_p, 0, zero_size); + memcpy (data_p + zero_size, digits, digits_size); + + if (number < 0) + { + result_p->u.bigint_sign_and_size |= ECMA_BIGINT_SIGN; + } + } + + return ecma_make_extended_primitive_value (result_p, ECMA_TYPE_BIGINT); +} /* ecma_bigint_number_to_bigint */ + +/** + * Convert a value to BigInt value + * + * See also: + * ECMA-262 v11, 7.1.13 + * + * @return ecma BigInt value or ECMA_VALUE_ERROR + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_bigint_to_bigint (ecma_value_t value) /**< any value */ +{ + if (ecma_is_value_boolean (value)) + { + uint32_t size = ecma_is_value_true (value) ? sizeof (ecma_bigint_digit_t) : 0; + + ecma_extended_primitive_t *result_p = ecma_bigint_create (size); + + if (JERRY_UNLIKELY (result_p == NULL)) + { + return ecma_bigint_raise_memory_error (); + } + + if (ecma_is_value_true (value)) + { + *ECMA_BIGINT_GET_DIGITS (result_p, 0) = 1; + } + + return ecma_make_extended_primitive_value (result_p, ECMA_TYPE_BIGINT); + } + + if (!ecma_is_value_string (value)) + { + return ecma_raise_type_error (ECMA_ERR_MSG ("Value cannot be converted to BigInt")); + } + + return ecma_bigint_parse_string_value (value, true); +} /* ecma_bigint_to_bigint */ + +/** + * Compare two BigInt values + * + * @return true if they are the same, false otherwise + */ +bool +ecma_bigint_is_equal_to_bigint (ecma_value_t left_value, /**< left BigInt value */ + ecma_value_t right_value) /**< right BigInt value */ +{ + JERRY_ASSERT (ecma_is_value_bigint (left_value) && ecma_is_value_bigint (right_value)); + + ecma_extended_primitive_t *left_p = ecma_get_extended_primitive_from_value (left_value); + ecma_extended_primitive_t *right_p = ecma_get_extended_primitive_from_value (right_value); + + if (left_p->u.bigint_sign_and_size != right_p->u.bigint_sign_and_size) + { + return false; + } + + uint32_t size = ECMA_BIGINT_GET_SIZE (left_p); + return memcmp (ECMA_BIGINT_GET_DIGITS (left_p, 0), ECMA_BIGINT_GET_DIGITS (right_p, 0), size) == 0; +} /* ecma_bigint_is_equal_to_bigint */ + +/** + * Compare a BigInt value and a number + * + * @return true if they are the same, false otherwise + */ +bool +ecma_bigint_is_equal_to_number (ecma_value_t left_value, /**< left BigInt value */ + ecma_number_t right_value) /**< right number value */ +{ + JERRY_ASSERT (ecma_is_value_bigint (left_value)); + + if (ecma_number_is_nan (right_value) || ecma_number_is_infinity (right_value)) + { + return false; + } + + ecma_extended_primitive_t *left_value_p = ecma_get_extended_primitive_from_value (left_value); + uint32_t left_size = ECMA_BIGINT_GET_SIZE (left_value_p); + + if (right_value == 0) + { + return left_size == 0; + } + + /* Sign must be the same. */ + if (left_value_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN) + { + if (right_value > 0) + { + return false; + } + } + else if (right_value < 0) + { + return false; + } + + ecma_bigint_digit_t digits[3]; + uint32_t result = ecma_bigint_number_to_digits (right_value, digits); + + JERRY_ASSERT (ECMA_BIGINT_NUMBER_TO_DIGITS_GET_DIGITS (result) == 0 + || digits[ECMA_BIGINT_NUMBER_TO_DIGITS_GET_DIGITS (result) - 1] > 0); + + if (result & ECMA_BIGINT_NUMBER_TO_DIGITS_HAS_FRACTION) + { + return false; + } + + uint32_t digits_size = ECMA_BIGINT_NUMBER_TO_DIGITS_GET_DIGITS_SIZE (result); + uint32_t zero_size = ECMA_BIGINT_NUMBER_TO_DIGITS_GET_ZERO_SIZE (result); + + if (left_size != digits_size + zero_size) + { + return false; + } + + ecma_bigint_digit_t *left_p = ECMA_BIGINT_GET_DIGITS (left_value_p, 0); + ecma_bigint_digit_t *left_end_p = (ecma_bigint_digit_t *) (((uint8_t *) left_p) + zero_size); + + /* Check value bits first. */ + if (memcmp (left_end_p, digits, digits_size) != 0) + { + return false; + } + + while (left_p < left_end_p) + { + if (*left_p++ != 0) + { + return false; + } + } + + return true; +} /* ecma_bigint_is_equal_to_number */ + +/** + * Convert 0 to 1, and 1 to -1. Useful for getting sign. + */ +#define ECMA_BIGINT_TO_SIGN(value) (1 - (((int) (value)) << 1)) + +/** + * Compare two BigInt values + * + * return -1, if left value < right value, 0 if they are equal, 1 otherwise + */ +int +ecma_bigint_compare_to_bigint (ecma_value_t left_value, /**< left BigInt value */ + ecma_value_t right_value) /**< right BigInt value */ +{ + JERRY_ASSERT (ecma_is_value_bigint (left_value) && ecma_is_value_bigint (right_value)); + + ecma_extended_primitive_t *left_p = ecma_get_extended_primitive_from_value (left_value); + ecma_extended_primitive_t *right_p = ecma_get_extended_primitive_from_value (right_value); + + uint32_t left_sign = left_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN; + uint32_t right_sign = right_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN; + + if ((left_sign ^ right_sign) != 0) + { + return ECMA_BIGINT_TO_SIGN (left_sign); + } + + return ecma_big_uint_compare (left_p, right_p); +} /* ecma_bigint_compare_to_bigint */ + +/** + * Compare a BigInt value and a number + * + * return -1, if left value < right value, 0 if they are equal, 1 otherwise + */ +int +ecma_bigint_compare_to_number (ecma_value_t left_value, /**< left BigInt value */ + ecma_number_t right_value) /**< right number value */ +{ + JERRY_ASSERT (ecma_is_value_bigint (left_value)); + JERRY_ASSERT (!ecma_number_is_nan (right_value)); + + ecma_extended_primitive_t *left_value_p = ecma_get_extended_primitive_from_value (left_value); + uint32_t left_size = ECMA_BIGINT_GET_SIZE (left_value_p); + int left_sign = ECMA_BIGINT_TO_SIGN (left_value_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN); + int right_invert_sign = ECMA_BIGINT_TO_SIGN (right_value > 0); + + if (left_size == 0) + { + if (right_value == 0) + { + return 0; + } + + return right_invert_sign; + } + + if (right_value == 0 || left_sign == right_invert_sign) + { + /* Second condition: a positive BigInt is always greater than any negative number, and the opposite is true. */ + return left_sign; + } + + if (ecma_number_is_infinity (right_value)) + { + /* Infinity is always bigger than any BigInt number. */ + return right_invert_sign; + } + + ecma_bigint_digit_t digits[3]; + uint32_t result = ecma_bigint_number_to_digits (right_value, digits); + + JERRY_ASSERT (ECMA_BIGINT_NUMBER_TO_DIGITS_GET_DIGITS (result) == 0 + || digits[ECMA_BIGINT_NUMBER_TO_DIGITS_GET_DIGITS (result) - 1] > 0); + + uint32_t digits_size = ECMA_BIGINT_NUMBER_TO_DIGITS_GET_DIGITS_SIZE (result); + + if (digits_size == 0) + { + JERRY_ASSERT (result & ECMA_BIGINT_NUMBER_TO_DIGITS_HAS_FRACTION); + /* The number is between [-1 .. 1] exclusive. */ + return left_sign; + } + + uint32_t right_size = digits_size + ECMA_BIGINT_NUMBER_TO_DIGITS_GET_ZERO_SIZE (result); + + if (left_size != right_size) + { + return left_size > right_size ? left_sign : -left_sign; + } + + ecma_bigint_digit_t *left_p = ECMA_BIGINT_GET_DIGITS (left_value_p, right_size); + ecma_bigint_digit_t *left_end_p = (ecma_bigint_digit_t *) (((uint8_t *) left_p) - digits_size); + ecma_bigint_digit_t *digits_p = (ecma_bigint_digit_t *) (((uint8_t *) digits) + digits_size); + + do + { + ecma_bigint_digit_t left = *(--left_p); + ecma_bigint_digit_t right = *(--digits_p); + + if (left != right) + { + return left > right ? left_sign : -left_sign; + } + } + while (left_p > left_end_p); + + left_end_p = ECMA_BIGINT_GET_DIGITS (left_value_p, 0); + + while (left_p > left_end_p) + { + if (*(--left_p) != 0) + { + return left_sign; + } + } + + return (result & ECMA_BIGINT_NUMBER_TO_DIGITS_HAS_FRACTION) ? -left_sign : 0; +} /* ecma_bigint_compare_to_number */ + +#undef ECMA_BIGINT_TO_SIGN + /** * Negate a non-zero BigInt value * diff --git a/jerry-core/ecma/operations/ecma-bigint.h b/jerry-core/ecma/operations/ecma-bigint.h index e88be1739..e48cffe6c 100644 --- a/jerry-core/ecma/operations/ecma-bigint.h +++ b/jerry-core/ecma/operations/ecma-bigint.h @@ -25,8 +25,17 @@ */ #define ECMA_BIGINT_SIGN 0x1 -ecma_value_t ecma_bigint_parse_string (const lit_utf8_byte_t *string_p, lit_utf8_size_t size); +ecma_value_t ecma_bigint_parse_string (const lit_utf8_byte_t *string_p, lit_utf8_size_t size, + bool throw_syntax_error); +ecma_value_t ecma_bigint_parse_string_value (ecma_value_t string, bool throw_syntax_error); ecma_string_t *ecma_bigint_to_string (ecma_value_t value, ecma_bigint_digit_t radix); +ecma_value_t ecma_bigint_number_to_bigint (ecma_number_t number); +ecma_value_t ecma_bigint_to_bigint (ecma_value_t value); + +bool ecma_bigint_is_equal_to_bigint (ecma_value_t left_value, ecma_value_t right_value); +bool ecma_bigint_is_equal_to_number (ecma_value_t left_value, ecma_number_t right_value); +int ecma_bigint_compare_to_bigint (ecma_value_t left_value, ecma_value_t right_value); +int ecma_bigint_compare_to_number (ecma_value_t left_value, ecma_number_t right_value); ecma_value_t ecma_bigint_negate (ecma_extended_primitive_t *value_p); ecma_value_t ecma_bigint_add_sub (ecma_value_t left_value, ecma_value_t right_value, bool is_add); diff --git a/jerry-core/ecma/operations/ecma-comparison.c b/jerry-core/ecma/operations/ecma-comparison.c index 0f041ca16..89e7e73b5 100644 --- a/jerry-core/ecma/operations/ecma-comparison.c +++ b/jerry-core/ecma/operations/ecma-comparison.c @@ -13,6 +13,7 @@ * limitations under the License. */ +#include "ecma-bigint.h" #include "ecma-comparison.h" #include "ecma-conversion.h" #include "ecma-globals.h" @@ -131,13 +132,6 @@ ecma_op_abstract_equality_compare (ecma_value_t x, /**< first operand */ y = tmp; } -#if ENABLED (JERRY_ESNEXT) - if (ecma_is_value_symbol (x)) - { - return ECMA_VALUE_FALSE; - } -#endif /* ENABLED (JERRY_ESNEXT) */ - if (ecma_is_value_boolean (y)) { if (ecma_is_value_boolean (x)) @@ -167,12 +161,57 @@ ecma_op_abstract_equality_compare (ecma_value_t x, /**< first operand */ return ecma_make_boolean_value (is_equal); } +#if ENABLED (JERRY_BUILTIN_BIGINT) + if (JERRY_UNLIKELY (ecma_is_value_bigint (x))) + { + if (ecma_is_value_bigint (y)) + { + return ecma_make_boolean_value (ecma_bigint_is_equal_to_bigint (x, y)); + } + + if (ecma_is_value_string (y)) + { + ecma_value_t bigint = ecma_bigint_parse_string_value (y, false); + + if (ECMA_IS_VALUE_ERROR (bigint) + || bigint == ECMA_VALUE_FALSE) + { + return bigint; + } + + JERRY_ASSERT (ecma_is_value_bigint (bigint)); + + ecma_value_t result = ecma_make_boolean_value (ecma_bigint_is_equal_to_bigint (x, bigint)); + + ecma_free_value (bigint); + return result; + } + + if (ecma_is_value_number (y)) + { + return ecma_make_boolean_value (ecma_bigint_is_equal_to_number (x, ecma_get_number_from_value (y))); + } + + return ECMA_VALUE_FALSE; + } +#endif /* ENABLED (JERRY_BUILTIN_BIGINT) */ + +#if ENABLED (JERRY_ESNEXT) + if (JERRY_UNLIKELY (ecma_is_value_symbol (x))) + { + return ECMA_VALUE_FALSE; + } +#endif /* ENABLED (JERRY_ESNEXT) */ + JERRY_ASSERT (ecma_is_value_object (x)); if (ecma_is_value_string (y) #if ENABLED (JERRY_ESNEXT) || ecma_is_value_symbol (y) #endif /* ENABLED (JERRY_ESNEXT) */ +#if ENABLED (JERRY_BUILTIN_BIGINT) + || ecma_is_value_bigint (y) +#endif /* ENABLED (JERRY_BUILTIN_BIGINT) */ || ecma_is_value_number (y)) { /* 9. */ @@ -237,8 +276,8 @@ ecma_op_strict_equality_compare (ecma_value_t x, /**< first operand */ /* The +0 === -0 case handled below. */ } - JERRY_ASSERT (ecma_is_value_number (x) || ecma_is_value_string (x)); - JERRY_ASSERT (ecma_is_value_number (y) || ecma_is_value_string (y)); + JERRY_ASSERT (ecma_is_value_number (x) || ecma_is_value_string (x) || ECMA_CHECK_BIGINT_IN_ASSERT (x)); + JERRY_ASSERT (ecma_is_value_number (y) || ecma_is_value_string (y) || ECMA_CHECK_BIGINT_IN_ASSERT (y)); if (ecma_is_value_string (x)) { @@ -253,6 +292,18 @@ ecma_op_strict_equality_compare (ecma_value_t x, /**< first operand */ return ecma_compare_ecma_strings (x_str_p, y_str_p); } +#if ENABLED (JERRY_BUILTIN_BIGINT) + if (JERRY_UNLIKELY (ecma_is_value_bigint (x))) + { + if (!ecma_is_value_bigint (y)) + { + return false; + } + + return ecma_bigint_is_equal_to_bigint (x, y); + } +#endif /* ENABLED (JERRY_BUILTIN_BIGINT) */ + if (!ecma_is_value_number (y)) { return false; @@ -317,93 +368,164 @@ ecma_op_abstract_relational_compare (ecma_value_t x, /**< first operand */ return prim_second_converted_value; } - const ecma_value_t px = left_first ? prim_first_converted_value : prim_second_converted_value; - const ecma_value_t py = left_first ? prim_second_converted_value : prim_first_converted_value; + ecma_value_t px = left_first ? prim_first_converted_value : prim_second_converted_value; + ecma_value_t py = left_first ? prim_second_converted_value : prim_first_converted_value; const bool is_px_string = ecma_is_value_string (px); const bool is_py_string = ecma_is_value_string (py); if (!(is_px_string && is_py_string)) { - /* 3. */ - - /* a. */ - ECMA_OP_TO_NUMBER_TRY_CATCH (nx, px, ret_value); - ECMA_OP_TO_NUMBER_TRY_CATCH (ny, py, ret_value); - - /* b. */ - if (ecma_number_is_nan (nx) - || ecma_number_is_nan (ny)) +#if ENABLED (JERRY_BUILTIN_BIGINT) + if (JERRY_LIKELY (!ecma_is_value_bigint (px)) + && JERRY_LIKELY (!ecma_is_value_bigint (py))) { - /* c., d. */ - ret_value = ECMA_VALUE_UNDEFINED; - } - else - { - bool is_x_less_than_y = (nx < ny); +#endif /* ENABLED (JERRY_BUILTIN_BIGINT) */ + /* 3. */ -#ifndef JERRY_NDEBUG - bool is_x_less_than_y_check; + /* a. */ + ECMA_OP_TO_NUMBER_TRY_CATCH (nx, px, ret_value); + ECMA_OP_TO_NUMBER_TRY_CATCH (ny, py, ret_value); - if (nx == ny - || (ecma_number_is_zero (nx) - && ecma_number_is_zero (ny))) + /* b. */ + if (ecma_number_is_nan (nx) + || ecma_number_is_nan (ny)) { - /* e., f., g. */ - is_x_less_than_y_check = false; - } - else if (ecma_number_is_infinity (nx) - && !ecma_number_is_negative (nx)) - { - /* h. */ - is_x_less_than_y_check = false; - } - else if (ecma_number_is_infinity (ny) - && !ecma_number_is_negative (ny)) - { - /* i. */ - is_x_less_than_y_check = true; - } - else if (ecma_number_is_infinity (ny) - && ecma_number_is_negative (ny)) - { - /* j. */ - is_x_less_than_y_check = false; - } - else if (ecma_number_is_infinity (nx) - && ecma_number_is_negative (nx)) - { - /* k. */ - is_x_less_than_y_check = true; + /* c., d. */ + ret_value = ECMA_VALUE_UNDEFINED; } else { - /* l. */ - JERRY_ASSERT (!ecma_number_is_nan (nx) - && !ecma_number_is_infinity (nx)); - JERRY_ASSERT (!ecma_number_is_nan (ny) - && !ecma_number_is_infinity (ny)); - JERRY_ASSERT (!(ecma_number_is_zero (nx) - && ecma_number_is_zero (ny))); + bool is_x_less_than_y = (nx < ny); - if (nx < ny) +#ifndef JERRY_NDEBUG + bool is_x_less_than_y_check; + + if (nx == ny + || (ecma_number_is_zero (nx) + && ecma_number_is_zero (ny))) { + /* e., f., g. */ + is_x_less_than_y_check = false; + } + else if (ecma_number_is_infinity (nx) + && !ecma_number_is_negative (nx)) + { + /* h. */ + is_x_less_than_y_check = false; + } + else if (ecma_number_is_infinity (ny) + && !ecma_number_is_negative (ny)) + { + /* i. */ + is_x_less_than_y_check = true; + } + else if (ecma_number_is_infinity (ny) + && ecma_number_is_negative (ny)) + { + /* j. */ + is_x_less_than_y_check = false; + } + else if (ecma_number_is_infinity (nx) + && ecma_number_is_negative (nx)) + { + /* k. */ is_x_less_than_y_check = true; } else { - is_x_less_than_y_check = false; - } - } + /* l. */ + JERRY_ASSERT (!ecma_number_is_nan (nx) + && !ecma_number_is_infinity (nx)); + JERRY_ASSERT (!ecma_number_is_nan (ny) + && !ecma_number_is_infinity (ny)); + JERRY_ASSERT (!(ecma_number_is_zero (nx) + && ecma_number_is_zero (ny))); - JERRY_ASSERT (is_x_less_than_y_check == is_x_less_than_y); + if (nx < ny) + { + is_x_less_than_y_check = true; + } + else + { + is_x_less_than_y_check = false; + } + } + + JERRY_ASSERT (is_x_less_than_y_check == is_x_less_than_y); #endif /* !JERRY_NDEBUG */ - ret_value = ecma_make_boolean_value (is_x_less_than_y); - } + ret_value = ecma_make_boolean_value (is_x_less_than_y); + } - ECMA_OP_TO_NUMBER_FINALIZE (ny); - ECMA_OP_TO_NUMBER_FINALIZE (nx); + ECMA_OP_TO_NUMBER_FINALIZE (ny); + ECMA_OP_TO_NUMBER_FINALIZE (nx); +#if ENABLED (JERRY_BUILTIN_BIGINT) + } + else + { + bool invert_result = false; + int compare_result = 0; + + if (!ecma_is_value_bigint (px)) + { + ecma_value_t tmp = px; + px = py; + py = tmp; + invert_result = true; + } + + JERRY_ASSERT (ecma_is_value_bigint (px)); + + if (ecma_is_value_bigint (py)) + { + compare_result = ecma_bigint_compare_to_bigint (px, py); + } + else if (ecma_is_value_string (py)) + { + ret_value = ecma_bigint_parse_string_value (py, false); + + if (!ECMA_IS_VALUE_ERROR (ret_value)) + { + if (ret_value == ECMA_VALUE_FALSE) + { + ret_value = ECMA_VALUE_UNDEFINED; + } + else + { + compare_result = ecma_bigint_compare_to_bigint (px, ret_value); + ecma_free_value (ret_value); + ret_value = ECMA_VALUE_EMPTY; + } + } + } + else + { + ECMA_OP_TO_NUMBER_TRY_CATCH (ny, py, ret_value); + + if (ecma_number_is_nan (ny)) + { + ret_value = ECMA_VALUE_UNDEFINED; + } + else + { + compare_result = ecma_bigint_compare_to_number (px, ny); + } + + ECMA_OP_TO_NUMBER_FINALIZE (ny); + } + + if (ret_value == ECMA_VALUE_EMPTY) + { + if (invert_result) + { + compare_result = -compare_result; + } + + ret_value = ecma_make_boolean_value (compare_result < 0); + } + } +#endif /* ENABLED (JERRY_BUILTIN_BIGINT) */ } else { /* 4. */ diff --git a/jerry-core/ecma/operations/ecma-conversion.c b/jerry-core/ecma/operations/ecma-conversion.c index f1aeb7819..9e010ea4c 100644 --- a/jerry-core/ecma/operations/ecma-conversion.c +++ b/jerry-core/ecma/operations/ecma-conversion.c @@ -125,7 +125,7 @@ ecma_op_same_value (ecma_value_t x, /**< ecma value */ return ecma_compare_ecma_strings (x_str_p, y_str_p); } - JERRY_ASSERT (ecma_is_value_object (x) || ECMA_ASSERT_VALUE_IS_SYMBOL (x)); + JERRY_ASSERT (ecma_is_value_object (x) || ECMA_CHECK_SYMBOL_IN_ASSERT (x)); return false; } /* ecma_op_same_value */ @@ -247,7 +247,7 @@ ecma_op_to_boolean (ecma_value_t value) /**< ecma value */ return !ecma_string_is_empty (str_p); } - JERRY_ASSERT (ecma_is_value_object (value) || ECMA_ASSERT_VALUE_IS_SYMBOL (value)); + JERRY_ASSERT (ecma_is_value_object (value) || ECMA_CHECK_SYMBOL_IN_ASSERT (value)); return true; } /* ecma_op_to_boolean */ diff --git a/tests/jerry/es.next/bigint3.js b/tests/jerry/es.next/bigint3.js new file mode 100644 index 000000000..d3d0c3e1d --- /dev/null +++ b/tests/jerry/es.next/bigint3.js @@ -0,0 +1,56 @@ +/* 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. + */ + +function check_result(bigint, expected) +{ + assert(bigint.toString() === expected) +} + +function check_error (code, error_type) +{ + try { + eval(code) + assert(false) + } catch (e) { + assert(e instanceof error_type) + } +} + +check_error("BigInt(undefined)", TypeError) +check_error("BigInt(null)", TypeError) +check_error("BigInt(Symbol())", TypeError) + +check_error("BigInt(0.25)", RangeError) +check_error("BigInt(-0.25)", RangeError) +check_error("BigInt(-10000000.25)", RangeError) +check_error("BigInt(4503599627370495.5)", RangeError) +check_error("BigInt(NaN)", RangeError) +check_error("BigInt(Infinity)", RangeError) + +check_result(BigInt(true), "1") +check_result(BigInt(false), "0") +check_result(BigInt({ valueOf() { return "0x100" } }), "256") + +check_result(BigInt(0), "0") +check_result(BigInt(-0), "0") +check_result(BigInt(8192), "8192") +check_result(BigInt(-0xffffffffff), "-1099511627775") +check_result(BigInt(0x1fffffffffffff), "9007199254740991") +check_result(BigInt(-4503599627370496), "-4503599627370496") +check_result(BigInt(4503599627370496.5), "4503599627370496") +check_result(BigInt(9007199254740991.5), "9007199254740992") +check_result(BigInt(0x1fffffffffffff * (2 ** 70)), "10633823966279325802638835764831453184") +check_result(BigInt(-0x1fffffffffffff * (2 ** 128)), "-3064991081731777376434327133362154903862870812598992896") + diff --git a/tests/jerry/es.next/bigint4.js b/tests/jerry/es.next/bigint4.js new file mode 100644 index 000000000..ef1a0e14d --- /dev/null +++ b/tests/jerry/es.next/bigint4.js @@ -0,0 +1,177 @@ +/* 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. + */ + +/* Strict equal. */ + +assert(BigInt("0") === BigInt("0")) +assert(BigInt("-77") === BigInt("-77")) +assert(!(BigInt("-77") !== BigInt("-77"))) + +assert(!(Object(BigInt("-77")) === BigInt("-77"))) +assert(BigInt("-77") !== Object(BigInt("-77"))) + +assert(BigInt("0xffffffffffffffffffffffffffffffff") === BigInt("0xffffffffffffffffffffffffffffffff")) +assert(!(BigInt("0xfffffffffffffffffffffffffffffffe") === BigInt("0xffffffffffffffffffffffffffffffff"))) +assert(BigInt("0x100000000000000000000000000000000") !== BigInt("0xffffffffffffffffffffffffffffffff")) +assert(!(BigInt("1234") === 1234)) +assert(-4567 !== BigInt("-4567")) + +/* Equal. */ + +assert(BigInt("0x100") == BigInt("256")) +assert(BigInt("-77") == "-77") +assert("168" == BigInt("168")) +assert(!("0xffffffffffffffffffffffffffffffff" != BigInt("0xffffffffffffffffffffffffffffffff"))) + +assert(BigInt("0x1000") == 0x1000) +assert(468123 == BigInt("468123")) + +assert(!(BigInt("100000000") == 100000000.5)) +assert(-0.125 != BigInt("0")) +assert(!("InvalidBigIntString" == BigInt("100000000"))) +assert(BigInt("100000000") != "10000 0000") + +assert(BigInt("0") == 0) +assert(!(-0 != BigInt("0"))) +assert(!(BigInt("0") == 0.0000152587890625)) +assert(0.0000152587890625 != BigInt("0")) + +assert(!(BigInt("100000000") == NaN)) +assert(NaN != BigInt("-100000000")) +assert(!(BigInt("100000000000000000000000000") == Infinity)) +assert(Infinity != BigInt("100000000000000000000000000")) + +/* Relational. */ + +assert(!(BigInt("1234") < BigInt("1234"))) +assert(BigInt("1234") >= BigInt("1234")) +assert(BigInt("1234") <= BigInt("1234")) +assert(!(BigInt("1234") > BigInt("1234"))) + +assert(BigInt("1234") < BigInt("1235")) +assert(!(BigInt("1234") >= BigInt("1235"))) +assert(BigInt("1234") <= BigInt("1235")) +assert(!(BigInt("1234") > BigInt("1235"))) + +assert(!(BigInt("123456789012345678901234567890") < "123456789012345678901234567890")) +assert(BigInt("123456789012345678901234567890") >= "123456789012345678901234567890") +assert(BigInt("123456789012345678901234567890") <= "123456789012345678901234567890") +assert(!(BigInt("123456789012345678901234567890") > "123456789012345678901234567890")) + +assert(!("0x1234567890abcdef1234567890abcdef" < BigInt("0x1234567890abcdef1234567890abcdef"))) +assert("0x1234567890abcdef1234567890abcdef" >= BigInt("0x1234567890abcdef1234567890abcdef")) +assert("0x1234567890abcdef1234567890abcdef" <= BigInt("0x1234567890abcdef1234567890abcdef")) +assert(!("0x1234567890abcdef1234567890abcdef" > BigInt("0x1234567890abcdef1234567890abcdef"))) + +assert(!("Invalid" < BigInt("100"))) +assert(!("Invalid" >= BigInt("100"))) +assert(!("Invalid" <= BigInt("100"))) +assert(!("Invalid" > BigInt("100"))) + +assert(!(BigInt("0") < "NotABigInt")) +assert(!(BigInt("0") >= "NotABigInt")) +assert(!(BigInt("0") <= "NotABigInt")) +assert(!(BigInt("0") > "NotABigInt")) + +assert(!(BigInt("0") < 0)) +assert(BigInt("0") >= 0) +assert(BigInt("0") <= 0) +assert(!(BigInt("0") > 0)) + +assert(!(-0 < BigInt("0"))) +assert(-0 >= BigInt("0")) +assert(-0 <= BigInt("0")) +assert(!(-0 > BigInt("0"))) + +assert(BigInt("0") < 67) +assert(!(BigInt("0") > 67)) +assert(!(BigInt("0") < -0.125)) +assert(BigInt("0") > -0.125) + +assert(!(BigInt("7") < NaN)) +assert(!(BigInt("7") >= NaN)) +assert(!(BigInt("7") <= NaN)) +assert(!(BigInt("7") > NaN)) + +assert(!(Infinity < BigInt("1000000000000000000000000000000"))) +assert(!(Infinity <= BigInt("1000000000000000000000000000000"))) +assert(Infinity >= BigInt("1000000000000000000000000000000")) +assert(Infinity > BigInt("1000000000000000000000000000000")) + +assert(-Infinity < BigInt("1000000000000000000000000000000")) +assert(-Infinity <= BigInt("1000000000000000000000000000000")) +assert(!(-Infinity >= BigInt("1000000000000000000000000000000"))) +assert(!(-Infinity > BigInt("1000000000000000000000000000000"))) + +assert(BigInt("-10000") < 1) +assert(BigInt("-10000") <= 1) +assert(!(BigInt("-10000") >= 1)) +assert(!(BigInt("-10000") > 1)) + +assert(!(1 < BigInt("-12345678"))) +assert(!(1 <= BigInt("-12345678"))) +assert(1 >= BigInt("-12345678")) +assert(1 > BigInt("-12345678")) + +assert(!(BigInt("1") < 0.5)) +assert(!(BigInt("1") <= 0.5)) +assert(BigInt("1") >= 0.5) +assert(BigInt("1") > 0.5) + +assert(!(-0.5 < BigInt("-1"))) +assert(!(-0.5 <= BigInt("-1"))) +assert(-0.5 >= BigInt("-1")) +assert(-0.5 > BigInt("-1")) + +assert(!(BigInt("0x1000000000000000000000000000000") < 0x100000)) +assert(!(BigInt("0x1000000000000000000000000000000") <= 0x100000)) +assert(BigInt("0x1000000000000000000000000000000") >= 0x100000) +assert(BigInt("0x1000000000000000000000000000000") > 0x100000) + +assert(-0x1000000000000000000000000000000 < BigInt("-1234")) +assert(-0x1000000000000000000000000000000 <= BigInt("-1234")) +assert(!(-0x1000000000000000000000000000000 >= BigInt("-1234"))) +assert(!(-0x1000000000000000000000000000000 > BigInt("-1234"))) + +assert(0x1234567880000000000000000000000 < BigInt("0x1234567890000000000000000000000")) +assert(0x1234567880000000000000000000000 <= BigInt("0x1234567890000000000000000000000")) +assert(!(0x1234567880000000000000000000000 > BigInt("0x1234567890000000000000000000000"))) +assert(!(0x1234567880000000000000000000000 >= BigInt("0x1234567890000000000000000000000"))) + +assert(-BigInt("0x1234567890000000000000000000000") < -0x1234567880000000000000000000000) +assert(-BigInt("0x1234567890000000000000000000000") <= -0x1234567880000000000000000000000) +assert(!(-BigInt("0x1234567890000000000000000000000") >= -0x1234567880000000000000000000000)) +assert(!(-BigInt("0x1234567890000000000000000000000") > -0x1234567880000000000000000000000)) + +// True because of rounding +assert(0x1234567890000000000000000000001 < BigInt("0x1234567890000000000000000000001")) +assert(0x1234567890000000000000000000001 <= BigInt("0x1234567890000000000000000000001")) +assert(!(0x1234567890000000000000000000001 >= BigInt("0x1234567890000000000000000000001"))) +assert(!(0x1234567890000000000000000000001 > BigInt("0x1234567890000000000000000000001"))) + +assert(-BigInt("0x1234567890000000000000000000001") < -0x1234567890000000000000000000001) +assert(-BigInt("0x1234567890000000000000000000001") <= -0x1234567890000000000000000000001) +assert(!(-BigInt("0x1234567890000000000000000000001") >= -0x1234567890000000000000000000001)) +assert(!(-BigInt("0x1234567890000000000000000000001") > -0x1234567890000000000000000000001)) + +assert(!(1.0000152587890625 < BigInt("1"))) +assert(!(1.0000152587890625 <= BigInt("1"))) +assert(1.0000152587890625 >= BigInt("1")) +assert(1.0000152587890625 > BigInt("1")) + +assert(!(BigInt("-1") < -1.0000152587890625)) +assert(!(BigInt("-1") <= -1.0000152587890625)) +assert(BigInt("-1") >= -1.0000152587890625) +assert(BigInt("-1") > -1.0000152587890625) diff --git a/tests/test262-esnext-excludelist.xml b/tests/test262-esnext-excludelist.xml index f40b913e9..1a95ec07a 100644 --- a/tests/test262-esnext-excludelist.xml +++ b/tests/test262-esnext-excludelist.xml @@ -707,9 +707,6 @@ - - - @@ -720,8 +717,6 @@ - - @@ -1167,7 +1162,6 @@ -