@@ -3204,6 +3204,14 @@ ParseNodePtr Parser::ParseTerm(BOOL fAllowCall,
32043204 pid = ParseSuper<buildAST>(!!fAllowCall );
32053205 isSpecialName = true ;
32063206
3207+ // Super reference and super call need to push a pid ref to 'this' even when not building an AST
3208+ ReferenceSpecialName (wellKnownPropertyPids._this , ichMin, ichLim);
3209+ // Super call needs to reference 'new.target'
3210+ if (pid == wellKnownPropertyPids._superConstructor )
3211+ {
3212+ ReferenceSpecialName (wellKnownPropertyPids._newTarget , ichMin, ichLim);
3213+ }
3214+
32073215 goto LIdentifier;
32083216
32093217 case tkTHIS:
@@ -4531,6 +4539,11 @@ ParseNodePtr Parser::ParseMemberList(LPCOLESTR pNameHint, uint32* pNameHintLengt
45314539 {
45324540 Error (ERRsyntax);
45334541 }
4542+
4543+ // Include star character in the function extents
4544+ ichMin = m_pscan->IchMinTok ();
4545+ iecpMin = m_pscan->IecpMinTok ();
4546+
45344547 m_pscan->ScanForcingPid ();
45354548 fncDeclFlags |= fFncGenerator ;
45364549 }
@@ -4704,7 +4717,7 @@ ParseNodePtr Parser::ParseMemberList(LPCOLESTR pNameHint, uint32* pNameHintLengt
47044717 ParseNodePtr pnodeFunc = ParseFncDecl<buildAST>(fncDeclFlags | (isAsyncMethod ? fFncAsync : fFncNoFlgs ), pFullNameHint,
47054718 /* needsPIDOnRCurlyScan*/ false , /* resetParsingSuperRestrictionState*/ false );
47064719
4707- if (isAsyncMethod)
4720+ if (isAsyncMethod || isGenerator )
47084721 {
47094722 pnodeFunc->sxFnc .cbMin = iecpMin;
47104723 pnodeFunc->ichMin = ichMin;
@@ -5277,7 +5290,6 @@ bool Parser::ParseFncDeclHelper(ParseNodePtr pnodeFnc, LPCOLESTR pNameHint, usho
52775290 // switch scanner to treat 'yield' as keyword in generator functions
52785291 // or as an identifier in non-generator functions
52795292 bool fPreviousYieldIsKeyword = m_pscan->SetYieldIsKeywordRegion (pnodeFnc && pnodeFnc->sxFnc .IsGenerator ());
5280-
52815293 bool fPreviousAwaitIsKeyword = m_pscan->SetAwaitIsKeywordRegion (fAsync );
52825294
52835295 if (pnodeFnc && pnodeFnc->sxFnc .IsGenerator ())
@@ -5318,10 +5330,10 @@ bool Parser::ParseFncDeclHelper(ParseNodePtr pnodeFnc, LPCOLESTR pNameHint, usho
53185330 }
53195331
53205332 uint uDeferSave = m_grfscr & fscrDeferFncParse;
5321- if (flags & fFncNoName )
5333+ if (flags & fFncClassMember )
53225334 {
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.
53255337 // NOTE: It is probably worth supporting these cases for memory and load-time purposes,
53265338 // especially as they become more and more common.
53275339 m_grfscr &= ~fscrDeferFncParse;
@@ -7170,6 +7182,7 @@ void Parser::FinishFncNode(ParseNodePtr pnodeFnc)
71707182 m_pnestedCount = &pnodeFnc->sxFnc .nestedCount ;
71717183
71727184 bool fLambda = pnodeFnc->sxFnc .IsLambda ();
7185+ bool fMethod = pnodeFnc->sxFnc .IsMethod ();
71737186
71747187 // Cue up the parser to the start of the function body.
71757188 if (pnodeFnc->sxFnc .pnodeName )
@@ -7180,7 +7193,30 @@ void Parser::FinishFncNode(ParseNodePtr pnodeFnc)
71807193 else
71817194 {
71827195 m_pscan->SetCurrentCharacter (pnodeFnc->ichMin , pnodeFnc->sxFnc .lineNumber );
7183- if (pnodeFnc->sxFnc .IsAccessor ())
7196+
7197+ if (fMethod )
7198+ {
7199+ // Method. Skip identifier name, computed property name, "async", "get", "set", and '*' or '(' characters.
7200+ for (;;)
7201+ {
7202+ m_pscan->Scan ();
7203+ // '[' character indicates a computed property name for this method. We should consume it.
7204+ if (m_token.tk == tkLBrack)
7205+ {
7206+ // We don't care what the name expr is.
7207+ m_pscan->Scan ();
7208+ ParseExpr<false >();
7209+ Assert (m_token.tk == tkRBrack);
7210+ continue ;
7211+ }
7212+ // Quit scanning ahead when we reach a '(' character which opens the arg list.
7213+ if (m_token.tk == tkLParen)
7214+ {
7215+ break ;
7216+ }
7217+ }
7218+ }
7219+ else if (pnodeFnc->sxFnc .IsAccessor ())
71847220 {
71857221 // Getter/setter. The node text starts with the name, so eat that.
71867222 m_pscan->ScanNoKeywords ();
@@ -7212,7 +7248,11 @@ void Parser::FinishFncNode(ParseNodePtr pnodeFnc)
72127248 bool fPreviousAwaitIsKeyword = m_pscan->SetAwaitIsKeywordRegion (pnodeFnc && pnodeFnc->sxFnc .IsAsync ());
72137249
72147250 // Skip the arg list.
7215- m_pscan->Scan ();
7251+ if (!fMethod )
7252+ {
7253+ // If this is a method, we've already advanced to the '(' token.
7254+ m_pscan->Scan ();
7255+ }
72167256 if (m_token.tk == tkStar)
72177257 {
72187258 Assert (pnodeFnc->sxFnc .IsGenerator ());
@@ -11576,7 +11616,9 @@ ParseNodePtr Parser::Parse(LPCUTF8 pszSrc, size_t offset, size_t length, charcou
1157611616 ushort flags = fFncNoFlgs ;
1157711617 size_t iecpMin = 0 ;
1157811618 charcount_t ichMin = 0 ;
11579- bool isAsyncMethod = false ;
11619+ bool isAsync = false ;
11620+ bool isGenerator = false ;
11621+ bool isMethod = false ;
1158011622
1158111623 // The top-level deferred function body was defined by a function expression whose parsing was deferred. We are now
1158211624 // parsing it, so unset the flag so that any nested functions are parsed normally. This flag is only applicable the
@@ -11595,49 +11637,73 @@ ParseNodePtr Parser::Parse(LPCUTF8 pszSrc, size_t offset, size_t length, charcou
1159511637 flags |= fFncDeclaration ;
1159611638 }
1159711639
11598- // There are three cases which can confirm async function:
11599- // async function... -> async function
11600- // async (... -> async lambda with parens around the formal parameter
11601- // async identifier... -> async lambda with single identifier parameter
11640+ if (m_grfscr & fscrDeferredFncIsMethod)
11641+ {
11642+ m_grfscr &= ~fscrDeferredFncIsMethod;
11643+ isMethod = true ;
11644+ flags |= fFncNoName | fFncMethod ;
11645+ }
11646+
11647+ // These are the cases which can confirm async function:
11648+ // async function() {} -> async function
11649+ // async () => {} -> async lambda with parens around the formal parameter
11650+ // async arg => {} -> async lambda with single identifier parameter
11651+ // async name() {} -> async method
11652+ // async [computed_name]() {} -> async method with a computed name
1160211653 if (m_token.tk == tkID && m_token.GetIdentifier (m_phtbl) == wellKnownPropertyPids.async && m_scriptContext->GetConfig ()->IsES7AsyncAndAwaitEnabled ())
1160311654 {
1160411655 ichMin = m_pscan->IchMinTok ();
1160511656 iecpMin = m_pscan->IecpMinTok ();
1160611657
11607- // Keep state so we can rewind if it turns out that this isn't an async function.
11608- // The only way this can happen is if we have a lambda with a single formal parameter named 'async' not enclosed by parens.
11658+ // Keep state so we can rewind if it turns out that this isn't an async function:
11659+ // async() {} -> method named async
11660+ // async => {} -> lambda with single parameter named async
1160911661 RestorePoint termStart;
1161011662 m_pscan->Capture (&termStart);
1161111663
1161211664 m_pscan->Scan ();
11613- if ((m_token.tk == tkID || m_token.tk == tkLParen || m_token.tk == tkFUNCTION) && !m_pscan->FHadNewLine ())
11665+
11666+ if (m_token.tk == tkDArrow || (m_token.tk == tkLParen && isMethod) || m_pscan->FHadNewLine ())
1161411667 {
11615- flags |= fFncAsync ;
11616- isAsyncMethod = true ;
11668+ m_pscan->SeekTo (termStart);
1161711669 }
1161811670 else
1161911671 {
11620- m_pscan->SeekTo (termStart);
11672+ flags |= fFncAsync ;
11673+ isAsync = true ;
1162111674 }
1162211675 }
1162311676
11624- // If first token of the function is tkID or tkLParen, this is a lambda.
11625- if (m_token.tk == tkID || m_token.tk == tkLParen)
11677+ if (m_token.tk == tkStar && m_scriptContext->GetConfig ()->IsES6GeneratorsEnabled ())
1162611678 {
11627- flags |= fFncLambda ;
11679+ ichMin = m_pscan->IchMinTok ();
11680+ iecpMin = m_pscan->IecpMinTok ();
11681+
11682+ flags |= fFncGenerator ;
11683+ isGenerator = true ;
11684+
11685+ m_pscan->Scan ();
1162811686 }
11629- else
11687+
11688+ // Eat the computed name expression
11689+ if (m_token.tk == tkLBrack && isMethod)
11690+ {
11691+ m_pscan->Scan ();
11692+ ParseExpr<false >();
11693+ }
11694+
11695+ if (!isMethod && (m_token.tk == tkID || m_token.tk == tkLParen))
1163011696 {
11631- // Must be ordinary function keyword - do not eat the token
11632- ChkCurTokNoScan (tkFUNCTION, ERRsyntax) ;
11697+ // If first token of the function is tkID or tkLParen, this is a lambda.
11698+ flags |= fFncLambda ;
1163311699 }
1163411700
1163511701 ParseNodePtr pnodeFnc = ParseFncDecl<true >(flags, nullptr , false , false );
1163611702 pnodeProg->sxFnc .pnodeBody = nullptr ;
1163711703 AddToNodeList (&pnodeProg->sxFnc .pnodeBody , &lastNodeRef, pnodeFnc);
1163811704
11639- // Include the async keyword in the function extents
11640- if (isAsyncMethod )
11705+ // Include the async keyword or star character in the function extents
11706+ if (isAsync || isGenerator )
1164111707 {
1164211708 pnodeFnc->sxFnc .cbMin = iecpMin;
1164311709 pnodeFnc->ichMin = ichMin;
@@ -12578,6 +12644,16 @@ IdentPtr Parser::ParseSuper(bool fAllowCall)
1257812644 break ;
1257912645 }
1258012646
12647+ currentNodeFunc->sxFnc .SetHasSuperReference (TRUE );
12648+ CHAKRATEL_LANGSTATS_INC_LANGFEATURECOUNT (Super, m_scriptContext);
12649+
12650+ // If we are defer parsing, we can skip verifying that the super reference is valid.
12651+ // If it wasn't the parser would have thrown during upfront parsing and we wouldn't be defer parsing the function.
12652+ if (m_parseType == ParseType_Deferred)
12653+ {
12654+ return superPid;
12655+ }
12656+
1258112657 if (!fAllowCall && (m_token.tk == tkLParen))
1258212658 {
1258312659 Error (ERRInvalidSuper); // new super() is not allowed
@@ -12616,9 +12692,6 @@ IdentPtr Parser::ParseSuper(bool fAllowCall)
1261612692 Error (ERRInvalidSuper);
1261712693 }
1261812694
12619- currentNodeFunc->sxFnc .SetHasSuperReference (TRUE );
12620- CHAKRATEL_LANGSTATS_INC_LANGFEATURECOUNT (Super, m_scriptContext);
12621-
1262212695 return superPid;
1262312696}
1262412697
0 commit comments