Skip to content

Commit a088b8c

Browse files
AndrewKushnirIgorMinar
authored andcommitted
feat(ivy): introduce "allocHostVars" instruction as a replacement for "hostVars" field (FW-692) (angular#27299)
PR Close angular#27299
1 parent 0df914e commit a088b8c

25 files changed

+329
-144
lines changed

packages/compiler-cli/test/compliance/r3_view_compiler_binding_spec.ts

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -146,11 +146,13 @@ describe('compiler compliance: bindings', () => {
146146
selectors: [["", "hostBindingDir", ""]],
147147
factory: function HostBindingDir_Factory(t) { return new (t || HostBindingDir)(); },
148148
hostBindings: function HostBindingDir_HostBindings(rf, ctx, elIndex) {
149+
if (rf & 1) {
150+
$r3$.ɵallocHostVars(1);
151+
}
149152
if (rf & 2) {
150153
$r3$.ɵelementProperty(elIndex, "id", $r3$.ɵbind(ctx.dirId));
151154
}
152-
},
153-
hostVars: 1
155+
}
154156
});
155157
`;
156158

@@ -191,11 +193,13 @@ describe('compiler compliance: bindings', () => {
191193
selectors: [["host-binding-comp"]],
192194
factory: function HostBindingComp_Factory(t) { return new (t || HostBindingComp)(); },
193195
hostBindings: function HostBindingComp_HostBindings(rf, ctx, elIndex) {
196+
if (rf & 1) {
197+
$r3$.ɵallocHostVars(3);
198+
}
194199
if (rf & 2) {
195200
$r3$.ɵelementProperty(elIndex, "id", $r3$.ɵbind($r3$.ɵpureFunction1(1, $ff$, ctx.id)));
196201
}
197202
},
198-
hostVars: 3,
199203
consts: 0,
200204
vars: 0,
201205
template: function HostBindingComp_Template(rf, ctx) {},
@@ -237,11 +241,13 @@ describe('compiler compliance: bindings', () => {
237241
selectors: [["", "hostAttributeDir", ""]],
238242
factory: function HostAttributeDir_Factory(t) { return new (t || HostAttributeDir)(); },
239243
hostBindings: function HostAttributeDir_HostBindings(rf, ctx, elIndex) {
244+
if (rf & 1) {
245+
$r3$.ɵallocHostVars(1);
246+
}
240247
if (rf & 2) {
241248
$r3$.ɵelementAttribute(elIndex, "required", $r3$.ɵbind(ctx.required));
242249
}
243-
},
244-
hostVars: 1
250+
}
245251
});
246252
`;
247253

packages/compiler-cli/test/compliance/r3_view_compiler_styling_spec.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -773,6 +773,7 @@ describe('compiler compliance: styling', () => {
773773
774774
hostBindings: function MyComponent_HostBindings(rf, ctx, elIndex) {
775775
if (rf & 1) {
776+
$r3$.ɵallocHostVars(4);
776777
$r3$.ɵelementStyling(_c0, _c1, $r3$.ɵdefaultStyleSanitizer, ctx);
777778
}
778779
if (rf & 2) {
@@ -831,6 +832,7 @@ describe('compiler compliance: styling', () => {
831832
832833
hostBindings: function MyComponent_HostBindings(rf, ctx, elIndex) {
833834
if (rf & 1) {
835+
$r3$.ɵallocHostVars(6);
834836
$r3$.ɵelementStyling(_c0, _c1, $r3$.ɵdefaultStyleSanitizer, ctx);
835837
}
836838
if (rf & 2) {
@@ -896,6 +898,7 @@ describe('compiler compliance: styling', () => {
896898
897899
function WidthDirective_HostBindings(rf, ctx, elIndex) {
898900
if (rf & 1) {
901+
$r3$.ɵallocHostVars(2);
899902
$r3$.ɵelementStyling(_c0, _c1, null, ctx);
900903
}
901904
if (rf & 2) {
@@ -907,6 +910,7 @@ describe('compiler compliance: styling', () => {
907910
908911
function HeightDirective_HostBindings(rf, ctx, elIndex) {
909912
if (rf & 1) {
913+
$r3$.ɵallocHostVars(2);
910914
$r3$.ɵelementStyling(_c2, _c3, null, ctx);
911915
}
912916
if (rf & 2) {

packages/compiler-cli/test/ngtsc/ngtsc_spec.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -512,6 +512,7 @@ describe('ngtsc behavioral tests', () => {
512512
const hostBindingsFn = `
513513
hostBindings: function FooCmp_HostBindings(rf, ctx, elIndex) {
514514
if (rf & 1) {
515+
i0.ɵallocHostVars(3);
515516
i0.ɵlistener("click", function FooCmp_click_HostBindingHandler($event) { return ctx.onClick($event); });
516517
i0.ɵlistener("change", function FooCmp_change_HostBindingHandler($event) { return ctx.onChange(ctx.arg1, ctx.arg2, ctx.arg3); });
517518
i0.ɵelementStyling(_c0, null, null, ctx);

packages/compiler/src/render3/r3_identifiers.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ export class Identifiers {
6666

6767
static disableBindings: o.ExternalReference = {name: 'ɵdisableBindings', moduleName: CORE};
6868

69+
static allocHostVars: o.ExternalReference = {name: 'ɵallocHostVars', moduleName: CORE};
70+
6971
static getCurrentView: o.ExternalReference = {name: 'ɵgetCurrentView', moduleName: CORE};
7072

7173
static restoreView: o.ExternalReference = {name: 'ɵrestoreView', moduleName: CORE};

packages/compiler/src/render3/view/compiler.ts

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,8 @@ function baseDirectiveFields(
6262

6363
definitionMap.set('contentQueriesRefresh', createContentQueriesRefreshFunction(meta));
6464

65-
// Initialize hostVars to number of bound host properties (interpolations illegal)
66-
let hostVars = Object.keys(meta.host.properties).length;
65+
// Initialize hostVarsCount to number of bound host properties (interpolations illegal)
66+
const hostVarsCount = Object.keys(meta.host.properties).length;
6767

6868
const elVarExp = o.variable('elIndex');
6969
const contextVarExp = o.variable(CONTEXT_NAME);
@@ -94,18 +94,9 @@ function baseDirectiveFields(
9494

9595
// e.g. `hostBindings: (rf, ctx, elIndex) => { ... }
9696
definitionMap.set(
97-
'hostBindings', createHostBindingsFunction(
98-
meta, elVarExp, contextVarExp, styleBuilder, bindingParser, constantPool,
99-
(slots: number) => {
100-
const originalSlots = hostVars;
101-
hostVars += slots;
102-
return originalSlots;
103-
}));
104-
105-
if (hostVars) {
106-
// e.g. `hostVars: 2
107-
definitionMap.set('hostVars', o.literal(hostVars));
108-
}
97+
'hostBindings',
98+
createHostBindingsFunction(
99+
meta, elVarExp, contextVarExp, styleBuilder, bindingParser, constantPool, hostVarsCount));
109100

110101
// e.g 'inputs: {a: 'a'}`
111102
definitionMap.set('inputs', conditionallyCreateMapObjectLiteral(meta.inputs));
@@ -645,12 +636,12 @@ function createViewQueriesFunction(
645636
function createHostBindingsFunction(
646637
meta: R3DirectiveMetadata, elVarExp: o.ReadVarExpr, bindingContext: o.ReadVarExpr,
647638
styleBuilder: StylingBuilder, bindingParser: BindingParser, constantPool: ConstantPool,
648-
allocatePureFunctionSlots: (slots: number) => number): o.Expression|null {
639+
hostVarsCount: number): o.Expression|null {
649640
const createStatements: o.Statement[] = [];
650641
const updateStatements: o.Statement[] = [];
651642

643+
let totalHostVarsCount = hostVarsCount;
652644
const hostBindingSourceSpan = meta.typeSourceSpan;
653-
654645
const directiveSummary = metadataAsSummary(meta);
655646

656647
// Calculate host event bindings
@@ -670,9 +661,13 @@ function createHostBindingsFunction(
670661
};
671662

672663
if (bindings) {
664+
const hostVarsCountFn = (numSlots: number): number => {
665+
totalHostVarsCount += numSlots;
666+
return hostVarsCount;
667+
};
673668
const valueConverter = new ValueConverter(
674669
constantPool,
675-
/* new nodes are illegal here */ () => error('Unexpected node'), allocatePureFunctionSlots,
670+
/* new nodes are illegal here */ () => error('Unexpected node'), hostVarsCountFn,
676671
/* pipes are illegal here */ () => error('Unexpected pipe'));
677672

678673
for (const binding of bindings) {
@@ -716,6 +711,11 @@ function createHostBindingsFunction(
716711
}
717712
}
718713

714+
if (totalHostVarsCount) {
715+
createStatements.unshift(
716+
o.importExpr(R3.allocHostVars).callFn([o.literal(totalHostVarsCount)]).toStmt());
717+
}
718+
719719
if (createStatements.length > 0 || updateStatements.length > 0) {
720720
const hostBindingsFnName = meta.name ? `${meta.name}_HostBindings` : null;
721721
const statements: o.Statement[] = [];

packages/core/src/core_render3_private_export.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ export {
8585
reference as ɵreference,
8686
enableBindings as ɵenableBindings,
8787
disableBindings as ɵdisableBindings,
88+
allocHostVars as ɵallocHostVars,
8889
elementAttribute as ɵelementAttribute,
8990
elementContainerStart as ɵelementContainerStart,
9091
elementContainerEnd as ɵelementContainerEnd,

packages/core/src/render3/component.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,13 @@ import {getComponentDef} from './definition';
1717
import {diPublicInInjector, getOrCreateNodeInjectorForNode} from './di';
1818
import {publishDefaultGlobalUtils} from './global_utils';
1919
import {queueInitHooks, queueLifecycleHooks} from './hooks';
20-
import {CLEAN_PROMISE, createLView, createNodeAtIndex, createTView, getOrCreateTView, initNodeFlags, instantiateRootComponent, locateHostElement, prefillHostVars, queueComponentIndexForCheck, refreshDescendantViews} from './instructions';
21-
import {ComponentDef, ComponentType} from './interfaces/definition';
20+
import {CLEAN_PROMISE, createLView, createNodeAtIndex, createTView, getOrCreateTView, initNodeFlags, instantiateRootComponent, locateHostElement, queueComponentIndexForCheck, refreshDescendantViews} from './instructions';
21+
import {ComponentDef, ComponentType, RenderFlags} from './interfaces/definition';
2222
import {TElementNode, TNodeFlags, TNodeType} from './interfaces/node';
2323
import {PlayerHandler} from './interfaces/player';
2424
import {RElement, Renderer3, RendererFactory3, domRendererFactory3} from './interfaces/renderer';
2525
import {CONTEXT, HEADER_OFFSET, HOST, HOST_NODE, INJECTOR, LView, LViewFlags, RootContext, RootContextFlags, TVIEW} from './interfaces/view';
26-
import {enterView, leaveView, resetComponentState} from './state';
26+
import {enterView, getPreviousOrParentTNode, leaveView, resetComponentState, setCurrentDirectiveDef} from './state';
2727
import {defaultScheduler, getRootView, readPatchedLView, stringify} from './util';
2828

2929

@@ -195,7 +195,13 @@ export function createRootComponent<T>(
195195

196196
hostFeatures && hostFeatures.forEach((feature) => feature(component, componentDef));
197197

198-
if (tView.firstTemplatePass) prefillHostVars(tView, rootView, componentDef.hostVars);
198+
if (tView.firstTemplatePass && componentDef.hostBindings) {
199+
const rootTNode = getPreviousOrParentTNode();
200+
setCurrentDirectiveDef(componentDef);
201+
componentDef.hostBindings(RenderFlags.Create, component, rootTNode.index);
202+
setCurrentDirectiveDef(null);
203+
}
204+
199205
return component;
200206
}
201207

packages/core/src/render3/definition.ts

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -73,14 +73,6 @@ export function defineComponent<T>(componentDefinition: {
7373
*/
7474
vars: number;
7575

76-
/**
77-
* The number of host bindings (including pure fn bindings) in this component.
78-
*
79-
* Used to calculate the length of the LView array for the *parent* component
80-
* of this component.
81-
*/
82-
hostVars?: number;
83-
8476
/**
8577
* Static attributes to set on host element.
8678
*
@@ -262,7 +254,6 @@ export function defineComponent<T>(componentDefinition: {
262254
providersResolver: null,
263255
consts: componentDefinition.consts,
264256
vars: componentDefinition.vars,
265-
hostVars: componentDefinition.hostVars || 0,
266257
factory: componentDefinition.factory,
267258
template: componentDefinition.template || null !,
268259
hostBindings: componentDefinition.hostBindings || null,
@@ -586,14 +577,6 @@ export const defineDirective = defineComponent as any as<T>(directiveDefinition:
586577
*/
587578
features?: DirectiveDefFeature[];
588579

589-
/**
590-
* The number of host bindings (including pure fn bindings) in this directive.
591-
*
592-
* Used to calculate the length of the LView array for the *parent* component
593-
* of this directive.
594-
*/
595-
hostVars?: number;
596-
597580
/**
598581
* Function executed by the parent template to allow child directive to apply host bindings.
599582
*/

packages/core/src/render3/features/inherit_definition_feature.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,6 @@ export function InheritDefinitionFeature(definition: DirectiveDef<any>| Componen
7676
superHostBindings(rf, ctx, elementIndex);
7777
prevHostBindings(rf, ctx, elementIndex);
7878
};
79-
(definition as any).hostVars += superDef.hostVars;
8079
} else {
8180
definition.hostBindings = superHostBindings;
8281
}

packages/core/src/render3/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ export {CssSelectorList} from './interfaces/projection';
2121

2222
// clang-format off
2323
export {
24+
allocHostVars,
2425
bind,
2526
interpolation1,
2627
interpolation2,

0 commit comments

Comments
 (0)