mirror of
https://github.com/fluencelabs/wasm-bindgen
synced 2025-06-17 06:51:24 +00:00
Allow returning Result
from functions
This commit adds support for exporting a function defined in Rust that returns a `Result`, translating the `Ok` variant to the actual return value and the `Err` variant to an exception that's thrown in JS. The support for return types and descriptors was rejiggered a bit to be a bit more abstract and more well suited for this purpose. We no longer distinguish between functions with a return value and those without a return value. Additionally a new trait, `ReturnWasmAbi`, is used for converting return values. This trait is an internal implementation detail, however, and shouldn't surface itself to users much (if at all). Closes #841
This commit is contained in:
@ -34,6 +34,7 @@ tys! {
|
||||
RUST_STRUCT
|
||||
CHAR
|
||||
OPTIONAL
|
||||
UNIT
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@ -61,12 +62,13 @@ pub enum Descriptor {
|
||||
RustStruct(String),
|
||||
Char,
|
||||
Option(Box<Descriptor>),
|
||||
Unit,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Function {
|
||||
pub arguments: Vec<Descriptor>,
|
||||
pub ret: Option<Descriptor>,
|
||||
pub ret: Descriptor,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@ -128,6 +130,7 @@ impl Descriptor {
|
||||
Descriptor::RustStruct(name)
|
||||
}
|
||||
CHAR => Descriptor::Char,
|
||||
UNIT => Descriptor::Unit,
|
||||
other => panic!("unknown descriptor: {}", other),
|
||||
}
|
||||
}
|
||||
@ -295,12 +298,10 @@ impl Function {
|
||||
let arguments = (0..get(data))
|
||||
.map(|_| Descriptor::_decode(data))
|
||||
.collect::<Vec<_>>();
|
||||
let ret = if get(data) == 0 {
|
||||
None
|
||||
} else {
|
||||
Some(Descriptor::_decode(data))
|
||||
};
|
||||
Function { arguments, ret }
|
||||
Function {
|
||||
arguments,
|
||||
ret: Descriptor::_decode(data),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -390,15 +390,12 @@ impl<'a, 'b> Js2Rust<'a, 'b> {
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
pub fn ret(&mut self, ret: &Option<Descriptor>) -> Result<&mut Self, Error> {
|
||||
let ty = match *ret {
|
||||
Some(ref t) => t,
|
||||
None => {
|
||||
self.ret_ty = "void".to_string();
|
||||
self.ret_expr = format!("return RET;");
|
||||
return Ok(self);
|
||||
}
|
||||
};
|
||||
pub fn ret(&mut self, ty: &Descriptor) -> Result<&mut Self, Error> {
|
||||
if let Descriptor::Unit = ty {
|
||||
self.ret_ty = "void".to_string();
|
||||
self.ret_expr = format!("return RET;");
|
||||
return Ok(self);
|
||||
}
|
||||
|
||||
let (ty, optional) = match ty {
|
||||
Descriptor::Option(t) => (&**t, true),
|
||||
|
@ -393,6 +393,11 @@ impl<'a> Context<'a> {
|
||||
))
|
||||
})?;
|
||||
|
||||
self.bind("__wbindgen_rethrow", &|me| {
|
||||
me.expose_take_object();
|
||||
Ok(String::from("function(idx) { throw takeObject(idx); }"))
|
||||
})?;
|
||||
|
||||
self.create_memory_export();
|
||||
self.unexport_unused_internal_exports();
|
||||
closures::rewrite(self)?;
|
||||
@ -626,7 +631,9 @@ impl<'a> Context<'a> {
|
||||
|
||||
let set = {
|
||||
let mut cx = Js2Rust::new(&field.name, self);
|
||||
cx.method(true, false).argument(&descriptor)?.ret(&None)?;
|
||||
cx.method(true, false)
|
||||
.argument(&descriptor)?
|
||||
.ret(&Descriptor::Unit)?;
|
||||
ts_dst.push_str(&format!(
|
||||
"{}{}: {}\n",
|
||||
if field.readonly { "readonly " } else { "" },
|
||||
@ -637,7 +644,7 @@ impl<'a> Context<'a> {
|
||||
};
|
||||
let (get, _ts, js_doc) = Js2Rust::new(&field.name, self)
|
||||
.method(true, false)
|
||||
.ret(&Some(descriptor))?
|
||||
.ret(&descriptor)?
|
||||
.finish("", &format!("wasm.{}", wasm_getter));
|
||||
if !dst.ends_with("\n") {
|
||||
dst.push_str("\n");
|
||||
|
@ -285,14 +285,11 @@ impl<'a, 'b> Rust2Js<'a, 'b> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn ret(&mut self, ret: &Option<Descriptor>) -> Result<(), Error> {
|
||||
let ty = match *ret {
|
||||
Some(ref t) => t,
|
||||
None => {
|
||||
self.ret_expr = "JS;".to_string();
|
||||
return Ok(());
|
||||
}
|
||||
};
|
||||
fn ret(&mut self, ty: &Descriptor) -> Result<(), Error> {
|
||||
if let Descriptor::Unit = ty {
|
||||
self.ret_expr = "JS;".to_string();
|
||||
return Ok(());
|
||||
}
|
||||
let (ty, optional) = match ty {
|
||||
Descriptor::Option(t) => (&**t, true),
|
||||
_ => (ty, false),
|
||||
|
Reference in New Issue
Block a user