n-api: add more int64_t
tests
* Updated tests for `Number` and `int32_t` * Added new tests for `int64_t` * Updated N-API `int64_t` behavior to return zero for all non-finite numbers * Clarified the documentation for these calls. PR-URL: https://github.com/nodejs/node/pull/19402 Refs: https://github.com/nodejs/node-chakracore/pull/500 Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com> Reviewed-By: James M Snell <jasnell@gmail.com>
This commit is contained in:
parent
08a36a0666
commit
c529168249
@ -1797,13 +1797,17 @@ napi_status napi_get_value_int32(napi_env env,
|
|||||||
- `[out] result`: C int32 primitive equivalent of the given JavaScript Number.
|
- `[out] result`: C int32 primitive equivalent of the given JavaScript Number.
|
||||||
|
|
||||||
Returns `napi_ok` if the API succeeded. If a non-number `napi_value`
|
Returns `napi_ok` if the API succeeded. If a non-number `napi_value`
|
||||||
is passed in `napi_number_expected .
|
is passed in `napi_number_expected`.
|
||||||
|
|
||||||
This API returns the C int32 primitive equivalent
|
This API returns the C int32 primitive equivalent
|
||||||
of the given JavaScript Number. If the number exceeds the range of the
|
of the given JavaScript Number.
|
||||||
32 bit integer, then the result is truncated to the equivalent of the
|
|
||||||
bottom 32 bits. This can result in a large positive number becoming
|
If the number exceeds the range of the 32 bit integer, then the result is
|
||||||
a negative number if the value is > 2^31 -1.
|
truncated to the equivalent of the bottom 32 bits. This can result in a large
|
||||||
|
positive number becoming a negative number if the value is > 2^31 -1.
|
||||||
|
|
||||||
|
Non-finite number values (NaN, positive infinity, or negative infinity) set the
|
||||||
|
result to zero.
|
||||||
|
|
||||||
#### napi_get_value_int64
|
#### napi_get_value_int64
|
||||||
<!-- YAML
|
<!-- YAML
|
||||||
@ -1822,8 +1826,17 @@ napi_status napi_get_value_int64(napi_env env,
|
|||||||
Returns `napi_ok` if the API succeeded. If a non-number `napi_value`
|
Returns `napi_ok` if the API succeeded. If a non-number `napi_value`
|
||||||
is passed in it returns `napi_number_expected`.
|
is passed in it returns `napi_number_expected`.
|
||||||
|
|
||||||
This API returns the C int64 primitive equivalent of the given
|
This API returns the C int64 primitive equivalent of the given JavaScript
|
||||||
JavaScript Number.
|
Number.
|
||||||
|
|
||||||
|
Number values outside the range of
|
||||||
|
[`Number.MIN_SAFE_INTEGER`](https://tc39.github.io/ecma262/#sec-number.min_safe_integer)
|
||||||
|
-(2^53 - 1) -
|
||||||
|
[`Number.MAX_SAFE_INTEGER`](https://tc39.github.io/ecma262/#sec-number.max_safe_integer)
|
||||||
|
(2^53 - 1) will lose precision.
|
||||||
|
|
||||||
|
Non-finite number values (NaN, positive infinity, or negative infinity) set the
|
||||||
|
result to zero.
|
||||||
|
|
||||||
#### napi_get_value_string_latin1
|
#### napi_get_value_string_latin1
|
||||||
<!-- YAML
|
<!-- YAML
|
||||||
|
@ -2170,15 +2170,16 @@ napi_status napi_get_value_int64(napi_env env,
|
|||||||
|
|
||||||
RETURN_STATUS_IF_FALSE(env, val->IsNumber(), napi_number_expected);
|
RETURN_STATUS_IF_FALSE(env, val->IsNumber(), napi_number_expected);
|
||||||
|
|
||||||
// v8::Value::IntegerValue() converts NaN to INT64_MIN, inconsistent with
|
// v8::Value::IntegerValue() converts NaN, +Inf, and -Inf to INT64_MIN,
|
||||||
// v8::Value::Int32Value() that converts NaN to 0. So special-case NaN here.
|
// inconsistent with v8::Value::Int32Value() which converts those values to 0.
|
||||||
|
// Special-case all non-finite values to match that behavior.
|
||||||
double doubleValue = val.As<v8::Number>()->Value();
|
double doubleValue = val.As<v8::Number>()->Value();
|
||||||
if (std::isnan(doubleValue)) {
|
if (std::isfinite(doubleValue)) {
|
||||||
*result = 0;
|
|
||||||
} else {
|
|
||||||
// Empty context: https://github.com/nodejs/node/issues/14379
|
// Empty context: https://github.com/nodejs/node/issues/14379
|
||||||
v8::Local<v8::Context> context;
|
v8::Local<v8::Context> context;
|
||||||
*result = val->IntegerValue(context).FromJust();
|
*result = val->IntegerValue(context).FromJust();
|
||||||
|
} else {
|
||||||
|
*result = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return napi_clear_last_error(env);
|
return napi_clear_last_error(env);
|
||||||
|
@ -5,50 +5,113 @@ const test_number = require(`./build/${common.buildType}/test_number`);
|
|||||||
|
|
||||||
|
|
||||||
// testing api calls for number
|
// testing api calls for number
|
||||||
assert.strictEqual(0, test_number.Test(0));
|
function testNumber(num) {
|
||||||
assert.strictEqual(1, test_number.Test(1));
|
assert.strictEqual(num, test_number.Test(num));
|
||||||
assert.strictEqual(-1, test_number.Test(-1));
|
}
|
||||||
assert.strictEqual(100, test_number.Test(100));
|
|
||||||
assert.strictEqual(2121, test_number.Test(2121));
|
|
||||||
assert.strictEqual(-1233, test_number.Test(-1233));
|
|
||||||
assert.strictEqual(986583, test_number.Test(986583));
|
|
||||||
assert.strictEqual(-976675, test_number.Test(-976675));
|
|
||||||
|
|
||||||
const num1 = 98765432213456789876546896323445679887645323232436587988766545658;
|
testNumber(0);
|
||||||
assert.strictEqual(num1, test_number.Test(num1));
|
testNumber(-0);
|
||||||
|
testNumber(1);
|
||||||
|
testNumber(-1);
|
||||||
|
testNumber(100);
|
||||||
|
testNumber(2121);
|
||||||
|
testNumber(-1233);
|
||||||
|
testNumber(986583);
|
||||||
|
testNumber(-976675);
|
||||||
|
|
||||||
const num2 = -4350987086545760976737453646576078997096876957864353245245769809;
|
testNumber(
|
||||||
assert.strictEqual(num2, test_number.Test(num2));
|
98765432213456789876546896323445679887645323232436587988766545658);
|
||||||
|
testNumber(
|
||||||
|
-4350987086545760976737453646576078997096876957864353245245769809);
|
||||||
|
testNumber(Number.MIN_SAFE_INTEGER);
|
||||||
|
testNumber(Number.MAX_SAFE_INTEGER);
|
||||||
|
testNumber(Number.MAX_SAFE_INTEGER + 10);
|
||||||
|
|
||||||
const num3 = Number.MAX_SAFE_INTEGER;
|
testNumber(Number.MIN_VALUE);
|
||||||
assert.strictEqual(num3, test_number.Test(num3));
|
testNumber(Number.MAX_VALUE);
|
||||||
|
testNumber(Number.MAX_VALUE + 10);
|
||||||
|
|
||||||
const num4 = Number.MAX_SAFE_INTEGER + 10;
|
testNumber(Number.POSITIVE_INFINITY);
|
||||||
assert.strictEqual(num4, test_number.Test(num4));
|
testNumber(Number.NEGATIVE_INFINITY);
|
||||||
|
testNumber(Number.NaN);
|
||||||
|
|
||||||
const num5 = Number.MAX_VALUE;
|
// validate documented behavior when value is retrieved as 32-bit integer with
|
||||||
assert.strictEqual(num5, test_number.Test(num5));
|
// `napi_get_value_int32`
|
||||||
|
function testInt32(input, expected = input) {
|
||||||
|
assert.strictEqual(expected, test_number.TestInt32Truncation(input));
|
||||||
|
}
|
||||||
|
|
||||||
const num6 = Number.MAX_VALUE + 10;
|
// Test zero
|
||||||
assert.strictEqual(num6, test_number.Test(num6));
|
testInt32(0.0, 0);
|
||||||
|
testInt32(-0.0, 0);
|
||||||
|
|
||||||
const num7 = Number.POSITIVE_INFINITY;
|
// Test min/max int32 range
|
||||||
assert.strictEqual(num7, test_number.Test(num7));
|
testInt32(-Math.pow(2, 31));
|
||||||
|
testInt32(Math.pow(2, 31) - 1);
|
||||||
|
|
||||||
const num8 = Number.NEGATIVE_INFINITY;
|
// Test overflow scenarios
|
||||||
assert.strictEqual(num8, test_number.Test(num8));
|
testInt32(4294967297, 1);
|
||||||
|
testInt32(4294967296, 0);
|
||||||
|
testInt32(4294967295, -1);
|
||||||
|
testInt32(4294967296 * 5 + 3, 3);
|
||||||
|
|
||||||
|
// Test min/max safe integer range
|
||||||
|
testInt32(Number.MIN_SAFE_INTEGER, 1);
|
||||||
|
testInt32(Number.MAX_SAFE_INTEGER, -1);
|
||||||
|
|
||||||
// validate documented behavior when value is retrieved
|
// Test within int64_t range (with precision loss)
|
||||||
// as 32 bit integer with napi_get_value_int32
|
testInt32(-Math.pow(2, 63) + (Math.pow(2, 9) + 1), 1024);
|
||||||
assert.strictEqual(1, test_number.TestInt32Truncation(4294967297));
|
testInt32(Math.pow(2, 63) - (Math.pow(2, 9) + 1), -1024);
|
||||||
assert.strictEqual(0, test_number.TestInt32Truncation(4294967296));
|
|
||||||
assert.strictEqual(-1, test_number.TestInt32Truncation(4294967295));
|
|
||||||
assert.strictEqual(3, test_number.TestInt32Truncation(4294967296 * 5 + 3));
|
|
||||||
|
|
||||||
// validate that the boundaries of safe integer can be passed through
|
// Test min/max double value
|
||||||
// successfully
|
testInt32(-Number.MIN_VALUE, 0);
|
||||||
assert.strictEqual(Number.MAX_SAFE_INTEGER,
|
testInt32(Number.MIN_VALUE, 0);
|
||||||
test_number.TestInt64Truncation(Number.MAX_SAFE_INTEGER));
|
testInt32(-Number.MAX_VALUE, 0);
|
||||||
assert.strictEqual(Number.MIN_SAFE_INTEGER,
|
testInt32(Number.MAX_VALUE, 0);
|
||||||
test_number.TestInt64Truncation(Number.MIN_SAFE_INTEGER));
|
|
||||||
|
// Test outside int64_t range
|
||||||
|
testInt32(-Math.pow(2, 63) + (Math.pow(2, 9)), 0);
|
||||||
|
testInt32(Math.pow(2, 63) - (Math.pow(2, 9)), 0);
|
||||||
|
|
||||||
|
// Test non-finite numbers
|
||||||
|
testInt32(Number.POSITIVE_INFINITY, 0);
|
||||||
|
testInt32(Number.NEGATIVE_INFINITY, 0);
|
||||||
|
testInt32(Number.NaN, 0);
|
||||||
|
|
||||||
|
// validate documented behavior when value is retrieved as 64-bit integer with
|
||||||
|
// `napi_get_value_int64`
|
||||||
|
function testInt64(input, expected = input) {
|
||||||
|
assert.strictEqual(expected, test_number.TestInt64Truncation(input));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Both V8 and ChakraCore return a sentinel value of `0x8000000000000000` when
|
||||||
|
// the conversion goes out of range, but V8 treats it as unsigned in some cases.
|
||||||
|
const RANGEERROR_POSITIVE = Math.pow(2, 63);
|
||||||
|
const RANGEERROR_NEGATIVE = -Math.pow(2, 63);
|
||||||
|
|
||||||
|
// Test zero
|
||||||
|
testInt64(0.0, 0);
|
||||||
|
testInt64(-0.0, 0);
|
||||||
|
|
||||||
|
// Test min/max safe integer range
|
||||||
|
testInt64(Number.MIN_SAFE_INTEGER);
|
||||||
|
testInt64(Number.MAX_SAFE_INTEGER);
|
||||||
|
|
||||||
|
// Test within int64_t range (with precision loss)
|
||||||
|
testInt64(-Math.pow(2, 63) + (Math.pow(2, 9) + 1));
|
||||||
|
testInt64(Math.pow(2, 63) - (Math.pow(2, 9) + 1));
|
||||||
|
|
||||||
|
// Test min/max double value
|
||||||
|
testInt64(-Number.MIN_VALUE, 0);
|
||||||
|
testInt64(Number.MIN_VALUE, 0);
|
||||||
|
testInt64(-Number.MAX_VALUE, RANGEERROR_NEGATIVE);
|
||||||
|
testInt64(Number.MAX_VALUE, RANGEERROR_POSITIVE);
|
||||||
|
|
||||||
|
// Test outside int64_t range
|
||||||
|
testInt64(-Math.pow(2, 63) + (Math.pow(2, 9)), RANGEERROR_NEGATIVE);
|
||||||
|
testInt64(Math.pow(2, 63) - (Math.pow(2, 9)), RANGEERROR_POSITIVE);
|
||||||
|
|
||||||
|
// Test non-finite numbers
|
||||||
|
testInt64(Number.POSITIVE_INFINITY, 0);
|
||||||
|
testInt64(Number.NEGATIVE_INFINITY, 0);
|
||||||
|
testInt64(Number.NaN, 0);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user