diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index e5bdb9a2585..da268892ad9 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -3090,32 +3090,39 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi } } - function emitExportMemberAssignments(name: Identifier) { + function emitExportMemberAssignmentsInNonSystemModule(name: Identifier) { + if (compilerOptions.module === ModuleKind.System) { + return; + } + if (!exportEquals && exportSpecifiers && hasProperty(exportSpecifiers, name.text)) { for (let specifier of exportSpecifiers[name.text]) { writeLine(); - if (compilerOptions.module === ModuleKind.System) { - emitStart(specifier.name); - write(`${exportFunctionForFile}("`); - emitNodeWithoutSourceMap(specifier.name); - write(`", `); - emitExpressionIdentifier(name); - write(")"); - emitEnd(specifier.name); - } - else { - emitStart(specifier.name); - emitContainingModuleName(specifier); - write("."); - emitNodeWithoutSourceMap(specifier.name); - emitEnd(specifier.name); - write(" = "); - emitExpressionIdentifier(name); - } + emitStart(specifier.name); + emitContainingModuleName(specifier); + write("."); + emitNodeWithoutSourceMap(specifier.name); + emitEnd(specifier.name); + write(" = "); + emitExpressionIdentifier(name); write(";"); } } } + + function emitExportSpecifierInSystemModule(specifier: ExportSpecifier): void { + Debug.assert(compilerOptions.module === ModuleKind.System); + + writeLine(); + emitStart(specifier.name); + write(`${exportFunctionForFile}("`); + emitNodeWithoutSourceMap(specifier.name); + write(`", `); + emitExpressionIdentifier(specifier.propertyName || specifier.name); + write(")"); + emitEnd(specifier.name); + write(";"); + } function emitDestructuring(root: BinaryExpression | VariableDeclaration | ParameterDeclaration, isAssignmentExpressionStatement: boolean, value?: Expression) { let emitCount = 0; @@ -3405,7 +3412,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi } let name = node.name; if (name.kind === SyntaxKind.Identifier) { - emitExportMemberAssignments(name); + emitExportMemberAssignmentsInNonSystemModule(name); } else if (isBindingPattern(name)) { forEach((name).elements, emitExportVariableAssignments); @@ -3660,7 +3667,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi emitSignatureAndBody(node); if (languageVersion < ScriptTarget.ES6 && node.kind === SyntaxKind.FunctionDeclaration && node.parent === currentSourceFile && node.name) { - emitExportMemberAssignments((node).name); + emitExportMemberAssignmentsInNonSystemModule((node).name); } if (node.kind !== SyntaxKind.MethodDeclaration && node.kind !== SyntaxKind.MethodSignature) { emitTrailingComments(node); @@ -4583,7 +4590,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi } if (languageVersion < ScriptTarget.ES6 && node.parent === currentSourceFile && node.name) { - emitExportMemberAssignments(node.name); + emitExportMemberAssignmentsInNonSystemModule(node.name); } } @@ -5172,7 +5179,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi emitDeclarationName(node); write(");"); } - emitExportMemberAssignments(node.name); + emitExportMemberAssignmentsInNonSystemModule(node.name); } } @@ -5293,7 +5300,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi emitDeclarationName(node); write(");"); } - emitExportMemberAssignments(node.name); + emitExportMemberAssignmentsInNonSystemModule(node.name); } } @@ -5326,7 +5333,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitExportImportAssignments(node: Node) { if (isAliasSymbolDeclaration(node) && resolver.isValueAliasDeclaration(node)) { - emitExportMemberAssignments((node).name); + emitExportMemberAssignmentsInNonSystemModule((node).name); } forEachChild(node, emitExportImportAssignments); } @@ -6134,45 +6141,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi writeLine(); // save import into the local write(`${importVariableName} = ${parameterName};`); - writeLine(); - - let defaultName = - importNode.kind === SyntaxKind.ImportDeclaration - ? (importNode).importClause.name - : (importNode).name; - - if (defaultName) { - // emit re-export for imported default name - // import n1 from 'foo1' - // import n2 = require('foo2') - // export {n1} - // export {n2} - emitExportMemberAssignments(defaultName); - writeLine(); - } - - if (importNode.kind === SyntaxKind.ImportDeclaration && - (importNode).importClause.namedBindings) { - - let namedBindings = (importNode).importClause.namedBindings; - if (namedBindings.kind === SyntaxKind.NamespaceImport) { - // emit re-export for namespace - // import * as n from 'foo' - // export {n} - emitExportMemberAssignments((namedBindings).name); - writeLine(); - } - else { - // emit re-exports for named imports - // import {a, b} from 'foo' - // export {a, b as c} - for (let element of (namedBindings).elements) { - emitExportMemberAssignments(element.name || element.propertyName); - writeLine(); - } - } - } - + writeLine(); decreaseIndent(); break; case SyntaxKind.ExportDeclaration: @@ -6226,26 +6195,39 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi writeLine(); for (let i = startIndex; i < node.statements.length; ++i) { let statement = node.statements[i]; - // - external module related imports/exports are not emitted for system modules - // - function declarations are not emitted because they were already hoisted switch (statement.kind) { + // - function declarations are not emitted because they were already hoisted + // - import declarations are not emitted since they are already handled in setters + // - export declarations with module specifiers are not emitted since they were already written in setters + // - export declarations without module specifiers are emitted preserving the order + case SyntaxKind.FunctionDeclaration: case SyntaxKind.ExportDeclaration: case SyntaxKind.ImportDeclaration: - case SyntaxKind.FunctionDeclaration: + if (statement.kind === SyntaxKind.ExportDeclaration) { + if (!(statement).moduleSpecifier) { + for (let element of (statement).exportClause.elements) { + // write call to exporter function for every export specifier in exports list + emitExportSpecifierInSystemModule(element); + } + } + } continue; case SyntaxKind.ImportEqualsDeclaration: if (!isInternalModuleImportEqualsDeclaration(statement)) { + // - import equals declarations that import external modules are not emitted continue; } - } - writeLine(); - emit(statement); + // fall-though for import declarations that import internal modules + default: + writeLine(); + emit(statement); + } } decreaseIndent(); writeLine(); write("}"); // execute } - + function emitSystemModule(node: SourceFile, startIndex: number): void { collectExternalModuleInfo(node); // System modules has the following shape diff --git a/tests/baselines/reference/systemModule10.js b/tests/baselines/reference/systemModule10.js index c63b3589085..dec185a3063 100644 --- a/tests/baselines/reference/systemModule10.js +++ b/tests/baselines/reference/systemModule10.js @@ -16,17 +16,17 @@ System.register(['file1', 'file2'], function(exports_1) { setters:[ function (_file1_1) { file1_1 = _file1_1; - exports_1("n", file1_1["default"]); - exports_1("n1", file1_1["default"]); - exports_1("x", file1_1.x); - exports_1("y", file1_1.x); }, function (_n2) { n2 = _n2; - exports_1("n2", n2); - exports_1("n3", n2); }], execute: function() { + exports_1("x", file1_1.x); + exports_1("y", file1_1.x); + exports_1("n", file1_1["default"]); + exports_1("n1", file1_1["default"]); + exports_1("n2", n2); + exports_1("n3", n2); } } }); diff --git a/tests/baselines/reference/systemModule10_ES5.js b/tests/baselines/reference/systemModule10_ES5.js index bdb920414de..c080b893513 100644 --- a/tests/baselines/reference/systemModule10_ES5.js +++ b/tests/baselines/reference/systemModule10_ES5.js @@ -16,17 +16,17 @@ System.register(['file1', 'file2'], function(exports_1) { setters:[ function (_file1_1) { file1_1 = _file1_1; - exports_1("n", file1_1.default); - exports_1("n1", file1_1.default); - exports_1("x", file1_1.x); - exports_1("y", file1_1.x); }, function (_n2) { n2 = _n2; - exports_1("n2", n2); - exports_1("n3", n2); }], execute: function() { + exports_1("x", file1_1.x); + exports_1("y", file1_1.x); + exports_1("n", file1_1.default); + exports_1("n1", file1_1.default); + exports_1("n2", n2); + exports_1("n3", n2); } } }); diff --git a/tests/baselines/reference/systemModule14.errors.txt b/tests/baselines/reference/systemModule14.errors.txt new file mode 100644 index 00000000000..6ba64896df8 --- /dev/null +++ b/tests/baselines/reference/systemModule14.errors.txt @@ -0,0 +1,16 @@ +tests/cases/compiler/systemModule14.ts(6,17): error TS2307: Cannot find module 'foo'. + + +==== tests/cases/compiler/systemModule14.ts (1 errors) ==== + + function foo() { + return a; + } + + import {a} from "foo"; + ~~~~~ +!!! error TS2307: Cannot find module 'foo'. + export {foo} + + var x = 1; + export {foo as b} \ No newline at end of file diff --git a/tests/baselines/reference/systemModule14.js b/tests/baselines/reference/systemModule14.js new file mode 100644 index 00000000000..9365754a1e5 --- /dev/null +++ b/tests/baselines/reference/systemModule14.js @@ -0,0 +1,31 @@ +//// [systemModule14.ts] + +function foo() { + return a; +} + +import {a} from "foo"; +export {foo} + +var x = 1; +export {foo as b} + +//// [systemModule14.js] +System.register(["foo"], function(exports_1) { + var foo_1; + var x; + function foo() { + return foo_1.a; + } + return { + setters:[ + function (_foo_1) { + foo_1 = _foo_1; + }], + execute: function() { + exports_1("foo", foo); + x = 1; + exports_1("b", foo); + } + } +}); diff --git a/tests/cases/compiler/systemModule14.ts b/tests/cases/compiler/systemModule14.ts new file mode 100644 index 00000000000..91192cec74a --- /dev/null +++ b/tests/cases/compiler/systemModule14.ts @@ -0,0 +1,12 @@ +// @module: system +// @isolatedModules: true + +function foo() { + return a; +} + +import {a} from "foo"; +export {foo} + +var x = 1; +export {foo as b} \ No newline at end of file