From 4a1c12c773f14dbfc5db61087f415d56f60127cf Mon Sep 17 00:00:00 2001 From: Kristiyan Kostadinov Date: Thu, 8 Oct 2020 16:59:29 +0200 Subject: [PATCH] feat(core): remove ViewEncapsulation.Native (#38882) Removes `ViewEncapsulation.Native` which has been deprecated for several major versions. BREAKING CHANGES: * `ViewEncapsulation.Native` has been removed. Use `ViewEncapsulation.ShadowDom` instead. Existing usages will be updated automatically by `ng update`. PR Close #38882 --- .../src/app/quest-summary.component.ts | 6 ++-- aio/content/guide/deprecations.md | 2 -- aio/content/guide/view-encapsulation.md | 6 ++-- .../layout/doc-viewer/doc-viewer.component.ts | 2 +- goldens/public-api/core/core.d.ts | 1 - .../size-tracking/integration-payloads.json | 2 +- .../bazel/src/schematics/ng-new/schema.d.ts | 1 - .../r3_view_compiler_styling_spec.ts | 6 ++-- .../test/ngtsc/fake_core/index.ts | 2 +- .../compiler/src/compiler_facade_interface.ts | 2 +- packages/compiler/src/core.ts | 2 +- packages/compiler/src/render3/view/api.ts | 2 -- .../test/directive_normalizer_spec.ts | 2 +- .../src/compiler/compiler_facade_interface.ts | 2 +- packages/core/src/metadata/directives.ts | 1 - packages/core/src/metadata/view.ts | 12 ++------ .../core/src/render3/node_manipulation.ts | 4 +-- packages/core/src/view/util.ts | 5 +++- .../linker/projection_integration_spec.ts | 30 +++++++++---------- .../platform-browser/src/dom/dom_renderer.ts | 20 ++++++++----- .../test/dom/dom_renderer_spec.ts | 27 +++++------------ .../test/dom/shadow_dom_spec.ts | 4 +-- .../platform-browser/testing/src/matchers.ts | 10 +++++-- .../platform-server/src/server_renderer.ts | 1 - .../platform-server/test/integration_spec.ts | 16 +++++----- 25 files changed, 77 insertions(+), 91 deletions(-) diff --git a/aio/content/examples/component-styles/src/app/quest-summary.component.ts b/aio/content/examples/component-styles/src/app/quest-summary.component.ts index 25765ed16d..6d7b580582 100644 --- a/aio/content/examples/component-styles/src/app/quest-summary.component.ts +++ b/aio/content/examples/component-styles/src/app/quest-summary.component.ts @@ -13,8 +13,8 @@ import { Component, ViewEncapsulation } from '@angular/core'; export class QuestSummaryComponent { } // #enddocregion /* - // #docregion encapsulation.native + // #docregion encapsulation.shadow // warning: few browsers support shadow DOM encapsulation at this time - encapsulation: ViewEncapsulation.Native - // #enddocregion encapsulation.native + encapsulation: ViewEncapsulation.ShadowDom + // #enddocregion encapsulation.shadow */ diff --git a/aio/content/guide/deprecations.md b/aio/content/guide/deprecations.md index 20205263e3..a8879533b1 100644 --- a/aio/content/guide/deprecations.md +++ b/aio/content/guide/deprecations.md @@ -41,7 +41,6 @@ v9 - v12 | `@angular/core` | [`DefaultIterableDiffer`](#core) | v11 | | `@angular/core` | [`ReflectiveKey`](#core) | v11 | | `@angular/core` | [`RenderComponentType`](#core) | v11 | -| `@angular/core` | [`ViewEncapsulation.Native`](#core) | v11 | | `@angular/core` | [`WrappedValue`](#core) | v12 | | `@angular/forms` | [`ngModel` with reactive forms](#ngmodel-reactive) | v11 | | `@angular/router` | [`preserveQueryParams`](#router) | v11 | @@ -89,7 +88,6 @@ Tip: In the [API reference section](api) of this doc site, deprecated APIs are i | [`DefaultIterableDiffer`](api/core/DefaultIterableDiffer) | n/a | v4 | Not part of public API. | | [`ReflectiveInjector`](api/core/ReflectiveInjector) | [`Injector.create`](api/core/Injector#create) | v5 | See [`ReflectiveInjector`](#reflectiveinjector) | | [`ReflectiveKey`](api/core/ReflectiveKey) | none | v5 | none | -| [`ViewEncapsulation.Native`](api/core/ViewEncapsulation#Native) | [`ViewEncapsulation.ShadowDom`](api/core/ViewEncapsulation#ShadowDom) | v6 | Use the native encapsulation mechanism of the renderer. See [view.ts](https://github.com/angular/angular/blob/3e992e18ebf51d6036818f26c3d77b52d3ec48eb/packages/core/src/metadata/view.ts#L32). | [`defineInjectable`](api/core/defineInjectable) | `ɵɵdefineInjectable` | v8 | Used only in generated code. No source code should depend on this API. | | [`entryComponents`](api/core/NgModule#entryComponents) | none | v9 | See [`entryComponents`](#entryComponents) | | [`ANALYZE_FOR_ENTRY_COMPONENTS`](api/core/ANALYZE_FOR_ENTRY_COMPONENTS) | none | v9 | See [`ANALYZE_FOR_ENTRY_COMPONENTS`](#entryComponents) | diff --git a/aio/content/guide/view-encapsulation.md b/aio/content/guide/view-encapsulation.md index 0c82a247c8..b0e95d4eca 100644 --- a/aio/content/guide/view-encapsulation.md +++ b/aio/content/guide/view-encapsulation.md @@ -13,8 +13,6 @@ Choose from the following modes: to attach a shadow DOM to the component's host element, and then puts the component view inside that shadow DOM. The component's styles are included within the shadow DOM. -* `Native` view encapsulation uses a now deprecated version of the browser's native shadow DOM implementation - [learn about the changes](https://hayato.io/2016/shadowdomv1/). - * `Emulated` view encapsulation (the default) emulates the behavior of shadow DOM by preprocessing (and renaming) the CSS code to effectively scope the CSS to the component's view. For details, see [Inspecting generated CSS](guide/view-encapsulation#inspect-generated-css) below. @@ -26,7 +24,7 @@ Choose from the following modes: To set the components encapsulation mode, use the `encapsulation` property in the component metadata: - + `ShadowDom` view encapsulation only works on browsers that have native support for shadow DOM (see [Shadow DOM v1](https://caniuse.com/#feat=shadowdomv1) on the @@ -80,4 +78,4 @@ by the generated component styles, which are in the `` section of the DOM: These styles are post-processed so that each selector is augmented with `_nghost` or `_ngcontent` attribute selectors. -These extra selectors enable the scoping rules described in this page. \ No newline at end of file +These extra selectors enable the scoping rules described in this page. diff --git a/aio/src/app/layout/doc-viewer/doc-viewer.component.ts b/aio/src/app/layout/doc-viewer/doc-viewer.component.ts index 2661dfc533..0fce7f88cd 100644 --- a/aio/src/app/layout/doc-viewer/doc-viewer.component.ts +++ b/aio/src/app/layout/doc-viewer/doc-viewer.component.ts @@ -21,7 +21,7 @@ const initialDocViewerContent = initialDocViewerElement ? initialDocViewerElemen selector: 'aio-doc-viewer', template: '' // TODO(robwormald): shadow DOM and emulated don't work here (?!) - // encapsulation: ViewEncapsulation.Native + // encapsulation: ViewEncapsulation.ShadowDom }) export class DocViewerComponent implements OnDestroy { // Enable/Disable view transition animations. diff --git a/goldens/public-api/core/core.d.ts b/goldens/public-api/core/core.d.ts index 71a497aeb5..b128f9b3ae 100644 --- a/goldens/public-api/core/core.d.ts +++ b/goldens/public-api/core/core.d.ts @@ -1032,7 +1032,6 @@ export declare abstract class ViewContainerRef { export declare enum ViewEncapsulation { Emulated = 0, - Native = 1, None = 2, ShadowDom = 3 } diff --git a/goldens/size-tracking/integration-payloads.json b/goldens/size-tracking/integration-payloads.json index 7b1a63b4d1..7155628916 100644 --- a/goldens/size-tracking/integration-payloads.json +++ b/goldens/size-tracking/integration-payloads.json @@ -30,7 +30,7 @@ "master": { "uncompressed": { "runtime-es2015": 1485, - "main-es2015": 134891, + "main-es2015": 135003, "polyfills-es2015": 37248 } } diff --git a/packages/bazel/src/schematics/ng-new/schema.d.ts b/packages/bazel/src/schematics/ng-new/schema.d.ts index 69aedc72d8..a734a45e27 100644 --- a/packages/bazel/src/schematics/ng-new/schema.d.ts +++ b/packages/bazel/src/schematics/ng-new/schema.d.ts @@ -107,7 +107,6 @@ export declare enum Style { */ export declare enum ViewEncapsulation { Emulated = 'Emulated', - Native = 'Native', None = 'None', ShadowDom = 'ShadowDom' } diff --git a/packages/compiler-cli/test/compliance/r3_view_compiler_styling_spec.ts b/packages/compiler-cli/test/compliance/r3_view_compiler_styling_spec.ts index 80b97f9df9..7fdd3a4132 100644 --- a/packages/compiler-cli/test/compliance/r3_view_compiler_styling_spec.ts +++ b/packages/compiler-cli/test/compliance/r3_view_compiler_styling_spec.ts @@ -72,7 +72,7 @@ describe('compiler compliance: styling', () => { expectEmit(result.source, template, 'Incorrect template'); }); - it('should pass in the component metadata styles into the component definition but skip shimming when style encapsulation is set to native', + it('should pass in the component metadata styles into the component definition but skip shimming when style encapsulation is set to shadow dom', () => { const files = { app: { @@ -80,7 +80,7 @@ describe('compiler compliance: styling', () => { import {Component, NgModule, ViewEncapsulation} from '@angular/core'; @Component({ - encapsulation: ViewEncapsulation.Native, + encapsulation: ViewEncapsulation.ShadowDom, selector: "my-component", styles: ["div.cool { color: blue; }", ":host.nice p { color: gold; }"], template: "..." @@ -98,7 +98,7 @@ describe('compiler compliance: styling', () => { MyComponent.ɵcmp = $r3$.ɵɵdefineComponent({ … styles: ["div.cool { color: blue; }", ":host.nice p { color: gold; }"], - encapsulation: 1 + encapsulation: 3 }) `; const result = compile(files, angularFiles); diff --git a/packages/compiler-cli/test/ngtsc/fake_core/index.ts b/packages/compiler-cli/test/ngtsc/fake_core/index.ts index 7aad1050cf..4d9f8d3efb 100644 --- a/packages/compiler-cli/test/ngtsc/fake_core/index.ts +++ b/packages/compiler-cli/test/ngtsc/fake_core/index.ts @@ -77,7 +77,7 @@ export type ɵɵPipeDefWithMeta = any; export enum ViewEncapsulation { Emulated = 0, - Native = 1, + // Historically the 1 value was for `Native` encapsulation which has been removed as of v11. None = 2, ShadowDom = 3 } diff --git a/packages/compiler/src/compiler_facade_interface.ts b/packages/compiler/src/compiler_facade_interface.ts index 94e9a87fe9..dc0253771c 100644 --- a/packages/compiler/src/compiler_facade_interface.ts +++ b/packages/compiler/src/compiler_facade_interface.ts @@ -173,7 +173,7 @@ export interface R3FactoryDefMetadataFacade { export enum ViewEncapsulation { Emulated = 0, - Native = 1, + // Historically the 1 value was for `Native` encapsulation which has been removed as of v11. None = 2, ShadowDom = 3 } diff --git a/packages/compiler/src/core.ts b/packages/compiler/src/core.ts index f6612c93de..d9360f45fa 100644 --- a/packages/compiler/src/core.ts +++ b/packages/compiler/src/core.ts @@ -82,7 +82,7 @@ export interface Component extends Directive { } export enum ViewEncapsulation { Emulated = 0, - Native = 1, + // Historically the 1 value was for `Native` encapsulation which has been removed as of v11. None = 2, ShadowDom = 3 } diff --git a/packages/compiler/src/render3/view/api.ts b/packages/compiler/src/render3/view/api.ts index acc8126c83..162f74fdfa 100644 --- a/packages/compiler/src/render3/view/api.ts +++ b/packages/compiler/src/render3/view/api.ts @@ -163,8 +163,6 @@ export interface R3ComponentMetadata extends R3DirectiveMetadata { /** * An encapsulation policy for the template and CSS styles. One of: - * - `ViewEncapsulation.Native`: Use shadow roots. This works only if natively available on the - * platform (note that this is marked the as the "deprecated shadow DOM" as of Angular v6.1. * - `ViewEncapsulation.Emulated`: Use shimmed CSS that emulates the native behavior. * - `ViewEncapsulation.None`: Use global CSS without any encapsulation. * - `ViewEncapsulation.ShadowDom`: Use the latest ShadowDOM API to natively encapsulate styles diff --git a/packages/compiler/test/directive_normalizer_spec.ts b/packages/compiler/test/directive_normalizer_spec.ts index a007b10fc2..94df9dcdb6 100644 --- a/packages/compiler/test/directive_normalizer_spec.ts +++ b/packages/compiler/test/directive_normalizer_spec.ts @@ -226,7 +226,7 @@ function normalizeTemplate(normalizer: DirectiveNormalizer, o: { describe('normalizeLoadedTemplate', () => { it('should store the viewEncapsulation in the result', inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => { - const viewEncapsulation = ViewEncapsulation.Native; + const viewEncapsulation = ViewEncapsulation.ShadowDom; const template = normalizeTemplate(normalizer, { encapsulation: viewEncapsulation, template: '', diff --git a/packages/core/src/compiler/compiler_facade_interface.ts b/packages/core/src/compiler/compiler_facade_interface.ts index 94e9a87fe9..dc0253771c 100644 --- a/packages/core/src/compiler/compiler_facade_interface.ts +++ b/packages/core/src/compiler/compiler_facade_interface.ts @@ -173,7 +173,7 @@ export interface R3FactoryDefMetadataFacade { export enum ViewEncapsulation { Emulated = 0, - Native = 1, + // Historically the 1 value was for `Native` encapsulation which has been removed as of v11. None = 2, ShadowDom = 3 } diff --git a/packages/core/src/metadata/directives.ts b/packages/core/src/metadata/directives.ts index 66abfee3f4..147a20e453 100644 --- a/packages/core/src/metadata/directives.ts +++ b/packages/core/src/metadata/directives.ts @@ -518,7 +518,6 @@ export interface Component extends Directive { /** * An encapsulation policy for the template and CSS styles. One of: - * - `ViewEncapsulation.Native`: Deprecated. Use `ViewEncapsulation.ShadowDom` instead. * - `ViewEncapsulation.Emulated`: Use shimmed CSS that * emulates the native behavior. * - `ViewEncapsulation.None`: Use global CSS without any diff --git a/packages/core/src/metadata/view.ts b/packages/core/src/metadata/view.ts index fbc5f492cd..d8295d2b16 100644 --- a/packages/core/src/metadata/view.ts +++ b/packages/core/src/metadata/view.ts @@ -28,15 +28,9 @@ export enum ViewEncapsulation { * This is the default option. */ Emulated = 0, - /** - * @deprecated v6.1.0 - use {ViewEncapsulation.ShadowDom} instead. - * Use the native encapsulation mechanism of the renderer. - * - * For the DOM this means using the deprecated [Shadow DOM - * v0](https://w3c.github.io/webcomponents/spec/shadow/) and - * creating a ShadowRoot for Component's Host Element. - */ - Native = 1, + + // Historically the 1 value was for `Native` encapsulation which has been removed as of v11. + /** * Don't provide any template or style encapsulation. */ diff --git a/packages/core/src/render3/node_manipulation.ts b/packages/core/src/render3/node_manipulation.ts index 44fe80c781..69b503a0d9 100644 --- a/packages/core/src/render3/node_manipulation.ts +++ b/packages/core/src/render3/node_manipulation.ts @@ -517,8 +517,8 @@ function getRenderParent(tView: TView, tNode: TNode, currentView: LView): REleme // Since the projection would then move it to its final destination. Note that we can't // make this assumption when using the Shadow DOM, because the native projection placeholders // ( or ) have to be in place as elements are being inserted. - if (encapsulation !== ViewEncapsulation.ShadowDom && - encapsulation !== ViewEncapsulation.Native) { + if (encapsulation === ViewEncapsulation.None || + encapsulation === ViewEncapsulation.Emulated) { return null; } } diff --git a/packages/core/src/view/util.ts b/packages/core/src/view/util.ts index 9d5b52b5ba..2259808c10 100644 --- a/packages/core/src/view/util.ts +++ b/packages/core/src/view/util.ts @@ -230,7 +230,10 @@ export function getParentRenderElement(view: ViewData, renderHost: any, def: Nod if ((renderParent.flags & NodeFlags.TypeElement) === 0 || (renderParent.flags & NodeFlags.ComponentView) === 0 || (renderParent.element!.componentRendererType && - renderParent.element!.componentRendererType!.encapsulation === ViewEncapsulation.Native)) { + (renderParent.element!.componentRendererType!.encapsulation === + ViewEncapsulation.ShadowDom || + // TODO(FW-2290): remove the `encapsulation === 1` fallback logic in v12. + renderParent.element!.componentRendererType!.encapsulation === 1))) { // only children of non components, or children of components with native encapsulation should // be attached. return asElementData(view, def.renderParent!.nodeIndex).renderElement; diff --git a/packages/core/test/linker/projection_integration_spec.ts b/packages/core/test/linker/projection_integration_spec.ts index 6392969c32..d97673918f 100644 --- a/packages/core/test/linker/projection_integration_spec.ts +++ b/packages/core/test/linker/projection_integration_spec.ts @@ -490,13 +490,13 @@ describe('projection', () => { expect(main.nativeElement).toHaveText('TREE(0:TREE2(1:TREE(2:)))'); }); - if (supportsNativeShadowDOM()) { - it('should support native content projection and isolate styles per component', () => { - TestBed.configureTestingModule({declarations: [SimpleNative1, SimpleNative2]}); + if (supportsShadowDOM()) { + it('should support shadow dom content projection and isolate styles per component', () => { + TestBed.configureTestingModule({declarations: [SimpleShadowDom1, SimpleShadowDom2]}); TestBed.overrideComponent(MainComp, { set: { - template: '
A
' + - '
B
' + template: '
A
' + + '
B
' } }); const main = TestBed.createComponent(MainComp); @@ -857,21 +857,21 @@ class Simple { } @Component({ - selector: 'simple-native1', - template: 'SIMPLE1()', - encapsulation: ViewEncapsulation.Native, + selector: 'simple-shadow-dom1', + template: 'SIMPLE1()', + encapsulation: ViewEncapsulation.ShadowDom, styles: ['div {color: red}'] }) -class SimpleNative1 { +class SimpleShadowDom1 { } @Component({ - selector: 'simple-native2', - template: 'SIMPLE2()', - encapsulation: ViewEncapsulation.Native, + selector: 'simple-shadow-dom2', + template: 'SIMPLE2()', + encapsulation: ViewEncapsulation.ShadowDom, styles: ['div {color: blue}'] }) -class SimpleNative2 { +class SimpleShadowDom2 { } @Component({selector: 'empty', template: ''}) @@ -1043,6 +1043,6 @@ class CmpA1 { class CmpA2 { } -function supportsNativeShadowDOM(): boolean { - return typeof (document.body).createShadowRoot === 'function'; +function supportsShadowDOM(): boolean { + return typeof (document.body).attachShadow !== 'undefined'; } diff --git a/packages/platform-browser/src/dom/dom_renderer.ts b/packages/platform-browser/src/dom/dom_renderer.ts index 6925873d29..33d0bc67bc 100644 --- a/packages/platform-browser/src/dom/dom_renderer.ts +++ b/packages/platform-browser/src/dom/dom_renderer.ts @@ -74,6 +74,8 @@ function decoratePreventDefault(eventHandler: Function): Function { }; } +let hasLoggedNativeEncapsulationWarning = false; + @Injectable() export class DomRendererFactory2 implements RendererFactory2 { private rendererByCompId = new Map(); @@ -100,8 +102,16 @@ export class DomRendererFactory2 implements RendererFactory2 { (renderer).applyToHost(element); return renderer; } - case ViewEncapsulation.Native: + case 1: case ViewEncapsulation.ShadowDom: + // TODO(FW-2290): remove the `case 1:` fallback logic and the warning in v12. + if ((typeof ngDevMode === 'undefined' || ngDevMode) && + !hasLoggedNativeEncapsulationWarning && type.encapsulation === 1) { + hasLoggedNativeEncapsulationWarning = true; + console.warn( + 'ViewEncapsulation.Native is no longer supported. Falling back to ViewEncapsulation.ShadowDom. The fallback will be removed in v12.'); + } + return new ShadowDomRenderer(this.eventManager, this.sharedStylesHost, element, type); default: { if (!this.rendererByCompId.has(type.id)) { @@ -302,13 +312,9 @@ class ShadowDomRenderer extends DefaultDomRenderer2 { constructor( eventManager: EventManager, private sharedStylesHost: DomSharedStylesHost, - private hostEl: any, private component: RendererType2) { + private hostEl: any, component: RendererType2) { super(eventManager); - if (component.encapsulation === ViewEncapsulation.ShadowDom) { - this.shadowRoot = (hostEl as any).attachShadow({mode: 'open'}); - } else { - this.shadowRoot = (hostEl as any).createShadowRoot(); - } + this.shadowRoot = (hostEl as any).attachShadow({mode: 'open'}); this.sharedStylesHost.addHost(this.shadowRoot); const styles = flattenStyles(component.id, component.styles, []); for (let i = 0; i < styles.length; i++) { diff --git a/packages/platform-browser/test/dom/dom_renderer_spec.ts b/packages/platform-browser/test/dom/dom_renderer_spec.ts index 8ee0cf550e..1dfb5deeaf 100644 --- a/packages/platform-browser/test/dom/dom_renderer_spec.ts +++ b/packages/platform-browser/test/dom/dom_renderer_spec.ts @@ -20,8 +20,8 @@ import {expect} from '@angular/platform-browser/testing/src/matchers'; beforeEach(() => { TestBed.configureTestingModule({ declarations: [ - TestCmp, SomeApp, CmpEncapsulationEmulated, CmpEncapsulationNative, CmpEncapsulationNone, - CmpEncapsulationNative + TestCmp, SomeApp, CmpEncapsulationEmulated, CmpEncapsulationShadow, CmpEncapsulationNone, + CmpEncapsulationShadow ] }); renderer = TestBed.createComponent(TestCmp).componentInstance.renderer; @@ -98,16 +98,14 @@ import {expect} from '@angular/platform-browser/testing/src/matchers'; }); }); - if (browserDetection.supportsDeprecatedShadowDomV0) { + if (browserDetection.supportsShadowDom) { it('should allow to style components with emulated encapsulation and no encapsulation inside of components with shadow DOM', () => { const fixture = TestBed.createComponent(SomeApp); + const cmp = fixture.debugElement.query(By.css('cmp-shadow')).nativeElement; + const shadow = cmp.shadowRoot.querySelector('.shadow'); - const cmp = fixture.debugElement.query(By.css('cmp-native')).nativeElement; - - - const native = cmp.shadowRoot.querySelector('.native'); - expect(window.getComputedStyle(native).color).toEqual('rgb(255, 0, 0)'); + expect(window.getComputedStyle(shadow).color).toEqual('rgb(255, 0, 0)'); const emulated = cmp.shadowRoot.querySelector('.emulated'); expect(window.getComputedStyle(emulated).color).toEqual('rgb(0, 0, 255)'); @@ -119,15 +117,6 @@ import {expect} from '@angular/platform-browser/testing/src/matchers'; }); } -@Component({ - selector: 'cmp-native', - template: `
`, - styles: [`.native { color: red; }`], - encapsulation: ViewEncapsulation.Native -}) -class CmpEncapsulationNative { -} - @Component({ selector: 'cmp-emulated', template: `
`, @@ -149,7 +138,7 @@ class CmpEncapsulationNone { @Component({ selector: 'cmp-shadow', template: `
`, - styles: [`.native { color: red; }`], + styles: [`.shadow { color: red; }`], encapsulation: ViewEncapsulation.ShadowDom }) class CmpEncapsulationShadow { @@ -158,7 +147,7 @@ class CmpEncapsulationShadow { @Component({ selector: 'some-app', template: ` - + `, diff --git a/packages/platform-browser/test/dom/shadow_dom_spec.ts b/packages/platform-browser/test/dom/shadow_dom_spec.ts index 9a4abab09d..afb6d1f462 100644 --- a/packages/platform-browser/test/dom/shadow_dom_spec.ts +++ b/packages/platform-browser/test/dom/shadow_dom_spec.ts @@ -15,13 +15,11 @@ import {expect} from '@angular/platform-browser/testing/src/matchers'; if (browserDetection.supportsShadowDom) { describe('ShadowDOM Support', () => { - let testContainer: HTMLDivElement; - beforeEach(() => { TestBed.configureTestingModule({imports: [TestModule]}); }); - it('should attach and use a shadowRoot when ViewEncapsulation.Native is set', () => { + it('should attach and use a shadowRoot when ViewEncapsulation.ShadowDom is set', () => { const compEl = TestBed.createComponent(ShadowComponent).nativeElement; expect(compEl.shadowRoot!.textContent).toEqual('Hello World'); }); diff --git a/packages/platform-browser/testing/src/matchers.ts b/packages/platform-browser/testing/src/matchers.ts index cd3bbec46b..ffdac71739 100644 --- a/packages/platform-browser/testing/src/matchers.ts +++ b/packages/platform-browser/testing/src/matchers.ts @@ -305,8 +305,14 @@ function elementText(n: any): string { return ''; } - if (getDOM().isElementNode(n) && (n as Element).tagName == 'CONTENT') { - return elementText(Array.prototype.slice.apply((n).getDistributedNodes())); + if (getDOM().isElementNode(n)) { + const tagName = (n as Element).tagName; + + if (tagName === 'CONTENT') { + return elementText(Array.prototype.slice.apply((n).getDistributedNodes())); + } else if (tagName === 'SLOT') { + return elementText(Array.prototype.slice.apply((n).assignedNodes())); + } } if (hasShadowRoot(n)) { diff --git a/packages/platform-server/src/server_renderer.ts b/packages/platform-server/src/server_renderer.ts index d4198825e1..fb6334ad67 100644 --- a/packages/platform-server/src/server_renderer.ts +++ b/packages/platform-server/src/server_renderer.ts @@ -32,7 +32,6 @@ export class ServerRendererFactory2 implements RendererFactory2 { return this.defaultRenderer; } switch (type.encapsulation) { - case ViewEncapsulation.Native: case ViewEncapsulation.Emulated: { let renderer = this.rendererByCompId.get(type.id); if (!renderer) { diff --git a/packages/platform-server/test/integration_spec.ts b/packages/platform-server/test/integration_spec.ts index 8fc8c91325..d345ab4afb 100644 --- a/packages/platform-server/test/integration_spec.ts +++ b/packages/platform-server/test/integration_spec.ts @@ -272,19 +272,19 @@ class ImageExampleModule { @Component({ selector: 'app', - template: 'Native works', - encapsulation: ViewEncapsulation.Native, + template: 'Shadow DOM works', + encapsulation: ViewEncapsulation.ShadowDom, styles: [':host { color: red; }'] }) -class NativeEncapsulationApp { +class ShadowDomEncapsulationApp { } @NgModule({ - declarations: [NativeEncapsulationApp], + declarations: [ShadowDomEncapsulationApp], imports: [BrowserModule.withServerTransition({appId: 'test'}), ServerModule], - bootstrap: [NativeEncapsulationApp] + bootstrap: [ShadowDomEncapsulationApp] }) -class NativeExampleModule { +class ShadowDomExampleModule { } @Component({selector: 'my-child', template: 'Works!'}) @@ -666,8 +666,8 @@ describe('platform-server integration', () => { }); })); - it('should handle ViewEncapsulation.Native', waitForAsync(() => { - renderModule(NativeExampleModule, {document: doc}).then(output => { + it('should handle ViewEncapsulation.ShadowDom', waitForAsync(() => { + renderModule(ShadowDomExampleModule, {document: doc}).then(output => { expect(output).not.toBe(''); expect(output).toContain('color: red'); called = true;