Skip to content

Commit 83090a9

Browse files
committed
[MSFT 13209141]: Defer default expressions in a formals list if the function containing them is going to be deferred. We know that the expressions can't be evaluated until the function has been fully compiled, so compiling the expressions up front is wasted work. And generating code for a function nested inside a deferred function creates inconsistencies.
1 parent 78ba372 commit 83090a9

3 files changed

Lines changed: 27 additions & 5 deletions

File tree

lib/Parser/Parse.cpp

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5195,7 +5195,7 @@ bool Parser::ParseFncDeclHelper(ParseNodePtr pnodeFnc, LPCOLESTR pNameHint, usho
51955195
saveDeferredStub = m_currDeferredStub;
51965196
m_currDeferredStub = nullptr;
51975197
}
5198-
this->ParseFncFormals<buildAST>(pnodeFnc, pnodeFncParent, flags);
5198+
this->ParseFncFormals<buildAST>(pnodeFnc, pnodeFncParent, flags, isTopLevelDeferredFunc);
51995199
if (buildAST)
52005200
{
52015201
m_currDeferredStub = saveDeferredStub;
@@ -6227,7 +6227,7 @@ void Parser::UpdateOrCheckForDuplicateInFormals(IdentPtr pid, SList<IdentPtr> *f
62276227
}
62286228

62296229
template<bool buildAST>
6230-
void Parser::ParseFncFormals(ParseNodePtr pnodeFnc, ParseNodePtr pnodeParentFnc, ushort flags)
6230+
void Parser::ParseFncFormals(ParseNodePtr pnodeFnc, ParseNodePtr pnodeParentFnc, ushort flags, bool isTopLevelDeferredFunc)
62316231
{
62326232
bool fLambda = (flags & fFncLambda) != 0;
62336233
bool fMethod = (flags & fFncMethod) != 0;
@@ -6439,9 +6439,21 @@ void Parser::ParseFncFormals(ParseNodePtr pnodeFnc, ParseNodePtr pnodeParentFnc,
64396439
}
64406440

64416441
m_pscan->Scan();
6442-
ParseNodePtr pnodeInit = ParseExpr<buildAST>(koplCma, nullptr, TRUE, FALSE, pNameHint, &nameHintLength, &nameHintOffset);
64436442

6444-
if (buildAST && pnodeInit->nop == knopFncDecl)
6443+
ParseNodePtr pnodeInit;
6444+
if (isTopLevelDeferredFunc)
6445+
{
6446+
// Defer default expressions if the function will be deferred, since we know they can't be evaluated
6447+
// until the function is fully compiled, and generating code for a function nested inside a deferred function
6448+
// creates inconsistencies.
6449+
pnodeInit = ParseExpr<false>(koplCma, nullptr, TRUE, FALSE, pNameHint, &nameHintLength, &nameHintOffset);
6450+
}
6451+
else
6452+
{
6453+
pnodeInit = ParseExpr<buildAST>(koplCma, nullptr, TRUE, FALSE, pNameHint, &nameHintLength, &nameHintOffset);
6454+
}
6455+
6456+
if (buildAST && pnodeInit && pnodeInit->nop == knopFncDecl)
64456457
{
64466458
Assert(nameHintLength >= nameHintOffset);
64476459
pnodeInit->sxFnc.hint = pNameHint;

lib/Parser/Parse.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -773,7 +773,7 @@ class Parser
773773
template<bool buildAST> ParseNodePtr ParseMemberGetSet(OpCode nop, LPCOLESTR* ppNameHint);
774774
template<bool buildAST> ParseNodePtr ParseFncDecl(ushort flags, LPCOLESTR pNameHint = NULL, const bool needsPIDOnRCurlyScan = false, bool resetParsingSuperRestrictionState = true, bool fUnaryOrParen = false);
775775
template<bool buildAST> bool ParseFncNames(ParseNodePtr pnodeFnc, ParseNodePtr pnodeFncParent, ushort flags, ParseNodePtr **pLastNodeRef);
776-
template<bool buildAST> void ParseFncFormals(ParseNodePtr pnodeFnc, ParseNodePtr pnodeParentFnc, ushort flags);
776+
template<bool buildAST> void ParseFncFormals(ParseNodePtr pnodeFnc, ParseNodePtr pnodeParentFnc, ushort flags, bool isTopLevelDeferredFunc = false);
777777
template<bool buildAST> bool ParseFncDeclHelper(ParseNodePtr pnodeFnc, LPCOLESTR pNameHint, ushort flags, bool *pHasName, bool fUnaryOrParen, bool noStmtContext, bool *pNeedScanRCurly, bool skipFormals = false);
778778
template<bool buildAST> void ParseExpressionLambdaBody(ParseNodePtr pnodeFnc);
779779
template<bool buildAST> void UpdateCurrentNodeFunc(ParseNodePtr pnodeFnc, bool fLambda);

test/es6/classes_bugfixes.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -464,6 +464,16 @@ var tests = [
464464
assert.areEqual('Bsetter;Bgetter;', result);
465465
}
466466
},
467+
{
468+
name: "MSFT:13209141: Confusion on deferred function containing non-deferred extends cause calling eval",
469+
body: function () {
470+
function foo(a = class c extends eval("") {}) {}
471+
try {
472+
foo();
473+
}
474+
catch(e) {}
475+
}
476+
},
467477
];
468478

469479
testRunner.runTests(tests, { verbose: WScript.Arguments[0] != "summary" });

0 commit comments

Comments
 (0)