From a05e50fda31c271d6a0c375a49a0a75375e0ab05 Mon Sep 17 00:00:00 2001 From: Tobias Bosch Date: Wed, 1 Feb 2017 07:27:38 -0800 Subject: [PATCH] feat(core): view engine - add missing DI features (#14225) Part of #14013 PR Close #14225 --- modules/@angular/core/src/view/index.ts | 2 +- modules/@angular/core/src/view/provider.ts | 155 ++++++++++++--- .../@angular/core/src/view/pure_expression.ts | 2 +- modules/@angular/core/src/view/services.ts | 27 ++- modules/@angular/core/src/view/types.ts | 19 +- modules/@angular/core/src/view/util.ts | 12 ++ modules/@angular/core/src/view/view.ts | 39 ++-- .../core/test/view/component_view_spec.ts | 16 +- .../core/test/view/embedded_view_spec.ts | 4 +- .../core/test/view/ng_content_spec.ts | 6 +- .../@angular/core/test/view/provider_spec.ts | 188 ++++++++++++++---- .../core/test/view/pure_expression_spec.ts | 12 +- modules/@angular/core/test/view/query_spec.ts | 20 +- .../@angular/core/test/view/services_spec.ts | 6 +- .../@angular/core/test/view/view_def_spec.ts | 34 ++-- modules/benchmarks/src/tree/ng2_next/tree.ts | 12 +- 16 files changed, 396 insertions(+), 158 deletions(-) diff --git a/modules/@angular/core/src/view/index.ts b/modules/@angular/core/src/view/index.ts index 2d8f82cc46..291ccc30ae 100644 --- a/modules/@angular/core/src/view/index.ts +++ b/modules/@angular/core/src/view/index.ts @@ -8,7 +8,7 @@ export {anchorDef, elementDef} from './element'; export {ngContentDef} from './ng_content'; -export {providerDef} from './provider'; +export {directiveDef, providerDef} from './provider'; export {pureArrayDef, pureObjectDef, purePipeDef} from './pure_expression'; export {queryDef} from './query'; export {textDef} from './text'; diff --git a/modules/@angular/core/src/view/provider.ts b/modules/@angular/core/src/view/provider.ts index 9448c4d5af..caf97fc5c0 100644 --- a/modules/@angular/core/src/view/provider.ts +++ b/modules/@angular/core/src/view/provider.ts @@ -7,17 +7,18 @@ */ import {isDevMode} from '../application_ref'; -import {SimpleChange, SimpleChanges} from '../change_detection/change_detection'; +import {ChangeDetectorRef, SimpleChange, SimpleChanges} from '../change_detection/change_detection'; import {Injector} from '../di'; import {stringify} from '../facade/lang'; import {ElementRef} from '../linker/element_ref'; import {TemplateRef} from '../linker/template_ref'; import {ViewContainerRef} from '../linker/view_container_ref'; import {Renderer} from '../render/api'; +import {Type} from '../type'; import {queryDef} from './query'; -import {BindingDef, BindingType, DepDef, DepFlags, DisposableFn, EntryAction, NodeData, NodeDef, NodeFlags, NodeType, ProviderData, ProviderOutputDef, QueryBindingType, QueryDef, QueryValueType, Services, ViewData, ViewDefinition, ViewFlags, ViewState, asElementData, asProviderData} from './types'; -import {checkAndUpdateBinding, dispatchEvent, entryAction, setBindingDebugInfo, setCurrentNode, unwrapValue} from './util'; +import {BindingDef, BindingType, DepDef, DepFlags, DisposableFn, EntryAction, NodeData, NodeDef, NodeFlags, NodeType, ProviderData, ProviderOutputDef, ProviderType, QueryBindingType, QueryDef, QueryValueType, Services, ViewData, ViewDefinition, ViewFlags, ViewState, asElementData, asProviderData} from './types'; +import {checkAndUpdateBinding, dispatchEvent, entryAction, findElementDef, setBindingDebugInfo, setCurrentNode, unwrapValue} from './util'; const _tokenKeyCache = new Map(); @@ -25,11 +26,31 @@ const RendererTokenKey = tokenKey(Renderer); const ElementRefTokenKey = tokenKey(ElementRef); const ViewContainerRefTokenKey = tokenKey(ViewContainerRef); const TemplateRefTokenKey = tokenKey(TemplateRef); +const ChangeDetectorRefTokenKey = tokenKey(ChangeDetectorRef); +const InjectorRefTokenKey = tokenKey(Injector); -export function providerDef( +const NOT_CREATED = new Object(); + +export function directiveDef( flags: NodeFlags, matchedQueries: [string, QueryValueType][], childCount: number, ctor: any, deps: ([DepFlags, any] | any)[], props?: {[name: string]: [number, string]}, outputs?: {[name: string]: string}, component?: () => ViewDefinition): NodeDef { + return _providerDef( + flags, matchedQueries, childCount, ProviderType.Class, ctor, ctor, deps, props, outputs, + component); +} + +export function providerDef( + flags: NodeFlags, matchedQueries: [string, QueryValueType][], type: ProviderType, token: any, + value: any, deps: ([DepFlags, any] | any)[]): NodeDef { + return _providerDef(flags, matchedQueries, 0, type, token, value, deps); +} + +export function _providerDef( + flags: NodeFlags, matchedQueries: [string, QueryValueType][], childCount: number, + type: ProviderType, token: any, value: any, deps: ([DepFlags, any] | any)[], + props?: {[name: string]: [number, string]}, outputs?: {[name: string]: string}, + component?: () => ViewDefinition): NodeDef { const matchedQueryDefs: {[queryId: string]: QueryValueType} = {}; if (matchedQueries) { matchedQueries.forEach(([queryId, valueType]) => { matchedQueryDefs[queryId] = valueType; }); @@ -85,8 +106,9 @@ export function providerDef( disposableCount: outputDefs.length, element: undefined, provider: { - tokenKey: tokenKey(ctor), - token: ctor, ctor, + type, + token, + tokenKey: tokenKey(token), value, deps: depDefs, outputs: outputDefs, component }, @@ -106,19 +128,9 @@ export function tokenKey(token: any): string { return key; } -export function createProvider( - view: ViewData, def: NodeDef, componentView: ViewData): ProviderData { +export function createProviderInstance(view: ViewData, def: NodeDef): any { const providerDef = def.provider; - const provider = createInstance(view, def.parent, providerDef.ctor, providerDef.deps); - if (providerDef.outputs.length) { - for (let i = 0; i < providerDef.outputs.length; i++) { - const output = providerDef.outputs[i]; - const subscription = provider[output.propName].subscribe( - eventHandlerClosure(view, def.parent, output.eventName)); - view.disposables[def.disposableIndex + i] = subscription.unsubscribe.bind(subscription); - } - } - return {instance: provider, componentView: componentView}; + return def.flags & NodeFlags.LazyProvider ? NOT_CREATED : createInstance(view, def); } function eventHandlerClosure(view: ViewData, index: number, eventName: string) { @@ -182,7 +194,38 @@ export function checkAndUpdateProviderDynamic(view: ViewData, def: NodeDef, valu } } -function createInstance(view: ViewData, elIndex: number, ctor: any, deps: DepDef[]): any { +function createInstance(view: ViewData, nodeDef: NodeDef): any { + const providerDef = nodeDef.provider; + let injectable: any; + switch (providerDef.type) { + case ProviderType.Class: + injectable = + createClass(view, nodeDef.index, nodeDef.parent, providerDef.value, providerDef.deps); + break; + case ProviderType.Factory: + injectable = + callFactory(view, nodeDef.index, nodeDef.parent, providerDef.value, providerDef.deps); + break; + case ProviderType.UseExisting: + injectable = resolveDep(view, nodeDef.index, nodeDef.parent, providerDef.deps[0]); + break; + case ProviderType.Value: + injectable = providerDef.value; + break; + } + if (providerDef.outputs.length) { + for (let i = 0; i < providerDef.outputs.length; i++) { + const output = providerDef.outputs[i]; + const subscription = injectable[output.propName].subscribe( + eventHandlerClosure(view, nodeDef.parent, output.eventName)); + view.disposables[nodeDef.disposableIndex + i] = subscription.unsubscribe.bind(subscription); + } + } + return injectable; +} + +function createClass( + view: ViewData, requestorNodeIndex: number, elIndex: number, ctor: any, deps: DepDef[]): any { const len = deps.length; let injectable: any; switch (len) { @@ -190,32 +233,69 @@ function createInstance(view: ViewData, elIndex: number, ctor: any, deps: DepDef injectable = new ctor(); break; case 1: - injectable = new ctor(resolveDep(view, elIndex, deps[0])); + injectable = new ctor(resolveDep(view, requestorNodeIndex, elIndex, deps[0])); break; case 2: - injectable = new ctor(resolveDep(view, elIndex, deps[0]), resolveDep(view, elIndex, deps[1])); + injectable = new ctor( + resolveDep(view, requestorNodeIndex, elIndex, deps[0]), + resolveDep(view, requestorNodeIndex, elIndex, deps[1])); break; case 3: injectable = new ctor( - resolveDep(view, elIndex, deps[0]), resolveDep(view, elIndex, deps[1]), - resolveDep(view, elIndex, deps[2])); + resolveDep(view, requestorNodeIndex, elIndex, deps[0]), + resolveDep(view, requestorNodeIndex, elIndex, deps[1]), + resolveDep(view, requestorNodeIndex, elIndex, deps[2])); break; default: const depValues = new Array(len); for (let i = 0; i < len; i++) { - depValues[i] = resolveDep(view, elIndex, deps[i]); + depValues[i] = resolveDep(view, requestorNodeIndex, elIndex, deps[i]); } injectable = new ctor(...depValues); } return injectable; } +function callFactory( + view: ViewData, requestorNodeIndex: number, elIndex: number, factory: any, + deps: DepDef[]): any { + const len = deps.length; + let injectable: any; + switch (len) { + case 0: + injectable = factory(); + break; + case 1: + injectable = factory(resolveDep(view, requestorNodeIndex, elIndex, deps[0])); + break; + case 2: + injectable = factory( + resolveDep(view, requestorNodeIndex, elIndex, deps[0]), + resolveDep(view, requestorNodeIndex, elIndex, deps[1])); + break; + case 3: + injectable = factory( + resolveDep(view, requestorNodeIndex, elIndex, deps[0]), + resolveDep(view, requestorNodeIndex, elIndex, deps[1]), + resolveDep(view, requestorNodeIndex, elIndex, deps[2])); + break; + default: + const depValues = Array(len); + for (let i = 0; i < len; i++) { + depValues[i] = resolveDep(view, requestorNodeIndex, elIndex, deps[i]); + } + injectable = factory(...depValues); + } + return injectable; +} + export function resolveDep( - view: ViewData, elIndex: number, depDef: DepDef, - notFoundValue: any = Injector.THROW_IF_NOT_FOUND): any { + view: ViewData, requestNodeIndex: number, elIndex: number, depDef: DepDef): any { + const notFoundValue = depDef.flags & DepFlags.Optional ? null : Injector.THROW_IF_NOT_FOUND; const tokenKey = depDef.tokenKey; if (depDef.flags & DepFlags.SkipSelf) { + requestNodeIndex = null; const elDef = view.def.nodes[elIndex]; if (elDef.parent != null) { elIndex = elDef.parent; @@ -240,12 +320,30 @@ export function resolveDep( return view.services.createViewContainerRef(asElementData(view, elIndex)); case TemplateRefTokenKey: return view.services.createTemplateRef(view, elDef); + case ChangeDetectorRefTokenKey: + let cdView = view; + // If we are still checking dependencies on the initial element... + if (requestNodeIndex != null) { + const requestorNodeDef = view.def.nodes[requestNodeIndex]; + if (requestorNodeDef.flags & NodeFlags.HasComponent) { + cdView = asProviderData(view, requestNodeIndex).componentView; + } + } + // A ViewRef is also a ChangeDetectorRef + return view.services.createViewRef(cdView); + case InjectorRefTokenKey: + return createInjector(view, elIndex); default: const providerIndex = elDef.element.providerIndices[tokenKey]; if (providerIndex != null) { - return asProviderData(view, providerIndex).instance; + const providerData = asProviderData(view, providerIndex); + if (providerData.instance === NOT_CREATED) { + providerData.instance = createInstance(view, view.def.nodes[providerIndex]); + } + return providerData.instance; } } + requestNodeIndex = null; elIndex = parentDiIndex(view); view = view.parent; } @@ -274,7 +372,8 @@ class Injector_ implements Injector { constructor(private view: ViewData, private elIndex: number) {} get(token: any, notFoundValue?: any): any { return resolveDep( - this.view, this.elIndex, {flags: DepFlags.None, token, tokenKey: tokenKey(token)}); + this.view, undefined, this.elIndex, + {flags: DepFlags.None, token, tokenKey: tokenKey(token)}); } } diff --git a/modules/@angular/core/src/view/pure_expression.ts b/modules/@angular/core/src/view/pure_expression.ts index 5cbf7a6e70..1c7c5ba873 100644 --- a/modules/@angular/core/src/view/pure_expression.ts +++ b/modules/@angular/core/src/view/pure_expression.ts @@ -64,7 +64,7 @@ function _pureExpressionDef( export function createPureExpression(view: ViewData, def: NodeDef): PureExpressionData { const pipe = def.pureExpression.pipeDep ? - resolveDep(view, def.parent, def.pureExpression.pipeDep) : + resolveDep(view, def.index, def.parent, def.pureExpression.pipeDep) : undefined; return {value: undefined, pipe}; } diff --git a/modules/@angular/core/src/view/services.ts b/modules/@angular/core/src/view/services.ts index 946fc9c796..41b85cfcb2 100644 --- a/modules/@angular/core/src/view/services.ts +++ b/modules/@angular/core/src/view/services.ts @@ -19,7 +19,7 @@ import {Sanitizer, SecurityContext} from '../security'; import {createInjector} from './provider'; import {getQueryValue} from './query'; import {DebugContext, ElementData, NodeData, NodeDef, NodeType, Services, ViewData, ViewDefinition, ViewState, asElementData} from './types'; -import {isComponentView, renderNode, rootRenderNodes} from './util'; +import {findElementDef, isComponentView, renderNode, rootRenderNodes} from './util'; import {checkAndUpdateView, checkNoChangesView, createEmbeddedView, destroyView} from './view'; import {attachEmbeddedView, detachEmbeddedView} from './view_attach'; @@ -33,6 +33,7 @@ export class DefaultServices implements Services { sanitize(context: SecurityContext, value: string): string { return this._sanitizer.sanitize(context, value); } + createViewRef(data: ViewData): ViewRef { return new ViewRef_(data); } createViewContainerRef(data: ElementData): ViewContainerRef { return new ViewContainerRef_(data); } @@ -120,8 +121,16 @@ class ViewRef_ implements EmbeddedViewRef { this._view.state = ViewState.ChecksDisabled; } } - detectChanges(): void { checkAndUpdateView(this._view); } - checkNoChanges(): void { checkNoChangesView(this._view); } + detectChanges(): void { + if (this._view.state !== ViewState.FirstCheck) { + checkAndUpdateView(this._view); + } + } + checkNoChanges(): void { + if (this._view.state !== ViewState.FirstCheck) { + checkNoChangesView(this._view); + } + } reattach(): void { if (this._view.state === ViewState.ChecksDisabled) { @@ -217,18 +226,6 @@ function findHostElement(view: ViewData): ElementData { return undefined; } -function findElementDef(view: ViewData, nodeIndex: number): NodeDef { - const viewDef = view.def; - let nodeDef = viewDef.nodes[nodeIndex]; - while (nodeDef) { - if (nodeDef.type === NodeType.Element) { - return nodeDef; - } - nodeDef = nodeDef.parent != null ? viewDef.nodes[nodeDef.parent] : undefined; - } - return undefined; -} - function collectReferences(view: ViewData, nodeDef: NodeDef, references: {[key: string]: any}) { for (let queryId in nodeDef.matchedQueries) { if (queryId.startsWith('#')) { diff --git a/modules/@angular/core/src/view/types.ts b/modules/@angular/core/src/view/types.ts index d8969de975..22fc7e59ce 100644 --- a/modules/@angular/core/src/view/types.ts +++ b/modules/@angular/core/src/view/types.ts @@ -10,6 +10,7 @@ import {PipeTransform} from '../change_detection/change_detection'; import {QueryList} from '../linker/query_list'; import {TemplateRef} from '../linker/template_ref'; import {ViewContainerRef} from '../linker/view_container_ref'; +import {ViewRef} from '../linker/view_ref'; import {RenderComponentType, RenderDebugInfo, Renderer, RootRenderer} from '../render/api'; import {Sanitizer, SecurityContext} from '../security'; @@ -126,6 +127,7 @@ export enum NodeFlags { HasComponent = 1 << 9, HasContentQuery = 1 << 10, HasViewQuery = 1 << 11, + LazyProvider = 1 << 12 } export interface BindingDef { @@ -162,8 +164,6 @@ export interface ElementDef { /** * visible providers for DI in the view, * as see from this element. - * Note: We use protoypical inheritance - * to indices in parent ElementDefs. */ providerIndices: {[tokenKey: string]: number}; source: string; @@ -175,15 +175,23 @@ export interface ElementOutputDef { } export interface ProviderDef { + type: ProviderType; token: any; tokenKey: string; - ctor: any; + value: any; deps: DepDef[]; outputs: ProviderOutputDef[]; // closure to allow recursive components component: ViewDefinitionFactory; } +export enum ProviderType { + Value, + Class, + Factory, + UseExisting +} + export interface DepDef { flags: DepFlags; token: any; @@ -195,7 +203,8 @@ export interface DepDef { */ export enum DepFlags { None = 0, - SkipSelf = 1 << 0 + SkipSelf = 1 << 0, + Optional = 1 << 1 } export interface ProviderOutputDef { @@ -377,6 +386,8 @@ export interface Services { renderComponent(rcp: RenderComponentType): Renderer; sanitize(context: SecurityContext, value: string): string; // Note: This needs to be here to prevent a cycle in source files. + createViewRef(data: ViewData): ViewRef; + // Note: This needs to be here to prevent a cycle in source files. createViewContainerRef(data: ElementData): ViewContainerRef; // Note: This needs to be here to prevent a cycle in source files. createTemplateRef(parentView: ViewData, def: NodeDef): TemplateRef; diff --git a/modules/@angular/core/src/view/util.ts b/modules/@angular/core/src/view/util.ts index a9aecf7221..307c2e8e76 100644 --- a/modules/@angular/core/src/view/util.ts +++ b/modules/@angular/core/src/view/util.ts @@ -88,6 +88,18 @@ export function declaredViewContainer(view: ViewData): ElementData { return undefined; } +export function findElementDef(view: ViewData, nodeIndex: number): NodeDef { + const viewDef = view.def; + let nodeDef = viewDef.nodes[nodeIndex]; + while (nodeDef) { + if (nodeDef.type === NodeType.Element) { + return nodeDef; + } + nodeDef = nodeDef.parent != null ? viewDef.nodes[nodeDef.parent] : undefined; + } + return undefined; +} + export function renderNode(view: ViewData, def: NodeDef): any { switch (def.type) { case NodeType.Element: diff --git a/modules/@angular/core/src/view/view.ts b/modules/@angular/core/src/view/view.ts index 19006d6f2e..59a378b9c1 100644 --- a/modules/@angular/core/src/view/view.ts +++ b/modules/@angular/core/src/view/view.ts @@ -12,7 +12,7 @@ import {RenderComponentType, Renderer} from '../render/api'; import {checkAndUpdateElementDynamic, checkAndUpdateElementInline, createElement} from './element'; import {expressionChangedAfterItHasBeenCheckedError} from './errors'; import {appendNgContent} from './ng_content'; -import {callLifecycleHooksChildrenFirst, checkAndUpdateProviderDynamic, checkAndUpdateProviderInline, createProvider} from './provider'; +import {callLifecycleHooksChildrenFirst, checkAndUpdateProviderDynamic, checkAndUpdateProviderInline, createProviderInstance} from './provider'; import {checkAndUpdatePureExpressionDynamic, checkAndUpdatePureExpressionInline, createPureExpression} from './pure_expression'; import {checkAndUpdateQuery, createQuery, queryDef} from './query'; import {checkAndUpdateTextDynamic, checkAndUpdateTextInline, createText} from './text'; @@ -58,6 +58,7 @@ export function viewDef( }); if (node.element) { node.element = cloneAndModifyElement(node.element, { + // Use protoypical inheritance to not get O(n^2) complexity... providerIndices: Object.create(currentParent ? currentParent.element.providerIndices : null), }); @@ -284,43 +285,49 @@ function _createViewNodes(view: ViewData) { const nodes = view.nodes; for (let i = 0; i < def.nodes.length; i++) { const nodeDef = def.nodes[i]; - let nodeData: any; // As the current node is being created, we have to use // the parent node as the current node for error messages, ... setCurrentNode(view, nodeDef.parent); switch (nodeDef.type) { case NodeType.Element: - nodeData = createElement(view, renderHost, nodeDef); + nodes[i] = createElement(view, renderHost, nodeDef) as any; break; case NodeType.Text: - nodeData = createText(view, renderHost, nodeDef); + nodes[i] = createText(view, renderHost, nodeDef) as any; break; case NodeType.Provider: - let componentView: ViewData; if (nodeDef.provider.component) { - const hostElIndex = nodeDef.parent; - componentView = createView( - view.services, view, hostElIndex, resolveViewDefinition(nodeDef.provider.component)); - } - const providerData = nodeData = createProvider(view, nodeDef, componentView); - if (componentView) { - initView(componentView, providerData.instance, providerData.instance); + // Components can inject a ChangeDetectorRef that needs a references to + // the component view. Therefore, we create the component view first + // and set the ProviderData in ViewData, and then instantiate the provider. + const componentView = createView( + view.services, view, nodeDef.parent, + resolveViewDefinition(nodeDef.provider.component)); + const providerData = {componentView, instance: undefined}; + nodes[i] = providerData as any; + const instance = providerData.instance = createProviderInstance(view, nodeDef); + initView(componentView, instance, instance); + } else { + const instance = createProviderInstance(view, nodeDef); + const providerData = {componentView: undefined, instance}; + nodes[i] = providerData as any; } break; case NodeType.PureExpression: - nodeData = createPureExpression(view, nodeDef); + nodes[i] = createPureExpression(view, nodeDef) as any; break; case NodeType.Query: - nodeData = createQuery(); + nodes[i] = createQuery() as any; break; case NodeType.NgContent: appendNgContent(view, renderHost, nodeDef); // no runtime data needed for NgContent... - nodeData = undefined; + nodes[i] = undefined; break; } - nodes[i] = nodeData; } + // Create the ViewData.nodes of component views after we created everything else, + // so that e.g. ng-content works execComponentViewsAction(view, ViewAction.CreateViewNodes); } diff --git a/modules/@angular/core/test/view/component_view_spec.ts b/modules/@angular/core/test/view/component_view_spec.ts index 3c2711a7d7..65f6678706 100644 --- a/modules/@angular/core/test/view/component_view_spec.ts +++ b/modules/@angular/core/test/view/component_view_spec.ts @@ -7,7 +7,7 @@ */ import {RenderComponentType, RootRenderer, Sanitizer, SecurityContext, ViewEncapsulation} from '@angular/core'; -import {BindingType, DefaultServices, NodeDef, NodeFlags, Services, ViewData, ViewDefinition, ViewFlags, ViewHandleEventFn, ViewState, ViewUpdateFn, anchorDef, asProviderData, checkAndUpdateView, checkNoChangesView, checkNodeDynamic, checkNodeInline, createRootView, destroyView, elementDef, providerDef, rootRenderNodes, setCurrentNode, textDef, viewDef} from '@angular/core/src/view/index'; +import {BindingType, DefaultServices, NodeDef, NodeFlags, Services, ViewData, ViewDefinition, ViewFlags, ViewHandleEventFn, ViewState, ViewUpdateFn, anchorDef, asProviderData, checkAndUpdateView, checkNoChangesView, checkNodeDynamic, checkNodeInline, createRootView, destroyView, directiveDef, elementDef, rootRenderNodes, setCurrentNode, textDef, viewDef} from '@angular/core/src/view/index'; import {inject} from '@angular/core/testing'; import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter'; @@ -54,7 +54,7 @@ function defineTests(config: {directDom: boolean, viewFlags: number}) { const {view, rootNodes} = createAndGetRootNodes(compViewDef([ elementDef(NodeFlags.None, null, null, 1, 'div'), - providerDef( + directiveDef( NodeFlags.None, null, 0, AComp, [], null, null, () => compViewDef([ elementDef(NodeFlags.None, null, null, 0, 'span'), @@ -85,7 +85,7 @@ function defineTests(config: {directDom: boolean, viewFlags: number}) { const {view, rootNodes} = createAndGetRootNodes( compViewDef([ elementDef(NodeFlags.None, null, null, 1, 'div'), - providerDef(NodeFlags.None, null, 0, AComp, [], null, null, () => compViewDef( + directiveDef(NodeFlags.None, null, 0, AComp, [], null, null, () => compViewDef( [ elementDef(NodeFlags.None, null, null, 0, 'span', null, [[BindingType.ElementAttribute, 'a', SecurityContext.NONE]]), ], update @@ -118,7 +118,7 @@ function defineTests(config: {directDom: boolean, viewFlags: number}) { const {view, rootNodes} = createAndGetRootNodes(compViewDef([ elementDef(NodeFlags.None, null, null, 1, 'div'), - providerDef( + directiveDef( NodeFlags.None, null, 0, AComp, [], null, null, () => compViewDef( [ @@ -156,7 +156,7 @@ function defineTests(config: {directDom: boolean, viewFlags: number}) { compViewDef( [ elementDef(NodeFlags.None, null, null, 1, 'div'), - providerDef( + directiveDef( NodeFlags.None, null, 0, AComp, [], {a: [0, 'a']}, null, () => compViewDef( @@ -212,7 +212,7 @@ function defineTests(config: {directDom: boolean, viewFlags: number}) { const {view, rootNodes} = createAndGetRootNodes(compViewDef([ elementDef(NodeFlags.None, null, null, 1, 'div'), - providerDef( + directiveDef( NodeFlags.None, null, 0, AComp, [], null, null, () => compViewDef( [ @@ -249,11 +249,11 @@ function defineTests(config: {directDom: boolean, viewFlags: number}) { const {view, rootNodes} = createAndGetRootNodes(compViewDef([ elementDef(NodeFlags.None, null, null, 1, 'div'), - providerDef( + directiveDef( NodeFlags.None, null, 0, AComp, [], null, null, () => compViewDef([ elementDef(NodeFlags.None, null, null, 1, 'span'), - providerDef(NodeFlags.OnDestroy, null, 0, ChildProvider, []) + directiveDef(NodeFlags.OnDestroy, null, 0, ChildProvider, []) ])), ])); diff --git a/modules/@angular/core/test/view/embedded_view_spec.ts b/modules/@angular/core/test/view/embedded_view_spec.ts index 4e25189f29..28994d0511 100644 --- a/modules/@angular/core/test/view/embedded_view_spec.ts +++ b/modules/@angular/core/test/view/embedded_view_spec.ts @@ -7,7 +7,7 @@ */ import {RenderComponentType, RootRenderer, Sanitizer, SecurityContext, ViewEncapsulation} from '@angular/core'; -import {BindingType, DefaultServices, NodeDef, NodeFlags, Services, ViewData, ViewDefinition, ViewFlags, ViewHandleEventFn, ViewUpdateFn, anchorDef, asElementData, attachEmbeddedView, checkAndUpdateView, checkNoChangesView, checkNodeDynamic, checkNodeInline, createEmbeddedView, createRootView, destroyView, detachEmbeddedView, elementDef, providerDef, rootRenderNodes, setCurrentNode, textDef, viewDef} from '@angular/core/src/view/index'; +import {BindingType, DefaultServices, NodeDef, NodeFlags, Services, ViewData, ViewDefinition, ViewFlags, ViewHandleEventFn, ViewUpdateFn, anchorDef, asElementData, attachEmbeddedView, checkAndUpdateView, checkNoChangesView, checkNodeDynamic, checkNodeInline, createEmbeddedView, createRootView, destroyView, detachEmbeddedView, directiveDef, elementDef, rootRenderNodes, setCurrentNode, textDef, viewDef} from '@angular/core/src/view/index'; import {inject} from '@angular/core/testing'; import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter'; @@ -164,7 +164,7 @@ function defineTests(config: {directDom: boolean, viewFlags: number}) { elementDef(NodeFlags.None, null, null, 1, 'div'), anchorDef(NodeFlags.HasEmbeddedViews, null, null, 0, embeddedViewDef([ elementDef(NodeFlags.None, null, null, 1, 'span'), - providerDef(NodeFlags.OnDestroy, null, 0, ChildProvider, []) + directiveDef(NodeFlags.OnDestroy, null, 0, ChildProvider, []) ])) ])); diff --git a/modules/@angular/core/test/view/ng_content_spec.ts b/modules/@angular/core/test/view/ng_content_spec.ts index ff102e9e3b..7e87ace66f 100644 --- a/modules/@angular/core/test/view/ng_content_spec.ts +++ b/modules/@angular/core/test/view/ng_content_spec.ts @@ -7,7 +7,7 @@ */ import {RenderComponentType, RootRenderer, Sanitizer, SecurityContext, TemplateRef, ViewContainerRef, ViewEncapsulation, getDebugNode} from '@angular/core'; -import {DebugContext, DefaultServices, NodeDef, NodeFlags, Services, ViewData, ViewDefinition, ViewFlags, ViewHandleEventFn, ViewUpdateFn, anchorDef, asElementData, asProviderData, asTextData, attachEmbeddedView, checkAndUpdateView, checkNoChangesView, checkNodeDynamic, checkNodeInline, createEmbeddedView, createRootView, detachEmbeddedView, elementDef, ngContentDef, providerDef, rootRenderNodes, setCurrentNode, textDef, viewDef} from '@angular/core/src/view/index'; +import {DebugContext, DefaultServices, NodeDef, NodeFlags, Services, ViewData, ViewDefinition, ViewFlags, ViewHandleEventFn, ViewUpdateFn, anchorDef, asElementData, asProviderData, asTextData, attachEmbeddedView, checkAndUpdateView, checkNoChangesView, checkNodeDynamic, checkNodeInline, createEmbeddedView, createRootView, detachEmbeddedView, directiveDef, elementDef, ngContentDef, rootRenderNodes, setCurrentNode, textDef, viewDef} from '@angular/core/src/view/index'; import {inject} from '@angular/core/testing'; import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter'; @@ -50,7 +50,7 @@ function defineTests(config: {directDom: boolean, viewFlags: number}) { return [ elementDef(NodeFlags.None, null, null, 1 + contentNodes.length, 'acomp'), - providerDef(NodeFlags.None, null, 0, AComp, [], null, null, () => aCompViewDef), + directiveDef(NodeFlags.None, null, 0, AComp, [], null, null, () => aCompViewDef), ...contentNodes ]; } @@ -106,7 +106,7 @@ function defineTests(config: {directDom: boolean, viewFlags: number}) { [ anchorDef( NodeFlags.HasEmbeddedViews, null, 0, 1, embeddedViewDef([textDef(null, ['a'])])), - providerDef( + directiveDef( NodeFlags.None, null, 0, CreateViewService, [TemplateRef, ViewContainerRef]) ], [elementDef(NodeFlags.None, null, null, 1, 'div'), ngContentDef(null, 0)]))); diff --git a/modules/@angular/core/test/view/provider_spec.ts b/modules/@angular/core/test/view/provider_spec.ts index a6ba5f0eb1..3b8a168624 100644 --- a/modules/@angular/core/test/view/provider_spec.ts +++ b/modules/@angular/core/test/view/provider_spec.ts @@ -6,8 +6,8 @@ * found in the LICENSE file at https://angular.io/license */ -import {AfterContentChecked, AfterContentInit, AfterViewChecked, AfterViewInit, DoCheck, ElementRef, EventEmitter, OnChanges, OnDestroy, OnInit, RenderComponentType, Renderer, RootRenderer, Sanitizer, SecurityContext, SimpleChange, TemplateRef, ViewContainerRef, ViewEncapsulation, WrappedValue, getDebugNode} from '@angular/core'; -import {BindingType, DebugContext, DefaultServices, NodeDef, NodeFlags, Services, ViewData, ViewDefinition, ViewFlags, ViewHandleEventFn, ViewUpdateFn, anchorDef, asElementData, asProviderData, checkAndUpdateView, checkNoChangesView, checkNodeDynamic, checkNodeInline, createRootView, destroyView, elementDef, providerDef, rootRenderNodes, setCurrentNode, textDef, viewDef} from '@angular/core/src/view/index'; +import {AfterContentChecked, AfterContentInit, AfterViewChecked, AfterViewInit, ChangeDetectorRef, DoCheck, ElementRef, EventEmitter, Injector, OnChanges, OnDestroy, OnInit, RenderComponentType, Renderer, RootRenderer, Sanitizer, SecurityContext, SimpleChange, TemplateRef, ViewContainerRef, ViewEncapsulation, WrappedValue, getDebugNode} from '@angular/core'; +import {BindingType, DebugContext, DefaultServices, DepFlags, NodeDef, NodeFlags, ProviderType, Services, ViewData, ViewDefinition, ViewFlags, ViewHandleEventFn, ViewUpdateFn, anchorDef, asElementData, asProviderData, checkAndUpdateView, checkNoChangesView, checkNodeDynamic, checkNodeInline, createRootView, destroyView, directiveDef, elementDef, providerDef, rootRenderNodes, setCurrentNode, textDef, viewDef} from '@angular/core/src/view/index'; import {inject} from '@angular/core/testing'; import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter'; @@ -50,18 +50,74 @@ function defineTests(config: {directDom: boolean, viewFlags: number}) { } describe('create', () => { + let instance: SomeService; + + class SomeService { + constructor(public dep: any) { instance = this; } + } + + beforeEach(() => { instance = null; }); + it('should create providers eagerly', () => { - let instances: SomeService[] = []; - class SomeService { - constructor() { instances.push(this); } + createAndGetRootNodes(compViewDef([ + elementDef(NodeFlags.None, null, null, 1, 'span'), + directiveDef(NodeFlags.None, null, 0, SomeService, []) + ])); + + expect(instance instanceof SomeService).toBe(true); + }); + + it('should create providers lazily', () => { + let lazy: LazyService; + class LazyService { + constructor() { lazy = this; } } createAndGetRootNodes(compViewDef([ - elementDef(NodeFlags.None, null, null, 1, 'span'), - providerDef(NodeFlags.None, null, 0, SomeService, []) + elementDef(NodeFlags.None, null, null, 2, 'span'), + directiveDef(NodeFlags.LazyProvider, null, 0, LazyService, []), + directiveDef(NodeFlags.None, null, 0, SomeService, [Injector]) ])); - expect(instances.length).toBe(1); + expect(lazy).toBeUndefined(); + instance.dep.get(LazyService); + expect(lazy instanceof LazyService).toBe(true); + }); + + it('should create value providers', () => { + createAndGetRootNodes(compViewDef([ + elementDef(NodeFlags.None, null, null, 2, 'span'), + providerDef(NodeFlags.None, null, ProviderType.Value, 'someToken', 'someValue', []), + directiveDef(NodeFlags.None, null, 0, SomeService, ['someToken']), + ])); + + expect(instance.dep).toBe('someValue'); + }); + + it('should create factory providers', () => { + function someFactory() { return 'someValue'; } + + createAndGetRootNodes(compViewDef([ + elementDef(NodeFlags.None, null, null, 2, 'span'), + providerDef(NodeFlags.None, null, ProviderType.Factory, 'someToken', someFactory, []), + directiveDef(NodeFlags.None, null, 0, SomeService, ['someToken']), + ])); + + expect(instance.dep).toBe('someValue'); + }); + + it('should create useExisting providers', () => { + createAndGetRootNodes(compViewDef([ + elementDef(NodeFlags.None, null, null, 3, 'span'), + providerDef( + NodeFlags.None, null, ProviderType.Value, 'someExistingToken', 'someValue', []), + providerDef( + NodeFlags.None, null, ProviderType.UseExisting, 'someToken', null, + ['someExistingToken']), + directiveDef(NodeFlags.None, null, 0, SomeService, ['someToken']), + ])); + + expect(instance.dep).toBe('someValue'); }); it('should add a DebugContext to errors in provider factories', () => { @@ -73,7 +129,7 @@ function defineTests(config: {directDom: boolean, viewFlags: number}) { try { createAndGetRootNodes(compViewDef([ elementDef(NodeFlags.None, null, null, 1, 'span'), - providerDef(NodeFlags.None, null, 0, SomeService, []) + directiveDef(NodeFlags.None, null, 0, SomeService, []) ])); } catch (e) { err = e; @@ -87,20 +143,13 @@ function defineTests(config: {directDom: boolean, viewFlags: number}) { }); describe('deps', () => { - let instance: SomeService; class Dep {} - class SomeService { - constructor(public dep: any) { instance = this; } - } - - beforeEach(() => { instance = null; }); - it('should inject deps from the same element', () => { createAndGetRootNodes(compViewDef([ elementDef(NodeFlags.None, null, null, 2, 'span'), - providerDef(NodeFlags.None, null, 0, Dep, []), - providerDef(NodeFlags.None, null, 0, SomeService, [Dep]) + directiveDef(NodeFlags.None, null, 0, Dep, []), + directiveDef(NodeFlags.None, null, 0, SomeService, [Dep]) ])); expect(instance.dep instanceof Dep).toBeTruthy(); @@ -109,9 +158,9 @@ function defineTests(config: {directDom: boolean, viewFlags: number}) { it('should inject deps from a parent element', () => { createAndGetRootNodes(compViewDef([ elementDef(NodeFlags.None, null, null, 3, 'span'), - providerDef(NodeFlags.None, null, 0, Dep, []), + directiveDef(NodeFlags.None, null, 0, Dep, []), elementDef(NodeFlags.None, null, null, 1, 'span'), - providerDef(NodeFlags.None, null, 0, SomeService, [Dep]) + directiveDef(NodeFlags.None, null, 0, SomeService, [Dep]) ])); expect(instance.dep instanceof Dep).toBeTruthy(); @@ -120,9 +169,9 @@ function defineTests(config: {directDom: boolean, viewFlags: number}) { it('should not inject deps from sibling root elements', () => { const nodes = [ elementDef(NodeFlags.None, null, null, 1, 'span'), - providerDef(NodeFlags.None, null, 0, Dep, []), + directiveDef(NodeFlags.None, null, 0, Dep, []), elementDef(NodeFlags.None, null, null, 1, 'span'), - providerDef(NodeFlags.None, null, 0, SomeService, [Dep]) + directiveDef(NodeFlags.None, null, 0, SomeService, [Dep]) ]; // root elements @@ -139,22 +188,52 @@ function defineTests(config: {directDom: boolean, viewFlags: number}) { it('should inject from a parent elment in a parent view', () => { createAndGetRootNodes(compViewDef([ elementDef(NodeFlags.None, null, null, 1, 'div'), - providerDef( + directiveDef( NodeFlags.None, null, 0, Dep, [], null, null, () => compViewDef([ elementDef(NodeFlags.None, null, null, 1, 'span'), - providerDef(NodeFlags.None, null, 0, SomeService, [Dep]) + directiveDef(NodeFlags.None, null, 0, SomeService, [Dep]) ])), ])); expect(instance.dep instanceof Dep).toBeTruthy(); }); + it('should throw for missing dependencies', () => { + expect(() => createAndGetRootNodes(compViewDef([ + elementDef(NodeFlags.None, null, null, 1, 'span'), + directiveDef(NodeFlags.None, null, 0, SomeService, ['nonExistingDep']) + ]))) + .toThrowError('No provider for nonExistingDep!'); + }); + + it('should use null for optional missing dependencies', () => { + createAndGetRootNodes(compViewDef([ + elementDef(NodeFlags.None, null, null, 1, 'span'), + directiveDef( + NodeFlags.None, null, 0, SomeService, [[DepFlags.Optional, 'nonExistingDep']]) + ])); + expect(instance.dep).toBe(null); + }); + + it('should skip the current element when using SkipSelf', () => { + createAndGetRootNodes(compViewDef([ + elementDef(NodeFlags.None, null, null, 4, 'span'), + providerDef( + NodeFlags.None, null, ProviderType.Value, 'someToken', 'someParentValue', []), + elementDef(NodeFlags.None, null, null, 2, 'span'), + providerDef(NodeFlags.None, null, ProviderType.Value, 'someToken', 'someValue', []), + directiveDef( + NodeFlags.None, null, 0, SomeService, [[DepFlags.SkipSelf, 'someToken']]) + ])); + expect(instance.dep).toBe('someParentValue'); + }); + describe('builtin tokens', () => { it('should inject ViewContainerRef', () => { createAndGetRootNodes(compViewDef([ anchorDef(NodeFlags.HasEmbeddedViews, null, null, 1), - providerDef(NodeFlags.None, null, 0, SomeService, [ViewContainerRef]) + directiveDef(NodeFlags.None, null, 0, SomeService, [ViewContainerRef]) ])); expect(instance.dep.createEmbeddedView).toBeTruthy(); @@ -164,7 +243,7 @@ function defineTests(config: {directDom: boolean, viewFlags: number}) { createAndGetRootNodes(compViewDef([ anchorDef(NodeFlags.None, null, null, 1, embeddedViewDef([anchorDef( NodeFlags.None, null, null, 0)])), - providerDef(NodeFlags.None, null, 0, SomeService, [TemplateRef]) + directiveDef(NodeFlags.None, null, 0, SomeService, [TemplateRef]) ])); expect(instance.dep.createEmbeddedView).toBeTruthy(); @@ -173,17 +252,49 @@ function defineTests(config: {directDom: boolean, viewFlags: number}) { it('should inject ElementRef', () => { const {view} = createAndGetRootNodes(compViewDef([ elementDef(NodeFlags.None, null, null, 1, 'span'), - providerDef(NodeFlags.None, null, 0, SomeService, [ElementRef]) + directiveDef(NodeFlags.None, null, 0, SomeService, [ElementRef]) ])); expect(instance.dep.nativeElement).toBe(asElementData(view, 0).renderElement); }); + it('should inject Injector', () => { + const {view} = createAndGetRootNodes(compViewDef([ + elementDef(NodeFlags.None, null, null, 1, 'span'), + directiveDef(NodeFlags.None, null, 0, SomeService, [Injector]) + ])); + + expect(instance.dep.get(SomeService)).toBe(instance); + }); + + it('should inject ChangeDetectorRef for non component providers', () => { + const {view} = createAndGetRootNodes(compViewDef([ + elementDef(NodeFlags.None, null, null, 1, 'span'), + directiveDef(NodeFlags.None, null, 0, SomeService, [ChangeDetectorRef]) + ])); + + expect(instance.dep._view).toBe(view); + }); + + it('should inject ChangeDetectorRef for component providers', () => { + const {view, rootNodes} = createAndGetRootNodes(compViewDef([ + elementDef(NodeFlags.None, null, null, 1, 'div'), + directiveDef( + NodeFlags.None, null, 0, SomeService, [ChangeDetectorRef], null, null, + () => compViewDef([ + elementDef(NodeFlags.None, null, null, 0, 'span'), + ])), + ])); + + const compView = asProviderData(view, 1).componentView; + expect(instance.dep._view).toBe(compView); + }); + if (config.directDom) { it('should not inject Renderer when using directDom', () => { expect(() => createAndGetRootNodes(compViewDef([ elementDef(NodeFlags.None, null, null, 1, 'span'), - providerDef(NodeFlags.None, null, 0, SomeService, [Renderer]) + directiveDef(NodeFlags.None, null, 0, SomeService, [Renderer]) ]))) .toThrowError('No provider for Renderer!'); }); @@ -191,7 +302,7 @@ function defineTests(config: {directDom: boolean, viewFlags: number}) { it('should inject Renderer when not using directDom', () => { createAndGetRootNodes(compViewDef([ elementDef(NodeFlags.None, null, null, 1, 'span'), - providerDef(NodeFlags.None, null, 0, SomeService, [Renderer]) + directiveDef(NodeFlags.None, null, 0, SomeService, [Renderer]) ])); expect(instance.dep.createElement).toBeTruthy(); @@ -217,7 +328,7 @@ function defineTests(config: {directDom: boolean, viewFlags: number}) { const {view, rootNodes} = createAndGetRootNodes(compViewDef( [ elementDef(NodeFlags.None, null, null, 1, 'span'), - providerDef(NodeFlags.None, null, 0, SomeService, [], {a: [0, 'a'], b: [1, 'b']}) + directiveDef(NodeFlags.None, null, 0, SomeService, [], {a: [0, 'a'], b: [1, 'b']}) ], (view) => { setCurrentNode(view, 1); @@ -246,7 +357,7 @@ function defineTests(config: {directDom: boolean, viewFlags: number}) { const {view, rootNodes} = createAndGetRootNodes(compViewDef( [ elementDef(NodeFlags.None, null, null, 1, 'span'), - providerDef(NodeFlags.None, null, 0, SomeService, [], {a: [0, 'a']}) + directiveDef(NodeFlags.None, null, 0, SomeService, [], {a: [0, 'a']}) ], (view) => { setCurrentNode(view, 1); @@ -291,7 +402,7 @@ function defineTests(config: {directDom: boolean, viewFlags: number}) { const {view, rootNodes} = createAndGetRootNodes(compViewDef( [ elementDef(NodeFlags.None, null, null, 1, 'span'), - providerDef( + directiveDef( NodeFlags.None, null, 0, SomeService, [], null, {emitter: 'someEventName'}) ], null, handleEvent)); @@ -313,7 +424,7 @@ function defineTests(config: {directDom: boolean, viewFlags: number}) { const {view, rootNodes} = createAndGetRootNodes(compViewDef( [ elementDef(NodeFlags.None, null, null, 1, 'span'), - providerDef( + directiveDef( NodeFlags.None, null, 0, SomeService, [], null, {emitter: 'someEventName'}) ], null, () => { throw new Error('Test'); })); @@ -358,9 +469,9 @@ function defineTests(config: {directDom: boolean, viewFlags: number}) { const {view, rootNodes} = createAndGetRootNodes(compViewDef( [ elementDef(NodeFlags.None, null, null, 3, 'span'), - providerDef(allFlags, null, 0, SomeService, [], {a: [0, 'a']}), + directiveDef(allFlags, null, 0, SomeService, [], {a: [0, 'a']}), elementDef(NodeFlags.None, null, null, 1, 'span'), - providerDef(allFlags, null, 0, SomeService, [], {a: [0, 'a']}) + directiveDef(allFlags, null, 0, SomeService, [], {a: [0, 'a']}) ], (updater) => { setCurrentNode(view, 1); @@ -419,7 +530,8 @@ function defineTests(config: {directDom: boolean, viewFlags: number}) { const {view, rootNodes} = createAndGetRootNodes(compViewDef( [ elementDef(NodeFlags.None, null, null, 1, 'span'), - providerDef(NodeFlags.OnChanges, null, 0, SomeService, [], {a: [0, 'nonMinifiedA']}) + directiveDef( + NodeFlags.OnChanges, null, 0, SomeService, [], {a: [0, 'nonMinifiedA']}) ], (updater) => { setCurrentNode(view, 1); @@ -442,7 +554,7 @@ function defineTests(config: {directDom: boolean, viewFlags: number}) { const {view, rootNodes} = createAndGetRootNodes(compViewDef([ elementDef(NodeFlags.None, null, null, 1, 'span'), - providerDef(NodeFlags.AfterContentChecked, null, 0, SomeService, [], {a: [0, 'a']}), + directiveDef(NodeFlags.AfterContentChecked, null, 0, SomeService, [], {a: [0, 'a']}), ])); let err: any; @@ -465,7 +577,7 @@ function defineTests(config: {directDom: boolean, viewFlags: number}) { const {view, rootNodes} = createAndGetRootNodes(compViewDef([ elementDef(NodeFlags.None, null, null, 1, 'span'), - providerDef(NodeFlags.OnDestroy, null, 0, SomeService, [], {a: [0, 'a']}), + directiveDef(NodeFlags.OnDestroy, null, 0, SomeService, [], {a: [0, 'a']}), ])); let err: any; diff --git a/modules/@angular/core/test/view/pure_expression_spec.ts b/modules/@angular/core/test/view/pure_expression_spec.ts index ebf7b01344..5d8defe00c 100644 --- a/modules/@angular/core/test/view/pure_expression_spec.ts +++ b/modules/@angular/core/test/view/pure_expression_spec.ts @@ -7,7 +7,7 @@ */ import {PipeTransform, RenderComponentType, RootRenderer, Sanitizer, SecurityContext, ViewEncapsulation, WrappedValue} from '@angular/core'; -import {DefaultServices, NodeDef, NodeFlags, Services, ViewData, ViewDefinition, ViewFlags, ViewHandleEventFn, ViewUpdateFn, anchorDef, asProviderData, asPureExpressionData, checkAndUpdateView, checkNoChangesView, checkNodeDynamic, checkNodeInline, createRootView, elementDef, providerDef, pureArrayDef, pureObjectDef, purePipeDef, rootRenderNodes, setCurrentNode, textDef, viewDef} from '@angular/core/src/view/index'; +import {DefaultServices, NodeDef, NodeFlags, Services, ViewData, ViewDefinition, ViewFlags, ViewHandleEventFn, ViewUpdateFn, anchorDef, asProviderData, asPureExpressionData, checkAndUpdateView, checkNoChangesView, checkNodeDynamic, checkNodeInline, createRootView, directiveDef, elementDef, pureArrayDef, pureObjectDef, purePipeDef, rootRenderNodes, setCurrentNode, textDef, viewDef} from '@angular/core/src/view/index'; import {inject} from '@angular/core/testing'; import {INLINE_DYNAMIC_VALUES, InlineDynamic, checkNodeInlineOrDynamic} from './helper'; @@ -48,7 +48,7 @@ export function main() { const {view, rootNodes} = createAndGetRootNodes(compViewDef( [ elementDef(NodeFlags.None, null, null, 2, 'span'), pureArrayDef(2), - providerDef(NodeFlags.None, null, 0, Service, [], {data: [0, 'data']}) + directiveDef(NodeFlags.None, null, 0, Service, [], {data: [0, 'data']}) ], (view) => { setCurrentNode(view, 1); @@ -114,7 +114,7 @@ export function main() { const {view, rootNodes} = createAndGetRootNodes(compViewDef( [ elementDef(NodeFlags.None, null, null, 2, 'span'), pureObjectDef(['a', 'b']), - providerDef(NodeFlags.None, null, 0, Service, [], {data: [0, 'data']}) + directiveDef(NodeFlags.None, null, 0, Service, [], {data: [0, 'data']}) ], (view) => { setCurrentNode(view, 1); @@ -183,8 +183,8 @@ export function main() { const {view, rootNodes} = createAndGetRootNodes(compViewDef( [ elementDef(NodeFlags.None, null, null, 3, 'span'), - providerDef(NodeFlags.None, null, 0, SomePipe, []), purePipeDef(SomePipe, 2), - providerDef(NodeFlags.None, null, 0, Service, [], {data: [0, 'data']}) + directiveDef(NodeFlags.None, null, 0, SomePipe, []), purePipeDef(SomePipe, 2), + directiveDef(NodeFlags.None, null, 0, Service, [], {data: [0, 'data']}) ], (view) => { setCurrentNode(view, 2); @@ -222,7 +222,7 @@ export function main() { const {view, rootNodes} = createAndGetRootNodes(compViewDef( [ elementDef(NodeFlags.None, null, null, 2, 'span'), - providerDef(NodeFlags.None, null, 0, SomePipe, []), + directiveDef(NodeFlags.None, null, 0, SomePipe, []), purePipeDef(SomePipe, 1), ], (view) => { diff --git a/modules/@angular/core/test/view/query_spec.ts b/modules/@angular/core/test/view/query_spec.ts index e4aab40a98..7d8fc21442 100644 --- a/modules/@angular/core/test/view/query_spec.ts +++ b/modules/@angular/core/test/view/query_spec.ts @@ -7,7 +7,7 @@ */ import {ElementRef, QueryList, RenderComponentType, RootRenderer, Sanitizer, SecurityContext, TemplateRef, ViewContainerRef, ViewEncapsulation, getDebugNode} from '@angular/core'; -import {BindingType, DebugContext, DefaultServices, NodeDef, NodeFlags, QueryBindingType, QueryValueType, Services, ViewData, ViewDefinition, ViewFlags, ViewHandleEventFn, ViewUpdateFn, anchorDef, asElementData, asProviderData, attachEmbeddedView, checkAndUpdateView, checkNoChangesView, checkNodeDynamic, checkNodeInline, createEmbeddedView, createRootView, destroyView, detachEmbeddedView, elementDef, providerDef, queryDef, rootRenderNodes, setCurrentNode, textDef, viewDef} from '@angular/core/src/view/index'; +import {BindingType, DebugContext, DefaultServices, NodeDef, NodeFlags, QueryBindingType, QueryValueType, Services, ViewData, ViewDefinition, ViewFlags, ViewHandleEventFn, ViewUpdateFn, anchorDef, asElementData, asProviderData, attachEmbeddedView, checkAndUpdateView, checkNoChangesView, checkNodeDynamic, checkNodeInline, createEmbeddedView, createRootView, destroyView, detachEmbeddedView, directiveDef, elementDef, queryDef, rootRenderNodes, setCurrentNode, textDef, viewDef} from '@angular/core/src/view/index'; import {inject} from '@angular/core/testing'; import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter'; @@ -47,20 +47,20 @@ export function main() { function contentQueryProviders() { return [ - providerDef(NodeFlags.None, null, 1, QueryService, []), + directiveDef(NodeFlags.None, null, 1, QueryService, []), queryDef(NodeFlags.HasContentQuery, 'query1', {'a': QueryBindingType.All}) ]; } function viewQueryProviders(compView: ViewDefinition) { return [ - providerDef(NodeFlags.None, null, 1, QueryService, [], null, null, () => compView), + directiveDef(NodeFlags.None, null, 1, QueryService, [], null, null, () => compView), queryDef(NodeFlags.HasViewQuery, 'query1', {'a': QueryBindingType.All}) ]; } function aServiceProvider() { - return providerDef(NodeFlags.None, [['query1', QueryValueType.Provider]], 0, AService, []); + return directiveDef(NodeFlags.None, [['query1', QueryValueType.Provider]], 0, AService, []); } describe('content queries', () => { @@ -272,7 +272,7 @@ export function main() { const {view} = createAndGetRootNodes(compViewDef([ elementDef(NodeFlags.None, null, null, 4, 'div'), - providerDef(NodeFlags.None, null, 1, QueryService, []), + directiveDef(NodeFlags.None, null, 1, QueryService, []), queryDef(NodeFlags.HasContentQuery, 'query1', {'a': QueryBindingType.All}), aServiceProvider(), aServiceProvider(), @@ -295,7 +295,7 @@ export function main() { const {view} = createAndGetRootNodes(compViewDef([ elementDef(NodeFlags.None, null, null, 4, 'div'), - providerDef(NodeFlags.None, null, 1, QueryService, []), + directiveDef(NodeFlags.None, null, 1, QueryService, []), queryDef(NodeFlags.HasContentQuery, 'query1', {'a': QueryBindingType.First}), aServiceProvider(), aServiceProvider(), @@ -316,7 +316,7 @@ export function main() { const {view} = createAndGetRootNodes(compViewDef([ elementDef(NodeFlags.None, [['query1', QueryValueType.ElementRef]], null, 2, 'div'), - providerDef(NodeFlags.None, null, 1, QueryService, []), + directiveDef(NodeFlags.None, null, 1, QueryService, []), queryDef(NodeFlags.HasContentQuery, 'query1', {'a': QueryBindingType.First}), ])); @@ -335,7 +335,7 @@ export function main() { anchorDef( NodeFlags.None, [['query1', QueryValueType.TemplateRef]], null, 2, viewDef(ViewFlags.None, [anchorDef(NodeFlags.None, null, null, 0)])), - providerDef(NodeFlags.None, null, 1, QueryService, []), + directiveDef(NodeFlags.None, null, 1, QueryService, []), queryDef(NodeFlags.HasContentQuery, 'query1', {'a': QueryBindingType.First}), ])); @@ -352,7 +352,7 @@ export function main() { const {view} = createAndGetRootNodes(compViewDef([ anchorDef(NodeFlags.None, [['query1', QueryValueType.ViewContainerRef]], null, 2), - providerDef(NodeFlags.None, null, 1, QueryService, []), + directiveDef(NodeFlags.None, null, 1, QueryService, []), queryDef(NodeFlags.HasContentQuery, 'query1', {'a': QueryBindingType.First}), ])); @@ -406,7 +406,7 @@ export function main() { const {view} = createAndGetRootNodes(compViewDef([ elementDef(NodeFlags.None, null, null, 3, 'div'), - providerDef(NodeFlags.None, null, 1, QueryService, []), + directiveDef(NodeFlags.None, null, 1, QueryService, []), queryDef(NodeFlags.HasContentQuery, 'query1', {'a': QueryBindingType.All}), aServiceProvider(), ])); diff --git a/modules/@angular/core/test/view/services_spec.ts b/modules/@angular/core/test/view/services_spec.ts index 52660723fb..3495388b91 100644 --- a/modules/@angular/core/test/view/services_spec.ts +++ b/modules/@angular/core/test/view/services_spec.ts @@ -7,7 +7,7 @@ */ import {RenderComponentType, RootRenderer, Sanitizer, SecurityContext, ViewEncapsulation, getDebugNode} from '@angular/core'; -import {DebugContext, DefaultServices, NodeDef, NodeFlags, QueryValueType, Services, ViewData, ViewDefinition, ViewFlags, ViewHandleEventFn, ViewUpdateFn, anchorDef, asElementData, asProviderData, asTextData, checkAndUpdateView, checkNoChangesView, checkNodeDynamic, checkNodeInline, createRootView, elementDef, providerDef, rootRenderNodes, setCurrentNode, textDef, viewDef} from '@angular/core/src/view/index'; +import {DebugContext, DefaultServices, NodeDef, NodeFlags, QueryValueType, Services, ViewData, ViewDefinition, ViewFlags, ViewHandleEventFn, ViewUpdateFn, anchorDef, asElementData, asProviderData, asTextData, checkAndUpdateView, checkNoChangesView, checkNodeDynamic, checkNodeInline, createRootView, directiveDef, elementDef, rootRenderNodes, setCurrentNode, textDef, viewDef} from '@angular/core/src/view/index'; import {inject} from '@angular/core/testing'; import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter'; @@ -45,11 +45,11 @@ export function main() { function createViewWithData() { const {view} = createAndGetRootNodes(compViewDef([ elementDef(NodeFlags.None, null, null, 1, 'div'), - providerDef( + directiveDef( NodeFlags.None, null, 0, AComp, [], null, null, () => compViewDef([ elementDef(NodeFlags.None, [['#ref', QueryValueType.ElementRef]], null, 2, 'span'), - providerDef(NodeFlags.None, null, 0, AService, []), textDef(null, ['a']) + directiveDef(NodeFlags.None, null, 0, AService, []), textDef(null, ['a']) ])), ])); return view; diff --git a/modules/@angular/core/test/view/view_def_spec.ts b/modules/@angular/core/test/view/view_def_spec.ts index 938f0618bb..e2f042c82a 100644 --- a/modules/@angular/core/test/view/view_def_spec.ts +++ b/modules/@angular/core/test/view/view_def_spec.ts @@ -6,7 +6,7 @@ * found in the LICENSE file at https://angular.io/license */ -import {NodeFlags, QueryValueType, ViewData, ViewDefinition, ViewFlags, anchorDef, checkAndUpdateView, checkNoChangesView, checkNodeDynamic, checkNodeInline, elementDef, providerDef, setCurrentNode, textDef, viewDef} from '@angular/core/src/view/index'; +import {NodeFlags, QueryValueType, ViewData, ViewDefinition, ViewFlags, anchorDef, checkAndUpdateView, checkNoChangesView, checkNodeDynamic, checkNodeInline, directiveDef, elementDef, setCurrentNode, textDef, viewDef} from '@angular/core/src/view/index'; export function main() { describe('viewDef', () => { @@ -124,7 +124,7 @@ export function main() { it('should calculate childFlags for one level', () => { const vd = viewDef(ViewFlags.None, [ elementDef(NodeFlags.None, null, null, 1, 'span'), - providerDef(NodeFlags.AfterContentChecked, null, 0, AService, []) + directiveDef(NodeFlags.AfterContentChecked, null, 0, AService, []) ]); expect(childFlags(vd)).toEqual([NodeFlags.AfterContentChecked, NodeFlags.None]); @@ -134,7 +134,7 @@ export function main() { const vd = viewDef(ViewFlags.None, [ elementDef(NodeFlags.None, null, null, 2, 'span'), elementDef(NodeFlags.None, null, null, 1, 'span'), - providerDef(NodeFlags.AfterContentChecked, null, 0, AService, []) + directiveDef(NodeFlags.AfterContentChecked, null, 0, AService, []) ]); expect(childFlags(vd)).toEqual([ @@ -145,10 +145,10 @@ export function main() { it('should calculate childFlags for one level, multiple roots', () => { const vd = viewDef(ViewFlags.None, [ elementDef(NodeFlags.None, null, null, 1, 'span'), - providerDef(NodeFlags.AfterContentChecked, null, 0, AService, []), + directiveDef(NodeFlags.AfterContentChecked, null, 0, AService, []), elementDef(NodeFlags.None, null, null, 2, 'span'), - providerDef(NodeFlags.AfterContentInit, null, 0, AService, []), - providerDef(NodeFlags.AfterViewChecked, null, 0, AService, []), + directiveDef(NodeFlags.AfterContentInit, null, 0, AService, []), + directiveDef(NodeFlags.AfterViewChecked, null, 0, AService, []), ]); expect(childFlags(vd)).toEqual([ @@ -161,10 +161,10 @@ export function main() { const vd = viewDef(ViewFlags.None, [ elementDef(NodeFlags.None, null, null, 2, 'span'), elementDef(NodeFlags.None, null, null, 1, 'span'), - providerDef(NodeFlags.AfterContentChecked, null, 0, AService, []), + directiveDef(NodeFlags.AfterContentChecked, null, 0, AService, []), elementDef(NodeFlags.None, null, null, 2, 'span'), - providerDef(NodeFlags.AfterContentInit, null, 0, AService, []), - providerDef(NodeFlags.AfterViewInit, null, 0, AService, []), + directiveDef(NodeFlags.AfterContentInit, null, 0, AService, []), + directiveDef(NodeFlags.AfterViewInit, null, 0, AService, []), ]); expect(childFlags(vd)).toEqual([ @@ -182,7 +182,7 @@ export function main() { it('should calculate childMatchedQueries for one level', () => { const vd = viewDef(ViewFlags.None, [ elementDef(NodeFlags.None, null, null, 1, 'span'), - providerDef(NodeFlags.None, [['q1', QueryValueType.Provider]], 0, AService, []) + directiveDef(NodeFlags.None, [['q1', QueryValueType.Provider]], 0, AService, []) ]); expect(childMatchedQueries(vd)).toEqual([['q1'], []]); @@ -192,7 +192,7 @@ export function main() { const vd = viewDef(ViewFlags.None, [ elementDef(NodeFlags.None, null, null, 2, 'span'), elementDef(NodeFlags.None, null, null, 1, 'span'), - providerDef(NodeFlags.None, [['q1', QueryValueType.Provider]], 0, AService, []) + directiveDef(NodeFlags.None, [['q1', QueryValueType.Provider]], 0, AService, []) ]); expect(childMatchedQueries(vd)).toEqual([['q1'], ['q1'], []]); @@ -201,10 +201,10 @@ export function main() { it('should calculate childMatchedQueries for one level, multiple roots', () => { const vd = viewDef(ViewFlags.None, [ elementDef(NodeFlags.None, null, null, 1, 'span'), - providerDef(NodeFlags.None, [['q1', QueryValueType.Provider]], 0, AService, []), + directiveDef(NodeFlags.None, [['q1', QueryValueType.Provider]], 0, AService, []), elementDef(NodeFlags.None, null, null, 2, 'span'), - providerDef(NodeFlags.None, [['q2', QueryValueType.Provider]], 0, AService, []), - providerDef(NodeFlags.None, [['q3', QueryValueType.Provider]], 0, AService, []), + directiveDef(NodeFlags.None, [['q2', QueryValueType.Provider]], 0, AService, []), + directiveDef(NodeFlags.None, [['q3', QueryValueType.Provider]], 0, AService, []), ]); expect(childMatchedQueries(vd)).toEqual([['q1'], [], ['q2', 'q3'], [], []]); @@ -214,10 +214,10 @@ export function main() { const vd = viewDef(ViewFlags.None, [ elementDef(NodeFlags.None, null, null, 2, 'span'), elementDef(NodeFlags.None, null, null, 1, 'span'), - providerDef(NodeFlags.None, [['q1', QueryValueType.Provider]], 0, AService, []), + directiveDef(NodeFlags.None, [['q1', QueryValueType.Provider]], 0, AService, []), elementDef(NodeFlags.None, null, null, 2, 'span'), - providerDef(NodeFlags.None, [['q2', QueryValueType.Provider]], 0, AService, []), - providerDef(NodeFlags.None, [['q3', QueryValueType.Provider]], 0, AService, []), + directiveDef(NodeFlags.None, [['q2', QueryValueType.Provider]], 0, AService, []), + directiveDef(NodeFlags.None, [['q3', QueryValueType.Provider]], 0, AService, []), ]); expect(childMatchedQueries(vd)).toEqual([['q1'], ['q1'], [], ['q2', 'q3'], [], []]); diff --git a/modules/benchmarks/src/tree/ng2_next/tree.ts b/modules/benchmarks/src/tree/ng2_next/tree.ts index 323a7977ea..a2e4e05937 100644 --- a/modules/benchmarks/src/tree/ng2_next/tree.ts +++ b/modules/benchmarks/src/tree/ng2_next/tree.ts @@ -8,7 +8,7 @@ import {NgIf} from '@angular/common'; import {Component, NgModule, TemplateRef, ViewContainerRef, ViewEncapsulation} from '@angular/core'; -import {BindingType, DefaultServices, NodeFlags, ViewData, ViewDefinition, ViewFlags, anchorDef, asElementData, asProviderData, checkAndUpdateView, checkNodeInline, createRootView, elementDef, providerDef, setCurrentNode, textDef, viewDef} from '@angular/core/src/view/index'; +import {BindingType, DefaultServices, NodeFlags, ViewData, ViewDefinition, ViewFlags, anchorDef, asElementData, asProviderData, checkAndUpdateView, checkNodeInline, createRootView, directiveDef, elementDef, setCurrentNode, textDef, viewDef} from '@angular/core/src/view/index'; import {DomSanitizer, DomSanitizerImpl, SafeStyle} from '@angular/platform-browser/src/security/dom_sanitization_service'; import {TreeNode, emptyTree} from '../util'; @@ -26,7 +26,7 @@ let viewFlags = ViewFlags.DirectDom; function TreeComponent_Host(): ViewDefinition { return viewDef(viewFlags, [ elementDef(NodeFlags.None, null, null, 1, 'tree'), - providerDef(NodeFlags.None, null, 0, TreeComponent, [], null, null, TreeComponent_0), + directiveDef(NodeFlags.None, null, 0, TreeComponent, [], null, null, TreeComponent_0), ]); } @@ -35,7 +35,7 @@ function TreeComponent_0(): ViewDefinition { viewFlags, [ elementDef(NodeFlags.None, null, null, 1, 'tree'), - providerDef( + directiveDef( NodeFlags.None, null, 0, TreeComponent, [], {data: [0, 'data']}, null, TreeComponent_0), ], (view: ViewData) => { @@ -48,7 +48,7 @@ function TreeComponent_0(): ViewDefinition { viewFlags, [ elementDef(NodeFlags.None, null, null, 1, 'tree'), - providerDef( + directiveDef( NodeFlags.None, null, 0, TreeComponent, [], {data: [0, 'data']}, null, TreeComponent_0), ], (view: ViewData) => { @@ -65,10 +65,10 @@ function TreeComponent_0(): ViewDefinition { [[BindingType.ElementStyle, 'backgroundColor', null]]), textDef(null, [' ', ' ']), anchorDef(NodeFlags.HasEmbeddedViews, null, null, 1, TreeComponent_1), - providerDef( + directiveDef( NodeFlags.None, null, 0, NgIf, [ViewContainerRef, TemplateRef], {ngIf: [0, 'ngIf']}), anchorDef(NodeFlags.HasEmbeddedViews, null, null, 1, TreeComponent_2), - providerDef( + directiveDef( NodeFlags.None, null, 0, NgIf, [ViewContainerRef, TemplateRef], {ngIf: [0, 'ngIf']}), ], (view: ViewData) => {