From e5e2340af9215bb541d1301f67c97bd5cf01c8b4 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Mon, 21 Mar 2016 17:31:24 -0700 Subject: [PATCH] Fixes issue with variable declarations for modules --- src/compiler/transformers/ts.ts | 91 ++++++++++++++++++--------------- 1 file changed, 51 insertions(+), 40 deletions(-) diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts index a8619495f11..464bfb6ce2c 100644 --- a/src/compiler/transformers/ts.ts +++ b/src/compiler/transformers/ts.ts @@ -2172,7 +2172,7 @@ namespace ts { if (!isExported(node) || (isExternalModuleExport(node) && isFirstDeclarationOfKind(node, SyntaxKind.EnumDeclaration))) { // Emit a VariableStatement if the enum is not exported, or is the first enum // with the same name exported from an external module. - addNode(statements, + statements.push( createVariableStatement( visitNodes(node.modifiers, visitor, isModifier), createVariableDeclarationList([ @@ -2189,7 +2189,12 @@ namespace ts { : getSynthesizedClone(node.name); currentNamespaceLocalName = getGeneratedNameForNode(node); - addNode(statements, + + // (function (x) { + // x[x["y"] = 0] = "y"; + // ... + // })(x || (x = {})); + statements.push( createStatement( createCall( createParen( @@ -2207,7 +2212,7 @@ namespace ts { createObjectLiteral() ) )] - ), + ), location ) ); @@ -2365,6 +2370,31 @@ namespace ts { return child; } + /** + * Determines whether to elide a module declaration. + * + * @param node The module declaration node. + */ + function shouldEmitModuleDeclaration(node: ModuleDeclaration) { + return isInstantiatedModule(node, compilerOptions.preserveConstEnums || compilerOptions.isolatedModules); + } + + /** + * Determines whether a module declaration has a name that merges with a class declaration. + * + * @param node The module declaration node. + */ + function isModuleMergedWithClass(node: ModuleDeclaration) { + return languageVersion === ScriptTarget.ES6 + && !!(resolver.getNodeCheckFlags(getOriginalNode(node)) & NodeCheckFlags.LexicalModuleMergesWithClass); + } + + function shouldEmitVarForModuleDeclaration(node: ModuleDeclaration) { + return !isModuleMergedWithClass(node) + && (!isExternalModuleExport(node) + || isFirstDeclarationOfKind(node, SyntaxKind.ModuleDeclaration)); + } + /** * Visits a module declaration node. * @@ -2373,7 +2403,7 @@ namespace ts { * @param node The module declaration node. */ function visitModuleDeclaration(node: ModuleDeclaration): VisitResult { - if (shouldElideModuleDeclaration(node)) { + if (!shouldEmitModuleDeclaration(node)) { return undefined; } @@ -2382,43 +2412,37 @@ namespace ts { enableExpressionSubstitutionForNamespaceExports(); const savedCurrentNamespaceLocalName = currentNamespaceLocalName; - const modifiers = visitNodes(node.modifiers, visitor, isModifier); + const savedCurrentNamespace = currentNamespace; const statements: Statement[] = []; - let location = node; - if (!isModuleMergedWithClass(node)) { + if (shouldEmitVarForModuleDeclaration(node)) { // var x; statements.push( createVariableStatement( - modifiers, + visitNodes(node.modifiers, visitor, isModifier), createVariableDeclarationList([ createVariableDeclaration(node.name) ]), - location + /*location*/ node ) ); - location = undefined; } const name = isNamespaceExport(node) ? getNamespaceMemberName(node.name) : getSynthesizedClone(node.name); - let moduleParam: Expression = createLogicalOr( + currentNamespaceLocalName = getGeneratedNameForNode(node); + currentNamespace = node; + + const moduleParam = createLogicalOr( name, createAssignment( name, - createObjectLiteral([]) + createObjectLiteral() ) ); - if (isNamespaceExport(node)) { - moduleParam = createAssignment(getSynthesizedClone(node.name), moduleParam); - } - - currentNamespaceLocalName = getGeneratedNameForNode(node); - currentNamespace = node; - // (function (x_1) { // x_1.y = ...; // })(x || (x = {})); @@ -2435,8 +2459,13 @@ namespace ts { transformModuleBody(node) ) ), - [moduleParam] - ) + [ + isNamespaceExport(node) + ? createAssignment(getSynthesizedClone(node.name), moduleParam) + : moduleParam + ] + ), + /*location*/ node ), node ), @@ -2445,6 +2474,7 @@ namespace ts { ); currentNamespaceLocalName = savedCurrentNamespaceLocalName; + currentNamespace = savedCurrentNamespace; return statements; } @@ -2468,24 +2498,6 @@ namespace ts { return createBlock(statements, /*location*/ undefined, /*multiLine*/ true); } - /** - * Determines whether to elide a module declaration. - * - * @param node The module declaration node. - */ - function shouldElideModuleDeclaration(node: ModuleDeclaration) { - return !isInstantiatedModule(node, compilerOptions.preserveConstEnums || compilerOptions.isolatedModules); - } - - /** - * Determines whether a module declaration has a name that merges with a class declaration. - * - * @param node The module declaration node. - */ - function isModuleMergedWithClass(node: ModuleDeclaration) { - return !!(resolver.getNodeCheckFlags(getOriginalNode(node)) & NodeCheckFlags.LexicalModuleMergesWithClass); - } - /** * Visits an import equals declaration. * @@ -2584,7 +2596,6 @@ namespace ts { return isExternalModuleExport(node) && hasModifier(node, ModifierFlags.Default); } - /** * Gets a value indicating whether a node is the first declaration of its kind. *