perf(ivy): add self-closing elementContainer instruction (#31444)

Adds a new `elementContainer` instruction that can be used to avoid two instruction (`elementContainerStart` and `elementContainerEnd`) for `ng-container` that has text-only content. This is particularly useful when we have `ng-container` inside i18n sections.

This PR resolves FW-1105.

PR Close #31444
This commit is contained in:
crisbeto
2019-07-07 16:35:58 +02:00
committed by Jason Aden
parent e92fb68f3c
commit 23e0d65471
10 changed files with 135 additions and 18 deletions

View File

@ -253,7 +253,7 @@ describe('compiler compliance', () => {
expectEmit(result.source, template, 'Incorrect template');
});
it('should generate elementContainerStart/End instructions for empty <ng-container>', () => {
it('should generate self-closing elementContainer instruction for empty <ng-container>', () => {
const files = {
app: {
'spec.ts': `
@ -276,8 +276,7 @@ describe('compiler compliance', () => {
template: function MyComponent_Template(rf, ctx) {
if (rf & 1) {
i0.ɵɵelementContainerStart(0);
i0.ɵɵelementContainerEnd();
i0.ɵɵelementContainer(0);
}
}
`;

View File

@ -1977,9 +1977,8 @@ describe('i18n support in the view compiler', () => {
$r3$.ɵɵelementStart(0, "div");
$r3$.ɵɵi18nStart(1, $I18N_0$);
$r3$.ɵɵtemplate(2, MyComponent_ng_template_2_Template, 2, 3, "ng-template");
$r3$.ɵɵelementContainerStart(3);
$r3$.ɵɵelementContainer(3);
$r3$.ɵɵpipe(4, "uppercase");
$r3$.ɵɵelementContainerEnd();
$r3$.ɵɵi18nEnd();
$r3$.ɵɵelementEnd();
}
@ -2324,6 +2323,76 @@ describe('i18n support in the view compiler', () => {
verify(input, output);
});
it('should generate a self-closing container instruction for ng-container inside i18n', () => {
const input = `
<div i18n>
Hello <ng-container>there</ng-container>
</div>
`;
const output = String.raw `
var $I18N_0$;
if (ngI18nClosureMode) {
const $MSG_APP_SPEC_TS_1$ = goog.getMsg(" Hello {$startTagNgContainer}there{$closeTagNgContainer}", { "startTagNgContainer": "\uFFFD#2\uFFFD", "closeTagNgContainer": "\uFFFD/#2\uFFFD" });
$I18N_0$ = $MSG_APP_SPEC_TS_1$;
}
else {
$I18N_0$ = $r3$.ɵɵi18nLocalize(" Hello {$startTagNgContainer}there{$closeTagNgContainer}", { "startTagNgContainer": "\uFFFD#2\uFFFD", "closeTagNgContainer": "\uFFFD/#2\uFFFD" });
}
consts: 3,
vars: 0,
template: function MyComponent_Template(rf, ctx) {
if (rf & 1) {
$r3$.ɵɵelementStart(0, "div");
$r3$.ɵɵi18nStart(1, I18N_0);
$r3$.ɵɵelementContainer(2);
$r3$.ɵɵi18nEnd();
$r3$.ɵɵelementEnd();
}
}
`;
verify(input, output);
});
it('should not generate a self-closing container instruction for ng-container with non-text content inside i18n',
() => {
const input = `
<div i18n>
Hello <ng-container>there <strong>!</strong></ng-container>
</div>
`;
const output = String.raw `
var $I18N_0$;
if (ngI18nClosureMode) {
const $MSG_APP_SPEC_TS_1$ = goog.getMsg(" Hello {$startTagNgContainer}there {$startTagStrong}!{$closeTagStrong}{$closeTagNgContainer}", { "startTagNgContainer": "\uFFFD#2\uFFFD", "startTagStrong": "\uFFFD#3\uFFFD", "closeTagStrong": "\uFFFD/#3\uFFFD", "closeTagNgContainer": "\uFFFD/#2\uFFFD" });
$I18N_0$ = $MSG_APP_SPEC_TS_1$;
}
else {
$I18N_0$ = $r3$.ɵɵi18nLocalize(" Hello {$startTagNgContainer}there {$startTagStrong}!{$closeTagStrong}{$closeTagNgContainer}", { "startTagNgContainer": "\uFFFD#2\uFFFD", "startTagStrong": "\uFFFD#3\uFFFD", "closeTagStrong": "\uFFFD/#3\uFFFD", "closeTagNgContainer": "\uFFFD/#2\uFFFD" });
}
consts: 4,
vars: 0,
template: function MyComponent_Template(rf, ctx) {
if (rf & 1) {
$r3$.ɵɵelementStart(0, "div");
$r3$.ɵɵi18nStart(1, I18N_0);
$r3$.ɵɵelementContainerStart(2);
$r3$.ɵɵelement(3, "strong");
$r3$.ɵɵelementContainerEnd();
$r3$.ɵɵi18nEnd();
$r3$.ɵɵelementEnd();
}
}
`;
verify(input, output);
});
});
describe('whitespace preserving mode', () => {