diff --git a/crates/web-sys/tests/wasm/location.rs b/crates/web-sys/tests/wasm/location.rs new file mode 100644 index 00000000..d6193a67 --- /dev/null +++ b/crates/web-sys/tests/wasm/location.rs @@ -0,0 +1,56 @@ +use wasm_bindgen_test::*; +use web_sys::Window; + +#[wasm_bindgen_test] +fn href() { + let loc = Window::location(); + loc.href().unwrap(); +} + +#[wasm_bindgen_test] +fn origin() { + let loc = Window::location(); + loc.origin().unwrap(); +} + +#[wasm_bindgen_test] +fn protocol() { + let loc = Window::location(); + loc.protocol().unwrap(); +} + +#[wasm_bindgen_test] +fn host() { + let loc = Window::location(); + loc.host().unwrap(); +} + +#[wasm_bindgen_test] +fn hostname() { + let loc = Window::location(); + loc.hostname().unwrap(); +} + +#[wasm_bindgen_test] +fn port() { + let loc = Window::location(); + loc.port().unwrap(); +} + +#[wasm_bindgen_test] +fn pathname() { + let loc = Window::location(); + loc.pathname().unwrap(); +} + +#[wasm_bindgen_test] +fn search() { + let loc = Window::location(); + loc.search().unwrap(); +} + +#[wasm_bindgen_test] +fn hash() { + let loc = Window::location(); + loc.hash().unwrap(); +} diff --git a/crates/web-sys/tests/wasm/main.rs b/crates/web-sys/tests/wasm/main.rs index 2f21cde6..05537755 100644 --- a/crates/web-sys/tests/wasm/main.rs +++ b/crates/web-sys/tests/wasm/main.rs @@ -52,3 +52,4 @@ pub mod title_element; pub mod xpath_result; pub mod dom_point; pub mod performance; +pub mod location; diff --git a/crates/webidl/src/first_pass.rs b/crates/webidl/src/first_pass.rs index 8c12ed47..39534791 100644 --- a/crates/webidl/src/first_pass.rs +++ b/crates/webidl/src/first_pass.rs @@ -44,7 +44,7 @@ pub(crate) struct InterfaceData<'src> { pub(crate) consts: Vec<&'src ConstMember<'src>>, pub(crate) operations: BTreeMap, OperationData<'src>>, pub(crate) superclass: Option<&'src str>, - pub(crate) definition_attributes: Option<&'src [ExtendedAttribute<'src>]>, + pub(crate) definition_attributes: Option<&'src ExtendedAttributeList<'src>>, } /// We need to collect mixin data during the first pass, to be used later. @@ -55,6 +55,7 @@ pub(crate) struct MixinData<'src> { pub(crate) attributes: Vec<&'src AttributeMixinMember<'src>>, pub(crate) consts: Vec<&'src ConstMember<'src>>, pub(crate) operations: BTreeMap, OperationData<'src>>, + pub(crate) definition_attributes: Option<&'src ExtendedAttributeList<'src>>, } /// We need to collect namespace data during the first pass, to be used later. @@ -300,8 +301,7 @@ impl<'src> FirstPass<'src, ()> for weedle::InterfaceDefinition<'src> { .or_default(); interface_data.partial = false; interface_data.superclass = self.inheritance.map(|s| s.identifier.0); - interface_data.definition_attributes = self.attributes.as_ref() - .map(|l| &l.body.list[..]); + interface_data.definition_attributes = self.attributes.as_ref(); } if let Some(attrs) = &self.attributes { for attr in attrs.body.list.iter() { @@ -510,6 +510,7 @@ impl<'src> FirstPass<'src, ()> for weedle::InterfaceMixinDefinition<'src>{ .entry(self.identifier.0) .or_default(); mixin_data.partial = false; + mixin_data.definition_attributes = self.attributes.as_ref(); } for member in &self.members.body { diff --git a/crates/webidl/src/lib.rs b/crates/webidl/src/lib.rs index aed5c584..aec8d42f 100644 --- a/crates/webidl/src/lib.rs +++ b/crates/webidl/src/lib.rs @@ -330,7 +330,7 @@ impl<'src> FirstPassRecord<'src> { ); let kind = backend::ast::ImportFunctionKind::Normal; - for mut import_function in self.create_imports(kind, id, data) { + for mut import_function in self.create_imports(None, kind, id, data) { import_function.doc_comment = Some(doc_comment.clone()); module.imports.push( backend::ast::Import { @@ -413,11 +413,12 @@ impl<'src> FirstPassRecord<'src> { self.member_attribute( program, name, - &member.attributes, member.modifier, member.readonly.is_some(), &member.type_, member.identifier.0, + &member.attributes, + data.definition_attributes, ); } @@ -432,7 +433,6 @@ impl<'src> FirstPassRecord<'src> { self.member_attribute( program, name, - &member.attributes, if let Some(s) = member.stringifier { Some(weedle::interface::StringifierOrInheritOrStatic::Stringifier(s)) } else { @@ -441,6 +441,8 @@ impl<'src> FirstPassRecord<'src> { member.readonly.is_some(), &member.type_, member.identifier.0, + &member.attributes, + mixin_data.definition_attributes, ); } } @@ -450,11 +452,12 @@ impl<'src> FirstPassRecord<'src> { &self, program: &mut backend::ast::Program, self_name: &'src str, - attrs: &'src Option, modifier: Option, readonly: bool, type_: &'src weedle::types::AttributedType<'src>, identifier: &'src str, + attrs: &'src Option>, + container_attrs: Option<&'src ExtendedAttributeList<'src>>, ) { use weedle::interface::StringifierOrInheritOrStatic::*; @@ -465,8 +468,6 @@ impl<'src> FirstPassRecord<'src> { None => false, }; - let is_structural = util::is_structural(attrs); - let throws = util::throws(attrs); let global = self .interfaces .get(self_name) @@ -478,9 +479,9 @@ impl<'src> FirstPassRecord<'src> { &type_.type_, self_name, is_static, - is_structural, - throws, global, + attrs, + container_attrs, ) { program.imports.push(wrap_import_function(import_function)); } @@ -488,12 +489,12 @@ impl<'src> FirstPassRecord<'src> { if !readonly { for import_function in self.create_setter( identifier, - type_.type_.clone(), + &type_.type_, self_name, is_static, - is_structural, - throws, global, + attrs, + container_attrs, ) { program.imports.push(wrap_import_function(import_function)); } @@ -533,7 +534,8 @@ impl<'src> FirstPassRecord<'src> { import_function_kind(backend::ast::OperationKind::IndexingDeleter) } }; - for method in self.create_imports(kind, id, op_data) { + let attrs = data.definition_attributes; + for method in self.create_imports(attrs, kind, id, op_data) { program.imports.push(wrap_import_function(method)); } } diff --git a/crates/webidl/src/util.rs b/crates/webidl/src/util.rs index b91478f9..50e59dc6 100644 --- a/crates/webidl/src/util.rs +++ b/crates/webidl/src/util.rs @@ -299,9 +299,9 @@ impl<'src> FirstPassRecord<'src> { ty: &weedle::types::Type<'src>, self_name: &str, is_static: bool, - is_structural: bool, - catch: bool, global: bool, + attrs: &Option, + container_attrs: Option<&ExtendedAttributeList>, ) -> Option { let kind = backend::ast::OperationKind::Getter(Some(raw_ident(name))); let kind = self.import_function_kind(self_name, global, is_static, kind); @@ -312,8 +312,8 @@ impl<'src> FirstPassRecord<'src> { None.into_iter(), &ret, kind, - is_structural, - catch, + is_structural(attrs.as_ref(), container_attrs), + throws(attrs), Some(format!("The `{}` getter\n\n{}", name, mdn_doc(self_name, Some(name)))) ) } @@ -322,12 +322,12 @@ impl<'src> FirstPassRecord<'src> { pub fn create_setter( &self, name: &str, - field_ty: weedle::types::Type<'src>, + field_ty: &weedle::types::Type<'src>, self_name: &str, is_static: bool, - is_structural: bool, - catch: bool, global: bool, + attrs: &Option, + container_attrs: Option<&ExtendedAttributeList>, ) -> Option { let kind = backend::ast::OperationKind::Setter(Some(raw_ident(name))); let kind = self.import_function_kind(self_name, global, is_static, kind); @@ -338,8 +338,8 @@ impl<'src> FirstPassRecord<'src> { Some((name, &field_ty)).into_iter(), &IdlType::Void, kind, - is_structural, - catch, + is_structural(attrs.as_ref(), container_attrs), + throws(attrs), Some(format!("The `{}` setter\n\n{}", name, mdn_doc(self_name, Some(name)))) ) } @@ -372,6 +372,7 @@ impl<'src> FirstPassRecord<'src> { pub fn create_imports( &self, + container_attrs: Option<&ExtendedAttributeList<'src>>, kind: backend::ast::ImportFunctionKind, id: &OperationId<'src>, data: &OperationData<'src>, @@ -552,7 +553,7 @@ impl<'src> FirstPassRecord<'src> { .map(|(ty, orig_arg)| (orig_arg.name, ty)), &ret_ty, kind.clone(), - force_structural || is_structural(&signature.orig.attrs), + force_structural || is_structural(signature.orig.attrs.as_ref(), container_attrs), force_throws || throws(&signature.orig.attrs), None, )); @@ -562,7 +563,7 @@ impl<'src> FirstPassRecord<'src> { } /// Search for an attribute by name in some webidl object's attributes. -fn has_named_attribute(list: &Option, attribute: &str) -> bool { +fn has_named_attribute(list: Option<&ExtendedAttributeList>, attribute: &str) -> bool { let list = match list { Some(list) => list, None => return false, @@ -575,22 +576,26 @@ fn has_named_attribute(list: &Option, attribute: &str) -> /// ChromeOnly is for things that are only exposed to privileged code in Firefox. pub fn is_chrome_only(ext_attrs: &Option) -> bool { - has_named_attribute(ext_attrs, "ChromeOnly") + has_named_attribute(ext_attrs.as_ref(), "ChromeOnly") } /// Whether a webidl object is marked as a no interface object. pub fn is_no_interface_object(ext_attrs: &Option) -> bool { - has_named_attribute(ext_attrs, "NoInterfaceObject") + has_named_attribute(ext_attrs.as_ref(), "NoInterfaceObject") } /// Whether a webidl object is marked as structural. -pub fn is_structural(attrs: &Option) -> bool { - has_named_attribute(attrs, "Unforgeable") +pub fn is_structural( + item_attrs: Option<&ExtendedAttributeList>, + container_attrs: Option<&ExtendedAttributeList>, +) -> bool { + has_named_attribute(item_attrs, "Unforgeable") || + has_named_attribute(container_attrs, "Unforgeable") } /// Whether a webidl object is marked as throwing. pub fn throws(attrs: &Option) -> bool { - has_named_attribute(attrs, "Throws") + has_named_attribute(attrs.as_ref(), "Throws") } /// Create a syn `pub` token