From 70f537334877f57c06fcf6edd617f6608f3f04f5 Mon Sep 17 00:00:00 2001 From: Caio Date: Thu, 14 Mar 2019 08:46:42 -0300 Subject: [PATCH 1/2] Preserve argument names --- crates/backend/src/encode.rs | 23 ++++++++++++++++- crates/cli-support/src/decode.rs | 9 +++++++ crates/cli-support/src/js/closures.rs | 2 +- crates/cli-support/src/js/js2rust.rs | 36 +++++++++++++++++++++------ crates/cli-support/src/js/mod.rs | 6 ++--- crates/cli-support/src/js/rust2js.rs | 2 +- crates/shared/src/lib.rs | 1 + tests/wasm/arg_names.js | 16 ++++++++++++ tests/wasm/arg_names.rs | 15 +++++++++++ tests/wasm/main.rs | 1 + 10 files changed, 97 insertions(+), 14 deletions(-) create mode 100644 tests/wasm/arg_names.js create mode 100644 tests/wasm/arg_names.rs diff --git a/crates/backend/src/encode.rs b/crates/backend/src/encode.rs index 791adb48b..abc8c6137 100644 --- a/crates/backend/src/encode.rs +++ b/crates/backend/src/encode.rs @@ -165,7 +165,22 @@ fn shared_export<'a>(export: &'a ast::Export, intern: &'a Interner) -> Export<'a } fn shared_function<'a>(func: &'a ast::Function, _intern: &'a Interner) -> Function<'a> { - Function { name: &func.name } + let arg_names = func + .arguments + .iter() + .enumerate() + .map(|(idx, arg)| { + if let syn::Pat::Ident(ref x) = arg.pat { + x.ident.to_string() + } else { + format!("arg{}", idx) + } + }) + .collect::>(); + Function { + name: &func.name, + arg_names, + } } fn shared_enum<'a>(e: &'a ast::Enum, intern: &'a Interner) -> Enum<'a> { @@ -364,6 +379,12 @@ impl<'a> Encode for &'a str { } } +impl<'a> Encode for String { + fn encode(&self, dst: &mut Encoder) { + self.as_bytes().encode(dst); + } +} + impl Encode for Vec { fn encode(&self, dst: &mut Encoder) { self.len().encode(dst); diff --git a/crates/cli-support/src/decode.rs b/crates/cli-support/src/decode.rs index e5283139a..1d337e27c 100644 --- a/crates/cli-support/src/decode.rs +++ b/crates/cli-support/src/decode.rs @@ -46,6 +46,15 @@ impl<'src> Decode<'src> for &'src str { } } +impl<'src> Decode<'src> for String { + fn decode(data: &mut &'src [u8]) -> String { + let n = u32::decode(data); + let (a, b) = data.split_at(n as usize); + *data = b; + String::from_utf8(a.to_vec()).unwrap() + } +} + impl<'src, T: Decode<'src>> Decode<'src> for Vec { fn decode(data: &mut &'src [u8]) -> Self { let n = u32::decode(data); diff --git a/crates/cli-support/src/js/closures.rs b/crates/cli-support/src/js/closures.rs index a4dcba4a3..96c56d4a7 100644 --- a/crates/cli-support/src/js/closures.rs +++ b/crates/cli-support/src/js/closures.rs @@ -193,7 +193,7 @@ impl ClosureDescriptors { builder.rust_argument("this.a").rust_argument("b"); } builder.finally("if (this.cnt-- == 1) d(this.a, b);"); - builder.process(&closure.function)?.finish( + builder.process(&closure.function, None)?.finish( "function", "f", ExportedShim::TableElement(&mut shim), diff --git a/crates/cli-support/src/js/js2rust.rs b/crates/cli-support/src/js/js2rust.rs index 22a62376e..e5b7e1139 100644 --- a/crates/cli-support/src/js/js2rust.rs +++ b/crates/cli-support/src/js/js2rust.rs @@ -75,9 +75,22 @@ impl<'a, 'b> Js2Rust<'a, 'b> { /// Generates all bindings necessary for the signature in `Function`, /// creating necessary argument conversions and return value processing. - pub fn process(&mut self, function: &Function) -> Result<&mut Self, Error> { - for arg in function.arguments.iter() { - self.argument(arg)?; + pub fn process<'c, I>( + &mut self, + function: &Function, + opt_arg_names: I, + ) -> Result<&mut Self, Error> + where + I: Into>>, + { + if let Some(arg_names) = opt_arg_names.into() { + for (arg, arg_name) in function.arguments.iter().zip(arg_names) { + self.argument(arg, arg_name.clone())?; + } + } else { + for arg in function.arguments.iter() { + self.argument(arg, None)?; + } } self.ret(&function.ret)?; Ok(self) @@ -138,15 +151,22 @@ impl<'a, 'b> Js2Rust<'a, 'b> { self } - fn abi_arg(&mut self) -> String { - let s = format!("arg{}", self.arg_idx); + fn abi_arg(&mut self, opt_arg_name: Option) -> String { + let ret = if let Some(x) = opt_arg_name { + x + } else { + format!("arg{}", self.arg_idx) + }; self.arg_idx += 1; - s + ret } - pub fn argument(&mut self, arg: &Descriptor) -> Result<&mut Self, Error> { + pub fn argument(&mut self, arg: &Descriptor, opt_arg_name: I) -> Result<&mut Self, Error> + where + I: Into>, + { let i = self.arg_idx; - let name = self.abi_arg(); + let name = self.abi_arg(opt_arg_name.into()); let (arg, optional) = match arg { Descriptor::Option(t) => (&**t, true), diff --git a/crates/cli-support/src/js/mod.rs b/crates/cli-support/src/js/mod.rs index c3a9c7a32..57e90368e 100644 --- a/crates/cli-support/src/js/mod.rs +++ b/crates/cli-support/src/js/mod.rs @@ -2498,7 +2498,7 @@ impl<'a, 'b> SubContext<'a, 'b> { } let (js, ts, js_doc) = Js2Rust::new(&export.function.name, self.cx) - .process(descriptor.unwrap_function())? + .process(descriptor.unwrap_function(), &export.function.arg_names)? .finish( "function", &format!("wasm.{}", export.function.name), @@ -2554,7 +2554,7 @@ impl<'a, 'b> SubContext<'a, 'b> { } else { None }) - .process(descriptor.unwrap_function())? + .process(descriptor.unwrap_function(), &export.function.arg_names)? .finish( "", &format!("wasm.{}", wasm_name), @@ -2772,7 +2772,7 @@ impl<'a, 'b> SubContext<'a, 'b> { let setter = ExportedShim::Named(&wasm_setter); let mut cx = Js2Rust::new(&field.name, self.cx); cx.method(true, false) - .argument(&descriptor)? + .argument(&descriptor, None)? .ret(&Descriptor::Unit)?; ts_dst.push_str(&format!( "\n {}{}: {};", diff --git a/crates/cli-support/src/js/rust2js.rs b/crates/cli-support/src/js/rust2js.rs index b0824580f..de4640a13 100644 --- a/crates/cli-support/src/js/rust2js.rs +++ b/crates/cli-support/src/js/rust2js.rs @@ -285,7 +285,7 @@ impl<'a, 'b> Rust2Js<'a, 'b> { } else { builder.rust_argument("this.a"); } - builder.rust_argument("this.b").process(f)?.finish( + builder.rust_argument("this.b").process(f, None)?.finish( "function", "this.f", ExportedShim::TableElement(&mut shim), diff --git a/crates/shared/src/lib.rs b/crates/shared/src/lib.rs index c32f4c14a..9b9356f24 100644 --- a/crates/shared/src/lib.rs +++ b/crates/shared/src/lib.rs @@ -106,6 +106,7 @@ macro_rules! shared_api { } struct Function<'a> { + arg_names: Vec, name: &'a str, } diff --git a/tests/wasm/arg_names.js b/tests/wasm/arg_names.js new file mode 100644 index 000000000..255604b3e --- /dev/null +++ b/tests/wasm/arg_names.js @@ -0,0 +1,16 @@ +const wasm = require('wasm-bindgen-test.js'); +const assert = require('assert'); + +const ARGUMENT_NAMES = /([^\s,]+)/g; +const STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg; + +// https://stackoverflow.com/q/1007981/210304 +function getArgNames(func) { + let fnStr = func.toString().replace(STRIP_COMMENTS, ''); + let result = fnStr.slice(fnStr.indexOf('(')+1, fnStr.indexOf(')')).match(ARGUMENT_NAMES); + return result === null ? [] : result; +} + +exports.js_arg_names = () => { + assert.deepEqual(getArgNames(wasm.fn_with_many_args), ['_a', '_b', '_c', '_d']); +}; diff --git a/tests/wasm/arg_names.rs b/tests/wasm/arg_names.rs new file mode 100644 index 000000000..e6f044ee1 --- /dev/null +++ b/tests/wasm/arg_names.rs @@ -0,0 +1,15 @@ +use wasm_bindgen::prelude::*; +use wasm_bindgen_test::*; + +#[wasm_bindgen(module = "tests/wasm/arg_names.js")] +extern "C" { + fn js_arg_names(); +} + +#[wasm_bindgen] +pub fn fn_with_many_args(_a: i32, _b: i32, _c: i32, _d: i32) {} + +#[wasm_bindgen_test] +fn rust_arg_names() { + js_arg_names(); +} diff --git a/tests/wasm/main.rs b/tests/wasm/main.rs index 283ecbd58..fff182284 100644 --- a/tests/wasm/main.rs +++ b/tests/wasm/main.rs @@ -13,6 +13,7 @@ extern crate serde_derive; use wasm_bindgen::prelude::*; pub mod api; +pub mod arg_names; pub mod char; pub mod classes; pub mod closures; From 91ea972c030781a0120085b22d165631b2f50753 Mon Sep 17 00:00:00 2001 From: Caio Date: Thu, 14 Mar 2019 12:21:41 -0300 Subject: [PATCH 2/2] Take &str instead of String in argument fn --- crates/cli-support/src/js/js2rust.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/cli-support/src/js/js2rust.rs b/crates/cli-support/src/js/js2rust.rs index e5b7e1139..1b25307a1 100644 --- a/crates/cli-support/src/js/js2rust.rs +++ b/crates/cli-support/src/js/js2rust.rs @@ -85,7 +85,7 @@ impl<'a, 'b> Js2Rust<'a, 'b> { { if let Some(arg_names) = opt_arg_names.into() { for (arg, arg_name) in function.arguments.iter().zip(arg_names) { - self.argument(arg, arg_name.clone())?; + self.argument(arg, arg_name.as_str())?; } } else { for arg in function.arguments.iter() { @@ -151,9 +151,9 @@ impl<'a, 'b> Js2Rust<'a, 'b> { self } - fn abi_arg(&mut self, opt_arg_name: Option) -> String { + fn abi_arg(&mut self, opt_arg_name: Option<&str>) -> String { let ret = if let Some(x) = opt_arg_name { - x + x.into() } else { format!("arg{}", self.arg_idx) }; @@ -161,9 +161,9 @@ impl<'a, 'b> Js2Rust<'a, 'b> { ret } - pub fn argument(&mut self, arg: &Descriptor, opt_arg_name: I) -> Result<&mut Self, Error> + pub fn argument<'c, I>(&mut self, arg: &Descriptor, opt_arg_name: I) -> Result<&mut Self, Error> where - I: Into>, + I: Into>, { let i = self.arg_idx; let name = self.abi_arg(opt_arg_name.into());