feat(rule): gate sync rule-result resolution behind runTypeASync flag#235
Open
chikara1608 wants to merge 1 commit into
Open
feat(rule): gate sync rule-result resolution behind runTypeASync flag#235chikara1608 wants to merge 1 commit into
chikara1608 wants to merge 1 commit into
Conversation
Resolving each rule's result via setTimeout(0) (Deque #1172) creates one
macrotask transition per rule (~335). On large DOMs with advance ON these
interleave with DevTools IPC (resource.getContent), ballooning the
per-rule resolve from ~8ms to ~180ms and inflating axe.run from ~14s to
~85s.
When axe._cache 'runTypeASync' is set (by a11y-engine-core run.js from the
a11yCoreConfig flag), resolve synchronously to eliminate the contention.
The flag defaults OFF, preserving the original deferred behaviour.
On the OFF path, instrument the schedule-to-fire delay of each yield and
accumulate {totalMs,count,maxMs} onto axe._typeASyncYield so every scan
reports how much wall-clock the async resolve costs — the exact time the
flag would recover. Read back into Type A telemetry by a11y-engine-core.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
351ca61 to
e023225
Compare
rohitsahu-bstack
approved these changes
Jun 4, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Gates per-rule result resolution on a new
runTypeASyncflag (set intoaxe._cachebya11y-engine-corefrom thea11yCoreConfig.runTypeASyncconfig field):resolve(ruleResult)synchronously.setTimeout(0)defer (Deque #1172), unchanged behaviour, plus lightweight yield-latency instrumentation.Why
The
setTimeout(0)wrapper aroundresolve(ruleResult)creates one macrotask transition per rule (~335). On large DOMs with advance ON, these interleave with concurrent DevTools IPC (resource.getContent), inflating the per-rule resolve from ~8ms to ~180ms andaxe.runfrom ~14s to ~85s (Savvas Realize investigation). Resolving synchronously eliminates the contention.We are shipping the fix behind a flag, default OFF, and want to measure which other customers exhibit the same pathology before enabling it for them.
Instrumentation (OFF path only)
Accumulates the schedule-to-fire delay of each resolve yield onto
axe._typeASyncYield{ totalMs, count, maxMs }.a11y-engine-corereads this back afteraxe.runand surfaces it in Type A telemetry.totalMs≈ the wall-clock the async resolve costs = the exact time the flag would recover.Cost / safety
setTimeoutthat already existed onmain. Event-loop behaviour on the OFF path is byte-for-byte identical to today.performance.now()+ a few arithmetic ops per rule ≈ ~1ms per scan; scales with rule count, not DOM size.Tagging
All changes carry
// [a11y-core]:per submodule convention.Test plan
build_axe.shcompiles clean;runTypeASync+_typeASyncYieldpresent in builtaxe.js.type_a_sync_yield_countreports 0.type_a_sync_yield_total_mspopulated on a large advance-ON scan.Paired with a11y-engine PR (flag extraction + telemetry surfacing + submodule bump).
🤖 Generated with Claude Code