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
This commit is contained in:
JoostK 2018-12-10 17:34:56 +01:00 committed by Miško Hevery
parent b39efdd9d6
commit 023bd31965
2 changed files with 26 additions and 1 deletions

View File

@ -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.',
() => {

View File

@ -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 {