fix(ngcc): handle CommonJS re-exports by reference (#34254)
In TS we can re-export imports using statements of the form: ``` export * from 'some-import'; ``` This can be downleveled in CommonJS to either: ``` __export(require('some-import')); ``` or ``` var someImport = require('some-import'); __export(someImport); ``` Previously we only supported the first downleveled version. This commit adds support for the second version. PR Close #34254
This commit is contained in:
parent
0b837e2f0d
commit
47666f548c
@ -137,24 +137,35 @@ export class CommonJsReflectionHost extends Esm5ReflectionHost {
|
|||||||
|
|
||||||
private extractCommonJsReexports(statement: ReexportStatement, containingFile: ts.SourceFile):
|
private extractCommonJsReexports(statement: ReexportStatement, containingFile: ts.SourceFile):
|
||||||
CommonJsExportDeclaration[] {
|
CommonJsExportDeclaration[] {
|
||||||
const reexports: CommonJsExportDeclaration[] = [];
|
const reexportArg = statement.expression.arguments[0];
|
||||||
const requireCall = statement.expression.arguments[0];
|
|
||||||
|
const requireCall = isRequireCall(reexportArg) ?
|
||||||
|
reexportArg :
|
||||||
|
ts.isIdentifier(reexportArg) ? this.findRequireCallReference(reexportArg) : null;
|
||||||
|
if (requireCall === null) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
const importPath = requireCall.arguments[0].text;
|
const importPath = requireCall.arguments[0].text;
|
||||||
const importedFile = this.resolveModuleName(importPath, containingFile);
|
const importedFile = this.resolveModuleName(importPath, containingFile);
|
||||||
if (importedFile !== undefined) {
|
if (importedFile === undefined) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
const viaModule = stripExtension(importedFile.fileName);
|
const viaModule = stripExtension(importedFile.fileName);
|
||||||
const importedExports = this.getExportsOfModule(importedFile);
|
const importedExports = this.getExportsOfModule(importedFile);
|
||||||
if (importedExports !== null) {
|
if (importedExports === null) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
const reexports: CommonJsExportDeclaration[] = [];
|
||||||
importedExports.forEach((decl, name) => {
|
importedExports.forEach((decl, name) => {
|
||||||
if (decl.node !== null) {
|
if (decl.node !== null) {
|
||||||
reexports.push({name, declaration: {node: decl.node, viaModule}});
|
reexports.push({name, declaration: {node: decl.node, viaModule}});
|
||||||
} else {
|
} else {
|
||||||
reexports.push(
|
reexports.push({name, declaration: {node: null, expression: decl.expression, viaModule}});
|
||||||
{name, declaration: {node: null, expression: decl.expression, viaModule}});
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
|
||||||
}
|
|
||||||
return reexports;
|
return reexports;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -162,11 +173,14 @@ export class CommonJsReflectionHost extends Esm5ReflectionHost {
|
|||||||
// Is `id` a namespaced property access, e.g. `Directive` in `core.Directive`?
|
// Is `id` a namespaced property access, e.g. `Directive` in `core.Directive`?
|
||||||
// If so capture the symbol of the namespace, e.g. `core`.
|
// If so capture the symbol of the namespace, e.g. `core`.
|
||||||
const nsIdentifier = findNamespaceOfIdentifier(id);
|
const nsIdentifier = findNamespaceOfIdentifier(id);
|
||||||
const nsSymbol = nsIdentifier && this.checker.getSymbolAtLocation(nsIdentifier) || null;
|
return nsIdentifier && this.findRequireCallReference(nsIdentifier);
|
||||||
const nsDeclaration = nsSymbol && nsSymbol.valueDeclaration;
|
}
|
||||||
|
|
||||||
|
private findRequireCallReference(id: ts.Identifier): RequireCall|null {
|
||||||
|
const symbol = id && this.checker.getSymbolAtLocation(id) || null;
|
||||||
|
const declaration = symbol && symbol.valueDeclaration;
|
||||||
const initializer =
|
const initializer =
|
||||||
nsDeclaration && ts.isVariableDeclaration(nsDeclaration) && nsDeclaration.initializer ||
|
declaration && ts.isVariableDeclaration(declaration) && declaration.initializer || null;
|
||||||
null;
|
|
||||||
return initializer && isRequireCall(initializer) ? initializer : null;
|
return initializer && isRequireCall(initializer) ? initializer : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -237,13 +251,12 @@ function findNamespaceOfIdentifier(id: ts.Identifier): ts.Identifier|null {
|
|||||||
null;
|
null;
|
||||||
}
|
}
|
||||||
|
|
||||||
type ReexportStatement = ts.ExpressionStatement & {expression: {arguments: [RequireCall]}};
|
type ReexportStatement = ts.ExpressionStatement & {expression: ts.CallExpression};
|
||||||
function isReexportStatement(statement: ts.Statement): statement is ReexportStatement {
|
function isReexportStatement(statement: ts.Statement): statement is ReexportStatement {
|
||||||
return ts.isExpressionStatement(statement) && ts.isCallExpression(statement.expression) &&
|
return ts.isExpressionStatement(statement) && ts.isCallExpression(statement.expression) &&
|
||||||
ts.isIdentifier(statement.expression.expression) &&
|
ts.isIdentifier(statement.expression.expression) &&
|
||||||
statement.expression.expression.text === '__export' &&
|
statement.expression.expression.text === '__export' &&
|
||||||
statement.expression.arguments.length === 1 &&
|
statement.expression.arguments.length === 1;
|
||||||
isRequireCall(statement.expression.arguments[0]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function stripExtension(fileName: string): string {
|
function stripExtension(fileName: string): string {
|
||||||
|
@ -557,7 +557,8 @@ exports.xtra2 = xtra2;
|
|||||||
function __export(m) {
|
function __export(m) {
|
||||||
for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
|
for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
|
||||||
}
|
}
|
||||||
__export(require("./b_module"));
|
var b_module = require("./b_module");
|
||||||
|
__export(b_module);
|
||||||
__export(require("./xtra_module"));
|
__export(require("./xtra_module"));
|
||||||
`
|
`
|
||||||
},
|
},
|
||||||
|
Loading…
x
Reference in New Issue
Block a user