fix(ivy): ensure animation @trigger ordering is correctly delivered to the renderer (#28165)

In Ivy when elements are created a series of static attribute names are provided
over to the construction instruction of that element. Static attribute names
include non-binding attribues (like `<div selected>`) as well as animation bindings
that do not have a RHS value (like `<div @foo>`). Because of this distinction,
value-less animation triggers are rendered first before value-full animation
bindings are and this improper ordering has caused various existing tests to fail.
This patch ensures that animation bindings are evaluated in the order that they
exist within the HTML template code (or host binding code).

PR Close #28165
This commit is contained in:
Matias Niemelä
2019-01-15 13:46:15 -08:00
committed by Alex Rickabaugh
parent 0d6913f037
commit e172e97e13
4 changed files with 141 additions and 154 deletions

View File

@ -122,7 +122,7 @@ describe('r3_view_compiler', () => {
});
describe('animations', () => {
it('should keep @attr but suppress [@attr]', () => {
it('should not register any @attr attributes as static attributes', () => {
const files: MockDirectory = {
app: {
'example.ts': `
@ -130,7 +130,7 @@ describe('r3_view_compiler', () => {
@Component({
selector: 'my-app',
template: '<div @attrOnly [@myAnimation]="exp"></div>'
template: '<div @attr [@binding]="exp"></div>'
})
export class MyApp {
}
@ -141,14 +141,14 @@ describe('r3_view_compiler', () => {
};
const template = `
const _c0 = ["@attrOnly", ""];
// ...
template: function MyApp_Template(rf, ctx) {
if (rf & 1) {
$i0$.ɵelement(0, "div", _c0);
// ...
$i0$.ɵelement(0, "div");
}
if (rf & 2) {
$i0$.ɵelementProperty(0, "@attr", …);
$i0$.ɵelementProperty(0, "@binding", …);
}
// ...
}`;
const result = compile(files, angularFiles);
expectEmit(result.source, template, 'Incorrect initialization attributes');
@ -173,14 +173,12 @@ describe('r3_view_compiler', () => {
};
const template = `
const _c0 = [3, "@mySelector"];
// ...
template: function MyApp_Template(rf, ctx) {
if (rf & 1) {
$i0$.ɵelementStart(0, "div", _c0);
// ...
$i0$.ɵelementStart(0, "div");
$i0$.ɵelementProperty(0, "@mySelector", …);
}
// ...
}`;
const result = compile(files, angularFiles);
expectEmit(result.source, template, 'Incorrect initialization attributes');

View File

@ -214,21 +214,21 @@ describe('compiler compliance: styling', () => {
};
const template = `
const $e1_attrs$ = ["@bar", ""];
const $e2_attrs$ = ["@baz", ""];
MyComponent.ngComponentDef = $r3$.ɵdefineComponent({
consts: 3,
vars: 1,
vars: 3,
template: function MyComponent_Template(rf, $ctx$) {
if (rf & 1) {
$r3$.ɵelement(0, "div");
$r3$.ɵelement(1, "div", $e1_attrs$);
$r3$.ɵelement(2, "div", $e2_attrs$);
$r3$.ɵelement(1, "div");
$r3$.ɵelement(2, "div");
}
if (rf & 2) {
$r3$.ɵelementProperty(0, "@foo", $r3$.ɵbind(ctx.exp));
$r3$.ɵelementProperty(1, "@bar", $r3$.ɵbind(undefined));
$r3$.ɵelementProperty(2, "@baz", $r3$.ɵbind(undefined));
}
},
encapsulation: 2
@ -280,7 +280,7 @@ describe('compiler compliance: styling', () => {
vars: 1,
template: function MyComponent_Template(rf, ctx) {
if (rf & 1) {
$r3$.ɵelementStart(0, "div", _c0);
$r3$.ɵelementStart(0, "div");
$r3$.ɵlistener("@myAnimation.start", function MyComponent_Template_div_animation_myAnimation_start_0_listener($event) { return ctx.onStart($event); });
$r3$.ɵlistener("@myAnimation.done", function MyComponent_Template_div_animation_myAnimation_done_0_listener($event) { return ctx.onDone($event); });
$r3$.ɵelementEnd();