This project has moved. For the latest updates, please go here.

Define the property with a function value

Apr 6, 2012 at 4:32 AM
Edited Apr 6, 2012 at 2:20 PM

Hello,
How can I define the property with a function value? Basically I would like to achieve in C#, what in JavaScript would look like this.

var o = {};
o.__values = { 'a': 'aaa', 'b':'bbb', 'c':'ccc' };
Object.defineProperty(o, '#get', { value: function(id){ return this.__values[id]; } } );

// another option
// o['#get'] = function(id){ return this.__values[id]; };

o['#get']('a'); // -> 'aaa'
o['#get']('b'); // -> 'bbb'

Using JSFunction will be great, but it does not work here because the name of the property is not valid identifier. I think, defining the property solves this problem, but I do not see how to do it using public api.
 
Greetings,
Alex

Coordinator
Apr 6, 2012 at 1:12 PM

Not sure why I was restricting JsFunction to valid identifiers - I have committed a fix.

In terms of a workaround, yeah it's a little tricky.  You can call ObjectConstructor.DefineProperty from C#, so that's no problem.  The tricky bit is converting your C# method into a valid FunctionInstance so you can pass it into DefineProperty (a lot of this stuff is internal).  The easiest way I can think of is to leverage PopulateFunctions:

        public class Test : ObjectInstance
        {
            public Test(ScriptEngine engine)
                : base(engine)
            {
                this.PopulateFunctions();
                this["#get"] = this["test"];
            }

            [JSFunction(Name = "test")]
            public void Test()
            {
            }
        }

PS: your syntax is wrong, it should be:

Object.defineProperty(o, '#get', { get: function(id){ return this.__values[id]; } } );

Apr 6, 2012 at 4:50 PM

Thanks Paul!
It's really neat you have fixed it so quickly. It perfectly works.
Speaking about your last comment. The idea is #get should be a method (it has a argument), not a property.

var o = {};
// => undefined

o.__values = {'a':'aaa'};
// => [object Object]

Object.defineProperty(o, '#get', { get: function(id){ return this.__values[id]; } } );
// => [object Object]  

o['#get']('a')
// => TypeError: 'o["#get"]' is not a function

Object.defineProperty(o, '#get2', { value: function(id){ return this.__values[id]; } } );
// => [object Object]  

o['#get2']('a')
// => aaa

Coordinator
Apr 7, 2012 at 6:44 AM

Ah, you're right, I thought you were defining a getter, but you're not.

Instead of using Object.defineProperty why not just use: o['#get'] = function(id){ return this.__values[id]; } ?

Apr 9, 2012 at 4:56 AM

The original question was how to do this using C#. Sure, I can change the name of the exposing function and then make an alias in JavaScript as you are suggesting, but it would be the last resort. Fortunately, you have fixed the problem with JSFunction and now everything works like a charm! Thanks!

Coordinator
Apr 10, 2012 at 6:36 AM

No problem :-)

Apr 10, 2012 at 7:52 PM
Edited Apr 11, 2012 at 1:59 AM

Related question:


how can I implement the method that returns Delegate? The use case is to have some dynamic callback built in C# for JavaScript. Looking in the code I see that it can be done easily if one of the ClrFunction constructors would be public but it's internal. Don't I see something simple or this feature is not public for some reason?

Coordinator
Apr 12, 2012 at 5:23 AM

It's not public because there are a lot of moving pieces and likely to change in the future.  I can see that there is a need for this though - I'll see if I can loosen up the restrictions a bit.