Skip to content

🐛 Fix Session Replay of shadow DOM adoptedStyleSheets - #5119

Closed
cristihasna wants to merge 2 commits into
DataDog:mainfrom
cristihasna:cristihasna/fix-adopted-stylesheets-replay
Closed

cristihasna wants to merge 2 commits into
DataDog:mainfrom
cristihasna:cristihasna/fix-adopted-stylesheets-replay

Conversation

@cristihasna

@cristihasna cristihasna commented Oct 8, 2026 •

Copy link
Copy Markdown

Motivation

Web components that style their shadow roots via constructed stylesheets
(shadowRoot.adoptedStyleSheets, the default for Stencil and common with Lit) are replayed
without styles or with another component's styles. Fixes #5117.

Two recorder issues:

  1. Stylesheet id drift: serializeStyleSheet always emitted AddStyleSheet (the player
    assigns ids sequentially) but only allocated a recorder id for unseen sheets. When one
    CSSStyleSheet is shared by several shadow roots, recorder and player ids diverge, and later
    shadow roots reference the wrong sheet.
  2. Late adoption not recorded: adoptedStyleSheets were only read when a node was first
    serialized, so stylesheets adopted afterwards (e.g. lazy-loaded components adopting styles on
    first render) were never recorded until the next full snapshot.

Changes

  • serializeStyleSheet returns the existing id for already-serialized sheets and only emits
    AddStyleSheet when a new id is allocated. This also avoids sending the same CSS repeatedly.
  • The adopted stylesheets of each serialized #document / #shadow-root are remembered in the
    RecordingScope (serializedAdoptedStyleSheets). At the end of each mutation batch they are
    compared with the current adoptedStyleSheets, and an AttachedStyleSheets change is emitted
    when they differ. This covers both reassignment and in-place push(). State is cleared on
    resetIds() (full snapshots) and when a shadow root's host is removed.
  • Stylesheet serialization moved to a new serializeStyleSheets.ts.

Known limitations (unchanged from before):

  • A change to adoptedStyleSheets with no subsequent DOM mutation is only recorded on the next
    mutation batch.
  • Rule changes on constructed sheets (insertRule/deleteRule/replace/replaceSync) are not
    recorded. The StyleSheetRule record references the owner node, which constructed sheets don't
    have, so this would need a schema change.

This change was written with the help of an AI coding agent. I reviewed it, and verified it
against a local patch of @datadog/browser-rum 7.14.0 applied to an affected application.

Test instructions

  • Unit: yarn test:unit --spec packages/browser-rum/src/domain/record/trackers/trackMutation.spec.ts --spec packages/browser-rum/src/domain/record/serialization/serializeNode.stylesheet.spec.ts
  • E2E: yarn test:e2e -g "recorder with shadow DOM"
  • Manual: on a page with several instances of a custom element sharing one constructed
    stylesheet, plus one element adopting its stylesheet asynchronously, record a session and
    check that every shadow root is styled correctly in the replay.

Checklist

  • Tested locally
  • Tested on staging
  • Added unit tests for this change.
  • Added e2e/integration tests for this change.
  • Updated documentation and/or relevant AGENTS.md file

@cristihasna
cristihasna requested review from a team as code owners October 8, 2026 10:33
@github-actions

github-actions Bot commented Oct 8, 2026 •

Copy link
Copy Markdown

All contributors have signed the CLA ✍️ ✅
Posted by the CLA Assistant Lite bot.

@cristihasna

Copy link
Copy Markdown
Author

I have read the CLA Document and I hereby sign the CLA

@sethfowler-datadog

Copy link
Copy Markdown
Contributor

Thank you for the PR, @cristihasna. The stylesheet ID issue you reported has been addressed in #5157. The other issue will be addressed soon. I'm going to close this PR in favor of those other PRs.

@github-actions github-actions Bot locked and limited conversation to collaborators Oct 19, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

🐛 [RUM] Session Replay: shadow root adoptedStyleSheets replayed with wrong or missing styles (stylesheet ID drift + late adoption not recorded)

2 participants