mirror of
https://github.com/jerryscript-project/jerryscript.git
synced 2025-12-15 16:29:21 +00:00
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
This commit is contained in:
parent
f1eba9f826
commit
cfd69d3b70
@ -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) */
|
||||
|
||||
@ -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 */
|
||||
|
||||
/**
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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 */
|
||||
|
||||
/**
|
||||
|
||||
@ -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 */
|
||||
|
||||
@ -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
|
||||
*
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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. */
|
||||
|
||||
@ -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 */
|
||||
|
||||
56
tests/jerry/es.next/bigint3.js
Normal file
56
tests/jerry/es.next/bigint3.js
Normal file
@ -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")
|
||||
|
||||
177
tests/jerry/es.next/bigint4.js
Normal file
177
tests/jerry/es.next/bigint4.js
Normal file
@ -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)
|
||||
@ -707,9 +707,6 @@
|
||||
<test id="built-ins/BigInt/constructor-from-octal-string.js"><reason></reason></test>
|
||||
<test id="built-ins/BigInt/constructor-integer.js"><reason></reason></test>
|
||||
<test id="built-ins/BigInt/constructor-trailing-leading-spaces.js"><reason></reason></test>
|
||||
<test id="built-ins/BigInt/infinity-throws-rangeerror.js"><reason></reason></test>
|
||||
<test id="built-ins/BigInt/nan-throws-rangeerror.js"><reason></reason></test>
|
||||
<test id="built-ins/BigInt/negative-infinity-throws.rangeerror.js"><reason></reason></test>
|
||||
<test id="built-ins/BigInt/non-integer-rangeerror.js"><reason></reason></test>
|
||||
<test id="built-ins/BigInt/prototype/toString/a-z.js"><reason></reason></test>
|
||||
<test id="built-ins/BigInt/prototype/toString/default-radix.js"><reason></reason></test>
|
||||
@ -720,8 +717,6 @@
|
||||
<test id="built-ins/BigInt/prototype/toString/thisbigintvalue-not-valid-throws.js"><reason></reason></test>
|
||||
<test id="built-ins/BigInt/prototype/valueOf/cross-realm.js"><reason></reason></test>
|
||||
<test id="built-ins/BigInt/prototype/valueOf/return.js"><reason></reason></test>
|
||||
<test id="built-ins/BigInt/tostring-throws.js"><reason></reason></test>
|
||||
<test id="built-ins/BigInt/valueof-throws.js"><reason></reason></test>
|
||||
<test id="built-ins/Boolean/proto-from-ctor-realm.js"><reason></reason></test>
|
||||
<test id="built-ins/DataView/buffer-does-not-have-arraybuffer-data-throws-sab.js"><reason></reason></test>
|
||||
<test id="built-ins/DataView/buffer-reference-sab.js"><reason></reason></test>
|
||||
@ -1167,7 +1162,6 @@
|
||||
<test id="built-ins/Object/prototype/toString/symbol-tag-non-str-bigint.js"><reason></reason></test>
|
||||
<test id="built-ins/Object/prototype/toString/symbol-tag-non-str-builtin.js"><reason></reason></test>
|
||||
<test id="built-ins/Object/prototype/toString/symbol-tag-non-str-proxy-function.js"><reason></reason></test>
|
||||
<test id="built-ins/Object/prototype/toString/symbol-tag-override-bigint.js"><reason></reason></test>
|
||||
<test id="built-ins/Object/setPrototypeOf/bigint.js"><reason></reason></test>
|
||||
<test id="built-ins/Object/subclass-object-arg.js"><reason></reason></test>
|
||||
<test id="built-ins/Object/values/order-after-define-property.js"><reason></reason></test>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user