diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index da268892ad9..76d07395f32 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -6058,7 +6058,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi return compilerOptions.module === ModuleKind.System && isExternalModule(currentSourceFile); } - function emitSystemModuleBody(node: SourceFile, startIndex: number): void { + function emitSystemModuleBody(node: SourceFile, dependencyGroups: DependencyGroup[], startIndex: number): void { // shape of the body in system modules: // function (exports) { // @@ -6103,7 +6103,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi write("return {"); increaseIndent(); writeLine(); - emitSetters(exportStarFunction); + emitSetters(exportStarFunction, dependencyGroups); writeLine(); emitExecute(node, startIndex); decreaseIndent(); @@ -6112,77 +6112,83 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi emitTempDeclarations(/*newLine*/ true); } - function emitSetters(exportStarFunction: string) { + function emitSetters(exportStarFunction: string, dependencyGroups: DependencyGroup[]) { write("setters:["); - for (let i = 0; i < externalImports.length; ++i) { + + for (let i = 0; i < dependencyGroups.length; ++i) { if (i !== 0) { write(","); } writeLine(); increaseIndent(); - let importNode = externalImports[i]; - let importVariableName = getLocalNameForExternalImport(importNode) || ""; - let parameterName = "_" + importVariableName; + + let group = dependencyGroups[i]; + + // derive a unique name for parameter from the first named entry in the group + let parameterName = makeUniqueName(forEach(group, getLocalNameForExternalImport) || ""); write(`function (${parameterName}) {`); - - switch (importNode.kind) { - case SyntaxKind.ImportDeclaration: - if (!(importNode).importClause) { - // 'import "..."' case - // module is imported only for side-effects, setter body will be empty - break; - } - // fall-through - case SyntaxKind.ImportEqualsDeclaration: - Debug.assert(importVariableName !== ""); - - increaseIndent(); - writeLine(); - // save import into the local - write(`${importVariableName} = ${parameterName};`); - writeLine(); - decreaseIndent(); - break; - case SyntaxKind.ExportDeclaration: - Debug.assert(importVariableName !== ""); - - increaseIndent(); - - if ((importNode).exportClause) { - // export {a, b as c} from 'foo' - // emit as: - // var reexports = {} - // reexports['a'] = _foo["a"]; - // reexports['c'] = _foo["b"]; - // exports_(reexports); - let reexportsVariableName = makeUniqueName("reexports"); - writeLine(); - write(`var ${reexportsVariableName} = {};`); - writeLine(); - for (let e of (importNode).exportClause.elements) { - write(`${reexportsVariableName}["`); - emitNodeWithoutSourceMap(e.name); - write(`"] = ${parameterName}["`); - emitNodeWithoutSourceMap(e.propertyName || e.name); - write(`"];`); - writeLine(); + increaseIndent(); + + for(let entry of group) { + let importVariableName = getLocalNameForExternalImport(entry) || ""; + + switch (entry.kind) { + case SyntaxKind.ImportDeclaration: + if (!(entry).importClause) { + // 'import "..."' case + // module is imported only for side-effects, no emit required + break; } - write(`${exportFunctionForFile}(${reexportsVariableName});`); - } - else { - writeLine(); - // export * from 'foo' - // emit as: - // exportStar(_foo); - write(`${exportStarFunction}(${parameterName});`); - } + // fall-through + case SyntaxKind.ImportEqualsDeclaration: + Debug.assert(importVariableName !== ""); + + writeLine(); + // save import into the local + write(`${importVariableName} = ${parameterName};`); + writeLine(); + break; + case SyntaxKind.ExportDeclaration: + Debug.assert(importVariableName !== ""); + + if ((entry).exportClause) { + // export {a, b as c} from 'foo' + // emit as: + // var reexports = {} + // reexports['a'] = _foo["a"]; + // reexports['c'] = _foo["b"]; + // exports_(reexports); + let reexportsVariableName = makeUniqueName("reexports"); + writeLine(); + write(`var ${reexportsVariableName} = {};`); + writeLine(); + for (let e of (entry).exportClause.elements) { + write(`${reexportsVariableName}["`); + emitNodeWithoutSourceMap(e.name); + write(`"] = ${parameterName}["`); + emitNodeWithoutSourceMap(e.propertyName || e.name); + write(`"];`); + writeLine(); + } + write(`${exportFunctionForFile}(${reexportsVariableName});`); + } + else { + writeLine(); + // export * from 'foo' + // emit as: + // exportStar(_foo); + write(`${exportStarFunction}(${parameterName});`); + } + + writeLine(); + break; + } - writeLine(); - decreaseIndent(); - break; } + decreaseIndent(); + write("}"); decreaseIndent(); } @@ -6228,6 +6234,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi write("}"); // execute } + type DependencyGroup = Array; + function emitSystemModule(node: SourceFile, startIndex: number): void { collectExternalModuleInfo(node); // System modules has the following shape @@ -6247,8 +6255,23 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi write(`"${node.moduleName}", `); } write("["); + + let groupIndices: Map = {}; + let dependencyGroups: DependencyGroup[] = []; + for (let i = 0; i < externalImports.length; ++i) { let text = getExternalModuleNameText(externalImports[i]); + if (hasProperty(groupIndices, text)) { + // deduplicate/group entries in dependency list by the dependency name + let groupIndex = groupIndices[text]; + dependencyGroups[groupIndex].push(externalImports[i]); + continue; + } + else { + groupIndices[text] = dependencyGroups.length; + dependencyGroups.push([externalImports[i]]); + } + if (i !== 0) { write(", "); } @@ -6259,7 +6282,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi increaseIndent(); emitEmitHelpers(node); emitCaptureThisForNodeIfNecessary(node); - emitSystemModuleBody(node, startIndex); + emitSystemModuleBody(node, dependencyGroups, startIndex); decreaseIndent(); writeLine(); write("});"); diff --git a/tests/baselines/reference/aliasesInSystemModule1.js b/tests/baselines/reference/aliasesInSystemModule1.js index 28ac1e9b4ad..05f74aef852 100644 --- a/tests/baselines/reference/aliasesInSystemModule1.js +++ b/tests/baselines/reference/aliasesInSystemModule1.js @@ -22,8 +22,8 @@ System.register(['foo'], function(exports_1) { var cls, cls2, x, y, z, M; return { setters:[ - function (_alias) { - alias = _alias; + function (alias_1) { + alias = alias_1; }], execute: function() { cls = alias.Class; diff --git a/tests/baselines/reference/aliasesInSystemModule2.js b/tests/baselines/reference/aliasesInSystemModule2.js index 0256d03a179..32d663a11e1 100644 --- a/tests/baselines/reference/aliasesInSystemModule2.js +++ b/tests/baselines/reference/aliasesInSystemModule2.js @@ -21,8 +21,8 @@ System.register(["foo"], function(exports_1) { var cls, cls2, x, y, z, M; return { setters:[ - function (_foo_1) { - foo_1 = _foo_1; + function (foo_1_1) { + foo_1 = foo_1_1; }], execute: function() { cls = foo_1.alias.Class; diff --git a/tests/baselines/reference/systemModule10.js b/tests/baselines/reference/systemModule10.js index dec185a3063..fcecfc9b0f8 100644 --- a/tests/baselines/reference/systemModule10.js +++ b/tests/baselines/reference/systemModule10.js @@ -14,11 +14,11 @@ System.register(['file1', 'file2'], function(exports_1) { var file1_1, n2; return { setters:[ - function (_file1_1) { - file1_1 = _file1_1; + function (file1_1_1) { + file1_1 = file1_1_1; }, - function (_n2) { - n2 = _n2; + function (n2_1) { + n2 = n2_1; }], execute: function() { exports_1("x", file1_1.x); diff --git a/tests/baselines/reference/systemModule10_ES5.js b/tests/baselines/reference/systemModule10_ES5.js index c080b893513..a86088a3463 100644 --- a/tests/baselines/reference/systemModule10_ES5.js +++ b/tests/baselines/reference/systemModule10_ES5.js @@ -14,11 +14,11 @@ System.register(['file1', 'file2'], function(exports_1) { var file1_1, n2; return { setters:[ - function (_file1_1) { - file1_1 = _file1_1; + function (file1_1_1) { + file1_1 = file1_1_1; }, - function (_n2) { - n2 = _n2; + function (n2_1) { + n2 = n2_1; }], execute: function() { exports_1("x", file1_1.x); diff --git a/tests/baselines/reference/systemModule11.js b/tests/baselines/reference/systemModule11.js index 34dd0d3df5f..7111968f3ce 100644 --- a/tests/baselines/reference/systemModule11.js +++ b/tests/baselines/reference/systemModule11.js @@ -59,8 +59,8 @@ System.register(['bar'], function(exports_1) { } return { setters:[ - function (_bar_1) { - exportStar_1(_bar_1); + function (bar_1_1) { + exportStar_1(bar_1_1); }], execute: function() { } @@ -82,8 +82,8 @@ System.register(['bar'], function(exports_1) { } return { setters:[ - function (_bar_1) { - exportStar_1(_bar_1); + function (bar_1_1) { + exportStar_1(bar_1_1); }], execute: function() { exports_1("x", x); @@ -108,14 +108,14 @@ System.register(['a', 'bar'], function(exports_1) { } return { setters:[ - function (_a_1) { + function (a_1_1) { var reexports_1 = {}; - reexports_1["x"] = _a_1["x"]; - reexports_1["z"] = _a_1["y"]; + reexports_1["x"] = a_1_1["x"]; + reexports_1["z"] = a_1_1["y"]; exports_1(reexports_1); }, - function (_bar_1) { - exportStar_1(_bar_1); + function (bar_1_1) { + exportStar_1(bar_1_1); }], execute: function() { } @@ -130,10 +130,10 @@ System.register(['a'], function(exports_1) { exports_1("default", default_1); return { setters:[ - function (_a_1) { + function (a_1_1) { var reexports_1 = {}; - reexports_1["s"] = _a_1["s"]; - reexports_1["s2"] = _a_1["s1"]; + reexports_1["s"] = a_1_1["s"]; + reexports_1["s2"] = a_1_1["s1"]; exports_1(reexports_1); }], execute: function() { @@ -154,8 +154,8 @@ System.register(['a'], function(exports_1) { } return { setters:[ - function (_a_1) { - exportStar_1(_a_1); + function (a_1_1) { + exportStar_1(a_1_1); }], execute: function() { } diff --git a/tests/baselines/reference/systemModule14.js b/tests/baselines/reference/systemModule14.js index 9365754a1e5..76906db5980 100644 --- a/tests/baselines/reference/systemModule14.js +++ b/tests/baselines/reference/systemModule14.js @@ -19,8 +19,8 @@ System.register(["foo"], function(exports_1) { } return { setters:[ - function (_foo_1) { - foo_1 = _foo_1; + function (foo_1_1) { + foo_1 = foo_1_1; }], execute: function() { exports_1("foo", foo); diff --git a/tests/baselines/reference/systemModule15.js b/tests/baselines/reference/systemModule15.js new file mode 100644 index 00000000000..4d5536cbaa1 --- /dev/null +++ b/tests/baselines/reference/systemModule15.js @@ -0,0 +1,88 @@ +//// [tests/cases/compiler/systemModule15.ts] //// + +//// [file1.ts] + + +import * as moduleB from "./file2" + +declare function use(v: any): void; + +use(moduleB.value); +use(moduleB.moduleC); +use(moduleB.moduleCStar); + +//// [file2.ts] + +import * as moduleCStar from "./file3" +import {value2} from "./file4" +import moduleC from "./file3" +import {value} from "./file3" + +export { + moduleCStar, + moduleC, + value +} + +//// [file3.ts] + +export var value = "youpi"; +export default value; + +//// [file4.ts] + +export var value2 = "v"; + +//// [file3.js] +System.register([], function(exports_1) { + var value; + return { + setters:[], + execute: function() { + exports_1("value", value = "youpi"); + exports_1("default",value); + } + } +}); +//// [file4.js] +System.register([], function(exports_1) { + var value2; + return { + setters:[], + execute: function() { + exports_1("value2", value2 = "v"); + } + } +}); +//// [file2.js] +System.register(["./file3"], function(exports_1) { + var moduleCStar, file3_1, file3_2; + return { + setters:[ + function (moduleCStar_1) { + moduleCStar = moduleCStar_1; + file3_1 = moduleCStar_1; + file3_2 = moduleCStar_1; + }], + execute: function() { + exports_1("moduleCStar", moduleCStar); + exports_1("moduleC", file3_1["default"]); + exports_1("value", file3_2.value); + } + } +}); +//// [file1.js] +System.register(["./file2"], function(exports_1) { + var moduleB; + return { + setters:[ + function (moduleB_1) { + moduleB = moduleB_1; + }], + execute: function() { + use(moduleB.value); + use(moduleB.moduleC); + use(moduleB.moduleCStar); + } + } +}); diff --git a/tests/baselines/reference/systemModule15.symbols b/tests/baselines/reference/systemModule15.symbols new file mode 100644 index 00000000000..2572950a7f2 --- /dev/null +++ b/tests/baselines/reference/systemModule15.symbols @@ -0,0 +1,66 @@ +=== tests/cases/compiler/file1.ts === + + +import * as moduleB from "./file2" +>moduleB : Symbol(moduleB, Decl(file1.ts, 2, 6)) + +declare function use(v: any): void; +>use : Symbol(use, Decl(file1.ts, 2, 34)) +>v : Symbol(v, Decl(file1.ts, 4, 21)) + +use(moduleB.value); +>use : Symbol(use, Decl(file1.ts, 2, 34)) +>moduleB.value : Symbol(moduleB.value, Decl(file2.ts, 8, 12)) +>moduleB : Symbol(moduleB, Decl(file1.ts, 2, 6)) +>value : Symbol(moduleB.value, Decl(file2.ts, 8, 12)) + +use(moduleB.moduleC); +>use : Symbol(use, Decl(file1.ts, 2, 34)) +>moduleB.moduleC : Symbol(moduleB.moduleC, Decl(file2.ts, 7, 16)) +>moduleB : Symbol(moduleB, Decl(file1.ts, 2, 6)) +>moduleC : Symbol(moduleB.moduleC, Decl(file2.ts, 7, 16)) + +use(moduleB.moduleCStar); +>use : Symbol(use, Decl(file1.ts, 2, 34)) +>moduleB.moduleCStar : Symbol(moduleB.moduleCStar, Decl(file2.ts, 6, 8)) +>moduleB : Symbol(moduleB, Decl(file1.ts, 2, 6)) +>moduleCStar : Symbol(moduleB.moduleCStar, Decl(file2.ts, 6, 8)) + +=== tests/cases/compiler/file2.ts === + +import * as moduleCStar from "./file3" +>moduleCStar : Symbol(moduleCStar, Decl(file2.ts, 1, 6)) + +import {value2} from "./file4" +>value2 : Symbol(value2, Decl(file2.ts, 2, 8)) + +import moduleC from "./file3" +>moduleC : Symbol(moduleC, Decl(file2.ts, 3, 6)) + +import {value} from "./file3" +>value : Symbol(value, Decl(file2.ts, 4, 8)) + +export { + moduleCStar, +>moduleCStar : Symbol(moduleCStar, Decl(file2.ts, 6, 8)) + + moduleC, +>moduleC : Symbol(moduleC, Decl(file2.ts, 7, 16)) + + value +>value : Symbol(value, Decl(file2.ts, 8, 12)) +} + +=== tests/cases/compiler/file3.ts === + +export var value = "youpi"; +>value : Symbol(value, Decl(file3.ts, 1, 10)) + +export default value; +>value : Symbol(value, Decl(file3.ts, 1, 10)) + +=== tests/cases/compiler/file4.ts === + +export var value2 = "v"; +>value2 : Symbol(value2, Decl(file4.ts, 1, 10)) + diff --git a/tests/baselines/reference/systemModule15.types b/tests/baselines/reference/systemModule15.types new file mode 100644 index 00000000000..502638dab93 --- /dev/null +++ b/tests/baselines/reference/systemModule15.types @@ -0,0 +1,71 @@ +=== tests/cases/compiler/file1.ts === + + +import * as moduleB from "./file2" +>moduleB : typeof moduleB + +declare function use(v: any): void; +>use : (v: any) => void +>v : any + +use(moduleB.value); +>use(moduleB.value) : void +>use : (v: any) => void +>moduleB.value : string +>moduleB : typeof moduleB +>value : string + +use(moduleB.moduleC); +>use(moduleB.moduleC) : void +>use : (v: any) => void +>moduleB.moduleC : string +>moduleB : typeof moduleB +>moduleC : string + +use(moduleB.moduleCStar); +>use(moduleB.moduleCStar) : void +>use : (v: any) => void +>moduleB.moduleCStar : typeof +>moduleB : typeof moduleB +>moduleCStar : typeof + +=== tests/cases/compiler/file2.ts === + +import * as moduleCStar from "./file3" +>moduleCStar : typeof moduleCStar + +import {value2} from "./file4" +>value2 : string + +import moduleC from "./file3" +>moduleC : string + +import {value} from "./file3" +>value : string + +export { + moduleCStar, +>moduleCStar : typeof moduleCStar + + moduleC, +>moduleC : string + + value +>value : string +} + +=== tests/cases/compiler/file3.ts === + +export var value = "youpi"; +>value : string +>"youpi" : string + +export default value; +>value : string + +=== tests/cases/compiler/file4.ts === + +export var value2 = "v"; +>value2 : string +>"v" : string + diff --git a/tests/baselines/reference/systemModule16.errors.txt b/tests/baselines/reference/systemModule16.errors.txt new file mode 100644 index 00000000000..8c79c9218e4 --- /dev/null +++ b/tests/baselines/reference/systemModule16.errors.txt @@ -0,0 +1,33 @@ +tests/cases/compiler/systemModule16.ts(2,20): error TS2307: Cannot find module 'foo'. +tests/cases/compiler/systemModule16.ts(3,20): error TS2307: Cannot find module 'bar'. +tests/cases/compiler/systemModule16.ts(4,15): error TS2307: Cannot find module 'foo'. +tests/cases/compiler/systemModule16.ts(5,15): error TS2307: Cannot find module 'bar'. +tests/cases/compiler/systemModule16.ts(8,32): error TS2307: Cannot find module 'foo'. +tests/cases/compiler/systemModule16.ts(9,32): error TS2307: Cannot find module 'bar'. + + +==== tests/cases/compiler/systemModule16.ts (6 errors) ==== + + import * as x from "foo"; + ~~~~~ +!!! error TS2307: Cannot find module 'foo'. + import * as y from "bar"; + ~~~~~ +!!! error TS2307: Cannot find module 'bar'. + export * from "foo"; + ~~~~~ +!!! error TS2307: Cannot find module 'foo'. + export * from "bar" + ~~~~~ +!!! error TS2307: Cannot find module 'bar'. + export {x} + export {y} + import {a1, b1, c1 as d1} from "foo"; + ~~~~~ +!!! error TS2307: Cannot find module 'foo'. + export {a2, b2, c2 as d2} from "bar"; + ~~~~~ +!!! error TS2307: Cannot find module 'bar'. + + x,y,a1,b1,d1; + \ No newline at end of file diff --git a/tests/baselines/reference/systemModule16.js b/tests/baselines/reference/systemModule16.js new file mode 100644 index 00000000000..0c53275cdd8 --- /dev/null +++ b/tests/baselines/reference/systemModule16.js @@ -0,0 +1,54 @@ +//// [systemModule16.ts] + +import * as x from "foo"; +import * as y from "bar"; +export * from "foo"; +export * from "bar" +export {x} +export {y} +import {a1, b1, c1 as d1} from "foo"; +export {a2, b2, c2 as d2} from "bar"; + +x,y,a1,b1,d1; + + +//// [systemModule16.js] +System.register(["foo", "bar"], function(exports_1) { + var x, y, foo_1; + var exportedNames_1 = { + 'x': true, + 'y': true, + 'a2': true, + 'b2': true, + 'd2': true + }; + function exportStar_1(m) { + var exports = {}; + for(var n in m) { + if (n !== "default"&& !exportedNames_1.hasOwnProperty(n)) exports[n] = m[n]; + } + exports_1(exports); + } + return { + setters:[ + function (x_1) { + x = x_1; + exportStar_1(x_1); + foo_1 = x_1; + }, + function (y_1) { + y = y_1; + exportStar_1(y_1); + var reexports_1 = {}; + reexports_1["a2"] = y_1["a2"]; + reexports_1["b2"] = y_1["b2"]; + reexports_1["d2"] = y_1["c2"]; + exports_1(reexports_1); + }], + execute: function() { + exports_1("x", x); + exports_1("y", y); + x, y, foo_1.a1, foo_1.b1, foo_1.c1; + } + } +}); diff --git a/tests/baselines/reference/systemModule9.js b/tests/baselines/reference/systemModule9.js index c282a47b686..d7913f2f8b7 100644 --- a/tests/baselines/reference/systemModule9.js +++ b/tests/baselines/reference/systemModule9.js @@ -38,24 +38,24 @@ System.register(['file1', 'file2', 'file3', 'file4', 'file5', 'file6', 'file7'], } return { setters:[ - function (_ns) { - ns = _ns; + function (ns_1) { + ns = ns_1; }, - function (_file2_1) { - file2_1 = _file2_1; + function (file2_1_1) { + file2_1 = file2_1_1; }, - function (_file3_1) { - file3_1 = _file3_1; + function (file3_1_1) { + file3_1 = file3_1_1; }, - function (_) {}, - function (_file5_1) { - file5_1 = _file5_1; + function (_1) {}, + function (file5_1_1) { + file5_1 = file5_1_1; }, - function (_ns3) { - ns3 = _ns3; + function (ns3_1) { + ns3 = ns3_1; }, - function (_file7_1) { - exportStar_1(_file7_1); + function (file7_1_1) { + exportStar_1(file7_1_1); }], execute: function() { ns.f(); diff --git a/tests/baselines/reference/systemModuleWithSuperClass.js b/tests/baselines/reference/systemModuleWithSuperClass.js index 3484606ee0e..9d1e87fbc66 100644 --- a/tests/baselines/reference/systemModuleWithSuperClass.js +++ b/tests/baselines/reference/systemModuleWithSuperClass.js @@ -38,8 +38,8 @@ System.register(['./foo'], function(exports_1) { var Bar; return { setters:[ - function (_foo_1) { - foo_1 = _foo_1; + function (foo_1_1) { + foo_1 = foo_1_1; }], execute: function() { Bar = (function (_super) { diff --git a/tests/cases/compiler/systemModule15.ts b/tests/cases/compiler/systemModule15.ts new file mode 100644 index 00000000000..2c29f0a5d20 --- /dev/null +++ b/tests/cases/compiler/systemModule15.ts @@ -0,0 +1,34 @@ +// @module: system +// @isolatedModules: true + +// @filename: file1.ts + +import * as moduleB from "./file2" + +declare function use(v: any): void; + +use(moduleB.value); +use(moduleB.moduleC); +use(moduleB.moduleCStar); + +// @filename: file2.ts + +import * as moduleCStar from "./file3" +import {value2} from "./file4" +import moduleC from "./file3" +import {value} from "./file3" + +export { + moduleCStar, + moduleC, + value +} + +// @filename: file3.ts + +export var value = "youpi"; +export default value; + +// @filename: file4.ts + +export var value2 = "v"; \ No newline at end of file diff --git a/tests/cases/compiler/systemModule16.ts b/tests/cases/compiler/systemModule16.ts new file mode 100644 index 00000000000..ba64bd32b59 --- /dev/null +++ b/tests/cases/compiler/systemModule16.ts @@ -0,0 +1,13 @@ +// @module: system +// @isolatedModules: true + +import * as x from "foo"; +import * as y from "bar"; +export * from "foo"; +export * from "bar" +export {x} +export {y} +import {a1, b1, c1 as d1} from "foo"; +export {a2, b2, c2 as d2} from "bar"; + +x,y,a1,b1,d1;