From 3d0b7fbc413f975d6302428947132366f0e339d5 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 4 Jun 2016 15:20:04 +0200 Subject: [PATCH] Implement EventListenerOptions for EventTarget For now, only "capture" is supported. --- .../dom/bindings/codegen/CodegenRust.py | 3 +- components/script/dom/eventtarget.rs | 87 ++++++++++++++++--- components/script/dom/mediaquerylist.rs | 17 ++-- .../script/dom/webidls/EventTarget.webidl | 27 ++++-- .../AddEventListenerOptions-passive.html.ini | 3 - .../EventListenerOptions-capture.html.ini | 12 --- 6 files changed, 108 insertions(+), 41 deletions(-) delete mode 100644 tests/wpt/metadata/dom/events/EventListenerOptions-capture.html.ini diff --git a/components/script/dom/bindings/codegen/CodegenRust.py b/components/script/dom/bindings/codegen/CodegenRust.py index 8880707f7d5f..a82ad040041b 100644 --- a/components/script/dom/bindings/codegen/CodegenRust.py +++ b/components/script/dom/bindings/codegen/CodegenRust.py @@ -6142,8 +6142,7 @@ def memberInsert(memberInfo): " } else if val.get().is_object() {\n" " val.get().to_object()\n" " } else {\n" - " throw_type_error(cx, \"Value not an object.\");\n" - " return Err(());\n" + " return Ok(ConversionResult::Failure(\"Value is not an object.\".into()));\n" " };\n" " rooted!(in(cx) let object = object);\n" "${preInitial}" diff --git a/components/script/dom/eventtarget.rs b/components/script/dom/eventtarget.rs index a33f7703e1a5..6742094068b8 100644 --- a/components/script/dom/eventtarget.rs +++ b/components/script/dom/eventtarget.rs @@ -12,8 +12,12 @@ use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull; use dom::bindings::codegen::Bindings::EventHandlerBinding::OnBeforeUnloadEventHandlerNonNull; use dom::bindings::codegen::Bindings::EventHandlerBinding::OnErrorEventHandlerNonNull; use dom::bindings::codegen::Bindings::EventListenerBinding::EventListener; +use dom::bindings::codegen::Bindings::EventTargetBinding::AddEventListenerOptions; +use dom::bindings::codegen::Bindings::EventTargetBinding::EventListenerOptions; use dom::bindings::codegen::Bindings::EventTargetBinding::EventTargetMethods; use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods; +use dom::bindings::codegen::UnionTypes::AddEventListenerOptionsOrBoolean; +use dom::bindings::codegen::UnionTypes::EventListenerOptionsOrBoolean; use dom::bindings::codegen::UnionTypes::EventOrString; use dom::bindings::error::{Error, Fallible, report_pending_exception}; use dom::bindings::inheritance::Castable; @@ -543,14 +547,13 @@ impl EventTarget { event.fire(self); event } -} - -impl EventTargetMethods for EventTarget { // https://dom.spec.whatwg.org/#dom-eventtarget-addeventlistener - fn AddEventListener(&self, - ty: DOMString, - listener: Option>, - capture: bool) { + pub fn add_event_listener( + &self, + ty: DOMString, + listener: Option>, + options: AddEventListenerOptions, + ) { let listener = match listener { Some(l) => l, None => return, @@ -561,7 +564,11 @@ impl EventTargetMethods for EventTarget { Vacant(entry) => entry.insert(EventListeners(vec!())), }; - let phase = if capture { ListenerPhase::Capturing } else { ListenerPhase::Bubbling }; + let phase = if options.parent.capture { + ListenerPhase::Capturing + } else { + ListenerPhase::Bubbling + }; let new_entry = EventListenerEntry { phase: phase, listener: EventListenerType::Additive(listener) @@ -572,10 +579,12 @@ impl EventTargetMethods for EventTarget { } // https://dom.spec.whatwg.org/#dom-eventtarget-removeeventlistener - fn RemoveEventListener(&self, - ty: DOMString, - listener: Option>, - capture: bool) { + pub fn remove_event_listener( + &self, + ty: DOMString, + listener: Option>, + options: EventListenerOptions, + ) { let ref listener = match listener { Some(l) => l, None => return, @@ -583,7 +592,11 @@ impl EventTargetMethods for EventTarget { let mut handlers = self.handlers.borrow_mut(); let entry = handlers.get_mut(&Atom::from(ty)); for entry in entry { - let phase = if capture { ListenerPhase::Capturing } else { ListenerPhase::Bubbling }; + let phase = if options.capture { + ListenerPhase::Capturing + } else { + ListenerPhase::Bubbling + }; let old_entry = EventListenerEntry { phase: phase, listener: EventListenerType::Additive(listener.clone()) @@ -593,6 +606,28 @@ impl EventTargetMethods for EventTarget { } } } +} + +impl EventTargetMethods for EventTarget { + // https://dom.spec.whatwg.org/#dom-eventtarget-addeventlistener + fn AddEventListener( + &self, + ty: DOMString, + listener: Option>, + options: AddEventListenerOptionsOrBoolean, + ) { + self.add_event_listener(ty, listener, options.into()) + } + + // https://dom.spec.whatwg.org/#dom-eventtarget-removeeventlistener + fn RemoveEventListener( + &self, + ty: DOMString, + listener: Option>, + options: EventListenerOptionsOrBoolean, + ) { + self.remove_event_listener(ty, listener, options.into()) + } // https://dom.spec.whatwg.org/#dom-eventtarget-dispatchevent fn DispatchEvent(&self, event: &Event) -> Fallible { @@ -612,3 +647,29 @@ impl VirtualMethods for EventTarget { None } } + +impl From for AddEventListenerOptions { + fn from(options: AddEventListenerOptionsOrBoolean) -> Self { + match options { + AddEventListenerOptionsOrBoolean::AddEventListenerOptions(options) => { + options + }, + AddEventListenerOptionsOrBoolean::Boolean(capture) => { + Self { parent: EventListenerOptions { capture } } + }, + } + } +} + +impl From for EventListenerOptions { + fn from(options: EventListenerOptionsOrBoolean) -> Self { + match options { + EventListenerOptionsOrBoolean::EventListenerOptions(options) => { + options + }, + EventListenerOptionsOrBoolean::Boolean(capture) => { + Self { capture } + }, + } + } +} diff --git a/components/script/dom/mediaquerylist.rs b/components/script/dom/mediaquerylist.rs index 33eb2dc92d53..97f6f5907798 100644 --- a/components/script/dom/mediaquerylist.rs +++ b/components/script/dom/mediaquerylist.rs @@ -4,7 +4,8 @@ use dom::bindings::cell::DomRefCell; use dom::bindings::codegen::Bindings::EventListenerBinding::EventListener; -use dom::bindings::codegen::Bindings::EventTargetBinding::EventTargetMethods; +use dom::bindings::codegen::Bindings::EventTargetBinding::AddEventListenerOptions; +use dom::bindings::codegen::Bindings::EventTargetBinding::EventListenerOptions; use dom::bindings::codegen::Bindings::MediaQueryListBinding::{self, MediaQueryListMethods}; use dom::bindings::inheritance::Castable; use dom::bindings::reflector::DomObject; @@ -97,14 +98,20 @@ impl MediaQueryListMethods for MediaQueryList { // https://drafts.csswg.org/cssom-view/#dom-mediaquerylist-addlistener fn AddListener(&self, listener: Option>) { - self.upcast::().AddEventListener(DOMString::from_string("change".to_owned()), - listener, false); + self.upcast::().add_event_listener( + DOMString::from_string("change".to_owned()), + listener, + AddEventListenerOptions { parent: EventListenerOptions { capture: false } }, + ); } // https://drafts.csswg.org/cssom-view/#dom-mediaquerylist-removelistener fn RemoveListener(&self, listener: Option>) { - self.upcast::().RemoveEventListener(DOMString::from_string("change".to_owned()), - listener, false); + self.upcast::().remove_event_listener( + DOMString::from_string("change".to_owned()), + listener, + EventListenerOptions { capture: false }, + ); } // https://drafts.csswg.org/cssom-view/#dom-mediaquerylist-onchange diff --git a/components/script/dom/webidls/EventTarget.webidl b/components/script/dom/webidls/EventTarget.webidl index ad25712122ae..fbdff52c02ce 100644 --- a/components/script/dom/webidls/EventTarget.webidl +++ b/components/script/dom/webidls/EventTarget.webidl @@ -7,12 +7,27 @@ [Abstract, Exposed=(Window,Worker,Worklet)] interface EventTarget { - void addEventListener(DOMString type, - EventListener? listener, - optional boolean capture = false); - void removeEventListener(DOMString type, - EventListener? listener, - optional boolean capture = false); + void addEventListener( + DOMString type, + EventListener? callback, + optional (AddEventListenerOptions or boolean) options + ); + + void removeEventListener( + DOMString type, + EventListener? callback, + optional (EventListenerOptions or boolean) options + ); + [Throws] boolean dispatchEvent(Event event); }; + +dictionary EventListenerOptions { + boolean capture = false; +}; + +dictionary AddEventListenerOptions : EventListenerOptions { + // boolean passive = false; + // boolean once = false; +}; diff --git a/tests/wpt/metadata/dom/events/AddEventListenerOptions-passive.html.ini b/tests/wpt/metadata/dom/events/AddEventListenerOptions-passive.html.ini index 552da8a11ef2..fc85c0ff835b 100644 --- a/tests/wpt/metadata/dom/events/AddEventListenerOptions-passive.html.ini +++ b/tests/wpt/metadata/dom/events/AddEventListenerOptions-passive.html.ini @@ -11,6 +11,3 @@ [passive behavior of one listener should be unaffeted by the presence of other listeners] expected: FAIL - [Equivalence of option values] - expected: FAIL - diff --git a/tests/wpt/metadata/dom/events/EventListenerOptions-capture.html.ini b/tests/wpt/metadata/dom/events/EventListenerOptions-capture.html.ini deleted file mode 100644 index 2a0772312681..000000000000 --- a/tests/wpt/metadata/dom/events/EventListenerOptions-capture.html.ini +++ /dev/null @@ -1,12 +0,0 @@ -[EventListenerOptions-capture.html] - type: testharness - bug: https://github.com/servo/servo/issues/9785 - [Capture option should be honored correctly] - expected: FAIL - - [Supports capture option] - expected: FAIL - - [Equivalence of option values] - expected: FAIL -