Browse Source

Refactoring object wrapping

Allows sub properties to be wrapped
as they are used.
Sebastien Ros 11 years ago
parent
commit
1e102887ce

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

@@ -54,6 +54,7 @@
   <ItemGroup>
     <Compile Include="Parser\JavascriptParserTests.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="Runtime\SamplesTests.cs" />
     <Compile Include="Runtime\InteropTests.cs" />
     <Compile Include="Runtime\EngineTests.cs" />
     <Compile Include="Runtime\SunSpiderTests.cs" />

+ 24 - 6
Jint.Tests/Runtime/InteropTests.cs

@@ -27,9 +27,9 @@ namespace Jint.Tests.Runtime
         [Fact]
         public void PrimitiveTypesCanBeSet()
         {
-            _engine.WithMember("x", 10);
-            _engine.WithMember("y", true);
-            _engine.WithMember("z", "foo");
+            _engine.SetValue("x", 10);
+            _engine.SetValue("y", true);
+            _engine.SetValue("z", "foo");
 
             RunTest(@"
                 assert(x === 10);
@@ -56,7 +56,7 @@ namespace Jint.Tests.Runtime
                 Name = "Mickey Mouse"
             };
 
-            _engine.WithMember("p", p);
+            _engine.SetValue("p", p);
 
             RunTest(@"
                 assert(p.Name === 'Mickey Mouse');
@@ -71,7 +71,7 @@ namespace Jint.Tests.Runtime
                 Name = "Mickey Mouse"
             };
 
-            _engine.WithMember("p", p);
+            _engine.SetValue("p", p);
 
             RunTest(@"
                 p.Name = 'Donald Duck';
@@ -89,13 +89,31 @@ namespace Jint.Tests.Runtime
                 Name = "Mickey Mouse",
             };
 
-            _engine.WithMember("p", p);
+            _engine.SetValue("p", p);
 
             RunTest(@"
                 assert(p.Name === 'Mickey Mouse');
             ");
         }
 
+        [Fact]
+        public void CanAccessAnonymousObjectProperties()
+        {
+            var p = new
+            {
+                Address = new
+                {
+                    City = "Mouseton"
+                }
+            };
+
+            _engine.SetValue("p", p);
+
+            RunTest(@"
+                assert(p.Address.City === 'Mouseton');
+            ");
+        }
+
         public class Person
         {
             public string Name { get; set; }

+ 39 - 0
Jint.Tests/Runtime/SamplesTests.cs

@@ -0,0 +1,39 @@
+using System;
+using System.Diagnostics;
+using Xunit;
+
+namespace Jint.Tests.Runtime
+{
+    public class SamplesTests : IDisposable
+    {
+        private readonly Engine _engine;
+
+        public SamplesTests()
+        {
+            _engine = new Engine()
+                .SetValue("log", new Action<object>(Console.WriteLine))
+                .SetValue("assert", new Action<bool>(Assert.True))
+                ;
+        }
+
+        void IDisposable.Dispose()
+        {
+        }
+
+        private void RunTest(string source)
+        {
+            _engine.Execute(source);
+        }
+
+        [Fact]
+        public void GithubReadme1()
+        {
+            var square = new Engine()
+                .SetValue("x", 3)
+                .Execute("x * x")
+                .ToObject();
+
+            Assert.Equal(9d, square);
+        }
+    }
+}

+ 10 - 14
Jint/Engine.cs

@@ -162,34 +162,30 @@ namespace Jint
             return this;
         }
 
-        public Engine WithMember(string name, string value)
+        public Engine SetValue(string name, string value)
         {
-            Global.FastAddProperty(name, new JsValue(value), true, false, true);
-            return this;
+            return SetValue(name, new JsValue(value));
         }
 
-        public Engine WithMember(string name, double value)
+        public Engine SetValue(string name, double value)
         {
-            Global.FastAddProperty(name, new JsValue(value), true, false, true);
-            return this;
+            return SetValue(name, new JsValue(value));
         }
 
-        public Engine WithMember(string name, bool value)
+        public Engine SetValue(string name, bool value)
         {
-            Global.FastAddProperty(name, new JsValue(value), true, false, true);
-            return this;
+            return SetValue(name, new JsValue(value));
         }
 
-        public Engine WithMember(string name, DateTime value)
+        public Engine SetValue(string name, JsValue value)
         {
-            Global.FastAddProperty(name, Date.Construct(value), true, false, true);
+            Global.FastAddProperty(name, value, true, false, true);
             return this;
         }
 
-        public Engine WithMember(string name, Object obj)
+        public Engine SetValue(string name, Object obj)
         {
-            Global.FastAddProperty(name, new ObjectWrapper(this, obj), true, false, true);
-            return this;
+            return SetValue(name, JsValue.FromObject(this, obj));
         }
 
         public void LeaveExecutionContext()

+ 2 - 0
Jint/Jint.csproj

@@ -50,6 +50,7 @@
     <Compile Include="Native\Function\BindFunctionInstance.cs" />
     <Compile Include="Native\IPrimitiveInstance.cs" />
     <Compile Include="Native\JsValue.cs" />
+    <Compile Include="Native\Null.cs" />
     <Compile Include="Native\RegExp\RegExpConstructor.cs" />
     <Compile Include="Native\RegExp\RegExpInstance.cs" />
     <Compile Include="Native\RegExp\RegExpPrototype.cs" />
@@ -82,6 +83,7 @@
     <Compile Include="Native\String\StringPrototype.cs" />
     <Compile Include="Native\String\StringConstructor.cs" />
     <Compile Include="Native\String\StringInstance.cs" />
+    <Compile Include="Native\Undefined.cs" />
     <Compile Include="Options.cs" />
     <Compile Include="Parser\Ast\ArrayExpression.cs" />
     <Compile Include="Parser\Ast\AssignmentExpression.cs" />

+ 21 - 21
Jint/Native/JsValue.cs

@@ -4,6 +4,7 @@ using System.Diagnostics.Contracts;
 using Jint.Native.Object;
 using Jint.Native.RegExp;
 using Jint.Runtime;
+using Jint.Runtime.Interop;
 
 namespace Jint.Native
 {
@@ -85,13 +86,13 @@ namespace Jint.Native
         [Pure]
         public bool IsArray()
         {
-            return this.IsObject() && this.AsObject() is Jint.Native.Array.ArrayInstance;
+            return IsObject() && AsObject() is Array.ArrayInstance;
         }
 
         [Pure]
         public bool IsRegExp()
         {
-            return this.IsObject() && this.AsObject() is RegExpInstance;
+            return IsObject() && AsObject() is RegExpInstance;
         }
         
         [Pure]
@@ -136,21 +137,21 @@ namespace Jint.Native
         }
 
         [Pure]
-        public Jint.Native.Array.ArrayInstance AsArray()
+        public Array.ArrayInstance AsArray()
         {
-            if (!this.IsArray())
+            if (!IsArray())
             {
                 throw new ArgumentException("The value is not an array");
             }
-            return this.AsObject() as Jint.Native.Array.ArrayInstance;            
+            return AsObject() as Array.ArrayInstance;            
         }
 
         [Pure]
         public T TryCast<T>(Action<JsValue> fail = null) where T: class
         {
-            if (this.IsObject())
+            if (IsObject())
             {
-                var o = this.AsObject();
+                var o = AsObject();
                 var t = o as T;
                 if (t != null)
                 {
@@ -258,7 +259,13 @@ namespace Jint.Native
         }
 
         private static readonly Type[] NumberTypes = { typeof(double), typeof(int), typeof(float), typeof(uint), typeof(byte), typeof(short), typeof(ushort), typeof(long), typeof(ulong) };
-        public static JsValue FromObject(object value)
+        /// <summary>
+        /// Creates a valid <see cref="JsValue"/> instance from any <see cref="Object"/> instance
+        /// </summary>
+        /// <param name="engine"></param>
+        /// <param name="value"></param>
+        /// <returns></returns>
+        public static JsValue FromObject(Engine engine, object value)
         {
             if (value == null)
             {
@@ -281,7 +288,12 @@ namespace Jint.Native
                 return (bool) value;
             }
 
-            return Undefined;
+            if (value is DateTime)
+            {
+                return engine.Date.Construct((DateTime) value);
+            }
+
+            return new ObjectWrapper(engine, value);
         }
 
         /// <summary>
@@ -394,16 +406,4 @@ namespace Jint.Native
         }
 
     }
-
-    public static class Undefined
-    {
-        public static JsValue Instance = JsValue.Undefined;
-        public static string Text = "undefined";
-    }
-
-    public static class Null
-    {
-        public static JsValue Instance = JsValue.Null;
-        public static string Text = "null";
-    }
 }

+ 8 - 0
Jint/Native/Null.cs

@@ -0,0 +1,8 @@
+namespace Jint.Native
+{
+    public static class Null
+    {
+        public static JsValue Instance = JsValue.Null;
+        public static string Text = "null";
+    }
+}

+ 8 - 0
Jint/Native/Undefined.cs

@@ -0,0 +1,8 @@
+namespace Jint.Native
+{
+    public static class Undefined
+    {
+        public static JsValue Instance = JsValue.Undefined;
+        public static string Text = "undefined";
+    }
+}

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

@@ -9,12 +9,12 @@ namespace Jint.Runtime.Descriptors.Specialized
         private readonly object _item;
         private JsValue? _value;
 
-        public ClrDataDescriptor(PropertyInfo propertyInfo, object item)
+        public ClrDataDescriptor(Engine engine, PropertyInfo propertyInfo, object item)
         {
             _propertyInfo = propertyInfo;
             _item = item;
 
-            _value = JsValue.FromObject(_propertyInfo.GetValue(_item, null));
+            _value = JsValue.FromObject(engine, _propertyInfo.GetValue(_item, null));
             Writable = propertyInfo.CanWrite;
         }
 

+ 1 - 1
Jint/Runtime/ExpressionIntepreter.cs

@@ -627,7 +627,7 @@ namespace Jint.Runtime
                 return _engine.RegExp.Construct(literal.Raw);
             }
 
-            return JsValue.FromObject(literal.Value);
+            return JsValue.FromObject(_engine, literal.Value);
         }
 
         public JsValue EvaluateObjectExpression(ObjectExpression objectExpression)

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

@@ -22,7 +22,7 @@ namespace Jint.Runtime.Interop
 
         public override JsValue Call(JsValue thisObject, JsValue[] arguments)
         {
-            return JsValue.FromObject(_d.DynamicInvoke(arguments.Select(x => x.ToObject()).ToArray()));
+            return JsValue.FromObject(Engine, _d.DynamicInvoke(arguments.Select(x => x.ToObject()).ToArray()));
         }
     }
 }

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

@@ -37,7 +37,7 @@ namespace Jint.Runtime.Interop
             }
             else
             {
-                var descriptor = new ClrDataDescriptor(property, _obj);
+                var descriptor = new ClrDataDescriptor(Engine, property, _obj);
                 Properties.Add(propertyName, descriptor);
                 return descriptor;
             }