mirror of
https://github.com/fluencelabs/wasm-bindgen
synced 2025-03-16 02:00:51 +00:00
commit
6d167116a0
@ -8,7 +8,7 @@ environment:
|
||||
DEPLOY: 1
|
||||
|
||||
install:
|
||||
- ps: Install-Product node 9
|
||||
- ps: Install-Product node 10
|
||||
- appveyor-retry appveyor DownloadFile https://win.rustup.rs/ -FileName rustup-init.exe
|
||||
- rustup-init.exe -y --default-host x86_64-pc-windows-msvc --default-toolchain nightly
|
||||
- set PATH=%PATH%;C:\Users\appveyor\.cargo\bin
|
||||
|
@ -61,7 +61,7 @@ matrix:
|
||||
install:
|
||||
- curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.8/install.sh | bash
|
||||
- source ~/.nvm/nvm.sh
|
||||
- nvm install 9
|
||||
- nvm install 10
|
||||
- yarn
|
||||
|
||||
notifications:
|
||||
|
@ -492,7 +492,7 @@ All structs referenced through arguments to functions should be defined in the
|
||||
macro itself. Arguments allowed implement the `WasmBoundary` trait, and examples
|
||||
are:
|
||||
|
||||
* Integers (not u64/i64)
|
||||
* Integers (u64/i64 require `BigInt` support)
|
||||
* Floats
|
||||
* Borrowed strings (`&str`)
|
||||
* Owned strings (`String`)
|
||||
|
@ -79,6 +79,8 @@ pub enum VectorKind {
|
||||
U16,
|
||||
I32,
|
||||
U32,
|
||||
I64,
|
||||
U64,
|
||||
F32,
|
||||
F64,
|
||||
String,
|
||||
@ -139,8 +141,6 @@ impl Descriptor {
|
||||
Descriptor::U16 |
|
||||
Descriptor::I32 |
|
||||
Descriptor::U32 |
|
||||
Descriptor::I64 |
|
||||
Descriptor::U64 |
|
||||
Descriptor::F32 |
|
||||
Descriptor::F64 |
|
||||
Descriptor::Enum => true,
|
||||
@ -148,6 +148,14 @@ impl Descriptor {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_64bit(&self) -> Option<bool> {
|
||||
match *self {
|
||||
Descriptor::I64 => Some(true),
|
||||
Descriptor::U64 => Some(false),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_ref_anyref(&self) -> bool {
|
||||
match *self {
|
||||
Descriptor::Ref(ref s) => s.is_anyref(),
|
||||
@ -199,9 +207,11 @@ impl Descriptor {
|
||||
Descriptor::I8 => Some(VectorKind::I8),
|
||||
Descriptor::I16 => Some(VectorKind::I16),
|
||||
Descriptor::I32 => Some(VectorKind::I32),
|
||||
Descriptor::I64 => Some(VectorKind::I64),
|
||||
Descriptor::U8 => Some(VectorKind::U8),
|
||||
Descriptor::U16 => Some(VectorKind::U16),
|
||||
Descriptor::U32 => Some(VectorKind::U32),
|
||||
Descriptor::U64 => Some(VectorKind::U64),
|
||||
Descriptor::F32 => Some(VectorKind::F32),
|
||||
Descriptor::F64 => Some(VectorKind::F64),
|
||||
Descriptor::Anyref => Some(VectorKind::Anyref),
|
||||
@ -290,6 +300,8 @@ impl VectorKind {
|
||||
VectorKind::U16 => "Uint16Array",
|
||||
VectorKind::I32 => "Int32Array",
|
||||
VectorKind::U32 => "Uint32Array",
|
||||
VectorKind::I64 => "BigInt64Array",
|
||||
VectorKind::U64 => "BigUint64Array",
|
||||
VectorKind::F32 => "Float32Array",
|
||||
VectorKind::F64 => "Float64Array",
|
||||
VectorKind::Anyref => "any[]",
|
||||
@ -305,6 +317,8 @@ impl VectorKind {
|
||||
VectorKind::U16 => 2,
|
||||
VectorKind::I32 => 4,
|
||||
VectorKind::U32 => 4,
|
||||
VectorKind::I64 => 8,
|
||||
VectorKind::U64 => 8,
|
||||
VectorKind::F32 => 4,
|
||||
VectorKind::F64 => 8,
|
||||
VectorKind::Anyref => 4,
|
||||
|
@ -168,6 +168,29 @@ impl<'a, 'b> Js2Rust<'a, 'b> {
|
||||
return Ok(self)
|
||||
}
|
||||
|
||||
if let Some(signed) = arg.get_64bit() {
|
||||
let f = if signed {
|
||||
self.cx.expose_int64_cvt_shim()
|
||||
} else {
|
||||
self.cx.expose_uint64_cvt_shim()
|
||||
};
|
||||
self.cx.expose_uint32_memory();
|
||||
self.cx.expose_global_argument_ptr()?;
|
||||
self.js_arguments.push((name.clone(), "BigInt".to_string()));
|
||||
self.prelude(&format!("\
|
||||
{f}[0] = {name};\n\
|
||||
const lo{i} = u32CvtShim[0];\n\
|
||||
const hi{i} = u32CvtShim[1];\n\
|
||||
",
|
||||
i = i,
|
||||
f = f,
|
||||
name = name,
|
||||
));
|
||||
self.rust_arguments.push(format!("lo{}", i));
|
||||
self.rust_arguments.push(format!("hi{}", i));
|
||||
return Ok(self)
|
||||
}
|
||||
|
||||
if arg.is_ref_anyref() {
|
||||
self.js_arguments.push((name.clone(), "any".to_string()));
|
||||
self.cx.expose_borrowed_objects();
|
||||
@ -252,6 +275,25 @@ impl<'a, 'b> Js2Rust<'a, 'b> {
|
||||
return Ok(self)
|
||||
}
|
||||
|
||||
if let Some(signed) = ty.get_64bit() {
|
||||
self.ret_ty = "BigInt".to_string();
|
||||
self.cx.expose_global_argument_ptr()?;
|
||||
let f = if signed {
|
||||
self.cx.expose_int64_memory();
|
||||
"getInt64Memory"
|
||||
} else {
|
||||
self.cx.expose_uint64_memory();
|
||||
"getUint64Memory"
|
||||
};
|
||||
self.prelude("const retptr = globalArgumentPtr();");
|
||||
self.rust_arguments.insert(0, "retptr".to_string());
|
||||
self.ret_expr = format!("\
|
||||
RET;\n\
|
||||
return {}()[retptr / 8];\n\
|
||||
", f);
|
||||
return Ok(self)
|
||||
}
|
||||
|
||||
match *ty {
|
||||
Descriptor::Boolean => {
|
||||
self.ret_ty = "boolean".to_string();
|
||||
|
@ -787,80 +787,52 @@ impl<'a> Context<'a> {
|
||||
}
|
||||
|
||||
fn expose_pass_array8_to_wasm(&mut self) -> Result<(), Error> {
|
||||
if !self.exposed_globals.insert("pass_array8_to_wasm") {
|
||||
return Ok(());
|
||||
}
|
||||
self.require_internal_export("__wbindgen_malloc")?;
|
||||
self.expose_uint8_memory();
|
||||
self.global(&format!("
|
||||
function passArray8ToWasm(arg) {{
|
||||
const ptr = wasm.__wbindgen_malloc(arg.length);
|
||||
getUint8Memory().set(arg, ptr);
|
||||
return [ptr, arg.length];
|
||||
}}
|
||||
"));
|
||||
Ok(())
|
||||
self.pass_array_to_wasm("passArray8ToWasm", "getUint8Memory", 1)
|
||||
}
|
||||
|
||||
fn expose_pass_array16_to_wasm(&mut self) -> Result<(), Error> {
|
||||
if !self.exposed_globals.insert("pass_array16_to_wasm") {
|
||||
return Ok(());
|
||||
}
|
||||
self.require_internal_export("__wbindgen_malloc")?;
|
||||
self.expose_uint16_memory();
|
||||
self.global(&format!("
|
||||
function passArray16ToWasm(arg) {{
|
||||
const ptr = wasm.__wbindgen_malloc(arg.length * 2);
|
||||
getUint16Memory().set(arg, ptr / 2);
|
||||
return [ptr, arg.length];
|
||||
}}
|
||||
"));
|
||||
Ok(())
|
||||
self.pass_array_to_wasm("passArray16ToWasm", "getUint16Memory", 2)
|
||||
}
|
||||
|
||||
fn expose_pass_array32_to_wasm(&mut self) -> Result<(), Error> {
|
||||
if !self.exposed_globals.insert("pass_array32_to_wasm") {
|
||||
return Ok(())
|
||||
}
|
||||
self.require_internal_export("__wbindgen_malloc")?;
|
||||
self.expose_uint32_memory();
|
||||
self.global(&format!("
|
||||
function passArray32ToWasm(arg) {{
|
||||
const ptr = wasm.__wbindgen_malloc(arg.length * 4);
|
||||
getUint32Memory().set(arg, ptr / 4);
|
||||
return [ptr, arg.length];
|
||||
}}
|
||||
"));
|
||||
Ok(())
|
||||
self.pass_array_to_wasm("passArray32ToWasm", "getUint32Memory", 4)
|
||||
}
|
||||
|
||||
fn expose_pass_array64_to_wasm(&mut self) -> Result<(), Error> {
|
||||
self.expose_uint64_memory();
|
||||
self.pass_array_to_wasm("passArray64ToWasm", "getUint64Memory", 8)
|
||||
}
|
||||
|
||||
fn expose_pass_array_f32_to_wasm(&mut self) -> Result<(), Error> {
|
||||
if !self.exposed_globals.insert("pass_array_f32_to_wasm") {
|
||||
return Ok(())
|
||||
}
|
||||
self.require_internal_export("__wbindgen_malloc")?;
|
||||
self.global(&format!("
|
||||
function passArrayF32ToWasm(arg) {{
|
||||
const ptr = wasm.__wbindgen_malloc(arg.length * 4);
|
||||
new Float32Array(wasm.memory.buffer).set(arg, ptr / 4);
|
||||
return [ptr, arg.length];
|
||||
}}
|
||||
"));
|
||||
Ok(())
|
||||
self.expose_f32_memory();
|
||||
self.pass_array_to_wasm("passArrayF32ToWasm", "getFloat32Memory", 4)
|
||||
}
|
||||
|
||||
fn expose_pass_array_f64_to_wasm(&mut self) -> Result<(), Error> {
|
||||
if !self.exposed_globals.insert("pass_array_f64_to_wasm") {
|
||||
self.expose_f64_memory();
|
||||
self.pass_array_to_wasm("passArrayF64ToWasm", "getFloat64Memory", 8)
|
||||
}
|
||||
|
||||
fn pass_array_to_wasm(&mut self,
|
||||
name: &'static str,
|
||||
delegate: &str,
|
||||
size: usize) -> Result<(), Error>
|
||||
{
|
||||
if !self.exposed_globals.insert(name) {
|
||||
return Ok(())
|
||||
}
|
||||
self.require_internal_export("__wbindgen_malloc")?;
|
||||
self.expose_uint64_memory();
|
||||
self.global(&format!("
|
||||
function passArrayF64ToWasm(arg) {{
|
||||
const ptr = wasm.__wbindgen_malloc(arg.length * 8);
|
||||
new Float64Array(wasm.memory.buffer).set(arg, ptr / 8);
|
||||
function {}(arg) {{
|
||||
const ptr = wasm.__wbindgen_malloc(arg.length * {size});
|
||||
{}().set(arg, ptr / {size});
|
||||
return [ptr, arg.length];
|
||||
}}
|
||||
"));
|
||||
", name, delegate, size = size));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -980,6 +952,16 @@ impl<'a> Context<'a> {
|
||||
self.arrayget("getArrayU32FromWasm", "getUint32Memory", 4);
|
||||
}
|
||||
|
||||
fn expose_get_array_i64_from_wasm(&mut self) {
|
||||
self.expose_int64_memory();
|
||||
self.arrayget("getArrayI64FromWasm", "getInt64Memory", 8);
|
||||
}
|
||||
|
||||
fn expose_get_array_u64_from_wasm(&mut self) {
|
||||
self.expose_uint64_memory();
|
||||
self.arrayget("getArrayU64FromWasm", "getUint64Memory", 8);
|
||||
}
|
||||
|
||||
fn expose_get_array_f32_from_wasm(&mut self) {
|
||||
self.expose_f32_memory();
|
||||
self.arrayget("getArrayF32FromWasm", "getFloat32Memory", 4);
|
||||
@ -1029,6 +1011,14 @@ impl<'a> Context<'a> {
|
||||
self.memview("getUint32Memory", "Uint32Array");
|
||||
}
|
||||
|
||||
fn expose_int64_memory(&mut self) {
|
||||
self.memview("getInt64Memory", "BigInt64Array");
|
||||
}
|
||||
|
||||
fn expose_uint64_memory(&mut self) {
|
||||
self.memview("getUint64Memory", "BigUint64Array");
|
||||
}
|
||||
|
||||
fn expose_f32_memory(&mut self) {
|
||||
self.memview("getFloat32Memory", "Float32Array");
|
||||
}
|
||||
@ -1067,6 +1057,14 @@ impl<'a> Context<'a> {
|
||||
self.expose_uint32_memory();
|
||||
"getUint32Memory"
|
||||
}
|
||||
VectorKind::I64 => {
|
||||
self.expose_int64_memory();
|
||||
"getInt64Memory"
|
||||
}
|
||||
VectorKind::U64 => {
|
||||
self.expose_uint64_memory();
|
||||
"getUint64Memory"
|
||||
}
|
||||
VectorKind::F32 => {
|
||||
self.expose_f32_memory();
|
||||
"getFloat32Memory"
|
||||
@ -1204,6 +1202,11 @@ impl<'a> Context<'a> {
|
||||
self.expose_pass_array32_to_wasm()?;
|
||||
"passArray32ToWasm"
|
||||
}
|
||||
VectorKind::I64 |
|
||||
VectorKind::U64 => {
|
||||
self.expose_pass_array64_to_wasm()?;
|
||||
"passArray64ToWasm"
|
||||
}
|
||||
VectorKind::F32 => {
|
||||
self.expose_pass_array_f32_to_wasm()?;
|
||||
"passArrayF32ToWasm"
|
||||
@ -1249,6 +1252,14 @@ impl<'a> Context<'a> {
|
||||
self.expose_get_array_u32_from_wasm();
|
||||
"getArrayU32FromWasm"
|
||||
}
|
||||
VectorKind::I64 => {
|
||||
self.expose_get_array_i64_from_wasm();
|
||||
"getArrayI64FromWasm"
|
||||
}
|
||||
VectorKind::U64 => {
|
||||
self.expose_get_array_u64_from_wasm();
|
||||
"getArrayU64FromWasm"
|
||||
}
|
||||
VectorKind::F32 => {
|
||||
self.expose_get_array_f32_from_wasm();
|
||||
"getArrayF32FromWasm"
|
||||
@ -1320,6 +1331,35 @@ impl<'a> Context<'a> {
|
||||
");
|
||||
}
|
||||
|
||||
fn expose_u32_cvt_shim(&mut self) -> &'static str {
|
||||
let name = "u32CvtShim";
|
||||
if !self.exposed_globals.insert(name) {
|
||||
return name
|
||||
}
|
||||
self.global(&format!("const {} = new Uint32Array(2);", name));
|
||||
name
|
||||
}
|
||||
|
||||
fn expose_int64_cvt_shim(&mut self) -> &'static str {
|
||||
let name = "int64CvtShim";
|
||||
if !self.exposed_globals.insert(name) {
|
||||
return name
|
||||
}
|
||||
let n = self.expose_u32_cvt_shim();
|
||||
self.global(&format!("const {} = new BigInt64Array({}.buffer);", name, n));
|
||||
name
|
||||
}
|
||||
|
||||
fn expose_uint64_cvt_shim(&mut self) -> &'static str {
|
||||
let name = "uint64CvtShim";
|
||||
if !self.exposed_globals.insert(name) {
|
||||
return name
|
||||
}
|
||||
let n = self.expose_u32_cvt_shim();
|
||||
self.global(&format!("const {} = new BigUint64Array({}.buffer);", name, n));
|
||||
name
|
||||
}
|
||||
|
||||
fn gc(&mut self) -> Result<(), Error> {
|
||||
let module = mem::replace(self.module, Module::default());
|
||||
let wasm_bytes = parity_wasm::serialize(module)?;
|
||||
|
@ -98,6 +98,28 @@ impl<'a, 'b> Rust2Js<'a, 'b> {
|
||||
return Ok(())
|
||||
}
|
||||
|
||||
if let Some(signed) = arg.get_64bit() {
|
||||
let f = if signed {
|
||||
self.cx.expose_int64_cvt_shim()
|
||||
} else {
|
||||
self.cx.expose_uint64_cvt_shim()
|
||||
};
|
||||
let hi = self.shim_argument();
|
||||
let name = format!("n{}", abi);
|
||||
self.prelude(&format!("\
|
||||
u32CvtShim[0] = {lo};\n\
|
||||
u32CvtShim[1] = {hi};\n\
|
||||
const {name} = {f}[0];\n\
|
||||
",
|
||||
lo = abi,
|
||||
hi = hi,
|
||||
f = f,
|
||||
name = name,
|
||||
));
|
||||
self.js_arguments.push(name);
|
||||
return Ok(())
|
||||
}
|
||||
|
||||
if let Some(class) = arg.rust_struct() {
|
||||
if arg.is_by_ref() {
|
||||
bail!("cannot invoke JS functions with custom ref types yet")
|
||||
@ -229,6 +251,21 @@ impl<'a, 'b> Rust2Js<'a, 'b> {
|
||||
self.ret_expr = "return JS;".to_string();
|
||||
return Ok(())
|
||||
}
|
||||
if let Some(signed) = ty.get_64bit() {
|
||||
let f = if signed {
|
||||
self.cx.expose_int64_memory();
|
||||
"getInt64Memory"
|
||||
} else {
|
||||
self.cx.expose_uint64_memory();
|
||||
"getUint64Memory"
|
||||
};
|
||||
self.shim_arguments.insert(0, "ret".to_string());
|
||||
self.ret_expr = format!("\
|
||||
const val = JS;\n\
|
||||
{}()[ret / 8] = val;\n\
|
||||
", f);
|
||||
return Ok(())
|
||||
}
|
||||
self.ret_expr = match *ty {
|
||||
Descriptor::Boolean => "return JS ? 1 : 0;".to_string(),
|
||||
Descriptor::Anyref => {
|
||||
|
@ -55,9 +55,7 @@ pub trait Stack {
|
||||
pub unsafe trait WasmAbi {}
|
||||
|
||||
unsafe impl WasmAbi for u32 {}
|
||||
unsafe impl WasmAbi for u64 {}
|
||||
unsafe impl WasmAbi for i32 {}
|
||||
unsafe impl WasmAbi for i64 {}
|
||||
unsafe impl WasmAbi for f32 {}
|
||||
unsafe impl WasmAbi for f64 {}
|
||||
|
||||
@ -83,7 +81,30 @@ macro_rules! simple {
|
||||
)*)
|
||||
}
|
||||
|
||||
simple!(u32 u64 i32 i64 f32 f64);
|
||||
simple!(u32 i32 f32 f64);
|
||||
|
||||
macro_rules! sixtyfour {
|
||||
($($t:tt)*) => ($(
|
||||
impl IntoWasmAbi for $t {
|
||||
type Abi = WasmSlice;
|
||||
fn into_abi(self, _extra: &mut Stack) -> WasmSlice {
|
||||
WasmSlice {
|
||||
ptr: self as u32,
|
||||
len: (self >> 32) as u32,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FromWasmAbi for $t {
|
||||
type Abi = WasmSlice;
|
||||
unsafe fn from_abi(js: WasmSlice, _extra: &mut Stack) -> $t {
|
||||
(js.ptr as $t) | ((js.len as $t) << 32)
|
||||
}
|
||||
}
|
||||
)*)
|
||||
}
|
||||
|
||||
sixtyfour!(i64 u64);
|
||||
|
||||
macro_rules! as_u32 {
|
||||
($($t:tt)*) => ($(
|
||||
@ -217,7 +238,7 @@ macro_rules! vectors {
|
||||
}
|
||||
|
||||
vectors! {
|
||||
u8 i8 u16 i16 u32 i32 f32 f64
|
||||
u8 i8 u16 i16 u32 i32 u64 i64 f32 f64
|
||||
}
|
||||
|
||||
if_std! {
|
||||
|
@ -4,7 +4,8 @@ use std::env;
|
||||
use std::fs::{self, File};
|
||||
use std::io::{self, Write, Read};
|
||||
use std::path::{PathBuf, Path};
|
||||
use std::process::Command;
|
||||
use std::process::{Command, Stdio};
|
||||
use std::sync::{Once, ONCE_INIT};
|
||||
use std::sync::atomic::*;
|
||||
use std::time::Instant;
|
||||
|
||||
@ -18,6 +19,7 @@ struct Project {
|
||||
no_std: bool,
|
||||
serde: bool,
|
||||
rlib: bool,
|
||||
node_args: Vec<String>,
|
||||
deps: Vec<String>,
|
||||
}
|
||||
|
||||
@ -33,6 +35,7 @@ fn project() -> Project {
|
||||
serde: false,
|
||||
rlib: false,
|
||||
deps: Vec::new(),
|
||||
node_args: Vec::new(),
|
||||
files: vec![
|
||||
("Cargo.lock".to_string(), lockfile),
|
||||
|
||||
@ -120,6 +123,40 @@ fn root() -> PathBuf {
|
||||
return me
|
||||
}
|
||||
|
||||
fn assert_bigint_support() -> Option<&'static str> {
|
||||
static BIGINT_SUPPORED: AtomicUsize = ATOMIC_USIZE_INIT;
|
||||
static INIT: Once = ONCE_INIT;
|
||||
|
||||
INIT.call_once(|| {
|
||||
let mut cmd = Command::new("node");
|
||||
cmd.arg("-e").arg("BigInt");
|
||||
cmd.stdin(Stdio::null())
|
||||
.stdout(Stdio::piped())
|
||||
.stderr(Stdio::piped());
|
||||
if cmd.status().unwrap().success() {
|
||||
BIGINT_SUPPORED.store(1, Ordering::SeqCst);
|
||||
return
|
||||
}
|
||||
|
||||
cmd.arg("--harmony-bigint");
|
||||
if cmd.status().unwrap().success() {
|
||||
BIGINT_SUPPORED.store(2, Ordering::SeqCst);
|
||||
return
|
||||
}
|
||||
});
|
||||
|
||||
match BIGINT_SUPPORED.load(Ordering::SeqCst) {
|
||||
1 => return None,
|
||||
2 => return Some("--harmony-bigint"),
|
||||
_ => {
|
||||
panic!("the version of node.js that is installed for these tests \
|
||||
does not support `BigInt`, you may wish to try installing \
|
||||
node 10 to fix this")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
impl Project {
|
||||
fn file(&mut self, name: &str, contents: &str) -> &mut Project {
|
||||
self.files.push((name.to_string(), contents.to_string()));
|
||||
@ -165,6 +202,13 @@ impl Project {
|
||||
format!("test{}", IDX.with(|x| *x))
|
||||
}
|
||||
|
||||
fn requires_bigint(&mut self) -> &mut Project {
|
||||
if let Some(arg) = assert_bigint_support() {
|
||||
self.node_args.push(arg.to_string());
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
fn build(&mut self) -> (PathBuf, PathBuf) {
|
||||
let mut manifest = format!(r#"
|
||||
[package]
|
||||
@ -265,6 +309,7 @@ impl Project {
|
||||
|
||||
if self.node {
|
||||
let mut cmd = Command::new("node");
|
||||
cmd.args(&self.node_args);
|
||||
cmd.arg(root.join("run-node.js"))
|
||||
.current_dir(&root);
|
||||
run(&mut cmd, "node");
|
||||
@ -281,6 +326,7 @@ impl Project {
|
||||
run(&mut cmd, "yarn");
|
||||
|
||||
let mut cmd = Command::new("node");
|
||||
cmd.args(&self.node_args);
|
||||
cmd.arg(root.join("bundle.js"))
|
||||
.current_dir(&root);
|
||||
run(&mut cmd, "node");
|
||||
@ -335,3 +381,4 @@ mod simple;
|
||||
mod slice;
|
||||
mod structural;
|
||||
mod non_wasm;
|
||||
mod u64;
|
||||
|
100
tests/all/u64.rs
Normal file
100
tests/all/u64.rs
Normal file
@ -0,0 +1,100 @@
|
||||
use super::project;
|
||||
|
||||
#[test]
|
||||
fn works() {
|
||||
project()
|
||||
.requires_bigint()
|
||||
.file("src/lib.rs", r#"
|
||||
#![feature(proc_macro, wasm_custom_section, wasm_import_module)]
|
||||
|
||||
extern crate wasm_bindgen;
|
||||
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
#[wasm_bindgen(module = "./test")]
|
||||
extern {
|
||||
fn js_i64_round(a: i64) -> i64;
|
||||
fn js_u64_round(a: u64) -> u64;
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn zero() -> u64 { 0 }
|
||||
#[wasm_bindgen]
|
||||
pub fn one() -> u64 { 1 }
|
||||
#[wasm_bindgen]
|
||||
pub fn neg_one() -> i64 { -1 }
|
||||
#[wasm_bindgen]
|
||||
pub fn u32_max() -> u64 { u32::max_value() as u64 }
|
||||
#[wasm_bindgen]
|
||||
pub fn i32_min() -> i64 { i32::min_value() as i64 }
|
||||
#[wasm_bindgen]
|
||||
pub fn u64_max() -> u64 { u64::max_value() }
|
||||
#[wasm_bindgen]
|
||||
pub fn i64_min() -> i64 { i64::min_value() }
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn i64_round(a: i64) -> i64 { js_i64_round(a) }
|
||||
#[wasm_bindgen]
|
||||
pub fn u64_round(a: u64) -> u64 { js_u64_round(a) }
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn i64_slice(a: &[i64]) -> Vec<i64> { a.to_vec() }
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn u64_slice(a: &[u64]) -> Vec<u64> { a.to_vec() }
|
||||
"#)
|
||||
.file("test.js", r#"
|
||||
import * as wasm from './out';
|
||||
|
||||
function assertEq(a, b) {
|
||||
console.log(a, '?=', b);
|
||||
if (a === b)
|
||||
return;
|
||||
throw new Error('not equal');
|
||||
}
|
||||
|
||||
function assertArrayEq(a, b) {
|
||||
console.log(a, '?=', b);
|
||||
if (a.length !== b.length)
|
||||
throw new Error('not equal');
|
||||
for (let i = 0; i < a.length; i++)
|
||||
assertEq(a[i], b[i]);
|
||||
}
|
||||
|
||||
export function test() {
|
||||
assertEq(wasm.zero(), BigInt(0));
|
||||
assertEq(wasm.one(), BigInt(1));
|
||||
assertEq(wasm.neg_one(), BigInt(-1));
|
||||
assertEq(wasm.u32_max(), BigInt(4294967295));
|
||||
assertEq(wasm.i32_min(), BigInt(-2147483648));
|
||||
assertEq(wasm.u64_max(), BigInt('18446744073709551615'));
|
||||
assertEq(wasm.i64_min(), BigInt('-9223372036854775808'));
|
||||
|
||||
assertEq(wasm.i64_round(BigInt(0)), BigInt(0));
|
||||
assertEq(wasm.i64_round(BigInt(1)), BigInt(1));
|
||||
assertEq(wasm.i64_round(BigInt(-1)), BigInt(-1));
|
||||
assertEq(wasm.u64_round(BigInt(0)), BigInt(0));
|
||||
assertEq(wasm.u64_round(BigInt(1)), BigInt(1));
|
||||
assertEq(wasm.u64_round(BigInt(1) << BigInt(64)), BigInt(0));
|
||||
|
||||
const u64_max = BigInt('18446744073709551615');
|
||||
const i64_min = BigInt('-9223372036854775808');
|
||||
assertEq(wasm.i64_round(i64_min), i64_min);
|
||||
assertEq(wasm.u64_round(u64_max), u64_max);
|
||||
|
||||
assertArrayEq(wasm.u64_slice([]), new BigUint64Array());
|
||||
assertArrayEq(wasm.i64_slice([]), new BigInt64Array());
|
||||
const arr1 = new BigUint64Array([BigInt(1), BigInt(2)]);
|
||||
assertArrayEq(wasm.u64_slice([BigInt(1), BigInt(2)]), arr1);
|
||||
const arr2 = new BigInt64Array([BigInt(1), BigInt(2)]);
|
||||
assertArrayEq(wasm.i64_slice([BigInt(1), BigInt(2)]), arr2);
|
||||
|
||||
assertArrayEq(wasm.i64_slice([i64_min]), new BigInt64Array([i64_min]));
|
||||
assertArrayEq(wasm.u64_slice([u64_max]), new BigUint64Array([u64_max]));
|
||||
}
|
||||
|
||||
export function js_i64_round(a) { return a; }
|
||||
export function js_u64_round(a) { return a; }
|
||||
"#)
|
||||
.test();
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user