Merge pull request #666 from fitzgen/instanceof-renamed-import-types

Instanceof renamed import types
This commit is contained in:
Nick Fitzgerald 2018-08-08 15:31:24 -07:00 committed by GitHub
commit 66f10b0c72
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 183 additions and 162 deletions

View File

@ -124,7 +124,8 @@ pub struct ImportStatic {
#[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq, Eq))] #[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq, Eq))]
pub struct ImportType { pub struct ImportType {
pub vis: syn::Visibility, pub vis: syn::Visibility,
pub name: Ident, pub rust_name: Ident,
pub js_name: String,
pub attrs: Vec<syn::Attribute>, pub attrs: Vec<syn::Attribute>,
pub doc_comment: Option<String>, pub doc_comment: Option<String>,
pub instanceof_shim: String, pub instanceof_shim: String,
@ -411,7 +412,7 @@ impl ImportStatic {
impl ImportType { impl ImportType {
fn shared(&self) -> shared::ImportType { fn shared(&self) -> shared::ImportType {
shared::ImportType { shared::ImportType {
name: self.name.to_string(), name: self.js_name.clone(),
instanceof_shim: self.instanceof_shim.clone(), instanceof_shim: self.instanceof_shim.clone(),
} }
} }

View File

@ -37,7 +37,7 @@ impl TryToTokens for ast::Program {
let mut types = HashSet::new(); let mut types = HashSet::new();
for i in self.imports.iter() { for i in self.imports.iter() {
if let ast::ImportKind::Type(t) = &i.kind { if let ast::ImportKind::Type(t) = &i.kind {
types.insert(t.name.clone()); types.insert(t.rust_name.clone());
} }
} }
for i in self.imports.iter() { for i in self.imports.iter() {
@ -513,13 +513,13 @@ impl TryToTokens for ast::ImportKind {
impl ToTokens for ast::ImportType { impl ToTokens for ast::ImportType {
fn to_tokens(&self, tokens: &mut TokenStream) { fn to_tokens(&self, tokens: &mut TokenStream) {
let vis = &self.vis; let vis = &self.vis;
let name = &self.name; let rust_name = &self.rust_name;
let attrs = &self.attrs; let attrs = &self.attrs;
let doc_comment = match &self.doc_comment { let doc_comment = match &self.doc_comment {
None => "", None => "",
Some(comment) => comment, Some(comment) => comment,
}; };
let const_name = format!("__wbg_generated_const_{}", name); let const_name = format!("__wbg_generated_const_{}", rust_name);
let const_name = Ident::new(&const_name, Span::call_site()); let const_name = Ident::new(&const_name, Span::call_site());
let instanceof_shim = Ident::new(&self.instanceof_shim, Span::call_site()); let instanceof_shim = Ident::new(&self.instanceof_shim, Span::call_site());
(quote! { (quote! {
@ -527,7 +527,7 @@ impl ToTokens for ast::ImportType {
#(#attrs)* #(#attrs)*
#[doc = #doc_comment] #[doc = #doc_comment]
#[repr(transparent)] #[repr(transparent)]
#vis struct #name { #vis struct #rust_name {
obj: ::wasm_bindgen::JsValue, obj: ::wasm_bindgen::JsValue,
} }
@ -540,13 +540,13 @@ impl ToTokens for ast::ImportType {
use wasm_bindgen::{JsValue, JsCast}; use wasm_bindgen::{JsValue, JsCast};
use wasm_bindgen::__rt::core::mem::ManuallyDrop; use wasm_bindgen::__rt::core::mem::ManuallyDrop;
impl WasmDescribe for #name { impl WasmDescribe for #rust_name {
fn describe() { fn describe() {
JsValue::describe(); JsValue::describe();
} }
} }
impl IntoWasmAbi for #name { impl IntoWasmAbi for #rust_name {
type Abi = <JsValue as IntoWasmAbi>::Abi; type Abi = <JsValue as IntoWasmAbi>::Abi;
fn into_abi(self, extra: &mut Stack) -> Self::Abi { fn into_abi(self, extra: &mut Stack) -> Self::Abi {
@ -554,29 +554,29 @@ impl ToTokens for ast::ImportType {
} }
} }
impl OptionIntoWasmAbi for #name { impl OptionIntoWasmAbi for #rust_name {
fn none() -> Self::Abi { 0 } fn none() -> Self::Abi { 0 }
} }
impl<'a> OptionIntoWasmAbi for &'a #name { impl<'a> OptionIntoWasmAbi for &'a #rust_name {
fn none() -> Self::Abi { 0 } fn none() -> Self::Abi { 0 }
} }
impl FromWasmAbi for #name { impl FromWasmAbi for #rust_name {
type Abi = <JsValue as FromWasmAbi>::Abi; type Abi = <JsValue 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 {
#name { #rust_name {
obj: JsValue::from_abi(js, extra), obj: JsValue::from_abi(js, extra),
} }
} }
} }
impl OptionFromWasmAbi for #name { impl OptionFromWasmAbi for #rust_name {
fn is_none(abi: &Self::Abi) -> bool { *abi == 0 } fn is_none(abi: &Self::Abi) -> bool { *abi == 0 }
} }
impl<'a> IntoWasmAbi for &'a #name { impl<'a> IntoWasmAbi for &'a #rust_name {
type Abi = <&'a JsValue as IntoWasmAbi>::Abi; type Abi = <&'a JsValue as IntoWasmAbi>::Abi;
fn into_abi(self, extra: &mut Stack) -> Self::Abi { fn into_abi(self, extra: &mut Stack) -> Self::Abi {
@ -584,40 +584,40 @@ impl ToTokens for ast::ImportType {
} }
} }
impl RefFromWasmAbi for #name { impl RefFromWasmAbi for #rust_name {
type Abi = <JsValue as RefFromWasmAbi>::Abi; type Abi = <JsValue as RefFromWasmAbi>::Abi;
type Anchor = ManuallyDrop<#name>; type Anchor = ManuallyDrop<#rust_name>;
unsafe fn ref_from_abi(js: Self::Abi, extra: &mut Stack) -> Self::Anchor { unsafe fn ref_from_abi(js: Self::Abi, extra: &mut Stack) -> Self::Anchor {
let tmp = <JsValue as RefFromWasmAbi>::ref_from_abi(js, extra); let tmp = <JsValue as RefFromWasmAbi>::ref_from_abi(js, extra);
ManuallyDrop::new(#name { ManuallyDrop::new(#rust_name {
obj: ManuallyDrop::into_inner(tmp), obj: ManuallyDrop::into_inner(tmp),
}) })
} }
} }
// TODO: remove this on the next major version // TODO: remove this on the next major version
impl From<JsValue> for #name { impl From<JsValue> for #rust_name {
fn from(obj: JsValue) -> #name { fn from(obj: JsValue) -> #rust_name {
#name { obj } #rust_name { obj }
} }
} }
impl AsRef<JsValue> for #name { impl AsRef<JsValue> for #rust_name {
fn as_ref(&self) -> &JsValue { &self.obj } fn as_ref(&self) -> &JsValue { &self.obj }
} }
impl AsMut<JsValue> for #name { impl AsMut<JsValue> for #rust_name {
fn as_mut(&mut self) -> &mut JsValue { &mut self.obj } fn as_mut(&mut self) -> &mut JsValue { &mut self.obj }
} }
impl From<#name> for JsValue { impl From<#rust_name> for JsValue {
fn from(obj: #name) -> JsValue { fn from(obj: #rust_name) -> JsValue {
obj.obj obj.obj
} }
} }
impl JsCast for #name { impl JsCast for #rust_name {
#[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))] #[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))]
fn instanceof(val: &JsValue) -> bool { fn instanceof(val: &JsValue) -> bool {
#[link(wasm_import_module = "__wbindgen_placeholder__")] #[link(wasm_import_module = "__wbindgen_placeholder__")]
@ -637,19 +637,19 @@ impl ToTokens for ast::ImportType {
} }
fn unchecked_from_js(val: JsValue) -> Self { fn unchecked_from_js(val: JsValue) -> Self {
#name { obj: val } #rust_name { obj: val }
} }
fn unchecked_from_js_ref(val: &JsValue) -> &Self { fn unchecked_from_js_ref(val: &JsValue) -> &Self {
// Should be safe because `#name` is a transparent // Should be safe because `#rust_name` is a transparent
// wrapper around `val` // wrapper around `val`
unsafe { &*(val as *const JsValue as *const #name) } unsafe { &*(val as *const JsValue as *const #rust_name) }
} }
fn unchecked_from_js_mut(val: &mut JsValue) -> &mut Self { fn unchecked_from_js_mut(val: &mut JsValue) -> &mut Self {
// Should be safe because `#name` is a transparent // Should be safe because `#rust_name` is a transparent
// wrapper around `val` // wrapper around `val`
unsafe { &mut *(val as *mut JsValue as *mut #name) } unsafe { &mut *(val as *mut JsValue as *mut #rust_name) }
} }
} }
@ -659,21 +659,21 @@ impl ToTokens for ast::ImportType {
for superclass in self.extends.iter() { for superclass in self.extends.iter() {
(quote! { (quote! {
impl From<#name> for #superclass { impl From<#rust_name> for #superclass {
fn from(obj: #name) -> #superclass { fn from(obj: #rust_name) -> #superclass {
use wasm_bindgen::JsCast; use wasm_bindgen::JsCast;
#superclass::unchecked_from_js(obj.into()) #superclass::unchecked_from_js(obj.into())
} }
} }
impl AsRef<#superclass> for #name { impl AsRef<#superclass> for #rust_name {
fn as_ref(&self) -> &#superclass { fn as_ref(&self) -> &#superclass {
use wasm_bindgen::JsCast; use wasm_bindgen::JsCast;
#superclass::unchecked_from_js_ref(self.as_ref()) #superclass::unchecked_from_js_ref(self.as_ref())
} }
} }
impl AsMut<#superclass> for #name { impl AsMut<#superclass> for #rust_name {
fn as_mut(&mut self) -> &mut #superclass { fn as_mut(&mut self) -> &mut #superclass {
use wasm_bindgen::JsCast; use wasm_bindgen::JsCast;
#superclass::unchecked_from_js_mut(self.as_mut()) #superclass::unchecked_from_js_mut(self.as_mut())

View File

@ -205,7 +205,7 @@ impl ImportedTypes for syn::PathArguments {
for input in data.inputs.iter() { for input in data.inputs.iter() {
input.imported_types(f); input.imported_types(f);
} }
// TODO do we need to handle output here? // TODO do we need to handle output here?
// https://docs.rs/syn/0.14.0/syn/struct.ParenthesizedGenericArguments.html // https://docs.rs/syn/0.14.0/syn/struct.ParenthesizedGenericArguments.html
} }
syn::PathArguments::None => {} syn::PathArguments::None => {}
@ -276,7 +276,7 @@ impl ImportedTypes for ast::ImportType {
where where
F: FnMut(&Ident, ImportedTypeKind), F: FnMut(&Ident, ImportedTypeKind),
{ {
f(&self.name, ImportedTypeKind::Definition); f(&self.rust_name, ImportedTypeKind::Definition);
} }
} }

View File

@ -1,7 +1,7 @@
use backend::ast; use backend::ast;
use backend::Diagnostic;
use backend::util::{ident_ty, ShortHash}; use backend::util::{ident_ty, ShortHash};
use proc_macro2::{Ident, Span, TokenStream, TokenTree, Delimiter}; use backend::Diagnostic;
use proc_macro2::{Delimiter, Ident, Span, TokenStream, TokenTree};
use quote::ToTokens; use quote::ToTokens;
use shared; use shared;
use syn; use syn;
@ -49,8 +49,7 @@ impl BindgenAttrs {
.filter_map(|a| match a { .filter_map(|a| match a {
BindgenAttr::Module(s) => Some(&s[..]), BindgenAttr::Module(s) => Some(&s[..]),
_ => None, _ => None,
}) }).next()
.next()
} }
/// Whether the catch attribute is present /// Whether the catch attribute is present
@ -76,8 +75,7 @@ impl BindgenAttrs {
.filter_map(|a| match a { .filter_map(|a| match a {
BindgenAttr::StaticMethodOf(c) => Some(c), BindgenAttr::StaticMethodOf(c) => Some(c),
_ => None, _ => None,
}) }).next()
.next()
} }
/// Whether the method attributes is present /// Whether the method attributes is present
@ -95,8 +93,7 @@ impl BindgenAttrs {
.filter_map(|a| match a { .filter_map(|a| match a {
BindgenAttr::JsNamespace(s) => Some(s), BindgenAttr::JsNamespace(s) => Some(s),
_ => None, _ => None,
}) }).next()
.next()
} }
/// Get the first getter attribute /// Get the first getter attribute
@ -106,8 +103,7 @@ impl BindgenAttrs {
.filter_map(|a| match a { .filter_map(|a| match a {
BindgenAttr::Getter(g) => Some(g.clone()), BindgenAttr::Getter(g) => Some(g.clone()),
_ => None, _ => None,
}) }).next()
.next()
} }
/// Get the first setter attribute /// Get the first setter attribute
@ -117,8 +113,7 @@ impl BindgenAttrs {
.filter_map(|a| match a { .filter_map(|a| match a {
BindgenAttr::Setter(s) => Some(s.clone()), BindgenAttr::Setter(s) => Some(s.clone()),
_ => None, _ => None,
}) }).next()
.next()
} }
/// Whether the indexing getter attributes is present /// Whether the indexing getter attributes is present
@ -168,8 +163,7 @@ impl BindgenAttrs {
.filter_map(|a| match a { .filter_map(|a| match a {
BindgenAttr::JsName(s) => Some(&s[..]), BindgenAttr::JsName(s) => Some(&s[..]),
_ => None, _ => None,
}) }).next()
.next()
} }
/// Get the first js_name attribute /// Get the first js_name attribute
@ -179,18 +173,15 @@ impl BindgenAttrs {
.filter_map(|a| match a { .filter_map(|a| match a {
BindgenAttr::JsClass(s) => Some(&s[..]), BindgenAttr::JsClass(s) => Some(&s[..]),
_ => None, _ => None,
}) }).next()
.next()
} }
/// Return the list of classes that a type extends /// Return the list of classes that a type extends
fn extends(&self) -> impl Iterator<Item = &Ident> { fn extends(&self) -> impl Iterator<Item = &Ident> {
self.attrs self.attrs.iter().filter_map(|a| match a {
.iter() BindgenAttr::Extends(s) => Some(s),
.filter_map(|a| match a { _ => None,
BindgenAttr::Extends(s) => Some(s), })
_ => None,
})
} }
} }
@ -398,9 +389,10 @@ impl<'a> ConvertToAst<()> for &'a mut syn::ItemStruct {
impl<'a> ConvertToAst<(BindgenAttrs, &'a Option<String>)> for syn::ForeignItemFn { impl<'a> ConvertToAst<(BindgenAttrs, &'a Option<String>)> for syn::ForeignItemFn {
type Target = ast::ImportKind; type Target = ast::ImportKind;
fn convert(self, (opts, module): (BindgenAttrs, &'a Option<String>)) fn convert(
-> Result<Self::Target, Diagnostic> self,
{ (opts, module): (BindgenAttrs, &'a Option<String>),
) -> Result<Self::Target, Diagnostic> {
let default_name = self.ident.to_string(); let default_name = self.ident.to_string();
let js_name = opts.js_name().unwrap_or(&default_name); let js_name = opts.js_name().unwrap_or(&default_name);
let wasm = function_from_decl( let wasm = function_from_decl(
@ -443,21 +435,19 @@ impl<'a> ConvertToAst<(BindgenAttrs, &'a Option<String>)> for syn::ForeignItemFn
} }
let kind = if opts.method() { let kind = if opts.method() {
let class = wasm let class = wasm.arguments.get(0).ok_or_else(|| {
.arguments err_span!(self, "imported methods must have at least one argument")
.get(0) })?;
.ok_or_else(|| {
err_span!(self, "imported methods must have at least one argument")
})?;
let class = match class.ty { let class = match class.ty {
syn::Type::Reference(syn::TypeReference { syn::Type::Reference(syn::TypeReference {
mutability: None, mutability: None,
ref elem, ref elem,
.. ..
}) => &**elem, }) => &**elem,
_ => { _ => bail_span!(
bail_span!(class.ty, "first argument of method must be a shared reference") class.ty,
} "first argument of method must be a shared reference"
),
}; };
let class_name = match *class { let class_name = match *class {
syn::Type::Path(syn::TypePath { syn::Type::Path(syn::TypePath {
@ -521,9 +511,14 @@ impl<'a> ConvertToAst<(BindgenAttrs, &'a Option<String>)> for syn::ForeignItemFn
ast::ImportFunctionKind::Method { ref class, .. } => (1, &class[..]), ast::ImportFunctionKind::Method { ref class, .. } => (1, &class[..]),
}; };
let data = (ns, &self.ident, module); let data = (ns, &self.ident, module);
format!("__wbg_{}_{}", format!(
js_name.chars().filter(|c| c.is_ascii_alphanumeric()).collect::<String>(), "__wbg_{}_{}",
ShortHash(data)) js_name
.chars()
.filter(|c| c.is_ascii_alphanumeric())
.collect::<String>(),
ShortHash(data)
)
}; };
Ok(ast::ImportKind::Function(ast::ImportFunction { Ok(ast::ImportKind::Function(ast::ImportFunction {
function: wasm, function: wasm,
@ -542,13 +537,17 @@ impl ConvertToAst<BindgenAttrs> for syn::ForeignItemType {
type Target = ast::ImportKind; type Target = ast::ImportKind;
fn convert(self, attrs: BindgenAttrs) -> Result<Self::Target, Diagnostic> { fn convert(self, attrs: BindgenAttrs) -> Result<Self::Target, Diagnostic> {
let js_name = attrs
.js_name()
.map_or_else(|| self.ident.to_string(), |s| s.to_string());
let shim = format!("__wbg_instanceof_{}_{}", self.ident, ShortHash(&self.ident)); let shim = format!("__wbg_instanceof_{}_{}", self.ident, ShortHash(&self.ident));
Ok(ast::ImportKind::Type(ast::ImportType { Ok(ast::ImportKind::Type(ast::ImportType {
vis: self.vis, vis: self.vis,
attrs: self.attrs, attrs: self.attrs,
doc_comment: None, doc_comment: None,
instanceof_shim: shim, instanceof_shim: shim,
name: self.ident, rust_name: self.ident,
js_name,
extends: attrs.extends().cloned().collect(), extends: attrs.extends().cloned().collect(),
})) }))
} }
@ -563,9 +562,14 @@ impl ConvertToAst<BindgenAttrs> for syn::ForeignItemStatic {
} }
let default_name = self.ident.to_string(); let default_name = self.ident.to_string();
let js_name = opts.js_name().unwrap_or(&default_name); let js_name = opts.js_name().unwrap_or(&default_name);
let shim = format!("__wbg_static_accessor_{}_{}", let shim = format!(
js_name.chars().filter(|c| c.is_ascii_alphanumeric()).collect::<String>(), "__wbg_static_accessor_{}_{}",
self.ident); js_name
.chars()
.filter(|c| c.is_ascii_alphanumeric())
.collect::<String>(),
self.ident
);
Ok(ast::ImportKind::Static(ast::ImportStatic { Ok(ast::ImportKind::Static(ast::ImportStatic {
ty: *self.ty, ty: *self.ty,
vis: self.vis, vis: self.vis,
@ -585,7 +589,10 @@ impl ConvertToAst<BindgenAttrs> for syn::ItemFn {
_ => bail_span!(self, "can only #[wasm_bindgen] public functions"), _ => bail_span!(self, "can only #[wasm_bindgen] public functions"),
} }
if self.constness.is_some() { if self.constness.is_some() {
bail_span!(self.constness, "can only #[wasm_bindgen] non-const functions"); bail_span!(
self.constness,
"can only #[wasm_bindgen] non-const functions"
);
} }
if self.unsafety.is_some() { if self.unsafety.is_some() {
bail_span!(self.unsafety, "can only #[wasm_bindgen] safe functions"); bail_span!(self.unsafety, "can only #[wasm_bindgen] safe functions");
@ -629,8 +636,7 @@ fn function_from_decl(
syn::Type::Path(syn::TypePath { qself: None, path }) => path, syn::Type::Path(syn::TypePath { qself: None, path }) => path,
other => return other, other => return other,
}; };
let new_path = if path.segments.len() == 1 && let new_path = if path.segments.len() == 1 && path.segments[0].ident == "Self" {
path.segments[0].ident == "Self" {
self_ty.clone().into() self_ty.clone().into()
} else { } else {
path path
@ -664,8 +670,7 @@ fn function_from_decl(
None None
} }
_ => panic!("arguments cannot be `self` or ignored"), _ => panic!("arguments cannot be `self` or ignored"),
}) }).collect::<Vec<_>>();
.collect::<Vec<_>>();
let ret = match output { let ret = match output {
syn::ReturnType::Default => None, syn::ReturnType::Default => None,
@ -689,8 +694,7 @@ pub(crate) trait MacroParse<Ctx> {
/// ///
/// The context is used to have access to the attributes on `#[wasm_bindgen]`, and to allow /// The context is used to have access to the attributes on `#[wasm_bindgen]`, and to allow
/// writing to the output `TokenStream`. /// writing to the output `TokenStream`.
fn macro_parse(self, program: &mut ast::Program, context: Ctx) fn macro_parse(self, program: &mut ast::Program, context: Ctx) -> Result<(), Diagnostic>;
-> Result<(), Diagnostic>;
} }
impl<'a> MacroParse<(Option<BindgenAttrs>, &'a mut TokenStream)> for syn::Item { impl<'a> MacroParse<(Option<BindgenAttrs>, &'a mut TokenStream)> for syn::Item {
@ -743,13 +747,11 @@ impl<'a> MacroParse<(Option<BindgenAttrs>, &'a mut TokenStream)> for syn::Item {
e.to_tokens(tokens); e.to_tokens(tokens);
e.macro_parse(program, ())?; e.macro_parse(program, ())?;
} }
_ => { _ => bail_span!(
bail_span!( self,
self, "#[wasm_bindgen] can only be applied to a function, \
"#[wasm_bindgen] can only be applied to a function, \ struct, enum, impl, or extern block"
struct, enum, impl, or extern block" ),
)
}
} }
Ok(()) Ok(())
@ -757,27 +759,37 @@ impl<'a> MacroParse<(Option<BindgenAttrs>, &'a mut TokenStream)> for syn::Item {
} }
impl<'a> MacroParse<()> for &'a mut syn::ItemImpl { impl<'a> MacroParse<()> for &'a mut syn::ItemImpl {
fn macro_parse(self, program: &mut ast::Program, (): ()) fn macro_parse(self, program: &mut ast::Program, (): ()) -> Result<(), Diagnostic> {
-> Result<(), Diagnostic>
{
if self.defaultness.is_some() { if self.defaultness.is_some() {
bail_span!(self.defaultness, "#[wasm_bindgen] default impls are not supported"); bail_span!(
self.defaultness,
"#[wasm_bindgen] default impls are not supported"
);
} }
if self.unsafety.is_some() { if self.unsafety.is_some() {
bail_span!(self.unsafety, "#[wasm_bindgen] unsafe impls are not supported"); bail_span!(
self.unsafety,
"#[wasm_bindgen] unsafe impls are not supported"
);
} }
if let Some((_, path, _)) = &self.trait_ { if let Some((_, path, _)) = &self.trait_ {
bail_span!(path, "#[wasm_bindgen] trait impls are not supported"); bail_span!(path, "#[wasm_bindgen] trait impls are not supported");
} }
if self.generics.params.len() > 0 { if self.generics.params.len() > 0 {
bail_span!(self.generics, "#[wasm_bindgen] generic impls aren't supported"); bail_span!(
self.generics,
"#[wasm_bindgen] generic impls aren't supported"
);
} }
let name = match *self.self_ty { let name = match *self.self_ty {
syn::Type::Path(syn::TypePath { syn::Type::Path(syn::TypePath {
qself: None, qself: None,
ref path, ref path,
}) => extract_path_ident(path)?, }) => extract_path_ident(path)?,
_ => bail_span!(self.self_ty, "unsupported self type in #[wasm_bindgen] impl"), _ => bail_span!(
self.self_ty,
"unsupported self type in #[wasm_bindgen] impl"
),
}; };
let mut errors = Vec::new(); let mut errors = Vec::new();
for item in self.items.iter_mut() { for item in self.items.iter_mut() {
@ -790,18 +802,20 @@ impl<'a> MacroParse<()> for &'a mut syn::ItemImpl {
} }
impl<'a, 'b> MacroParse<()> for (&'a Ident, &'b mut syn::ImplItem) { impl<'a, 'b> MacroParse<()> for (&'a Ident, &'b mut syn::ImplItem) {
fn macro_parse(self, program: &mut ast::Program, (): ()) fn macro_parse(self, program: &mut ast::Program, (): ()) -> Result<(), Diagnostic> {
-> Result<(), Diagnostic>
{
let (class, item) = self; let (class, item) = self;
let method = match item { let method = match item {
syn::ImplItem::Method(ref mut m) => m, syn::ImplItem::Method(ref mut m) => m,
syn::ImplItem::Const(_) => { syn::ImplItem::Const(_) => {
bail_span!(&*item, "const definitions aren't supported with #[wasm_bindgen]"); bail_span!(
} &*item,
syn::ImplItem::Type(_) => { "const definitions aren't supported with #[wasm_bindgen]"
bail_span!(&*item, "type definitions in impls aren't supported with #[wasm_bindgen]") );
} }
syn::ImplItem::Type(_) => bail_span!(
&*item,
"type definitions in impls aren't supported with #[wasm_bindgen]"
),
syn::ImplItem::Macro(_) => { syn::ImplItem::Macro(_) => {
bail_span!(&*item, "macros in impls aren't supported"); bail_span!(&*item, "macros in impls aren't supported");
} }
@ -821,10 +835,7 @@ impl<'a, 'b> MacroParse<()> for (&'a Ident, &'b mut syn::ImplItem) {
); );
} }
if method.sig.unsafety.is_some() { if method.sig.unsafety.is_some() {
bail_span!( bail_span!(method.sig.unsafety, "can only bindgen safe functions",);
method.sig.unsafety,
"can only bindgen safe functions",
);
} }
let opts = BindgenAttrs::find(&mut method.attrs)?; let opts = BindgenAttrs::find(&mut method.attrs)?;
@ -858,9 +869,7 @@ impl<'a, 'b> MacroParse<()> for (&'a Ident, &'b mut syn::ImplItem) {
} }
impl MacroParse<()> for syn::ItemEnum { impl MacroParse<()> for syn::ItemEnum {
fn macro_parse(self, program: &mut ast::Program, (): ()) fn macro_parse(self, program: &mut ast::Program, (): ()) -> Result<(), Diagnostic> {
-> Result<(), Diagnostic>
{
match self.vis { match self.vis {
syn::Visibility::Public(_) => {} syn::Visibility::Public(_) => {}
_ => bail_span!(self, "only public enums are allowed with #[wasm_bindgen]"), _ => bail_span!(self, "only public enums are allowed with #[wasm_bindgen]"),
@ -893,21 +902,18 @@ impl MacroParse<()> for syn::ItemEnum {
int_lit.value() as u32 int_lit.value() as u32
} }
None => i as u32, None => i as u32,
Some((_, ref expr)) => { Some((_, ref expr)) => bail_span!(
bail_span!( expr,
expr, "enums with #[wasm_bidngen] may only have \
"enums with #[wasm_bidngen] may only have \ number literal values",
number literal values", ),
)
}
}; };
Ok(ast::Variant { Ok(ast::Variant {
name: v.ident.clone(), name: v.ident.clone(),
value, value,
}) })
}) }).collect::<Result<_, Diagnostic>>()?;
.collect::<Result<_, Diagnostic>>()?;
let comments = extract_doc_comments(&self.attrs); let comments = extract_doc_comments(&self.attrs);
program.enums.push(ast::Enum { program.enums.push(ast::Enum {
name: self.ident, name: self.ident,
@ -919,15 +925,16 @@ impl MacroParse<()> for syn::ItemEnum {
} }
impl MacroParse<BindgenAttrs> for syn::ItemForeignMod { impl MacroParse<BindgenAttrs> for syn::ItemForeignMod {
fn macro_parse(self, program: &mut ast::Program, opts: BindgenAttrs) fn macro_parse(self, program: &mut ast::Program, opts: BindgenAttrs) -> Result<(), Diagnostic> {
-> Result<(), Diagnostic>
{
let mut errors = Vec::new(); let mut errors = Vec::new();
match self.abi.name { match self.abi.name {
Some(ref l) if l.value() == "C" => {} Some(ref l) if l.value() == "C" => {}
None => {} None => {}
Some(ref other) => { Some(ref other) => {
errors.push(err_span!(other, "only foreign mods with the `C` ABI are allowed")); errors.push(err_span!(
other,
"only foreign mods with the `C` ABI are allowed"
));
} }
} }
for mut item in self.items.into_iter() { for mut item in self.items.into_iter() {
@ -940,9 +947,11 @@ impl MacroParse<BindgenAttrs> for syn::ItemForeignMod {
} }
impl<'a> MacroParse<&'a BindgenAttrs> for syn::ForeignItem { impl<'a> MacroParse<&'a BindgenAttrs> for syn::ForeignItem {
fn macro_parse(mut self, program: &mut ast::Program, opts: &'a BindgenAttrs) fn macro_parse(
-> Result<(), Diagnostic> mut self,
{ program: &mut ast::Program,
opts: &'a BindgenAttrs,
) -> Result<(), Diagnostic> {
let item_opts = { let item_opts = {
let attrs = match self { let attrs = match self {
syn::ForeignItem::Fn(ref mut f) => &mut f.attrs, syn::ForeignItem::Fn(ref mut f) => &mut f.attrs,
@ -984,14 +993,18 @@ fn extract_first_ty_param(ty: Option<&syn::Type>) -> Result<Option<syn::Type>, D
}) => path, }) => path,
_ => bail_span!(t, "must be Result<...>"), _ => bail_span!(t, "must be Result<...>"),
}; };
let seg = path.segments.last() let seg = path
.segments
.last()
.ok_or_else(|| err_span!(t, "must have at least one segment"))? .ok_or_else(|| err_span!(t, "must have at least one segment"))?
.into_value(); .into_value();
let generics = match seg.arguments { let generics = match seg.arguments {
syn::PathArguments::AngleBracketed(ref t) => t, syn::PathArguments::AngleBracketed(ref t) => t,
_ => bail_span!(t, "must be Result<...>"), _ => bail_span!(t, "must be Result<...>"),
}; };
let generic = generics.args.first() let generic = generics
.args
.first()
.ok_or_else(|| err_span!(t, "must have at least one generic parameter"))? .ok_or_else(|| err_span!(t, "must have at least one generic parameter"))?
.into_value(); .into_value();
let ty = match generic { let ty = match generic {
@ -1047,7 +1060,9 @@ fn assert_no_lifetimes(decl: &syn::FnDecl) -> Result<(), Diagnostic> {
)); ));
} }
} }
let mut walk = Walk { diagnostics: Vec::new() }; let mut walk = Walk {
diagnostics: Vec::new(),
};
syn::visit::Visit::visit_fn_decl(&mut walk, decl); syn::visit::Visit::visit_fn_decl(&mut walk, decl);
Diagnostic::from_vec(walk.diagnostics) Diagnostic::from_vec(walk.diagnostics)
} }

View File

@ -1,5 +1,6 @@
use wasm_bindgen_test::*; use wasm_bindgen_test::*;
use wasm_bindgen::prelude::*; use wasm_bindgen::prelude::*;
use wasm_bindgen::JsCast;
use web_sys::HtmlElement; use web_sys::HtmlElement;
#[wasm_bindgen(module = "./tests/wasm/element.js")] #[wasm_bindgen(module = "./tests/wasm/element.js")]
@ -10,6 +11,8 @@ extern {
#[wasm_bindgen_test] #[wasm_bindgen_test]
fn test_html_element() { fn test_html_element() {
let element = new_html(); let element = new_html();
assert!(element.is_instance_of::<HtmlElement>());
assert_eq!(element.title(), "", "Shouldn't have a title"); assert_eq!(element.title(), "", "Shouldn't have a title");
element.set_title("boop"); element.set_title("boop");
assert_eq!(element.title(), "boop", "Should have a title"); assert_eq!(element.title(), "boop", "Should have a title");

View File

@ -244,7 +244,8 @@ impl<'src> WebidlParse<'src, ()> for weedle::InterfaceDefinition<'src> {
js_namespace: None, js_namespace: None,
kind: backend::ast::ImportKind::Type(backend::ast::ImportType { kind: backend::ast::ImportKind::Type(backend::ast::ImportType {
vis: public(), vis: public(),
name: rust_ident(camel_case_ident(self.identifier.0).as_str()), rust_name: rust_ident(camel_case_ident(self.identifier.0).as_str()),
js_name: self.identifier.0.to_string(),
attrs: Vec::new(), attrs: Vec::new(),
doc_comment, doc_comment,
instanceof_shim: format!("__widl_instanceof_{}", self.identifier.0), instanceof_shim: format!("__widl_instanceof_{}", self.identifier.0),

41
package-lock.json generated
View File

@ -1923,8 +1923,7 @@
"ansi-regex": { "ansi-regex": {
"version": "2.1.1", "version": "2.1.1",
"bundled": true, "bundled": true,
"dev": true, "dev": true
"optional": true
}, },
"aproba": { "aproba": {
"version": "1.2.0", "version": "1.2.0",
@ -1945,14 +1944,12 @@
"balanced-match": { "balanced-match": {
"version": "1.0.0", "version": "1.0.0",
"bundled": true, "bundled": true,
"dev": true, "dev": true
"optional": true
}, },
"brace-expansion": { "brace-expansion": {
"version": "1.1.11", "version": "1.1.11",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"balanced-match": "^1.0.0", "balanced-match": "^1.0.0",
"concat-map": "0.0.1" "concat-map": "0.0.1"
@ -1967,20 +1964,17 @@
"code-point-at": { "code-point-at": {
"version": "1.1.0", "version": "1.1.0",
"bundled": true, "bundled": true,
"dev": true, "dev": true
"optional": true
}, },
"concat-map": { "concat-map": {
"version": "0.0.1", "version": "0.0.1",
"bundled": true, "bundled": true,
"dev": true, "dev": true
"optional": true
}, },
"console-control-strings": { "console-control-strings": {
"version": "1.1.0", "version": "1.1.0",
"bundled": true, "bundled": true,
"dev": true, "dev": true
"optional": true
}, },
"core-util-is": { "core-util-is": {
"version": "1.0.2", "version": "1.0.2",
@ -2097,8 +2091,7 @@
"inherits": { "inherits": {
"version": "2.0.3", "version": "2.0.3",
"bundled": true, "bundled": true,
"dev": true, "dev": true
"optional": true
}, },
"ini": { "ini": {
"version": "1.3.5", "version": "1.3.5",
@ -2110,7 +2103,6 @@
"version": "1.0.0", "version": "1.0.0",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"number-is-nan": "^1.0.0" "number-is-nan": "^1.0.0"
} }
@ -2125,7 +2117,6 @@
"version": "3.0.4", "version": "3.0.4",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"brace-expansion": "^1.1.7" "brace-expansion": "^1.1.7"
} }
@ -2133,14 +2124,12 @@
"minimist": { "minimist": {
"version": "0.0.8", "version": "0.0.8",
"bundled": true, "bundled": true,
"dev": true, "dev": true
"optional": true
}, },
"minipass": { "minipass": {
"version": "2.2.4", "version": "2.2.4",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"safe-buffer": "^5.1.1", "safe-buffer": "^5.1.1",
"yallist": "^3.0.0" "yallist": "^3.0.0"
@ -2159,7 +2148,6 @@
"version": "0.5.1", "version": "0.5.1",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"minimist": "0.0.8" "minimist": "0.0.8"
} }
@ -2240,8 +2228,7 @@
"number-is-nan": { "number-is-nan": {
"version": "1.0.1", "version": "1.0.1",
"bundled": true, "bundled": true,
"dev": true, "dev": true
"optional": true
}, },
"object-assign": { "object-assign": {
"version": "4.1.1", "version": "4.1.1",
@ -2253,7 +2240,6 @@
"version": "1.4.0", "version": "1.4.0",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"wrappy": "1" "wrappy": "1"
} }
@ -2339,8 +2325,7 @@
"safe-buffer": { "safe-buffer": {
"version": "5.1.1", "version": "5.1.1",
"bundled": true, "bundled": true,
"dev": true, "dev": true
"optional": true
}, },
"safer-buffer": { "safer-buffer": {
"version": "2.1.2", "version": "2.1.2",
@ -2376,7 +2361,6 @@
"version": "1.0.2", "version": "1.0.2",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"code-point-at": "^1.0.0", "code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0", "is-fullwidth-code-point": "^1.0.0",
@ -2396,7 +2380,6 @@
"version": "3.0.1", "version": "3.0.1",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"ansi-regex": "^2.0.0" "ansi-regex": "^2.0.0"
} }
@ -2440,14 +2423,12 @@
"wrappy": { "wrappy": {
"version": "1.0.2", "version": "1.0.2",
"bundled": true, "bundled": true,
"dev": true, "dev": true
"optional": true
}, },
"yallist": { "yallist": {
"version": "3.0.2", "version": "3.0.2",
"bundled": true, "bundled": true,
"dev": true, "dev": true
"optional": true
} }
} }
}, },

View File

@ -87,3 +87,6 @@ exports.test_rust_optional = function() {
assert.strictEqual(wasm.return_optional_str_none(), undefined); assert.strictEqual(wasm.return_optional_str_none(), undefined);
assert.strictEqual(wasm.return_optional_str_some(), 'world'); assert.strictEqual(wasm.return_optional_str_some(), 'world');
}; };
exports.RenamedInRust = class {};
exports.new_renamed = () => new exports.RenamedInRust;

View File

@ -1,5 +1,6 @@
use wasm_bindgen_test::*; use wasm_bindgen_test::*;
use wasm_bindgen::prelude::*; use wasm_bindgen::prelude::*;
use wasm_bindgen::JsCast;
#[wasm_bindgen(module = "tests/wasm/simple.js")] #[wasm_bindgen(module = "tests/wasm/simple.js")]
extern { extern {
@ -20,6 +21,10 @@ extern {
fn return_string_none() -> Option<String>; fn return_string_none() -> Option<String>;
fn return_string_some() -> Option<String>; fn return_string_some() -> Option<String>;
fn test_rust_optional(); fn test_rust_optional();
#[wasm_bindgen(js_name = RenamedInRust)]
type Renamed;
fn new_renamed() -> Renamed;
} }
#[wasm_bindgen_test] #[wasm_bindgen_test]
@ -178,3 +183,15 @@ pub fn return_optional_str_none() -> Option<String> {
pub fn return_optional_str_some() -> Option<String> { pub fn return_optional_str_some() -> Option<String> {
Some("world".to_string()) Some("world".to_string())
} }
#[wasm_bindgen_test]
fn renaming_imports_and_instanceof() {
let null = JsValue::NULL;
assert!(!null.is_instance_of::<Renamed>());
let arr: JsValue = Array::new().into();
assert!(!arr.is_instance_of::<Renamed>());
let renamed: JsValue = new_renamed().into();
assert!(renamed.is_instance_of::<Renamed>());
}