Forráskód Böngészése

Implementation skeleton

Sebastien Ros 11 éve
szülő
commit
64f31c6651

+ 6 - 0
Jint.Tests/Runtime/Domain/A.cs

@@ -45,5 +45,11 @@ namespace Jint.Tests.Runtime.Domain
 
             return callback(thisArg, arguments).ToString();
         }
+
+        public bool Call7(string str, Func<string, bool> predicate)
+        {
+            return predicate(str);
+        }
+
     }
 }

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

@@ -459,6 +459,16 @@ namespace Jint.Tests.Runtime
             ");
         }
 
+        [Fact]
+        public void ShouldExecuteFunctionCallBackAsPredicate()
+        {
+            _engine.SetValue("a", new A());
+
+            RunTest(@"
+                assert(a.Call7('foo', function(a){ return a === 'foo'; }) === true);
+            ");
+        }
+
         [Fact]
         public void ShouldUseSystemIO()
         {

+ 4 - 1
Jint/Engine.cs

@@ -32,7 +32,8 @@ namespace Jint
         private readonly Stack<ExecutionContext> _executionContexts;
         private JsValue _completionValue = JsValue.Undefined;
         private int _statementsCount;
-        
+        public ITypeConverter ClrTypeConverter;
+
         // cache of types used when resolving CLR type names
         internal Dictionary<string, Type> TypeCache = new Dictionary<string, Type>(); 
 
@@ -128,6 +129,8 @@ namespace Jint
                     return new NamespaceReference(this, TypeConverter.ToString(arguments.At(0)));
                 }), false, false, false);
             }
+
+            ClrTypeConverter = new DefaultTypeConverter(this);
         }
 
         public LexicalEnvironment GlobalEnvironment;

+ 0 - 15
Jint/Options.cs

@@ -13,7 +13,6 @@ namespace Jint
         private bool _strict;
         private bool _allowDebuggerStatement;
         private bool _allowClr;
-        private ITypeConverter _typeConverter = new DefaultTypeConverter();
         private readonly List<IObjectConverter> _objectConverters = new List<IObjectConverter>();
         private int _maxStatements;
         private CultureInfo _culture = CultureInfo.CurrentCulture;
@@ -51,15 +50,6 @@ namespace Jint
             return this;
         }
 
-        /// <summary>
-        /// Sets a <see cref="ITypeConverter"/> instance to use when converting CLR types
-        /// </summary>
-        public Options SetTypeConverter(ITypeConverter typeConverter)
-        {
-            _typeConverter = typeConverter;
-            return this;
-        }
-
         /// <summary>
          /// Adds a <see cref="IObjectConverter"/> instance to convert CLR types to <see cref="JsValue"/>
         /// </summary>
@@ -117,11 +107,6 @@ namespace Jint
             return _lookupAssemblies;
         }
 
-        internal ITypeConverter GetTypeConverter()
-        {
-            return _typeConverter;
-        }
-
         internal IEnumerable<IObjectConverter> GetObjectConverters()
         {
             return _objectConverters;

+ 1 - 1
Jint/Runtime/Descriptors/Specialized/FieldInfoDescriptor.cs

@@ -40,7 +40,7 @@ namespace Jint.Runtime.Descriptors.Specialized
                     obj = currentValue.ToObject();
                     if (obj.GetType() != _fieldInfo.FieldType)
                     {
-                        obj = _engine.Options.GetTypeConverter().Convert(obj, _fieldInfo.FieldType, CultureInfo.InvariantCulture);
+                        obj = _engine.ClrTypeConverter.Convert(obj, _fieldInfo.FieldType, CultureInfo.InvariantCulture);
                     }
                 }
                 

+ 1 - 1
Jint/Runtime/Descriptors/Specialized/PropertyInfoDescriptor.cs

@@ -40,7 +40,7 @@ namespace Jint.Runtime.Descriptors.Specialized
                     obj = currentValue.ToObject();
                     if (obj.GetType() != _propertyInfo.PropertyType)
                     {
-                        obj = _engine.Options.GetTypeConverter().Convert(obj, _propertyInfo.PropertyType, CultureInfo.InvariantCulture);
+                        obj = _engine.ClrTypeConverter.Convert(obj, _propertyInfo.PropertyType, CultureInfo.InvariantCulture);
                     }
                 }
                 

+ 96 - 0
Jint/Runtime/Interop/DefaultTypeConverter.cs

@@ -1,9 +1,19 @@
 using System;
+using System.Linq;
+using System.Linq.Expressions;
+using Jint.Native;
 
 namespace Jint.Runtime.Interop
 {
     public class DefaultTypeConverter : ITypeConverter
     {
+        private readonly Engine _engine;
+
+        public DefaultTypeConverter(Engine engine)
+        {
+            _engine = engine;
+        }
+
         public object Convert(object value, Type type, IFormatProvider formatProvider)
         {
             // don't try to convert if value is derived from type
@@ -23,6 +33,92 @@ namespace Jint.Runtime.Interop
                 return Enum.ToObject(type, integer);
             }
 
+            var valueType = value.GetType();
+            // is the javascript value an ICallable instance ?
+            if (valueType == typeof (Func<JsValue, JsValue[], JsValue>))
+            {
+                var function = (Func<JsValue, JsValue[], JsValue>) value;
+
+                if (type.IsGenericType)
+                {
+                    var genericType = type.GetGenericTypeDefinition();
+
+                    if (type == typeof(Func<string, bool>))
+                    {
+                        //return (Func<string, bool>)(x =>
+                        //{
+                        //    var arguments = new JsValue[1];
+                        //    arguments[0] = JsValue.FromObject(_engine, x);
+                        //    var o = function(JsValue.Undefined, arguments).ToObject();
+                        //    return (bool)Convert(o, typeof(bool), formatProvider);
+                        //});
+                    }
+
+                    // create the requested Delegate
+                    if (genericType == typeof (Action<>))
+                    {
+                    }
+                    else if (genericType == typeof (Func<>))
+                    {
+                    }
+                    else if (genericType == typeof (Func<,>))
+                    {
+                        // return a function instance containing the following body
+
+                        //var arguments = new JsValue[1];
+                        //arguments[0] = JsValue.FromObject(_engine, x);
+                        //var o = function(JsValue.Undefined, arguments).ToObject();
+                        //return (bool) Convert(o, typeof (bool), formatProvider);
+
+                        var genericArguments = type.GetGenericArguments();
+                        var returnType = genericArguments.Last();
+
+                        ParameterExpression xExpr = Expression.Parameter(genericArguments[0], "x");
+
+                        // var arguments = new JsValue[1];
+                        ParameterExpression argumentsVariable = Expression.Variable(typeof (JsValue[]), "arguments");
+                        var argumentsExpression = Expression.Constant(new JsValue[genericArguments.Length - 1]);
+                        Expression.Assign(argumentsVariable, argumentsExpression);
+
+                        //arguments[0] = JsValue.FromObject(_engine, x);
+                        IndexExpression arrayAccess = Expression.ArrayAccess(argumentsExpression, Expression.Constant(0, typeof (int)));
+                        var convertExpression = Expression.Call(null,
+                            typeof (JsValue).GetMethod("FromObject"),
+                            Expression.Constant(_engine, typeof (Engine)),
+                            xExpr);
+
+                        Expression.Assign(arrayAccess, convertExpression);
+
+                        //var o = function(JsValue.Undefined, arguments).ToObject();
+                        ParameterExpression oVariable = Expression.Variable(typeof(object), "o");
+                        Expression.Assign(oVariable,
+                            Expression.Call(Expression.Constant(null),
+                                function.Method, 
+                                Expression.Constant(JsValue.Undefined, typeof (JsValue)),
+                                argumentsExpression));
+
+                        var castExpression = Expression.Convert(
+                            Expression.Call(
+                                Expression.Constant(this), 
+                                this.GetType().GetMethod("Convert"), 
+                                oVariable,
+                                Expression.Constant(returnType), 
+                                Expression.Constant(formatProvider)), 
+                            returnType);
+
+                        return Expression.Lambda(castExpression);
+                    }
+                }
+                else
+                {
+                    if (type == typeof (Action))
+                    {
+                        return (Action)(() => function(JsValue.Undefined, new JsValue[0]));
+                    }
+                }
+
+            }
+
             return System.Convert.ChangeType(value, type, formatProvider);
         }
     }

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

@@ -35,7 +35,7 @@ namespace Jint.Runtime.Interop
                 }
                 else
                 {
-                    parameters[i] = Engine.Options.GetTypeConverter().Convert(
+                    parameters[i] = Engine.ClrTypeConverter.Convert(
                         arguments[i].ToObject(),
                         parameterType,
                         CultureInfo.InvariantCulture);

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

@@ -41,7 +41,7 @@ namespace Jint.Runtime.Interop
                         }
                         else
                         {
-                            parameters[i] = Engine.Options.GetTypeConverter().Convert(
+                            parameters[i] = Engine.ClrTypeConverter.Convert(
                                 arguments[i].ToObject(),
                                 parameterType,
                                 CultureInfo.InvariantCulture);

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

@@ -63,7 +63,7 @@ namespace Jint.Runtime.Interop
                         }
                         else
                         {
-                            parameters[i] = Engine.Options.GetTypeConverter().Convert(
+                            parameters[i] = Engine.ClrTypeConverter.Convert(
                                 arguments[i].ToObject(),
                                 parameterType,
                                 CultureInfo.InvariantCulture);

+ 2 - 2
Jint/Runtime/TypeConverter.cs

@@ -388,8 +388,8 @@ namespace Jint.Runtime
                 {
                     for (var i = 0; i < arguments.Length; i++)
                     {
-                        parameters[i] = engine.Options.GetTypeConverter().Convert(
-                            arguments[i].ToObject(),
+                        parameters[i] = engine.ClrTypeConverter.Convert(
+                            objectArguments[i],
                             method.GetParameters()[i].ParameterType,
                             CultureInfo.InvariantCulture);
                     }