Skip to content

fix(pdf): detect nested pointer-events:none loading overlays#840

Closed
cursor[bot] wants to merge 2 commits into
masterfrom
cursor/critical-bug-investigation-0a8b
Closed

fix(pdf): detect nested pointer-events:none loading overlays#840
cursor[bot] wants to merge 2 commits into
masterfrom
cursor/critical-bug-investigation-0a8b

Conversation

@cursor

@cursor cursor Bot commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

Bug and impact

PDF waitUntil: auto can ship blank/white PDFs when a SPA mounts a pointer-events: none loading overlay as a sibling of content inside #root/#app.

#839 added a covered check so the zero-screenshot fast path is skipped when content hides behind an opaque overlay. That scan only inspected direct children of <body>, so nested loaders were missed: waitForReady reported covered: false with 200+ visible text chars, the fast path skipped the blank-SPA screenshot poll, and the PDF captured the white overlay.

Root cause

elementFromPoint (and elementsFromPoint) skip pointer-events: none elements in Chromium. The fallback scan in #839 was limited to document.body.children, missing the common body > #root > [overlay, content] structure.

Fix

For each content sample, walk up the ancestor chain and check siblings for unrelated opaque viewport-filling fixed/absolute/sticky layers. Replaces the body-children-only scan and covers both direct and nested mount patterns.

Validation

  • Added live test: covered: a pointer-events:none overlay nested in #root is caught
  • All existing wait-for-ready-live tests pass (16/16)
  • All @browserless/browserless PDF unit tests pass (11/11)
  • Full @browserless/screenshot suite passes (44/44)
Open in Web View Automation 

#839 only scanned direct children of body for pointer-events:none overlays. SPAs that mount loaders inside #root as siblings of content were missed, letting the PDF fast path skip the blank check and ship white PDFs.
@coveralls

coveralls commented Jul 18, 2026

Copy link
Copy Markdown

Coverage Status

Coverage is 80.546%cursor/critical-bug-investigation-0a8b into master. No base build found for master.

The ancestor-walking scan dropped two guards the body-level scan had,
turning ordinary layouts into false covered positives (fail-slow: the
fast path is skipped and the screenshot poll runs on pages it was built
to avoid):

- pointer-events filter: any positioned opaque sibling qualified, so a
  fixed page background painted behind the content (z-index:-1) flagged
  as covering it. Restored — anything hit-testable is coveredAt's job.
- content guard: a layer painting counted content paints with it, not
  over it. Restored as the only relation check; it subsumes the
  per-anchor === /contains checks, which sibling geometry made dead.

Also cheaper per poll: rect test before getComputedStyle, and scanned
parents are shared across content samples so each level resolves once.

Both regressions verified live against the previous commit and pinned
with not-covered tests.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DnCNthP4fLPv6yeEjjSaUh
@Kikobeats

Copy link
Copy Markdown
Member

Closing: the nested-overlay case is hypothetical at this point and the deeper per-poll scan isn't worth the cost. #839's body-level scan stays. If a real page ships blank because of a nested pointer-events:none loader, we'll reopen with that URL as the test case.

@Kikobeats Kikobeats closed this Jul 19, 2026
@Kikobeats
Kikobeats deleted the cursor/critical-bug-investigation-0a8b branch July 19, 2026 08:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants