Skip to content

Commit 4259417

Browse files
committed
hoist top level import equals declarations in System modules
1 parent 4e85864 commit 4259417

8 files changed

+208
-9
lines changed

src/compiler/emitter.ts

+46-8
Original file line numberDiff line numberDiff line change
@@ -5429,17 +5429,43 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
54295429
(!isExternalModule(currentSourceFile) && resolver.isTopLevelValueImportEqualsWithEntityName(node))) {
54305430
emitLeadingComments(node);
54315431
emitStart(node);
5432-
if (isES6ExportedDeclaration(node)) {
5433-
write("export ");
5434-
write("var ");
5432+
5433+
// variable declaration for import-equals declaration can be hoisted in system modules
5434+
// in this case 'var' should be omitted and emit should contain only initialization
5435+
let variableDeclarationIsHoisted = shouldHoistVariable(node, /*checkIfSourceFileLevelDecl*/ true);
5436+
5437+
// is it top level export import v = a.b.c in system module?
5438+
// if yes - it needs to be rewritten as exporter('v', v = a.b.c)
5439+
let isExported = isSourceFileLevelDeclarationInSystemJsModule(node, /*isExported*/ true);
5440+
5441+
if (!variableDeclarationIsHoisted) {
5442+
Debug.assert(!isExported);
5443+
5444+
if (isES6ExportedDeclaration(node)) {
5445+
write("export ");
5446+
write("var ");
5447+
}
5448+
else if (!(node.flags & NodeFlags.Export)) {
5449+
write("var ");
5450+
}
54355451
}
5436-
else if (!(node.flags & NodeFlags.Export)) {
5437-
write("var ");
5452+
5453+
5454+
if (isExported) {
5455+
write(`${exportFunctionForFile}("`);
5456+
emitNodeWithoutSourceMap(node.name);
5457+
write(`", `);
54385458
}
5459+
54395460
emitModuleMemberName(node);
54405461
write(" = ");
54415462
emit(node.moduleReference);
5442-
write(";");
5463+
5464+
if (isExported) {
5465+
write(")");
5466+
}
5467+
5468+
write(";");
54435469
emitEnd(node);
54445470
emitExportImportAssignments(node);
54455471
emitTrailingComments(node);
@@ -5965,6 +5991,15 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
59655991
}
59665992
return;
59675993
}
5994+
5995+
if (isInternalModuleImportEqualsDeclaration(node)) {
5996+
if (!hoistedVars) {
5997+
hoistedVars = [];
5998+
}
5999+
6000+
hoistedVars.push(node.name);
6001+
return;
6002+
}
59686003

59696004
if (isBindingPattern(node)) {
59706005
forEach((<BindingPattern>node).elements, visit);
@@ -6169,14 +6204,17 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
61696204
writeLine();
61706205
for (let i = startIndex; i < node.statements.length; ++i) {
61716206
let statement = node.statements[i];
6172-
// - imports/exports are not emitted for system modules
6207+
// - external module related imports/exports are not emitted for system modules
61736208
// - function declarations are not emitted because they were already hoisted
61746209
switch (statement.kind) {
61756210
case SyntaxKind.ExportDeclaration:
61766211
case SyntaxKind.ImportDeclaration:
6177-
case SyntaxKind.ImportEqualsDeclaration:
61786212
case SyntaxKind.FunctionDeclaration:
61796213
continue;
6214+
case SyntaxKind.ImportEqualsDeclaration:
6215+
if (!isInternalModuleImportEqualsDeclaration(statement)) {
6216+
continue;
6217+
}
61806218
}
61816219
writeLine();
61826220
emit(statement);

src/compiler/utilities.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -965,7 +965,7 @@ namespace ts {
965965
return (<ExternalModuleReference>(<ImportEqualsDeclaration>node).moduleReference).expression;
966966
}
967967

968-
export function isInternalModuleImportEqualsDeclaration(node: Node) {
968+
export function isInternalModuleImportEqualsDeclaration(node: Node): node is ImportEqualsDeclaration {
969969
return node.kind === SyntaxKind.ImportEqualsDeclaration && (<ImportEqualsDeclaration>node).moduleReference.kind !== SyntaxKind.ExternalModuleReference;
970970
}
971971

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
tests/cases/compiler/aliasesInSystemModule1.ts(2,24): error TS2307: Cannot find module 'foo'.
2+
3+
4+
==== tests/cases/compiler/aliasesInSystemModule1.ts (1 errors) ====
5+
6+
import alias = require('foo');
7+
~~~~~
8+
!!! error TS2307: Cannot find module 'foo'.
9+
import cls = alias.Class;
10+
export import cls2 = alias.Class;
11+
12+
let x = new alias.Class();
13+
let y = new cls();
14+
let z = new cls2();
15+
16+
module M {
17+
export import cls = alias.Class;
18+
let x = new alias.Class();
19+
let y = new cls();
20+
let z = new cls2();
21+
}
22+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
//// [aliasesInSystemModule1.ts]
2+
3+
import alias = require('foo');
4+
import cls = alias.Class;
5+
export import cls2 = alias.Class;
6+
7+
let x = new alias.Class();
8+
let y = new cls();
9+
let z = new cls2();
10+
11+
module M {
12+
export import cls = alias.Class;
13+
let x = new alias.Class();
14+
let y = new cls();
15+
let z = new cls2();
16+
}
17+
18+
19+
//// [aliasesInSystemModule1.js]
20+
System.register(['foo'], function(exports_1) {
21+
var alias;
22+
var cls, cls2, x, y, z, M;
23+
return {
24+
setters:[
25+
function (_alias) {
26+
alias = _alias;
27+
}],
28+
execute: function() {
29+
cls = alias.Class;
30+
exports_1("cls2", cls2 = alias.Class);
31+
x = new alias.Class();
32+
y = new cls();
33+
z = new cls2();
34+
(function (M) {
35+
M.cls = alias.Class;
36+
var x = new alias.Class();
37+
var y = new M.cls();
38+
var z = new cls2();
39+
})(M || (M = {}));
40+
}
41+
}
42+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
tests/cases/compiler/aliasesInSystemModule2.ts(2,21): error TS2307: Cannot find module 'foo'.
2+
3+
4+
==== tests/cases/compiler/aliasesInSystemModule2.ts (1 errors) ====
5+
6+
import {alias} from "foo";
7+
~~~~~
8+
!!! error TS2307: Cannot find module 'foo'.
9+
import cls = alias.Class;
10+
export import cls2 = alias.Class;
11+
12+
let x = new alias.Class();
13+
let y = new cls();
14+
let z = new cls2();
15+
16+
module M {
17+
export import cls = alias.Class;
18+
let x = new alias.Class();
19+
let y = new cls();
20+
let z = new cls2();
21+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
//// [aliasesInSystemModule2.ts]
2+
3+
import {alias} from "foo";
4+
import cls = alias.Class;
5+
export import cls2 = alias.Class;
6+
7+
let x = new alias.Class();
8+
let y = new cls();
9+
let z = new cls2();
10+
11+
module M {
12+
export import cls = alias.Class;
13+
let x = new alias.Class();
14+
let y = new cls();
15+
let z = new cls2();
16+
}
17+
18+
//// [aliasesInSystemModule2.js]
19+
System.register(["foo"], function(exports_1) {
20+
var foo_1;
21+
var cls, cls2, x, y, z, M;
22+
return {
23+
setters:[
24+
function (_foo_1) {
25+
foo_1 = _foo_1;
26+
}],
27+
execute: function() {
28+
cls = foo_1.alias.Class;
29+
exports_1("cls2", cls2 = foo_1.alias.Class);
30+
x = new foo_1.alias.Class();
31+
y = new cls();
32+
z = new cls2();
33+
(function (M) {
34+
M.cls = foo_1.alias.Class;
35+
var x = new foo_1.alias.Class();
36+
var y = new M.cls();
37+
var z = new cls2();
38+
})(M || (M = {}));
39+
}
40+
}
41+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// @module: system
2+
// @isolatedModules: true
3+
4+
import alias = require('foo');
5+
import cls = alias.Class;
6+
export import cls2 = alias.Class;
7+
8+
let x = new alias.Class();
9+
let y = new cls();
10+
let z = new cls2();
11+
12+
module M {
13+
export import cls = alias.Class;
14+
let x = new alias.Class();
15+
let y = new cls();
16+
let z = new cls2();
17+
}
18+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// @module: system
2+
// @isolatedModules: true
3+
4+
import {alias} from "foo";
5+
import cls = alias.Class;
6+
export import cls2 = alias.Class;
7+
8+
let x = new alias.Class();
9+
let y = new cls();
10+
let z = new cls2();
11+
12+
module M {
13+
export import cls = alias.Class;
14+
let x = new alias.Class();
15+
let y = new cls();
16+
let z = new cls2();
17+
}

0 commit comments

Comments
 (0)