@@ -3709,19 +3709,25 @@ ParseNodePtr Parser::ParseFncDecl(ushort flags, LPCOLESTR pNameHint, const bool
37093709 m_scopeCountNoAst = 0 ;
37103710
37113711 long * pAstSizeSave = m_pCurrentAstSize;
3712+ bool noStmtContext = false ;
37123713
37133714 if (buildAST || BindDeferredPidRefs ())
37143715 {
37153716 if (fDeclaration && m_scriptContext->GetConfig ()->IsBlockScopeEnabled ())
37163717 {
3717- bool needsBlockNode =
3718+ noStmtContext =
37183719 (m_pstmtCur->isDeferred && m_pstmtCur->op != knopBlock) ||
37193720 (!m_pstmtCur->isDeferred && m_pstmtCur->pnodeStmt ->nop != knopBlock);
37203721
3721- if (needsBlockNode )
3722+ if (noStmtContext )
37223723 {
37233724 // We have a function declaration like "if (a) function f() {}". We didn't see
3724- // a block scope on the way in, so we need to pretend we did.
3725+ // a block scope on the way in, so we need to pretend we did. Note that this is a syntax error
3726+ // in strict mode.
3727+ if (!this ->FncDeclAllowedWithoutContext (flags))
3728+ {
3729+ Error (ERRsyntax);
3730+ }
37253731 pnodeFncBlockScope = StartParseBlock<buildAST>(PnodeBlockType::Regular, ScopeType_Block);
37263732 if (buildAST)
37273733 {
@@ -3853,7 +3859,7 @@ ParseNodePtr Parser::ParseFncDecl(ushort flags, LPCOLESTR pNameHint, const bool
38533859 }
38543860
38553861 bool needScanRCurly = true ;
3856- bool result = ParseFncDeclHelper<buildAST>(pnodeFnc, pnodeFncSave, pNameHint, flags, &funcHasName, fUnaryOrParen , &needScanRCurly);
3862+ bool result = ParseFncDeclHelper<buildAST>(pnodeFnc, pnodeFncSave, pNameHint, flags, &funcHasName, fUnaryOrParen , noStmtContext, &needScanRCurly);
38573863 if (!result)
38583864 {
38593865 Assert (!pnodeFncBlockScope);
@@ -4037,6 +4043,13 @@ ParseNodePtr Parser::ParseFncDecl(ushort flags, LPCOLESTR pNameHint, const bool
40374043 return pnodeFnc;
40384044}
40394045
4046+ bool Parser::FncDeclAllowedWithoutContext (ushort flags)
4047+ {
4048+ // Statement context required for strict mode, async functions, and generators.
4049+ // Note that generators aren't detected yet when this method is called; they're checked elsewhere.
4050+ return !IsStrictMode () && !(flags & fFncAsync );
4051+ }
4052+
40404053uint Parser::CalculateFunctionColumnNumber ()
40414054{
40424055 uint columnNumber;
@@ -4089,7 +4102,7 @@ void Parser::AppendFunctionToScopeList(bool fDeclaration, ParseNodePtr pnodeFnc)
40894102Parse a function definition.
40904103***************************************************************************/
40914104template <bool buildAST>
4092- bool Parser::ParseFncDeclHelper (ParseNodePtr pnodeFnc, ParseNodePtr pnodeFncParent, LPCOLESTR pNameHint, ushort flags, bool *pHasName, bool fUnaryOrParen , bool *pNeedScanRCurly)
4105+ bool Parser::ParseFncDeclHelper (ParseNodePtr pnodeFnc, ParseNodePtr pnodeFncParent, LPCOLESTR pNameHint, ushort flags, bool *pHasName, bool fUnaryOrParen , bool noStmtContext, bool *pNeedScanRCurly)
40934106{
40944107 bool fDeclaration = (flags & fFncDeclaration ) != 0 ;
40954108 bool fLambda = (flags & fFncLambda ) != 0 ;
@@ -4120,6 +4133,13 @@ bool Parser::ParseFncDeclHelper(ParseNodePtr pnodeFnc, ParseNodePtr pnodeFncPare
41204133
41214134 *pHasName = !fLambda && this ->ParseFncNames <buildAST>(pnodeFnc, pnodeFncParent, flags, &lastNodeRef);
41224135
4136+ if (noStmtContext && pnodeFnc->sxFnc .IsGenerator ())
4137+ {
4138+ // Generator decl not allowed outside stmt context. (We have to wait until we've parsed the '*' to
4139+ // detect generator.)
4140+ Error (ERRsyntax, pnodeFnc);
4141+ }
4142+
41234143 // switch scanner to treat 'yield' as keyword in generator functions
41244144 // or as an identifier in non-generator functions
41254145 bool fPreviousYieldIsKeyword = m_pscan->SetYieldIsKeyword (pnodeFnc && pnodeFnc->sxFnc .IsGenerator ());
0 commit comments