mirror of
https://github.com/fluencelabs/wasm-bindgen
synced 2025-06-14 13:31:22 +00:00
Add docs and remove typecheck from variadic attribute
This commit is contained in:
@ -2128,7 +2128,6 @@ impl<'a, 'b> SubContext<'a, 'b> {
|
||||
import.shim,
|
||||
if op.is_static { "" } else { ".call" }
|
||||
))
|
||||
>>>>>>> master
|
||||
}
|
||||
|
||||
fn generate_import_type(
|
||||
|
@ -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<Ident, Diagnostic> {
|
||||
if path.leading_colon.is_some() {
|
||||
|
@ -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)
|
||||
|
38
guide/src/reference/attributes/on-js-imports/variadic.md
Normal file
38
guide/src/reference/attributes/on-js-imports/variadic.md
Normal file
@ -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<arguments.length; i++) {
|
||||
old_way += arguments[i];
|
||||
}
|
||||
// the new way
|
||||
let new_way = 0;
|
||||
for (i=0; i<rest.length; i++) {
|
||||
new_way += rest[i];
|
||||
}
|
||||
// both give the same answer
|
||||
assert(old_way === new_way);
|
||||
return new_way;
|
||||
}
|
||||
```
|
||||
|
||||
This function doesn't translate directly into rust, since we don't currently support variadic
|
||||
arguments on the wasm target. To bind to it, we use a slice as the last argument, and annotate the
|
||||
function as variadic:
|
||||
|
||||
```rust
|
||||
#[wasm_bindgen]
|
||||
extern {
|
||||
#[wasm_bindgen(variadic)]
|
||||
fn sum(args: &[i32]) -> i32;
|
||||
}
|
||||
```
|
||||
|
||||
when we call this function, the last argument will be expanded as the javascript expects.
|
||||
|
@ -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<args.length; i++) {
|
||||
answer += args[i];
|
||||
}
|
||||
return answer;
|
||||
}
|
||||
|
||||
booted.then(main);
|
||||
```
|
||||
|
@ -1,4 +1,3 @@
|
||||
const wasm = require('wasm-bindgen-test.js');
|
||||
const assert = require('assert');
|
||||
|
||||
// a function for testing numbers
|
||||
|
@ -34,9 +34,9 @@ extern {
|
||||
//#[wasm_bindgen(variadic)]
|
||||
//fn variadic_concat_string(first: String,
|
||||
// second: String,
|
||||
// rest: ::std::vec::Vec<String>) -> String;
|
||||
// rest: Vec<String>) -> String;
|
||||
#[wasm_bindgen(variadic)]
|
||||
fn variadic_sum_rest_vec(first: u8, second: u8, rest: ::std::vec::Vec<u8>) -> u8;
|
||||
fn variadic_sum_rest_vec(first: u8, second: u8, rest: Vec<u8>) -> u8;
|
||||
//#[wasm_bindgen(variadic)]
|
||||
//fn variadic_compare_pairs(first: JsValue, second: JsValue, rest: &[JsValue]);
|
||||
//TODO imported type
|
||||
|
Reference in New Issue
Block a user