Add a #[wasm_bindgen(constructor)] attribute

This can be used for specifying that a static function should actually delegate
to `new`
This commit is contained in:
Alex Crichton
2018-02-06 15:19:47 -08:00
parent e60aa6a990
commit ec5f0a29f7
6 changed files with 131 additions and 24 deletions

View File

@ -501,27 +501,26 @@ impl<'a> Js<'a> {
}
for f in import.functions.iter() {
self.generate_import_struct_function(&import.name,
f.method,
&f.function);
self.generate_import_struct_function(&import.name, f);
}
}
fn generate_import_struct_function(
&mut self,
class: &str,
is_method: bool,
function: &shared::Function,
f: &shared::ImportStructFunction,
) {
let delegate = if is_method {
format!("{}.prototype.{}.call", class, function.name)
let delegate = if f.method {
format!("{}.prototype.{}.call", class, f.function.name)
} else if f.js_new {
format!("new {}", class)
} else {
format!("{}.{}", class, function.name)
format!("{}.{}", class, f.function.name)
};
self.gen_import_shim(&shared::mangled_import_name(Some(class), &function.name),
self.gen_import_shim(&shared::mangled_import_name(Some(class), &f.function.name),
&delegate,
is_method,
function)
f.method,
&f.function)
}
fn gen_import_shim(

View File

@ -32,7 +32,13 @@ pub struct ImportFunction {
pub struct ImportStruct {
pub module: Option<String>,
pub name: syn::Ident,
pub functions: Vec<(bool, ImportFunction)>,
pub functions: Vec<(ImportFunctionKind, ImportFunction)>,
}
pub enum ImportFunctionKind {
Method,
Static,
JsConstructor,
}
pub enum Type {
@ -154,7 +160,43 @@ impl Program {
let functions = class.functions.iter()
.map(|f| {
let (f, method) = self.gen_foreign_item(f, true);
(method, f)
let kind = if method {
ImportFunctionKind::Method
} else {
let new = f.rust_attrs.iter()
.filter_map(|a| a.interpret_meta())
.filter_map(|m| {
match m {
syn::Meta::List(i) => {
if i.ident == "wasm_bindgen" {
Some(i.nested)
} else {
None
}
}
_ => None,
}
})
.flat_map(|a| a)
.filter_map(|a| {
match a {
syn::NestedMeta::Meta(a) => Some(a),
_ => None,
}
})
.any(|a| {
match a {
syn::Meta::Word(a) => a == "constructor",
_ => false,
}
});
if new {
ImportFunctionKind::JsConstructor
} else {
ImportFunctionKind::Static
}
};
(kind, f)
})
.collect();
self.imported_structs.push(ImportStruct {
@ -423,9 +465,15 @@ impl ImportStruct {
("name", &|a| a.str(self.name.as_ref())),
("functions", &|a| {
a.list(&self.functions,
|&(is_method, ref f), a| {
|&(ref kind, ref f), a| {
let (method, new) = match *kind {
ImportFunctionKind::Method => (true, false),
ImportFunctionKind::JsConstructor => (false, true),
ImportFunctionKind::Static => (false, false),
};
a.fields(&[
("method", &|a| a.bool(is_method)),
("method", &|a| a.bool(method)),
("js_new", &|a| a.bool(new)),
("function", &|a| f.wasm_function.wbg_literal(a)),
]);
})

View File

@ -367,7 +367,7 @@ fn bindgen_imported_struct(import: &ast::ImportStruct, tokens: &mut Tokens) {
let mut methods = Tokens::new();
for &(_is_method, ref f) in import.functions.iter() {
for &(_, ref f) in import.functions.iter() {
let import_name = shared::mangled_import_name(
Some(&import.name.to_string()),
f.wasm_function.name.as_ref(),

View File

@ -33,6 +33,7 @@ pub struct ImportStruct {
#[derive(Serialize, Deserialize)]
pub struct ImportStructFunction {
pub method: bool,
pub js_new: bool,
pub function: Function,
}