mirror of
https://github.com/servo/servo.git
synced 2025-06-06 16:45:39 +00:00
script: Stop using time
in DOM timers (#33262)
This switches to using `std::time` types for DOM timer operations, which allows removing our custom time units in favor of `Duration`. Signed-off-by: Martin Robinson <mrobinson@igalia.com>
This commit is contained in:
parent
8a0c7487e7
commit
a4ceb82ef5
13 changed files with 78 additions and 106 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -5744,7 +5744,6 @@ dependencies = [
|
|||
"servo_url",
|
||||
"smallvec",
|
||||
"style_traits",
|
||||
"time 0.1.45",
|
||||
"uuid",
|
||||
"webdriver",
|
||||
"webgpu",
|
||||
|
|
|
@ -64,10 +64,9 @@ impl TimerScheduler {
|
|||
/// Handle an incoming timer request.
|
||||
pub fn handle_timer_request(&mut self, request: TimerSchedulerMsg) {
|
||||
let TimerEventRequest(_, _, _, delay) = request.0;
|
||||
let schedule = Instant::now() + Duration::from_millis(delay.get());
|
||||
let event = ScheduledEvent {
|
||||
request: request.0,
|
||||
for_time: schedule,
|
||||
for_time: Instant::now() + delay,
|
||||
};
|
||||
self.0.push(event);
|
||||
}
|
||||
|
|
|
@ -47,8 +47,7 @@ use profile_traits::time::{TimerMetadata, TimerMetadataFrameType, TimerMetadataR
|
|||
use script_layout_interface::{PendingRestyle, ReflowGoal, TrustedNodeAddress};
|
||||
use script_traits::{
|
||||
AnimationState, AnimationTickType, CompositorEvent, DocumentActivity, MouseButton,
|
||||
MouseEventType, MsDuration, ScriptMsg, TouchEventType, TouchId, UntrustedNodeAddress,
|
||||
WheelDelta,
|
||||
MouseEventType, ScriptMsg, TouchEventType, TouchId, UntrustedNodeAddress, WheelDelta,
|
||||
};
|
||||
use servo_arc::Arc;
|
||||
use servo_atoms::Atom;
|
||||
|
@ -1993,7 +1992,7 @@ impl Document {
|
|||
};
|
||||
self.global().schedule_callback(
|
||||
OneshotTimerCallback::FakeRequestAnimationFrame(callback),
|
||||
MsDuration::new(FAKE_REQUEST_ANIMATION_FRAME_DELAY),
|
||||
Duration::from_millis(FAKE_REQUEST_ANIMATION_FRAME_DELAY),
|
||||
);
|
||||
} else if !self.running_animation_callbacks.get() {
|
||||
// No need to send a `ChangeRunningAnimationsState` if we're running animation callbacks:
|
||||
|
@ -2443,7 +2442,7 @@ impl Document {
|
|||
window: window_from_node(&*document),
|
||||
url: url.clone(),
|
||||
}),
|
||||
MsDuration::new(time.saturating_mul(1000)),
|
||||
Duration::from_secs(*time),
|
||||
);
|
||||
}
|
||||
// Note: this will, among others, result in the "iframe-load-event-steps" being run.
|
||||
|
|
|
@ -6,9 +6,9 @@ use std::cell::Cell;
|
|||
use std::mem;
|
||||
use std::str::{Chars, FromStr};
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::time::Duration;
|
||||
|
||||
use dom_struct::dom_struct;
|
||||
use euclid::Length;
|
||||
use headers::ContentType;
|
||||
use http::header::{self, HeaderName, HeaderValue};
|
||||
use ipc_channel::ipc;
|
||||
|
@ -48,7 +48,7 @@ use crate::script_runtime::CanGc;
|
|||
use crate::task_source::{TaskSource, TaskSourceName};
|
||||
use crate::timers::OneshotTimerCallback;
|
||||
|
||||
const DEFAULT_RECONNECTION_TIME: u64 = 5000;
|
||||
const DEFAULT_RECONNECTION_TIME: Duration = Duration::from_millis(5000);
|
||||
|
||||
#[derive(Clone, Copy, Debug, JSTraceable, MallocSizeOf, PartialEq)]
|
||||
struct GenerationId(u32);
|
||||
|
@ -69,7 +69,7 @@ pub struct EventSource {
|
|||
#[no_trace]
|
||||
request: DomRefCell<Option<RequestBuilder>>,
|
||||
last_event_id: DomRefCell<DOMString>,
|
||||
reconnection_time: Cell<u64>,
|
||||
reconnection_time: Cell<Duration>,
|
||||
generation_id: Cell<GenerationId>,
|
||||
|
||||
ready_state: Cell<ReadyState>,
|
||||
|
@ -162,7 +162,7 @@ impl EventSourceContext {
|
|||
event_source.upcast::<EventTarget>().fire_event(atom!("error"));
|
||||
|
||||
// Step 2.
|
||||
let duration = Length::new(event_source.reconnection_time.get());
|
||||
let duration = event_source.reconnection_time.get();
|
||||
|
||||
// Step 3.
|
||||
// TODO: Optionally wait some more.
|
||||
|
@ -192,7 +192,10 @@ impl EventSourceContext {
|
|||
"id" => mem::swap(&mut self.last_event_id, &mut self.value),
|
||||
"retry" => {
|
||||
if let Ok(time) = u64::from_str(&self.value) {
|
||||
self.event_source.root().reconnection_time.set(time);
|
||||
self.event_source
|
||||
.root()
|
||||
.reconnection_time
|
||||
.set(Duration::from_millis(time));
|
||||
}
|
||||
},
|
||||
_ => (),
|
||||
|
|
|
@ -11,7 +11,7 @@ use std::rc::Rc;
|
|||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::Arc;
|
||||
use std::thread::JoinHandle;
|
||||
use std::time::{Instant, SystemTime, UNIX_EPOCH};
|
||||
use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH};
|
||||
use std::{mem, ptr};
|
||||
|
||||
use base::id::{
|
||||
|
@ -53,7 +53,7 @@ use script_traits::serializable::{BlobData, BlobImpl, FileBlob};
|
|||
use script_traits::transferable::MessagePortImpl;
|
||||
use script_traits::{
|
||||
BroadcastMsg, GamepadEvent, GamepadSupportedHapticEffects, GamepadUpdateType, MessagePortMsg,
|
||||
MsDuration, PortMessageTask, ScriptMsg, ScriptToConstellationChan, TimerEvent, TimerEventId,
|
||||
PortMessageTask, ScriptMsg, ScriptToConstellationChan, TimerEvent, TimerEventId,
|
||||
TimerSchedulerMsg, TimerSource,
|
||||
};
|
||||
use servo_url::{ImmutableOrigin, MutableOrigin, ServoUrl};
|
||||
|
@ -2741,7 +2741,7 @@ impl GlobalScope {
|
|||
pub fn schedule_callback(
|
||||
&self,
|
||||
callback: OneshotTimerCallback,
|
||||
duration: MsDuration,
|
||||
duration: Duration,
|
||||
) -> OneshotTimerHandle {
|
||||
self.setup_timers();
|
||||
self.timers
|
||||
|
@ -2757,7 +2757,7 @@ impl GlobalScope {
|
|||
&self,
|
||||
callback: TimerCallback,
|
||||
arguments: Vec<HandleValue>,
|
||||
timeout: i32,
|
||||
timeout: Duration,
|
||||
is_interval: IsInterval,
|
||||
) -> i32 {
|
||||
self.setup_timers();
|
||||
|
|
|
@ -4,12 +4,13 @@
|
|||
|
||||
use std::str::FromStr;
|
||||
use std::sync::LazyLock;
|
||||
use std::time::Duration;
|
||||
|
||||
use dom_struct::dom_struct;
|
||||
use html5ever::{LocalName, Prefix};
|
||||
use js::rust::HandleObject;
|
||||
use regex::bytes::Regex;
|
||||
use script_traits::{HistoryEntryReplacement, MsDuration};
|
||||
use script_traits::HistoryEntryReplacement;
|
||||
use servo_url::ServoUrl;
|
||||
use style::str::HTML_SPACE_CHARACTERS;
|
||||
|
||||
|
@ -207,7 +208,7 @@ impl HTMLMetaElement {
|
|||
window: window.clone(),
|
||||
url: url_record,
|
||||
}),
|
||||
MsDuration::new(time.saturating_mul(1000)),
|
||||
Duration::from_secs(time),
|
||||
);
|
||||
document.set_declarative_refresh(DeclarativeRefresh::CreatedAfterLoad);
|
||||
} else {
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
use std::borrow::ToOwned;
|
||||
use std::ptr::{self, NonNull};
|
||||
use std::rc::Rc;
|
||||
use std::time::Duration;
|
||||
|
||||
use dom_struct::dom_struct;
|
||||
use js::jsapi::{Heap, JSObject, JS_NewPlainObject};
|
||||
|
@ -14,7 +15,6 @@ use js::jsval::{JSVal, NullValue};
|
|||
use js::rust::{CustomAutoRooterGuard, HandleObject, HandleValue};
|
||||
use js::typedarray::{self, Uint8ClampedArray};
|
||||
use script_traits::serializable::BlobImpl;
|
||||
use script_traits::MsDuration;
|
||||
use servo_config::prefs;
|
||||
|
||||
use crate::dom::bindings::buffer_source::create_buffer_source;
|
||||
|
@ -999,7 +999,7 @@ impl TestBindingMethods for TestBinding {
|
|||
};
|
||||
let _ = self.global().schedule_callback(
|
||||
OneshotTimerCallback::TestBindingCallback(cb),
|
||||
MsDuration::new(delay),
|
||||
Duration::from_millis(delay),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@ use std::ptr::NonNull;
|
|||
use std::rc::Rc;
|
||||
use std::sync::atomic::Ordering;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::time::Duration;
|
||||
use std::{cmp, env, mem};
|
||||
|
||||
use app_units::Au;
|
||||
|
@ -882,7 +883,7 @@ impl WindowMethods for Window {
|
|||
self.upcast::<GlobalScope>().set_timeout_or_interval(
|
||||
callback,
|
||||
args,
|
||||
timeout,
|
||||
Duration::from_millis(timeout.max(0) as u64),
|
||||
IsInterval::NonInterval,
|
||||
)
|
||||
}
|
||||
|
@ -908,7 +909,7 @@ impl WindowMethods for Window {
|
|||
self.upcast::<GlobalScope>().set_timeout_or_interval(
|
||||
callback,
|
||||
args,
|
||||
timeout,
|
||||
Duration::from_millis(timeout.max(0) as u64),
|
||||
IsInterval::Interval,
|
||||
)
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ use std::default::Default;
|
|||
use std::rc::Rc;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
|
||||
use base::id::{PipelineId, PipelineNamespace};
|
||||
use crossbeam_channel::Receiver;
|
||||
|
@ -345,7 +346,7 @@ impl WorkerGlobalScopeMethods for WorkerGlobalScope {
|
|||
self.upcast::<GlobalScope>().set_timeout_or_interval(
|
||||
callback,
|
||||
args,
|
||||
timeout,
|
||||
Duration::from_millis(timeout.max(0) as u64),
|
||||
IsInterval::NonInterval,
|
||||
)
|
||||
}
|
||||
|
@ -371,7 +372,7 @@ impl WorkerGlobalScopeMethods for WorkerGlobalScope {
|
|||
self.upcast::<GlobalScope>().set_timeout_or_interval(
|
||||
callback,
|
||||
args,
|
||||
timeout,
|
||||
Duration::from_millis(timeout.max(0) as u64),
|
||||
IsInterval::Interval,
|
||||
)
|
||||
}
|
||||
|
|
|
@ -7,11 +7,11 @@ use std::cell::Cell;
|
|||
use std::default::Default;
|
||||
use std::str::{self, FromStr};
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::time::{Duration, Instant};
|
||||
use std::{cmp, slice};
|
||||
|
||||
use dom_struct::dom_struct;
|
||||
use encoding_rs::{Encoding, UTF_8};
|
||||
use euclid::Length;
|
||||
use headers::{ContentLength, ContentType, HeaderMapExt};
|
||||
use html5ever::serialize;
|
||||
use html5ever::serialize::SerializeOpts;
|
||||
|
@ -125,7 +125,7 @@ impl XHRProgress {
|
|||
pub struct XMLHttpRequest {
|
||||
eventtarget: XMLHttpRequestEventTarget,
|
||||
ready_state: Cell<XMLHttpRequestState>,
|
||||
timeout: Cell<u32>,
|
||||
timeout: Cell<Duration>,
|
||||
with_credentials: Cell<bool>,
|
||||
upload: Dom<XMLHttpRequestUpload>,
|
||||
response_url: DomRefCell<String>,
|
||||
|
@ -162,7 +162,7 @@ pub struct XMLHttpRequest {
|
|||
send_flag: Cell<bool>,
|
||||
|
||||
timeout_cancel: DomRefCell<Option<OneshotTimerHandle>>,
|
||||
fetch_time: Cell<i64>,
|
||||
fetch_time: Cell<Instant>,
|
||||
generation_id: Cell<GenerationId>,
|
||||
response_status: Cell<Result<(), ()>>,
|
||||
#[no_trace]
|
||||
|
@ -185,7 +185,7 @@ impl XMLHttpRequest {
|
|||
XMLHttpRequest {
|
||||
eventtarget: XMLHttpRequestEventTarget::new_inherited(),
|
||||
ready_state: Cell::new(XMLHttpRequestState::Unsent),
|
||||
timeout: Cell::new(0u32),
|
||||
timeout: Cell::new(Duration::ZERO),
|
||||
with_credentials: Cell::new(false),
|
||||
upload: Dom::from_ref(&*XMLHttpRequestUpload::new(global)),
|
||||
response_url: DomRefCell::new(String::new()),
|
||||
|
@ -210,7 +210,7 @@ impl XMLHttpRequest {
|
|||
send_flag: Cell::new(false),
|
||||
|
||||
timeout_cancel: DomRefCell::new(None),
|
||||
fetch_time: Cell::new(0),
|
||||
fetch_time: Cell::new(Instant::now()),
|
||||
generation_id: Cell::new(GenerationId(0)),
|
||||
response_status: Cell::new(Ok(())),
|
||||
referrer: global.get_referrer(),
|
||||
|
@ -420,7 +420,7 @@ impl XMLHttpRequestMethods for XMLHttpRequest {
|
|||
// Step 10
|
||||
if !asynch {
|
||||
// FIXME: This should only happen if the global environment is a document environment
|
||||
if self.timeout.get() != 0 ||
|
||||
if !self.timeout.get().is_zero() ||
|
||||
self.response_type.get() != XMLHttpRequestResponseType::_empty
|
||||
{
|
||||
return Err(Error::InvalidAccess);
|
||||
|
@ -514,7 +514,7 @@ impl XMLHttpRequestMethods for XMLHttpRequest {
|
|||
|
||||
/// <https://xhr.spec.whatwg.org/#the-timeout-attribute>
|
||||
fn Timeout(&self) -> u32 {
|
||||
self.timeout.get()
|
||||
self.timeout.get().as_millis() as u32
|
||||
}
|
||||
|
||||
/// <https://xhr.spec.whatwg.org/#the-timeout-attribute>
|
||||
|
@ -523,20 +523,22 @@ impl XMLHttpRequestMethods for XMLHttpRequest {
|
|||
if self.sync_in_window() {
|
||||
return Err(Error::InvalidAccess);
|
||||
}
|
||||
|
||||
// Step 2
|
||||
let timeout = Duration::from_millis(timeout as u64);
|
||||
self.timeout.set(timeout);
|
||||
|
||||
if self.send_flag.get() {
|
||||
if timeout == 0 {
|
||||
if timeout.is_zero() {
|
||||
self.cancel_timeout();
|
||||
return Ok(());
|
||||
}
|
||||
let progress = time::now().to_timespec().sec - self.fetch_time.get();
|
||||
if timeout > (progress * 1000) as u32 {
|
||||
self.set_timeout(timeout - (progress * 1000) as u32);
|
||||
let progress = Instant::now() - self.fetch_time.get();
|
||||
if timeout > progress {
|
||||
self.set_timeout(timeout - progress);
|
||||
} else {
|
||||
// Immediately execute the timeout steps
|
||||
self.set_timeout(0);
|
||||
self.set_timeout(Duration::ZERO);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
|
@ -788,7 +790,7 @@ impl XMLHttpRequestMethods for XMLHttpRequest {
|
|||
}
|
||||
}
|
||||
|
||||
self.fetch_time.set(time::now().to_timespec().sec);
|
||||
self.fetch_time.set(Instant::now());
|
||||
|
||||
let rv = self.fetch(request, &self.global());
|
||||
// Step 10
|
||||
|
@ -797,7 +799,7 @@ impl XMLHttpRequestMethods for XMLHttpRequest {
|
|||
}
|
||||
|
||||
let timeout = self.timeout.get();
|
||||
if timeout > 0 {
|
||||
if timeout > Duration::ZERO {
|
||||
self.set_timeout(timeout);
|
||||
}
|
||||
Ok(())
|
||||
|
@ -1298,14 +1300,13 @@ impl XMLHttpRequest {
|
|||
self.dispatch_progress_event(false, type_, len, total);
|
||||
}
|
||||
|
||||
fn set_timeout(&self, duration_ms: u32) {
|
||||
fn set_timeout(&self, duration: Duration) {
|
||||
// Sets up the object to timeout in a given number of milliseconds
|
||||
// This will cancel all previous timeouts
|
||||
let callback = OneshotTimerCallback::XhrTimeout(XHRTimeoutCallback {
|
||||
xhr: Trusted::new(self),
|
||||
generation_id: self.generation_id.get(),
|
||||
});
|
||||
let duration = Length::new(duration_ms as u64);
|
||||
*self.timeout_cancel.borrow_mut() =
|
||||
Some(self.global().schedule_callback(callback, duration));
|
||||
}
|
||||
|
|
|
@ -3,21 +3,18 @@
|
|||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use std::cell::Cell;
|
||||
use std::cmp::{self, Ord, Ordering};
|
||||
use std::cmp::{Ord, Ordering};
|
||||
use std::collections::HashMap;
|
||||
use std::default::Default;
|
||||
use std::rc::Rc;
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
use deny_public_fields::DenyPublicFields;
|
||||
use euclid::Length;
|
||||
use ipc_channel::ipc::IpcSender;
|
||||
use js::jsapi::Heap;
|
||||
use js::jsval::{JSVal, UndefinedValue};
|
||||
use js::rust::HandleValue;
|
||||
use script_traits::{
|
||||
precise_time_ms, MsDuration, TimerEvent, TimerEventId, TimerEventRequest, TimerSchedulerMsg,
|
||||
TimerSource,
|
||||
};
|
||||
use script_traits::{TimerEvent, TimerEventId, TimerEventRequest, TimerSchedulerMsg, TimerSource};
|
||||
use servo_config::pref;
|
||||
|
||||
use crate::dom::bindings::callback::ExceptionHandling::Report;
|
||||
|
@ -52,14 +49,12 @@ pub struct OneshotTimers {
|
|||
scheduler_chan: IpcSender<TimerSchedulerMsg>,
|
||||
next_timer_handle: Cell<OneshotTimerHandle>,
|
||||
timers: DomRefCell<Vec<OneshotTimer>>,
|
||||
#[no_trace]
|
||||
suspended_since: Cell<Option<MsDuration>>,
|
||||
suspended_since: Cell<Option<Instant>>,
|
||||
/// Initially 0, increased whenever the associated document is reactivated
|
||||
/// by the amount of ms the document was inactive. The current time can be
|
||||
/// offset back by this amount for a coherent time across document
|
||||
/// activations.
|
||||
#[no_trace]
|
||||
suspension_offset: Cell<MsDuration>,
|
||||
suspension_offset: Cell<Duration>,
|
||||
/// Calls to `fire_timer` with a different argument than this get ignored.
|
||||
/// They were previously scheduled and got invalidated when
|
||||
/// - timers were suspended,
|
||||
|
@ -76,8 +71,7 @@ struct OneshotTimer {
|
|||
#[no_trace]
|
||||
source: TimerSource,
|
||||
callback: OneshotTimerCallback,
|
||||
#[no_trace]
|
||||
scheduled_for: MsDuration,
|
||||
scheduled_for: Instant,
|
||||
}
|
||||
|
||||
// This enum is required to work around the fact that trait objects do not support generic methods.
|
||||
|
@ -137,7 +131,7 @@ impl OneshotTimers {
|
|||
next_timer_handle: Cell::new(OneshotTimerHandle(1)),
|
||||
timers: DomRefCell::new(Vec::new()),
|
||||
suspended_since: Cell::new(None),
|
||||
suspension_offset: Cell::new(Length::new(0)),
|
||||
suspension_offset: Cell::new(Duration::ZERO),
|
||||
expected_event_id: Cell::new(TimerEventId(0)),
|
||||
}
|
||||
}
|
||||
|
@ -151,20 +145,18 @@ impl OneshotTimers {
|
|||
pub fn schedule_callback(
|
||||
&self,
|
||||
callback: OneshotTimerCallback,
|
||||
duration: MsDuration,
|
||||
duration: Duration,
|
||||
source: TimerSource,
|
||||
) -> OneshotTimerHandle {
|
||||
let new_handle = self.next_timer_handle.get();
|
||||
self.next_timer_handle
|
||||
.set(OneshotTimerHandle(new_handle.0 + 1));
|
||||
|
||||
let scheduled_for = self.base_time() + duration;
|
||||
|
||||
let timer = OneshotTimer {
|
||||
handle: new_handle,
|
||||
source,
|
||||
callback,
|
||||
scheduled_for,
|
||||
scheduled_for: self.base_time() + duration,
|
||||
};
|
||||
|
||||
{
|
||||
|
@ -247,18 +239,18 @@ impl OneshotTimers {
|
|||
self.schedule_timer_call();
|
||||
}
|
||||
|
||||
fn base_time(&self) -> MsDuration {
|
||||
fn base_time(&self) -> Instant {
|
||||
let offset = self.suspension_offset.get();
|
||||
|
||||
match self.suspended_since.get() {
|
||||
Some(time) => time - offset,
|
||||
None => precise_time_ms() - offset,
|
||||
Some(suspend_time) => suspend_time - offset,
|
||||
None => Instant::now() - offset,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn slow_down(&self) {
|
||||
let duration = pref!(js.timers.minimum_duration) as u64;
|
||||
self.js_timers.set_min_duration(MsDuration::new(duration));
|
||||
let min_duration_ms = pref!(js.timers.minimum_duration) as u64;
|
||||
self.js_timers
|
||||
.set_min_duration(Duration::from_millis(min_duration_ms));
|
||||
}
|
||||
|
||||
pub fn speed_up(&self) {
|
||||
|
@ -272,14 +264,14 @@ impl OneshotTimers {
|
|||
}
|
||||
|
||||
debug!("Suspending timers.");
|
||||
self.suspended_since.set(Some(precise_time_ms()));
|
||||
self.suspended_since.set(Some(Instant::now()));
|
||||
self.invalidate_expected_event_id();
|
||||
}
|
||||
|
||||
pub fn resume(&self) {
|
||||
// Resume is idempotent: do nothing if the timers are already resumed.
|
||||
let additional_offset = match self.suspended_since.get() {
|
||||
Some(suspended_since) => precise_time_ms() - suspended_since,
|
||||
Some(suspended_since) => Instant::now() - suspended_since,
|
||||
None => return warn!("Resuming an already resumed timer."),
|
||||
};
|
||||
|
||||
|
@ -302,12 +294,7 @@ impl OneshotTimers {
|
|||
if let Some(timer) = timers.last() {
|
||||
let expected_event_id = self.invalidate_expected_event_id();
|
||||
|
||||
let delay = Length::new(
|
||||
timer
|
||||
.scheduled_for
|
||||
.get()
|
||||
.saturating_sub(precise_time_ms().get()),
|
||||
);
|
||||
let delay = timer.scheduled_for - Instant::now();
|
||||
let request = TimerEventRequest(
|
||||
self.timer_event_chan
|
||||
.borrow()
|
||||
|
@ -339,7 +326,7 @@ impl OneshotTimers {
|
|||
global: &GlobalScope,
|
||||
callback: TimerCallback,
|
||||
arguments: Vec<HandleValue>,
|
||||
timeout: i32,
|
||||
timeout: Duration,
|
||||
is_interval: IsInterval,
|
||||
source: TimerSource,
|
||||
) -> i32 {
|
||||
|
@ -369,8 +356,7 @@ pub struct JsTimers {
|
|||
/// The nesting level of the currently executing timer task or 0.
|
||||
nesting_level: Cell<u32>,
|
||||
/// Used to introduce a minimum delay in event intervals
|
||||
#[no_trace]
|
||||
min_duration: Cell<Option<MsDuration>>,
|
||||
min_duration: Cell<Option<Duration>>,
|
||||
}
|
||||
|
||||
#[derive(JSTraceable, MallocSizeOf)]
|
||||
|
@ -391,8 +377,7 @@ pub struct JsTimerTask {
|
|||
callback: InternalTimerCallback,
|
||||
is_interval: IsInterval,
|
||||
nesting_level: u32,
|
||||
#[no_trace]
|
||||
duration: MsDuration,
|
||||
duration: Duration,
|
||||
is_user_interacting: bool,
|
||||
}
|
||||
|
||||
|
@ -436,7 +421,7 @@ impl JsTimers {
|
|||
global: &GlobalScope,
|
||||
callback: TimerCallback,
|
||||
arguments: Vec<HandleValue>,
|
||||
timeout: i32,
|
||||
timeout: Duration,
|
||||
is_interval: IsInterval,
|
||||
source: TimerSource,
|
||||
) -> i32 {
|
||||
|
@ -480,11 +465,11 @@ impl JsTimers {
|
|||
is_interval,
|
||||
is_user_interacting: ScriptThread::is_user_interacting(),
|
||||
nesting_level: 0,
|
||||
duration: Length::new(0),
|
||||
duration: Duration::ZERO,
|
||||
};
|
||||
|
||||
// step 5
|
||||
task.duration = Length::new(cmp::max(0, timeout) as u64);
|
||||
task.duration = timeout.max(Duration::ZERO);
|
||||
|
||||
// step 3, 6-9, 11-14
|
||||
self.initialize_and_schedule(global, task);
|
||||
|
@ -501,7 +486,7 @@ impl JsTimers {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn set_min_duration(&self, duration: MsDuration) {
|
||||
pub fn set_min_duration(&self, duration: Duration) {
|
||||
self.min_duration.set(Some(duration));
|
||||
}
|
||||
|
||||
|
@ -510,9 +495,9 @@ impl JsTimers {
|
|||
}
|
||||
|
||||
// see step 13 of https://html.spec.whatwg.org/multipage/#timer-initialisation-steps
|
||||
fn user_agent_pad(&self, current_duration: MsDuration) -> MsDuration {
|
||||
fn user_agent_pad(&self, current_duration: Duration) -> Duration {
|
||||
match self.min_duration.get() {
|
||||
Some(min_duration) => cmp::max(min_duration, current_duration),
|
||||
Some(min_duration) => min_duration.max(current_duration),
|
||||
None => current_duration,
|
||||
}
|
||||
}
|
||||
|
@ -543,10 +528,10 @@ impl JsTimers {
|
|||
}
|
||||
|
||||
// see step 7 of https://html.spec.whatwg.org/multipage/#timer-initialisation-steps
|
||||
fn clamp_duration(nesting_level: u32, unclamped: MsDuration) -> MsDuration {
|
||||
let lower_bound = if nesting_level > 5 { 4 } else { 0 };
|
||||
|
||||
cmp::max(Length::new(lower_bound), unclamped)
|
||||
fn clamp_duration(nesting_level: u32, unclamped: Duration) -> Duration {
|
||||
let lower_bound_ms = if nesting_level > 5 { 4 } else { 0 };
|
||||
let lower_bound = Duration::from_millis(lower_bound_ms);
|
||||
lower_bound.max(unclamped)
|
||||
}
|
||||
|
||||
impl JsTimerTask {
|
||||
|
|
|
@ -39,7 +39,6 @@ servo_atoms = { workspace = true }
|
|||
servo_url = { path = "../../url" }
|
||||
smallvec = { workspace = true }
|
||||
style_traits = { workspace = true }
|
||||
time = { workspace = true }
|
||||
uuid = { workspace = true }
|
||||
webdriver = { workspace = true }
|
||||
webgpu = { path = "../../webgpu" }
|
||||
|
|
|
@ -18,6 +18,7 @@ use std::borrow::Cow;
|
|||
use std::collections::{HashMap, VecDeque};
|
||||
use std::fmt;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
|
||||
use background_hang_monitor_api::BackgroundHangMonitorRegister;
|
||||
use base::id::{
|
||||
|
@ -32,7 +33,7 @@ use crossbeam_channel::{RecvTimeoutError, Sender};
|
|||
use devtools_traits::{DevtoolScriptControlMsg, ScriptToDevtoolsControlMsg, WorkerId};
|
||||
use embedder_traits::CompositorEventVariant;
|
||||
use euclid::default::Point2D;
|
||||
use euclid::{Length, Rect, Scale, Size2D, UnknownUnit, Vector2D};
|
||||
use euclid::{Rect, Scale, Size2D, UnknownUnit, Vector2D};
|
||||
use http::{HeaderMap, Method};
|
||||
use ipc_channel::ipc::{IpcReceiver, IpcSender};
|
||||
use ipc_channel::Error as IpcError;
|
||||
|
@ -577,7 +578,7 @@ pub struct TimerEventRequest(
|
|||
pub IpcSender<TimerEvent>,
|
||||
pub TimerSource,
|
||||
pub TimerEventId,
|
||||
pub MsDuration,
|
||||
pub Duration,
|
||||
);
|
||||
|
||||
/// The message used to send a request to the timer scheduler.
|
||||
|
@ -603,23 +604,6 @@ pub enum TimerSource {
|
|||
#[derive(Clone, Copy, Debug, Deserialize, Eq, MallocSizeOf, PartialEq, Serialize)]
|
||||
pub struct TimerEventId(pub u32);
|
||||
|
||||
/// Unit of measurement.
|
||||
#[derive(Clone, Copy, MallocSizeOf)]
|
||||
pub enum Milliseconds {}
|
||||
/// Unit of measurement.
|
||||
#[derive(Clone, Copy, MallocSizeOf)]
|
||||
pub enum Nanoseconds {}
|
||||
|
||||
/// Amount of milliseconds.
|
||||
pub type MsDuration = Length<u64, Milliseconds>;
|
||||
/// Amount of nanoseconds.
|
||||
pub type NsDuration = Length<u64, Nanoseconds>;
|
||||
|
||||
/// Returns the duration since an unspecified epoch measured in ms.
|
||||
pub fn precise_time_ms() -> MsDuration {
|
||||
Length::new(time::precise_time_ns() / (1000 * 1000))
|
||||
}
|
||||
|
||||
/// Data needed to construct a script thread.
|
||||
///
|
||||
/// NB: *DO NOT* add any Senders or Receivers here! pcwalton will have to rewrite your code if you
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue