diff --git a/src/compiler/transformers/module/module.ts b/src/compiler/transformers/module/module.ts index 1568f17ecf7..7e0d1685d18 100644 --- a/src/compiler/transformers/module/module.ts +++ b/src/compiler/transformers/module/module.ts @@ -665,14 +665,9 @@ namespace ts { function visitExpressionStatement(node: ExpressionStatement): VisitResult { const original = getOriginalNode(node); - if (hasModifier(original, ModifierFlags.Export)) { - switch (original.kind) { - case SyntaxKind.EnumDeclaration: - return visitExpressionStatementForEnumDeclaration(node, original); - - case SyntaxKind.ModuleDeclaration: - return visitExpressionStatementForModuleDeclaration(node, original); - } + if (original.kind === SyntaxKind.EnumDeclaration + && hasModifier(original, ModifierFlags.Export)) { + return visitExpressionStatementForEnumDeclaration(node, original); } return node; @@ -681,28 +676,7 @@ namespace ts { function visitExpressionStatementForEnumDeclaration(node: ExpressionStatement, original: EnumDeclaration): VisitResult { if (isFirstDeclarationOfKind(original, SyntaxKind.EnumDeclaration)) { const statements: Statement[] = [node]; - addVarForExportedEnumOrModule(statements, original); - return statements; - } - - return node; - } - - function isModuleMergedWithES6Class(node: ModuleDeclaration) { - return languageVersion === ScriptTarget.ES6 - && isMergedWithClass(node); - } - - function visitExpressionStatementForModuleDeclaration(node: ExpressionStatement, original: ModuleDeclaration): VisitResult { - if (isFirstDeclarationOfKind(original, SyntaxKind.ModuleDeclaration)) { - const statements: Statement[] = [node]; - if (isModuleMergedWithES6Class(original)) { - addAssignmentForExportedModule(statements, original); - } - else { - addVarForExportedEnumOrModule(statements, original); - } - + addVarForExportedEnumDeclaration(statements, original); return statements; } @@ -712,7 +686,7 @@ namespace ts { /** * Adds a trailing VariableStatement for an enum or module declaration. */ - function addVarForExportedEnumOrModule(statements: Statement[], node: EnumDeclaration | ModuleDeclaration) { + function addVarForExportedEnumDeclaration(statements: Statement[], node: EnumDeclaration | ModuleDeclaration) { statements.push( createVariableStatement( /*modifiers*/ undefined, @@ -725,21 +699,6 @@ namespace ts { ); } - /** - * Adds a trailing assignment for a module declaration. - */ - function addAssignmentForExportedModule(statements: Statement[], node: ModuleDeclaration) { - statements.push( - createStatement( - createAssignment( - getDeclarationName(node), - createPropertyAccess(createIdentifier("exports"), getDeclarationName(node)) - ), - /*location*/ node - ) - ); - } - function getDeclarationName(node: DeclarationStatement) { return node.name ? getSynthesizedClone(node.name) : getGeneratedNameForNode(node); } diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts index 968ac152065..b9f10f21330 100644 --- a/src/compiler/transformers/ts.ts +++ b/src/compiler/transformers/ts.ts @@ -27,6 +27,7 @@ namespace ts { const resolver = context.getEmitResolver(); const compilerOptions = context.getCompilerOptions(); const languageVersion = getEmitScriptTarget(compilerOptions); + const moduleKind = getEmitModuleKind(compilerOptions); // Save the previous transformation hooks. const previousOnEmitNode = context.onEmitNode; @@ -2167,14 +2168,32 @@ namespace ts { return createPartiallyEmittedExpression(expression, node); } + /** + * Determines whether to emit an enum declaration. + * + * @param node The enum declaration node. + */ + function shouldEmitEnumDeclaration(node: EnumDeclaration) { + return !isConst(node) + || compilerOptions.preserveConstEnums + || compilerOptions.isolatedModules; + } + + function shouldEmitVarForEnumDeclaration(node: EnumDeclaration | ModuleDeclaration) { + return !hasModifier(node, ModifierFlags.Export) + || (isES6ExportedDeclaration(node) && isFirstDeclarationOfKind(node, node.kind)); + } + /** * Adds a leading VariableStatement for an enum or module declaration. */ - function addVarForEnumOrModuleDeclaration(statements: Statement[], node: EnumDeclaration | ModuleDeclaration) { + function addVarForEnumDeclaration(statements: Statement[], node: EnumDeclaration) { // Emit a variable statement for the enum. statements.push( createVariableStatement( - visitNodes(node.modifiers, visitor, isModifier), + isES6ExportedDeclaration(node) + ? visitNodes(node.modifiers, visitor, isModifier) + : undefined, [createVariableDeclaration( getDeclarationName(node) )], @@ -2186,7 +2205,7 @@ namespace ts { /** * Adds a trailing VariableStatement for an enum or module declaration. */ - function addVarForEnumOrModuleExportedFromNamespace(statements: Statement[], node: EnumDeclaration | ModuleDeclaration) { + function addVarForEnumExportedFromNamespace(statements: Statement[], node: EnumDeclaration | ModuleDeclaration) { statements.push( createVariableStatement( /*modifiers*/ undefined, @@ -2199,34 +2218,6 @@ namespace ts { ) } - function addAssignmentForModuleExportedFromNamespace(statements: Statement[], node: ModuleDeclaration) { - statements.push( - createStatement( - createAssignment( - getDeclarationName(node), - setNodeEmitFlags(getDeclarationName(node), NodeEmitFlags.PrefixExportedLocal) - ), - /*location*/ node - ) - ); - } - - /** - * Determines whether to emit an enum declaration. - * - * @param node The enum declaration node. - */ - function shouldEmitEnumDeclaration(node: EnumDeclaration) { - return !isConst(node) - || compilerOptions.preserveConstEnums - || compilerOptions.isolatedModules; - } - - function shouldEmitVarForEnumOrModuleDeclaration(node: EnumDeclaration | ModuleDeclaration) { - return !hasModifier(node, ModifierFlags.Export) - || (isExternalModuleExport(node) && isFirstDeclarationOfKind(node, node.kind)); - } - /** * Visits an enum declaration. * @@ -2240,8 +2231,8 @@ namespace ts { } const statements: Statement[] = []; - if (shouldEmitVarForEnumOrModuleDeclaration(node)) { - addVarForEnumOrModuleDeclaration(statements, node); + if (shouldEmitVarForEnumDeclaration(node)) { + addVarForEnumDeclaration(statements, node); } const localName = getGeneratedNameForNode(node); @@ -2276,7 +2267,7 @@ namespace ts { ); if (isNamespaceExport(node)) { - addVarForEnumOrModuleExportedFromNamespace(statements, node); + addVarForEnumExportedFromNamespace(statements, node); } return statements; @@ -2357,6 +2348,38 @@ namespace ts { && isMergedWithClass(node); } + function isES6ExportedDeclaration(node: Node) { + return isExternalModuleExport(node) + && moduleKind >= ModuleKind.ES6; + } + + function shouldEmitVarForModuleDeclaration(node: ModuleDeclaration) { + return !isModuleMergedWithES6Class(node) + && (!isES6ExportedDeclaration(node) + || isFirstDeclarationOfKind(node, node.kind)); + } + + /** + * Adds a leading VariableStatement for a module declaration. + */ + function addVarForModuleDeclaration(statements: Statement[], node: ModuleDeclaration) { + // Emit a variable statement for the module. + statements.push( + setOriginalNode( + createVariableStatement( + isES6ExportedDeclaration(node) + ? visitNodes(node.modifiers, visitor, isModifier) + : undefined, + [createVariableDeclaration( + getDeclarationName(node) + )], + /*location*/ node + ), + node + ) + ); + } + /** * Visits a module declaration node. * @@ -2373,8 +2396,9 @@ namespace ts { enableExpressionSubstitutionForNamespaceExports(); const statements: Statement[] = []; - if (!isModuleMergedWithES6Class(node) && (isNamespaceExport(node) || shouldEmitVarForEnumOrModuleDeclaration(node))) { - addVarForEnumOrModuleDeclaration(statements, node); + + if (shouldEmitVarForModuleDeclaration(node)) { + addVarForModuleDeclaration(statements, node); } const localName = getGeneratedNameForNode(node); @@ -2389,7 +2413,7 @@ namespace ts { ) ); - if (isNamespaceExport(node)) { + if (hasModifier(node, ModifierFlags.Export) && !isES6ExportedDeclaration(node)) { moduleArg = createAssignment(getDeclarationName(node), moduleArg); }