aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/components/script/dom/webidls/Window.webidl2
-rw-r--r--src/components/script/dom/window.rs52
-rw-r--r--src/components/script/script_task.rs12
-rw-r--r--src/test/content/test_window_setInterval.html20
-rw-r--r--src/test/html/test_interval.html19
5 files changed, 92 insertions, 13 deletions
diff --git a/src/components/script/dom/webidls/Window.webidl b/src/components/script/dom/webidls/Window.webidl
index 0260324b91e..2405055c15c 100644
--- a/src/components/script/dom/webidls/Window.webidl
+++ b/src/components/script/dom/webidls/Window.webidl
@@ -71,6 +71,8 @@ interface WindowTimers {
//XXXjdm No support for Function or variadic arguments yet
long setTimeout(any handler, optional long timeout = 0/*, any... arguments*/);
void clearTimeout(optional long handle = 0);
+ long setInterval(any handler, optional long timeout = 0/*, any... arguments*/);
+ void clearInterval(optional long handler = 0);
/*long setTimeout(DOMString handler, optional long timeout = 0, any... arguments);
long setInterval(Function handler, optional long timeout = 0, any... arguments);
long setInterval(DOMString handler, optional long timeout = 0, any... arguments);
diff --git a/src/components/script/dom/window.rs b/src/components/script/dom/window.rs
index 9ba9d00da82..a0b7ef3740b 100644
--- a/src/components/script/dom/window.rs
+++ b/src/components/script/dom/window.rs
@@ -128,6 +128,7 @@ impl Drop for Window {
// to the function when calling it)
pub struct TimerData {
handle: i32,
+ is_interval: bool,
funval: JSVal,
args: ~[JSVal],
}
@@ -226,7 +227,7 @@ impl Reflectable for Window {
}
impl Window {
- pub fn SetTimeout(&mut self, _cx: *JSContext, callback: JSVal, timeout: i32) -> i32 {
+ fn set_timeout_or_interval(&mut 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;
@@ -236,9 +237,18 @@ impl Window {
let tm = Timer::new().unwrap();
let (cancel_chan, cancel_port) = channel();
let chan = self.extra.timer_chan.clone();
- spawn_named("Window:SetTimeout", proc() {
+ let spawn_name = if is_interval {
+ "Window:SetInterval"
+ } else {
+ "Window:SetTimeout"
+ };
+ spawn_named(spawn_name, proc() {
let mut tm = tm;
- let timeout_port = tm.oneshot(timeout);
+ let timeout_port = if is_interval {
+ tm.periodic(timeout)
+ } else {
+ tm.oneshot(timeout)
+ };
let cancel_port = cancel_port;
let select = Select::new();
@@ -246,19 +256,33 @@ impl Window {
unsafe { timeout_handle.add() };
let mut cancel_handle = select.handle(&cancel_port);
unsafe { cancel_handle.add() };
- let id = select.wait();
- if id == timeout_handle.id() {
- chan.send(TimerMessageFire(~TimerData {
- handle: handle,
- funval: callback,
- args: ~[],
- }));
+
+ loop {
+ let id = select.wait();
+ if id == timeout_handle.id() {
+ timeout_port.recv();
+ chan.send(TimerMessageFire(~TimerData {
+ handle: handle,
+ is_interval: is_interval,
+ funval: callback,
+ args: ~[],
+ }));
+ if !is_interval {
+ break;
+ }
+ } else if id == cancel_handle.id() {
+ break;
+ }
}
});
self.active_timers.insert(handle, TimerHandle { handle: handle, cancel_chan: Some(cancel_chan) });
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 {
@@ -267,6 +291,14 @@ impl Window {
}
}
+ 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 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
diff --git a/src/components/script/script_task.rs b/src/components/script/script_task.rs
index a585c320ad9..096a0d40b6a 100644
--- a/src/components/script/script_task.rs
+++ b/src/components/script/script_task.rs
@@ -660,9 +660,15 @@ impl ScriptTask {
let frame = page.frame();
let mut window = frame.get_ref().window.clone();
- let timer_handle = window.get_mut().active_timers.pop(&timer_data.handle);
- if timer_handle.is_none() {
- return;
+ {
+ let timer_handle = window.get().active_timers.find(&timer_data.handle);
+ if timer_handle.is_none() {
+ return;
+ }
+ }
+
+ if !timer_data.is_interval {
+ window.get_mut().active_timers.remove(&timer_data.handle);
}
let js_info = page.js_info();
diff --git a/src/test/content/test_window_setInterval.html b/src/test/content/test_window_setInterval.html
new file mode 100644
index 00000000000..6fb3ddeb6ba
--- /dev/null
+++ b/src/test/content/test_window_setInterval.html
@@ -0,0 +1,20 @@
+<html>
+ <head>
+ <script src="harness.js"></script>
+ </head>
+ <body>
+ <script>
+ var x = 0;
+ var intervalID = setInterval(function() {
+ x += 1;
+ if (x == 2) {
+ clearInterval(intervalID);
+ setTimeout(function() {
+ is(x, 2);
+ finish();
+ }, 300);
+ }
+ }, 10);
+ </script>
+ </body>
+</html>
diff --git a/src/test/html/test_interval.html b/src/test/html/test_interval.html
new file mode 100644
index 00000000000..3f95b98695a
--- /dev/null
+++ b/src/test/html/test_interval.html
@@ -0,0 +1,19 @@
+<html>
+ <head>
+ </head>
+ <body>
+ <script>
+ var x = 0;
+ alert("Interval begin");
+ var intervalID = setInterval(function() {
+ if (x < 10) {
+ alert("interval " + x);
+ x += 1;
+ } else {
+ clearInterval(intervalID);
+ alert("Interval deleted");
+ }
+ }, 300);
+ </script>
+ </body>
+</html>