diff --git a/components/script/dom/event.rs b/components/script/dom/event.rs index 561022f0f3a6..3c6bf956e9e5 100644 --- a/components/script/dom/event.rs +++ b/components/script/dom/event.rs @@ -10,7 +10,6 @@ use crate::dom::bindings::codegen::Bindings::PerformanceBinding::DOMHighResTimeS use crate::dom::bindings::codegen::Bindings::PerformanceBinding::PerformanceBinding::PerformanceMethods; use crate::dom::bindings::error::Fallible; use crate::dom::bindings::inheritance::Castable; -use crate::dom::bindings::num::Finite; use crate::dom::bindings::refcounted::Trusted; use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector}; use crate::dom::bindings::root::{DomRoot, DomSlice, MutNullableDom}; @@ -19,6 +18,7 @@ use crate::dom::document::Document; use crate::dom::eventtarget::{CompiledEventListener, EventTarget, ListenerPhase}; use crate::dom::globalscope::GlobalScope; use crate::dom::node::Node; +use crate::dom::performance::reduce_timing_resolution; use crate::dom::virtualmethods::vtable_for; use crate::dom::window::Window; use crate::task::TaskOnce; @@ -333,7 +333,7 @@ impl EventMethods for Event { // https://dom.spec.whatwg.org/#dom-event-timestamp fn TimeStamp(&self) -> DOMHighResTimeStamp { - Finite::wrap( + reduce_timing_resolution( (self.precise_time_ns - (*self.global().performance().TimeOrigin()).round() as u64) .to_ms(), ) diff --git a/components/script/dom/performance.rs b/components/script/dom/performance.rs index b1f72f405f2c..33e39303cb48 100644 --- a/components/script/dom/performance.rs +++ b/components/script/dom/performance.rs @@ -401,12 +401,12 @@ impl PerformanceMethods for Performance { // https://dvcs.w3.org/hg/webperf/raw-file/tip/specs/HighResolutionTime/Overview.html#dom-performance-now fn Now(&self) -> DOMHighResTimeStamp { - Finite::wrap(self.now()) + reduce_timing_resolution(self.now()) } // https://www.w3.org/TR/hr-time-2/#dom-performance-timeorigin fn TimeOrigin(&self) -> DOMHighResTimeStamp { - Finite::wrap(self.navigation_start_precise as f64) + reduce_timing_resolution(self.navigation_start_precise as f64) } // https://www.w3.org/TR/performance-timeline-2/#dom-performance-getentries @@ -525,3 +525,14 @@ impl PerformanceMethods for Performance { SetOnresourcetimingbufferfull ); } + +// https://www.w3.org/TR/hr-time-2/#clock-resolution +pub fn reduce_timing_resolution(exact: f64) -> DOMHighResTimeStamp { + // We need a granularity no finer than 5 microseconds. + // 5 microseconds isn't an exactly representable f64 so WPT tests + // might occasionally corner-case on rounding. + // web-platform-tests/wpt#21526 wants us to use an integer number of + // microseconds; the next divisor of milliseconds up from 5 microseconds + // is 10, which is 1/100th of a millisecond. + Finite::wrap((exact * 100.0).floor() / 100.0) +} diff --git a/components/script/dom/performanceentry.rs b/components/script/dom/performanceentry.rs index 334d8b6de855..e41cbc81667f 100644 --- a/components/script/dom/performanceentry.rs +++ b/components/script/dom/performanceentry.rs @@ -2,13 +2,14 @@ * 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 crate::dom::bindings::codegen::Bindings::PerformanceBinding::DOMHighResTimeStamp; use crate::dom::bindings::codegen::Bindings::PerformanceEntryBinding; use crate::dom::bindings::codegen::Bindings::PerformanceEntryBinding::PerformanceEntryMethods; -use crate::dom::bindings::num::Finite; use crate::dom::bindings::reflector::{reflect_dom_object, Reflector}; use crate::dom::bindings::root::DomRoot; use crate::dom::bindings::str::DOMString; use crate::dom::globalscope::GlobalScope; +use crate::dom::performance::reduce_timing_resolution; use dom_struct::dom_struct; #[dom_struct] @@ -77,12 +78,12 @@ impl PerformanceEntryMethods for PerformanceEntry { } // https://w3c.github.io/performance-timeline/#dom-performanceentry-starttime - fn StartTime(&self) -> Finite { - Finite::wrap(self.start_time) + fn StartTime(&self) -> DOMHighResTimeStamp { + reduce_timing_resolution(self.start_time) } // https://w3c.github.io/performance-timeline/#dom-performanceentry-duration - fn Duration(&self) -> Finite { - Finite::wrap(self.duration) + fn Duration(&self) -> DOMHighResTimeStamp { + reduce_timing_resolution(self.duration) } } diff --git a/components/script/dom/performanceresourcetiming.rs b/components/script/dom/performanceresourcetiming.rs index 586515d4365a..574016adc88c 100644 --- a/components/script/dom/performanceresourcetiming.rs +++ b/components/script/dom/performanceresourcetiming.rs @@ -6,11 +6,11 @@ use crate::dom::bindings::codegen::Bindings::PerformanceBinding::DOMHighResTimeS use crate::dom::bindings::codegen::Bindings::PerformanceResourceTimingBinding::{ self, PerformanceResourceTimingMethods, }; -use crate::dom::bindings::num::Finite; use crate::dom::bindings::reflector::reflect_dom_object; use crate::dom::bindings::root::DomRoot; use crate::dom::bindings::str::DOMString; use crate::dom::globalscope::GlobalScope; +use crate::dom::performance::reduce_timing_resolution; use crate::dom::performanceentry::PerformanceEntry; use dom_struct::dom_struct; use net_traits::ResourceFetchTiming; @@ -182,17 +182,17 @@ impl PerformanceResourceTimingMethods for PerformanceResourceTiming { // https://w3c.github.io/resource-timing/#dom-performanceresourcetiming-domainlookupstart fn DomainLookupStart(&self) -> DOMHighResTimeStamp { - Finite::wrap(self.domain_lookup_start) + reduce_timing_resolution(self.domain_lookup_start) } // https://w3c.github.io/resource-timing/#dom-performanceresourcetiming-domainlookupend fn DomainLookupEnd(&self) -> DOMHighResTimeStamp { - Finite::wrap(self.domain_lookup_end) + reduce_timing_resolution(self.domain_lookup_end) } // https://w3c.github.io/resource-timing/#dom-performanceresourcetiming-secureconnectionstart fn SecureConnectionStart(&self) -> DOMHighResTimeStamp { - Finite::wrap(self.secure_connection_start) + reduce_timing_resolution(self.secure_connection_start) } // https://w3c.github.io/resource-timing/#dom-performanceresourcetiming-transfersize @@ -212,41 +212,41 @@ impl PerformanceResourceTimingMethods for PerformanceResourceTiming { // https://w3c.github.io/resource-timing/#dom-performanceresourcetiming-requeststart fn RequestStart(&self) -> DOMHighResTimeStamp { - Finite::wrap(self.request_start) + reduce_timing_resolution(self.request_start) } // https://w3c.github.io/resource-timing/#dom-performanceresourcetiming-redirectstart fn RedirectStart(&self) -> DOMHighResTimeStamp { - Finite::wrap(self.redirect_start) + reduce_timing_resolution(self.redirect_start) } // https://w3c.github.io/resource-timing/#dom-performanceresourcetiming-redirectend fn RedirectEnd(&self) -> DOMHighResTimeStamp { - Finite::wrap(self.redirect_end) + reduce_timing_resolution(self.redirect_end) } // https://w3c.github.io/resource-timing/#dom-performanceresourcetiming-responsestart fn ResponseStart(&self) -> DOMHighResTimeStamp { - Finite::wrap(self.response_start) + reduce_timing_resolution(self.response_start) } // https://w3c.github.io/resource-timing/#dom-performanceresourcetiming-fetchstart fn FetchStart(&self) -> DOMHighResTimeStamp { - Finite::wrap(self.fetch_start) + reduce_timing_resolution(self.fetch_start) } // https://w3c.github.io/resource-timing/#dom-performanceresourcetiming-connectstart fn ConnectStart(&self) -> DOMHighResTimeStamp { - Finite::wrap(self.connect_start) + reduce_timing_resolution(self.connect_start) } // https://w3c.github.io/resource-timing/#dom-performanceresourcetiming-connectend fn ConnectEnd(&self) -> DOMHighResTimeStamp { - Finite::wrap(self.connect_end) + reduce_timing_resolution(self.connect_end) } // https://w3c.github.io/resource-timing/#dom-performanceresourcetiming-responseend fn ResponseEnd(&self) -> DOMHighResTimeStamp { - Finite::wrap(self.response_end) + reduce_timing_resolution(self.response_end) } } diff --git a/components/script/dom/vrframedata.rs b/components/script/dom/vrframedata.rs index d4e92433f109..32af3b394ef5 100644 --- a/components/script/dom/vrframedata.rs +++ b/components/script/dom/vrframedata.rs @@ -2,13 +2,14 @@ * 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 crate::dom::bindings::codegen::Bindings::PerformanceBinding::DOMHighResTimeStamp; use crate::dom::bindings::codegen::Bindings::VRFrameDataBinding; use crate::dom::bindings::codegen::Bindings::VRFrameDataBinding::VRFrameDataMethods; use crate::dom::bindings::error::Fallible; -use crate::dom::bindings::num::Finite; use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector}; use crate::dom::bindings::root::{Dom, DomRoot}; use crate::dom::globalscope::GlobalScope; +use crate::dom::performance::reduce_timing_resolution; use crate::dom::vrpose::VRPose; use crate::dom::window::Window; use crate::script_runtime::JSContext; @@ -119,8 +120,8 @@ impl VRFrameData { impl VRFrameDataMethods for VRFrameData { // https://w3c.github.io/webvr/#dom-vrframedata-timestamp - fn Timestamp(&self) -> Finite { - Finite::wrap(self.timestamp.get() - self.first_timestamp.get()) + fn Timestamp(&self) -> DOMHighResTimeStamp { + reduce_timing_resolution(self.timestamp.get() - self.first_timestamp.get()) } #[allow(unsafe_code)] diff --git a/components/script/dom/xrsession.rs b/components/script/dom/xrsession.rs index 4814eb379fff..68fe5a442fdb 100644 --- a/components/script/dom/xrsession.rs +++ b/components/script/dom/xrsession.rs @@ -19,7 +19,6 @@ use crate::dom::bindings::codegen::Bindings::XRSessionBinding::XRVisibilityState use crate::dom::bindings::codegen::Bindings::XRWebGLLayerBinding::XRWebGLLayerMethods; use crate::dom::bindings::error::{Error, ErrorResult}; use crate::dom::bindings::inheritance::Castable; -use crate::dom::bindings::num::Finite; use crate::dom::bindings::refcounted::Trusted; use crate::dom::bindings::reflector::{reflect_dom_object, DomObject}; use crate::dom::bindings::root::{Dom, DomRoot, MutDom, MutNullableDom}; @@ -28,6 +27,7 @@ use crate::dom::eventtarget::EventTarget; use crate::dom::globalscope::GlobalScope; use crate::dom::node::Node; use crate::dom::node::NodeDamage; +use crate::dom::performance::reduce_timing_resolution; use crate::dom::promise::Promise; use crate::dom::xrframe::XRFrame; use crate::dom::xrinputsourcearray::XRInputSourceArray; @@ -336,7 +336,7 @@ impl XRSession { // Step 4-5 let mut callbacks = mem::replace(&mut *self.raf_callback_list.borrow_mut(), vec![]); let start = self.global().as_window().get_navigation_start(); - let time = (frame.time_ns - start).to_ms(); + let time = reduce_timing_resolution((frame.time_ns - start).to_ms()); let frame = XRFrame::new(&self.global(), self, frame); // Step 6,7 @@ -347,7 +347,7 @@ impl XRSession { self.outside_raf.set(false); for (_, callback) in callbacks.drain(..) { if let Some(callback) = callback { - let _ = callback.Call__(Finite::wrap(time), &frame, ExceptionHandling::Report); + let _ = callback.Call__(time, &frame, ExceptionHandling::Report); } } self.outside_raf.set(true); diff --git a/tests/wpt/metadata/dom/events/Event-timestamp-safe-resolution.html.ini b/tests/wpt/metadata/dom/events/Event-timestamp-safe-resolution.html.ini deleted file mode 100644 index eba00488f661..000000000000 --- a/tests/wpt/metadata/dom/events/Event-timestamp-safe-resolution.html.ini +++ /dev/null @@ -1,6 +0,0 @@ -[Event-timestamp-safe-resolution.html] - type: testharness - - [Event timestamp should not have a resolution better than 5 microseconds] - expected: FAIL - diff --git a/tests/wpt/metadata/performance-timeline/webtiming-resolution.any.js.ini b/tests/wpt/metadata/performance-timeline/webtiming-resolution.any.js.ini deleted file mode 100644 index 97f8a0cc51f1..000000000000 --- a/tests/wpt/metadata/performance-timeline/webtiming-resolution.any.js.ini +++ /dev/null @@ -1,15 +0,0 @@ -[webtiming-resolution.any.html] - [Verifies the resolution of performance.now() is at least 5 microseconds.] - expected: FAIL - - -[webtiming-resolution.any.worker.html] - [Verifies the resolution of performance.now() is at least 20 microseconds.] - expected: FAIL - - [Verifies the resolution of entry.startTime is at least 20 microseconds.] - expected: TIMEOUT - - [Verifies the resolution of performance.now() is at least 5 microseconds.] - expected: FAIL - diff --git a/tests/wpt/mozilla/meta/MANIFEST.json b/tests/wpt/mozilla/meta/MANIFEST.json index 145f8189f022..b6843add8821 100644 --- a/tests/wpt/mozilla/meta/MANIFEST.json +++ b/tests/wpt/mozilla/meta/MANIFEST.json @@ -19708,7 +19708,7 @@ "testharness" ], "mozilla/window_performance.html": [ - "302073e8041763102d678326509d7ef0a1fb5c79", + "c1e38a1e00147caf82492dc82f1cb5e85759f8e3", "testharness" ], "mozilla/window_performance_topLevelDomComplete.html": [ diff --git a/tests/wpt/mozilla/tests/mozilla/window_performance.html b/tests/wpt/mozilla/tests/mozilla/window_performance.html index 302073e80417..c1e38a1e0014 100644 --- a/tests/wpt/mozilla/tests/mozilla/window_performance.html +++ b/tests/wpt/mozilla/tests/mozilla/window_performance.html @@ -27,12 +27,15 @@ var last = window.performance.now(); assert_greater_than(last, 0); - // Check that window.performance.now() is monotonically increasing + // Check that window.performance.now() is monotonically nondecreasing + // and eventually increases + var before_loop = window.performance.now(); for (var i = 0; i < 100; i++) { var next = window.performance.now(); - assert_greater_than(next, last); + assert_greater_than_equal(next, last); last = next; } + assert_greater_than(last, before_loop, "If this fails, either performance timing is broken, or Servo JS execution has gotten much faster since this test was written."); });