diff --git a/crates/backend/src/ast.rs b/crates/backend/src/ast.rs index 08c64975..719f385f 100644 --- a/crates/backend/src/ast.rs +++ b/crates/backend/src/ast.rs @@ -1,3 +1,4 @@ +use std::collections::HashMap; use proc_macro2::{Ident, Span}; use shared; use syn; @@ -20,18 +21,7 @@ pub struct Program { /// rust consts pub consts: Vec, /// rust submodules - pub modules: Vec, -} - -/// A rust module -/// -/// This exists to give the ability to namespace js imports. -#[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq, Eq))] -pub struct Module { - /// module name - pub name: String, - /// js -> rust interfaces - pub imports: Vec, + pub modules: HashMap, } /// A rust to js interface. Allows interaction with rust objects/functions @@ -233,6 +223,15 @@ pub enum ConstValue { Null, } +/// A rust module +/// +/// This exists to give the ability to namespace js imports. +#[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq, Eq))] +pub struct Module { + /// js -> rust interfaces + pub imports: Vec, +} + impl Program { pub(crate) fn shared(&self) -> Result { Ok(shared::Program { @@ -241,7 +240,7 @@ impl Program { enums: self.enums.iter().map(|a| a.shared()).collect(), imports: self.imports.iter() // add in imports from inside modules - .chain(self.modules.iter().flat_map(|m| m.imports.iter())) + .chain(self.modules.values().flat_map(|m| m.imports.iter())) .map(|a| a.shared()) .collect::>()?, version: shared::version(), diff --git a/crates/backend/src/codegen.rs b/crates/backend/src/codegen.rs index 5274a0ce..1908441d 100644 --- a/crates/backend/src/codegen.rs +++ b/crates/backend/src/codegen.rs @@ -64,7 +64,7 @@ impl TryToTokens for ast::Program { } } for m in self.modules.iter() { - if let Err(e) = m.try_to_tokens(tokens) { + if let Err(e) = ModuleInIter::from(m).try_to_tokens(tokens) { errors.push(e); } } @@ -1111,15 +1111,28 @@ impl ToTokens for ast::Const { } } -impl TryToTokens for ast::Module { +/// Struct to help implementing TryToTokens over the key/value pairs from the hashmap. +struct ModuleInIter<'a> { + name: &'a Ident, + module: &'a ast::Module +} + +impl<'a> From<(&'a Ident, &'a ast::Module)> for ModuleInIter<'a> { + fn from((name, module): (&'a Ident, &'a ast::Module)) -> ModuleInIter<'a> { + ModuleInIter { name, module } + } +} + +impl<'a> TryToTokens for ModuleInIter<'a> { fn try_to_tokens(&self, tokens: &mut TokenStream) -> Result<(), Diagnostic> { + let name = &self.name; + let imports = &self.module.imports; let mut errors = Vec::new(); - for i in self.imports.iter() { + for i in imports.iter() { DescribeImport(&i.kind).to_tokens(tokens); } - let name = &self.name; let mut body = TokenStream::new(); - for i in self.imports.iter() { + for i in imports.iter() { if let Err(e) = i.kind.try_to_tokens(&mut body) { errors.push(e); } diff --git a/crates/web-sys/build.rs b/crates/web-sys/build.rs index 8dbb232c..630975c9 100644 --- a/crates/web-sys/build.rs +++ b/crates/web-sys/build.rs @@ -13,6 +13,8 @@ use std::path; use std::process::{self, Command}; fn main() { + env_logger::init(); + if let Err(e) = try_main() { eprintln!("Error: {}", e); for c in e.iter_causes() { @@ -24,11 +26,9 @@ fn main() { fn try_main() -> Result<(), failure::Error> { println!("cargo:rerun-if-changed=build.rs"); - env_logger::init(); - println!("cargo:rerun-if-changed=webidls/enabled"); - let entries = fs::read_dir("webidls/enabled").context("reading webidls/enabled directory")?; + let entries = fs::read_dir("webidls/enabled").context("reading webidls/enabled directory")?; let mut source = SourceFile::default(); for entry in entries { let entry = entry.context("getting webidls/enabled/*.webidl entry")?; @@ -38,8 +38,7 @@ fn try_main() -> Result<(), failure::Error> { } println!("cargo:rerun-if-changed={}", path.display()); source = source.add_file(&path) - .with_context(|_| format!("reading contents of file \"{}\"", - path.display()))?; + .with_context(|_| format!("reading contents of file \"{}\"", path.display()))?; } let bindings = match wasm_bindgen_webidl::compile(&source.contents) { @@ -70,9 +69,9 @@ fn try_main() -> Result<(), failure::Error> { let status = Command::new("rustfmt") .arg(&out_file_path) .status() - .context("running rustfmt")?; + .context("running rustfmt")?; if !status.success() { - bail!("rustfmt failed: {}", status) + bail!("rustfmt failed: {}", status) } } diff --git a/crates/webidl/src/lib.rs b/crates/webidl/src/lib.rs index 0fb33c90..76d2cad4 100644 --- a/crates/webidl/src/lib.rs +++ b/crates/webidl/src/lib.rs @@ -185,13 +185,18 @@ impl<'src> WebidlParse<'src, ()> for weedle::Definition<'src> { weedle::Definition::Implements(..) => { // nothing to do for this, ignore it } + weedle::Definition::Namespace(namespace) => { + namespace.webidl_parse(program, first_pass, ())? + } + weedle::Definition::PartialNamespace(namespace) => { + // TODO + warn!("Unsupported WebIDL definition: {:?}", self) + } // TODO weedle::Definition::Callback(..) | weedle::Definition::CallbackInterface(..) | weedle::Definition::Dictionary(..) - | weedle::Definition::PartialDictionary(..) - | weedle::Definition::Namespace(..) - | weedle::Definition::PartialNamespace(..) => { + | weedle::Definition::PartialDictionary(..) => { warn!("Unsupported WebIDL definition: {:?}", self) } } @@ -657,12 +662,17 @@ fn member_operation<'src>( match identifier.map(|s| s.0) { None if specials.is_empty() => ::first_pass::OperationId::Operation(None), None if specials.len() == 1 => match specials[0] { - weedle::interface::Special::Getter(weedle::term::Getter) => ::first_pass::OperationId::IndexingGetter, - weedle::interface::Special::Setter(weedle::term::Setter) => ::first_pass::OperationId::IndexingSetter, - weedle::interface::Special::Deleter(weedle::term::Deleter) => ::first_pass::OperationId::IndexingDeleter, - weedle::interface::Special::LegacyCaller(weedle::term::LegacyCaller) => return Ok(()), + weedle::interface::Special::Getter(weedle::term::Getter) => + ::first_pass::OperationId::IndexingGetter, + weedle::interface::Special::Setter(weedle::term::Setter) => + ::first_pass::OperationId::IndexingSetter, + weedle::interface::Special::Deleter(weedle::term::Deleter) => + ::first_pass::OperationId::IndexingDeleter, + weedle::interface::Special::LegacyCaller(weedle::term::LegacyCaller) => + return Ok(()), }, - Some(ref name) if specials.is_empty() => ::first_pass::OperationId::Operation(Some(name.clone())), + Some(ref name) if specials.is_empty() => + ::first_pass::OperationId::Operation(Some(name.clone())), _ => { warn!("Unsupported specials on type {:?}", (self_name, identifier)); return Ok(()) @@ -744,8 +754,8 @@ impl<'src> WebidlParse<'src, ()> for weedle::EnumDefinition<'src> { variants: variants .iter() .map(|v| { - if !v.0.is_empty() { - rust_ident(camel_case_ident(&v.0).as_str()) + if !v.0.is_empty() { + rust_ident(camel_case_ident(&v.0).as_str()) } else { rust_ident("None") } @@ -783,3 +793,18 @@ impl<'src> WebidlParse<'src, &'src str> for weedle::interface::ConstMember<'src> Ok(()) } } + +impl<'src> WebidlParse<'src, ()> for weedle::interface::NamespaceDefinition<'src> { + fn webidl_parse( + &'src self, + program: &mut backend::ast::Program, + record: &FirstPassRecord<'src>, + (): (), + ) -> Result<()> { + if util::is_chrome_only(&self.attributes) { + return Ok(()); + } + + + } +}