Use internal mutability for Event.

This commit is contained in:
Ms2ger 2014-06-10 13:45:14 +02:00
parent d255a83a48
commit 0b364d13b6
8 changed files with 105 additions and 111 deletions

View file

@ -70,7 +70,7 @@ impl<'a> CustomEventMethods for JSRef<'a, CustomEvent> {
cancelable: bool, cancelable: bool,
detail: JSVal) { detail: JSVal) {
self.detail = Traceable::new(detail); self.detail = Traceable::new(detail);
let event: &mut JSRef<Event> = EventCast::from_mut_ref(self); let event: &JSRef<Event> = EventCast::from_ref(self);
event.InitEvent(type_, can_bubble, cancelable); event.InitEvent(type_, can_bubble, cancelable);
} }
} }

View file

@ -4,14 +4,15 @@
use dom::bindings::codegen::Bindings::EventBinding; use dom::bindings::codegen::Bindings::EventBinding;
use dom::bindings::codegen::Bindings::EventBinding::EventConstants; use dom::bindings::codegen::Bindings::EventBinding::EventConstants;
use dom::bindings::js::{JS, JSRef, Temporary};
use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object};
use dom::bindings::error::Fallible; use dom::bindings::error::Fallible;
use dom::bindings::js::{JS, JSRef, Temporary};
use dom::bindings::trace::Untraceable;
use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object};
use dom::eventtarget::EventTarget; use dom::eventtarget::EventTarget;
use dom::window::Window; use dom::window::Window;
use servo_util::str::DOMString; use servo_util::str::DOMString;
use servo_util::geometry::PagePx; use servo_util::geometry::PagePx;
use std::cell::Cell; use std::cell::{Cell, RefCell};
use geom::point::Point2D; use geom::point::Point2D;
use geom::size::TypedSize2D; use geom::size::TypedSize2D;
@ -51,16 +52,16 @@ pub struct Event {
pub reflector_: Reflector, pub reflector_: Reflector,
pub current_target: Cell<Option<JS<EventTarget>>>, pub current_target: Cell<Option<JS<EventTarget>>>,
pub target: Cell<Option<JS<EventTarget>>>, pub target: Cell<Option<JS<EventTarget>>>,
pub type_: DOMString, type_: Untraceable<RefCell<DOMString>>,
pub phase: EventPhase, pub phase: Untraceable<Cell<EventPhase>>,
pub canceled: bool, pub canceled: Untraceable<Cell<bool>>,
pub stop_propagation: bool, pub stop_propagation: Untraceable<Cell<bool>>,
pub stop_immediate: bool, pub stop_immediate: Untraceable<Cell<bool>>,
pub cancelable: bool, pub cancelable: Untraceable<Cell<bool>>,
pub bubbles: bool, pub bubbles: Untraceable<Cell<bool>>,
pub trusted: bool, pub trusted: Untraceable<Cell<bool>>,
pub dispatching: bool, pub dispatching: Untraceable<Cell<bool>>,
pub initialized: bool, pub initialized: Untraceable<Cell<bool>>,
pub timestamp: u64, pub timestamp: u64,
} }
@ -71,16 +72,16 @@ impl Event {
reflector_: Reflector::new(), reflector_: Reflector::new(),
current_target: Cell::new(None), current_target: Cell::new(None),
target: Cell::new(None), target: Cell::new(None),
phase: PhaseNone, phase: Untraceable::new(Cell::new(PhaseNone)),
type_: "".to_string(), type_: Untraceable::new(RefCell::new("".to_string())),
canceled: false, canceled: Untraceable::new(Cell::new(false)),
cancelable: true, cancelable: Untraceable::new(Cell::new(true)),
bubbles: false, bubbles: Untraceable::new(Cell::new(false)),
trusted: false, trusted: Untraceable::new(Cell::new(false)),
dispatching: false, dispatching: Untraceable::new(Cell::new(false)),
stop_propagation: false, stop_propagation: Untraceable::new(Cell::new(false)),
stop_immediate: false, stop_immediate: Untraceable::new(Cell::new(false)),
initialized: false, initialized: Untraceable::new(Cell::new(false)),
timestamp: time::get_time().sec as u64, timestamp: time::get_time().sec as u64,
} }
} }
@ -95,8 +96,8 @@ impl Event {
type_: DOMString, type_: DOMString,
can_bubble: bool, can_bubble: bool,
cancelable: bool) -> Temporary<Event> { cancelable: bool) -> Temporary<Event> {
let mut event = Event::new_uninitialized(window).root(); let event = Event::new_uninitialized(window).root();
event.InitEvent(type_, can_bubble, cancelable); event.deref().InitEvent(type_, can_bubble, cancelable);
Temporary::from_rooted(&*event) Temporary::from_rooted(&*event)
} }
@ -113,23 +114,23 @@ pub trait EventMethods {
fn GetTarget(&self) -> Option<Temporary<EventTarget>>; fn GetTarget(&self) -> Option<Temporary<EventTarget>>;
fn GetCurrentTarget(&self) -> Option<Temporary<EventTarget>>; fn GetCurrentTarget(&self) -> Option<Temporary<EventTarget>>;
fn DefaultPrevented(&self) -> bool; fn DefaultPrevented(&self) -> bool;
fn PreventDefault(&mut self); fn PreventDefault(&self);
fn StopPropagation(&mut self); fn StopPropagation(&self);
fn StopImmediatePropagation(&mut self); fn StopImmediatePropagation(&self);
fn Bubbles(&self) -> bool; fn Bubbles(&self) -> bool;
fn Cancelable(&self) -> bool; fn Cancelable(&self) -> bool;
fn TimeStamp(&self) -> u64; fn TimeStamp(&self) -> u64;
fn InitEvent(&mut self, type_: DOMString, bubbles: bool, cancelable: bool); fn InitEvent(&self, type_: DOMString, bubbles: bool, cancelable: bool);
fn IsTrusted(&self) -> bool; fn IsTrusted(&self) -> bool;
} }
impl<'a> EventMethods for JSRef<'a, Event> { impl<'a> EventMethods for JSRef<'a, Event> {
fn EventPhase(&self) -> u16 { fn EventPhase(&self) -> u16 {
self.phase as u16 self.phase.deref().get() as u16
} }
fn Type(&self) -> DOMString { fn Type(&self) -> DOMString {
self.type_.clone() self.type_.deref().borrow().clone()
} }
fn GetTarget(&self) -> Option<Temporary<EventTarget>> { fn GetTarget(&self) -> Option<Temporary<EventTarget>> {
@ -141,56 +142,56 @@ impl<'a> EventMethods for JSRef<'a, Event> {
} }
fn DefaultPrevented(&self) -> bool { fn DefaultPrevented(&self) -> bool {
self.canceled self.canceled.deref().get()
} }
fn PreventDefault(&mut self) { fn PreventDefault(&self) {
if self.cancelable { if self.cancelable.deref().get() {
self.canceled = true self.canceled.deref().set(true)
} }
} }
fn StopPropagation(&mut self) { fn StopPropagation(&self) {
self.stop_propagation = true; self.stop_propagation.deref().set(true);
} }
fn StopImmediatePropagation(&mut self) { fn StopImmediatePropagation(&self) {
self.stop_immediate = true; self.stop_immediate.deref().set(true);
self.stop_propagation = true; self.stop_propagation.deref().set(true);
} }
fn Bubbles(&self) -> bool { fn Bubbles(&self) -> bool {
self.bubbles self.bubbles.deref().get()
} }
fn Cancelable(&self) -> bool { fn Cancelable(&self) -> bool {
self.cancelable self.cancelable.deref().get()
} }
fn TimeStamp(&self) -> u64 { fn TimeStamp(&self) -> u64 {
self.timestamp self.timestamp
} }
fn InitEvent(&mut self, fn InitEvent(&self,
type_: DOMString, type_: DOMString,
bubbles: bool, bubbles: bool,
cancelable: bool) { cancelable: bool) {
self.initialized = true; self.initialized.deref().set(true);
if self.dispatching { if self.dispatching.deref().get() {
return; return;
} }
self.stop_propagation = false; self.stop_propagation.deref().set(false);
self.stop_immediate = false; self.stop_immediate.deref().set(false);
self.canceled = false; self.canceled.deref().set(false);
self.trusted = false; self.trusted.deref().set(false);
self.target.set(None); self.target.set(None);
self.type_ = type_; *self.type_.deref().borrow_mut() = type_;
self.bubbles = bubbles; self.bubbles.deref().set(bubbles);
self.cancelable = cancelable; self.cancelable.deref().set(cancelable);
} }
fn IsTrusted(&self) -> bool { fn IsTrusted(&self) -> bool {
self.trusted self.trusted.deref().get()
} }
} }

View file

@ -13,19 +13,16 @@ use dom::virtualmethods::vtable_for;
// See http://dom.spec.whatwg.org/#concept-event-dispatch for the full dispatch algorithm // See http://dom.spec.whatwg.org/#concept-event-dispatch for the full dispatch algorithm
pub fn dispatch_event<'a, 'b>(target: &JSRef<'a, EventTarget>, pub fn dispatch_event<'a, 'b>(target: &JSRef<'a, EventTarget>,
pseudo_target: Option<JSRef<'b, EventTarget>>, pseudo_target: Option<JSRef<'b, EventTarget>>,
event: &mut JSRef<Event>) -> bool { event: &JSRef<Event>) -> bool {
assert!(!event.deref().dispatching); assert!(!event.deref().dispatching.deref().get());
{
let event = event.deref_mut();
event.target.assign(Some(match pseudo_target { event.target.assign(Some(match pseudo_target {
Some(pseudo_target) => pseudo_target, Some(pseudo_target) => pseudo_target,
None => target.clone(), None => target.clone(),
})); }));
event.dispatching = true; event.dispatching.deref().set(true);
}
let type_ = event.deref().type_.clone(); let type_ = event.Type();
//TODO: no chain if not participating in a tree //TODO: no chain if not participating in a tree
let mut chain: Vec<Root<EventTarget>> = if target.deref().is_node() { let mut chain: Vec<Root<EventTarget>> = if target.deref().is_node() {
@ -38,7 +35,7 @@ pub fn dispatch_event<'a, 'b>(target: &JSRef<'a, EventTarget>,
vec!() vec!()
}; };
event.deref_mut().phase = PhaseCapturing; event.deref().phase.deref().set(PhaseCapturing);
//FIXME: The "callback this value" should be currentTarget //FIXME: The "callback this value" should be currentTarget
@ -51,12 +48,12 @@ pub fn dispatch_event<'a, 'b>(target: &JSRef<'a, EventTarget>,
// Explicitly drop any exception on the floor. // Explicitly drop any exception on the floor.
let _ = listener.HandleEvent_(&**cur_target, event, ReportExceptions); let _ = listener.HandleEvent_(&**cur_target, event, ReportExceptions);
if event.deref().stop_immediate { if event.deref().stop_immediate.deref().get() {
break; break;
} }
} }
event.deref().stop_propagation event.deref().stop_propagation.deref().get()
} }
None => false None => false
}; };
@ -67,12 +64,9 @@ pub fn dispatch_event<'a, 'b>(target: &JSRef<'a, EventTarget>,
} }
/* at target */ /* at target */
if !event.deref().stop_propagation { if !event.deref().stop_propagation.deref().get() {
{ event.phase.deref().set(PhaseAtTarget);
let event = event.deref_mut();
event.phase = PhaseAtTarget;
event.current_target.assign(Some(target.clone())); event.current_target.assign(Some(target.clone()));
}
let opt_listeners = target.deref().get_listeners(type_.as_slice()); let opt_listeners = target.deref().get_listeners(type_.as_slice());
for listeners in opt_listeners.iter() { for listeners in opt_listeners.iter() {
@ -80,7 +74,7 @@ pub fn dispatch_event<'a, 'b>(target: &JSRef<'a, EventTarget>,
// Explicitly drop any exception on the floor. // Explicitly drop any exception on the floor.
let _ = listener.HandleEvent_(target, event, ReportExceptions); let _ = listener.HandleEvent_(target, event, ReportExceptions);
if event.deref().stop_immediate { if event.deref().stop_immediate.deref().get() {
break; break;
} }
} }
@ -88,23 +82,23 @@ pub fn dispatch_event<'a, 'b>(target: &JSRef<'a, EventTarget>,
} }
/* bubbling */ /* bubbling */
if event.deref().bubbles && !event.deref().stop_propagation { if event.deref().bubbles.deref().get() && !event.deref().stop_propagation.deref().get() {
event.deref_mut().phase = PhaseBubbling; event.deref().phase.deref().set(PhaseBubbling);
for cur_target in chain.iter() { for cur_target in chain.iter() {
let stopped = match cur_target.deref().get_listeners_for(type_.as_slice(), Bubbling) { let stopped = match cur_target.deref().get_listeners_for(type_.as_slice(), Bubbling) {
Some(listeners) => { Some(listeners) => {
event.deref_mut().current_target.assign(Some(cur_target.deref().clone())); event.deref().current_target.assign(Some(cur_target.deref().clone()));
for listener in listeners.iter() { for listener in listeners.iter() {
// Explicitly drop any exception on the floor. // Explicitly drop any exception on the floor.
let _ = listener.HandleEvent_(&**cur_target, event, ReportExceptions); let _ = listener.HandleEvent_(&**cur_target, event, ReportExceptions);
if event.deref().stop_immediate { if event.deref().stop_immediate.deref().get() {
break; break;
} }
} }
event.deref().stop_propagation event.deref().stop_propagation.deref().get()
} }
None => false None => false
}; };
@ -136,8 +130,8 @@ pub fn dispatch_event<'a, 'b>(target: &JSRef<'a, EventTarget>,
let _ = chain.pop(); let _ = chain.pop();
} }
event.dispatching = false; event.dispatching.deref().set(false);
event.phase = PhaseNone; event.phase.deref().set(PhaseNone);
event.current_target.set(None); event.current_target.set(None);
!event.DefaultPrevented() !event.DefaultPrevented()

View file

@ -89,7 +89,7 @@ impl EventTarget {
pub trait EventTargetHelpers { pub trait EventTargetHelpers {
fn dispatch_event_with_target<'a>(&self, fn dispatch_event_with_target<'a>(&self,
target: Option<JSRef<'a, EventTarget>>, target: Option<JSRef<'a, EventTarget>>,
event: &mut JSRef<Event>) -> Fallible<bool>; event: &JSRef<Event>) -> Fallible<bool>;
fn set_inline_event_listener(&mut self, fn set_inline_event_listener(&mut self,
ty: DOMString, ty: DOMString,
listener: Option<EventListener>); listener: Option<EventListener>);
@ -108,8 +108,8 @@ pub trait EventTargetHelpers {
impl<'a> EventTargetHelpers for JSRef<'a, EventTarget> { impl<'a> EventTargetHelpers for JSRef<'a, EventTarget> {
fn dispatch_event_with_target<'b>(&self, fn dispatch_event_with_target<'b>(&self,
target: Option<JSRef<'b, EventTarget>>, target: Option<JSRef<'b, EventTarget>>,
event: &mut JSRef<Event>) -> Fallible<bool> { event: &JSRef<Event>) -> Fallible<bool> {
if event.deref().dispatching || !event.deref().initialized { if event.deref().dispatching.deref().get() || !event.deref().initialized.deref().get() {
return Err(InvalidState); return Err(InvalidState);
} }
Ok(dispatch_event(self, target, event)) Ok(dispatch_event(self, target, event))
@ -210,7 +210,7 @@ pub trait EventTargetMethods {
ty: DOMString, ty: DOMString,
listener: Option<EventListener>, listener: Option<EventListener>,
capture: bool); capture: bool);
fn DispatchEvent(&self, event: &mut JSRef<Event>) -> Fallible<bool>; fn DispatchEvent(&self, event: &JSRef<Event>) -> Fallible<bool>;
} }
impl<'a> EventTargetMethods for JSRef<'a, EventTarget> { impl<'a> EventTargetMethods for JSRef<'a, EventTarget> {
@ -251,7 +251,7 @@ impl<'a> EventTargetMethods for JSRef<'a, EventTarget> {
} }
} }
fn DispatchEvent(&self, event: &mut JSRef<Event>) -> Fallible<bool> { fn DispatchEvent(&self, event: &JSRef<Event>) -> Fallible<bool> {
self.dispatch_event_with_target(None, event) self.dispatch_event_with_target(None, event)
} }
} }

View file

@ -37,13 +37,11 @@ impl ProgressEvent {
pub fn new(window: &JSRef<Window>, type_: DOMString, pub fn new(window: &JSRef<Window>, type_: DOMString,
can_bubble: bool, cancelable: bool, can_bubble: bool, cancelable: bool,
length_computable: bool, loaded: u64, total: u64) -> Temporary<ProgressEvent> { length_computable: bool, loaded: u64, total: u64) -> Temporary<ProgressEvent> {
let mut ev = reflect_dom_object(box ProgressEvent::new_inherited(length_computable, loaded, total), let ev = reflect_dom_object(box ProgressEvent::new_inherited(length_computable, loaded, total),
window, window,
ProgressEventBinding::Wrap).root(); ProgressEventBinding::Wrap).root();
{ let event: &JSRef<Event> = EventCast::from_ref(&*ev);
let event: &mut JSRef<Event> = EventCast::from_mut_ref(&mut *ev);
event.InitEvent(type_, can_bubble, cancelable); event.InitEvent(type_, can_bubble, cancelable);
}
Temporary::from_rooted(&*ev) Temporary::from_rooted(&*ev)
} }
pub fn Constructor(owner: &JSRef<Window>, pub fn Constructor(owner: &JSRef<Window>,

View file

@ -90,7 +90,7 @@ impl<'a> UIEventMethods for JSRef<'a, UIEvent> {
view: Option<JSRef<Window>>, view: Option<JSRef<Window>>,
detail: i32) { detail: i32) {
{ {
let event: &mut JSRef<Event> = EventCast::from_mut_ref(self); let event: &JSRef<Event> = EventCast::from_ref(self);
event.InitEvent(type_, can_bubble, cancelable); event.InitEvent(type_, can_bubble, cancelable);
} }
self.view.assign(view); self.view.assign(view);

View file

@ -638,10 +638,10 @@ impl<'a> PrivateXMLHttpRequestHelpers for JSRef<'a, XMLHttpRequest> {
assert!(self.ready_state != rs) assert!(self.ready_state != rs)
self.ready_state = rs; self.ready_state = rs;
let win = &*self.global.root(); let win = &*self.global.root();
let mut event = let event =
Event::new(win, "readystatechange".to_string(), false, true).root(); Event::new(win, "readystatechange".to_string(), false, true).root();
let target: &JSRef<EventTarget> = EventTargetCast::from_ref(self); let target: &JSRef<EventTarget> = EventTargetCast::from_ref(self);
target.dispatch_event_with_target(None, &mut *event).ok(); target.dispatch_event_with_target(None, &*event).ok();
} }
fn process_partial_response(&mut self, progress: XHRProgress) { fn process_partial_response(&mut self, progress: XHRProgress) {
@ -739,7 +739,7 @@ impl<'a> PrivateXMLHttpRequestHelpers for JSRef<'a, XMLHttpRequest> {
fn dispatch_progress_event(&self, upload: bool, type_: DOMString, loaded: u64, total: Option<u64>) { fn dispatch_progress_event(&self, upload: bool, type_: DOMString, loaded: u64, total: Option<u64>) {
let win = &*self.global.root(); let win = &*self.global.root();
let upload_target = &*self.upload.get().root().unwrap(); let upload_target = &*self.upload.get().root().unwrap();
let mut progressevent = ProgressEvent::new(win, type_, false, false, let progressevent = ProgressEvent::new(win, type_, false, false,
total.is_some(), loaded, total.is_some(), loaded,
total.unwrap_or(0)).root(); total.unwrap_or(0)).root();
let target: &JSRef<EventTarget> = if upload { let target: &JSRef<EventTarget> = if upload {
@ -747,8 +747,8 @@ impl<'a> PrivateXMLHttpRequestHelpers for JSRef<'a, XMLHttpRequest> {
} else { } else {
EventTargetCast::from_ref(self) EventTargetCast::from_ref(self)
}; };
let event: &mut JSRef<Event> = EventCast::from_mut_ref(&mut *progressevent); let event: &JSRef<Event> = EventCast::from_ref(&*progressevent);
target.dispatch_event_with_target(None, &mut *event).ok(); target.dispatch_event_with_target(None, event).ok();
} }
fn dispatch_upload_progress_event(&self, type_: DOMString, partial_load: Option<u64>) { fn dispatch_upload_progress_event(&self, type_: DOMString, partial_load: Option<u64>) {

View file

@ -1033,12 +1033,11 @@ impl ScriptTask {
// We have no concept of a document loader right now, so just dispatch the // We have no concept of a document loader right now, so just dispatch the
// "load" event as soon as we've finished executing all scripts parsed during // "load" event as soon as we've finished executing all scripts parsed during
// the initial load. // the initial load.
let mut event = let event = Event::new(&*window, "load".to_string(), false, false).root();
Event::new(&*window, "load".to_string(), false, false).root();
let doctarget: &JSRef<EventTarget> = EventTargetCast::from_ref(&*document); let doctarget: &JSRef<EventTarget> = EventTargetCast::from_ref(&*document);
let wintarget: &JSRef<EventTarget> = EventTargetCast::from_ref(&*window); let wintarget: &JSRef<EventTarget> = EventTargetCast::from_ref(&*window);
let _ = wintarget.dispatch_event_with_target(Some((*doctarget).clone()), let _ = wintarget.dispatch_event_with_target(Some((*doctarget).clone()),
&mut *event); &*event);
page.fragment_node.assign(fragment.map_or(None, |fragid| page.find_fragment_node(fragid))); page.fragment_node.assign(fragment.map_or(None, |fragid| page.find_fragment_node(fragid)));
@ -1089,12 +1088,14 @@ impl ScriptTask {
Some(mut window) => { Some(mut window) => {
// http://dev.w3.org/csswg/cssom-view/#resizing-viewports // http://dev.w3.org/csswg/cssom-view/#resizing-viewports
// https://dvcs.w3.org/hg/dom3events/raw-file/tip/html/DOM3-Events.html#event-type-resize // https://dvcs.w3.org/hg/dom3events/raw-file/tip/html/DOM3-Events.html#event-type-resize
let mut uievent = UIEvent::new(&window.clone(), "resize".to_string(), false, false, let uievent = UIEvent::new(&window.clone(),
Some((*window).clone()), 0i32).root(); "resize".to_string(), false,
let event: &mut JSRef<Event> = EventCast::from_mut_ref(&mut *uievent); false, Some(window.clone()),
0i32).root();
let event: &JSRef<Event> = EventCast::from_ref(&*uievent);
let wintarget: &mut JSRef<EventTarget> = EventTargetCast::from_mut_ref(&mut *window); let wintarget: &mut JSRef<EventTarget> = EventTargetCast::from_mut_ref(&mut *window);
let _ = wintarget.dispatch_event_with_target(None, &mut *event); let _ = wintarget.dispatch_event_with_target(None, event);
} }
None => () None => ()
} }
@ -1129,12 +1130,12 @@ impl ScriptTask {
match *page.frame() { match *page.frame() {
Some(ref frame) => { Some(ref frame) => {
let window = frame.window.root(); let window = frame.window.root();
let mut event = let event =
Event::new(&*window, Event::new(&*window,
"click".to_string(), "click".to_string(),
true, true).root(); true, true).root();
let eventtarget: &JSRef<EventTarget> = EventTargetCast::from_ref(&node); let eventtarget: &JSRef<EventTarget> = EventTargetCast::from_ref(&node);
let _ = eventtarget.dispatch_event_with_target(None, &mut *event); let _ = eventtarget.dispatch_event_with_target(None, &*event);
} }
None => {} None => {}
} }