Navigation Menu

Skip to content

Commit

Permalink
Implement Window.set/clearInterval.(fixes #2116)
Browse files Browse the repository at this point in the history
  • Loading branch information
lpy committed Apr 17, 2014
1 parent 896cadb commit b7dcf62
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 13 deletions.
2 changes: 2 additions & 0 deletions src/components/script/dom/webidls/Window.webidl
Expand Up @@ -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);
Expand Down
52 changes: 42 additions & 10 deletions src/components/script/dom/window.rs
Expand Up @@ -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],
}
Expand Down Expand Up @@ -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;
Expand All @@ -236,29 +237,52 @@ 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();
let mut timeout_handle = select.handle(&timeout_port);
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 {
Expand All @@ -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
Expand Down
12 changes: 9 additions & 3 deletions src/components/script/script_task.rs
Expand Up @@ -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();
Expand Down
20 changes: 20 additions & 0 deletions 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>
19 changes: 19 additions & 0 deletions 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>

5 comments on commit b7dcf62

@bors-servo
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bors-servo
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

merging lpy/servo/issue2116 = b7dcf62 into auto

@bors-servo
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lpy/servo/issue2116 = b7dcf62 merged ok, testing candidate = 7441dae

@bors-servo
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bors-servo
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fast-forwarding master to auto = 7441dae

Please sign in to comment.