blob: e1c36e302108b1bd886130c7df38d8e536dc4473 [file] [log] [blame]
<!DOCTYPE html>
<html>
<meta charset=utf-8 />
<title>Event Timing: Performance observers can observe long-latency events
</title>
<meta name="timeout" content="long">
<button id='button'>Generate a 'click' event</button>
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<script src=/resources/testdriver.js></script>
<script src=/resources/testdriver-vendor.js></script>
<script src=resources/event-timing-test-utils.js></script>
<img src=resources/slow-image.py>
<script>
let timeBeforeFirstClick;
let timeAfterFirstClick;
let timeAfterSecondClick;
let onloadStart;
let observedEntries = [];
function verifyBuffer(bufferedEntries) {
assert_equals(bufferedEntries.length, 1,
"Only events before onload should be buffered.");
const entry = bufferedEntries[0];
assert_greater_than(onloadStart, entry.startTime,
"Onload should be later than entry's start time.");
assert_greater_than(entry.processingStart, timeBeforeFirstClick,
"The entry's processing start should be after timeBeforeFirstClick");
assert_less_than(entry.processingStart, timeAfterFirstClick,
"The entry's processing start should be before timeAfterFirstClick.");
verifyClickEvent(entry, true);
}
function verifyObserverEntries(observedEntries) {
const entriesAfterFirstClick = observedEntries.filter(
e => e.startTime > timeAfterFirstClick);
assert_equals(entriesAfterFirstClick.length, 1,
'There should be one event after timeAfterFirstClick.');
const entry1 = entriesAfterFirstClick[0];
verifyClickEvent(entry1);
assert_greater_than(entry1.processingStart, timeAfterFirstClick,
"entry1's processing start should be after timeAfterFirstClick");
assert_less_than(entry1.processingStart, timeAfterSecondClick,
"entry1's processing start should be before timeAfterSecondClick.");
assert_greater_than(entry1.startTime, onloadStart,
"entry1's start time should be later than onloadStart.");
const entriesBeforeFirstClick =
observedEntries.filter(e => e.startTime < timeAfterFirstClick);
assert_equals(entriesBeforeFirstClick.length, 1,
'There should be one event before timeAfterFirstClick.'
);
const entry2 = entriesBeforeFirstClick[0];
verifyClickEvent(entry2);
assert_greater_than(entry2.processingStart, timeBeforeFirstClick,
"entry2's processing start should be after timeBeforeFirstClick");
assert_less_than(entry2.processingStart, timeAfterFirstClick,
"entry2's processing start should be berfore timeAfterFirstClick.");
assert_greater_than(timeAfterFirstClick, entry2.startTime,
"timeAfterFirstClick should be later than entry2's start time.");
}
/* Timeline:
Observer starts
Begin Busy Loop
Click 1 arrives
End Busy Loop
(Dispatch and Process Click 1 (buffered, observed))
Onload Event Fires
Begin Busy Loop
Click 2 arrives
End Busy Loop
(Dispatch and Process Click 2 (buffered, observed))
observer callback start
*/
async_test(function(t) {
const observerPromise = new Promise((resolve, reject) => {
new PerformanceObserver(function(entryList) {
observedEntries = observedEntries.concat(entryList.getEntries().filter(
entry => entry.name === 'mousedown'));
if (observedEntries.length < 2) return;
resolve(observedEntries);
}).observe({ entryTypes: ['event'] });
});
timeBeforeFirstClick = performance.now();
clickAndBlockMain('button').then( () => {
timeAfterFirstClick = performance.now();
});
on_event(window, 'load', function(e) {
onloadStart = performance.now();
// After onload start and before registering observer.
const bufferPromise = clickAndBlockMain('button').then(wait);
Promise.all([observerPromise, bufferPromise]).then((results) => {
timeAfterSecondClick = performance.now();
t.step(verifyObserverEntries.bind(null, results[0]));
t.step(verifyBuffer.bind(null, performance.getEntriesByName('mousedown', 'event')));
t.done();
});
});
}, "Event Timing: click, observer, onload, click.");
</script>
</html>