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

Every method must have the same name - regression from 2.1.0 to 2.2.0

Mar 6, 2015 at 4:03 PM
Consider the following code:
namespace jurassicTest
{
    public class JSField : ObjectInstance
    {
        private object value;

        public JSField(JSField jsfield)
            : base(jsfield)
        {
            this.value = jsfield.value;
        }

        public JSField(ScriptEngine engine)
            : base(engine)
        {
            this.value = string.Empty;
            this.PopulateFunctions();
        }

        [JSFunction(Name = "value")]
        public object GetValue() { return this.value ?? ""; }

        [JSFunction(Name = "value")]
        public void SetValue(object value) { this.value = value; }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var engine = new ScriptEngine();
            engine.SetGlobalValue("variable", new JSField(engine));
            engine.Execute("variable.value('qwe');");
            Console.WriteLine(engine.Evaluate("variable.value()"));
        }
    }
}
It works in Jurassic 2.1.0, but on 2.2.0 it throws:
Wyjątek nieobsłużony: System.ArgumentException: Every method must have the same name.
Nazwa parametru: targetMethods
   w Jurassic.Compiler.MethodBinder..ctor(IEnumerable`1 targetMethods) w c:\Users\Paul\Documents\Visual Studio 2012\Projects\jurassic\Jurassic\Compiler\Binders\
MethodBinder.cs:wiersz 62
   w Jurassic.Compiler.JSBinder..ctor(IEnumerable`1 targetMethods) w c:\Users\Paul\Documents\Visual Studio 2012\Projects\jurassic\Jurassic\Compiler\Binders\JSBi
nder.cs:wiersz 39
   w Jurassic.Library.ClrFunction..ctor(ObjectInstance prototype, IEnumerable`1 methods, String name, Int32 length) w c:\Users\Paul\Documents\Visual Studio 2012
\Projects\jurassic\Jurassic\Library\Function\ClrFunction.cs:wiersz 130
   w Jurassic.Library.ObjectInstance.PopulateFunctions(Type type, BindingFlags bindingFlags) w c:\Users\Paul\Documents\Visual Studio 2012\Projects\jurassic\Jura
ssic\Library\Object\ObjectInstance.cs:wiersz 1260
   w jurassicTest.JSField..ctor(ScriptEngine engine) w d:\Users\tomasz.grobelny\Documents\Visual Studio 2013\Projects\variousTests\jurassic\Program.cs:wiersz 25

   w jurassicTest.Program.Main(String[] args) w d:\Users\tomasz.grobelny\Documents\Visual Studio 2013\Projects\variousTests\jurassic\Program.cs:wiersz 40
Any idea how to fix the code to support a scenario where object's property is a function acting both as setter and getter?
Coordinator
Mar 9, 2015 at 12:11 AM
Edited Mar 9, 2015 at 12:12 AM
Why not just do this?
    public class JSField : ObjectInstance
    {
        private object value;

        public JSField(JSField jsfield)
            : base(jsfield)
        {
            this.value = jsfield.value;
        }

        public JSField(ScriptEngine engine)
            : base(engine)
        {
            this.value = string.Empty;
            this.PopulateFunctions();
        }

        [JSProperty(Name = "value")]
        public object Value
        {
            get { return this.value ?? ""; }
            set { this.value = value; }
        }
    }
Mar 9, 2015 at 12:18 AM
I think I tried something similar, but then it would probably be possible to assign eg. string to 'value', but it was impossible to call it as as an accessor function. 'variable.value()' would not work. I will check again tomorrow.
Coordinator
Mar 9, 2015 at 4:50 AM
If you need variable.value() to work (as opposed to x = variable.value, which seems more natural to me), then I think this will work (untested):
    public class JSField : ObjectInstance
    {
        private object value;

        public JSField(JSField jsfield)
            : base(jsfield)
        {
            this.value = jsfield.value;
        }

        public JSField(ScriptEngine engine)
            : base(engine)
        {
            this.value = string.Empty;
            this.PopulateFunctions();
        }

        [JSFunction(Name = "value")]
        public object GetOrSetValue(object value)
        {
            if (TypeUtilities.IsUndefined(value))
                return this.value;
            this.value = value;
        }
    }
Mar 9, 2015 at 1:47 PM
Indeed it might be more natural to write javascript code this way, but I need to keep backward compatibility with knockoutjs and earlier version of my application. This did work:
        [JSFunction(Name = "value")]
        public object GetOrSetValue(object value)
        {
            if (value == Undefined.Value)
                return this.value;
            this.value = value;
            return this.value;
        }
(Nothing like TypeUtilities.IsUndefined seems to exist.)
Thanks a lot for your help.
Coordinator
Mar 9, 2015 at 9:19 PM
Edited Mar 9, 2015 at 9:19 PM
(Nothing like TypeUtilities.IsUndefined seems to exist.)
Whoops, you're right. That method is marked as internal.
Thanks a lot for your help.
No problem :-)