feat(core): view engine - add missing DI features (#14225)
Part of #14013 PR Close #14225
This commit is contained in:

committed by
Miško Hevery

parent
ae7f5f37d2
commit
a05e50fda3
@ -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';
|
||||
|
@ -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)});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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};
|
||||
}
|
||||
|
@ -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('#')) {
|
||||
|
@ -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>;
|
||||
|
@ -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:
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user