diff options
Diffstat (limited to 'src/components/script/dom/eventdispatcher.rs')
-rw-r--r-- | src/components/script/dom/eventdispatcher.rs | 70 |
1 files changed, 38 insertions, 32 deletions
diff --git a/src/components/script/dom/eventdispatcher.rs b/src/components/script/dom/eventdispatcher.rs index d298ab38492..1bd90f93137 100644 --- a/src/components/script/dom/eventdispatcher.rs +++ b/src/components/script/dom/eventdispatcher.rs @@ -4,58 +4,59 @@ use dom::bindings::callback::ReportExceptions; use dom::bindings::codegen::InheritTypes::{EventTargetCast, NodeCast, NodeDerived}; -use dom::bindings::js::JS; +use dom::bindings::js::{JSRef, OptionalSettable, Root}; use dom::eventtarget::{Capturing, Bubbling, EventTarget}; -use dom::event::{Event, PhaseAtTarget, PhaseNone, PhaseBubbling, PhaseCapturing}; +use dom::event::{Event, PhaseAtTarget, PhaseNone, PhaseBubbling, PhaseCapturing, EventMethods}; use dom::node::{Node, NodeHelpers}; // See http://dom.spec.whatwg.org/#concept-event-dispatch for the full dispatch algorithm -pub fn dispatch_event(target: &JS<EventTarget>, - pseudo_target: Option<JS<EventTarget>>, - event: &mut JS<Event>) -> bool { - assert!(!event.get().dispatching); +pub fn dispatch_event<'a, 'b>(target: &JSRef<'a, EventTarget>, + pseudo_target: Option<JSRef<'b, EventTarget>>, + event: &mut JSRef<Event>) -> bool { + assert!(!event.deref().dispatching); { - let event = event.get_mut(); - event.target = pseudo_target.or_else(|| { - Some(target.clone()) - }); + let event = event.deref_mut(); + event.target.assign(Some(match pseudo_target { + Some(pseudo_target) => pseudo_target, + None => target.clone(), + })); event.dispatching = true; } - let type_ = event.get().type_.clone(); + let type_ = event.deref().type_.clone(); //TODO: no chain if not participating in a tree - let chain: Vec<JS<EventTarget>> = if target.get().is_node() { - let target_node: JS<Node> = NodeCast::to(target).unwrap(); + let mut chain: Vec<Root<EventTarget>> = if target.deref().is_node() { + let target_node: &JSRef<Node> = NodeCast::to_ref(target).unwrap(); target_node.ancestors().map(|ancestor| { - let ancestor_target: JS<EventTarget> = EventTargetCast::from(&ancestor); - ancestor_target + let ancestor_target: &JSRef<EventTarget> = EventTargetCast::from_ref(&ancestor); + ancestor_target.unrooted().root() }).collect() } else { vec!() }; - event.get_mut().phase = PhaseCapturing; + event.deref_mut().phase = PhaseCapturing; //FIXME: The "callback this value" should be currentTarget /* capturing */ for cur_target in chain.as_slice().rev_iter() { - let stopped = match cur_target.get().get_listeners_for(type_, Capturing) { + let stopped = match cur_target.get_listeners_for(type_, Capturing) { Some(listeners) => { - event.get_mut().current_target = Some(cur_target.clone()); + event.current_target.assign(Some(cur_target.deref().clone())); for listener in listeners.iter() { //FIXME: this should have proper error handling, or explicitly // drop the exception on the floor assert!(listener.HandleEvent__(event, ReportExceptions).is_ok()); - if event.get().stop_immediate { + if event.deref().stop_immediate { break; } } - event.get().stop_propagation + event.deref().stop_propagation } None => false }; @@ -66,20 +67,20 @@ pub fn dispatch_event(target: &JS<EventTarget>, } /* at target */ - if !event.get().stop_propagation { + if !event.deref().stop_propagation { { - let event = event.get_mut(); + let event = event.deref_mut(); event.phase = PhaseAtTarget; - event.current_target = Some(target.clone()); + event.current_target.assign(Some(target.clone())); } - let opt_listeners = target.get().get_listeners(type_); + let opt_listeners = target.deref().get_listeners(type_); for listeners in opt_listeners.iter() { for listener in listeners.iter() { //FIXME: this should have proper error handling, or explicitly drop the // exception on the floor. assert!(listener.HandleEvent__(event, ReportExceptions).is_ok()); - if event.get().stop_immediate { + if event.deref().stop_immediate { break; } } @@ -87,24 +88,24 @@ pub fn dispatch_event(target: &JS<EventTarget>, } /* bubbling */ - if event.get().bubbles && !event.get().stop_propagation { - event.get_mut().phase = PhaseBubbling; + if event.deref().bubbles && !event.deref().stop_propagation { + event.deref_mut().phase = PhaseBubbling; for cur_target in chain.iter() { - let stopped = match cur_target.get().get_listeners_for(type_, Bubbling) { + let stopped = match cur_target.deref().get_listeners_for(type_, Bubbling) { Some(listeners) => { - event.get_mut().current_target = Some(cur_target.clone()); + event.deref_mut().current_target.assign(Some(cur_target.deref().clone())); for listener in listeners.iter() { //FIXME: this should have proper error handling or explicitly // drop exceptions on the floor. assert!(listener.HandleEvent__(event, ReportExceptions).is_ok()); - if event.get().stop_immediate { + if event.deref().stop_immediate { break; } } - event.get().stop_propagation + event.deref().stop_propagation } None => false }; @@ -114,7 +115,12 @@ pub fn dispatch_event(target: &JS<EventTarget>, } } - let event = event.get_mut(); + // Root ordering restrictions mean we need to unroot the chain entries + // in the same order they were rooted. + while chain.len() > 0 { + let _ = chain.pop(); + } + event.dispatching = false; event.phase = PhaseNone; event.current_target = None; |