Thanks to visit codestin.com
Credit goes to github.com

Skip to content

fix(transitions): prevent WebGL context loss on persist canvas during Safari swap#15728

Open
SvetimFM wants to merge 1 commit intowithastro:mainfrom
SvetimFM:fix/safari-persist-canvas-context-loss
Open

fix(transitions): prevent WebGL context loss on persist canvas during Safari swap#15728
SvetimFM wants to merge 1 commit intowithastro:mainfrom
SvetimFM:fix/safari-persist-canvas-context-loss

Conversation

@SvetimFM
Copy link

@SvetimFM SvetimFM commented Mar 3, 2026

Summary

  • Fixes swapBodyElement() to lift transition:persist elements to <html> before the body replaceWith(), preventing Safari from losing WebGL2 context on <canvas> elements during page transitions.

Details

Safari loses WebGL2 context when canvas elements are briefly detached from the DOM tree. The current swapBodyElement() calls oldBody.replaceWith(newBody) first, which detaches the entire old body (including persist elements), then moves persist elements from old to new body. In the gap between detach and reattach, Safari fires webglcontextlost.

The fix moves persist elements to <html> (a safe parent that survives the swap) before replaceWith(), then places them into the new body afterward. This means persist elements are never detached from the DOM, so Safari doesn't lose the WebGL context.

Chrome and Firefox are unaffected by this change — they don't lose WebGL context on brief DOM detachment, so the fix is a no-op for them behaviorally.

Closes #15727 (Bug 3 — canvas context loss)

Test plan

  • Astro project with <ClientRouter /> + <canvas transition:persist> initializing WebGL2
  • Navigate between pages on Safari 18 (desktop and iPad) — canvas should retain WebGL context
  • Rapid navigation (5+ quick clicks) — no blank canvas, no console errors
  • Chrome/Firefox — no regression, persist elements still work correctly
  • astro-island persist elements — props still copied correctly after swap

🤖 Generated with Claude Code

… Safari swap

Safari loses WebGL2 context when canvas elements are briefly detached
from the DOM. swapBodyElement() previously called replaceWith() which
detached all old body children (including transition:persist elements)
before moving them to the new body.

Fix: lift persist elements to <html> before the body swap so they stay
in the DOM tree throughout the transition, then move them into the new
body afterward.

Fixes withastro#15727

Co-Authored-By: Claude Opus 4.6 <[email protected]>
@changeset-bot
Copy link

changeset-bot bot commented Mar 3, 2026

🦋 Changeset detected

Latest commit: 4a14184

The changes in this PR will be included in the next version bump.

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@codspeed-hq
Copy link

codspeed-hq bot commented Mar 3, 2026

Merging this PR will not alter performance

✅ 18 untouched benchmarks


Comparing SvetimFM:fix/safari-persist-canvas-context-loss (4a14184) with main (e6e146c)1

Open in CodSpeed

Footnotes

  1. No successful run was found on main (cc9ee02) during the generation of this report, so e6e146c was used instead as the comparison base. There might be some changes unrelated to this pull request in this report.

@SvetimFM
Copy link
Author

SvetimFM commented Mar 3, 2026

Re: E2E test failure — [Firefox Stable] view-transitions.test.js:174

The failing test (Moving from a page without ClientRouter w/ back button) expects 3 page loads but gets 2. This is unrelated to our change:

  • The test pages have zero transition:persist elements — swapBodyElement() is never called in this test flow
  • The forward navigation (page 1 → page 3) falls through to location.href since page 3 has no ClientRouter
  • The back navigation is handled entirely by the browser — no Astro code involved

Why 2 loads instead of 3: Firefox used bfcache to restore page 1 on back-navigation. bfcache restore fires pageshow (with persisted: true), not load — so collectLoads() doesn't count it. The test already acknowledges this is fragile (line 188): "Mainly for Firefox on Windows. Wait for navigation to complete."

This appears to be a pre-existing flaky assertion that depends on whether the CI runner's Firefox instance uses bfcache for the back-navigation. Chrome Stable passed all 408 tests.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

pkg: astro Related to the core `astro` package (scope)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Safari 18: View Transitions break CSS rendering and cause WebGL context loss on transition:persist canvas

1 participant