Browse Source

Merge pull request #56 from flts/master

Implementing Index support - Fixes #48
Sébastien Ros 11 years ago
parent
commit
b7796bef8f

+ 66 - 1
Jint.Tests/Runtime/InteropTests.cs

@@ -99,7 +99,72 @@ namespace Jint.Tests.Runtime
                 assert(p.Name === 'Donald Duck');
             ");
 
-            Assert.Equal("Donald Duck", p.Name);
+            Assert.Equal("Donald Duck", p.Name);
+        }
+
+        [Fact]
+        public void CanGetIndexUsingStringKey()
+        {
+            var dictionary = new Dictionary<string, Person>();
+            dictionary.Add("person1", new Person { Name = "Mickey Mouse" });
+            dictionary.Add("person2", new Person { Name = "Goofy" });
+
+            _engine.SetValue("dictionary", dictionary);
+
+            RunTest(@"
+                assert(dictionary['person1'].Name === 'Mickey Mouse');
+                assert(dictionary['person2'].Name === 'Goofy');
+            ");
+        }
+
+        [Fact]
+        public void CanSetIndexUsingStringKey()
+        {
+            var dictionary = new Dictionary<string, Person>();
+            dictionary.Add("person1", new Person { Name = "Mickey Mouse" });
+            dictionary.Add("person2", new Person { Name = "Goofy" });
+
+            _engine.SetValue("dictionary", dictionary);
+
+            RunTest(@"
+                dictionary['person2'].Name = 'Donald Duck';
+                assert(dictionary['person2'].Name === 'Donald Duck');
+            ");
+
+            Assert.Equal("Donald Duck", dictionary["person2"].Name);
+        }
+
+        [Fact]
+        public void CanGetIndexUsingIntegerKey()
+        {
+            var dictionary = new Dictionary<int, string>();
+            dictionary.Add(1, "Mickey Mouse");
+            dictionary.Add(2, "Goofy");
+
+            _engine.SetValue("dictionary", dictionary);
+
+            RunTest(@"
+                assert(dictionary[1] === 'Mickey Mouse');
+                assert(dictionary[2] === 'Goofy');
+            ");
+        }
+
+        [Fact]
+        public void CanSetIndexUsingIntegerKey()
+        {
+            var dictionary = new Dictionary<int, string>();
+            dictionary.Add(1, "Mickey Mouse");
+            dictionary.Add(2, "Goofy");
+
+            _engine.SetValue("dictionary", dictionary);
+
+            RunTest(@"
+                dictionary[2] = 'Donald Duck';
+                assert(dictionary[2] === 'Donald Duck');
+            ");
+
+            Assert.Equal("Mickey Mouse", dictionary[1]);
+            Assert.Equal("Donald Duck", dictionary[2]);
         }
 
         [Fact]

+ 1 - 0
Jint/Jint.csproj

@@ -162,6 +162,7 @@
     <Compile Include="Runtime\Completion.cs" />
     <Compile Include="Runtime\Descriptors\PropertyDescriptor.cs" />
     <Compile Include="Runtime\Descriptors\Specialized\FieldInfoDescriptor.cs" />
+    <Compile Include="Runtime\Descriptors\Specialized\IndexDescriptor.cs" />
     <Compile Include="Runtime\Descriptors\Specialized\PropertyInfoDescriptor.cs" />
     <Compile Include="Runtime\Descriptors\Specialized\ClrAccessDescriptor.cs" />
     <Compile Include="Runtime\Environments\Binding.cs" />

+ 44 - 0
Jint/Runtime/Descriptors/Specialized/IndexDescriptor.cs

@@ -0,0 +1,44 @@
+using System.Globalization;
+using System.Reflection;
+using Jint.Native;
+
+namespace Jint.Runtime.Descriptors.Specialized
+{
+    public sealed class IndexDescriptor : PropertyDescriptor
+    {
+        private readonly Engine _engine;
+        private readonly object _key;
+        private readonly object _item;
+        private readonly MethodInfo _getter;
+        private readonly MethodInfo _setter;
+
+        public IndexDescriptor(Engine engine, string key, object item)
+        {
+            _engine = engine;
+            _item = item;
+
+            _getter = item.GetType().GetMethod("get_Item", BindingFlags.Instance | BindingFlags.Public);
+            _setter = item.GetType().GetMethod("set_Item", BindingFlags.Instance | BindingFlags.Public);
+
+            _key = _engine.Options.GetTypeConverter().Convert(key, _getter.GetParameters()[0].ParameterType, CultureInfo.InvariantCulture);
+
+            Writable = true;
+        }
+
+        public override JsValue? Value
+        {
+            get
+            {
+                object[] parameters = { _key };
+                return JsValue.FromObject(_engine, _getter.Invoke(_item, parameters));
+            }
+
+            set
+            {
+                var defaultValue = _item.GetType().IsValueType ? System.Activator.CreateInstance(_item.GetType()) : null;
+                object[] parameters = { _key, value.HasValue ? value.Value.ToObject() : null };
+                _setter.Invoke(_item, parameters);
+            }
+        }
+    }
+}

+ 9 - 2
Jint/Runtime/Interop/ObjectWrapper .cs

@@ -4,7 +4,8 @@ using System.Reflection;
 using Jint.Native;
 using Jint.Native.Object;
 using Jint.Runtime.Descriptors;
-using Jint.Runtime.Descriptors.Specialized;
+using Jint.Runtime.Descriptors.Specialized;
+using System.Collections;
 
 namespace Jint.Runtime.Interop
 {
@@ -87,7 +88,13 @@ namespace Jint.Runtime.Interop
             if (methods.Any())
             {
                 return new PropertyDescriptor(new MethodInfoFunctionInstance(Engine, methods), false, true, false);
-            }
+            }
+
+            // if no methods are found check if target is an IDictionary
+            if (typeof(IDictionary).IsAssignableFrom(type))
+            {
+                return new IndexDescriptor(Engine, propertyName, Target);
+            }
 
             return PropertyDescriptor.Undefined;
         }