Skip to content
Permalink
Browse files

fix(ivy): handle empty bindings in template type checker (#31594)

When a template contains a binding without a value, the template parser
creates an `EmptyExpr` node. This would previously be translated into
an `undefined` value, which would cause a crash downstream as `undefined`
is not included in the allowed type, so it was not handled properly.

This commit prevents the crash by returning an actual expression for empty
bindings.

Fixes #30076
Fixes #30929

PR Close #31594
  • Loading branch information...
JoostK authored and AndrewKushnir committed Jun 9, 2019
1 parent 8e1a725 commit 0db1b5d8f11b23d29ee1a4f2226cb95ef8748bc0
@@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/

import {AST, ASTWithSource, AstVisitor, Binary, BindingPipe, Chain, Conditional, FunctionCall, ImplicitReceiver, Interpolation, KeyedRead, KeyedWrite, LiteralArray, LiteralMap, LiteralPrimitive, MethodCall, NonNullAssert, ParseSpan, PrefixNot, PropertyRead, PropertyWrite, Quote, SafeMethodCall, SafePropertyRead} from '@angular/compiler';
import {AST, ASTWithSource, AstVisitor, Binary, BindingPipe, Chain, Conditional, EmptyExpr, FunctionCall, ImplicitReceiver, Interpolation, KeyedRead, KeyedWrite, LiteralArray, LiteralMap, LiteralPrimitive, MethodCall, NonNullAssert, ParseSpan, PrefixNot, PropertyRead, PropertyWrite, Quote, SafeMethodCall, SafePropertyRead} from '@angular/compiler';
import * as ts from 'typescript';

import {TypeCheckingConfig} from './api';
@@ -60,6 +60,11 @@ class AstTranslator implements AstVisitor {
ast = ast.ast;
}

// The `EmptyExpr` doesn't have a dedicated method on `AstVisitor`, so it's special cased here.
if (ast instanceof EmptyExpr) {
return UNDEFINED;
}

// First attempt to let any custom resolution logic provide a translation for the given node.
const resolved = this.maybeResolve(ast);
if (resolved !== null) {
@@ -39,6 +39,16 @@ describe('type check blocks', () => {
expect(tcb(TEMPLATE)).toContain('_t1.htmlFor = ("test");');
});

it('should handle empty bindings', () => {
const TEMPLATE = `<input [type]="">`;
expect(tcb(TEMPLATE)).toContain('_t1.type = (undefined);');
});

it('should handle bindings without value', () => {
const TEMPLATE = `<input [type]>`;
expect(tcb(TEMPLATE)).toContain('_t1.type = (undefined);');
});

it('should handle implicit vars on ng-template', () => {
const TEMPLATE = `<ng-template let-a></ng-template>`;
expect(tcb(TEMPLATE)).toContain('var _t2 = _t1.$implicit;');

0 comments on commit 0db1b5d

Please sign in to comment.
You can’t perform that action at this time.