@@ -2410,7 +2410,7 @@ void Parser::ParseNamedImportOrExportClause(ModuleImportOrExportEntryList* impor
2410
2410
if (m_token.tk == tkID)
2411
2411
{
2412
2412
// We have the pattern "IdentifierName as"
2413
- if (wellKnownPropertyPids.as != m_token.GetIdentifier(this->GetHashTbl() ))
2413
+ if (!CheckContextualKeyword( wellKnownPropertyPids.as))
2414
2414
{
2415
2415
Error(ERRsyntax);
2416
2416
}
@@ -2666,7 +2666,7 @@ void Parser::ParseImportClause(ModuleImportOrExportEntryList* importEntryList, b
2666
2666
2667
2667
// Token following * must be the identifier 'as'
2668
2668
this->GetScanner()->Scan();
2669
- if (m_token.tk != tkID || wellKnownPropertyPids.as != m_token.GetIdentifier(this->GetHashTbl() ))
2669
+ if (!CheckContextualKeyword( wellKnownPropertyPids.as))
2670
2670
{
2671
2671
Error(ERRsyntax);
2672
2672
}
@@ -2828,7 +2828,7 @@ IdentPtr Parser::ParseImportOrExportFromClause(bool throwIfNotFound)
2828
2828
{
2829
2829
IdentPtr moduleSpecifier = nullptr;
2830
2830
2831
- if (m_token.tk == tkID && wellKnownPropertyPids.from == m_token.GetIdentifier(this->GetHashTbl() ))
2831
+ if (CheckContextualKeyword( wellKnownPropertyPids.from))
2832
2832
{
2833
2833
this->GetScanner()->Scan();
2834
2834
@@ -2901,7 +2901,7 @@ ParseNodePtr Parser::ParseDefaultExportClause()
2901
2901
// function token) or it could be an identifier (let async = 0; export default async;).
2902
2902
// To handle both cases, when we parse an async token we need to keep the parser state
2903
2903
// and rewind if the next token is not function.
2904
- if (wellKnownPropertyPids.async == m_token.GetIdentifier(this->GetHashTbl() ))
2904
+ if (CheckContextualKeyword( wellKnownPropertyPids.async))
2905
2905
{
2906
2906
RestorePoint parsedAsync;
2907
2907
this->GetScanner()->Capture(&parsedAsync);
@@ -3023,26 +3023,22 @@ ParseNodePtr Parser::ParseExportDeclaration(bool *needTerminator)
3023
3023
3024
3024
if (m_scriptContext->GetConfig()->IsESExportNsAsEnabled())
3025
3025
{
3026
- // export * as name
3027
- if (m_token.tk == tkID )
3026
+ // check for 'as'
3027
+ if (CheckContextualKeyword(wellKnownPropertyPids.as) )
3028
3028
{
3029
- // check for 'as'
3030
- if (wellKnownPropertyPids.as == m_token.GetIdentifier(this->GetHashTbl()))
3029
+ // scan to the next token
3030
+ this->GetScanner()->Scan();
3031
+
3032
+ // token after as must be an identifier
3033
+ if (!(m_token.IsIdentifier() || m_token.IsReservedWord()))
3031
3034
{
3032
- // scan to the next token
3033
- this->GetScanner()->Scan();
3035
+ Error(ERRValidIfFollowedBy, _u("'as'"), _u("an identifier."));
3036
+ }
3034
3037
3035
- // token after as must be an identifier
3036
- if (!(m_token.IsIdentifier() || m_token.IsReservedWord()))
3037
- {
3038
- Error(ERRValidIfFollowedBy, _u("'as'"), _u("an identifier."));
3039
- }
3038
+ exportName = m_token.GetIdentifier(this->GetHashTbl());
3040
3039
3041
- exportName = m_token.GetIdentifier(this->GetHashTbl());
3042
-
3043
- // scan to next token
3044
- this->GetScanner()->Scan();
3045
- }
3040
+ // scan to next token
3041
+ this->GetScanner()->Scan();
3046
3042
}
3047
3043
}
3048
3044
@@ -3122,14 +3118,18 @@ ParseNodePtr Parser::ParseExportDeclaration(bool *needTerminator)
3122
3118
3123
3119
case tkID:
3124
3120
{
3125
- IdentPtr pid = m_token.GetIdentifier(this->GetHashTbl());
3121
+ IdentPtr pid = nullptr;
3122
+ if (!this->GetScanner()->LastIdentifierHasEscape())
3123
+ {
3124
+ pid = m_token.GetIdentifier(this->GetHashTbl());
3125
+ }
3126
3126
3127
- if (wellKnownPropertyPids.let == pid )
3127
+ if (pid == wellKnownPropertyPids.let )
3128
3128
{
3129
3129
declarationType = tkLET;
3130
3130
goto ParseVarDecl;
3131
3131
}
3132
- if (wellKnownPropertyPids.async == pid && m_scriptContext->GetConfig()->IsES7AsyncAndAwaitEnabled())
3132
+ if (pid == wellKnownPropertyPids.async && m_scriptContext->GetConfig()->IsES7AsyncAndAwaitEnabled())
3133
3133
{
3134
3134
// In module export statements, async token is only valid if it's followed by function.
3135
3135
// We need to check here because ParseStatement would think 'async = 20' is a var decl.
@@ -3267,6 +3267,7 @@ ParseNodePtr Parser::ParseTerm(BOOL fAllowCall,
3267
3267
iecpLim = this->GetScanner()->IecpLimTok();
3268
3268
3269
3269
if (pid == wellKnownPropertyPids.async &&
3270
+ !this->GetScanner()->LastIdentifierHasEscape() &&
3270
3271
m_scriptContext->GetConfig()->IsES7AsyncAndAwaitEnabled())
3271
3272
{
3272
3273
isAsyncExpr = true;
@@ -4747,7 +4748,7 @@ ParseNodePtr Parser::ParseMemberList(LPCOLESTR pNameHint, uint32* pNameHintLengt
4747
4748
bool isAsyncMethod = false;
4748
4749
charcount_t ichMin = this->GetScanner()->IchMinTok();
4749
4750
size_t iecpMin = this->GetScanner()->IecpMinTok();
4750
- if (m_token.tk == tkID && m_token.GetIdentifier(this->GetHashTbl()) == wellKnownPropertyPids.async && m_scriptContext->GetConfig()->IsES7AsyncAndAwaitEnabled())
4751
+ if (CheckContextualKeyword( wellKnownPropertyPids.async) && m_scriptContext->GetConfig()->IsES7AsyncAndAwaitEnabled())
4751
4752
{
4752
4753
RestorePoint parsedAsync;
4753
4754
this->GetScanner()->Capture(&parsedAsync);
@@ -4789,6 +4790,7 @@ ParseNodePtr Parser::ParseMemberList(LPCOLESTR pNameHint, uint32* pNameHintLengt
4789
4790
charcount_t idHintIchLim = static_cast<charcount_t>(this->GetScanner()->IecpLimTok());
4790
4791
bool wrapInBrackets = false;
4791
4792
bool seenEllipsis = false;
4793
+ bool maybeKeyword = false;
4792
4794
switch (m_token.tk)
4793
4795
{
4794
4796
default:
@@ -4801,6 +4803,7 @@ ParseNodePtr Parser::ParseMemberList(LPCOLESTR pNameHint, uint32* pNameHintLengt
4801
4803
// fall-through
4802
4804
case tkID:
4803
4805
pidHint = m_token.GetIdentifier(this->GetHashTbl());
4806
+ maybeKeyword = !this->GetScanner()->LastIdentifierHasEscape();
4804
4807
if (buildAST)
4805
4808
{
4806
4809
pnodeName = CreateStrNode(pidHint);
@@ -5066,9 +5069,10 @@ ParseNodePtr Parser::ParseMemberList(LPCOLESTR pNameHint, uint32* pNameHintLengt
5066
5069
{
5067
5070
Assert(pidHint->Psz() != nullptr);
5068
5071
5072
+ // get/set are only pseudo keywords when they are identifiers (i.e. not strings)
5069
5073
if ((pidHint == wellKnownPropertyPids.get || pidHint == wellKnownPropertyPids.set) &&
5070
- // get/set are only pseudo keywords when they are identifiers (i.e. not strings)
5071
- tkHint.tk == tkID && NextTokenIsPropertyNameStart())
5074
+ maybeKeyword &&
5075
+ NextTokenIsPropertyNameStart())
5072
5076
{
5073
5077
if (isObjectPattern)
5074
5078
{
@@ -7471,7 +7475,7 @@ void Parser::FinishFncNode(ParseNodeFnc * pnodeFnc, bool fAllowIn)
7471
7475
for (;;)
7472
7476
{
7473
7477
this->GetScanner()->Scan();
7474
- if (m_token.GetIdentifier(this->GetHashTbl()) == wellKnownPropertyPids.async)
7478
+ if (CheckContextualKeyword( wellKnownPropertyPids.async) )
7475
7479
{
7476
7480
Assert(pnodeFnc->IsAsync());
7477
7481
continue;
@@ -7502,7 +7506,7 @@ void Parser::FinishFncNode(ParseNodeFnc * pnodeFnc, bool fAllowIn)
7502
7506
Assert(pnodeFnc->IsGenerator());
7503
7507
this->GetScanner()->ScanNoKeywords();
7504
7508
}
7505
- if (fLambda && m_token.tk == tkID && m_token.GetIdentifier(this->GetHashTbl()) == wellKnownPropertyPids.async)
7509
+ if (fLambda && CheckContextualKeyword( wellKnownPropertyPids.async) )
7506
7510
{
7507
7511
Assert(pnodeFnc->IsAsync());
7508
7512
this->GetScanner()->ScanNoKeywords();
@@ -7960,13 +7964,14 @@ ParseNodeClass * Parser::ParseClassDecl(BOOL isDeclaration, LPCOLESTR pNameHint,
7960
7964
ParseNodePtr pnodeMemberName = nullptr;
7961
7965
IdentPtr pidHint = nullptr;
7962
7966
IdentPtr memberPid = nullptr;
7967
+ bool maybeAccessor = false;
7963
7968
LPCOLESTR pMemberNameHint = nullptr;
7964
- uint32 memberNameHintLength = 0;
7965
- uint32 memberNameOffset = 0;
7969
+ uint32 memberNameHintLength = 0;
7970
+ uint32 memberNameOffset = 0;
7966
7971
bool isComputedName = false;
7967
7972
bool isAsyncMethod = false;
7968
7973
7969
- if (m_token.tk == tkID && m_token.GetIdentifier(this->GetHashTbl()) == wellKnownPropertyPids.async && m_scriptContext->GetConfig()->IsES7AsyncAndAwaitEnabled())
7974
+ if (CheckContextualKeyword( wellKnownPropertyPids.async) && m_scriptContext->GetConfig()->IsES7AsyncAndAwaitEnabled())
7970
7975
{
7971
7976
RestorePoint parsedAsync;
7972
7977
this->GetScanner()->Capture(&parsedAsync);
@@ -8002,6 +8007,7 @@ ParseNodeClass * Parser::ParseClassDecl(BOOL isDeclaration, LPCOLESTR pNameHint,
8002
8007
}
8003
8008
else // not computed name
8004
8009
{
8010
+ maybeAccessor = !this->GetScanner()->LastIdentifierHasEscape();
8005
8011
memberPid = this->ParseClassPropertyName(&pidHint);
8006
8012
if (pidHint)
8007
8013
{
@@ -8063,21 +8069,21 @@ ParseNodeClass * Parser::ParseClassDecl(BOOL isDeclaration, LPCOLESTR pNameHint,
8063
8069
else
8064
8070
{
8065
8071
ParseNodePtr pnodeMember = nullptr;
8066
-
8067
- bool isMemberNamedGetOrSet = false;
8068
8072
RestorePoint beginMethodName;
8069
8073
this->GetScanner()->Capture(&beginMethodName);
8070
- if (memberPid == wellKnownPropertyPids.get || memberPid == wellKnownPropertyPids.set)
8074
+
8075
+ if (maybeAccessor && (memberPid == wellKnownPropertyPids.get || memberPid == wellKnownPropertyPids.set))
8071
8076
{
8072
8077
this->GetScanner()->ScanForcingPid();
8073
8078
}
8079
+
8074
8080
if (m_token.tk == tkLParen)
8075
8081
{
8076
8082
this->GetScanner()->SeekTo(beginMethodName);
8077
- isMemberNamedGetOrSet = true ;
8083
+ maybeAccessor = false ;
8078
8084
}
8079
8085
8080
- if ((memberPid == wellKnownPropertyPids.get || memberPid == wellKnownPropertyPids.set) && !isMemberNamedGetOrSet )
8086
+ if (maybeAccessor && (memberPid == wellKnownPropertyPids.get || memberPid == wellKnownPropertyPids.set))
8081
8087
{
8082
8088
bool isGetter = (memberPid == wellKnownPropertyPids.get);
8083
8089
@@ -9244,7 +9250,7 @@ ParseNodePtr Parser::ParseExpr(int oplMin,
9244
9250
RestoreStateFrom(&parserState);
9245
9251
9246
9252
this->GetScanner()->SeekTo(termStart);
9247
- if (m_token.tk == tkID && m_token.GetIdentifier(this->GetHashTbl()) == wellKnownPropertyPids.async && m_scriptContext->GetConfig()->IsES7AsyncAndAwaitEnabled())
9253
+ if (CheckContextualKeyword( wellKnownPropertyPids.async) && m_scriptContext->GetConfig()->IsES7AsyncAndAwaitEnabled())
9248
9254
{
9249
9255
ichMin = this->GetScanner()->IchMinTok();
9250
9256
iecpMin = this->GetScanner()->IecpMinTok();
@@ -10216,7 +10222,7 @@ ParseNodePtr Parser::ParseStatement()
10216
10222
10217
10223
case tkID:
10218
10224
case tkLET:
10219
- if (m_token.GetIdentifier(this->GetHashTbl()) == wellKnownPropertyPids.let)
10225
+ if (tok == tkLET || CheckContextualKeyword( wellKnownPropertyPids.let) )
10220
10226
{
10221
10227
// We see "let" at the start of a statement. This could either be a declaration or an identifier
10222
10228
// reference. The next token determines which.
@@ -10241,7 +10247,7 @@ ParseNodePtr Parser::ParseStatement()
10241
10247
}
10242
10248
this->GetScanner()->SeekTo(parsedLet);
10243
10249
}
10244
- else if (m_token.GetIdentifier(this->GetHashTbl()) == wellKnownPropertyPids.async && m_scriptContext->GetConfig()->IsES7AsyncAndAwaitEnabled())
10250
+ else if (CheckContextualKeyword( wellKnownPropertyPids.async) && m_scriptContext->GetConfig()->IsES7AsyncAndAwaitEnabled())
10245
10251
{
10246
10252
RestorePoint parsedAsync;
10247
10253
this->GetScanner()->Capture(&parsedAsync);
@@ -10286,7 +10292,7 @@ ParseNodePtr Parser::ParseStatement()
10286
10292
ichMin = this->GetScanner()->IchMinTok();
10287
10293
10288
10294
this->GetScanner()->Scan();
10289
- if (m_token.tk == tkAWAIT || (m_token.tk == tkID && m_token.GetIdentifier(this->GetHashTbl()) == wellKnownPropertyPids.await))
10295
+ if (m_token.tk == tkAWAIT || CheckContextualKeyword( wellKnownPropertyPids.await))
10290
10296
{
10291
10297
if (!this->GetScanner()->AwaitIsKeywordRegion())
10292
10298
{
@@ -10317,7 +10323,7 @@ ParseNodePtr Parser::ParseStatement()
10317
10323
switch (tok)
10318
10324
{
10319
10325
case tkID:
10320
- if (m_token.GetIdentifier(this->GetHashTbl()) == wellKnownPropertyPids.let)
10326
+ if (CheckContextualKeyword( wellKnownPropertyPids.let) )
10321
10327
{
10322
10328
// We see "let" in the init part of a for loop. This could either be a declaration or an identifier
10323
10329
// reference. The next token determines which.
@@ -10426,7 +10432,7 @@ ParseNodePtr Parser::ParseStatement()
10426
10432
if (TokIsForInOrForOf())
10427
10433
{
10428
10434
bool isForOf = (m_token.tk != tkIN);
10429
- Assert(!isForOf || (m_token.tk == tkID && m_token.GetIdentifier(this->GetHashTbl()) == wellKnownPropertyPids.of));
10435
+ Assert(!isForOf || CheckContextualKeyword( wellKnownPropertyPids.of));
10430
10436
10431
10437
if (isForAwait && !isForOf)
10432
10438
{
@@ -11321,9 +11327,7 @@ ParseNodePtr Parser::ParseStatement()
11321
11327
BOOL
11322
11328
Parser::TokIsForInOrForOf()
11323
11329
{
11324
- return m_token.tk == tkIN ||
11325
- (m_token.tk == tkID &&
11326
- m_token.GetIdentifier(this->GetHashTbl()) == wellKnownPropertyPids.of);
11330
+ return m_token.tk == tkIN || CheckContextualKeyword(wellKnownPropertyPids.of);
11327
11331
}
11328
11332
11329
11333
/***************************************************************************
0 commit comments