소스 검색

Allow delegates to return values from .NET (#854)

* Allow delegates to return values from .NET
* Added unit test for DelegateCanReturnValue
DerekDiamond 4 년 전
부모
커밋
5b51036334
2개의 변경된 파일66개의 추가작업 그리고 4개의 파일을 삭제
  1. 64 0
      Jint.Tests/Runtime/InteropTests.cs
  2. 2 4
      Jint/Runtime/Interop/DefaultTypeConverter.cs

+ 64 - 0
Jint.Tests/Runtime/InteropTests.cs

@@ -2387,5 +2387,69 @@ namespace Jint.Tests.Runtime
             engine.SetValue("E", TypeReference.CreateTypeReference(engine, typeof(UintEnum)));
             Assert.Equal(1, engine.Execute("E.b;").GetCompletionValue().AsNumber());
         }
+
+        #region DelegateCanReturnValue
+
+        public class TestItem
+        {
+            public double Cost { get; set; }
+
+            public double Age { get; set; }
+
+            public string Name { get; set; }
+        }
+
+        public class TestItemList : List<TestItem>
+        {
+            public double Sum(Func<TestItem, double> calc)
+            {
+                double rc = 0;
+
+                foreach (var item in this)
+                {
+                    rc += calc(item);
+                }
+
+                return rc;
+            }
+
+            public TestItemList Where(Func<TestItem, bool> cond)
+            {
+                var rc = new TestItemList();
+
+                foreach (var item in this)
+                {
+                    if (cond(item))
+                    {
+                        rc.Add(item);
+                    }
+                }
+
+                return rc;
+            }
+        }
+
+        [Fact]
+        public void DelegateCanReturnValue()
+        {
+            var engine = new Engine(options => options.AllowClr(GetType().Assembly));
+
+            var lst = new TestItemList();
+
+            lst.Add(new TestItem() { Name = "a", Cost = 1, Age = 10 });
+            lst.Add(new TestItem() { Name = "a", Cost = 1, Age = 10 });
+            lst.Add(new TestItem() { Name = "b", Cost = 1, Age = 10 });
+            lst.Add(new TestItem() { Name = "b", Cost = 1, Age = 10 });
+            lst.Add(new TestItem() { Name = "b", Cost = 1, Age = 10 });
+
+            engine.SetValue("lst", lst);
+
+            Assert.Equal(5, engine.Execute("lst.Sum(x => x.Cost);").GetCompletionValue().AsNumber());
+            Assert.Equal(50, engine.Execute("lst.Sum(x => x.Age);").GetCompletionValue().AsNumber());
+            Assert.Equal(3, engine.Execute("lst.Where(x => x.Name == 'b').Count;").GetCompletionValue().AsNumber());
+            Assert.Equal(30, engine.Execute("lst.Where(x => x.Name == 'b').Sum(x => x.Age);").GetCompletionValue().AsNumber());
+        }
+
+        #endregion
     }
 }

+ 2 - 4
Jint/Runtime/Interop/DefaultTypeConverter.cs

@@ -181,14 +181,12 @@ namespace Jint.Runtime.Interop
 
                         var @vars = Expression.NewArrayInit(jsValueType, initializers);
 
-                        var callExpression = Expression.Block(
-                                                Expression.Call(
+                        var callExpression = Expression.Call(
                                                     Expression.Call(Expression.Constant(function.Target),
                                                         function.Method,
                                                         Expression.Constant(JsValue.Undefined, jsValueType),
                                                         @vars),
-                                                    jsValueType.GetMethod("ToObject")),
-                                                Expression.Empty());
+                                                    jsValueType.GetMethod("ToObject"));
 
                         var dynamicExpression = Expression.Invoke(Expression.Lambda(callExpression, new ReadOnlyCollection<ParameterExpression>(@params)), new ReadOnlyCollection<ParameterExpression>(@params));