mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
do not emit exportsStar function if module does not expose any values
This commit is contained in:
+29
-1
@@ -14493,6 +14493,33 @@ namespace ts {
|
||||
|
||||
// Emitter support
|
||||
|
||||
function moduleExportsSomeValue(moduleReferenceExpression: Expression): boolean {
|
||||
let moduleSymbol = resolveExternalModuleName(moduleReferenceExpression.parent, moduleReferenceExpression);
|
||||
if (!moduleSymbol) {
|
||||
// module not found - be conservative
|
||||
return true;
|
||||
}
|
||||
|
||||
const hasExportAssignment = getExportAssignmentSymbol(moduleSymbol) !== undefined;
|
||||
moduleSymbol = resolveExternalModuleSymbol(moduleSymbol);
|
||||
|
||||
const symbolLinks = getSymbolLinks(moduleSymbol);
|
||||
if (symbolLinks.exportsSomeValue == undefined) {
|
||||
// for export assignments - check if resolved symbol for RHS is itself a value
|
||||
// otherwise - check if at least one export is value
|
||||
symbolLinks.exportsSomeValue = hasExportAssignment
|
||||
? !!(moduleSymbol.flags & SymbolFlags.Value)
|
||||
: forEachValue(getExportsOfModule(moduleSymbol), isValue);
|
||||
}
|
||||
|
||||
return symbolLinks.exportsSomeValue;
|
||||
|
||||
function isValue(s: Symbol): boolean {
|
||||
s = resolveSymbol(s);
|
||||
return s && !!(s.flags & SymbolFlags.Value);
|
||||
}
|
||||
}
|
||||
|
||||
// When resolved as an expression identifier, if the given node references an exported entity, return the declaration
|
||||
// node of the exported entity's container. Otherwise, return undefined.
|
||||
function getReferencedExportContainer(node: Identifier): SourceFile | ModuleDeclaration | EnumDeclaration {
|
||||
@@ -14823,7 +14850,8 @@ namespace ts {
|
||||
getBlockScopedVariableId,
|
||||
getReferencedValueDeclaration,
|
||||
getTypeReferenceSerializationKind,
|
||||
isOptionalParameter
|
||||
isOptionalParameter,
|
||||
moduleExportsSomeValue
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
+22
-16
@@ -406,7 +406,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
|
||||
let externalImports: (ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration)[];
|
||||
let exportSpecifiers: Map<ExportSpecifier[]>;
|
||||
let exportEquals: ExportAssignment;
|
||||
let hasExportStars: boolean;
|
||||
let hasExportStarsToExportValues: boolean;
|
||||
|
||||
/** Write emitted output to disk */
|
||||
let writeEmittedFiles = writeJavaScriptFile;
|
||||
@@ -5892,15 +5892,17 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
|
||||
}
|
||||
else {
|
||||
// export * from "foo"
|
||||
writeLine();
|
||||
write("__export(");
|
||||
if (modulekind !== ModuleKind.AMD) {
|
||||
emitRequire(getExternalModuleName(node));
|
||||
if (hasExportStarsToExportValues && resolver.moduleExportsSomeValue(node.moduleSpecifier)) {
|
||||
writeLine();
|
||||
write("__export(");
|
||||
if (modulekind !== ModuleKind.AMD) {
|
||||
emitRequire(getExternalModuleName(node));
|
||||
}
|
||||
else {
|
||||
write(generatedName);
|
||||
}
|
||||
write(");");
|
||||
}
|
||||
else {
|
||||
write(generatedName);
|
||||
}
|
||||
write(");");
|
||||
}
|
||||
emitEnd(node);
|
||||
}
|
||||
@@ -5988,7 +5990,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
|
||||
externalImports = [];
|
||||
exportSpecifiers = {};
|
||||
exportEquals = undefined;
|
||||
hasExportStars = false;
|
||||
hasExportStarsToExportValues = false;
|
||||
for (let node of sourceFile.statements) {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.ImportDeclaration:
|
||||
@@ -6011,8 +6013,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
|
||||
if ((<ExportDeclaration>node).moduleSpecifier) {
|
||||
if (!(<ExportDeclaration>node).exportClause) {
|
||||
// export * from "mod"
|
||||
externalImports.push(<ExportDeclaration>node);
|
||||
hasExportStars = true;
|
||||
if (resolver.moduleExportsSomeValue((<ExportDeclaration>node).moduleSpecifier)) {
|
||||
externalImports.push(<ExportDeclaration>node);
|
||||
hasExportStarsToExportValues = true;
|
||||
}
|
||||
}
|
||||
else if (resolver.isValueAliasDeclaration(node)) {
|
||||
// export { x, y } from "mod" where at least one export is a value symbol
|
||||
@@ -6038,7 +6042,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
|
||||
}
|
||||
|
||||
function emitExportStarHelper() {
|
||||
if (hasExportStars) {
|
||||
if (hasExportStarsToExportValues) {
|
||||
writeLine();
|
||||
write("function __export(m) {");
|
||||
increaseIndent();
|
||||
@@ -6110,7 +6114,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
|
||||
// should always win over entries with similar names that were added via star exports
|
||||
// to support this we store names of local/indirect exported entries in a set.
|
||||
// this set is used to filter names brought by star expors.
|
||||
if (!hasExportStars) {
|
||||
if (!hasExportStarsToExportValues) {
|
||||
// local names set is needed only in presence of star exports
|
||||
return undefined;
|
||||
}
|
||||
@@ -6535,6 +6539,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
|
||||
write("});");
|
||||
}
|
||||
else {
|
||||
// collectExternalModuleInfo prefilters star exports to keep only ones that export values
|
||||
// this means that check 'resolver.moduleExportsSomeValue' is redundant and can be omitted here
|
||||
writeLine();
|
||||
// export * from 'foo'
|
||||
// emit as:
|
||||
@@ -6796,7 +6802,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
|
||||
externalImports = undefined;
|
||||
exportSpecifiers = undefined;
|
||||
exportEquals = undefined;
|
||||
hasExportStars = false;
|
||||
hasExportStarsToExportValues = false;
|
||||
emitEmitHelpers(node);
|
||||
emitCaptureThisForNodeIfNecessary(node);
|
||||
emitLinesStartingAt(node.statements, startIndex);
|
||||
@@ -6996,7 +7002,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
|
||||
externalImports = undefined;
|
||||
exportSpecifiers = undefined;
|
||||
exportEquals = undefined;
|
||||
hasExportStars = false;
|
||||
hasExportStarsToExportValues = false;
|
||||
emitEmitHelpers(node);
|
||||
emitCaptureThisForNodeIfNecessary(node);
|
||||
emitLinesStartingAt(node.statements, startIndex);
|
||||
|
||||
@@ -1602,6 +1602,7 @@ namespace ts {
|
||||
getReferencedValueDeclaration(reference: Identifier): Declaration;
|
||||
getTypeReferenceSerializationKind(typeName: EntityName): TypeReferenceSerializationKind;
|
||||
isOptionalParameter(node: ParameterDeclaration): boolean;
|
||||
moduleExportsSomeValue(moduleReferenceExpression: Expression): boolean;
|
||||
}
|
||||
|
||||
export const enum SymbolFlags {
|
||||
@@ -1718,6 +1719,7 @@ namespace ts {
|
||||
exportsChecked?: boolean; // True if exports of external module have been checked
|
||||
isNestedRedeclaration?: boolean; // True if symbol is block scoped redeclaration
|
||||
bindingElement?: BindingElement; // Binding element associated with property symbol
|
||||
exportsSomeValue?: boolean; // true if module exports some value (not just types)
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
|
||||
Reference in New Issue
Block a user