Skip to content

Commit 7a4826f

Browse files
committed
Use correct deferred stubs for functions declared in parameter scope of function expression
We failed to shift the deferred stubs down to those belonging to the child function when parsing the argument list of a function expression.
1 parent c4c2208 commit 7a4826f

File tree

3 files changed

+39
-7
lines changed

3 files changed

+39
-7
lines changed

lib/Parser/Parse.cpp

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5463,8 +5463,15 @@ void Parser::ParseFncDeclHelper(ParseNodeFnc * pnodeFnc, LPCOLESTR pNameHint, us
54635463
m_reparsingLambdaParams = true;
54645464
}
54655465

5466+
uint savedStubCount = m_currDeferredStubCount;
5467+
DeferredFunctionStub* savedStub = m_currDeferredStub;
5468+
ShiftCurrDeferredStubToChildFunction(pnodeFnc, pnodeFncParent);
5469+
54665470
this->ParseFncFormals<buildAST>(pnodeFnc, pnodeFncParent, flags, isTopLevelDeferredFunc);
54675471

5472+
m_currDeferredStub = savedStub;
5473+
m_currDeferredStubCount = savedStubCount;
5474+
54685475
m_reparsingLambdaParams = fLambdaParamsSave;
54695476
}
54705477

@@ -5637,13 +5644,10 @@ void Parser::ParseFncDeclHelper(ParseNodeFnc * pnodeFnc, LPCOLESTR pNameHint, us
56375644
}
56385645
uint savedStubCount = m_currDeferredStubCount;
56395646
DeferredFunctionStub* savedStub = m_currDeferredStub;
5640-
if (pnodeFnc->IsNested() && pnodeFncSave != nullptr && m_currDeferredStub != nullptr && pnodeFncSave->ichMin != pnodeFnc->ichMin)
5641-
{
5642-
DeferredFunctionStub* childStub = m_currDeferredStub + (pnodeFncSave->nestedCount - 1);
5643-
m_currDeferredStubCount = childStub->nestedCount;
5644-
m_currDeferredStub = childStub->deferredStubs;
5645-
}
5647+
ShiftCurrDeferredStubToChildFunction(pnodeFnc, pnodeFncSave);
5648+
56465649
this->FinishFncDecl(pnodeFnc, pNameHint, fLambda, skipFormals, fAllowIn);
5650+
56475651
m_currDeferredStub = savedStub;
56485652
m_currDeferredStubCount = savedStubCount;
56495653
}
@@ -14021,6 +14025,23 @@ bool Parser::IsCreatingStateCache()
1402114025
&& CONFIG_FLAG(ParserStateCache));
1402214026
}
1402314027

14028+
void Parser::ShiftCurrDeferredStubToChildFunction(ParseNodeFnc* pnodeFnc, ParseNodeFnc* pnodeFncParent)
14029+
{
14030+
// Goal here is to shift the current deferred stub to point to the stubs for pnodeFnc
14031+
// so we may continue parsing pnodeFnc using the correct set of stubs instead of the
14032+
// stubs for pnodeFncParent.
14033+
// This function assumes we are in the middle of parsing pnodeFnc which is a child
14034+
// nested in pnodeFncParent.
14035+
if (pnodeFnc->IsNested() && pnodeFncParent != nullptr && m_currDeferredStub != nullptr && pnodeFncParent->ichMin != pnodeFnc->ichMin)
14036+
{
14037+
AssertOrFailFast(pnodeFncParent->nestedCount > 0);
14038+
14039+
DeferredFunctionStub* childStub = m_currDeferredStub + (pnodeFncParent->nestedCount - 1);
14040+
m_currDeferredStubCount = childStub->nestedCount;
14041+
m_currDeferredStub = childStub->deferredStubs;
14042+
}
14043+
}
14044+
1402414045
uint Parser::BuildDeferredStubTreeHelper(ParseNodeBlock* pnodeBlock, DeferredFunctionStub* deferredStubs, uint currentStubIndex, uint deferredStubCount, Recycler *recycler)
1402514046
{
1402614047
Assert(pnodeBlock != nullptr

lib/Parser/Parse.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,7 @@ class Parser
273273

274274
protected:
275275
static uint BuildDeferredStubTreeHelper(ParseNodeBlock* pnodeBlock, DeferredFunctionStub* deferredStubs, uint currentStubIndex, uint deferredStubCount, Recycler *recycler);
276+
void ShiftCurrDeferredStubToChildFunction(ParseNodeFnc* pnodeFnc, ParseNodeFnc* pnodeFncParent);
276277

277278
HRESULT ParseSourceInternal(
278279
__out ParseNodeProg ** parseTree, LPCUTF8 pszSrc, size_t offsetInBytes,

test/Bugs/deferredStubBugs.js

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ var func5 = (a = 123) => (function v6() {
2626
})()
2727
func5();
2828

29-
function func6(a = v => { console.log('pass'); }, b = v => { return a; }) {
29+
function func6(a = v => { console.log(pass); }, b = v => { return a; }) {
3030
function c() {
3131
return b();
3232
}
@@ -84,3 +84,13 @@ function func18(a = class A { meth() { return fail } static meth2() { return fai
8484
return c();
8585
}
8686
console.log(func18());
87+
88+
function func19() {
89+
return (function(a = { b() {} }){ return pass; })();
90+
}
91+
console.log(func19());
92+
93+
function func20() {
94+
return (function(a = { b() {} }, c = function() { return pass; }){ return c(); })();
95+
}
96+
console.log(func20());

0 commit comments

Comments
 (0)