diff --git a/crates/cli-support/src/js/mod.rs b/crates/cli-support/src/js/mod.rs index c085abd4..09aeaf09 100644 --- a/crates/cli-support/src/js/mod.rs +++ b/crates/cli-support/src/js/mod.rs @@ -2128,7 +2128,6 @@ impl<'a, 'b> SubContext<'a, 'b> { import.shim, if op.is_static { "" } else { ".call" } )) ->>>>>>> master } fn generate_import_type( diff --git a/crates/macro-support/src/parser.rs b/crates/macro-support/src/parser.rs index 942bca0a..91f7f7ad 100644 --- a/crates/macro-support/src/parser.rs +++ b/crates/macro-support/src/parser.rs @@ -1101,60 +1101,6 @@ fn assert_not_variadic(attrs: &BindgenAttrs, span: &dyn ToTokens) -> Result<(), Ok(()) } -/// Checks the function signature to ensure it finishes with a slice -/// -/// Example of a valid signature: `fn my_func(arg1: u64, res: &[u64])`. -fn assert_last_param_is_slice(decl: &syn::FnDecl) -> Result<(), Diagnostic> { - #[inline] - fn not_slice_error(tok: &dyn ToTokens) -> Diagnostic { - Diagnostic::span_error(tok, "for variadic extern functions, the last argument must be a \ - slice or `::std::vec::Vec`, to hold the arguments of unknown length") - } - - /// Is this path `::std::vec::Vec`. - /// - /// I could add `Vec`, but this would break in wierd ways if the user does - /// `use SomethingElse as Vec;`. - #[inline] - fn path_is_vec(path: &syn::Path) -> bool { - #[inline] - fn is_path_segment(path: Option<&syn::PathSegment>, - name: Option<&str>, - plain: bool) -> bool { - match (path, name) { - (Some(ref path), Some(ref name)) => - (path.arguments.is_empty() || ! plain) && path.ident == name, - (None, None) => true, - _ => false - } - } - - let mut iter = (&path.segments).into_iter(); - path.leading_colon.is_some() - && is_path_segment(iter.next(), Some("std"), true) - && is_path_segment(iter.next(), Some("vec"), true) - && is_path_segment(iter.next(), Some("Vec"), false) - && is_path_segment(iter.next(), None, true) - } - - let arg = decl.inputs.last().ok_or_else(|| not_slice_error(&decl.inputs))?; - if let syn::FnArg::Captured(ref arg_cap) = arg.value() { - // check for slice reference - if let syn::Type::Reference(ref ref_ty) = arg_cap.ty { - if let syn::Type::Slice(_) = *ref_ty.elem { - return Ok(()); - } - } - // check for `Vec` - if let syn::Type::Path(ref path) = arg_cap.ty { - if path_is_vec(&path.path) { - return Ok(()); - } - } - } - Err(not_slice_error(&arg)) -} - /// If the path is a single ident, return it. fn extract_path_ident(path: &syn::Path) -> Result { if path.leading_colon.is_some() { diff --git a/guide/src/SUMMARY.md b/guide/src/SUMMARY.md index 720e4b84..89dfa890 100644 --- a/guide/src/SUMMARY.md +++ b/guide/src/SUMMARY.md @@ -42,6 +42,7 @@ - [`module = "blah"`](./reference/attributes/on-js-imports/module.md) - [`static_method_of = Blah`](./reference/attributes/on-js-imports/static_method_of.md) - [`structural`](./reference/attributes/on-js-imports/structural.md) + - [variadic](./reference/attributes/on-js-imports/variadic.md) - [On Rust Exports](./reference/attributes/on-rust-exports/index.md) - [`constructor`](./reference/attributes/on-rust-exports/constructor.md) - [`js_name = Blah`](./reference/attributes/on-rust-exports/js_name.md) diff --git a/guide/src/reference/attributes/on-js-imports/variadic.md b/guide/src/reference/attributes/on-js-imports/variadic.md new file mode 100644 index 00000000..a9ad97b4 --- /dev/null +++ b/guide/src/reference/attributes/on-js-imports/variadic.md @@ -0,0 +1,38 @@ +# Variadic Parameters + +In javascript, both the types of function arguments, and the number of function arguments are +dynamic. For example + +```js +function sum(...rest) { + let i; + // the old way + let old_way = 0; + for (i=0; i i32; +} +``` + +when we call this function, the last argument will be expanded as the javascript expects. + diff --git a/guide/src/whirlwind-tour/what-else-can-we-do.md b/guide/src/whirlwind-tour/what-else-can-we-do.md index 80bc19b0..7d9ec2b0 100644 --- a/guide/src/whirlwind-tour/what-else-can-we-do.md +++ b/guide/src/whirlwind-tour/what-else-can-we-do.md @@ -64,6 +64,10 @@ extern { fn new() -> Awesome; #[wasm_bindgen(method)] fn get_internal(this: &Awesome) -> u32; + // We can call javascript functions that have a dynamic number of arguments, + // e.g. rust `sum(&[1, 2, 3])` will be called like `sum(1, 2, 3)` + #[wasm_bindgen(variadic)] + fn sum(vals: &[u32]) -> u32; } #[wasm_bindgen] @@ -143,5 +147,13 @@ export class Awesome { } } +export function sum(...args) { + let answer = 0; + for(var i=0; i) -> String; + // rest: Vec) -> String; #[wasm_bindgen(variadic)] - fn variadic_sum_rest_vec(first: u8, second: u8, rest: ::std::vec::Vec) -> u8; + fn variadic_sum_rest_vec(first: u8, second: u8, rest: Vec) -> u8; //#[wasm_bindgen(variadic)] //fn variadic_compare_pairs(first: JsValue, second: JsValue, rest: &[JsValue]); //TODO imported type