Просмотр исходного кода

Fix for issue with using this object in the param scope of a lambda function

When there are function definitions in the param scope of lambda functions with split scope, those functions belong to the param scope. When we were doing the look up for a non-lambda function, like in the case of looking up for this object, we were always starting from the body which was causing issues.
Aneesh Divakarakurup 10 лет назад
Родитель
Сommit
730b33ca44

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

@@ -2518,10 +2518,11 @@ void ByteCodeGenerator::EmitInternalScopeObjInit(FuncInfo *funcInfo, Scope *scop
 
 void ByteCodeGenerator::GetEnclosingNonLambdaScope(FuncInfo *funcInfo, Scope * &scope, Js::PropertyId &envIndex)
 {
+    Assert(funcInfo->IsLambda());
     envIndex = -1;
-    for (scope = funcInfo->GetBodyScope()->GetEnclosingScope(); scope; scope = scope->GetEnclosingScope())
+    for (scope = GetCurrentScope(); scope; scope = scope->GetEnclosingScope())
     {
-        if (scope->GetMustInstantiate())
+        if (scope->GetMustInstantiate() && scope->GetFunc() != funcInfo)
         {
             envIndex++;
         }

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

@@ -1757,7 +1757,7 @@ Symbol * ByteCodeGenerator::AddSymbolToFunctionScope(const char16 *key, int keyL
 
 FuncInfo *ByteCodeGenerator::FindEnclosingNonLambda()
 {
-    for (Scope *scope = TopFuncInfo()->GetBodyScope(); scope; scope = scope->GetEnclosingScope())
+    for (Scope *scope = GetCurrentScope(); scope; scope = scope->GetEnclosingScope())
     {
         if (!scope->GetFunc()->IsLambda())
         {

+ 28 - 1
test/es6/default-splitscope.js

@@ -195,7 +195,7 @@ var tests = [
         }).call({x : 10}); 
          
         this.x = 10; 
-        ((a = this.x, b = function() {this.x = 20}) => { 
+        ((a = this.x, b = function() { a; this.x = 20; }) => { 
             assert.areEqual(10, this.x, "this objects property retains the value in param scope before the inner function call in lambda"); 
             b.call(this); 
             assert.areEqual(20, this.x, "Update to a this's property from the param scope of lambda function is reflected in the body scope"); 
@@ -220,6 +220,33 @@ var tests = [
             return b;
         }
         assert.areEqual(thisObj, f4.call(thisObj)(), "Lambda defined in the param scope returns the right this object"); 
+        
+        var thisObj = { x : 1 };
+        function f5() {
+            return (a = this, b = function() { return a; }) => b;
+        }
+        assert.areEqual(thisObj, f5.call(thisObj)()(), "This object is returned properly from the inner lambda method's child function");
+
+        function f6(a, b = function () { return a; }) {
+            return (a = this, b = function() { return a; }) => b;
+        }
+        assert.areEqual(thisObj, f6.call(thisObj)()(), "This object is returned properly from the inner lambda defnied inside a split scoped function");
+
+        function f7(a, b = function () { return a; }) {
+            function f8() {
+                return (a = this, b = function() { return a; }) => b;
+            }
+            return f8.call(this);
+        }
+        assert.areEqual(thisObj, f7.call(thisObj)()(), "This object is returned properly from the inner lambda defnied inside a nested split scoped function");
+
+        function f9(a, b = function () { return a; }) {
+            function f10(c, d = function () { c; }) {
+                return (a = this, b = function() { return a; }) => b;
+            }
+            return f10.call(this);
+        }
+        assert.areEqual(thisObj, f9.call(thisObj)()(), "This object is returned properly from the inner lambda defnied inside a double nested split scoped function");
     } 
   },
   {