Browse Source

Implementing generics support

Sebastien Ros 11 years ago
parent
commit
5680d3b8b7

+ 0 - 2
Jint.Tests/Runtime/EngineTests.cs

@@ -1,11 +1,9 @@
 using System;
 using System;
-using System.Diagnostics;
 using System.Globalization;
 using System.Globalization;
 using System.IO;
 using System.IO;
 using System.Reflection;
 using System.Reflection;
 using System.Threading;
 using System.Threading;
 using Jint.Native.Number;
 using Jint.Native.Number;
-using Jint.Native.Number.Dtoa;
 using Jint.Runtime;
 using Jint.Runtime;
 using Xunit;
 using Xunit;
 using Xunit.Extensions;
 using Xunit.Extensions;

+ 12 - 3
Jint.Tests/Runtime/InteropTests.cs

@@ -336,7 +336,7 @@ namespace Jint.Tests.Runtime
         {
         {
             var result = _engine
             var result = _engine
                 .SetValue("values", new List<object> { 1, 2, 3, 4, 5, 6 })
                 .SetValue("values", new List<object> { 1, 2, 3, 4, 5, 6 })
-                .Execute("values.filter(function(x){ return x % 2 == 0; })");
+                .Execute("new Array(values).filter(function(x){ return x % 2 == 0; })");
 
 
             var parts = result.GetCompletionValue().ToObject();
             var parts = result.GetCompletionValue().ToObject();
 
 
@@ -591,7 +591,16 @@ namespace Jint.Tests.Runtime
             ");
             ");
         }
         }
 
 
-
-
+        [Fact]
+        public void ShouldCreateGenericType()
+        {
+            RunTest(@"
+                var ListOfString = System.Collections.Generic.List(System.String);
+                var list = new ListOfString();
+                list.Add('foo');
+                list.Add(1);
+                assert(2 === list.Count);
+            ");
+        }
     }
     }
 }
 }

+ 18 - 1
Jint/Native/Array/ArrayConstructor.cs

@@ -1,4 +1,5 @@
-using Jint.Native.Function;
+using System.Collections;
+using Jint.Native.Function;
 using Jint.Native.Object;
 using Jint.Native.Object;
 using Jint.Runtime;
 using Jint.Runtime;
 using Jint.Runtime.Interop;
 using Jint.Runtime.Interop;
@@ -68,6 +69,22 @@ namespace Jint.Native.Array
                 
                 
                 instance.FastAddProperty("length", length, true, false, false);
                 instance.FastAddProperty("length", length, true, false, false);
             }
             }
+            else if (arguments.Length == 1 && arguments.At(0).IsObject() && arguments.At(0).As<ObjectWrapper>() != null )
+            {
+                var enumerable = arguments.At(0).As<ObjectWrapper>().Target as IEnumerable;
+
+                if (enumerable != null)
+                {
+                    var jsArray = Engine.Array.Construct(Arguments.Empty);
+                    foreach (var item in enumerable)
+                    {
+                        var jsItem = JsValue.FromObject(Engine, item);
+                        Engine.Array.PrototypeObject.Push(jsArray, Arguments.From(jsItem));
+                    }
+
+                    return jsArray;
+                }
+            }
             else
             else
             {
             {
                 instance.FastAddProperty("length", 0, true, false, false);
                 instance.FastAddProperty("length", 0, true, false, false);

+ 1 - 1
Jint/Native/JsValue.cs

@@ -348,7 +348,7 @@ namespace Jint.Native
                 return (JsValue) value;
                 return (JsValue) value;
             }
             }
 
 
-            var array = value as IEnumerable;
+            var array = value as System.Array;
             if (array != null)
             if (array != null)
             {
             {
                 var jsArray = engine.Array.Construct(Arguments.Empty);
                 var jsArray = engine.Array.Construct(Arguments.Empty);

+ 45 - 12
Jint/Runtime/Interop/NamespaceReference.cs

@@ -1,4 +1,5 @@
 using System;
 using System;
+using System.Globalization;
 using System.Linq;
 using System.Linq;
 using System.Reflection;
 using System.Reflection;
 using Jint.Native;
 using Jint.Native;
@@ -13,7 +14,7 @@ namespace Jint.Runtime.Interop
     /// a new <see cref="NamespaceReference"/> as it assumes that the property is a deeper
     /// a new <see cref="NamespaceReference"/> as it assumes that the property is a deeper
     /// level of the current namespace
     /// level of the current namespace
     /// </summary>
     /// </summary>
-    public class NamespaceReference : ObjectInstance
+    public class NamespaceReference : ObjectInstance, ICallable
     {
     {
         private readonly string _path;
         private readonly string _path;
 
 
@@ -42,37 +43,69 @@ namespace Jint.Runtime.Interop
             return false;
             return false;
         }
         }
 
 
+        public JsValue Call(JsValue thisObject, JsValue[] arguments)
+        {
+            // direct calls on a NamespaceReference constructor object is creating a generic type 
+            var genericTypes = new Type[arguments.Length];
+            for (int i = 0; i < arguments.Length; i++)
+            {
+                var genericTypeReference = arguments.At(i);
+                if (genericTypeReference == Undefined.Instance || !genericTypeReference.IsObject() || genericTypeReference.AsObject().Class != "TypeReference")
+                {
+                    throw new JavaScriptException(Engine.TypeError, "Invalid generic type parameter");
+                }
+
+                genericTypes[i] = arguments.At(0).As<TypeReference>().Type;
+            }
+
+            var typeReference = GetPath(_path + "`" + arguments.Length.ToString(CultureInfo.InvariantCulture)).As<TypeReference>();
+
+            if (typeReference == null)
+            {
+                return Undefined.Instance;
+            }
+
+            var genericType = typeReference.Type.MakeGenericType(genericTypes);
+
+            return TypeReference.CreateTypeReference(Engine, genericType);
+        }
+
         public override JsValue Get(string propertyName)
         public override JsValue Get(string propertyName)
         {
         {
             var newPath = _path + "." + propertyName;
             var newPath = _path + "." + propertyName;
 
 
+            return GetPath(newPath);
+        }
+
+        public JsValue GetPath(string path)
+        {
             Type type;
             Type type;
 
 
-            if (Engine.TypeCache.TryGetValue(newPath, out type))
+            if (Engine.TypeCache.TryGetValue(path, out type))
             {
             {
                 if (type == null)
                 if (type == null)
                 {
                 {
-                    return new NamespaceReference(Engine, newPath);
+                    return new NamespaceReference(Engine, path);
                 }
                 }
 
 
                 return TypeReference.CreateTypeReference(Engine, type);
                 return TypeReference.CreateTypeReference(Engine, type);
             }
             }
 
 
             // search for type in mscorlib
             // search for type in mscorlib
-            type = Type.GetType(newPath);
+            type = Type.GetType(path);
             if (type != null)
             if (type != null)
             {
             {
-                Engine.TypeCache.Add(newPath, type);
+                Engine.TypeCache.Add(path, type);
                 return TypeReference.CreateTypeReference(Engine, type);
                 return TypeReference.CreateTypeReference(Engine, type);
             }
             }
 
 
             // search in loaded assemblies
             // search in loaded assemblies
-            foreach (var assembly in new [] { Assembly.GetCallingAssembly(), Assembly.GetExecutingAssembly() }.Distinct())
+            foreach (var assembly in new[] { Assembly.GetCallingAssembly(), Assembly.GetExecutingAssembly() }.Distinct())
             {
             {
-                type = assembly.GetType(newPath);
+                type = assembly.GetType(path);
                 if (type != null)
                 if (type != null)
                 {
                 {
-                    Engine.TypeCache.Add(newPath, type);
+                    Engine.TypeCache.Add(path, type);
                     return TypeReference.CreateTypeReference(Engine, type);
                     return TypeReference.CreateTypeReference(Engine, type);
                 }
                 }
             }
             }
@@ -80,18 +113,18 @@ namespace Jint.Runtime.Interop
             // search in lookup asemblies
             // search in lookup asemblies
             foreach (var assembly in Engine.Options.GetLookupAssemblies())
             foreach (var assembly in Engine.Options.GetLookupAssemblies())
             {
             {
-                type = assembly.GetType(newPath);
+                type = assembly.GetType(path);
                 if (type != null)
                 if (type != null)
                 {
                 {
-                    Engine.TypeCache.Add(newPath, type);
+                    Engine.TypeCache.Add(path, type);
                     return TypeReference.CreateTypeReference(Engine, type);
                     return TypeReference.CreateTypeReference(Engine, type);
                 }
                 }
             }
             }
 
 
             // the new path doesn't represent a known class, thus return a new namespace instance
             // the new path doesn't represent a known class, thus return a new namespace instance
 
 
-            Engine.TypeCache.Add(newPath, null);
-            return new NamespaceReference(Engine, newPath);
+            Engine.TypeCache.Add(path, null);
+            return new NamespaceReference(Engine, path);
         }
         }
 
 
         public override PropertyDescriptor GetOwnProperty(string propertyName)
         public override PropertyDescriptor GetOwnProperty(string propertyName)

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

@@ -139,7 +139,7 @@ namespace Jint.Runtime.Interop
 
 
         public override string Class
         public override string Class
         {
         {
-            get { return Type.FullName; }
+            get { return "TypeReference"; }
         }
         }
     }
     }
 }
 }