mirror of
https://github.com/fluencelabs/wasm-bindgen
synced 2025-03-31 01:11:06 +00:00
Overhaul the conversion traits
This commit overhauls the conversion traits used for types crossing the Rust/JS boundary. Previously there were a few ad-hoc traits but now there've been slightly reduced and decoupled. Conversion from Rust values to JS values is now exclusively done through `IntoWasmAbi` with no special treatment for references. Conversion from JS to Rust is a bit trickier as we want to create references in Rust which have implications in terms of safety. As a result there are now three traits for this, `FromWasmAbi`, `RefFromWasmAbi`, and `RefMutFromWasmAbi`. These three traits are implemented for various types and specially dispatched to depending on the type of argument in the code generator. The goal of this commit is to lay the groundwork for using these traits in closures with straightforward-ish definitions.
This commit is contained in:
parent
9976971e7e
commit
0e6325d833
@ -57,8 +57,8 @@ pub struct ImportType {
|
|||||||
|
|
||||||
pub struct Function {
|
pub struct Function {
|
||||||
pub name: syn::Ident,
|
pub name: syn::Ident,
|
||||||
pub arguments: Vec<Type>,
|
pub arguments: Vec<syn::Type>,
|
||||||
pub ret: Option<Type>,
|
pub ret: Option<syn::Type>,
|
||||||
pub opts: BindgenAttrs,
|
pub opts: BindgenAttrs,
|
||||||
pub rust_attrs: Vec<syn::Attribute>,
|
pub rust_attrs: Vec<syn::Attribute>,
|
||||||
pub rust_decl: Box<syn::FnDecl>,
|
pub rust_decl: Box<syn::FnDecl>,
|
||||||
@ -79,12 +79,6 @@ pub struct Variant {
|
|||||||
pub value: u32,
|
pub value: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Type {
|
|
||||||
pub ty: syn::Type,
|
|
||||||
pub kind: TypeKind,
|
|
||||||
pub loc: TypeLocation,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub enum TypeKind {
|
pub enum TypeKind {
|
||||||
ByRef,
|
ByRef,
|
||||||
@ -210,7 +204,6 @@ impl Program {
|
|||||||
opts,
|
opts,
|
||||||
method.vis,
|
method.vis,
|
||||||
true,
|
true,
|
||||||
false,
|
|
||||||
);
|
);
|
||||||
self.exports.push(Export {
|
self.exports.push(Export {
|
||||||
class: Some(class),
|
class: Some(class),
|
||||||
@ -305,7 +298,6 @@ impl Program {
|
|||||||
opts,
|
opts,
|
||||||
f.vis,
|
f.vis,
|
||||||
false,
|
false,
|
||||||
true,
|
|
||||||
).0;
|
).0;
|
||||||
if wasm.opts.catch() {
|
if wasm.opts.catch() {
|
||||||
// TODO: this assumes a whole bunch:
|
// TODO: this assumes a whole bunch:
|
||||||
@ -323,7 +315,15 @@ impl Program {
|
|||||||
let class = wasm.arguments
|
let class = wasm.arguments
|
||||||
.get(0)
|
.get(0)
|
||||||
.expect("methods must have at least one argument");
|
.expect("methods must have at least one argument");
|
||||||
let class_name = match class.ty {
|
let class = match *class {
|
||||||
|
syn::Type::Reference(syn::TypeReference {
|
||||||
|
mutability: None,
|
||||||
|
ref elem,
|
||||||
|
..
|
||||||
|
}) => &**elem,
|
||||||
|
_ => panic!("first argument of method must be a shared reference"),
|
||||||
|
};
|
||||||
|
let class_name = match *class {
|
||||||
syn::Type::Path(syn::TypePath {
|
syn::Type::Path(syn::TypePath {
|
||||||
qself: None,
|
qself: None,
|
||||||
ref path,
|
ref path,
|
||||||
@ -335,11 +335,11 @@ impl Program {
|
|||||||
|
|
||||||
ImportFunctionKind::Method {
|
ImportFunctionKind::Method {
|
||||||
class: class_name.as_ref().to_string(),
|
class: class_name.as_ref().to_string(),
|
||||||
ty: class.ty.clone(),
|
ty: class.clone(),
|
||||||
}
|
}
|
||||||
} else if wasm.opts.constructor() {
|
} else if wasm.opts.constructor() {
|
||||||
let class = match wasm.ret {
|
let class = match wasm.ret {
|
||||||
Some(Type { ref ty, kind: TypeKind::ByValue, .. }) => ty,
|
Some(ref ty) => ty,
|
||||||
_ => panic!("constructor returns must be bare types"),
|
_ => panic!("constructor returns must be bare types"),
|
||||||
};
|
};
|
||||||
let class_name = match *class {
|
let class_name = match *class {
|
||||||
@ -433,7 +433,6 @@ impl Function {
|
|||||||
opts,
|
opts,
|
||||||
input.vis,
|
input.vis,
|
||||||
false,
|
false,
|
||||||
false,
|
|
||||||
).0
|
).0
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -444,7 +443,6 @@ impl Function {
|
|||||||
opts: BindgenAttrs,
|
opts: BindgenAttrs,
|
||||||
vis: syn::Visibility,
|
vis: syn::Visibility,
|
||||||
allow_self: bool,
|
allow_self: bool,
|
||||||
import: bool,
|
|
||||||
) -> (Function, Option<bool>) {
|
) -> (Function, Option<bool>) {
|
||||||
if decl.variadic.is_some() {
|
if decl.variadic.is_some() {
|
||||||
panic!("can't bindgen variadic functions")
|
panic!("can't bindgen variadic functions")
|
||||||
@ -453,6 +451,8 @@ impl Function {
|
|||||||
panic!("can't bindgen functions with lifetime or type parameters")
|
panic!("can't bindgen functions with lifetime or type parameters")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assert_no_lifetimes(&decl);
|
||||||
|
|
||||||
let mut mutable = None;
|
let mut mutable = None;
|
||||||
let arguments = decl.inputs
|
let arguments = decl.inputs
|
||||||
.iter()
|
.iter()
|
||||||
@ -468,24 +468,12 @@ impl Function {
|
|||||||
}
|
}
|
||||||
_ => panic!("arguments cannot be `self` or ignored"),
|
_ => panic!("arguments cannot be `self` or ignored"),
|
||||||
})
|
})
|
||||||
.map(|arg| {
|
.map(|arg| arg.ty.clone())
|
||||||
Type::from(&arg.ty, if import {
|
|
||||||
TypeLocation::ImportArgument
|
|
||||||
} else {
|
|
||||||
TypeLocation::ExportArgument
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
let ret = match decl.output {
|
let ret = match decl.output {
|
||||||
syn::ReturnType::Default => None,
|
syn::ReturnType::Default => None,
|
||||||
syn::ReturnType::Type(_, ref t) => {
|
syn::ReturnType::Type(_, ref t) => Some((**t).clone()),
|
||||||
Some(Type::from(t, if import {
|
|
||||||
TypeLocation::ImportRet
|
|
||||||
} else {
|
|
||||||
TypeLocation::ExportRet
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
(
|
(
|
||||||
@ -663,22 +651,6 @@ impl Struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Type {
|
|
||||||
pub fn from(ty: &syn::Type, loc: TypeLocation) -> Type {
|
|
||||||
let (ty, kind) = match *ty {
|
|
||||||
syn::Type::Reference(ref r) => {
|
|
||||||
if r.mutability.is_some() {
|
|
||||||
((*r.elem).clone(), TypeKind::ByMutRef)
|
|
||||||
} else {
|
|
||||||
((*r.elem).clone(), TypeKind::ByRef)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => (ty.clone(), TypeKind::ByValue),
|
|
||||||
};
|
|
||||||
Type { loc, ty, kind }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct BindgenAttrs {
|
pub struct BindgenAttrs {
|
||||||
attrs: Vec<BindgenAttr>,
|
attrs: Vec<BindgenAttr>,
|
||||||
@ -857,16 +829,12 @@ impl syn::synom::Synom for BindgenAttr {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn extract_first_ty_param(ty: Option<&Type>) -> Option<Option<Type>> {
|
fn extract_first_ty_param(ty: Option<&syn::Type>) -> Option<Option<syn::Type>> {
|
||||||
let t = match ty {
|
let t = match ty {
|
||||||
Some(t) => t,
|
Some(t) => t,
|
||||||
None => return Some(None),
|
None => return Some(None),
|
||||||
};
|
};
|
||||||
let ty = match *t {
|
let path = match *t {
|
||||||
Type { ref ty, kind: TypeKind::ByValue, .. } => ty,
|
|
||||||
_ => return None,
|
|
||||||
};
|
|
||||||
let path = match *ty {
|
|
||||||
syn::Type::Path(syn::TypePath {
|
syn::Type::Path(syn::TypePath {
|
||||||
qself: None,
|
qself: None,
|
||||||
ref path,
|
ref path,
|
||||||
@ -886,11 +854,7 @@ fn extract_first_ty_param(ty: Option<&Type>) -> Option<Option<Type>> {
|
|||||||
syn::Type::Tuple(ref t) if t.elems.len() == 0 => return Some(None),
|
syn::Type::Tuple(ref t) if t.elems.len() == 0 => return Some(None),
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
Some(Some(Type {
|
Some(Some(ty.clone()))
|
||||||
ty: ty.clone(),
|
|
||||||
kind: TypeKind::ByValue,
|
|
||||||
loc: t.loc,
|
|
||||||
}))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn term<'a>(cursor: syn::buffer::Cursor<'a>, name: &str) -> syn::synom::PResult<'a, ()> {
|
fn term<'a>(cursor: syn::buffer::Cursor<'a>, name: &str) -> syn::synom::PResult<'a, ()> {
|
||||||
@ -901,3 +865,16 @@ fn term<'a>(cursor: syn::buffer::Cursor<'a>, name: &str) -> syn::synom::PResult<
|
|||||||
}
|
}
|
||||||
syn::parse_error()
|
syn::parse_error()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn assert_no_lifetimes(decl: &syn::FnDecl) {
|
||||||
|
struct Walk;
|
||||||
|
|
||||||
|
impl<'ast> syn::visit::Visit<'ast> for Walk {
|
||||||
|
fn visit_lifetime(&mut self, _i: &'ast syn::Lifetime) {
|
||||||
|
panic!("it is currently not sound to use lifetimes in function \
|
||||||
|
signatures");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
syn::visit::Visit::visit_fn_decl(&mut Walk, decl);
|
||||||
|
}
|
||||||
|
@ -116,7 +116,7 @@ impl ToTokens for ast::Struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ::wasm_bindgen::convert::WasmBoundary for #name {
|
impl ::wasm_bindgen::convert::IntoWasmAbi for #name {
|
||||||
type Abi = u32;
|
type Abi = u32;
|
||||||
|
|
||||||
fn into_abi(self, _extra: &mut ::wasm_bindgen::convert::Stack)
|
fn into_abi(self, _extra: &mut ::wasm_bindgen::convert::Stack)
|
||||||
@ -124,40 +124,44 @@ impl ToTokens for ast::Struct {
|
|||||||
{
|
{
|
||||||
Box::into_raw(Box::new(::wasm_bindgen::__rt::WasmRefCell::new(self))) as u32
|
Box::into_raw(Box::new(::wasm_bindgen::__rt::WasmRefCell::new(self))) as u32
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
unsafe fn from_abi(js: u32, _extra: &mut ::wasm_bindgen::convert::Stack)
|
impl ::wasm_bindgen::convert::FromWasmAbi for #name {
|
||||||
|
type Abi = u32;
|
||||||
|
|
||||||
|
unsafe fn from_abi(js: u32, extra: &mut ::wasm_bindgen::convert::Stack)
|
||||||
-> Self
|
-> Self
|
||||||
{
|
{
|
||||||
let js = js as *mut ::wasm_bindgen::__rt::WasmRefCell<#name>;
|
let ptr = js as *mut ::wasm_bindgen::__rt::WasmRefCell<#name>;
|
||||||
::wasm_bindgen::__rt::assert_not_null(js);
|
::wasm_bindgen::__rt::assert_not_null(ptr);
|
||||||
let js = Box::from_raw(js);
|
let js = Box::from_raw(ptr);
|
||||||
js.borrow_mut(); // make sure no one's borrowing
|
js.borrow_mut(); // make sure no one's borrowing
|
||||||
js.into_inner()
|
js.into_inner()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ::wasm_bindgen::convert::FromRefWasmBoundary for #name {
|
impl ::wasm_bindgen::convert::RefFromWasmAbi for #name {
|
||||||
type Abi = u32;
|
type Abi = u32;
|
||||||
type RefAnchor = ::wasm_bindgen::__rt::Ref<'static, #name>;
|
type Anchor = ::wasm_bindgen::__rt::Ref<'static, #name>;
|
||||||
|
|
||||||
unsafe fn from_abi_ref(
|
unsafe fn ref_from_abi(
|
||||||
js: Self::Abi,
|
js: Self::Abi,
|
||||||
_extra: &mut ::wasm_bindgen::convert::Stack,
|
_extra: &mut ::wasm_bindgen::convert::Stack,
|
||||||
) -> Self::RefAnchor {
|
) -> Self::Anchor {
|
||||||
let js = js as *mut ::wasm_bindgen::__rt::WasmRefCell<#name>;
|
let js = js as *mut ::wasm_bindgen::__rt::WasmRefCell<#name>;
|
||||||
::wasm_bindgen::__rt::assert_not_null(js);
|
::wasm_bindgen::__rt::assert_not_null(js);
|
||||||
(*js).borrow()
|
(*js).borrow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ::wasm_bindgen::convert::FromRefMutWasmBoundary for #name {
|
impl ::wasm_bindgen::convert::RefMutFromWasmAbi for #name {
|
||||||
type Abi = u32;
|
type Abi = u32;
|
||||||
type RefAnchor = ::wasm_bindgen::__rt::RefMut<'static, #name>;
|
type Anchor = ::wasm_bindgen::__rt::RefMut<'static, #name>;
|
||||||
|
|
||||||
unsafe fn from_abi_ref_mut(
|
unsafe fn ref_mut_from_abi(
|
||||||
js: Self::Abi,
|
js: Self::Abi,
|
||||||
_extra: &mut ::wasm_bindgen::convert::Stack,
|
_extra: &mut ::wasm_bindgen::convert::Stack,
|
||||||
) -> Self::RefAnchor {
|
) -> Self::Anchor {
|
||||||
let js = js as *mut ::wasm_bindgen::__rt::WasmRefCell<#name>;
|
let js = js as *mut ::wasm_bindgen::__rt::WasmRefCell<#name>;
|
||||||
::wasm_bindgen::__rt::assert_not_null(js);
|
::wasm_bindgen::__rt::assert_not_null(js);
|
||||||
(*js).borrow_mut()
|
(*js).borrow_mut()
|
||||||
@ -166,7 +170,7 @@ impl ToTokens for ast::Struct {
|
|||||||
|
|
||||||
impl ::std::convert::From<#name> for ::wasm_bindgen::JsValue {
|
impl ::std::convert::From<#name> for ::wasm_bindgen::JsValue {
|
||||||
fn from(value: #name) -> Self {
|
fn from(value: #name) -> Self {
|
||||||
let ptr = ::wasm_bindgen::convert::WasmBoundary::into_abi(
|
let ptr = ::wasm_bindgen::convert::IntoWasmAbi::into_abi(
|
||||||
value,
|
value,
|
||||||
unsafe { &mut ::wasm_bindgen::convert::GlobalStack::new() },
|
unsafe { &mut ::wasm_bindgen::convert::GlobalStack::new() },
|
||||||
);
|
);
|
||||||
@ -177,7 +181,7 @@ impl ToTokens for ast::Struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
<::wasm_bindgen::JsValue as ::wasm_bindgen::convert::WasmBoundary>
|
<::wasm_bindgen::JsValue as ::wasm_bindgen::convert::FromWasmAbi>
|
||||||
::from_abi(
|
::from_abi(
|
||||||
#new_fn(ptr),
|
#new_fn(ptr),
|
||||||
&mut ::wasm_bindgen::convert::GlobalStack::new(),
|
&mut ::wasm_bindgen::convert::GlobalStack::new(),
|
||||||
@ -188,7 +192,7 @@ impl ToTokens for ast::Struct {
|
|||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern fn #free_fn(ptr: u32) {
|
pub unsafe extern fn #free_fn(ptr: u32) {
|
||||||
<#name as ::wasm_bindgen::convert::WasmBoundary>::from_abi(
|
<#name as ::wasm_bindgen::convert::FromWasmAbi>::from_abi(
|
||||||
ptr,
|
ptr,
|
||||||
&mut ::wasm_bindgen::convert::GlobalStack::new(),
|
&mut ::wasm_bindgen::convert::GlobalStack::new(),
|
||||||
);
|
);
|
||||||
@ -220,41 +224,44 @@ impl ToTokens for ast::Export {
|
|||||||
for (i, ty) in self.function.arguments.iter().enumerate() {
|
for (i, ty) in self.function.arguments.iter().enumerate() {
|
||||||
let i = i + offset;
|
let i = i + offset;
|
||||||
let ident = syn::Ident::from(format!("arg{}", i));
|
let ident = syn::Ident::from(format!("arg{}", i));
|
||||||
let t = &ty.ty;
|
match *ty {
|
||||||
match ty.kind {
|
syn::Type::Reference(syn::TypeReference {
|
||||||
ast::TypeKind::ByValue => {
|
mutability: Some(_),
|
||||||
|
ref elem,
|
||||||
|
..
|
||||||
|
}) => {
|
||||||
args.push(quote! {
|
args.push(quote! {
|
||||||
#ident: <#t as ::wasm_bindgen::convert::WasmBoundary>::Abi
|
#ident: <#elem as ::wasm_bindgen::convert::RefMutFromWasmAbi>::Abi
|
||||||
});
|
});
|
||||||
arg_conversions.push(quote! {
|
arg_conversions.push(quote! {
|
||||||
let #ident = unsafe {
|
let mut #ident = unsafe {
|
||||||
<#t as ::wasm_bindgen::convert::WasmBoundary>
|
<#elem as ::wasm_bindgen::convert::RefMutFromWasmAbi>
|
||||||
::from_abi(#ident, &mut __stack)
|
::ref_mut_from_abi(#ident, &mut __stack)
|
||||||
};
|
};
|
||||||
|
let #ident = &mut *#ident;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
ast::TypeKind::ByRef => {
|
syn::Type::Reference(syn::TypeReference { ref elem, .. }) => {
|
||||||
args.push(quote! {
|
args.push(quote! {
|
||||||
#ident: <#t as ::wasm_bindgen::convert::FromRefWasmBoundary>::Abi
|
#ident: <#elem as ::wasm_bindgen::convert::RefFromWasmAbi>::Abi
|
||||||
});
|
});
|
||||||
arg_conversions.push(quote! {
|
arg_conversions.push(quote! {
|
||||||
let #ident = unsafe {
|
let #ident = unsafe {
|
||||||
<#t as ::wasm_bindgen::convert::FromRefWasmBoundary>
|
<#elem as ::wasm_bindgen::convert::RefFromWasmAbi>
|
||||||
::from_abi_ref(#ident, &mut __stack)
|
::ref_from_abi(#ident, &mut __stack)
|
||||||
};
|
};
|
||||||
let #ident = &*#ident;
|
let #ident = &*#ident;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
ast::TypeKind::ByMutRef => {
|
_ => {
|
||||||
args.push(quote! {
|
args.push(quote! {
|
||||||
#ident: <#t as ::wasm_bindgen::convert::FromRefMutWasmBoundary>::Abi
|
#ident: <#ty as ::wasm_bindgen::convert::FromWasmAbi>::Abi
|
||||||
});
|
});
|
||||||
arg_conversions.push(quote! {
|
arg_conversions.push(quote! {
|
||||||
let mut #ident = unsafe {
|
let #ident = unsafe {
|
||||||
<#t as ::wasm_bindgen::convert::FromRefMutWasmBoundary>
|
<#ty as ::wasm_bindgen::convert::FromWasmAbi>
|
||||||
::from_abi_ref_mut(#ident, &mut __stack)
|
::from_abi(#ident, &mut __stack)
|
||||||
};
|
};
|
||||||
let #ident = &mut *#ident;
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -263,28 +270,25 @@ impl ToTokens for ast::Export {
|
|||||||
let ret_ty;
|
let ret_ty;
|
||||||
let convert_ret;
|
let convert_ret;
|
||||||
match self.function.ret {
|
match self.function.ret {
|
||||||
Some(ast::Type { ref ty, kind: ast::TypeKind::ByValue, .. }) => {
|
Some(syn::Type::Reference(_)) => panic!("can't return a borrowed ref"),
|
||||||
|
Some(ref ty) => {
|
||||||
ret_ty = quote! {
|
ret_ty = quote! {
|
||||||
-> <#ty as ::wasm_bindgen::convert::WasmBoundary>::Abi
|
-> <#ty as ::wasm_bindgen::convert::IntoWasmAbi>::Abi
|
||||||
};
|
};
|
||||||
convert_ret = quote! {
|
convert_ret = quote! {
|
||||||
<#ty as ::wasm_bindgen::convert::WasmBoundary>
|
<#ty as ::wasm_bindgen::convert::IntoWasmAbi>
|
||||||
::into_abi(#ret, &mut unsafe {
|
::into_abi(#ret, &mut unsafe {
|
||||||
::wasm_bindgen::convert::GlobalStack::new()
|
::wasm_bindgen::convert::GlobalStack::new()
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
Some(ast::Type { kind: ast::TypeKind::ByMutRef, .. }) |
|
|
||||||
Some(ast::Type { kind: ast::TypeKind::ByRef, .. }) => {
|
|
||||||
panic!("can't return a borrowed ref");
|
|
||||||
}
|
|
||||||
None => {
|
None => {
|
||||||
ret_ty = quote!{};
|
ret_ty = quote!{};
|
||||||
convert_ret = quote!{};
|
convert_ret = quote!{};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let describe_ret = match self.function.ret {
|
let describe_ret = match self.function.ret {
|
||||||
Some(ast::Type { ref ty, .. }) => {
|
Some(ref ty) => {
|
||||||
quote! {
|
quote! {
|
||||||
inform(1);
|
inform(1);
|
||||||
<#ty as WasmDescribe>::describe();
|
<#ty as WasmDescribe>::describe();
|
||||||
@ -380,47 +384,55 @@ impl ToTokens for ast::ImportType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ::wasm_bindgen::convert::WasmBoundary for #name {
|
impl ::wasm_bindgen::convert::IntoWasmAbi for #name {
|
||||||
type Abi = <::wasm_bindgen::JsValue as
|
type Abi = <::wasm_bindgen::JsValue as
|
||||||
::wasm_bindgen::convert::WasmBoundary>::Abi;
|
::wasm_bindgen::convert::IntoWasmAbi>::Abi;
|
||||||
|
|
||||||
fn into_abi(self, extra: &mut ::wasm_bindgen::convert::Stack) -> Self::Abi {
|
fn into_abi(self, extra: &mut ::wasm_bindgen::convert::Stack) -> Self::Abi {
|
||||||
self.obj.into_abi(extra)
|
self.obj.into_abi(extra)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ::wasm_bindgen::convert::FromWasmAbi for #name {
|
||||||
|
type Abi = <::wasm_bindgen::JsValue as
|
||||||
|
::wasm_bindgen::convert::FromWasmAbi>::Abi;
|
||||||
|
|
||||||
unsafe fn from_abi(
|
unsafe fn from_abi(
|
||||||
js: Self::Abi,
|
js: Self::Abi,
|
||||||
extra: &mut ::wasm_bindgen::convert::Stack,
|
extra: &mut ::wasm_bindgen::convert::Stack,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
#name { obj: ::wasm_bindgen::JsValue::from_abi(js, extra) }
|
#name {
|
||||||
|
obj: ::wasm_bindgen::JsValue::from_abi(js, extra),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ::wasm_bindgen::convert::ToRefWasmBoundary for #name {
|
impl<'a> ::wasm_bindgen::convert::IntoWasmAbi for &'a #name {
|
||||||
type Abi = <::wasm_bindgen::JsValue as
|
type Abi = <&'a ::wasm_bindgen::JsValue as
|
||||||
::wasm_bindgen::convert::ToRefWasmBoundary>::Abi;
|
::wasm_bindgen::convert::IntoWasmAbi>::Abi;
|
||||||
|
|
||||||
fn to_abi_ref(&self, extra: &mut ::wasm_bindgen::convert::Stack) -> u32 {
|
fn into_abi(self, extra: &mut ::wasm_bindgen::convert::Stack) -> Self::Abi {
|
||||||
self.obj.to_abi_ref(extra)
|
(&self.obj).into_abi(extra)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ::wasm_bindgen::convert::FromRefWasmBoundary for #name {
|
impl ::wasm_bindgen::convert::RefFromWasmAbi for #name {
|
||||||
type Abi = <::wasm_bindgen::JsValue as
|
type Abi = <::wasm_bindgen::JsValue as
|
||||||
::wasm_bindgen::convert::ToRefWasmBoundary>::Abi;
|
::wasm_bindgen::convert::RefFromWasmAbi>::Abi;
|
||||||
type RefAnchor = ::std::mem::ManuallyDrop<#name>;
|
type Anchor = ::std::mem::ManuallyDrop<#name>;
|
||||||
|
|
||||||
unsafe fn from_abi_ref(
|
unsafe fn ref_from_abi(
|
||||||
js: Self::Abi,
|
js: Self::Abi,
|
||||||
extra: &mut ::wasm_bindgen::convert::Stack,
|
extra: &mut ::wasm_bindgen::convert::Stack,
|
||||||
) -> Self::RefAnchor {
|
) -> Self::Anchor {
|
||||||
let obj = <::wasm_bindgen::JsValue as ::wasm_bindgen::convert::WasmBoundary>
|
let tmp = <::wasm_bindgen::JsValue as ::wasm_bindgen::convert::RefFromWasmAbi>
|
||||||
::from_abi(js, extra);
|
::ref_from_abi(js, extra);
|
||||||
::std::mem::ManuallyDrop::new(#name { obj })
|
::std::mem::ManuallyDrop::new(#name {
|
||||||
|
obj: ::std::mem::ManuallyDrop::into_inner(tmp),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl From<::wasm_bindgen::JsValue> for #name {
|
impl From<::wasm_bindgen::JsValue> for #name {
|
||||||
fn from(obj: ::wasm_bindgen::JsValue) -> #name {
|
fn from(obj: ::wasm_bindgen::JsValue) -> #name {
|
||||||
#name { obj }
|
#name { obj }
|
||||||
@ -478,65 +490,38 @@ impl ToTokens for ast::ImportFunction {
|
|||||||
});
|
});
|
||||||
|
|
||||||
for (i, (ty, name)) in self.function.arguments.iter().zip(names).enumerate() {
|
for (i, (ty, name)) in self.function.arguments.iter().zip(names).enumerate() {
|
||||||
let t = &ty.ty;
|
abi_argument_names.push(name);
|
||||||
match ty.kind {
|
abi_arguments.push(quote! {
|
||||||
ast::TypeKind::ByValue => {
|
#name: <#ty as ::wasm_bindgen::convert::IntoWasmAbi>::Abi
|
||||||
abi_argument_names.push(name);
|
});
|
||||||
abi_arguments.push(quote! {
|
let var = if i == 0 && is_method {
|
||||||
#name: <#t as ::wasm_bindgen::convert::WasmBoundary>::Abi
|
quote! { self }
|
||||||
});
|
} else {
|
||||||
let var = if i == 0 && is_method {
|
quote! { #name }
|
||||||
quote! { self }
|
};
|
||||||
} else {
|
arg_conversions.push(quote! {
|
||||||
quote! { #name }
|
let #name = <#ty as ::wasm_bindgen::convert::IntoWasmAbi>
|
||||||
};
|
::into_abi(#var, &mut __stack);
|
||||||
arg_conversions.push(quote! {
|
});
|
||||||
let #name = <#t as ::wasm_bindgen::convert::WasmBoundary>
|
|
||||||
::into_abi(#var, &mut __stack);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
ast::TypeKind::ByMutRef => {
|
|
||||||
abi_argument_names.push(name);
|
|
||||||
abi_arguments.push(quote! { #name: u32 });
|
|
||||||
arg_conversions.push(quote! {
|
|
||||||
let #name = <#t as ::wasm_bindgen::convert::ToRefMutWasmBoundary>
|
|
||||||
::to_abi_ref_mut(#name, &mut __stack);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
ast::TypeKind::ByRef => {
|
|
||||||
abi_argument_names.push(name);
|
|
||||||
abi_arguments.push(quote! { #name: u32 });
|
|
||||||
let var = if i == 0 && is_method {
|
|
||||||
quote! { self }
|
|
||||||
} else {
|
|
||||||
quote! { #name }
|
|
||||||
};
|
|
||||||
arg_conversions.push(quote! {
|
|
||||||
let #name = <#t as ::wasm_bindgen::convert::ToRefWasmBoundary>
|
|
||||||
::to_abi_ref(#var, &mut __stack);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
let abi_ret;
|
let abi_ret;
|
||||||
let mut convert_ret;
|
let mut convert_ret;
|
||||||
match self.function.ret {
|
match self.function.ret {
|
||||||
Some(ast::Type { ref ty, kind: ast::TypeKind::ByValue, .. }) => {
|
Some(syn::Type::Reference(_)) => {
|
||||||
|
panic!("cannot return references in imports yet");
|
||||||
|
}
|
||||||
|
Some(ref ty) => {
|
||||||
abi_ret = quote! {
|
abi_ret = quote! {
|
||||||
<#ty as ::wasm_bindgen::convert::WasmBoundary>::Abi
|
<#ty as ::wasm_bindgen::convert::FromWasmAbi>::Abi
|
||||||
};
|
};
|
||||||
convert_ret = quote! {
|
convert_ret = quote! {
|
||||||
<#ty as ::wasm_bindgen::convert::WasmBoundary>
|
<#ty as ::wasm_bindgen::convert::FromWasmAbi>
|
||||||
::from_abi(
|
::from_abi(
|
||||||
#ret_ident,
|
#ret_ident,
|
||||||
&mut ::wasm_bindgen::convert::GlobalStack::new(),
|
&mut ::wasm_bindgen::convert::GlobalStack::new(),
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
Some(ast::Type { kind: ast::TypeKind::ByRef, .. }) |
|
|
||||||
Some(ast::Type { kind: ast::TypeKind::ByMutRef, .. }) => {
|
|
||||||
panic!("can't return a borrowed ref")
|
|
||||||
}
|
|
||||||
None => {
|
None => {
|
||||||
abi_ret = quote! { () };
|
abi_ret = quote! { () };
|
||||||
convert_ret = quote! { () };
|
convert_ret = quote! { () };
|
||||||
@ -554,8 +539,8 @@ impl ToTokens for ast::ImportFunction {
|
|||||||
if #exn_data[0] == 1 {
|
if #exn_data[0] == 1 {
|
||||||
return Err(
|
return Err(
|
||||||
<
|
<
|
||||||
::wasm_bindgen::JsValue as ::wasm_bindgen::convert::WasmBoundary
|
::wasm_bindgen::JsValue as ::wasm_bindgen::convert::FromWasmAbi
|
||||||
>::from_abi(#exn_data[1], &mut ::wasm_bindgen::convert::GlobalStack::new()),
|
>::from_abi(#exn_data[1], &mut ::wasm_bindgen::convert::GlobalStack::new())
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -663,12 +648,16 @@ impl ToTokens for ast::Enum {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
(quote! {
|
(quote! {
|
||||||
impl ::wasm_bindgen::convert::WasmBoundary for #enum_name {
|
impl ::wasm_bindgen::convert::IntoWasmAbi for #enum_name {
|
||||||
type Abi = u32;
|
type Abi = u32;
|
||||||
|
|
||||||
fn into_abi(self, _extra: &mut ::wasm_bindgen::convert::Stack) -> u32 {
|
fn into_abi(self, _extra: &mut ::wasm_bindgen::convert::Stack) -> u32 {
|
||||||
self as u32
|
self as u32
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ::wasm_bindgen::convert::FromWasmAbi for #enum_name {
|
||||||
|
type Abi = u32;
|
||||||
|
|
||||||
unsafe fn from_abi(
|
unsafe fn from_abi(
|
||||||
js: u32,
|
js: u32,
|
||||||
@ -702,13 +691,14 @@ impl ToTokens for ast::ImportStatic {
|
|||||||
fn init() -> #ty {
|
fn init() -> #ty {
|
||||||
#[wasm_import_module = "__wbindgen_placeholder__"]
|
#[wasm_import_module = "__wbindgen_placeholder__"]
|
||||||
extern {
|
extern {
|
||||||
fn #shim_name() -> <#ty as ::wasm_bindgen::convert::WasmBoundary>::Abi;
|
fn #shim_name() -> <#ty as ::wasm_bindgen::convert::FromWasmAbi>::Abi;
|
||||||
}
|
}
|
||||||
unsafe {
|
unsafe {
|
||||||
::wasm_bindgen::convert::WasmBoundary::from_abi(
|
<#ty as ::wasm_bindgen::convert::FromWasmAbi>::from_abi(
|
||||||
#shim_name(),
|
#shim_name(),
|
||||||
&mut ::wasm_bindgen::convert::GlobalStack::new(),
|
&mut ::wasm_bindgen::convert::GlobalStack::new(),
|
||||||
)
|
)
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
::wasm_bindgen::JsStatic {
|
::wasm_bindgen::JsStatic {
|
||||||
@ -719,19 +709,3 @@ impl ToTokens for ast::ImportStatic {
|
|||||||
}).to_tokens(into);
|
}).to_tokens(into);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToTokens for ast::Type {
|
|
||||||
fn to_tokens(&self, into: &mut Tokens) {
|
|
||||||
match self.kind {
|
|
||||||
ast::TypeKind::ByValue => {}
|
|
||||||
ast::TypeKind::ByRef => {
|
|
||||||
syn::token::And::default().to_tokens(into);
|
|
||||||
}
|
|
||||||
ast::TypeKind::ByMutRef => {
|
|
||||||
syn::token::And::default().to_tokens(into);
|
|
||||||
syn::token::Mut::default().to_tokens(into);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self.ty.to_tokens(into);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -8,7 +8,7 @@ use shared;
|
|||||||
use wasm_gc;
|
use wasm_gc;
|
||||||
|
|
||||||
use super::Bindgen;
|
use super::Bindgen;
|
||||||
use descriptor::{Descriptor, VectorKind};
|
use descriptor::{Descriptor, VectorKind, Function};
|
||||||
|
|
||||||
pub struct Context<'a> {
|
pub struct Context<'a> {
|
||||||
pub globals: String,
|
pub globals: String,
|
||||||
@ -1311,10 +1311,12 @@ impl<'a, 'b> SubContext<'a, 'b> {
|
|||||||
if let Some(ref class) = export.class {
|
if let Some(ref class) = export.class {
|
||||||
return self.generate_export_for_class(class, export);
|
return self.generate_export_for_class(class, export);
|
||||||
}
|
}
|
||||||
|
let descriptor = self.cx.describe(&export.function.name);
|
||||||
let (js, ts) = self.generate_function("function",
|
let (js, ts) = self.generate_function("function",
|
||||||
|
&export.function.name,
|
||||||
&export.function.name,
|
&export.function.name,
|
||||||
false,
|
false,
|
||||||
&export.function);
|
descriptor.unwrap_function());
|
||||||
self.cx.export(&export.function.name, &js);
|
self.cx.export(&export.function.name, &js);
|
||||||
self.cx.globals.push_str("\n");
|
self.cx.globals.push_str("\n");
|
||||||
self.cx.typescript.push_str("export ");
|
self.cx.typescript.push_str("export ");
|
||||||
@ -1323,11 +1325,14 @@ impl<'a, 'b> SubContext<'a, 'b> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn generate_export_for_class(&mut self, class: &str, export: &shared::Export) {
|
pub fn generate_export_for_class(&mut self, class: &str, export: &shared::Export) {
|
||||||
|
let wasm_name = shared::struct_function_export_name(class, &export.function.name);
|
||||||
|
let descriptor = self.cx.describe(&wasm_name);
|
||||||
let (js, ts) = self.generate_function(
|
let (js, ts) = self.generate_function(
|
||||||
"",
|
"",
|
||||||
&shared::struct_function_export_name(class, &export.function.name),
|
&export.function.name,
|
||||||
|
&wasm_name,
|
||||||
export.method,
|
export.method,
|
||||||
&export.function,
|
&descriptor.unwrap_function(),
|
||||||
);
|
);
|
||||||
let class = self.cx.exported_classes.entry(class.to_string())
|
let class = self.cx.exported_classes.entry(class.to_string())
|
||||||
.or_insert(ExportedClass::default());
|
.or_insert(ExportedClass::default());
|
||||||
@ -1344,13 +1349,12 @@ impl<'a, 'b> SubContext<'a, 'b> {
|
|||||||
|
|
||||||
fn generate_function(&mut self,
|
fn generate_function(&mut self,
|
||||||
prefix: &str,
|
prefix: &str,
|
||||||
|
js_name: &str,
|
||||||
wasm_name: &str,
|
wasm_name: &str,
|
||||||
is_method: bool,
|
is_method: bool,
|
||||||
function: &shared::Function) -> (String, String) {
|
function: &Function) -> (String, String) {
|
||||||
let descriptor = self.cx.describe(wasm_name);
|
|
||||||
let desc_function = descriptor.unwrap_function();
|
|
||||||
let mut dst = String::from("(");
|
let mut dst = String::from("(");
|
||||||
let mut dst_ts = format!("{}(", function.name);
|
let mut dst_ts = format!("{}(", js_name);
|
||||||
let mut passed_args = String::new();
|
let mut passed_args = String::new();
|
||||||
let mut arg_conversions = String::new();
|
let mut arg_conversions = String::new();
|
||||||
let mut destructors = String::new();
|
let mut destructors = String::new();
|
||||||
@ -1360,7 +1364,7 @@ impl<'a, 'b> SubContext<'a, 'b> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let mut global_idx = 0;
|
let mut global_idx = 0;
|
||||||
for (i, arg) in desc_function.arguments.iter().enumerate() {
|
for (i, arg) in function.arguments.iter().enumerate() {
|
||||||
let name = format!("arg{}", i);
|
let name = format!("arg{}", i);
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
dst.push_str(", ");
|
dst.push_str(", ");
|
||||||
@ -1459,7 +1463,7 @@ impl<'a, 'b> SubContext<'a, 'b> {
|
|||||||
}
|
}
|
||||||
dst.push_str(")");
|
dst.push_str(")");
|
||||||
dst_ts.push_str(")");
|
dst_ts.push_str(")");
|
||||||
let convert_ret = self.cx.return_from_rust(&desc_function.ret, &mut dst_ts);
|
let convert_ret = self.cx.return_from_rust(&function.ret, &mut dst_ts);
|
||||||
dst_ts.push_str(";");
|
dst_ts.push_str(";");
|
||||||
dst.push_str(" {\n ");
|
dst.push_str(" {\n ");
|
||||||
dst.push_str(&arg_conversions);
|
dst.push_str(&arg_conversions);
|
||||||
|
@ -99,7 +99,7 @@ impl<T> Closure<T>
|
|||||||
let js = T::factory()(T::shim(), data[0], data[1]);
|
let js = T::factory()(T::shim(), data[0], data[1]);
|
||||||
Closure {
|
Closure {
|
||||||
_inner: t,
|
_inner: t,
|
||||||
js: ManuallyDrop::new(JsValue::from_abi(js, &mut GlobalStack::new())),
|
js: ManuallyDrop::new(JsValue { idx: js }),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -117,7 +117,7 @@ impl<T> Closure<T>
|
|||||||
/// cleanup as it can.
|
/// cleanup as it can.
|
||||||
pub fn forget(self) {
|
pub fn forget(self) {
|
||||||
unsafe {
|
unsafe {
|
||||||
super::__wbindgen_cb_forget(self.js.to_abi_ref(&mut GlobalStack::new()));
|
super::__wbindgen_cb_forget(self.js.idx);
|
||||||
mem::forget(self);
|
mem::forget(self);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -133,13 +133,13 @@ impl<T> WasmDescribe for Closure<T>
|
|||||||
}
|
}
|
||||||
|
|
||||||
// `Closure` can only be passed by reference to imports.
|
// `Closure` can only be passed by reference to imports.
|
||||||
impl<T> ToRefWasmBoundary for Closure<T>
|
impl<'a, T> IntoWasmAbi for &'a Closure<T>
|
||||||
where T: WasmShim + ?Sized,
|
where T: WasmShim + ?Sized,
|
||||||
{
|
{
|
||||||
type Abi = u32;
|
type Abi = u32;
|
||||||
|
|
||||||
fn to_abi_ref(&self, extra: &mut Stack) -> u32 {
|
fn into_abi(self, _extra: &mut Stack) -> u32 {
|
||||||
self.js.to_abi_ref(extra)
|
self.js.idx
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -148,8 +148,7 @@ impl<T> Drop for Closure<T>
|
|||||||
{
|
{
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let idx = self.js.to_abi_ref(&mut GlobalStack::new());
|
super::__wbindgen_cb_drop(self.js.idx);
|
||||||
super::__wbindgen_cb_drop(idx);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
205
src/convert.rs
205
src/convert.rs
@ -15,37 +15,27 @@ pub struct Descriptor {
|
|||||||
pub __x: [u8; 4],
|
pub __x: [u8; 4],
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait WasmBoundary: WasmDescribe {
|
pub trait IntoWasmAbi: WasmDescribe {
|
||||||
type Abi: WasmAbi;
|
type Abi: WasmAbi;
|
||||||
|
|
||||||
fn into_abi(self, extra: &mut Stack) -> Self::Abi;
|
fn into_abi(self, extra: &mut Stack) -> Self::Abi;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait FromWasmAbi: WasmDescribe {
|
||||||
|
type Abi: WasmAbi;
|
||||||
unsafe fn from_abi(js: Self::Abi, extra: &mut Stack) -> Self;
|
unsafe fn from_abi(js: Self::Abi, extra: &mut Stack) -> Self;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait FromRefWasmBoundary: WasmDescribe {
|
pub trait RefFromWasmAbi: WasmDescribe {
|
||||||
type Abi: WasmAbi;
|
type Abi: WasmAbi;
|
||||||
type RefAnchor: Deref<Target = Self>;
|
type Anchor: Deref<Target=Self>;
|
||||||
|
unsafe fn ref_from_abi(js: Self::Abi, extra: &mut Stack) -> Self::Anchor;
|
||||||
unsafe fn from_abi_ref(js: Self::Abi, extra: &mut Stack) -> Self::RefAnchor;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait FromRefMutWasmBoundary: WasmDescribe {
|
pub trait RefMutFromWasmAbi: WasmDescribe {
|
||||||
type Abi: WasmAbi;
|
type Abi: WasmAbi;
|
||||||
type RefAnchor: DerefMut<Target = Self>;
|
type Anchor: DerefMut<Target=Self>;
|
||||||
|
unsafe fn ref_mut_from_abi(js: Self::Abi, extra: &mut Stack) -> Self::Anchor;
|
||||||
unsafe fn from_abi_ref_mut(js: Self::Abi, extra: &mut Stack) -> Self::RefAnchor;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait ToRefWasmBoundary: WasmDescribe {
|
|
||||||
type Abi: WasmAbi;
|
|
||||||
|
|
||||||
fn to_abi_ref(&self, extra: &mut Stack) -> u32;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait ToRefMutWasmBoundary: WasmDescribe {
|
|
||||||
type Abi: WasmAbi;
|
|
||||||
|
|
||||||
fn to_abi_ref_mut(&mut self, extra: &mut Stack) -> u32;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Stack {
|
pub trait Stack {
|
||||||
@ -70,10 +60,13 @@ unsafe impl WasmAbi for f64 {}
|
|||||||
|
|
||||||
macro_rules! simple {
|
macro_rules! simple {
|
||||||
($($t:tt)*) => ($(
|
($($t:tt)*) => ($(
|
||||||
impl WasmBoundary for $t {
|
impl IntoWasmAbi for $t {
|
||||||
type Abi = $t;
|
type Abi = $t;
|
||||||
|
|
||||||
fn into_abi(self, _extra: &mut Stack) -> $t { self }
|
fn into_abi(self, _extra: &mut Stack) -> $t { self }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromWasmAbi for $t {
|
||||||
|
type Abi = $t;
|
||||||
unsafe fn from_abi(js: $t, _extra: &mut Stack) -> $t { js }
|
unsafe fn from_abi(js: $t, _extra: &mut Stack) -> $t { js }
|
||||||
}
|
}
|
||||||
)*)
|
)*)
|
||||||
@ -83,10 +76,13 @@ simple!(u32 u64 i32 i64 f32 f64);
|
|||||||
|
|
||||||
macro_rules! as_u32 {
|
macro_rules! as_u32 {
|
||||||
($($t:tt)*) => ($(
|
($($t:tt)*) => ($(
|
||||||
impl WasmBoundary for $t {
|
impl IntoWasmAbi for $t {
|
||||||
type Abi = u32;
|
type Abi = u32;
|
||||||
|
|
||||||
fn into_abi(self, _extra: &mut Stack) -> u32 { self as u32 }
|
fn into_abi(self, _extra: &mut Stack) -> u32 { self as u32 }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromWasmAbi for $t {
|
||||||
|
type Abi = u32;
|
||||||
unsafe fn from_abi(js: u32, _extra: &mut Stack) -> $t { js as $t }
|
unsafe fn from_abi(js: u32, _extra: &mut Stack) -> $t { js as $t }
|
||||||
}
|
}
|
||||||
)*)
|
)*)
|
||||||
@ -94,30 +90,49 @@ macro_rules! as_u32 {
|
|||||||
|
|
||||||
as_u32!(i8 u8 i16 u16 isize usize);
|
as_u32!(i8 u8 i16 u16 isize usize);
|
||||||
|
|
||||||
impl WasmBoundary for bool {
|
impl IntoWasmAbi for bool {
|
||||||
type Abi = u32;
|
type Abi = u32;
|
||||||
|
|
||||||
fn into_abi(self, _extra: &mut Stack) -> u32 { self as u32 }
|
fn into_abi(self, _extra: &mut Stack) -> u32 { self as u32 }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromWasmAbi for bool {
|
||||||
|
type Abi = u32;
|
||||||
|
|
||||||
unsafe fn from_abi(js: u32, _extra: &mut Stack) -> bool { js != 0 }
|
unsafe fn from_abi(js: u32, _extra: &mut Stack) -> bool { js != 0 }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> WasmBoundary for *const T {
|
impl<T> IntoWasmAbi for *const T {
|
||||||
type Abi = u32;
|
type Abi = u32;
|
||||||
|
|
||||||
fn into_abi(self, _extra: &mut Stack) -> u32 { self as u32 }
|
fn into_abi(self, _extra: &mut Stack) -> u32 { self as u32 }
|
||||||
unsafe fn from_abi(js: u32, _extra: &mut Stack) -> *const T { js as *const T }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> WasmBoundary for *mut T {
|
impl<T> FromWasmAbi for *const T {
|
||||||
|
type Abi = u32;
|
||||||
|
|
||||||
|
unsafe fn from_abi(js: u32, _extra: &mut Stack) -> *const T {
|
||||||
|
js as *const T
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> IntoWasmAbi for *mut T {
|
||||||
type Abi = u32;
|
type Abi = u32;
|
||||||
|
|
||||||
fn into_abi(self, _extra: &mut Stack) -> u32 { self as u32 }
|
fn into_abi(self, _extra: &mut Stack) -> u32 { self as u32 }
|
||||||
unsafe fn from_abi(js: u32, _extra: &mut Stack) -> *mut T { js as *mut T }
|
}
|
||||||
|
|
||||||
|
impl<T> FromWasmAbi for *mut T {
|
||||||
|
type Abi = u32;
|
||||||
|
|
||||||
|
unsafe fn from_abi(js: u32, _extra: &mut Stack) -> *mut T {
|
||||||
|
js as *mut T
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! vectors {
|
macro_rules! vectors {
|
||||||
($($t:ident)*) => ($(
|
($($t:ident)*) => ($(
|
||||||
impl WasmBoundary for Box<[$t]> {
|
impl IntoWasmAbi for Box<[$t]> {
|
||||||
type Abi = u32;
|
type Abi = u32;
|
||||||
|
|
||||||
fn into_abi(self, extra: &mut Stack) -> u32 {
|
fn into_abi(self, extra: &mut Stack) -> u32 {
|
||||||
@ -127,19 +142,22 @@ macro_rules! vectors {
|
|||||||
extra.push(len as u32);
|
extra.push(len as u32);
|
||||||
ptr.into_abi(extra)
|
ptr.into_abi(extra)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
unsafe fn from_abi(js: u32, extra: &mut Stack) -> Box<[$t]> {
|
impl FromWasmAbi for Box<[$t]> {
|
||||||
|
type Abi = u32;
|
||||||
|
|
||||||
|
unsafe fn from_abi(js: u32, extra: &mut Stack) -> Self {
|
||||||
let ptr = <*mut $t>::from_abi(js, extra);
|
let ptr = <*mut $t>::from_abi(js, extra);
|
||||||
let len = extra.pop() as usize;
|
let len = extra.pop() as usize;
|
||||||
Vec::from_raw_parts(ptr, len, len).into_boxed_slice()
|
Vec::from_raw_parts(ptr, len, len).into_boxed_slice()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToRefWasmBoundary for [$t] {
|
impl<'a> IntoWasmAbi for &'a [$t] {
|
||||||
type Abi = u32;
|
type Abi = u32;
|
||||||
|
|
||||||
fn to_abi_ref(&self, extra: &mut Stack) -> u32 {
|
fn into_abi(self, extra: &mut Stack) -> u32 {
|
||||||
let ptr = self.as_ptr();
|
let ptr = self.as_ptr();
|
||||||
let len = self.len();
|
let len = self.len();
|
||||||
extra.push(len as u32);
|
extra.push(len as u32);
|
||||||
@ -147,90 +165,73 @@ macro_rules! vectors {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromRefWasmBoundary for [$t] {
|
impl RefFromWasmAbi for [$t] {
|
||||||
type Abi = u32;
|
type Abi = u32;
|
||||||
type RefAnchor = SliceAnchor<$t>;
|
type Anchor = &'static [$t];
|
||||||
|
|
||||||
unsafe fn from_abi_ref(js: u32, extra: &mut Stack) -> SliceAnchor<$t> {
|
unsafe fn ref_from_abi(js: u32, extra: &mut Stack) -> &'static [$t] {
|
||||||
SliceAnchor {
|
slice::from_raw_parts(
|
||||||
ptr: <*mut $t>::from_abi(js, extra),
|
<*const $t>::from_abi(js, extra),
|
||||||
len: extra.pop() as usize,
|
extra.pop() as usize,
|
||||||
}
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)*)
|
)*)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct SliceAnchor<T> {
|
|
||||||
ptr: *mut T,
|
|
||||||
len: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> Deref for SliceAnchor<T> {
|
|
||||||
type Target = [T];
|
|
||||||
fn deref(&self) -> &[T] {
|
|
||||||
unsafe { slice::from_raw_parts(self.ptr, self.len) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
vectors! {
|
vectors! {
|
||||||
u8 i8 u16 i16 u32 i32 f32 f64
|
u8 i8 u16 i16 u32 i32 f32 f64
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> WasmBoundary for Vec<T> where Box<[T]>: WasmBoundary {
|
impl<T> IntoWasmAbi for Vec<T> where Box<[T]>: IntoWasmAbi {
|
||||||
type Abi = <Box<[T]> as WasmBoundary>::Abi;
|
type Abi = <Box<[T]> as IntoWasmAbi>::Abi;
|
||||||
|
|
||||||
fn into_abi(self, extra: &mut Stack) -> Self::Abi {
|
fn into_abi(self, extra: &mut Stack) -> Self::Abi {
|
||||||
self.into_boxed_slice().into_abi(extra)
|
self.into_boxed_slice().into_abi(extra)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> FromWasmAbi for Vec<T> where Box<[T]>: FromWasmAbi {
|
||||||
|
type Abi = <Box<[T]> as FromWasmAbi>::Abi;
|
||||||
|
|
||||||
unsafe fn from_abi(js: Self::Abi, extra: &mut Stack) -> Self {
|
unsafe fn from_abi(js: Self::Abi, extra: &mut Stack) -> Self {
|
||||||
<Box<[T]>>::from_abi(js, extra).into()
|
<Box<[T]>>::from_abi(js, extra).into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WasmBoundary for String {
|
impl IntoWasmAbi for String {
|
||||||
type Abi = u32;
|
type Abi = u32;
|
||||||
|
|
||||||
fn into_abi(self, extra: &mut Stack) -> u32 {
|
fn into_abi(self, extra: &mut Stack) -> u32 {
|
||||||
self.into_bytes().into_abi(extra)
|
self.into_bytes().into_abi(extra)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
unsafe fn from_abi(js: u32, extra: &mut Stack) -> String {
|
impl FromWasmAbi for String {
|
||||||
String::from_utf8_unchecked(Vec::from_abi(js, extra))
|
type Abi = u32;
|
||||||
|
|
||||||
|
unsafe fn from_abi(js: u32, extra: &mut Stack) -> Self {
|
||||||
|
String::from_utf8_unchecked(<Vec<u8>>::from_abi(js, extra))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToRefWasmBoundary for str {
|
impl<'a> IntoWasmAbi for &'a str {
|
||||||
type Abi = <[u8] as ToRefWasmBoundary>::Abi;
|
type Abi = <&'a [u8] as IntoWasmAbi>::Abi;
|
||||||
|
|
||||||
fn to_abi_ref(&self, extra: &mut Stack) -> Self::Abi {
|
fn into_abi(self, extra: &mut Stack) -> Self::Abi {
|
||||||
self.as_bytes().to_abi_ref(extra)
|
self.as_bytes().into_abi(extra)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromRefWasmBoundary for str {
|
impl RefFromWasmAbi for str {
|
||||||
type Abi = <[u8] as ToRefWasmBoundary>::Abi;
|
type Abi = <[u8] as RefFromWasmAbi>::Abi;
|
||||||
type RefAnchor = StrAnchor;
|
type Anchor = &'static str;
|
||||||
|
|
||||||
unsafe fn from_abi_ref(js: Self::Abi, extra: &mut Stack) -> Self::RefAnchor {
|
unsafe fn ref_from_abi(js: Self::Abi, extra: &mut Stack) -> Self::Anchor {
|
||||||
StrAnchor { inner: <[u8]>::from_abi_ref(js, extra) }
|
str::from_utf8_unchecked(<[u8]>::ref_from_abi(js, extra))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct StrAnchor {
|
impl IntoWasmAbi for JsValue {
|
||||||
inner: SliceAnchor<u8>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Deref for StrAnchor {
|
|
||||||
type Target = str;
|
|
||||||
|
|
||||||
fn deref(&self) -> &str {
|
|
||||||
unsafe { str::from_utf8_unchecked(&self.inner) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl WasmBoundary for JsValue {
|
|
||||||
type Abi = u32;
|
type Abi = u32;
|
||||||
|
|
||||||
fn into_abi(self, _extra: &mut Stack) -> u32 {
|
fn into_abi(self, _extra: &mut Stack) -> u32 {
|
||||||
@ -238,29 +239,33 @@ impl WasmBoundary for JsValue {
|
|||||||
mem::forget(self);
|
mem::forget(self);
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromWasmAbi for JsValue {
|
||||||
|
type Abi = u32;
|
||||||
|
|
||||||
unsafe fn from_abi(js: u32, _extra: &mut Stack) -> JsValue {
|
unsafe fn from_abi(js: u32, _extra: &mut Stack) -> JsValue {
|
||||||
JsValue { idx: js }
|
JsValue { idx: js }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToRefWasmBoundary for JsValue {
|
impl<'a> IntoWasmAbi for &'a JsValue {
|
||||||
type Abi = u32;
|
type Abi = u32;
|
||||||
fn to_abi_ref(&self, _extra: &mut Stack) -> u32 {
|
fn into_abi(self, _extra: &mut Stack) -> u32 {
|
||||||
self.idx
|
self.idx
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromRefWasmBoundary for JsValue {
|
impl RefFromWasmAbi for JsValue {
|
||||||
type Abi = u32;
|
type Abi = u32;
|
||||||
type RefAnchor = ManuallyDrop<JsValue>;
|
type Anchor = ManuallyDrop<JsValue>;
|
||||||
|
|
||||||
unsafe fn from_abi_ref(js: u32, _extra: &mut Stack) -> ManuallyDrop<JsValue> {
|
unsafe fn ref_from_abi(js: u32, _extra: &mut Stack) -> Self::Anchor {
|
||||||
ManuallyDrop::new(JsValue { idx: js })
|
ManuallyDrop::new(JsValue { idx: js })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WasmBoundary for Box<[JsValue]> {
|
impl IntoWasmAbi for Box<[JsValue]> {
|
||||||
type Abi = u32;
|
type Abi = u32;
|
||||||
|
|
||||||
fn into_abi(self, extra: &mut Stack) -> u32 {
|
fn into_abi(self, extra: &mut Stack) -> u32 {
|
||||||
@ -270,8 +275,12 @@ impl WasmBoundary for Box<[JsValue]> {
|
|||||||
extra.push(len as u32);
|
extra.push(len as u32);
|
||||||
ptr.into_abi(extra)
|
ptr.into_abi(extra)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
unsafe fn from_abi(js: u32, extra: &mut Stack) -> Box<[JsValue]> {
|
impl FromWasmAbi for Box<[JsValue]> {
|
||||||
|
type Abi = u32;
|
||||||
|
|
||||||
|
unsafe fn from_abi(js: u32, extra: &mut Stack) -> Self {
|
||||||
let ptr = <*mut JsValue>::from_abi(js, extra);
|
let ptr = <*mut JsValue>::from_abi(js, extra);
|
||||||
let len = extra.pop() as usize;
|
let len = extra.pop() as usize;
|
||||||
Vec::from_raw_parts(ptr, len, len).into_boxed_slice()
|
Vec::from_raw_parts(ptr, len, len).into_boxed_slice()
|
||||||
@ -316,13 +325,13 @@ pub unsafe extern fn __wbindgen_global_argument_ptr() -> *mut u32 {
|
|||||||
|
|
||||||
macro_rules! stack_closures {
|
macro_rules! stack_closures {
|
||||||
($( ($($var:ident)*) )*) => ($(
|
($( ($($var:ident)*) )*) => ($(
|
||||||
impl<'a, $($var,)* R> ToRefWasmBoundary for Fn($($var),*) -> R + 'a
|
impl<'a, $($var,)* R> IntoWasmAbi for &'a (Fn($($var),*) -> R + 'a)
|
||||||
where $($var: WasmAbi + WasmDescribe,)*
|
where $($var: WasmAbi + WasmDescribe,)*
|
||||||
R: WasmAbi + WasmDescribe
|
R: WasmAbi + WasmDescribe
|
||||||
{
|
{
|
||||||
type Abi = u32;
|
type Abi = u32;
|
||||||
|
|
||||||
fn to_abi_ref(&self, extra: &mut Stack) -> u32 {
|
fn into_abi(self, extra: &mut Stack) -> u32 {
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
unsafe extern fn invoke<$($var,)* R>(
|
unsafe extern fn invoke<$($var,)* R>(
|
||||||
a: usize,
|
a: usize,
|
||||||
@ -344,12 +353,12 @@ macro_rules! stack_closures {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, $($var,)*> ToRefWasmBoundary for Fn($($var),*) + 'a
|
impl<'a, $($var,)*> IntoWasmAbi for &'a (Fn($($var),*) + 'a)
|
||||||
where $($var: WasmAbi + WasmDescribe,)*
|
where $($var: WasmAbi + WasmDescribe,)*
|
||||||
{
|
{
|
||||||
type Abi = u32;
|
type Abi = u32;
|
||||||
|
|
||||||
fn to_abi_ref(&self, extra: &mut Stack) -> u32 {
|
fn into_abi(self, extra: &mut Stack) -> u32 {
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
unsafe extern fn invoke<$($var,)* >(
|
unsafe extern fn invoke<$($var,)* >(
|
||||||
a: usize,
|
a: usize,
|
||||||
@ -371,13 +380,13 @@ macro_rules! stack_closures {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, $($var,)* R> ToRefMutWasmBoundary for FnMut($($var),*) -> R + 'a
|
impl<'a, $($var,)* R> IntoWasmAbi for &'a mut (FnMut($($var),*) -> R + 'a)
|
||||||
where $($var: WasmAbi + WasmDescribe,)*
|
where $($var: WasmAbi + WasmDescribe,)*
|
||||||
R: WasmAbi + WasmDescribe
|
R: WasmAbi + WasmDescribe
|
||||||
{
|
{
|
||||||
type Abi = u32;
|
type Abi = u32;
|
||||||
|
|
||||||
fn to_abi_ref_mut(&mut self, extra: &mut Stack) -> u32 {
|
fn into_abi(self, extra: &mut Stack) -> u32 {
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
unsafe extern fn invoke<$($var,)* R>(
|
unsafe extern fn invoke<$($var,)* R>(
|
||||||
a: usize,
|
a: usize,
|
||||||
@ -399,12 +408,12 @@ macro_rules! stack_closures {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, $($var,)*> ToRefMutWasmBoundary for FnMut($($var),*) + 'a
|
impl<'a, $($var,)*> IntoWasmAbi for &'a mut (FnMut($($var),*) + 'a)
|
||||||
where $($var: WasmAbi + WasmDescribe,)*
|
where $($var: WasmAbi + WasmDescribe,)*
|
||||||
{
|
{
|
||||||
type Abi = u32;
|
type Abi = u32;
|
||||||
|
|
||||||
fn to_abi_ref_mut(&mut self, extra: &mut Stack) -> u32 {
|
fn into_abi(self, extra: &mut Stack) -> u32 {
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
unsafe extern fn invoke<$($var,)* >(
|
unsafe extern fn invoke<$($var,)* >(
|
||||||
a: usize,
|
a: usize,
|
||||||
|
@ -13,7 +13,7 @@ use std::cell::UnsafeCell;
|
|||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
|
|
||||||
use convert::WasmBoundary;
|
use convert::FromWasmAbi;
|
||||||
|
|
||||||
/// A module which is typically glob imported from:
|
/// A module which is typically glob imported from:
|
||||||
///
|
///
|
||||||
@ -295,7 +295,7 @@ pub struct JsStatic<T> {
|
|||||||
unsafe impl<T: Sync> Sync for JsStatic<T> {}
|
unsafe impl<T: Sync> Sync for JsStatic<T> {}
|
||||||
unsafe impl<T: Send> Send for JsStatic<T> {}
|
unsafe impl<T: Send> Send for JsStatic<T> {}
|
||||||
|
|
||||||
impl<T: WasmBoundary> Deref for JsStatic<T> {
|
impl<T: FromWasmAbi + 'static> Deref for JsStatic<T> {
|
||||||
type Target = T;
|
type Target = T;
|
||||||
fn deref(&self) -> &T {
|
fn deref(&self) -> &T {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user