Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ReadOnly ScriptMember still writable according to getOwnPropertyDescriptor #585

Open
lukewarlow opened this issue Jul 20, 2024 · 1 comment
Assignees
Labels

Comments

@lukewarlow
Copy link

When setting a HostObject's property to be readonly to script, the descriptor from getOwnPropertyDescriptor() still says that the property is writable?

using Microsoft.ClearScript;
using Microsoft.ClearScript.V8;

namespace WebPlatform;

class Program
{
    class Foo
    {
        [ScriptMember(ScriptAccess.ReadOnly)]
        public int Prop { get; }
    }

    class JSConsole
    {
        public void log(object param)
        {
            Console.WriteLine(param.ToString());
        }
    }
    
    static void Main(string[] args)
    {
        var engine = new V8ScriptEngine();
        engine.AccessContext = typeof(Program);
        engine.AddHostObject("foo", new Foo());
        engine.AddHostObject("console", new JSConsole());
        engine.Execute("const descriptor = Object.getOwnPropertyDescriptor(foo, 'Prop'); console.log(descriptor.writable); foo.Prop = 2;");
    }
}

Results in

True
Unhandled exception. Microsoft.ClearScript.ScriptEngineException: Error: The property is read-only
 ---> Microsoft.ClearScript.ScriptEngineException: Error: The property is read-only
 ---> System.UnauthorizedAccessException: The property is read-only

I would have expected descriptor.writable to be false?

I would also expect the exception to be a TypeError?

Is there a way to define a property as being non-writable in the javascript sense using attributes like this?

@ClearScriptLib
Copy link
Collaborator

Hi @lukewarlow,

I would have expected descriptor.writable to be false?

Host objects always return { writable: true, enumerable: true, configurable: true } or undefined for Object.getOwnPropertyDescriptor. The interceptor that V8 invokes for that function currently checks only whether an accessible .NET member with the specified name exists.

The problem is that the JavaScript and .NET type systems are very different. There are .NET scenarios that JavaScript descriptors don't cover – e.g., write-only properties – and cases where a .NET property's meta-information can't be determined upfront – e.g., situations involving custom setters and dynamic objects.

I would also expect the exception to be a TypeError?

No, ClearScript maps all .NET exceptions to JavaScript's Error.

Is there a way to define a property as being non-writable in the javascript sense using attributes like this?

No, but you can use the facade pattern or JavaScript's Proxy to make host objects behave more like JavaScript objects in the script environment.

Good luck!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants