napi: add bigint support
PR-URL: https://github.com/nodejs/node/pull/21226 Reviewed-By: Gabriel Schulhof <gabriel.schulhof@intel.com> Reviewed-By: Kyle Farnung <kfarnung@microsoft.com>
This commit is contained in:
parent
d85449dcdf
commit
1849a2b2e9
164
doc/api/n-api.md
164
doc/api/n-api.md
@ -113,10 +113,9 @@ typedef enum {
|
||||
napi_escape_called_twice,
|
||||
napi_handle_scope_mismatch,
|
||||
napi_callback_scope_mismatch,
|
||||
#ifdef NAPI_EXPERIMENTAL
|
||||
napi_queue_full,
|
||||
napi_closing,
|
||||
#endif // NAPI_EXPERIMENTAL
|
||||
napi_bigint_expected,
|
||||
} napi_status;
|
||||
```
|
||||
If additional information is required upon an API returning a failed status,
|
||||
@ -1225,6 +1224,7 @@ typedef enum {
|
||||
napi_object,
|
||||
napi_function,
|
||||
napi_external,
|
||||
napi_bigint,
|
||||
} napi_valuetype;
|
||||
```
|
||||
|
||||
@ -1250,6 +1250,8 @@ typedef enum {
|
||||
napi_uint32_array,
|
||||
napi_float32_array,
|
||||
napi_float64_array,
|
||||
napi_bigint64_array,
|
||||
napi_biguint64_array,
|
||||
} napi_typedarray_type;
|
||||
```
|
||||
|
||||
@ -1691,6 +1693,78 @@ This API is used to convert from the C `double` type to the JavaScript
|
||||
The JavaScript `Number` type is described in
|
||||
[Section 6.1.6][] of the ECMAScript Language Specification.
|
||||
|
||||
#### napi_create_bigint_int64
|
||||
<!-- YAML
|
||||
added: REPLACEME
|
||||
-->
|
||||
|
||||
> Stability: 1 - Experimental
|
||||
|
||||
```C
|
||||
napi_status napi_create_bigint_int64(napi_env env,
|
||||
int64_t value,
|
||||
napi_value* result);
|
||||
```
|
||||
|
||||
- `[in] env`: The environment that the API is invoked under.
|
||||
- `[in] value`: Integer value to be represented in JavaScript.
|
||||
- `[out] result`: A `napi_value` representing a JavaScript `BigInt`.
|
||||
|
||||
Returns `napi_ok` if the API succeeded.
|
||||
|
||||
This API converts the C `int64_t` type to the JavaScript `BigInt` type.
|
||||
|
||||
#### napi_create_bigint_uint64
|
||||
<!-- YAML
|
||||
added: REPLACEME
|
||||
-->
|
||||
|
||||
> Stability: 1 - Experimental
|
||||
|
||||
```C
|
||||
napi_status napi_create_bigint_uint64(napi_env env,
|
||||
uint64_t vaue,
|
||||
napi_value* result);
|
||||
```
|
||||
|
||||
- `[in] env`: The environment that the API is invoked under.
|
||||
- `[in] value`: Unsigned integer value to be represented in JavaScript.
|
||||
- `[out] result`: A `napi_value` representing a JavaScript `BigInt`.
|
||||
|
||||
Returns `napi_ok` if the API succeeded.
|
||||
|
||||
This API converts the C `uint64_t` type to the JavaScript `BigInt` type.
|
||||
|
||||
#### napi_create_bigint_words
|
||||
<!-- YAML
|
||||
added: REPLACEME
|
||||
-->
|
||||
|
||||
> Stability: 1 - Experimental
|
||||
|
||||
```C
|
||||
napi_status napi_create_bigint_words(napi_env env,
|
||||
int sign_bit,
|
||||
size_t word_count,
|
||||
const uint64_t* words,
|
||||
napi_value* result);
|
||||
```
|
||||
|
||||
- `[in] env`: The environment that the API is invoked under.
|
||||
- `[in] sign_bit`: Determines if the resulting `BigInt` will be positive or
|
||||
negative.
|
||||
- `[in] word_count`: The length of the `words` array.
|
||||
- `[in] words`: An array of `uint64_t` little-endian 64-bit words.
|
||||
- `[out] result`: A `napi_value` representing a JavaScript `BigInt`.
|
||||
|
||||
Returns `napi_ok` if the API succeeded.
|
||||
|
||||
This API converts an array of unsigned 64-bit words into a single `BigInt`
|
||||
value.
|
||||
|
||||
The resulting `BigInt` is calculated as: (–1)<sup>`sign_bit`</sup> (`words[0]`
|
||||
× (2<sup>64</sup>)<sup>0</sup> + `words[1]` × (2<sup>64</sup>)<sup>1</sup> + …)
|
||||
|
||||
#### napi_create_string_latin1
|
||||
<!-- YAML
|
||||
added: v8.0.0
|
||||
@ -1975,6 +2049,92 @@ in it returns `napi_number_expected`.
|
||||
This API returns the C double primitive equivalent of the given JavaScript
|
||||
`Number`.
|
||||
|
||||
#### napi_get_value_bigint_int64
|
||||
<!-- YAML
|
||||
added: REPLACEME
|
||||
-->
|
||||
|
||||
> Stability: 1 - Experimental
|
||||
|
||||
```C
|
||||
napi_status napi_get_value_bigint_int64(napi_env env,
|
||||
napi_value value,
|
||||
int64_t* result,
|
||||
bool* lossless);
|
||||
```
|
||||
|
||||
- `[in] env`: The environment that the API is invoked under
|
||||
- `[in] value`: `napi_value` representing JavaScript `BigInt`.
|
||||
- `[out] result`: C `int64_t` primitive equivalent of the given JavaScript
|
||||
`BigInt`.
|
||||
- `[out] lossless`: Indicates whether the `BigInt` value was converted
|
||||
losslessly.
|
||||
|
||||
Returns `napi_ok` if the API succeeded. If a non-`BigInt` is passed in it
|
||||
returns `napi_bigint_expected`.
|
||||
|
||||
This API returns the C `int64_t` primitive equivalent of the given JavaScript
|
||||
`BigInt`. If needed it will truncate the value, setting `lossless` to `false`.
|
||||
|
||||
|
||||
#### napi_get_value_bigint_uint64
|
||||
<!-- YAML
|
||||
added: REPLACEME
|
||||
-->
|
||||
|
||||
> Stability: 1 - Experimental
|
||||
|
||||
```C
|
||||
napi_status napi_get_value_bigint_uint64(napi_env env,
|
||||
napi_value value,
|
||||
uint64_t* result,
|
||||
bool* lossless);
|
||||
```
|
||||
|
||||
- `[in] env`: The environment that the API is invoked under.
|
||||
- `[in] value`: `napi_value` representing JavaScript `BigInt`.
|
||||
- `[out] result`: C `uint64_t` primitive equivalent of the given JavaScript
|
||||
`BigInt`.
|
||||
- `[out] lossless`: Indicates whether the `BigInt` value was converted
|
||||
losslessly.
|
||||
|
||||
Returns `napi_ok` if the API succeeded. If a non-`BigInt` is passed in it
|
||||
returns `napi_bigint_expected`.
|
||||
|
||||
This API returns the C `uint64_t` primitive equivalent of the given JavaScript
|
||||
`BigInt`. If needed it will truncate the value, setting `lossless` to `false`.
|
||||
|
||||
|
||||
#### napi_get_value_bigint_words
|
||||
<!-- YAML
|
||||
added: REPLACEME
|
||||
-->
|
||||
|
||||
> Stability: 1 - Experimental
|
||||
|
||||
```C
|
||||
napi_status napi_get_value_bigint_words(napi_env env,
|
||||
napi_value value,
|
||||
size_t* word_count,
|
||||
int* sign_bit,
|
||||
uint64_t* words);
|
||||
```
|
||||
|
||||
- `[in] env`: The environment that the API is invoked under.
|
||||
- `[in] value`: `napi_value` representing JavaScript `BigInt`.
|
||||
- `[out] sign_bit`: Integer representing if the JavaScript `BigInt` is positive
|
||||
or negative.
|
||||
- `[in/out] word_count`: Must be initialized to the length of the `words`
|
||||
array. Upon return, it will be set to the actual number of words that
|
||||
would be needed to store this `BigInt`.
|
||||
- `[out] words`: Pointer to a pre-allocated 64-bit word array.
|
||||
|
||||
Returns `napi_ok` if the API succeeded.
|
||||
|
||||
This API converts a single `BigInt` value into a sign bit, 64-bit little-endian
|
||||
array, and the number of elements in the array. `sign_bit` and `words` may be
|
||||
both set to `NULL`, in order to get only `word_count`.
|
||||
|
||||
#### napi_get_value_external
|
||||
<!-- YAML
|
||||
added: v8.0.0
|
||||
|
137
src/node_api.cc
137
src/node_api.cc
@ -926,7 +926,8 @@ const char* error_messages[] = {nullptr,
|
||||
"Invalid handle scope usage",
|
||||
"Invalid callback scope usage",
|
||||
"Thread-safe function queue is full",
|
||||
"Thread-safe function handle is closing"
|
||||
"Thread-safe function handle is closing",
|
||||
"A bigint was expected",
|
||||
};
|
||||
|
||||
static inline napi_status napi_clear_last_error(napi_env env) {
|
||||
@ -958,7 +959,7 @@ napi_status napi_get_last_error_info(napi_env env,
|
||||
// We don't have a napi_status_last as this would result in an ABI
|
||||
// change each time a message was added.
|
||||
static_assert(
|
||||
node::arraysize(error_messages) == napi_closing + 1,
|
||||
node::arraysize(error_messages) == napi_bigint_expected + 1,
|
||||
"Count of error messages must match count of error values");
|
||||
CHECK_LE(env->last_error.error_code, napi_callback_scope_mismatch);
|
||||
|
||||
@ -1713,6 +1714,58 @@ napi_status napi_create_int64(napi_env env,
|
||||
return napi_clear_last_error(env);
|
||||
}
|
||||
|
||||
napi_status napi_create_bigint_int64(napi_env env,
|
||||
int64_t value,
|
||||
napi_value* result) {
|
||||
CHECK_ENV(env);
|
||||
CHECK_ARG(env, result);
|
||||
|
||||
*result = v8impl::JsValueFromV8LocalValue(
|
||||
v8::BigInt::New(env->isolate, value));
|
||||
|
||||
return napi_clear_last_error(env);
|
||||
}
|
||||
|
||||
napi_status napi_create_bigint_uint64(napi_env env,
|
||||
uint64_t value,
|
||||
napi_value* result) {
|
||||
CHECK_ENV(env);
|
||||
CHECK_ARG(env, result);
|
||||
|
||||
*result = v8impl::JsValueFromV8LocalValue(
|
||||
v8::BigInt::NewFromUnsigned(env->isolate, value));
|
||||
|
||||
return napi_clear_last_error(env);
|
||||
}
|
||||
|
||||
napi_status napi_create_bigint_words(napi_env env,
|
||||
int sign_bit,
|
||||
size_t word_count,
|
||||
const uint64_t* words,
|
||||
napi_value* result) {
|
||||
NAPI_PREAMBLE(env);
|
||||
CHECK_ARG(env, words);
|
||||
CHECK_ARG(env, result);
|
||||
|
||||
v8::Local<v8::Context> context = env->isolate->GetCurrentContext();
|
||||
|
||||
if (word_count > INT_MAX) {
|
||||
napi_throw_range_error(env, nullptr, "Maximum BigInt size exceeded");
|
||||
return napi_set_last_error(env, napi_pending_exception);
|
||||
}
|
||||
|
||||
v8::MaybeLocal<v8::BigInt> b = v8::BigInt::NewFromWords(
|
||||
context, sign_bit, word_count, words);
|
||||
|
||||
if (try_catch.HasCaught()) {
|
||||
return napi_set_last_error(env, napi_pending_exception);
|
||||
} else {
|
||||
CHECK_MAYBE_EMPTY(env, b, napi_generic_failure);
|
||||
*result = v8impl::JsValueFromV8LocalValue(b.ToLocalChecked());
|
||||
return napi_clear_last_error(env);
|
||||
}
|
||||
}
|
||||
|
||||
napi_status napi_get_boolean(napi_env env, bool value, napi_value* result) {
|
||||
CHECK_ENV(env);
|
||||
CHECK_ARG(env, result);
|
||||
@ -1878,6 +1931,8 @@ napi_status napi_typeof(napi_env env,
|
||||
|
||||
if (v->IsNumber()) {
|
||||
*result = napi_number;
|
||||
} else if (v->IsBigInt()) {
|
||||
*result = napi_bigint;
|
||||
} else if (v->IsString()) {
|
||||
*result = napi_string;
|
||||
} else if (v->IsFunction()) {
|
||||
@ -2201,6 +2256,72 @@ napi_status napi_get_value_int64(napi_env env,
|
||||
return napi_clear_last_error(env);
|
||||
}
|
||||
|
||||
napi_status napi_get_value_bigint_int64(napi_env env,
|
||||
napi_value value,
|
||||
int64_t* result,
|
||||
bool* lossless) {
|
||||
CHECK_ENV(env);
|
||||
CHECK_ARG(env, value);
|
||||
CHECK_ARG(env, result);
|
||||
CHECK_ARG(env, lossless);
|
||||
|
||||
v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
|
||||
|
||||
RETURN_STATUS_IF_FALSE(env, val->IsBigInt(), napi_bigint_expected);
|
||||
|
||||
*result = val.As<v8::BigInt>()->Int64Value(lossless);
|
||||
|
||||
return napi_clear_last_error(env);
|
||||
}
|
||||
|
||||
napi_status napi_get_value_bigint_uint64(napi_env env,
|
||||
napi_value value,
|
||||
uint64_t* result,
|
||||
bool* lossless) {
|
||||
CHECK_ENV(env);
|
||||
CHECK_ARG(env, value);
|
||||
CHECK_ARG(env, result);
|
||||
CHECK_ARG(env, lossless);
|
||||
|
||||
v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
|
||||
|
||||
RETURN_STATUS_IF_FALSE(env, val->IsBigInt(), napi_bigint_expected);
|
||||
|
||||
*result = val.As<v8::BigInt>()->Uint64Value(lossless);
|
||||
|
||||
return napi_clear_last_error(env);
|
||||
}
|
||||
|
||||
napi_status napi_get_value_bigint_words(napi_env env,
|
||||
napi_value value,
|
||||
int* sign_bit,
|
||||
size_t* word_count,
|
||||
uint64_t* words) {
|
||||
CHECK_ENV(env);
|
||||
CHECK_ARG(env, value);
|
||||
CHECK_ARG(env, word_count);
|
||||
|
||||
v8::Local<v8::Value> val = v8impl::V8LocalValueFromJsValue(value);
|
||||
|
||||
RETURN_STATUS_IF_FALSE(env, val->IsBigInt(), napi_bigint_expected);
|
||||
|
||||
v8::Local<v8::BigInt> big = val.As<v8::BigInt>();
|
||||
|
||||
int word_count_int = *word_count;
|
||||
|
||||
if (sign_bit == nullptr && words == nullptr) {
|
||||
word_count_int = big->WordCount();
|
||||
} else {
|
||||
CHECK_ARG(env, sign_bit);
|
||||
CHECK_ARG(env, words);
|
||||
big->ToWordsArray(sign_bit, &word_count_int, words);
|
||||
}
|
||||
|
||||
*word_count = word_count_int;
|
||||
|
||||
return napi_clear_last_error(env);
|
||||
}
|
||||
|
||||
napi_status napi_get_value_bool(napi_env env, napi_value value, bool* result) {
|
||||
// Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw
|
||||
// JS exceptions.
|
||||
@ -3139,6 +3260,14 @@ napi_status napi_create_typedarray(napi_env env,
|
||||
CREATE_TYPED_ARRAY(
|
||||
env, Float64Array, 8, buffer, byte_offset, length, typedArray);
|
||||
break;
|
||||
case napi_bigint64_array:
|
||||
CREATE_TYPED_ARRAY(
|
||||
env, BigInt64Array, 8, buffer, byte_offset, length, typedArray);
|
||||
break;
|
||||
case napi_biguint64_array:
|
||||
CREATE_TYPED_ARRAY(
|
||||
env, BigUint64Array, 8, buffer, byte_offset, length, typedArray);
|
||||
break;
|
||||
default:
|
||||
return napi_set_last_error(env, napi_invalid_arg);
|
||||
}
|
||||
@ -3181,6 +3310,10 @@ napi_status napi_get_typedarray_info(napi_env env,
|
||||
*type = napi_float32_array;
|
||||
} else if (value->IsFloat64Array()) {
|
||||
*type = napi_float64_array;
|
||||
} else if (value->IsBigInt64Array()) {
|
||||
*type = napi_bigint64_array;
|
||||
} else if (value->IsBigUint64Array()) {
|
||||
*type = napi_biguint64_array;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -671,6 +671,30 @@ napi_unref_threadsafe_function(napi_env env, napi_threadsafe_function func);
|
||||
NAPI_EXTERN napi_status
|
||||
napi_ref_threadsafe_function(napi_env env, napi_threadsafe_function func);
|
||||
|
||||
NAPI_EXTERN napi_status napi_create_bigint_int64(napi_env env,
|
||||
int64_t value,
|
||||
napi_value* result);
|
||||
NAPI_EXTERN napi_status napi_create_bigint_uint64(napi_env env,
|
||||
uint64_t value,
|
||||
napi_value* result);
|
||||
NAPI_EXTERN napi_status napi_create_bigint_words(napi_env env,
|
||||
int sign_bit,
|
||||
size_t word_count,
|
||||
const uint64_t* words,
|
||||
napi_value* result);
|
||||
NAPI_EXTERN napi_status napi_get_value_bigint_int64(napi_env env,
|
||||
napi_value value,
|
||||
int64_t* result,
|
||||
bool* lossless);
|
||||
NAPI_EXTERN napi_status napi_get_value_bigint_uint64(napi_env env,
|
||||
napi_value value,
|
||||
uint64_t* result,
|
||||
bool* lossless);
|
||||
NAPI_EXTERN napi_status napi_get_value_bigint_words(napi_env env,
|
||||
napi_value value,
|
||||
int* sign_bit,
|
||||
size_t* word_count,
|
||||
uint64_t* words);
|
||||
#endif // NAPI_EXPERIMENTAL
|
||||
|
||||
EXTERN_C_END
|
||||
|
@ -46,6 +46,7 @@ typedef enum {
|
||||
napi_object,
|
||||
napi_function,
|
||||
napi_external,
|
||||
napi_bigint,
|
||||
} napi_valuetype;
|
||||
|
||||
typedef enum {
|
||||
@ -58,6 +59,8 @@ typedef enum {
|
||||
napi_uint32_array,
|
||||
napi_float32_array,
|
||||
napi_float64_array,
|
||||
napi_bigint64_array,
|
||||
napi_biguint64_array,
|
||||
} napi_typedarray_type;
|
||||
|
||||
typedef enum {
|
||||
@ -78,6 +81,7 @@ typedef enum {
|
||||
napi_callback_scope_mismatch,
|
||||
napi_queue_full,
|
||||
napi_closing,
|
||||
napi_bigint_expected,
|
||||
} napi_status;
|
||||
|
||||
#ifdef NAPI_EXPERIMENTAL
|
||||
|
8
test/addons-napi/test_bigint/binding.gyp
Normal file
8
test/addons-napi/test_bigint/binding.gyp
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"targets": [
|
||||
{
|
||||
"target_name": "test_bigint",
|
||||
"sources": [ "test_bigint.c" ]
|
||||
}
|
||||
]
|
||||
}
|
45
test/addons-napi/test_bigint/test.js
Normal file
45
test/addons-napi/test_bigint/test.js
Normal file
@ -0,0 +1,45 @@
|
||||
'use strict';
|
||||
const common = require('../../common');
|
||||
const assert = require('assert');
|
||||
const {
|
||||
IsLossless,
|
||||
TestInt64,
|
||||
TestUint64,
|
||||
TestWords,
|
||||
CreateTooBigBigInt,
|
||||
} = require(`./build/${common.buildType}/test_bigint`);
|
||||
|
||||
[
|
||||
0n,
|
||||
-0n,
|
||||
1n,
|
||||
-1n,
|
||||
100n,
|
||||
2121n,
|
||||
-1233n,
|
||||
986583n,
|
||||
-976675n,
|
||||
98765432213456789876546896323445679887645323232436587988766545658n,
|
||||
-4350987086545760976737453646576078997096876957864353245245769809n,
|
||||
].forEach((num) => {
|
||||
if (num > -(2n ** 63n) && num < 2n ** 63n) {
|
||||
assert.strictEqual(TestInt64(num), num);
|
||||
assert.strictEqual(IsLossless(num, true), true);
|
||||
} else {
|
||||
assert.strictEqual(IsLossless(num, true), false);
|
||||
}
|
||||
|
||||
if (num >= 0 && num < 2n ** 64n) {
|
||||
assert.strictEqual(TestUint64(num), num);
|
||||
assert.strictEqual(IsLossless(num, false), true);
|
||||
} else {
|
||||
assert.strictEqual(IsLossless(num, false), false);
|
||||
}
|
||||
|
||||
assert.strictEqual(num, TestWords(num));
|
||||
});
|
||||
|
||||
assert.throws(CreateTooBigBigInt, {
|
||||
name: 'RangeError',
|
||||
message: 'Maximum BigInt size exceeded',
|
||||
});
|
142
test/addons-napi/test_bigint/test_bigint.c
Normal file
142
test/addons-napi/test_bigint/test_bigint.c
Normal file
@ -0,0 +1,142 @@
|
||||
#define NAPI_EXPERIMENTAL
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include <node_api.h>
|
||||
#include "../common.h"
|
||||
|
||||
static napi_value IsLossless(napi_env env, napi_callback_info info) {
|
||||
size_t argc = 2;
|
||||
napi_value args[2];
|
||||
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, &args, NULL, NULL));
|
||||
|
||||
bool is_signed;
|
||||
NAPI_CALL(env, napi_get_value_bool(env, args[1], &is_signed));
|
||||
|
||||
bool lossless;
|
||||
|
||||
if (is_signed) {
|
||||
int64_t input;
|
||||
NAPI_CALL(env, napi_get_value_bigint_int64(env, args[0], &input, &lossless));
|
||||
} else {
|
||||
uint64_t input;
|
||||
NAPI_CALL(env, napi_get_value_bigint_uint64(env, args[0], &input, &lossless));
|
||||
}
|
||||
|
||||
napi_value output;
|
||||
NAPI_CALL(env, napi_get_boolean(env, lossless, &output));
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
static napi_value TestInt64(napi_env env, napi_callback_info info) {
|
||||
size_t argc = 1;
|
||||
napi_value args[1];
|
||||
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
|
||||
|
||||
NAPI_ASSERT(env, argc >= 1, "Wrong number of arguments");
|
||||
|
||||
napi_valuetype valuetype0;
|
||||
NAPI_CALL(env, napi_typeof(env, args[0], &valuetype0));
|
||||
|
||||
NAPI_ASSERT(env, valuetype0 == napi_bigint,
|
||||
"Wrong type of arguments. Expects a bigint as first argument.");
|
||||
|
||||
int64_t input;
|
||||
bool lossless;
|
||||
NAPI_CALL(env, napi_get_value_bigint_int64(env, args[0], &input, &lossless));
|
||||
|
||||
napi_value output;
|
||||
NAPI_CALL(env, napi_create_bigint_int64(env, input, &output));
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
static napi_value TestUint64(napi_env env, napi_callback_info info) {
|
||||
size_t argc = 1;
|
||||
napi_value args[1];
|
||||
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
|
||||
|
||||
NAPI_ASSERT(env, argc >= 1, "Wrong number of arguments");
|
||||
|
||||
napi_valuetype valuetype0;
|
||||
NAPI_CALL(env, napi_typeof(env, args[0], &valuetype0));
|
||||
|
||||
NAPI_ASSERT(env, valuetype0 == napi_bigint,
|
||||
"Wrong type of arguments. Expects a bigint as first argument.");
|
||||
|
||||
uint64_t input;
|
||||
bool lossless;
|
||||
NAPI_CALL(env, napi_get_value_bigint_uint64(
|
||||
env, args[0], &input, &lossless));
|
||||
|
||||
napi_value output;
|
||||
NAPI_CALL(env, napi_create_bigint_uint64(env, input, &output));
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
static napi_value TestWords(napi_env env, napi_callback_info info) {
|
||||
size_t argc = 1;
|
||||
napi_value args[1];
|
||||
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
|
||||
|
||||
NAPI_ASSERT(env, argc >= 1, "Wrong number of arguments");
|
||||
|
||||
napi_valuetype valuetype0;
|
||||
NAPI_CALL(env, napi_typeof(env, args[0], &valuetype0));
|
||||
|
||||
NAPI_ASSERT(env, valuetype0 == napi_bigint,
|
||||
"Wrong type of arguments. Expects a bigint as first argument.");
|
||||
|
||||
size_t expected_word_count;
|
||||
NAPI_CALL(env, napi_get_value_bigint_words(
|
||||
env, args[0], NULL, &expected_word_count, NULL));
|
||||
|
||||
int sign_bit;
|
||||
size_t word_count = 10;
|
||||
uint64_t words[10];
|
||||
|
||||
NAPI_CALL(env, napi_get_value_bigint_words(
|
||||
env, args[0], &sign_bit, &word_count, &words));
|
||||
|
||||
NAPI_ASSERT(env, word_count == expected_word_count,
|
||||
"word counts do not match");
|
||||
|
||||
napi_value output;
|
||||
NAPI_CALL(env, napi_create_bigint_words(
|
||||
env, sign_bit, word_count, words, &output));
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
// throws RangeError
|
||||
static napi_value CreateTooBigBigInt(napi_env env, napi_callback_info info) {
|
||||
int sign_bit = 0;
|
||||
size_t word_count = SIZE_MAX;
|
||||
uint64_t words[10];
|
||||
|
||||
napi_value output;
|
||||
|
||||
NAPI_CALL(env, napi_create_bigint_words(
|
||||
env, sign_bit, word_count, words, &output));
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
static napi_value Init(napi_env env, napi_value exports) {
|
||||
napi_property_descriptor descriptors[] = {
|
||||
DECLARE_NAPI_PROPERTY("IsLossless", IsLossless),
|
||||
DECLARE_NAPI_PROPERTY("TestInt64", TestInt64),
|
||||
DECLARE_NAPI_PROPERTY("TestUint64", TestUint64),
|
||||
DECLARE_NAPI_PROPERTY("TestWords", TestWords),
|
||||
DECLARE_NAPI_PROPERTY("CreateTooBigBigInt", CreateTooBigBigInt),
|
||||
};
|
||||
|
||||
NAPI_CALL(env, napi_define_properties(
|
||||
env, exports, sizeof(descriptors) / sizeof(*descriptors), descriptors));
|
||||
|
||||
return exports;
|
||||
}
|
||||
|
||||
NAPI_MODULE(NODE_GYP_MODULE_NAME, Init)
|
@ -42,7 +42,7 @@ assert.strictEqual(externalResult[2], 2);
|
||||
const buffer = new ArrayBuffer(128);
|
||||
const arrayTypes = [ Int8Array, Uint8Array, Uint8ClampedArray, Int16Array,
|
||||
Uint16Array, Int32Array, Uint32Array, Float32Array,
|
||||
Float64Array ];
|
||||
Float64Array, BigInt64Array, BigUint64Array ];
|
||||
|
||||
arrayTypes.forEach((currentType) => {
|
||||
const template = Reflect.construct(currentType, buffer);
|
||||
@ -64,7 +64,8 @@ arrayTypes.forEach((currentType) => {
|
||||
});
|
||||
|
||||
const nonByteArrayTypes = [ Int16Array, Uint16Array, Int32Array, Uint32Array,
|
||||
Float32Array, Float64Array ];
|
||||
Float32Array, Float64Array,
|
||||
BigInt64Array, BigUint64Array ];
|
||||
nonByteArrayTypes.forEach((currentType) => {
|
||||
const template = Reflect.construct(currentType, buffer);
|
||||
assert.throws(() => {
|
||||
|
Loading…
x
Reference in New Issue
Block a user