fix(ivy): merge static style rendering across elements, directives and components (#27661)

PR Close #27661
This commit is contained in:
Matias Niemelä
2018-12-13 15:51:47 -08:00
parent 0b3ae3d70c
commit 13eb57a59f
39 changed files with 3493 additions and 1588 deletions

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {AttributeMarker, InitialStylingFlags} from '@angular/compiler/src/core';
import {AttributeMarker} from '@angular/compiler/src/core';
import {setup} from '@angular/compiler/test/aot/test_util';
import {compile, expectEmit} from './mock_compile';
@ -48,17 +48,15 @@ describe('compiler compliance', () => {
// The template should look like this (where IDENT is a wild card for an identifier):
const template = `
const $c1$ = ["title", "Hello"];
const $c2$ = ["my-app", ${InitialStylingFlags.VALUES_MODE}, "my-app", true];
const $c3$ = ["cx", "20", "cy", "30", "r", "50"];
const $c1$ = ["title", "Hello", ${AttributeMarker.Classes}, "my-app"];
const $c2$ = ["cx", "20", "cy", "30", "r", "50"];
template: function MyComponent_Template(rf, ctx) {
if (rf & 1) {
$r3$.ɵelementStart(0, "div", $c1$);
$r3$.ɵelementStyling($c2$);
$r3$.ɵnamespaceSVG();
$r3$.ɵelementStart(1, "svg");
$r3$.ɵelement(2, "circle", $c3$);
$r3$.ɵelement(2, "circle", $c2$);
$r3$.ɵelementEnd();
$r3$.ɵnamespaceHTML();
$r3$.ɵelementStart(3, "p");
@ -100,13 +98,11 @@ describe('compiler compliance', () => {
// The template should look like this (where IDENT is a wild card for an identifier):
const template = `
const $c1$ = ["title", "Hello"];
const $c2$ = ["my-app", ${InitialStylingFlags.VALUES_MODE}, "my-app", true];
const $c1$ = ["title", "Hello", ${AttributeMarker.Classes}, "my-app"];
template: function MyComponent_Template(rf, ctx) {
if (rf & 1) {
$r3$.ɵelementStart(0, "div", $c1$);
$r3$.ɵelementStyling($c2$);
$r3$.ɵnamespaceMathML();
$r3$.ɵelementStart(1, "math");
$r3$.ɵelement(2, "infinity");
@ -150,13 +146,11 @@ describe('compiler compliance', () => {
// The template should look like this (where IDENT is a wild card for an identifier):
const template = `
const $c1$ = ["title", "Hello"];
const $c2$ = ["my-app", ${InitialStylingFlags.VALUES_MODE}, "my-app", true];
const $c1$ = ["title", "Hello", ${AttributeMarker.Classes}, "my-app"];
template: function MyComponent_Template(rf, ctx) {
if (rf & 1) {
$r3$.ɵelementStart(0, "div", $c1$);
$r3$.ɵelementStyling($c2$);
$r3$.ɵtext(1, "Hello ");
$r3$.ɵelementStart(2, "b");
$r3$.ɵtext(3, "World");
@ -486,8 +480,8 @@ describe('compiler compliance', () => {
const factory =
'factory: function MyComponent_Factory(t) { return new (t || MyComponent)(); }';
const template = `
const _c0 = ["error"];
const _c1 = ["background-color"];
const $e0_classBindings$ = ["error"];
const $e0_styleBindings$ = ["background-color"];
MyComponent.ngComponentDef = i0.ɵdefineComponent({type:MyComponent,selectors:[["my-component"]],
factory: function MyComponent_Factory(t){
@ -498,7 +492,7 @@ describe('compiler compliance', () => {
template: function MyComponent_Template(rf,ctx){
if (rf & 1) {
$r3$.ɵelementStart(0, "div");
$r3$.ɵelementStyling(_c0, _c1);
$r3$.ɵelementStyling($e0_classBindings$, $e0_styleBindings$);
$r3$.ɵelementEnd();
}
if (rf & 2) {
@ -1204,7 +1198,7 @@ describe('compiler compliance', () => {
}
};
const output = `
const $_c0$ = [1, "ngIf"];
const $_c0$ = [${AttributeMarker.SelectOnly}, "ngIf"];
const $_c1$ = ["id", "second"];
function Cmp_div_Template_0(rf, ctx) { if (rf & 1) {
$r3$.ɵelementStart(0, "div", $_c1$);
@ -1310,7 +1304,6 @@ describe('compiler compliance', () => {
const {source} = compile(files, angularFiles);
expectEmit(source, output, 'Invalid content projection instructions generated');
});
});
describe('queries', () => {

View File

@ -236,7 +236,7 @@ describe('compiler compliance: directives', () => {
const MyComponentDefinition = `
const $_c0$ = [1, "ngIf"];
const $_c0$ = [${AttributeMarker.SelectOnly}, "ngIf"];
const $_c1$ = ["directiveA", ""];
function MyComponent_ng_container_Template_0(rf, ctx) {
if (rf & 1) {

View File

@ -6,6 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {AttributeMarker} from '@angular/compiler/src/core';
import {setup} from '@angular/compiler/test/aot/test_util';
import {DEFAULT_INTERPOLATION_CONFIG, InterpolationConfig} from '../../../compiler/src/compiler';
@ -393,7 +394,7 @@ describe('i18n support in the view compiler', () => {
`;
const output = String.raw `
const $_c0$ = ["ngFor", "", 1, "ngForOf"];
const $_c0$ = ["ngFor", "", ${AttributeMarker.SelectOnly}, "ngForOf"];
/**
* @desc d
* @meaning m
@ -522,7 +523,7 @@ describe('i18n support in the view compiler', () => {
`;
const output = String.raw `
const $_c0$ = ["ngFor", "", 1, "ngForOf"];
const $_c0$ = ["ngFor", "", ${AttributeMarker.SelectOnly}, "ngForOf"];
/**
* @desc d
* @meaning m
@ -922,7 +923,7 @@ describe('i18n support in the view compiler', () => {
`;
const output = String.raw `
const $_c0$ = [1, "ngIf"];
const $_c0$ = [${AttributeMarker.SelectOnly}, "ngIf"];
const $MSG_EXTERNAL_7679414751795588050$$APP_SPEC_TS__1$ = goog.getMsg(" Some other content {$interpolation} {$startTagDiv} More nested levels with bindings {$interpolation_1} {$closeTagDiv}", {
"interpolation": "\uFFFD0\uFFFD",
"startTagDiv": "\uFFFD#3\uFFFD",
@ -976,7 +977,7 @@ describe('i18n support in the view compiler', () => {
const output = String.raw `
const $_c0$ = ["src", "logo.png"];
const $_c1$ = [1, "ngIf"];
const $_c1$ = [${AttributeMarker.SelectOnly}, "ngIf"];
function MyComponent_img_Template_1(rf, ctx) {
if (rf & 1) {
$r3$.ɵelement(0, "img", $_c0$);
@ -1043,7 +1044,7 @@ describe('i18n support in the view compiler', () => {
`;
const output = String.raw `
const $_c0$ = [1, "ngIf"];
const $_c0$ = [${AttributeMarker.SelectOnly}, "ngIf"];
function MyComponent_div_div_Template_4(rf, ctx) {
if (rf & 1) {
$r3$.ɵi18nStart(0, $I18N_EXTERNAL_1221890473527419724$$APP_SPEC_TS_0$, 2);
@ -1136,7 +1137,7 @@ describe('i18n support in the view compiler', () => {
`;
const output = String.raw `
const $_c0$ = [1, "ngIf"];
const $_c0$ = [${AttributeMarker.SelectOnly}, "ngIf"];
const $MSG_EXTERNAL_119975189388320493$$APP_SPEC_TS__1$ = goog.getMsg("Some other content {$startTagSpan}{$interpolation}{$closeTagSpan}", {
"startTagSpan": "\uFFFD#2\uFFFD",
"interpolation": "\uFFFD0\uFFFD",
@ -1259,23 +1260,21 @@ describe('i18n support in the view compiler', () => {
`;
const output = String.raw `
const $_c0$ = ["myClass", 1, "myClass", true];
const $_c0$ = [${AttributeMarker.Classes}, "myClass"];
const $MSG_EXTERNAL_5295701706185791735$$APP_SPEC_TS_0$ = goog.getMsg("Text #1");
const $_c1$ = ["padding", 1, "padding", "10px"];
const $_c1$ = [${AttributeMarker.Styles}, "padding", "10px"];
const $MSG_EXTERNAL_4722270221386399294$$APP_SPEC_TS_2$ = goog.getMsg("Text #2");
consts: 4,
vars: 0,
template: function MyComponent_Template(rf, ctx) {
if (rf & 1) {
$r3$.ɵelementStart(0, "span");
$r3$.ɵelementStart(0, "span", $_c0$);
$r3$.ɵi18nStart(1, $MSG_EXTERNAL_5295701706185791735$$APP_SPEC_TS_0$);
$r3$.ɵelementStyling($_c0$);
$r3$.ɵi18nEnd();
$r3$.ɵelementEnd();
$r3$.ɵelementStart(2, "span");
$r3$.ɵelementStart(2, "span", $_c1$);
$r3$.ɵi18nStart(3, $MSG_EXTERNAL_4722270221386399294$$APP_SPEC_TS_2$);
$r3$.ɵelementStyling(null, $_c1$);
$r3$.ɵi18nEnd();
$r3$.ɵelementEnd();
}
@ -1701,7 +1700,7 @@ describe('i18n support in the view compiler', () => {
const $I18N_EXTERNAL_7842238767399919809$$APP_SPEC_TS_0$ = $r3$.ɵi18nPostprocess($MSG_EXTERNAL_7842238767399919809$$APP_SPEC_TS_0$, {
"VAR_SELECT": "\uFFFD0\uFFFD"
});
const $_c0$ = [1, "ngIf"];
const $_c0$ = [${AttributeMarker.SelectOnly}, "ngIf"];
const $_c1$ = ["title", "icu only"];
const $MSG_EXTERNAL_8806993169187953163$$APP_SPEC_TS__3$ = goog.getMsg("{VAR_SELECT, select, 10 {ten} 20 {twenty} other {other}}");
const $I18N_EXTERNAL_8806993169187953163$$APP_SPEC_TS__3$ = $r3$.ɵi18nPostprocess($MSG_EXTERNAL_8806993169187953163$$APP_SPEC_TS__3$, {
@ -1942,7 +1941,7 @@ describe('i18n support in the view compiler', () => {
const $I18N_APP_SPEC_TS_2$ = $r3$.ɵi18nPostprocess($MSG_APP_SPEC_TS_2$, {
"VAR_SELECT": "\uFFFD1\uFFFD"
});
const $_c3$ = [1, "ngIf"];
const $_c3$ = [${AttributeMarker.SelectOnly}, "ngIf"];
const $MSG_APP_SPEC_TS__4$ = goog.getMsg("{VAR_SELECT, select, male {male} female {female} other {other}}");
const $I18N_APP_SPEC_TS__4$ = $r3$.ɵi18nPostprocess($MSG_APP_SPEC_TS__4$, {
"VAR_SELECT": "\uFFFD0:1\uFFFD"
@ -2050,7 +2049,7 @@ describe('i18n support in the view compiler', () => {
const $I18N_EXTERNAL_7842238767399919809$$APP_SPEC_TS_1$ = $r3$.ɵi18nPostprocess($MSG_EXTERNAL_7842238767399919809$$APP_SPEC_TS_1$, {
"VAR_SELECT": "\uFFFD0\uFFFD"
});
const $_c0$ = [1, "ngIf"];
const $_c0$ = [${AttributeMarker.SelectOnly}, "ngIf"];
const $MSG_EXTERNAL_7068143081688428291$$APP_SPEC_TS__3$ = goog.getMsg("{VAR_SELECT, select, 10 {ten} 20 {twenty} 30 {thirty} other {other}}");
const $I18N_EXTERNAL_7068143081688428291$$APP_SPEC_TS__3$ = $r3$.ɵi18nPostprocess($MSG_EXTERNAL_7068143081688428291$$APP_SPEC_TS__3$, {
"VAR_SELECT": "\uFFFD0:1\uFFFD"
@ -2113,7 +2112,7 @@ describe('i18n support in the view compiler', () => {
const $I18N_EXTERNAL_7825031864601787094$$APP_SPEC_TS_1$ = $r3$.ɵi18nPostprocess($MSG_EXTERNAL_7825031864601787094$$APP_SPEC_TS_1$, {
"VAR_SELECT": "\uFFFD0\uFFFD"
});
const $_c0$ = [1, "ngIf"];
const $_c0$ = [${AttributeMarker.SelectOnly}, "ngIf"];
const $MSG_EXTERNAL_2310343208266678305$$APP_SPEC_TS__3$ = goog.getMsg("{VAR_SELECT, select, 10 {ten} 20 {twenty} 30 {thirty} other {other: {$interpolation}}}", {
"interpolation": "\uFFFD1:1\uFFFD"
});

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {AttributeMarker, InitialStylingFlags, ViewEncapsulation} from '@angular/compiler/src/core';
import {AttributeMarker, ViewEncapsulation} from '@angular/compiler/src/core';
import {setup} from '@angular/compiler/test/aot/test_util';
import {compile, expectEmit} from './mock_compile';
@ -366,8 +366,8 @@ describe('compiler compliance: styling', () => {
};
const template = `
const $e0_attrs$ = [${AttributeMarker.SelectOnly}, "style"];
const $e0_styling$ = ["opacity","width","height",${InitialStylingFlags.VALUES_MODE},"opacity","1"];
const $_c0$ = [${AttributeMarker.Styles}, "opacity", "1", ${AttributeMarker.SelectOnly}, "style"];
const $_c1$ = ["width", "height"];
MyComponent.ngComponentDef = $r3$.ɵdefineComponent({
type: MyComponent,
@ -379,14 +379,14 @@ describe('compiler compliance: styling', () => {
vars: 1,
template: function MyComponent_Template(rf, $ctx$) {
if (rf & 1) {
$r3$.ɵelementStart(0, "div", $e0_attrs$);
$r3$.ɵelementStyling(null, $e0_styling$, $r3$.ɵdefaultStyleSanitizer);
$r3$.ɵelementStart(0, "div", $_c0$);
$r3$.ɵelementStyling(null, $_c1$, $r3$.ɵdefaultStyleSanitizer);
$r3$.ɵelementEnd();
}
if (rf & 2) {
$r3$.ɵelementStylingMap(0, null, $ctx$.myStyleExp);
$r3$.ɵelementStyleProp(0, 1, $ctx$.myWidth);
$r3$.ɵelementStyleProp(0, 2, $ctx$.myHeight);
$r3$.ɵelementStyleProp(0, 0, $ctx$.myWidth);
$r3$.ɵelementStyleProp(0, 1, $ctx$.myHeight);
$r3$.ɵelementStylingApply(0);
$r3$.ɵelementAttribute(0, "style", $r3$.ɵbind("border-width: 10px"), $r3$.ɵsanitizeStyle);
}
@ -421,7 +421,7 @@ describe('compiler compliance: styling', () => {
};
const template = `
const _c0 = ["background-image"];
const $_c0$ = ["background-image"];
export class MyComponent {
constructor() {
this.myImage = 'url(foo.jpg)';
@ -456,7 +456,6 @@ describe('compiler compliance: styling', () => {
});
it('should support [style.foo.suffix] style bindings with a suffix', () => {
const files = {
app: {
'spec.ts': `
@ -476,7 +475,7 @@ describe('compiler compliance: styling', () => {
};
const template = `
const $e0_styles$= ["font-size"];
const $e0_styles$ = ["font-size"];
template: function MyComponent_Template(rf, ctx) {
if (rf & 1) {
@ -564,8 +563,8 @@ describe('compiler compliance: styling', () => {
};
const template = `
const $e0_attrs$ = [${AttributeMarker.SelectOnly}, "class"];
const $e0_cd$ = ["grape","apple","orange",${InitialStylingFlags.VALUES_MODE},"grape",true];
const $e0_attrs$ = [${AttributeMarker.Classes}, "grape", ${AttributeMarker.SelectOnly}, "class"];
const $e0_bindings$ = ["apple", "orange"];
MyComponent.ngComponentDef = $r3$.ɵdefineComponent({
type: MyComponent,
@ -578,13 +577,13 @@ describe('compiler compliance: styling', () => {
template: function MyComponent_Template(rf, $ctx$) {
if (rf & 1) {
$r3$.ɵelementStart(0, "div", $e0_attrs$);
$r3$.ɵelementStyling($e0_cd$);
$r3$.ɵelementStyling($e0_bindings$);
$r3$.ɵelementEnd();
}
if (rf & 2) {
$r3$.ɵelementStylingMap(0, $ctx$.myClassExp);
$r3$.ɵelementClassProp(0, 1, $ctx$.yesToApple);
$r3$.ɵelementClassProp(0, 2, $ctx$.yesToOrange);
$r3$.ɵelementClassProp(0, 0, $ctx$.yesToApple);
$r3$.ɵelementClassProp(0, 1, $ctx$.yesToOrange);
$r3$.ɵelementStylingApply(0);
$r3$.ɵelementAttribute(0, "class", $r3$.ɵbind("banana"));
}
@ -606,7 +605,7 @@ describe('compiler compliance: styling', () => {
@Component({
selector: 'my-component',
template: \`<div class="foo"
template: \`<div class=" foo "
style="width:100px"
[attr.class]="'round'"
[attr.style]="'height:100px'"></div>\`
@ -620,9 +619,7 @@ describe('compiler compliance: styling', () => {
};
const template = `
const $e0_attrs$ = [${AttributeMarker.SelectOnly}, "class", "style"];
const $e0_cd$ = ["foo",${InitialStylingFlags.VALUES_MODE},"foo",true];
const $e0_sd$ = ["width",${InitialStylingFlags.VALUES_MODE},"width","100px"];
const $e0_attrs$ = [${AttributeMarker.Classes}, "foo", ${AttributeMarker.Styles}, "width", "100px", ${AttributeMarker.SelectOnly}, "class", "style"];
MyComponent.ngComponentDef = $r3$.ɵdefineComponent({
type: MyComponent,
@ -635,7 +632,6 @@ describe('compiler compliance: styling', () => {
template: function MyComponent_Template(rf, $ctx$) {
if (rf & 1) {
$r3$.ɵelementStart(0, "div", $e0_attrs$);
$r3$.ɵelementStyling($e0_cd$, $e0_sd$);
$r3$.ɵelementEnd();
}
if (rf & 2) {
@ -765,10 +761,13 @@ describe('compiler compliance: styling', () => {
};
const template = `
const $e0_classBindings$ = ["foo"];
const $e0_styleBindings$ = ["bar", "baz"];
template: function MyComponent_Template(rf, $ctx$) {
if (rf & 1) {
$r3$.ɵelementStart(0, "div");
$r3$.ɵelementStyling($e0_styling$, $e1_styling$, $r3$.ɵdefaultStyleSanitizer);
$r3$.ɵelementStyling($e0_classBindings$, $e0_styleBindings$, $r3$.ɵdefaultStyleSanitizer);
$r3$.ɵpipe(1, "pipe");
$r3$.ɵpipe(2, "pipe");
$r3$.ɵpipe(3, "pipe");
@ -828,16 +827,18 @@ describe('compiler compliance: styling', () => {
};
const template = `
const _c0 = ["foo", "baz", ${InitialStylingFlags.VALUES_MODE}, "foo", true, "baz", true];
const _c1 = ["width", "height", "color", ${InitialStylingFlags.VALUES_MODE}, "width", "200px", "height", "500px"];
const $e0_attrs$ = [${AttributeMarker.Classes}, "foo", "baz", ${AttributeMarker.Styles}, "width", "200px", "height", "500px"];
const $e0_classBindings$ = ["foo"];
const $e0_styleBindings$ = ["color"];
hostBindings: function MyComponent_HostBindings(rf, ctx, elIndex) {
if (rf & 1) {
$r3$.ɵelementStyling(_c0, _c1, $r3$.ɵdefaultStyleSanitizer, ctx);
$r3$.ɵelementHostAttrs(ctx, $e0_attrs$);
$r3$.ɵelementStyling($e0_classBindings$, $e0_styleBindings$, $r3$.ɵdefaultStyleSanitizer, ctx);
}
if (rf & 2) {
$r3$.ɵelementStylingMap(elIndex, ctx.myClass, ctx.myStyle, ctx);
$r3$.ɵelementStyleProp(elIndex, 2, ctx.myColorProp, null, ctx);
$r3$.ɵelementStyleProp(elIndex, 0, ctx.myColorProp, null, ctx);
$r3$.ɵelementClassProp(elIndex, 0, ctx.myFooClass, ctx);
$r3$.ɵelementStylingApply(elIndex, ctx);
}
@ -959,10 +960,10 @@ describe('compiler compliance: styling', () => {
};
const template = `
const _c0 = ["foo"];
const _c1 = ["width"];
const _c2 = ["bar"];
const _c3 = ["height"];
const $widthDir_classes$ = ["foo"];
const $widthDir_styles$ = ["width"];
const $heightDir_classes$ = ["bar"];
const $heightDir_styles$ = ["height"];
function ClassDirective_HostBindings(rf, ctx, elIndex) {
if (rf & 1) {
@ -976,7 +977,7 @@ describe('compiler compliance: styling', () => {
function WidthDirective_HostBindings(rf, ctx, elIndex) {
if (rf & 1) {
$r3$.ɵelementStyling(_c0, _c1, null, ctx);
$r3$.ɵelementStyling($widthDir_classes$, $widthDir_styles$, null, ctx);
}
if (rf & 2) {
$r3$.ɵelementStyleProp(elIndex, 0, ctx.myWidth, null, ctx);
@ -987,7 +988,7 @@ describe('compiler compliance: styling', () => {
function HeightDirective_HostBindings(rf, ctx, elIndex) {
if (rf & 1) {
$r3$.ɵelementStyling(_c2, _c3, null, ctx);
$r3$.ɵelementStyling($heightDir_classes$, $heightDir_styles$, null, ctx);
}
if (rf & 2) {
$r3$.ɵelementStyleProp(elIndex, 0, ctx.myHeight, null, ctx);
@ -1014,7 +1015,8 @@ describe('compiler compliance: styling', () => {
template: '',
host: {
'style': 'width:200px; height:500px',
'class': 'foo baz'
'class': 'foo baz',
'title': 'foo title'
}
})
export class MyComponent {
@ -1029,6 +1031,9 @@ describe('compiler compliance: styling', () => {
@HostBinding('title')
title = 'some title';
@Input('name')
name = '';
}
@NgModule({declarations: [MyComponent]})
@ -1038,13 +1043,13 @@ describe('compiler compliance: styling', () => {
};
const template = `
const $_c0$ = ["foo", "baz", ${InitialStylingFlags.VALUES_MODE}, "foo", true, "baz", true];
const $_c1$ = ["width", "height", ${InitialStylingFlags.VALUES_MODE}, "width", "200px", "height", "500px"];
const $_c0$ = [${AttributeMarker.Classes}, "foo", "baz", ${AttributeMarker.Styles}, "width", "200px", "height", "500px"];
hostBindings: function MyComponent_HostBindings(rf, ctx, elIndex) {
if (rf & 1) {
$r3$.ɵallocHostVars(2);
$r3$.ɵelementStyling($_c0$, $_c1$, $r3$.ɵdefaultStyleSanitizer, ctx);
$r3$.ɵelementHostAttrs(ctx, $_c0$);
$r3$.ɵelementStyling(null, null, $r3$.ɵdefaultStyleSanitizer, ctx);
}
if (rf & 2) {
$r3$.ɵelementProperty(elIndex, "id", $r3$.ɵbind(ctx.id), null, true);