script: Start replacing time with std::time and chrono (#30639)

* Replace `time` with `chrono` in `script/animation_timeline`

Signed-off-by: Auguste Baum <auguste.apple@gmail.com>

* Replace `time` with `std::time` in `script/script_thread.rs`

Signed-off-by: Auguste Baum <auguste.apple@gmail.com>

* Replace `time` with `std::time` and `chrono` in `script/script_thread.rs`

Signed-off-by: Auguste Baum <auguste.apple@gmail.com>

* Replace `time` with `std::time` in `script/script_runtime.rs`

Signed-off-by: Auguste Baum <auguste.apple@gmail.com>

* Replace `time` with `std::time` in `script/script_runtime.rs`

Signed-off-by: Auguste Baum <auguste.apple@gmail.com>

* Replace `time` with `std::time` in `script/dom/workerglobalscope.rs`

Signed-off-by: Auguste Baum <auguste.apple@gmail.com>

* Replace `time` with `chrono` in `script/dom/workerglobalscope.rs`

Signed-off-by: Auguste Baum <auguste.apple@gmail.com>

* Replace `time` with `std::time` in `script/dom/htmlmedialelement.rs`

Signed-off-by: Auguste Baum <auguste.apple@gmail.com>

* Replace `time` with `std::time` in `script/dom/htmlmedialelement.rs`

Signed-off-by: Auguste Baum <auguste.apple@gmail.com>

* Replace `time` with `std::time` in `script/dom/globalscope.rs`

Signed-off-by: Auguste Baum <auguste.apple@gmail.com>

* Replace `time` with `chrono` in `script/dom/globalscope.rs`

Signed-off-by: Auguste Baum <auguste.apple@gmail.com>

* Replace `time` with `std::time` in `script/dom/htmlformelement.rs`

Signed-off-by: Auguste Baum <auguste.apple@gmail.com>

* Replace `time` with `std::time` in `script/dom/htmlformelement.rs`

Signed-off-by: Auguste Baum <auguste.apple@gmail.com>

* Increase precision of animation timeline

* Some fixes

Use Instant a bit more and stop using chrono. Do not transition
`navigation_start_precise` to Instant yet as we need to coordinate this
across all crates.

---------

Signed-off-by: Auguste Baum <auguste.apple@gmail.com>
Co-authored-by: Martin Robinson <mrobinson@igalia.com>
This commit is contained in:
Auguste Baum 2024-01-16 13:23:18 +01:00 committed by GitHub
parent c06ae7faf2
commit 9654363c18
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 62 additions and 61 deletions

View file

@ -896,6 +896,8 @@ malloc_size_of_is_0!(time::Tm);
malloc_size_of_is_0!(std::time::Duration); malloc_size_of_is_0!(std::time::Duration);
#[cfg(feature = "servo")] #[cfg(feature = "servo")]
malloc_size_of_is_0!(std::time::SystemTime); malloc_size_of_is_0!(std::time::SystemTime);
#[cfg(feature = "servo")]
malloc_size_of_is_0!(std::time::Instant);
#[cfg(feature = "servo")] #[cfg(feature = "servo")]
impl<T> MallocSizeOf for hyper_serde::Serde<T> impl<T> MallocSizeOf for hyper_serde::Serde<T>

View file

@ -7,8 +7,9 @@
//! A timeline module, used to specify an `AnimationTimeline` which determines //! A timeline module, used to specify an `AnimationTimeline` which determines
//! the time used for synchronizing animations in the script thread. //! the time used for synchronizing animations in the script thread.
use std::time::{SystemTime, UNIX_EPOCH};
use jstraceable_derive::JSTraceable; use jstraceable_derive::JSTraceable;
use time;
/// A `AnimationTimeline` which is used to synchronize animations during the script /// A `AnimationTimeline` which is used to synchronize animations during the script
/// event loop. /// event loop.
@ -22,7 +23,10 @@ impl AnimationTimeline {
#[inline] #[inline]
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
current_value: time::precise_time_s(), current_value: SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap_or_default()
.as_secs_f64(),
} }
} }
@ -39,7 +43,10 @@ impl AnimationTimeline {
/// Updates the value of the `AnimationTimeline` to the current clock time. /// Updates the value of the `AnimationTimeline` to the current clock time.
pub fn update(&mut self) { pub fn update(&mut self) {
self.current_value = time::precise_time_s(); self.current_value = SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap_or_default()
.as_secs_f64();
} }
/// Increments the current value of the timeline by a specific number of seconds. /// Increments the current value of the timeline by a specific number of seconds.

View file

@ -11,6 +11,7 @@ use std::rc::Rc;
use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc; use std::sync::Arc;
use std::thread::JoinHandle; use std::thread::JoinHandle;
use std::time::Instant;
use std::{mem, ptr}; use std::{mem, ptr};
use content_security_policy::CspList; use content_security_policy::CspList;
@ -54,7 +55,6 @@ use script_traits::{
ScriptToConstellationChan, TimerEvent, TimerEventId, TimerSchedulerMsg, TimerSource, ScriptToConstellationChan, TimerEvent, TimerEventId, TimerSchedulerMsg, TimerSource,
}; };
use servo_url::{ImmutableOrigin, MutableOrigin, ServoUrl}; use servo_url::{ImmutableOrigin, MutableOrigin, ServoUrl};
use time::{get_time, Timespec};
use uuid::Uuid; use uuid::Uuid;
use webgpu::identity::WebGPUOpResult; use webgpu::identity::WebGPUOpResult;
use webgpu::{ErrorScopeId, WebGPUDevice}; use webgpu::{ErrorScopeId, WebGPUDevice};
@ -203,8 +203,8 @@ pub struct GlobalScope {
/// live updates from the worker. /// live updates from the worker.
devtools_wants_updates: Cell<bool>, devtools_wants_updates: Cell<bool>,
/// Timers used by the Console API. /// Timers (milliseconds) used by the Console API.
console_timers: DomRefCell<HashMap<DOMString, u64>>, console_timers: DomRefCell<HashMap<DOMString, Instant>>,
/// module map is used when importing JavaScript modules /// module map is used when importing JavaScript modules
/// https://html.spec.whatwg.org/multipage/#concept-settings-object-module-map /// https://html.spec.whatwg.org/multipage/#concept-settings-object-module-map
@ -2262,7 +2262,7 @@ impl GlobalScope {
} }
match timers.entry(label) { match timers.entry(label) {
Entry::Vacant(entry) => { Entry::Vacant(entry) => {
entry.insert(timestamp_in_ms(get_time())); entry.insert(Instant::now());
Ok(()) Ok(())
}, },
Entry::Occupied(_) => Err(()), Entry::Occupied(_) => Err(()),
@ -2274,7 +2274,7 @@ impl GlobalScope {
.borrow_mut() .borrow_mut()
.remove(label) .remove(label)
.ok_or(()) .ok_or(())
.map(|start| timestamp_in_ms(get_time()) - start) .map(|start| (Instant::now() - start).as_millis() as u64)
} }
/// Get an `&IpcSender<ScriptToDevtoolsControlMsg>` to send messages /// Get an `&IpcSender<ScriptToDevtoolsControlMsg>` to send messages
@ -3111,10 +3111,6 @@ impl GlobalScope {
} }
} }
fn timestamp_in_ms(time: Timespec) -> u64 {
(time.sec * 1000 + (time.nsec / 1000000) as i64) as u64
}
/// Returns the Rust global scope from a JS global object. /// Returns the Rust global scope from a JS global object.
#[allow(unsafe_code)] #[allow(unsafe_code)]
unsafe fn global_scope_from_global( unsafe fn global_scope_from_global(

View file

@ -4,6 +4,7 @@
use std::borrow::ToOwned; use std::borrow::ToOwned;
use std::cell::Cell; use std::cell::Cell;
use std::time::{Duration, Instant};
use dom_struct::dom_struct; use dom_struct::dom_struct;
use encoding_rs::{Encoding, UTF_8}; use encoding_rs::{Encoding, UTF_8};
@ -20,7 +21,6 @@ use servo_rand::random;
use style::attr::AttrValue; use style::attr::AttrValue;
use style::str::split_html_space_chars; use style::str::split_html_space_chars;
use style_traits::dom::ElementState; use style_traits::dom::ElementState;
use time::{now, Duration, Tm};
use super::bindings::trace::{HashMapTracedValues, NoTrace}; use super::bindings::trace::{HashMapTracedValues, NoTrace};
use crate::body::Extractable; use crate::body::Extractable;
@ -94,7 +94,7 @@ pub struct HTMLFormElement {
elements: DomOnceCell<HTMLFormControlsCollection>, elements: DomOnceCell<HTMLFormControlsCollection>,
generation_id: Cell<GenerationId>, generation_id: Cell<GenerationId>,
controls: DomRefCell<Vec<Dom<Element>>>, controls: DomRefCell<Vec<Dom<Element>>>,
past_names_map: DomRefCell<HashMapTracedValues<Atom, (Dom<Element>, NoTrace<Tm>)>>, past_names_map: DomRefCell<HashMapTracedValues<Atom, (Dom<Element>, NoTrace<Instant>)>>,
firing_submission_events: Cell<bool>, firing_submission_events: Cell<bool>,
rel_list: MutNullableDom<DOMTokenList>, rel_list: MutNullableDom<DOMTokenList>,
} }
@ -442,7 +442,7 @@ impl HTMLFormElementMethods for HTMLFormElement {
name, name,
( (
Dom::from_ref(&*element_node.downcast::<Element>().unwrap()), Dom::from_ref(&*element_node.downcast::<Element>().unwrap()),
NoTrace(now()), NoTrace(Instant::now()),
), ),
); );
@ -556,7 +556,7 @@ impl HTMLFormElementMethods for HTMLFormElement {
let entry = SourcedName { let entry = SourcedName {
name: key.clone(), name: key.clone(),
element: DomRoot::from_ref(&*val.0), element: DomRoot::from_ref(&*val.0),
source: SourcedNameSource::Past(now() - val.1 .0), // calculate difference now()-val.1 to find age source: SourcedNameSource::Past(Instant::now().duration_since(val.1 .0)),
}; };
sourced_names_vec.push(entry); sourced_names_vec.push(entry);
} }

View file

@ -6,6 +6,7 @@ use std::cell::Cell;
use std::collections::VecDeque; use std::collections::VecDeque;
use std::rc::Rc; use std::rc::Rc;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use std::time::{Duration, Instant};
use std::{f64, mem}; use std::{f64, mem};
use dom_struct::dom_struct; use dom_struct::dom_struct;
@ -33,7 +34,6 @@ use servo_media::player::video::{VideoFrame, VideoFrameRenderer};
use servo_media::player::{PlaybackState, Player, PlayerError, PlayerEvent, SeekLock, StreamType}; use servo_media::player::{PlaybackState, Player, PlayerError, PlayerEvent, SeekLock, StreamType};
use servo_media::{ClientContextId, ServoMedia, SupportsMediaType}; use servo_media::{ClientContextId, ServoMedia, SupportsMediaType};
use servo_url::ServoUrl; use servo_url::ServoUrl;
use time::{self, Duration, Timespec};
use webrender_api::{ use webrender_api::{
ExternalImageData, ExternalImageId, ExternalImageType, ImageBufferKind, ImageData, ExternalImageData, ExternalImageId, ExternalImageType, ImageBufferKind, ImageData,
ImageDescriptor, ImageDescriptorFlags, ImageFormat, ImageKey, ImageDescriptor, ImageDescriptorFlags, ImageFormat, ImageKey,
@ -377,9 +377,8 @@ pub struct HTMLMediaElement {
/// https://html.spec.whatwg.org/multipage/#dom-media-texttracks /// https://html.spec.whatwg.org/multipage/#dom-media-texttracks
text_tracks_list: MutNullableDom<TextTrackList>, text_tracks_list: MutNullableDom<TextTrackList>,
/// Time of last timeupdate notification. /// Time of last timeupdate notification.
#[ignore_malloc_size_of = "Defined in time"] #[ignore_malloc_size_of = "Defined in std::time"]
#[no_trace] next_timeupdate_event: Cell<Instant>,
next_timeupdate_event: Cell<Timespec>,
/// Latest fetch request context. /// Latest fetch request context.
current_fetch_context: DomRefCell<Option<HTMLMediaElementFetchContext>>, current_fetch_context: DomRefCell<Option<HTMLMediaElementFetchContext>>,
/// Player Id reported the player thread /// Player Id reported the player thread
@ -452,7 +451,7 @@ impl HTMLMediaElement {
audio_tracks_list: Default::default(), audio_tracks_list: Default::default(),
video_tracks_list: Default::default(), video_tracks_list: Default::default(),
text_tracks_list: Default::default(), text_tracks_list: Default::default(),
next_timeupdate_event: Cell::new(time::get_time() + Duration::milliseconds(250)), next_timeupdate_event: Cell::new(Instant::now() + Duration::from_millis(250)),
current_fetch_context: DomRefCell::new(None), current_fetch_context: DomRefCell::new(None),
id: Cell::new(0), id: Cell::new(0),
media_controls_id: DomRefCell::new(None), media_controls_id: DomRefCell::new(None),
@ -502,14 +501,14 @@ impl HTMLMediaElement {
/// https://html.spec.whatwg.org/multipage/#time-marches-on /// https://html.spec.whatwg.org/multipage/#time-marches-on
fn time_marches_on(&self) { fn time_marches_on(&self) {
// Step 6. // Step 6.
if time::get_time() > self.next_timeupdate_event.get() { if Instant::now() > self.next_timeupdate_event.get() {
let window = window_from_node(self); let window = window_from_node(self);
window window
.task_manager() .task_manager()
.media_element_task_source() .media_element_task_source()
.queue_simple_event(self.upcast(), atom!("timeupdate"), &window); .queue_simple_event(self.upcast(), atom!("timeupdate"), &window);
self.next_timeupdate_event self.next_timeupdate_event
.set(time::get_time() + Duration::milliseconds(350)); .set(Instant::now() + Duration::from_millis(350));
} }
} }
@ -2602,7 +2601,7 @@ struct HTMLMediaElementFetchListener {
/// The generation of the media element when this fetch started. /// The generation of the media element when this fetch started.
generation_id: u32, generation_id: u32,
/// Time of last progress notification. /// Time of last progress notification.
next_progress_event: Timespec, next_progress_event: Instant,
/// Timing data for this resource. /// Timing data for this resource.
resource_timing: ResourceFetchTiming, resource_timing: ResourceFetchTiming,
/// Url for the resource. /// Url for the resource.
@ -2751,13 +2750,13 @@ impl FetchResponseListener for HTMLMediaElementFetchListener {
// https://html.spec.whatwg.org/multipage/#concept-media-load-resource step 4, // https://html.spec.whatwg.org/multipage/#concept-media-load-resource step 4,
// => "If mode is remote" step 2 // => "If mode is remote" step 2
if time::get_time() > self.next_progress_event { if Instant::now() > self.next_progress_event {
let window = window_from_node(&*elem); let window = window_from_node(&*elem);
window window
.task_manager() .task_manager()
.media_element_task_source() .media_element_task_source()
.queue_simple_event(elem.upcast(), atom!("progress"), &window); .queue_simple_event(elem.upcast(), atom!("progress"), &window);
self.next_progress_event = time::get_time() + Duration::milliseconds(350); self.next_progress_event = Instant::now() + Duration::from_millis(350);
} }
} }
@ -2886,7 +2885,7 @@ impl HTMLMediaElementFetchListener {
elem: Trusted::new(elem), elem: Trusted::new(elem),
metadata: None, metadata: None,
generation_id: elem.generation_id.get(), generation_id: elem.generation_id.get(),
next_progress_event: time::get_time() + Duration::milliseconds(350), next_progress_event: Instant::now() + Duration::from_millis(350),
resource_timing: ResourceFetchTiming::new(ResourceTimingType::Resource), resource_timing: ResourceFetchTiming::new(ResourceTimingType::Resource),
url, url,
expected_content_length: None, expected_content_length: None,

View file

@ -15,7 +15,7 @@ use std::ops::Deref;
use std::os::raw::c_void; use std::os::raw::c_void;
use std::rc::Rc; use std::rc::Rc;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use std::time::Duration; use std::time::{Duration, Instant};
use std::{fmt, os, ptr, thread}; use std::{fmt, os, ptr, thread};
use js::glue::{ use js::glue::{
@ -50,7 +50,6 @@ use profile_traits::mem::{Report, ReportKind, ReportsChan};
use profile_traits::path; use profile_traits::path;
use servo_config::{opts, pref}; use servo_config::{opts, pref};
use style::thread_state::{self, ThreadState}; use style::thread_state::{self, ThreadState};
use time::{now, Tm};
use crate::body::BodyMixin; use crate::body::BodyMixin;
use crate::dom::bindings::codegen::Bindings::PromiseBinding::PromiseJobCallback; use crate::dom::bindings::codegen::Bindings::PromiseBinding::PromiseJobCallback;
@ -750,8 +749,8 @@ pub fn get_reports(cx: *mut RawJSContext, path_seg: String) -> Vec<Report> {
reports reports
} }
thread_local!(static GC_CYCLE_START: Cell<Option<Tm>> = Cell::new(None)); thread_local!(static GC_CYCLE_START: Cell<Option<Instant>> = Cell::new(None));
thread_local!(static GC_SLICE_START: Cell<Option<Tm>> = Cell::new(None)); thread_local!(static GC_SLICE_START: Cell<Option<Instant>> = Cell::new(None));
#[allow(unsafe_code)] #[allow(unsafe_code)]
unsafe extern "C" fn gc_slice_callback( unsafe extern "C" fn gc_slice_callback(
@ -761,22 +760,22 @@ unsafe extern "C" fn gc_slice_callback(
) { ) {
match progress { match progress {
GCProgress::GC_CYCLE_BEGIN => GC_CYCLE_START.with(|start| { GCProgress::GC_CYCLE_BEGIN => GC_CYCLE_START.with(|start| {
start.set(Some(now())); start.set(Some(Instant::now()));
println!("GC cycle began"); println!("GC cycle began");
}), }),
GCProgress::GC_SLICE_BEGIN => GC_SLICE_START.with(|start| { GCProgress::GC_SLICE_BEGIN => GC_SLICE_START.with(|start| {
start.set(Some(now())); start.set(Some(Instant::now()));
println!("GC slice began"); println!("GC slice began");
}), }),
GCProgress::GC_SLICE_END => GC_SLICE_START.with(|start| { GCProgress::GC_SLICE_END => GC_SLICE_START.with(|start| {
let dur = now() - start.get().unwrap(); let duration = start.get().unwrap().elapsed();
start.set(None); start.set(None);
println!("GC slice ended: duration={}", dur); println!("GC slice ended: duration={:?}", duration);
}), }),
GCProgress::GC_CYCLE_END => GC_CYCLE_START.with(|start| { GCProgress::GC_CYCLE_END => GC_CYCLE_START.with(|start| {
let dur = now() - start.get().unwrap(); let duration = start.get().unwrap().elapsed();
start.set(None); start.set(None);
println!("GC cycle ended: duration={}", dur); println!("GC cycle ended: duration={:?}", duration);
}), }),
}; };
if !desc.is_null() { if !desc.is_null() {

View file

@ -27,11 +27,12 @@ use std::rc::Rc;
use std::result::Result; use std::result::Result;
use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc; use std::sync::Arc;
use std::time::{Duration, SystemTime}; use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH};
use std::{ptr, thread}; use std::{ptr, thread};
use bluetooth_traits::BluetoothRequest; use bluetooth_traits::BluetoothRequest;
use canvas_traits::webgl::WebGLPipeline; use canvas_traits::webgl::WebGLPipeline;
use chrono::{DateTime, Local};
use crossbeam_channel::{select, unbounded, Receiver, Sender}; use crossbeam_channel::{select, unbounded, Receiver, Sender};
use devtools_traits::{ use devtools_traits::{
CSSError, DevtoolScriptControlMsg, DevtoolsPageInfo, NavigationState, CSSError, DevtoolScriptControlMsg, DevtoolsPageInfo, NavigationState,
@ -91,7 +92,7 @@ use servo_config::opts;
use servo_url::{ImmutableOrigin, MutableOrigin, ServoUrl}; use servo_url::{ImmutableOrigin, MutableOrigin, ServoUrl};
use style::dom::OpaqueNode; use style::dom::OpaqueNode;
use style::thread_state::{self, ThreadState}; use style::thread_state::{self, ThreadState};
use time::{at_utc, get_time, precise_time_ns, Timespec}; use time::precise_time_ns;
use url::Position; use url::Position;
use webgpu::identity::WebGPUMsg; use webgpu::identity::WebGPUMsg;
use webrender_api::units::LayoutPixel; use webrender_api::units::LayoutPixel;
@ -214,9 +215,9 @@ struct InProgressLoad {
/// The origin for the document /// The origin for the document
#[no_trace] #[no_trace]
origin: MutableOrigin, origin: MutableOrigin,
/// Timestamp reporting the time when the browser started this load. /// Timestamp reporting the time in milliseconds when the browser started this load.
navigation_start: u64, navigation_start: u64,
/// High res timestamp reporting the time when the browser started this load. /// High res timestamp reporting the time in nanoseconds when the browser started this load.
navigation_start_precise: u64, navigation_start_precise: u64,
/// For cancelling the fetch /// For cancelling the fetch
canceller: FetchCanceller, canceller: FetchCanceller,
@ -241,10 +242,15 @@ impl InProgressLoad {
layout_is_busy: Arc<AtomicBool>, layout_is_busy: Arc<AtomicBool>,
inherited_secure_context: Option<bool>, inherited_secure_context: Option<bool>,
) -> InProgressLoad { ) -> InProgressLoad {
let current_time = get_time(); let duration = SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap_or_default();
let navigation_start = duration.as_millis();
let navigation_start_precise = precise_time_ns(); let navigation_start_precise = precise_time_ns();
layout_chan layout_chan
.send(message::Msg::SetNavigationStart(navigation_start_precise)) .send(message::Msg::SetNavigationStart(
navigation_start_precise as u64,
))
.unwrap(); .unwrap();
InProgressLoad { InProgressLoad {
pipeline_id: id, pipeline_id: id,
@ -258,7 +264,7 @@ impl InProgressLoad {
is_visible: true, is_visible: true,
url: url, url: url,
origin: origin, origin: origin,
navigation_start: (current_time.sec * 1000 + current_time.nsec as i64 / 1000000) as u64, navigation_start: navigation_start as u64,
navigation_start_precise: navigation_start_precise, navigation_start_precise: navigation_start_precise,
canceller: Default::default(), canceller: Default::default(),
layout_is_busy: layout_is_busy, layout_is_busy: layout_is_busy,
@ -1864,7 +1870,7 @@ impl ScriptThread {
F: FnOnce() -> R, F: FnOnce() -> R,
{ {
self.notify_activity_to_hang_monitor(&category); self.notify_activity_to_hang_monitor(&category);
let start = precise_time_ns(); let start = Instant::now();
let value = if self.profile_script_events { let value = if self.profile_script_events {
let profiler_cat = match category { let profiler_cat = match category {
ScriptThreadEventCategory::AttachLayout => ProfilerCategory::ScriptAttachLayout, ScriptThreadEventCategory::AttachLayout => ProfilerCategory::ScriptAttachLayout,
@ -1911,15 +1917,15 @@ impl ScriptThread {
} else { } else {
f() f()
}; };
let end = precise_time_ns(); let task_duration = start.elapsed();
for (doc_id, doc) in self.documents.borrow().iter() { for (doc_id, doc) in self.documents.borrow().iter() {
if let Some(pipeline_id) = pipeline_id { if let Some(pipeline_id) = pipeline_id {
if pipeline_id == doc_id && end - start > MAX_TASK_NS { if pipeline_id == doc_id && task_duration.as_nanos() > MAX_TASK_NS.into() {
if self.print_pwm { if self.print_pwm {
println!( println!(
"Task took longer than max allowed ({:?}) {:?}", "Task took longer than max allowed ({:?}) {:?}",
category, category,
end - start task_duration.as_nanos()
); );
} }
doc.start_tti(); doc.start_tti();
@ -3351,9 +3357,11 @@ impl ScriptThread {
window.init_window_proxy(&window_proxy); window.init_window_proxy(&window_proxy);
let last_modified = metadata.headers.as_ref().and_then(|headers| { let last_modified = metadata.headers.as_ref().and_then(|headers| {
headers headers.typed_get::<LastModified>().map(|tm| {
.typed_get::<LastModified>() let tm: SystemTime = tm.into();
.map(|tm| dom_last_modified(&tm.into())) let local_time: DateTime<Local> = tm.into();
local_time.format("%m/%d/%Y %H:%M:%S").to_string()
})
}); });
let loader = DocumentLoader::new_with_threads( let loader = DocumentLoader::new_with_threads(
@ -4057,13 +4065,3 @@ impl Drop for ScriptThread {
}); });
} }
} }
fn dom_last_modified(tm: &SystemTime) -> String {
let tm = tm.duration_since(SystemTime::UNIX_EPOCH).unwrap();
let tm = Timespec::new(tm.as_secs() as i64, 0);
let tm = at_utc(tm);
tm.to_local()
.strftime("%m/%d/%Y %H:%M:%S")
.unwrap()
.to_string()
}