deduplicate module dependencies

This commit is contained in:
Vladimir Matveev 2015-08-06 16:38:53 -07:00
parent eab6911bce
commit 02539d91e2
16 changed files with 487 additions and 105 deletions

View file

@ -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) {
// <list of local aliases for imports>
@ -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 (!(<ImportDeclaration>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 ((<ExportDeclaration>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 (<ExportDeclaration>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 (!(<ImportDeclaration>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 ((<ExportDeclaration>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 (<ExportDeclaration>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<ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration>;
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<number> = {};
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("});");

View file

@ -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;

View file

@ -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;

View file

@ -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);

View file

@ -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);

View file

@ -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() {
}

View file

@ -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);

View file

@ -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);
}
}
});

View file

@ -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))

View file

@ -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

View file

@ -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;

View file

@ -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;
}
}
});

View file

@ -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();

View file

@ -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) {

View file

@ -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";

View file

@ -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;