fix(ivy): ensure select(n)
instructions are always generated around style/class bindings (#30311)
Prior to this patch, the `select(n)` instruction would only be generated when property bindings are encountered which meant that styling-related bindings were skipped. This patch ensures that all styling-related bindings (i.e. class and style bindings) are always prepended with a `select()` instruction prior to being generated in AOT. PR Close #30311
This commit is contained in:

committed by
Kara Erickson

parent
bd37622050
commit
345a3cd9aa
@ -506,6 +506,7 @@ describe('compiler compliance', () => {
|
||||
$r3$.ɵɵelementEnd();
|
||||
}
|
||||
if (rf & 2) {
|
||||
$r3$.ɵɵselect(0);
|
||||
$r3$.ɵɵelementStyleProp(0, 0, ctx.color);
|
||||
$r3$.ɵɵelementClassProp(0, 0, ctx.error);
|
||||
$r3$.ɵɵelementStylingApply(0);
|
||||
|
@ -389,6 +389,7 @@ describe('compiler compliance: styling', () => {
|
||||
$r3$.ɵɵelementEnd();
|
||||
}
|
||||
if (rf & 2) {
|
||||
$r3$.ɵɵselect(0);
|
||||
$r3$.ɵɵelementStyleMap(0, $ctx$.myStyleExp);
|
||||
$r3$.ɵɵelementStylingApply(0);
|
||||
}
|
||||
@ -454,6 +455,7 @@ describe('compiler compliance: styling', () => {
|
||||
$r3$.ɵɵelementEnd();
|
||||
}
|
||||
if (rf & 2) {
|
||||
$r3$.ɵɵselect(0);
|
||||
$r3$.ɵɵelementClassMap(0, $r3$.ɵɵinterpolation1("foo foo-", $ctx$.fooId, ""));
|
||||
$r3$.ɵɵelementStylingApply(0);
|
||||
}
|
||||
@ -468,6 +470,7 @@ describe('compiler compliance: styling', () => {
|
||||
$r3$.ɵɵelementEnd();
|
||||
}
|
||||
if (rf & 2) {
|
||||
$r3$.ɵɵselect(0);
|
||||
$r3$.ɵɵelementClassMap(0, $r3$.ɵɵinterpolation2("foo foo-", $ctx$.fooId, "-", $ctx$.fooUsername, ""));
|
||||
$r3$.ɵɵelementStylingApply(0);
|
||||
}
|
||||
@ -482,6 +485,7 @@ describe('compiler compliance: styling', () => {
|
||||
$r3$.ɵɵelementEnd();
|
||||
}
|
||||
if (rf & 2) {
|
||||
$r3$.ɵɵselect(0);
|
||||
$r3$.ɵɵelementClassMap(0, $ctx$.exp);
|
||||
$r3$.ɵɵelementStylingApply(0);
|
||||
}
|
||||
@ -538,11 +542,11 @@ describe('compiler compliance: styling', () => {
|
||||
$r3$.ɵɵelementEnd();
|
||||
}
|
||||
if (rf & 2) {
|
||||
$r3$.ɵɵselect(0);
|
||||
$r3$.ɵɵelementStyleMap(0, $ctx$.myStyleExp);
|
||||
$r3$.ɵɵelementStyleProp(0, 0, $ctx$.myWidth);
|
||||
$r3$.ɵɵelementStyleProp(0, 1, $ctx$.myHeight);
|
||||
$r3$.ɵɵelementStylingApply(0);
|
||||
$r3$.ɵɵselect(0);
|
||||
$r3$.ɵɵelementAttribute(0, "style", $r3$.ɵɵbind("border-width: 10px"), $r3$.ɵɵsanitizeStyle);
|
||||
}
|
||||
},
|
||||
@ -598,6 +602,7 @@ describe('compiler compliance: styling', () => {
|
||||
$r3$.ɵɵelementEnd();
|
||||
}
|
||||
if (rf & 2) {
|
||||
$r3$.ɵɵselect(0);
|
||||
$r3$.ɵɵelementStyleProp(0, 0, ctx.myImage);
|
||||
$r3$.ɵɵelementStylingApply(0);
|
||||
}
|
||||
@ -639,6 +644,7 @@ describe('compiler compliance: styling', () => {
|
||||
$r3$.ɵɵelementEnd();
|
||||
}
|
||||
if (rf & 2) {
|
||||
$r3$.ɵɵselect(0);
|
||||
$r3$.ɵɵelementStyleProp(0, 0, 12, "px");
|
||||
$r3$.ɵɵelementStylingApply(0);
|
||||
}
|
||||
@ -704,6 +710,7 @@ describe('compiler compliance: styling', () => {
|
||||
$r3$.ɵɵelementEnd();
|
||||
}
|
||||
if (rf & 2) {
|
||||
$r3$.ɵɵselect(0);
|
||||
$r3$.ɵɵelementClassMap(0,$ctx$.myClassExp);
|
||||
$r3$.ɵɵelementStylingApply(0);
|
||||
}
|
||||
@ -760,11 +767,11 @@ describe('compiler compliance: styling', () => {
|
||||
$r3$.ɵɵelementEnd();
|
||||
}
|
||||
if (rf & 2) {
|
||||
$r3$.ɵɵselect(0);
|
||||
$r3$.ɵɵelementClassMap(0, $ctx$.myClassExp);
|
||||
$r3$.ɵɵelementClassProp(0, 0, $ctx$.yesToApple);
|
||||
$r3$.ɵɵelementClassProp(0, 1, $ctx$.yesToOrange);
|
||||
$r3$.ɵɵelementStylingApply(0);
|
||||
$r3$.ɵɵselect(0);
|
||||
$r3$.ɵɵelementAttribute(0, "class", $r3$.ɵɵbind("banana"));
|
||||
}
|
||||
},
|
||||
@ -853,7 +860,7 @@ describe('compiler compliance: styling', () => {
|
||||
});
|
||||
|
||||
describe('[style] mixed with [class]', () => {
|
||||
it('should combine [style] and [class] bindings into a single instruction', () => {
|
||||
it('should split [style] and [class] bindings into a separate instructions', () => {
|
||||
const files = {
|
||||
app: {
|
||||
'spec.ts': `
|
||||
@ -882,6 +889,7 @@ describe('compiler compliance: styling', () => {
|
||||
$r3$.ɵɵelementEnd();
|
||||
}
|
||||
if (rf & 2) {
|
||||
$r3$.ɵɵselect(0);
|
||||
$r3$.ɵɵelementStyleMap(0, $ctx$.myStyleExp);
|
||||
$r3$.ɵɵelementClassMap(0, $ctx$.myClassExp);
|
||||
$r3$.ɵɵelementStylingApply(0);
|
||||
@ -925,6 +933,7 @@ describe('compiler compliance: styling', () => {
|
||||
$r3$.ɵɵelementEnd();
|
||||
}
|
||||
if (rf & 2) {
|
||||
$r3$.ɵɵselect(0);
|
||||
$r3$.ɵɵelementStyleMap(0, $r3$.ɵɵpipeBind1(1, 0, $ctx$.myStyleExp));
|
||||
$r3$.ɵɵelementClassMap(0, $r3$.ɵɵpipeBind1(2, 2, $ctx$.myClassExp));
|
||||
$r3$.ɵɵelementStylingApply(0);
|
||||
@ -982,6 +991,7 @@ describe('compiler compliance: styling', () => {
|
||||
$r3$.ɵɵelementEnd();
|
||||
}
|
||||
if (rf & 2) {
|
||||
$r3$.ɵɵselect(0);
|
||||
$r3$.ɵɵelementStyleMap(0, $r3$.ɵɵpipeBind2(1, 1, $ctx$.myStyleExp, 1000));
|
||||
$r3$.ɵɵelementClassMap(0, $e2_styling$);
|
||||
$r3$.ɵɵelementStyleProp(0, 0, $r3$.ɵɵpipeBind2(2, 4, $ctx$.barExp, 3000));
|
||||
@ -997,6 +1007,59 @@ describe('compiler compliance: styling', () => {
|
||||
const result = compile(files, angularFiles);
|
||||
expectEmit(result.source, template, 'Incorrect template');
|
||||
});
|
||||
|
||||
it('should always generate select() statements before any styling instructions', () => {
|
||||
const files = {
|
||||
app: {
|
||||
'spec.ts': `
|
||||
import {Component, NgModule} from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'my-component',
|
||||
template: \`
|
||||
<div [style.width]="w1"></div>
|
||||
<div [style.height]="h1"></div>
|
||||
<div [class.active]="a1"></div>
|
||||
<div [class.removed]="r1"></div>
|
||||
\`
|
||||
})
|
||||
export class MyComponent {
|
||||
w1 = '100px';
|
||||
h1 = '100px';
|
||||
a1 = true;
|
||||
r1 = true;
|
||||
}
|
||||
|
||||
@NgModule({declarations: [MyComponent]})
|
||||
export class MyModule {}
|
||||
`
|
||||
}
|
||||
};
|
||||
|
||||
const template = `
|
||||
…
|
||||
template: function MyComponent_Template(rf, $ctx$) {
|
||||
…
|
||||
if (rf & 2) {
|
||||
$r3$.ɵɵselect(0);
|
||||
$r3$.ɵɵelementStyleProp(0, 0, $ctx$.w1);
|
||||
$r3$.ɵɵelementStylingApply(0);
|
||||
$r3$.ɵɵselect(1);
|
||||
$r3$.ɵɵelementStyleProp(1, 0, $ctx$.h1);
|
||||
$r3$.ɵɵelementStylingApply(1);
|
||||
$r3$.ɵɵselect(2);
|
||||
$r3$.ɵɵelementClassProp(2, 0, $ctx$.a1);
|
||||
$r3$.ɵɵelementStylingApply(2);
|
||||
$r3$.ɵɵselect(3);
|
||||
$r3$.ɵɵelementClassProp(3, 0, $ctx$.r1);
|
||||
$r3$.ɵɵelementStylingApply(3);
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const result = compile(files, angularFiles);
|
||||
expectEmit(result.source, template, 'Incorrect template');
|
||||
});
|
||||
});
|
||||
|
||||
describe('@Component host styles/classes', () => {
|
||||
@ -1171,6 +1234,7 @@ describe('compiler compliance: styling', () => {
|
||||
$r3$.ɵɵelementEnd();
|
||||
}
|
||||
if (rf & 2) {
|
||||
$r3$.ɵɵselect(0);
|
||||
$r3$.ɵɵelementStyleMap(0, ctx.myStyleExp);
|
||||
$r3$.ɵɵelementClassMap(0, ctx.myClassExp);
|
||||
$r3$.ɵɵelementStyleProp(0, 0, ctx.myHeightExp, null, true);
|
||||
|
Reference in New Issue
Block a user