Skip to content

fix: wait for stylesheets to be loaded before adopting them - #834

Merged
samuel-olivier merged 2 commits into
mainfrom
fix/wait-for-css-before-adopting
Oct 19, 2026
Merged

samuel-olivier merged 2 commits into
mainfrom
fix/wait-for-css-before-adopting

Conversation

@samuel-olivier

Copy link
Copy Markdown
Contributor

Problem

Since #825 (d16f931), registerCss creates constructed stylesheets with the async CSSStyleSheet.replace(), and injectCss() adopts them right away at the start of initialize().

On Firefox, a constructed sheet stays "still-loading" until its replace() promise settles, and reading its cssRules in the meantime throws InvalidAccessError: Can't access rules of still-loading style sheet. Browser extensions that proxy the adoptedStyleSheets setter read cssRules on each adopted sheet — Dark Reader does (isDRAdoptedSheetOverride → onAdoptedSheetsChange, upstream issue darkreader/darkreader#14329). The setter throws, initialize() rejects.

Fix

  • src/css.ts: keep every replace() promise in sheetPromises; whenSheetsLoaded() is Promise.allSettled over them.
  • injectCss() becomes async and awaits whenSheetsLoaded() before setting root.adoptedStyleSheets.
  • The @font-face sheet adopted on document is deferred the same way.
  • src/services.ts: initialize() now awaits injectCss(container) (it was already async, so no API change for callers).

Validation

Repro loading the editor with Dark Reader's adoptedStyleSheets proxy injected:

  • Firefox, before: InvalidAccessError on adoption, initialize() rejects.
  • Firefox, after: 187 sheets adopted, 0 errors.
  • Chromium: unchanged before/after (it never throws on still-loading sheets).

@samuel-olivier samuel-olivier self-assigned this Oct 19, 2026
On Firefox, a constructed CSSStyleSheet stays "still-loading" until its
replace() promise settles, and reading its cssRules throws an
InvalidAccessError. Browser extensions that proxy the adoptedStyleSheets
setter (e.g. Dark Reader) read cssRules from the setter, so adopting the
sheets right after registering them made initialize() reject and the
editor never load.

Refs darkreader/darkreader#14329

Co-authored-by: Cursor <cursoragent@cursor.com>
Comment thread src/css.ts Outdated
@samuel-olivier
samuel-olivier force-pushed the fix/wait-for-css-before-adopting branch from 3455f48 to 11323f8 Compare October 19, 2026 15:48
The font face sheet is built synchronously with insertRule inside the
then of its own sheet promise, so it is never still-loading and there is
no need to wait for the other sheets before adopting it on the document.

Co-authored-by: Cursor <cursoragent@cursor.com>
Comment thread src/services.ts
@github-actions

Copy link
Copy Markdown

@CGNonofr
CGNonofr self-requested a review October 19, 2026 16:18
@samuel-olivier
samuel-olivier merged commit ce91f35 into main Oct 19, 2026
3 checks passed
@samuel-olivier
samuel-olivier deleted the fix/wait-for-css-before-adopting branch October 19, 2026 17:19
@github-actions

Copy link
Copy Markdown

🎉 This PR is included in version 38.0.1 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

This branch was successfully deployed

1 active deployment
pull request — 3d7b9e11 Deployed Oct 19, 2026 by github-actions[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants