perf(ivy): chain host binding instructions (#31296)
Adds chaining to the `property`, `attribute` and `updateSyntheticHostBinding` instructions when they're used in a host binding. This PR resolves FW-1404. PR Close #31296
This commit is contained in:
parent
c6b29f4c6d
commit
81332150aa
|
@ -443,8 +443,7 @@ describe('compiler compliance', () => {
|
||||||
$r3$.ɵɵpureFunction2(2, $_c0$, ctx.collapsedHeight, ctx.expandedHeight)
|
$r3$.ɵɵpureFunction2(2, $_c0$, ctx.collapsedHeight, ctx.expandedHeight)
|
||||||
)
|
)
|
||||||
, null, true
|
, null, true
|
||||||
);
|
)("@expansionWidth",
|
||||||
$r3$.ɵɵupdateSyntheticHostBinding("@expansionWidth",
|
|
||||||
$r3$.ɵɵpureFunction2(11, $_c1$, ctx.getExpandedState(),
|
$r3$.ɵɵpureFunction2(11, $_c1$, ctx.getExpandedState(),
|
||||||
$r3$.ɵɵpureFunction2(8, $_c2$, ctx.collapsedWidth, ctx.expandedWidth)
|
$r3$.ɵɵpureFunction2(8, $_c2$, ctx.collapsedWidth, ctx.expandedWidth)
|
||||||
)
|
)
|
||||||
|
|
|
@ -210,7 +210,7 @@ describe('compiler compliance: bindings', () => {
|
||||||
expectEmit(result.source, template, 'Incorrect template');
|
expectEmit(result.source, template, 'Incorrect template');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should chain property bindings in the presence of other instructions', () => {
|
it('should chain property bindings in the presence of other bindings', () => {
|
||||||
const files = {
|
const files = {
|
||||||
app: {
|
app: {
|
||||||
'example.ts': `
|
'example.ts': `
|
||||||
|
@ -473,7 +473,7 @@ describe('compiler compliance: bindings', () => {
|
||||||
expectEmit(result.source, template, 'Incorrect template');
|
expectEmit(result.source, template, 'Incorrect template');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should chain attribute bindings in the presence of other instructions', () => {
|
it('should chain attribute bindings in the presence of other bindings', () => {
|
||||||
const files = {
|
const files = {
|
||||||
app: {
|
app: {
|
||||||
'example.ts': `
|
'example.ts': `
|
||||||
|
@ -860,6 +860,250 @@ describe('compiler compliance: bindings', () => {
|
||||||
const source = result.source;
|
const source = result.source;
|
||||||
expectEmit(source, CompAndDirDeclaration, 'Invalid host attribute code');
|
expectEmit(source, CompAndDirDeclaration, 'Invalid host attribute code');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should chain multiple host property bindings into a single instruction', () => {
|
||||||
|
const files = {
|
||||||
|
app: {
|
||||||
|
'example.ts': `
|
||||||
|
import {Directive} from '@angular/core';
|
||||||
|
|
||||||
|
@Directive({
|
||||||
|
selector: '[my-dir]',
|
||||||
|
host: {
|
||||||
|
'[title]': 'myTitle',
|
||||||
|
'[tabindex]': '1',
|
||||||
|
'[id]': 'myId'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
export class MyDirective {
|
||||||
|
myTitle = 'hello';
|
||||||
|
myId = 'special-directive';
|
||||||
|
}`
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const result = compile(files, angularFiles);
|
||||||
|
const template = `
|
||||||
|
…
|
||||||
|
hostBindings: function MyDirective_HostBindings(rf, ctx, elIndex) {
|
||||||
|
…
|
||||||
|
if (rf & 2) {
|
||||||
|
$r3$.ɵɵproperty("title", ctx.myTitle, null, true)("tabindex", 1, null, true)("id", ctx.myId, null, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
expectEmit(result.source, template, 'Incorrect template');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should chain both host properties in the decorator and on the class', () => {
|
||||||
|
const files = {
|
||||||
|
app: {
|
||||||
|
'example.ts': `
|
||||||
|
import {Directive, HostBinding} from '@angular/core';
|
||||||
|
|
||||||
|
@Directive({
|
||||||
|
selector: '[my-dir]',
|
||||||
|
host: {
|
||||||
|
'[tabindex]': '1'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
export class MyDirective {
|
||||||
|
@HostBinding('title')
|
||||||
|
myTitle = 'hello';
|
||||||
|
|
||||||
|
@HostBinding('id')
|
||||||
|
myId = 'special-directive';
|
||||||
|
}`
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const result = compile(files, angularFiles);
|
||||||
|
const template = `
|
||||||
|
…
|
||||||
|
hostBindings: function MyDirective_HostBindings(rf, ctx, elIndex) {
|
||||||
|
…
|
||||||
|
if (rf & 2) {
|
||||||
|
$r3$.ɵɵproperty("tabindex", 1, null, true)("title", ctx.myTitle, null, true)("id", ctx.myId, null, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
expectEmit(result.source, template, 'Incorrect template');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should chain multiple host property bindings in the presence of other bindings', () => {
|
||||||
|
const files = {
|
||||||
|
app: {
|
||||||
|
'example.ts': `
|
||||||
|
import {Directive} from '@angular/core';
|
||||||
|
|
||||||
|
@Directive({
|
||||||
|
selector: '[my-dir]',
|
||||||
|
host: {
|
||||||
|
'[title]': '"my title"',
|
||||||
|
'[attr.tabindex]': '1',
|
||||||
|
'[id]': '"my-id"'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
export class MyDirective {}`
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const result = compile(files, angularFiles);
|
||||||
|
const template = `
|
||||||
|
…
|
||||||
|
hostBindings: function MyDirective_HostBindings(rf, ctx, elIndex) {
|
||||||
|
…
|
||||||
|
if (rf & 2) {
|
||||||
|
$r3$.ɵɵproperty("title", "my title", null, true)("id", "my-id", null, true);
|
||||||
|
$r3$.ɵɵattribute("tabindex", 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
expectEmit(result.source, template, 'Incorrect template');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should chain multiple synthetic properties into a single instruction call', () => {
|
||||||
|
const files = {
|
||||||
|
app: {
|
||||||
|
'example.ts': `
|
||||||
|
import {Directive} from '@angular/core';
|
||||||
|
|
||||||
|
@Directive({
|
||||||
|
selector: '[my-dir]',
|
||||||
|
host: {
|
||||||
|
'[@expand]': 'expandedState',
|
||||||
|
'[@fadeOut]': 'true',
|
||||||
|
'[@shrink]': 'isSmall'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
export class MyDirective {
|
||||||
|
expandedState = 'collapsed';
|
||||||
|
isSmall = true;
|
||||||
|
}`
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const result = compile(files, angularFiles);
|
||||||
|
const template = `
|
||||||
|
…
|
||||||
|
hostBindings: function MyDirective_HostBindings(rf, ctx, elIndex) {
|
||||||
|
…
|
||||||
|
if (rf & 2) {
|
||||||
|
$r3$.ɵɵupdateSyntheticHostBinding("@expand", ctx.expandedState, null, true)("@fadeOut", true, null, true)("@shrink", ctx.isSmall, null, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
expectEmit(result.source, template, 'Incorrect template');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should chain multiple host attribute bindings into a single instruction', () => {
|
||||||
|
const files = {
|
||||||
|
app: {
|
||||||
|
'example.ts': `
|
||||||
|
import {Directive} from '@angular/core';
|
||||||
|
|
||||||
|
@Directive({
|
||||||
|
selector: '[my-dir]',
|
||||||
|
host: {
|
||||||
|
'[attr.title]': 'myTitle',
|
||||||
|
'[attr.tabindex]': '1',
|
||||||
|
'[attr.id]': 'myId'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
export class MyDirective {
|
||||||
|
myTitle = 'hello';
|
||||||
|
myId = 'special-directive';
|
||||||
|
}`
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const result = compile(files, angularFiles);
|
||||||
|
const template = `
|
||||||
|
…
|
||||||
|
hostBindings: function MyDirective_HostBindings(rf, ctx, elIndex) {
|
||||||
|
…
|
||||||
|
if (rf & 2) {
|
||||||
|
$r3$.ɵɵattribute("title", ctx.myTitle)("tabindex", 1)("id", ctx.myId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
expectEmit(result.source, template, 'Incorrect template');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should chain both host attributes in the decorator and on the class', () => {
|
||||||
|
const files = {
|
||||||
|
app: {
|
||||||
|
'example.ts': `
|
||||||
|
import {Directive, HostBinding} from '@angular/core';
|
||||||
|
|
||||||
|
@Directive({
|
||||||
|
selector: '[my-dir]',
|
||||||
|
host: {
|
||||||
|
'[attr.tabindex]': '1'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
export class MyDirective {
|
||||||
|
@HostBinding('attr.title')
|
||||||
|
myTitle = 'hello';
|
||||||
|
|
||||||
|
@HostBinding('attr.id')
|
||||||
|
myId = 'special-directive';
|
||||||
|
}`
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const result = compile(files, angularFiles);
|
||||||
|
const template = `
|
||||||
|
…
|
||||||
|
hostBindings: function MyDirective_HostBindings(rf, ctx, elIndex) {
|
||||||
|
…
|
||||||
|
if (rf & 2) {
|
||||||
|
$r3$.ɵɵattribute("tabindex", 1)("title", ctx.myTitle)("id", ctx.myId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
expectEmit(result.source, template, 'Incorrect template');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should chain multiple host attribute bindings in the presence of other bindings', () => {
|
||||||
|
const files = {
|
||||||
|
app: {
|
||||||
|
'example.ts': `
|
||||||
|
import {Directive} from '@angular/core';
|
||||||
|
|
||||||
|
@Directive({
|
||||||
|
selector: '[my-dir]',
|
||||||
|
host: {
|
||||||
|
'[attr.title]': '"my title"',
|
||||||
|
'[tabindex]': '1',
|
||||||
|
'[attr.id]': '"my-id"'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
export class MyDirective {}`
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const result = compile(files, angularFiles);
|
||||||
|
const template = `
|
||||||
|
…
|
||||||
|
hostBindings: function MyDirective_HostBindings(rf, ctx, elIndex) {
|
||||||
|
…
|
||||||
|
if (rf & 2) {
|
||||||
|
$r3$.ɵɵproperty("tabindex", 1, null, true);
|
||||||
|
$r3$.ɵɵattribute("title", "my title")("id", "my-id");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
expectEmit(result.source, template, 'Incorrect template');
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('non bindable behavior', () => {
|
describe('non bindable behavior', () => {
|
||||||
|
|
|
@ -1388,8 +1388,7 @@ describe('compiler compliance: styling', () => {
|
||||||
$r3$.ɵɵstyling(null, null, $r3$.ɵɵdefaultStyleSanitizer);
|
$r3$.ɵɵstyling(null, null, $r3$.ɵɵdefaultStyleSanitizer);
|
||||||
}
|
}
|
||||||
if (rf & 2) {
|
if (rf & 2) {
|
||||||
$r3$.ɵɵproperty("id", ctx.id, null, true);
|
$r3$.ɵɵproperty("id", ctx.id, null, true)("title", ctx.title, null, true);
|
||||||
$r3$.ɵɵproperty("title", ctx.title, null, true);
|
|
||||||
$r3$.ɵɵstyleMap(ctx.myStyle);
|
$r3$.ɵɵstyleMap(ctx.myStyle);
|
||||||
$r3$.ɵɵclassMap(ctx.myClass);
|
$r3$.ɵɵclassMap(ctx.myClass);
|
||||||
$r3$.ɵɵstylingApply();
|
$r3$.ɵɵstylingApply();
|
||||||
|
@ -1435,8 +1434,7 @@ describe('compiler compliance: styling', () => {
|
||||||
$r3$.ɵɵstyling($_c0$, $_c1$);
|
$r3$.ɵɵstyling($_c0$, $_c1$);
|
||||||
}
|
}
|
||||||
if (rf & 2) {
|
if (rf & 2) {
|
||||||
$r3$.ɵɵproperty("id", ctx.id, null, true);
|
$r3$.ɵɵproperty("id", ctx.id, null, true)("title", ctx.title, null, true);
|
||||||
$r3$.ɵɵproperty("title", ctx.title, null, true);
|
|
||||||
$r3$.ɵɵstyleProp(0, ctx.myWidth);
|
$r3$.ɵɵstyleProp(0, ctx.myWidth);
|
||||||
$r3$.ɵɵclassProp(0, ctx.myFooClass);
|
$r3$.ɵɵclassProp(0, ctx.myFooClass);
|
||||||
$r3$.ɵɵstylingApply();
|
$r3$.ɵɵstylingApply();
|
||||||
|
|
|
@ -1795,8 +1795,8 @@ runInEachFileSystem(os => {
|
||||||
i0.ɵɵstyling(_c0);
|
i0.ɵɵstyling(_c0);
|
||||||
}
|
}
|
||||||
if (rf & 2) {
|
if (rf & 2) {
|
||||||
i0.ɵɵattribute("hello", ctx.foo);
|
|
||||||
i0.ɵɵproperty("prop", ctx.bar, null, true);
|
i0.ɵɵproperty("prop", ctx.bar, null, true);
|
||||||
|
i0.ɵɵattribute("hello", ctx.foo);
|
||||||
i0.ɵɵclassProp(0, ctx.someClass);
|
i0.ɵɵclassProp(0, ctx.someClass);
|
||||||
i0.ɵɵstylingApply();
|
i0.ɵɵstylingApply();
|
||||||
}
|
}
|
||||||
|
@ -3236,12 +3236,7 @@ runInEachFileSystem(os => {
|
||||||
i0.ɵɵallocHostVars(6);
|
i0.ɵɵallocHostVars(6);
|
||||||
}
|
}
|
||||||
if (rf & 2) {
|
if (rf & 2) {
|
||||||
i0.ɵɵattribute("href", ctx.attrHref, i0.ɵɵsanitizeUrlOrResourceUrl);
|
i0.ɵɵattribute("href", ctx.attrHref, i0.ɵɵsanitizeUrlOrResourceUrl)("src", ctx.attrSrc, i0.ɵɵsanitizeUrlOrResourceUrl)("action", ctx.attrAction, i0.ɵɵsanitizeUrl)("profile", ctx.attrProfile, i0.ɵɵsanitizeResourceUrl)("innerHTML", ctx.attrInnerHTML, i0.ɵɵsanitizeHtml)("title", ctx.attrSafeTitle);
|
||||||
i0.ɵɵattribute("src", ctx.attrSrc, i0.ɵɵsanitizeUrlOrResourceUrl);
|
|
||||||
i0.ɵɵattribute("action", ctx.attrAction, i0.ɵɵsanitizeUrl);
|
|
||||||
i0.ɵɵattribute("profile", ctx.attrProfile, i0.ɵɵsanitizeResourceUrl);
|
|
||||||
i0.ɵɵattribute("innerHTML", ctx.attrInnerHTML, i0.ɵɵsanitizeHtml);
|
|
||||||
i0.ɵɵattribute("title", ctx.attrSafeTitle);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
@ -3291,12 +3286,7 @@ runInEachFileSystem(os => {
|
||||||
i0.ɵɵallocHostVars(6);
|
i0.ɵɵallocHostVars(6);
|
||||||
}
|
}
|
||||||
if (rf & 2) {
|
if (rf & 2) {
|
||||||
i0.ɵɵproperty("href", ctx.propHref, i0.ɵɵsanitizeUrlOrResourceUrl, true);
|
i0.ɵɵproperty("href", ctx.propHref, i0.ɵɵsanitizeUrlOrResourceUrl, true)("src", ctx.propSrc, i0.ɵɵsanitizeUrlOrResourceUrl, true)("action", ctx.propAction, i0.ɵɵsanitizeUrl, true)("profile", ctx.propProfile, i0.ɵɵsanitizeResourceUrl, true)("innerHTML", ctx.propInnerHTML, i0.ɵɵsanitizeHtml, true)("title", ctx.propSafeTitle, null, true);
|
||||||
i0.ɵɵproperty("src", ctx.propSrc, i0.ɵɵsanitizeUrlOrResourceUrl, true);
|
|
||||||
i0.ɵɵproperty("action", ctx.propAction, i0.ɵɵsanitizeUrl, true);
|
|
||||||
i0.ɵɵproperty("profile", ctx.propProfile, i0.ɵɵsanitizeResourceUrl, true);
|
|
||||||
i0.ɵɵproperty("innerHTML", ctx.propInnerHTML, i0.ɵɵsanitizeHtml, true);
|
|
||||||
i0.ɵɵproperty("title", ctx.propSafeTitle, null, true);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
@ -3331,12 +3321,8 @@ runInEachFileSystem(os => {
|
||||||
i0.ɵɵallocHostVars(6);
|
i0.ɵɵallocHostVars(6);
|
||||||
}
|
}
|
||||||
if (rf & 2) {
|
if (rf & 2) {
|
||||||
i0.ɵɵproperty("src", ctx.srcProp, null, true);
|
i0.ɵɵproperty("src", ctx.srcProp, null, true)("href", ctx.hrefProp, null, true)("title", ctx.titleProp, null, true);
|
||||||
i0.ɵɵproperty("href", ctx.hrefProp, null, true);
|
i0.ɵɵattribute("src", ctx.srcAttr)("href", ctx.hrefAttr)("title", ctx.titleAttr);
|
||||||
i0.ɵɵproperty("title", ctx.titleProp, null, true);
|
|
||||||
i0.ɵɵattribute("src", ctx.srcAttr);
|
|
||||||
i0.ɵɵattribute("href", ctx.hrefAttr);
|
|
||||||
i0.ɵɵattribute("title", ctx.titleAttr);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
|
@ -30,7 +30,7 @@ import {prepareSyntheticListenerFunctionName, prepareSyntheticPropertyName, type
|
||||||
import {R3ComponentDef, R3ComponentMetadata, R3DirectiveDef, R3DirectiveMetadata, R3HostMetadata, R3QueryMetadata} from './api';
|
import {R3ComponentDef, R3ComponentMetadata, R3DirectiveDef, R3DirectiveMetadata, R3HostMetadata, R3QueryMetadata} from './api';
|
||||||
import {Instruction, StylingBuilder} from './styling_builder';
|
import {Instruction, StylingBuilder} from './styling_builder';
|
||||||
import {BindingScope, TemplateDefinitionBuilder, ValueConverter, makeBindingParser, prepareEventListenerParameters, renderFlagCheckIfStmt, resolveSanitizationFn} from './template';
|
import {BindingScope, TemplateDefinitionBuilder, ValueConverter, makeBindingParser, prepareEventListenerParameters, renderFlagCheckIfStmt, resolveSanitizationFn} from './template';
|
||||||
import {CONTEXT_NAME, DefinitionMap, RENDER_FLAGS, TEMPORARY_NAME, asLiteral, conditionallyCreateMapObjectLiteral, getQueryPredicate, temporaryAllocator} from './util';
|
import {CONTEXT_NAME, DefinitionMap, RENDER_FLAGS, TEMPORARY_NAME, asLiteral, chainedInstruction, conditionallyCreateMapObjectLiteral, getQueryPredicate, temporaryAllocator} from './util';
|
||||||
|
|
||||||
const EMPTY_ARRAY: any[] = [];
|
const EMPTY_ARRAY: any[] = [];
|
||||||
|
|
||||||
|
@ -638,6 +638,10 @@ function createHostBindingsFunction(
|
||||||
|
|
||||||
// Calculate the host property bindings
|
// Calculate the host property bindings
|
||||||
const bindings = bindingParser.createBoundHostProperties(directiveSummary, hostBindingSourceSpan);
|
const bindings = bindingParser.createBoundHostProperties(directiveSummary, hostBindingSourceSpan);
|
||||||
|
const propertyBindings: o.Expression[][] = [];
|
||||||
|
const attributeBindings: o.Expression[][] = [];
|
||||||
|
const syntheticHostBindings: o.Expression[][] = [];
|
||||||
|
|
||||||
(bindings || []).forEach((binding: ParsedProperty) => {
|
(bindings || []).forEach((binding: ParsedProperty) => {
|
||||||
const name = binding.name;
|
const name = binding.name;
|
||||||
const stylingInputWasSet =
|
const stylingInputWasSet =
|
||||||
|
@ -681,10 +685,32 @@ function createHostBindingsFunction(
|
||||||
}
|
}
|
||||||
|
|
||||||
updateStatements.push(...bindingExpr.stmts);
|
updateStatements.push(...bindingExpr.stmts);
|
||||||
updateStatements.push(o.importExpr(instruction).callFn(instructionParams).toStmt());
|
|
||||||
|
if (instruction === R3.property) {
|
||||||
|
propertyBindings.push(instructionParams);
|
||||||
|
} else if (instruction === R3.attribute) {
|
||||||
|
attributeBindings.push(instructionParams);
|
||||||
|
} else if (instruction === R3.updateSyntheticHostBinding) {
|
||||||
|
syntheticHostBindings.push(instructionParams);
|
||||||
|
} else {
|
||||||
|
updateStatements.push(o.importExpr(instruction).callFn(instructionParams).toStmt());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (propertyBindings.length > 0) {
|
||||||
|
updateStatements.push(chainedInstruction(R3.property, propertyBindings).toStmt());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attributeBindings.length > 0) {
|
||||||
|
updateStatements.push(chainedInstruction(R3.attribute, attributeBindings).toStmt());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (syntheticHostBindings.length > 0) {
|
||||||
|
updateStatements.push(
|
||||||
|
chainedInstruction(R3.updateSyntheticHostBinding, syntheticHostBindings).toStmt());
|
||||||
|
}
|
||||||
|
|
||||||
// since we're dealing with directives/components and both have hostBinding
|
// since we're dealing with directives/components and both have hostBinding
|
||||||
// functions, we need to generate a special hostAttrs instruction that deals
|
// functions, we need to generate a special hostAttrs instruction that deals
|
||||||
// with both the assignment of styling as well as static attributes to the host
|
// with both the assignment of styling as well as static attributes to the host
|
||||||
|
|
|
@ -37,7 +37,8 @@ import {I18nMetaVisitor} from './i18n/meta';
|
||||||
import {getSerializedI18nContent} from './i18n/serializer';
|
import {getSerializedI18nContent} from './i18n/serializer';
|
||||||
import {I18N_ICU_MAPPING_PREFIX, TRANSLATION_PREFIX, assembleBoundTextPlaceholders, assembleI18nBoundString, formatI18nPlaceholderName, getTranslationConstPrefix, getTranslationDeclStmts, icuFromI18nMessage, isI18nRootNode, isSingleI18nIcu, metaFromI18nMessage, placeholdersToParams, wrapI18nPlaceholder} from './i18n/util';
|
import {I18N_ICU_MAPPING_PREFIX, TRANSLATION_PREFIX, assembleBoundTextPlaceholders, assembleI18nBoundString, formatI18nPlaceholderName, getTranslationConstPrefix, getTranslationDeclStmts, icuFromI18nMessage, isI18nRootNode, isSingleI18nIcu, metaFromI18nMessage, placeholdersToParams, wrapI18nPlaceholder} from './i18n/util';
|
||||||
import {Instruction, StylingBuilder} from './styling_builder';
|
import {Instruction, StylingBuilder} from './styling_builder';
|
||||||
import {CONTEXT_NAME, IMPLICIT_REFERENCE, NON_BINDABLE_ATTR, REFERENCE_PREFIX, RENDER_FLAGS, asLiteral, getAttrsForDirectiveMatching, invalid, trimTrailingNulls, unsupported} from './util';
|
import {CONTEXT_NAME, IMPLICIT_REFERENCE, NON_BINDABLE_ATTR, REFERENCE_PREFIX, RENDER_FLAGS, asLiteral, chainedInstruction, getAttrsForDirectiveMatching, invalid, trimTrailingNulls, unsupported} from './util';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Selector attribute name of `<ng-content>`
|
// Selector attribute name of `<ng-content>`
|
||||||
|
@ -1105,7 +1106,7 @@ export class TemplateDefinitionBuilder implements t.Visitor<void>, LocalResolver
|
||||||
return fnParams;
|
return fnParams;
|
||||||
});
|
});
|
||||||
|
|
||||||
return chainedInstruction(span, reference, calls).toStmt();
|
return chainedInstruction(reference, calls, span).toStmt();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1417,22 +1418,6 @@ function instruction(
|
||||||
return o.importExpr(reference, null, span).callFn(params, span);
|
return o.importExpr(reference, null, span).callFn(params, span);
|
||||||
}
|
}
|
||||||
|
|
||||||
function chainedInstruction(
|
|
||||||
span: ParseSourceSpan | null, reference: o.ExternalReference, calls: o.Expression[][]) {
|
|
||||||
let expression = o.importExpr(reference, null, span) as o.Expression;
|
|
||||||
|
|
||||||
if (calls.length > 0) {
|
|
||||||
for (let i = 0; i < calls.length; i++) {
|
|
||||||
expression = expression.callFn(calls[i], span);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Add a blank invocation, in case the `calls` array is empty.
|
|
||||||
expression = expression.callFn([], span);
|
|
||||||
}
|
|
||||||
|
|
||||||
return expression;
|
|
||||||
}
|
|
||||||
|
|
||||||
// e.g. x(2);
|
// e.g. x(2);
|
||||||
function generateNextContextExpr(relativeLevelDiff: number): o.Expression {
|
function generateNextContextExpr(relativeLevelDiff: number): o.Expression {
|
||||||
return o.importExpr(R3.nextContext)
|
return o.importExpr(R3.nextContext)
|
||||||
|
|
|
@ -8,11 +8,14 @@
|
||||||
|
|
||||||
import {ConstantPool} from '../../constant_pool';
|
import {ConstantPool} from '../../constant_pool';
|
||||||
import * as o from '../../output/output_ast';
|
import * as o from '../../output/output_ast';
|
||||||
|
import {ParseSourceSpan} from '../../parse_util';
|
||||||
import {splitAtColon} from '../../util';
|
import {splitAtColon} from '../../util';
|
||||||
import * as t from '../r3_ast';
|
import * as t from '../r3_ast';
|
||||||
|
|
||||||
import {R3QueryMetadata} from './api';
|
import {R3QueryMetadata} from './api';
|
||||||
import {isI18nAttribute} from './i18n/util';
|
import {isI18nAttribute} from './i18n/util';
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks whether an object key contains potentially unsafe chars, thus the key should be wrapped in
|
* Checks whether an object key contains potentially unsafe chars, thus the key should be wrapped in
|
||||||
* quotes. Note: we do not wrap all keys into quotes, as it may have impact on minification and may
|
* quotes. Note: we do not wrap all keys into quotes, as it may have impact on minification and may
|
||||||
|
@ -181,3 +184,20 @@ export function getAttrsForDirectiveMatching(elOrTpl: t.Element | t.Template):
|
||||||
|
|
||||||
return attributesMap;
|
return attributesMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Returns a call expression to a chained instruction, e.g. `property(params[0])(params[1])`. */
|
||||||
|
export function chainedInstruction(
|
||||||
|
reference: o.ExternalReference, calls: o.Expression[][], span?: ParseSourceSpan | null) {
|
||||||
|
let expression = o.importExpr(reference, null, span) as o.Expression;
|
||||||
|
|
||||||
|
if (calls.length > 0) {
|
||||||
|
for (let i = 0; i < calls.length; i++) {
|
||||||
|
expression = expression.callFn(calls[i], span);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Add a blank invocation, in case the `calls` array is empty.
|
||||||
|
expression = expression.callFn([], span);
|
||||||
|
}
|
||||||
|
|
||||||
|
return expression;
|
||||||
|
}
|
||||||
|
|
|
@ -84,7 +84,8 @@ export function bind<T>(lView: LView, value: T): T|NO_CHANGE {
|
||||||
* @codeGenApi
|
* @codeGenApi
|
||||||
*/
|
*/
|
||||||
export function ɵɵupdateSyntheticHostBinding<T>(
|
export function ɵɵupdateSyntheticHostBinding<T>(
|
||||||
propName: string, value: T | NO_CHANGE, sanitizer?: SanitizerFn | null, nativeOnly?: boolean) {
|
propName: string, value: T | NO_CHANGE, sanitizer?: SanitizerFn | null,
|
||||||
|
nativeOnly?: boolean): TsickleIssue1009 {
|
||||||
const index = getSelectedIndex();
|
const index = getSelectedIndex();
|
||||||
const lView = getLView();
|
const lView = getLView();
|
||||||
// TODO(benlesh): remove bind call here.
|
// TODO(benlesh): remove bind call here.
|
||||||
|
@ -92,4 +93,5 @@ export function ɵɵupdateSyntheticHostBinding<T>(
|
||||||
if (bound !== NO_CHANGE) {
|
if (bound !== NO_CHANGE) {
|
||||||
elementPropertyInternal(index, propName, bound, sanitizer, nativeOnly, loadComponentRenderer);
|
elementPropertyInternal(index, propName, bound, sanitizer, nativeOnly, loadComponentRenderer);
|
||||||
}
|
}
|
||||||
|
return ɵɵupdateSyntheticHostBinding;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1075,7 +1075,7 @@ export declare function ɵɵtextInterpolate8(prefix: string, v0: any, i0: string
|
||||||
|
|
||||||
export declare function ɵɵtextInterpolateV(values: any[]): TsickleIssue1009;
|
export declare function ɵɵtextInterpolateV(values: any[]): TsickleIssue1009;
|
||||||
|
|
||||||
export declare function ɵɵupdateSyntheticHostBinding<T>(propName: string, value: T | NO_CHANGE, sanitizer?: SanitizerFn | null, nativeOnly?: boolean): void;
|
export declare function ɵɵupdateSyntheticHostBinding<T>(propName: string, value: T | NO_CHANGE, sanitizer?: SanitizerFn | null, nativeOnly?: boolean): TsickleIssue1009;
|
||||||
|
|
||||||
export declare function ɵɵviewQuery<T>(predicate: Type<any> | string[], descend: boolean, read: any): QueryList<T>;
|
export declare function ɵɵviewQuery<T>(predicate: Type<any> | string[], descend: boolean, read: any): QueryList<T>;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue