fix(ngcc): remove __decorator calls even when part of the IIFE return statement (#33777)

Previously we only removed `__decorate()` calls that looked like:

```
SomeClass = __decorate(...);
```

But in some minified scenarios this call gets wrapped up with the
return statement of the IIFE.

```
return SomeClass = __decorate(...);
```

This is now removed also, leaving just the return statement:

```
return SomeClass;
```

PR Close #33777
This commit is contained in:
Pete Bacon Darwin
2019-11-13 08:36:13 +00:00
committed by Kara Erickson
parent 1b489083bc
commit e1df98be17
2 changed files with 116 additions and 54 deletions

View File

@ -17,6 +17,7 @@ import {ExportInfo} from '../analysis/private_declarations_analyzer';
import {RenderingFormatter, RedundantDecoratorMap} from './rendering_formatter';
import {stripExtension} from './utils';
import {Reexport} from '../../../src/ngtsc/imports';
import {isAssignment} from '../host/esm2015_host';
/**
* A RenderingFormatter that works with ECMAScript Module import and export statements.
@ -124,7 +125,19 @@ export class EsmRenderingFormatter implements RenderingFormatter {
// Remove the entire statement
const statement = findStatement(containerNode);
if (statement) {
output.remove(statement.getFullStart(), statement.getEnd());
if (ts.isExpressionStatement(statement)) {
// The statement looks like: `SomeClass = __decorate(...);`
// Remove it completely
output.remove(statement.getFullStart(), statement.getEnd());
} else if (
ts.isReturnStatement(statement) && statement.expression &&
isAssignment(statement.expression)) {
// The statement looks like: `return SomeClass = __decorate(...);`
// We only want to end up with: `return SomeClass;`
const startOfRemoval = statement.expression.left.getEnd();
const endOfRemoval = getEndExceptSemicolon(statement);
output.remove(startOfRemoval, endOfRemoval);
}
}
} else {
nodesToRemove.forEach(node => {
@ -239,7 +252,7 @@ export class EsmRenderingFormatter implements RenderingFormatter {
function findStatement(node: ts.Node) {
while (node) {
if (ts.isExpressionStatement(node)) {
if (ts.isExpressionStatement(node) || ts.isReturnStatement(node)) {
return node;
}
node = node.parent;
@ -257,3 +270,9 @@ function getNextSiblingInArray<T extends ts.Node>(node: T, array: ts.NodeArray<T
const index = array.indexOf(node);
return index !== -1 && array.length > index + 1 ? array[index + 1] : null;
}
function getEndExceptSemicolon(statement: ts.Statement): number {
const lastToken = statement.getLastToken();
return (lastToken && lastToken.kind === ts.SyntaxKind.SemicolonToken) ? statement.getEnd() - 1 :
statement.getEnd();
}