diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 38e74aa0cc6..b60ae97ceee 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -19,6 +19,8 @@ module ts { return isExternalModule(sourceFile) || isDeclarationFile(sourceFile); } + // flag enum used to request and track usages of few dedicated temp variables + // enum values are used to set/check bit values and thus should not have bit collisions. const enum TempVariableKind { auto = 0, _i = 1, @@ -216,7 +218,7 @@ module ts { // _i; // } // we should be able to detect if let _i was shadowed by some temp variable that was allocated in scope - function hasConflictsWithTempVariables(name: string): boolean { + function nameConflictsWithSomeTempVariable(name: string): boolean { // temp variable names always start with '_' if (name.length < 2 || name.charCodeAt(0) !== CharacterCodes._) { return false; @@ -242,7 +244,12 @@ module ts { } } + // This function generates a name using the following pattern: // _a .. _h, _j ... _z, _0, _1, ... + // It is guaranteed that generated name will not shadow any existing user-defined names, + // however it can hide another name generated by this function higher in the scope. + // NOTE: names generated by 'makeTempVariableName' and 'makeUniqueName' will never conflict. + // see comment for 'makeTempVariableName' for more information. function makeTempVariableName(location: Node, tempVariableKind: TempVariableKind): string { let tempName: string; if (tempVariableKind !== TempVariableKind.auto && !(predefinedTempsInUse & tempVariableKind)) { @@ -272,8 +279,17 @@ module ts { return tempName; } - // unique names always end with _ - // generated unique names: name_1, name_2... + // Generates a name that is unique within current file and does not collide with + // any names in global scope. + // NOTE: names generated by 'makeTempVariableName' and 'makeUniqueName' will never conflict + // because of the way how these names are generated + // - makeUniqueName builds a name by picking a base name (which should not be empty string) + // and appending suffix '_' + // - makeTempVariableName creates a name using the following pattern: + // _a .. _h, _j ... _z, _0, _1, ... + // This means that names from 'makeTempVariableName' will have only one underscore at the beginning + // and names from 'makeUniqieName' will have at least one underscore in the middle + // so they will never collide. function makeUniqueName(baseName: string): string { Debug.assert(!!baseName); @@ -2787,8 +2803,9 @@ module ts { let list = getAncestor(node, SyntaxKind.VariableDeclarationList); if (list.parent.kind === SyntaxKind.VariableStatement) { let isSourceFileLevelBinding = list.parent.parent.kind === SyntaxKind.SourceFile; - let isModuleLevelBinding = list.parent.parent.kind === SyntaxKind.ModuleDeclaration; - let isFunctionLevelBinding = isFunctionLike(list.parent.parent); + let isModuleLevelBinding = list.parent.parent.kind === SyntaxKind.ModuleBlock; + let isFunctionLevelBinding = + list.parent.parent.kind === SyntaxKind.Block && isFunctionLike(list.parent.parent.parent); if (isSourceFileLevelBinding || isModuleLevelBinding || isFunctionLevelBinding) { return; } @@ -2801,7 +2818,7 @@ module ts { var hasConflictsInEnclosingScope = !resolver.isUnknownIdentifier(parent, (node).text) || - hasConflictsWithTempVariables((node).text); + nameConflictsWithSomeTempVariable((node).text); if (hasConflictsInEnclosingScope) { let variableId = resolver.getBlockScopedVariableId(node); diff --git a/tests/baselines/reference/downlevelLetConst16.js b/tests/baselines/reference/downlevelLetConst16.js index 4f67b275e00..aefe2830adc 100644 --- a/tests/baselines/reference/downlevelLetConst16.js +++ b/tests/baselines/reference/downlevelLetConst16.js @@ -236,29 +236,29 @@ use(x); use(y); use(z); function foo1() { - var x_1 = 1; - use(x_1); - var y_1 = ([ + var x = 1; + use(x); + var y = ([ 1 ])[0]; - use(y_1); - var z_1 = ({ + use(y); + var z = ({ a: 1 }).a; - use(z_1); + use(z); } function foo2() { { - var x_2 = 1; - use(x_2); - var y_2 = ([ + var x_1 = 1; + use(x_1); + var y_1 = ([ 1 ])[0]; - use(y_2); - var z_2 = ({ + use(y_1); + var z_1 = ({ a: 1 }).a; - use(z_2); + use(z_1); } use(x); } @@ -266,29 +266,29 @@ var A = (function () { function A() { } A.prototype.m1 = function () { - var x_3 = 1; - use(x_3); - var y_3 = ([ + var x = 1; + use(x); + var y = ([ 1 ])[0]; - use(y_3); - var z_3 = ({ + use(y); + var z = ({ a: 1 }).a; - use(z_3); + use(z); }; A.prototype.m2 = function () { { - var x_4 = 1; - use(x_4); - var y_4 = ([ + var x_2 = 1; + use(x_2); + var y_2 = ([ 1 ])[0]; - use(y_4); - var z_4 = ({ + use(y_2); + var z_2 = ({ a: 1 }).a; - use(z_4); + use(z_2); } use(x); }; @@ -298,6 +298,77 @@ var B = (function () { function B() { } B.prototype.m1 = function () { + var x = 1; + use(x); + var y = ([ + 1 + ])[0]; + use(y); + var z = ({ + a: 1 + }).a; + use(z); + }; + B.prototype.m2 = function () { + { + var x_3 = 1; + use(x_3); + var y_3 = ([ + 1 + ])[0]; + use(y_3); + var z_3 = ({ + a: 1 + }).a; + use(z_3); + } + use(x); + }; + return B; +})(); +function bar1() { + var x = 1; + use(x); + var y = ([ + 1 + ])[0]; + use(y); + var z = ({ + a: 1 + }).a; + use(z); +} +function bar2() { + { + var x_4 = 1; + use(x_4); + var y_4 = ([ + 1 + ])[0]; + use(y_4); + var z_4 = ({ + a: 1 + }).a; + use(z_4); + } + use(x); +} +var M1; +(function (M1) { + var x = 1; + use(x); + var y = ([ + 1 + ])[0]; + use(y); + var z = ({ + a: 1 + }).a; + use(z); +})(M1 || (M1 = {})); +var M2; +(function (M2) { + { var x_5 = 1; use(x_5); var y_5 = ([ @@ -308,190 +379,119 @@ var B = (function () { a: 1 }).a; use(z_5); - }; - B.prototype.m2 = function () { - { - var x_6 = 1; - use(x_6); - var y_6 = ([ - 1 - ])[0]; - use(y_6); - var z_6 = ({ - a: 1 - }).a; - use(z_6); - } - use(x); - }; - return B; -})(); -function bar1() { - var x_7 = 1; - use(x_7); - var y_7 = ([ - 1 - ])[0]; - use(y_7); - var z_7 = ({ - a: 1 - }).a; - use(z_7); -} -function bar2() { - { - var x_8 = 1; - use(x_8); - var y_8 = ([ - 1 - ])[0]; - use(y_8); - var z_8 = ({ - a: 1 - }).a; - use(z_8); - } - use(x); -} -var M1; -(function (M1) { - var x_9 = 1; - use(x_9); - var y_9 = ([ - 1 - ])[0]; - use(y_9); - var z_9 = ({ - a: 1 - }).a; - use(z_9); -})(M1 || (M1 = {})); -var M2; -(function (M2) { - { - var x_10 = 1; - use(x_10); - var y_10 = ([ - 1 - ])[0]; - use(y_10); - var z_10 = ({ - a: 1 - }).a; - use(z_10); } use(x); })(M2 || (M2 = {})); var M3; (function (M3) { - var x_11 = 1; - use(x_11); - var y_11 = ([ + var x = 1; + use(x); + var y = ([ 1 ])[0]; - use(y_11); - var z_11 = ({ + use(y); + var z = ({ a: 1 }).a; - use(z_11); + use(z); })(M3 || (M3 = {})); var M4; (function (M4) { { - var x_12 = 1; - use(x_12); - var y_12 = ([ + var x_6 = 1; + use(x_6); + var y_6 = ([ 1 ])[0]; - use(y_12); - var z_12 = ({ + use(y_6); + var z_6 = ({ a: 1 }).a; - use(z_12); + use(z_6); } use(x); use(y); use(z); })(M4 || (M4 = {})); function foo3() { - for (var x_13 = void 0;;) { - use(x_13); + for (var x_7 = void 0;;) { + use(x_7); } - for (var y_13 = ([])[0];;) { - use(y_13); + for (var y_7 = ([])[0];;) { + use(y_7); } - for (var z_13 = ({ + for (var z_7 = ({ a: 1 }).a;;) { - use(z_13); + use(z_7); } use(x); } function foo4() { - for (var x_14 = 1;;) { - use(x_14); + for (var x_8 = 1;;) { + use(x_8); } - for (var y_14 = ([])[0];;) { - use(y_14); + for (var y_8 = ([])[0];;) { + use(y_8); } - for (var z_14 = ({ + for (var z_8 = ({ a: 1 }).a;;) { - use(z_14); + use(z_8); } use(x); } function foo5() { - for (var x_15 in []) { - use(x_15); + for (var x_9 in []) { + use(x_9); } use(x); } function foo6() { - for (var x_16 in []) { - use(x_16); + for (var x_10 in []) { + use(x_10); } use(x); } function foo7() { for (var _i = 0, _a = []; _i < _a.length; _i++) { - var x_17 = _a[_i]; - use(x_17); + var x_11 = _a[_i]; + use(x_11); } use(x); } function foo8() { for (var _i = 0, _a = []; _i < _a.length; _i++) { - var x_18 = _a[_i][0]; - use(x_18); + var x_12 = _a[_i][0]; + use(x_12); } use(x); } function foo9() { for (var _i = 0, _a = []; _i < _a.length; _i++) { - var x_19 = _a[_i].a; - use(x_19); + var x_13 = _a[_i].a; + use(x_13); } use(x); } function foo10() { for (var _i = 0, _a = []; _i < _a.length; _i++) { - var x_20 = _a[_i]; - use(x_20); + var x_14 = _a[_i]; + use(x_14); } use(x); } function foo11() { for (var _i = 0, _a = []; _i < _a.length; _i++) { - var x_21 = _a[_i][0]; - use(x_21); + var x_15 = _a[_i][0]; + use(x_15); } use(x); } function foo12() { for (var _i = 0, _a = []; _i < _a.length; _i++) { - var x_22 = _a[_i].a; - use(x_22); + var x_16 = _a[_i].a; + use(x_16); } use(x); } diff --git a/tests/baselines/reference/letConstMatchingParameterNames.js b/tests/baselines/reference/letConstMatchingParameterNames.js index 34443aeb122..392f0e7ae94 100644 --- a/tests/baselines/reference/letConstMatchingParameterNames.js +++ b/tests/baselines/reference/letConstMatchingParameterNames.js @@ -19,8 +19,8 @@ function a() { var parent = true; var parent2 = true; function a() { - var parent_1 = 1; - var parent2_1 = 2; + var parent = 1; + var parent2 = 2; function b(parent, parent2) { use(parent); use(parent2); diff --git a/tests/baselines/reference/letKeepNamesOfTopLevelItems.js b/tests/baselines/reference/letKeepNamesOfTopLevelItems.js new file mode 100644 index 00000000000..96fd31ae536 --- /dev/null +++ b/tests/baselines/reference/letKeepNamesOfTopLevelItems.js @@ -0,0 +1,19 @@ +//// [letKeepNamesOfTopLevelItems.ts] +let x; +function foo() { + let x; +} + +module A { + let x; +} + +//// [letKeepNamesOfTopLevelItems.js] +var x; +function foo() { + var x; +} +var A; +(function (A) { + var x; +})(A || (A = {})); diff --git a/tests/baselines/reference/letKeepNamesOfTopLevelItems.types b/tests/baselines/reference/letKeepNamesOfTopLevelItems.types new file mode 100644 index 00000000000..952be1512a9 --- /dev/null +++ b/tests/baselines/reference/letKeepNamesOfTopLevelItems.types @@ -0,0 +1,17 @@ +=== tests/cases/compiler/letKeepNamesOfTopLevelItems.ts === +let x; +>x : any + +function foo() { +>foo : () => void + + let x; +>x : any +} + +module A { +>A : typeof A + + let x; +>x : any +} diff --git a/tests/baselines/reference/letShadowedByNameInNestedScope.js b/tests/baselines/reference/letShadowedByNameInNestedScope.js index b085f755795..648fe0b8e94 100644 --- a/tests/baselines/reference/letShadowedByNameInNestedScope.js +++ b/tests/baselines/reference/letShadowedByNameInNestedScope.js @@ -11,9 +11,9 @@ function foo() { //// [letShadowedByNameInNestedScope.js] var x; function foo() { - var x_1 = 0; + var x = 0; (function () { var _x = 1; - console.log(x_1); + console.log(x); })(); } diff --git a/tests/cases/compiler/letKeepNamesOfTopLevelItems.ts b/tests/cases/compiler/letKeepNamesOfTopLevelItems.ts new file mode 100644 index 00000000000..b5fc5fc031c --- /dev/null +++ b/tests/cases/compiler/letKeepNamesOfTopLevelItems.ts @@ -0,0 +1,8 @@ +let x; +function foo() { + let x; +} + +module A { + let x; +} \ No newline at end of file