mirror of
https://github.com/fluencelabs/wasm-bindgen
synced 2025-06-17 23:11:23 +00:00
Map u64/i64 to BigInt in JS
This commit is an implementation of mapping u64/i64 to `BigInt` in JS through the unstable BigInt APIs. The BigInt type will ship soon in Chrome and so this commit builds out the necessary support for wasm-bindgen to use it!
This commit is contained in:
@ -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 => {
|
||||
|
Reference in New Issue
Block a user