mirror of
https://github.com/fluencelabs/wasm-bindgen
synced 2025-04-26 14:32:12 +00:00
Rename static
to namespace
This commit renames the `static` attribute to `namespace` and simultaneously reduces and expands the scope. The `namespace` attribute can now be applied to all imports in addition to functions, and it no longer recognizes full typed paths but rather just a bare identifier. The `namespace` attribute will generate a Rust namespace to invoke the item through if one doesn't already exist (aka bindign a type).
This commit is contained in:
parent
dd054fa357
commit
4a4f8b18b6
@ -658,7 +658,7 @@ extern {
|
|||||||
#[wasm_bindgen(constructor)]
|
#[wasm_bindgen(constructor)]
|
||||||
fn new(arg: i32) -> Bar;
|
fn new(arg: i32) -> Bar;
|
||||||
|
|
||||||
#[wasm_bindgen(static = Bar)]
|
#[wasm_bindgen(namespace = Bar)]
|
||||||
fn another_function() -> i32;
|
fn another_function() -> i32;
|
||||||
|
|
||||||
#[wasm_bindgen(method)]
|
#[wasm_bindgen(method)]
|
||||||
@ -698,8 +698,8 @@ let's go through one-by-one:
|
|||||||
* `#[wasm_bindgen(constructor)]` - this indicates that the binding's name isn't
|
* `#[wasm_bindgen(constructor)]` - this indicates that the binding's name isn't
|
||||||
actually used in JS but rather translates to `new Bar()`. The return value of
|
actually used in JS but rather translates to `new Bar()`. The return value of
|
||||||
this function must be a bare type, like `Bar`.
|
this function must be a bare type, like `Bar`.
|
||||||
* `#[wasm_bindgen(static = Bar)]` - this attribute indicates that the function
|
* `#[wasm_bindgen(namespace = Bar)]` - this attribute indicates that the
|
||||||
declaration is a static function accessed through the `Bar` class in JS.
|
function declaration is namespaced through the `Bar` class in JS.
|
||||||
* `#[wasm_bindgen(method)]` - and finally, this attribute indicates that a
|
* `#[wasm_bindgen(method)]` - and finally, this attribute indicates that a
|
||||||
method call is going to happen. The first argument must be a JS struct, like
|
method call is going to happen. The first argument must be a JS struct, like
|
||||||
`Bar`, and the call in JS looks like `Bar.prototype.set.call(...)`.
|
`Bar`, and the call in JS looks like `Bar.prototype.set.call(...)`.
|
||||||
|
@ -1044,12 +1044,9 @@ impl<'a, 'b> SubContext<'a, 'b> {
|
|||||||
for f in self.program.exports.iter() {
|
for f in self.program.exports.iter() {
|
||||||
self.generate_export(f);
|
self.generate_export(f);
|
||||||
}
|
}
|
||||||
for f in self.program.imported_functions.iter() {
|
for f in self.program.imports.iter() {
|
||||||
self.generate_import(f);
|
self.generate_import(f);
|
||||||
}
|
}
|
||||||
for f in self.program.imported_fields.iter() {
|
|
||||||
self.generate_import_field(f);
|
|
||||||
}
|
|
||||||
for e in self.program.enums.iter() {
|
for e in self.program.enums.iter() {
|
||||||
self.generate_enum(e);
|
self.generate_enum(e);
|
||||||
}
|
}
|
||||||
@ -1322,35 +1319,36 @@ impl<'a, 'b> SubContext<'a, 'b> {
|
|||||||
(format!("{} {}", prefix, dst), format!("{} {}", prefix, dst_ts))
|
(format!("{} {}", prefix, dst), format!("{} {}", prefix, dst_ts))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn generate_import_field(&mut self, import: &shared::ImportField) {
|
pub fn generate_import(&mut self, import: &shared::Import) {
|
||||||
let name = import.shim_name();
|
match import.kind {
|
||||||
self.cx.imports_to_rewrite.insert(name.clone());
|
shared::ImportKind::Function(ref f) => {
|
||||||
|
self.generate_import_function(import, f)
|
||||||
if let Some(ref module) = import.module {
|
}
|
||||||
self.cx.imports.push_str(&format!("
|
shared::ImportKind::Static(ref s) => {
|
||||||
import {{ {} }} from '{}';
|
self.generate_import_static(import, s)
|
||||||
", import.name, module));
|
}
|
||||||
|
shared::ImportKind::Type(_) => {}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn generate_import_static(&mut self,
|
||||||
|
info: &shared::Import,
|
||||||
|
import: &shared::ImportStatic) {
|
||||||
|
// TODO: should support more types to import here
|
||||||
|
let name = shared::static_import_shim_name(&import.name);
|
||||||
|
self.cx.imports_to_rewrite.insert(name.clone());
|
||||||
|
let obj = self.import_name(info, &import.name);
|
||||||
self.cx.expose_add_heap_object();
|
self.cx.expose_add_heap_object();
|
||||||
self.cx.globals.push_str(&format!("
|
self.cx.globals.push_str(&format!("
|
||||||
export function {}() {{
|
export function {}() {{
|
||||||
return addHeapObject({});
|
return addHeapObject({});
|
||||||
}}
|
}}
|
||||||
", name, import.name));
|
", name, obj));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn generate_import(&mut self, import: &shared::Import) {
|
pub fn generate_import_function(&mut self,
|
||||||
if let Some(ref module) = import.module {
|
info: &shared::Import,
|
||||||
let name_to_import = import.class.as_ref().unwrap_or(&import.function.name);
|
import: &shared::ImportFunction) {
|
||||||
|
|
||||||
if self.cx.imported_names.insert(name_to_import.clone()) {
|
|
||||||
self.cx.imports.push_str(&format!("
|
|
||||||
import {{ {} }} from '{}';
|
|
||||||
", name_to_import, module));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let name = shared::mangled_import_name(import.class.as_ref().map(|s| &**s),
|
let name = shared::mangled_import_name(import.class.as_ref().map(|s| &**s),
|
||||||
&import.function.name);
|
&import.function.name);
|
||||||
self.cx.imports_to_rewrite.insert(name.clone());
|
self.cx.imports_to_rewrite.insert(name.clone());
|
||||||
@ -1361,12 +1359,6 @@ impl<'a, 'b> SubContext<'a, 'b> {
|
|||||||
let mut invoc_args = Vec::new();
|
let mut invoc_args = Vec::new();
|
||||||
let mut abi_args = Vec::new();
|
let mut abi_args = Vec::new();
|
||||||
|
|
||||||
// if import.method {
|
|
||||||
// abi_args.push("ptr".to_string());
|
|
||||||
// invoc_args.push("getObject(ptr)".to_string());
|
|
||||||
// self.cx.expose_get_object();
|
|
||||||
// }
|
|
||||||
|
|
||||||
let mut extra = String::new();
|
let mut extra = String::new();
|
||||||
|
|
||||||
for (i, arg) in import.function.arguments.iter().enumerate() {
|
for (i, arg) in import.function.arguments.iter().enumerate() {
|
||||||
@ -1444,9 +1436,10 @@ impl<'a, 'b> SubContext<'a, 'b> {
|
|||||||
let function_name = &import.function.name;
|
let function_name = &import.function.name;
|
||||||
let invoc = match import.class {
|
let invoc = match import.class {
|
||||||
Some(ref class) if import.js_new => {
|
Some(ref class) if import.js_new => {
|
||||||
format!("new {}", class)
|
format!("new {}", self.import_name(info, class))
|
||||||
}
|
}
|
||||||
Some(ref class) if import.method => {
|
Some(ref class) if import.method => {
|
||||||
|
let class = self.import_name(info, class);
|
||||||
let target = if let Some(ref g) = import.getter {
|
let target = if let Some(ref g) = import.getter {
|
||||||
format!(
|
format!(
|
||||||
"Object.getOwnPropertyDescriptor({}.prototype, '{}').get;",
|
"Object.getOwnPropertyDescriptor({}.prototype, '{}').get;",
|
||||||
@ -1468,12 +1461,23 @@ impl<'a, 'b> SubContext<'a, 'b> {
|
|||||||
format!("{}_target.call", name)
|
format!("{}_target.call", name)
|
||||||
}
|
}
|
||||||
Some(ref class) => {
|
Some(ref class) => {
|
||||||
|
let class = self.import_name(info, class);
|
||||||
self.cx.globals.push_str(&format!("
|
self.cx.globals.push_str(&format!("
|
||||||
const {}_target = {}.{};
|
const {}_target = {}.{};
|
||||||
", name, class, function_name));
|
", name, class, function_name));
|
||||||
format!("{}_target", name)
|
format!("{}_target", name)
|
||||||
}
|
}
|
||||||
None => function_name.to_string(),
|
None => {
|
||||||
|
let import = self.import_name(info, function_name);
|
||||||
|
if import.contains(".") {
|
||||||
|
self.cx.globals.push_str(&format!("
|
||||||
|
const {}_target = {};
|
||||||
|
", name, import));
|
||||||
|
format!("{}_target", name)
|
||||||
|
} else {
|
||||||
|
import
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
let invoc = format!("{}({})", invoc, invoc_args);
|
let invoc = format!("{}({})", invoc, invoc_args);
|
||||||
let invoc = match import.function.ret {
|
let invoc = match import.function.ret {
|
||||||
@ -1551,6 +1555,22 @@ impl<'a, 'b> SubContext<'a, 'b> {
|
|||||||
self.cx.typescript.push_str(&variants);
|
self.cx.typescript.push_str(&variants);
|
||||||
self.cx.typescript.push_str("}\n");
|
self.cx.typescript.push_str("}\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn import_name(&mut self, import: &shared::Import, item: &str) -> String {
|
||||||
|
if let Some(ref module) = import.module {
|
||||||
|
let name = import.namespace.as_ref().map(|s| &**s).unwrap_or(item);
|
||||||
|
|
||||||
|
if self.cx.imported_names.insert(name.to_string()) {
|
||||||
|
self.cx.imports.push_str(&format!("
|
||||||
|
import {{ {} }} from '{}';
|
||||||
|
", name, module));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
match import.namespace {
|
||||||
|
Some(ref s) => format!("{}.{}", s, item),
|
||||||
|
None => item.to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct VectorType {
|
struct VectorType {
|
||||||
|
@ -168,6 +168,7 @@ fn extract_programs(module: &mut Module) -> Vec<shared::Program> {
|
|||||||
let json = a[3..].iter()
|
let json = a[3..].iter()
|
||||||
.map(|i| char::from_u32(i.0).unwrap())
|
.map(|i| char::from_u32(i.0).unwrap())
|
||||||
.collect::<String>();
|
.collect::<String>();
|
||||||
|
println!("{}", json);
|
||||||
let p: shared::Program = match serde_json::from_str(&json) {
|
let p: shared::Program = match serde_json::from_str(&json) {
|
||||||
Ok(f) => f,
|
Ok(f) => f,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
|
@ -9,9 +9,7 @@ pub struct Program {
|
|||||||
pub exports: Vec<Export>,
|
pub exports: Vec<Export>,
|
||||||
pub imports: Vec<Import>,
|
pub imports: Vec<Import>,
|
||||||
pub enums: Vec<Enum>,
|
pub enums: Vec<Enum>,
|
||||||
pub imported_types: Vec<ImportedType>,
|
|
||||||
pub structs: Vec<Struct>,
|
pub structs: Vec<Struct>,
|
||||||
pub imported_fields: Vec<ImportField>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Export {
|
pub struct Export {
|
||||||
@ -23,17 +21,44 @@ pub struct Export {
|
|||||||
|
|
||||||
pub struct Import {
|
pub struct Import {
|
||||||
pub module: Option<String>,
|
pub module: Option<String>,
|
||||||
|
pub namespace: Option<syn::Ident>,
|
||||||
pub kind: ImportKind,
|
pub kind: ImportKind,
|
||||||
pub function: Function,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum ImportKind {
|
pub enum ImportKind {
|
||||||
Method { class: String, ty: syn::Type },
|
Function(ImportFunction),
|
||||||
Static { class: String, ty: syn::Type },
|
Static(ImportStatic),
|
||||||
JsConstructor { class: String, ty: syn::Type },
|
Type(ImportType),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct ImportFunction {
|
||||||
|
pub function: Function,
|
||||||
|
pub kind: ImportFunctionKind,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum ImportFunctionKind {
|
||||||
|
Method {
|
||||||
|
class: String,
|
||||||
|
ty: syn::Type,
|
||||||
|
},
|
||||||
|
JsConstructor {
|
||||||
|
class: String,
|
||||||
|
ty: syn::Type,
|
||||||
|
},
|
||||||
Normal,
|
Normal,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct ImportStatic {
|
||||||
|
pub vis: syn::Visibility,
|
||||||
|
pub ty: syn::Type,
|
||||||
|
pub name: syn::Ident,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct ImportType {
|
||||||
|
pub vis: syn::Visibility,
|
||||||
|
pub name: syn::Ident,
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Function {
|
pub struct Function {
|
||||||
pub name: syn::Ident,
|
pub name: syn::Ident,
|
||||||
pub arguments: Vec<Type>,
|
pub arguments: Vec<Type>,
|
||||||
@ -58,18 +83,6 @@ pub struct Variant {
|
|||||||
pub value: u32,
|
pub value: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ImportedType {
|
|
||||||
pub vis: syn::Visibility,
|
|
||||||
pub name: syn::Ident,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct ImportField {
|
|
||||||
pub vis: syn::Visibility,
|
|
||||||
pub ty: syn::Type,
|
|
||||||
pub module: Option<String>,
|
|
||||||
pub name: syn::Ident,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub enum Type {
|
pub enum Type {
|
||||||
// special
|
// special
|
||||||
Vector(VectorType, bool),
|
Vector(VectorType, bool),
|
||||||
@ -206,22 +219,6 @@ impl Program {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn push_foreign_mod(&mut self, f: syn::ItemForeignMod, opts: BindgenAttrs) {
|
|
||||||
match f.abi.name {
|
|
||||||
Some(ref l) if l.value() == "C" => {}
|
|
||||||
None => {}
|
|
||||||
_ => panic!("only foreign mods with the `C` ABI are allowed"),
|
|
||||||
}
|
|
||||||
for item in f.items.into_iter() {
|
|
||||||
match item {
|
|
||||||
syn::ForeignItem::Fn(f) => self.push_foreign_fn(f, &opts),
|
|
||||||
syn::ForeignItem::Type(t) => self.push_foreign_ty(t, &opts),
|
|
||||||
syn::ForeignItem::Static(s) => self.push_foreign_static(s, &opts),
|
|
||||||
_ => panic!("only foreign functions/types allowed for now"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn push_enum(&mut self, item: syn::ItemEnum, _opts: BindgenAttrs) {
|
pub fn push_enum(&mut self, item: syn::ItemEnum, _opts: BindgenAttrs) {
|
||||||
match item.vis {
|
match item.vis {
|
||||||
syn::Visibility::Public(_) => {}
|
syn::Visibility::Public(_) => {}
|
||||||
@ -255,11 +252,38 @@ impl Program {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn push_foreign_fn(&mut self,
|
pub fn push_foreign_mod(&mut self, f: syn::ItemForeignMod, opts: BindgenAttrs) {
|
||||||
mut f: syn::ForeignItemFn,
|
match f.abi.name {
|
||||||
module_opts: &BindgenAttrs) {
|
Some(ref l) if l.value() == "C" => {}
|
||||||
let opts = BindgenAttrs::find(&mut f.attrs);
|
None => {}
|
||||||
|
_ => panic!("only foreign mods with the `C` ABI are allowed"),
|
||||||
|
}
|
||||||
|
for mut item in f.items.into_iter() {
|
||||||
|
let item_opts = {
|
||||||
|
let attrs = match item {
|
||||||
|
syn::ForeignItem::Fn(ref mut f) => &mut f.attrs,
|
||||||
|
syn::ForeignItem::Type(ref mut t) => &mut t.attrs,
|
||||||
|
syn::ForeignItem::Static(ref mut s) => &mut s.attrs,
|
||||||
|
_ => panic!("only foreign functions/types allowed for now"),
|
||||||
|
};
|
||||||
|
BindgenAttrs::find(attrs)
|
||||||
|
};
|
||||||
|
let module = item_opts.module().or(opts.module()).map(|s| s.to_string());
|
||||||
|
let namespace = item_opts.namespace().or(opts.namespace());
|
||||||
|
let mut kind = match item {
|
||||||
|
syn::ForeignItem::Fn(f) => self.push_foreign_fn(f, item_opts),
|
||||||
|
syn::ForeignItem::Type(t) => self.push_foreign_ty(t),
|
||||||
|
syn::ForeignItem::Static(s) => self.push_foreign_static(s),
|
||||||
|
_ => panic!("only foreign functions/types allowed for now"),
|
||||||
|
};
|
||||||
|
|
||||||
|
self.imports.push(Import { module, namespace, kind });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn push_foreign_fn(&mut self, f: syn::ForeignItemFn, opts: BindgenAttrs)
|
||||||
|
-> ImportKind
|
||||||
|
{
|
||||||
let mut wasm = Function::from_decl(f.ident,
|
let mut wasm = Function::from_decl(f.ident,
|
||||||
f.decl,
|
f.decl,
|
||||||
f.attrs,
|
f.attrs,
|
||||||
@ -298,7 +322,7 @@ impl Program {
|
|||||||
let class_name = extract_path_ident(class_name)
|
let class_name = extract_path_ident(class_name)
|
||||||
.expect("first argument of method must be a bare type");
|
.expect("first argument of method must be a bare type");
|
||||||
|
|
||||||
ImportKind::Method {
|
ImportFunctionKind::Method {
|
||||||
class: class_name.as_ref().to_string(),
|
class: class_name.as_ref().to_string(),
|
||||||
ty: class.clone(),
|
ty: class.clone(),
|
||||||
}
|
}
|
||||||
@ -314,54 +338,40 @@ impl Program {
|
|||||||
let class_name = extract_path_ident(class_name)
|
let class_name = extract_path_ident(class_name)
|
||||||
.expect("first argument of method must be a bare type");
|
.expect("first argument of method must be a bare type");
|
||||||
|
|
||||||
ImportKind::JsConstructor {
|
ImportFunctionKind::JsConstructor {
|
||||||
class: class_name.as_ref().to_string(),
|
class: class_name.as_ref().to_string(),
|
||||||
ty: class.clone(),
|
ty: class.clone(),
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if let Some(class) = wasm.opts.static_receiver() {
|
|
||||||
let class_name = match *class {
|
|
||||||
syn::Type::Path(syn::TypePath { qself: None, ref path }) => path,
|
|
||||||
_ => panic!("first argument of method must be a path"),
|
|
||||||
};
|
|
||||||
let class_name = extract_path_ident(class_name)
|
|
||||||
.expect("first argument of method must be a bare type");
|
|
||||||
ImportKind::Static {
|
|
||||||
class: class_name.to_string(),
|
|
||||||
ty: class.clone(),
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
ImportKind::Normal
|
ImportFunctionKind::Normal
|
||||||
};
|
};
|
||||||
|
|
||||||
self.imports.push(Import {
|
ImportKind::Function(ImportFunction {
|
||||||
module: module_opts.module().map(|s| s.to_string()),
|
|
||||||
kind,
|
|
||||||
function: wasm,
|
function: wasm,
|
||||||
});
|
kind,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn push_foreign_ty(&mut self,
|
pub fn push_foreign_ty(&mut self, f: syn::ForeignItemType)
|
||||||
f: syn::ForeignItemType,
|
-> ImportKind
|
||||||
_module_opts: &BindgenAttrs) {
|
{
|
||||||
self.imported_types.push(ImportedType {
|
ImportKind::Type(ImportType {
|
||||||
vis: f.vis,
|
vis: f.vis,
|
||||||
name: f.ident
|
name: f.ident
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn push_foreign_static(&mut self,
|
pub fn push_foreign_static(&mut self, f: syn::ForeignItemStatic)
|
||||||
f: syn::ForeignItemStatic,
|
-> ImportKind
|
||||||
module_opts: &BindgenAttrs) {
|
{
|
||||||
if f.mutability.is_some() {
|
if f.mutability.is_some() {
|
||||||
panic!("cannot import mutable globals yet")
|
panic!("cannot import mutable globals yet")
|
||||||
}
|
}
|
||||||
self.imported_fields.push(ImportField {
|
ImportKind::Static(ImportStatic {
|
||||||
module: module_opts.module().map(|s| s.to_string()),
|
|
||||||
ty: *f.ty,
|
ty: *f.ty,
|
||||||
vis: f.vis,
|
vis: f.vis,
|
||||||
name: f.ident
|
name: f.ident,
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn literal(&self, dst: &mut Tokens) -> usize {
|
pub fn literal(&self, dst: &mut Tokens) -> usize {
|
||||||
@ -552,7 +562,7 @@ impl Export {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Import {
|
impl ImportFunction {
|
||||||
pub fn infer_getter_property(&self) -> String {
|
pub fn infer_getter_property(&self) -> String {
|
||||||
self.function.name.as_ref().to_string()
|
self.function.name.as_ref().to_string()
|
||||||
}
|
}
|
||||||
@ -630,11 +640,11 @@ impl BindgenAttrs {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn static_receiver(&self) -> Option<&syn::Type> {
|
fn namespace(&self) -> Option<syn::Ident> {
|
||||||
self.attrs.iter()
|
self.attrs.iter()
|
||||||
.filter_map(|a| {
|
.filter_map(|a| {
|
||||||
match *a {
|
match *a {
|
||||||
BindgenAttr::Static(ref s) => Some(s),
|
BindgenAttr::Namespace(s) => Some(s),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -681,7 +691,7 @@ enum BindgenAttr {
|
|||||||
Catch,
|
Catch,
|
||||||
Constructor,
|
Constructor,
|
||||||
Method,
|
Method,
|
||||||
Static(syn::Type),
|
Namespace(syn::Ident),
|
||||||
Module(String),
|
Module(String),
|
||||||
Getter,
|
Getter,
|
||||||
Setter,
|
Setter,
|
||||||
@ -700,11 +710,11 @@ impl syn::synom::Synom for BindgenAttr {
|
|||||||
call!(term, "setter") => { |_| BindgenAttr::Setter }
|
call!(term, "setter") => { |_| BindgenAttr::Setter }
|
||||||
|
|
|
|
||||||
do_parse!(
|
do_parse!(
|
||||||
call!(term, "static") >>
|
call!(term, "namespace") >>
|
||||||
punct!(=) >>
|
punct!(=) >>
|
||||||
s: syn!(syn::Type) >>
|
ns: syn!(syn::Ident) >>
|
||||||
(s)
|
(ns)
|
||||||
)=> { BindgenAttr::Static }
|
)=> { BindgenAttr::Namespace }
|
||||||
|
|
|
|
||||||
do_parse!(
|
do_parse!(
|
||||||
call!(term, "module") >>
|
call!(term, "module") >>
|
||||||
@ -815,12 +825,3 @@ impl ToTokens for VectorType {
|
|||||||
me.to_tokens(tokens);
|
me.to_tokens(tokens);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ImportField {
|
|
||||||
pub fn shared(&self) -> shared::ImportField {
|
|
||||||
shared::ImportField {
|
|
||||||
module: self.module.clone(),
|
|
||||||
name: self.name.to_string(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -13,6 +13,7 @@ extern crate wasm_bindgen_shared as shared;
|
|||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::sync::atomic::*;
|
use std::sync::atomic::*;
|
||||||
|
use std::collections::{BTreeMap, HashSet};
|
||||||
|
|
||||||
use proc_macro::TokenStream;
|
use proc_macro::TokenStream;
|
||||||
use proc_macro2::Span;
|
use proc_macro2::Span;
|
||||||
@ -69,18 +70,44 @@ impl ToTokens for ast::Program {
|
|||||||
for s in self.structs.iter() {
|
for s in self.structs.iter() {
|
||||||
s.to_tokens(tokens);
|
s.to_tokens(tokens);
|
||||||
}
|
}
|
||||||
|
let mut types = HashSet::new();
|
||||||
|
let mut buckets = BTreeMap::new();
|
||||||
for i in self.imports.iter() {
|
for i in self.imports.iter() {
|
||||||
i.to_tokens(tokens);
|
buckets.entry(i.namespace)
|
||||||
|
.or_insert(Vec::new())
|
||||||
|
.push(i);
|
||||||
|
if let ast::ImportKind::Type(ref t) = i.kind {
|
||||||
|
types.insert(t.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (namespace, imports) in buckets {
|
||||||
|
let mut sub_tokens = Tokens::new();
|
||||||
|
for import in imports {
|
||||||
|
import.kind.to_tokens(&mut sub_tokens);
|
||||||
|
}
|
||||||
|
match namespace {
|
||||||
|
Some(ns) if types.contains(&ns) => {
|
||||||
|
(quote! { impl #ns { #sub_tokens } }).to_tokens(tokens);
|
||||||
|
}
|
||||||
|
Some(ns) => {
|
||||||
|
(quote! {
|
||||||
|
// TODO: allow controlling `pub` here.
|
||||||
|
//
|
||||||
|
// TODO: we don't really want to generate a type here,
|
||||||
|
// it'd be preferrable to generate a namespace indicator
|
||||||
|
// or something like that (but modules interact weirdly
|
||||||
|
// with imports and such)
|
||||||
|
pub struct #ns { _priv: () }
|
||||||
|
|
||||||
|
impl #ns { #sub_tokens }
|
||||||
|
}).to_tokens(tokens);
|
||||||
|
}
|
||||||
|
None => sub_tokens.to_tokens(tokens),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for e in self.enums.iter() {
|
for e in self.enums.iter() {
|
||||||
e.to_tokens(tokens);
|
e.to_tokens(tokens);
|
||||||
}
|
}
|
||||||
for it in self.imported_types.iter() {
|
|
||||||
it.to_tokens(tokens);
|
|
||||||
}
|
|
||||||
for it in self.imported_fields.iter() {
|
|
||||||
it.to_tokens(tokens);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate a static which will eventually be what lives in a custom section
|
// Generate a static which will eventually be what lives in a custom section
|
||||||
// of the wasm executable. For now it's just a plain old static, but we'll
|
// of the wasm executable. For now it's just a plain old static, but we'll
|
||||||
@ -311,7 +338,7 @@ impl ToTokens for ast::Export {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToTokens for ast::ImportedType {
|
impl ToTokens for ast::ImportType {
|
||||||
fn to_tokens(&self, tokens: &mut Tokens) {
|
fn to_tokens(&self, tokens: &mut Tokens) {
|
||||||
let vis = &self.vis;
|
let vis = &self.vis;
|
||||||
let name = &self.name;
|
let name = &self.name;
|
||||||
@ -344,23 +371,32 @@ impl ToTokens for ast::ImportedType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToTokens for ast::Import {
|
impl ToTokens for ast::ImportKind {
|
||||||
|
fn to_tokens(&self, tokens: &mut Tokens) {
|
||||||
|
match *self {
|
||||||
|
ast::ImportKind::Function(ref f) => f.to_tokens(tokens),
|
||||||
|
ast::ImportKind::Static(ref s) => s.to_tokens(tokens),
|
||||||
|
ast::ImportKind::Type(ref t) => t.to_tokens(tokens),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToTokens for ast::ImportFunction {
|
||||||
fn to_tokens(&self, tokens: &mut Tokens) {
|
fn to_tokens(&self, tokens: &mut Tokens) {
|
||||||
let mut class_ty = None;
|
let mut class_ty = None;
|
||||||
let mut is_method = false;
|
let mut is_method = false;
|
||||||
let mut class_name = None;
|
let mut class_name = None;
|
||||||
match self.kind {
|
match self.kind {
|
||||||
ast::ImportKind::Method { ref ty, ref class } => {
|
ast::ImportFunctionKind::Method { ref ty, ref class } => {
|
||||||
is_method = true;
|
is_method = true;
|
||||||
class_ty = Some(ty);
|
class_ty = Some(ty);
|
||||||
class_name = Some(class);
|
class_name = Some(class);
|
||||||
}
|
}
|
||||||
ast::ImportKind::Static { ref ty, ref class } |
|
ast::ImportFunctionKind::JsConstructor { ref ty, ref class } => {
|
||||||
ast::ImportKind::JsConstructor { ref ty, ref class } => {
|
|
||||||
class_ty = Some(ty);
|
class_ty = Some(ty);
|
||||||
class_name = Some(class);
|
class_name = Some(class);
|
||||||
}
|
}
|
||||||
ast::ImportKind::Normal => {}
|
ast::ImportFunctionKind::Normal => {}
|
||||||
}
|
}
|
||||||
let import_name = shared::mangled_import_name(
|
let import_name = shared::mangled_import_name(
|
||||||
class_name.map(|s| &**s),
|
class_name.map(|s| &**s),
|
||||||
@ -595,11 +631,12 @@ impl ToTokens for ast::Enum {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToTokens for ast::ImportField {
|
impl ToTokens for ast::ImportStatic {
|
||||||
fn to_tokens(&self, into: &mut Tokens) {
|
fn to_tokens(&self, into: &mut Tokens) {
|
||||||
let name = self.name;
|
let name = self.name;
|
||||||
let ty = &self.ty;
|
let ty = &self.ty;
|
||||||
let shim_name = syn::Ident::from(self.shared().shim_name());
|
let shim_name = shared::static_import_shim_name(name.as_ref());
|
||||||
|
let shim_name = syn::Ident::from(shim_name);
|
||||||
let vis = &self.vis;
|
let vis = &self.vis;
|
||||||
(my_quote! {
|
(my_quote! {
|
||||||
#vis static #name: ::wasm_bindgen::JsStatic<#ty> = {
|
#vis static #name: ::wasm_bindgen::JsStatic<#ty> = {
|
||||||
|
@ -107,8 +107,7 @@ impl Literal for ast::Program {
|
|||||||
fn literal(&self, a: &mut LiteralBuilder) {
|
fn literal(&self, a: &mut LiteralBuilder) {
|
||||||
a.fields(&[
|
a.fields(&[
|
||||||
("exports", &|a| a.list_of(&self.exports)),
|
("exports", &|a| a.list_of(&self.exports)),
|
||||||
("imported_functions", &|a| a.list_of(&self.imports)),
|
("imports", &|a| a.list_of(&self.imports)),
|
||||||
("imported_fields", &|a| a.list_of(&self.imported_fields)),
|
|
||||||
("enums", &|a| a.list_of(&self.enums)),
|
("enums", &|a| a.list_of(&self.enums)),
|
||||||
("custom_type_names", &|a| {
|
("custom_type_names", &|a| {
|
||||||
let names = self.exports
|
let names = self.exports
|
||||||
@ -199,25 +198,46 @@ impl Literal for ast::Export {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Literal for ast::Import {
|
impl Literal for ast::Import {
|
||||||
|
fn literal(&self, a: &mut LiteralBuilder) {
|
||||||
|
a.fields(&[
|
||||||
|
("module", &|a| match self.module {
|
||||||
|
Some(ref s) => a.str(s),
|
||||||
|
None => a.append("null"),
|
||||||
|
}),
|
||||||
|
("namespace", &|a| match self.namespace {
|
||||||
|
Some(ref s) => a.str(s.as_ref()),
|
||||||
|
None => a.append("null"),
|
||||||
|
}),
|
||||||
|
("kind", &|a| self.kind.literal(a)),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Literal for ast::ImportKind {
|
||||||
|
fn literal(&self, a: &mut LiteralBuilder) {
|
||||||
|
match *self {
|
||||||
|
ast::ImportKind::Function(ref f) => f.literal(a),
|
||||||
|
ast::ImportKind::Static(ref s) => s.literal(a),
|
||||||
|
ast::ImportKind::Type(ref t) => t.literal(a),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Literal for ast::ImportFunction {
|
||||||
fn literal(&self, a: &mut LiteralBuilder) {
|
fn literal(&self, a: &mut LiteralBuilder) {
|
||||||
let mut method = false;
|
let mut method = false;
|
||||||
let mut js_new = false;
|
let mut js_new = false;
|
||||||
let mut statik = false;
|
|
||||||
let mut class_name = None;
|
let mut class_name = None;
|
||||||
match self.kind {
|
match self.kind {
|
||||||
ast::ImportKind::Method { ref class, .. } => {
|
ast::ImportFunctionKind::Method { ref class, .. } => {
|
||||||
method = true;
|
method = true;
|
||||||
class_name = Some(class);
|
class_name = Some(class);
|
||||||
}
|
}
|
||||||
ast::ImportKind::JsConstructor { ref class, .. } => {
|
ast::ImportFunctionKind::JsConstructor { ref class, .. } => {
|
||||||
js_new = true;
|
js_new = true;
|
||||||
class_name = Some(class);
|
class_name = Some(class);
|
||||||
}
|
}
|
||||||
ast::ImportKind::Static { ref class, .. } => {
|
ast::ImportFunctionKind::Normal => {}
|
||||||
statik = true;
|
|
||||||
class_name = Some(class);
|
|
||||||
}
|
|
||||||
ast::ImportKind::Normal => {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut getter = None;
|
let mut getter = None;
|
||||||
@ -230,14 +250,10 @@ impl Literal for ast::Import {
|
|||||||
setter = Some(self.infer_setter_property());
|
setter = Some(self.infer_setter_property());
|
||||||
}
|
}
|
||||||
a.fields(&[
|
a.fields(&[
|
||||||
("module", &|a| match self.module {
|
("kind", &|a| a.str("function")),
|
||||||
Some(ref s) => a.str(s),
|
|
||||||
None => a.append("null"),
|
|
||||||
}),
|
|
||||||
("catch", &|a| a.bool(self.function.opts.catch())),
|
("catch", &|a| a.bool(self.function.opts.catch())),
|
||||||
("method", &|a| a.bool(method)),
|
("method", &|a| a.bool(method)),
|
||||||
("js_new", &|a| a.bool(js_new)),
|
("js_new", &|a| a.bool(js_new)),
|
||||||
("statik", &|a| a.bool(statik)),
|
|
||||||
("getter", &|a| match getter {
|
("getter", &|a| match getter {
|
||||||
Some(ref s) => a.str(s),
|
Some(ref s) => a.str(s),
|
||||||
None => a.append("null"),
|
None => a.append("null"),
|
||||||
@ -273,14 +289,19 @@ impl Literal for ast::Variant {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Literal for ast::ImportField {
|
impl Literal for ast::ImportStatic {
|
||||||
fn literal(&self, a: &mut LiteralBuilder) {
|
fn literal(&self, a: &mut LiteralBuilder) {
|
||||||
a.fields(&[
|
a.fields(&[
|
||||||
|
("kind", &|a| a.str("static")),
|
||||||
("name", &|a| a.str(self.name.as_ref())),
|
("name", &|a| a.str(self.name.as_ref())),
|
||||||
("module", &|a| match self.module {
|
])
|
||||||
Some(ref s) => a.str(s),
|
}
|
||||||
None => a.append("null"),
|
}
|
||||||
}),
|
|
||||||
|
impl Literal for ast::ImportType {
|
||||||
|
fn literal(&self, a: &mut LiteralBuilder) {
|
||||||
|
a.fields(&[
|
||||||
|
("kind", &|a| a.str("type")),
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,8 +11,7 @@ pub const SCHEMA_VERSION: &str = "0";
|
|||||||
pub struct Program {
|
pub struct Program {
|
||||||
pub exports: Vec<Export>,
|
pub exports: Vec<Export>,
|
||||||
pub enums: Vec<Enum>,
|
pub enums: Vec<Enum>,
|
||||||
pub imported_functions: Vec<Import>,
|
pub imports: Vec<Import>,
|
||||||
pub imported_fields: Vec<ImportField>,
|
|
||||||
pub custom_type_names: Vec<CustomTypeName>,
|
pub custom_type_names: Vec<CustomTypeName>,
|
||||||
pub version: String,
|
pub version: String,
|
||||||
pub schema_version: String,
|
pub schema_version: String,
|
||||||
@ -20,11 +19,25 @@ pub struct Program {
|
|||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
pub struct Import {
|
pub struct Import {
|
||||||
|
pub module: Option<String>,
|
||||||
|
pub namespace: Option<String>,
|
||||||
|
pub kind: ImportKind,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
#[serde(tag = "kind", rename_all = "lowercase")]
|
||||||
|
pub enum ImportKind {
|
||||||
|
Function(ImportFunction),
|
||||||
|
Static(ImportStatic),
|
||||||
|
Type(ImportType),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
pub struct ImportFunction {
|
||||||
pub module: Option<String>,
|
pub module: Option<String>,
|
||||||
pub catch: bool,
|
pub catch: bool,
|
||||||
pub method: bool,
|
pub method: bool,
|
||||||
pub js_new: bool,
|
pub js_new: bool,
|
||||||
pub statik: bool,
|
|
||||||
pub getter: Option<String>,
|
pub getter: Option<String>,
|
||||||
pub setter: Option<String>,
|
pub setter: Option<String>,
|
||||||
pub class: Option<String>,
|
pub class: Option<String>,
|
||||||
@ -32,11 +45,15 @@ pub struct Import {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
pub struct ImportField {
|
pub struct ImportStatic {
|
||||||
pub module: Option<String>,
|
pub module: Option<String>,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
pub struct ImportType {
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
pub struct Export {
|
pub struct Export {
|
||||||
pub class: Option<String>,
|
pub class: Option<String>,
|
||||||
@ -99,6 +116,10 @@ pub fn mangled_import_name(struct_: Option<&str>, f: &str) -> String {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn static_import_shim_name(statik: &str) -> String {
|
||||||
|
format!("__wbg_field_import_shim_{}", statik)
|
||||||
|
}
|
||||||
|
|
||||||
pub type Type = char;
|
pub type Type = char;
|
||||||
|
|
||||||
pub const TYPE_VECTOR_JSVALUE: char = '\u{5b}';
|
pub const TYPE_VECTOR_JSVALUE: char = '\u{5b}';
|
||||||
@ -155,9 +176,3 @@ pub fn version() -> String {
|
|||||||
}
|
}
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ImportField {
|
|
||||||
pub fn shim_name(&self) -> String {
|
|
||||||
format!("__wbg_field_import_shim_{}", self.name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -6,9 +6,7 @@ use wasm_bindgen::prelude::*;
|
|||||||
|
|
||||||
#[wasm_bindgen]
|
#[wasm_bindgen]
|
||||||
extern {
|
extern {
|
||||||
type console;
|
#[wasm_bindgen(namespace = console)]
|
||||||
|
|
||||||
#[wasm_bindgen(static = console)]
|
|
||||||
fn log(s: &str);
|
fn log(s: &str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,10 +22,9 @@ fn simple() {
|
|||||||
|
|
||||||
#[wasm_bindgen]
|
#[wasm_bindgen]
|
||||||
extern {
|
extern {
|
||||||
type Math;
|
#[wasm_bindgen(namespace = Math)]
|
||||||
#[wasm_bindgen(static = Math)]
|
|
||||||
fn random() -> f64;
|
fn random() -> f64;
|
||||||
#[wasm_bindgen(static = Math)]
|
#[wasm_bindgen(namespace = Math)]
|
||||||
fn log(a: f64) -> f64;
|
fn log(a: f64) -> f64;
|
||||||
}
|
}
|
||||||
"#)
|
"#)
|
||||||
@ -53,8 +52,7 @@ fn import_class() {
|
|||||||
|
|
||||||
#[wasm_bindgen(module = "./another")]
|
#[wasm_bindgen(module = "./another")]
|
||||||
extern {
|
extern {
|
||||||
type Foo;
|
#[wasm_bindgen(namespace = Foo)]
|
||||||
#[wasm_bindgen(static = Foo)]
|
|
||||||
fn bar();
|
fn bar();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -98,7 +96,7 @@ fn construct() {
|
|||||||
#[wasm_bindgen(module = "./another")]
|
#[wasm_bindgen(module = "./another")]
|
||||||
extern {
|
extern {
|
||||||
type Foo;
|
type Foo;
|
||||||
#[wasm_bindgen(static = Foo)]
|
#[wasm_bindgen(namespace = Foo)]
|
||||||
fn create() -> Foo;
|
fn create() -> Foo;
|
||||||
#[wasm_bindgen(method)]
|
#[wasm_bindgen(method)]
|
||||||
fn get_internal_string(this: &Foo) -> String;
|
fn get_internal_string(this: &Foo) -> String;
|
||||||
@ -219,7 +217,7 @@ fn switch_methods() {
|
|||||||
#[wasm_bindgen(constructor)]
|
#[wasm_bindgen(constructor)]
|
||||||
fn new() -> Foo;
|
fn new() -> Foo;
|
||||||
|
|
||||||
#[wasm_bindgen(static = Foo)]
|
#[wasm_bindgen(namespace = Foo)]
|
||||||
fn a();
|
fn a();
|
||||||
|
|
||||||
#[wasm_bindgen(method)]
|
#[wasm_bindgen(method)]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user