From cc87e29e13824e1c68749878d2b2f20fa3e43beb Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Thu, 8 Jun 2017 13:45:21 -0700 Subject: [PATCH 1/2] Skip block scope check with no error location An example of a symbol with no error location is a global symbol like Promise. --- src/compiler/checker.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 266fbe573be..65f85b25b53 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1124,7 +1124,7 @@ namespace ts { return undefined; } - // Only check for block-scoped variable if we are looking for the + // Only check for block-scoped variable if we have an error location and are looking for the // name with variable meaning // For example, // declare module foo { @@ -1135,8 +1135,9 @@ namespace ts { // block-scoped variable and namespace module. However, only when we // try to resolve name in /*1*/ which is used in variable position, // we want to check for block-scoped - if (meaning & SymbolFlags.BlockScopedVariable || - ((meaning & SymbolFlags.Class || meaning & SymbolFlags.Enum) && (meaning & SymbolFlags.Value) === SymbolFlags.Value)) { + if (errorLocation && + (meaning & SymbolFlags.BlockScopedVariable || + ((meaning & SymbolFlags.Class || meaning & SymbolFlags.Enum) && (meaning & SymbolFlags.Value) === SymbolFlags.Value))) { const exportOrLocalSymbol = getExportSymbolOfValueSymbolIfExported(result); if (exportOrLocalSymbol.flags & SymbolFlags.BlockScopedVariable || exportOrLocalSymbol.flags & SymbolFlags.Class || exportOrLocalSymbol.flags & SymbolFlags.Enum) { checkResolvedBlockScopedVariable(exportOrLocalSymbol, errorLocation); From 91f4f3910dd9a7f04e1addb5630cd25ebb492edf Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Thu, 8 Jun 2017 13:46:48 -0700 Subject: [PATCH 2/2] Test:Block-scoped definition of Promise works Previously, a block-scoped definition of Promise like `class Promise` in a script would cause a crash --- .../reference/promiseDefinitionTest.js | 53 +++++++++++++++++++ .../reference/promiseDefinitionTest.symbols | 12 +++++ .../reference/promiseDefinitionTest.types | 13 +++++ tests/cases/compiler/promiseDefinitionTest.ts | 4 ++ 4 files changed, 82 insertions(+) create mode 100644 tests/baselines/reference/promiseDefinitionTest.js create mode 100644 tests/baselines/reference/promiseDefinitionTest.symbols create mode 100644 tests/baselines/reference/promiseDefinitionTest.types create mode 100644 tests/cases/compiler/promiseDefinitionTest.ts diff --git a/tests/baselines/reference/promiseDefinitionTest.js b/tests/baselines/reference/promiseDefinitionTest.js new file mode 100644 index 00000000000..317e15c99ca --- /dev/null +++ b/tests/baselines/reference/promiseDefinitionTest.js @@ -0,0 +1,53 @@ +//// [promiseDefinitionTest.ts] +class Promise {} +async function foo() {} +const x = foo(); + + +//// [promiseDefinitionTest.js] +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [0, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +var Promise = (function () { + function Promise() { + } + return Promise; +}()); +function foo() { + return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) { + return [2 /*return*/]; + }); }); +} +var x = foo(); diff --git a/tests/baselines/reference/promiseDefinitionTest.symbols b/tests/baselines/reference/promiseDefinitionTest.symbols new file mode 100644 index 00000000000..cd9fcd6c4dd --- /dev/null +++ b/tests/baselines/reference/promiseDefinitionTest.symbols @@ -0,0 +1,12 @@ +=== tests/cases/compiler/promiseDefinitionTest.ts === +class Promise {} +>Promise : Symbol(Promise, Decl(lib.d.ts, --, --), Decl(promiseDefinitionTest.ts, 0, 0)) +>T : Symbol(T, Decl(lib.d.ts, --, --), Decl(promiseDefinitionTest.ts, 0, 14)) + +async function foo() {} +>foo : Symbol(foo, Decl(promiseDefinitionTest.ts, 0, 19)) + +const x = foo(); +>x : Symbol(x, Decl(promiseDefinitionTest.ts, 2, 5)) +>foo : Symbol(foo, Decl(promiseDefinitionTest.ts, 0, 19)) + diff --git a/tests/baselines/reference/promiseDefinitionTest.types b/tests/baselines/reference/promiseDefinitionTest.types new file mode 100644 index 00000000000..2181ea01c4d --- /dev/null +++ b/tests/baselines/reference/promiseDefinitionTest.types @@ -0,0 +1,13 @@ +=== tests/cases/compiler/promiseDefinitionTest.ts === +class Promise {} +>Promise : Promise +>T : T + +async function foo() {} +>foo : () => Promise + +const x = foo(); +>x : Promise +>foo() : Promise +>foo : () => Promise + diff --git a/tests/cases/compiler/promiseDefinitionTest.ts b/tests/cases/compiler/promiseDefinitionTest.ts new file mode 100644 index 00000000000..0e80137983c --- /dev/null +++ b/tests/cases/compiler/promiseDefinitionTest.ts @@ -0,0 +1,4 @@ +// @target: es5 +class Promise {} +async function foo() {} +const x = foo();