From 83a40c51809cdac3c7d58731b555dc95cdc5c5bf Mon Sep 17 00:00:00 2001 From: Martin Robinson Date: Fri, 30 Aug 2024 10:00:34 +0200 Subject: [PATCH] script: Stop using legacy `time` for `Document::reflow_timeout` (#33258) Use `std::time` from the Rust standard library instead. This is one step toward removing our use of the legacy `time` crate which has security issues. Signed-off-by: Martin Robinson --- components/script/dom/document.rs | 39 +++++++++++++----------- components/script/dom/htmlbodyelement.rs | 9 +++--- 2 files changed, 27 insertions(+), 21 deletions(-) diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs index c8adb924aec..2f42a3cfe60 100644 --- a/components/script/dom/document.rs +++ b/components/script/dom/document.rs @@ -327,7 +327,7 @@ pub struct Document { /// The current active HTML parser, to allow resuming after interruptions. current_parser: MutNullableDom, /// When we should kick off a reflow. This happens during parsing. - reflow_timeout: Cell>, + reflow_timeout: Cell>, /// The cached first `base` element with an `href` attribute. base_element: MutNullableDom, /// This field is set to the document itself for inert documents. @@ -898,27 +898,32 @@ impl Document { /// Reflows and disarms the timer if the reflow timer has expired. pub fn reflow_if_reflow_timer_expired(&self) { - if let Some(reflow_timeout) = self.reflow_timeout.get() { - if time::precise_time_ns() < reflow_timeout { - return; - } + let Some(reflow_timeout) = self.reflow_timeout.get() else { + return; + }; - self.reflow_timeout.set(None); - self.window - .reflow(ReflowGoal::Full, ReflowReason::RefreshTick); + if Instant::now() < reflow_timeout { + return; } + + self.reflow_timeout.set(None); + self.window + .reflow(ReflowGoal::Full, ReflowReason::RefreshTick); } - /// Schedules a reflow to be kicked off at the given `timeout` (in `time::precise_time_ns()` - /// units). This reflow happens even if the event loop is busy. This is used to display initial - /// page content during parsing. - pub fn set_reflow_timeout(&self, timeout: u64) { - if let Some(existing_timeout) = self.reflow_timeout.get() { - if existing_timeout < timeout { - return; - } + /// Schedules a reflow to be kicked off at the given [`Duration`] in the future. This reflow + /// happens even if the event loop is busy. This is used to display initial page content during + /// parsing. + pub fn set_reflow_timeout(&self, duration: Duration) { + let new_reflow_time = Instant::now() + duration; + + // Do not schedule a timeout that is longer than the one that is currently queued. + if matches!(self.reflow_timeout.get(), Some(existing_timeout) if existing_timeout < new_reflow_time) + { + return; } - self.reflow_timeout.set(Some(timeout)) + + self.reflow_timeout.set(Some(new_reflow_time)) } /// Remove any existing association between the provided id and any elements in this document. diff --git a/components/script/dom/htmlbodyelement.rs b/components/script/dom/htmlbodyelement.rs index a5b18210e1a..bc544e5491a 100644 --- a/components/script/dom/htmlbodyelement.rs +++ b/components/script/dom/htmlbodyelement.rs @@ -2,6 +2,8 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +use std::time::Duration; + use dom_struct::dom_struct; use embedder_traits::EmbedderMsg; use html5ever::{local_name, namespace_url, ns, LocalName, Prefix}; @@ -23,9 +25,8 @@ use crate::dom::htmlelement::HTMLElement; use crate::dom::node::{document_from_node, window_from_node, BindContext, Node}; use crate::dom::virtualmethods::VirtualMethods; -/// How long we should wait before performing the initial reflow after `` is parsed, in -/// nanoseconds. -const INITIAL_REFLOW_DELAY: u64 = 200_000_000; +/// How long we should wait before performing the initial reflow after `` is parsed. +const INITIAL_REFLOW_DELAY: Duration = Duration::from_millis(200); #[dom_struct] pub struct HTMLBodyElement { @@ -155,7 +156,7 @@ impl VirtualMethods for HTMLBodyElement { let window = window_from_node(self); let document = window.Document(); - document.set_reflow_timeout(time::precise_time_ns() + INITIAL_REFLOW_DELAY); + document.set_reflow_timeout(INITIAL_REFLOW_DELAY); if window.is_top_level() { let msg = EmbedderMsg::HeadParsed; window.send_to_embedder(msg);