fix(compiler): don’t call `check` if we don’t need to (#15322)
If a directive has not bindings nor has a `ngDoCheck` / `ngOnInit` lifecycle hook, don’t generate a `check` call. This does not have an impact on the behavior, but produces less code. PR Close #15322
This commit is contained in:
parent
9bf2fb4a74
commit
764e90f9bb
|
@ -108,6 +108,7 @@ class ViewBuilder implements TemplateAstVisitor, LocalResolver {
|
||||||
private nodes: (() => {
|
private nodes: (() => {
|
||||||
sourceSpan: ParseSourceSpan,
|
sourceSpan: ParseSourceSpan,
|
||||||
nodeDef: o.Expression,
|
nodeDef: o.Expression,
|
||||||
|
directive?: CompileTypeMetadata,
|
||||||
updateDirectives?: UpdateExpression[],
|
updateDirectives?: UpdateExpression[],
|
||||||
updateRenderer?: UpdateExpression[]
|
updateRenderer?: UpdateExpression[]
|
||||||
})[] = [];
|
})[] = [];
|
||||||
|
@ -582,6 +583,7 @@ class ViewBuilder implements TemplateAstVisitor, LocalResolver {
|
||||||
outputDefs.length ? new o.LiteralMapExpr(outputDefs) : o.NULL_EXPR
|
outputDefs.length ? new o.LiteralMapExpr(outputDefs) : o.NULL_EXPR
|
||||||
]),
|
]),
|
||||||
updateDirectives: updateDirectiveExpressions,
|
updateDirectives: updateDirectiveExpressions,
|
||||||
|
directive: dirAst.directive.type,
|
||||||
});
|
});
|
||||||
|
|
||||||
return {hostBindings, hostEvents};
|
return {hostBindings, hostEvents};
|
||||||
|
@ -790,13 +792,14 @@ class ViewBuilder implements TemplateAstVisitor, LocalResolver {
|
||||||
const updateRendererStmts: o.Statement[] = [];
|
const updateRendererStmts: o.Statement[] = [];
|
||||||
const updateDirectivesStmts: o.Statement[] = [];
|
const updateDirectivesStmts: o.Statement[] = [];
|
||||||
const nodeDefExprs = this.nodes.map((factory, nodeIndex) => {
|
const nodeDefExprs = this.nodes.map((factory, nodeIndex) => {
|
||||||
const {nodeDef, updateDirectives, updateRenderer, sourceSpan} = factory();
|
const {nodeDef, directive, updateDirectives, updateRenderer, sourceSpan} = factory();
|
||||||
if (updateRenderer) {
|
if (updateRenderer) {
|
||||||
updateRendererStmts.push(...createUpdateStatements(nodeIndex, sourceSpan, updateRenderer));
|
updateRendererStmts.push(
|
||||||
|
...createUpdateStatements(nodeIndex, sourceSpan, updateRenderer, null));
|
||||||
}
|
}
|
||||||
if (updateDirectives) {
|
if (updateDirectives) {
|
||||||
updateDirectivesStmts.push(
|
updateDirectivesStmts.push(
|
||||||
...createUpdateStatements(nodeIndex, sourceSpan, updateDirectives));
|
...createUpdateStatements(nodeIndex, sourceSpan, updateDirectives, directive));
|
||||||
}
|
}
|
||||||
// We use a comma expression to call the log function before
|
// We use a comma expression to call the log function before
|
||||||
// the nodeDef function, but still use the result of the nodeDef function
|
// the nodeDef function, but still use the result of the nodeDef function
|
||||||
|
@ -807,8 +810,8 @@ class ViewBuilder implements TemplateAstVisitor, LocalResolver {
|
||||||
return {updateRendererStmts, updateDirectivesStmts, nodeDefExprs};
|
return {updateRendererStmts, updateDirectivesStmts, nodeDefExprs};
|
||||||
|
|
||||||
function createUpdateStatements(
|
function createUpdateStatements(
|
||||||
nodeIndex: number, sourceSpan: ParseSourceSpan,
|
nodeIndex: number, sourceSpan: ParseSourceSpan, expressions: UpdateExpression[],
|
||||||
expressions: UpdateExpression[]): o.Statement[] {
|
directive: CompileTypeMetadata): o.Statement[] {
|
||||||
const updateStmts: o.Statement[] = [];
|
const updateStmts: o.Statement[] = [];
|
||||||
const exprs = expressions.map(({sourceSpan, context, value}) => {
|
const exprs = expressions.map(({sourceSpan, context, value}) => {
|
||||||
const bindingId = `${updateBindingCount++}`;
|
const bindingId = `${updateBindingCount++}`;
|
||||||
|
@ -819,8 +822,12 @@ class ViewBuilder implements TemplateAstVisitor, LocalResolver {
|
||||||
...stmts.map(stmt => o.applySourceSpanToStatementIfNeeded(stmt, sourceSpan)));
|
...stmts.map(stmt => o.applySourceSpanToStatementIfNeeded(stmt, sourceSpan)));
|
||||||
return o.applySourceSpanToExpressionIfNeeded(currValExpr, sourceSpan);
|
return o.applySourceSpanToExpressionIfNeeded(currValExpr, sourceSpan);
|
||||||
});
|
});
|
||||||
updateStmts.push(o.applySourceSpanToStatementIfNeeded(
|
if (expressions.length ||
|
||||||
callCheckStmt(nodeIndex, exprs).toStmt(), sourceSpan));
|
(directive && (directive.lifecycleHooks.indexOf(LifecycleHooks.DoCheck) !== -1 ||
|
||||||
|
directive.lifecycleHooks.indexOf(LifecycleHooks.OnInit) !== -1))) {
|
||||||
|
updateStmts.push(o.applySourceSpanToStatementIfNeeded(
|
||||||
|
callCheckStmt(nodeIndex, exprs).toStmt(), sourceSpan));
|
||||||
|
}
|
||||||
return updateStmts;
|
return updateStmts;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -339,6 +339,35 @@ describe('compiler (unbundled Angular)', () => {
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('generated templates', () => {
|
||||||
|
it('should not call `check` for directives without bindings nor ngDoCheck/ngOnInit',
|
||||||
|
async(() => {
|
||||||
|
const FILES: MockData = {
|
||||||
|
app: {
|
||||||
|
'app.ts': `
|
||||||
|
import { NgModule, Component } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({ template: '' })
|
||||||
|
export class AppComponent {}
|
||||||
|
|
||||||
|
@NgModule({ declarations: [ AppComponent ] })
|
||||||
|
export class AppModule { }
|
||||||
|
`
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const host = new MockCompilerHost(['/app/app.ts'], FILES, angularFiles);
|
||||||
|
const aotHost = new MockAotCompilerHost(host);
|
||||||
|
const genFilePreamble = '/* Hello world! */';
|
||||||
|
compile(host, aotHost, expectNoDiagnostics, expectNoDiagnostics, {genFilePreamble})
|
||||||
|
.then((generatedFiles) => {
|
||||||
|
const genFile = generatedFiles.find(
|
||||||
|
gf => gf.srcFileUrl === '/app/app.ts' && gf.genFileUrl.endsWith('.ts'));
|
||||||
|
expect(genFile.source).not.toContain('check(');
|
||||||
|
});
|
||||||
|
|
||||||
|
}));
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('compiler (bundled Angular)', () => {
|
describe('compiler (bundled Angular)', () => {
|
||||||
|
|
Loading…
Reference in New Issue