Explorar el Código

Fix FuncInfoStack to be correct when emitting a function with a split body and param scope

When we emit a function with a split body and param scope, we emit the param scope before we push the FuncInfo into the FuncInfoStack. This means that functions defined in the param scope will see an incorrect FuncInfoStack.
Taylor Woll hace 6 años
padre
commit
6ae6c0ac89

+ 2 - 2
lib/Runtime/ByteCode/ByteCodeEmitter.cpp

@@ -3481,8 +3481,6 @@ void ByteCodeGenerator::EmitScopeList(ParseNode *pnode, ParseNode *breakOnBodySc
                 }
                 this->StartEmitFunction(pnode->AsParseNodeFnc());
 
-                PushFuncInfo(_u("StartEmitFunction"), funcInfo);
-
                 if (!funcInfo->IsBodyAndParamScopeMerged())
                 {
                     this->EmitScopeList(pnode->AsParseNodeFnc()->pnodeBodyScope->pnodeScopes);
@@ -3886,6 +3884,8 @@ void ByteCodeGenerator::StartEmitFunction(ParseNodeFnc *pnodeFnc)
         }
     }
 
+    PushFuncInfo(_u("StartEmitFunction"), funcInfo);
+
     if (!funcInfo->IsBodyAndParamScopeMerged())
     {
         ParseNodeBlock * paramBlock = pnodeFnc->pnodeScopes;

+ 15 - 2
lib/Runtime/ByteCode/ByteCodeGenerator.cpp

@@ -1840,7 +1840,7 @@ FuncInfo *ByteCodeGenerator::FindEnclosingNonLambda()
     return nullptr;
 }
 
-FuncInfo* GetParentFuncInfo(FuncInfo* child)
+FuncInfo* ByteCodeGenerator::GetParentFuncInfo(FuncInfo* child)
 {
     for (Scope* scope = child->GetBodyScope(); scope; scope = scope->GetEnclosingScope())
     {
@@ -1853,6 +1853,19 @@ FuncInfo* GetParentFuncInfo(FuncInfo* child)
     return nullptr;
 }
 
+FuncInfo* ByteCodeGenerator::GetEnclosingFuncInfo()
+{
+    FuncInfo* top = this->funcInfoStack->Pop();
+
+    Assert(!this->funcInfoStack->Empty());
+
+    FuncInfo* second = this->funcInfoStack->Top();
+
+    this->funcInfoStack->Push(top);
+
+    return second;
+}
+
 bool ByteCodeGenerator::CanStackNestedFunc(FuncInfo * funcInfo, bool trace)
 {
 #if ENABLE_DEBUG_CONFIG_OPTIONS
@@ -2634,7 +2647,7 @@ void AssignFuncSymRegister(ParseNodeFnc * pnodeFnc, ByteCodeGenerator * byteCode
                 Assert(byteCodeGenerator->GetCurrentScope()->GetFunc() == sym->GetScope()->GetFunc());
                 if (byteCodeGenerator->GetCurrentScope()->GetFunc() != sym->GetScope()->GetFunc())
                 {
-                    Assert(GetParentFuncInfo(byteCodeGenerator->GetCurrentScope()->GetFunc()) == sym->GetScope()->GetFunc());
+                    Assert(ByteCodeGenerator::GetParentFuncInfo(byteCodeGenerator->GetCurrentScope()->GetFunc()) == sym->GetScope()->GetFunc());
                     sym->GetScope()->SetMustInstantiate(true);
                     byteCodeGenerator->ProcessCapturedSym(sym);
                     sym->GetScope()->GetFunc()->SetHasLocalInClosure(true);

+ 2 - 0
lib/Runtime/ByteCode/ByteCodeGenerator.h

@@ -402,6 +402,8 @@ public:
     void PopulateFormalsScope(uint beginOffset, FuncInfo *funcInfo, ParseNodeFnc *pnodeFnc);
     void InsertPropertyToDebuggerScope(FuncInfo* funcInfo, Js::DebuggerScope* debuggerScope, Symbol* sym);
     FuncInfo *FindEnclosingNonLambda();
+    static FuncInfo* GetParentFuncInfo(FuncInfo* child);
+    FuncInfo* GetEnclosingFuncInfo();
 
     bool CanStackNestedFunc(FuncInfo * funcInfo, bool trace = false);
     void CheckDeferParseHasMaybeEscapedNestedFunc();

+ 1 - 1
lib/Runtime/ByteCode/ScopeInfo.cpp

@@ -166,7 +166,7 @@ namespace Js
             Assert(currentScope->GetScopeType() == ScopeType_FunctionBody);
             Assert(currentScope->GetEnclosingScope());
 
-            FuncInfo* func = currentScope->GetEnclosingScope()->GetFunc();
+            FuncInfo* func = byteCodeGenerator->GetEnclosingFuncInfo();
             Assert(func);
 
             if (func->IsBodyAndParamScopeMerged() && !(func->funcExprScope && func->funcExprScope->GetCanMerge()))

+ 47 - 1
test/Bugs/bug_OS18926499.js

@@ -24,7 +24,7 @@ try {
     console.log('pass');
 }
 
-var foo3 = function foo3a(a = (function foo3b() { foo3a; })()) {
+var foo3 = function foo3a(a = (function foo3b() { +foo3a; })()) {
     a;
 };
 
@@ -46,3 +46,49 @@ try {
 } catch {
     console.log('pass');
 }
+
+var foo5 = function foo5a(a = (function(){(function(b = 123) { +x; })()})()) {
+    function bar() { eval(''); }
+    var x;
+};
+
+try {
+    foo5();
+    console.log('fail');
+} catch {
+    console.log('pass');
+}
+
+function foo6(a, b = (function() {a; +x;})()) {
+    function bar() { eval(''); }
+    var x;
+};
+
+try {
+    foo6();
+    console.log('fail');
+} catch {
+    console.log('pass');
+}
+
+var foo8 = function foo8a(b, a = (function foo8b() { console.log(x); })()) {
+    a;
+    var x = 'fail';
+};
+
+try {
+    foo8()
+    console.log('fail');
+} catch {
+    console.log('pass');
+}
+
+var foo9 = function foo9a(b = 'pass', a = (function foo9b() { console.log(b); })()) {
+};
+
+try {
+    foo9()
+    console.log('pass');
+} catch {
+    console.log('fail');
+}