do not emit exportsStar function if module does not expose any values

This commit is contained in:
Vladimir Matveev
2015-10-04 22:00:57 -07:00
parent 331d26f402
commit 32b1ad36ec
52 changed files with 1020 additions and 22 deletions
+29 -1
View File
@@ -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
View File
@@ -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);
+2
View File
@@ -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 */