diff --git a/packages/compiler/src/shadow_css.ts b/packages/compiler/src/shadow_css.ts index 0ca0858a25..2b8ec4eb5d 100644 --- a/packages/compiler/src/shadow_css.ts +++ b/packages/compiler/src/shadow_css.ts @@ -314,7 +314,7 @@ export class ShadowCss { // The context selectors now must be combined with each other to capture all the possible // selectors that `:host-context` can match. - return combineHostContextSelectors(_polyfillHostNoCombinator, contextSelectors, selectorText); + return combineHostContextSelectors(contextSelectors, selectorText); }); } @@ -682,8 +682,10 @@ function escapeBlocks( * @param contextSelectors an array of context selectors that will be combined. * @param otherSelectors the rest of the selectors that are not context selectors. */ -function combineHostContextSelectors( - hostMarker: string, contextSelectors: string[], otherSelectors: string): string { +function combineHostContextSelectors(contextSelectors: string[], otherSelectors: string): string { + const hostMarker = _polyfillHostNoCombinator; + const otherSelectorsHasHost = _polyfillHostRe.test(otherSelectors); + // If there are no context selectors then just output a host marker if (contextSelectors.length === 0) { return hostMarker + otherSelectors; @@ -706,6 +708,9 @@ function combineHostContextSelectors( // Finally connect the selector to the `hostMarker`s: either acting directly on the host // (A) or as an ancestor (A ). return combined - .map(s => `${s}${hostMarker}${otherSelectors}, ${s} ${hostMarker}${otherSelectors}`) + .map( + s => otherSelectorsHasHost ? + `${s}${otherSelectors}` : + `${s}${hostMarker}${otherSelectors}, ${s} ${hostMarker}${otherSelectors}`) .join(','); } diff --git a/packages/compiler/test/shadow_css_spec.ts b/packages/compiler/test/shadow_css_spec.ts index f652706ec3..ac0560f82b 100644 --- a/packages/compiler/test/shadow_css_spec.ts +++ b/packages/compiler/test/shadow_css_spec.ts @@ -260,6 +260,21 @@ import {normalizeCSS} from '@angular/platform-browser/testing/src/browser_util'; }); }); + describe((':host-context and :host combination selector'), () => { + it('should handle selectors on the same element', () => { + expect(s(':host-context(div):host(.x) > .y {}', 'contenta', 'a-host')) + .toEqual('div.x[a-host] > .y[contenta] {}'); + }); + + it('should handle selectors on different elements', () => { + expect(s(':host-context(div) :host(.x) > .y {}', 'contenta', 'a-host')) + .toEqual('div .x[a-host] > .y[contenta] {}'); + + expect(s(':host-context(div) > :host(.x) > .y {}', 'contenta', 'a-host')) + .toEqual('div > .x[a-host] > .y[contenta] {}'); + }); + }); + it('should support polyfill-next-selector', () => { let css = s('polyfill-next-selector {content: \'x > y\'} z {}', 'contenta'); expect(css).toEqual('x[contenta] > y[contenta]{}');