@@ -3215,6 +3215,14 @@ ParseNodePtr Parser::ParseTerm(BOOL fAllowCall,
3215
3215
pid = ParseSuper<buildAST>(!!fAllowCall);
3216
3216
isSpecialName = true;
3217
3217
3218
+ // Super reference and super call need to push a pid ref to 'this' even when not building an AST
3219
+ ReferenceSpecialName(wellKnownPropertyPids._this, ichMin, ichLim);
3220
+ // Super call needs to reference 'new.target'
3221
+ if (pid == wellKnownPropertyPids._superConstructor)
3222
+ {
3223
+ ReferenceSpecialName(wellKnownPropertyPids._newTarget, ichMin, ichLim);
3224
+ }
3225
+
3218
3226
goto LIdentifier;
3219
3227
3220
3228
case tkTHIS:
@@ -4529,6 +4537,11 @@ ParseNodePtr Parser::ParseMemberList(LPCOLESTR pNameHint, uint32* pNameHintLengt
4529
4537
{
4530
4538
Error(ERRsyntax);
4531
4539
}
4540
+
4541
+ // Include star character in the function extents
4542
+ ichMin = m_pscan->IchMinTok();
4543
+ iecpMin = m_pscan->IecpMinTok();
4544
+
4532
4545
m_pscan->ScanForcingPid();
4533
4546
fncDeclFlags |= fFncGenerator;
4534
4547
}
@@ -4702,7 +4715,7 @@ ParseNodePtr Parser::ParseMemberList(LPCOLESTR pNameHint, uint32* pNameHintLengt
4702
4715
ParseNodePtr pnodeFunc = ParseFncDecl<buildAST>(fncDeclFlags | (isAsyncMethod ? fFncAsync : fFncNoFlgs), pFullNameHint,
4703
4716
/*needsPIDOnRCurlyScan*/ false, /*resetParsingSuperRestrictionState*/ false);
4704
4717
4705
- if (isAsyncMethod)
4718
+ if (isAsyncMethod || isGenerator )
4706
4719
{
4707
4720
pnodeFunc->sxFnc.cbMin = iecpMin;
4708
4721
pnodeFunc->ichMin = ichMin;
@@ -5277,7 +5290,6 @@ bool Parser::ParseFncDeclHelper(ParseNodePtr pnodeFnc, LPCOLESTR pNameHint, usho
5277
5290
// switch scanner to treat 'yield' as keyword in generator functions
5278
5291
// or as an identifier in non-generator functions
5279
5292
bool fPreviousYieldIsKeyword = m_pscan->SetYieldIsKeywordRegion(pnodeFnc && pnodeFnc->sxFnc.IsGenerator());
5280
-
5281
5293
bool fPreviousAwaitIsKeyword = m_pscan->SetAwaitIsKeywordRegion(fAsync);
5282
5294
5283
5295
if (pnodeFnc && pnodeFnc->sxFnc.IsGenerator())
@@ -5318,10 +5330,10 @@ bool Parser::ParseFncDeclHelper(ParseNodePtr pnodeFnc, LPCOLESTR pNameHint, usho
5318
5330
}
5319
5331
5320
5332
uint uDeferSave = m_grfscr & fscrDeferFncParse;
5321
- if (flags & fFncNoName )
5333
+ if (flags & fFncClassMember )
5322
5334
{
5323
- // Disable deferral on getter/setter or other construct with unusual text bounds
5324
- // (fFncNoName) as these are usually trivial, and re-parsing is problematic.
5335
+ // Disable deferral on class members or other construct with unusual text bounds
5336
+ // as these are usually trivial, and re-parsing is problematic.
5325
5337
// NOTE: It is probably worth supporting these cases for memory and load-time purposes,
5326
5338
// especially as they become more and more common.
5327
5339
m_grfscr &= ~fscrDeferFncParse;
@@ -7129,6 +7141,7 @@ void Parser::FinishFncNode(ParseNodePtr pnodeFnc)
7129
7141
m_pnestedCount = &pnodeFnc->sxFnc.nestedCount;
7130
7142
7131
7143
bool fLambda = pnodeFnc->sxFnc.IsLambda();
7144
+ bool fMethod = pnodeFnc->sxFnc.IsMethod();
7132
7145
7133
7146
// Cue up the parser to the start of the function body.
7134
7147
if (pnodeFnc->sxFnc.pnodeName)
@@ -7139,7 +7152,30 @@ void Parser::FinishFncNode(ParseNodePtr pnodeFnc)
7139
7152
else
7140
7153
{
7141
7154
m_pscan->SetCurrentCharacter(pnodeFnc->ichMin, pnodeFnc->sxFnc.lineNumber);
7142
- if (pnodeFnc->sxFnc.IsAccessor())
7155
+
7156
+ if (fMethod)
7157
+ {
7158
+ // Method. Skip identifier name, computed property name, "async", "get", "set", and '*' or '(' characters.
7159
+ for (;;)
7160
+ {
7161
+ m_pscan->Scan();
7162
+ // '[' character indicates a computed property name for this method. We should consume it.
7163
+ if (m_token.tk == tkLBrack)
7164
+ {
7165
+ // We don't care what the name expr is.
7166
+ m_pscan->Scan();
7167
+ ParseExpr<false>();
7168
+ Assert(m_token.tk == tkRBrack);
7169
+ continue;
7170
+ }
7171
+ // Quit scanning ahead when we reach a '(' character which opens the arg list.
7172
+ if (m_token.tk == tkLParen)
7173
+ {
7174
+ break;
7175
+ }
7176
+ }
7177
+ }
7178
+ else if (pnodeFnc->sxFnc.IsAccessor())
7143
7179
{
7144
7180
// Getter/setter. The node text starts with the name, so eat that.
7145
7181
m_pscan->ScanNoKeywords();
@@ -7171,7 +7207,11 @@ void Parser::FinishFncNode(ParseNodePtr pnodeFnc)
7171
7207
bool fPreviousAwaitIsKeyword = m_pscan->SetAwaitIsKeywordRegion(pnodeFnc && pnodeFnc->sxFnc.IsAsync());
7172
7208
7173
7209
// Skip the arg list.
7174
- m_pscan->Scan();
7210
+ if (!fMethod)
7211
+ {
7212
+ // If this is a method, we've already advanced to the '(' token.
7213
+ m_pscan->Scan();
7214
+ }
7175
7215
if (m_token.tk == tkStar)
7176
7216
{
7177
7217
Assert(pnodeFnc->sxFnc.IsGenerator());
@@ -11517,7 +11557,9 @@ ParseNodePtr Parser::Parse(LPCUTF8 pszSrc, size_t offset, size_t length, charcou
11517
11557
ushort flags = fFncNoFlgs;
11518
11558
size_t iecpMin = 0;
11519
11559
charcount_t ichMin = 0;
11520
- bool isAsyncMethod = false;
11560
+ bool isAsync = false;
11561
+ bool isGenerator = false;
11562
+ bool isMethod = false;
11521
11563
11522
11564
// The top-level deferred function body was defined by a function expression whose parsing was deferred. We are now
11523
11565
// parsing it, so unset the flag so that any nested functions are parsed normally. This flag is only applicable the
@@ -11536,49 +11578,73 @@ ParseNodePtr Parser::Parse(LPCUTF8 pszSrc, size_t offset, size_t length, charcou
11536
11578
flags |= fFncDeclaration;
11537
11579
}
11538
11580
11539
- // There are three cases which can confirm async function:
11540
- // async function... -> async function
11541
- // async (... -> async lambda with parens around the formal parameter
11542
- // async identifier... -> async lambda with single identifier parameter
11581
+ if (m_grfscr & fscrDeferredFncIsMethod)
11582
+ {
11583
+ m_grfscr &= ~fscrDeferredFncIsMethod;
11584
+ isMethod = true;
11585
+ flags |= fFncNoName | fFncMethod;
11586
+ }
11587
+
11588
+ // These are the cases which can confirm async function:
11589
+ // async function() {} -> async function
11590
+ // async () => {} -> async lambda with parens around the formal parameter
11591
+ // async arg => {} -> async lambda with single identifier parameter
11592
+ // async name() {} -> async method
11593
+ // async [computed_name]() {} -> async method with a computed name
11543
11594
if (m_token.tk == tkID && m_token.GetIdentifier(m_phtbl) == wellKnownPropertyPids.async && m_scriptContext->GetConfig()->IsES7AsyncAndAwaitEnabled())
11544
11595
{
11545
11596
ichMin = m_pscan->IchMinTok();
11546
11597
iecpMin = m_pscan->IecpMinTok();
11547
11598
11548
- // Keep state so we can rewind if it turns out that this isn't an async function.
11549
- // The only way this can happen is if we have a lambda with a single formal parameter named 'async' not enclosed by parens.
11599
+ // Keep state so we can rewind if it turns out that this isn't an async function:
11600
+ // async() {} -> method named async
11601
+ // async => {} -> lambda with single parameter named async
11550
11602
RestorePoint termStart;
11551
11603
m_pscan->Capture(&termStart);
11552
11604
11553
11605
m_pscan->Scan();
11554
- if ((m_token.tk == tkID || m_token.tk == tkLParen || m_token.tk == tkFUNCTION) && !m_pscan->FHadNewLine())
11606
+
11607
+ if (m_token.tk == tkDArrow || (m_token.tk == tkLParen && isMethod) || m_pscan->FHadNewLine())
11555
11608
{
11556
- flags |= fFncAsync;
11557
- isAsyncMethod = true;
11609
+ m_pscan->SeekTo(termStart);
11558
11610
}
11559
11611
else
11560
11612
{
11561
- m_pscan->SeekTo(termStart);
11613
+ flags |= fFncAsync;
11614
+ isAsync = true;
11562
11615
}
11563
11616
}
11564
11617
11565
- // If first token of the function is tkID or tkLParen, this is a lambda.
11566
- if (m_token.tk == tkID || m_token.tk == tkLParen)
11618
+ if (m_token.tk == tkStar && m_scriptContext->GetConfig()->IsES6GeneratorsEnabled())
11567
11619
{
11568
- flags |= fFncLambda;
11620
+ ichMin = m_pscan->IchMinTok();
11621
+ iecpMin = m_pscan->IecpMinTok();
11622
+
11623
+ flags |= fFncGenerator;
11624
+ isGenerator = true;
11625
+
11626
+ m_pscan->Scan();
11569
11627
}
11570
- else
11628
+
11629
+ // Eat the computed name expression
11630
+ if (m_token.tk == tkLBrack && isMethod)
11571
11631
{
11572
- // Must be ordinary function keyword - do not eat the token
11573
- ChkCurTokNoScan(tkFUNCTION, ERRsyntax);
11632
+ m_pscan->Scan();
11633
+ ParseExpr<false>();
11634
+ }
11635
+
11636
+ if (!isMethod && (m_token.tk == tkID || m_token.tk == tkLParen))
11637
+ {
11638
+ // If first token of the function is tkID or tkLParen, this is a lambda.
11639
+ flags |= fFncLambda;
11574
11640
}
11575
11641
11576
11642
ParseNodePtr pnodeFnc = ParseFncDecl<true>(flags, nullptr, false, false);
11577
11643
pnodeProg->sxFnc.pnodeBody = nullptr;
11578
11644
AddToNodeList(&pnodeProg->sxFnc.pnodeBody, &lastNodeRef, pnodeFnc);
11579
11645
11580
- // Include the async keyword in the function extents
11581
- if (isAsyncMethod )
11646
+ // Include the async keyword or star character in the function extents
11647
+ if (isAsync || isGenerator )
11582
11648
{
11583
11649
pnodeFnc->sxFnc.cbMin = iecpMin;
11584
11650
pnodeFnc->ichMin = ichMin;
@@ -12519,6 +12585,16 @@ IdentPtr Parser::ParseSuper(bool fAllowCall)
12519
12585
break;
12520
12586
}
12521
12587
12588
+ currentNodeFunc->sxFnc.SetHasSuperReference(TRUE);
12589
+ CHAKRATEL_LANGSTATS_INC_LANGFEATURECOUNT(Super, m_scriptContext);
12590
+
12591
+ // If we are defer parsing, we can skip verifying that the super reference is valid.
12592
+ // If it wasn't the parser would have thrown during upfront parsing and we wouldn't be defer parsing the function.
12593
+ if (m_parseType == ParseType_Deferred)
12594
+ {
12595
+ return superPid;
12596
+ }
12597
+
12522
12598
if (!fAllowCall && (m_token.tk == tkLParen))
12523
12599
{
12524
12600
Error(ERRInvalidSuper); // new super() is not allowed
@@ -12556,9 +12632,6 @@ IdentPtr Parser::ParseSuper(bool fAllowCall)
12556
12632
// Anything else is an error
12557
12633
Error(ERRInvalidSuper);
12558
12634
}
12559
-
12560
- currentNodeFunc->sxFnc.SetHasSuperReference(TRUE);
12561
- CHAKRATEL_LANGSTATS_INC_LANGFEATURECOUNT(Super, m_scriptContext);
12562
12635
12563
12636
return superPid;
12564
12637
}
0 commit comments