Member Access

Mar 12, 2013 at 8:35 PM
Edited Mar 12, 2013 at 8:48 PM
Hi, I noticed that you can only specify read-only for applied attributes, but not when using one of the the "Add..." methods. It would be nice if this were consistent. I need the ability to construct an object with restricted properties "manually" (since there's no way to apply attributes to types during run-time).

The reason is that I have my own plugin architecture for loading C# extensions, and I have to construct the JavaScript object based on the developers implementation using my interface. Perhaps you should expose the ability to hook into some callbacks or something via your proxy for V8?

This is a deal breaker for me, so if it won't be done, or will take some time to do, I'll have to create a C++ wrapper for V8 myself to provide more control in order to stay on my timeline.

Thanks.

Side note (regarding V8): You really should keep the access consistent. The "Add..." property/object methods should use the same member access attribute as would be applied to class members, and get rid of the "global scope" enum in the methods, and instead create a method itself separate for that purpose, also supporting the member access enum.
Coordinator
Mar 12, 2013 at 9:46 PM
Edited Aug 3, 2013 at 3:29 AM
Hi jamesnw,

We're a bit unclear about some aspects of your request.

I noticed that you can only specify read-only for applied attributes, but not when using one of the "Add..." methods. It would be nice if this were consistent.

What would be the meaning of exposing an object as read-only? Or are you asking for a way to specify at runtime which properties of an object are to be exposed as read-only? Perhaps you could provide a hypothetical code sample?

The reason is that I have my own plugin architecture for loading C# extensions, and I have to construct the JavaScript object based on the developers implementation using my interface.

You don't know the types of the plug-in objects at compile time, but they all implement your interface. Is that correct? If so, what are your requirements for script access to these objects? Does script code need to access only members of your interface, or to all the members of the plug-in?

Thanks!
Mar 13, 2013 at 6:57 AM
Edited Mar 13, 2013 at 7:01 AM
When creating classes, you have attributes like this:
[ScriptMember(ScriptAccess.ReadOnly)]
This attribute controls the access level of the class member. You also have methods for adding properties, such as "AddHostObject()", which creates a global property associated with an object instance, but no way to specify readonly, that is what I mean. As well, I see no way to construct an object programmatically without the need to use the attribute above. You need a way to support manually adding objects and controlling "ScriptAccess...".

I have an interface that classes can implement to become extensions (plugins) to my .NET server (a wrapper for the V8 engine). My server is responsible for using this extension interface to determine how to integrate the extension. This obviously means I need to construct/integrate an object instance IN RUN-TIME for each extension, with properties marked for read/readwrite access. The whole point is to not be completely reliant on ClearScript for cross-platform reasons. As such, it is not acceptable to require the extension developers to also need ClearScript.

I guess, as an example, I might use "AddHostObject("SomeExtName",...)" with the name of the extension and mark it READONLY. Then, I would need a way to assign properties to that object instance as well, marked either read/write, or just read-only. I would end up with a global object property "SomeExtName" and various associated properties with various security accesses. Perhaps a better idea would be an ability to use something like "AddHostType()" in a way that would allow member usage details during run-time. For that matter, I'm thinking it might be easier to create a new "AddHostType()" method overload, and accept a dictionary of MemberInfo objects and assigned ScriptAccess values, such as: AddHostType("SomeExtName", userExtension.GetType(), new Dictionary { { MemberInfo1, ScriptAccess.ReadOnly) }, { MemberInfo2, ScriptAccess.Full) }, etc... });
Coordinator
Mar 13, 2013 at 3:19 PM
Edited Aug 3, 2013 at 3:30 AM
Hi jamesnw!

You also have methods for adding properties, such as "AddHostObject()", which creates a global property associated with an object instance, but no way to specify readonly, that is what I mean.

According to our current design, global properties created via the Add() methods should always be read-only. It is a bug in V8ScriptEngine that script code can currently modify and delete them. We'll fix that.

I need to construct/integrate an object instance IN RUN-TIME for each extension, with properties marked for read/readwrite access. The whole point is to not be completely reliant on ClearScript for cross-platform reasons. As such, it is not acceptable to require the extension developers to also need ClearScript.

Ah, interesting. So you need to create, at runtime, a custom-tailored scriptable proxy for a host object. If that's correct, it's definitely a little outside ClearScript's comfort zone; after all, ClearScript is all about giving script code full, direct access to host objects.

Nevertheless, there may already be a way to do what you need, although we haven't tested this technique extensively. You might be able to create a proxy by implementing IPropertyBag. Your implementation can route property access to the target object, blocking writes where necessary. You can implement methods by returning delegates as property values; here's an example that uses PropertyBag:
// C#
var proxy = new PropertyBag();
proxy["sayHello"] = new Action(() => Console.WriteLine("Hello!"));
engine.AddHostObject("myObj", proxy);
// JavaScript
myObj.sayHello();
Now of course PropertyBag isn't quite what you need because it routes property access to its internal collection rather than another object, but a custom implementation of IPropertyBag might do the trick. Please let us know what you think!
Mar 13, 2013 at 7:43 PM
Good idea, I'll look into that, thanks.

-jw
(sent via iPhone)

On 2013-03-13, at 10:19 AM, "ClearScript" <notifications@codeplex.com> wrote:

From: ClearScript

Hi jamesnw!
You also have methods for adding properties, such as "AddHostObject()", which creates a global property associated with an object instance, but no way to specify readonly, that is what I mean.
According to our current design, global properties created via the Add() methods should always be read-only. It is a bug in V8ScriptEngine that script code can currently modify and delete them. We'll fix that.
I need to construct/integrate an object instance IN RUN-TIME for each extension, with properties marked for read/readwrite access. The whole point is to not be completely reliant on ClearScript for cross-platform reasons. As such, it is not acceptable to require the extension developers to also need ClearScript.
Ah, interesting. So you need to create, at runtime, a custom-tailored scriptable proxy for a host object. If that's correct, it's definitely a little outside ClearScript's comfort zone; after all, ClearScript is all about giving script code full, direct access to host objects.

Nevertheless, there may already be a way to do what you need, although we haven't tested this technique extensively. You might be able to create a proxy by implementing IPropertyBag. Your implementation can route property access to the target object, blocking writes where necessary. You can implement methods by returning a delegate as a property value; here's an example that uses PropertyBag:
// C#
var proxy = new PropertyBag();
proxy["sayHello"] = new Action(() => Console.WriteLine("Hello!"));
engine.AddHostObject("myObj", proxy);
// JavaScript
myObj.sayHello();
Now of course PropertyBag isn't quite what you need because it routes property access to its internal collection rather than another object, but a custom implementation of IPropertyBag might do the trick. Please let us know what you think!