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:
Zoltan Herczeg 2020-07-30 12:08:34 +02:00 committed by GitHub
parent 3eb69075f7
commit df2f7782f7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
29 changed files with 3237 additions and 192 deletions

View File

@ -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;
}

View File

@ -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."

View File

@ -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;

View File

@ -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
*/

View File

@ -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));

View File

@ -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;

View File

@ -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);

View 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) */

View File

@ -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"

View 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) */

View 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"

View File

@ -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) */

View File

@ -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)

File diff suppressed because it is too large Load Diff

View 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 */

View 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) */

View 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 */

View 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) */

View 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 */

View File

@ -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)

View File

@ -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));

View File

@ -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));

View File

@ -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;

View File

@ -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

View File

@ -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"

View File

@ -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 */

View File

@ -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 */

View 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)
}

View 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')")