From afc3dd3c6206508235b42ec0157343510595554f Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Tue, 21 Apr 2015 22:27:33 -0700 Subject: [PATCH] addressed PR feedback --- src/compiler/emitter.ts | 55 ++++++++++++++----- .../reference/systemModule10_ES5.errors.txt | 18 ++++++ .../baselines/reference/systemModule10_ES5.js | 32 +++++++++++ tests/cases/compiler/systemModule10_ES5.ts | 12 ++++ 4 files changed, 103 insertions(+), 14 deletions(-) create mode 100644 tests/baselines/reference/systemModule10_ES5.errors.txt create mode 100644 tests/baselines/reference/systemModule10_ES5.js create mode 100644 tests/cases/compiler/systemModule10_ES5.ts diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index d7b5aa61f93..dce57ca15f6 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -117,6 +117,12 @@ var __param = this.__param || function(index, decorator) { return function (targ let decreaseIndent = writer.decreaseIndent; let currentSourceFile: SourceFile; + // name of an exporter function if file is a System external module + // System.register([...], function () {...}) + // exporting in System modules looks like: + // export var x; ... x = 1 + // => + // var x;... exporter("x", x = 1) let exportFunctionForFile: string; let generatedNameSet: Map = {}; @@ -2190,7 +2196,11 @@ var __param = this.__param || function(index, decorator) { return function (targ emitEmbeddedStatement(node.statement); } - function emitStartOfVariableDeclarationList(decl: VariableDeclarationList, startPos?: number): boolean { + /* Returns true if start of variable declaration list was emitted. + * Return false if nothing was written - this can happen for source file level variable declarations + * in system modules - such variable declarations are hoisted. + */ + function tryEmitStartOfVariableDeclarationList(decl: VariableDeclarationList, startPos?: number): boolean { if (shouldHoistVariable(decl, /*checkIfSourceFileLevelDecl*/ true)) { // variables in variable declaration list were already hoisted return false; @@ -2253,7 +2263,7 @@ var __param = this.__param || function(index, decorator) { return function (targ endPos = emitToken(SyntaxKind.OpenParenToken, endPos); if (node.initializer && node.initializer.kind === SyntaxKind.VariableDeclarationList) { let variableDeclarationList = node.initializer; - let startIsEmitted = emitStartOfVariableDeclarationList(variableDeclarationList, endPos); + let startIsEmitted = tryEmitStartOfVariableDeclarationList(variableDeclarationList, endPos); if (startIsEmitted) { emitCommaList(variableDeclarationList.declarations); } @@ -2283,7 +2293,7 @@ var __param = this.__param || function(index, decorator) { return function (targ if (node.initializer.kind === SyntaxKind.VariableDeclarationList) { let variableDeclarationList = node.initializer; if (variableDeclarationList.declarations.length >= 1) { - emitStartOfVariableDeclarationList(variableDeclarationList, endPos); + tryEmitStartOfVariableDeclarationList(variableDeclarationList, endPos); emit(variableDeclarationList.declarations[0]); } } @@ -2664,14 +2674,14 @@ var __param = this.__param || function(index, decorator) { return function (targ // temporary variables in an exported declaration need to have real declarations elsewhere // Also temporary variables should be explicitly allocated for source level declarations when module target is system // because actual variable declarations are hoisted - let canDefineTempVariablesInplace = false; + let canDefineTempVariablesInPlace = false; if (root.kind === SyntaxKind.VariableDeclaration) { let isExported = getCombinedNodeFlags(root) & NodeFlags.Export; let isSourceLevelForSystemModuleKind = isSourceFileLevelDeclarationInSystemExternalModule(root, /*isExported*/ false); - canDefineTempVariablesInplace = !isExported && !isSourceLevelForSystemModuleKind; + canDefineTempVariablesInPlace = !isExported && !isSourceLevelForSystemModuleKind; } else if (root.kind === SyntaxKind.Parameter) { - canDefineTempVariablesInplace = true; + canDefineTempVariablesInPlace = true; } if (root.kind === SyntaxKind.BinaryExpression) { @@ -2718,7 +2728,7 @@ var __param = this.__param || function(index, decorator) { return function (targ function ensureIdentifier(expr: Expression): Expression { if (expr.kind !== SyntaxKind.Identifier) { let identifier = createTempVariable(TempFlags.Auto); - if (!canDefineTempVariablesInplace) { + if (!canDefineTempVariablesInPlace) { recordTempDeclaration(identifier); } emitAssignment(identifier, expr); @@ -3015,12 +3025,12 @@ var __param = this.__param || function(index, decorator) { return function (targ function emitVariableStatement(node: VariableStatement) { let startIsEmitted = true; if (!(node.flags & NodeFlags.Export)) { - startIsEmitted = emitStartOfVariableDeclarationList(node.declarationList); + startIsEmitted = tryEmitStartOfVariableDeclarationList(node.declarationList); } else if (isES6ExportedDeclaration(node)) { // Exported ES6 module member write("export "); - startIsEmitted = emitStartOfVariableDeclarationList(node.declarationList); + startIsEmitted = tryEmitStartOfVariableDeclarationList(node.declarationList); } if (startIsEmitted) { emitCommaList(node.declarationList.declarations); @@ -3922,6 +3932,7 @@ var __param = this.__param || function(index, decorator) { return function (targ function emitClassLikeDeclarationBelowES6(node: ClassLikeDeclaration) { if (node.kind === SyntaxKind.ClassDeclaration) { + // source file level classes in system modules are hoisted so 'var's for them are already defined if (!isSourceFileLevelDeclarationInSystemExternalModule(node, /*isExported*/ false)) { write("var "); } @@ -4962,18 +4973,30 @@ var __param = this.__param || function(index, decorator) { return function (targ function visit(node: Node): void { if (node.kind === SyntaxKind.FunctionDeclaration) { - (hoistedFunctionDeclarations || (hoistedFunctionDeclarations = [])).push(node); + if (!hoistedFunctionDeclarations) { + hoistedFunctionDeclarations = []; + } + + hoistedFunctionDeclarations.push(node); return; } if (node.kind === SyntaxKind.ClassDeclaration) { // TODO: rename block scoped classes - (hoistedVars || (hoistedVars = [])).push(node); + if (!hoistedVars) { + hoistedVars = []; + } + + hoistedVars.push(node); return; } if (node.kind === SyntaxKind.ModuleDeclaration && shouldEmitModuleDeclaration(node)) { - (hoistedVars || (hoistedVars = [])).push(node); + if (!hoistedVars) { + hoistedVars = []; + } + + hoistedVars.push(node); return; } @@ -4981,7 +5004,11 @@ var __param = this.__param || function(index, decorator) { return function (targ if (shouldHoistVariable(node, /*checkIfSourceFileLevelDecl*/ false)) { let name = (node).name; if (name.kind === SyntaxKind.Identifier) { - (hoistedVars || (hoistedVars = [])).push(name); + if (!hoistedVars) { + hoistedVars = []; + } + + hoistedVars.push(name); } else { forEachChild(name, visit); @@ -5072,7 +5099,7 @@ var __param = this.__param || function(index, decorator) { return function (targ } function emitSetters() { - write("setters:[") + write("setters:["); for (let i = 0; i < externalImports.length; ++i) { if (i !== 0) { write(","); diff --git a/tests/baselines/reference/systemModule10_ES5.errors.txt b/tests/baselines/reference/systemModule10_ES5.errors.txt new file mode 100644 index 00000000000..5c384837a84 --- /dev/null +++ b/tests/baselines/reference/systemModule10_ES5.errors.txt @@ -0,0 +1,18 @@ +tests/cases/compiler/systemModule10_ES5.ts(2,20): error TS2307: Cannot find external module 'file1'. +tests/cases/compiler/systemModule10_ES5.ts(3,21): error TS2307: Cannot find external module 'file2'. + + +==== tests/cases/compiler/systemModule10_ES5.ts (2 errors) ==== + + import n, {x} from 'file1' + ~~~~~~~ +!!! error TS2307: Cannot find external module 'file1'. + import n2 = require('file2'); + ~~~~~~~ +!!! error TS2307: Cannot find external module 'file2'. + export {x} + export {x as y} + export {n} + export {n as n1} + export {n2} + export {n2 as n3} \ No newline at end of file diff --git a/tests/baselines/reference/systemModule10_ES5.js b/tests/baselines/reference/systemModule10_ES5.js new file mode 100644 index 00000000000..04c946d9abe --- /dev/null +++ b/tests/baselines/reference/systemModule10_ES5.js @@ -0,0 +1,32 @@ +//// [systemModule10_ES5.ts] + +import n, {x} from 'file1' +import n2 = require('file2'); +export {x} +export {x as y} +export {n} +export {n as n1} +export {n2} +export {n2 as n3} + +//// [systemModule10_ES5.js] +System.register(['file1', 'file2'], function(exports_1) { + var file1_1, n2; + return { + 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() { + } + } +}); diff --git a/tests/cases/compiler/systemModule10_ES5.ts b/tests/cases/compiler/systemModule10_ES5.ts new file mode 100644 index 00000000000..6468e4125d1 --- /dev/null +++ b/tests/cases/compiler/systemModule10_ES5.ts @@ -0,0 +1,12 @@ +// @target: es5 +// @module: system +// @separateCompilation: true + +import n, {x} from 'file1' +import n2 = require('file2'); +export {x} +export {x as y} +export {n} +export {n as n1} +export {n2} +export {n2 as n3} \ No newline at end of file