Import assertion: do no parse } if { is not present (#46388)

Previously, import assertion parsing would try to parse both { and },
even if both were missing. If both were missing, the error for } could
occur past the end of the file, causing an assertion.

Fixes #46364
This commit is contained in:
Nathan Shively-Sanders 2021-10-15 13:26:46 -07:00 committed by GitHub
parent 7582b1bbae
commit 6a75689a25
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 71 additions and 11 deletions

View file

@ -7277,19 +7277,24 @@ namespace ts {
const pos = getNodePos();
parseExpected(SyntaxKind.AssertKeyword);
const openBracePosition = scanner.getTokenPos();
parseExpected(SyntaxKind.OpenBraceToken);
const multiLine = scanner.hasPrecedingLineBreak();
const elements = parseDelimitedList(ParsingContext.AssertEntries, parseAssertEntry, /*considerSemicolonAsDelimiter*/ true);
if (!parseExpected(SyntaxKind.CloseBraceToken)) {
const lastError = lastOrUndefined(parseDiagnostics);
if (lastError && lastError.code === Diagnostics._0_expected.code) {
addRelatedInfo(
lastError,
createDetachedDiagnostic(fileName, openBracePosition, 1, Diagnostics.The_parser_expected_to_find_a_to_match_the_token_here)
);
if (parseExpected(SyntaxKind.OpenBraceToken)) {
const multiLine = scanner.hasPrecedingLineBreak();
const elements = parseDelimitedList(ParsingContext.AssertEntries, parseAssertEntry, /*considerSemicolonAsDelimiter*/ true);
if (!parseExpected(SyntaxKind.CloseBraceToken)) {
const lastError = lastOrUndefined(parseDiagnostics);
if (lastError && lastError.code === Diagnostics._0_expected.code) {
addRelatedInfo(
lastError,
createDetachedDiagnostic(fileName, openBracePosition, 1, Diagnostics.The_parser_expected_to_find_a_to_match_the_token_here)
);
}
}
return finishNode(factory.createAssertClause(elements, multiLine), pos);
}
else {
const elements = createNodeArray([], getNodePos(), /*end*/ undefined, /*hasTrailingComma*/ false);
return finishNode(factory.createAssertClause(elements, /*multiLine*/ false), pos);
}
return finishNode(factory.createAssertClause(elements, multiLine), pos);
}
function tokenAfterImportDefinitelyProducesImportDeclaration() {

View file

@ -0,0 +1,11 @@
tests/cases/conformance/importAssertion/importAssertion4.ts(1,20): error TS2307: Cannot find module './first' or its corresponding type declarations.
tests/cases/conformance/importAssertion/importAssertion4.ts(2,1): error TS1005: '{' expected.
==== tests/cases/conformance/importAssertion/importAssertion4.ts (2 errors) ====
import * as f from "./first" assert
~~~~~~~~~
!!! error TS2307: Cannot find module './first' or its corresponding type declarations.
!!! error TS1005: '{' expected.

View file

@ -0,0 +1,7 @@
//// [importAssertion4.ts]
import * as f from "./first" assert
//// [importAssertion4.js]
"use strict";
exports.__esModule = true;

View file

@ -0,0 +1,4 @@
=== tests/cases/conformance/importAssertion/importAssertion4.ts ===
import * as f from "./first" assert
>f : Symbol(f, Decl(importAssertion4.ts, 0, 6))

View file

@ -0,0 +1,4 @@
=== tests/cases/conformance/importAssertion/importAssertion4.ts ===
import * as f from "./first" assert
>f : any

View file

@ -0,0 +1,12 @@
tests/cases/conformance/importAssertion/importAssertion5.ts(1,20): error TS2307: Cannot find module './first' or its corresponding type declarations.
tests/cases/conformance/importAssertion/importAssertion5.ts(2,1): error TS1005: '}' expected.
==== tests/cases/conformance/importAssertion/importAssertion5.ts (2 errors) ====
import * as f from "./first" assert {
~~~~~~~~~
!!! error TS2307: Cannot find module './first' or its corresponding type declarations.
!!! error TS1005: '}' expected.
!!! related TS1007 tests/cases/conformance/importAssertion/importAssertion5.ts:1:37: The parser expected to find a '}' to match the '{' token here.

View file

@ -0,0 +1,7 @@
//// [importAssertion5.ts]
import * as f from "./first" assert {
//// [importAssertion5.js]
"use strict";
exports.__esModule = true;

View file

@ -0,0 +1,4 @@
=== tests/cases/conformance/importAssertion/importAssertion5.ts ===
import * as f from "./first" assert {
>f : Symbol(f, Decl(importAssertion5.ts, 0, 6))

View file

@ -0,0 +1,4 @@
=== tests/cases/conformance/importAssertion/importAssertion5.ts ===
import * as f from "./first" assert {
>f : any

View file

@ -0,0 +1 @@
import * as f from "./first" assert

View file

@ -0,0 +1 @@
import * as f from "./first" assert {