From 0b364d13b6f4eeffbaca66559016b44d26581b8f Mon Sep 17 00:00:00 2001 From: Ms2ger Date: Tue, 10 Jun 2014 13:45:14 +0200 Subject: [PATCH 01/13] Use internal mutability for Event. --- src/components/script/dom/customevent.rs | 2 +- src/components/script/dom/event.rs | 107 ++++++++++--------- src/components/script/dom/eventdispatcher.rs | 50 ++++----- src/components/script/dom/eventtarget.rs | 10 +- src/components/script/dom/progressevent.rs | 12 +-- src/components/script/dom/uievent.rs | 2 +- src/components/script/dom/xmlhttprequest.rs | 14 +-- src/components/script/script_task.rs | 19 ++-- 8 files changed, 105 insertions(+), 111 deletions(-) diff --git a/src/components/script/dom/customevent.rs b/src/components/script/dom/customevent.rs index f528f8861f4..4e391cfd06c 100644 --- a/src/components/script/dom/customevent.rs +++ b/src/components/script/dom/customevent.rs @@ -70,7 +70,7 @@ impl<'a> CustomEventMethods for JSRef<'a, CustomEvent> { cancelable: bool, detail: JSVal) { self.detail = Traceable::new(detail); - let event: &mut JSRef = EventCast::from_mut_ref(self); + let event: &JSRef = EventCast::from_ref(self); event.InitEvent(type_, can_bubble, cancelable); } } diff --git a/src/components/script/dom/event.rs b/src/components/script/dom/event.rs index 8bb636c0f82..a151aed5026 100644 --- a/src/components/script/dom/event.rs +++ b/src/components/script/dom/event.rs @@ -4,14 +4,15 @@ use dom::bindings::codegen::Bindings::EventBinding; 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::js::{JS, JSRef, Temporary}; +use dom::bindings::trace::Untraceable; +use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::eventtarget::EventTarget; use dom::window::Window; use servo_util::str::DOMString; use servo_util::geometry::PagePx; -use std::cell::Cell; +use std::cell::{Cell, RefCell}; use geom::point::Point2D; use geom::size::TypedSize2D; @@ -51,16 +52,16 @@ pub struct Event { pub reflector_: Reflector, pub current_target: Cell>>, pub target: Cell>>, - pub type_: DOMString, - pub phase: EventPhase, - pub canceled: bool, - pub stop_propagation: bool, - pub stop_immediate: bool, - pub cancelable: bool, - pub bubbles: bool, - pub trusted: bool, - pub dispatching: bool, - pub initialized: bool, + type_: Untraceable>, + pub phase: Untraceable>, + pub canceled: Untraceable>, + pub stop_propagation: Untraceable>, + pub stop_immediate: Untraceable>, + pub cancelable: Untraceable>, + pub bubbles: Untraceable>, + pub trusted: Untraceable>, + pub dispatching: Untraceable>, + pub initialized: Untraceable>, pub timestamp: u64, } @@ -71,16 +72,16 @@ impl Event { reflector_: Reflector::new(), current_target: Cell::new(None), target: Cell::new(None), - phase: PhaseNone, - type_: "".to_string(), - canceled: false, - cancelable: true, - bubbles: false, - trusted: false, - dispatching: false, - stop_propagation: false, - stop_immediate: false, - initialized: false, + phase: Untraceable::new(Cell::new(PhaseNone)), + type_: Untraceable::new(RefCell::new("".to_string())), + canceled: Untraceable::new(Cell::new(false)), + cancelable: Untraceable::new(Cell::new(true)), + bubbles: Untraceable::new(Cell::new(false)), + trusted: Untraceable::new(Cell::new(false)), + dispatching: Untraceable::new(Cell::new(false)), + stop_propagation: Untraceable::new(Cell::new(false)), + stop_immediate: Untraceable::new(Cell::new(false)), + initialized: Untraceable::new(Cell::new(false)), timestamp: time::get_time().sec as u64, } } @@ -95,8 +96,8 @@ impl Event { type_: DOMString, can_bubble: bool, cancelable: bool) -> Temporary { - let mut event = Event::new_uninitialized(window).root(); - event.InitEvent(type_, can_bubble, cancelable); + let event = Event::new_uninitialized(window).root(); + event.deref().InitEvent(type_, can_bubble, cancelable); Temporary::from_rooted(&*event) } @@ -113,23 +114,23 @@ pub trait EventMethods { fn GetTarget(&self) -> Option>; fn GetCurrentTarget(&self) -> Option>; fn DefaultPrevented(&self) -> bool; - fn PreventDefault(&mut self); - fn StopPropagation(&mut self); - fn StopImmediatePropagation(&mut self); + fn PreventDefault(&self); + fn StopPropagation(&self); + fn StopImmediatePropagation(&self); fn Bubbles(&self) -> bool; fn Cancelable(&self) -> bool; 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; } impl<'a> EventMethods for JSRef<'a, Event> { fn EventPhase(&self) -> u16 { - self.phase as u16 + self.phase.deref().get() as u16 } fn Type(&self) -> DOMString { - self.type_.clone() + self.type_.deref().borrow().clone() } fn GetTarget(&self) -> Option> { @@ -141,56 +142,56 @@ impl<'a> EventMethods for JSRef<'a, Event> { } fn DefaultPrevented(&self) -> bool { - self.canceled + self.canceled.deref().get() } - fn PreventDefault(&mut self) { - if self.cancelable { - self.canceled = true + fn PreventDefault(&self) { + if self.cancelable.deref().get() { + self.canceled.deref().set(true) } } - fn StopPropagation(&mut self) { - self.stop_propagation = true; + fn StopPropagation(&self) { + self.stop_propagation.deref().set(true); } - fn StopImmediatePropagation(&mut self) { - self.stop_immediate = true; - self.stop_propagation = true; + fn StopImmediatePropagation(&self) { + self.stop_immediate.deref().set(true); + self.stop_propagation.deref().set(true); } fn Bubbles(&self) -> bool { - self.bubbles + self.bubbles.deref().get() } fn Cancelable(&self) -> bool { - self.cancelable + self.cancelable.deref().get() } fn TimeStamp(&self) -> u64 { self.timestamp } - fn InitEvent(&mut self, + fn InitEvent(&self, type_: DOMString, bubbles: bool, cancelable: bool) { - self.initialized = true; - if self.dispatching { + self.initialized.deref().set(true); + if self.dispatching.deref().get() { return; } - self.stop_propagation = false; - self.stop_immediate = false; - self.canceled = false; - self.trusted = false; + self.stop_propagation.deref().set(false); + self.stop_immediate.deref().set(false); + self.canceled.deref().set(false); + self.trusted.deref().set(false); self.target.set(None); - self.type_ = type_; - self.bubbles = bubbles; - self.cancelable = cancelable; + *self.type_.deref().borrow_mut() = type_; + self.bubbles.deref().set(bubbles); + self.cancelable.deref().set(cancelable); } fn IsTrusted(&self) -> bool { - self.trusted + self.trusted.deref().get() } } diff --git a/src/components/script/dom/eventdispatcher.rs b/src/components/script/dom/eventdispatcher.rs index 83a716c4c07..6dd3d20213d 100644 --- a/src/components/script/dom/eventdispatcher.rs +++ b/src/components/script/dom/eventdispatcher.rs @@ -13,19 +13,16 @@ use dom::virtualmethods::vtable_for; // See http://dom.spec.whatwg.org/#concept-event-dispatch for the full dispatch algorithm pub fn dispatch_event<'a, 'b>(target: &JSRef<'a, EventTarget>, pseudo_target: Option>, - event: &mut JSRef) -> bool { - assert!(!event.deref().dispatching); + event: &JSRef) -> bool { + assert!(!event.deref().dispatching.deref().get()); - { - let event = event.deref_mut(); - event.target.assign(Some(match pseudo_target { - Some(pseudo_target) => pseudo_target, - None => target.clone(), - })); - event.dispatching = true; - } + event.target.assign(Some(match pseudo_target { + Some(pseudo_target) => pseudo_target, + None => target.clone(), + })); + event.dispatching.deref().set(true); - let type_ = event.deref().type_.clone(); + let type_ = event.Type(); //TODO: no chain if not participating in a tree let mut chain: Vec> = if target.deref().is_node() { @@ -38,7 +35,7 @@ pub fn dispatch_event<'a, 'b>(target: &JSRef<'a, EventTarget>, vec!() }; - event.deref_mut().phase = PhaseCapturing; + event.deref().phase.deref().set(PhaseCapturing); //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. let _ = listener.HandleEvent_(&**cur_target, event, ReportExceptions); - if event.deref().stop_immediate { + if event.deref().stop_immediate.deref().get() { break; } } - event.deref().stop_propagation + event.deref().stop_propagation.deref().get() } None => false }; @@ -67,12 +64,9 @@ pub fn dispatch_event<'a, 'b>(target: &JSRef<'a, EventTarget>, } /* at target */ - if !event.deref().stop_propagation { - { - let event = event.deref_mut(); - event.phase = PhaseAtTarget; - event.current_target.assign(Some(target.clone())); - } + if !event.deref().stop_propagation.deref().get() { + event.phase.deref().set(PhaseAtTarget); + event.current_target.assign(Some(target.clone())); let opt_listeners = target.deref().get_listeners(type_.as_slice()); 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. let _ = listener.HandleEvent_(target, event, ReportExceptions); - if event.deref().stop_immediate { + if event.deref().stop_immediate.deref().get() { break; } } @@ -88,23 +82,23 @@ pub fn dispatch_event<'a, 'b>(target: &JSRef<'a, EventTarget>, } /* bubbling */ - if event.deref().bubbles && !event.deref().stop_propagation { - event.deref_mut().phase = PhaseBubbling; + if event.deref().bubbles.deref().get() && !event.deref().stop_propagation.deref().get() { + event.deref().phase.deref().set(PhaseBubbling); for cur_target in chain.iter() { let stopped = match cur_target.deref().get_listeners_for(type_.as_slice(), Bubbling) { 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() { // Explicitly drop any exception on the floor. let _ = listener.HandleEvent_(&**cur_target, event, ReportExceptions); - if event.deref().stop_immediate { + if event.deref().stop_immediate.deref().get() { break; } } - event.deref().stop_propagation + event.deref().stop_propagation.deref().get() } None => false }; @@ -136,8 +130,8 @@ pub fn dispatch_event<'a, 'b>(target: &JSRef<'a, EventTarget>, let _ = chain.pop(); } - event.dispatching = false; - event.phase = PhaseNone; + event.dispatching.deref().set(false); + event.phase.deref().set(PhaseNone); event.current_target.set(None); !event.DefaultPrevented() diff --git a/src/components/script/dom/eventtarget.rs b/src/components/script/dom/eventtarget.rs index 5c144056ca6..185913be1dd 100644 --- a/src/components/script/dom/eventtarget.rs +++ b/src/components/script/dom/eventtarget.rs @@ -89,7 +89,7 @@ impl EventTarget { pub trait EventTargetHelpers { fn dispatch_event_with_target<'a>(&self, target: Option>, - event: &mut JSRef) -> Fallible; + event: &JSRef) -> Fallible; fn set_inline_event_listener(&mut self, ty: DOMString, listener: Option); @@ -108,8 +108,8 @@ pub trait EventTargetHelpers { impl<'a> EventTargetHelpers for JSRef<'a, EventTarget> { fn dispatch_event_with_target<'b>(&self, target: Option>, - event: &mut JSRef) -> Fallible { - if event.deref().dispatching || !event.deref().initialized { + event: &JSRef) -> Fallible { + if event.deref().dispatching.deref().get() || !event.deref().initialized.deref().get() { return Err(InvalidState); } Ok(dispatch_event(self, target, event)) @@ -210,7 +210,7 @@ pub trait EventTargetMethods { ty: DOMString, listener: Option, capture: bool); - fn DispatchEvent(&self, event: &mut JSRef) -> Fallible; + fn DispatchEvent(&self, event: &JSRef) -> Fallible; } impl<'a> EventTargetMethods for JSRef<'a, EventTarget> { @@ -251,7 +251,7 @@ impl<'a> EventTargetMethods for JSRef<'a, EventTarget> { } } - fn DispatchEvent(&self, event: &mut JSRef) -> Fallible { + fn DispatchEvent(&self, event: &JSRef) -> Fallible { self.dispatch_event_with_target(None, event) } } diff --git a/src/components/script/dom/progressevent.rs b/src/components/script/dom/progressevent.rs index b5dde42efe9..7cc06d0a115 100644 --- a/src/components/script/dom/progressevent.rs +++ b/src/components/script/dom/progressevent.rs @@ -37,13 +37,11 @@ impl ProgressEvent { pub fn new(window: &JSRef, type_: DOMString, can_bubble: bool, cancelable: bool, length_computable: bool, loaded: u64, total: u64) -> Temporary { - let mut ev = reflect_dom_object(box ProgressEvent::new_inherited(length_computable, loaded, total), - window, - ProgressEventBinding::Wrap).root(); - { - let event: &mut JSRef = EventCast::from_mut_ref(&mut *ev); - event.InitEvent(type_, can_bubble, cancelable); - } + let ev = reflect_dom_object(box ProgressEvent::new_inherited(length_computable, loaded, total), + window, + ProgressEventBinding::Wrap).root(); + let event: &JSRef = EventCast::from_ref(&*ev); + event.InitEvent(type_, can_bubble, cancelable); Temporary::from_rooted(&*ev) } pub fn Constructor(owner: &JSRef, diff --git a/src/components/script/dom/uievent.rs b/src/components/script/dom/uievent.rs index 226c4090dcd..ea2328cb8f9 100644 --- a/src/components/script/dom/uievent.rs +++ b/src/components/script/dom/uievent.rs @@ -90,7 +90,7 @@ impl<'a> UIEventMethods for JSRef<'a, UIEvent> { view: Option>, detail: i32) { { - let event: &mut JSRef = EventCast::from_mut_ref(self); + let event: &JSRef = EventCast::from_ref(self); event.InitEvent(type_, can_bubble, cancelable); } self.view.assign(view); diff --git a/src/components/script/dom/xmlhttprequest.rs b/src/components/script/dom/xmlhttprequest.rs index cc99bb4ea88..e780e03ae77 100644 --- a/src/components/script/dom/xmlhttprequest.rs +++ b/src/components/script/dom/xmlhttprequest.rs @@ -638,10 +638,10 @@ impl<'a> PrivateXMLHttpRequestHelpers for JSRef<'a, XMLHttpRequest> { assert!(self.ready_state != rs) self.ready_state = rs; let win = &*self.global.root(); - let mut event = + let event = Event::new(win, "readystatechange".to_string(), false, true).root(); let target: &JSRef = 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) { @@ -739,16 +739,16 @@ impl<'a> PrivateXMLHttpRequestHelpers for JSRef<'a, XMLHttpRequest> { fn dispatch_progress_event(&self, upload: bool, type_: DOMString, loaded: u64, total: Option) { let win = &*self.global.root(); let upload_target = &*self.upload.get().root().unwrap(); - let mut progressevent = ProgressEvent::new(win, type_, false, false, - total.is_some(), loaded, - total.unwrap_or(0)).root(); + let progressevent = ProgressEvent::new(win, type_, false, false, + total.is_some(), loaded, + total.unwrap_or(0)).root(); let target: &JSRef = if upload { EventTargetCast::from_ref(upload_target) } else { EventTargetCast::from_ref(self) }; - let event: &mut JSRef = EventCast::from_mut_ref(&mut *progressevent); - target.dispatch_event_with_target(None, &mut *event).ok(); + let event: &JSRef = EventCast::from_ref(&*progressevent); + target.dispatch_event_with_target(None, event).ok(); } fn dispatch_upload_progress_event(&self, type_: DOMString, partial_load: Option) { diff --git a/src/components/script/script_task.rs b/src/components/script/script_task.rs index c733f6acaf9..df1a0a3bd96 100644 --- a/src/components/script/script_task.rs +++ b/src/components/script/script_task.rs @@ -1033,12 +1033,11 @@ impl ScriptTask { // 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 // the initial load. - let mut event = - Event::new(&*window, "load".to_string(), false, false).root(); + let event = Event::new(&*window, "load".to_string(), false, false).root(); let doctarget: &JSRef = EventTargetCast::from_ref(&*document); let wintarget: &JSRef = EventTargetCast::from_ref(&*window); 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))); @@ -1089,12 +1088,14 @@ impl ScriptTask { Some(mut window) => { // 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 - let mut uievent = UIEvent::new(&window.clone(), "resize".to_string(), false, false, - Some((*window).clone()), 0i32).root(); - let event: &mut JSRef = EventCast::from_mut_ref(&mut *uievent); + let uievent = UIEvent::new(&window.clone(), + "resize".to_string(), false, + false, Some(window.clone()), + 0i32).root(); + let event: &JSRef = EventCast::from_ref(&*uievent); let wintarget: &mut JSRef = EventTargetCast::from_mut_ref(&mut *window); - let _ = wintarget.dispatch_event_with_target(None, &mut *event); + let _ = wintarget.dispatch_event_with_target(None, event); } None => () } @@ -1129,12 +1130,12 @@ impl ScriptTask { match *page.frame() { Some(ref frame) => { let window = frame.window.root(); - let mut event = + let event = Event::new(&*window, "click".to_string(), true, true).root(); let eventtarget: &JSRef = EventTargetCast::from_ref(&node); - let _ = eventtarget.dispatch_event_with_target(None, &mut *event); + let _ = eventtarget.dispatch_event_with_target(None, &*event); } None => {} } From 781299aaa69ae40ebefa27a36309e2d558314f77 Mon Sep 17 00:00:00 2001 From: Ms2ger Date: Tue, 10 Jun 2014 16:03:53 +0200 Subject: [PATCH 02/13] Use internal mutability for CustomEvent. --- src/components/script/dom/customevent.rs | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/components/script/dom/customevent.rs b/src/components/script/dom/customevent.rs index 4e391cfd06c..9abd64b215e 100644 --- a/src/components/script/dom/customevent.rs +++ b/src/components/script/dom/customevent.rs @@ -14,10 +14,12 @@ use js::jsapi::JSContext; use js::jsval::{JSVal, NullValue}; use servo_util::str::DOMString; +use std::cell::Cell; + #[deriving(Encodable)] pub struct CustomEvent { event: Event, - detail: Traceable + detail: Traceable>>, } impl CustomEventDerived for Event { @@ -28,7 +30,7 @@ impl CustomEventDerived for Event { pub trait CustomEventMethods { fn Detail(&self, _cx: *mut JSContext) -> JSVal; - fn InitCustomEvent(&mut self, _cx: *mut JSContext, + fn InitCustomEvent(&self, _cx: *mut JSContext, type_: DOMString, can_bubble: bool, cancelable: bool, detail: JSVal); } @@ -37,7 +39,7 @@ impl CustomEvent { pub fn new_inherited(type_id: EventTypeId) -> CustomEvent { CustomEvent { event: Event::new_inherited(type_id), - detail: Traceable::new(NullValue()) + detail: Traceable::new(Cell::new(Traceable::new(NullValue()))), } } @@ -47,8 +49,8 @@ impl CustomEvent { CustomEventBinding::Wrap) } pub fn new(window: &JSRef, type_: DOMString, bubbles: bool, cancelable: bool, detail: JSVal) -> Temporary { - let mut ev = CustomEvent::new_uninitialized(window).root(); - ev.InitCustomEvent(window.deref().get_cx(), type_, bubbles, cancelable, detail); + let ev = CustomEvent::new_uninitialized(window).root(); + ev.deref().InitCustomEvent(window.deref().get_cx(), type_, bubbles, cancelable, detail); Temporary::from_rooted(&*ev) } pub fn Constructor(owner: &JSRef, @@ -60,16 +62,16 @@ impl CustomEvent { impl<'a> CustomEventMethods for JSRef<'a, CustomEvent> { fn Detail(&self, _cx: *mut JSContext) -> JSVal { - self.detail.deref().clone() + *self.detail.deref().get() } - fn InitCustomEvent(&mut self, - _cx: *mut JSContext, + fn InitCustomEvent(&self, + _cx: *mut JSContext, type_: DOMString, can_bubble: bool, cancelable: bool, detail: JSVal) { - self.detail = Traceable::new(detail); + self.detail.deref().set(Traceable::new(detail)); let event: &JSRef = EventCast::from_ref(self); event.InitEvent(type_, can_bubble, cancelable); } From 2aefa3f8055fcb31c34553623b6da6fd15fe9cb0 Mon Sep 17 00:00:00 2001 From: Ms2ger Date: Tue, 10 Jun 2014 16:13:00 +0200 Subject: [PATCH 03/13] Use internal mutability for UIEvent. --- src/components/script/dom/uievent.rs | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/src/components/script/dom/uievent.rs b/src/components/script/dom/uievent.rs index ea2328cb8f9..91a4cbd24e3 100644 --- a/src/components/script/dom/uievent.rs +++ b/src/components/script/dom/uievent.rs @@ -4,8 +4,9 @@ use dom::bindings::codegen::Bindings::UIEventBinding; use dom::bindings::codegen::InheritTypes::{EventCast, UIEventDerived}; -use dom::bindings::js::{JS, JSRef, RootedReference, Temporary, OptionalSettable}; use dom::bindings::error::Fallible; +use dom::bindings::js::{JS, JSRef, RootedReference, Temporary, OptionalSettable}; +use dom::bindings::trace::Untraceable; use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::event::{Event, EventMethods, EventTypeId, UIEventTypeId}; use dom::window::Window; @@ -18,7 +19,7 @@ use std::cell::Cell; pub struct UIEvent { pub event: Event, pub view: Cell>>, - pub detail: i32 + pub detail: Untraceable> } impl UIEventDerived for Event { @@ -32,7 +33,7 @@ impl UIEvent { UIEvent { event: Event::new_inherited(type_id), view: Cell::new(None), - detail: 0 + detail: Untraceable::new(Cell::new(0)), } } @@ -48,8 +49,8 @@ impl UIEvent { cancelable: bool, view: Option>, detail: i32) -> Temporary { - let mut ev = UIEvent::new_uninitialized(window).root(); - ev.InitUIEvent(type_, can_bubble, cancelable, view, detail); + let ev = UIEvent::new_uninitialized(window).root(); + ev.deref().InitUIEvent(type_, can_bubble, cancelable, view, detail); Temporary::from_rooted(&*ev) } @@ -66,7 +67,7 @@ impl UIEvent { pub trait UIEventMethods { fn GetView(&self) -> Option>; fn Detail(&self) -> i32; - fn InitUIEvent(&mut self, + fn InitUIEvent(&self, type_: DOMString, can_bubble: bool, cancelable: bool, @@ -80,21 +81,19 @@ impl<'a> UIEventMethods for JSRef<'a, UIEvent> { } fn Detail(&self) -> i32 { - self.detail + self.detail.deref().get() } - fn InitUIEvent(&mut self, + fn InitUIEvent(&self, type_: DOMString, can_bubble: bool, cancelable: bool, view: Option>, detail: i32) { - { - let event: &JSRef = EventCast::from_ref(self); - event.InitEvent(type_, can_bubble, cancelable); - } + let event: &JSRef = EventCast::from_ref(self); + event.InitEvent(type_, can_bubble, cancelable); self.view.assign(view); - self.detail = detail; + self.detail.deref().set(detail); } } From 9acba1477cbfdbc280ed0d6423443f4a37f5168c Mon Sep 17 00:00:00 2001 From: Ms2ger Date: Tue, 10 Jun 2014 14:03:04 +0200 Subject: [PATCH 04/13] Use internal mutability for EventTarget. --- src/components/script/dom/document.rs | 12 +-- src/components/script/dom/eventtarget.rs | 98 +++++++++++-------- src/components/script/dom/htmlbodyelement.rs | 7 +- src/components/script/dom/htmlelement.rs | 18 ++-- src/components/script/dom/window.rs | 24 ++--- src/components/script/dom/xmlhttprequest.rs | 8 +- .../script/dom/xmlhttprequesteventtarget.rs | 42 ++++---- src/components/script/script_task.rs | 2 +- 8 files changed, 113 insertions(+), 98 deletions(-) diff --git a/src/components/script/dom/document.rs b/src/components/script/dom/document.rs index 3a0fa2e7f3b..1830936e6bd 100644 --- a/src/components/script/dom/document.rs +++ b/src/components/script/dom/document.rs @@ -331,9 +331,9 @@ pub trait DocumentMethods { fn Children(&self) -> Temporary; fn QuerySelector(&self, selectors: DOMString) -> Fallible>>; fn GetOnclick(&self) -> Option; - fn SetOnclick(&mut self, listener: Option); + fn SetOnclick(&self, listener: Option); fn GetOnload(&self) -> Option; - fn SetOnload(&mut self, listener: Option); + fn SetOnload(&self, listener: Option); } impl<'a> DocumentMethods for JSRef<'a, Document> { @@ -826,8 +826,8 @@ impl<'a> DocumentMethods for JSRef<'a, Document> { eventtarget.get_event_handler_common("click") } - fn SetOnclick(&mut self, listener: Option) { - let eventtarget: &mut JSRef = EventTargetCast::from_mut_ref(self); + fn SetOnclick(&self, listener: Option) { + let eventtarget: &JSRef = EventTargetCast::from_ref(self); eventtarget.set_event_handler_common("click", listener) } @@ -836,8 +836,8 @@ impl<'a> DocumentMethods for JSRef<'a, Document> { eventtarget.get_event_handler_common("load") } - fn SetOnload(&mut self, listener: Option) { - let eventtarget: &mut JSRef = EventTargetCast::from_mut_ref(self); + fn SetOnload(&self, listener: Option) { + let eventtarget: &JSRef = EventTargetCast::from_ref(self); eventtarget.set_event_handler_common("load", listener) } } diff --git a/src/components/script/dom/eventtarget.rs b/src/components/script/dom/eventtarget.rs index 185913be1dd..7a192d58ab6 100644 --- a/src/components/script/dom/eventtarget.rs +++ b/src/components/script/dom/eventtarget.rs @@ -7,6 +7,7 @@ use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull; use dom::bindings::codegen::Bindings::EventListenerBinding::EventListener; use dom::bindings::error::{Fallible, InvalidState}; use dom::bindings::js::JSRef; +use dom::bindings::trace::Traceable; use dom::bindings::utils::{Reflectable, Reflector}; use dom::event::Event; use dom::eventdispatcher::dispatch_event; @@ -17,6 +18,7 @@ use js::jsapi::{JS_CompileUCFunction, JS_GetFunctionObject, JS_CloneFunctionObje use js::jsapi::{JSContext, JSObject}; use servo_util::str::DOMString; use libc::{c_char, size_t}; +use std::cell::RefCell; use std::ptr; use url::Url; @@ -59,7 +61,7 @@ pub struct EventListenerEntry { pub struct EventTarget { pub type_id: EventTargetTypeId, pub reflector_: Reflector, - pub handlers: HashMap>, + handlers: Traceable>>>, } impl EventTarget { @@ -67,19 +69,19 @@ impl EventTarget { EventTarget { type_id: type_id, reflector_: Reflector::new(), - handlers: HashMap::new(), + handlers: Traceable::new(RefCell::new(HashMap::new())), } } pub fn get_listeners(&self, type_: &str) -> Option> { - self.handlers.find_equiv(&type_).map(|listeners| { + self.handlers.deref().borrow().find_equiv(&type_).map(|listeners| { listeners.iter().map(|entry| entry.listener.get_listener()).collect() }) } pub fn get_listeners_for(&self, type_: &str, desired_phase: ListenerPhase) -> Option> { - self.handlers.find_equiv(&type_).map(|listeners| { + self.handlers.deref().borrow().find_equiv(&type_).map(|listeners| { let filtered = listeners.iter().filter(|entry| entry.phase == desired_phase); filtered.map(|entry| entry.listener.get_listener()).collect() }) @@ -90,19 +92,21 @@ pub trait EventTargetHelpers { fn dispatch_event_with_target<'a>(&self, target: Option>, event: &JSRef) -> Fallible; - fn set_inline_event_listener(&mut self, + fn set_inline_event_listener(&self, ty: DOMString, listener: Option); fn get_inline_event_listener(&self, ty: DOMString) -> Option; - fn set_event_handler_uncompiled(&mut self, + fn set_event_handler_uncompiled(&self, cx: *mut JSContext, url: Url, scope: *mut JSObject, ty: &str, source: DOMString); - fn set_event_handler_common(&mut self, ty: &str, + fn set_event_handler_common(&self, ty: &str, listener: Option); fn get_event_handler_common(&self, ty: &str) -> Option; + + fn has_handlers(&self) -> bool; } impl<'a> EventTargetHelpers for JSRef<'a, EventTarget> { @@ -115,10 +119,11 @@ impl<'a> EventTargetHelpers for JSRef<'a, EventTarget> { Ok(dispatch_event(self, target, event)) } - fn set_inline_event_listener(&mut self, + fn set_inline_event_listener(&self, ty: DOMString, listener: Option) { - let entries = self.handlers.find_or_insert_with(ty, |_| vec!()); + let mut handlers = self.handlers.deref().borrow_mut(); + let entries = handlers.find_or_insert_with(ty, |_| vec!()); let idx = entries.iter().position(|&entry| { match entry.listener { Inline(_) => true, @@ -147,7 +152,8 @@ impl<'a> EventTargetHelpers for JSRef<'a, EventTarget> { } fn get_inline_event_listener(&self, ty: DOMString) -> Option { - let entries = self.handlers.find(&ty); + let handlers = self.handlers.deref().borrow(); + let entries = handlers.find(&ty); entries.and_then(|entries| entries.iter().find(|entry| { match entry.listener { Inline(_) => true, @@ -156,7 +162,7 @@ impl<'a> EventTargetHelpers for JSRef<'a, EventTarget> { }).map(|entry| entry.listener.get_listener())) } - fn set_event_handler_uncompiled(&mut self, + fn set_event_handler_uncompiled(&self, cx: *mut JSContext, url: Url, scope: *mut JSObject, @@ -188,7 +194,7 @@ impl<'a> EventTargetHelpers for JSRef<'a, EventTarget> { } fn set_event_handler_common( - &mut self, ty: &str, listener: Option) + &self, ty: &str, listener: Option) { let event_listener = listener.map(|listener| EventListener::new(listener.callback())); @@ -199,14 +205,18 @@ impl<'a> EventTargetHelpers for JSRef<'a, EventTarget> { let listener = self.get_inline_event_listener(ty.to_string()); listener.map(|listener| CallbackContainer::new(listener.parent.callback())) } + + fn has_handlers(&self) -> bool { + !self.handlers.deref().borrow().is_empty() + } } pub trait EventTargetMethods { - fn AddEventListener(&mut self, + fn AddEventListener(&self, ty: DOMString, listener: Option, capture: bool); - fn RemoveEventListener(&mut self, + fn RemoveEventListener(&self, ty: DOMString, listener: Option, capture: bool); @@ -214,40 +224,48 @@ pub trait EventTargetMethods { } impl<'a> EventTargetMethods for JSRef<'a, EventTarget> { - fn AddEventListener(&mut self, + fn AddEventListener(&self, ty: DOMString, listener: Option, capture: bool) { - for &listener in listener.iter() { - let entry = self.handlers.find_or_insert_with(ty.clone(), |_| vec!()); - let phase = if capture { Capturing } else { Bubbling }; - let new_entry = EventListenerEntry { - phase: phase, - listener: Additive(listener) - }; - if entry.as_slice().position_elem(&new_entry).is_none() { - entry.push(new_entry); - } - } - } - - fn RemoveEventListener(&mut self, - ty: DOMString, - listener: Option, - capture: bool) { - for &listener in listener.iter() { - let mut entry = self.handlers.find_mut(&ty); - for entry in entry.mut_iter() { + match listener { + Some(listener) => { + let mut handlers = self.handlers.deref().borrow_mut(); + let entry = handlers.find_or_insert_with(ty, |_| vec!()); let phase = if capture { Capturing } else { Bubbling }; - let old_entry = EventListenerEntry { + let new_entry = EventListenerEntry { phase: phase, listener: Additive(listener) }; - let position = entry.as_slice().position_elem(&old_entry); - for &position in position.iter() { - entry.remove(position); + if entry.as_slice().position_elem(&new_entry).is_none() { + entry.push(new_entry); } - } + }, + _ => (), + } + } + + fn RemoveEventListener(&self, + ty: DOMString, + listener: Option, + capture: bool) { + match listener { + Some(listener) => { + let mut handlers = self.handlers.deref().borrow_mut(); + let mut entry = handlers.find_mut(&ty); + for entry in entry.mut_iter() { + let phase = if capture { Capturing } else { Bubbling }; + let old_entry = EventListenerEntry { + phase: phase, + listener: Additive(listener) + }; + let position = entry.as_slice().position_elem(&old_entry); + for &position in position.iter() { + entry.remove(position); + } + } + }, + _ => (), } } diff --git a/src/components/script/dom/htmlbodyelement.rs b/src/components/script/dom/htmlbodyelement.rs index e94f15a8d47..6e82d78fa50 100644 --- a/src/components/script/dom/htmlbodyelement.rs +++ b/src/components/script/dom/htmlbodyelement.rs @@ -80,12 +80,11 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLBodyElement> { let (cx, url, reflector) = (window.get_cx(), window.get_url(), window.reflector().get_jsobject()); - let mut self_alias = self.clone(); - let evtarget: &mut JSRef = + let evtarget: &JSRef = if forwarded_events.iter().any(|&event| name.as_slice() == event) { - EventTargetCast::from_mut_ref(&mut *window) + EventTargetCast::from_ref(&*window) } else { - EventTargetCast::from_mut_ref(&mut self_alias) + EventTargetCast::from_ref(self) }; evtarget.set_event_handler_uncompiled(cx, url, reflector, name.as_slice().slice_from(2), diff --git a/src/components/script/dom/htmlelement.rs b/src/components/script/dom/htmlelement.rs index 29ac184987b..5168b822669 100644 --- a/src/components/script/dom/htmlelement.rs +++ b/src/components/script/dom/htmlelement.rs @@ -59,9 +59,9 @@ impl<'a> PrivateHTMLElementHelpers for JSRef<'a, HTMLElement> { pub trait HTMLElementMethods { fn GetOnclick(&self) -> Option; - fn SetOnclick(&mut self, listener: Option); + fn SetOnclick(&self, listener: Option); fn GetOnload(&self) -> Option; - fn SetOnload(&mut self, listener: Option); + fn SetOnload(&self, listener: Option); } impl<'a> HTMLElementMethods for JSRef<'a, HTMLElement> { @@ -70,8 +70,8 @@ impl<'a> HTMLElementMethods for JSRef<'a, HTMLElement> { eventtarget.get_event_handler_common("click") } - fn SetOnclick(&mut self, listener: Option) { - let eventtarget: &mut JSRef = EventTargetCast::from_mut_ref(self); + fn SetOnclick(&self, listener: Option) { + let eventtarget: &JSRef = EventTargetCast::from_ref(self); eventtarget.set_event_handler_common("click", listener) } @@ -84,10 +84,10 @@ impl<'a> HTMLElementMethods for JSRef<'a, HTMLElement> { } } - fn SetOnload(&mut self, listener: Option) { + fn SetOnload(&self, listener: Option) { if self.is_body_or_frameset() { - let mut win = window_from_node(self).root(); - win.SetOnload(listener) + let win = window_from_node(self).root(); + win.deref().SetOnload(listener) } } } @@ -109,9 +109,7 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLElement> { let (cx, url, reflector) = (window.get_cx(), window.get_url(), window.reflector().get_jsobject()); - let mut self_alias = self.clone(); - let evtarget: &mut JSRef = - EventTargetCast::from_mut_ref(&mut self_alias); + let evtarget: &JSRef = EventTargetCast::from_ref(self); evtarget.set_event_handler_uncompiled(cx, url, reflector, name.as_slice().slice_from(2), value); diff --git a/src/components/script/dom/window.rs b/src/components/script/dom/window.rs index 16e3f39dbba..098d118d3aa 100644 --- a/src/components/script/dom/window.rs +++ b/src/components/script/dom/window.rs @@ -130,13 +130,13 @@ pub trait WindowMethods { fn Self(&self) -> Temporary; fn Performance(&self) -> Temporary; fn GetOnclick(&self) -> Option; - fn SetOnclick(&mut self, listener: Option); + fn SetOnclick(&self, listener: Option); fn GetOnload(&self) -> Option; - fn SetOnload(&mut self, listener: Option); + fn SetOnload(&self, listener: Option); fn GetOnunload(&self) -> Option; - fn SetOnunload(&mut self, listener: Option); + fn SetOnunload(&self, listener: Option); fn GetOnerror(&self) -> Option; - fn SetOnerror(&mut self, listener: Option); + fn SetOnerror(&self, listener: Option); fn Debug(&self, message: DOMString); fn Gc(&self); } @@ -224,8 +224,8 @@ impl<'a> WindowMethods for JSRef<'a, Window> { eventtarget.get_event_handler_common("click") } - fn SetOnclick(&mut self, listener: Option) { - let eventtarget: &mut JSRef = EventTargetCast::from_mut_ref(self); + fn SetOnclick(&self, listener: Option) { + let eventtarget: &JSRef = EventTargetCast::from_ref(self); eventtarget.set_event_handler_common("click", listener) } @@ -234,8 +234,8 @@ impl<'a> WindowMethods for JSRef<'a, Window> { eventtarget.get_event_handler_common("load") } - fn SetOnload(&mut self, listener: Option) { - let eventtarget: &mut JSRef = EventTargetCast::from_mut_ref(self); + fn SetOnload(&self, listener: Option) { + let eventtarget: &JSRef = EventTargetCast::from_ref(self); eventtarget.set_event_handler_common("load", listener) } @@ -244,8 +244,8 @@ impl<'a> WindowMethods for JSRef<'a, Window> { eventtarget.get_event_handler_common("unload") } - fn SetOnunload(&mut self, listener: Option) { - let eventtarget: &mut JSRef = EventTargetCast::from_mut_ref(self); + fn SetOnunload(&self, listener: Option) { + let eventtarget: &JSRef = EventTargetCast::from_ref(self); eventtarget.set_event_handler_common("unload", listener) } @@ -254,8 +254,8 @@ impl<'a> WindowMethods for JSRef<'a, Window> { eventtarget.get_event_handler_common("error") } - fn SetOnerror(&mut self, listener: Option) { - let eventtarget: &mut JSRef = EventTargetCast::from_mut_ref(self); + fn SetOnerror(&self, listener: Option) { + let eventtarget: &JSRef = EventTargetCast::from_ref(self); eventtarget.set_event_handler_common("error", listener) } diff --git a/src/components/script/dom/xmlhttprequest.rs b/src/components/script/dom/xmlhttprequest.rs index e780e03ae77..f3d76acca39 100644 --- a/src/components/script/dom/xmlhttprequest.rs +++ b/src/components/script/dom/xmlhttprequest.rs @@ -225,7 +225,7 @@ impl XMLHttpRequest { pub trait XMLHttpRequestMethods<'a> { fn GetOnreadystatechange(&self) -> Option; - fn SetOnreadystatechange(&mut self, listener: Option); + fn SetOnreadystatechange(&self, listener: Option); fn ReadyState(&self) -> u16; fn Open(&mut self, _method: ByteString, _url: DOMString) -> ErrorResult; fn Open_(&mut self, _method: ByteString, _url: DOMString, _async: bool, @@ -257,8 +257,8 @@ impl<'a> XMLHttpRequestMethods<'a> for JSRef<'a, XMLHttpRequest> { eventtarget.get_event_handler_common("readystatechange") } - fn SetOnreadystatechange(&mut self, listener: Option) { - let eventtarget: &mut JSRef = EventTargetCast::from_mut_ref(self); + fn SetOnreadystatechange(&self, listener: Option) { + let eventtarget: &JSRef = EventTargetCast::from_ref(self); eventtarget.set_event_handler_common("readystatechange", listener) } @@ -431,7 +431,7 @@ impl<'a> XMLHttpRequestMethods<'a> for JSRef<'a, XMLHttpRequest> { // Step 8 let upload_target = &*self.upload.get().root().unwrap(); let event_target: &JSRef = EventTargetCast::from_ref(upload_target); - if event_target.handlers.iter().len() > 0 { + if event_target.has_handlers() { self.upload_events = true; } diff --git a/src/components/script/dom/xmlhttprequesteventtarget.rs b/src/components/script/dom/xmlhttprequesteventtarget.rs index d64c2af8690..29f77c62149 100644 --- a/src/components/script/dom/xmlhttprequesteventtarget.rs +++ b/src/components/script/dom/xmlhttprequesteventtarget.rs @@ -44,19 +44,19 @@ impl Reflectable for XMLHttpRequestEventTarget { pub trait XMLHttpRequestEventTargetMethods { fn GetOnloadstart(&self) -> Option; - fn SetOnloadstart(&mut self, listener: Option); + fn SetOnloadstart(&self, listener: Option); fn GetOnprogress(&self) -> Option; - fn SetOnprogress(&mut self, listener: Option); + fn SetOnprogress(&self, listener: Option); fn GetOnabort(&self) -> Option; - fn SetOnabort(&mut self, listener: Option); + fn SetOnabort(&self, listener: Option); fn GetOnerror(&self) -> Option; - fn SetOnerror(&mut self, listener: Option); + fn SetOnerror(&self, listener: Option); fn GetOnload(&self) -> Option; - fn SetOnload(&mut self, listener: Option); + fn SetOnload(&self, listener: Option); fn GetOntimeout(&self) -> Option; - fn SetOntimeout(&mut self, listener: Option); + fn SetOntimeout(&self, listener: Option); fn GetOnloadend(&self) -> Option; - fn SetOnloadend(&mut self, listener: Option); + fn SetOnloadend(&self, listener: Option); } impl<'a> XMLHttpRequestEventTargetMethods for JSRef<'a, XMLHttpRequestEventTarget> { @@ -65,8 +65,8 @@ impl<'a> XMLHttpRequestEventTargetMethods for JSRef<'a, XMLHttpRequestEventTarge eventtarget.get_event_handler_common("loadstart") } - fn SetOnloadstart(&mut self, listener: Option) { - let eventtarget: &mut JSRef = EventTargetCast::from_mut_ref(self); + fn SetOnloadstart(&self, listener: Option) { + let eventtarget: &JSRef = EventTargetCast::from_ref(self); eventtarget.set_event_handler_common("loadstart", listener) } @@ -75,8 +75,8 @@ impl<'a> XMLHttpRequestEventTargetMethods for JSRef<'a, XMLHttpRequestEventTarge eventtarget.get_event_handler_common("progress") } - fn SetOnprogress(&mut self, listener: Option) { - let eventtarget: &mut JSRef = EventTargetCast::from_mut_ref(self); + fn SetOnprogress(&self, listener: Option) { + let eventtarget: &JSRef = EventTargetCast::from_ref(self); eventtarget.set_event_handler_common("progress", listener) } @@ -85,8 +85,8 @@ impl<'a> XMLHttpRequestEventTargetMethods for JSRef<'a, XMLHttpRequestEventTarge eventtarget.get_event_handler_common("abort") } - fn SetOnabort(&mut self, listener: Option) { - let eventtarget: &mut JSRef = EventTargetCast::from_mut_ref(self); + fn SetOnabort(&self, listener: Option) { + let eventtarget: &JSRef = EventTargetCast::from_ref(self); eventtarget.set_event_handler_common("abort", listener) } @@ -95,8 +95,8 @@ impl<'a> XMLHttpRequestEventTargetMethods for JSRef<'a, XMLHttpRequestEventTarge eventtarget.get_event_handler_common("error") } - fn SetOnerror(&mut self, listener: Option) { - let eventtarget: &mut JSRef = EventTargetCast::from_mut_ref(self); + fn SetOnerror(&self, listener: Option) { + let eventtarget: &JSRef = EventTargetCast::from_ref(self); eventtarget.set_event_handler_common("error", listener) } @@ -105,8 +105,8 @@ impl<'a> XMLHttpRequestEventTargetMethods for JSRef<'a, XMLHttpRequestEventTarge eventtarget.get_event_handler_common("load") } - fn SetOnload(&mut self, listener: Option) { - let eventtarget: &mut JSRef = EventTargetCast::from_mut_ref(self); + fn SetOnload(&self, listener: Option) { + let eventtarget: &JSRef = EventTargetCast::from_ref(self); eventtarget.set_event_handler_common("load", listener) } @@ -115,8 +115,8 @@ impl<'a> XMLHttpRequestEventTargetMethods for JSRef<'a, XMLHttpRequestEventTarge eventtarget.get_event_handler_common("timeout") } - fn SetOntimeout(&mut self, listener: Option) { - let eventtarget: &mut JSRef = EventTargetCast::from_mut_ref(self); + fn SetOntimeout(&self, listener: Option) { + let eventtarget: &JSRef = EventTargetCast::from_ref(self); eventtarget.set_event_handler_common("timeout", listener) } @@ -125,8 +125,8 @@ impl<'a> XMLHttpRequestEventTargetMethods for JSRef<'a, XMLHttpRequestEventTarge eventtarget.get_event_handler_common("loadend") } - fn SetOnloadend(&mut self, listener: Option) { - let eventtarget: &mut JSRef = EventTargetCast::from_mut_ref(self); + fn SetOnloadend(&self, listener: Option) { + let eventtarget: &JSRef = EventTargetCast::from_ref(self); eventtarget.set_event_handler_common("loadend", listener) } } diff --git a/src/components/script/script_task.rs b/src/components/script/script_task.rs index df1a0a3bd96..73ad372b4d4 100644 --- a/src/components/script/script_task.rs +++ b/src/components/script/script_task.rs @@ -1094,7 +1094,7 @@ impl ScriptTask { 0i32).root(); let event: &JSRef = EventCast::from_ref(&*uievent); - let wintarget: &mut JSRef = EventTargetCast::from_mut_ref(&mut *window); + let wintarget: &JSRef = EventTargetCast::from_ref(&*window); let _ = wintarget.dispatch_event_with_target(None, event); } None => () From bb0cbb0a746aff66a6288df66caf55d995a017c2 Mon Sep 17 00:00:00 2001 From: Ms2ger Date: Tue, 10 Jun 2014 14:11:49 +0200 Subject: [PATCH 05/13] Use internal mutability for HTMLIFrameElement. --- src/components/main/layout/wrapper.rs | 2 +- src/components/script/dom/htmliframeelement.rs | 11 +++++------ 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/components/main/layout/wrapper.rs b/src/components/main/layout/wrapper.rs index fdda4115744..cabf046a17d 100644 --- a/src/components/main/layout/wrapper.rs +++ b/src/components/main/layout/wrapper.rs @@ -112,7 +112,7 @@ pub trait TLayoutNode { fail!("not an iframe element!") } let iframe_element: JS = self.get_jsmanaged().transmute_copy(); - let size = (*iframe_element.unsafe_get()).size.unwrap(); + let size = (*iframe_element.unsafe_get()).size.deref().get().unwrap(); (size.pipeline_id, size.subpage_id) } } diff --git a/src/components/script/dom/htmliframeelement.rs b/src/components/script/dom/htmliframeelement.rs index 8adc17d25a0..d747d0c179a 100644 --- a/src/components/script/dom/htmliframeelement.rs +++ b/src/components/script/dom/htmliframeelement.rs @@ -39,7 +39,7 @@ enum SandboxAllowance { #[deriving(Encodable)] pub struct HTMLIFrameElement { pub htmlelement: HTMLElement, - pub size: Option, + pub size: Traceable>>, pub sandbox: Traceable>>, } @@ -79,7 +79,7 @@ impl HTMLIFrameElement { pub fn new_inherited(localName: DOMString, document: &JSRef) -> HTMLIFrameElement { HTMLIFrameElement { htmlelement: HTMLElement::new_inherited(HTMLIFrameElementTypeId, localName, document), - size: None, + size: Traceable::new(Cell::new(None)), sandbox: Traceable::new(Cell::new(None)), } } @@ -120,7 +120,7 @@ impl<'a> HTMLIFrameElementMethods for JSRef<'a, HTMLIFrameElement> { } fn GetContentWindow(&self) -> Option> { - self.size.and_then(|size| { + self.size.deref().get().and_then(|size| { let window = window_from_node(self).root(); let children = &*window.deref().page.children.deref().borrow(); let child = children.iter().find(|child| { @@ -194,11 +194,10 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLIFrameElement> { let page = window.deref().page(); let subpage_id = page.get_next_subpage_id(); - let mut self_alias = self.clone(); - self_alias.deref_mut().size = Some(IFrameSize { + self.deref().size.deref().set(Some(IFrameSize { pipeline_id: page.id, subpage_id: subpage_id, - }); + })); let ConstellationChan(ref chan) = *page.constellation_chan.deref(); chan.send(LoadIframeUrlMsg(url, page.id, subpage_id, sandboxed)); From 6df6a7d51246307dddc314861a7e1e31963018b2 Mon Sep 17 00:00:00 2001 From: Ms2ger Date: Tue, 10 Jun 2014 14:26:28 +0200 Subject: [PATCH 06/13] Use internal mutability for Node.flags. --- src/components/script/dom/node.rs | 31 ++++++++++++++-------------- src/components/script/script_task.rs | 6 +++--- 2 files changed, 18 insertions(+), 19 deletions(-) diff --git a/src/components/script/dom/node.rs b/src/components/script/dom/node.rs index 775a330ab55..181c99fe686 100644 --- a/src/components/script/dom/node.rs +++ b/src/components/script/dom/node.rs @@ -11,12 +11,13 @@ use dom::bindings::codegen::InheritTypes::{ElementCast, TextCast, NodeCast, Elem use dom::bindings::codegen::InheritTypes::{CharacterDataCast, NodeBase, NodeDerived}; use dom::bindings::codegen::InheritTypes::{ProcessingInstructionCast, EventTargetCast}; use dom::bindings::codegen::Bindings::NodeBinding::NodeConstants; +use dom::bindings::error::{ErrorResult, Fallible, NotFound, HierarchyRequest, Syntax}; use dom::bindings::js::{JS, JSRef, RootedReference, Temporary, Root, OptionalUnrootable}; use dom::bindings::js::{OptionalSettable, TemporaryPushable, OptionalRootedRootable}; use dom::bindings::js::{ResultRootable, OptionalRootable}; -use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; -use dom::bindings::error::{ErrorResult, Fallible, NotFound, HierarchyRequest, Syntax}; +use dom::bindings::trace::Untraceable; use dom::bindings::utils; +use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::characterdata::{CharacterData, CharacterDataMethods}; use dom::comment::Comment; use dom::document::{Document, DocumentMethods, DocumentHelpers, HTMLDocument, NonHTMLDocument}; @@ -86,7 +87,7 @@ pub struct Node { pub child_list: Cell>>, /// A bitfield of flags for node items. - flags: NodeFlags, + flags: Untraceable>, /// Layout information. Only the layout task may touch this data. /// @@ -382,7 +383,7 @@ pub trait NodeHelpers { fn is_anchor_element(&self) -> bool; fn get_hover_state(&self) -> bool; - fn set_hover_state(&mut self, state: bool); + fn set_hover_state(&self, state: bool); fn dump(&self); fn dump_indent(&self, indent: uint); @@ -430,7 +431,7 @@ impl<'a> NodeHelpers for JSRef<'a, Node> { } fn is_in_doc(&self) -> bool { - self.deref().flags.contains(IsInDoc) + self.deref().flags.deref().borrow().contains(IsInDoc) } /// Returns the type ID of this node. Fails if this node is borrowed mutably. @@ -489,14 +490,14 @@ impl<'a> NodeHelpers for JSRef<'a, Node> { } fn get_hover_state(&self) -> bool { - self.flags.contains(InHoverState) + self.flags.deref().borrow().contains(InHoverState) } - fn set_hover_state(&mut self, state: bool) { + fn set_hover_state(&self, state: bool) { if state { - self.flags.insert(InHoverState); + self.flags.deref().borrow_mut().insert(InHoverState); } else { - self.flags.remove(InHoverState); + self.flags.deref().borrow_mut().remove(InHoverState); } } @@ -706,7 +707,7 @@ pub trait RawLayoutNodeHelpers { impl RawLayoutNodeHelpers for Node { unsafe fn get_hover_state_for_layout(&self) -> bool { - self.flags.contains(InHoverState) + self.flags.deref().borrow().contains(InHoverState) } } @@ -916,7 +917,7 @@ impl Node { owner_doc: Cell::new(doc.unrooted()), child_list: Cell::new(None), - flags: NodeFlags::new(type_id), + flags: Untraceable::new(RefCell::new(NodeFlags::new(type_id))), layout_data: LayoutDataRef::new(), } @@ -1110,9 +1111,9 @@ impl Node { for node in nodes.mut_iter() { parent.add_child(node, child); if parent.is_in_doc() { - node.flags.insert(IsInDoc); + node.flags.deref().borrow_mut().insert(IsInDoc); } else { - node.flags.remove(IsInDoc); + node.flags.deref().borrow_mut().remove(IsInDoc); } } @@ -1197,9 +1198,7 @@ impl Node { // Step 8. parent.remove_child(node); - // FIXME(2513): remove this `node_alias` when in fix mozilla#2513 - let mut node_alias = node.clone(); - node_alias.deref_mut().flags.remove(IsInDoc); + node.deref().flags.deref().borrow_mut().remove(IsInDoc); // Step 9. match suppress_observers { diff --git a/src/components/script/script_task.rs b/src/components/script/script_task.rs index 73ad372b4d4..878d67dd3f5 100644 --- a/src/components/script/script_task.rs +++ b/src/components/script/script_task.rs @@ -1161,8 +1161,8 @@ impl ScriptTask { match *mouse_over_targets { Some(ref mut mouse_over_targets) => { for node in mouse_over_targets.mut_iter() { - let mut node = node.root(); - node.set_hover_state(false); + let node = node.root(); + node.deref().set_hover_state(false); } } None => {} @@ -1176,7 +1176,7 @@ impl ScriptTask { let maybe_node = temp_node.root().ancestors().find(|node| node.is_element()); match maybe_node { - Some(mut node) => { + Some(node) => { node.set_hover_state(true); match *mouse_over_targets { From d230077f9f269d8f46af07004dd659496f701044 Mon Sep 17 00:00:00 2001 From: Ms2ger Date: Tue, 10 Jun 2014 14:46:43 +0200 Subject: [PATCH 07/13] Stop mutating Element::namespace. --- src/components/script/dom/document.rs | 4 ++-- src/components/script/dom/node.rs | 17 ++++++----------- .../script/html/hubbub_html_parser.rs | 18 ++++++++++++++---- 3 files changed, 22 insertions(+), 17 deletions(-) diff --git a/src/components/script/dom/document.rs b/src/components/script/dom/document.rs index 1830936e6bd..d28dc78ea55 100644 --- a/src/components/script/dom/document.rs +++ b/src/components/script/dom/document.rs @@ -430,7 +430,7 @@ impl<'a> DocumentMethods for JSRef<'a, Document> { return Err(InvalidCharacter); } let local_name = local_name.as_slice().to_ascii_lower(); - Ok(build_element_from_tag(local_name, self)) + Ok(build_element_from_tag(local_name, namespace::HTML, self)) } // http://dom.spec.whatwg.org/#dom-document-createelementns @@ -473,7 +473,7 @@ impl<'a> DocumentMethods for JSRef<'a, Document> { } if ns == namespace::HTML { - Ok(build_element_from_tag(local_name_from_qname, self)) + Ok(build_element_from_tag(local_name_from_qname, ns, self)) } else { Ok(Element::new(local_name_from_qname, ns, prefix_from_qname, self)) } diff --git a/src/components/script/dom/node.rs b/src/components/script/dom/node.rs index 181c99fe686..4a021abd582 100644 --- a/src/components/script/dom/node.rs +++ b/src/components/script/dom/node.rs @@ -1252,7 +1252,8 @@ impl Node { ElementNodeTypeId(..) => { let element: &JSRef = ElementCast::to_ref(node).unwrap(); let element = element.deref(); - let element = build_element_from_tag(element.local_name.clone(), &*document); + let element = build_element_from_tag(element.local_name.clone(), + element.namespace.clone(), &*document); NodeCast::from_temporary(element) }, TextNodeTypeId => { @@ -1289,22 +1290,16 @@ impl Node { }, ElementNodeTypeId(..) => { let node_elem: &JSRef = ElementCast::to_ref(node).unwrap(); - let node_elem = node_elem.deref(); - let copy_elem: &mut JSRef = ElementCast::to_mut_ref(&mut *copy).unwrap(); + let copy_elem: &JSRef = ElementCast::to_ref(&*copy).unwrap(); - // XXX: to avoid double borrowing compile error. we might be able to fix this after #1854 - let copy_elem_alias = copy_elem.clone(); - - let copy_elem = copy_elem.deref_mut(); // FIXME: https://github.com/mozilla/servo/issues/1737 - copy_elem.namespace = node_elem.namespace.clone(); let window = document.deref().window.root(); - for attr in node_elem.attrs.borrow().iter().map(|attr| attr.root()) { - copy_elem.attrs.borrow_mut().push_unrooted( + for attr in node_elem.deref().attrs.borrow().iter().map(|attr| attr.root()) { + copy_elem.deref().attrs.borrow_mut().push_unrooted( &Attr::new(&*window, attr.deref().local_name.clone(), attr.deref().value.clone(), attr.deref().name.clone(), attr.deref().namespace.clone(), - attr.deref().prefix.clone(), ©_elem_alias)); + attr.deref().prefix.clone(), copy_elem)); } }, _ => () diff --git a/src/components/script/html/hubbub_html_parser.rs b/src/components/script/html/hubbub_html_parser.rs index fac27f299b1..23247341325 100644 --- a/src/components/script/html/hubbub_html_parser.rs +++ b/src/components/script/html/hubbub_html_parser.rs @@ -17,10 +17,10 @@ use html::cssparse::{StylesheetProvenance, UrlProvenance, spawn_css_parser}; use script_task::Page; use hubbub::hubbub; -use hubbub::hubbub::{NullNs, XLinkNs, XmlNs, XmlNsNs}; +use hubbub::hubbub::{NullNs, HtmlNs, MathMlNs, SvgNs, XLinkNs, XmlNs, XmlNsNs}; use servo_net::resource_task::{Load, LoadData, Payload, Done, ResourceTask, load_whole_resource}; use servo_util::namespace; -use servo_util::namespace::Null; +use servo_util::namespace::{Namespace, Null}; use servo_util::str::{DOMString, HTML_SPACE_CHARACTERS}; use servo_util::task::spawn_named; use servo_util::url::parse_url; @@ -158,7 +158,11 @@ fn js_script_listener(to_parent: Sender, // Silly macros to handle constructing DOM nodes. This produces bad code and should be optimized // via atomization (issue #85). -pub fn build_element_from_tag(tag: DOMString, document: &JSRef) -> Temporary { +pub fn build_element_from_tag(tag: DOMString, ns: Namespace, document: &JSRef) -> Temporary { + if ns != namespace::HTML { + return Element::new(tag, ns, None, document); + } + // TODO (Issue #85): use atoms handle_element!(document, tag, "a", HTMLAnchorElement); handle_element!(document, tag, "abbr", HTMLElement); @@ -369,7 +373,13 @@ pub fn parse_html(page: &Page, // NOTE: tmp vars are workaround for lifetime issues. Both required. let tmp_borrow = doc_cell.borrow(); let tmp = &*tmp_borrow; - let mut element: Root = build_element_from_tag(tag.name.clone(), *tmp).root(); + let namespace = match tag.ns { + HtmlNs => namespace::HTML, + MathMlNs => namespace::MathML, + SvgNs => namespace::SVG, + ns => fail!("Not expecting namespace {:?}", ns), + }; + let mut element: Root = build_element_from_tag(tag.name.clone(), namespace, *tmp).root(); debug!("-- attach attrs"); for attr in tag.attributes.iter() { From 288e0bc877aa09a95f440c603eddbaf166e8f592 Mon Sep 17 00:00:00 2001 From: Ms2ger Date: Tue, 10 Jun 2014 15:07:33 +0200 Subject: [PATCH 08/13] Use internal mutability for CharacterData::data. --- src/components/main/layout/wrapper.rs | 6 +-- src/components/script/dom/characterdata.rs | 47 ++++++++++--------- src/components/script/dom/document.rs | 2 +- src/components/script/dom/htmlserializer.rs | 12 ++--- src/components/script/dom/node.rs | 18 ++++--- .../script/html/hubbub_html_parser.rs | 6 +-- 6 files changed, 46 insertions(+), 45 deletions(-) diff --git a/src/components/main/layout/wrapper.rs b/src/components/main/layout/wrapper.rs index cabf046a17d..73dd2483a71 100644 --- a/src/components/main/layout/wrapper.rs +++ b/src/components/main/layout/wrapper.rs @@ -188,7 +188,7 @@ impl<'ln> TLayoutNode for LayoutNode<'ln> { fail!("not text!") } let text: JS = self.get_jsmanaged().transmute_copy(); - (*text.unsafe_get()).characterdata.data.to_str() + (*text.unsafe_get()).characterdata.data.deref().borrow().clone() } } } @@ -494,7 +494,7 @@ impl<'ln> TLayoutNode for ThreadSafeLayoutNode<'ln> { fail!("not text!") } let text: JS = self.get_jsmanaged().transmute_copy(); - (*text.unsafe_get()).characterdata.data.to_str() + (*text.unsafe_get()).characterdata.data.deref().borrow().clone() } } } @@ -636,7 +636,7 @@ impl<'ln> ThreadSafeLayoutNode<'ln> { Some(TextNodeTypeId) => { unsafe { let text: JS = self.get_jsmanaged().transmute_copy(); - if !is_whitespace((*text.unsafe_get()).characterdata.data.as_slice()) { + if !is_whitespace((*text.unsafe_get()).characterdata.data.deref().borrow().as_slice()) { return false } diff --git a/src/components/script/dom/characterdata.rs b/src/components/script/dom/characterdata.rs index c4fe6700a3a..309c4de1cd5 100644 --- a/src/components/script/dom/characterdata.rs +++ b/src/components/script/dom/characterdata.rs @@ -5,18 +5,21 @@ //! DOM bindings for `CharacterData`. use dom::bindings::codegen::InheritTypes::{CharacterDataDerived, NodeCast}; -use dom::bindings::js::JSRef; use dom::bindings::error::{Fallible, ErrorResult, IndexSize}; +use dom::bindings::js::JSRef; +use dom::bindings::trace::Untraceable; use dom::bindings::utils::{Reflectable, Reflector}; use dom::document::Document; use dom::eventtarget::{EventTarget, NodeTargetTypeId}; use dom::node::{CommentNodeTypeId, Node, NodeTypeId, TextNodeTypeId, ProcessingInstructionNodeTypeId, NodeHelpers}; use servo_util::str::DOMString; +use std::cell::RefCell; + #[deriving(Encodable)] pub struct CharacterData { pub node: Node, - pub data: DOMString, + pub data: Untraceable>, } impl CharacterDataDerived for EventTarget { @@ -34,56 +37,56 @@ impl CharacterData { pub fn new_inherited(id: NodeTypeId, data: DOMString, document: &JSRef) -> CharacterData { CharacterData { node: Node::new_inherited(id, document), - data: data + data: Untraceable::new(RefCell::new(data)), } } } pub trait CharacterDataMethods { fn Data(&self) -> DOMString; - fn SetData(&mut self, arg: DOMString) -> ErrorResult; + fn SetData(&self, arg: DOMString) -> ErrorResult; fn Length(&self) -> u32; fn SubstringData(&self, offset: u32, count: u32) -> Fallible; - fn AppendData(&mut self, arg: DOMString) -> ErrorResult; - fn InsertData(&mut self, _offset: u32, _arg: DOMString) -> ErrorResult; - fn DeleteData(&mut self, _offset: u32, _count: u32) -> ErrorResult; - fn ReplaceData(&mut self, _offset: u32, _count: u32, _arg: DOMString) -> ErrorResult; + fn AppendData(&self, arg: DOMString) -> ErrorResult; + fn InsertData(&self, _offset: u32, _arg: DOMString) -> ErrorResult; + fn DeleteData(&self, _offset: u32, _count: u32) -> ErrorResult; + fn ReplaceData(&self, _offset: u32, _count: u32, _arg: DOMString) -> ErrorResult; fn Remove(&self); } impl<'a> CharacterDataMethods for JSRef<'a, CharacterData> { fn Data(&self) -> DOMString { - self.data.clone() + self.data.deref().borrow().clone() } - fn SetData(&mut self, arg: DOMString) -> ErrorResult { - self.data = arg; + fn SetData(&self, arg: DOMString) -> ErrorResult { + *self.data.deref().borrow_mut() = arg; Ok(()) } fn Length(&self) -> u32 { - self.data.len() as u32 + self.data.deref().borrow().len() as u32 } fn SubstringData(&self, offset: u32, count: u32) -> Fallible { - Ok(self.data.as_slice().slice(offset as uint, count as uint).to_str()) + Ok(self.data.deref().borrow().as_slice().slice(offset as uint, count as uint).to_string()) } - fn AppendData(&mut self, arg: DOMString) -> ErrorResult { - self.data.push_str(arg.as_slice()); + fn AppendData(&self, arg: DOMString) -> ErrorResult { + self.data.deref().borrow_mut().push_str(arg.as_slice()); Ok(()) } - fn InsertData(&mut self, offset: u32, arg: DOMString) -> ErrorResult { + fn InsertData(&self, offset: u32, arg: DOMString) -> ErrorResult { self.ReplaceData(offset, 0, arg) } - fn DeleteData(&mut self, offset: u32, count: u32) -> ErrorResult { + fn DeleteData(&self, offset: u32, count: u32) -> ErrorResult { self.ReplaceData(offset, count, "".to_string()) } - fn ReplaceData(&mut self, offset: u32, count: u32, arg: DOMString) -> ErrorResult { - let length = self.data.len() as u32; + fn ReplaceData(&self, offset: u32, count: u32, arg: DOMString) -> ErrorResult { + let length = self.data.deref().borrow().len() as u32; if offset > length { return Err(IndexSize); } @@ -92,10 +95,10 @@ impl<'a> CharacterDataMethods for JSRef<'a, CharacterData> { } else { count }; - let mut data = self.data.as_slice().slice(0, offset as uint).to_string(); + let mut data = self.data.deref().borrow().as_slice().slice(0, offset as uint).to_string(); data.push_str(arg.as_slice()); - data.push_str(self.data.as_slice().slice((offset + count) as uint, length as uint)); - self.data = data.into_owned(); + data.push_str(self.data.deref().borrow().as_slice().slice((offset + count) as uint, length as uint)); + *self.data.deref().borrow_mut() = data.into_owned(); // FIXME: Once we have `Range`, we should implement step7 to step11 Ok(()) } diff --git a/src/components/script/dom/document.rs b/src/components/script/dom/document.rs index d28dc78ea55..87ca5c6c4c1 100644 --- a/src/components/script/dom/document.rs +++ b/src/components/script/dom/document.rs @@ -567,7 +567,7 @@ impl<'a> DocumentMethods for JSRef<'a, Document> { for child in title_elem.children() { if child.is_text() { let text: &JSRef = TextCast::to_ref(&child).unwrap(); - title.push_str(text.deref().characterdata.data.as_slice()); + title.push_str(text.deref().characterdata.data.deref().borrow().as_slice()); } } }); diff --git a/src/components/script/dom/htmlserializer.rs b/src/components/script/dom/htmlserializer.rs index a1c6d709a47..bb0364672d0 100644 --- a/src/components/script/dom/htmlserializer.rs +++ b/src/components/script/dom/htmlserializer.rs @@ -67,7 +67,7 @@ pub fn serialize(iterator: &mut NodeIterator) -> String { fn serialize_comment(comment: &JSRef, html: &mut String) { html.push_str(""); } @@ -80,11 +80,11 @@ fn serialize_text(text: &JSRef, html: &mut String) { "style" | "script" | "xmp" | "iframe" | "noembed" | "noframes" | "plaintext" | "noscript" if elem.deref().namespace == namespace::HTML - => html.push_str(text.deref().characterdata.data.as_slice()), - _ => escape(text.deref().characterdata.data.as_slice(), false, html) + => html.push_str(text.deref().characterdata.data.deref().borrow().as_slice()), + _ => escape(text.deref().characterdata.data.deref().borrow().as_slice(), false, html) } } - _ => escape(text.deref().characterdata.data.as_slice(), false, html) + _ => escape(text.deref().characterdata.data.deref().borrow().as_slice(), false, html) } } @@ -93,7 +93,7 @@ fn serialize_processing_instruction(processing_instruction: &JSRef"); } @@ -118,7 +118,7 @@ fn serialize_elem(elem: &JSRef, open_elements: &mut Vec, html: match node.first_child().map(|child| child.root()) { Some(ref child) if child.is_text() => { let text: &JSRef = CharacterDataCast::to_ref(&**child).unwrap(); - if text.deref().data.len() > 0 && text.deref().data.as_slice().char_at(0) == '\n' { + if text.deref().data.deref().borrow().len() > 0 && text.deref().data.deref().borrow().as_slice().char_at(0) == '\n' { html.push_char('\x0A'); } }, diff --git a/src/components/script/dom/node.rs b/src/components/script/dom/node.rs index 4a021abd582..323ae5a1c14 100644 --- a/src/components/script/dom/node.rs +++ b/src/components/script/dom/node.rs @@ -1235,7 +1235,7 @@ impl Node { CommentNodeTypeId => { let comment: &JSRef = CommentCast::to_ref(node).unwrap(); let comment = comment.deref(); - let comment = Comment::new(comment.characterdata.data.clone(), &*document); + let comment = Comment::new(comment.characterdata.data.deref().borrow().clone(), &*document); NodeCast::from_temporary(comment) }, DocumentNodeTypeId => { @@ -1259,14 +1259,14 @@ impl Node { TextNodeTypeId => { let text: &JSRef = TextCast::to_ref(node).unwrap(); let text = text.deref(); - let text = Text::new(text.characterdata.data.clone(), &*document); + let text = Text::new(text.characterdata.data.deref().borrow().clone(), &*document); NodeCast::from_temporary(text) }, ProcessingInstructionNodeTypeId => { let pi: &JSRef = ProcessingInstructionCast::to_ref(node).unwrap(); let pi = pi.deref(); let pi = ProcessingInstruction::new(pi.target.clone(), - pi.characterdata.data.clone(), &*document); + pi.characterdata.data.deref().borrow().clone(), &*document); NodeCast::from_temporary(pi) }, }.root(); @@ -1514,7 +1514,7 @@ impl<'a> NodeMethods for JSRef<'a, Node> { for node in self.traverse_preorder() { if node.is_text() { let text: &JSRef = TextCast::to_ref(&node).unwrap(); - content.push_str(text.deref().characterdata.data.as_slice()); + content.push_str(text.deref().characterdata.data.deref().borrow().as_slice()); } } Some(content.into_owned()) @@ -1555,10 +1555,8 @@ impl<'a> NodeMethods for JSRef<'a, Node> { ProcessingInstructionNodeTypeId => { self.wait_until_safe_to_modify_dom(); - { - let characterdata: &mut JSRef = CharacterDataCast::to_mut_ref(self).unwrap(); - characterdata.deref_mut().data = value; - } + let characterdata: &JSRef = CharacterDataCast::to_ref(self).unwrap(); + *characterdata.data.deref().borrow_mut() = value; // Notify the document that the content of this node is different let document = self.owner_doc().root(); @@ -1772,12 +1770,12 @@ impl<'a> NodeMethods for JSRef<'a, Node> { let pi: &JSRef = ProcessingInstructionCast::to_ref(node).unwrap(); let other_pi: &JSRef = ProcessingInstructionCast::to_ref(other).unwrap(); (pi.deref().target == other_pi.deref().target) && - (pi.deref().characterdata.data == other_pi.deref().characterdata.data) + (*pi.deref().characterdata.data.deref().borrow() == *other_pi.deref().characterdata.data.deref().borrow()) } fn is_equal_characterdata(node: &JSRef, other: &JSRef) -> bool { let characterdata: &JSRef = CharacterDataCast::to_ref(node).unwrap(); let other_characterdata: &JSRef = CharacterDataCast::to_ref(other).unwrap(); - characterdata.deref().data == other_characterdata.deref().data + *characterdata.deref().data.deref().borrow() == *other_characterdata.deref().data.deref().borrow() } fn is_equal_element_attrs(node: &JSRef, other: &JSRef) -> bool { let element: &JSRef = ElementCast::to_ref(node).unwrap(); diff --git a/src/components/script/html/hubbub_html_parser.rs b/src/components/script/html/hubbub_html_parser.rs index 23247341325..c7629958d33 100644 --- a/src/components/script/html/hubbub_html_parser.rs +++ b/src/components/script/html/hubbub_html_parser.rs @@ -506,17 +506,17 @@ pub fn parse_html(page: &Page, js_chan2.send(JSTaskNewFile(new_url)); } None => { - let mut data = vec!(); + let mut data = String::new(); let scriptnode: &JSRef = NodeCast::from_ref(script); debug!("iterating over children {:?}", scriptnode.first_child()); for child in scriptnode.children() { debug!("child = {:?}", child); let text: &JSRef = TextCast::to_ref(&child).unwrap(); - data.push(text.deref().characterdata.data.to_str()); // FIXME: Bad copy. + data.push_str(text.deref().characterdata.data.deref().borrow().as_slice()); } debug!("script data = {:?}", data); - js_chan2.send(JSTaskNewInlineScript(data.concat(), url3.clone())); + js_chan2.send(JSTaskNewInlineScript(data, url3.clone())); } } } From 07c67a1d5a1aacd5422b4f1968b6e103e75a9d0a Mon Sep 17 00:00:00 2001 From: Ms2ger Date: Tue, 10 Jun 2014 15:10:10 +0200 Subject: [PATCH 09/13] Use internal mutability for Window::browser_context. --- src/components/script/dom/bindings/utils.rs | 2 +- src/components/script/dom/window.rs | 12 ++++++------ src/components/script/script_task.rs | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/components/script/dom/bindings/utils.rs b/src/components/script/dom/bindings/utils.rs index c91169ad9b0..99c90007846 100644 --- a/src/components/script/dom/bindings/utils.rs +++ b/src/components/script/dom/bindings/utils.rs @@ -632,7 +632,7 @@ pub extern fn outerize_global(_cx: *mut JSContext, obj: JSHandleObject) -> *mut IDLInterface::get_prototype_depth(None::)) .unwrap() .root(); - win.deref().browser_context.get_ref().window_proxy() + win.deref().browser_context.deref().borrow().get_ref().window_proxy() } } diff --git a/src/components/script/dom/window.rs b/src/components/script/dom/window.rs index 098d118d3aa..7a25aac3761 100644 --- a/src/components/script/dom/window.rs +++ b/src/components/script/dom/window.rs @@ -29,7 +29,7 @@ use js::jsapi::{JS_GC, JS_GetRuntime}; use js::jsval::JSVal; use collections::hashmap::HashMap; -use std::cell::Cell; +use std::cell::{Cell, RefCell}; use std::cmp; use std::comm::{channel, Sender}; use std::comm::Select; @@ -76,7 +76,7 @@ pub struct Window { pub active_timers: Box>, pub next_timer_handle: i32, pub compositor: Untraceable>, - pub browser_context: Option, + pub browser_context: Traceable>>, pub page: Rc, pub performance: Cell>>, pub navigationStart: u64, @@ -283,7 +283,7 @@ impl Reflectable for Window { pub trait WindowHelpers { fn damage_and_reflow(&self, damage: DocumentDamageLevel); fn wait_until_safe_to_modify_dom(&self); - fn init_browser_context(&mut self, doc: &JSRef); + fn init_browser_context(&self, doc: &JSRef); fn load_url(&self, href: DOMString); } @@ -306,8 +306,8 @@ impl<'a> WindowHelpers for JSRef<'a, Window> { self.page().join_layout(); } - fn init_browser_context(&mut self, doc: &JSRef) { - self.browser_context = Some(BrowserContext::new(doc)); + fn init_browser_context(&self, doc: &JSRef) { + *self.browser_context.deref().borrow_mut() = Some(BrowserContext::new(doc)); } /// Commence a new URL load which will either replace this window or scroll to a fragment. @@ -402,7 +402,7 @@ impl Window { image_cache_task: image_cache_task, active_timers: box HashMap::new(), next_timer_handle: 0, - browser_context: None, + browser_context: Traceable::new(RefCell::new(None)), performance: Cell::new(None), navigationStart: time::get_time().sec as u64, navigationStartPrecise: time::precise_time_s(), diff --git a/src/components/script/script_task.rs b/src/components/script/script_task.rs index 878d67dd3f5..1b7fc2d1241 100644 --- a/src/components/script/script_task.rs +++ b/src/components/script/script_task.rs @@ -952,7 +952,7 @@ impl ScriptTask { self.compositor.dup(), self.image_cache_task.clone()).root(); let mut document = Document::new(&*window, Some(url.clone()), HTMLDocument, None).root(); - window.deref_mut().init_browser_context(&*document); + window.deref().init_browser_context(&*document); with_compartment((**cx).ptr, window.reflector().get_jsobject(), || { let mut js_info = page.mut_js_info(); From e9b64dc361db2b068a0079e599ad0725c2eb8a0c Mon Sep 17 00:00:00 2001 From: Ms2ger Date: Tue, 10 Jun 2014 15:20:01 +0200 Subject: [PATCH 10/13] Use internal mutability for Window::{active_timers, next_timer_handle}. --- src/components/script/dom/window.rs | 41 ++++++++++++++-------------- src/components/script/script_task.rs | 32 ++++++++++------------ 2 files changed, 35 insertions(+), 38 deletions(-) diff --git a/src/components/script/dom/window.rs b/src/components/script/dom/window.rs index 7a25aac3761..f6036ef9aec 100644 --- a/src/components/script/dom/window.rs +++ b/src/components/script/dom/window.rs @@ -73,8 +73,8 @@ pub struct Window { pub location: Cell>>, pub navigator: Cell>>, pub image_cache_task: ImageCacheTask, - pub active_timers: Box>, - pub next_timer_handle: i32, + pub active_timers: Traceable>>, + pub next_timer_handle: Untraceable>, pub compositor: Untraceable>, pub browser_context: Traceable>>, pub page: Rc, @@ -100,7 +100,7 @@ impl Window { #[unsafe_destructor] impl Drop for Window { fn drop(&mut self) { - for (_, timer_handle) in self.active_timers.mut_iter() { + for (_, timer_handle) in self.active_timers.borrow_mut().mut_iter() { timer_handle.cancel(); } } @@ -122,10 +122,10 @@ pub trait WindowMethods { fn Location(&self) -> Temporary; fn Console(&self) -> Temporary; fn Navigator(&self) -> Temporary; - fn SetTimeout(&mut self, _cx: *mut JSContext, callback: JSVal, timeout: i32) -> i32; - fn ClearTimeout(&mut self, handle: i32); - fn SetInterval(&mut self, _cx: *mut JSContext, callback: JSVal, timeout: i32) -> i32; - fn ClearInterval(&mut self, handle: i32); + fn SetTimeout(&self, _cx: *mut JSContext, callback: JSVal, timeout: i32) -> i32; + fn ClearTimeout(&self, handle: i32); + fn SetInterval(&self, _cx: *mut JSContext, callback: JSVal, timeout: i32) -> i32; + fn ClearInterval(&self, handle: i32); fn Window(&self) -> Temporary; fn Self(&self) -> Temporary; fn Performance(&self) -> Temporary; @@ -182,24 +182,25 @@ impl<'a> WindowMethods for JSRef<'a, Window> { Temporary::new(self.navigator.get().get_ref().clone()) } - fn SetTimeout(&mut self, _cx: *mut JSContext, callback: JSVal, timeout: i32) -> i32 { + fn SetTimeout(&self, _cx: *mut JSContext, callback: JSVal, timeout: i32) -> i32 { self.set_timeout_or_interval(callback, timeout, false) } - fn ClearTimeout(&mut self, handle: i32) { - let mut timer_handle = self.active_timers.pop(&TimerId(handle)); + fn ClearTimeout(&self, handle: i32) { + let mut timers = self.active_timers.deref().borrow_mut(); + let mut timer_handle = timers.pop(&TimerId(handle)); match timer_handle { Some(ref mut handle) => handle.cancel(), None => { } } - self.active_timers.remove(&TimerId(handle)); + timers.remove(&TimerId(handle)); } - fn SetInterval(&mut self, _cx: *mut JSContext, callback: JSVal, timeout: i32) -> i32 { + fn SetInterval(&self, _cx: *mut JSContext, callback: JSVal, timeout: i32) -> i32 { self.set_timeout_or_interval(callback, timeout, true) } - fn ClearInterval(&mut self, handle: i32) { + fn ClearInterval(&self, handle: i32) { self.ClearTimeout(handle); } @@ -288,7 +289,7 @@ pub trait WindowHelpers { } trait PrivateWindowHelpers { - fn set_timeout_or_interval(&mut self, callback: JSVal, timeout: i32, is_interval: bool) -> i32; + fn set_timeout_or_interval(&self, callback: JSVal, timeout: i32, is_interval: bool) -> i32; } impl<'a> WindowHelpers for JSRef<'a, Window> { @@ -325,10 +326,10 @@ impl<'a> WindowHelpers for JSRef<'a, Window> { } impl<'a> PrivateWindowHelpers for JSRef<'a, Window> { - fn set_timeout_or_interval(&mut self, callback: JSVal, timeout: i32, is_interval: bool) -> i32 { + fn set_timeout_or_interval(&self, callback: JSVal, timeout: i32, is_interval: bool) -> i32 { let timeout = cmp::max(0, timeout) as u64; - let handle = self.next_timer_handle; - self.next_timer_handle += 1; + let handle = self.next_timer_handle.deref().get(); + self.next_timer_handle.deref().set(handle + 1); // Post a delayed message to the per-window timer task; it will dispatch it // to the relevant script handler that will deal with it. @@ -379,7 +380,7 @@ impl<'a> PrivateWindowHelpers for JSRef<'a, Window> { funval: Traceable::new(callback), } }; - self.active_timers.insert(timer_id, timer); + self.active_timers.deref().borrow_mut().insert(timer_id, timer); handle } } @@ -400,8 +401,8 @@ impl Window { location: Cell::new(None), navigator: Cell::new(None), image_cache_task: image_cache_task, - active_timers: box HashMap::new(), - next_timer_handle: 0, + active_timers: Traceable::new(RefCell::new(HashMap::new())), + next_timer_handle: Untraceable::new(Cell::new(0)), browser_context: Traceable::new(RefCell::new(None)), performance: Cell::new(None), navigationStart: time::get_time().sec as u64, diff --git a/src/components/script/script_task.rs b/src/components/script/script_task.rs index 1b7fc2d1241..adcbd050ee8 100644 --- a/src/components/script/script_task.rs +++ b/src/components/script/script_task.rs @@ -817,31 +817,27 @@ impl ScriptTask { let page = page.find(id).expect("ScriptTask: received fire timer msg for a pipeline ID not associated with this script task. This is a bug."); let frame = page.frame(); - let mut window = frame.get_ref().window.root(); + let window = frame.get_ref().window.root(); let this_value = window.deref().reflector().get_jsobject(); - let is_interval; - match window.deref().active_timers.find(&timer_id) { + let data = match window.deref().active_timers.deref().borrow().find(&timer_id) { None => return, - Some(timer_handle) => { - // TODO: Support extra arguments. This requires passing a `*JSVal` array as `argv`. - let cx = self.get_cx(); - with_compartment(cx, this_value, || { - let mut rval = NullValue(); - unsafe { - JS_CallFunctionValue(cx, this_value, - *timer_handle.data.funval, - 0, ptr::mut_null(), &mut rval); - } - }); + Some(timer_handle) => timer_handle.data, + }; - is_interval = timer_handle.data.is_interval; + // TODO: Support extra arguments. This requires passing a `*JSVal` array as `argv`. + let cx = self.get_cx(); + with_compartment(cx, this_value, || { + let mut rval = NullValue(); + unsafe { + JS_CallFunctionValue(cx, this_value, *data.funval, + 0, ptr::mut_null(), &mut rval); } - } + }); - if !is_interval { - window.deref_mut().active_timers.remove(&timer_id); + if !data.is_interval { + window.deref().active_timers.deref().borrow_mut().remove(&timer_id); } } From 23a6b6823ba844b97dba7bf29f1c9ea31ba27130 Mon Sep 17 00:00:00 2001 From: Ms2ger Date: Tue, 10 Jun 2014 17:48:42 +0200 Subject: [PATCH 11/13] Use internal mutability for Document::{quirks_mode, encoding_name}. --- src/components/script/dom/document.rs | 28 +++++++++++++-------------- src/components/script/dom/node.rs | 4 ++-- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/components/script/dom/document.rs b/src/components/script/dom/document.rs index 87ca5c6c4c1..13e891ee5cc 100644 --- a/src/components/script/dom/document.rs +++ b/src/components/script/dom/document.rs @@ -49,7 +49,7 @@ use servo_util::str::{DOMString, null_str_as_empty_ref}; use collections::hashmap::HashMap; use js::jsapi::JSContext; use std::ascii::StrAsciiExt; -use std::cell::Cell; +use std::cell::{Cell, RefCell}; use url::{Url, from_str}; #[deriving(Eq,Encodable)] @@ -66,10 +66,10 @@ pub struct Document { pub idmap: HashMap>>, pub implementation: Cell>>, pub content_type: DOMString, - pub encoding_name: DOMString, + pub encoding_name: Untraceable>, pub is_html_document: bool, pub url: Untraceable, - pub quirks_mode: Untraceable, + pub quirks_mode: Untraceable>, } impl DocumentDerived for EventTarget { @@ -81,8 +81,8 @@ impl DocumentDerived for EventTarget { pub trait DocumentHelpers { fn url<'a>(&'a self) -> &'a Url; fn quirks_mode(&self) -> QuirksMode; - fn set_quirks_mode(&mut self, mode: QuirksMode); - fn set_encoding_name(&mut self, name: DOMString); + fn set_quirks_mode(&self, mode: QuirksMode); + fn set_encoding_name(&self, name: DOMString); fn content_changed(&self); fn damage_and_reflow(&self, damage: DocumentDamageLevel); fn wait_until_safe_to_modify_dom(&self); @@ -97,15 +97,15 @@ impl<'a> DocumentHelpers for JSRef<'a, Document> { } fn quirks_mode(&self) -> QuirksMode { - *self.quirks_mode + self.quirks_mode.deref().get() } - fn set_quirks_mode(&mut self, mode: QuirksMode) { - *self.quirks_mode = mode; + fn set_quirks_mode(&self, mode: QuirksMode) { + self.quirks_mode.deref().set(mode); } - fn set_encoding_name(&mut self, name: DOMString) { - self.encoding_name = name; + fn set_encoding_name(&self, name: DOMString) { + *self.encoding_name.deref().borrow_mut() = name; } fn content_changed(&self) { @@ -227,9 +227,9 @@ impl Document { }, url: Untraceable::new(url), // http://dom.spec.whatwg.org/#concept-document-quirks - quirks_mode: Untraceable::new(NoQuirks), + quirks_mode: Untraceable::new(Cell::new(NoQuirks)), // http://dom.spec.whatwg.org/#concept-document-encoding - encoding_name: "utf-8".to_string(), + encoding_name: Untraceable::new(RefCell::new("utf-8".to_string())), is_html_document: is_html_document == HTMLDocument, } } @@ -358,7 +358,7 @@ impl<'a> DocumentMethods for JSRef<'a, Document> { // http://dom.spec.whatwg.org/#dom-document-compatmode fn CompatMode(&self) -> DOMString { - match *self.quirks_mode { + match self.quirks_mode.deref().get() { NoQuirks => "CSS1Compat".to_string(), LimitedQuirks | FullQuirks => "BackCompat".to_string() } @@ -366,7 +366,7 @@ impl<'a> DocumentMethods for JSRef<'a, Document> { // http://dom.spec.whatwg.org/#dom-document-characterset fn CharacterSet(&self) -> DOMString { - self.encoding_name.as_slice().to_ascii_lower() + self.encoding_name.deref().borrow().as_slice().to_ascii_lower() } // http://dom.spec.whatwg.org/#dom-document-content_type diff --git a/src/components/script/dom/node.rs b/src/components/script/dom/node.rs index 323ae5a1c14..a3d2132f601 100644 --- a/src/components/script/dom/node.rs +++ b/src/components/script/dom/node.rs @@ -1284,8 +1284,8 @@ impl Node { match node.type_id() { DocumentNodeTypeId => { let node_doc: &JSRef = DocumentCast::to_ref(node).unwrap(); - let copy_doc: &mut JSRef = DocumentCast::to_mut_ref(&mut *copy).unwrap(); - copy_doc.set_encoding_name(node_doc.encoding_name.clone()); + let copy_doc: &JSRef = DocumentCast::to_ref(&*copy).unwrap(); + copy_doc.set_encoding_name(node_doc.encoding_name.deref().borrow().clone()); copy_doc.set_quirks_mode(node_doc.quirks_mode()); }, ElementNodeTypeId(..) => { From be375de91f1b3ae4366cb12dd2cd103c138d7d8e Mon Sep 17 00:00:00 2001 From: Ms2ger Date: Tue, 10 Jun 2014 19:12:16 +0200 Subject: [PATCH 12/13] Use internal mutability for FormData. --- src/components/script/dom/formdata.rs | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/components/script/dom/formdata.rs b/src/components/script/dom/formdata.rs index 142b08fc262..40dc6935fe6 100644 --- a/src/components/script/dom/formdata.rs +++ b/src/components/script/dom/formdata.rs @@ -2,15 +2,17 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; -use dom::bindings::error::{Fallible}; use dom::bindings::codegen::Bindings::FormDataBinding; +use dom::bindings::error::{Fallible}; use dom::bindings::js::{JS, JSRef, Temporary, OptionalUnrootable}; +use dom::bindings::trace::Traceable; +use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::blob::Blob; use dom::htmlformelement::HTMLFormElement; use dom::window::Window; use servo_util::str::DOMString; use collections::hashmap::HashMap; +use std::cell::RefCell; #[deriving(Encodable)] pub enum FormDatum { @@ -20,7 +22,7 @@ pub enum FormDatum { #[deriving(Encodable)] pub struct FormData { - pub data: HashMap, + pub data: Traceable>>, pub reflector_: Reflector, pub window: JS, pub form: Option> @@ -29,7 +31,7 @@ pub struct FormData { impl FormData { pub fn new_inherited(form: Option>, window: &JSRef) -> FormData { FormData { - data: HashMap::new(), + data: Traceable::new(RefCell::new(HashMap::new())), reflector_: Reflector::new(), window: window.unrooted(), form: form.unrooted(), @@ -46,21 +48,21 @@ impl FormData { } pub trait FormDataMethods { - fn Append(&mut self, name: DOMString, value: &JSRef, filename: Option); - fn Append_(&mut self, name: DOMString, value: DOMString); + fn Append(&self, name: DOMString, value: &JSRef, filename: Option); + fn Append_(&self, name: DOMString, value: DOMString); } impl<'a> FormDataMethods for JSRef<'a, FormData> { - fn Append(&mut self, name: DOMString, value: &JSRef, filename: Option) { + fn Append(&self, name: DOMString, value: &JSRef, filename: Option) { let blob = BlobData { blob: value.unrooted(), name: filename.unwrap_or("default".to_string()) }; - self.data.insert(name.clone(), blob); + self.data.deref().borrow_mut().insert(name.clone(), blob); } - fn Append_(&mut self, name: DOMString, value: DOMString) { - self.data.insert(name, StringData(value)); + fn Append_(&self, name: DOMString, value: DOMString) { + self.data.deref().borrow_mut().insert(name, StringData(value)); } } From c41dd2477d19e68272afc11f198f2a71c320abd2 Mon Sep 17 00:00:00 2001 From: Ms2ger Date: Tue, 10 Jun 2014 19:22:39 +0200 Subject: [PATCH 13/13] Use internal mutability for HTMLImageElement. --- src/components/script/dom/htmlimageelement.rs | 30 +++++++++---------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/src/components/script/dom/htmlimageelement.rs b/src/components/script/dom/htmlimageelement.rs index d2a0346c879..35d85441e64 100644 --- a/src/components/script/dom/htmlimageelement.rs +++ b/src/components/script/dom/htmlimageelement.rs @@ -17,12 +17,13 @@ use servo_util::geometry::to_px; use servo_net::image_cache_task; use servo_util::url::parse_url; use servo_util::str::DOMString; +use std::cell::RefCell; use url::Url; #[deriving(Encodable)] pub struct HTMLImageElement { pub htmlelement: HTMLElement, - image: Untraceable>, + image: Untraceable>>, } impl HTMLImageElementDerived for EventTarget { @@ -32,25 +33,24 @@ impl HTMLImageElementDerived for EventTarget { } trait PrivateHTMLImageElementHelpers { - fn update_image(&mut self, value: Option, url: Option); + fn update_image(&self, value: Option, url: Option); } impl<'a> PrivateHTMLImageElementHelpers for JSRef<'a, HTMLImageElement> { /// Makes the local `image` member match the status of the `src` attribute and starts /// prefetching the image. This method must be called after `src` is changed. - fn update_image(&mut self, value: Option, url: Option) { - let self_alias = self.clone(); - let node_alias: &JSRef = NodeCast::from_ref(&self_alias); - let document = node_alias.owner_doc().root(); + fn update_image(&self, value: Option, url: Option) { + let node: &JSRef = NodeCast::from_ref(self); + let document = node.owner_doc().root(); let window = document.deref().window.root(); let image_cache = &window.image_cache_task; match value { None => { - *self.image = None; + *self.image.deref().borrow_mut() = None; } Some(src) => { let img_url = parse_url(src.as_slice(), url); - *self.image = Some(img_url.clone()); + *self.image.deref().borrow_mut() = Some(img_url.clone()); // inform the image cache to load this, but don't store a // handle. @@ -67,7 +67,7 @@ impl HTMLImageElement { pub fn new_inherited(localName: DOMString, document: &JSRef) -> HTMLImageElement { HTMLImageElement { htmlelement: HTMLElement::new_inherited(HTMLImageElementTypeId, localName, document), - image: Untraceable::new(None), + image: Untraceable::new(RefCell::new(None)), } } @@ -78,12 +78,12 @@ impl HTMLImageElement { } pub trait LayoutHTMLImageElementHelpers { - unsafe fn image<'a>(&'a self) -> &'a Option; + unsafe fn image(&self) -> Option; } impl LayoutHTMLImageElementHelpers for JS { - unsafe fn image<'a>(&'a self) -> &'a Option { - &*(*self.unsafe_get()).image + unsafe fn image(&self) -> Option { + (*self.unsafe_get()).image.borrow().clone() } } @@ -253,8 +253,7 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLImageElement> { if "src" == name.as_slice() { let window = window_from_node(self).root(); let url = Some(window.deref().get_url()); - let mut self_alias = self.clone(); - self_alias.update_image(Some(value), url); + self.update_image(Some(value), url); } } @@ -265,8 +264,7 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLImageElement> { } if "src" == name.as_slice() { - let mut self_alias = self.clone(); - self_alias.update_image(None, None); + self.update_image(None, None); } } }