diff --git a/docs/02.API-REFERENCE.md b/docs/02.API-REFERENCE.md
index 278b46e6c..d8d7af98f 100644
--- a/docs/02.API-REFERENCE.md
+++ b/docs/02.API-REFERENCE.md
@@ -2031,6 +2031,69 @@ main (void)
- [jerry_release_value](#jerry_release_value)
- [jerry_create_symbol](#jerry_create_symbol)
+
+## jerry_value_is_bigint
+
+**Summary**
+
+Returns whether the given `jerry_value_t` is a bigint value.
+
+*Notes*:
+- This API depends on a build option (`JERRY_BUILTIN_BIGINT`) and can be checked
+ in runtime with the `JERRY_FEATURE_BIGINT` feature enum value,
+ see: [jerry_is_feature_enabled](#jerry_is_feature_enabled).
+- The es.next profile enables this by default.
+
+**Prototype**
+
+```c
+bool
+jerry_value_is_bigint (const jerry_value_t value)
+```
+
+- `value` - API value
+- return value
+ - true, if the given `jerry_value_t` is a BigInt
+ - false, otherwise
+
+*New in version [[NEXT_RELEASE]]*
+
+**Example**
+
+[doctest]: # ()
+
+```c
+#include "jerryscript.h"
+
+int
+main (void)
+{
+ jerry_init (JERRY_INIT_EMPTY);
+
+ jerry_value_t string_value = jerry_create_string ((const jerry_char_t *) "12345678");
+ jerry_value_t bigint_value = jerry_value_to_bigint (string_value);
+
+ jerry_release_value (string_value);
+
+ if (jerry_value_is_bigint (bigint_value))
+ {
+ // usage of bigint_value
+ }
+
+ jerry_release_value (bigint_value);
+
+ jerry_cleanup ();
+ return 0;
+}
+```
+
+**See also**
+
+- [jerry_release_value](#jerry_release_value)
+- [jerry_create_bigint](#jerry_create_bigint)
+- [jerry_value_to_bigint](#jerry_value_to_bigint)
+
+
## jerry_value_is_typedarray
**Summary**
@@ -3374,6 +3437,50 @@ jerry_value_to_string (const jerry_value_t value);
- [jerry_value_to_primitive](#jerry_value_to_primitive)
+## jerry_value_to_bigint
+
+**Summary**
+
+Call the BigInt constructor ecma builtin operation on the api value.
+
+*Note*: Returned value must be freed with [jerry_release_value](#jerry_release_value) when it
+is no longer needed.
+
+**Prototype**
+
+```c
+jerry_value_t
+jerry_value_to_bigint (const jerry_value_t value);
+```
+
+- `value` - api value
+- return value
+ - converted BigInt value, if success
+ - thrown error, otherwise
+
+*New in version [[NEXT_RELEASE]]*
+
+**Example**
+
+```c
+{
+ jerry_value_t value;
+ ... // create or acquire value
+
+ jerry_value_t bigint_value = jerry_value_to_bigint (value);
+
+ jerry_release_value (bigint_value);
+ jerry_release_value (value);
+}
+```
+
+**See also**
+
+- [jerry_release_value](#jerry_release_value)
+- [jerry_value_is_bigint](#jerry_value_is_bigint)
+- [jerry_get_bigint_digits](#jerry_get_bigint_digits)
+
+
# Functions for promise objects
These APIs all depend on the es.next profile (or on some build options).
@@ -3643,6 +3750,133 @@ main (void)
}
```
+# Functions for BigInts
+
+These APIs all depend on build option (`JERRY_BUILTIN_BIGINT`).
+
+## jerry_get_bigint_size_in_digits
+
+**Summary**
+
+Returns the size of uint64 digits of a BigInt value. This value is the
+minimum size of the buffer which can hold all digits of a BigInt value when
+the digits are retreived by `[jerry_get_bigint_digits](#jerry_get_bigint_digits)`.
+
+*Notes*:
+- This API depends on a build option (`JERRY_BUILTIN_BIGINT`) and can be checked
+ in runtime with the `JERRY_FEATURE_BIGINT` feature enum value,
+ see: [jerry_is_feature_enabled](#jerry_is_feature_enabled).
+- Returned value must be freed with [jerry_release_value](#jerry_release_value) when it
+ is no longer needed.
+
+**Prototype**
+
+```c
+uint32_t
+jerry_get_bigint_size_in_digits (jerry_value_t value)
+```
+
+- `value` - BigInt value
+- return value
+ - number of digits (can be zero for BigInt zero)
+ - if value is not a BigInt value, it returns with zero
+
+*New in version [[NEXT_RELEASE]]*
+
+**Example**
+
+[doctest]: # ()
+
+```c
+#include "jerryscript.h"
+
+int
+main (void)
+{
+ jerry_init (JERRY_INIT_EMPTY);
+
+ uint64_t digits[4] = { 0x1, 0x1, 0x0, 0x0 };
+ jerry_value_t bigint_value = jerry_create_bigint (digits, 4, true);
+
+ /* Prints two, because the leading zeroes in digits buffer are discarded. */
+ printf("size: %d\n", (int) jerry_get_bigint_size_in_digits (bigint_value));
+
+ jerry_release_value (bigint_value);
+
+ jerry_cleanup ();
+ return 0;
+}
+```
+
+**See also**
+
+- [jerry_value_is_bigint](#jerry_value_is_bigint)
+- [jerry_get_bigint_digits](#jerry_get_bigint_digits)
+
+
+## jerry_get_bigint_digits
+
+**Summary**
+
+Copies the uint64 digits of a BigInt value into a buffer. This function supports any
+buffer sizes. If the buffer size is smaller than the size returned by
+`[jerry_get_bigint_size_in_digits](#jerry_get_bigint_size_in_digits)`, only the
+least significant digits are copied into the buffer. If the buffer size is greater,
+the unused digits are filled with zero.
+
+*Notes*:
+- This API depends on a build option (`JERRY_BUILTIN_BIGINT`) and can be checked
+ in runtime with the `JERRY_FEATURE_BIGINT` feature enum value,
+ see: [jerry_is_feature_enabled](#jerry_is_feature_enabled).
+- Returned value must be freed with [jerry_release_value](#jerry_release_value) when it
+ is no longer needed.
+
+**Prototype**
+
+```c
+void
+jerry_get_bigint_digits (jerry_value_t value, uint64_t *digits_p, uint32_t size, bool *sign_p)
+```
+
+- `value` - BigInt value
+- `digits_p` - output buffer for digits
+- `size` - size of the output buffer
+- `sign_p` - the boolean passed to the function is set to false when the BigInt
+ is positive, and set to true otherwise (this parameter can be NULL)
+
+*New in version [[NEXT_RELEASE]]*
+
+**Example**
+
+[doctest]: # ()
+
+```c
+#include "jerryscript.h"
+
+int
+main (void)
+{
+ jerry_init (JERRY_INIT_EMPTY);
+
+ uint64_t digits[4] = { 0x1, 0x1, 0x0, 0x0 };
+ jerry_value_t bigint_value = jerry_create_bigint (digits, 4, true);
+
+ uint64_t get_digits[4];
+ bool sign;
+ jerry_get_bigint_digits (bigint_value, get_digits, 2, &sign);
+
+ jerry_release_value (bigint_value);
+
+ jerry_cleanup ();
+ return 0;
+}
+```
+
+**See also**
+
+- [jerry_value_is_bigint](#jerry_value_is_bigint)
+- [jerry_get_bigint_size_in_digits](#jerry_get_bigint_size_in_digits)
+
# Acquire and release API values
@@ -4716,6 +4950,65 @@ main (void)
- [jerry_release_value](#jerry_release_value)
+## jerry_create_bigint
+
+**Summary**
+
+Create BigInt value from uint64 digits
+
+*Note*:
+- This API depends on a build option (`JERRY_BUILTIN_BIGINT`) and can be checked
+ in runtime with the `JERRY_FEATURE_BIGINT` feature enum value,
+ see: [jerry_is_feature_enabled](#jerry_is_feature_enabled).
+- Returned value must be freed with [jerry_release_value](#jerry_release_value)
+ when it is no longer needed.
+
+**Prototype**
+
+```c
+jerry_value_t
+jerry_create_bigint (const uint64_t *digits_p, uint32_t size, bool sign)
+```
+
+- `digits_p` - array of uint64 digits, least significant digit first
+- `size` - size of the `digits_p` array
+- `sign` - false if the created value should be positive, and true if the created value should be negative
+- return value
+ - value of the created bigint, if success
+ - thrown error, otherwise
+
+*New in version [[NEXT_RELEASE]]*
+
+**Example**
+
+[doctest]: # ()
+
+```c
+#include "jerryscript.h"
+
+int
+main (void)
+{
+ jerry_init (JERRY_INIT_EMPTY);
+
+ uint64_t digits[2] = { 0x1, 0x1 };
+ jerry_value_t bigint_value = jerry_create_bigint (digits, 2, true);
+
+ // usage of bigint_value
+
+ jerry_release_value (bigint_value);
+
+ jerry_cleanup ();
+}
+```
+
+**See also**
+
+- [jerry_release_value](#jerry_release_value)
+- [jerry_value_is_bigint](#jerry_value_is_bigint)
+- [jerry_get_bigint_digits](#jerry_get_bigint_digits)
+
+
## jerry_create_regexp
**Summary**
diff --git a/jerry-core/api/jerry.c b/jerry-core/api/jerry.c
index 6a4423a7e..e870a7747 100644
--- a/jerry-core/api/jerry.c
+++ b/jerry-core/api/jerry.c
@@ -19,6 +19,7 @@
#include "ecma-alloc.h"
#include "ecma-array-object.h"
#include "ecma-arraybuffer-object.h"
+#include "ecma-bigint.h"
#include "ecma-builtin-helpers.h"
#include "ecma-builtins.h"
#include "ecma-comparison.h"
@@ -108,6 +109,15 @@ static const char * const error_value_msg_p = "argument cannot have an error fla
*/
static const char * const wrong_args_msg_p = "wrong type of argument";
+#if !ENABLED (JERRY_BUILTIN_BIGINT)
+
+/**
+ * Error message, if BigInt support is disabled
+ */
+static const char * const error_bigint_not_supported_p = "BigInt support is disabled";
+
+#endif /* !ENABLED (JERRY_BUILTIN_BIGINT) */
+
#endif /* ENABLED (JERRY_ERROR_MESSAGES) */
/** \addtogroup jerry Jerry engine interface
@@ -841,6 +851,25 @@ jerry_value_is_symbol (const jerry_value_t value) /**< api value */
#endif /* ENABLED (JERRY_ESNEXT) */
} /* jerry_value_is_symbol */
+/**
+ * Check if the specified value is BigInt.
+ *
+ * @return true - if the specified value is BigInt,
+ * false - otherwise
+ */
+bool
+jerry_value_is_bigint (const jerry_value_t value) /**< api value */
+{
+ jerry_assert_api_available ();
+
+#if ENABLED (JERRY_BUILTIN_BIGINT)
+ return ecma_is_value_bigint (value);
+#else /* !ENABLED (JERRY_BUILTIN_BIGINT) */
+ JERRY_UNUSED (value);
+ return false;
+#endif /* ENABLED (JERRY_BUILTIN_BIGINT) */
+} /* jerry_value_is_bigint */
+
/**
* Check if the specified value is undefined.
*
@@ -1345,9 +1374,36 @@ jerry_value_to_string (const jerry_value_t value) /**< input value */
return ecma_create_error_reference_from_context ();
}
- return jerry_return (ecma_make_string_value (str_p));
+ return ecma_make_string_value (str_p);
} /* jerry_value_to_string */
+/**
+ * Call the BigInt constructor ecma builtin operation on the api value.
+ *
+ * Note:
+ * returned value must be freed with jerry_release_value, when it is no longer needed.
+ *
+ * @return BigInt value - if success
+ * thrown error - otherwise
+ */
+jerry_value_t
+jerry_value_to_bigint (const jerry_value_t value) /**< input value */
+{
+ jerry_assert_api_available ();
+
+#if ENABLED (JERRY_BUILTIN_BIGINT)
+ if (ecma_is_value_error_reference (value))
+ {
+ return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (error_value_msg_p)));
+ }
+
+ return jerry_return (ecma_bigint_to_bigint (value, true));
+#else /* !ENABLED (JERRY_BUILTIN_BIGINT) */
+ JERRY_UNUSED (value);
+ return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (error_bigint_not_supported_p)));
+#endif /* ENABLED (JERRY_BUILTIN_BIGINT) */
+} /* jerry_value_to_bigint */
+
/**
* Acquire specified Jerry API value.
*
@@ -1776,6 +1832,29 @@ jerry_create_symbol (const jerry_value_t value) /**< api value */
#endif /* ENABLED (JERRY_ESNEXT) */
} /* jerry_create_symbol */
+/**
+ * Create BigInt from a sequence of uint64 digits
+ *
+ * @return value of the created bigint, if success
+ * thrown error, otherwise
+ */
+jerry_value_t
+jerry_create_bigint (const uint64_t *digits_p, /**< BigInt digits (lowest digit first) */
+ uint32_t size, /**< number of BigInt digits */
+ bool sign) /**< sign bit, true if the result should be negative */
+{
+ jerry_assert_api_available ();
+
+#if ENABLED (JERRY_BUILTIN_BIGINT)
+ return jerry_return (ecma_bigint_create_from_digits (digits_p, size, sign));
+#else /* !ENABLED (JERRY_BUILTIN_BIGINT) */
+ JERRY_UNUSED (digits_p);
+ JERRY_UNUSED (size);
+ JERRY_UNUSED (sign);
+ return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (error_bigint_not_supported_p)));
+#endif /* ENABLED (JERRY_BUILTIN_BIGINT) */
+} /* jerry_create_bigint */
+
/**
* Calculates the size of the given pattern and creates a RegExp object.
*
@@ -3405,6 +3484,60 @@ jerry_get_symbol_descriptive_string (const jerry_value_t symbol) /**< symbol val
#endif /* ENABLED (JERRY_ESNEXT) */
} /** jerry_get_symbol_descriptive_string */
+/**
+ * Get the number of uint64 digits of a BigInt value
+ *
+ * @return number of uint64 digits
+ */
+uint32_t
+jerry_get_bigint_size_in_digits (jerry_value_t value) /**< BigInt value */
+{
+ jerry_assert_api_available ();
+
+#if ENABLED (JERRY_BUILTIN_BIGINT)
+ if (!ecma_is_value_bigint (value))
+ {
+ return 0;
+ }
+
+ return ecma_bigint_get_size_in_digits (value);
+#else /* !ENABLED (JERRY_BUILTIN_BIGINT) */
+ JERRY_UNUSED (value);
+ return 0;
+#endif /* ENABLED (JERRY_BUILTIN_BIGINT) */
+} /* jerry_get_bigint_size_in_digits */
+
+/**
+ * Get the uint64 digits of a BigInt value (lowest digit first)
+ */
+void
+jerry_get_bigint_digits (jerry_value_t value, /**< BigInt value */
+ uint64_t *digits_p, /**< [out] buffer for digits */
+ uint32_t size, /**< buffer size in digits */
+ bool *sign_p) /**< [out] sign of BigInt */
+{
+#if ENABLED (JERRY_BUILTIN_BIGINT)
+ if (!ecma_is_value_bigint (value))
+ {
+ if (sign_p != NULL)
+ {
+ *sign_p = false;
+ }
+ memset (digits_p, 0, size * sizeof (uint64_t));
+ }
+
+ ecma_bigint_get_digits_and_sign (value, digits_p, size, sign_p);
+#else /* !ENABLED (JERRY_BUILTIN_BIGINT) */
+ JERRY_UNUSED (value);
+
+ if (sign_p != NULL)
+ {
+ *sign_p = false;
+ }
+ memset (digits_p, 0, size * sizeof (uint64_t));
+#endif /* ENABLED (JERRY_BUILTIN_BIGINT) */
+} /* jerry_get_bigint_digits */
+
/**
* Validate UTF-8 string
*
diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-bigint.c b/jerry-core/ecma/builtin-objects/ecma-builtin-bigint.c
index fcc06bfe4..d298873a1 100644
--- a/jerry-core/ecma/builtin-objects/ecma-builtin-bigint.c
+++ b/jerry-core/ecma/builtin-objects/ecma-builtin-bigint.c
@@ -51,37 +51,7 @@ ecma_builtin_bigint_dispatch_call (const ecma_value_t *arguments_list_p, /**< ar
JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL);
ecma_value_t value = (arguments_list_len == 0) ? ECMA_VALUE_UNDEFINED : arguments_list_p[0];
- bool free_value = false;
-
- if (ecma_is_value_object (value))
- {
- ecma_object_t *obj_p = ecma_get_object_from_value (value);
- value = ecma_op_object_default_value (obj_p, ECMA_PREFERRED_TYPE_NUMBER);
- free_value = true;
-
- if (ECMA_IS_VALUE_ERROR (value))
- {
- return value;
- }
- }
-
- ecma_value_t ret_value = ECMA_VALUE_EMPTY;
-
- if (ecma_is_value_number (value))
- {
- ret_value = ecma_bigint_number_to_bigint (ecma_get_number_from_value (value));
- }
- else
- {
- ret_value = ecma_bigint_to_bigint (value);
- }
-
- if (free_value)
- {
- ecma_free_value (value);
- }
-
- return ret_value;
+ return ecma_bigint_to_bigint (value, true);
} /* ecma_builtin_bigint_dispatch_call */
/**
diff --git a/jerry-core/ecma/operations/ecma-bigint.c b/jerry-core/ecma/operations/ecma-bigint.c
index b6d2d6d31..8cbc84479 100644
--- a/jerry-core/ecma/operations/ecma-bigint.c
+++ b/jerry-core/ecma/operations/ecma-bigint.c
@@ -17,6 +17,7 @@
#include "ecma-big-uint.h"
#include "ecma-exceptions.h"
#include "ecma-helpers.h"
+#include "ecma-objects.h"
#include "lit-char-helpers.h"
#if ENABLED (JERRY_BUILTIN_BIGINT)
@@ -340,7 +341,7 @@ ecma_bigint_number_to_digits (ecma_number_t number, /**< ecma number */
* @return ecma BigInt value or ECMA_VALUE_ERROR
* Returned value must be freed with ecma_free_value.
*/
-ecma_value_t
+static ecma_value_t
ecma_bigint_number_to_bigint (ecma_number_t number) /**< ecma number */
{
if (ecma_number_is_nan (number) || ecma_number_is_infinity (number))
@@ -397,34 +398,222 @@ ecma_bigint_number_to_bigint (ecma_number_t number) /**< ecma number */
* Returned value must be freed with ecma_free_value.
*/
ecma_value_t
-ecma_bigint_to_bigint (ecma_value_t value) /**< any value */
+ecma_bigint_to_bigint (ecma_value_t value, /**< any value */
+ bool allow_numbers) /**< converting ecma numbers is allowed */
{
- if (ecma_is_value_boolean (value))
- {
- if (ecma_is_value_false (value))
- {
- return ECMA_BIGINT_ZERO;
- }
+ bool free_value = false;
+ if (ecma_is_value_object (value))
+ {
+ value = ecma_op_object_default_value (ecma_get_object_from_value (value), ECMA_PREFERRED_TYPE_NUMBER);
+ free_value = true;
+
+ if (ECMA_IS_VALUE_ERROR (value))
+ {
+ return value;
+ }
+ }
+
+ ecma_value_t result;
+
+ if (ecma_is_value_string (value))
+ {
+ result = ecma_bigint_parse_string_value (value, ECMA_BIGINT_PARSE_NO_OPTIONS);
+ }
+ else if (ecma_is_value_bigint (value))
+ {
+ result = value;
+
+ if (!free_value && value != ECMA_BIGINT_ZERO)
+ {
+ ecma_ref_extended_primitive (ecma_get_extended_primitive_from_value (value));
+ }
+ else
+ {
+ free_value = false;
+ }
+ }
+ else if (allow_numbers && ecma_is_value_number (value))
+ {
+ result = ecma_bigint_number_to_bigint (ecma_get_number_from_value (value));
+ }
+ else if (ecma_is_value_false (value))
+ {
+ result = ECMA_BIGINT_ZERO;
+ }
+ else if (ecma_is_value_true (value))
+ {
ecma_extended_primitive_t *result_p = ecma_bigint_create (sizeof (ecma_bigint_digit_t));
- if (JERRY_UNLIKELY (result_p == NULL))
+ if (result_p != NULL)
{
- return ecma_bigint_raise_memory_error ();
+ *ECMA_BIGINT_GET_DIGITS (result_p, 0) = 1;
+ result = ecma_make_extended_primitive_value (result_p, ECMA_TYPE_BIGINT);
+ }
+ else
+ {
+ result = ecma_bigint_raise_memory_error ();
}
-
- *ECMA_BIGINT_GET_DIGITS (result_p, 0) = 1;
- return ecma_make_extended_primitive_value (result_p, ECMA_TYPE_BIGINT);
}
-
- if (!ecma_is_value_string (value))
+ else
{
- return ecma_raise_type_error (ECMA_ERR_MSG ("Value cannot be converted to BigInt"));
+ result = ecma_raise_type_error (ECMA_ERR_MSG ("Value cannot be converted to BigInt"));
}
- return ecma_bigint_parse_string_value (value, ECMA_BIGINT_PARSE_NO_OPTIONS);
+ if (free_value)
+ {
+ ecma_free_value (value);
+ }
+
+ return result;
} /* ecma_bigint_to_bigint */
+/**
+ * Create BigInt value from uint64 digits
+ *
+ * @return ecma BigInt value or ECMA_VALUE_ERROR
+ * Returned value must be freed with ecma_free_value.
+ */
+ecma_value_t
+ecma_bigint_create_from_digits (const uint64_t *digits_p, /**< BigInt digits */
+ uint32_t size, /**< number of BigInt digits */
+ bool sign) /**< sign bit, true if the result should be negative */
+{
+ const uint64_t *digits_end_p = digits_p + size;
+
+ while (digits_end_p > digits_p && digits_end_p[-1] == 0)
+ {
+ digits_end_p--;
+ }
+
+ if (digits_p == digits_end_p)
+ {
+ return ECMA_BIGINT_ZERO;
+ }
+
+ size = (uint32_t) (digits_end_p - digits_p);
+
+ if (size < ECMA_BIGINT_MAX_SIZE)
+ {
+ size *= (uint32_t) sizeof (uint64_t);
+ }
+
+ if ((digits_end_p[-1] >> (8 * sizeof (ecma_bigint_digit_t))) == 0)
+ {
+ size -= (uint32_t) sizeof (ecma_bigint_digit_t);
+ }
+
+ ecma_extended_primitive_t *result_value_p = ecma_bigint_create (size);
+
+ if (JERRY_UNLIKELY (result_value_p == NULL))
+ {
+ return ecma_bigint_raise_memory_error ();
+ }
+
+ if (sign)
+ {
+ result_value_p->u.bigint_sign_and_size |= ECMA_BIGINT_SIGN;
+ }
+
+ ecma_bigint_digit_t *result_p = ECMA_BIGINT_GET_DIGITS (result_value_p, 0);
+
+ while (digits_p < digits_end_p)
+ {
+ uint64_t digit = *digits_p++;
+
+ result_p[0] = (ecma_bigint_digit_t) digit;
+ result_p[1] = (ecma_bigint_digit_t) (digit >> (8 * sizeof (ecma_bigint_digit_t)));
+ result_p+= 2;
+ }
+
+ return ecma_make_extended_primitive_value (result_value_p, ECMA_TYPE_BIGINT);
+} /* ecma_bigint_create_from_digits */
+
+/**
+ * Get the number of uint64 digits of a BigInt value
+ *
+ * @return number of uint64 digits
+ */
+uint32_t
+ecma_bigint_get_size_in_digits (ecma_value_t value) /**< BigInt value */
+{
+ JERRY_ASSERT (ecma_is_value_bigint (value));
+
+ if (value == ECMA_BIGINT_ZERO)
+ {
+ return 0;
+ }
+
+ ecma_extended_primitive_t *value_p = ecma_get_extended_primitive_from_value (value);
+ uint32_t size = ECMA_BIGINT_GET_SIZE (value_p);
+
+ return (size + (uint32_t) sizeof (ecma_bigint_digit_t)) / sizeof (uint64_t);
+} /* ecma_bigint_get_size_in_digits */
+
+/**
+ * Get the uint64 digits of a BigInt value
+ */
+void
+ecma_bigint_get_digits_and_sign (ecma_value_t value, /**< BigInt value */
+ uint64_t *digits_p, /**< [out] buffer for digits */
+ uint32_t size, /**< buffer size in digits */
+ bool *sign_p) /**< [out] sign of BigInt */
+{
+ JERRY_ASSERT (ecma_is_value_bigint (value));
+
+ if (value == ECMA_BIGINT_ZERO)
+ {
+ if (sign_p != NULL)
+ {
+ *sign_p = false;
+ }
+ memset (digits_p, 0, size * sizeof (uint64_t));
+ return;
+ }
+
+ ecma_extended_primitive_t *value_p = ecma_get_extended_primitive_from_value (value);
+
+ if (sign_p != NULL)
+ {
+ *sign_p = (value_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN) != 0;
+ }
+
+ uint32_t bigint_size = ECMA_BIGINT_GET_SIZE (value_p);
+ uint32_t copy_size = bigint_size / sizeof (uint64_t);
+
+ if (copy_size > size)
+ {
+ copy_size = size;
+ }
+
+ const uint64_t *digits_end_p = digits_p + copy_size;
+ ecma_bigint_digit_t *source_p = ECMA_BIGINT_GET_DIGITS (value_p, 0);
+
+ while (digits_p < digits_end_p)
+ {
+ *digits_p++ = source_p[0] | (((uint64_t) source_p[1]) << (8 * sizeof (ecma_bigint_digit_t)));
+ source_p += 2;
+ }
+
+ size -= copy_size;
+
+ if (size == 0)
+ {
+ return;
+ }
+
+ if (ECMA_BIGINT_SIZE_IS_ODD (bigint_size))
+ {
+ *digits_p++ = source_p[0];
+ size--;
+ }
+
+ if (size > 0)
+ {
+ memset (digits_p, 0, size * sizeof (uint64_t));
+ }
+} /* ecma_bigint_get_digits_and_sign */
+
/**
* Compare two BigInt values
*
diff --git a/jerry-core/ecma/operations/ecma-bigint.h b/jerry-core/ecma/operations/ecma-bigint.h
index d617f16a3..014189f43 100644
--- a/jerry-core/ecma/operations/ecma-bigint.h
+++ b/jerry-core/ecma/operations/ecma-bigint.h
@@ -42,8 +42,10 @@ ecma_value_t ecma_bigint_parse_string (const lit_utf8_byte_t *string_p, lit_utf8
uint32_t options);
ecma_value_t ecma_bigint_parse_string_value (ecma_value_t string, uint32_t options);
ecma_string_t *ecma_bigint_to_string (ecma_value_t value, ecma_bigint_digit_t radix);
-ecma_value_t ecma_bigint_number_to_bigint (ecma_number_t number);
-ecma_value_t ecma_bigint_to_bigint (ecma_value_t value);
+ecma_value_t ecma_bigint_to_bigint (ecma_value_t value, bool allow_numbers);
+ecma_value_t ecma_bigint_create_from_digits (const uint64_t *digits_p, uint32_t size, bool sign);
+uint32_t ecma_bigint_get_size_in_digits (ecma_value_t value);
+void ecma_bigint_get_digits_and_sign (ecma_value_t value, uint64_t *digits_p, uint32_t size, bool *sign_p);
bool ecma_bigint_is_equal_to_bigint (ecma_value_t left_value, ecma_value_t right_value);
bool ecma_bigint_is_equal_to_number (ecma_value_t left_value, ecma_number_t right_value);
diff --git a/jerry-core/include/jerryscript-core.h b/jerry-core/include/jerryscript-core.h
index f88b01002..1db8611be 100644
--- a/jerry-core/include/jerryscript-core.h
+++ b/jerry-core/include/jerryscript-core.h
@@ -388,6 +388,7 @@ bool jerry_value_is_promise (const jerry_value_t value);
bool jerry_value_is_proxy (const jerry_value_t value);
bool jerry_value_is_string (const jerry_value_t value);
bool jerry_value_is_symbol (const jerry_value_t value);
+bool jerry_value_is_bigint (const jerry_value_t value);
bool jerry_value_is_undefined (const jerry_value_t value);
/**
@@ -474,6 +475,7 @@ jerry_value_t jerry_value_to_number (const jerry_value_t value);
jerry_value_t jerry_value_to_object (const jerry_value_t value);
jerry_value_t jerry_value_to_primitive (const jerry_value_t value);
jerry_value_t jerry_value_to_string (const jerry_value_t value);
+jerry_value_t jerry_value_to_bigint (const jerry_value_t value);
/**
* Acquire types with reference counter (increase the references).
@@ -512,6 +514,7 @@ jerry_value_t jerry_create_external_string (const jerry_char_t *str_p,
jerry_value_t jerry_create_external_string_sz (const jerry_char_t *str_p, jerry_size_t str_size,
jerry_object_native_free_callback_t free_cb);
jerry_value_t jerry_create_symbol (const jerry_value_t value);
+jerry_value_t jerry_create_bigint (const uint64_t *digits_p, uint32_t size, bool sign);
jerry_value_t jerry_create_undefined (void);
/**
@@ -595,6 +598,12 @@ jerry_promise_state_t jerry_get_promise_state (const jerry_value_t promise);
*/
jerry_value_t jerry_get_symbol_descriptive_string (const jerry_value_t symbol);
+/**
+ * BigInt functions.
+ */
+uint32_t jerry_get_bigint_size_in_digits (jerry_value_t value);
+void jerry_get_bigint_digits (jerry_value_t value, uint64_t *digits_p, uint32_t size, bool *sign_p);
+
/**
* Input validator functions.
*/
diff --git a/tests/test262-esnext-excludelist.xml b/tests/test262-esnext-excludelist.xml
index 234a6a712..9ada3426e 100644
--- a/tests/test262-esnext-excludelist.xml
+++ b/tests/test262-esnext-excludelist.xml
@@ -662,7 +662,6 @@
-
@@ -1097,7 +1096,6 @@
-
@@ -6833,7 +6831,6 @@
-
diff --git a/tests/unit-core/test-bigint.c b/tests/unit-core/test-bigint.c
new file mode 100644
index 000000000..3fb654d5b
--- /dev/null
+++ b/tests/unit-core/test-bigint.c
@@ -0,0 +1,186 @@
+/* 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 "jerryscript.h"
+#include "test-common.h"
+
+int
+main (void)
+{
+ if (!jerry_is_feature_enabled (JERRY_FEATURE_BIGINT))
+ {
+ jerry_port_log (JERRY_LOG_LEVEL_ERROR, "Bigint support is disabled!\n");
+ return 0;
+ }
+
+ jerry_init (JERRY_INIT_EMPTY);
+
+ jerry_value_t string = jerry_create_string ((const jerry_char_t *) "0xfffffff1fffffff2fffffff3");
+ TEST_ASSERT (!jerry_value_is_error (string));
+
+ jerry_value_t bigint = jerry_value_to_bigint (string);
+ jerry_release_value (string);
+
+ TEST_ASSERT (!jerry_value_is_error (bigint));
+ TEST_ASSERT (jerry_value_is_bigint (bigint));
+
+ string = jerry_value_to_string (bigint);
+ TEST_ASSERT (!jerry_value_is_error (string));
+
+ static jerry_char_t str_buffer[64];
+ const char *expected_string_p = "79228162256009920505775652851";
+
+ jerry_size_t size = jerry_string_to_char_buffer (string, str_buffer, sizeof (str_buffer));
+ TEST_ASSERT (size == strlen (expected_string_p));
+ TEST_ASSERT (memcmp (str_buffer, expected_string_p, size) == 0);
+ jerry_release_value (string);
+
+ TEST_ASSERT (jerry_get_bigint_size_in_digits (bigint) == 2);
+
+ uint64_t digits_buffer[4];
+ bool sign;
+
+ memset (digits_buffer, 0xff, sizeof (digits_buffer));
+ sign = true;
+ jerry_get_bigint_digits (bigint, digits_buffer, 0, &sign);
+ TEST_ASSERT (sign == false);
+ TEST_ASSERT (digits_buffer[0] == ~((uint64_t) 0));
+ TEST_ASSERT (digits_buffer[1] == ~((uint64_t) 0));
+ TEST_ASSERT (digits_buffer[2] == ~((uint64_t) 0));
+ TEST_ASSERT (digits_buffer[3] == ~((uint64_t) 0));
+
+ memset (digits_buffer, 0xff, sizeof (digits_buffer));
+ sign = true;
+ jerry_get_bigint_digits (bigint, digits_buffer, 1, &sign);
+ TEST_ASSERT (sign == false);
+ TEST_ASSERT (digits_buffer[0] == 0xfffffff2fffffff3ull);
+ TEST_ASSERT (digits_buffer[1] == ~((uint64_t) 0));
+ TEST_ASSERT (digits_buffer[2] == ~((uint64_t) 0));
+ TEST_ASSERT (digits_buffer[3] == ~((uint64_t) 0));
+
+ memset (digits_buffer, 0xff, sizeof (digits_buffer));
+ sign = true;
+ jerry_get_bigint_digits (bigint, digits_buffer, 2, &sign);
+ TEST_ASSERT (sign == false);
+ TEST_ASSERT (digits_buffer[0] == 0xfffffff2fffffff3ull);
+ TEST_ASSERT (digits_buffer[1] == 0xfffffff1ull);
+ TEST_ASSERT (digits_buffer[2] == ~((uint64_t) 0));
+ TEST_ASSERT (digits_buffer[3] == ~((uint64_t) 0));
+
+ memset (digits_buffer, 0xff, sizeof (digits_buffer));
+ sign = true;
+ jerry_get_bigint_digits (bigint, digits_buffer, 3, &sign);
+ TEST_ASSERT (sign == false);
+ TEST_ASSERT (digits_buffer[0] == 0xfffffff2fffffff3ull);
+ TEST_ASSERT (digits_buffer[1] == 0xfffffff1ull);
+ TEST_ASSERT (digits_buffer[2] == 0);
+ TEST_ASSERT (digits_buffer[3] == ~((uint64_t) 0));
+
+ memset (digits_buffer, 0xff, sizeof (digits_buffer));
+ jerry_get_bigint_digits (bigint, digits_buffer, 4, NULL);
+ TEST_ASSERT (digits_buffer[0] == 0xfffffff2fffffff3ull);
+ TEST_ASSERT (digits_buffer[1] == 0xfffffff1ull);
+ TEST_ASSERT (digits_buffer[2] == 0);
+ TEST_ASSERT (digits_buffer[3] == 0);
+
+ jerry_release_value (bigint);
+
+ digits_buffer[0] = 0;
+ digits_buffer[1] = 0;
+ digits_buffer[2] = 0;
+ /* Sign of zero value is always positive, even if we set negative. */
+ bigint = jerry_create_bigint (digits_buffer, 3, true);
+ TEST_ASSERT (jerry_value_is_bigint (bigint));
+ TEST_ASSERT (jerry_get_bigint_size_in_digits (bigint) == 0);
+
+ memset (digits_buffer, 0xff, sizeof (digits_buffer));
+ sign = true;
+ jerry_get_bigint_digits (bigint, digits_buffer, 2, &sign);
+ TEST_ASSERT (sign == false);
+ TEST_ASSERT (digits_buffer[0] == 0);
+ TEST_ASSERT (digits_buffer[1] == 0);
+ TEST_ASSERT (digits_buffer[2] == ~((uint64_t) 0));
+ TEST_ASSERT (digits_buffer[3] == ~((uint64_t) 0));
+
+ jerry_release_value (bigint);
+
+ digits_buffer[0] = 1;
+ digits_buffer[1] = 0;
+ digits_buffer[2] = 0;
+ digits_buffer[3] = 0;
+ bigint = jerry_create_bigint (digits_buffer, 4, true);
+ TEST_ASSERT (jerry_value_is_bigint (bigint));
+ TEST_ASSERT (jerry_get_bigint_size_in_digits (bigint) == 1);
+
+ memset (digits_buffer, 0xff, sizeof (digits_buffer));
+ sign = false;
+ jerry_get_bigint_digits (bigint, digits_buffer, 1, &sign);
+ TEST_ASSERT (sign == true);
+ TEST_ASSERT (digits_buffer[0] == 1);
+ TEST_ASSERT (digits_buffer[1] == ~((uint64_t) 0));
+ TEST_ASSERT (digits_buffer[2] == ~((uint64_t) 0));
+ TEST_ASSERT (digits_buffer[3] == ~((uint64_t) 0));
+
+ memset (digits_buffer, 0xff, sizeof (digits_buffer));
+ sign = false;
+ jerry_get_bigint_digits (bigint, digits_buffer, 2, &sign);
+ TEST_ASSERT (sign == true);
+ TEST_ASSERT (digits_buffer[0] == 1);
+ TEST_ASSERT (digits_buffer[1] == 0);
+ TEST_ASSERT (digits_buffer[2] == ~((uint64_t) 0));
+ TEST_ASSERT (digits_buffer[3] == ~((uint64_t) 0));
+
+ jerry_release_value (bigint);
+
+ digits_buffer[0] = 0;
+ digits_buffer[1] = 1;
+ digits_buffer[2] = 0;
+ digits_buffer[3] = 0;
+ bigint = jerry_create_bigint (digits_buffer, 4, true);
+ TEST_ASSERT (jerry_value_is_bigint (bigint));
+ TEST_ASSERT (jerry_get_bigint_size_in_digits (bigint) == 2);
+
+ memset (digits_buffer, 0xff, sizeof (digits_buffer));
+ sign = false;
+ jerry_get_bigint_digits (bigint, digits_buffer, 1, &sign);
+ TEST_ASSERT (sign == true);
+ TEST_ASSERT (digits_buffer[0] == 0);
+ TEST_ASSERT (digits_buffer[1] == ~((uint64_t) 0));
+ TEST_ASSERT (digits_buffer[2] == ~((uint64_t) 0));
+ TEST_ASSERT (digits_buffer[3] == ~((uint64_t) 0));
+
+ memset (digits_buffer, 0xff, sizeof (digits_buffer));
+ sign = false;
+ jerry_get_bigint_digits (bigint, digits_buffer, 2, &sign);
+ TEST_ASSERT (sign == true);
+ TEST_ASSERT (digits_buffer[0] == 0);
+ TEST_ASSERT (digits_buffer[1] == 1);
+ TEST_ASSERT (digits_buffer[2] == ~((uint64_t) 0));
+ TEST_ASSERT (digits_buffer[3] == ~((uint64_t) 0));
+
+ memset (digits_buffer, 0xff, sizeof (digits_buffer));
+ sign = false;
+ jerry_get_bigint_digits (bigint, digits_buffer, 3, &sign);
+ TEST_ASSERT (sign == true);
+ TEST_ASSERT (digits_buffer[0] == 0);
+ TEST_ASSERT (digits_buffer[1] == 1);
+ TEST_ASSERT (digits_buffer[2] == 0);
+ TEST_ASSERT (digits_buffer[3] == ~((uint64_t) 0));
+
+ jerry_release_value (bigint);
+
+ jerry_cleanup ();
+ return 0;
+} /* main */