mirror of
https://github.com/rustwasm/wasm-bindgen.git
synced 2024-12-01 06:46:20 +03: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 name: syn::Ident,
|
||||
pub arguments: Vec<Type>,
|
||||
pub ret: Option<Type>,
|
||||
pub arguments: Vec<syn::Type>,
|
||||
pub ret: Option<syn::Type>,
|
||||
pub opts: BindgenAttrs,
|
||||
pub rust_attrs: Vec<syn::Attribute>,
|
||||
pub rust_decl: Box<syn::FnDecl>,
|
||||
@ -79,12 +79,6 @@ pub struct Variant {
|
||||
pub value: u32,
|
||||
}
|
||||
|
||||
pub struct Type {
|
||||
pub ty: syn::Type,
|
||||
pub kind: TypeKind,
|
||||
pub loc: TypeLocation,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum TypeKind {
|
||||
ByRef,
|
||||
@ -210,7 +204,6 @@ impl Program {
|
||||
opts,
|
||||
method.vis,
|
||||
true,
|
||||
false,
|
||||
);
|
||||
self.exports.push(Export {
|
||||
class: Some(class),
|
||||
@ -305,7 +298,6 @@ impl Program {
|
||||
opts,
|
||||
f.vis,
|
||||
false,
|
||||
true,
|
||||
).0;
|
||||
if wasm.opts.catch() {
|
||||
// TODO: this assumes a whole bunch:
|
||||
@ -323,7 +315,15 @@ impl Program {
|
||||
let class = wasm.arguments
|
||||
.get(0)
|
||||
.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 {
|
||||
qself: None,
|
||||
ref path,
|
||||
@ -335,11 +335,11 @@ impl Program {
|
||||
|
||||
ImportFunctionKind::Method {
|
||||
class: class_name.as_ref().to_string(),
|
||||
ty: class.ty.clone(),
|
||||
ty: class.clone(),
|
||||
}
|
||||
} else if wasm.opts.constructor() {
|
||||
let class = match wasm.ret {
|
||||
Some(Type { ref ty, kind: TypeKind::ByValue, .. }) => ty,
|
||||
Some(ref ty) => ty,
|
||||
_ => panic!("constructor returns must be bare types"),
|
||||
};
|
||||
let class_name = match *class {
|
||||
@ -433,7 +433,6 @@ impl Function {
|
||||
opts,
|
||||
input.vis,
|
||||
false,
|
||||
false,
|
||||
).0
|
||||
}
|
||||
|
||||
@ -444,7 +443,6 @@ impl Function {
|
||||
opts: BindgenAttrs,
|
||||
vis: syn::Visibility,
|
||||
allow_self: bool,
|
||||
import: bool,
|
||||
) -> (Function, Option<bool>) {
|
||||
if decl.variadic.is_some() {
|
||||
panic!("can't bindgen variadic functions")
|
||||
@ -453,6 +451,8 @@ impl Function {
|
||||
panic!("can't bindgen functions with lifetime or type parameters")
|
||||
}
|
||||
|
||||
assert_no_lifetimes(&decl);
|
||||
|
||||
let mut mutable = None;
|
||||
let arguments = decl.inputs
|
||||
.iter()
|
||||
@ -468,24 +468,12 @@ impl Function {
|
||||
}
|
||||
_ => panic!("arguments cannot be `self` or ignored"),
|
||||
})
|
||||
.map(|arg| {
|
||||
Type::from(&arg.ty, if import {
|
||||
TypeLocation::ImportArgument
|
||||
} else {
|
||||
TypeLocation::ExportArgument
|
||||
})
|
||||
})
|
||||
.map(|arg| arg.ty.clone())
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let ret = match decl.output {
|
||||
syn::ReturnType::Default => None,
|
||||
syn::ReturnType::Type(_, ref t) => {
|
||||
Some(Type::from(t, if import {
|
||||
TypeLocation::ImportRet
|
||||
} else {
|
||||
TypeLocation::ExportRet
|
||||
}))
|
||||
}
|
||||
syn::ReturnType::Type(_, ref t) => Some((**t).clone()),
|
||||
};
|
||||
|
||||
(
|
||||
@ -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)]
|
||||
pub struct BindgenAttrs {
|
||||
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 {
|
||||
Some(t) => t,
|
||||
None => return Some(None),
|
||||
};
|
||||
let ty = match *t {
|
||||
Type { ref ty, kind: TypeKind::ByValue, .. } => ty,
|
||||
_ => return None,
|
||||
};
|
||||
let path = match *ty {
|
||||
let path = match *t {
|
||||
syn::Type::Path(syn::TypePath {
|
||||
qself: None,
|
||||
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),
|
||||
_ => {}
|
||||
}
|
||||
Some(Some(Type {
|
||||
ty: ty.clone(),
|
||||
kind: TypeKind::ByValue,
|
||||
loc: t.loc,
|
||||
}))
|
||||
Some(Some(ty.clone()))
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
let js = js as *mut ::wasm_bindgen::__rt::WasmRefCell<#name>;
|
||||
::wasm_bindgen::__rt::assert_not_null(js);
|
||||
let js = Box::from_raw(js);
|
||||
let ptr = js as *mut ::wasm_bindgen::__rt::WasmRefCell<#name>;
|
||||
::wasm_bindgen::__rt::assert_not_null(ptr);
|
||||
let js = Box::from_raw(ptr);
|
||||
js.borrow_mut(); // make sure no one's borrowing
|
||||
js.into_inner()
|
||||
}
|
||||
}
|
||||
|
||||
impl ::wasm_bindgen::convert::FromRefWasmBoundary for #name {
|
||||
impl ::wasm_bindgen::convert::RefFromWasmAbi for #name {
|
||||
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,
|
||||
_extra: &mut ::wasm_bindgen::convert::Stack,
|
||||
) -> Self::RefAnchor {
|
||||
) -> Self::Anchor {
|
||||
let js = js as *mut ::wasm_bindgen::__rt::WasmRefCell<#name>;
|
||||
::wasm_bindgen::__rt::assert_not_null(js);
|
||||
(*js).borrow()
|
||||
}
|
||||
}
|
||||
|
||||
impl ::wasm_bindgen::convert::FromRefMutWasmBoundary for #name {
|
||||
impl ::wasm_bindgen::convert::RefMutFromWasmAbi for #name {
|
||||
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,
|
||||
_extra: &mut ::wasm_bindgen::convert::Stack,
|
||||
) -> Self::RefAnchor {
|
||||
) -> Self::Anchor {
|
||||
let js = js as *mut ::wasm_bindgen::__rt::WasmRefCell<#name>;
|
||||
::wasm_bindgen::__rt::assert_not_null(js);
|
||||
(*js).borrow_mut()
|
||||
@ -166,7 +170,7 @@ impl ToTokens for ast::Struct {
|
||||
|
||||
impl ::std::convert::From<#name> for ::wasm_bindgen::JsValue {
|
||||
fn from(value: #name) -> Self {
|
||||
let ptr = ::wasm_bindgen::convert::WasmBoundary::into_abi(
|
||||
let ptr = ::wasm_bindgen::convert::IntoWasmAbi::into_abi(
|
||||
value,
|
||||
unsafe { &mut ::wasm_bindgen::convert::GlobalStack::new() },
|
||||
);
|
||||
@ -177,7 +181,7 @@ impl ToTokens for ast::Struct {
|
||||
}
|
||||
|
||||
unsafe {
|
||||
<::wasm_bindgen::JsValue as ::wasm_bindgen::convert::WasmBoundary>
|
||||
<::wasm_bindgen::JsValue as ::wasm_bindgen::convert::FromWasmAbi>
|
||||
::from_abi(
|
||||
#new_fn(ptr),
|
||||
&mut ::wasm_bindgen::convert::GlobalStack::new(),
|
||||
@ -188,7 +192,7 @@ impl ToTokens for ast::Struct {
|
||||
|
||||
#[no_mangle]
|
||||
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,
|
||||
&mut ::wasm_bindgen::convert::GlobalStack::new(),
|
||||
);
|
||||
@ -220,41 +224,44 @@ impl ToTokens for ast::Export {
|
||||
for (i, ty) in self.function.arguments.iter().enumerate() {
|
||||
let i = i + offset;
|
||||
let ident = syn::Ident::from(format!("arg{}", i));
|
||||
let t = &ty.ty;
|
||||
match ty.kind {
|
||||
ast::TypeKind::ByValue => {
|
||||
match *ty {
|
||||
syn::Type::Reference(syn::TypeReference {
|
||||
mutability: Some(_),
|
||||
ref elem,
|
||||
..
|
||||
}) => {
|
||||
args.push(quote! {
|
||||
#ident: <#t as ::wasm_bindgen::convert::WasmBoundary>::Abi
|
||||
#ident: <#elem as ::wasm_bindgen::convert::RefMutFromWasmAbi>::Abi
|
||||
});
|
||||
arg_conversions.push(quote! {
|
||||
let #ident = unsafe {
|
||||
<#t as ::wasm_bindgen::convert::WasmBoundary>
|
||||
::from_abi(#ident, &mut __stack)
|
||||
let mut #ident = unsafe {
|
||||
<#elem as ::wasm_bindgen::convert::RefMutFromWasmAbi>
|
||||
::ref_mut_from_abi(#ident, &mut __stack)
|
||||
};
|
||||
let #ident = &mut *#ident;
|
||||
});
|
||||
}
|
||||
ast::TypeKind::ByRef => {
|
||||
syn::Type::Reference(syn::TypeReference { ref elem, .. }) => {
|
||||
args.push(quote! {
|
||||
#ident: <#t as ::wasm_bindgen::convert::FromRefWasmBoundary>::Abi
|
||||
#ident: <#elem as ::wasm_bindgen::convert::RefFromWasmAbi>::Abi
|
||||
});
|
||||
arg_conversions.push(quote! {
|
||||
let #ident = unsafe {
|
||||
<#t as ::wasm_bindgen::convert::FromRefWasmBoundary>
|
||||
::from_abi_ref(#ident, &mut __stack)
|
||||
<#elem as ::wasm_bindgen::convert::RefFromWasmAbi>
|
||||
::ref_from_abi(#ident, &mut __stack)
|
||||
};
|
||||
let #ident = &*#ident;
|
||||
});
|
||||
}
|
||||
ast::TypeKind::ByMutRef => {
|
||||
_ => {
|
||||
args.push(quote! {
|
||||
#ident: <#t as ::wasm_bindgen::convert::FromRefMutWasmBoundary>::Abi
|
||||
#ident: <#ty as ::wasm_bindgen::convert::FromWasmAbi>::Abi
|
||||
});
|
||||
arg_conversions.push(quote! {
|
||||
let mut #ident = unsafe {
|
||||
<#t as ::wasm_bindgen::convert::FromRefMutWasmBoundary>
|
||||
::from_abi_ref_mut(#ident, &mut __stack)
|
||||
let #ident = unsafe {
|
||||
<#ty as ::wasm_bindgen::convert::FromWasmAbi>
|
||||
::from_abi(#ident, &mut __stack)
|
||||
};
|
||||
let #ident = &mut *#ident;
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -263,28 +270,25 @@ impl ToTokens for ast::Export {
|
||||
let ret_ty;
|
||||
let convert_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! {
|
||||
-> <#ty as ::wasm_bindgen::convert::WasmBoundary>::Abi
|
||||
-> <#ty as ::wasm_bindgen::convert::IntoWasmAbi>::Abi
|
||||
};
|
||||
convert_ret = quote! {
|
||||
<#ty as ::wasm_bindgen::convert::WasmBoundary>
|
||||
<#ty as ::wasm_bindgen::convert::IntoWasmAbi>
|
||||
::into_abi(#ret, &mut unsafe {
|
||||
::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 => {
|
||||
ret_ty = quote!{};
|
||||
convert_ret = quote!{};
|
||||
}
|
||||
}
|
||||
let describe_ret = match self.function.ret {
|
||||
Some(ast::Type { ref ty, .. }) => {
|
||||
Some(ref ty) => {
|
||||
quote! {
|
||||
inform(1);
|
||||
<#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
|
||||
::wasm_bindgen::convert::WasmBoundary>::Abi;
|
||||
::wasm_bindgen::convert::IntoWasmAbi>::Abi;
|
||||
|
||||
fn into_abi(self, extra: &mut ::wasm_bindgen::convert::Stack) -> Self::Abi {
|
||||
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(
|
||||
js: Self::Abi,
|
||||
extra: &mut ::wasm_bindgen::convert::Stack,
|
||||
) -> 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 {
|
||||
type Abi = <::wasm_bindgen::JsValue as
|
||||
::wasm_bindgen::convert::ToRefWasmBoundary>::Abi;
|
||||
impl<'a> ::wasm_bindgen::convert::IntoWasmAbi for &'a #name {
|
||||
type Abi = <&'a ::wasm_bindgen::JsValue as
|
||||
::wasm_bindgen::convert::IntoWasmAbi>::Abi;
|
||||
|
||||
fn to_abi_ref(&self, extra: &mut ::wasm_bindgen::convert::Stack) -> u32 {
|
||||
self.obj.to_abi_ref(extra)
|
||||
fn into_abi(self, extra: &mut ::wasm_bindgen::convert::Stack) -> Self::Abi {
|
||||
(&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
|
||||
::wasm_bindgen::convert::ToRefWasmBoundary>::Abi;
|
||||
type RefAnchor = ::std::mem::ManuallyDrop<#name>;
|
||||
::wasm_bindgen::convert::RefFromWasmAbi>::Abi;
|
||||
type Anchor = ::std::mem::ManuallyDrop<#name>;
|
||||
|
||||
unsafe fn from_abi_ref(
|
||||
unsafe fn ref_from_abi(
|
||||
js: Self::Abi,
|
||||
extra: &mut ::wasm_bindgen::convert::Stack,
|
||||
) -> Self::RefAnchor {
|
||||
let obj = <::wasm_bindgen::JsValue as ::wasm_bindgen::convert::WasmBoundary>
|
||||
::from_abi(js, extra);
|
||||
::std::mem::ManuallyDrop::new(#name { obj })
|
||||
) -> Self::Anchor {
|
||||
let tmp = <::wasm_bindgen::JsValue as ::wasm_bindgen::convert::RefFromWasmAbi>
|
||||
::ref_from_abi(js, extra);
|
||||
::std::mem::ManuallyDrop::new(#name {
|
||||
obj: ::std::mem::ManuallyDrop::into_inner(tmp),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl From<::wasm_bindgen::JsValue> for #name {
|
||||
fn from(obj: ::wasm_bindgen::JsValue) -> #name {
|
||||
#name { obj }
|
||||
@ -478,65 +490,38 @@ impl ToTokens for ast::ImportFunction {
|
||||
});
|
||||
|
||||
for (i, (ty, name)) in self.function.arguments.iter().zip(names).enumerate() {
|
||||
let t = &ty.ty;
|
||||
match ty.kind {
|
||||
ast::TypeKind::ByValue => {
|
||||
abi_argument_names.push(name);
|
||||
abi_arguments.push(quote! {
|
||||
#name: <#t as ::wasm_bindgen::convert::WasmBoundary>::Abi
|
||||
});
|
||||
let var = if i == 0 && is_method {
|
||||
quote! { self }
|
||||
} else {
|
||||
quote! { #name }
|
||||
};
|
||||
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);
|
||||
});
|
||||
}
|
||||
}
|
||||
abi_argument_names.push(name);
|
||||
abi_arguments.push(quote! {
|
||||
#name: <#ty as ::wasm_bindgen::convert::IntoWasmAbi>::Abi
|
||||
});
|
||||
let var = if i == 0 && is_method {
|
||||
quote! { self }
|
||||
} else {
|
||||
quote! { #name }
|
||||
};
|
||||
arg_conversions.push(quote! {
|
||||
let #name = <#ty as ::wasm_bindgen::convert::IntoWasmAbi>
|
||||
::into_abi(#var, &mut __stack);
|
||||
});
|
||||
}
|
||||
let abi_ret;
|
||||
let mut convert_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! {
|
||||
<#ty as ::wasm_bindgen::convert::WasmBoundary>::Abi
|
||||
<#ty as ::wasm_bindgen::convert::FromWasmAbi>::Abi
|
||||
};
|
||||
convert_ret = quote! {
|
||||
<#ty as ::wasm_bindgen::convert::WasmBoundary>
|
||||
<#ty as ::wasm_bindgen::convert::FromWasmAbi>
|
||||
::from_abi(
|
||||
#ret_ident,
|
||||
&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 => {
|
||||
abi_ret = quote! { () };
|
||||
convert_ret = quote! { () };
|
||||
@ -554,8 +539,8 @@ impl ToTokens for ast::ImportFunction {
|
||||
if #exn_data[0] == 1 {
|
||||
return Err(
|
||||
<
|
||||
::wasm_bindgen::JsValue as ::wasm_bindgen::convert::WasmBoundary
|
||||
>::from_abi(#exn_data[1], &mut ::wasm_bindgen::convert::GlobalStack::new()),
|
||||
::wasm_bindgen::JsValue as ::wasm_bindgen::convert::FromWasmAbi
|
||||
>::from_abi(#exn_data[1], &mut ::wasm_bindgen::convert::GlobalStack::new())
|
||||
)
|
||||
}
|
||||
};
|
||||
@ -663,12 +648,16 @@ impl ToTokens for ast::Enum {
|
||||
}
|
||||
});
|
||||
(quote! {
|
||||
impl ::wasm_bindgen::convert::WasmBoundary for #enum_name {
|
||||
impl ::wasm_bindgen::convert::IntoWasmAbi for #enum_name {
|
||||
type Abi = u32;
|
||||
|
||||
fn into_abi(self, _extra: &mut ::wasm_bindgen::convert::Stack) -> u32 {
|
||||
self as u32
|
||||
}
|
||||
}
|
||||
|
||||
impl ::wasm_bindgen::convert::FromWasmAbi for #enum_name {
|
||||
type Abi = u32;
|
||||
|
||||
unsafe fn from_abi(
|
||||
js: u32,
|
||||
@ -702,13 +691,14 @@ impl ToTokens for ast::ImportStatic {
|
||||
fn init() -> #ty {
|
||||
#[wasm_import_module = "__wbindgen_placeholder__"]
|
||||
extern {
|
||||
fn #shim_name() -> <#ty as ::wasm_bindgen::convert::WasmBoundary>::Abi;
|
||||
fn #shim_name() -> <#ty as ::wasm_bindgen::convert::FromWasmAbi>::Abi;
|
||||
}
|
||||
unsafe {
|
||||
::wasm_bindgen::convert::WasmBoundary::from_abi(
|
||||
<#ty as ::wasm_bindgen::convert::FromWasmAbi>::from_abi(
|
||||
#shim_name(),
|
||||
&mut ::wasm_bindgen::convert::GlobalStack::new(),
|
||||
)
|
||||
|
||||
}
|
||||
}
|
||||
::wasm_bindgen::JsStatic {
|
||||
@ -719,19 +709,3 @@ impl ToTokens for ast::ImportStatic {
|
||||
}).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 super::Bindgen;
|
||||
use descriptor::{Descriptor, VectorKind};
|
||||
use descriptor::{Descriptor, VectorKind, Function};
|
||||
|
||||
pub struct Context<'a> {
|
||||
pub globals: String,
|
||||
@ -1311,10 +1311,12 @@ impl<'a, 'b> SubContext<'a, 'b> {
|
||||
if let Some(ref class) = export.class {
|
||||
return self.generate_export_for_class(class, export);
|
||||
}
|
||||
let descriptor = self.cx.describe(&export.function.name);
|
||||
let (js, ts) = self.generate_function("function",
|
||||
&export.function.name,
|
||||
&export.function.name,
|
||||
false,
|
||||
&export.function);
|
||||
descriptor.unwrap_function());
|
||||
self.cx.export(&export.function.name, &js);
|
||||
self.cx.globals.push_str("\n");
|
||||
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) {
|
||||
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(
|
||||
"",
|
||||
&shared::struct_function_export_name(class, &export.function.name),
|
||||
&export.function.name,
|
||||
&wasm_name,
|
||||
export.method,
|
||||
&export.function,
|
||||
&descriptor.unwrap_function(),
|
||||
);
|
||||
let class = self.cx.exported_classes.entry(class.to_string())
|
||||
.or_insert(ExportedClass::default());
|
||||
@ -1344,13 +1349,12 @@ impl<'a, 'b> SubContext<'a, 'b> {
|
||||
|
||||
fn generate_function(&mut self,
|
||||
prefix: &str,
|
||||
js_name: &str,
|
||||
wasm_name: &str,
|
||||
is_method: bool,
|
||||
function: &shared::Function) -> (String, String) {
|
||||
let descriptor = self.cx.describe(wasm_name);
|
||||
let desc_function = descriptor.unwrap_function();
|
||||
function: &Function) -> (String, String) {
|
||||
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 arg_conversions = String::new();
|
||||
let mut destructors = String::new();
|
||||
@ -1360,7 +1364,7 @@ impl<'a, 'b> SubContext<'a, 'b> {
|
||||
}
|
||||
|
||||
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);
|
||||
if i > 0 {
|
||||
dst.push_str(", ");
|
||||
@ -1459,7 +1463,7 @@ impl<'a, 'b> SubContext<'a, 'b> {
|
||||
}
|
||||
dst.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.push_str(" {\n ");
|
||||
dst.push_str(&arg_conversions);
|
||||
|
@ -99,7 +99,7 @@ impl<T> Closure<T>
|
||||
let js = T::factory()(T::shim(), data[0], data[1]);
|
||||
Closure {
|
||||
_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.
|
||||
pub fn forget(self) {
|
||||
unsafe {
|
||||
super::__wbindgen_cb_forget(self.js.to_abi_ref(&mut GlobalStack::new()));
|
||||
super::__wbindgen_cb_forget(self.js.idx);
|
||||
mem::forget(self);
|
||||
}
|
||||
}
|
||||
@ -133,13 +133,13 @@ impl<T> WasmDescribe for Closure<T>
|
||||
}
|
||||
|
||||
// `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,
|
||||
{
|
||||
type Abi = u32;
|
||||
|
||||
fn to_abi_ref(&self, extra: &mut Stack) -> u32 {
|
||||
self.js.to_abi_ref(extra)
|
||||
fn into_abi(self, _extra: &mut Stack) -> u32 {
|
||||
self.js.idx
|
||||
}
|
||||
}
|
||||
|
||||
@ -148,8 +148,7 @@ impl<T> Drop for Closure<T>
|
||||
{
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
let idx = self.js.to_abi_ref(&mut GlobalStack::new());
|
||||
super::__wbindgen_cb_drop(idx);
|
||||
super::__wbindgen_cb_drop(self.js.idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
205
src/convert.rs
205
src/convert.rs
@ -15,37 +15,27 @@ pub struct Descriptor {
|
||||
pub __x: [u8; 4],
|
||||
}
|
||||
|
||||
pub trait WasmBoundary: WasmDescribe {
|
||||
pub trait IntoWasmAbi: WasmDescribe {
|
||||
type Abi: WasmAbi;
|
||||
|
||||
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;
|
||||
|
||||
}
|
||||
|
||||
pub trait FromRefWasmBoundary: WasmDescribe {
|
||||
pub trait RefFromWasmAbi: WasmDescribe {
|
||||
type Abi: WasmAbi;
|
||||
type RefAnchor: Deref<Target = Self>;
|
||||
|
||||
unsafe fn from_abi_ref(js: Self::Abi, extra: &mut Stack) -> Self::RefAnchor;
|
||||
type Anchor: Deref<Target=Self>;
|
||||
unsafe fn ref_from_abi(js: Self::Abi, extra: &mut Stack) -> Self::Anchor;
|
||||
}
|
||||
|
||||
pub trait FromRefMutWasmBoundary: WasmDescribe {
|
||||
pub trait RefMutFromWasmAbi: WasmDescribe {
|
||||
type Abi: WasmAbi;
|
||||
type RefAnchor: DerefMut<Target = Self>;
|
||||
|
||||
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;
|
||||
type Anchor: DerefMut<Target=Self>;
|
||||
unsafe fn ref_mut_from_abi(js: Self::Abi, extra: &mut Stack) -> Self::Anchor;
|
||||
}
|
||||
|
||||
pub trait Stack {
|
||||
@ -70,10 +60,13 @@ unsafe impl WasmAbi for f64 {}
|
||||
|
||||
macro_rules! simple {
|
||||
($($t:tt)*) => ($(
|
||||
impl WasmBoundary for $t {
|
||||
impl IntoWasmAbi for $t {
|
||||
type Abi = $t;
|
||||
|
||||
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 }
|
||||
}
|
||||
)*)
|
||||
@ -83,10 +76,13 @@ simple!(u32 u64 i32 i64 f32 f64);
|
||||
|
||||
macro_rules! as_u32 {
|
||||
($($t:tt)*) => ($(
|
||||
impl WasmBoundary for $t {
|
||||
impl IntoWasmAbi for $t {
|
||||
type Abi = 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 }
|
||||
}
|
||||
)*)
|
||||
@ -94,30 +90,49 @@ macro_rules! as_u32 {
|
||||
|
||||
as_u32!(i8 u8 i16 u16 isize usize);
|
||||
|
||||
impl WasmBoundary for bool {
|
||||
impl IntoWasmAbi for bool {
|
||||
type Abi = 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 }
|
||||
}
|
||||
|
||||
impl<T> WasmBoundary for *const T {
|
||||
impl<T> IntoWasmAbi for *const T {
|
||||
type Abi = 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;
|
||||
|
||||
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 {
|
||||
($($t:ident)*) => ($(
|
||||
impl WasmBoundary for Box<[$t]> {
|
||||
impl IntoWasmAbi for Box<[$t]> {
|
||||
type Abi = u32;
|
||||
|
||||
fn into_abi(self, extra: &mut Stack) -> u32 {
|
||||
@ -127,19 +142,22 @@ macro_rules! vectors {
|
||||
extra.push(len as u32);
|
||||
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 len = extra.pop() as usize;
|
||||
Vec::from_raw_parts(ptr, len, len).into_boxed_slice()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
impl ToRefWasmBoundary for [$t] {
|
||||
impl<'a> IntoWasmAbi for &'a [$t] {
|
||||
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 len = self.len();
|
||||
extra.push(len as u32);
|
||||
@ -147,90 +165,73 @@ macro_rules! vectors {
|
||||
}
|
||||
}
|
||||
|
||||
impl FromRefWasmBoundary for [$t] {
|
||||
impl RefFromWasmAbi for [$t] {
|
||||
type Abi = u32;
|
||||
type RefAnchor = SliceAnchor<$t>;
|
||||
type Anchor = &'static [$t];
|
||||
|
||||
unsafe fn from_abi_ref(js: u32, extra: &mut Stack) -> SliceAnchor<$t> {
|
||||
SliceAnchor {
|
||||
ptr: <*mut $t>::from_abi(js, extra),
|
||||
len: extra.pop() as usize,
|
||||
}
|
||||
unsafe fn ref_from_abi(js: u32, extra: &mut Stack) -> &'static [$t] {
|
||||
slice::from_raw_parts(
|
||||
<*const $t>::from_abi(js, extra),
|
||||
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! {
|
||||
u8 i8 u16 i16 u32 i32 f32 f64
|
||||
}
|
||||
|
||||
impl<T> WasmBoundary for Vec<T> where Box<[T]>: WasmBoundary {
|
||||
type Abi = <Box<[T]> as WasmBoundary>::Abi;
|
||||
|
||||
impl<T> IntoWasmAbi for Vec<T> where Box<[T]>: IntoWasmAbi {
|
||||
type Abi = <Box<[T]> as IntoWasmAbi>::Abi;
|
||||
fn into_abi(self, extra: &mut Stack) -> Self::Abi {
|
||||
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 {
|
||||
<Box<[T]>>::from_abi(js, extra).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl WasmBoundary for String {
|
||||
impl IntoWasmAbi for String {
|
||||
type Abi = u32;
|
||||
|
||||
fn into_abi(self, extra: &mut Stack) -> u32 {
|
||||
self.into_bytes().into_abi(extra)
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn from_abi(js: u32, extra: &mut Stack) -> String {
|
||||
String::from_utf8_unchecked(Vec::from_abi(js, extra))
|
||||
impl FromWasmAbi for String {
|
||||
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 {
|
||||
type Abi = <[u8] as ToRefWasmBoundary>::Abi;
|
||||
impl<'a> IntoWasmAbi for &'a str {
|
||||
type Abi = <&'a [u8] as IntoWasmAbi>::Abi;
|
||||
|
||||
fn to_abi_ref(&self, extra: &mut Stack) -> Self::Abi {
|
||||
self.as_bytes().to_abi_ref(extra)
|
||||
fn into_abi(self, extra: &mut Stack) -> Self::Abi {
|
||||
self.as_bytes().into_abi(extra)
|
||||
}
|
||||
}
|
||||
|
||||
impl FromRefWasmBoundary for str {
|
||||
type Abi = <[u8] as ToRefWasmBoundary>::Abi;
|
||||
type RefAnchor = StrAnchor;
|
||||
impl RefFromWasmAbi for str {
|
||||
type Abi = <[u8] as RefFromWasmAbi>::Abi;
|
||||
type Anchor = &'static str;
|
||||
|
||||
unsafe fn from_abi_ref(js: Self::Abi, extra: &mut Stack) -> Self::RefAnchor {
|
||||
StrAnchor { inner: <[u8]>::from_abi_ref(js, extra) }
|
||||
unsafe fn ref_from_abi(js: Self::Abi, extra: &mut Stack) -> Self::Anchor {
|
||||
str::from_utf8_unchecked(<[u8]>::ref_from_abi(js, extra))
|
||||
}
|
||||
}
|
||||
|
||||
pub struct StrAnchor {
|
||||
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 {
|
||||
impl IntoWasmAbi for JsValue {
|
||||
type Abi = u32;
|
||||
|
||||
fn into_abi(self, _extra: &mut Stack) -> u32 {
|
||||
@ -238,29 +239,33 @@ impl WasmBoundary for JsValue {
|
||||
mem::forget(self);
|
||||
return ret
|
||||
}
|
||||
}
|
||||
|
||||
impl FromWasmAbi for JsValue {
|
||||
type Abi = u32;
|
||||
|
||||
unsafe fn from_abi(js: u32, _extra: &mut Stack) -> JsValue {
|
||||
JsValue { idx: js }
|
||||
}
|
||||
}
|
||||
|
||||
impl ToRefWasmBoundary for JsValue {
|
||||
impl<'a> IntoWasmAbi for &'a JsValue {
|
||||
type Abi = u32;
|
||||
fn to_abi_ref(&self, _extra: &mut Stack) -> u32 {
|
||||
fn into_abi(self, _extra: &mut Stack) -> u32 {
|
||||
self.idx
|
||||
}
|
||||
}
|
||||
|
||||
impl FromRefWasmBoundary for JsValue {
|
||||
impl RefFromWasmAbi for JsValue {
|
||||
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 })
|
||||
}
|
||||
}
|
||||
|
||||
impl WasmBoundary for Box<[JsValue]> {
|
||||
impl IntoWasmAbi for Box<[JsValue]> {
|
||||
type Abi = u32;
|
||||
|
||||
fn into_abi(self, extra: &mut Stack) -> u32 {
|
||||
@ -270,8 +275,12 @@ impl WasmBoundary for Box<[JsValue]> {
|
||||
extra.push(len as u32);
|
||||
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 len = extra.pop() as usize;
|
||||
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 {
|
||||
($( ($($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,)*
|
||||
R: WasmAbi + WasmDescribe
|
||||
{
|
||||
type Abi = u32;
|
||||
|
||||
fn to_abi_ref(&self, extra: &mut Stack) -> u32 {
|
||||
fn into_abi(self, extra: &mut Stack) -> u32 {
|
||||
#[allow(non_snake_case)]
|
||||
unsafe extern fn invoke<$($var,)* R>(
|
||||
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,)*
|
||||
{
|
||||
type Abi = u32;
|
||||
|
||||
fn to_abi_ref(&self, extra: &mut Stack) -> u32 {
|
||||
fn into_abi(self, extra: &mut Stack) -> u32 {
|
||||
#[allow(non_snake_case)]
|
||||
unsafe extern fn invoke<$($var,)* >(
|
||||
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,)*
|
||||
R: WasmAbi + WasmDescribe
|
||||
{
|
||||
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)]
|
||||
unsafe extern fn invoke<$($var,)* R>(
|
||||
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,)*
|
||||
{
|
||||
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)]
|
||||
unsafe extern fn invoke<$($var,)* >(
|
||||
a: usize,
|
||||
|
@ -13,7 +13,7 @@ use std::cell::UnsafeCell;
|
||||
use std::ops::Deref;
|
||||
use std::ptr;
|
||||
|
||||
use convert::WasmBoundary;
|
||||
use convert::FromWasmAbi;
|
||||
|
||||
/// 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: Send> Send for JsStatic<T> {}
|
||||
|
||||
impl<T: WasmBoundary> Deref for JsStatic<T> {
|
||||
impl<T: FromWasmAbi + 'static> Deref for JsStatic<T> {
|
||||
type Target = T;
|
||||
fn deref(&self) -> &T {
|
||||
unsafe {
|
||||
|
Loading…
Reference in New Issue
Block a user