fix(highlight): adopt highlight styles into the host's tree scope - #2315
Open
rkaraivanov wants to merge 1 commit into
Open
fix(highlight): adopt highlight styles into the host's tree scope#2315rkaraivanov wants to merge 1 commit into
rkaraivanov wants to merge 1 commit into
Conversation
Matches are painted again in Firefox. The `::highlight()` rules now live in the tree scope that owns the text they style, instead of in the component's own shadow root. `::highlight()` rules are tree-scoped - they only reach text nodes belonging to the same tree scope as the stylesheet. The service adopted its sheet into `renderRoot`, but `igc-highlight` renders nothing except a `<slot>`, so the text it highlights is light DOM sitting in the host's scope. The two never matched up. Earlier Firefox versions resolved such rules across scopes, as Chromium still does, so the mismatch went unnoticed; once Firefox began enforcing the scoping, nothing was painted at all. Matching itself was never affected - `size` and the `Range` objects were correct throughout, only the styles failed to apply. The sheet is now adopted by `getRootNode()`, which is the document or an outer shadow root depending on where the component sits. `attachStylesheet` stays idempotent and tracks where the sheet actually landed, so a host that moves between scopes drops it from the old root before adopting into the new one, and a host that is detached - or built inside a `<template>`, whose fragment has no `adoptedStyleSheets` - resolves to no root and is skipped. `hostConnected` attaches the sheet directly rather than waiting on the theming controller's `themeChange` callback. That callback is still needed, since `adoptStyles` replaces `adoptedStyleSheets` wholesale on every theme change, but it is no longer the only path that gets the sheet installed. This also settles a Chromium bug that predates the Firefox change: an `igc-highlight` nested inside another component's shadow root matched the cross-scope rule but resolved `--background` / `--foreground` against the wrong scope, painting the theme fallback instead of the configured colors. Covered by three regression tests over scope placement, re-targeting on move, and cleanup on disconnect.
Contributor
There was a problem hiding this comment.
Pull request overview
This pull request fixes igc-highlight rendering in browsers that enforce ::highlight() tree scoping (notably recent Firefox) by adopting the constructed ::highlight() stylesheet into the same tree scope as the highlighted text nodes (document or an outer shadow root), rather than into the component’s own shadow root (which only contains a <slot>).
Changes:
- Resolve the correct “style root” via
getRootNode()and adopt/remove the constructed highlight sheet in that root, tracking the currently attached root to support re-targeting. - Attach the stylesheet on
hostConnected(in addition to the existing themingthemeChangepath) so styles are installed immediately on connect. - Add regression tests covering correct scope placement, re-targeting on move between scopes, and cleanup on disconnect.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
src/components/highlight/service.ts |
Moves ::highlight() stylesheet adoption from renderRoot to the host’s tree scope root and tracks/removes/re-attaches across scope changes. |
src/components/highlight/highlight.spec.ts |
Adds regression tests validating stylesheet adoption scope, re-targeting after moving into another shadow root, and removal on disconnect. |
CHANGELOG.md |
Documents the Firefox regression cause and the fix, plus the related Chromium custom-property resolution improvement. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Matches are painted again in Firefox. The
::highlight()rules now live in the tree scope that owns the text they style, instead of in the component's own shadow root.::highlight()rules are tree-scoped - they only reach text nodes belonging to the same tree scope as the stylesheet. The service adopted its sheet intorenderRoot, butigc-highlightrenders nothing except a<slot>, so the text it highlights is light DOM sitting in the host's scope. The two never matched up. Earlier Firefox versions resolved such rules across scopes, as Chromium still does, so the mismatch went unnoticed; once Firefox began enforcing the scoping, nothing was painted at all. Matching itself was never affected -sizeand theRangeobjects were correct throughout, only the styles failed to apply.The sheet is now adopted by
getRootNode(), which is the document or an outer shadow root depending on where the component sits.attachStylesheetstays idempotent and tracks where the sheet actually landed, so a host that moves between scopes drops it from the old root before adopting into the new one, and a host that is detached - or built inside a<template>, whose fragment has noadoptedStyleSheets- resolves to no root and is skipped.hostConnectedattaches the sheet directly rather than waiting on the theming controller'sthemeChangecallback. That callback is still needed, sinceadoptStylesreplacesadoptedStyleSheetswholesale on every theme change, but it is no longer the only path that gets the sheet installed.This also settles a Chromium bug that predates the Firefox change: an
igc-highlightnested inside another component's shadow root matched the cross-scope rule but resolved--background/--foregroundagainst the wrong scope, painting the theme fallback instead of the configured colors.Type of Change
Testing
Covered by three regression tests over scope placement, re-targeting on move, and cleanup on disconnect.
Checklist