Skip to content

Commit e6707bf

Browse files
clydinBrocco
authored andcommittedJan 18, 2018
fix(@angular/cli): workaround TS decorator transformer defect
1 parent c411734 commit e6707bf

File tree

2 files changed

+59
-4
lines changed

2 files changed

+59
-4
lines changed
 

Diff for: ‎packages/@ngtools/webpack/src/transformers/make_transform.ts

+11-4
Original file line numberDiff line numberDiff line change
@@ -129,11 +129,18 @@ function visitEachChildWorkaround(node: ts.Node, visitor: ts.Visitor,
129129
}
130130

131131

132-
// If TS sees an empty decorator array, it will still emit a `__decorate` call.
133-
// This seems to be a TS bug.
132+
// 1) If TS sees an empty decorator array, it will still emit a `__decorate` call.
133+
// This seems to be a TS bug.
134+
// 2) Also ensure nodes with modified decorators have parents
135+
// built in TS transformers assume certain nodes have parents (fixed in TS 2.7+)
134136
function cleanupDecorators(node: ts.Node) {
135-
if (node.decorators && node.decorators.length == 0) {
136-
node.decorators = undefined;
137+
if (node.decorators) {
138+
if (node.decorators.length == 0) {
139+
node.decorators = undefined;
140+
} else if (node.parent == undefined) {
141+
const originalNode = ts.getParseTreeNode(node);
142+
node.parent = originalNode.parent;
143+
}
137144
}
138145

139146
ts.forEachChild(node, node => cleanupDecorators(node));

Diff for: ‎packages/@ngtools/webpack/src/transformers/remove_decorators.spec.ts

+48
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,54 @@ describe('@ngtools/webpack transformers', () => {
7676
expect(oneLine`${result}`).toEqual(oneLine`${output}`);
7777
});
7878

79+
it('should keep other decorators on class member', () => {
80+
const input = stripIndent`
81+
import { Component, HostListener } from '@angular/core';
82+
import { AnotherDecorator } from 'another-lib';
83+
84+
@Component({
85+
selector: 'app-root',
86+
templateUrl: './app.component.html',
87+
styleUrls: ['./app.component.css']
88+
})
89+
export class AppComponent {
90+
title = 'app';
91+
92+
@HostListener('document:keydown.escape')
93+
@AnotherDecorator()
94+
onEscape() {
95+
console.log('run');
96+
}
97+
}
98+
`;
99+
const output = stripIndent`
100+
import * as tslib_1 from "tslib";
101+
import { AnotherDecorator } from 'another-lib';
102+
103+
export class AppComponent {
104+
constructor() {
105+
this.title = 'app';
106+
}
107+
108+
onEscape() {
109+
console.log('run');
110+
}
111+
}
112+
tslib_1.__decorate([
113+
AnotherDecorator()
114+
], AppComponent.prototype, "onEscape", null);
115+
`;
116+
117+
const { program, compilerHost } = createTypescriptContext(input);
118+
const transformer = removeDecorators(
119+
() => true,
120+
() => program.getTypeChecker(),
121+
);
122+
const result = transformTypescript(undefined, [transformer], program, compilerHost);
123+
124+
expect(oneLine`${result}`).toEqual(oneLine`${output}`);
125+
});
126+
79127
it('should remove imports for identifiers within the decorator', () => {
80128
const input = stripIndent`
81129
import { Component } from '@angular/core';

0 commit comments

Comments
 (0)
Please sign in to comment.