diff --git a/packages/core/src/render3/component.ts b/packages/core/src/render3/component.ts index 42af53fbba..579c93bd9a 100644 --- a/packages/core/src/render3/component.ts +++ b/packages/core/src/render3/component.ts @@ -106,7 +106,7 @@ export function renderComponent( const rootContext = createRootContext(opts.scheduler || requestAnimationFrame.bind(window)); const rootView: LViewData = createLViewData( - rendererFactory.createRenderer(hostNode, componentDef.rendererType), + rendererFactory.createRenderer(hostNode, componentDef), createTView(-1, null, null, null, null), rootContext, componentDef.onPush ? LViewFlags.Dirty : LViewFlags.CheckAlways); rootView[INJECTOR] = opts.injector || null; diff --git a/packages/core/src/render3/component_ref.ts b/packages/core/src/render3/component_ref.ts index 6c1a79c8af..34c0b98e15 100644 --- a/packages/core/src/render3/component_ref.ts +++ b/packages/core/src/render3/component_ref.ts @@ -87,8 +87,7 @@ export class ComponentFactory extends viewEngine_ComponentFactory { const rendererFactory = ngModule ? ngModule.injector.get(RendererFactory2) : domRendererFactory3; const hostNode = isInternalRootView ? - elementCreate( - this.selector, rendererFactory.createRenderer(null, this.componentDef.rendererType)) : + elementCreate(this.selector, rendererFactory.createRenderer(null, this.componentDef)) : locateHostElement(rendererFactory, rootSelectorOrNode); // The first index of the first selector is the tag name. @@ -100,7 +99,7 @@ export class ComponentFactory extends viewEngine_ComponentFactory { // Create the root view. Uses empty TView and ContentTemplate. const rootView: LViewData = createLViewData( - rendererFactory.createRenderer(hostNode, this.componentDef.rendererType), + rendererFactory.createRenderer(hostNode, this.componentDef), createTView(-1, null, null, null, null), rootContext, this.componentDef.onPush ? LViewFlags.Dirty : LViewFlags.CheckAlways); rootView[INJECTOR] = ngModule && ngModule.injector || null; diff --git a/packages/core/src/render3/definition.ts b/packages/core/src/render3/definition.ts index 92e0601fa8..ead1db96c9 100644 --- a/packages/core/src/render3/definition.ts +++ b/packages/core/src/render3/definition.ts @@ -6,17 +6,22 @@ * found in the LICENSE file at https://angular.io/license */ +import './ng_dev_mode'; + import {ChangeDetectionStrategy} from '../change_detection/constants'; -import {Provider} from '../core'; +import {Provider, ViewEncapsulation} from '../core'; import {NgModuleDef, NgModuleDefInternal} from '../metadata/ng_module'; -import {RendererType2} from '../render/api'; import {Type} from '../type'; -import {resolveRendererType2} from '../view/util'; import {BaseDef, ComponentDefFeature, ComponentDefInternal, ComponentQuery, ComponentTemplate, ComponentType, DirectiveDefFeature, DirectiveDefInternal, DirectiveType, DirectiveTypesOrFactory, PipeDefInternal, PipeType, PipeTypesOrFactory} from './interfaces/definition'; import {CssSelectorList, SelectorFlags} from './interfaces/projection'; +const EMPTY: {} = {}; +const EMPTY_ARRAY: any[] = []; +ngDevMode && Object.freeze(EMPTY); +ngDevMode && Object.freeze(EMPTY_ARRAY); +let _renderCompCount = 0; /** * Create a component definition object. @@ -180,8 +185,28 @@ export function defineComponent(componentDefinition: { */ features?: ComponentDefFeature[]; - rendererType?: RendererType2; + /** + * Defines template and style encapsulation options available for Component's {@link Component}. + */ + encapsulation?: ViewEncapsulation; + /** + * Defines arbitrary developer-defined data to be stored on a renderer instance. + * This is useful for renderers that delegate to other renderers. + * + * see: animation + */ + data?: {[kind: string]: any}; + + /** + * A set of styles that the component needs to be present for component to render correctly. + */ + styles?: string[]; + + /** + * The strategy that the default change detector uses to detect changes. + * When set, takes effect the next time change detection is triggered. + */ changeDetection?: ChangeDetectionStrategy; /** @@ -215,6 +240,7 @@ export function defineComponent(componentDefinition: { const pipeTypes = componentDefinition.pipes !; const directiveTypes = componentDefinition.directives !; const declaredInputs: {[key: string]: string} = {} as any; + const encapsulation = componentDefinition.encapsulation; const def: ComponentDefInternal = { type: type, diPublic: null, @@ -227,7 +253,6 @@ export function defineComponent(componentDefinition: { inputs: invertObject(componentDefinition.inputs, declaredInputs), declaredInputs: declaredInputs, outputs: invertObject(componentDefinition.outputs), - rendererType: resolveRendererType2(componentDefinition.rendererType) || null, exportAs: componentDefinition.exportAs || null, onInit: type.prototype.ngOnInit || null, doCheck: type.prototype.ngDoCheck || null, @@ -247,6 +272,12 @@ export function defineComponent(componentDefinition: { selectors: componentDefinition.selectors, viewQuery: componentDefinition.viewQuery || null, features: componentDefinition.features || null, + data: componentDefinition.data || EMPTY, + // TODO(misko): convert ViewEncapsulation into const enum so that it can be used directly in the + // next line. Also `None` should be 0 not 2. + encapsulation: encapsulation == null ? 2 /* ViewEncapsulation.None */ : encapsulation, + id: `c${_renderCompCount++}`, + styles: EMPTY_ARRAY, }; const feature = componentDefinition.features; feature && feature.forEach((fn) => fn(def)); @@ -273,17 +304,15 @@ export function extractPipeDef(type: PipeType): PipeDefInternal { export function defineNgModule(def: {type: T} & Partial>): never { const res: NgModuleDefInternal = { type: def.type, - bootstrap: def.bootstrap || [], - declarations: def.declarations || [], - imports: def.imports || [], - exports: def.exports || [], + bootstrap: def.bootstrap || EMPTY_ARRAY, + declarations: def.declarations || EMPTY_ARRAY, + imports: def.imports || EMPTY_ARRAY, + exports: def.exports || EMPTY_ARRAY, transitiveCompileScopes: null, }; return res as never; } -const EMPTY = {}; - /** * Inverts an inputs or outputs lookup such that the keys, which were the * minified keys, are part of the values, and the values are parsed so that diff --git a/packages/core/src/render3/instructions.ts b/packages/core/src/render3/instructions.ts index f44d5d8bea..ee19081c1c 100644 --- a/packages/core/src/render3/instructions.ts +++ b/packages/core/src/render3/instructions.ts @@ -22,7 +22,7 @@ import {AttributeMarker, InitialInputData, InitialInputs, LContainerNode, LEleme import {CssSelectorList, NG_PROJECT_AS_ATTR_NAME} from './interfaces/projection'; import {LQueries} from './interfaces/query'; import {ProceduralRenderer3, RComment, RElement, RText, Renderer3, RendererFactory3, RendererStyleFlags3, isProceduralRenderer} from './interfaces/renderer'; -import {BINDING_INDEX, CLEANUP, CONTAINER_INDEX, CONTENT_QUERIES, CONTEXT, CurrentMatchesList, DECLARATION_VIEW, DIRECTIVES, FLAGS, HEADER_OFFSET, HOST_NODE, INJECTOR, LViewData, LViewFlags, NEXT, OpaqueViewState, PARENT, QUERIES, RENDERER, RootContext, SANITIZER, TAIL, TData, TVIEW, TView} from './interfaces/view'; +import {BINDING_INDEX, CLEANUP, CONTENT_QUERIES, CONTEXT, CurrentMatchesList, DECLARATION_VIEW, DIRECTIVES, FLAGS, HEADER_OFFSET, HOST_NODE, INJECTOR, LViewData, LViewFlags, NEXT, OpaqueViewState, PARENT, QUERIES, RENDERER, RootContext, SANITIZER, TAIL, TData, TVIEW, TView} from './interfaces/view'; import {assertNodeOfPossibleTypes, assertNodeType} from './node_assert'; import {appendChild, appendProjectedNode, canInsertNativeNode, createTextNode, findComponentHost, getChildLNode, getLViewChild, getNextLNode, getParentLNode, insertView, removeView} from './node_manipulation'; import {isNodeMatchingSelectorList, matchingSelectorIndex} from './node_selector_matcher'; @@ -1668,9 +1668,8 @@ function addComponentLogic( const componentView = addToViewTree( viewData, previousOrParentNode.tNode.index as number, createLViewData( - rendererFactory.createRenderer(previousOrParentNode.native as RElement, def.rendererType), - tView, instance, def.onPush ? LViewFlags.Dirty : LViewFlags.CheckAlways, - getCurrentSanitizer())); + rendererFactory.createRenderer(previousOrParentNode.native as RElement, def), tView, + instance, def.onPush ? LViewFlags.Dirty : LViewFlags.CheckAlways, getCurrentSanitizer())); // We need to set the host node/data here because when the component LNode was created, // we didn't yet know it was a component (just an element). diff --git a/packages/core/src/render3/interfaces/definition.ts b/packages/core/src/render3/interfaces/definition.ts index 3368172111..c6bb7890ce 100644 --- a/packages/core/src/render3/interfaces/definition.ts +++ b/packages/core/src/render3/interfaces/definition.ts @@ -6,8 +6,7 @@ * found in the LICENSE file at https://angular.io/license */ -import {Provider} from '../../core'; -import {RendererType2} from '../../render/api'; +import {Provider, ViewEncapsulation} from '../../core'; import {Type} from '../../type'; import {CssSelectorList} from './projection'; @@ -187,20 +186,42 @@ export type ComponentDefInternal = ComponentDef; * See: {@link defineComponent} */ export interface ComponentDef extends DirectiveDef { + /** + * Runtime unique component ID. + */ + id: string; + /** * The View template of the component. */ readonly template: ComponentTemplate; + /** + * A set of styles that the component needs to be present for component to render correctly. + */ + readonly styles: string[]; + /** * Query-related instructions for a component. */ readonly viewQuery: ComponentQuery|null; /** - * Renderer type data of the component. + * The view encapsulation type, which determines how styles are applied to + * DOM elements. One of + * - `Emulated` (default): Emulate native scoping of styles. + * - `Native`: Use the native encapsulation mechanism of the renderer. + * - `ShadowDom`: Use modern [ShadowDOM](https://w3c.github.io/webcomponents/spec/shadow/) and + * create a ShadowRoot for component's host element. + * - `None`: Do not provide any template or style encapsulation. */ - readonly rendererType: RendererType2|null; + readonly encapsulation: ViewEncapsulation; + + /** + * Defines arbitrary developer-defined data to be stored on a renderer instance. + * This is useful for renderers that delegate to other renderers. + */ + readonly data: {[kind: string]: any}; /** Whether or not this component's ChangeDetectionStrategy is OnPush */ readonly onPush: boolean; diff --git a/packages/core/src/render3/ng_dev_mode.ts b/packages/core/src/render3/ng_dev_mode.ts index 24c638e06e..776d5935c1 100644 --- a/packages/core/src/render3/ng_dev_mode.ts +++ b/packages/core/src/render3/ng_dev_mode.ts @@ -42,7 +42,8 @@ const __global: {ngDevMode: NgDevModePerfCounters | boolean} = typeof global != 'undefined' && global; export function ngDevModeResetPerfCounters(): NgDevModePerfCounters { - return __global.ngDevMode = { + // Make sure to refer to ngDevMode as ['ngDevMode'] for clousre. + return __global['ngDevMode'] = { firstTemplatePass: 0, tNode: 0, tView: 0, @@ -75,5 +76,6 @@ export function ngDevModeResetPerfCounters(): NgDevModePerfCounters { * as much early warning and errors as possible. */ if (typeof ngDevMode === 'undefined' || ngDevMode) { - __global.ngDevMode = ngDevModeResetPerfCounters(); + // Make sure to refer to ngDevMode as ['ngDevMode'] for clousre. + __global['ngDevMode'] = ngDevModeResetPerfCounters(); } diff --git a/packages/core/test/bundling/hello_world/bundle.golden_symbols.json b/packages/core/test/bundling/hello_world/bundle.golden_symbols.json index 5e2a1f5010..ce331251be 100644 --- a/packages/core/test/bundling/hello_world/bundle.golden_symbols.json +++ b/packages/core/test/bundling/hello_world/bundle.golden_symbols.json @@ -27,7 +27,7 @@ "name": "EMPTY$1" }, { - "name": "EMPTY_RENDERER_TYPE_ID" + "name": "EMPTY_ARRAY$2" }, { "name": "FLAGS" @@ -77,15 +77,9 @@ { "name": "TVIEW" }, - { - "name": "UNDEFINED_RENDERER_TYPE_ID" - }, { "name": "VIEWS" }, - { - "name": "ViewEncapsulation$1" - }, { "name": "_CLEAN_PROMISE" }, @@ -269,9 +263,6 @@ { "name": "resetApplicationState" }, - { - "name": "resolveRendererType2" - }, { "name": "setHostBindings" }, diff --git a/packages/core/test/bundling/todo/bundle.golden_symbols.json b/packages/core/test/bundling/todo/bundle.golden_symbols.json index 64dfeda319..cd9cee0afe 100644 --- a/packages/core/test/bundling/todo/bundle.golden_symbols.json +++ b/packages/core/test/bundling/todo/bundle.golden_symbols.json @@ -45,7 +45,7 @@ "name": "EMPTY$1" }, { - "name": "EMPTY_RENDERER_TYPE_ID" + "name": "EMPTY_ARRAY$2" }, { "name": "ElementRef" @@ -182,9 +182,6 @@ { "name": "TodoStore" }, - { - "name": "UNDEFINED_RENDERER_TYPE_ID" - }, { "name": "VIEWS" }, @@ -194,9 +191,6 @@ { "name": "ViewContainerRef$1" }, - { - "name": "ViewEncapsulation$1" - }, { "name": "ViewRef" }, @@ -836,9 +830,6 @@ { "name": "resolveDirective" }, - { - "name": "resolveRendererType2" - }, { "name": "restoreView" }, diff --git a/packages/core/test/render3/component_spec.ts b/packages/core/test/render3/component_spec.ts index 76b0858e7e..7ae35b138f 100644 --- a/packages/core/test/render3/component_spec.ts +++ b/packages/core/test/render3/component_spec.ts @@ -204,8 +204,9 @@ describe('encapsulation', () => { } }, factory: () => new EncapsulatedComponent, - rendererType: - createRendererType2({encapsulation: ViewEncapsulation.Emulated, styles: [], data: {}}), + encapsulation: ViewEncapsulation.Emulated, + styles: [], + data: {}, directives: () => [LeafComponent] }); } @@ -250,8 +251,9 @@ describe('encapsulation', () => { } }, factory: () => new WrapperComponentWith, - rendererType: - createRendererType2({encapsulation: ViewEncapsulation.Emulated, styles: [], data: {}}), + encapsulation: ViewEncapsulation.Emulated, + styles: [], + data: {}, directives: () => [LeafComponentwith] }); } @@ -268,8 +270,9 @@ describe('encapsulation', () => { } }, factory: () => new LeafComponentwith, - rendererType: - createRendererType2({encapsulation: ViewEncapsulation.Emulated, styles: [], data: {}}), + encapsulation: ViewEncapsulation.Emulated, + styles: [], + data: {}, }); } diff --git a/packages/core/test/render3/renderer_factory_spec.ts b/packages/core/test/render3/renderer_factory_spec.ts index e7fc46acdc..194a65671f 100644 --- a/packages/core/test/render3/renderer_factory_spec.ts +++ b/packages/core/test/render3/renderer_factory_spec.ts @@ -158,24 +158,22 @@ describe('animation renderer factory', () => { } }, factory: () => new SomeComponentWithAnimation, - rendererType: createRendererType2({ - encapsulation: ViewEncapsulation.None, - styles: [], - data: { - animation: [{ - type: 7, - name: 'myAnimation', - definitions: [{ - type: 1, - expr: '* => on', - animation: - [{type: 4, styles: {type: 6, styles: {opacity: 1}, offset: null}, timings: 10}], - options: null - }], - options: {} - }] - } - }), + encapsulation: ViewEncapsulation.None, + styles: [], + data: { + animation: [{ + type: 7, + name: 'myAnimation', + definitions: [{ + type: 1, + expr: '* => on', + animation: + [{type: 4, styles: {type: 6, styles: {opacity: 1}, offset: null}, timings: 10}], + options: null + }], + options: {} + }] + }, }); }