mirror of
https://github.com/fluencelabs/wasm-bindgen
synced 2025-04-01 18:01:06 +00:00
Merge pull request #726 from derekdreery/variadic_js_functions
Support variadic javascript function parameters
This commit is contained in:
commit
1a00e94324
@ -85,6 +85,7 @@ pub struct ImportFunction {
|
|||||||
pub rust_name: Ident,
|
pub rust_name: Ident,
|
||||||
pub js_ret: Option<syn::Type>,
|
pub js_ret: Option<syn::Type>,
|
||||||
pub catch: bool,
|
pub catch: bool,
|
||||||
|
pub variadic: bool,
|
||||||
pub structural: bool,
|
pub structural: bool,
|
||||||
pub kind: ImportFunctionKind,
|
pub kind: ImportFunctionKind,
|
||||||
pub shim: Ident,
|
pub shim: Ident,
|
||||||
@ -463,6 +464,7 @@ impl ImportFunction {
|
|||||||
shared::ImportFunction {
|
shared::ImportFunction {
|
||||||
shim: self.shim.to_string(),
|
shim: self.shim.to_string(),
|
||||||
catch: self.catch,
|
catch: self.catch,
|
||||||
|
variadic: self.variadic,
|
||||||
method,
|
method,
|
||||||
structural: self.structural,
|
structural: self.structural,
|
||||||
function: self.function.shared(),
|
function: self.function.shared(),
|
||||||
|
@ -1733,7 +1733,6 @@ impl<'a> Context<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn global(&mut self, s: &str) {
|
fn global(&mut self, s: &str) {
|
||||||
let s = s;
|
|
||||||
let s = s.trim();
|
let s = s.trim();
|
||||||
|
|
||||||
// Ensure a blank line between adjacent items, and ensure everything is
|
// Ensure a blank line between adjacent items, and ensure everything is
|
||||||
@ -1963,8 +1962,9 @@ impl<'a, 'b> SubContext<'a, 'b> {
|
|||||||
|
|
||||||
let js = Rust2Js::new(self.cx)
|
let js = Rust2Js::new(self.cx)
|
||||||
.catch(import.catch)
|
.catch(import.catch)
|
||||||
|
.variadic(import.variadic)
|
||||||
.process(descriptor.unwrap_function())?
|
.process(descriptor.unwrap_function())?
|
||||||
.finish(&target);
|
.finish(&target)?;
|
||||||
self.cx.export(&import.shim, &js, None);
|
self.cx.export(&import.shim, &js, None);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use failure::Error;
|
use failure::{self, Error};
|
||||||
|
|
||||||
use super::{Context, Js2Rust};
|
use super::{Context, Js2Rust};
|
||||||
use descriptor::{Descriptor, Function};
|
use descriptor::{Descriptor, Function};
|
||||||
@ -36,6 +36,9 @@ pub struct Rust2Js<'a, 'b: 'a> {
|
|||||||
|
|
||||||
/// Whether or not we're catching JS exceptions
|
/// Whether or not we're catching JS exceptions
|
||||||
catch: bool,
|
catch: bool,
|
||||||
|
|
||||||
|
/// Whether or not the last argument is a slice representing variadic arguments.
|
||||||
|
variadic: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'b> Rust2Js<'a, 'b> {
|
impl<'a, 'b> Rust2Js<'a, 'b> {
|
||||||
@ -50,6 +53,7 @@ impl<'a, 'b> Rust2Js<'a, 'b> {
|
|||||||
arg_idx: 0,
|
arg_idx: 0,
|
||||||
ret_expr: String::new(),
|
ret_expr: String::new(),
|
||||||
catch: false,
|
catch: false,
|
||||||
|
variadic: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,6 +66,15 @@ impl<'a, 'b> Rust2Js<'a, 'b> {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn variadic(&mut self, variadic: bool) -> &mut Self {
|
||||||
|
if variadic {
|
||||||
|
self.cx.expose_uint32_memory();
|
||||||
|
self.cx.expose_add_heap_object();
|
||||||
|
}
|
||||||
|
self.variadic = variadic;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
/// Generates all bindings necessary for the signature in `Function`,
|
/// Generates all bindings necessary for the signature in `Function`,
|
||||||
/// creating necessary argument conversions and return value processing.
|
/// creating necessary argument conversions and return value processing.
|
||||||
pub fn process(&mut self, function: &Function) -> Result<&mut Self, Error> {
|
pub fn process(&mut self, function: &Function) -> Result<&mut Self, Error> {
|
||||||
@ -72,6 +85,7 @@ impl<'a, 'b> Rust2Js<'a, 'b> {
|
|||||||
Ok(self)
|
Ok(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get a generated name for an argument.
|
||||||
fn shim_argument(&mut self) -> String {
|
fn shim_argument(&mut self) -> String {
|
||||||
let s = format!("arg{}", self.arg_idx);
|
let s = format!("arg{}", self.arg_idx);
|
||||||
self.arg_idx += 1;
|
self.arg_idx += 1;
|
||||||
@ -515,7 +529,7 @@ impl<'a, 'b> Rust2Js<'a, 'b> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn finish(&self, invoc: &str) -> String {
|
pub fn finish(&self, invoc: &str) -> Result<String, Error> {
|
||||||
let mut ret = String::new();
|
let mut ret = String::new();
|
||||||
ret.push_str("function(");
|
ret.push_str("function(");
|
||||||
ret.push_str(&self.shim_arguments.join(", "));
|
ret.push_str(&self.shim_arguments.join(", "));
|
||||||
@ -528,10 +542,24 @@ impl<'a, 'b> Rust2Js<'a, 'b> {
|
|||||||
ret.push_str(") {\n");
|
ret.push_str(") {\n");
|
||||||
ret.push_str(&self.prelude);
|
ret.push_str(&self.prelude);
|
||||||
|
|
||||||
let mut invoc = self.ret_expr.replace(
|
let mut invoc = if self.variadic {
|
||||||
"JS",
|
if self.js_arguments.is_empty() {
|
||||||
&format!("{}({})", invoc, self.js_arguments.join(", ")),
|
return Err(failure::err_msg("a function with no arguments cannot be variadic"));
|
||||||
);
|
}
|
||||||
|
let last_arg = self.js_arguments.len() - 1; // check implies >= 0
|
||||||
|
self.ret_expr.replace(
|
||||||
|
"JS",
|
||||||
|
&format!("{}({}, ...{})",
|
||||||
|
invoc,
|
||||||
|
self.js_arguments[..last_arg].join(", "),
|
||||||
|
self.js_arguments[last_arg])
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
self.ret_expr.replace(
|
||||||
|
"JS",
|
||||||
|
&format!("{}({})", invoc, self.js_arguments.join(", ")),
|
||||||
|
)
|
||||||
|
};
|
||||||
if self.catch {
|
if self.catch {
|
||||||
let catch = "\
|
let catch = "\
|
||||||
const view = getUint32Memory();\n\
|
const view = getUint32Memory();\n\
|
||||||
@ -566,7 +594,7 @@ impl<'a, 'b> Rust2Js<'a, 'b> {
|
|||||||
ret.push_str(&invoc);
|
ret.push_str(&invoc);
|
||||||
|
|
||||||
ret.push_str("\n}\n");
|
ret.push_str("\n}\n");
|
||||||
return ret;
|
Ok(ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn global_idx(&mut self) -> usize {
|
fn global_idx(&mut self) -> usize {
|
||||||
|
@ -183,6 +183,14 @@ impl BindgenAttrs {
|
|||||||
_ => None,
|
_ => None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Whether the variadic attributes is present
|
||||||
|
fn variadic(&self) -> bool {
|
||||||
|
self.attrs.iter().any(|a| match *a {
|
||||||
|
BindgenAttr::Variadic => true,
|
||||||
|
_ => false,
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl syn::synom::Synom for BindgenAttrs {
|
impl syn::synom::Synom for BindgenAttrs {
|
||||||
@ -219,6 +227,7 @@ pub enum BindgenAttr {
|
|||||||
JsName(String),
|
JsName(String),
|
||||||
JsClass(String),
|
JsClass(String),
|
||||||
Extends(Ident),
|
Extends(Ident),
|
||||||
|
Variadic,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl syn::synom::Synom for BindgenAttr {
|
impl syn::synom::Synom for BindgenAttr {
|
||||||
@ -304,6 +313,8 @@ impl syn::synom::Synom for BindgenAttr {
|
|||||||
ns: call!(term2ident) >>
|
ns: call!(term2ident) >>
|
||||||
(ns)
|
(ns)
|
||||||
)=> { BindgenAttr::Extends }
|
)=> { BindgenAttr::Extends }
|
||||||
|
|
|
||||||
|
call!(term, "variadic") => { |_| BindgenAttr::Variadic }
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -365,6 +376,7 @@ impl<'a> ConvertToAst<()> for &'a mut syn::ItemStruct {
|
|||||||
let getter = shared::struct_field_get(&ident, &name_str);
|
let getter = shared::struct_field_get(&ident, &name_str);
|
||||||
let setter = shared::struct_field_set(&ident, &name_str);
|
let setter = shared::struct_field_set(&ident, &name_str);
|
||||||
let opts = BindgenAttrs::find(&mut field.attrs)?;
|
let opts = BindgenAttrs::find(&mut field.attrs)?;
|
||||||
|
assert_not_variadic(&opts, &field)?;
|
||||||
let comments = extract_doc_comments(&field.attrs);
|
let comments = extract_doc_comments(&field.attrs);
|
||||||
fields.push(ast::StructField {
|
fields.push(ast::StructField {
|
||||||
name: name.clone(),
|
name: name.clone(),
|
||||||
@ -395,6 +407,7 @@ impl<'a> ConvertToAst<(BindgenAttrs, &'a Option<String>)> for syn::ForeignItemFn
|
|||||||
) -> Result<Self::Target, Diagnostic> {
|
) -> Result<Self::Target, Diagnostic> {
|
||||||
let default_name = self.ident.to_string();
|
let default_name = self.ident.to_string();
|
||||||
let js_name = opts.js_name().unwrap_or(&default_name);
|
let js_name = opts.js_name().unwrap_or(&default_name);
|
||||||
|
|
||||||
let wasm = function_from_decl(
|
let wasm = function_from_decl(
|
||||||
js_name,
|
js_name,
|
||||||
self.decl.clone(),
|
self.decl.clone(),
|
||||||
@ -404,6 +417,7 @@ impl<'a> ConvertToAst<(BindgenAttrs, &'a Option<String>)> for syn::ForeignItemFn
|
|||||||
None,
|
None,
|
||||||
)?.0;
|
)?.0;
|
||||||
let catch = opts.catch();
|
let catch = opts.catch();
|
||||||
|
let variadic = opts.variadic();
|
||||||
let js_ret = if catch {
|
let js_ret = if catch {
|
||||||
// TODO: this assumes a whole bunch:
|
// TODO: this assumes a whole bunch:
|
||||||
//
|
//
|
||||||
@ -533,6 +547,7 @@ impl<'a> ConvertToAst<(BindgenAttrs, &'a Option<String>)> for syn::ForeignItemFn
|
|||||||
kind,
|
kind,
|
||||||
js_ret,
|
js_ret,
|
||||||
catch,
|
catch,
|
||||||
|
variadic,
|
||||||
structural: opts.structural(),
|
structural: opts.structural(),
|
||||||
rust_name: self.ident.clone(),
|
rust_name: self.ident.clone(),
|
||||||
shim: Ident::new(&shim, Span::call_site()),
|
shim: Ident::new(&shim, Span::call_site()),
|
||||||
@ -545,6 +560,7 @@ impl ConvertToAst<BindgenAttrs> for syn::ForeignItemType {
|
|||||||
type Target = ast::ImportKind;
|
type Target = ast::ImportKind;
|
||||||
|
|
||||||
fn convert(self, attrs: BindgenAttrs) -> Result<Self::Target, Diagnostic> {
|
fn convert(self, attrs: BindgenAttrs) -> Result<Self::Target, Diagnostic> {
|
||||||
|
assert_not_variadic(&attrs, &self)?;
|
||||||
let js_name = attrs
|
let js_name = attrs
|
||||||
.js_name()
|
.js_name()
|
||||||
.map_or_else(|| self.ident.to_string(), |s| s.to_string());
|
.map_or_else(|| self.ident.to_string(), |s| s.to_string());
|
||||||
@ -570,6 +586,7 @@ impl<'a> ConvertToAst<(BindgenAttrs, &'a Option<String>)> for syn::ForeignItemSt
|
|||||||
if self.mutability.is_some() {
|
if self.mutability.is_some() {
|
||||||
bail_span!(self.mutability, "cannot import mutable globals yet")
|
bail_span!(self.mutability, "cannot import mutable globals yet")
|
||||||
}
|
}
|
||||||
|
assert_not_variadic(&opts, &self)?;
|
||||||
let default_name = self.ident.to_string();
|
let default_name = self.ident.to_string();
|
||||||
let js_name = opts.js_name().unwrap_or(&default_name);
|
let js_name = opts.js_name().unwrap_or(&default_name);
|
||||||
let shim = format!(
|
let shim = format!(
|
||||||
@ -604,6 +621,7 @@ impl ConvertToAst<BindgenAttrs> for syn::ItemFn {
|
|||||||
if self.unsafety.is_some() {
|
if self.unsafety.is_some() {
|
||||||
bail_span!(self.unsafety, "can only #[wasm_bindgen] safe functions");
|
bail_span!(self.unsafety, "can only #[wasm_bindgen] safe functions");
|
||||||
}
|
}
|
||||||
|
assert_not_variadic(&attrs, &self)?;
|
||||||
|
|
||||||
let default_name = self.ident.to_string();
|
let default_name = self.ident.to_string();
|
||||||
let name = attrs.js_name().unwrap_or(&default_name);
|
let name = attrs.js_name().unwrap_or(&default_name);
|
||||||
@ -1074,6 +1092,15 @@ fn assert_no_lifetimes(decl: &syn::FnDecl) -> Result<(), Diagnostic> {
|
|||||||
Diagnostic::from_vec(walk.diagnostics)
|
Diagnostic::from_vec(walk.diagnostics)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This method always fails if the BindgenAttrs contain variadic
|
||||||
|
fn assert_not_variadic(attrs: &BindgenAttrs, span: &dyn ToTokens) -> Result<(), Diagnostic> {
|
||||||
|
if attrs.variadic() {
|
||||||
|
bail_span!(span, "the `variadic` attribute can only be applied to imported \
|
||||||
|
(`extern`) functions")
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
/// If the path is a single ident, return it.
|
/// If the path is a single ident, return it.
|
||||||
fn extract_path_ident(path: &syn::Path) -> Result<Ident, Diagnostic> {
|
fn extract_path_ident(path: &syn::Path) -> Result<Ident, Diagnostic> {
|
||||||
if path.leading_colon.is_some() {
|
if path.leading_colon.is_some() {
|
||||||
|
@ -43,6 +43,7 @@ pub enum ImportKind {
|
|||||||
pub struct ImportFunction {
|
pub struct ImportFunction {
|
||||||
pub shim: String,
|
pub shim: String,
|
||||||
pub catch: bool,
|
pub catch: bool,
|
||||||
|
pub variadic: bool,
|
||||||
pub method: Option<MethodData>,
|
pub method: Option<MethodData>,
|
||||||
pub structural: bool,
|
pub structural: bool,
|
||||||
pub function: Function,
|
pub function: Function,
|
||||||
|
@ -277,6 +277,7 @@ impl<'src> FirstPassRecord<'src> {
|
|||||||
},
|
},
|
||||||
rust_name: rust_ident(rust_name),
|
rust_name: rust_ident(rust_name),
|
||||||
js_ret: js_ret.clone(),
|
js_ret: js_ret.clone(),
|
||||||
|
variadic: false,
|
||||||
catch,
|
catch,
|
||||||
structural,
|
structural,
|
||||||
shim:{
|
shim:{
|
||||||
|
@ -42,6 +42,7 @@
|
|||||||
- [`module = "blah"`](./reference/attributes/on-js-imports/module.md)
|
- [`module = "blah"`](./reference/attributes/on-js-imports/module.md)
|
||||||
- [`static_method_of = Blah`](./reference/attributes/on-js-imports/static_method_of.md)
|
- [`static_method_of = Blah`](./reference/attributes/on-js-imports/static_method_of.md)
|
||||||
- [`structural`](./reference/attributes/on-js-imports/structural.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)
|
- [On Rust Exports](./reference/attributes/on-rust-exports/index.md)
|
||||||
- [`constructor`](./reference/attributes/on-rust-exports/constructor.md)
|
- [`constructor`](./reference/attributes/on-rust-exports/constructor.md)
|
||||||
- [`js_name = Blah`](./reference/attributes/on-rust-exports/js_name.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;
|
fn new() -> Awesome;
|
||||||
#[wasm_bindgen(method)]
|
#[wasm_bindgen(method)]
|
||||||
fn get_internal(this: &Awesome) -> u32;
|
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]
|
#[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);
|
booted.then(main);
|
||||||
```
|
```
|
||||||
|
@ -31,3 +31,4 @@ pub mod slice;
|
|||||||
pub mod structural;
|
pub mod structural;
|
||||||
pub mod u64;
|
pub mod u64;
|
||||||
pub mod validate_prt;
|
pub mod validate_prt;
|
||||||
|
pub mod variadic;
|
||||||
|
59
tests/wasm/variadic.js
Normal file
59
tests/wasm/variadic.js
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
const assert = require('assert');
|
||||||
|
|
||||||
|
// a function for testing numbers
|
||||||
|
function variadic_sum(...args) {
|
||||||
|
let answer = 0;
|
||||||
|
for(var i=0; i<args.length; i++) {
|
||||||
|
answer += args[i];
|
||||||
|
}
|
||||||
|
return answer;
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.variadic_sum_u8 = variadic_sum;
|
||||||
|
exports.variadic_sum_u16 = variadic_sum;
|
||||||
|
exports.variadic_sum_u32 = variadic_sum;
|
||||||
|
exports.variadic_sum_u64 = variadic_sum;
|
||||||
|
exports.variadic_sum_i8 = variadic_sum;
|
||||||
|
exports.variadic_sum_i16 = variadic_sum;
|
||||||
|
exports.variadic_sum_i32 = variadic_sum;
|
||||||
|
exports.variadic_sum_i64 = variadic_sum;
|
||||||
|
exports.variadic_sum_f32 = variadic_sum;
|
||||||
|
exports.variadic_sum_f64 = variadic_sum;
|
||||||
|
exports.variadic_sum_rest_vec = variadic_sum;
|
||||||
|
|
||||||
|
// a function for testing nullable numbers
|
||||||
|
function variadic_sum_opt(...args) {
|
||||||
|
let answer = 0;
|
||||||
|
for(var i=0; i<args.length; i++) {
|
||||||
|
if(args[i] != null) {
|
||||||
|
answer += args[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return answer;
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.variadic_sum_opt = variadic_sum_opt;
|
||||||
|
|
||||||
|
// a function for testing strings
|
||||||
|
function variadic_concat(...args) {
|
||||||
|
let answer = "";
|
||||||
|
for(var i=0; i<args.length; i++) {
|
||||||
|
answer = `${answer}${args[i]}`;
|
||||||
|
}
|
||||||
|
return answer;
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.variadic_concat_str = variadic_concat;
|
||||||
|
exports.variadic_concat_string = variadic_concat;
|
||||||
|
|
||||||
|
// a test that takes any type of arguments (for testing JsValue).
|
||||||
|
function variadic_compare_pairs(...args) {
|
||||||
|
assert(args.length % 2 == 0, "args must be sequence of pairs");
|
||||||
|
for(var i=0; i<args.length; i++) {
|
||||||
|
const first = args[i++];
|
||||||
|
const second = args[i];
|
||||||
|
assert.equal(first, second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.variadic_compare_pairs = variadic_compare_pairs;
|
135
tests/wasm/variadic.rs
Normal file
135
tests/wasm/variadic.rs
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
use wasm_bindgen_test::*;
|
||||||
|
use wasm_bindgen::prelude::*;
|
||||||
|
|
||||||
|
#[wasm_bindgen(module = "tests/wasm/variadic.js")]
|
||||||
|
extern {
|
||||||
|
#[wasm_bindgen(variadic)]
|
||||||
|
fn variadic_sum_u8(first: u8, second: u8, rest: &[u8]) -> u8;
|
||||||
|
#[wasm_bindgen(variadic)]
|
||||||
|
fn variadic_sum_u16(first: u16, second: u16, rest: &[u16]) -> u16;
|
||||||
|
#[wasm_bindgen(variadic)]
|
||||||
|
fn variadic_sum_u32(first: u32, second: u32, rest: &[u32]) -> u32;
|
||||||
|
#[wasm_bindgen(variadic)]
|
||||||
|
fn variadic_sum_u64(first: u64, second: u64, rest: &[u64]) -> u64;
|
||||||
|
//#[wasm_bindgen(variadic)]
|
||||||
|
//fn variadic_sum_usize(first: usize, second: usize, rest: &[usize]) -> usize;
|
||||||
|
#[wasm_bindgen(variadic)]
|
||||||
|
fn variadic_sum_i8(first: i8, second: i8, rest: &[i8]) -> i8;
|
||||||
|
#[wasm_bindgen(variadic)]
|
||||||
|
fn variadic_sum_i16(first: i16, second: i16, rest: &[i16]) -> i16;
|
||||||
|
#[wasm_bindgen(variadic)]
|
||||||
|
fn variadic_sum_i32(first: i32, second: i32, rest: &[i32]) -> i32;
|
||||||
|
#[wasm_bindgen(variadic)]
|
||||||
|
fn variadic_sum_i64(first: i64, second: i64, rest: &[i64]) -> i64;
|
||||||
|
//#[wasm_bindgen(variadic)]
|
||||||
|
//fn variadic_sum_isize(first: isize, second: isize, rest: &[isize]) -> isize;
|
||||||
|
#[wasm_bindgen(variadic)]
|
||||||
|
fn variadic_sum_f32(first: f32, second: f32, rest: &[f32]) -> f32;
|
||||||
|
#[wasm_bindgen(variadic)]
|
||||||
|
fn variadic_sum_f64(first: f64, second: f64, rest: &[f64]) -> f64;
|
||||||
|
//#[wasm_bindgen(variadic)]
|
||||||
|
//fn variadic_sum_opt(first: Option<u32>, second: Option<u32>, rest: &[Option<u32>]) -> u32;
|
||||||
|
//#[wasm_bindgen(variadic)]
|
||||||
|
//fn variadic_concat_str(first: &str, second: &str, rest: &[&str]) -> String;
|
||||||
|
//#[wasm_bindgen(variadic)]
|
||||||
|
//fn variadic_concat_string(first: String,
|
||||||
|
// second: String,
|
||||||
|
// rest: Vec<String>) -> String;
|
||||||
|
#[wasm_bindgen(variadic)]
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
// ints
|
||||||
|
|
||||||
|
macro_rules! variadic_test_int {
|
||||||
|
($fn_name:ident, $extern_name:ident) => {
|
||||||
|
#[wasm_bindgen_test]
|
||||||
|
fn $fn_name() {
|
||||||
|
assert_eq!($extern_name(1, 2, &[]), 3);
|
||||||
|
assert_eq!($extern_name(1, 2, &[3]), 6);
|
||||||
|
assert_eq!($extern_name(1, 2, &[3, 4]), 10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The <int>64 tests throw js `Cannot mix BigInt and other types, use explicit conversions`
|
||||||
|
variadic_test_int!(u8, variadic_sum_u8);
|
||||||
|
variadic_test_int!(u16, variadic_sum_u16);
|
||||||
|
variadic_test_int!(u32, variadic_sum_u32);
|
||||||
|
//variadic_test_int!(u64, variadic_sum_u64);
|
||||||
|
//variadic_test_int!(usize, variadic_sum_usize);
|
||||||
|
variadic_test_int!(i8, variadic_sum_i8);
|
||||||
|
variadic_test_int!(i16, variadic_sum_i16);
|
||||||
|
variadic_test_int!(i32, variadic_sum_i32);
|
||||||
|
//variadic_test_int!(i64, variadic_sum_i64);
|
||||||
|
//variadic_test_int!(isize, variadic_sum_isize);
|
||||||
|
|
||||||
|
// floats
|
||||||
|
|
||||||
|
macro_rules! variadic_test_float {
|
||||||
|
($fn_name:ident, $extern_name:ident) => {
|
||||||
|
#[wasm_bindgen_test]
|
||||||
|
fn $fn_name() {
|
||||||
|
assert_eq!($extern_name(1., 2., &[]), 3.);
|
||||||
|
assert_eq!($extern_name(1., 2., &[3.]), 6.);
|
||||||
|
assert_eq!($extern_name(1., 2., &[3., 4.]), 10.);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
variadic_test_float!(f32, variadic_sum_f32);
|
||||||
|
variadic_test_float!(f64, variadic_sum_f64);
|
||||||
|
|
||||||
|
// strings
|
||||||
|
|
||||||
|
// `the trait `wasm_bindgen::convert::IntoWasmAbi` is not implemented for `&[&str]`
|
||||||
|
/*
|
||||||
|
#[wasm_bindgen_test]
|
||||||
|
fn str() {
|
||||||
|
assert_eq!(variadic_concat_str("a ", "test", &[]), "a test");
|
||||||
|
assert_eq!(variadic_concat_str("a", "nother ", &["test"]), "another test");
|
||||||
|
assert_eq!(variadic_concat_str("yet ", "a", &["nother ", "test"]), "yet another test");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[wasm_bindgen_test]
|
||||||
|
fn string() {
|
||||||
|
assert_eq!(variadic_concat_string("a ".into(), "test".into(), vec![]), "a test");
|
||||||
|
assert_eq!(variadic_concat_string("a".into(), "nother ".into(), vec!["test".into()]),
|
||||||
|
"another test");
|
||||||
|
assert_eq!(variadic_concat_string("yet ".into(),
|
||||||
|
"a".into(),
|
||||||
|
vec!["nother ".into(), "test".into()]),
|
||||||
|
"yet another test");
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
// options
|
||||||
|
|
||||||
|
/*
|
||||||
|
#[wasm_bindgen_test]
|
||||||
|
fn opt() {
|
||||||
|
assert_eq!(variadic_sum_opt(Some(1), None, &[]), 1);
|
||||||
|
assert_eq!(variadic_sum_opt(Some(1), None, &[Some(2)]), 3);
|
||||||
|
assert_eq!(variadic_sum_opt(Some(1), None, &[None, Some(2)]), 3);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
// vec not slice
|
||||||
|
|
||||||
|
#[wasm_bindgen_test]
|
||||||
|
fn rest_vec() {
|
||||||
|
assert_eq!(variadic_sum_rest_vec(1, 2, vec![]), 3);
|
||||||
|
assert_eq!(variadic_sum_rest_vec(1, 2, vec![3]), 6);
|
||||||
|
assert_eq!(variadic_sum_rest_vec(1, 2, vec![3, 4]), 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
// JsValue
|
||||||
|
//#[wasm_bindgen_test]
|
||||||
|
//fn jsvalue() {
|
||||||
|
// variadic_compare_pairs_jsvalue(true, true, vec![]);
|
||||||
|
// variadic_compare_pairs_jsvalue(false, false, vec![3, 3]);
|
||||||
|
//}
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user