fix(ngcc): handle aliases in UMD export declarations (#38959)

Sometimes UMD exports appear in the following form:

```
exports.MyClass = alias1 = alias2 = <<declaration>>
```

Previously the declaration of the export would have been captured
as `alias1 = alias2 = <<declaration>>`, which the `PartialInterpreter`
would have failed on, since it cannot handle assignments.

Now we skip over these aliases capturing only the `<<declaration>>`
expression.

Fixes #38947

PR Close #38959
This commit is contained in:
Pete Bacon Darwin 2020-09-23 22:02:13 +01:00 committed by atscott
parent 11485d96fb
commit 5038e5741b
3 changed files with 22 additions and 3 deletions

View File

@ -2311,7 +2311,7 @@ function isInitializedVariableClassDeclaration(node: ts.Node):
* var MyClass = alias1 = alias2 = <<declaration>>
* ```
*
* @node the LHS of a variable declaration.
* @param node the LHS of a variable declaration.
* @returns the original AST node or the RHS of a series of assignments in a variable
* declaration.
*/

View File

@ -15,6 +15,7 @@ import {BundleProgram} from '../packages/bundle_program';
import {FactoryMap, getTsHelperFnFromIdentifier, stripExtension} from '../utils';
import {DefinePropertyReexportStatement, ExportDeclaration, ExportsStatement, extractGetterFnExpression, findNamespaceOfIdentifier, findRequireCallReference, isDefinePropertyReexportStatement, isExportsStatement, isExternalImport, isRequireCall, isWildcardReexportStatement, WildcardReexportStatement} from './commonjs_umd_utils';
import {isAssignment} from './esm2015_host';
import {Esm5ReflectionHost} from './esm5_host';
import {stripParentheses} from './utils';
@ -134,7 +135,7 @@ export class UmdReflectionHost extends Esm5ReflectionHost {
private extractBasicUmdExportDeclaration(statement: ExportsStatement): ExportDeclaration {
const name = statement.expression.left.name.text;
const exportExpression = statement.expression.right;
const exportExpression = skipAliases(statement.expression.right);
return this.extractUmdExportDeclaration(name, exportExpression);
}
@ -400,3 +401,20 @@ function getRequiredModulePath(wrapperFn: ts.FunctionExpression, paramIndex: num
export function isExportIdentifier(node: ts.Node): node is ts.Identifier {
return ts.isIdentifier(node) && node.text === 'exports';
}
/**
* 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;
}

View File

@ -638,7 +638,8 @@ runInEachFileSystem(() => {
` exports.d = b;\n` +
` exports.e = e;\n` +
` exports.DirectiveX = core.Directive;\n` +
` exports.SomeClass = SomeClass;\n` +
` var SomeClass_1;\n` +
` exports.SomeClass = SomeClass_1 = SomeClass;\n` +
`})));\n`,
},
{