fix(ngcc): ensure that "inline exports" can be interpreted correctly (#39267)

Previously, inline exports of the form `exports.foo = <implementation>;` were
being interpreted (by the ngtsc `PartialInterpeter`) as `Reference` objects.
This is not what is desired since it prevents the value of the export
from being unpacked, such as when analyzing `NgModule` declarations:

```
exports.directives = [Directive1, Directive2];

@NgImport({declarations: [exports.directives]})
class AppModule {}
```

In this example the interpreter would think that `exports.directives`
was a reference rather than an array that needs to be unpacked.

This bug was picked up by the ngcc-validation repository. See
https://github.com/angular/ngcc-validation/pull/1990 and
https://circleci.com/gh/angular/ngcc-validation/17130

PR Close #39267
This commit is contained in:
Pete Bacon Darwin
2020-10-14 16:30:09 +01:00
committed by atscott
parent ac0016cd82
commit 822b838fbc
5 changed files with 57 additions and 43 deletions

View File

@ -264,3 +264,20 @@ export interface ExportsStatement extends ts.ExpressionStatement {
export function isExportsStatement(stmt: ts.Node): stmt is ExportsStatement {
return ts.isExpressionStatement(stmt) && isExportsAssignment(stmt.expression);
}
/**
* Find the far right hand side of a sequence of aliased assignements of the form
*
* ```
* exports.MyClass = alias1 = alias2 = <<declaration>>
* ```
*
* @param node the expression to parse
* @returns the original `node` or the far right expression of a series of assignments.
*/
export function skipAliases(node: ts.Expression): ts.Expression {
while (isAssignment(node)) {
node = node.right;
}
return node;
}