mirror of
https://github.com/servo/servo.git
synced 2025-08-03 12:40:06 +01:00
Make Performance Timeline API work in Workers
This commit is contained in:
parent
449ffb23ac
commit
fb843c251a
20 changed files with 146 additions and 128 deletions
|
@ -1586,7 +1586,7 @@ impl Document {
|
|||
|
||||
self.running_animation_callbacks.set(true);
|
||||
let was_faking_animation_frames = self.is_faking_animation_frames();
|
||||
let timing = self.window.Performance().Now();
|
||||
let timing = self.global().performance().Now();
|
||||
|
||||
for (_, callback) in animation_frame_list.drain(..) {
|
||||
if let Some(callback) = callback {
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
use devtools_traits::{ScriptToDevtoolsControlMsg, WorkerId};
|
||||
use dom::bindings::cell::DOMRefCell;
|
||||
use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
|
||||
use dom::bindings::codegen::Bindings::WorkerGlobalScopeBinding::WorkerGlobalScopeMethods;
|
||||
use dom::bindings::conversions::root_from_object;
|
||||
use dom::bindings::error::{ErrorInfo, report_pending_exception};
|
||||
use dom::bindings::inheritance::Castable;
|
||||
|
@ -17,6 +18,7 @@ use dom::dedicatedworkerglobalscope::DedicatedWorkerGlobalScope;
|
|||
use dom::errorevent::ErrorEvent;
|
||||
use dom::event::{Event, EventBubbles, EventCancelable, EventStatus};
|
||||
use dom::eventtarget::EventTarget;
|
||||
use dom::performance::Performance;
|
||||
use dom::window::Window;
|
||||
use dom::workerglobalscope::WorkerGlobalScope;
|
||||
use dom::workletglobalscope::WorkletGlobalScope;
|
||||
|
@ -46,6 +48,7 @@ use std::collections::hash_map::Entry;
|
|||
use std::ffi::CString;
|
||||
use task_source::file_reading::FileReadingTaskSource;
|
||||
use task_source::networking::NetworkingTaskSource;
|
||||
use task_source::performance_timeline::PerformanceTimelineTaskSource;
|
||||
use time::{Timespec, get_time};
|
||||
use timers::{IsInterval, OneshotTimerCallback, OneshotTimerHandle};
|
||||
use timers::{OneshotTimers, TimerCallback};
|
||||
|
@ -569,6 +572,29 @@ impl GlobalScope {
|
|||
pub fn incumbent() -> Option<Root<Self>> {
|
||||
incumbent_global()
|
||||
}
|
||||
|
||||
pub fn performance(&self) -> Root<Performance> {
|
||||
if let Some(window) = self.downcast::<Window>() {
|
||||
return window.Performance();
|
||||
}
|
||||
if let Some(worker) = self.downcast::<WorkerGlobalScope>() {
|
||||
return worker.Performance();
|
||||
}
|
||||
unreachable!();
|
||||
}
|
||||
|
||||
/// Channel to send messages to the performance timeline task source
|
||||
/// of this global scope.
|
||||
pub fn performance_timeline_task_source(&self) -> PerformanceTimelineTaskSource {
|
||||
if let Some(window) = self.downcast::<Window>() {
|
||||
return window.performance_timeline_task_source();
|
||||
}
|
||||
if let Some(worker) = self.downcast::<WorkerGlobalScope>() {
|
||||
return worker.performance_timeline_task_source();
|
||||
}
|
||||
unreachable!();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fn timestamp_in_ms(time: Timespec) -> u64 {
|
||||
|
|
|
@ -6,17 +6,17 @@ use dom::bindings::cell::DOMRefCell;
|
|||
use dom::bindings::codegen::Bindings::PerformanceBinding;
|
||||
use dom::bindings::codegen::Bindings::PerformanceBinding::{DOMHighResTimeStamp, PerformanceMethods};
|
||||
use dom::bindings::codegen::Bindings::PerformanceBinding::PerformanceEntryList as DOMPerformanceEntryList;
|
||||
use dom::bindings::inheritance::Castable;
|
||||
use dom::bindings::js::{JS, Root};
|
||||
use dom::bindings::num::Finite;
|
||||
use dom::bindings::refcounted::Trusted;
|
||||
use dom::bindings::reflector::{DomObject, Reflector, reflect_dom_object};
|
||||
use dom::bindings::str::DOMString;
|
||||
use dom::globalscope::GlobalScope;
|
||||
use dom::performanceentry::PerformanceEntry;
|
||||
use dom::performanceobserver::PerformanceObserver as DOMPerformanceObserver;
|
||||
use dom::performancetiming::PerformanceTiming;
|
||||
use dom::window::Window;
|
||||
use dom_struct::dom_struct;
|
||||
use script_thread::{Runnable, ScriptThread};
|
||||
use std::cell::Cell;
|
||||
use std::cmp::Ordering;
|
||||
use time;
|
||||
|
@ -64,34 +64,40 @@ struct PerformanceObserver {
|
|||
#[dom_struct]
|
||||
pub struct Performance {
|
||||
reflector_: Reflector,
|
||||
timing: JS<PerformanceTiming>,
|
||||
timing: Option<JS<PerformanceTiming>>,
|
||||
entries: DOMRefCell<PerformanceEntryList>,
|
||||
observers: DOMRefCell<Vec<PerformanceObserver>>,
|
||||
pending_notification_observers_task: Cell<bool>,
|
||||
navigation_start_precise: f64,
|
||||
}
|
||||
|
||||
impl Performance {
|
||||
fn new_inherited(window: &Window,
|
||||
fn new_inherited(global: &GlobalScope,
|
||||
navigation_start: u64,
|
||||
navigation_start_precise: f64) -> Performance {
|
||||
Performance {
|
||||
reflector_: Reflector::new(),
|
||||
timing: JS::from_ref(&*PerformanceTiming::new(window,
|
||||
navigation_start,
|
||||
navigation_start_precise)),
|
||||
timing: if global.is::<Window>() {
|
||||
Some(JS::from_ref(&*PerformanceTiming::new(global.as_window(),
|
||||
navigation_start,
|
||||
navigation_start_precise)))
|
||||
} else {
|
||||
None
|
||||
},
|
||||
entries: DOMRefCell::new(PerformanceEntryList::new(Vec::new())),
|
||||
observers: DOMRefCell::new(Vec::new()),
|
||||
pending_notification_observers_task: Cell::new(false),
|
||||
navigation_start_precise,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new(window: &Window,
|
||||
pub fn new(global: &GlobalScope,
|
||||
navigation_start: u64,
|
||||
navigation_start_precise: f64) -> Root<Performance> {
|
||||
reflect_dom_object(box Performance::new_inherited(window,
|
||||
reflect_dom_object(box Performance::new_inherited(global,
|
||||
navigation_start,
|
||||
navigation_start_precise),
|
||||
window,
|
||||
global,
|
||||
PerformanceBinding::Wrap)
|
||||
}
|
||||
|
||||
|
@ -168,17 +174,15 @@ impl Performance {
|
|||
// Step 6.
|
||||
// Queue a new notification task.
|
||||
self.pending_notification_observers_task.set(true);
|
||||
let global = self.global();
|
||||
let window = global.as_window();
|
||||
let task_source = window.performance_timeline_task_source();
|
||||
task_source.queue_notification(self, window);
|
||||
let task_source = self.global().performance_timeline_task_source();
|
||||
task_source.queue_notification(&self.global());
|
||||
}
|
||||
|
||||
/// Observers notifications task.
|
||||
///
|
||||
/// Algorithm spec (step 7):
|
||||
/// https://w3c.github.io/performance-timeline/#queue-a-performanceentry
|
||||
fn notify_observers(&self) {
|
||||
pub fn notify_observers(&self) {
|
||||
// Step 7.1.
|
||||
self.pending_notification_observers_task.set(false);
|
||||
|
||||
|
@ -200,34 +204,21 @@ impl Performance {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct NotifyPerformanceObserverRunnable {
|
||||
owner: Trusted<Performance>,
|
||||
}
|
||||
|
||||
impl NotifyPerformanceObserverRunnable {
|
||||
pub fn new(owner: Trusted<Performance>) -> Self {
|
||||
NotifyPerformanceObserverRunnable {
|
||||
owner,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Runnable for NotifyPerformanceObserverRunnable {
|
||||
fn main_thread_handler(self: Box<NotifyPerformanceObserverRunnable>,
|
||||
_: &ScriptThread) {
|
||||
self.owner.root().notify_observers();
|
||||
}
|
||||
}
|
||||
|
||||
impl PerformanceMethods for Performance {
|
||||
// https://dvcs.w3.org/hg/webperf/raw-file/tip/specs/NavigationTiming/Overview.html#performance-timing-attribute
|
||||
fn Timing(&self) -> Root<PerformanceTiming> {
|
||||
Root::from_ref(&*self.timing)
|
||||
match self.timing {
|
||||
Some(ref timing) => Root::from_ref(&*timing),
|
||||
None => unreachable!("Are we trying to expose Performance.timing in workers?"),
|
||||
}
|
||||
}
|
||||
|
||||
// https://dvcs.w3.org/hg/webperf/raw-file/tip/specs/HighResolutionTime/Overview.html#dom-performance-now
|
||||
fn Now(&self) -> DOMHighResTimeStamp {
|
||||
let nav_start = self.timing.navigation_start_precise();
|
||||
let nav_start = match self.timing {
|
||||
Some(ref timing) => timing.navigation_start_precise(),
|
||||
None => self.navigation_start_precise,
|
||||
};
|
||||
let now = (time::precise_time_ns() as f64 - nav_start) / 1000000 as f64;
|
||||
Finite::wrap(now)
|
||||
}
|
||||
|
|
|
@ -9,7 +9,6 @@ use dom::bindings::codegen::Bindings::PerformanceObserverBinding;
|
|||
use dom::bindings::codegen::Bindings::PerformanceObserverBinding::PerformanceObserverCallback;
|
||||
use dom::bindings::codegen::Bindings::PerformanceObserverBinding::PerformanceObserverInit;
|
||||
use dom::bindings::codegen::Bindings::PerformanceObserverBinding::PerformanceObserverMethods;
|
||||
use dom::bindings::codegen::Bindings::WindowBinding::WindowBinding::WindowMethods;
|
||||
use dom::bindings::error::{Error, Fallible};
|
||||
use dom::bindings::js::Root;
|
||||
use dom::bindings::reflector::{DomObject, Reflector, reflect_dom_object};
|
||||
|
@ -51,8 +50,8 @@ impl PerformanceObserver {
|
|||
|
||||
#[allow(unrooted_must_root)]
|
||||
pub fn new(global: &GlobalScope,
|
||||
callback: Rc<PerformanceObserverCallback>,
|
||||
entries: DOMPerformanceEntryList)
|
||||
callback: Rc<PerformanceObserverCallback>,
|
||||
entries: DOMPerformanceEntryList)
|
||||
-> Root<PerformanceObserver> {
|
||||
let observer = PerformanceObserver::new_inherited(callback, DOMRefCell::new(entries));
|
||||
reflect_dom_object(box observer, global, PerformanceObserverBinding::Wrap)
|
||||
|
@ -110,15 +109,15 @@ impl PerformanceObserverMethods for PerformanceObserver {
|
|||
return Err((Error::Type("entryTypes cannot be empty".to_string())));
|
||||
}
|
||||
|
||||
let performance = self.global().as_window().Performance();
|
||||
// step 3-4-5
|
||||
performance.add_observer(self, entry_types, options.buffered);
|
||||
self.global().performance().add_observer(self, entry_types, options.buffered);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// https://w3c.github.io/performance-timeline/#dom-performanceobserver-disconnect()
|
||||
fn Disconnect(&self) {
|
||||
self.global().as_window().Performance().remove_observer(self);
|
||||
self.global().performance().remove_observer(self);
|
||||
self.entries.borrow_mut().clear();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,17 +9,19 @@
|
|||
typedef double DOMHighResTimeStamp;
|
||||
typedef sequence<PerformanceEntry> PerformanceEntryList;
|
||||
|
||||
[Exposed=(Window,Worker)]
|
||||
[Exposed=(Window, Worker)]
|
||||
interface Performance {
|
||||
DOMHighResTimeStamp now();
|
||||
};
|
||||
|
||||
[Exposed=(Window)]
|
||||
partial interface Performance {
|
||||
readonly attribute PerformanceTiming timing;
|
||||
/* readonly attribute PerformanceNavigation navigation; */
|
||||
};
|
||||
|
||||
partial interface Performance {
|
||||
DOMHighResTimeStamp now();
|
||||
};
|
||||
|
||||
// https://w3c.github.io/performance-timeline/#extensions-to-the-performance-interface
|
||||
[Exposed=(Window, Worker)]
|
||||
partial interface Performance {
|
||||
PerformanceEntryList getEntries();
|
||||
PerformanceEntryList getEntriesByType(DOMString type);
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
* https://dvcs.w3.org/hg/webperf/raw-file/tip/specs/NavigationTiming/Overview.html#sec-navigation-timing-interface
|
||||
*/
|
||||
|
||||
[Exposed=(Window,Worker)]
|
||||
[Exposed=(Window)]
|
||||
interface PerformanceTiming {
|
||||
readonly attribute unsigned long long navigationStart;
|
||||
/* readonly attribute unsigned long long unloadEventStart;
|
||||
|
|
|
@ -98,11 +98,6 @@ interface WindowBase64 {
|
|||
};
|
||||
Window implements WindowBase64;
|
||||
|
||||
// https://dvcs.w3.org/hg/webperf/raw-file/tip/specs/NavigationTiming/Overview.html#sec-window.performance-attribute
|
||||
partial interface Window {
|
||||
[Replaceable] readonly attribute Performance performance;
|
||||
};
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#Window-partial
|
||||
partial interface Window {
|
||||
void captureEvents();
|
||||
|
|
|
@ -26,5 +26,11 @@ interface WindowOrWorkerGlobalScope {
|
|||
// ImageBitmapSource image, long sx, long sy, long sw, long sh, optional ImageBitmapOptions options);
|
||||
};
|
||||
|
||||
// https://w3c.github.io/hr-time/#the-performance-attribute
|
||||
partial interface WindowOrWorkerGlobalScope {
|
||||
[Replaceable]
|
||||
readonly attribute Performance performance;
|
||||
};
|
||||
|
||||
Window implements WindowOrWorkerGlobalScope;
|
||||
WorkerGlobalScope implements WindowOrWorkerGlobalScope;
|
||||
|
|
|
@ -710,7 +710,8 @@ impl WindowMethods for Window {
|
|||
// NavigationTiming/Overview.html#sec-window.performance-attribute
|
||||
fn Performance(&self) -> Root<Performance> {
|
||||
self.performance.or_init(|| {
|
||||
Performance::new(self, self.navigation_start.get(),
|
||||
let global_scope = self.upcast::<GlobalScope>();
|
||||
Performance::new(global_scope, self.navigation_start.get(),
|
||||
self.navigation_start_precise.get())
|
||||
})
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ use dom::bindings::trace::RootedTraceableBox;
|
|||
use dom::crypto::Crypto;
|
||||
use dom::dedicatedworkerglobalscope::DedicatedWorkerGlobalScope;
|
||||
use dom::globalscope::GlobalScope;
|
||||
use dom::performance::Performance;
|
||||
use dom::promise::Promise;
|
||||
use dom::serviceworkerglobalscope::ServiceWorkerGlobalScope;
|
||||
use dom::window::{base64_atob, base64_btoa};
|
||||
|
@ -44,6 +45,8 @@ use std::sync::atomic::{AtomicBool, Ordering};
|
|||
use std::sync::mpsc::Receiver;
|
||||
use task_source::file_reading::FileReadingTaskSource;
|
||||
use task_source::networking::NetworkingTaskSource;
|
||||
use task_source::performance_timeline::PerformanceTimelineTaskSource;
|
||||
use time::precise_time_ns;
|
||||
use timers::{IsInterval, TimerCallback};
|
||||
|
||||
pub fn prepare_workerscope_init(global: &GlobalScope,
|
||||
|
@ -89,6 +92,9 @@ pub struct WorkerGlobalScope {
|
|||
from_devtools_receiver: Receiver<DevtoolScriptControlMsg>,
|
||||
|
||||
microtask_queue: MicrotaskQueue,
|
||||
|
||||
navigation_start_precise: f64,
|
||||
performance: MutNullableJS<Performance>,
|
||||
}
|
||||
|
||||
impl WorkerGlobalScope {
|
||||
|
@ -120,6 +126,8 @@ impl WorkerGlobalScope {
|
|||
from_devtools_sender: init.from_devtools_sender,
|
||||
from_devtools_receiver: from_devtools_receiver,
|
||||
microtask_queue: MicrotaskQueue::default(),
|
||||
navigation_start_precise: precise_time_ns() as f64,
|
||||
performance: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -320,6 +328,16 @@ impl WorkerGlobalScopeMethods for WorkerGlobalScope {
|
|||
fn Fetch(&self, input: RequestOrUSVString, init: RootedTraceableBox<RequestInit>) -> Rc<Promise> {
|
||||
fetch::Fetch(self.upcast(), input, init)
|
||||
}
|
||||
|
||||
// https://w3c.github.io/hr-time/#the-performance-attribute
|
||||
fn Performance(&self) -> Root<Performance> {
|
||||
self.performance.or_init(|| {
|
||||
let global_scope = self.upcast::<GlobalScope>();
|
||||
Performance::new(global_scope,
|
||||
0 /* navigation start is not used in workers */,
|
||||
self.navigation_start_precise)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -368,6 +386,10 @@ impl WorkerGlobalScope {
|
|||
NetworkingTaskSource(self.script_chan())
|
||||
}
|
||||
|
||||
pub fn performance_timeline_task_source(&self) -> PerformanceTimelineTaskSource {
|
||||
PerformanceTimelineTaskSource(self.script_chan())
|
||||
}
|
||||
|
||||
pub fn new_script_pair(&self) -> (Box<ScriptChan + Send>, Box<ScriptPort + Send>) {
|
||||
let dedicated = self.downcast::<DedicatedWorkerGlobalScope>();
|
||||
if let Some(dedicated) = dedicated {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue