@@ -123,6 +123,7 @@ import {
123123 ImportDeclaration,
124124 ImportEqualsDeclaration,
125125 ImportOrExportSpecifier,
126+ ImportPhase,
126127 ImportSpecifier,
127128 ImportTypeAssertionContainer,
128129 ImportTypeNode,
@@ -7190,6 +7191,7 @@ namespace Parser {
71907191 // could be legal, it would add complexity for very little gain.
71917192 case SyntaxKind.InterfaceKeyword:
71927193 case SyntaxKind.TypeKeyword:
7194+ case SyntaxKind.DeferKeyword:
71937195 return nextTokenIsIdentifierOnSameLine();
71947196 case SyntaxKind.ModuleKeyword:
71957197 case SyntaxKind.NamespaceKeyword:
@@ -7221,7 +7223,7 @@ namespace Parser {
72217223
72227224 case SyntaxKind.ImportKeyword:
72237225 nextToken();
7224- return token() === SyntaxKind.StringLiteral || token() === SyntaxKind.AsteriskToken ||
7226+ return token() === SyntaxKind.DeferKeyword || token() === SyntaxKind. StringLiteral || token() === SyntaxKind.AsteriskToken ||
72257227 token() === SyntaxKind.OpenBraceToken || tokenIsIdentifierOrKeyword(token());
72267228 case SyntaxKind.ExportKeyword:
72277229 let currentToken = nextToken();
@@ -7295,6 +7297,7 @@ namespace Parser {
72957297 case SyntaxKind.NamespaceKeyword:
72967298 case SyntaxKind.TypeKeyword:
72977299 case SyntaxKind.GlobalKeyword:
7300+ case SyntaxKind.DeferKeyword:
72987301 // When these don't start a declaration, they're an identifier in an expression statement
72997302 return true;
73007303
@@ -8366,6 +8369,7 @@ namespace Parser {
83668369 }
83678370
83688371 let isTypeOnly = false;
8372+ let phase = ImportPhase.Evaluation;
83698373 if (
83708374 identifier?.escapedText === "type" &&
83718375 (token() !== SyntaxKind.FromKeyword || isIdentifier() && lookAhead(nextTokenIsFromKeywordOrEqualsToken)) &&
@@ -8374,12 +8378,20 @@ namespace Parser {
83748378 isTypeOnly = true;
83758379 identifier = isIdentifier() ? parseIdentifier() : undefined;
83768380 }
8381+ else if (identifier?.escapedText === "defer" && token() !== SyntaxKind.FromKeyword) {
8382+ phase = ImportPhase.Defer;
8383+ identifier = undefined;
8384+ if (isIdentifier()) {
8385+ parseErrorAtCurrentToken(Diagnostics.Default_imports_aren_t_allowed_for_deferred_imports);
8386+ identifier = parseIdentifier();
8387+ }
8388+ }
83778389
8378- if (identifier && !tokenAfterImportedIdentifierDefinitelyProducesImportDeclaration()) {
8390+ if (identifier && !tokenAfterImportedIdentifierDefinitelyProducesImportDeclaration() && phase !== ImportPhase.Defer ) {
83798391 return parseImportEqualsDeclaration(pos, hasJSDoc, modifiers, identifier, isTypeOnly);
83808392 }
83818393
8382- const importClause = tryParseImportClause(identifier, afterImportPos, isTypeOnly);
8394+ const importClause = tryParseImportClause(identifier, afterImportPos, isTypeOnly, /*skipJsDocLeadingAsterisks*/ undefined, phase );
83838395 const moduleSpecifier = parseModuleSpecifier();
83848396 const attributes = tryParseImportAttributes();
83858397
@@ -8388,7 +8400,7 @@ namespace Parser {
83888400 return withJSDoc(finishNode(node, pos), hasJSDoc);
83898401 }
83908402
8391- function tryParseImportClause(identifier: Identifier | undefined, pos: number, isTypeOnly: boolean, skipJsDocLeadingAsterisks = false) {
8403+ function tryParseImportClause(identifier: Identifier | undefined, pos: number, isTypeOnly: boolean, skipJsDocLeadingAsterisks = false, phase: ImportPhase ) {
83928404 // ImportDeclaration:
83938405 // import ImportClause from ModuleSpecifier ;
83948406 // import ModuleSpecifier;
@@ -8398,7 +8410,7 @@ namespace Parser {
83988410 token() === SyntaxKind.AsteriskToken || // import *
83998411 token() === SyntaxKind.OpenBraceToken // import {
84008412 ) {
8401- importClause = parseImportClause(identifier, pos, isTypeOnly, skipJsDocLeadingAsterisks);
8413+ importClause = parseImportClause(identifier, pos, isTypeOnly, skipJsDocLeadingAsterisks, phase );
84028414 parseExpected(SyntaxKind.FromKeyword);
84038415 }
84048416 return importClause;
@@ -8464,7 +8476,7 @@ namespace Parser {
84648476 return finished;
84658477 }
84668478
8467- function parseImportClause(identifier: Identifier | undefined, pos: number, isTypeOnly: boolean, skipJsDocLeadingAsterisks: boolean) {
8479+ function parseImportClause(identifier: Identifier | undefined, pos: number, isTypeOnly: boolean, skipJsDocLeadingAsterisks: boolean, phase: ImportPhase ) {
84688480 // ImportClause:
84698481 // ImportedDefaultBinding
84708482 // NameSpaceImport
@@ -8480,11 +8492,19 @@ namespace Parser {
84808492 parseOptional(SyntaxKind.CommaToken)
84818493 ) {
84828494 if (skipJsDocLeadingAsterisks) scanner.setSkipJsDocLeadingAsterisks(true);
8483- namedBindings = token() === SyntaxKind.AsteriskToken ? parseNamespaceImport() : parseNamedImportsOrExports(SyntaxKind.NamedImports);
8495+ if (token() === SyntaxKind.AsteriskToken) {
8496+ namedBindings = parseNamespaceImport();
8497+ }
8498+ else {
8499+ if (phase === ImportPhase.Defer) {
8500+ parseErrorAtCurrentToken(Diagnostics.Named_imports_aren_t_allowed_for_deferred_imports);
8501+ }
8502+ namedBindings = parseNamedImportsOrExports(SyntaxKind.NamedImports);
8503+ }
84848504 if (skipJsDocLeadingAsterisks) scanner.setSkipJsDocLeadingAsterisks(false);
84858505 }
84868506
8487- return finishNode(factory.createImportClause(isTypeOnly, identifier, namedBindings), pos);
8507+ return finishNode(factory.createImportClause(isTypeOnly, identifier, namedBindings, phase ), pos);
84888508 }
84898509
84908510 function parseModuleReference() {
@@ -9518,7 +9538,7 @@ namespace Parser {
95189538 identifier = parseIdentifier();
95199539 }
95209540
9521- const importClause = tryParseImportClause(identifier, afterImportTagPos, /*isTypeOnly*/ true, /*skipJsDocLeadingAsterisks*/ true);
9541+ const importClause = tryParseImportClause(identifier, afterImportTagPos, /*isTypeOnly*/ true, /*skipJsDocLeadingAsterisks*/ true, ImportPhase.Evaluation );
95229542 const moduleSpecifier = parseModuleSpecifier();
95239543 const attributes = tryParseImportAttributes();
95249544
0 commit comments