Ver código fonte

Fix MethodAccessor property flags (#2153)

---------

Co-authored-by: Martin Burtscher <[email protected]>
Marko Lahma 1 dia atrás
pai
commit
feeab4725b

+ 1 - 1
Jint.Tests/Runtime/PropertyDescriptorTests.cs

@@ -189,7 +189,7 @@ public class PropertyDescriptorTests
     public void PropertyDescriptorMethod()
     {
         var pdMethod = _engine.Evaluate("Object.getOwnPropertyDescriptor(testClass, 'Method')");
-        CheckPropertyDescriptor(pdMethod, false, false, false, true, false, false);
+        CheckPropertyDescriptor(jsPropertyDescriptor: pdMethod, configurable: true, enumerable: false, writable: false, hasValue: true, hasGet: false, hasSet: false);
 
         var pd = _engine.Evaluate("testClass").AsObject().GetOwnProperty("Method");
         // use PropertyDescriptor to wrap method directly

+ 85 - 0
Jint.Tests/Runtime/ProxyTests.cs

@@ -522,4 +522,89 @@ public class ProxyTests
 
         Assert.Equal([1, 2, 3, 3], res.AsArray());
     }
+
+    [Fact]
+    public void ProxyClrObjectMethod()
+    {
+        var res = _engine
+            .SetValue("T", new TestClass())
+            .Evaluate("""
+                 const handler = {
+                     get(target, property, receiver) {
+
+                         if (property == "Add") {
+                             return function(...args) { return 42};
+                         }
+
+                         return Reflect.get(...arguments);
+                     }
+                 };
+
+                 const p = new Proxy(T, handler);
+                 p.Add(5,3); // throws 'get' on proxy: property 'Add' is a read-only and non-configurable data property
+                             // on the proxy target but the proxy did not return its actual value
+                             // (expected 'function Jint.Tests.Runtime.ProxyTests+TestClass.Add() { [native code] }' but got 'function () { [native code] }')
+             """);
+
+        Assert.Equal(42, res.AsInteger());
+    }
+
+    [Fact]
+    public void ProxyClrObjectMethodWithDelegate()
+    {
+        var res = _engine
+            .SetValue("T", new TestClass())
+            .Evaluate("""
+                 const handler = {
+                     get(target, property, receiver) {
+
+                         if (property == "Add") {
+                             return (...args) => 42;
+                         }
+
+                         return Reflect.get(...arguments);
+                     }
+                 };
+
+                 const p = new Proxy(T, handler);
+                 p.Add(5,3); // throws 'get' on proxy: property 'Add' is a read-only and non-configurable data property
+                             // on the proxy target but the proxy did not return its actual value
+                             // (expected 'function Jint.Tests.Runtime.ProxyTests+TestClass.Add() { [native code] }' but got 'function () { [native code] }')
+             """);
+
+        Assert.Equal(42, res.AsInteger());
+    }
+
+    [Fact]
+    public void ProxyClrObjectWithTmpObjectMethod()
+    {
+        var res = _engine
+            .SetValue("T", new TestClass())
+            .Evaluate("""
+                 const handler = {
+                     get(target, property, receiver) {
+
+                         if (property == "Add") {
+                             return (...args) => target.target[property](...args) + 34;
+                         }
+
+                         if (typeof target.target[property] === "function")
+                            return (...args) => target.target[property](...args);
+
+                        return Reflect.get(target.target, property, receiver)
+                     }
+                 };
+
+                 const tmpObj = { target: T };
+                 const p = new Proxy(tmpObj, handler);
+
+                 const name = p.Name;
+                 p.SayHello();
+                 const res = p.Add(5,3); // works now
+
+                 name + " " + res
+             """);
+
+        Assert.Equal("My Name is Test 42", res.AsString());
+    }
 }

+ 1 - 1
Jint/Runtime/Interop/Reflection/MethodAccessor.cs

@@ -23,6 +23,6 @@ internal sealed class MethodAccessor : ReflectionAccessor
 
     public override PropertyDescriptor CreatePropertyDescriptor(Engine engine, object target, string memberName, bool enumerable = true)
     {
-        return new(new MethodInfoFunction(engine, _targetType, target, memberName, _methods), PropertyFlag.AllForbidden);
+        return new(new MethodInfoFunction(engine, _targetType, target, memberName, _methods), PropertyFlag.Configurable | PropertyFlag.NonData);
     }
 }