Return an enum instead of a boolean from dispatch_event

Fixes #13196
This commit is contained in:
Adolfo Ochagavía 2016-09-23 17:51:24 +02:00
parent 821797d6f7
commit 6c8bfdb774
7 changed files with 45 additions and 17 deletions

View file

@ -19,6 +19,7 @@ use dom::bindings::str::DOMString;
use dom::bindings::structuredclone::StructuredCloneData; use dom::bindings::structuredclone::StructuredCloneData;
use dom::errorevent::ErrorEvent; use dom::errorevent::ErrorEvent;
use dom::event::{Event, EventBubbles, EventCancelable}; use dom::event::{Event, EventBubbles, EventCancelable};
use dom::eventdispatcher::EventStatus;
use dom::eventtarget::EventTarget; use dom::eventtarget::EventTarget;
use dom::messageevent::MessageEvent; use dom::messageevent::MessageEvent;
use dom::worker::{TrustedWorkerAddress, WorkerErrorHandler, WorkerMessageHandler}; use dom::worker::{TrustedWorkerAddress, WorkerErrorHandler, WorkerMessageHandler};
@ -370,8 +371,10 @@ impl DedicatedWorkerGlobalScope {
value); value);
// Step 13. // Step 13.
let handled = !event.upcast::<Event>().fire(self.upcast::<EventTarget>()); let event_status = event.upcast::<Event>().fire(self.upcast::<EventTarget>());
if !handled {
// Step 15
if event_status == EventStatus::NotCanceled {
let worker = self.worker.borrow().as_ref().unwrap().clone(); let worker = self.worker.borrow().as_ref().unwrap().clone();
// TODO: Should use the DOM manipulation task source. // TODO: Should use the DOM manipulation task source.
self.parent_sender self.parent_sender
@ -380,6 +383,7 @@ impl DedicatedWorkerGlobalScope {
.unwrap(); .unwrap();
} }
// Step 14
self.in_error_reporting_mode.set(false); self.in_error_reporting_mode.set(false);
} }
} }

View file

@ -41,6 +41,7 @@ use dom::domimplementation::DOMImplementation;
use dom::element::{Element, ElementCreator}; use dom::element::{Element, ElementCreator};
use dom::errorevent::ErrorEvent; use dom::errorevent::ErrorEvent;
use dom::event::{Event, EventBubbles, EventCancelable}; use dom::event::{Event, EventBubbles, EventCancelable};
use dom::eventdispatcher::EventStatus;
use dom::eventtarget::EventTarget; use dom::eventtarget::EventTarget;
use dom::focusevent::FocusEvent; use dom::focusevent::FocusEvent;
use dom::forcetouchevent::ForceTouchEvent; use dom::forcetouchevent::ForceTouchEvent;
@ -1118,7 +1119,11 @@ impl Document {
window.reflow(ReflowGoal::ForDisplay, window.reflow(ReflowGoal::ForDisplay,
ReflowQueryType::NoQuery, ReflowQueryType::NoQuery,
ReflowReason::MouseEvent); ReflowReason::MouseEvent);
result
match result {
EventStatus::Canceled => false,
EventStatus::NotCanceled => true
}
} }
/// The entry point for all key processing for web content /// The entry point for all key processing for web content

View file

@ -11,6 +11,7 @@ use dom::bindings::js::{JS, MutNullableHeap, Root};
use dom::bindings::refcounted::Trusted; use dom::bindings::refcounted::Trusted;
use dom::bindings::reflector::{Reflector, reflect_dom_object}; use dom::bindings::reflector::{Reflector, reflect_dom_object};
use dom::bindings::str::DOMString; use dom::bindings::str::DOMString;
use dom::eventdispatcher::EventStatus;
use dom::eventtarget::EventTarget; use dom::eventtarget::EventTarget;
use script_thread::Runnable; use script_thread::Runnable;
use std::cell::Cell; use std::cell::Cell;
@ -153,6 +154,13 @@ impl Event {
self.cancelable.set(cancelable); self.cancelable.set(cancelable);
} }
pub fn status(&self) -> EventStatus {
match self.DefaultPrevented() {
true => EventStatus::Canceled,
false => EventStatus::NotCanceled
}
}
#[inline] #[inline]
pub fn set_current_target(&self, val: &EventTarget) { pub fn set_current_target(&self, val: &EventTarget) {
self.current_target.set(Some(val)); self.current_target.set(Some(val));
@ -303,7 +311,7 @@ impl Event {
} }
// https://html.spec.whatwg.org/multipage/#fire-a-simple-event // https://html.spec.whatwg.org/multipage/#fire-a-simple-event
pub fn fire(&self, target: &EventTarget) -> bool { pub fn fire(&self, target: &EventTarget) -> EventStatus {
self.set_trusted(true); self.set_trusted(true);
target.dispatch_event(self) target.dispatch_event(self)
} }

View file

@ -103,10 +103,16 @@ fn dispatch_to_listeners(event: &Event, target: &EventTarget, event_path: &[&Eve
} }
} }
#[derive(PartialEq)]
pub enum EventStatus {
Canceled,
NotCanceled
}
// https://dom.spec.whatwg.org/#concept-event-dispatch // https://dom.spec.whatwg.org/#concept-event-dispatch
pub fn dispatch_event(target: &EventTarget, pub fn dispatch_event(target: &EventTarget,
target_override: Option<&EventTarget>, target_override: Option<&EventTarget>,
event: &Event) -> bool { event: &Event) -> EventStatus {
assert!(!event.dispatching()); assert!(!event.dispatching());
assert!(event.initialized()); assert!(event.initialized());
assert_eq!(event.phase(), EventPhase::None); assert_eq!(event.phase(), EventPhase::None);
@ -126,7 +132,7 @@ pub fn dispatch_event(target: &EventTarget,
event.clear_dispatching_flags(); event.clear_dispatching_flags();
// Step 14. // Step 14.
return !event.DefaultPrevented(); return event.status();
} }
// Step 3. The "invoke" algorithm is only used on `target` separately, // Step 3. The "invoke" algorithm is only used on `target` separately,
@ -165,8 +171,8 @@ pub fn dispatch_event(target: &EventTarget,
// Step 10-12. // Step 10-12.
event.clear_dispatching_flags(); event.clear_dispatching_flags();
// Step 13. // Step 14.
!event.DefaultPrevented() event.status()
} }
// https://dom.spec.whatwg.org/#concept-event-listener-invoke // https://dom.spec.whatwg.org/#concept-event-listener-invoke

View file

@ -23,7 +23,7 @@ use dom::bindings::str::DOMString;
use dom::element::Element; use dom::element::Element;
use dom::errorevent::ErrorEvent; use dom::errorevent::ErrorEvent;
use dom::event::{Event, EventBubbles, EventCancelable}; use dom::event::{Event, EventBubbles, EventCancelable};
use dom::eventdispatcher::dispatch_event; use dom::eventdispatcher::{EventStatus, dispatch_event};
use dom::node::document_from_node; use dom::node::document_from_node;
use dom::virtualmethods::VirtualMethods; use dom::virtualmethods::VirtualMethods;
use dom::window::Window; use dom::window::Window;
@ -300,11 +300,11 @@ impl EventTarget {
pub fn dispatch_event_with_target(&self, pub fn dispatch_event_with_target(&self,
target: &EventTarget, target: &EventTarget,
event: &Event) -> bool { event: &Event) -> EventStatus {
dispatch_event(self, Some(target), event) dispatch_event(self, Some(target), event)
} }
pub fn dispatch_event(&self, event: &Event) -> bool { pub fn dispatch_event(&self, event: &Event) -> EventStatus {
dispatch_event(self, None, event) dispatch_event(self, None, event)
} }
@ -560,7 +560,10 @@ impl EventTargetMethods for EventTarget {
return Err(Error::InvalidState); return Err(Error::InvalidState);
} }
event.set_trusted(false); event.set_trusted(false);
Ok(self.dispatch_event(event)) Ok(match self.dispatch_event(event) {
EventStatus::Canceled => false,
EventStatus::NotCanceled => true
})
} }
} }

View file

@ -18,6 +18,7 @@ use dom::bindings::str::DOMString;
use dom::document::Document; use dom::document::Document;
use dom::element::{AttributeMutation, Element, ElementCreator}; use dom::element::{AttributeMutation, Element, ElementCreator};
use dom::event::{Event, EventBubbles, EventCancelable}; use dom::event::{Event, EventBubbles, EventCancelable};
use dom::eventdispatcher::EventStatus;
use dom::htmlelement::HTMLElement; use dom::htmlelement::HTMLElement;
use dom::node::{ChildrenMutation, CloneChildrenFlag, Node}; use dom::node::{ChildrenMutation, CloneChildrenFlag, Node};
use dom::node::{document_from_node, window_from_node}; use dom::node::{document_from_node, window_from_node};
@ -444,7 +445,7 @@ impl HTMLScriptElement {
} }
// TODO(#12446): beforescriptexecute. // TODO(#12446): beforescriptexecute.
if !self.dispatch_before_script_execute_event() { if self.dispatch_before_script_execute_event() == EventStatus::Canceled {
return; return;
} }
@ -491,7 +492,7 @@ impl HTMLScriptElement {
window.dom_manipulation_task_source().queue_simple_event(self.upcast(), atom!("error"), window.r()); window.dom_manipulation_task_source().queue_simple_event(self.upcast(), atom!("error"), window.r());
} }
pub fn dispatch_before_script_execute_event(&self) -> bool { pub fn dispatch_before_script_execute_event(&self) -> EventStatus {
self.dispatch_event(atom!("beforescriptexecute"), self.dispatch_event(atom!("beforescriptexecute"),
EventBubbles::Bubbles, EventBubbles::Bubbles,
EventCancelable::Cancelable) EventCancelable::Cancelable)
@ -562,7 +563,7 @@ impl HTMLScriptElement {
fn dispatch_event(&self, fn dispatch_event(&self,
type_: Atom, type_: Atom,
bubbles: EventBubbles, bubbles: EventBubbles,
cancelable: EventCancelable) -> bool { cancelable: EventCancelable) -> EventStatus {
let window = window_from_node(self); let window = window_from_node(self);
let window = window.r(); let window = window.r();
let event = Event::new(GlobalRef::Window(window), type_, bubbles, cancelable); let event = Event::new(GlobalRef::Window(window), type_, bubbles, cancelable);

View file

@ -19,6 +19,7 @@ use dom::bindings::structuredclone::StructuredCloneData;
use dom::dedicatedworkerglobalscope::DedicatedWorkerGlobalScope; use dom::dedicatedworkerglobalscope::DedicatedWorkerGlobalScope;
use dom::errorevent::ErrorEvent; use dom::errorevent::ErrorEvent;
use dom::event::{Event, EventBubbles, EventCancelable}; use dom::event::{Event, EventBubbles, EventCancelable};
use dom::eventdispatcher::EventStatus;
use dom::eventtarget::EventTarget; use dom::eventtarget::EventTarget;
use dom::messageevent::MessageEvent; use dom::messageevent::MessageEvent;
use dom::workerglobalscope::prepare_workerscope_init; use dom::workerglobalscope::prepare_workerscope_init;
@ -153,8 +154,8 @@ impl Worker {
error_info.column, error_info.column,
unsafe { NullHandleValue }); unsafe { NullHandleValue });
let handled = !event.upcast::<Event>().fire(self.upcast::<EventTarget>()); let event_status = event.upcast::<Event>().fire(self.upcast::<EventTarget>());
if handled { if event_status == EventStatus::Canceled {
return; return;
} }