feat(core): view engine - add missing DI features (#14225)

Part of #14013

PR Close #14225
This commit is contained in:
Tobias Bosch 2017-02-01 07:27:38 -08:00 committed by Miško Hevery
parent ae7f5f37d2
commit a05e50fda3
16 changed files with 396 additions and 158 deletions

View File

@ -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';

View File

@ -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<any, string>();
@ -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)});
}
}

View File

@ -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};
}

View File

@ -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<any> {
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('#')) {

View File

@ -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<any>;

View File

@ -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:

View File

@ -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 = <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 = <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);
}

View File

@ -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, [])
])),
]));

View File

@ -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, [])
]))
]));

View File

@ -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)])));

View File

@ -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;

View File

@ -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) => {

View File

@ -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(),
]));

View File

@ -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;

View File

@ -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'], [], []]);

View File

@ -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) => {