mirror of
https://github.com/jerryscript-project/jerryscript.git
synced 2025-12-15 16:29:21 +00:00
Implement BigInt primitve type and some of its operations (#4062)
Supported operations: - parse BigInt (decimal, hexadecimal, binary) - toString with any radix between 2 and 36 - arithmetic operations: negate, add, subtract, multiply, divide, modulo - left and right shift JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com
This commit is contained in:
parent
3eb69075f7
commit
df2f7782f7
@ -652,9 +652,9 @@ jerry_value_is_abort (const jerry_value_t value) /**< api value */
|
||||
return false;
|
||||
}
|
||||
|
||||
ecma_error_reference_t *error_ref_p = ecma_get_error_reference_from_value (value);
|
||||
ecma_extended_primitive_t *error_ref_p = ecma_get_extended_primitive_from_value (value);
|
||||
|
||||
return (error_ref_p->refs_and_flags & ECMA_ERROR_REF_ABORT) != 0;
|
||||
return ECMA_EXTENDED_PRIMITIVE_GET_TYPE (error_ref_p) == ECMA_EXTENDED_PRIMITIVE_ABORT;
|
||||
} /* jerry_value_is_abort */
|
||||
|
||||
/**
|
||||
@ -998,6 +998,9 @@ jerry_is_feature_enabled (const jerry_feature_t feature) /**< feature to check *
|
||||
#if ENABLED (JERRY_BUILTIN_WEAKSET)
|
||||
|| feature == JERRY_FEATURE_WEAKSET
|
||||
#endif /* ENABLED (JERRY_BUILTIN_WEAKSET) */
|
||||
#if ENABLED (JERRY_BUILTIN_BIGINT)
|
||||
|| feature == JERRY_FEATURE_BIGINT
|
||||
#endif /* ENABLED (JERRY_BUILTIN_BIGINT) */
|
||||
);
|
||||
} /* jerry_is_feature_enabled */
|
||||
|
||||
@ -1166,7 +1169,7 @@ jerry_get_value_from_error (jerry_value_t value, /**< api value */
|
||||
return release ? value : ecma_copy_value (value);
|
||||
}
|
||||
|
||||
jerry_value_t ret_val = jerry_acquire_value (ecma_get_error_reference_from_value (value)->value);
|
||||
jerry_value_t ret_val = jerry_acquire_value (ecma_get_extended_primitive_from_value (value)->u.value);
|
||||
|
||||
if (release)
|
||||
{
|
||||
@ -1186,7 +1189,7 @@ jerry_get_error_type (jerry_value_t value) /**< api value */
|
||||
{
|
||||
if (JERRY_UNLIKELY (ecma_is_value_error_reference (value)))
|
||||
{
|
||||
value = ecma_get_error_reference_from_value (value)->value;
|
||||
value = ecma_get_extended_primitive_from_value (value)->u.value;
|
||||
}
|
||||
|
||||
if (!ecma_is_value_object (value))
|
||||
@ -1360,7 +1363,7 @@ jerry_acquire_value (jerry_value_t value) /**< API value */
|
||||
|
||||
if (JERRY_UNLIKELY (ecma_is_value_error_reference (value)))
|
||||
{
|
||||
ecma_ref_error_reference (ecma_get_error_reference_from_value (value));
|
||||
ecma_ref_extended_primitive (ecma_get_extended_primitive_from_value (value));
|
||||
return value;
|
||||
}
|
||||
|
||||
@ -1377,7 +1380,7 @@ jerry_release_value (jerry_value_t value) /**< API value */
|
||||
|
||||
if (JERRY_UNLIKELY (ecma_is_value_error_reference (value)))
|
||||
{
|
||||
ecma_deref_error_reference (ecma_get_error_reference_from_value (value));
|
||||
ecma_deref_error_reference (ecma_get_extended_primitive_from_value (value));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@ -115,6 +115,10 @@
|
||||
# define JERRY_BUILTIN_TYPEDARRAY JERRY_ESNEXT
|
||||
#endif /* !defined (JERRY_BUILTIN_TYPEDARRAY) */
|
||||
|
||||
#ifndef JERRY_BUILTIN_BIGINT
|
||||
# define JERRY_BUILTIN_BIGINT JERRY_ESNEXT
|
||||
#endif /* !defined (JERRY_BUILTIN_BIGINT) */
|
||||
|
||||
#ifndef JERRY_MODULE_SYSTEM
|
||||
# define JERRY_MODULE_SYSTEM JERRY_ESNEXT
|
||||
#endif /* !defined (JERRY_MODULE_SYSTEM) */
|
||||
@ -555,6 +559,10 @@
|
||||
|| ((JERRY_BUILTIN_TYPEDARRAY != 0) && (JERRY_BUILTIN_TYPEDARRAY != 1))
|
||||
# error "Invalid value for JERRY_BUILTIN_TYPEDARRAY macro."
|
||||
#endif
|
||||
#if !defined (JERRY_BUILTIN_BIGINT) \
|
||||
|| ((JERRY_BUILTIN_BIGINT != 0) && (JERRY_BUILTIN_BIGINT != 1))
|
||||
# error "Invalid value for JERRY_BUILTIN_BIGINT macro."
|
||||
#endif
|
||||
#if !defined (JERRY_MODULE_SYSTEM) \
|
||||
|| ((JERRY_MODULE_SYSTEM != 0) && (JERRY_MODULE_SYSTEM != 1))
|
||||
# error "Invalid value for JERRY_MODULE_SYSTEM macro."
|
||||
|
||||
@ -1202,11 +1202,14 @@ ecma_gc_free_object (ecma_object_t *object_p) /**< object to free */
|
||||
|
||||
switch (ext_object_p->u.class_prop.class_id)
|
||||
{
|
||||
case LIT_MAGIC_STRING_STRING_UL:
|
||||
case LIT_MAGIC_STRING_NUMBER_UL:
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
case LIT_MAGIC_STRING_SYMBOL_UL:
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
case LIT_MAGIC_STRING_STRING_UL:
|
||||
case LIT_MAGIC_STRING_NUMBER_UL:
|
||||
#if ENABLED (JERRY_BUILTIN_BIGINT)
|
||||
case LIT_MAGIC_STRING_BIGINT_UL:
|
||||
#endif /* ENABLED (JERRY_BUILTIN_BIGINT) */
|
||||
{
|
||||
ecma_free_value (ext_object_p->u.class_prop.u.value);
|
||||
break;
|
||||
|
||||
@ -85,6 +85,7 @@ typedef enum
|
||||
ECMA_TYPE_OBJECT = 3, /**< pointer to description of an object */
|
||||
ECMA_TYPE_SYMBOL = 4, /**< pointer to description of a symbol */
|
||||
ECMA_TYPE_DIRECT_STRING = 5, /**< directly encoded string values */
|
||||
ECMA_TYPE_BIGINT = 6, /**< pointer to a bigint primitive */
|
||||
ECMA_TYPE_ERROR = 7, /**< pointer to description of an error reference (only supported by C API) */
|
||||
ECMA_TYPE_SNAPSHOT_OFFSET = ECMA_TYPE_ERROR, /**< offset to a snapshot number/string */
|
||||
ECMA_TYPE___MAX = ECMA_TYPE_ERROR /** highest value for ecma types */
|
||||
@ -1710,28 +1711,44 @@ typedef struct
|
||||
} ecma_stringbuilder_t;
|
||||
|
||||
/**
|
||||
* Abort flag for error reference.
|
||||
* Types for extended primitive values.
|
||||
*/
|
||||
#define ECMA_ERROR_REF_ABORT 0x1
|
||||
|
||||
/**
|
||||
* Value for increasing or decreasing the reference counter.
|
||||
*/
|
||||
#define ECMA_ERROR_REF_ONE (1u << 1)
|
||||
|
||||
/**
|
||||
* Maximum value of the reference counter.
|
||||
*/
|
||||
#define ECMA_ERROR_MAX_REF (UINT32_MAX - 1u)
|
||||
typedef enum
|
||||
{
|
||||
#ifndef JERRY_BUILTIN_BIGINT
|
||||
ECMA_EXTENDED_PRIMITIVE_BIGINT, /**< BigInt value */
|
||||
#endif /* !defined (JERRY_BUILTIN_BIGINT) */
|
||||
ECMA_EXTENDED_PRIMITIVE_ERROR, /**< external API error reference */
|
||||
ECMA_EXTENDED_PRIMITIVE_ABORT, /**< external API abort reference */
|
||||
} ecma_extended_primitive_type_t;
|
||||
|
||||
/**
|
||||
* Representation of a thrown value on API level.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint32_t refs_and_flags; /**< reference counter */
|
||||
ecma_value_t value; /**< referenced value */
|
||||
} ecma_error_reference_t;
|
||||
uint32_t refs_and_type; /**< reference counter and type */
|
||||
union
|
||||
{
|
||||
ecma_value_t value; /**< referenced value */
|
||||
uint32_t bigint_sign_and_size; /**< BigInt properties */
|
||||
} u;
|
||||
} ecma_extended_primitive_t;
|
||||
|
||||
/**
|
||||
* Get the type of an extended primitve value.
|
||||
*/
|
||||
#define ECMA_EXTENDED_PRIMITIVE_GET_TYPE(primitve_p) ((primitve_p)->refs_and_type & 0x7)
|
||||
|
||||
/**
|
||||
* Value for increasing or decreasing the reference counter.
|
||||
*/
|
||||
#define ECMA_EXTENDED_PRIMITIVE_REF_ONE (1u << 3)
|
||||
|
||||
/**
|
||||
* Maximum value of the reference counter.
|
||||
*/
|
||||
#define ECMA_EXTENDED_PRIMITIVE_MAX_REF (UINT32_MAX - (ECMA_EXTENDED_PRIMITIVE_REF_ONE - 1))
|
||||
|
||||
#if ENABLED (JERRY_PROPRETY_HASHMAP)
|
||||
|
||||
@ -2009,7 +2026,7 @@ typedef struct
|
||||
ecma_object_t *buffer_p; /**< [[ViewedArrayBuffer]] internal slot */
|
||||
uint32_t byte_offset; /**< [[ByteOffset]] internal slot */
|
||||
} ecma_dataview_object_t;
|
||||
#endif /* ENABLED (JERRY_BUILTIN_DATAVIEW */
|
||||
#endif /* ENABLED (JERRY_BUILTIN_DATAVIEW) */
|
||||
|
||||
/**
|
||||
* Flag for indicating whether the symbol is a well known symbol
|
||||
@ -2091,6 +2108,28 @@ typedef uint64_t ecma_length_t;
|
||||
typedef uint32_t ecma_length_t;
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
|
||||
#if ENABLED (JERRY_BUILTIN_BIGINT)
|
||||
|
||||
/**
|
||||
* BigUInt data is a sequence of uint32_t numbers.
|
||||
*/
|
||||
typedef uint32_t ecma_bigint_digit_t;
|
||||
|
||||
/**
|
||||
* Return the size of a BigInt value in ecma_bigint_data_t units.
|
||||
*/
|
||||
#define ECMA_BIGINT_GET_SIZE(value_p) \
|
||||
((value_p)->u.bigint_sign_and_size & ~(uint32_t) (sizeof (ecma_bigint_digit_t) - 1))
|
||||
|
||||
/**
|
||||
* Size of memory needs to be allocated for the digits of a BigInt.
|
||||
* The value is rounded up for two digits.
|
||||
*/
|
||||
#define ECMA_BIGINT_GET_BYTE_SIZE(size) \
|
||||
(size_t) (((size) + sizeof (ecma_bigint_digit_t)) & ~(2 * sizeof (ecma_bigint_digit_t) - 1))
|
||||
|
||||
#endif /* ENABLED (JERRY_BUILTIN_BIGINT) */
|
||||
|
||||
/**
|
||||
* Struct for counting the different types properties in objects
|
||||
*/
|
||||
|
||||
@ -330,6 +330,22 @@ ecma_is_value_symbol (ecma_value_t value) /**< ecma value */
|
||||
} /* ecma_is_value_symbol */
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
|
||||
#if ENABLED (JERRY_BUILTIN_BIGINT)
|
||||
|
||||
/**
|
||||
* Check if the value is bigint.
|
||||
*
|
||||
* @return true - if the value contains bigint value,
|
||||
* false - otherwise
|
||||
*/
|
||||
inline bool JERRY_ATTR_CONST JERRY_ATTR_ALWAYS_INLINE
|
||||
ecma_is_value_bigint (ecma_value_t value) /**< ecma value */
|
||||
{
|
||||
return (ecma_get_value_type_field (value) == ECMA_TYPE_BIGINT);
|
||||
} /* ecma_is_value_bigint */
|
||||
|
||||
#endif /* ENABLED (JERRY_BUILTIN_BIGINT) */
|
||||
|
||||
/**
|
||||
* Check if the value can be property name.
|
||||
*
|
||||
@ -401,13 +417,29 @@ 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_ASSERT_VALUE_IS_SYMBOL (value)
|
||||
|| ECMA_CHECK_IS_VALUE_SYMBOL (value)
|
||||
|| ECMA_CHECK_IS_VALUE_BIGINT (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 */
|
||||
|
||||
/**
|
||||
@ -686,12 +718,14 @@ ecma_make_object_value (const ecma_object_t *object_p) /**< object to reference
|
||||
* @return ecma-value representation of the Error reference
|
||||
*/
|
||||
inline ecma_value_t JERRY_ATTR_PURE JERRY_ATTR_ALWAYS_INLINE
|
||||
ecma_make_error_reference_value (const ecma_error_reference_t *error_ref_p) /**< error reference */
|
||||
ecma_make_extended_primitive_value (const ecma_extended_primitive_t *primitve_p, /**< extended primitve value */
|
||||
uint32_t type) /**< ecma type of extended primitve value */
|
||||
{
|
||||
JERRY_ASSERT (error_ref_p != NULL);
|
||||
JERRY_ASSERT (primitve_p != NULL);
|
||||
JERRY_ASSERT (type == ECMA_TYPE_BIGINT || type == ECMA_TYPE_ERROR);
|
||||
|
||||
return ecma_pointer_to_ecma_value (error_ref_p) | ECMA_TYPE_ERROR;
|
||||
} /* ecma_make_error_reference_value */
|
||||
return ecma_pointer_to_ecma_value (primitve_p) | type;
|
||||
} /* ecma_make_extended_primitive_value */
|
||||
|
||||
/**
|
||||
* Get integer value from an integer ecma value
|
||||
@ -817,13 +851,14 @@ ecma_get_object_from_value (ecma_value_t value) /**< ecma value */
|
||||
*
|
||||
* @return the pointer
|
||||
*/
|
||||
inline ecma_error_reference_t *JERRY_ATTR_PURE JERRY_ATTR_ALWAYS_INLINE
|
||||
ecma_get_error_reference_from_value (ecma_value_t value) /**< ecma value */
|
||||
inline ecma_extended_primitive_t *JERRY_ATTR_PURE JERRY_ATTR_ALWAYS_INLINE
|
||||
ecma_get_extended_primitive_from_value (ecma_value_t value) /**< ecma value */
|
||||
{
|
||||
JERRY_ASSERT (ecma_get_value_type_field (value) == ECMA_TYPE_ERROR);
|
||||
JERRY_ASSERT (ecma_get_value_type_field (value) == ECMA_TYPE_BIGINT
|
||||
|| ecma_get_value_type_field (value) == ECMA_TYPE_ERROR);
|
||||
|
||||
return (ecma_error_reference_t *) ecma_get_pointer_from_ecma_value (value);
|
||||
} /* ecma_get_error_reference_from_value */
|
||||
return (ecma_extended_primitive_t *) ecma_get_pointer_from_ecma_value (value);
|
||||
} /* ecma_get_extended_primitive_from_value */
|
||||
|
||||
/**
|
||||
* Invert a boolean value
|
||||
@ -866,6 +901,13 @@ ecma_copy_value (ecma_value_t value) /**< value description */
|
||||
return value;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
#if ENABLED (JERRY_BUILTIN_BIGINT)
|
||||
case ECMA_TYPE_BIGINT:
|
||||
{
|
||||
ecma_ref_extended_primitive (ecma_get_extended_primitive_from_value (value));
|
||||
return value;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_BUILTIN_BIGINT) */
|
||||
case ECMA_TYPE_OBJECT:
|
||||
{
|
||||
ecma_ref_object (ecma_get_object_from_value (value));
|
||||
@ -1093,6 +1135,14 @@ ecma_free_value (ecma_value_t value) /**< value description */
|
||||
break;
|
||||
}
|
||||
|
||||
#if ENABLED (JERRY_BUILTIN_BIGINT)
|
||||
case ECMA_TYPE_BIGINT:
|
||||
{
|
||||
ecma_deref_bigint (ecma_get_extended_primitive_from_value (value));
|
||||
break;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_BUILTIN_BIGINT) */
|
||||
|
||||
default:
|
||||
{
|
||||
JERRY_ASSERT (ecma_get_value_type_field (value) == ECMA_TYPE_DIRECT
|
||||
@ -1192,6 +1242,12 @@ ecma_get_typeof_lit_id (ecma_value_t value) /**< input ecma value */
|
||||
ret_value = LIT_MAGIC_STRING_SYMBOL;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
#if ENABLED (JERRY_BUILTIN_BIGINT)
|
||||
else if (ecma_is_value_bigint (value))
|
||||
{
|
||||
ret_value = LIT_MAGIC_STRING_BIGINT;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_BUILTIN_BIGINT) */
|
||||
else
|
||||
{
|
||||
JERRY_ASSERT (ecma_is_value_object (value));
|
||||
|
||||
@ -1216,9 +1216,73 @@ ecma_free_property_descriptor (ecma_property_descriptor_t *prop_desc_p) /**< pro
|
||||
/**
|
||||
* The size of error reference must be 8 bytes to use jmem_pools_alloc().
|
||||
*/
|
||||
JERRY_STATIC_ASSERT (sizeof (ecma_error_reference_t) == 8,
|
||||
JERRY_STATIC_ASSERT (sizeof (ecma_extended_primitive_t) == 8,
|
||||
ecma_error_reference_size_must_be_8_bytes);
|
||||
|
||||
/**
|
||||
* Increase ref count of an extended primitve value.
|
||||
*/
|
||||
void
|
||||
ecma_ref_extended_primitive (ecma_extended_primitive_t *primitve_p) /**< extended primitve value */
|
||||
{
|
||||
if (JERRY_LIKELY (primitve_p->refs_and_type < ECMA_EXTENDED_PRIMITIVE_MAX_REF))
|
||||
{
|
||||
primitve_p->refs_and_type += ECMA_EXTENDED_PRIMITIVE_REF_ONE;
|
||||
}
|
||||
else
|
||||
{
|
||||
jerry_fatal (ERR_REF_COUNT_LIMIT);
|
||||
}
|
||||
} /* ecma_ref_extended_primitive */
|
||||
|
||||
/**
|
||||
* Decrease ref count of an error reference.
|
||||
*/
|
||||
void
|
||||
ecma_deref_error_reference (ecma_extended_primitive_t *error_ref_p) /**< error reference */
|
||||
{
|
||||
JERRY_ASSERT (error_ref_p->refs_and_type >= ECMA_EXTENDED_PRIMITIVE_REF_ONE);
|
||||
|
||||
error_ref_p->refs_and_type -= ECMA_EXTENDED_PRIMITIVE_REF_ONE;
|
||||
|
||||
if (error_ref_p->refs_and_type < ECMA_EXTENDED_PRIMITIVE_REF_ONE)
|
||||
{
|
||||
ecma_free_value (error_ref_p->u.value);
|
||||
jmem_pools_free (error_ref_p, sizeof (ecma_extended_primitive_t));
|
||||
}
|
||||
} /* ecma_deref_error_reference */
|
||||
|
||||
#if ENABLED (JERRY_BUILTIN_BIGINT)
|
||||
|
||||
/**
|
||||
* Decrease ref count of a bigint value.
|
||||
*/
|
||||
void
|
||||
ecma_deref_bigint (ecma_extended_primitive_t *bigint_p) /**< bigint value */
|
||||
{
|
||||
JERRY_ASSERT (bigint_p->refs_and_type >= ECMA_EXTENDED_PRIMITIVE_REF_ONE);
|
||||
|
||||
bigint_p->refs_and_type -= ECMA_EXTENDED_PRIMITIVE_REF_ONE;
|
||||
|
||||
if (bigint_p->refs_and_type >= ECMA_EXTENDED_PRIMITIVE_REF_ONE)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t size = ECMA_BIGINT_GET_SIZE (bigint_p);
|
||||
|
||||
if (size == 0)
|
||||
{
|
||||
jmem_pools_free (bigint_p, sizeof (ecma_extended_primitive_t));
|
||||
return;
|
||||
}
|
||||
|
||||
size_t mem_size = ECMA_BIGINT_GET_BYTE_SIZE (size) + sizeof (ecma_extended_primitive_t);
|
||||
jmem_heap_free_block (bigint_p, mem_size);
|
||||
} /* ecma_deref_bigint */
|
||||
|
||||
#endif /* ENABLED (JERRY_BUILTIN_BIGINT) */
|
||||
|
||||
/**
|
||||
* Create an error reference from a given value.
|
||||
*
|
||||
@ -1231,11 +1295,13 @@ ecma_value_t
|
||||
ecma_create_error_reference (ecma_value_t value, /**< referenced value */
|
||||
bool is_exception) /**< error reference is an exception */
|
||||
{
|
||||
ecma_error_reference_t *error_ref_p = (ecma_error_reference_t *) jmem_pools_alloc (sizeof (ecma_error_reference_t));
|
||||
ecma_extended_primitive_t *error_ref_p;
|
||||
error_ref_p = (ecma_extended_primitive_t *) jmem_pools_alloc (sizeof (ecma_extended_primitive_t));
|
||||
|
||||
error_ref_p->refs_and_flags = ECMA_ERROR_REF_ONE | (is_exception ? 0 : ECMA_ERROR_REF_ABORT);
|
||||
error_ref_p->value = value;
|
||||
return ecma_make_error_reference_value (error_ref_p);
|
||||
error_ref_p->refs_and_type = (ECMA_EXTENDED_PRIMITIVE_REF_ONE
|
||||
| (is_exception ? ECMA_EXTENDED_PRIMITIVE_ERROR : ECMA_EXTENDED_PRIMITIVE_ABORT));
|
||||
error_ref_p->u.value = value;
|
||||
return ecma_make_extended_primitive_value (error_ref_p, ECMA_TYPE_ERROR);
|
||||
} /* ecma_create_error_reference */
|
||||
|
||||
/**
|
||||
@ -1269,39 +1335,6 @@ ecma_create_error_object_reference (ecma_object_t *object_p) /**< referenced obj
|
||||
return ecma_create_error_reference (ecma_make_object_value (object_p), true);
|
||||
} /* ecma_create_error_object_reference */
|
||||
|
||||
/**
|
||||
* Increase ref count of an error reference.
|
||||
*/
|
||||
void
|
||||
ecma_ref_error_reference (ecma_error_reference_t *error_ref_p) /**< error reference */
|
||||
{
|
||||
if (JERRY_LIKELY (error_ref_p->refs_and_flags < ECMA_ERROR_MAX_REF))
|
||||
{
|
||||
error_ref_p->refs_and_flags += ECMA_ERROR_REF_ONE;
|
||||
}
|
||||
else
|
||||
{
|
||||
jerry_fatal (ERR_REF_COUNT_LIMIT);
|
||||
}
|
||||
} /* ecma_ref_error_reference */
|
||||
|
||||
/**
|
||||
* Decrease ref count of an error reference.
|
||||
*/
|
||||
void
|
||||
ecma_deref_error_reference (ecma_error_reference_t *error_ref_p) /**< error reference */
|
||||
{
|
||||
JERRY_ASSERT (error_ref_p->refs_and_flags >= ECMA_ERROR_REF_ONE);
|
||||
|
||||
error_ref_p->refs_and_flags -= ECMA_ERROR_REF_ONE;
|
||||
|
||||
if (error_ref_p->refs_and_flags < ECMA_ERROR_REF_ONE)
|
||||
{
|
||||
ecma_free_value (error_ref_p->value);
|
||||
jmem_pools_free (error_ref_p, sizeof (ecma_error_reference_t));
|
||||
}
|
||||
} /* ecma_deref_error_reference */
|
||||
|
||||
/**
|
||||
* Raise error from the given error reference.
|
||||
*
|
||||
@ -1311,23 +1344,23 @@ void
|
||||
ecma_raise_error_from_error_reference (ecma_value_t value) /**< error reference */
|
||||
{
|
||||
JERRY_ASSERT (!jcontext_has_pending_exception () && !jcontext_has_pending_abort ());
|
||||
ecma_error_reference_t *error_ref_p = ecma_get_error_reference_from_value (value);
|
||||
ecma_extended_primitive_t *error_ref_p = ecma_get_extended_primitive_from_value (value);
|
||||
|
||||
JERRY_ASSERT (error_ref_p->refs_and_flags >= ECMA_ERROR_REF_ONE);
|
||||
JERRY_ASSERT (error_ref_p->refs_and_type >= ECMA_EXTENDED_PRIMITIVE_REF_ONE);
|
||||
|
||||
ecma_value_t referenced_value = error_ref_p->value;
|
||||
ecma_value_t referenced_value = error_ref_p->u.value;
|
||||
|
||||
jcontext_set_exception_flag (true);
|
||||
jcontext_set_abort_flag (error_ref_p->refs_and_flags & ECMA_ERROR_REF_ABORT);
|
||||
jcontext_set_abort_flag (ECMA_EXTENDED_PRIMITIVE_GET_TYPE (error_ref_p) == ECMA_EXTENDED_PRIMITIVE_ABORT);
|
||||
|
||||
if (error_ref_p->refs_and_flags >= 2 * ECMA_ERROR_REF_ONE)
|
||||
if (error_ref_p->refs_and_type >= 2 * ECMA_EXTENDED_PRIMITIVE_REF_ONE)
|
||||
{
|
||||
error_ref_p->refs_and_flags -= ECMA_ERROR_REF_ONE;
|
||||
error_ref_p->refs_and_type -= ECMA_EXTENDED_PRIMITIVE_REF_ONE;
|
||||
referenced_value = ecma_copy_value (referenced_value);
|
||||
}
|
||||
else
|
||||
{
|
||||
jmem_pools_free (error_ref_p, sizeof (ecma_error_reference_t));
|
||||
jmem_pools_free (error_ref_p, sizeof (ecma_extended_primitive_t));
|
||||
}
|
||||
|
||||
JERRY_CONTEXT (error_value) = referenced_value;
|
||||
|
||||
@ -243,6 +243,9 @@ bool JERRY_ATTR_CONST ecma_is_value_string (ecma_value_t value);
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
bool JERRY_ATTR_CONST ecma_is_value_symbol (ecma_value_t value);
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
#if ENABLED (JERRY_BUILTIN_BIGINT)
|
||||
bool JERRY_ATTR_CONST ecma_is_value_bigint (ecma_value_t value);
|
||||
#endif /* ENABLED (JERRY_BUILTIN_BIGINT) */
|
||||
bool JERRY_ATTR_CONST ecma_is_value_prop_name (ecma_value_t value);
|
||||
bool JERRY_ATTR_CONST ecma_is_value_direct_string (ecma_value_t value);
|
||||
bool JERRY_ATTR_CONST ecma_is_value_non_direct_string (ecma_value_t value);
|
||||
@ -267,7 +270,8 @@ ecma_value_t JERRY_ATTR_PURE ecma_make_symbol_value (const ecma_string_t *ecma_s
|
||||
ecma_value_t JERRY_ATTR_PURE ecma_make_prop_name_value (const ecma_string_t *ecma_prop_name_p);
|
||||
ecma_value_t JERRY_ATTR_PURE ecma_make_magic_string_value (lit_magic_string_id_t id);
|
||||
ecma_value_t JERRY_ATTR_PURE ecma_make_object_value (const ecma_object_t *object_p);
|
||||
ecma_value_t JERRY_ATTR_PURE ecma_make_error_reference_value (const ecma_error_reference_t *error_ref_p);
|
||||
ecma_value_t JERRY_ATTR_PURE ecma_make_extended_primitive_value (const ecma_extended_primitive_t *primitve_p,
|
||||
uint32_t type);
|
||||
ecma_integer_value_t JERRY_ATTR_CONST ecma_get_integer_from_value (ecma_value_t value);
|
||||
ecma_number_t JERRY_ATTR_PURE ecma_get_float_from_value (ecma_value_t value);
|
||||
ecma_number_t * ecma_get_pointer_from_float_value (ecma_value_t value);
|
||||
@ -278,7 +282,7 @@ ecma_string_t JERRY_ATTR_PURE *ecma_get_symbol_from_value (ecma_value_t value);
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
ecma_string_t JERRY_ATTR_PURE *ecma_get_prop_name_from_value (ecma_value_t value);
|
||||
ecma_object_t JERRY_ATTR_PURE *ecma_get_object_from_value (ecma_value_t value);
|
||||
ecma_error_reference_t JERRY_ATTR_PURE *ecma_get_error_reference_from_value (ecma_value_t value);
|
||||
ecma_extended_primitive_t JERRY_ATTR_PURE *ecma_get_extended_primitive_from_value (ecma_value_t value);
|
||||
ecma_value_t JERRY_ATTR_CONST ecma_invert_boolean_value (ecma_value_t value);
|
||||
ecma_value_t ecma_copy_value (ecma_value_t value);
|
||||
ecma_value_t ecma_fast_copy_value (ecma_value_t value);
|
||||
@ -498,11 +502,15 @@ void ecma_set_property_lcached (ecma_property_t *property_p, bool is_lcached);
|
||||
ecma_property_descriptor_t ecma_make_empty_property_descriptor (void);
|
||||
void ecma_free_property_descriptor (ecma_property_descriptor_t *prop_desc_p);
|
||||
|
||||
void ecma_ref_extended_primitive (ecma_extended_primitive_t *primitve_p);
|
||||
void ecma_deref_error_reference (ecma_extended_primitive_t *error_ref_p);
|
||||
#if ENABLED (JERRY_BUILTIN_BIGINT)
|
||||
void ecma_deref_bigint (ecma_extended_primitive_t *bigint_p);
|
||||
#endif /* ENABLED (JERRY_BUILTIN_BIGINT) */
|
||||
|
||||
ecma_value_t ecma_create_error_reference (ecma_value_t value, bool is_exception);
|
||||
ecma_value_t ecma_create_error_reference_from_context (void);
|
||||
ecma_value_t ecma_create_error_object_reference (ecma_object_t *object_p);
|
||||
void ecma_ref_error_reference (ecma_error_reference_t *error_ref_p);
|
||||
void ecma_deref_error_reference (ecma_error_reference_t *error_ref_p);
|
||||
void ecma_raise_error_from_error_reference (ecma_value_t value);
|
||||
|
||||
void ecma_bytecode_ref (ecma_compiled_code_t *bytecode_p);
|
||||
|
||||
134
jerry-core/ecma/builtin-objects/ecma-builtin-bigint-prototype.c
Normal file
134
jerry-core/ecma/builtin-objects/ecma-builtin-bigint-prototype.c
Normal file
@ -0,0 +1,134 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
#include "ecma-bigint.h"
|
||||
#include "ecma-exceptions.h"
|
||||
|
||||
#if ENABLED (JERRY_BUILTIN_BIGINT)
|
||||
|
||||
#define ECMA_BUILTINS_INTERNAL
|
||||
#include "ecma-builtins-internal.h"
|
||||
|
||||
/**
|
||||
* This object has a custom dispatch function.
|
||||
*/
|
||||
#define BUILTIN_INC_HEADER_NAME "ecma-builtin-bigint-prototype.inc.h"
|
||||
#define BUILTIN_UNDERSCORED_ID bigint_prototype
|
||||
#include "ecma-builtin-internal-routines-template.inc.h"
|
||||
|
||||
/** \addtogroup ecma ECMA
|
||||
* @{
|
||||
*
|
||||
* \addtogroup ecmabuiltins
|
||||
* @{
|
||||
*
|
||||
* \addtogroup bigint ECMA BigInt object built-in
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* The BigInt.prototype object's 'valueOf' routine
|
||||
*
|
||||
* See also:
|
||||
* ECMA-262 v11, 20.2.3.4
|
||||
*
|
||||
* @return ecma value
|
||||
* Returned value must be freed with ecma_free_value.
|
||||
*/
|
||||
static ecma_value_t
|
||||
ecma_builtin_bigint_prototype_object_value_of (ecma_value_t this_arg) /**< this argument */
|
||||
{
|
||||
if (ecma_is_value_bigint (this_arg))
|
||||
{
|
||||
return ecma_copy_value (this_arg);
|
||||
}
|
||||
|
||||
if (ecma_is_value_object (this_arg))
|
||||
{
|
||||
ecma_object_t *object_p = ecma_get_object_from_value (this_arg);
|
||||
|
||||
if (ecma_object_class_is (object_p, LIT_MAGIC_STRING_BIGINT_UL))
|
||||
{
|
||||
ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p;
|
||||
|
||||
JERRY_ASSERT (ecma_is_value_bigint (ext_object_p->u.class_prop.u.value));
|
||||
|
||||
return ecma_copy_value (ext_object_p->u.class_prop.u.value);
|
||||
}
|
||||
}
|
||||
|
||||
return ecma_raise_type_error (ECMA_ERR_MSG ("BigInt value expected."));
|
||||
} /* ecma_builtin_bigint_prototype_object_value_of */
|
||||
|
||||
/**
|
||||
* The BigInt.prototype object's 'toString' routine
|
||||
*
|
||||
* See also:
|
||||
* ECMA-262 v11, 20.2.3.3
|
||||
*
|
||||
* @return ecma value
|
||||
* Returned value must be freed with ecma_free_value.
|
||||
*/
|
||||
static ecma_value_t
|
||||
ecma_builtin_bigint_prototype_object_to_string (ecma_value_t this_arg, /**< this argument */
|
||||
const ecma_value_t *arguments_list_p, /**< arguments list */
|
||||
uint32_t arguments_list_len) /**< number of arguments */
|
||||
{
|
||||
ecma_value_t bigint = ecma_builtin_bigint_prototype_object_value_of (this_arg);
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (bigint))
|
||||
{
|
||||
return bigint;
|
||||
}
|
||||
|
||||
uint32_t radix = 10;
|
||||
|
||||
if (arguments_list_len > 0 && !ecma_is_value_undefined (arguments_list_p[0]))
|
||||
{
|
||||
ecma_number_t arg_num;
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (ecma_op_to_integer (arguments_list_p[0], &arg_num)))
|
||||
{
|
||||
ecma_free_value (bigint);
|
||||
return ECMA_VALUE_ERROR;
|
||||
}
|
||||
|
||||
if (arg_num < 2 || arg_num > 36)
|
||||
{
|
||||
ecma_free_value (bigint);
|
||||
return ecma_raise_range_error (ECMA_ERR_MSG ("Radix must be between 2 and 36."));
|
||||
}
|
||||
|
||||
radix = (uint32_t) arg_num;
|
||||
}
|
||||
|
||||
ecma_string_t *string_p = ecma_bigint_to_string (bigint, radix);
|
||||
ecma_free_value (bigint);
|
||||
|
||||
if (string_p == NULL)
|
||||
{
|
||||
return ECMA_VALUE_ERROR;
|
||||
}
|
||||
|
||||
return ecma_make_string_value (string_p);
|
||||
} /* ecma_builtin_bigint_prototype_object_to_string */
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* ENABLED (JERRY_BUILTIN_BIGINT) */
|
||||
@ -0,0 +1,44 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* BigInt.prototype built-in description
|
||||
*/
|
||||
|
||||
#include "ecma-builtin-helpers-macro-defines.inc.h"
|
||||
|
||||
#if ENABLED (JERRY_BUILTIN_BIGINT)
|
||||
|
||||
/* Object properties:
|
||||
* (property name, object pointer getter) */
|
||||
|
||||
/* ECMA-262 v11, 20.2.3.1 */
|
||||
OBJECT_VALUE (LIT_MAGIC_STRING_CONSTRUCTOR,
|
||||
ECMA_BUILTIN_ID_BIGINT,
|
||||
ECMA_PROPERTY_CONFIGURABLE_WRITABLE)
|
||||
|
||||
/* ECMA-262 v11, 20.2.3.5 */
|
||||
STRING_VALUE (LIT_GLOBAL_SYMBOL_TO_STRING_TAG,
|
||||
LIT_MAGIC_STRING_BIGINT_UL,
|
||||
ECMA_PROPERTY_FLAG_CONFIGURABLE)
|
||||
|
||||
/* Routine properties:
|
||||
* (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */
|
||||
ROUTINE (LIT_MAGIC_STRING_VALUE_OF_UL, ecma_builtin_bigint_prototype_object_value_of, 0, 0)
|
||||
ROUTINE (LIT_MAGIC_STRING_TO_STRING_UL, ecma_builtin_bigint_prototype_object_to_string, NON_FIXED, 1)
|
||||
|
||||
#endif /* ENABLED (JERRY_BUILTIN_BIGINT) */
|
||||
|
||||
#include "ecma-builtin-helpers-macro-undefs.inc.h"
|
||||
93
jerry-core/ecma/builtin-objects/ecma-builtin-bigint.c
Normal file
93
jerry-core/ecma/builtin-objects/ecma-builtin-bigint.c
Normal file
@ -0,0 +1,93 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
#include "ecma-bigint.h"
|
||||
#include "ecma-builtins.h"
|
||||
#include "ecma-exceptions.h"
|
||||
|
||||
#if ENABLED (JERRY_BUILTIN_BIGINT)
|
||||
|
||||
#define ECMA_BUILTINS_INTERNAL
|
||||
#include "ecma-builtins-internal.h"
|
||||
|
||||
#define BUILTIN_INC_HEADER_NAME "ecma-builtin-bigint.inc.h"
|
||||
#define BUILTIN_UNDERSCORED_ID bigint
|
||||
#include "ecma-builtin-internal-routines-template.inc.h"
|
||||
|
||||
/** \addtogroup ecma ECMA
|
||||
* @{
|
||||
*
|
||||
* \addtogroup ecmabuiltins
|
||||
* @{
|
||||
*
|
||||
* \addtogroup bigint ECMA BigInt object built-in
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Handle calling [[Call]] of built-in BigInt object
|
||||
*
|
||||
* See also:
|
||||
* ECMA-262 v11, 20.2.1.1
|
||||
*
|
||||
* @return ecma value
|
||||
*/
|
||||
ecma_value_t
|
||||
ecma_builtin_bigint_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */
|
||||
uint32_t arguments_list_len) /**< number of arguments */
|
||||
{
|
||||
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];
|
||||
|
||||
if (!ecma_is_value_string (value))
|
||||
{
|
||||
return ecma_raise_type_error (ECMA_ERR_MSG ("TODO: Only strings are supported now"));
|
||||
}
|
||||
|
||||
ecma_string_t *string_p = ecma_get_string_from_value (value);
|
||||
|
||||
ECMA_STRING_TO_UTF8_STRING (string_p, string_buffer_p, string_buffer_size);
|
||||
|
||||
ecma_value_t result = ecma_bigint_parse_string (string_buffer_p, string_buffer_size);
|
||||
|
||||
ECMA_FINALIZE_UTF8_STRING (string_buffer_p, string_buffer_size);
|
||||
return result;
|
||||
} /* ecma_builtin_bigint_dispatch_call */
|
||||
|
||||
/**
|
||||
* Handle calling [[Construct]] of built-in BigInt object
|
||||
*
|
||||
* See also:
|
||||
* ECMA-262 v11, 20.2.1
|
||||
*
|
||||
* @return ecma value
|
||||
*/
|
||||
ecma_value_t
|
||||
ecma_builtin_bigint_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */
|
||||
uint32_t arguments_list_len) /**< number of arguments */
|
||||
{
|
||||
JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL);
|
||||
|
||||
return ecma_raise_type_error (ECMA_ERR_MSG ("BigInt function is not a constructor."));
|
||||
} /* ecma_builtin_bigint_dispatch_construct */
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* ENABLED (JERRY_BUILTIN_BIGINT) */
|
||||
47
jerry-core/ecma/builtin-objects/ecma-builtin-bigint.inc.h
Normal file
47
jerry-core/ecma/builtin-objects/ecma-builtin-bigint.inc.h
Normal file
@ -0,0 +1,47 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* BigInt built-in description
|
||||
*/
|
||||
|
||||
#include "ecma-builtin-helpers-macro-defines.inc.h"
|
||||
|
||||
#if ENABLED (JERRY_BUILTIN_BIGINT)
|
||||
|
||||
/* Number properties:
|
||||
* (property name, number value, writable, enumerable, configurable) */
|
||||
|
||||
/* ECMA-262 v11, 20.2.1 */
|
||||
NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH,
|
||||
1,
|
||||
ECMA_PROPERTY_FLAG_CONFIGURABLE)
|
||||
|
||||
/* ECMA-262 v11, 20.2.1 */
|
||||
STRING_VALUE (LIT_MAGIC_STRING_NAME,
|
||||
LIT_MAGIC_STRING_BIGINT_UL,
|
||||
ECMA_PROPERTY_FLAG_CONFIGURABLE)
|
||||
|
||||
/* Object properties:
|
||||
* (property name, object pointer getter) */
|
||||
|
||||
/* ECMA-262 v11, 20.2.2.3 */
|
||||
OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE,
|
||||
ECMA_BUILTIN_ID_BIGINT_PROTOTYPE,
|
||||
ECMA_PROPERTY_FIXED)
|
||||
|
||||
#endif /* ENABLED (JERRY_BUILTIN_BIGINT) */
|
||||
|
||||
#include "ecma-builtin-helpers-macro-undefs.inc.h"
|
||||
@ -253,6 +253,13 @@ OBJECT_VALUE (LIT_MAGIC_STRING_PROXY_UL,
|
||||
ECMA_PROPERTY_CONFIGURABLE_WRITABLE)
|
||||
#endif /* ENABLED (JERRY_BUILTIN_PROXY) */
|
||||
|
||||
#if ENABLED (JERRY_BUILTIN_BIGINT)
|
||||
/* ECMA-262 v11, 20.2.1 */
|
||||
OBJECT_VALUE (LIT_MAGIC_STRING_BIGINT_UL,
|
||||
ECMA_BUILTIN_ID_BIGINT,
|
||||
ECMA_PROPERTY_CONFIGURABLE_WRITABLE)
|
||||
#endif /* ENABLED (JERRY_BUILTIN_BIGINT) */
|
||||
|
||||
/* Routine properties:
|
||||
* (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */
|
||||
|
||||
|
||||
@ -677,6 +677,23 @@ BUILTIN (ECMA_BUILTIN_ID_MAP_ITERATOR_PROTOTYPE,
|
||||
true,
|
||||
map_iterator_prototype)
|
||||
#endif /* ENABLED (JERRY_BUILTIN_SET) */
|
||||
|
||||
#if ENABLED (JERRY_BUILTIN_BIGINT)
|
||||
/* The %BigInt.prototype% object */
|
||||
BUILTIN (ECMA_BUILTIN_ID_BIGINT_PROTOTYPE,
|
||||
ECMA_OBJECT_TYPE_GENERAL,
|
||||
ECMA_BUILTIN_ID_OBJECT_PROTOTYPE,
|
||||
true,
|
||||
bigint_prototype)
|
||||
|
||||
/* The %BigInt% object */
|
||||
BUILTIN_ROUTINE (ECMA_BUILTIN_ID_BIGINT,
|
||||
ECMA_OBJECT_TYPE_FUNCTION,
|
||||
ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE,
|
||||
true,
|
||||
bigint)
|
||||
#endif /* ENABLED (JERRY_BUILTIN_BIGINT) */
|
||||
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
|
||||
#if ENABLED (JERRY_BUILTIN_DATAVIEW)
|
||||
|
||||
1252
jerry-core/ecma/operations/ecma-big-uint.c
Normal file
1252
jerry-core/ecma/operations/ecma-big-uint.c
Normal file
File diff suppressed because it is too large
Load Diff
88
jerry-core/ecma/operations/ecma-big-uint.h
Normal file
88
jerry-core/ecma/operations/ecma-big-uint.h
Normal file
@ -0,0 +1,88 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
#ifndef ECMA_BIG_UINT_H
|
||||
#define ECMA_BIG_UINT_H
|
||||
|
||||
#include "ecma-globals.h"
|
||||
|
||||
#if ENABLED (JERRY_BUILTIN_BIGINT)
|
||||
|
||||
/**
|
||||
* Limit of BigUInt memory allocation in JerryScript.
|
||||
*/
|
||||
#define ECMA_BIGINT_MAX_SIZE 0x10000
|
||||
|
||||
/**
|
||||
* Unsigned type which can hold two digits.
|
||||
*/
|
||||
typedef uint64_t ecma_bigint_two_digits_t;
|
||||
|
||||
/**
|
||||
* Shift used by left/right shifting of a value.
|
||||
*/
|
||||
#define ECMA_BIGINT_DIGIT_SHIFT 5
|
||||
|
||||
/**
|
||||
* Return with the digits of a BigInt value.
|
||||
*/
|
||||
#define ECMA_BIGINT_GET_DIGITS(value_p, offset) \
|
||||
((ecma_bigint_digit_t *) (((uint8_t *) (value_p)) + sizeof (ecma_extended_primitive_t) + (offset)))
|
||||
|
||||
/**
|
||||
* Return with the digits of a BigInt value.
|
||||
*/
|
||||
#define ECMA_BIGINT_GET_LAST_DIGIT(value_p, size) \
|
||||
*ECMA_BIGINT_GET_DIGITS (value_p, size - sizeof (ecma_bigint_digit_t))
|
||||
|
||||
/**
|
||||
* Returns true if size is an odd number.
|
||||
*/
|
||||
#define ECMA_BIGINT_SIZE_IS_ODD(size) \
|
||||
(((size) & sizeof (ecma_bigint_digit_t)) != 0)
|
||||
|
||||
/**
|
||||
* Returns a two digit value where the high digit is set to the passed digit.
|
||||
*/
|
||||
#define ECMA_BIGINT_HIGH_DIGIT(digit) \
|
||||
(((ecma_bigint_two_digits_t) digit) << (8 * sizeof (ecma_bigint_digit_t)))
|
||||
|
||||
ecma_extended_primitive_t *ecma_bigint_create (uint32_t size);
|
||||
ecma_extended_primitive_t *ecma_big_uint_extend (ecma_extended_primitive_t *value_p, ecma_bigint_digit_t digit);
|
||||
|
||||
int ecma_big_uint_compare (ecma_extended_primitive_t *left_value_p, ecma_extended_primitive_t *right_value_p);
|
||||
|
||||
ecma_extended_primitive_t *ecma_big_uint_mul_digit (ecma_extended_primitive_t *value_p,
|
||||
ecma_bigint_digit_t mul, ecma_bigint_digit_t add);
|
||||
|
||||
uint8_t *ecma_big_uint_to_string (ecma_extended_primitive_t *value_p, uint32_t radix,
|
||||
uint32_t *char_start_p, uint32_t *char_size_p);
|
||||
|
||||
ecma_extended_primitive_t *ecma_big_uint_add (ecma_extended_primitive_t *left_value_p,
|
||||
ecma_extended_primitive_t *right_value_p);
|
||||
ecma_extended_primitive_t *ecma_big_uint_sub (ecma_extended_primitive_t *left_value_p,
|
||||
ecma_extended_primitive_t *right_value_p);
|
||||
ecma_extended_primitive_t *ecma_big_uint_mul (ecma_extended_primitive_t *left_value_p,
|
||||
ecma_extended_primitive_t *right_value_p);
|
||||
ecma_extended_primitive_t *ecma_big_uint_div_mod (ecma_extended_primitive_t *dividend_value_p,
|
||||
ecma_extended_primitive_t *divisor_value_p,
|
||||
bool is_mod);
|
||||
|
||||
ecma_extended_primitive_t *ecma_big_uint_shift_left (ecma_extended_primitive_t *left_value_p, uint32_t right_value);
|
||||
ecma_extended_primitive_t *ecma_big_uint_shift_right (ecma_extended_primitive_t *left_value_p, uint32_t right_value);
|
||||
|
||||
#endif /* ENABLED (JERRY_BUILTIN_BIGINT) */
|
||||
|
||||
#endif /* ECMA_BIG_UINT_H */
|
||||
66
jerry-core/ecma/operations/ecma-bigint-object.c
Normal file
66
jerry-core/ecma/operations/ecma-bigint-object.c
Normal file
@ -0,0 +1,66 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
#include "ecma-alloc.h"
|
||||
#include "ecma-bigint-object.h"
|
||||
#include "ecma-builtins.h"
|
||||
#include "ecma-exceptions.h"
|
||||
#include "ecma-gc.h"
|
||||
#include "ecma-globals.h"
|
||||
#include "ecma-helpers.h"
|
||||
#include "ecma-objects.h"
|
||||
#include "ecma-objects-general.h"
|
||||
|
||||
#if ENABLED (JERRY_BUILTIN_BIGINT)
|
||||
|
||||
/** \addtogroup ecma ECMA
|
||||
* @{
|
||||
*
|
||||
* \addtogroup ecmabigintobject ECMA BigInt object related routines
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* BigInt object creation operation.
|
||||
*
|
||||
* See also: ECMA-262 v11, 7.1.18
|
||||
*
|
||||
* @return ecma value
|
||||
* Returned value must be freed with ecma_free_value
|
||||
*/
|
||||
ecma_value_t
|
||||
ecma_op_create_bigint_object (ecma_value_t arg) /**< argument passed to the toObject operation */
|
||||
{
|
||||
JERRY_ASSERT (ecma_is_value_bigint (arg));
|
||||
|
||||
ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_BIGINT_PROTOTYPE);
|
||||
|
||||
ecma_object_t *object_p = ecma_create_object (prototype_obj_p,
|
||||
sizeof (ecma_extended_object_t),
|
||||
ECMA_OBJECT_TYPE_CLASS);
|
||||
|
||||
ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p;
|
||||
ext_object_p->u.class_prop.class_id = LIT_MAGIC_STRING_BIGINT_UL;
|
||||
ext_object_p->u.class_prop.u.value = ecma_copy_value (arg);
|
||||
|
||||
return ecma_make_object_value (object_p);
|
||||
} /* ecma_op_create_bigint_object */
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* ENABLED (JERRY_BUILTIN_BIGINT) */
|
||||
39
jerry-core/ecma/operations/ecma-bigint-object.h
Normal file
39
jerry-core/ecma/operations/ecma-bigint-object.h
Normal file
@ -0,0 +1,39 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
#ifndef ECMA_BIGINT_OBJECT_H
|
||||
#define ECMA_BIGINT_OBJECT_H
|
||||
|
||||
#include "ecma-globals.h"
|
||||
|
||||
#if ENABLED (JERRY_BUILTIN_BIGINT)
|
||||
|
||||
/** \addtogroup ecma ECMA
|
||||
* @{
|
||||
*
|
||||
* \addtogroup ecmabigintobject ECMA BigInt object related routines
|
||||
* @{
|
||||
*/
|
||||
|
||||
ecma_value_t ecma_op_create_bigint_object (ecma_value_t arg);
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* ENABLED (JERRY_BUILTIN_BIGINT) */
|
||||
|
||||
#endif /* !ECMA_BIGINT_OBJECT_H */
|
||||
508
jerry-core/ecma/operations/ecma-bigint.c
Normal file
508
jerry-core/ecma/operations/ecma-bigint.c
Normal file
@ -0,0 +1,508 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
#include "ecma-bigint.h"
|
||||
#include "ecma-big-uint.h"
|
||||
#include "ecma-exceptions.h"
|
||||
#include "ecma-helpers.h"
|
||||
#include "lit-char-helpers.h"
|
||||
|
||||
#if ENABLED (JERRY_BUILTIN_BIGINT)
|
||||
|
||||
/**
|
||||
* Raise a not enough memory error
|
||||
*
|
||||
* @return ECMA_VALUE_ERROR
|
||||
* Returned value must be freed with ecma_free_value.
|
||||
*/
|
||||
static ecma_value_t
|
||||
ecma_bigint_raise_memory_error (void)
|
||||
{
|
||||
return ecma_raise_range_error (ECMA_ERR_MSG ("Cannot allocate memory for a BigInt value"));
|
||||
} /* ecma_bigint_raise_memory_error */
|
||||
|
||||
/**
|
||||
* Parse a string 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 (const lit_utf8_byte_t *string_p, /**< string represenation of the BigInt */
|
||||
lit_utf8_size_t size) /**< string size */
|
||||
{
|
||||
ecma_bigint_digit_t radix = 10;
|
||||
uint32_t sign = 0;
|
||||
|
||||
if (size >= 3 && string_p[0] == LIT_CHAR_0)
|
||||
{
|
||||
if (string_p[1] == LIT_CHAR_LOWERCASE_X || string_p[1] == LIT_CHAR_UPPERCASE_X)
|
||||
{
|
||||
radix = 16;
|
||||
string_p += 2;
|
||||
size -= 2;
|
||||
}
|
||||
else if (string_p[1] == LIT_CHAR_LOWERCASE_B || string_p[1] == LIT_CHAR_UPPERCASE_B)
|
||||
{
|
||||
radix = 2;
|
||||
string_p += 2;
|
||||
size -= 2;
|
||||
}
|
||||
}
|
||||
else if (size >= 2)
|
||||
{
|
||||
if (string_p[0] == LIT_CHAR_PLUS)
|
||||
{
|
||||
size--;
|
||||
string_p++;
|
||||
}
|
||||
else if (string_p[0] == LIT_CHAR_MINUS)
|
||||
{
|
||||
sign = ECMA_BIGINT_SIGN;
|
||||
size--;
|
||||
string_p++;
|
||||
}
|
||||
}
|
||||
else if (size == 0)
|
||||
{
|
||||
return ecma_raise_syntax_error (ECMA_ERR_MSG ("BigInt cannot be constructed from empty string"));
|
||||
}
|
||||
|
||||
const lit_utf8_byte_t *string_end_p = string_p + size;
|
||||
|
||||
while (string_p < string_end_p && *string_p == LIT_CHAR_0)
|
||||
{
|
||||
string_p++;
|
||||
}
|
||||
|
||||
ecma_extended_primitive_t *result_p = NULL;
|
||||
|
||||
if (string_p == string_end_p)
|
||||
{
|
||||
result_p = ecma_bigint_create (0);
|
||||
}
|
||||
else
|
||||
{
|
||||
do
|
||||
{
|
||||
ecma_bigint_digit_t digit = radix;
|
||||
|
||||
if (*string_p >= LIT_CHAR_0 && *string_p <= LIT_CHAR_9)
|
||||
{
|
||||
digit = (ecma_bigint_digit_t) (*string_p - LIT_CHAR_0);
|
||||
}
|
||||
else
|
||||
{
|
||||
lit_utf8_byte_t character = (lit_utf8_byte_t) LEXER_TO_ASCII_LOWERCASE (*string_p);
|
||||
|
||||
if (character >= LIT_CHAR_LOWERCASE_A && character <= LIT_CHAR_LOWERCASE_F)
|
||||
{
|
||||
digit = (ecma_bigint_digit_t) (character - (LIT_CHAR_LOWERCASE_A - 10));
|
||||
}
|
||||
}
|
||||
|
||||
if (digit >= radix)
|
||||
{
|
||||
if (result_p != NULL)
|
||||
{
|
||||
ecma_deref_bigint (result_p);
|
||||
}
|
||||
return ecma_raise_syntax_error (ECMA_ERR_MSG ("String cannot be converted to BigInt value"));
|
||||
}
|
||||
|
||||
result_p = ecma_big_uint_mul_digit (result_p, radix, digit);
|
||||
|
||||
if (JERRY_UNLIKELY (result_p == NULL))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (++string_p < string_end_p);
|
||||
}
|
||||
|
||||
if (JERRY_UNLIKELY (result_p == NULL))
|
||||
{
|
||||
return ecma_bigint_raise_memory_error ();
|
||||
}
|
||||
|
||||
result_p->u.bigint_sign_and_size |= sign;
|
||||
return ecma_make_extended_primitive_value (result_p, ECMA_TYPE_BIGINT);
|
||||
} /* ecma_bigint_parse_string */
|
||||
|
||||
/**
|
||||
* Create a string representation for a BigInt value
|
||||
*
|
||||
* @return ecma string or ECMA_VALUE_ERROR
|
||||
* Returned value must be freed with ecma_free_value.
|
||||
*/
|
||||
ecma_string_t *
|
||||
ecma_bigint_to_string (ecma_value_t value, /**< BigInt value */
|
||||
ecma_bigint_digit_t radix) /**< conversion radix */
|
||||
{
|
||||
JERRY_ASSERT (ecma_is_value_bigint (value));
|
||||
|
||||
ecma_extended_primitive_t *bigint_p = ecma_get_extended_primitive_from_value (value);
|
||||
|
||||
if (ECMA_BIGINT_GET_SIZE (bigint_p) == 0)
|
||||
{
|
||||
return ecma_new_ecma_string_from_code_unit (LIT_CHAR_0);
|
||||
}
|
||||
|
||||
uint32_t char_start_p, char_size_p;
|
||||
lit_utf8_byte_t *string_buffer_p = ecma_big_uint_to_string (bigint_p, radix, &char_start_p, &char_size_p);
|
||||
|
||||
if (JERRY_UNLIKELY (string_buffer_p == NULL))
|
||||
{
|
||||
ecma_raise_range_error (ECMA_ERR_MSG ("Cannot allocate memory for a string representation of a BigInt value"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
JERRY_ASSERT (char_start_p > 0);
|
||||
|
||||
if (bigint_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN)
|
||||
{
|
||||
string_buffer_p[--char_start_p] = LIT_CHAR_MINUS;
|
||||
}
|
||||
|
||||
ecma_string_t *string_p;
|
||||
string_p = ecma_new_ecma_string_from_utf8 (string_buffer_p + char_start_p, char_size_p - char_start_p);
|
||||
|
||||
jmem_heap_free_block (string_buffer_p, char_size_p);
|
||||
return string_p;
|
||||
} /* ecma_bigint_to_string */
|
||||
|
||||
/**
|
||||
* Negate a non-zero BigInt value
|
||||
*
|
||||
* @return ecma BigInt value or ECMA_VALUE_ERROR
|
||||
* Returned value must be freed with ecma_free_value.
|
||||
*/
|
||||
ecma_value_t
|
||||
ecma_bigint_negate (ecma_extended_primitive_t *value_p) /**< BigInt value */
|
||||
{
|
||||
uint32_t size = ECMA_BIGINT_GET_SIZE (value_p);
|
||||
|
||||
JERRY_ASSERT (size > 0 && ECMA_BIGINT_GET_LAST_DIGIT (value_p, size) != 0);
|
||||
|
||||
ecma_extended_primitive_t *result_p = ecma_bigint_create (size);
|
||||
|
||||
if (JERRY_UNLIKELY (result_p == NULL))
|
||||
{
|
||||
return ecma_bigint_raise_memory_error ();
|
||||
}
|
||||
|
||||
memcpy (result_p + 1, value_p + 1, size);
|
||||
result_p->refs_and_type = ECMA_EXTENDED_PRIMITIVE_REF_ONE | ECMA_TYPE_BIGINT;
|
||||
result_p->u.bigint_sign_and_size = value_p->u.bigint_sign_and_size ^ ECMA_BIGINT_SIGN;
|
||||
|
||||
return ecma_make_extended_primitive_value (result_p, ECMA_TYPE_BIGINT);
|
||||
} /* ecma_bigint_negate */
|
||||
|
||||
/**
|
||||
* Add/subtract right BigInt value to/from left BigInt value
|
||||
*
|
||||
* @return ecma BigInt value or ECMA_VALUE_ERROR
|
||||
* Returned value must be freed with ecma_free_value.
|
||||
*/
|
||||
ecma_value_t
|
||||
ecma_bigint_add_sub (ecma_value_t left_value, /**< left BigInt value */
|
||||
ecma_value_t right_value, /**< right BigInt value */
|
||||
bool is_add) /**< true if add operation should be performed */
|
||||
{
|
||||
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_size = ECMA_BIGINT_GET_SIZE (left_p);
|
||||
uint32_t right_size = ECMA_BIGINT_GET_SIZE (right_p);
|
||||
|
||||
if (right_size == 0)
|
||||
{
|
||||
ecma_ref_extended_primitive (left_p);
|
||||
return left_value;
|
||||
}
|
||||
|
||||
if (left_size == 0)
|
||||
{
|
||||
if (!is_add)
|
||||
{
|
||||
return ecma_bigint_negate (right_p);
|
||||
}
|
||||
|
||||
ecma_ref_extended_primitive (right_p);
|
||||
return right_value;
|
||||
}
|
||||
|
||||
uint32_t sign = is_add ? 0 : ECMA_BIGINT_SIGN;
|
||||
|
||||
if (((left_p->u.bigint_sign_and_size ^ right_p->u.bigint_sign_and_size) & ECMA_BIGINT_SIGN) == sign)
|
||||
{
|
||||
ecma_extended_primitive_t *result_p = ecma_big_uint_add (left_p, right_p);
|
||||
|
||||
if (JERRY_UNLIKELY (result_p == NULL))
|
||||
{
|
||||
return ecma_bigint_raise_memory_error ();
|
||||
}
|
||||
|
||||
result_p->u.bigint_sign_and_size |= left_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN;
|
||||
return ecma_make_extended_primitive_value (result_p, ECMA_TYPE_BIGINT);
|
||||
}
|
||||
|
||||
int compare_result = ecma_big_uint_compare (left_p, right_p);
|
||||
ecma_extended_primitive_t *result_p;
|
||||
|
||||
if (compare_result == 0)
|
||||
{
|
||||
sign = 0;
|
||||
result_p = ecma_bigint_create (0);
|
||||
}
|
||||
else if (compare_result > 0)
|
||||
{
|
||||
sign = left_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN;
|
||||
result_p = ecma_big_uint_sub (left_p, right_p);
|
||||
}
|
||||
else
|
||||
{
|
||||
sign = right_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN;
|
||||
|
||||
if (!is_add)
|
||||
{
|
||||
sign ^= ECMA_BIGINT_SIGN;
|
||||
}
|
||||
|
||||
result_p = ecma_big_uint_sub (right_p, left_p);
|
||||
}
|
||||
|
||||
if (JERRY_UNLIKELY (result_p == NULL))
|
||||
{
|
||||
return ecma_bigint_raise_memory_error ();
|
||||
}
|
||||
|
||||
result_p->u.bigint_sign_and_size |= sign;
|
||||
return ecma_make_extended_primitive_value (result_p, ECMA_TYPE_BIGINT);
|
||||
} /* ecma_bigint_add_sub */
|
||||
|
||||
/**
|
||||
* Multiply two BigInt values
|
||||
*
|
||||
* @return ecma BigInt value or ECMA_VALUE_ERROR
|
||||
* Returned value must be freed with ecma_free_value.
|
||||
*/
|
||||
ecma_value_t
|
||||
ecma_bigint_mul (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_size = ECMA_BIGINT_GET_SIZE (left_p);
|
||||
uint32_t right_size = ECMA_BIGINT_GET_SIZE (right_p);
|
||||
|
||||
if (left_size == 0)
|
||||
{
|
||||
ecma_ref_extended_primitive (left_p);
|
||||
return left_value;
|
||||
}
|
||||
|
||||
if (right_size == 0)
|
||||
{
|
||||
ecma_ref_extended_primitive (right_p);
|
||||
return right_value;
|
||||
}
|
||||
|
||||
if (left_size == sizeof (ecma_bigint_digit_t)
|
||||
&& ECMA_BIGINT_GET_LAST_DIGIT (left_p, sizeof (ecma_bigint_digit_t)) == 1)
|
||||
{
|
||||
if (left_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN)
|
||||
{
|
||||
return ecma_bigint_negate (right_p);
|
||||
}
|
||||
|
||||
ecma_ref_extended_primitive (right_p);
|
||||
return right_value;
|
||||
}
|
||||
|
||||
if (right_size == sizeof (ecma_bigint_digit_t)
|
||||
&& ECMA_BIGINT_GET_LAST_DIGIT (right_p, sizeof (ecma_bigint_digit_t)) == 1)
|
||||
{
|
||||
if (right_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN)
|
||||
{
|
||||
return ecma_bigint_negate (left_p);
|
||||
}
|
||||
|
||||
ecma_ref_extended_primitive (left_p);
|
||||
return left_value;
|
||||
}
|
||||
|
||||
ecma_extended_primitive_t *result_p = ecma_big_uint_mul (left_p, right_p);
|
||||
|
||||
if (JERRY_UNLIKELY (result_p == NULL))
|
||||
{
|
||||
return ecma_bigint_raise_memory_error ();
|
||||
}
|
||||
|
||||
uint32_t sign = (left_p->u.bigint_sign_and_size ^ right_p->u.bigint_sign_and_size) & ECMA_BIGINT_SIGN;
|
||||
result_p->u.bigint_sign_and_size |= sign;
|
||||
return ecma_make_extended_primitive_value (result_p, ECMA_TYPE_BIGINT);
|
||||
} /* ecma_bigint_mul */
|
||||
|
||||
/**
|
||||
* Divide two BigInt values
|
||||
*
|
||||
* @return ecma BigInt value or ECMA_VALUE_ERROR
|
||||
* Returned value must be freed with ecma_free_value.
|
||||
*/
|
||||
ecma_value_t
|
||||
ecma_bigint_div_mod (ecma_value_t left_value, /**< left BigInt value */
|
||||
ecma_value_t right_value, /**< right BigInt value */
|
||||
bool is_mod) /**< true if return with remainder */
|
||||
{
|
||||
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_size = ECMA_BIGINT_GET_SIZE (left_p);
|
||||
uint32_t right_size = ECMA_BIGINT_GET_SIZE (right_p);
|
||||
|
||||
if (right_size == 0)
|
||||
{
|
||||
return ecma_raise_range_error (ECMA_ERR_MSG ("BigInt division by zero"));
|
||||
}
|
||||
|
||||
if (left_size == 0)
|
||||
{
|
||||
ecma_ref_extended_primitive (left_p);
|
||||
return left_value;
|
||||
}
|
||||
|
||||
int compare_result = ecma_big_uint_compare (left_p, right_p);
|
||||
ecma_extended_primitive_t *result_p;
|
||||
|
||||
if (compare_result < 0)
|
||||
{
|
||||
if (is_mod)
|
||||
{
|
||||
ecma_ref_extended_primitive (left_p);
|
||||
return left_value;
|
||||
}
|
||||
else
|
||||
{
|
||||
result_p = ecma_bigint_create (0);
|
||||
}
|
||||
}
|
||||
else if (compare_result == 0)
|
||||
{
|
||||
if (is_mod)
|
||||
{
|
||||
result_p = ecma_bigint_create (0);
|
||||
}
|
||||
else
|
||||
{
|
||||
result_p = ecma_bigint_create (sizeof (ecma_bigint_digit_t));
|
||||
|
||||
if (result_p != NULL)
|
||||
{
|
||||
*ECMA_BIGINT_GET_DIGITS (result_p, 0) = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result_p = ecma_big_uint_div_mod (left_p, right_p, is_mod);
|
||||
}
|
||||
|
||||
if (JERRY_UNLIKELY (result_p == NULL))
|
||||
{
|
||||
return ecma_bigint_raise_memory_error ();
|
||||
}
|
||||
|
||||
if (ECMA_BIGINT_GET_SIZE (result_p) == 0)
|
||||
{
|
||||
return ecma_make_extended_primitive_value (result_p, ECMA_TYPE_BIGINT);
|
||||
}
|
||||
|
||||
if (is_mod)
|
||||
{
|
||||
result_p->u.bigint_sign_and_size |= left_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t sign = (left_p->u.bigint_sign_and_size ^ right_p->u.bigint_sign_and_size) & ECMA_BIGINT_SIGN;
|
||||
result_p->u.bigint_sign_and_size |= sign;
|
||||
}
|
||||
|
||||
return ecma_make_extended_primitive_value (result_p, ECMA_TYPE_BIGINT);
|
||||
} /* ecma_bigint_div_mod */
|
||||
|
||||
/**
|
||||
* Shift left BigInt value to left or right
|
||||
*
|
||||
* @return ecma BigInt value or ECMA_VALUE_ERROR
|
||||
* Returned value must be freed with ecma_free_value.
|
||||
*/
|
||||
ecma_value_t
|
||||
ecma_bigint_shift (ecma_value_t left_value, /**< left BigInt value */
|
||||
ecma_value_t right_value, /**< right BigInt value */
|
||||
bool is_left) /**< true if left shift operation should be performed */
|
||||
{
|
||||
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 right_size = ECMA_BIGINT_GET_SIZE (right_p);
|
||||
|
||||
if (right_size == 0 || ECMA_BIGINT_GET_SIZE (left_p) == 0)
|
||||
{
|
||||
ecma_ref_extended_primitive (left_p);
|
||||
return left_value;
|
||||
}
|
||||
|
||||
if (right_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN)
|
||||
{
|
||||
is_left = !is_left;
|
||||
}
|
||||
|
||||
if (right_size > sizeof (ecma_bigint_digit_t))
|
||||
{
|
||||
if (is_left)
|
||||
{
|
||||
return ecma_bigint_raise_memory_error ();
|
||||
}
|
||||
|
||||
return ecma_make_extended_primitive_value (ecma_bigint_create (0), ECMA_TYPE_BIGINT);
|
||||
}
|
||||
|
||||
ecma_extended_primitive_t *result_p;
|
||||
ecma_bigint_digit_t shift = ECMA_BIGINT_GET_LAST_DIGIT (right_p, sizeof (ecma_bigint_digit_t));
|
||||
|
||||
if (is_left)
|
||||
{
|
||||
result_p = ecma_big_uint_shift_left (left_p, shift);
|
||||
}
|
||||
else
|
||||
{
|
||||
result_p = ecma_big_uint_shift_right (left_p, shift);
|
||||
}
|
||||
|
||||
if (JERRY_UNLIKELY (result_p == NULL))
|
||||
{
|
||||
return ecma_bigint_raise_memory_error ();
|
||||
}
|
||||
|
||||
result_p->u.bigint_sign_and_size |= left_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN;
|
||||
return ecma_make_extended_primitive_value (result_p, ECMA_TYPE_BIGINT);
|
||||
} /* ecma_bigint_shift */
|
||||
#endif /* ENABLED (JERRY_BUILTIN_BIGINT) */
|
||||
39
jerry-core/ecma/operations/ecma-bigint.h
Normal file
39
jerry-core/ecma/operations/ecma-bigint.h
Normal file
@ -0,0 +1,39 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
#ifndef ECMA_BIG_INT_H
|
||||
#define ECMA_BIG_INT_H
|
||||
|
||||
#include "ecma-globals.h"
|
||||
|
||||
#if ENABLED (JERRY_BUILTIN_BIGINT)
|
||||
|
||||
/**
|
||||
* Sign bit of a BigInt value. The number is negative, if this bit is set.
|
||||
*/
|
||||
#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_string_t *ecma_bigint_to_string (ecma_value_t value, ecma_bigint_digit_t radix);
|
||||
|
||||
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);
|
||||
ecma_value_t ecma_bigint_mul (ecma_value_t left_value, ecma_value_t right_value);
|
||||
ecma_value_t ecma_bigint_div_mod (ecma_value_t left_value, ecma_value_t right_value, bool is_mod);
|
||||
ecma_value_t ecma_bigint_shift (ecma_value_t left_value, ecma_value_t right_value, bool is_left);
|
||||
|
||||
#endif /* ENABLED (JERRY_BUILTIN_BIGINT) */
|
||||
|
||||
#endif /* ECMA_BIG_INT_H */
|
||||
@ -20,6 +20,8 @@
|
||||
#include <math.h>
|
||||
|
||||
#include "ecma-alloc.h"
|
||||
#include "ecma-bigint.h"
|
||||
#include "ecma-bigint-object.h"
|
||||
#include "ecma-boolean-object.h"
|
||||
#include "ecma-conversion.h"
|
||||
#include "ecma-exceptions.h"
|
||||
@ -279,12 +281,6 @@ ecma_op_to_number (ecma_value_t value) /**< ecma value */
|
||||
ecma_string_t *str_p = ecma_get_string_from_value (value);
|
||||
return ecma_make_number_value (ecma_string_to_number (str_p));
|
||||
}
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
if (ecma_is_value_symbol (value))
|
||||
{
|
||||
return ecma_raise_type_error (ECMA_ERR_MSG ("Cannot convert a Symbol value to a number."));
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
|
||||
if (ecma_is_value_undefined (value))
|
||||
{
|
||||
@ -301,6 +297,20 @@ ecma_op_to_number (ecma_value_t value) /**< ecma value */
|
||||
return ecma_make_integer_value (ecma_is_value_true (value) ? 1 : 0);
|
||||
}
|
||||
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
if (ecma_is_value_symbol (value))
|
||||
{
|
||||
return ecma_raise_type_error (ECMA_ERR_MSG ("Cannot convert a Symbol value to a number"));
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
|
||||
#if ENABLED (JERRY_BUILTIN_BIGINT)
|
||||
if (ecma_is_value_bigint (value))
|
||||
{
|
||||
return ecma_raise_type_error (ECMA_ERR_MSG ("Cannot convert a BigInt value to a number"));
|
||||
}
|
||||
#endif /* ENABLED (JERRY_BUILTIN_BIGINT) */
|
||||
|
||||
JERRY_ASSERT (ecma_is_value_object (value));
|
||||
|
||||
ecma_object_t *obj_p = ecma_get_object_from_value (value);
|
||||
@ -364,13 +374,6 @@ ecma_get_number (ecma_value_t value, /**< ecma value*/
|
||||
return ECMA_VALUE_EMPTY;
|
||||
}
|
||||
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
if (ecma_is_value_symbol (value))
|
||||
{
|
||||
return ecma_raise_type_error (ECMA_ERR_MSG ("Cannot convert a Symbol value to a number."));
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
|
||||
if (ecma_is_value_true (value))
|
||||
{
|
||||
*number_p = 1;
|
||||
@ -383,6 +386,20 @@ ecma_get_number (ecma_value_t value, /**< ecma value*/
|
||||
return ECMA_VALUE_EMPTY;
|
||||
}
|
||||
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
if (ecma_is_value_symbol (value))
|
||||
{
|
||||
return ecma_raise_type_error (ECMA_ERR_MSG ("Cannot convert a Symbol value to a number."));
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
|
||||
#if ENABLED (JERRY_BUILTIN_BIGINT)
|
||||
if (ecma_is_value_bigint (value))
|
||||
{
|
||||
return ecma_raise_type_error (ECMA_ERR_MSG ("Cannot convert a BigInt value to a number"));
|
||||
}
|
||||
#endif /* ENABLED (JERRY_BUILTIN_BIGINT) */
|
||||
|
||||
JERRY_ASSERT (ecma_is_value_object (value));
|
||||
|
||||
ecma_object_t *obj_p = ecma_get_object_from_value (value);
|
||||
@ -452,14 +469,6 @@ ecma_op_to_string (ecma_value_t value) /**< ecma value */
|
||||
return ecma_get_magic_string (LIT_MAGIC_STRING_NULL);
|
||||
}
|
||||
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
if (ecma_is_value_symbol (value))
|
||||
{
|
||||
ecma_raise_type_error (ECMA_ERR_MSG ("Cannot convert a Symbol value to a string."));
|
||||
return NULL;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
|
||||
if (ecma_is_value_true (value))
|
||||
{
|
||||
return ecma_get_magic_string (LIT_MAGIC_STRING_TRUE);
|
||||
@ -470,6 +479,21 @@ ecma_op_to_string (ecma_value_t value) /**< ecma value */
|
||||
return ecma_get_magic_string (LIT_MAGIC_STRING_FALSE);
|
||||
}
|
||||
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
if (ecma_is_value_symbol (value))
|
||||
{
|
||||
ecma_raise_type_error (ECMA_ERR_MSG ("Cannot convert a Symbol value to a string."));
|
||||
return NULL;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
|
||||
#if ENABLED (JERRY_BUILTIN_BIGINT)
|
||||
if (ecma_is_value_bigint (value))
|
||||
{
|
||||
return ecma_bigint_to_string (value, 10);
|
||||
}
|
||||
#endif /* ENABLED (JERRY_BUILTIN_BIGINT) */
|
||||
|
||||
JERRY_ASSERT (ecma_is_value_object (value));
|
||||
|
||||
ecma_object_t *obj_p = ecma_get_object_from_value (value);
|
||||
@ -567,6 +591,12 @@ ecma_op_to_object (ecma_value_t value) /**< ecma value */
|
||||
return ecma_op_create_symbol_object (value);
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
#if ENABLED (JERRY_BUILTIN_BIGINT)
|
||||
else if (ecma_is_value_bigint (value))
|
||||
{
|
||||
return ecma_op_create_bigint_object (value);
|
||||
}
|
||||
#endif /* ENABLED (JERRY_BUILTIN_BIGINT) */
|
||||
else
|
||||
{
|
||||
if (ecma_is_value_undefined (value)
|
||||
|
||||
@ -174,6 +174,12 @@ ecma_op_get_value_object_base (ecma_value_t base_value, /**< base value */
|
||||
id = ECMA_BUILTIN_ID_SYMBOL_PROTOTYPE;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
#if ENABLED (JERRY_BUILTIN_BIGINT)
|
||||
else if (ecma_is_value_bigint (base_value))
|
||||
{
|
||||
id = ECMA_BUILTIN_ID_BIGINT_PROTOTYPE;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_BUILTIN_BIGINT) */
|
||||
else
|
||||
{
|
||||
JERRY_ASSERT (ecma_is_value_boolean (base_value));
|
||||
|
||||
@ -2648,6 +2648,12 @@ ecma_object_get_class_name (ecma_object_t *obj_p) /**< object */
|
||||
return LIT_MAGIC_STRING_FUNCTION_UL;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_BUILTIN_PROXY) */
|
||||
#if ENABLED (JERRY_BUILTIN_BIGINT)
|
||||
case ECMA_BUILTIN_ID_BIGINT:
|
||||
{
|
||||
return LIT_MAGIC_STRING_FUNCTION_UL;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_BUILTIN_BIGINT) */
|
||||
default:
|
||||
{
|
||||
JERRY_ASSERT (ecma_object_check_class_name_is_object (obj_p));
|
||||
|
||||
@ -104,6 +104,7 @@ typedef enum
|
||||
JERRY_FEATURE_SET, /**< Set support */
|
||||
JERRY_FEATURE_WEAKMAP, /**< WeakMap support */
|
||||
JERRY_FEATURE_WEAKSET, /**< WeakSet support */
|
||||
JERRY_FEATURE_BIGINT, /**< BigInt support */
|
||||
JERRY_FEATURE__COUNT /**< number of features. NOTE: must be at the end of the list */
|
||||
} jerry_feature_t;
|
||||
|
||||
|
||||
@ -307,6 +307,9 @@ LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_VALUE, "value")
|
||||
#if ENABLED (JERRY_PARSER)
|
||||
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_RESOURCE_EVAL, "<eval>")
|
||||
#endif
|
||||
#if ENABLED (JERRY_BUILTIN_BIGINT)
|
||||
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_BIGINT_UL, "BigInt")
|
||||
#endif
|
||||
#if ENABLED (JERRY_BUILTIN_MATH)
|
||||
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_LOG10E_U, "LOG10E")
|
||||
#endif
|
||||
@ -318,6 +321,9 @@ LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_STRING_UL, "String")
|
||||
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SYMBOL_UL, "Symbol")
|
||||
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ASSIGN, "assign")
|
||||
#endif
|
||||
#if ENABLED (JERRY_BUILTIN_BIGINT)
|
||||
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_BIGINT, "bigint")
|
||||
#endif
|
||||
#if ENABLED (JERRY_BUILTIN_DATAVIEW) \
|
||||
|| ENABLED (JERRY_BUILTIN_TYPEDARRAY)
|
||||
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_BUFFER, "buffer")
|
||||
@ -981,6 +987,8 @@ LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (4, LIT_MAGIC_STRING_DATE_UL)
|
||||
LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (5, LIT_MAGIC_STRING_ARRAY_UL)
|
||||
#if ENABLED (JERRY_PARSER)
|
||||
LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (6, LIT_MAGIC_STRING_RESOURCE_EVAL)
|
||||
#elif ENABLED (JERRY_BUILTIN_BIGINT)
|
||||
LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (6, LIT_MAGIC_STRING_BIGINT_UL)
|
||||
#elif ENABLED (JERRY_BUILTIN_MATH)
|
||||
LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (6, LIT_MAGIC_STRING_LOG10E_U)
|
||||
#else
|
||||
|
||||
@ -132,6 +132,7 @@ LIT_MAGIC_STRING_THROW = "throw"
|
||||
LIT_MAGIC_STRING_TRUNC = "trunc"
|
||||
LIT_MAGIC_STRING_VALUE = "value"
|
||||
LIT_MAGIC_STRING_RESOURCE_EVAL = "<eval>"
|
||||
LIT_MAGIC_STRING_BIGINT_UL = "BigInt"
|
||||
LIT_MAGIC_STRING_LOG10E_U = "LOG10E"
|
||||
LIT_MAGIC_STRING_NUMBER_UL = "Number"
|
||||
LIT_MAGIC_STRING_OBJECT_UL = "Object"
|
||||
@ -139,6 +140,7 @@ LIT_MAGIC_STRING_REGEXP_UL = "RegExp"
|
||||
LIT_MAGIC_STRING_STRING_UL = "String"
|
||||
LIT_MAGIC_STRING_SYMBOL_UL = "Symbol"
|
||||
LIT_MAGIC_STRING_ASSIGN = "assign"
|
||||
LIT_MAGIC_STRING_BIGINT = "bigint"
|
||||
LIT_MAGIC_STRING_BUFFER = "buffer"
|
||||
LIT_MAGIC_STRING_CALLEE = "callee"
|
||||
LIT_MAGIC_STRING_CALLER = "caller"
|
||||
|
||||
@ -14,7 +14,9 @@
|
||||
*/
|
||||
|
||||
#include "ecma-alloc.h"
|
||||
#include "ecma-bigint.h"
|
||||
#include "ecma-conversion.h"
|
||||
#include "ecma-exceptions.h"
|
||||
#include "ecma-helpers.h"
|
||||
#include "ecma-number-arithmetic.h"
|
||||
#include "ecma-objects.h"
|
||||
@ -45,48 +47,128 @@ do_number_arithmetic (number_arithmetic_op op, /**< number arithmetic operation
|
||||
ecma_value_t left_value, /**< left value */
|
||||
ecma_value_t right_value) /**< right value */
|
||||
{
|
||||
ecma_value_t ret_value = ECMA_VALUE_EMPTY;
|
||||
bool free_left_value = false;
|
||||
bool free_right_value = false;
|
||||
|
||||
ECMA_OP_TO_NUMBER_TRY_CATCH (num_left, left_value, ret_value);
|
||||
ECMA_OP_TO_NUMBER_TRY_CATCH (num_right, right_value, ret_value);
|
||||
|
||||
ecma_number_t result = ECMA_NUMBER_ZERO;
|
||||
|
||||
switch (op)
|
||||
if (ecma_is_value_object (left_value))
|
||||
{
|
||||
case NUMBER_ARITHMETIC_SUBTRACTION:
|
||||
ecma_object_t *obj_p = ecma_get_object_from_value (left_value);
|
||||
left_value = ecma_op_object_default_value (obj_p, ECMA_PREFERRED_TYPE_NUMBER);
|
||||
free_left_value = true;
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (left_value))
|
||||
{
|
||||
result = num_left - num_right;
|
||||
break;
|
||||
return left_value;
|
||||
}
|
||||
case NUMBER_ARITHMETIC_MULTIPLICATION:
|
||||
{
|
||||
result = num_left * num_right;
|
||||
break;
|
||||
}
|
||||
case NUMBER_ARITHMETIC_DIVISION:
|
||||
{
|
||||
result = num_left / num_right;
|
||||
break;
|
||||
}
|
||||
case NUMBER_ARITHMETIC_REMAINDER:
|
||||
{
|
||||
result = ecma_op_number_remainder (num_left, num_right);
|
||||
break;
|
||||
}
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
case NUMBER_ARITHMETIC_EXPONENTIATION:
|
||||
{
|
||||
result = ecma_number_pow (num_left, num_right);
|
||||
break;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
}
|
||||
|
||||
ret_value = ecma_make_number_value (result);
|
||||
if (ecma_is_value_object (right_value))
|
||||
{
|
||||
ecma_object_t *obj_p = ecma_get_object_from_value (right_value);
|
||||
right_value = ecma_op_object_default_value (obj_p, ECMA_PREFERRED_TYPE_NUMBER);
|
||||
free_right_value = true;
|
||||
|
||||
ECMA_OP_TO_NUMBER_FINALIZE (num_right);
|
||||
ECMA_OP_TO_NUMBER_FINALIZE (num_left);
|
||||
if (ECMA_IS_VALUE_ERROR (right_value))
|
||||
{
|
||||
if (free_left_value)
|
||||
{
|
||||
ecma_free_value (left_value);
|
||||
}
|
||||
return right_value;
|
||||
}
|
||||
}
|
||||
|
||||
ecma_value_t ret_value = ECMA_VALUE_EMPTY;
|
||||
|
||||
#if ENABLED (JERRY_BUILTIN_BIGINT)
|
||||
if (JERRY_LIKELY (!ecma_is_value_bigint (left_value))
|
||||
|| JERRY_LIKELY (!ecma_is_value_bigint (right_value)))
|
||||
{
|
||||
#endif /* ENABLED (JERRY_BUILTIN_BIGINT) */
|
||||
ECMA_OP_TO_NUMBER_TRY_CATCH (num_left, left_value, ret_value);
|
||||
ECMA_OP_TO_NUMBER_TRY_CATCH (num_right, right_value, ret_value);
|
||||
|
||||
ecma_number_t result = ECMA_NUMBER_ZERO;
|
||||
|
||||
switch (op)
|
||||
{
|
||||
case NUMBER_ARITHMETIC_SUBTRACTION:
|
||||
{
|
||||
result = num_left - num_right;
|
||||
break;
|
||||
}
|
||||
case NUMBER_ARITHMETIC_MULTIPLICATION:
|
||||
{
|
||||
result = num_left * num_right;
|
||||
break;
|
||||
}
|
||||
case NUMBER_ARITHMETIC_DIVISION:
|
||||
{
|
||||
result = num_left / num_right;
|
||||
break;
|
||||
}
|
||||
case NUMBER_ARITHMETIC_REMAINDER:
|
||||
{
|
||||
result = ecma_op_number_remainder (num_left, num_right);
|
||||
break;
|
||||
}
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
case NUMBER_ARITHMETIC_EXPONENTIATION:
|
||||
{
|
||||
result = ecma_number_pow (num_left, num_right);
|
||||
break;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
}
|
||||
|
||||
ret_value = ecma_make_number_value (result);
|
||||
|
||||
ECMA_OP_TO_NUMBER_FINALIZE (num_right);
|
||||
ECMA_OP_TO_NUMBER_FINALIZE (num_left);
|
||||
#if ENABLED (JERRY_BUILTIN_BIGINT)
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (op)
|
||||
{
|
||||
case NUMBER_ARITHMETIC_SUBTRACTION:
|
||||
{
|
||||
ret_value = ecma_bigint_add_sub (left_value, right_value, false);
|
||||
break;
|
||||
}
|
||||
case NUMBER_ARITHMETIC_MULTIPLICATION:
|
||||
{
|
||||
ret_value = ecma_bigint_mul (left_value, right_value);
|
||||
break;
|
||||
}
|
||||
case NUMBER_ARITHMETIC_DIVISION:
|
||||
{
|
||||
ret_value = ecma_bigint_div_mod (left_value, right_value, false);
|
||||
break;
|
||||
}
|
||||
case NUMBER_ARITHMETIC_REMAINDER:
|
||||
{
|
||||
ret_value = ecma_bigint_div_mod (left_value, right_value, true);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
ret_value = ecma_raise_common_error (ECMA_ERR_MSG ("Not supported BigInt operation"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* ENABLED (JERRY_BUILTIN_BIGINT) */
|
||||
|
||||
if (free_left_value)
|
||||
{
|
||||
ecma_free_value (left_value);
|
||||
}
|
||||
|
||||
if (free_right_value)
|
||||
{
|
||||
ecma_free_value (right_value);
|
||||
}
|
||||
|
||||
return ret_value;
|
||||
} /* do_number_arithmetic */
|
||||
@ -175,6 +257,13 @@ opfunc_addition (ecma_value_t left_value, /**< left value */
|
||||
|
||||
ecma_deref_ecma_string (string2_p);
|
||||
}
|
||||
#if ENABLED (JERRY_BUILTIN_BIGINT)
|
||||
else if (JERRY_UNLIKELY (ecma_is_value_bigint (left_value))
|
||||
&& JERRY_UNLIKELY (ecma_is_value_bigint (right_value)))
|
||||
{
|
||||
ret_value = ecma_bigint_add_sub (left_value, right_value, true);
|
||||
}
|
||||
#endif /* ENABLED (JERRY_BUILTIN_BIGINT) */
|
||||
else
|
||||
{
|
||||
ECMA_OP_TO_NUMBER_TRY_CATCH (num_left, left_value, ret_value);
|
||||
@ -211,15 +300,63 @@ ecma_value_t
|
||||
opfunc_unary_operation (ecma_value_t left_value, /**< left value */
|
||||
bool is_plus) /**< unary plus flag */
|
||||
{
|
||||
bool free_left_value = false;
|
||||
|
||||
if (ecma_is_value_object (left_value))
|
||||
{
|
||||
ecma_object_t *obj_p = ecma_get_object_from_value (left_value);
|
||||
left_value = ecma_op_object_default_value (obj_p, ECMA_PREFERRED_TYPE_NUMBER);
|
||||
free_left_value = true;
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (left_value))
|
||||
{
|
||||
return left_value;
|
||||
}
|
||||
}
|
||||
|
||||
ecma_value_t ret_value = ECMA_VALUE_EMPTY;
|
||||
|
||||
ECMA_OP_TO_NUMBER_TRY_CATCH (num_var_value,
|
||||
left_value,
|
||||
ret_value);
|
||||
#if ENABLED (JERRY_BUILTIN_BIGINT)
|
||||
if (JERRY_LIKELY (!ecma_is_value_bigint (left_value)))
|
||||
{
|
||||
#endif /* ENABLED (JERRY_BUILTIN_BIGINT) */
|
||||
ECMA_OP_TO_NUMBER_TRY_CATCH (num_var_value,
|
||||
left_value,
|
||||
ret_value);
|
||||
|
||||
ret_value = ecma_make_number_value (is_plus ? num_var_value : -num_var_value);
|
||||
ret_value = ecma_make_number_value (is_plus ? num_var_value : -num_var_value);
|
||||
|
||||
ECMA_OP_TO_NUMBER_FINALIZE (num_var_value);
|
||||
ECMA_OP_TO_NUMBER_FINALIZE (num_var_value);
|
||||
|
||||
#if ENABLED (JERRY_BUILTIN_BIGINT)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (is_plus)
|
||||
{
|
||||
ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("Unary operation plus is not allowed for BigInt numbers"));
|
||||
}
|
||||
else
|
||||
{
|
||||
ecma_extended_primitive_t *left_p = ecma_get_extended_primitive_from_value (left_value);
|
||||
|
||||
if (ECMA_BIGINT_GET_SIZE (left_p) == 0)
|
||||
{
|
||||
ecma_ref_extended_primitive (left_p);
|
||||
ret_value = left_value;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret_value = ecma_bigint_negate (left_p);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* ENABLED (JERRY_BUILTIN_BIGINT) */
|
||||
|
||||
if (free_left_value)
|
||||
{
|
||||
ecma_free_value (left_value);
|
||||
}
|
||||
|
||||
return ret_value;
|
||||
} /* opfunc_unary_operation */
|
||||
|
||||
@ -14,8 +14,11 @@
|
||||
*/
|
||||
|
||||
#include "ecma-alloc.h"
|
||||
#include "ecma-bigint.h"
|
||||
#include "ecma-conversion.h"
|
||||
#include "ecma-exceptions.h"
|
||||
#include "ecma-helpers.h"
|
||||
#include "ecma-objects.h"
|
||||
#include "ecma-try-catch-macro.h"
|
||||
#include "opcodes.h"
|
||||
|
||||
@ -45,61 +48,131 @@ do_number_bitwise_logic (number_bitwise_logic_op op, /**< number bitwise logic o
|
||||
JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (left_value)
|
||||
&& !ECMA_IS_VALUE_ERROR (right_value));
|
||||
|
||||
ecma_value_t ret_value = ECMA_VALUE_EMPTY;
|
||||
bool free_left_value = false;
|
||||
bool free_right_value = false;
|
||||
|
||||
ECMA_OP_TO_NUMBER_TRY_CATCH (num_left, left_value, ret_value);
|
||||
ECMA_OP_TO_NUMBER_TRY_CATCH (num_right, right_value, ret_value);
|
||||
|
||||
ecma_number_t result = ECMA_NUMBER_ZERO;
|
||||
uint32_t right_uint32 = ecma_number_to_uint32 (num_right);
|
||||
|
||||
switch (op)
|
||||
if (ecma_is_value_object (left_value))
|
||||
{
|
||||
case NUMBER_BITWISE_LOGIC_AND:
|
||||
ecma_object_t *obj_p = ecma_get_object_from_value (left_value);
|
||||
left_value = ecma_op_object_default_value (obj_p, ECMA_PREFERRED_TYPE_NUMBER);
|
||||
free_left_value = true;
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (left_value))
|
||||
{
|
||||
uint32_t left_uint32 = ecma_number_to_uint32 (num_left);
|
||||
result = (ecma_number_t) ((int32_t) (left_uint32 & right_uint32));
|
||||
break;
|
||||
}
|
||||
case NUMBER_BITWISE_LOGIC_OR:
|
||||
{
|
||||
uint32_t left_uint32 = ecma_number_to_uint32 (num_left);
|
||||
result = (ecma_number_t) ((int32_t) (left_uint32 | right_uint32));
|
||||
break;
|
||||
}
|
||||
case NUMBER_BITWISE_LOGIC_XOR:
|
||||
{
|
||||
uint32_t left_uint32 = ecma_number_to_uint32 (num_left);
|
||||
result = (ecma_number_t) ((int32_t) (left_uint32 ^ right_uint32));
|
||||
break;
|
||||
}
|
||||
case NUMBER_BITWISE_SHIFT_LEFT:
|
||||
{
|
||||
result = (ecma_number_t) (ecma_number_to_int32 (num_left) << (right_uint32 & 0x1F));
|
||||
break;
|
||||
}
|
||||
case NUMBER_BITWISE_SHIFT_RIGHT:
|
||||
{
|
||||
result = (ecma_number_t) (ecma_number_to_int32 (num_left) >> (right_uint32 & 0x1F));
|
||||
break;
|
||||
}
|
||||
case NUMBER_BITWISE_SHIFT_URIGHT:
|
||||
{
|
||||
uint32_t left_uint32 = ecma_number_to_uint32 (num_left);
|
||||
result = (ecma_number_t) (left_uint32 >> (right_uint32 & 0x1F));
|
||||
break;
|
||||
}
|
||||
case NUMBER_BITWISE_NOT:
|
||||
{
|
||||
result = (ecma_number_t) ((int32_t) ~right_uint32);
|
||||
break;
|
||||
return left_value;
|
||||
}
|
||||
}
|
||||
|
||||
ret_value = ecma_make_number_value (result);
|
||||
if (ecma_is_value_object (right_value))
|
||||
{
|
||||
ecma_object_t *obj_p = ecma_get_object_from_value (right_value);
|
||||
right_value = ecma_op_object_default_value (obj_p, ECMA_PREFERRED_TYPE_NUMBER);
|
||||
free_right_value = true;
|
||||
|
||||
ECMA_OP_TO_NUMBER_FINALIZE (num_right);
|
||||
ECMA_OP_TO_NUMBER_FINALIZE (num_left);
|
||||
if (ECMA_IS_VALUE_ERROR (right_value))
|
||||
{
|
||||
if (free_left_value)
|
||||
{
|
||||
ecma_free_value (left_value);
|
||||
}
|
||||
return right_value;
|
||||
}
|
||||
}
|
||||
|
||||
ecma_value_t ret_value = ECMA_VALUE_EMPTY;
|
||||
|
||||
#if ENABLED (JERRY_BUILTIN_BIGINT)
|
||||
if (JERRY_LIKELY (!ecma_is_value_bigint (left_value))
|
||||
|| JERRY_LIKELY (!ecma_is_value_bigint (right_value)))
|
||||
{
|
||||
#endif /* ENABLED (JERRY_BUILTIN_BIGINT) */
|
||||
ECMA_OP_TO_NUMBER_TRY_CATCH (num_left, left_value, ret_value);
|
||||
ECMA_OP_TO_NUMBER_TRY_CATCH (num_right, right_value, ret_value);
|
||||
|
||||
ecma_number_t result = ECMA_NUMBER_ZERO;
|
||||
uint32_t right_uint32 = ecma_number_to_uint32 (num_right);
|
||||
|
||||
switch (op)
|
||||
{
|
||||
case NUMBER_BITWISE_LOGIC_AND:
|
||||
{
|
||||
uint32_t left_uint32 = ecma_number_to_uint32 (num_left);
|
||||
result = (ecma_number_t) ((int32_t) (left_uint32 & right_uint32));
|
||||
break;
|
||||
}
|
||||
case NUMBER_BITWISE_LOGIC_OR:
|
||||
{
|
||||
uint32_t left_uint32 = ecma_number_to_uint32 (num_left);
|
||||
result = (ecma_number_t) ((int32_t) (left_uint32 | right_uint32));
|
||||
break;
|
||||
}
|
||||
case NUMBER_BITWISE_LOGIC_XOR:
|
||||
{
|
||||
uint32_t left_uint32 = ecma_number_to_uint32 (num_left);
|
||||
result = (ecma_number_t) ((int32_t) (left_uint32 ^ right_uint32));
|
||||
break;
|
||||
}
|
||||
case NUMBER_BITWISE_SHIFT_LEFT:
|
||||
{
|
||||
result = (ecma_number_t) (ecma_number_to_int32 (num_left) << (right_uint32 & 0x1F));
|
||||
break;
|
||||
}
|
||||
case NUMBER_BITWISE_SHIFT_RIGHT:
|
||||
{
|
||||
result = (ecma_number_t) (ecma_number_to_int32 (num_left) >> (right_uint32 & 0x1F));
|
||||
break;
|
||||
}
|
||||
case NUMBER_BITWISE_SHIFT_URIGHT:
|
||||
{
|
||||
uint32_t left_uint32 = ecma_number_to_uint32 (num_left);
|
||||
result = (ecma_number_t) (left_uint32 >> (right_uint32 & 0x1F));
|
||||
break;
|
||||
}
|
||||
case NUMBER_BITWISE_NOT:
|
||||
{
|
||||
result = (ecma_number_t) ((int32_t) ~right_uint32);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ret_value = ecma_make_number_value (result);
|
||||
|
||||
ECMA_OP_TO_NUMBER_FINALIZE (num_right);
|
||||
ECMA_OP_TO_NUMBER_FINALIZE (num_left);
|
||||
#if ENABLED (JERRY_BUILTIN_BIGINT)
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (op)
|
||||
{
|
||||
case NUMBER_BITWISE_SHIFT_LEFT:
|
||||
{
|
||||
ret_value = ecma_bigint_shift (left_value, right_value, true);
|
||||
break;
|
||||
}
|
||||
case NUMBER_BITWISE_SHIFT_RIGHT:
|
||||
{
|
||||
ret_value = ecma_bigint_shift (left_value, right_value, false);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
ret_value = ecma_raise_common_error (ECMA_ERR_MSG ("Not supported BigInt operation"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* ENABLED (JERRY_BUILTIN_BIGINT) */
|
||||
|
||||
if (free_left_value)
|
||||
{
|
||||
ecma_free_value (left_value);
|
||||
}
|
||||
|
||||
if (free_right_value)
|
||||
{
|
||||
ecma_free_value (right_value);
|
||||
}
|
||||
|
||||
return ret_value;
|
||||
} /* do_number_bitwise_logic */
|
||||
|
||||
237
tests/jerry/es.next/bigint1.js
Normal file
237
tests/jerry/es.next/bigint1.js
Normal file
@ -0,0 +1,237 @@
|
||||
/* 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_result16(bigint, expected)
|
||||
{
|
||||
assert(bigint.toString(16) === expected)
|
||||
}
|
||||
|
||||
function check_syntax_error(code)
|
||||
{
|
||||
try {
|
||||
eval(code)
|
||||
assert(false)
|
||||
} catch (e) {
|
||||
assert(e instanceof SyntaxError)
|
||||
}
|
||||
}
|
||||
|
||||
assert(typeof BigInt("0") == "bigint")
|
||||
|
||||
// Test BigInt string parsing and toString
|
||||
|
||||
check_syntax_error("BigInt('-0x5')");
|
||||
check_syntax_error("BigInt('-')");
|
||||
check_syntax_error("BigInt('00x5')");
|
||||
check_syntax_error("BigInt('11a')");
|
||||
check_syntax_error("BigInt('0b2')");
|
||||
check_syntax_error("BigInt('1n')");
|
||||
|
||||
check_result(BigInt("0"), "0")
|
||||
check_result(BigInt("-0"), "0")
|
||||
check_result(BigInt("100000000000000000000000000000000000000"), "100000000000000000000000000000000000000")
|
||||
check_result(BigInt("-1234567890123456789012345678901234567890"), "-1234567890123456789012345678901234567890")
|
||||
check_result(BigInt("+1"), "1")
|
||||
check_result(BigInt("+000000000000000000001"), "1")
|
||||
check_result(BigInt("-000000000000000000000"), "0")
|
||||
check_result(BigInt("0x00abcdefABCDEF0123456789000000000000000"), "239460437713606077082343926293727858623774720")
|
||||
check_result(BigInt("0b00100000000000010000000000010000000000010"), "274911469570")
|
||||
|
||||
assert(BigInt("100000000000000000000000000000000000000").toString(22) === "2ci67fiek1bkhec5fig7aiii9hf8c")
|
||||
check_result16(BigInt("239460437713606077082343926293727858623774720"), "abcdefabcdef0123456789000000000000000")
|
||||
|
||||
// Test negate
|
||||
|
||||
check_result(-BigInt("0"), "0")
|
||||
check_result(-BigInt("100"), "-100")
|
||||
check_result(-BigInt("-100"), "100")
|
||||
check_result(-BigInt("100000000000000000000000000000000000000000000"), "-100000000000000000000000000000000000000000000")
|
||||
check_result(-BigInt("-100000000000000000000000000000000000000000000"), "100000000000000000000000000000000000000000000")
|
||||
|
||||
// Test addition
|
||||
|
||||
check_result(BigInt("0") + BigInt("0"), "0")
|
||||
check_result(BigInt("1") + BigInt("1"), "2")
|
||||
check_result(BigInt("0") + BigInt("100"), "100")
|
||||
check_result(BigInt("0") + BigInt("-100"), "-100")
|
||||
check_result(BigInt("100") + BigInt("0"), "100")
|
||||
check_result(BigInt("-100") + BigInt("0"), "-100")
|
||||
|
||||
check_result(BigInt("100000000000000000000000000000000000000") + BigInt("100000000000000000000000000000000000000"),
|
||||
"200000000000000000000000000000000000000");
|
||||
check_result(BigInt("-100000000000000000000000000000000000000") + BigInt("-100000000000000000000000000000000000000"),
|
||||
"-200000000000000000000000000000000000000");
|
||||
check_result(BigInt("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff3") + BigInt("0xd"),
|
||||
"115792089237316195423570985008687907853269984665640564039457584007913129639936");
|
||||
check_result(BigInt("0xd") + BigInt("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff3"),
|
||||
"115792089237316195423570985008687907853269984665640564039457584007913129639936");
|
||||
|
||||
check_result(BigInt("100000000000000000000000000000000000000") + BigInt("-100000000000000000000000000000000000000"), "0")
|
||||
check_result(BigInt("100000000000000000000000000000000000001") + BigInt("-100000000000000000000000000000000000000"), "1")
|
||||
check_result(BigInt("100000000000000000000000000000000000000") + BigInt("-100000000000000000000000000000000000001"), "-1")
|
||||
check_result(BigInt("-100000000000000000000000000000000000000") + BigInt("100000000000000000000000000000000000000"), "0")
|
||||
check_result(BigInt("-100000000000000000000000000000000000001") + BigInt("100000000000000000000000000000000000000"), "-1")
|
||||
check_result(BigInt("-100000000000000000000000000000000000000") + BigInt("100000000000000000000000000000000000001"), "1")
|
||||
|
||||
// Test substraction
|
||||
|
||||
check_result(BigInt("0") - BigInt("0"), "0")
|
||||
check_result(BigInt("2") - BigInt("1"), "1")
|
||||
check_result(BigInt("0") - BigInt("100"), "-100")
|
||||
check_result(BigInt("0") - BigInt("-100"), "100")
|
||||
check_result(BigInt("100") - BigInt("0"), "100")
|
||||
check_result(BigInt("-100") - BigInt("0"), "-100")
|
||||
|
||||
check_result(BigInt("100000000000000000000000000000000000000") - BigInt("-100000000000000000000000000000000000000"),
|
||||
"200000000000000000000000000000000000000");
|
||||
check_result(BigInt("-100000000000000000000000000000000000000") - BigInt("100000000000000000000000000000000000000"),
|
||||
"-200000000000000000000000000000000000000");
|
||||
check_result(BigInt("100000000000000000000000000000000000000") - BigInt("-1"),
|
||||
"100000000000000000000000000000000000001");
|
||||
check_result(BigInt("-100000000000000000000000000000000000000") - BigInt("1"),
|
||||
"-100000000000000000000000000000000000001");
|
||||
check_result(BigInt("1") - BigInt("-100000000000000000000000000000000000000"),
|
||||
"100000000000000000000000000000000000001");
|
||||
check_result(BigInt("-1") - BigInt("100000000000000000000000000000000000000"),
|
||||
"-100000000000000000000000000000000000001");
|
||||
|
||||
check_result(BigInt("100000000000000000000000000000000000000") - BigInt("100000000000000000000000000000000000000"), "0")
|
||||
check_result(BigInt("100000000000000000000000000000000000001") - BigInt("100000000000000000000000000000000000000"), "1")
|
||||
check_result(BigInt("100000000000000000000000000000000000000") - BigInt("100000000000000000000000000000000000001"), "-1")
|
||||
check_result(BigInt("-100000000000000000000000000000000000000") - BigInt("-100000000000000000000000000000000000000"), "0")
|
||||
check_result(BigInt("-100000000000000000000000000000000000001") - BigInt("-100000000000000000000000000000000000000"), "-1")
|
||||
check_result(BigInt("-100000000000000000000000000000000000000") - BigInt("-100000000000000000000000000000000000001"), "1")
|
||||
|
||||
// Test multiplication
|
||||
|
||||
check_result(BigInt("0") * BigInt("0"), "0")
|
||||
check_result(BigInt("1000") * BigInt("0"), "0")
|
||||
check_result(BigInt("0") * BigInt("1000"), "0")
|
||||
check_result(BigInt("1") * BigInt("100000000000000000000000000000000000000"), "100000000000000000000000000000000000000")
|
||||
check_result(BigInt("1") * BigInt("-100000000000000000000000000000000000000"), "-100000000000000000000000000000000000000")
|
||||
check_result(BigInt("-1") * BigInt("100000000000000000000000000000000000000"), "-100000000000000000000000000000000000000")
|
||||
check_result(BigInt("-1") * BigInt("-100000000000000000000000000000000000000"), "100000000000000000000000000000000000000")
|
||||
check_result(BigInt("100000000000000000000000000000000000000") * BigInt("1"), "100000000000000000000000000000000000000")
|
||||
check_result(BigInt("-100000000000000000000000000000000000000") * BigInt("1"), "-100000000000000000000000000000000000000")
|
||||
check_result(BigInt("100000000000000000000000000000000000000") * BigInt("-1"), "-100000000000000000000000000000000000000")
|
||||
check_result(BigInt("-100000000000000000000000000000000000000") * BigInt("-1"), "100000000000000000000000000000000000000")
|
||||
|
||||
check_result(BigInt("100000000000000000000000000000000000000") * BigInt("100000000000000000000000000000000000000"),
|
||||
"10000000000000000000000000000000000000000000000000000000000000000000000000000")
|
||||
check_result(BigInt("100000000000000000000000000000000000000") * BigInt("-100000000000000000000000000000000000000"),
|
||||
"-10000000000000000000000000000000000000000000000000000000000000000000000000000")
|
||||
check_result(BigInt("-100000000000000000000000000000000000000") * BigInt("100000000000000000000000000000000000000"),
|
||||
"-10000000000000000000000000000000000000000000000000000000000000000000000000000")
|
||||
check_result(BigInt("-100000000000000000000000000000000000000") * BigInt("-100000000000000000000000000000000000000"),
|
||||
"10000000000000000000000000000000000000000000000000000000000000000000000000000")
|
||||
|
||||
// Test divide
|
||||
|
||||
try {
|
||||
BigInt("32") / BigInt("0")
|
||||
assert(false)
|
||||
} catch (e) {
|
||||
assert(e instanceof RangeError)
|
||||
}
|
||||
|
||||
try {
|
||||
BigInt("32") % BigInt("0")
|
||||
assert(false)
|
||||
} catch (e) {
|
||||
assert(e instanceof RangeError)
|
||||
}
|
||||
|
||||
check_result(BigInt("0") / BigInt("1234"), "0")
|
||||
check_result(BigInt("0") % BigInt("1234"), "0")
|
||||
|
||||
check_result(BigInt("100") / BigInt("70"), "1")
|
||||
check_result(BigInt("100") % BigInt("70"), "30")
|
||||
check_result(BigInt("-100") / BigInt("70"), "-1")
|
||||
check_result(BigInt("-100") % BigInt("70"), "-30")
|
||||
check_result(BigInt("100") / BigInt("-70"), "-1")
|
||||
check_result(BigInt("100") % BigInt("-70"), "30")
|
||||
check_result(BigInt("-100") / BigInt("-70"), "1")
|
||||
check_result(BigInt("-100") % BigInt("-70"), "-30")
|
||||
|
||||
check_result(BigInt("100") / BigInt("100"), "1")
|
||||
check_result(BigInt("100") % BigInt("100"), "0")
|
||||
check_result(BigInt("-100") / BigInt("100"), "-1")
|
||||
check_result(BigInt("-100") % BigInt("100"), "0")
|
||||
check_result(BigInt("100") / BigInt("-100"), "-1")
|
||||
check_result(BigInt("100") % BigInt("-100"), "0")
|
||||
check_result(BigInt("-100") / BigInt("-100"), "1")
|
||||
check_result(BigInt("-100") % BigInt("-100"), "0")
|
||||
|
||||
/* Division by small value. */
|
||||
check_result(BigInt("100000000000000000000") / BigInt("1000000"), "100000000000000")
|
||||
check_result(BigInt("100000000000000000000") % BigInt("1000000"), "0")
|
||||
check_result(BigInt("12345678901234567890") / BigInt("1000000"), "12345678901234")
|
||||
check_result(BigInt("12345678901234567890") % BigInt("1000000"), "567890")
|
||||
|
||||
/* Division by large value. */
|
||||
check_result(BigInt("100000000000000000000") / BigInt("100000000000000000"), "1000")
|
||||
check_result(BigInt("100000000000000000000") % BigInt("100000000000000000"), "0")
|
||||
check_result(BigInt("12345678901234567890123456789012345678901234567890123456789012345678901234567890") / BigInt("10000000000000000000000000000000000000"),
|
||||
"1234567890123456789012345678901234567890123")
|
||||
check_result(BigInt("12345678901234567890123456789012345678901234567890123456789012345678901234567890") % BigInt("10000000000000000000000000000000000000"),
|
||||
"4567890123456789012345678901234567890")
|
||||
check_result16(BigInt("0xffffffffffffffffffffffff") / BigInt("0x100000000"), "ffffffffffffffff")
|
||||
check_result16(BigInt("0xffffffffffffffffffffffff") % BigInt("0x100000000"), "ffffffff")
|
||||
|
||||
/* Triggers a corner case. */
|
||||
check_result(BigInt("170141183420855150493001878992821682176") / BigInt("39614081266355540842216685573"), "4294967293")
|
||||
check_result(BigInt("170141183420855150493001878992821682176") % BigInt("39614081266355540842216685573"), "39614081266355540837921718287")
|
||||
|
||||
// Test shift
|
||||
|
||||
check_result(BigInt("0") << BigInt("10000000"), "0")
|
||||
check_result(BigInt("0") >> BigInt("10000000"), "0")
|
||||
check_result(BigInt("10000000") << BigInt("0"), "10000000")
|
||||
check_result(BigInt("10000000") >> BigInt("0"), "10000000")
|
||||
|
||||
check_result(BigInt("4096") << BigInt("2"), "16384")
|
||||
check_result(BigInt("4096") << BigInt("-2"), "1024")
|
||||
check_result(BigInt("4096") >> BigInt("2"), "1024")
|
||||
check_result(BigInt("4096") >> BigInt("-2"), "16384")
|
||||
|
||||
check_result16(BigInt("0x8fef5fcfffef5fcfffef5fcfffef5fcff") << BigInt("1"), "11fdebf9fffdebf9fffdebf9fffdebf9fe")
|
||||
check_result16(BigInt("0x8fef5fcfffef5fcfffef5fcfffef5fcff") << BigInt("19"), "47f7afe7fff7afe7fff7afe7fff7afe7f80000")
|
||||
check_result16(BigInt("0x8fef5fcfffef5fcfffef5fcfffef5fcff") << BigInt("31"), "47f7afe7fff7afe7fff7afe7fff7afe7f80000000")
|
||||
check_result16(BigInt("0x8fef5fcfffef5fcfffef5fcfffef5fcff") << BigInt("32"), "8fef5fcfffef5fcfffef5fcfffef5fcff00000000")
|
||||
check_result16(BigInt("0x8fef5fcfffef5fcfffef5fcfffef5fcff") << BigInt("51"), "47f7afe7fff7afe7fff7afe7fff7afe7f8000000000000")
|
||||
check_result16(BigInt("0x8fef5fcfffef5fcfffef5fcfffef5fcff") << BigInt("63"), "47f7afe7fff7afe7fff7afe7fff7afe7f8000000000000000")
|
||||
check_result16(BigInt("0x8fef5fcfffef5fcfffef5fcfffef5fcff") << BigInt("64"), "8fef5fcfffef5fcfffef5fcfffef5fcff0000000000000000")
|
||||
|
||||
check_result16(BigInt("0x8fef5fcfffef5fcfffef5fcfffef5fcff") >> BigInt("1"), "47f7afe7fff7afe7fff7afe7fff7afe7f")
|
||||
check_result16(BigInt("0x8fef5fcfffef5fcfffef5fcfffef5fcff") >> BigInt("19"), "11fdebf9fffdebf9fffdebf9fffde")
|
||||
check_result16(BigInt("0x8fef5fcfffef5fcfffef5fcfffef5fcff") >> BigInt("31"), "11fdebf9fffdebf9fffdebf9ff")
|
||||
check_result16(BigInt("0x8fef5fcfffef5fcfffef5fcfffef5fcff") >> BigInt("32"), "8fef5fcfffef5fcfffef5fcff")
|
||||
check_result16(BigInt("0x8fef5fcfffef5fcfffef5fcfffef5fcff") >> BigInt("51"), "11fdebf9fffdebf9fffde")
|
||||
check_result16(BigInt("0x8fef5fcfffef5fcfffef5fcfffef5fcff") >> BigInt("63"), "11fdebf9fffdebf9ff")
|
||||
check_result16(BigInt("0x8fef5fcfffef5fcfffef5fcfffef5fcff") >> BigInt("64"), "8fef5fcfffef5fcff")
|
||||
|
||||
check_result16(BigInt("0x8fef5fcfffef5fcfffef5fcfffef5fcff") >> BigInt("10000000000000000000000000"), "0")
|
||||
|
||||
try {
|
||||
BigInt("0x8fef5fcfffef5fcfffef5fcfffef5fcff") << BigInt("10000000000000000000000000");
|
||||
assert(false)
|
||||
} catch (e) {
|
||||
assert(e instanceof RangeError)
|
||||
}
|
||||
61
tests/jerry/es.next/bigint2.js
Normal file
61
tests/jerry/es.next/bigint2.js
Normal file
@ -0,0 +1,61 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
try {
|
||||
new BigInt("1")
|
||||
assert(false)
|
||||
} catch (e) {
|
||||
assert(e instanceof TypeError)
|
||||
}
|
||||
|
||||
function check_type_error (code)
|
||||
{
|
||||
try {
|
||||
eval(code)
|
||||
assert(false)
|
||||
} catch (e) {
|
||||
assert(e instanceof TypeError)
|
||||
}
|
||||
}
|
||||
|
||||
check_type_error("+BigInt('0')")
|
||||
|
||||
check_type_error("BigInt('1') + 1")
|
||||
check_type_error("BigInt('2') - 2")
|
||||
check_type_error("BigInt('3') * 3")
|
||||
check_type_error("BigInt('4') / 4")
|
||||
check_type_error("BigInt('5') % 5")
|
||||
check_type_error("BigInt('6') ** 6")
|
||||
|
||||
check_type_error("1 + BigInt('1')")
|
||||
check_type_error("2 - BigInt('2')")
|
||||
check_type_error("3 * BigInt('3')")
|
||||
check_type_error("4 / BigInt('4')")
|
||||
check_type_error("5 % BigInt('5')")
|
||||
check_type_error("6 ** BigInt('6')")
|
||||
|
||||
check_type_error("BigInt('1') & 1")
|
||||
check_type_error("BigInt('2') | 2")
|
||||
check_type_error("BigInt('3') ^ 3")
|
||||
check_type_error("BigInt('4') << 4")
|
||||
check_type_error("BigInt('5') >> 5")
|
||||
check_type_error("BigInt('6') >>> 6")
|
||||
|
||||
check_type_error("1 & BigInt('1')")
|
||||
check_type_error("2 | BigInt('2')")
|
||||
check_type_error("3 ^ BigInt('3')")
|
||||
check_type_error("4 << BigInt('4')")
|
||||
check_type_error("5 >> BigInt('5')")
|
||||
check_type_error("6 >>> BigInt('6')")
|
||||
Loading…
x
Reference in New Issue
Block a user