tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit b6ff8e834eb0d7a62805abc9c31cccc268d6dfa1
parent 88d477aed09a620620fa63cc24ffc32a92df4cf5
Author: francovs <34865963+francovs@users.noreply.github.com>
Date:   Thu, 11 Dec 2025 09:28:18 +0000

Bug 1995713 [wpt PR 55577] - WebKit export of https://bugs.webkit.org/show_bug.cgi?id=300102, a=testonly

Automatic update from web-platform-tests
WebKit export of https://bugs.webkit.org/show_bug.cgi?id=300102 (#55577)

Verifies that `pointerdown`/`keydown` event timing entries can have their durations set before the matching `*up` event is fired.

Original patch was modified to resolve a potential race in browsers in which `await afterNextPaint()` does not guarantee the dispatch of event timing entries. To make sure the pointerdown/keydown's event timing entry had its duration set, we now produce an interleaving event and await until its event timing entry is observed. This ensures that the "Dispatch pending Event Timing entries" step ran.
--

wpt-commits: f77e140355cde2fac3c8c9f1a16a154a34fda15c
wpt-pr: 55577

Diffstat:
Atesting/web-platform/tests/event-timing/gap-keydown-keyup.html | 62++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atesting/web-platform/tests/event-timing/gap-pointerdown-pointerup.html | 62++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 124 insertions(+), 0 deletions(-)

diff --git a/testing/web-platform/tests/event-timing/gap-keydown-keyup.html b/testing/web-platform/tests/event-timing/gap-keydown-keyup.html @@ -0,0 +1,62 @@ +<!DOCTYPE html> +<html> +<meta charset=utf-8 /> +<title>Event Timing: keydown/up gap.</title> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script src=/resources/testdriver.js></script> +<script src=/resources/testdriver-actions.js></script> +<script src=/resources/testdriver-vendor.js></script> +<script src=resources/event-timing-test-utils.js></script> +<div id='target'>Click me</div> +<script> + promise_test(async t => { + const keyDowns = [] + const keyUps = [] + blockNextEventListener(window, 'keydown', 30) + blockNextEventListener(window, 'keyup', 30) + + // A pointerdown is used as an interleaving event, to make sure the keydown's + // timing entry had it's duration set before triggering the keyup. Using + // only `await afterNextPaint()` after the first event is not enough to + // guarantee this in all browsers. See discussion in + // https://github.com/web-platform-tests/wpt/pull/55577#discussion_r2466579023 + blockNextEventListener(window, 'pointerdown', 30) + const {promise: interleavingEventTimingEntryObserved, resolve: resolveInterleaving } = Promise.withResolvers(); + new PerformanceObserver( (entries) => { + entries.getEntries().forEach( (e) => { + if (e.name == 'keydown') + keyDowns.push(e) + if (e.name =='keyup') + keyUps.push(e) + if (e.name == 'pointerdown') + resolveInterleaving() + }) + }).observe({type: 'event', durationThreshold: 16}) + const keyDownHandled = new Promise( resolve => window.addEventListener('keydown', e => resolve(), true) ) + const keyUpHandled = new Promise( resolve => window.addEventListener('keyup', e => resolve(), true) ) + + await new test_driver.Actions() + .keyDown('a') + .send() + await keyDownHandled + await afterNextPaint() + await new test_driver.Actions() + .pointerMove(0, 0) + .pointerDown() + .pointerUp() + .send() + await interleavingEventTimingEntryObserved + const waitStart = performance.now() + await t.step_wait(() => (performance.now() - waitStart > 50)) + await new test_driver.Actions() + .keyUp('a') + .send() + await keyUpHandled + await t.step_wait(() => (keyDowns.length != 0 && keyUps.length != 0), 'Wait for the event timing entries to be processed.') + assert_equals(keyDowns.length, 1) + assert_equals(keyUps.length, 1) + assert_greater_than(keyUps[0].startTime, keyDowns[0].startTime + keyDowns[0].duration) + }, "keydown duration shouldn't wait for keyup.") +</script> +</html> diff --git a/testing/web-platform/tests/event-timing/gap-pointerdown-pointerup.html b/testing/web-platform/tests/event-timing/gap-pointerdown-pointerup.html @@ -0,0 +1,62 @@ +<!DOCTYPE html> +<html> +<meta charset=utf-8 /> +<title>Event Timing: pointerdown/up gap.</title> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script src=/resources/testdriver.js></script> +<script src=/resources/testdriver-actions.js></script> +<script src=/resources/testdriver-vendor.js></script> +<script src=resources/event-timing-test-utils.js></script> +<div id='target'>Click me</div> +<script> + promise_test(async t => { + const pointerDowns = [] + const pointerUps = [] + blockNextEventListener(window, 'pointerdown', 30) + blockNextEventListener(window, 'pointerup', 30) + + // A keydown is used as an interleaving event, to make sure the pointerdown's + // timing entry had it's duration set before triggering the pointerup. Using + // only `await afterNextPaint()` after the first event is not enough to + // guarantee this in all browsers. See discussion in + // https://github.com/web-platform-tests/wpt/pull/55577#discussion_r2466579023 + blockNextEventListener(window, 'keydown', 30) + const {promise: interleavingEventTimingEntryObserved, resolve: resolveInterleaving } = Promise.withResolvers(); + new PerformanceObserver( (entries) => { + entries.getEntries().forEach( (e) => { + if (e.name == 'pointerdown') + pointerDowns.push(e) + if (e.name =='pointerup') + pointerUps.push(e) + if (e.name == 'keydown') + resolveInterleaving() + }) + }).observe({type: 'event', durationThreshold: 16}) + const pointerDownHandled = new Promise( resolve => window.addEventListener('pointerdown', e => resolve(), true) ) + const pointerUpHandled = new Promise( resolve => window.addEventListener('pointerup', e => resolve(), true) ) + + await new test_driver.Actions() + .pointerMove(0, 0) + .pointerDown() + .send() + await pointerDownHandled + await afterNextPaint() + await new test_driver.Actions() + .keyDown('k') + .keyUp('k') + .send() + await interleavingEventTimingEntryObserved + const waitStart = performance.now() + await t.step_wait(() => (performance.now() - waitStart > 50)) + await new test_driver.Actions() + .pointerUp() + .send() + await pointerUpHandled + await t.step_wait(() => (pointerDowns.length != 0 && pointerUps.length != 0), 'Wait for the event timing entries to be processed.') + assert_equals(pointerDowns.length, 1) + assert_equals(pointerUps.length, 1) + assert_greater_than(pointerUps[0].startTime, pointerDowns[0].startTime + pointerDowns[0].duration) + }, "pointerdown duration shouldn't wait for pointerup.") +</script> +</html>