From 023bd31965856b00cad0f1132e46141ea58b4934 Mon Sep 17 00:00:00 2001 From: JoostK Date: Mon, 10 Dec 2018 17:34:56 +0100 Subject: [PATCH] fix(ivy): ngcc should not emit TypeScript syntax (#27051) If a template contains specific TypeScript syntax, such as a non-null assertion, the code that is emitted from ngcc into a JavaScript bundle should not retain such syntax as it is invalid in JS. A full-blown TypeScript emit of a complete ts.SourceFile would be required to be able to emit JS and possibly downlevel into a lower language target, which is not an option for ngcc as it currently operates on partial ASTs, not full source files. Instead, ngtsc no longer produces TypeScript specific syntax in the first place, such that TypeScript print logic will only generate JS code. PR Close #27051 --- .../src/ngcc/test/rendering/renderer_spec.ts | 25 +++++++++++++++++++ .../src/ngtsc/translator/src/translator.ts | 2 +- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/packages/compiler-cli/src/ngcc/test/rendering/renderer_spec.ts b/packages/compiler-cli/src/ngcc/test/rendering/renderer_spec.ts index e27c1f4514..c00b85bef3 100644 --- a/packages/compiler-cli/src/ngcc/test/rendering/renderer_spec.ts +++ b/packages/compiler-cli/src/ngcc/test/rendering/renderer_spec.ts @@ -79,6 +79,12 @@ describe('Renderer', () => { contents: `export declare class A {\nfoo(x: number): number;\n}\n` }; + const COMPONENT_PROGRAM = { + name: '/src/component.js', + contents: + `import { Component } from '@angular/core';\nexport class A {}\nA.decorators = [\n { type: Component, args: [{ selector: 'a', template: '{{ person!.name }}' }] }\n];\n` + }; + const INPUT_PROGRAM_MAP = fromObject({ 'version': 3, 'file': '/src/file.js', @@ -126,6 +132,25 @@ describe('Renderer', () => { expect(result[1].contents).toEqual(OUTPUT_PROGRAM_MAP.toJSON()); }); + + it('should render as JavaScript', () => { + const {renderer, decorationAnalyses, switchMarkerAnalyses, privateDeclarationsAnalyses} = + createTestRenderer('test-package', [COMPONENT_PROGRAM]); + renderer.renderProgram(decorationAnalyses, switchMarkerAnalyses, privateDeclarationsAnalyses); + const addDefinitionsSpy = renderer.addDefinitions as jasmine.Spy; + expect(addDefinitionsSpy.calls.first().args[2]) + .toEqual(`/*@__PURE__*/ ɵngcc0.ɵsetClassMetadata(A, [{ + type: Component, + args: [{ selector: 'a', template: '{{ person!.name }}' }] + }], null, null); +A.ngComponentDef = ɵngcc0.ɵdefineComponent({ type: A, selectors: [["a"]], factory: function A_Factory(t) { return new (t || A)(); }, consts: 1, vars: 1, template: function A_Template(rf, ctx) { if (rf & 1) { + ɵngcc0.ɵtext(0); + } if (rf & 2) { + ɵngcc0.ɵtextBinding(0, ɵngcc0.ɵinterpolation1("", ctx.person.name, "")); + } }, encapsulation: 2 });`); + }); + + describe('calling abstract methods', () => { it('should call addImports with the source code and info about the core Angular library.', () => { diff --git a/packages/compiler-cli/src/ngtsc/translator/src/translator.ts b/packages/compiler-cli/src/ngtsc/translator/src/translator.ts index e24d0d69f4..814a56e47a 100644 --- a/packages/compiler-cli/src/ngtsc/translator/src/translator.ts +++ b/packages/compiler-cli/src/ngtsc/translator/src/translator.ts @@ -252,7 +252,7 @@ class ExpressionTranslatorVisitor implements ExpressionVisitor, StatementVisitor } visitAssertNotNullExpr(ast: AssertNotNull, context: Context): ts.NonNullExpression { - return ts.createNonNullExpression(ast.condition.visitExpression(this, context)); + return ast.condition.visitExpression(this, context); } visitCastExpr(ast: CastExpr, context: Context): ts.Expression {