-
Notifications
You must be signed in to change notification settings - Fork 5.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix(napi): BigInt related APIs (#19174)
Doesn't make the API bullet-proof and there are some TODOs left, but greatly improves the situation. Tests were ported from Node.js. Closes #18276.
- Loading branch information
1 parent
99c3028
commit 9dc3ae8
Showing
5 changed files
with
307 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. | ||
|
||
import { assertEquals, assertThrows, loadTestLibrary } from "./common.js"; | ||
|
||
const bi = loadTestLibrary(); | ||
|
||
Deno.test("cases", function () { | ||
const cases = [ | ||
0n, | ||
-0n, | ||
1n, | ||
-1n, | ||
100n, | ||
2121n, | ||
-1233n, | ||
986583n, | ||
-976675n, | ||
98765432213456789876546896323445679887645323232436587988766545658n, | ||
-4350987086545760976737453646576078997096876957864353245245769809n, | ||
]; | ||
|
||
for (const num of cases) { | ||
if (num > -(2n ** 63n) && num < 2n ** 63n) { | ||
assertEquals(bi.testInt64(num), num); | ||
assertEquals(bi.isLossless(num, true), true); | ||
} else { | ||
assertEquals(bi.isLossless(num, true), false); | ||
} | ||
|
||
if (num >= 0 && num < 2n ** 64n) { | ||
assertEquals(bi.testUint64(num), num); | ||
assertEquals(bi.isLossless(num, false), true); | ||
} else { | ||
assertEquals(bi.isLossless(num, false), false); | ||
} | ||
|
||
assertEquals(bi.testWords(num), num); | ||
} | ||
}); | ||
|
||
Deno.test( | ||
// TODO(bartlomieju): fix this test | ||
{ ignore: true }, | ||
function tooBigBigInt() { | ||
assertThrows( | ||
() => bi.createTooBigBigInt(), | ||
Error, | ||
"Invalid argument", | ||
); | ||
}, | ||
); | ||
|
||
Deno.test( | ||
// TODO(bartlomieju): fix this test | ||
{ ignore: true }, | ||
function exceptionForwarding() { | ||
assertThrows( | ||
() => bi.makeBigIntWordsThrow(), | ||
Error, | ||
"Maximum BigInt size exceeded", | ||
); | ||
}, | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,205 @@ | ||
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. | ||
|
||
use crate::assert_napi_ok; | ||
use crate::cstr; | ||
use crate::napi_get_callback_info; | ||
use crate::napi_new_property; | ||
use napi_sys::Status::napi_pending_exception; | ||
use napi_sys::ValueType::napi_bigint; | ||
use napi_sys::*; | ||
use std::ptr; | ||
|
||
extern "C" fn is_lossless( | ||
env: napi_env, | ||
info: napi_callback_info, | ||
) -> napi_value { | ||
let (args, argc, _) = napi_get_callback_info!(env, info, 2); | ||
assert_eq!(argc, 2); | ||
|
||
let mut is_signed = false; | ||
assert_napi_ok!(napi_get_value_bool(env, args[1], &mut is_signed)); | ||
|
||
let mut lossless = false; | ||
|
||
if is_signed { | ||
let mut input: i64 = 0; | ||
assert_napi_ok!(napi_get_value_bigint_int64( | ||
env, | ||
args[0], | ||
&mut input, | ||
&mut lossless | ||
)); | ||
} else { | ||
let mut input: u64 = 0; | ||
assert_napi_ok!(napi_get_value_bigint_uint64( | ||
env, | ||
args[0], | ||
&mut input, | ||
&mut lossless | ||
)); | ||
} | ||
|
||
let mut output: napi_value = ptr::null_mut(); | ||
assert_napi_ok!(napi_get_boolean(env, lossless, &mut output)); | ||
|
||
output | ||
} | ||
|
||
extern "C" fn test_int64( | ||
env: napi_env, | ||
info: napi_callback_info, | ||
) -> napi_value { | ||
let (args, _argc, _) = napi_get_callback_info!(env, info, 2); | ||
|
||
let mut ty = -1; | ||
assert_napi_ok!(napi_typeof(env, args[0], &mut ty)); | ||
assert_eq!(ty, napi_bigint); | ||
|
||
let mut input: i64 = 0; | ||
let mut lossless = false; | ||
assert_napi_ok!(napi_get_value_bigint_int64( | ||
env, | ||
args[0], | ||
&mut input, | ||
&mut lossless | ||
)); | ||
|
||
let mut output: napi_value = ptr::null_mut(); | ||
assert_napi_ok!(napi_create_bigint_int64(env, input, &mut output)); | ||
|
||
output | ||
} | ||
|
||
extern "C" fn test_uint64( | ||
env: napi_env, | ||
info: napi_callback_info, | ||
) -> napi_value { | ||
let (args, _argc, _) = napi_get_callback_info!(env, info, 2); | ||
|
||
let mut ty = -1; | ||
assert_napi_ok!(napi_typeof(env, args[0], &mut ty)); | ||
assert_eq!(ty, napi_bigint); | ||
|
||
let mut input: u64 = 0; | ||
let mut lossless = false; | ||
assert_napi_ok!(napi_get_value_bigint_uint64( | ||
env, | ||
args[0], | ||
&mut input, | ||
&mut lossless | ||
)); | ||
|
||
let mut output: napi_value = ptr::null_mut(); | ||
assert_napi_ok!(napi_create_bigint_uint64(env, input, &mut output)); | ||
|
||
output | ||
} | ||
|
||
extern "C" fn test_words( | ||
env: napi_env, | ||
info: napi_callback_info, | ||
) -> napi_value { | ||
let (args, _argc, _) = napi_get_callback_info!(env, info, 1); | ||
|
||
let mut ty = -1; | ||
assert_napi_ok!(napi_typeof(env, args[0], &mut ty)); | ||
assert_eq!(ty, napi_bigint); | ||
|
||
let mut expected_work_count = 0; | ||
assert_napi_ok!(napi_get_value_bigint_words( | ||
env, | ||
args[0], | ||
ptr::null_mut(), | ||
&mut expected_work_count, | ||
ptr::null_mut() | ||
)); | ||
|
||
let mut sign_bit = 0; | ||
let mut word_count: usize = 10; | ||
let mut words: Vec<u64> = Vec::with_capacity(10); | ||
|
||
assert_napi_ok!(napi_get_value_bigint_words( | ||
env, | ||
args[0], | ||
&mut sign_bit, | ||
&mut word_count, | ||
words.as_mut_ptr(), | ||
)); | ||
|
||
assert_eq!(word_count, expected_work_count); | ||
let mut output: napi_value = ptr::null_mut(); | ||
|
||
assert_napi_ok!(napi_create_bigint_words( | ||
env, | ||
sign_bit, | ||
word_count, | ||
words.as_ptr(), | ||
&mut output, | ||
)); | ||
output | ||
} | ||
|
||
extern "C" fn create_too_big_big_int( | ||
env: napi_env, | ||
_info: napi_callback_info, | ||
) -> napi_value { | ||
let sign_bit = 0; | ||
let word_count = usize::MAX; | ||
let words: Vec<u64> = Vec::with_capacity(10); | ||
|
||
let mut output: napi_value = ptr::null_mut(); | ||
let result = unsafe { | ||
napi_create_bigint_words( | ||
env, | ||
sign_bit, | ||
word_count, | ||
words.as_ptr(), | ||
&mut output, | ||
) | ||
}; | ||
assert_eq!(result, 1); | ||
|
||
output | ||
} | ||
|
||
extern "C" fn make_big_int_words_throw( | ||
env: napi_env, | ||
_info: napi_callback_info, | ||
) -> napi_value { | ||
let words: Vec<u64> = Vec::with_capacity(10); | ||
let mut output = ptr::null_mut(); | ||
|
||
let status = unsafe { | ||
napi_create_bigint_words(env, 0, usize::MAX, words.as_ptr(), &mut output) | ||
}; | ||
|
||
if status != napi_pending_exception { | ||
unsafe { | ||
napi_throw_error( | ||
env, | ||
ptr::null_mut(), | ||
cstr!("Expected status 'napi_pending_exception'"), | ||
) | ||
}; | ||
} | ||
|
||
ptr::null_mut() | ||
} | ||
|
||
pub fn init(env: napi_env, exports: napi_value) { | ||
let properties = &[ | ||
napi_new_property!(env, "isLossless", is_lossless), | ||
napi_new_property!(env, "testInt64", test_int64), | ||
napi_new_property!(env, "testUint64", test_uint64), | ||
napi_new_property!(env, "testWords", test_words), | ||
napi_new_property!(env, "createTooBigBigInt", create_too_big_big_int), | ||
napi_new_property!(env, "makeBigIntWordsThrow", make_big_int_words_throw), | ||
]; | ||
|
||
assert_napi_ok!(napi_define_properties( | ||
env, | ||
exports, | ||
properties.len(), | ||
properties.as_ptr() | ||
)); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters