Allow js_name attribute to accept a string

This commit is contained in:
Michael Hoffmann 2018-08-05 00:17:30 +02:00 committed by Alex Crichton
parent 63ee9a024d
commit 21c36d3902
4 changed files with 114 additions and 18 deletions

View File

@ -116,7 +116,7 @@ pub struct ImportStatic {
pub ty: syn::Type, pub ty: syn::Type,
pub shim: Ident, pub shim: Ident,
pub rust_name: Ident, pub rust_name: Ident,
pub js_name: Ident, pub js_name: String,
} }
#[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq, Eq))] #[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq, Eq))]
@ -143,7 +143,7 @@ pub struct ImportEnum {
#[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq, Eq))] #[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq, Eq))]
pub struct Function { pub struct Function {
pub name: Ident, pub name: String,
pub arguments: Vec<syn::ArgCaptured>, pub arguments: Vec<syn::ArgCaptured>,
pub ret: Option<syn::Type>, pub ret: Option<syn::Type>,
pub rust_attrs: Vec<syn::Attribute>, pub rust_attrs: Vec<syn::Attribute>,

View File

@ -149,11 +149,11 @@ impl BindgenAttrs {
} }
/// Get the first js_name attribute /// Get the first js_name attribute
fn js_name(&self) -> Option<&Ident> { fn js_name(&self) -> Option<&str> {
self.attrs self.attrs
.iter() .iter()
.filter_map(|a| match a { .filter_map(|a| match a {
BindgenAttr::JsName(s) => Some(s), BindgenAttr::JsName(s) => Some(&s[..]),
_ => None, _ => None,
}) })
.next() .next()
@ -200,7 +200,7 @@ pub enum BindgenAttr {
Setter(Option<Ident>), Setter(Option<Ident>),
Structural, Structural,
Readonly, Readonly,
JsName(Ident), JsName(String),
JsClass(String), JsClass(String),
} }
@ -267,8 +267,12 @@ impl syn::synom::Synom for BindgenAttr {
do_parse!( do_parse!(
call!(term, "js_name") >> call!(term, "js_name") >>
punct!(=) >> punct!(=) >>
ns: call!(term2ident) >> name: alt!(
(ns) syn!(syn::LitStr) => { |s| s.value() }
|
call!(term2ident) => { |s| s.to_string() }
) >>
(name)
)=> { BindgenAttr::JsName } )=> { BindgenAttr::JsName }
| |
do_parse!( do_parse!(
@ -365,9 +369,10 @@ impl<'a> ConvertToAst<(BindgenAttrs, &'a Option<String>)> for syn::ForeignItemFn
fn convert(self, (opts, module): (BindgenAttrs, &'a Option<String>)) fn convert(self, (opts, module): (BindgenAttrs, &'a Option<String>))
-> Result<Self::Target, Diagnostic> -> Result<Self::Target, Diagnostic>
{ {
let js_name = opts.js_name().unwrap_or(&self.ident).clone(); let default_name = self.ident.to_string();
let js_name = opts.js_name().unwrap_or(&default_name);
let wasm = function_from_decl( let wasm = function_from_decl(
&js_name, js_name,
self.decl.clone(), self.decl.clone(),
self.attrs.clone(), self.attrs.clone(),
self.vis.clone(), self.vis.clone(),
@ -475,7 +480,9 @@ 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_{}_{}", js_name, ShortHash(data)) format!("__wbg_{}_{}",
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,
@ -510,13 +517,16 @@ impl ConvertToAst<BindgenAttrs> for syn::ForeignItemStatic {
if self.mutability.is_some() { if self.mutability.is_some() {
bail_span!(self.mutability, "cannot import mutable globals yet") bail_span!(self.mutability, "cannot import mutable globals yet")
} }
let js_name = opts.js_name().unwrap_or(&self.ident); let default_name = self.ident.to_string();
let shim = format!("__wbg_static_accessor_{}_{}", js_name, self.ident); let js_name = opts.js_name().unwrap_or(&default_name);
let shim = format!("__wbg_static_accessor_{}_{}",
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,
rust_name: self.ident.clone(), rust_name: self.ident.clone(),
js_name: js_name.clone(), js_name: js_name.to_string(),
shim: Ident::new(&shim, Span::call_site()), shim: Ident::new(&shim, Span::call_site()),
})) }))
} }
@ -537,14 +547,15 @@ impl ConvertToAst<BindgenAttrs> for syn::ItemFn {
bail_span!(self.unsafety, "can only #[wasm_bindgen] safe functions"); bail_span!(self.unsafety, "can only #[wasm_bindgen] safe functions");
} }
let name = attrs.js_name().unwrap_or(&self.ident); let default_name = self.ident.to_string();
let name = attrs.js_name().unwrap_or(&default_name);
Ok(function_from_decl(name, self.decl, self.attrs, self.vis, false, None)?.0) Ok(function_from_decl(name, self.decl, self.attrs, self.vis, false, None)?.0)
} }
} }
/// Construct a function (and gets the self type if appropriate) for our AST from a syn function. /// Construct a function (and gets the self type if appropriate) for our AST from a syn function.
fn function_from_decl( fn function_from_decl(
name: &Ident, name: &str,
decl: Box<syn::FnDecl>, decl: Box<syn::FnDecl>,
attrs: Vec<syn::Attribute>, attrs: Vec<syn::Attribute>,
vis: syn::Visibility, vis: syn::Visibility,
@ -619,7 +630,7 @@ fn function_from_decl(
Ok(( Ok((
ast::Function { ast::Function {
name: name.clone(), name: name.to_string(),
arguments, arguments,
ret, ret,
rust_vis: vis, rust_vis: vis,
@ -782,7 +793,7 @@ impl<'a, 'b> MacroParse<()> for (&'a Ident, &'b mut syn::ImplItem) {
}; };
let (function, method_self) = function_from_decl( let (function, method_self) = function_from_decl(
opts.js_name().unwrap_or(&method.sig.ident), opts.js_name().unwrap_or(&method.sig.ident.to_string()),
Box::new(method.sig.decl.clone()), Box::new(method.sig.decl.clone()),
method.attrs.clone(), method.attrs.clone(),
method.vis.clone(), method.vis.clone(),

View File

@ -563,7 +563,7 @@ impl<'a> FirstPassRecord<'a> {
name.to_snake_case() name.to_snake_case()
} }
); );
let name = raw_ident(name); let name = name.to_string();
let arguments = self.webidl_arguments_to_syn_arg_captured(arguments.into_iter(), &kind)?; let arguments = self.webidl_arguments_to_syn_arg_captured(arguments.into_iter(), &kind)?;

View File

@ -36,6 +36,91 @@ fn unused_imports_not_generated() {
assert!(!contents.contains("foo"), "found `foo` in {}", contents); assert!(!contents.contains("foo"), "found `foo` in {}", contents);
} }
#[test]
fn rename_with_string() {
project()
.file(
"src/lib.rs",
r#"
#![feature(use_extern_macros)]
extern crate wasm_bindgen;
use wasm_bindgen::prelude::*;
#[wasm_bindgen(module = "./test")]
extern {
#[wasm_bindgen(js_name = "baz$")]
fn foo();
}
#[wasm_bindgen]
pub fn run() {
foo();
}
"#,
)
.file(
"test.js",
r#"
import * as wasm from "./out";
import * as assert from "assert";
let called = false;
export function baz$() {
called = true;
}
export function test() {
wasm.run();
assert.strictEqual(called, true);
}
"#,
)
.test();
}
#[test]
fn rename_static_with_string() {
project()
.debug(false)
.file(
"src/lib.rs",
r#"
#![feature(use_extern_macros)]
extern crate wasm_bindgen;
use wasm_bindgen::prelude::*;
#[wasm_bindgen(module = "./test")]
extern {
#[wasm_bindgen(js_name = "$foo")]
static FOO: JsValue;
}
#[wasm_bindgen]
pub fn run() {
assert_eq!(FOO.as_f64(), Some(1.0));
}
"#,
)
.file(
"test.js",
r#"
import { run } from "./out";
export const $foo = 1.0;
export function test() {
run();
}
"#,
)
.test();
}
#[test] #[test]
fn versions() { fn versions() {
project() project()