| <!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> |