Skip to content

Commit 50ce23e

Browse files
committed
[MERGE chakra-core#3610 @pleath] [MSFT 13209141]: Defer default expressions in a formals list if the function containing them is going to be deferred.
Merge pull request chakra-core#3610 from pleath:13209141 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.
2 parents 55a14b9 + 83090a9 commit 50ce23e

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)