diff --git a/components/script/dom/bindings/js.rs b/components/script/dom/bindings/js.rs index f24115a349a..c9f3e157b75 100644 --- a/components/script/dom/bindings/js.rs +++ b/components/script/dom/bindings/js.rs @@ -575,3 +575,24 @@ impl<'a, T: Reflectable> Reflectable for JSRef<'a, T> { self.deref().reflector() } } + +/// A trait for comparing smart pointers ignoring the lifetimes +pub trait Comparable { + fn equals(&self, other: T) -> bool; +} + +impl<'a, 'b, T> Comparable> for JSRef<'b, T> { + fn equals(&self, other: JSRef<'a, T>) -> bool { + self.ptr == other.ptr + } +} + +impl<'a, 'b, T> Comparable>> for Option> { + fn equals(&self, other: Option>) -> bool { + match (*self, other) { + (Some(x), Some(y)) => x.ptr == y.ptr, + (None, None) => true, + _ => false + } + } +} diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs index cc5245d7537..aa671d98cb4 100644 --- a/components/script/dom/element.rs +++ b/components/script/dom/element.rs @@ -1253,7 +1253,7 @@ impl<'a> ActivationElementHelpers<'a> for JSRef<'a, Element> { // Step 4 let e = self.nearest_activable_element().root(); match e { - Some (el) => match el.as_maybe_activatable() { + Some(el) => match el.as_maybe_activatable() { Some(elem) => { // Step 5-6 elem.pre_click_activation(); diff --git a/components/script/dom/htmlinputelement.rs b/components/script/dom/htmlinputelement.rs index bfe686330fe..a736a7a8f3d 100644 --- a/components/script/dom/htmlinputelement.rs +++ b/components/script/dom/htmlinputelement.rs @@ -16,7 +16,8 @@ use dom::bindings::codegen::InheritTypes::{ElementCast, HTMLElementCast, HTMLFor use dom::bindings::codegen::InheritTypes::{HTMLInputElementDerived, HTMLFieldSetElementDerived, EventTargetCast}; use dom::bindings::codegen::InheritTypes::KeyboardEventCast; use dom::bindings::global::Window; -use dom::bindings::js::{JS, JSRef, Root, Temporary, OptionalRootable, ResultRootable, MutNullableJS}; +use dom::bindings::js::{Comparable, JS, JSRef, Root, Temporary, OptionalRootable}; +use dom::bindings::js::{ResultRootable, RootedReference, MutNullableJS}; use dom::bindings::utils::{Reflectable, Reflector}; use dom::document::{Document, DocumentHelpers}; use dom::element::{AttributeHandlers, Element, HTMLInputElementTypeId}; @@ -260,16 +261,13 @@ pub trait HTMLInputElementHelpers { fn force_relayout(self); fn radio_group_updated(self, group: Option<&str>); fn get_radio_group_name(self) -> Option; - fn in_same_group<'a,'b>(self, other: JSRef<'a, HTMLInputElement>, - owner: Option>, - group: Option<&str>) -> bool; fn update_checked_state(self, checked: bool); fn get_size(&self) -> u32; } fn broadcast_radio_checked(broadcaster: JSRef, group: Option<&str>) { //TODO: if not in document, use root ancestor instead of document - let owner = broadcaster.form_owner().root().map(|r| *r); + let owner = broadcaster.form_owner().root(); let doc = document_from_node(broadcaster).root(); let doc_node: JSRef = NodeCast::from_ref(*doc); @@ -277,7 +275,7 @@ fn broadcast_radio_checked(broadcaster: JSRef, group: Option<& let mut iter = unsafe { doc_node.query_selector_iter("input[type=radio]".to_string()).unwrap() .filter_map(|t| HTMLInputElementCast::to_ref(t)) - .filter(|&r| broadcaster.in_same_group(r, owner, group) && broadcaster != r) + .filter(|&r| in_same_group(r, owner.root_ref(), group) && broadcaster != r) }; for r in iter { if r.Checked() { @@ -286,6 +284,22 @@ fn broadcast_radio_checked(broadcaster: JSRef, group: Option<& } } +fn in_same_group<'a,'b>(other: JSRef<'a, HTMLInputElement>, + owner: Option>, + group: Option<&str>) -> bool { + let other_owner = other.form_owner().root(); + let other_owner = other_owner.root_ref(); + other.input_type.get() == InputRadio && + // TODO Both a and b are in the same home subtree. + other_owner.equals(owner) && + // TODO should be a unicode compatibility caseless match + match (other.get_radio_group_name(), group) { + (Some(ref s1), Some(s2)) => s1.as_slice() == s2, + (None, None) => true, + _ => false + } +} + impl<'a> HTMLInputElementHelpers for JSRef<'a, HTMLInputElement> { fn force_relayout(self) { let doc = document_from_node(self).root(); @@ -307,21 +321,6 @@ impl<'a> HTMLInputElementHelpers for JSRef<'a, HTMLInputElement> { .map(|name| name.Value()) } - fn in_same_group<'a,'b>(self, other: JSRef<'a, HTMLInputElement>, - owner: Option>, - group: Option<&str>) -> bool { - let other_owner: Option> = other.form_owner().root().map(|r| *r); - other.input_type.get() == InputRadio && - // TODO Both a and b are in the same home subtree. - other_owner == owner && - // TODO should be a unicode compatibility caseless match - match (other.get_radio_group_name(), group) { - (Some(ref s1), Some(s2)) => s1.as_slice() == s2, - (None, None) => true, - _ => false - } - } - fn update_checked_state(self, checked: bool) { self.checked.set(checked); if self.input_type.get() == InputRadio && checked { @@ -582,7 +581,7 @@ impl<'a> Activatable for JSRef<'a, HTMLInputElement> { // https://html.spec.whatwg.org/multipage/forms.html#radio-button-state-(type=radio):pre-click-activation-steps InputRadio => { //TODO: if not in document, use root ancestor instead of document - let owner = self.form_owner().root().map(|r| *r); + let owner = self.form_owner().root(); let doc = document_from_node(*self).root(); let doc_node: JSRef = NodeCast::from_ref(*doc); let group = self.get_radio_group_name();; @@ -591,8 +590,8 @@ impl<'a> Activatable for JSRef<'a, HTMLInputElement> { let checked_member = unsafe { doc_node.query_selector_iter("input[type=radio]".to_string()).unwrap() .filter_map(|t| HTMLInputElementCast::to_ref(t)) - .filter(|&r| self.in_same_group(r, owner, - group.as_ref().map(|gr| gr.as_slice()))) + .filter(|&r| in_same_group(r, owner.root_ref(), + group.as_ref().map(|gr| gr.as_slice()))) .find(|r| r.Checked()) }; cache.checked_radio.assign(checked_member); @@ -673,16 +672,16 @@ impl<'a> Activatable for JSRef<'a, HTMLInputElement> { // https://html.spec.whatwg.org/multipage/forms.html#radio-button-state-(type=radio):activation-behavior if self.mutable() { let win = window_from_node(*self).root(); - let event = Event::new(&Window(*win), - "input".to_string(), - Bubbles, NotCancelable).root(); + let event = Event::new(Window(*win), + "input".to_string(), + Bubbles, NotCancelable).root(); event.set_trusted(true); let target: JSRef = EventTargetCast::from_ref(*self); target.DispatchEvent(*event).ok(); - let event = Event::new(&Window(*win), - "change".to_string(), - Bubbles, NotCancelable).root(); + let event = Event::new(Window(*win), + "change".to_string(), + Bubbles, NotCancelable).root(); event.set_trusted(true); let target: JSRef = EventTargetCast::from_ref(*self); target.DispatchEvent(*event).ok(); diff --git a/components/script/dom/macros.rs b/components/script/dom/macros.rs index b98d67a090f..a5789a5cc61 100644 --- a/components/script/dom/macros.rs +++ b/components/script/dom/macros.rs @@ -226,4 +226,4 @@ macro_rules! global_event_handlers( event_handler!(input, GetOninput, SetOninput) event_handler!(change, GetOnchange, SetOnchange) ) -) \ No newline at end of file +) diff --git a/components/script/script_task.rs b/components/script/script_task.rs index b826ac98047..28c7c2e8a0b 100644 --- a/components/script/script_task.rs +++ b/components/script/script_task.rs @@ -10,7 +10,7 @@ use dom::bindings::codegen::Bindings::DocumentBinding::{DocumentMethods, Documen use dom::bindings::codegen::Bindings::EventBinding::EventMethods; use dom::bindings::codegen::Bindings::EventTargetBinding::EventTargetMethods; use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods; -use dom::bindings::codegen::InheritTypes::{EventTargetCast, NodeCast, EventCast}; +use dom::bindings::codegen::InheritTypes::{ElementCast, EventTargetCast, NodeCast, EventCast}; use dom::bindings::conversions::{FromJSValConvertible, Empty}; use dom::bindings::global; use dom::bindings::js::{JS, JSRef, RootCollection, Temporary, OptionalRootable}; diff --git a/tests/wpt/metadata/html/dom/interfaces.html.ini b/tests/wpt/metadata/html/dom/interfaces.html.ini index 3a281c37b6f..566546e4cb7 100644 --- a/tests/wpt/metadata/html/dom/interfaces.html.ini +++ b/tests/wpt/metadata/html/dom/interfaces.html.ini @@ -9591,9 +9591,6 @@ [Document interface: document.implementation.createDocument(null, "", null) must inherit property "oncanplaythrough" with the proper type (99)] expected: FAIL - [Document interface: document.implementation.createDocument(null, "", null) must inherit property "onchange" with the proper type (100)] - expected: FAIL - [Document interface: document.implementation.createDocument(null, "", null) must inherit property "onclose" with the proper type (102)] expected: FAIL @@ -9645,9 +9642,6 @@ [Document interface: document.implementation.createDocument(null, "", null) must inherit property "onfocus" with the proper type (118)] expected: FAIL - [Document interface: document.implementation.createDocument(null, "", null) must inherit property "oninput" with the proper type (119)] - expected: FAIL - [Document interface: document.implementation.createDocument(null, "", null) must inherit property "oninvalid" with the proper type (120)] expected: FAIL