Expose the task AbortSignal as `signal` in the script scope so cooperative
code can cancel promptly, and re-check signal.throwIfAborted() after the
script settles to discard stale results.
Closes#537.
Two debug log statements were left in production code:
- `isScrollableElement()` logged `scrollData!!!` for every scrollable
element found during DOM tree construction. Because the DOM is rebuilt
on every agent action, this fired repeatedly and also triggered
unnecessary JSON serialisation of scroll metrics on the hot path.
- `SimulatorMask.dispose()` logged 'dispose SimulatorMask' every time
the highlight overlay was torn down.
Neither had a structured prefix or was gated behind a debug flag.
Removing both silences console noise for end users and removes the
serialisation overhead in the scroll-detection hot path.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Resolve the @TODO in checkDarkMode.ts by adding 3 new detection
strategies and expanding data-attribute coverage:
- Check data-color-mode, data-bs-theme, data-color-scheme attributes
- Read CSS color-scheme property and <meta name="color-scheme"> tag
- Inspect background of SPA containers (#app, #root, #__next, etc.)
- Detect light text color as a dark-theme signal
The #moveCursorToTarget() method recursively schedules itself via
requestAnimationFrame, creating a continuous animation loop for the
AI cursor. However, dispose() only removes the DOM wrapper element
without stopping this loop, causing:
- CPU waste: rAF callback continues executing every frame (~60fps)
after the mask is disposed, performing unnecessary calculations
on a detached cursor element.
- Resource leak: Each SimulatorMask instance creates an unrecoverable
animation loop that persists for the lifetime of the page.
- Console noise: style assignments to removed DOM nodes may produce
browser warnings.
Fix: Add a #disposed boolean flag, checked at the top of
#moveCursorToTarget() to short-circuit the recursion. Set the flag
to true in dispose() before removing DOM elements.
Changes:
- Add #disposed field (default false)
- Guard #moveCursorToTarget() with early return when #disposed
- Set #disposed = true in dispose() before cleanup
Replace broken el.hasAttribute("aria-") with a curated list of 27
aria attributes checked via hasAttribute. Each check is O(1).
WAI-ARIA 1.2 defines ~50 aria attributes total per MDN.
Of these ~27 appear on interactive elements such as buttons,
inputs, sliders, and dialogs. The remaining ~20 are structural
container attributes like aria-live, aria-colcount, and
aria-rowspan that only appear on non-interactive containers.
Checking them would not change results.
Two bugs in the scroll direction logic:
1. Vertical scroll with `pixels` ignores the `down` boolean because the
`??` operator bypasses the direction multiplier when pixels is provided.
Fix: move the direction multiplier outside the `??` so it applies to
both the pixels and numPages paths.
2. Horizontal scroll with `pixels` applies direction twice - once in
PageController.ts and again in actions.ts - causing a double negation
that reverses the intended direction. Fix: remove the redundant
direction logic from actions.ts since PageController already signs
the scroll amount.
Also removes the now-unused `down` and `right` parameters from the
scrollVertically() and scrollHorizontally() action functions.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>