Browse Source

Do not wrap native Jint types

When a POCO returns a native Jint value, this value
should not be wrapped into ObjectWrapper or JsValue
Sebastien Ros 11 years ago
parent
commit
5504974f6b
2 changed files with 96 additions and 13 deletions
  1. 52 0
      Jint.Tests/Runtime/InteropTests.cs
  2. 44 13
      Jint/Native/JsValue.cs

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

@@ -1,4 +1,6 @@
 using System;
+using Jint.Native;
+using Jint.Native.Object;
 using Xunit;
 
 namespace Jint.Tests.Runtime
@@ -129,6 +131,56 @@ namespace Jint.Tests.Runtime
             ");
         }
 
+        [Fact]
+        public void PocosCanReturnJsValueDirectly()
+        {
+            var o = new
+            {
+                x = new JsValue(1),
+                y = new JsValue("string"),
+            };
+
+            _engine.SetValue("o", o);
+
+            RunTest(@"
+                assert(o.x === 1);
+                assert(o.y === 'string');
+            ");
+        }
+
+        [Fact]
+        public void PocosCanReturnObjectInstanceDirectly()
+        {
+            var x = new ObjectInstance(_engine) { Extensible = true};
+            x.Put("foo", new JsValue("bar"), false);
+
+            var o = new
+            {
+                x
+            };
+
+            _engine.SetValue("o", o);
+
+            RunTest(@"
+                assert(o.x.foo === 'bar');
+            ");
+        }
+
+        [Fact]
+        public void DateTimeIsConvertedToDate()
+        {
+            var o = new
+            {
+                z = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)
+            };
+
+            _engine.SetValue("o", o);
+
+            RunTest(@"
+                assert(o.z.valueOf() === 0);
+            ");
+        }
+
         public class Person
         {
             public string Name { get; set; }

+ 44 - 13
Jint/Native/JsValue.cs

@@ -258,7 +258,6 @@ namespace Jint.Native
             get { return _type; }
         }
 
-        private static readonly Type[] NumberTypes = { typeof(double), typeof(int), typeof(float), typeof(uint), typeof(byte), typeof(short), typeof(ushort), typeof(long), typeof(ulong) };
         /// <summary>
         /// Creates a valid <see cref="JsValue"/> instance from any <see cref="Object"/> instance
         /// </summary>
@@ -272,27 +271,59 @@ namespace Jint.Native
                 return Null;
             }
 
-            var s = value as string;
-            if (s != null)
+            var typeCode = System.Type.GetTypeCode(value.GetType());
+            switch (typeCode)
             {
-                return s;
-            }
-
-            if (System.Array.IndexOf(NumberTypes, value.GetType()) != -1)
-            {
-                return Convert.ToDouble(value);
+                case TypeCode.Boolean:
+                    return new JsValue((bool)value);
+                case TypeCode.Byte:
+                    return new JsValue((double)(byte)value);
+                case TypeCode.Char:
+                    return new JsValue(value.ToString());
+                case TypeCode.DateTime:
+                    return engine.Date.Construct((DateTime)value);
+                case TypeCode.Decimal:
+                    return new JsValue((double)(decimal)value);
+                case TypeCode.Double:
+                    return new JsValue((double)value);
+                case TypeCode.Int16:
+                    return new JsValue((double)(Int16)value);
+                case TypeCode.Int32:
+                    return new JsValue((double)(Int32)value);
+                case TypeCode.Int64:
+                    return new JsValue((double)(Int64)value);
+                case TypeCode.SByte:
+                    return new JsValue((double)(SByte)value);
+                case TypeCode.Single:
+                    return new JsValue((double)(Single)value);
+                case TypeCode.String:
+                    return new JsValue((string)value);
+                case TypeCode.UInt16:
+                    return new JsValue((double)(UInt16)value);
+                case TypeCode.UInt32:
+                    return new JsValue((double)(UInt32)value);
+                case TypeCode.UInt64:
+                    return new JsValue((double)(UInt64)value);
+                case TypeCode.Object:
+                    break;
+                case TypeCode.Empty:
+                    break;
+                default:
+                    throw new ArgumentOutOfRangeException();
             }
 
-            if (value is bool)
+            var instance = value as ObjectInstance;
+            if (instance != null)
             {
-                return (bool) value;
+                return new JsValue(instance);
             }
 
-            if (value is DateTime)
+            if (value is JsValue)
             {
-                return engine.Date.Construct((DateTime) value);
+                return (JsValue) value;
             }
 
+            // if no known type could be guessed, wrap it as an ObjectInstance
             return new ObjectWrapper(engine, value);
         }