Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Directive instance refactor #33322

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions packages/core/src/render3/di.ts
Expand Up @@ -19,7 +19,7 @@ import {getFactoryDef} from './definition';
import {NG_ELEMENT_ID, NG_FACTORY_DEF} from './fields';
import {DirectiveDef, FactoryFn} from './interfaces/definition';
import {NO_PARENT_INJECTOR, NodeInjectorFactory, PARENT_INJECTOR, RelativeInjectorLocation, RelativeInjectorLocationFlags, TNODE, isFactory} from './interfaces/injector';
import {AttributeMarker, TContainerNode, TElementContainerNode, TElementNode, TNode, TNodeProviderIndexes, TNodeType} from './interfaces/node';
import {AttributeMarker, TContainerNode, TDirectiveHostNode, TElementContainerNode, TElementNode, TNode, TNodeProviderIndexes, TNodeType} from './interfaces/node';
import {isComponentDef, isComponentHost} from './interfaces/type_checks';
import {DECLARATION_VIEW, INJECTOR, LView, TData, TVIEW, TView, T_HOST} from './interfaces/view';
import {assertNodeOfPossibleTypes} from './node_assert';
Expand Down Expand Up @@ -528,7 +528,7 @@ export function locateDirectiveOrProvider<T>(
* instantiates the `injectable` and caches the value.
*/
export function getNodeInjectable(
tData: TData, lView: LView, index: number, tNode: TElementNode): any {
tData: TData, lView: LView, index: number, tNode: TDirectiveHostNode): any {
let value = lView[index];
if (isFactory(value)) {
const factory: NodeInjectorFactory = value;
Expand Down
10 changes: 5 additions & 5 deletions packages/core/src/render3/di_setup.ts
Expand Up @@ -15,7 +15,7 @@ import {diPublicInInjector, getNodeInjectable, getOrCreateNodeInjectorForNode} f
import {ɵɵdirectiveInject} from './instructions/all';
import {DirectiveDef} from './interfaces/definition';
import {NodeInjectorFactory} from './interfaces/injector';
import {TContainerNode, TElementContainerNode, TElementNode, TNodeProviderIndexes} from './interfaces/node';
import {TContainerNode, TDirectiveHostNode, TElementContainerNode, TElementNode, TNodeProviderIndexes} from './interfaces/node';
import {isComponentDef} from './interfaces/type_checks';
import {LView, TData, TVIEW, TView} from './interfaces/view';
import {getLView, getPreviousOrParentTNode} from './state';
Expand Down Expand Up @@ -205,7 +205,7 @@ function indexOf(item: any, arr: any[], begin: number, end: number) {
*/
function multiProvidersFactoryResolver(
this: NodeInjectorFactory, _: undefined, tData: TData, lData: LView,
tNode: TElementNode): any[] {
tNode: TDirectiveHostNode): any[] {
return multiResolve(this.multi !, []);
}

Expand All @@ -216,7 +216,7 @@ function multiProvidersFactoryResolver(
*/
function multiViewProvidersFactoryResolver(
this: NodeInjectorFactory, _: undefined, tData: TData, lData: LView,
tNode: TElementNode): any[] {
tNode: TDirectiveHostNode): any[] {
const factories = this.multi !;
let result: any[];
if (this.providerFactory) {
Expand Down Expand Up @@ -254,8 +254,8 @@ function multiResolve(factories: Array<() => any>, result: any[]): any[] {
*/
function multiFactory(
factoryFn: (
this: NodeInjectorFactory, _: undefined, tData: TData, lData: LView, tNode: TElementNode) =>
any,
this: NodeInjectorFactory, _: undefined, tData: TData, lData: LView,
tNode: TDirectiveHostNode) => any,
index: number, isViewProvider: boolean, isComponent: boolean,
f: () => any): NodeInjectorFactory {
const factory = new NodeInjectorFactory(factoryFn, isViewProvider, ɵɵdirectiveInject);
Expand Down
94 changes: 41 additions & 53 deletions packages/core/src/render3/instructions/shared.ts
Expand Up @@ -23,8 +23,8 @@ import {executeCheckHooks, executeInitAndCheckHooks, incrementInitPhaseFlags, re
import {ACTIVE_INDEX, CONTAINER_HEADER_OFFSET, LContainer} from '../interfaces/container';
import {ComponentDef, ComponentTemplate, DirectiveDef, DirectiveDefListOrFactory, PipeDefListOrFactory, RenderFlags, ViewQueriesFunction} from '../interfaces/definition';
import {INJECTOR_BLOOM_PARENT_SIZE, NodeInjectorFactory} from '../interfaces/injector';
import {AttributeMarker, InitialInputData, InitialInputs, LocalRefExtractor, PropertyAliasValue, PropertyAliases, TAttributes, TContainerNode, TElementContainerNode, TElementNode, TIcuContainerNode, TNode, TNodeFlags, TNodeProviderIndexes, TNodeType, TProjectionNode, TViewNode} from '../interfaces/node';
import {RComment, RElement, RText, Renderer3, RendererFactory3, isProceduralRenderer} from '../interfaces/renderer';
import {AttributeMarker, InitialInputData, InitialInputs, LocalRefExtractor, PropertyAliasValue, PropertyAliases, TAttributes, TContainerNode, TDirectiveHostNode, TElementContainerNode, TElementNode, TIcuContainerNode, TNode, TNodeFlags, TNodeProviderIndexes, TNodeType, TProjectionNode, TViewNode} from '../interfaces/node';
import {RComment, RElement, RNode, RText, Renderer3, RendererFactory3, isProceduralRenderer} from '../interfaces/renderer';
import {SanitizerFn} from '../interfaces/sanitization';
import {isComponentDef, isComponentHost, isContentQueryHost, isLContainer, isRootView} from '../interfaces/type_checks';
import {CHILD_HEAD, CHILD_TAIL, CLEANUP, CONTEXT, DECLARATION_VIEW, ExpandoInstructions, FLAGS, HEADER_OFFSET, HOST, INJECTOR, InitPhaseState, LView, LViewFlags, NEXT, PARENT, RENDERER, RENDERER_FACTORY, RootContext, RootContextFlags, SANITIZER, TData, TVIEW, TView, T_HOST} from '../interfaces/view';
Expand Down Expand Up @@ -529,10 +529,9 @@ export function executeContentQueries(tView: TView, tNode: TNode, lView: LView)
/**
* Creates directive instances.
*/
export function createDirectivesInstances(
tView: TView, lView: LView, tNode: TElementNode | TContainerNode | TElementContainerNode) {
export function createDirectivesInstances(tView: TView, lView: LView, tNode: TDirectiveHostNode) {
if (!getBindingsEnabled()) return;
instantiateAllDirectives(tView, lView, tNode);
instantiateAllDirectives(tView, lView, tNode, getNativeByTNode(tNode, lView));
if ((tNode.flags & TNodeFlags.hasHostBindings) === TNodeFlags.hasHostBindings) {
invokeDirectivesHostBindings(tView, lView, tNode);
}
Expand All @@ -543,7 +542,8 @@ export function createDirectivesInstances(
* to LView in the same order as they are loaded in the template with load().
*/
export function saveResolvedLocalsInData(
viewData: LView, tNode: TNode, localRefExtractor: LocalRefExtractor = getNativeByTNode): void {
viewData: LView, tNode: TDirectiveHostNode,
localRefExtractor: LocalRefExtractor = getNativeByTNode): void {
const localNames = tNode.localNames;
if (localNames) {
let localIndex = tNode.index + 1;
Expand Down Expand Up @@ -1018,17 +1018,20 @@ function warnAboutUnknownProperty(propName: string, tNode: TNode): void {
/**
* Instantiate a root component.
*/
export function instantiateRootComponent<T>(
tView: TView, viewData: LView, def: ComponentDef<T>): T {
export function instantiateRootComponent<T>(tView: TView, lView: LView, def: ComponentDef<T>): T {
const rootTNode = getPreviousOrParentTNode();
if (tView.firstTemplatePass) {
if (def.providersResolver) def.providersResolver(def);
generateExpandoInstructionBlock(tView, rootTNode, 1);
baseResolveDirective(tView, viewData, def);
baseResolveDirective(tView, lView, def);
}
const directive =
getNodeInjectable(tView.data, viewData, viewData.length - 1, rootTNode as TElementNode);
postProcessBaseDirective(viewData, rootTNode, directive);
getNodeInjectable(tView.data, lView, lView.length - 1, rootTNode as TElementNode);
attachPatchData(directive, lView);
const native = getNativeByTNode(rootTNode, lView);
if (native) {
attachPatchData(native, lView);
}
return directive;
}

Expand Down Expand Up @@ -1090,20 +1093,37 @@ export function resolveDirectives(
/**
* Instantiate all the directives that were previously resolved on the current node.
*/
function instantiateAllDirectives(tView: TView, lView: LView, tNode: TNode) {
function instantiateAllDirectives(
tView: TView, lView: LView, tNode: TDirectiveHostNode, native: RNode) {
const start = tNode.directiveStart;
const end = tNode.directiveEnd;
if (!tView.firstTemplatePass) {
getOrCreateNodeInjectorForNode(
tNode as TElementNode | TContainerNode | TElementContainerNode, lView);
getOrCreateNodeInjectorForNode(tNode, lView);
}

attachPatchData(native, lView);

const initialInputs = tNode.initialInputs;
for (let i = start; i < end; i++) {
const def = tView.data[i] as DirectiveDef<any>;
if (isComponentDef(def)) {
addComponentLogic(lView, tNode, def as ComponentDef<any>);
const isComponent = isComponentDef(def);

if (isComponent) {
ngDevMode && assertNodeOfPossibleTypes(tNode, TNodeType.Element);
kara marked this conversation as resolved.
Show resolved Hide resolved
addComponentLogic(lView, tNode as TElementNode, def as ComponentDef<any>);
}

const directive = getNodeInjectable(tView.data, lView, i, tNode);
attachPatchData(directive, lView);

if (initialInputs !== null) {
setInputsFromAttrs(lView, i - start, directive, def, tNode, initialInputs !);
}

if (isComponent) {
const componentView = getComponentLViewByIndex(tNode.index, lView);
componentView[CONTEXT] = directive;
}
const directive = getNodeInjectable(tView.data, lView !, i, tNode as TElementNode);
postProcessDirective(lView, tNode, directive, def, i - start);
}
}

Expand Down Expand Up @@ -1169,38 +1189,6 @@ export function generateExpandoInstructionBlock(
])).push(elementIndex, providerCount, directiveCount);
}

/**
* Process a directive on the current node after its creation.
*/
function postProcessDirective<T>(
lView: LView, hostTNode: TNode, directive: T, def: DirectiveDef<T>,
directiveDefIdx: number): void {
postProcessBaseDirective(lView, hostTNode, directive);
if (hostTNode.initialInputs !== null) {
setInputsFromAttrs(lView, directiveDefIdx, directive, def, hostTNode);
}

if (isComponentDef(def)) {
const componentView = getComponentLViewByIndex(hostTNode.index, lView);
componentView[CONTEXT] = directive;
}
}

/**
* A lighter version of postProcessDirective() that is used for the root component.
*/
function postProcessBaseDirective<T>(lView: LView, hostTNode: TNode, directive: T): void {
ngDevMode && assertLessThanOrEqual(
getBindingIndex(), lView[TVIEW].bindingStartIndex,
'directives should be created before any bindings');
attachPatchData(directive, lView);
const native = getNativeByTNode(hostTNode, lView);
if (native) {
attachPatchData(native, lView);
}
}


/**
* Matches the current node against all available selectors.
* If a component is matched (at most one), it is returned in first position in the array.
Expand Down Expand Up @@ -1306,7 +1294,7 @@ function baseResolveDirective<T>(tView: TView, viewData: LView, def: DirectiveDe
viewData.push(nodeInjectorFactory);
}

function addComponentLogic<T>(lView: LView, hostTNode: TNode, def: ComponentDef<T>): void {
function addComponentLogic<T>(lView: LView, hostTNode: TElementNode, def: ComponentDef<T>): void {
const native = getNativeByTNode(hostTNode, lView) as RElement;
const tView = getOrCreateTView(def);

Expand Down Expand Up @@ -1361,8 +1349,8 @@ export function elementAttributeInternal(
* @param tNode The static data for this node
*/
function setInputsFromAttrs<T>(
lView: LView, directiveIndex: number, instance: T, def: DirectiveDef<T>, tNode: TNode): void {
const initialInputData = tNode.initialInputs as InitialInputData;
lView: LView, directiveIndex: number, instance: T, def: DirectiveDef<T>, tNode: TNode,
initialInputData: InitialInputData): void {
const initialInputs: InitialInputs|null = initialInputData ![directiveIndex];
if (initialInputs !== null) {
const setInput = def.setInput;
Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/render3/interfaces/injector.ts
Expand Up @@ -10,7 +10,7 @@ import {InjectionToken} from '../../di/injection_token';
import {InjectFlags} from '../../di/interface/injector';
import {Type} from '../../interface/type';

import {TElementNode} from './node';
import {TDirectiveHostNode} from './node';
import {LView, TData} from './view';

export const TNODE = 8;
Expand Down Expand Up @@ -230,7 +230,7 @@ export class NodeInjectorFactory {
/**
* The TNode of the same element injector.
*/
tNode: TElementNode) => any,
tNode: TDirectiveHostNode) => any,
/**
* Set to `true` if the token is declared in `viewProviders` (or if it is component).
*/
Expand Down
5 changes: 5 additions & 0 deletions packages/core/src/render3/interfaces/node.ts
Expand Up @@ -602,6 +602,11 @@ export interface TProjectionNode extends TNode {
projection: number;
}

/**
* A union type representing all TNode types that can host a directive.
*/
export type TDirectiveHostNode = TElementNode | TContainerNode | TElementContainerNode;

/**
* This mapping is necessary so we can set input properties and output listeners
* properly at runtime when property names are minified or aliased.
Expand Down
Expand Up @@ -533,12 +533,6 @@
{
"name": "objectToClassName"
},
{
"name": "postProcessBaseDirective"
},
{
"name": "postProcessDirective"
},
{
"name": "refreshChildComponents"
},
Expand Down
Expand Up @@ -392,9 +392,6 @@
{
"name": "noSideEffects"
},
{
"name": "postProcessBaseDirective"
},
{
"name": "refreshChildComponents"
},
Expand Down
6 changes: 0 additions & 6 deletions packages/core/test/bundling/todo/bundle.golden_symbols.json
Expand Up @@ -1088,12 +1088,6 @@
{
"name": "patchConfig"
},
{
"name": "postProcessBaseDirective"
},
{
"name": "postProcessDirective"
},
{
"name": "readPatchedData"
},
Expand Down