@@ -542,7 +542,7 @@ namespace ts {
542542 const newSourceFile = IncrementalParser . updateSourceFile ( sourceFile , newText , textChangeRange , aggressiveChecks ) ;
543543 // Because new source file node is created, it may not have the flag PossiblyContainDynamicImport. This is the case if there is no new edit to add dynamic import.
544544 // We will manually port the flag to the new source file.
545- newSourceFile . flags |= ( sourceFile . flags & NodeFlags . PossiblyContainsDynamicImport ) ;
545+ newSourceFile . flags |= ( sourceFile . flags & NodeFlags . PermanentlySetIncrementalFlags ) ;
546546 return newSourceFile ;
547547 }
548548
@@ -2627,6 +2627,20 @@ namespace ts {
26272627 return token ( ) === SyntaxKind . OpenParenToken || token ( ) === SyntaxKind . LessThanToken ;
26282628 }
26292629
2630+ function nextTokenIsDot ( ) {
2631+ return nextToken ( ) === SyntaxKind . DotToken ;
2632+ }
2633+
2634+ function nextTokenIsOpenParenOrLessThanOrDot ( ) {
2635+ switch ( nextToken ( ) ) {
2636+ case SyntaxKind . OpenParenToken :
2637+ case SyntaxKind . LessThanToken :
2638+ case SyntaxKind . DotToken :
2639+ return true ;
2640+ }
2641+ return false ;
2642+ }
2643+
26302644 function parseTypeLiteral ( ) : TypeLiteralNode {
26312645 const node = < TypeLiteralNode > createNode ( SyntaxKind . TypeLiteral ) ;
26322646 node . members = parseObjectTypeMembers ( ) ;
@@ -3095,7 +3109,7 @@ namespace ts {
30953109 case SyntaxKind . Identifier :
30963110 return true ;
30973111 case SyntaxKind . ImportKeyword :
3098- return lookAhead ( nextTokenIsOpenParenOrLessThan ) ;
3112+ return lookAhead ( nextTokenIsOpenParenOrLessThanOrDot ) ;
30993113 default :
31003114 return isIdentifier ( ) ;
31013115 }
@@ -3957,14 +3971,31 @@ namespace ts {
39573971 // 3)we have a MemberExpression which either completes the LeftHandSideExpression,
39583972 // or starts the beginning of the first four CallExpression productions.
39593973 let expression : MemberExpression ;
3960- if ( token ( ) === SyntaxKind . ImportKeyword && lookAhead ( nextTokenIsOpenParenOrLessThan ) ) {
3961- // We don't want to eagerly consume all import keyword as import call expression so we look a head to find "("
3962- // For example:
3963- // var foo3 = require("subfolder
3964- // import * as foo1 from "module-from-node
3965- // We want this import to be a statement rather than import call expression
3966- sourceFile . flags |= NodeFlags . PossiblyContainsDynamicImport ;
3967- expression = parseTokenNode < PrimaryExpression > ( ) ;
3974+ if ( token ( ) === SyntaxKind . ImportKeyword ) {
3975+ if ( lookAhead ( nextTokenIsOpenParenOrLessThan ) ) {
3976+ // We don't want to eagerly consume all import keyword as import call expression so we look ahead to find "("
3977+ // For example:
3978+ // var foo3 = require("subfolder
3979+ // import * as foo1 from "module-from-node
3980+ // We want this import to be a statement rather than import call expression
3981+ sourceFile . flags |= NodeFlags . PossiblyContainsDynamicImport ;
3982+ expression = parseTokenNode < PrimaryExpression > ( ) ;
3983+ }
3984+ else if ( lookAhead ( nextTokenIsDot ) ) {
3985+ // This is an 'import.*' metaproperty (i.e. 'import.meta')
3986+ const fullStart = scanner . getStartPos ( ) ;
3987+ nextToken ( ) ; // advance past the 'import'
3988+ nextToken ( ) ; // advance past the dot
3989+ const node = createNode ( SyntaxKind . MetaProperty , fullStart ) as MetaProperty ;
3990+ node . keywordToken = SyntaxKind . ImportKeyword ;
3991+ node . name = parseIdentifierName ( ) ;
3992+ expression = finishNode ( node ) ;
3993+
3994+ sourceFile . flags |= NodeFlags . PossiblyContainsImportMeta ;
3995+ }
3996+ else {
3997+ expression = parseMemberExpressionOrHigher ( ) ;
3998+ }
39683999 }
39694000 else {
39704001 expression = token ( ) === SyntaxKind . SuperKeyword ? parseSuperExpression ( ) : parseMemberExpressionOrHigher ( ) ;
@@ -4508,7 +4539,7 @@ namespace ts {
45084539 case SyntaxKind . FunctionKeyword :
45094540 return parseFunctionExpression ( ) ;
45104541 case SyntaxKind . NewKeyword :
4511- return parseNewExpression ( ) ;
4542+ return parseNewExpressionOrNewDotTarget ( ) ;
45124543 case SyntaxKind . SlashToken :
45134544 case SyntaxKind . SlashEqualsToken :
45144545 if ( reScanSlashToken ( ) === SyntaxKind . RegularExpressionLiteral ) {
@@ -4659,7 +4690,7 @@ namespace ts {
46594690 return isIdentifier ( ) ? parseIdentifier ( ) : undefined ;
46604691 }
46614692
4662- function parseNewExpression ( ) : NewExpression | MetaProperty {
4693+ function parseNewExpressionOrNewDotTarget ( ) : NewExpression | MetaProperty {
46634694 const fullStart = scanner . getStartPos ( ) ;
46644695 parseExpected ( SyntaxKind . NewKeyword ) ;
46654696 if ( parseOptional ( SyntaxKind . DotToken ) ) {
@@ -5093,7 +5124,7 @@ namespace ts {
50935124 return true ;
50945125
50955126 case SyntaxKind . ImportKeyword :
5096- return isStartOfDeclaration ( ) || lookAhead ( nextTokenIsOpenParenOrLessThan ) ;
5127+ return isStartOfDeclaration ( ) || lookAhead ( nextTokenIsOpenParenOrLessThanOrDot ) ;
50975128
50985129 case SyntaxKind . ConstKeyword :
50995130 case SyntaxKind . ExportKeyword :
@@ -6079,14 +6110,29 @@ namespace ts {
60796110 }
60806111
60816112 function setExternalModuleIndicator ( sourceFile : SourceFile ) {
6082- sourceFile . externalModuleIndicator = forEach ( sourceFile . statements , node =>
6083- hasModifier ( node , ModifierFlags . Export )
6084- || node . kind === SyntaxKind . ImportEqualsDeclaration && ( < ImportEqualsDeclaration > node ) . moduleReference . kind === SyntaxKind . ExternalModuleReference
6085- || node . kind === SyntaxKind . ImportDeclaration
6086- || node . kind === SyntaxKind . ExportAssignment
6087- || node . kind === SyntaxKind . ExportDeclaration
6113+ // Usually we'd like to avoid a full tree walk, but it's possible
6114+ // that we have a deeper external module indicator (e.g. `import.meta`,
6115+ // and possibly nested import statements in the future).
6116+ // Ideally the first few statements will be an import/export anyway.
6117+ sourceFile . externalModuleIndicator =
6118+ ! ( sourceFile . flags & NodeFlags . PossiblyContainsImportMeta ) ?
6119+ forEach ( sourceFile . statements , isAnExternalModuleIndicatorNode ) :
6120+ walkTreeForExternalModuleIndicators ( sourceFile ) ;
6121+ }
6122+
6123+ function isAnExternalModuleIndicatorNode ( node : Node ) {
6124+ return hasModifier ( node , ModifierFlags . Export )
6125+ || node . kind === SyntaxKind . ImportEqualsDeclaration && ( < ImportEqualsDeclaration > node ) . moduleReference . kind === SyntaxKind . ExternalModuleReference
6126+ || node . kind === SyntaxKind . ImportDeclaration
6127+ || node . kind === SyntaxKind . ExportAssignment
6128+ || node . kind === SyntaxKind . ExportDeclaration
6129+ || isMetaProperty ( node ) && node . keywordToken === SyntaxKind . ImportKeyword && node . name . escapedText === "meta"
60886130 ? node
6089- : undefined ) ;
6131+ : undefined
6132+ }
6133+
6134+ function walkTreeForExternalModuleIndicators ( node : Node ) : Node {
6135+ return isAnExternalModuleIndicatorNode ( node ) ? node : forEachChild ( node , walkTreeForExternalModuleIndicators ) ;
60906136 }
60916137
60926138 const enum ParsingContext {
0 commit comments