Skip to content

Commit 036c5d2

Browse files
mattrbeckthePunderWoman
authored andcommitted
fix(compiler): support one additional level of nesting in :host()
Previously we supported one level of nested parentheses inside of a `:host()` selector, e.g. `:host(:not(p))`. This caused a breakage in g3 when I migrated a selector from `:host:not(:has(p))` to `:host(:not(:has(p)))`. This change adds support for just one more level of nesting. It'd be nice to move everything to a real CSS parser (or even update it to count parentheses like I did with :host-context()), but I wasn't able to get that to work in ~20 minutes and I'm focusing on other things at the moment. This change punts the problem until somebody tries to use just one more level of nesting in a selector. Fixes angular#64830 (cherry picked from commit 4441437)
1 parent ee578d3 commit 036c5d2

File tree

2 files changed

+10
-1
lines changed

2 files changed

+10
-1
lines changed

packages/compiler/src/shadow_css.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1045,7 +1045,13 @@ const _cssContentUnscopedRuleRe =
10451045
const _polyfillHost = '-shadowcsshost';
10461046
// note: :host-context pre-processed to -shadowcsshostcontext.
10471047
const _polyfillHostContext = '-shadowcsscontext';
1048-
const _parenSuffix = '(?:\\((' + '(?:\\([^)(]*\\)|[^)(]*)+?' + ')\\))';
1048+
// Matches text content with no parentheses, e.g., "foo"
1049+
const _noParens = '[^)(]*';
1050+
// Matches content with at most ONE level of nesting, e.g., "a(b)c"
1051+
const _level1Parens = String.raw`(?:\(${_noParens}\)|${_noParens})+?`;
1052+
// Matches content with at most TWO levels of nesting, e.g., "a(b(c)d)e"
1053+
const _level2Parens = String.raw`(?:\(${_level1Parens}\)|${_noParens})+?`;
1054+
const _parenSuffix = String.raw`(?:\((${_level2Parens})\))`;
10491055
const _cssColonHostRe = new RegExp(_polyfillHost + _parenSuffix + '?([^,{]*)', 'gim');
10501056
// note: :host-context patterns are terminated with `{`, as opposed to :host which
10511057
// is both `{` and `,` because :host-context handles top-level commas differently.

packages/compiler/test/shadow_css/host_and_host_context_spec.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,9 @@ describe('ShadowCss, :host and :host-context', () => {
8383
expect(shim(':host(:not(p)):before {}', 'contenta', 'a-host')).toEqualCss(
8484
'[a-host]:not(p):before {}',
8585
);
86+
expect(shim(':host(:not(:has(p))) {}', 'contenta', 'a-host')).toEqualCss(
87+
'[a-host]:not(:has(p)) {}',
88+
);
8689
expect(shim(':host:not(:host.foo) {}', 'contenta', 'a-host')).toEqualCss(
8790
'[a-host]:not([a-host].foo) {}',
8891
);

0 commit comments

Comments
 (0)