Skip to content

Commit 7555a46

Browse files
benleshjasonaden
authored andcommitted
refactor(ivy): add new attribute interpolation instructions (angular#30503)
PR Close angular#30503
1 parent 38d7ace commit 7555a46

File tree

8 files changed

+939
-6
lines changed

8 files changed

+939
-6
lines changed

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

+45
Original file line numberDiff line numberDiff line change
@@ -496,6 +496,51 @@ describe('compiler compliance: bindings', () => {
496496
expectEmit(result.source, template, 'Incorrect handling of interpolated properties');
497497
});
498498

499+
500+
it('should generate the proper update instructions for interpolated attributes', () => {
501+
const files: MockDirectory = getAppFiles(`
502+
<div attr.title="a{{one}}b{{two}}c{{three}}d{{four}}e{{five}}f{{six}}g{{seven}}h{{eight}}i{{nine}}j"></div>
503+
<div attr.title="a{{one}}b{{two}}c{{three}}d{{four}}e{{five}}f{{six}}g{{seven}}h{{eight}}i"></div>
504+
<div attr.title="a{{one}}b{{two}}c{{three}}d{{four}}e{{five}}f{{six}}g{{seven}}h"></div>
505+
<div attr.title="a{{one}}b{{two}}c{{three}}d{{four}}e{{five}}f{{six}}g"></div>
506+
<div attr.title="a{{one}}b{{two}}c{{three}}d{{four}}e{{five}}f"></div>
507+
<div attr.title="a{{one}}b{{two}}c{{three}}d{{four}}e"></div>
508+
<div attr.title="a{{one}}b{{two}}c{{three}}d"></div>
509+
<div attr.title="a{{one}}b{{two}}c"></div>
510+
<div attr.title="a{{one}}b"></div>
511+
<div attr.title="{{one}}"></div>
512+
`);
513+
514+
const template = `
515+
516+
if (rf & 2) {
517+
i0.Δselect(0);
518+
i0.ΔattributeInterpolateV("title", ["a", ctx.one, "b", ctx.two, "c", ctx.three, "d", ctx.four, "e", ctx.five, "f", ctx.six, "g", ctx.seven, "h", ctx.eight, "i", ctx.nine, "j"]);
519+
i0.Δselect(1);
520+
i0.ΔattributeInterpolate8("title", "a", ctx.one, "b", ctx.two, "c", ctx.three, "d", ctx.four, "e", ctx.five, "f", ctx.six, "g", ctx.seven, "h", ctx.eight, "i");
521+
i0.Δselect(2);
522+
i0.ΔattributeInterpolate7("title", "a", ctx.one, "b", ctx.two, "c", ctx.three, "d", ctx.four, "e", ctx.five, "f", ctx.six, "g", ctx.seven, "h");
523+
i0.Δselect(3);
524+
i0.ΔattributeInterpolate6("title", "a", ctx.one, "b", ctx.two, "c", ctx.three, "d", ctx.four, "e", ctx.five, "f", ctx.six, "g");
525+
i0.Δselect(4);
526+
i0.ΔattributeInterpolate5("title", "a", ctx.one, "b", ctx.two, "c", ctx.three, "d", ctx.four, "e", ctx.five, "f");
527+
i0.Δselect(5);
528+
i0.ΔattributeInterpolate4("title", "a", ctx.one, "b", ctx.two, "c", ctx.three, "d", ctx.four, "e");
529+
i0.Δselect(6);
530+
i0.ΔattributeInterpolate3("title", "a", ctx.one, "b", ctx.two, "c", ctx.three, "d");
531+
i0.Δselect(7);
532+
i0.ΔattributeInterpolate2("title", "a", ctx.one, "b", ctx.two, "c");
533+
i0.Δselect(8);
534+
i0.ΔattributeInterpolate1("title", "a", ctx.one, "b");
535+
i0.Δselect(9);
536+
i0.ΔattributeInterpolate("title", ctx.one);
537+
}
538+
539+
`;
540+
const result = compile(files, angularFiles);
541+
expectEmit(result.source, template, 'Incorrect handling of interpolated properties');
542+
});
543+
499544
it('should keep local ref for host element', () => {
500545
const files: MockDirectory = getAppFiles(`
501546
<b ngNonBindable #myRef id="my-id">

packages/compiler/src/render3/r3_identifiers.ts

+21
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,27 @@ export class Identifiers {
4343

4444
static attribute: o.ExternalReference = {name: 'ɵɵattribute', moduleName: CORE};
4545

46+
static attributeInterpolate:
47+
o.ExternalReference = {name: 'ɵɵattributeInterpolate', moduleName: CORE};
48+
static attributeInterpolate1:
49+
o.ExternalReference = {name: 'ɵɵattributeInterpolate1', moduleName: CORE};
50+
static attributeInterpolate2:
51+
o.ExternalReference = {name: 'ɵɵattributeInterpolate2', moduleName: CORE};
52+
static attributeInterpolate3:
53+
o.ExternalReference = {name: 'ɵɵattributeInterpolate3', moduleName: CORE};
54+
static attributeInterpolate4:
55+
o.ExternalReference = {name: 'ɵɵattributeInterpolate4', moduleName: CORE};
56+
static attributeInterpolate5:
57+
o.ExternalReference = {name: 'ɵɵattributeInterpolate5', moduleName: CORE};
58+
static attributeInterpolate6:
59+
o.ExternalReference = {name: 'ɵɵattributeInterpolate6', moduleName: CORE};
60+
static attributeInterpolate7:
61+
o.ExternalReference = {name: 'ɵɵattributeInterpolate7', moduleName: CORE};
62+
static attributeInterpolate8:
63+
o.ExternalReference = {name: 'ɵɵattributeInterpolate8', moduleName: CORE};
64+
static attributeInterpolateV:
65+
o.ExternalReference = {name: 'ɵɵattributeInterpolateV', moduleName: CORE};
66+
4667
static classProp: o.ExternalReference = {name: 'ɵɵclassProp', moduleName: CORE};
4768

4869
static elementContainerStart:

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

+35-6
Original file line numberDiff line numberDiff line change
@@ -772,12 +772,12 @@ export class TemplateDefinitionBuilder implements t.Visitor<void>, LocalResolver
772772
} else if (inputType === BindingType.Attribute) {
773773
if (value instanceof Interpolation) {
774774
// attr.name="{{value}}" and friends
775-
this.updateInstruction(elementIndex, input.sourceSpan, R3.elementAttribute, () => {
776-
return [
777-
o.literal(elementIndex), o.literal(attrName),
778-
this.convertPropertyBinding(implicit, value), ...params
779-
];
780-
});
775+
this.updateInstruction(
776+
elementIndex, input.sourceSpan, getAttributeInterpolationExpression(value),
777+
() =>
778+
[o.literal(attrName),
779+
...this.getUpdateInstructionArguments(o.variable(CONTEXT_NAME), value),
780+
...params]);
781781
} else {
782782
// [attr.name]="value"
783783
this.updateInstruction(elementIndex, input.sourceSpan, R3.attribute, () => {
@@ -1695,6 +1695,35 @@ function getPropertyInterpolationExpression(interpolation: Interpolation) {
16951695
}
16961696
}
16971697

1698+
/**
1699+
* Gets the instruction to generate for an interpolated attribute
1700+
* @param interpolation An Interpolation AST
1701+
*/
1702+
function getAttributeInterpolationExpression(interpolation: Interpolation) {
1703+
switch (getInterpolationArgsLength(interpolation)) {
1704+
case 1:
1705+
return R3.attributeInterpolate;
1706+
case 3:
1707+
return R3.attributeInterpolate1;
1708+
case 5:
1709+
return R3.attributeInterpolate2;
1710+
case 7:
1711+
return R3.attributeInterpolate3;
1712+
case 9:
1713+
return R3.attributeInterpolate4;
1714+
case 11:
1715+
return R3.attributeInterpolate5;
1716+
case 13:
1717+
return R3.attributeInterpolate6;
1718+
case 15:
1719+
return R3.attributeInterpolate7;
1720+
case 17:
1721+
return R3.attributeInterpolate8;
1722+
default:
1723+
return R3.attributeInterpolateV;
1724+
}
1725+
}
1726+
16981727
/**
16991728
* Gets the number of arguments expected to be passed to a generated instruction in the case of
17001729
* interpolation instructions.

packages/core/src/core_render3_private_export.ts

+10
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,16 @@
99
// clang-format off
1010
export {
1111
ɵɵattribute,
12+
ɵɵattributeInterpolate,
13+
ɵɵattributeInterpolate1,
14+
ɵɵattributeInterpolate2,
15+
ɵɵattributeInterpolate3,
16+
ɵɵattributeInterpolate4,
17+
ɵɵattributeInterpolate5,
18+
ɵɵattributeInterpolate6,
19+
ɵɵattributeInterpolate7,
20+
ɵɵattributeInterpolate8,
21+
ɵɵattributeInterpolateV,
1222
ɵɵdefineBase,
1323
ɵɵdefineComponent,
1424
ɵɵdefineDirective,

packages/core/src/render3/index.ts

+12
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,19 @@ export {
2323
tick,
2424

2525
ɵɵallocHostVars,
26+
2627
ɵɵattribute,
28+
ɵɵattributeInterpolate,
29+
ɵɵattributeInterpolate1,
30+
ɵɵattributeInterpolate2,
31+
ɵɵattributeInterpolate3,
32+
ɵɵattributeInterpolate4,
33+
ɵɵattributeInterpolate5,
34+
ɵɵattributeInterpolate6,
35+
ɵɵattributeInterpolate7,
36+
ɵɵattributeInterpolate8,
37+
ɵɵattributeInterpolateV,
38+
2739
ɵɵbind,
2840
ɵɵclassMap,
2941
ɵɵclassProp,

packages/core/src/render3/instructions/all.ts

+1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
*/
2828
export * from './alloc_host_vars';
2929
export * from './attribute';
30+
export * from './attribute_interpolation';
3031
export * from './change_detection';
3132
export * from './container';
3233
export * from './storage';

0 commit comments

Comments
 (0)