Browse Source

Fix indexer value conversion (#792)

Marko Lahma 4 years ago
parent
commit
b0529f99e8

+ 18 - 0
Jint.Tests/Runtime/Domain/IntegerIndexer.cs

@@ -0,0 +1,18 @@
+namespace Jint.Tests.Runtime.Domain
+{
+    public class IntegerIndexer
+    {
+        private readonly int[] data;
+
+        public IntegerIndexer()
+        {
+            data = new[] {123, 0, 0, 0, 0};
+        }
+
+        public int this[int i]
+        {
+            get => data[i];
+            set => data[i] = value;
+        }
+    }
+}

+ 16 - 0
Jint.Tests/Runtime/InteropTests.cs

@@ -2249,5 +2249,21 @@ namespace Jint.Tests.Runtime
 
             Assert.Equal("Orange", engine.Execute("m.Member1").GetCompletionValue().ToString());
         }
+
+        [Fact]
+        public void SettingValueViaIntegerIndexer()
+        {			
+            var engine = new Engine(cfg => cfg.AllowClr(typeof(FloatIndexer).GetTypeInfo().Assembly));
+            engine.SetValue("log", new Action<object>(Console.WriteLine));
+            engine.Execute(@"
+                var domain = importNamespace('Jint.Tests.Runtime.Domain');
+                var fia = new domain.IntegerIndexer();
+                log(fia[0]);
+            ");
+            
+            Assert.Equal(123, engine.Execute("fia[0]").GetCompletionValue().AsNumber());
+            engine.Execute("fia[0] = 678;");
+            Assert.Equal(678, engine.Execute("fia[0]").GetCompletionValue().AsNumber());
+        }
     }
 }

+ 9 - 1
Jint/Runtime/Descriptors/Specialized/IndexDescriptor.cs

@@ -121,7 +121,15 @@ namespace Jint.Runtime.Descriptors.Specialized
                     ExceptionHelper.ThrowInvalidOperationException("Indexer has no public setter.");
                 }
 
-                object[] parameters = { _key,  value?.ToObject() };
+                var obj = value?.ToObject();
+                
+                // attempt to convert to expected type
+                if (obj != null && obj.GetType() != _indexer.PropertyType)
+                {
+                    obj = _engine.ClrTypeConverter.Convert(obj, _indexer.PropertyType, CultureInfo.InvariantCulture);
+                }
+                
+                object[] parameters = { _key,  obj };
                 try
                 {
                     setter!.Invoke(_target, parameters);