Skip to content

Commit

Permalink
fix(@angular/cli): workaround TS decorator transformer defect
Browse files Browse the repository at this point in the history
  • Loading branch information
clydin authored and Brocco committed Jan 19, 2018
1 parent 52494b4 commit c38b1ed
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 4 deletions.
15 changes: 11 additions & 4 deletions packages/@ngtools/webpack/src/transformers/make_transform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,11 +129,18 @@ function visitEachChildWorkaround(node: ts.Node, visitor: ts.Visitor,
}


// If TS sees an empty decorator array, it will still emit a `__decorate` call.
// This seems to be a TS bug.
// 1) If TS sees an empty decorator array, it will still emit a `__decorate` call.
// This seems to be a TS bug.
// 2) Also ensure nodes with modified decorators have parents
// built in TS transformers assume certain nodes have parents (fixed in TS 2.7+)
function cleanupDecorators(node: ts.Node) {
if (node.decorators && node.decorators.length == 0) {
node.decorators = undefined;
if (node.decorators) {
if (node.decorators.length == 0) {
node.decorators = undefined;
} else if (node.parent == undefined) {
const originalNode = ts.getParseTreeNode(node);
node.parent = originalNode.parent;
}
}

ts.forEachChild(node, node => cleanupDecorators(node));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,54 @@ describe('@ngtools/webpack transformers', () => {
expect(oneLine`${result}`).toEqual(oneLine`${output}`);
});

it('should keep other decorators on class member', () => {
const input = stripIndent`
import { Component, HostListener } from '@angular/core';
import { AnotherDecorator } from 'another-lib';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'app';
@HostListener('document:keydown.escape')
@AnotherDecorator()
onEscape() {
console.log('run');
}
}
`;
const output = stripIndent`
import * as tslib_1 from "tslib";
import { AnotherDecorator } from 'another-lib';
export class AppComponent {
constructor() {
this.title = 'app';
}
onEscape() {
console.log('run');
}
}
tslib_1.__decorate([
AnotherDecorator()
], AppComponent.prototype, "onEscape", null);
`;

const { program, compilerHost } = createTypescriptContext(input);
const transformer = removeDecorators(
() => true,
() => program.getTypeChecker(),
);
const result = transformTypescript(undefined, [transformer], program, compilerHost);

expect(oneLine`${result}`).toEqual(oneLine`${output}`);
});

it('should remove imports for identifiers within the decorator', () => {
const input = stripIndent`
import { Component } from '@angular/core';
Expand Down

0 comments on commit c38b1ed

Please sign in to comment.