dequelabs / dequelabs/axe-core

Axe:ping will time out for long gather steps

Open
#4,831 2 comments 0 reactions 0 assignees View on GitHub
core fix high
Dominant language
JavaScript
Stars
7.5k
Forks
933
Avg merge
2d 23h
Merged PRs (30d)
17

Description

Axe-core uses setTimeout(..., 0) between rules to give the browser an opportunity to do other things while axe is running. This is necessary as without it the page would become completely unresponsive. Firefox even raises an error on scripts that take too long to run (or used to, it has been a few years since I looked).

We **only** do this after completing a rule. But there are other parts of axe-core that can take multiple seconds on especially large pages. I ran into this problem with the gather step in particular. A very large page can take multiple seconds to gather nodes. This blocks the vent loop for multiple seconds, which is a problem for cross-frame testing.

What happens is this:

1. Axe sends a message to frames, starting with a ping to check if axe is even in that frame, this times out after 500ms by default
2. Axe starts gathering nodes in the top-window
3. In the frame, the ping message is received, but because gather is running in the same thread, the browser has to wait executing the handler
4. Several seconds later gather completes, now unblocking other scripts from executing
5. In the frame, the event listener finally gets the ping and sends a message back
6. The ping timeout runs, logging the frame has timed out
7. The response to the ping is received, but too late

## Steps to reproduce

1. Go to https://qateam.dequecloud.com/demos/dynamic/index.html?profiles=5000
2. Run the axe extension
3. Check the console, it will have a "Uncaught (in promise) No response received from frame within timeout of 5000ms." error

This is 5 seconds, not 500ms. Axe extension already overrides axe-core's ping, but that isn't enough on this page.

## How to fix?

I'm not sure... perhaps we can enhance the queue to keep track of how long it has been running synchronous tasks and if it exceeds 100s have it defer the next task. That would work for both gather and rules. We still have the selector generation code that's all synchronous that takes a long time. But that won't cause frame timeout problems since it all happens afterwards.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.