diff --git a/lib/Runtime/ByteCode/ByteCodeEmitter.cpp b/lib/Runtime/ByteCode/ByteCodeEmitter.cpp index 47ddc3ca6a1..d4864ff4de8 100644 --- a/lib/Runtime/ByteCode/ByteCodeEmitter.cpp +++ b/lib/Runtime/ByteCode/ByteCodeEmitter.cpp @@ -3654,15 +3654,20 @@ void ByteCodeGenerator::EmitScopeList(ParseNode *pnode, ParseNode *breakOnBodySc PushFuncInfo(_u("StartEmitFunction"), funcInfo); } - if (paramScope && !paramScope->GetCanMergeWithBodyScope()) - { - // Before emitting the body scoped functions let us switch the special scope slot to use the body ones - pnode->sxFnc.funcInfo->UseInnerSpecialScopeSlots(); - this->EmitScopeList(pnode->sxFnc.pnodeBodyScope->sxBlock.pnodeScopes); - } - else + // In DeferParse scenario, ByteCodeGenerator would not have yet visited the nested + // scopes, so the emitter should also not process these nodes either. + if (pnode->sxFnc.pnodeBody) { - this->EmitScopeList(pnode->sxFnc.pnodeScopes); + if (paramScope && !paramScope->GetCanMergeWithBodyScope()) + { + // Before emitting the body scoped functions let us switch the special scope slot to use the body ones + pnode->sxFnc.funcInfo->UseInnerSpecialScopeSlots(); + this->EmitScopeList(pnode->sxFnc.pnodeBodyScope->sxBlock.pnodeScopes); + } + else + { + this->EmitScopeList(pnode->sxFnc.pnodeScopes); + } } this->EmitOneFunction(pnode); @@ -4135,9 +4140,15 @@ void ByteCodeGenerator::StartEmitFunction(ParseNode *pnodeFnc) PushScope(paramScope); - // While emitting the functions we have to stop when we see the body scope block. - // Otherwise functions defined in the body scope will not be able to get the right references. - this->EmitScopeList(paramBlock->sxBlock.pnodeScopes, pnodeFnc->sxFnc.pnodeBodyScope); + // In DeferParse scenario, ByteCodeGenerator would not have yet visited the nested + // scopes, so the emitter should also not process these nodes either. + if (pnodeFnc->sxFnc.pnodeBody) + { + // While emitting the functions we have to stop when we see the body scope block. + // Otherwise functions defined in the body scope will not be able to get the right references. + this->EmitScopeList(paramBlock->sxBlock.pnodeScopes, pnodeFnc->sxFnc.pnodeBodyScope); + } + Assert(this->GetCurrentScope() == paramScope); } diff --git a/test/es6/default-splitscope.js b/test/es6/default-splitscope.js index 0a5da26a816..b01eb5d355e 100644 --- a/test/es6/default-splitscope.js +++ b/test/es6/default-splitscope.js @@ -1175,6 +1175,32 @@ var tests = [ return h(); } assert.areEqual(9, f2(), "Paramater scope remains split"); + + // Bug 8971506: This used to throw an ASSERT. The test is considered to be passing if no ASSERT is thrown. + function f3(a1 = class c1 extends eval('') { }) { + } + + // Bug 8971506: This used to throw an ASSERT. The test is considered to be passing if no ASSERT is thrown. + var f4 = function () { + }; + { + f4(); + } + function f5() { + function f6(a2 = class c2 extends eval('') { }) { + } + } + + // Bug 8971506: This used to throw an ASSERT. The test is considered to be passing if no ASSERT is thrown. + (eval(` + function f6(jirfmx = class c3 {}) { }; + `)); + + // Bug 8971506: This used to throw an ASSERT. The test is considered to be passing if no ASSERT is thrown. + (eval(` + function f7(a3 = class c4 extends false { + }) { }; + `)); } }, {