w3c / long-animation-frames

Long Animation Frame API specification repository
Other
10 stars 1 forks source link

pauseDuration is 0 while synchronous dialogs are shown #17

Open rviscomi opened 3 months ago

rviscomi commented 3 months ago

According to MDN, pauseDuration represents:

the total time, in milliseconds, spent by the script on "pausing" synchronous operations (for example, Window.alert() calls or synchronous XMLHttpRequests)

However, script entries have a pauseDuration of 0, even while an alert is open.

Example LoAF entry ```json { "name": "long-animation-frame", "entryType": "long-animation-frame", "startTime": 4816.9000000059605, "duration": 4081, "navigationId": "ddfd6f3a-9257-457e-99ff-b67f267b1c31", "renderStart": 8898.40000000596, "styleAndLayoutStart": 8898.5, "firstUIEventTimestamp": 4878.700000017881, "blockingDuration": 3967, "scripts": [ { "name": "script", "entryType": "script", "startTime": 4831.5, "duration": 302, "navigationId": "ddfd6f3a-9257-457e-99ff-b67f267b1c31", "invoker": "TimerHandler:setTimeout", "invokerType": "user-callback", "windowAttribution": "self", "executionStart": 4831.5, "forcedStyleAndLayoutDuration": 0, "pauseDuration": 0, "sourceURL": "https://inp-demo-dialog.glitch.me/main.js", "sourceFunctionName": "periodicBlock", "sourceCharPosition": 1403 }, { "name": "script", "entryType": "script", "startTime": 5134.700000017881, "duration": 3763, "navigationId": "ddfd6f3a-9257-457e-99ff-b67f267b1c31", "invoker": "BUTTON.onclick", "invokerType": "event-listener", "windowAttribution": "self", "executionStart": 5134.700000017881, "forcedStyleAndLayoutDuration": 0, "pauseDuration": 0, "sourceURL": "https://inp-demo-dialog.glitch.me/", "sourceFunctionName": "onclick", "sourceCharPosition": 0 } ] } ```

Example trace: https://trace.cafe/t/GBb9saklW7

To reproduce:

  1. Open DevTools and go to https://inp-demo-dialog.glitch.me/
  2. Set blocking frequency to "Often"
  3. Trigger an alert
  4. Inspect the LoAF entry in the console

(You may need to try again if your interaction was < 50ms)

https://github.com/user-attachments/assets/68c3e356-e757-47c5-b4ee-9db8d42347a4

mmocny commented 3 months ago

I think that the setTimeout is expected to be 0 here, and the event-listener is expected to be non-0 here (assuming you called alert() directly from the event listener)

rviscomi commented 3 months ago

That's right, here's the button source:

<button onclick="alert('This no longer blocks INP as of Chrome 127! 🎉')">
  Alert
</button>
mmocny commented 3 months ago

Ah, I know there are some oddities with inline scripts and LoAF. If you changed to use addEventListener would it be any different?

rviscomi commented 3 months ago

Updated:

loafAlert.addEventListener('click', () => {
  alert('This no longer blocks INP as of Chrome 127! 🎉');
});

Still repros:

{
    "name": "script",
    "entryType": "script",
    "startTime": 13446.699999988079,
    "duration": 3763,
    "navigationId": "e754322a-fc20-4220-80f0-dfda1ffebbde",
    "invoker": "BUTTON#loafAlert.onclick",
    "invokerType": "event-listener",
    "windowAttribution": "self",
    "executionStart": 13446.699999988079,
    "forcedStyleAndLayoutDuration": 0,
    "pauseDuration": 0,
    "sourceURL": "https://inp-demo-dialog.glitch.me/",
    "sourceFunctionName": "",
    "sourceCharPosition": 37
}
mmocny commented 2 months ago

The demo page won't consistently report long INP now that the Event Timing duration was fixed for alerts. You can still make it long and get logged (via input delay) by interacting with the button while the page is blocked.

Alternatively, just open DevTools console and log all LoAFs with a script for event-listener:

new PerformanceObserver(list => list.getEntries()
  .flatMap(entry => entry.scripts)
  .filter(s => s.invokerType == "event-listener")
  .forEach(s => console.log(s)))
.observe({ type: 'long-animation-frame' });

(It still reproduces, fwiw)