diff --git a/packages/compiler-cli/test/ngtsc/ngtsc_spec.ts b/packages/compiler-cli/test/ngtsc/ngtsc_spec.ts index 1950d63a27..5ce8dea047 100644 --- a/packages/compiler-cli/test/ngtsc/ngtsc_spec.ts +++ b/packages/compiler-cli/test/ngtsc/ngtsc_spec.ts @@ -640,4 +640,21 @@ describe('ngtsc behavioral tests', () => { expect(emptyFactory).toContain(`import * as i0 from '@angular/core';`); expect(emptyFactory).toContain(`export var ɵNonEmptyModule = true;`); }); + + it('should compile a banana-in-a-box inside of a template', () => { + writeConfig(); + write('test.ts', ` + import {Component} from '@angular/core'; + + @Component({ + template: '
', + selector: 'test' + }) + class TestCmp {} + `); + + const exitCode = main(['-p', basePath], errorSpy); + expect(errorSpy).not.toHaveBeenCalled(); + expect(exitCode).toBe(0); + }); }); diff --git a/packages/compiler/src/compiler_util/expression_converter.ts b/packages/compiler/src/compiler_util/expression_converter.ts index 9974d86492..84d3c8639e 100644 --- a/packages/compiler/src/compiler_util/expression_converter.ts +++ b/packages/compiler/src/compiler_util/expression_converter.ts @@ -449,14 +449,28 @@ class _AstToIrVisitor implements cdAst.AstVisitor { visitPropertyWrite(ast: cdAst.PropertyWrite, mode: _Mode): any { const receiver: o.Expression = this._visit(ast.receiver, _Mode.Expression); + + let varExpr: o.ReadPropExpr|null = null; if (receiver === this._implicitReceiver) { - const varExpr = this._getLocal(ast.name); - if (varExpr) { - throw new Error('Cannot assign to a reference or variable!'); + const localExpr = this._getLocal(ast.name); + if (localExpr) { + if (localExpr instanceof o.ReadPropExpr) { + // If the local variable is a property read expression, it's a reference + // to a 'context.property' value and will be used as the target of the + // write expression. + varExpr = localExpr; + } else { + // Otherwise it's an error. + throw new Error('Cannot assign to a reference or variable!'); + } } } - return convertToStatementIfNeeded( - mode, receiver.prop(ast.name).set(this._visit(ast.value, _Mode.Expression))); + // If no local expression could be produced, use the original receiver's + // property as the target. + if (varExpr === null) { + varExpr = receiver.prop(ast.name); + } + return convertToStatementIfNeeded(mode, varExpr.set(this._visit(ast.value, _Mode.Expression))); } visitSafePropertyRead(ast: cdAst.SafePropertyRead, mode: _Mode): any {