@@ -540,7 +540,7 @@ namespace ts {
540
540
const newSourceFile = IncrementalParser . updateSourceFile ( sourceFile , newText , textChangeRange , aggressiveChecks ) ;
541
541
// 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.
542
542
// We will manually port the flag to the new source file.
543
- newSourceFile . flags |= ( sourceFile . flags & NodeFlags . PossiblyContainsDynamicImport ) ;
543
+ newSourceFile . flags |= ( sourceFile . flags & NodeFlags . PermanentlySetIncrementalFlags ) ;
544
544
return newSourceFile ;
545
545
}
546
546
@@ -2628,6 +2628,20 @@ namespace ts {
2628
2628
return token ( ) === SyntaxKind . OpenParenToken || token ( ) === SyntaxKind . LessThanToken ;
2629
2629
}
2630
2630
2631
+ function nextTokenIsDot ( ) {
2632
+ return nextToken ( ) === SyntaxKind . DotToken ;
2633
+ }
2634
+
2635
+ function nextTokenIsOpenParenOrLessThanOrDot ( ) {
2636
+ switch ( nextToken ( ) ) {
2637
+ case SyntaxKind . OpenParenToken :
2638
+ case SyntaxKind . LessThanToken :
2639
+ case SyntaxKind . DotToken :
2640
+ return true ;
2641
+ }
2642
+ return false ;
2643
+ }
2644
+
2631
2645
function parseTypeLiteral ( ) : TypeLiteralNode {
2632
2646
const node = < TypeLiteralNode > createNode ( SyntaxKind . TypeLiteral ) ;
2633
2647
node . members = parseObjectTypeMembers ( ) ;
@@ -3096,7 +3110,7 @@ namespace ts {
3096
3110
case SyntaxKind . Identifier :
3097
3111
return true ;
3098
3112
case SyntaxKind . ImportKeyword :
3099
- return lookAhead ( nextTokenIsOpenParenOrLessThan ) ;
3113
+ return lookAhead ( nextTokenIsOpenParenOrLessThanOrDot ) ;
3100
3114
default :
3101
3115
return isIdentifier ( ) ;
3102
3116
}
@@ -3958,14 +3972,31 @@ namespace ts {
3958
3972
// 3)we have a MemberExpression which either completes the LeftHandSideExpression,
3959
3973
// or starts the beginning of the first four CallExpression productions.
3960
3974
let expression : MemberExpression ;
3961
- if ( token ( ) === SyntaxKind . ImportKeyword && lookAhead ( nextTokenIsOpenParenOrLessThan ) ) {
3962
- // We don't want to eagerly consume all import keyword as import call expression so we look a head to find "("
3963
- // For example:
3964
- // var foo3 = require("subfolder
3965
- // import * as foo1 from "module-from-node
3966
- // We want this import to be a statement rather than import call expression
3967
- sourceFile . flags |= NodeFlags . PossiblyContainsDynamicImport ;
3968
- expression = parseTokenNode < PrimaryExpression > ( ) ;
3975
+ if ( token ( ) === SyntaxKind . ImportKeyword ) {
3976
+ if ( lookAhead ( nextTokenIsOpenParenOrLessThan ) ) {
3977
+ // We don't want to eagerly consume all import keyword as import call expression so we look ahead to find "("
3978
+ // For example:
3979
+ // var foo3 = require("subfolder
3980
+ // import * as foo1 from "module-from-node
3981
+ // We want this import to be a statement rather than import call expression
3982
+ sourceFile . flags |= NodeFlags . PossiblyContainsDynamicImport ;
3983
+ expression = parseTokenNode < PrimaryExpression > ( ) ;
3984
+ }
3985
+ else if ( lookAhead ( nextTokenIsDot ) ) {
3986
+ // This is an 'import.*' metaproperty (i.e. 'import.meta')
3987
+ const fullStart = scanner . getStartPos ( ) ;
3988
+ nextToken ( ) ; // advance past the 'import'
3989
+ nextToken ( ) ; // advance past the dot
3990
+ const node = createNode ( SyntaxKind . MetaProperty , fullStart ) as MetaProperty ;
3991
+ node . keywordToken = SyntaxKind . ImportKeyword ;
3992
+ node . name = parseIdentifierName ( ) ;
3993
+ expression = finishNode ( node ) ;
3994
+
3995
+ sourceFile . flags |= NodeFlags . PossiblyContainsImportMeta ;
3996
+ }
3997
+ else {
3998
+ expression = parseMemberExpressionOrHigher ( ) ;
3999
+ }
3969
4000
}
3970
4001
else {
3971
4002
expression = token ( ) === SyntaxKind . SuperKeyword ? parseSuperExpression ( ) : parseMemberExpressionOrHigher ( ) ;
@@ -4526,7 +4557,7 @@ namespace ts {
4526
4557
case SyntaxKind . FunctionKeyword :
4527
4558
return parseFunctionExpression ( ) ;
4528
4559
case SyntaxKind . NewKeyword :
4529
- return parseNewExpression ( ) ;
4560
+ return parseNewExpressionOrNewDotTarget ( ) ;
4530
4561
case SyntaxKind . SlashToken :
4531
4562
case SyntaxKind . SlashEqualsToken :
4532
4563
if ( reScanSlashToken ( ) === SyntaxKind . RegularExpressionLiteral ) {
@@ -4677,7 +4708,7 @@ namespace ts {
4677
4708
return isIdentifier ( ) ? parseIdentifier ( ) : undefined ;
4678
4709
}
4679
4710
4680
- function parseNewExpression ( ) : NewExpression | MetaProperty {
4711
+ function parseNewExpressionOrNewDotTarget ( ) : NewExpression | MetaProperty {
4681
4712
const fullStart = scanner . getStartPos ( ) ;
4682
4713
parseExpected ( SyntaxKind . NewKeyword ) ;
4683
4714
if ( parseOptional ( SyntaxKind . DotToken ) ) {
@@ -5125,7 +5156,7 @@ namespace ts {
5125
5156
return true ;
5126
5157
5127
5158
case SyntaxKind . ImportKeyword :
5128
- return isStartOfDeclaration ( ) || lookAhead ( nextTokenIsOpenParenOrLessThan ) ;
5159
+ return isStartOfDeclaration ( ) || lookAhead ( nextTokenIsOpenParenOrLessThanOrDot ) ;
5129
5160
5130
5161
case SyntaxKind . ConstKeyword :
5131
5162
case SyntaxKind . ExportKeyword :
@@ -6109,14 +6140,35 @@ namespace ts {
6109
6140
}
6110
6141
6111
6142
function setExternalModuleIndicator ( sourceFile : SourceFile ) {
6112
- sourceFile . externalModuleIndicator = forEach ( sourceFile . statements , node =>
6113
- hasModifier ( node , ModifierFlags . Export )
6114
- || node . kind === SyntaxKind . ImportEqualsDeclaration && ( < ImportEqualsDeclaration > node ) . moduleReference . kind === SyntaxKind . ExternalModuleReference
6115
- || node . kind === SyntaxKind . ImportDeclaration
6116
- || node . kind === SyntaxKind . ExportAssignment
6117
- || node . kind === SyntaxKind . ExportDeclaration
6143
+ // Try to use the first top-level import/export when available, then
6144
+ // fall back to looking for an 'import.meta' somewhere in the tree if necessary.
6145
+ sourceFile . externalModuleIndicator =
6146
+ forEach ( sourceFile . statements , isAnExternalModuleIndicatorNode ) ||
6147
+ getImportMetaIfNecessary ( sourceFile ) ;
6148
+ }
6149
+
6150
+ function isAnExternalModuleIndicatorNode ( node : Node ) {
6151
+ return hasModifier ( node , ModifierFlags . Export )
6152
+ || node . kind === SyntaxKind . ImportEqualsDeclaration && ( < ImportEqualsDeclaration > node ) . moduleReference . kind === SyntaxKind . ExternalModuleReference
6153
+ || node . kind === SyntaxKind . ImportDeclaration
6154
+ || node . kind === SyntaxKind . ExportAssignment
6155
+ || node . kind === SyntaxKind . ExportDeclaration
6118
6156
? node
6119
- : undefined ) ;
6157
+ : undefined ;
6158
+ }
6159
+
6160
+ function getImportMetaIfNecessary ( sourceFile : SourceFile ) {
6161
+ return sourceFile . flags & NodeFlags . PossiblyContainsImportMeta ?
6162
+ walkTreeForExternalModuleIndicators ( sourceFile ) :
6163
+ undefined ;
6164
+ }
6165
+
6166
+ function walkTreeForExternalModuleIndicators ( node : Node ) : Node | undefined {
6167
+ return isImportMeta ( node ) ? node : forEachChild ( node , walkTreeForExternalModuleIndicators ) ;
6168
+ }
6169
+
6170
+ function isImportMeta ( node : Node ) : boolean {
6171
+ return isMetaProperty ( node ) && node . keywordToken === SyntaxKind . ImportKeyword && node . name . escapedText === "meta" ;
6120
6172
}
6121
6173
6122
6174
const enum ParsingContext {
0 commit comments