Skip to content

Commit 2bc3385

Browse files
committed
[MERGE #6242 @boingoing] Fix environment calculation for symbol captured in the param scope
Merge pull request #6242 from boingoing:23102586 Consider this repro: ```javascript function test0() { var k; function foo(a = function() { +k; }) { a(); function bar() { a } }; eval('') foo(); } test0(); ``` We're hitting a miscalculation of the environment index when we're attempting to look up the scope for symbol 'k'. In particular, the miscalculation occurs in ByteCodeGenerator::FindScopeForSym. In this function, we walk up the scope chain starting from the body scope of the anonymous function declared in the param scope of foo. Each scope we walk to for a function other than the anonymous function which requires instantiation will increment the environment index. The enclosing scope for the anonymous function body scope is the param scope of foo and the body scope of foo is not in the restored scope chain. When we walk to the param scope for foo, it does not have the must instantiate flag set so we (incorrectly) do not increment the environment index. Back when the body scope for foo was incorrectly enclosing the body scope of the anonymous function, we correctly calculated the environment index because the body scope for foo has the must instantiate flag set. Now that param scope for foo is in the scope chain instead of body scope, we need to mark the param scope as must instantiate so this lookup is correct.
2 parents 5533dbe + e6888a4 commit 2bc3385

File tree

4 files changed

+31
-1
lines changed

4 files changed

+31
-1
lines changed

lib/Runtime/ByteCode/ByteCodeEmitter.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3855,6 +3855,11 @@ void ByteCodeGenerator::StartEmitFunction(ParseNodeFnc *pnodeFnc)
38553855
else if (pnodeFnc->IsBodyAndParamScopeMerged() || bodyScope->GetScopeSlotCount() != 0)
38563856
{
38573857
bodyScope->SetMustInstantiate(funcInfo->frameSlotsRegister != Js::Constants::NoRegister);
3858+
3859+
if (pnodeFnc->IsBodyAndParamScopeMerged() && paramScope && paramScope->GetHasNestedParamFunc())
3860+
{
3861+
paramScope->SetMustInstantiate(funcInfo->frameSlotsRegister != Js::Constants::NoRegister);
3862+
}
38583863
}
38593864

38603865
if (!pnodeFnc->IsBodyAndParamScopeMerged())

lib/Runtime/ByteCode/ScopeInfo.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,6 @@ namespace Js
185185
{
186186
currentScope = func->GetParamScope();
187187
Assert(currentScope->GetScopeType() == ScopeType_Parameter);
188-
Assert(!currentScope->GetMustInstantiate());
189188
}
190189
}
191190

test/Bugs/bug_OS23102586.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
//-------------------------------------------------------------------------------------------------------
2+
// Copyright (C) Microsoft. All rights reserved.
3+
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
4+
//-------------------------------------------------------------------------------------------------------
5+
6+
// force:deferparse
7+
8+
function test0() {
9+
var k;
10+
11+
function foo(a = function() { +k; }) {
12+
a();
13+
function bar() { a }
14+
};
15+
16+
eval('')
17+
foo();
18+
}
19+
test0();
20+
console.log('pass')

test/Bugs/rlexe.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -618,4 +618,10 @@
618618
<compile-flags>-force:deferparse</compile-flags>
619619
</default>
620620
</test>
621+
<test>
622+
<default>
623+
<files>bug_OS23102586.js</files>
624+
<compile-flags>-force:deferparse</compile-flags>
625+
</default>
626+
</test>
621627
</regress-exe>

0 commit comments

Comments
 (0)