diff options
Diffstat (limited to 'src/components/script/dom/window.rs')
-rw-r--r-- | src/components/script/dom/window.rs | 205 |
1 files changed, 117 insertions, 88 deletions
diff --git a/src/components/script/dom/window.rs b/src/components/script/dom/window.rs index 1e4f7167f45..258a85b1455 100644 --- a/src/components/script/dom/window.rs +++ b/src/components/script/dom/window.rs @@ -3,8 +3,8 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::BindingDeclarations::WindowBinding; -use dom::bindings::js::JS; -use dom::bindings::trace::Untraceable; +use dom::bindings::js::{JS, JSRef, Temporary, OptionalSettable}; +use dom::bindings::trace::{Traceable, Untraceable}; use dom::bindings::utils::{Reflectable, Reflector}; use dom::browsercontext::BrowserContext; use dom::document::Document; @@ -35,33 +35,25 @@ use std::rc::Rc; use serialize::{Encoder, Encodable}; use url::Url; -pub struct TimerHandle { - pub handle: i32, - pub cancel_chan: Option<Sender<()>>, -} +#[deriving(Eq, Encodable, TotalEq)] +pub struct TimerId(i32); -impl<S: Encoder<E>, E> Encodable<S, E> for TimerHandle { - fn encode(&self, _s: &mut S) -> Result<(), E> { - Ok(()) - } +#[deriving(Encodable)] +pub struct TimerHandle { + pub handle: TimerId, + pub data: TimerData, + pub cancel_chan: Untraceable<Option<Sender<()>>>, } -impl Hash for TimerHandle { +impl Hash for TimerId { fn hash(&self, state: &mut sip::SipState) { - self.handle.hash(state); + let TimerId(id) = *self; + id.hash(state); } } -impl Eq for TimerHandle { - fn eq(&self, other: &TimerHandle) -> bool { - self.handle == other.handle - } -} - -impl TotalEq for TimerHandle { } - impl TimerHandle { - fn cancel(&self) { + fn cancel(&mut self) { self.cancel_chan.as_ref().map(|chan| chan.send(())); } } @@ -74,7 +66,7 @@ pub struct Window { pub location: Option<JS<Location>>, pub navigator: Option<JS<Navigator>>, pub image_cache_task: ImageCacheTask, - pub active_timers: ~HashMap<i32, TimerHandle>, + pub active_timers: ~HashMap<TimerId, TimerHandle>, pub next_timer_handle: i32, pub compositor: Untraceable<~ScriptListener>, pub browser_context: Option<BrowserContext>, @@ -98,7 +90,7 @@ impl Window { #[unsafe_destructor] impl Drop for Window { fn drop(&mut self) { - for timer_handle in self.active_timers.values() { + for (_, timer_handle) in self.active_timers.mut_iter() { timer_handle.cancel(); } } @@ -107,94 +99,155 @@ impl Drop for Window { // Holder for the various JS values associated with setTimeout // (ie. function value to invoke and all arguments to pass // to the function when calling it) +#[deriving(Encodable)] pub struct TimerData { - pub handle: i32, pub is_interval: bool, - pub funval: JSVal, + pub funval: Traceable<JSVal>, } -impl Window { - pub fn Alert(&self, s: DOMString) { +pub trait WindowMethods { + fn Alert(&self, s: DOMString); + fn Close(&self); + fn Document(&self) -> Temporary<Document>; + fn Name(&self) -> DOMString; + fn SetName(&self, _name: DOMString); + fn Status(&self) -> DOMString; + fn SetStatus(&self, _status: DOMString); + fn Closed(&self) -> bool; + fn Stop(&self); + fn Focus(&self); + fn Blur(&self); + fn GetFrameElement(&self) -> Option<Temporary<Element>>; + fn Location(&mut self) -> Temporary<Location>; + fn Console(&mut self) -> Temporary<Console>; + fn Navigator(&mut self) -> Temporary<Navigator>; + fn Confirm(&self, _message: DOMString) -> bool; + fn Prompt(&self, _message: DOMString, _default: DOMString) -> Option<DOMString>; + fn Print(&self); + fn ShowModalDialog(&self, _cx: *JSContext, _url: DOMString, _argument: Option<JSVal>) -> JSVal; + fn SetTimeout(&mut self, _cx: *JSContext, callback: JSVal, timeout: i32) -> i32; + fn ClearTimeout(&mut self, handle: i32); + fn SetInterval(&mut self, _cx: *JSContext, callback: JSVal, timeout: i32) -> i32; + fn ClearInterval(&mut self, handle: i32); + fn Window(&self) -> Temporary<Window>; + fn Self(&self) -> Temporary<Window>; +} + +impl<'a> WindowMethods for JSRef<'a, Window> { + fn Alert(&self, s: DOMString) { // Right now, just print to the console println!("ALERT: {:s}", s); } - pub fn Close(&self) { + fn Close(&self) { let ScriptChan(ref chan) = self.script_chan; chan.send(ExitWindowMsg(self.page.id.clone())); } - pub fn Document(&self) -> JS<Document> { + fn Document(&self) -> Temporary<Document> { let frame = self.page().frame(); - frame.get_ref().document.clone() + Temporary::new(frame.get_ref().document.clone()) } - pub fn Name(&self) -> DOMString { + fn Name(&self) -> DOMString { ~"" } - pub fn SetName(&self, _name: DOMString) { + fn SetName(&self, _name: DOMString) { } - pub fn Status(&self) -> DOMString { + fn Status(&self) -> DOMString { ~"" } - pub fn SetStatus(&self, _status: DOMString) { + fn SetStatus(&self, _status: DOMString) { } - pub fn Closed(&self) -> bool { + fn Closed(&self) -> bool { false } - pub fn Stop(&self) { + fn Stop(&self) { } - pub fn Focus(&self) { + fn Focus(&self) { } - pub fn Blur(&self) { + fn Blur(&self) { } - pub fn GetFrameElement(&self) -> Option<JS<Element>> { + fn GetFrameElement(&self) -> Option<Temporary<Element>> { None } - pub fn Location(&mut self, abstract_self: &JS<Window>) -> JS<Location> { + fn Location(&mut self) -> Temporary<Location> { if self.location.is_none() { - self.location = Some(Location::new(abstract_self, self.page.clone())); + let page = self.deref().page.clone(); + let location = Location::new(self, page); + self.location.assign(Some(location)); } - self.location.get_ref().clone() + Temporary::new(self.location.get_ref().clone()) } - pub fn Console(&mut self, abstract_self: &JS<Window>) -> JS<Console> { + fn Console(&mut self) -> Temporary<Console> { if self.console.is_none() { - self.console = Some(Console::new(abstract_self)); + let console = Console::new(self); + self.console.assign(Some(console)); } - self.console.get_ref().clone() + Temporary::new(self.console.get_ref().clone()) } - pub fn Navigator(&mut self, abstract_self: &JS<Window>) -> JS<Navigator> { + fn Navigator(&mut self) -> Temporary<Navigator> { if self.navigator.is_none() { - self.navigator = Some(Navigator::new(abstract_self)); + let navigator = Navigator::new(self); + self.navigator.assign(Some(navigator)); } - self.navigator.get_ref().clone() + Temporary::new(self.navigator.get_ref().clone()) } - pub fn Confirm(&self, _message: DOMString) -> bool { + fn Confirm(&self, _message: DOMString) -> bool { false } - pub fn Prompt(&self, _message: DOMString, _default: DOMString) -> Option<DOMString> { + fn Prompt(&self, _message: DOMString, _default: DOMString) -> Option<DOMString> { None } - pub fn Print(&self) { + fn Print(&self) { } - pub fn ShowModalDialog(&self, _cx: *JSContext, _url: DOMString, _argument: Option<JSVal>) -> JSVal { + fn ShowModalDialog(&self, _cx: *JSContext, _url: DOMString, _argument: Option<JSVal>) -> JSVal { NullValue() } + + fn SetTimeout(&mut self, _cx: *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)); + match timer_handle { + Some(ref mut handle) => handle.cancel(), + None => { } + } + self.active_timers.remove(&TimerId(handle)); + } + + fn SetInterval(&mut self, _cx: *JSContext, callback: JSVal, timeout: i32) -> i32 { + self.set_timeout_or_interval(callback, timeout, true) + } + + fn ClearInterval(&mut self, handle: i32) { + self.ClearTimeout(handle); + } + + fn Window(&self) -> Temporary<Window> { + Temporary::from_rooted(self) + } + + fn Self(&self) -> Temporary<Window> { + self.Window() + } } impl Reflectable for Window { @@ -243,13 +296,8 @@ impl Window { let id = select.wait(); if id == timeout_handle.id() { timeout_port.recv(); - let data = ~TimerData { - handle: handle, - is_interval: is_interval, - funval: callback, - }; let ScriptChan(ref chan) = chan; - chan.send(FireTimerMsg(page_id, data)); + chan.send(FireTimerMsg(page_id, TimerId(handle))); if !is_interval { break; } @@ -258,38 +306,19 @@ impl Window { } } }); - self.active_timers.insert(handle, TimerHandle { handle: handle, cancel_chan: Some(cancel_chan) }); + let timer_id = TimerId(handle); + let timer = TimerHandle { + handle: timer_id, + cancel_chan: Untraceable::new(Some(cancel_chan)), + data: TimerData { + is_interval: is_interval, + funval: Traceable::new(callback), + } + }; + self.active_timers.insert(timer_id, timer); handle } - pub fn SetTimeout(&mut self, _cx: *JSContext, callback: JSVal, timeout: i32) -> i32 { - self.set_timeout_or_interval(callback, timeout, false) - } - - pub fn ClearTimeout(&mut self, handle: i32) { - let timer_handle = self.active_timers.pop(&handle); - match timer_handle { - Some(handle) => handle.cancel(), - None => { } - } - } - - pub fn SetInterval(&mut self, _cx: *JSContext, callback: JSVal, timeout: i32) -> i32 { - self.set_timeout_or_interval(callback, timeout, true) - } - - pub fn ClearInterval(&mut self, handle: i32) { - self.ClearTimeout(handle); - } - - pub fn Window(&self, abstract_self: &JS<Window>) -> JS<Window> { - abstract_self.clone() - } - - pub fn Self(&self, abstract_self: &JS<Window>) -> JS<Window> { - self.Window(abstract_self) - } - pub fn damage_and_reflow(&self, damage: DocumentDamageLevel) { // FIXME This should probably be ReflowForQuery, not Display. All queries currently // currently rely on the display list, which means we can't destroy it by @@ -304,7 +333,7 @@ impl Window { self.page().join_layout(); } - pub fn init_browser_context(&mut self, doc: &JS<Document>) { + pub fn init_browser_context(&mut self, doc: &JSRef<Document>) { self.browser_context = Some(BrowserContext::new(doc)); } |