Skip to content

fix(compiler): avoid leaking ::ng-deep detection state between rules - #71119

Open
irontaek wants to merge 1 commit into
angular:mainfrom
irontaek:fix/shadow-css-ng-deep-last-index
Open

irontaek wants to merge 1 commit into
angular:mainfrom
irontaek:fix/shadow-css-ng-deep-last-index

Conversation

@irontaek

@irontaek irontaek commented Oct 1, 2026

Copy link
Copy Markdown

PR Checklist

  • The commit message follows Angular's guidelines.
  • Tests for the changes have been added.
  • Docs have been added / updated (not applicable: no API change).

PR Type

  • Bugfix

What is the current behavior?

#69885 skips encapsulating nested selectors when the parent selector contains ::ng-deep. The check uses _shadowDeepSelectors.test(part), but _shadowDeepSelectors is a module-level regex with the g flag, so a match leaves lastIndex set for the next call.

When the matched rule has an empty body, nothing resets it. The next ::ng-deep rule is then tested from the stale offset, is not detected, and its nested selectors get scoped. This also crosses stylesheets: with @angular/compiler@22.2.1,

encapsulateStyle('::ng-deep .p { .q { color: blue; } }', 'b');
// .p { .q { color: blue; } }

encapsulateStyle('.foo ::ng-deep .bar {}', 'a');
encapsulateStyle('::ng-deep .p { .q { color: blue; } }', 'b');
// .p { .q[_ngcontent-b] { color: blue; } }

Issue Number: N/A

What is the new behavior?

The check uses a non-global copy of the same pattern, so the result no longer depends on earlier rules. _shadowDeepSelectors keeps the g flag for its replace and split uses.

Does this PR introduce a breaking change?

  • No

Other information

  • pnpm bazel test //packages/compiler/test:test — the new spec fails without the fix (.qux[contenta]) and passes with it; the rest of the suite passes.
  • Prettier and commit message checks passed.

The check that skips encapsulating nested selectors under `::ng-deep` used
`.test()` on a global regex, so `lastIndex` carried over to the next rule
(or the next stylesheet) when nothing else reset it. A following
`::ng-deep` rule could then be missed and its nested selectors scoped.
@pullapprove
pullapprove Bot requested a review from JoostK October 1, 2026 14:02
@angular-robot angular-robot Bot added the area: compiler Issues related to `ngc`, Angular's template compiler label Oct 1, 2026
@ngbot ngbot Bot added this to the Backlog milestone Oct 1, 2026
@JoostK JoostK added action: merge The PR is ready for merge by the caretaker target: patch This PR is targeted for the next patch release action: presubmit The PR is in need of a google3 presubmit labels Oct 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

action: merge The PR is ready for merge by the caretaker action: presubmit The PR is in need of a google3 presubmit area: compiler Issues related to `ngc`, Angular's template compiler target: patch This PR is targeted for the next patch release

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants