From 53105b3afff2b3e054d5e3f2ff013d124ae783b4 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Tue, 25 Sep 2018 16:06:23 -0700 Subject: [PATCH] Fix crash in use-before-def checking of enum tag (#27350) --- src/compiler/checker.ts | 4 +++- .../reference/enumTagUseBeforeDefCrash.symbols | 13 +++++++++++++ .../reference/enumTagUseBeforeDefCrash.types | 14 ++++++++++++++ .../conformance/jsdoc/enumTagUseBeforeDefCrash.ts | 13 +++++++++++++ 4 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 tests/baselines/reference/enumTagUseBeforeDefCrash.symbols create mode 100644 tests/baselines/reference/enumTagUseBeforeDefCrash.types create mode 100644 tests/cases/conformance/jsdoc/enumTagUseBeforeDefCrash.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index d5eda73b4d1af..86bc7ec1d16b5 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1707,7 +1707,9 @@ namespace ts { function checkResolvedBlockScopedVariable(result: Symbol, errorLocation: Node): void { Debug.assert(!!(result.flags & SymbolFlags.BlockScopedVariable || result.flags & SymbolFlags.Class || result.flags & SymbolFlags.Enum)); // Block-scoped variables cannot be used before their definition - const declaration = forEach(result.declarations, d => isBlockOrCatchScoped(d) || isClassLike(d) || (d.kind === SyntaxKind.EnumDeclaration) ? d : undefined); + const declaration = find( + result.declarations, + d => isBlockOrCatchScoped(d) || isClassLike(d) || (d.kind === SyntaxKind.EnumDeclaration) || isInJSFile(d) && !!getJSDocEnumTag(d)); if (declaration === undefined) return Debug.fail("Declaration to checkResolvedBlockScopedVariable is undefined"); diff --git a/tests/baselines/reference/enumTagUseBeforeDefCrash.symbols b/tests/baselines/reference/enumTagUseBeforeDefCrash.symbols new file mode 100644 index 0000000000000..1cef96a9823a7 --- /dev/null +++ b/tests/baselines/reference/enumTagUseBeforeDefCrash.symbols @@ -0,0 +1,13 @@ +=== tests/cases/conformance/jsdoc/bug27134.js === +/** + * @enum {number} + */ +var foo = { }; +>foo : Symbol(foo, Decl(bug27134.js, 3, 3)) + +/** + * @type {foo} + */ +var s; +>s : Symbol(s, Decl(bug27134.js, 8, 3)) + diff --git a/tests/baselines/reference/enumTagUseBeforeDefCrash.types b/tests/baselines/reference/enumTagUseBeforeDefCrash.types new file mode 100644 index 0000000000000..159781fee05f1 --- /dev/null +++ b/tests/baselines/reference/enumTagUseBeforeDefCrash.types @@ -0,0 +1,14 @@ +=== tests/cases/conformance/jsdoc/bug27134.js === +/** + * @enum {number} + */ +var foo = { }; +>foo : typeof foo +>{ } : {} + +/** + * @type {foo} + */ +var s; +>s : number + diff --git a/tests/cases/conformance/jsdoc/enumTagUseBeforeDefCrash.ts b/tests/cases/conformance/jsdoc/enumTagUseBeforeDefCrash.ts new file mode 100644 index 0000000000000..f8f92b7bcc1bf --- /dev/null +++ b/tests/cases/conformance/jsdoc/enumTagUseBeforeDefCrash.ts @@ -0,0 +1,13 @@ +// @noEmit: true +// @allowJs: true +// @checkJs: true +// @Filename: bug27134.js +/** + * @enum {number} + */ +var foo = { }; + +/** + * @type {foo} + */ +var s;