hoist top level import equals declarations in System modules

This commit is contained in:
Vladimir Matveev 2015-07-21 15:56:30 -07:00
parent 4e85864b2d
commit 4259417821
8 changed files with 208 additions and 9 deletions

View file

@ -5429,17 +5429,43 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
(!isExternalModule(currentSourceFile) && resolver.isTopLevelValueImportEqualsWithEntityName(node))) {
emitLeadingComments(node);
emitStart(node);
if (isES6ExportedDeclaration(node)) {
write("export ");
write("var ");
// variable declaration for import-equals declaration can be hoisted in system modules
// in this case 'var' should be omitted and emit should contain only initialization
let variableDeclarationIsHoisted = shouldHoistVariable(node, /*checkIfSourceFileLevelDecl*/ true);
// is it top level export import v = a.b.c in system module?
// if yes - it needs to be rewritten as exporter('v', v = a.b.c)
let isExported = isSourceFileLevelDeclarationInSystemJsModule(node, /*isExported*/ true);
if (!variableDeclarationIsHoisted) {
Debug.assert(!isExported);
if (isES6ExportedDeclaration(node)) {
write("export ");
write("var ");
}
else if (!(node.flags & NodeFlags.Export)) {
write("var ");
}
}
else if (!(node.flags & NodeFlags.Export)) {
write("var ");
if (isExported) {
write(`${exportFunctionForFile}("`);
emitNodeWithoutSourceMap(node.name);
write(`", `);
}
emitModuleMemberName(node);
write(" = ");
emit(node.moduleReference);
write(";");
if (isExported) {
write(")");
}
write(";");
emitEnd(node);
emitExportImportAssignments(node);
emitTrailingComments(node);
@ -5965,6 +5991,15 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
}
return;
}
if (isInternalModuleImportEqualsDeclaration(node)) {
if (!hoistedVars) {
hoistedVars = [];
}
hoistedVars.push(node.name);
return;
}
if (isBindingPattern(node)) {
forEach((<BindingPattern>node).elements, visit);
@ -6169,14 +6204,17 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
writeLine();
for (let i = startIndex; i < node.statements.length; ++i) {
let statement = node.statements[i];
// - imports/exports are not emitted for system modules
// - external module related imports/exports are not emitted for system modules
// - function declarations are not emitted because they were already hoisted
switch (statement.kind) {
case SyntaxKind.ExportDeclaration:
case SyntaxKind.ImportDeclaration:
case SyntaxKind.ImportEqualsDeclaration:
case SyntaxKind.FunctionDeclaration:
continue;
case SyntaxKind.ImportEqualsDeclaration:
if (!isInternalModuleImportEqualsDeclaration(statement)) {
continue;
}
}
writeLine();
emit(statement);

View file

@ -965,7 +965,7 @@ namespace ts {
return (<ExternalModuleReference>(<ImportEqualsDeclaration>node).moduleReference).expression;
}
export function isInternalModuleImportEqualsDeclaration(node: Node) {
export function isInternalModuleImportEqualsDeclaration(node: Node): node is ImportEqualsDeclaration {
return node.kind === SyntaxKind.ImportEqualsDeclaration && (<ImportEqualsDeclaration>node).moduleReference.kind !== SyntaxKind.ExternalModuleReference;
}

View file

@ -0,0 +1,22 @@
tests/cases/compiler/aliasesInSystemModule1.ts(2,24): error TS2307: Cannot find module 'foo'.
==== tests/cases/compiler/aliasesInSystemModule1.ts (1 errors) ====
import alias = require('foo');
~~~~~
!!! error TS2307: Cannot find module 'foo'.
import cls = alias.Class;
export import cls2 = alias.Class;
let x = new alias.Class();
let y = new cls();
let z = new cls2();
module M {
export import cls = alias.Class;
let x = new alias.Class();
let y = new cls();
let z = new cls2();
}

View file

@ -0,0 +1,42 @@
//// [aliasesInSystemModule1.ts]
import alias = require('foo');
import cls = alias.Class;
export import cls2 = alias.Class;
let x = new alias.Class();
let y = new cls();
let z = new cls2();
module M {
export import cls = alias.Class;
let x = new alias.Class();
let y = new cls();
let z = new cls2();
}
//// [aliasesInSystemModule1.js]
System.register(['foo'], function(exports_1) {
var alias;
var cls, cls2, x, y, z, M;
return {
setters:[
function (_alias) {
alias = _alias;
}],
execute: function() {
cls = alias.Class;
exports_1("cls2", cls2 = alias.Class);
x = new alias.Class();
y = new cls();
z = new cls2();
(function (M) {
M.cls = alias.Class;
var x = new alias.Class();
var y = new M.cls();
var z = new cls2();
})(M || (M = {}));
}
}
});

View file

@ -0,0 +1,21 @@
tests/cases/compiler/aliasesInSystemModule2.ts(2,21): error TS2307: Cannot find module 'foo'.
==== tests/cases/compiler/aliasesInSystemModule2.ts (1 errors) ====
import {alias} from "foo";
~~~~~
!!! error TS2307: Cannot find module 'foo'.
import cls = alias.Class;
export import cls2 = alias.Class;
let x = new alias.Class();
let y = new cls();
let z = new cls2();
module M {
export import cls = alias.Class;
let x = new alias.Class();
let y = new cls();
let z = new cls2();
}

View file

@ -0,0 +1,41 @@
//// [aliasesInSystemModule2.ts]
import {alias} from "foo";
import cls = alias.Class;
export import cls2 = alias.Class;
let x = new alias.Class();
let y = new cls();
let z = new cls2();
module M {
export import cls = alias.Class;
let x = new alias.Class();
let y = new cls();
let z = new cls2();
}
//// [aliasesInSystemModule2.js]
System.register(["foo"], function(exports_1) {
var foo_1;
var cls, cls2, x, y, z, M;
return {
setters:[
function (_foo_1) {
foo_1 = _foo_1;
}],
execute: function() {
cls = foo_1.alias.Class;
exports_1("cls2", cls2 = foo_1.alias.Class);
x = new foo_1.alias.Class();
y = new cls();
z = new cls2();
(function (M) {
M.cls = foo_1.alias.Class;
var x = new foo_1.alias.Class();
var y = new M.cls();
var z = new cls2();
})(M || (M = {}));
}
}
});

View file

@ -0,0 +1,18 @@
// @module: system
// @isolatedModules: true
import alias = require('foo');
import cls = alias.Class;
export import cls2 = alias.Class;
let x = new alias.Class();
let y = new cls();
let z = new cls2();
module M {
export import cls = alias.Class;
let x = new alias.Class();
let y = new cls();
let z = new cls2();
}

View file

@ -0,0 +1,17 @@
// @module: system
// @isolatedModules: true
import {alias} from "foo";
import cls = alias.Class;
export import cls2 = alias.Class;
let x = new alias.Class();
let y = new cls();
let z = new cls2();
module M {
export import cls = alias.Class;
let x = new alias.Class();
let y = new cls();
let z = new cls2();
}