diff --git a/Jint.Tests/Runtime/PropertyDescriptorTests.cs b/Jint.Tests/Runtime/PropertyDescriptorTests.cs index 7f1b0fda39..7c2c7ac23b 100644 --- a/Jint.Tests/Runtime/PropertyDescriptorTests.cs +++ b/Jint.Tests/Runtime/PropertyDescriptorTests.cs @@ -189,7 +189,7 @@ JsValue ExtractClrAccessDescriptor(JsValue jsArugments) 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 diff --git a/Jint.Tests/Runtime/ProxyTests.cs b/Jint.Tests/Runtime/ProxyTests.cs index 1b21a9dfbc..eb6b5fc3a5 100644 --- a/Jint.Tests/Runtime/ProxyTests.cs +++ b/Jint.Tests/Runtime/ProxyTests.cs @@ -522,4 +522,89 @@ public void ProxyIterateClrList() 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()); + } } diff --git a/Jint/Runtime/Interop/Reflection/MethodAccessor.cs b/Jint/Runtime/Interop/Reflection/MethodAccessor.cs index a53acc93c9..9a7a005495 100644 --- a/Jint/Runtime/Interop/Reflection/MethodAccessor.cs +++ b/Jint/Runtime/Interop/Reflection/MethodAccessor.cs @@ -23,6 +23,6 @@ protected override void DoSetValue(object target, string memberName, object? val 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); } }