Skip to content

Commit be8fbac

Browse files
matskokara
authored andcommitted
refactor(ivy): break apart stylingMap into styleMap and classMap instructions (angular#30293)
This patch breaks up the existing `elementStylingMap` into `elementClassMap` and `elementStyleMap` instructions. It also breaks apart `hostStlyingMap` into `hostClassMap` and `hostStyleMap` instructions. This change allows for better tree-shaking and reduces the complexity of the styling algorithm code for `[style]` and `[class]` bindings. PR Close angular#30293
1 parent 98a38ec commit be8fbac

File tree

18 files changed

+415
-321
lines changed

18 files changed

+415
-321
lines changed

packages/common/src/directives/ng_class.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* Use of this source code is governed by an MIT-style license that can be
66
* found in the LICENSE file at https://angular.io/license
77
*/
8-
import {Directive, DoCheck, Input, ɵRenderFlags, ɵɵdefineDirective, ɵɵelementHostStyling, ɵɵelementHostStylingApply, ɵɵelementHostStylingMap} from '@angular/core';
8+
import {Directive, DoCheck, Input, ɵRenderFlags, ɵɵdefineDirective, ɵɵelementHostClassMap, ɵɵelementHostStyling, ɵɵelementHostStylingApply} from '@angular/core';
99

1010
import {NgClassImpl, NgClassImplProvider} from './ng_class_impl';
1111

@@ -38,7 +38,7 @@ export const ngClassDirectiveDef__POST_R3__ = ɵɵdefineDirective({
3838
ɵɵelementHostStyling();
3939
}
4040
if (rf & ɵRenderFlags.Update) {
41-
ɵɵelementHostStylingMap(ctx.getValue());
41+
ɵɵelementHostClassMap(ctx.getValue());
4242
ɵɵelementHostStylingApply();
4343
}
4444
}

packages/common/src/directives/ng_style.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* Use of this source code is governed by an MIT-style license that can be
66
* found in the LICENSE file at https://angular.io/license
77
*/
8-
import {Directive, DoCheck, Input, ɵRenderFlags, ɵɵdefineDirective, ɵɵelementHostStyling, ɵɵelementHostStylingApply, ɵɵelementHostStylingMap} from '@angular/core';
8+
import {Directive, DoCheck, Input, ɵRenderFlags, ɵɵdefineDirective, ɵɵelementHostStyleMap, ɵɵelementHostStyling, ɵɵelementHostStylingApply} from '@angular/core';
99

1010
import {NgStyleImpl, NgStyleImplProvider} from './ng_style_impl';
1111

@@ -38,7 +38,7 @@ export const ngStyleDirectiveDef__POST_R3__ = ɵɵdefineDirective({
3838
ɵɵelementHostStyling();
3939
}
4040
if (rf & ɵRenderFlags.Update) {
41-
ɵɵelementHostStylingMap(null, ctx.getValue());
41+
ɵɵelementHostStyleMap(ctx.getValue());
4242
ɵɵelementHostStylingApply();
4343
}
4444
}

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

+26-18
Original file line numberDiff line numberDiff line change
@@ -389,7 +389,7 @@ describe('compiler compliance: styling', () => {
389389
$r3$.ɵɵelementEnd();
390390
}
391391
if (rf & 2) {
392-
$r3$.ɵɵelementStylingMap(0, null, $ctx$.myStyleExp);
392+
$r3$.ɵɵelementStyleMap(0, $ctx$.myStyleExp);
393393
$r3$.ɵɵelementStylingApply(0);
394394
}
395395
}
@@ -454,7 +454,7 @@ describe('compiler compliance: styling', () => {
454454
$r3$.ɵɵelementEnd();
455455
}
456456
if (rf & 2) {
457-
$r3$.ɵɵelementStylingMap(0, $r3$.ɵɵinterpolation1("foo foo-", $ctx$.fooId, ""));
457+
$r3$.ɵɵelementClassMap(0, $r3$.ɵɵinterpolation1("foo foo-", $ctx$.fooId, ""));
458458
$r3$.ɵɵelementStylingApply(0);
459459
}
460460
}
@@ -468,7 +468,7 @@ describe('compiler compliance: styling', () => {
468468
$r3$.ɵɵelementEnd();
469469
}
470470
if (rf & 2) {
471-
$r3$.ɵɵelementStylingMap(0, $r3$.ɵɵinterpolation2("foo foo-", $ctx$.fooId, "-", $ctx$.fooUsername, ""));
471+
$r3$.ɵɵelementClassMap(0, $r3$.ɵɵinterpolation2("foo foo-", $ctx$.fooId, "-", $ctx$.fooUsername, ""));
472472
$r3$.ɵɵelementStylingApply(0);
473473
}
474474
}
@@ -482,7 +482,7 @@ describe('compiler compliance: styling', () => {
482482
$r3$.ɵɵelementEnd();
483483
}
484484
if (rf & 2) {
485-
$r3$.ɵɵelementStylingMap(0, $ctx$.exp);
485+
$r3$.ɵɵelementClassMap(0, $ctx$.exp);
486486
$r3$.ɵɵelementStylingApply(0);
487487
}
488488
}
@@ -538,7 +538,7 @@ describe('compiler compliance: styling', () => {
538538
$r3$.ɵɵelementEnd();
539539
}
540540
if (rf & 2) {
541-
$r3$.ɵɵelementStylingMap(0, null, $ctx$.myStyleExp);
541+
$r3$.ɵɵelementStyleMap(0, $ctx$.myStyleExp);
542542
$r3$.ɵɵelementStyleProp(0, 0, $ctx$.myWidth);
543543
$r3$.ɵɵelementStyleProp(0, 1, $ctx$.myHeight);
544544
$r3$.ɵɵelementStylingApply(0);
@@ -704,7 +704,7 @@ describe('compiler compliance: styling', () => {
704704
$r3$.ɵɵelementEnd();
705705
}
706706
if (rf & 2) {
707-
$r3$.ɵɵelementStylingMap(0,$ctx$.myClassExp);
707+
$r3$.ɵɵelementClassMap(0,$ctx$.myClassExp);
708708
$r3$.ɵɵelementStylingApply(0);
709709
}
710710
}
@@ -760,7 +760,7 @@ describe('compiler compliance: styling', () => {
760760
$r3$.ɵɵelementEnd();
761761
}
762762
if (rf & 2) {
763-
$r3$.ɵɵelementStylingMap(0, $ctx$.myClassExp);
763+
$r3$.ɵɵelementClassMap(0, $ctx$.myClassExp);
764764
$r3$.ɵɵelementClassProp(0, 0, $ctx$.yesToApple);
765765
$r3$.ɵɵelementClassProp(0, 1, $ctx$.yesToOrange);
766766
$r3$.ɵɵelementStylingApply(0);
@@ -882,7 +882,8 @@ describe('compiler compliance: styling', () => {
882882
$r3$.ɵɵelementEnd();
883883
}
884884
if (rf & 2) {
885-
$r3$.ɵɵelementStylingMap(0, $ctx$.myClassExp, $ctx$.myStyleExp);
885+
$r3$.ɵɵelementStyleMap(0, $ctx$.myStyleExp);
886+
$r3$.ɵɵelementClassMap(0, $ctx$.myClassExp);
886887
$r3$.ɵɵelementStylingApply(0);
887888
}
888889
}
@@ -919,12 +920,13 @@ describe('compiler compliance: styling', () => {
919920
if (rf & 1) {
920921
$r3$.ɵɵelementStart(0, "div");
921922
$r3$.ɵɵelementStyling(null, null, $r3$.ɵɵdefaultStyleSanitizer);
922-
$r3$.ɵɵpipe(1, "classPipe");
923-
$r3$.ɵɵpipe(2, "stylePipe");
923+
$r3$.ɵɵpipe(1, "stylePipe");
924+
$r3$.ɵɵpipe(2, "classPipe");
924925
$r3$.ɵɵelementEnd();
925926
}
926927
if (rf & 2) {
927-
$r3$.ɵɵelementStylingMap(0, $r3$.ɵɵpipeBind1(1, 0, $ctx$.myClassExp), $r3$.ɵɵpipeBind1(2, 2, $ctx$.myStyleExp));
928+
$r3$.ɵɵelementStyleMap(0, $r3$.ɵɵpipeBind1(1, 0, $ctx$.myStyleExp));
929+
$r3$.ɵɵelementClassMap(0, $r3$.ɵɵpipeBind1(2, 2, $ctx$.myClassExp));
928930
$r3$.ɵɵelementStylingApply(0);
929931
}
930932
}
@@ -980,7 +982,8 @@ describe('compiler compliance: styling', () => {
980982
$r3$.ɵɵelementEnd();
981983
}
982984
if (rf & 2) {
983-
$r3$.ɵɵelementStylingMap(0, $e2_styling$, $r3$.ɵɵpipeBind2(1, 1, $ctx$.myStyleExp, 1000));
985+
$r3$.ɵɵelementStyleMap(0, $r3$.ɵɵpipeBind2(1, 1, $ctx$.myStyleExp, 1000));
986+
$r3$.ɵɵelementClassMap(0, $e2_styling$);
984987
$r3$.ɵɵelementStyleProp(0, 0, $r3$.ɵɵpipeBind2(2, 4, $ctx$.barExp, 3000));
985988
$r3$.ɵɵelementStyleProp(0, 1, $r3$.ɵɵpipeBind2(3, 7, $ctx$.bazExp, 4000));
986989
$r3$.ɵɵelementClassProp(0, 0, $r3$.ɵɵpipeBind2(4, 10, $ctx$.fooExp, 2000));
@@ -1042,7 +1045,8 @@ describe('compiler compliance: styling', () => {
10421045
$r3$.ɵɵelementHostStyling($e0_classBindings$, $e0_styleBindings$, $r3$.ɵɵdefaultStyleSanitizer);
10431046
}
10441047
if (rf & 2) {
1045-
$r3$.ɵɵelementHostStylingMap(ctx.myClass, ctx.myStyle);
1048+
$r3$.ɵɵelementHostStyleMap(ctx.myStyle);
1049+
$r3$.ɵɵelementHostClassMap(ctx.myClass);
10461050
$r3$.ɵɵelementHostStyleProp(0, ctx.myColorProp);
10471051
$r3$.ɵɵelementHostClassProp(0, ctx.myFooClass);
10481052
$r3$.ɵɵelementHostStylingApply();
@@ -1102,7 +1106,8 @@ describe('compiler compliance: styling', () => {
11021106
$r3$.ɵɵelementHostStyling(_c0, _c1, $r3$.ɵɵdefaultStyleSanitizer);
11031107
}
11041108
if (rf & 2) {
1105-
$r3$.ɵɵelementHostStylingMap(ctx.myClasses, ctx.myStyle);
1109+
$r3$.ɵɵelementHostStyleMap(ctx.myStyle);
1110+
$r3$.ɵɵelementHostClassMap(ctx.myClasses);
11061111
$r3$.ɵɵelementHostStyleProp(0, ctx.myHeightProp, "pt");
11071112
$r3$.ɵɵelementHostStyleProp(1, ctx.myWidthProp);
11081113
$r3$.ɵɵelementHostClassProp(0, ctx.myBarClass);
@@ -1166,7 +1171,8 @@ describe('compiler compliance: styling', () => {
11661171
$r3$.ɵɵelementEnd();
11671172
}
11681173
if (rf & 2) {
1169-
$r3$.ɵɵelementStylingMap(0, ctx.myClassExp, ctx.myStyleExp);
1174+
$r3$.ɵɵelementStyleMap(0, ctx.myStyleExp);
1175+
$r3$.ɵɵelementClassMap(0, ctx.myClassExp);
11701176
$r3$.ɵɵelementStyleProp(0, 0, ctx.myHeightExp, null, true);
11711177
$r3$.ɵɵelementClassProp(0, 0, ctx.myBarClassExp, true);
11721178
$r3$.ɵɵelementStylingApply(0);
@@ -1183,7 +1189,8 @@ describe('compiler compliance: styling', () => {
11831189
$r3$.ɵɵelementHostStyling(_c0, _c1, $r3$.ɵɵdefaultStyleSanitizer);
11841190
}
11851191
if (rf & 2) {
1186-
$r3$.ɵɵelementHostStylingMap(ctx.myClassExp, ctx.myStyleExp);
1192+
$r3$.ɵɵelementHostStyleMap(ctx.myStyleExp);
1193+
$r3$.ɵɵelementHostClassMap(ctx.myClassExp);
11871194
$r3$.ɵɵelementHostStyleProp(0, ctx.myWidthExp, null, true);
11881195
$r3$.ɵɵelementHostClassProp(0, ctx.myFooClassExp, true);
11891196
$r3$.ɵɵelementHostStylingApply();
@@ -1251,7 +1258,7 @@ describe('compiler compliance: styling', () => {
12511258
$r3$.ɵɵelementHostStyling();
12521259
}
12531260
if (rf & 2) {
1254-
$r3$.ɵɵelementHostStylingMap(ctx.myClassMap);
1261+
$r3$.ɵɵelementHostClassMap(ctx.myClassMap);
12551262
$r3$.ɵɵelementHostStylingApply();
12561263
}
12571264
}
@@ -1335,7 +1342,8 @@ describe('compiler compliance: styling', () => {
13351342
if (rf & 2) {
13361343
$r3$.ɵɵproperty("id", ctx.id, null, true);
13371344
$r3$.ɵɵproperty("title", ctx.title, null, true);
1338-
$r3$.ɵɵelementHostStylingMap(ctx.myClass, ctx.myStyle);
1345+
$r3$.ɵɵelementHostStyleMap(ctx.myStyle);
1346+
$r3$.ɵɵelementHostClassMap(ctx.myClass);
13391347
$r3$.ɵɵelementHostStylingApply();
13401348
}
13411349
}

packages/compiler/src/render3/r3_identifiers.ts

+8-3
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,9 @@ export class Identifiers {
5151

5252
static elementStyling: o.ExternalReference = {name: 'ɵɵelementStyling', moduleName: CORE};
5353

54-
static elementStylingMap: o.ExternalReference = {name: 'ɵɵelementStylingMap', moduleName: CORE};
54+
static elementStyleMap: o.ExternalReference = {name: 'ɵɵelementStyleMap', moduleName: CORE};
55+
56+
static elementClassMap: o.ExternalReference = {name: 'ɵɵelementClassMap', moduleName: CORE};
5557

5658
static elementStyleProp: o.ExternalReference = {name: 'ɵɵelementStyleProp', moduleName: CORE};
5759

@@ -62,8 +64,11 @@ export class Identifiers {
6264

6365
static elementHostStyling: o.ExternalReference = {name: 'ɵɵelementHostStyling', moduleName: CORE};
6466

65-
static elementHostStylingMap:
66-
o.ExternalReference = {name: 'ɵɵelementHostStylingMap', moduleName: CORE};
67+
static elementHostStyleMap:
68+
o.ExternalReference = {name: 'ɵɵelementHostStyleMap', moduleName: CORE};
69+
70+
static elementHostClassMap:
71+
o.ExternalReference = {name: 'ɵɵelementHostClassMap', moduleName: CORE};
6772

6873
static elementHostStyleProp:
6974
o.ExternalReference = {name: 'ɵɵelementHostStyleProp', moduleName: CORE};

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

+60-61
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,8 @@ interface BoundStylingEntry {
6161
* elementStyling(...)
6262
* }
6363
* if (updateMode) {
64-
* elementStylingMap(...)
64+
* elementStyleMap(...)
65+
* elementClassMap(...)
6566
* elementStyleProp(...)
6667
* elementClassProp(...)
6768
* elementStylingApp(...)
@@ -339,71 +340,65 @@ export class StylingBuilder {
339340
}
340341

341342
/**
342-
* Builds an instruction with all the expressions and parameters for `elementStylingMap`.
343+
* Builds an instruction with all the expressions and parameters for `elementClassMap`.
343344
*
344-
* The instruction data will contain all expressions for `elementStylingMap` to function
345-
* which include the `[style]` and `[class]` expression params (if they exist) as well as
346-
* the sanitizer and directive reference expression.
345+
* The instruction data will contain all expressions for `elementClassMap` to function
346+
* which includes the `[class]` expression params.
347347
*/
348-
buildElementStylingMapInstruction(valueConverter: ValueConverter): Instruction|null {
349-
if (this._classMapInput || this._styleMapInput) {
350-
const stylingInput = this._classMapInput ! || this._styleMapInput !;
351-
let totalBindingSlotsRequired = 0;
352-
353-
// these values must be outside of the update block so that they can
354-
// be evaluted (the AST visit call) during creation time so that any
355-
// pipes can be picked up in time before the template is built
356-
const mapBasedClassValue =
357-
this._classMapInput ? this._classMapInput.value.visit(valueConverter) : null;
358-
if (mapBasedClassValue instanceof Interpolation) {
359-
totalBindingSlotsRequired += mapBasedClassValue.expressions.length;
360-
}
361-
362-
const mapBasedStyleValue =
363-
this._styleMapInput ? this._styleMapInput.value.visit(valueConverter) : null;
364-
if (mapBasedStyleValue instanceof Interpolation) {
365-
totalBindingSlotsRequired += mapBasedStyleValue.expressions.length;
366-
}
348+
buildElementClassMapInstruction(valueConverter: ValueConverter): Instruction|null {
349+
if (this._classMapInput) {
350+
return this._buildMapBasedInstruction(valueConverter, true, this._classMapInput);
351+
}
352+
return null;
353+
}
367354

368-
const isHostBinding = this._directiveExpr;
369-
const reference = isHostBinding ? R3.elementHostStylingMap : R3.elementStylingMap;
355+
/**
356+
* Builds an instruction with all the expressions and parameters for `elementStyleMap`.
357+
*
358+
* The instruction data will contain all expressions for `elementStyleMap` to function
359+
* which includes the `[style]` expression params.
360+
*/
361+
buildElementStyleMapInstruction(valueConverter: ValueConverter): Instruction|null {
362+
if (this._styleMapInput) {
363+
return this._buildMapBasedInstruction(valueConverter, false, this._styleMapInput);
364+
}
365+
return null;
366+
}
370367

371-
return {
372-
sourceSpan: stylingInput.sourceSpan,
373-
reference,
374-
allocateBindingSlots: totalBindingSlotsRequired,
375-
buildParams: (convertFn: (value: any) => o.Expression) => {
376-
// HOST:
377-
// min params => elementHostStylingMap(classMap)
378-
// max params => elementHostStylingMap(classMap, styleMap)
379-
// Template:
380-
// min params => elementStylingMap(elmIndex, classMap)
381-
// max params => elementStylingMap(elmIndex, classMap, styleMap)
368+
private _buildMapBasedInstruction(
369+
valueConverter: ValueConverter, isClassBased: boolean, stylingInput: BoundStylingEntry) {
370+
let totalBindingSlotsRequired = 0;
382371

383-
const params: o.Expression[] = [];
384-
if (!isHostBinding) {
385-
params.push(this._elementIndexExpr);
386-
}
372+
// these values must be outside of the update block so that they can
373+
// be evaluated (the AST visit call) during creation time so that any
374+
// pipes can be picked up in time before the template is built
375+
const mapValue = stylingInput.value.visit(valueConverter);
376+
if (mapValue instanceof Interpolation) {
377+
totalBindingSlotsRequired += mapValue.expressions.length;
378+
}
387379

388-
let expectedNumberOfArgs = 0;
389-
if (mapBasedStyleValue) {
390-
expectedNumberOfArgs = 2;
391-
} else if (mapBasedClassValue) {
392-
// index and class = 2
393-
expectedNumberOfArgs = 1;
394-
}
380+
const isHostBinding = this._directiveExpr;
381+
let reference: o.ExternalReference;
382+
if (isClassBased) {
383+
reference = isHostBinding ? R3.elementHostClassMap : R3.elementClassMap;
384+
} else {
385+
reference = isHostBinding ? R3.elementHostStyleMap : R3.elementStyleMap;
386+
}
395387

396-
addParam(
397-
params, mapBasedClassValue, mapBasedClassValue ? convertFn(mapBasedClassValue) : null,
398-
1, expectedNumberOfArgs);
399-
addParam(
400-
params, mapBasedStyleValue, mapBasedStyleValue ? convertFn(mapBasedStyleValue) : null,
401-
2, expectedNumberOfArgs);
402-
return params;
388+
return {
389+
sourceSpan: stylingInput.sourceSpan,
390+
reference,
391+
allocateBindingSlots: totalBindingSlotsRequired,
392+
buildParams: (convertFn: (value: any) => o.Expression) => {
393+
const params: o.Expression[] = [];
394+
if (!isHostBinding) {
395+
params.push(this._elementIndexExpr);
403396
}
404-
};
405-
}
406-
return null;
397+
398+
params.push(convertFn(mapValue));
399+
return params;
400+
}
401+
};
407402
}
408403

409404
private _buildSingleInputs(
@@ -498,9 +493,13 @@ export class StylingBuilder {
498493
buildUpdateLevelInstructions(valueConverter: ValueConverter) {
499494
const instructions: Instruction[] = [];
500495
if (this.hasBindings) {
501-
const mapInstruction = this.buildElementStylingMapInstruction(valueConverter);
502-
if (mapInstruction) {
503-
instructions.push(mapInstruction);
496+
const styleMapInstruction = this.buildElementStyleMapInstruction(valueConverter);
497+
if (styleMapInstruction) {
498+
instructions.push(styleMapInstruction);
499+
}
500+
const classMapInstruction = this.buildElementClassMapInstruction(valueConverter);
501+
if (classMapInstruction) {
502+
instructions.push(classMapInstruction);
504503
}
505504
instructions.push(...this._buildStyleInputs(valueConverter));
506505
instructions.push(...this._buildClassInputs(valueConverter));

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

+2-2
Original file line numberDiff line numberDiff line change
@@ -686,8 +686,8 @@ export class TemplateDefinitionBuilder implements t.Visitor<void>, LocalResolver
686686

687687
// the code here will collect all update-level styling instructions and add them to the
688688
// update block of the template function AOT code. Instructions like `elementStyleProp`,
689-
// `elementStylingMap`, `elementClassProp` and `elementStylingApply` are all generated
690-
// and assign in the code below.
689+
// `elementStyleMap`, `elementClassMap`, `elementClassProp` and `elementStylingApply`
690+
// are all generated and assigned in the code below.
691691
stylingBuilder.buildUpdateLevelInstructions(this._valueConverter).forEach(instruction => {
692692
this._bindingSlots += instruction.allocateBindingSlots;
693693
this.processStylingInstruction(implicit, instruction, false);

packages/core/src/core_render3_private_export.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -111,14 +111,16 @@ export {
111111
ɵɵelementContainerStart,
112112
ɵɵelementContainerEnd,
113113
ɵɵelementStyling,
114-
ɵɵelementStylingMap,
114+
ɵɵelementStyleMap,
115+
ɵɵelementClassMap,
115116
ɵɵelementStyleProp,
116117
ɵɵelementStylingApply,
117118
ɵɵelementClassProp,
118119

119120
ɵɵelementHostAttrs,
121+
ɵɵelementHostClassMap,
122+
ɵɵelementHostStyleMap,
120123
ɵɵelementHostStyling,
121-
ɵɵelementHostStylingMap,
122124
ɵɵelementHostStyleProp,
123125
ɵɵelementHostClassProp,
124126
ɵɵelementHostStylingApply,

0 commit comments

Comments
 (0)