mirror of
https://github.com/servo/servo.git
synced 2025-06-06 16:45:39 +00:00
Expose DOMHighResTimeStamps at lower res
This commit is contained in:
parent
5f55cd5d71
commit
8e65782efb
10 changed files with 46 additions and 51 deletions
|
@ -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::codegen::Bindings::PerformanceBinding::PerformanceBinding::PerformanceMethods;
|
||||||
use crate::dom::bindings::error::Fallible;
|
use crate::dom::bindings::error::Fallible;
|
||||||
use crate::dom::bindings::inheritance::Castable;
|
use crate::dom::bindings::inheritance::Castable;
|
||||||
use crate::dom::bindings::num::Finite;
|
|
||||||
use crate::dom::bindings::refcounted::Trusted;
|
use crate::dom::bindings::refcounted::Trusted;
|
||||||
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector};
|
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector};
|
||||||
use crate::dom::bindings::root::{DomRoot, DomSlice, MutNullableDom};
|
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::eventtarget::{CompiledEventListener, EventTarget, ListenerPhase};
|
||||||
use crate::dom::globalscope::GlobalScope;
|
use crate::dom::globalscope::GlobalScope;
|
||||||
use crate::dom::node::Node;
|
use crate::dom::node::Node;
|
||||||
|
use crate::dom::performance::reduce_timing_resolution;
|
||||||
use crate::dom::virtualmethods::vtable_for;
|
use crate::dom::virtualmethods::vtable_for;
|
||||||
use crate::dom::window::Window;
|
use crate::dom::window::Window;
|
||||||
use crate::task::TaskOnce;
|
use crate::task::TaskOnce;
|
||||||
|
@ -333,7 +333,7 @@ impl EventMethods for Event {
|
||||||
|
|
||||||
// https://dom.spec.whatwg.org/#dom-event-timestamp
|
// https://dom.spec.whatwg.org/#dom-event-timestamp
|
||||||
fn TimeStamp(&self) -> DOMHighResTimeStamp {
|
fn TimeStamp(&self) -> DOMHighResTimeStamp {
|
||||||
Finite::wrap(
|
reduce_timing_resolution(
|
||||||
(self.precise_time_ns - (*self.global().performance().TimeOrigin()).round() as u64)
|
(self.precise_time_ns - (*self.global().performance().TimeOrigin()).round() as u64)
|
||||||
.to_ms(),
|
.to_ms(),
|
||||||
)
|
)
|
||||||
|
|
|
@ -401,12 +401,12 @@ impl PerformanceMethods for Performance {
|
||||||
|
|
||||||
// https://dvcs.w3.org/hg/webperf/raw-file/tip/specs/HighResolutionTime/Overview.html#dom-performance-now
|
// https://dvcs.w3.org/hg/webperf/raw-file/tip/specs/HighResolutionTime/Overview.html#dom-performance-now
|
||||||
fn Now(&self) -> DOMHighResTimeStamp {
|
fn Now(&self) -> DOMHighResTimeStamp {
|
||||||
Finite::wrap(self.now())
|
reduce_timing_resolution(self.now())
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://www.w3.org/TR/hr-time-2/#dom-performance-timeorigin
|
// https://www.w3.org/TR/hr-time-2/#dom-performance-timeorigin
|
||||||
fn TimeOrigin(&self) -> DOMHighResTimeStamp {
|
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
|
// https://www.w3.org/TR/performance-timeline-2/#dom-performance-getentries
|
||||||
|
@ -525,3 +525,14 @@ impl PerformanceMethods for Performance {
|
||||||
SetOnresourcetimingbufferfull
|
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)
|
||||||
|
}
|
||||||
|
|
|
@ -2,13 +2,14 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* 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;
|
||||||
use crate::dom::bindings::codegen::Bindings::PerformanceEntryBinding::PerformanceEntryMethods;
|
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::reflector::{reflect_dom_object, Reflector};
|
||||||
use crate::dom::bindings::root::DomRoot;
|
use crate::dom::bindings::root::DomRoot;
|
||||||
use crate::dom::bindings::str::DOMString;
|
use crate::dom::bindings::str::DOMString;
|
||||||
use crate::dom::globalscope::GlobalScope;
|
use crate::dom::globalscope::GlobalScope;
|
||||||
|
use crate::dom::performance::reduce_timing_resolution;
|
||||||
use dom_struct::dom_struct;
|
use dom_struct::dom_struct;
|
||||||
|
|
||||||
#[dom_struct]
|
#[dom_struct]
|
||||||
|
@ -77,12 +78,12 @@ impl PerformanceEntryMethods for PerformanceEntry {
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://w3c.github.io/performance-timeline/#dom-performanceentry-starttime
|
// https://w3c.github.io/performance-timeline/#dom-performanceentry-starttime
|
||||||
fn StartTime(&self) -> Finite<f64> {
|
fn StartTime(&self) -> DOMHighResTimeStamp {
|
||||||
Finite::wrap(self.start_time)
|
reduce_timing_resolution(self.start_time)
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://w3c.github.io/performance-timeline/#dom-performanceentry-duration
|
// https://w3c.github.io/performance-timeline/#dom-performanceentry-duration
|
||||||
fn Duration(&self) -> Finite<f64> {
|
fn Duration(&self) -> DOMHighResTimeStamp {
|
||||||
Finite::wrap(self.duration)
|
reduce_timing_resolution(self.duration)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,11 +6,11 @@ use crate::dom::bindings::codegen::Bindings::PerformanceBinding::DOMHighResTimeS
|
||||||
use crate::dom::bindings::codegen::Bindings::PerformanceResourceTimingBinding::{
|
use crate::dom::bindings::codegen::Bindings::PerformanceResourceTimingBinding::{
|
||||||
self, PerformanceResourceTimingMethods,
|
self, PerformanceResourceTimingMethods,
|
||||||
};
|
};
|
||||||
use crate::dom::bindings::num::Finite;
|
|
||||||
use crate::dom::bindings::reflector::reflect_dom_object;
|
use crate::dom::bindings::reflector::reflect_dom_object;
|
||||||
use crate::dom::bindings::root::DomRoot;
|
use crate::dom::bindings::root::DomRoot;
|
||||||
use crate::dom::bindings::str::DOMString;
|
use crate::dom::bindings::str::DOMString;
|
||||||
use crate::dom::globalscope::GlobalScope;
|
use crate::dom::globalscope::GlobalScope;
|
||||||
|
use crate::dom::performance::reduce_timing_resolution;
|
||||||
use crate::dom::performanceentry::PerformanceEntry;
|
use crate::dom::performanceentry::PerformanceEntry;
|
||||||
use dom_struct::dom_struct;
|
use dom_struct::dom_struct;
|
||||||
use net_traits::ResourceFetchTiming;
|
use net_traits::ResourceFetchTiming;
|
||||||
|
@ -182,17 +182,17 @@ impl PerformanceResourceTimingMethods for PerformanceResourceTiming {
|
||||||
|
|
||||||
// https://w3c.github.io/resource-timing/#dom-performanceresourcetiming-domainlookupstart
|
// https://w3c.github.io/resource-timing/#dom-performanceresourcetiming-domainlookupstart
|
||||||
fn DomainLookupStart(&self) -> DOMHighResTimeStamp {
|
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
|
// https://w3c.github.io/resource-timing/#dom-performanceresourcetiming-domainlookupend
|
||||||
fn DomainLookupEnd(&self) -> DOMHighResTimeStamp {
|
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
|
// https://w3c.github.io/resource-timing/#dom-performanceresourcetiming-secureconnectionstart
|
||||||
fn SecureConnectionStart(&self) -> DOMHighResTimeStamp {
|
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
|
// 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
|
// https://w3c.github.io/resource-timing/#dom-performanceresourcetiming-requeststart
|
||||||
fn RequestStart(&self) -> DOMHighResTimeStamp {
|
fn RequestStart(&self) -> DOMHighResTimeStamp {
|
||||||
Finite::wrap(self.request_start)
|
reduce_timing_resolution(self.request_start)
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://w3c.github.io/resource-timing/#dom-performanceresourcetiming-redirectstart
|
// https://w3c.github.io/resource-timing/#dom-performanceresourcetiming-redirectstart
|
||||||
fn RedirectStart(&self) -> DOMHighResTimeStamp {
|
fn RedirectStart(&self) -> DOMHighResTimeStamp {
|
||||||
Finite::wrap(self.redirect_start)
|
reduce_timing_resolution(self.redirect_start)
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://w3c.github.io/resource-timing/#dom-performanceresourcetiming-redirectend
|
// https://w3c.github.io/resource-timing/#dom-performanceresourcetiming-redirectend
|
||||||
fn RedirectEnd(&self) -> DOMHighResTimeStamp {
|
fn RedirectEnd(&self) -> DOMHighResTimeStamp {
|
||||||
Finite::wrap(self.redirect_end)
|
reduce_timing_resolution(self.redirect_end)
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://w3c.github.io/resource-timing/#dom-performanceresourcetiming-responsestart
|
// https://w3c.github.io/resource-timing/#dom-performanceresourcetiming-responsestart
|
||||||
fn ResponseStart(&self) -> DOMHighResTimeStamp {
|
fn ResponseStart(&self) -> DOMHighResTimeStamp {
|
||||||
Finite::wrap(self.response_start)
|
reduce_timing_resolution(self.response_start)
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://w3c.github.io/resource-timing/#dom-performanceresourcetiming-fetchstart
|
// https://w3c.github.io/resource-timing/#dom-performanceresourcetiming-fetchstart
|
||||||
fn FetchStart(&self) -> DOMHighResTimeStamp {
|
fn FetchStart(&self) -> DOMHighResTimeStamp {
|
||||||
Finite::wrap(self.fetch_start)
|
reduce_timing_resolution(self.fetch_start)
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://w3c.github.io/resource-timing/#dom-performanceresourcetiming-connectstart
|
// https://w3c.github.io/resource-timing/#dom-performanceresourcetiming-connectstart
|
||||||
fn ConnectStart(&self) -> DOMHighResTimeStamp {
|
fn ConnectStart(&self) -> DOMHighResTimeStamp {
|
||||||
Finite::wrap(self.connect_start)
|
reduce_timing_resolution(self.connect_start)
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://w3c.github.io/resource-timing/#dom-performanceresourcetiming-connectend
|
// https://w3c.github.io/resource-timing/#dom-performanceresourcetiming-connectend
|
||||||
fn ConnectEnd(&self) -> DOMHighResTimeStamp {
|
fn ConnectEnd(&self) -> DOMHighResTimeStamp {
|
||||||
Finite::wrap(self.connect_end)
|
reduce_timing_resolution(self.connect_end)
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://w3c.github.io/resource-timing/#dom-performanceresourcetiming-responseend
|
// https://w3c.github.io/resource-timing/#dom-performanceresourcetiming-responseend
|
||||||
fn ResponseEnd(&self) -> DOMHighResTimeStamp {
|
fn ResponseEnd(&self) -> DOMHighResTimeStamp {
|
||||||
Finite::wrap(self.response_end)
|
reduce_timing_resolution(self.response_end)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,13 +2,14 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* 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;
|
||||||
use crate::dom::bindings::codegen::Bindings::VRFrameDataBinding::VRFrameDataMethods;
|
use crate::dom::bindings::codegen::Bindings::VRFrameDataBinding::VRFrameDataMethods;
|
||||||
use crate::dom::bindings::error::Fallible;
|
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::reflector::{reflect_dom_object, DomObject, Reflector};
|
||||||
use crate::dom::bindings::root::{Dom, DomRoot};
|
use crate::dom::bindings::root::{Dom, DomRoot};
|
||||||
use crate::dom::globalscope::GlobalScope;
|
use crate::dom::globalscope::GlobalScope;
|
||||||
|
use crate::dom::performance::reduce_timing_resolution;
|
||||||
use crate::dom::vrpose::VRPose;
|
use crate::dom::vrpose::VRPose;
|
||||||
use crate::dom::window::Window;
|
use crate::dom::window::Window;
|
||||||
use crate::script_runtime::JSContext;
|
use crate::script_runtime::JSContext;
|
||||||
|
@ -119,8 +120,8 @@ impl VRFrameData {
|
||||||
|
|
||||||
impl VRFrameDataMethods for VRFrameData {
|
impl VRFrameDataMethods for VRFrameData {
|
||||||
// https://w3c.github.io/webvr/#dom-vrframedata-timestamp
|
// https://w3c.github.io/webvr/#dom-vrframedata-timestamp
|
||||||
fn Timestamp(&self) -> Finite<f64> {
|
fn Timestamp(&self) -> DOMHighResTimeStamp {
|
||||||
Finite::wrap(self.timestamp.get() - self.first_timestamp.get())
|
reduce_timing_resolution(self.timestamp.get() - self.first_timestamp.get())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
|
|
|
@ -19,7 +19,6 @@ use crate::dom::bindings::codegen::Bindings::XRSessionBinding::XRVisibilityState
|
||||||
use crate::dom::bindings::codegen::Bindings::XRWebGLLayerBinding::XRWebGLLayerMethods;
|
use crate::dom::bindings::codegen::Bindings::XRWebGLLayerBinding::XRWebGLLayerMethods;
|
||||||
use crate::dom::bindings::error::{Error, ErrorResult};
|
use crate::dom::bindings::error::{Error, ErrorResult};
|
||||||
use crate::dom::bindings::inheritance::Castable;
|
use crate::dom::bindings::inheritance::Castable;
|
||||||
use crate::dom::bindings::num::Finite;
|
|
||||||
use crate::dom::bindings::refcounted::Trusted;
|
use crate::dom::bindings::refcounted::Trusted;
|
||||||
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject};
|
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject};
|
||||||
use crate::dom::bindings::root::{Dom, DomRoot, MutDom, MutNullableDom};
|
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::globalscope::GlobalScope;
|
||||||
use crate::dom::node::Node;
|
use crate::dom::node::Node;
|
||||||
use crate::dom::node::NodeDamage;
|
use crate::dom::node::NodeDamage;
|
||||||
|
use crate::dom::performance::reduce_timing_resolution;
|
||||||
use crate::dom::promise::Promise;
|
use crate::dom::promise::Promise;
|
||||||
use crate::dom::xrframe::XRFrame;
|
use crate::dom::xrframe::XRFrame;
|
||||||
use crate::dom::xrinputsourcearray::XRInputSourceArray;
|
use crate::dom::xrinputsourcearray::XRInputSourceArray;
|
||||||
|
@ -336,7 +336,7 @@ impl XRSession {
|
||||||
// Step 4-5
|
// Step 4-5
|
||||||
let mut callbacks = mem::replace(&mut *self.raf_callback_list.borrow_mut(), vec![]);
|
let mut callbacks = mem::replace(&mut *self.raf_callback_list.borrow_mut(), vec![]);
|
||||||
let start = self.global().as_window().get_navigation_start();
|
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);
|
let frame = XRFrame::new(&self.global(), self, frame);
|
||||||
// Step 6,7
|
// Step 6,7
|
||||||
|
@ -347,7 +347,7 @@ impl XRSession {
|
||||||
self.outside_raf.set(false);
|
self.outside_raf.set(false);
|
||||||
for (_, callback) in callbacks.drain(..) {
|
for (_, callback) in callbacks.drain(..) {
|
||||||
if let Some(callback) = callback {
|
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);
|
self.outside_raf.set(true);
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
[Event-timestamp-safe-resolution.html]
|
|
||||||
type: testharness
|
|
||||||
|
|
||||||
[Event timestamp should not have a resolution better than 5 microseconds]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
|
@ -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
|
|
||||||
|
|
|
@ -19708,7 +19708,7 @@
|
||||||
"testharness"
|
"testharness"
|
||||||
],
|
],
|
||||||
"mozilla/window_performance.html": [
|
"mozilla/window_performance.html": [
|
||||||
"302073e8041763102d678326509d7ef0a1fb5c79",
|
"c1e38a1e00147caf82492dc82f1cb5e85759f8e3",
|
||||||
"testharness"
|
"testharness"
|
||||||
],
|
],
|
||||||
"mozilla/window_performance_topLevelDomComplete.html": [
|
"mozilla/window_performance_topLevelDomComplete.html": [
|
||||||
|
|
|
@ -27,12 +27,15 @@ test(function() {
|
||||||
var last = window.performance.now();
|
var last = window.performance.now();
|
||||||
assert_greater_than(last, 0);
|
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++) {
|
for (var i = 0; i < 100; i++) {
|
||||||
var next = window.performance.now();
|
var next = window.performance.now();
|
||||||
assert_greater_than(next, last);
|
assert_greater_than_equal(next, last);
|
||||||
last = next;
|
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.");
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue