Browse Source

Implementing fields read/write support

#17
Sebastien Ros 11 years ago
parent
commit
1dc94b9b97

+ 1 - 0
Jint.Tests/Jint.Tests.csproj

@@ -55,6 +55,7 @@
     <Compile Include="Parser\JavascriptParserTests.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
     <Compile Include="Runtime\Domain\A.cs" />
+    <Compile Include="Runtime\Domain\ClassWithField.cs" />
     <Compile Include="Runtime\Domain\IPerson.cs" />
     <Compile Include="Runtime\Domain\Person.cs" />
     <Compile Include="Runtime\Domain\Shape.cs" />

+ 7 - 0
Jint.Tests/Runtime/Domain/ClassWithField.cs

@@ -0,0 +1,7 @@
+namespace Jint.Tests.Runtime.Domain
+{
+    public class ClassWithField
+    {
+        public string Field;
+    }
+}

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

@@ -500,5 +500,37 @@ namespace Jint.Tests.Runtime
 
             Assert.Throws<ArgumentException>(() => _engine.Invoke("x", 1, 2));
         }
+
+        [Fact]
+        public void CanGetField()
+        {
+            var o = new ClassWithField
+            {
+                Field = "Mickey Mouse"
+            };
+
+            _engine.SetValue("o", o);
+
+            RunTest(@"
+                assert(o.Field === 'Mickey Mouse');
+            ");
+        }
+
+        [Fact]
+        public void CanSetField()
+        {
+            var o = new ClassWithField();
+
+            _engine.SetValue("o", o);
+
+            RunTest(@"
+                o.Field = 'Mickey Mouse';
+                assert(o.Field === 'Mickey Mouse');
+            ");
+
+            Assert.Equal("Mickey Mouse", o.Field);
+        }
+
+
     }
 }

+ 2 - 1
Jint/Jint.csproj

@@ -161,7 +161,8 @@
     <Compile Include="Runtime\Arguments.cs" />
     <Compile Include="Runtime\Completion.cs" />
     <Compile Include="Runtime\Descriptors\PropertyDescriptor.cs" />
-    <Compile Include="Runtime\Descriptors\Specialized\ClrDataDescriptor.cs" />
+    <Compile Include="Runtime\Descriptors\Specialized\FieldInfoDescriptor.cs" />
+    <Compile Include="Runtime\Descriptors\Specialized\PropertyInfoDescriptor.cs" />
     <Compile Include="Runtime\Descriptors\Specialized\ClrAccessDescriptor.cs" />
     <Compile Include="Runtime\Environments\Binding.cs" />
     <Compile Include="Runtime\Environments\DeclarativeEnvironmentRecord.cs" />

+ 51 - 0
Jint/Runtime/Descriptors/Specialized/FieldInfoDescriptor.cs

@@ -0,0 +1,51 @@
+using System.Globalization;
+using System.Reflection;
+using Jint.Native;
+
+namespace Jint.Runtime.Descriptors.Specialized
+{
+    public sealed class FieldInfoDescriptor : PropertyDescriptor
+    {
+        private readonly Engine _engine;
+        private readonly FieldInfo _fieldInfo;
+        private readonly object _item;
+
+        public FieldInfoDescriptor(Engine engine, FieldInfo fieldInfo, object item)
+        {
+            _engine = engine;
+            _fieldInfo = fieldInfo;
+            _item = item;
+
+            Writable = true; // a field is always writable
+        }
+
+        public override JsValue? Value
+        {
+            get
+            {
+                return JsValue.FromObject(_engine, _fieldInfo.GetValue(_item));
+            }
+
+            set
+            {
+                var currentValue = value.GetValueOrDefault();
+                object obj;
+                if (_fieldInfo.FieldType == typeof (JsValue))
+                {
+                    obj = currentValue;
+                }
+                else
+                {
+                    // attempt to convert the JsValue to the target type
+                    obj = currentValue.ToObject();
+                    if (obj.GetType() != _fieldInfo.FieldType)
+                    {
+                        obj = _engine.Options.GetTypeConverter().Convert(obj, _fieldInfo.FieldType, CultureInfo.InvariantCulture);
+                    }
+                }
+                
+                _fieldInfo.SetValue(_item, obj);
+            }
+        }
+    }
+}

+ 2 - 2
Jint/Runtime/Descriptors/Specialized/ClrDataDescriptor.cs → Jint/Runtime/Descriptors/Specialized/PropertyInfoDescriptor.cs

@@ -4,13 +4,13 @@ using Jint.Native;
 
 namespace Jint.Runtime.Descriptors.Specialized
 {
-    public sealed class ClrDataDescriptor : PropertyDescriptor
+    public sealed class PropertyInfoDescriptor : PropertyDescriptor
     {
         private readonly Engine _engine;
         private readonly PropertyInfo _propertyInfo;
         private readonly object _item;
 
-        public ClrDataDescriptor(Engine engine, PropertyInfo propertyInfo, object item)
+        public PropertyInfoDescriptor(Engine engine, PropertyInfo propertyInfo, object item)
         {
             _engine = engine;
             _propertyInfo = propertyInfo;

+ 13 - 4
Jint/Runtime/Interop/ObjectWrapper .cs

@@ -28,14 +28,23 @@ namespace Jint.Runtime.Interop
             }
 
             var type = Target.GetType();
-            
+
             // look for a property
-            var property = type.GetProperties(BindingFlags.Instance | BindingFlags.Public)
-                .FirstOrDefault(m => m.Name == propertyName);
+            var property = type.GetProperty(propertyName, BindingFlags.Instance | BindingFlags.Public);
 
             if (property != null)
             {
-                var descriptor = new ClrDataDescriptor(Engine, property, Target);
+                var descriptor = new PropertyInfoDescriptor(Engine, property, Target);
+                Properties.Add(propertyName, descriptor);
+                return descriptor;
+            }
+
+            // look for a field
+            var field = type.GetField(propertyName, BindingFlags.Instance | BindingFlags.Public);
+
+            if (field != null)
+            {
+                var descriptor = new FieldInfoDescriptor(Engine, field, Target);
                 Properties.Add(propertyName, descriptor);
                 return descriptor;
             }

+ 1 - 1
Jint/Runtime/Interop/TypeReference.cs

@@ -113,7 +113,7 @@ namespace Jint.Runtime.Interop
             var propertyInfo = Type.GetProperty(propertyName);
             if (propertyInfo != null)
             {
-                return new ClrDataDescriptor(Engine, propertyInfo, Type);
+                return new PropertyInfoDescriptor(Engine, propertyInfo, Type);
             }
 
             var methodInfo = Type