aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/timers.rs
diff options
context:
space:
mode:
Diffstat (limited to 'components/script/timers.rs')
-rw-r--r--components/script/timers.rs67
1 files changed, 55 insertions, 12 deletions
diff --git a/components/script/timers.rs b/components/script/timers.rs
index ad6547b0341..2fd39c189f8 100644
--- a/components/script/timers.rs
+++ b/components/script/timers.rs
@@ -7,6 +7,7 @@ use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::FunctionBinding::Function;
use dom::bindings::global::global_object_for_js_object;
use dom::bindings::reflector::Reflectable;
+use dom::bindings::trace::JSTraceable;
use dom::window::ScriptHelpers;
use euclid::length::Length;
use js::jsapi::{HandleValue, Heap, RootedValue};
@@ -106,6 +107,7 @@ pub enum TimerCallback {
enum InternalTimerCallback {
StringTimerCallback(DOMString),
FunctionTimerCallback(Rc<Function>, Rc<Vec<Heap<JSVal>>>),
+ InternalCallback(Box<ScheduledCallback>),
}
impl HeapSizeOf for InternalTimerCallback {
@@ -115,6 +117,18 @@ impl HeapSizeOf for InternalTimerCallback {
}
}
+pub trait ScheduledCallback: JSTraceable + HeapSizeOf {
+ fn invoke(self: Box<Self>);
+
+ fn box_clone(&self) -> Box<ScheduledCallback>;
+}
+
+impl Clone for Box<ScheduledCallback> {
+ fn clone(&self) -> Box<ScheduledCallback> {
+ self.box_clone()
+ }
+}
+
impl ActiveTimers {
pub fn new(timer_event_chan: Box<TimerEventChan + Send>,
scheduler_chan: Sender<TimerEventRequest>)
@@ -139,15 +153,6 @@ impl ActiveTimers {
is_interval: IsInterval,
source: TimerSource)
-> i32 {
- // step 3
- let TimerHandle(new_handle) = self.next_timer_handle.get();
- self.next_timer_handle.set(TimerHandle(new_handle + 1));
-
- let timeout = cmp::max(0, timeout);
- // step 7
- let duration = self.clamp_duration(Length::new(timeout as u64));
- let next_call = self.base_time() + duration;
-
let callback = match callback {
TimerCallback::StringTimerCallback(code_str) =>
InternalTimerCallback::StringTimerCallback(code_str),
@@ -165,6 +170,38 @@ impl ActiveTimers {
}
};
+ let timeout = cmp::max(0, timeout);
+ // step 7
+ let duration = self.clamp_duration(Length::new(timeout as u64));
+
+ let TimerHandle(handle) = self.schedule_internal_callback(callback, duration, is_interval, source);
+ handle
+ }
+
+ pub fn schedule_callback(&self,
+ callback: Box<ScheduledCallback>,
+ duration: MsDuration,
+ source: TimerSource) -> TimerHandle {
+ self.schedule_internal_callback(InternalTimerCallback::InternalCallback(callback),
+ duration,
+ IsInterval::NonInterval,
+ source)
+ }
+
+ // see https://html.spec.whatwg.org/multipage/#timer-initialisation-steps
+ fn schedule_internal_callback(&self,
+ callback: InternalTimerCallback,
+ duration: MsDuration,
+ is_interval: IsInterval,
+ source: TimerSource) -> TimerHandle {
+ assert!(self.suspended_since.get().is_none());
+
+ // step 3
+ let TimerHandle(new_handle) = self.next_timer_handle.get();
+ self.next_timer_handle.set(TimerHandle(new_handle + 1));
+
+ let next_call = self.base_time() + duration;
+
let timer = Timer {
handle: TimerHandle(new_handle),
source: source,
@@ -184,11 +221,14 @@ impl ActiveTimers {
}
// step 10
- new_handle
+ TimerHandle(new_handle)
}
pub fn clear_timeout_or_interval(&self, handle: i32) {
- let handle = TimerHandle(handle);
+ self.unschedule_callback(TimerHandle(handle));
+ }
+
+ pub fn unschedule_callback(&self, handle: TimerHandle) {
let was_next = self.is_next_timer(handle);
self.timers.borrow_mut().retain(|t| t.handle != handle);
@@ -258,7 +298,10 @@ impl ActiveTimers {
}).collect();
let _ = function.Call_(this, arguments, Report);
- }
+ },
+ InternalTimerCallback::InternalCallback(callback) => {
+ callback.invoke();
+ },
};
self.nesting_level.set(0);