From 877c31cdc8da03e90d40455be87a9b78a9599cce Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 3 Jun 2019 12:56:18 -0700 Subject: [PATCH] web-sys: Don't remove dictionaries if required fields are removed This commit updates the conditional binding generation for dictionaries to ensure that a dictionary is not entirely removed if any of its required fields are removed. If a required field is removed, however, it cannot be constructed, so the constructor is removed. --- crates/backend/src/ast.rs | 1 + crates/backend/src/codegen.rs | 19 +++++++++++++------ crates/backend/src/defined.rs | 17 ++++++----------- crates/webidl/src/lib.rs | 2 ++ 4 files changed, 22 insertions(+), 17 deletions(-) diff --git a/crates/backend/src/ast.rs b/crates/backend/src/ast.rs index 78e26af4..0cef9011 100644 --- a/crates/backend/src/ast.rs +++ b/crates/backend/src/ast.rs @@ -292,6 +292,7 @@ pub enum ConstValue { pub struct Dictionary { pub name: Ident, pub fields: Vec, + pub ctor: bool, } #[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq, Eq))] diff --git a/crates/backend/src/codegen.rs b/crates/backend/src/codegen.rs index 4fb6642e..09ff71a7 100644 --- a/crates/backend/src/codegen.rs +++ b/crates/backend/src/codegen.rs @@ -1282,6 +1282,18 @@ impl ToTokens for ast::Dictionary { let required_names2 = required_names; let required_names3 = required_names; + let ctor = if self.ctor { + quote! { + pub fn new(#(#required_names: #required_types),*) -> #name { + let mut _ret = #name { obj: ::js_sys::Object::new() }; + #(_ret.#required_names2(#required_names3);)* + return _ret + } + } + } else { + quote! {} + }; + let const_name = Ident::new(&format!("_CONST_{}", name), Span::call_site()); (quote! { #[derive(Clone, Debug)] @@ -1293,12 +1305,7 @@ impl ToTokens for ast::Dictionary { #[allow(clippy::all)] impl #name { - pub fn new(#(#required_names: #required_types),*) -> #name { - let mut _ret = #name { obj: ::js_sys::Object::new() }; - #(_ret.#required_names2(#required_names3);)* - return _ret - } - + #ctor #methods } diff --git a/crates/backend/src/defined.rs b/crates/backend/src/defined.rs index df13bc3c..14bd9b0e 100644 --- a/crates/backend/src/defined.rs +++ b/crates/backend/src/defined.rs @@ -348,25 +348,20 @@ impl RemoveUndefinedImports for ast::Program { let mut changed = self.imports.remove_undefined_imports(is_defined); changed = self.consts.remove_undefined_imports(is_defined) || changed; - let mut dictionaries_to_remove = Vec::new(); - for (i, dictionary) in self.dictionaries.iter_mut().enumerate() { + for dictionary in self.dictionaries.iter_mut() { let num_required = |dict: &ast::Dictionary| dict.fields.iter().filter(|f| f.required).count(); let before = num_required(dictionary); changed = dictionary.fields.remove_undefined_imports(is_defined) || changed; + + // If a required field was removed we can no longer construct this + // dictionary so disable the constructor. if before != num_required(dictionary) { - log::warn!( - "removing {} due to a required field being removed", - dictionary.name - ); - dictionaries_to_remove.push(i); + dictionary.ctor = false; } } - for i in dictionaries_to_remove.iter().rev() { - self.dictionaries.swap_remove(*i); - } - changed || dictionaries_to_remove.len() > 0 + changed } } diff --git a/crates/webidl/src/lib.rs b/crates/webidl/src/lib.rs index 92ff8db8..4dc04255 100644 --- a/crates/webidl/src/lib.rs +++ b/crates/webidl/src/lib.rs @@ -317,6 +317,7 @@ impl<'src> FirstPassRecord<'src> { program.dictionaries.push(ast::Dictionary { name: rust_ident(&camel_case_ident(def.identifier.0)), fields, + ctor: true, }); } @@ -784,6 +785,7 @@ impl<'src> FirstPassRecord<'src> { program.dictionaries.push(ast::Dictionary { name: rust_ident(&camel_case_ident(item.definition.identifier.0)), fields, + ctor: true, }); } }