public override object CallLateBound(object thisObject, params object[] argumentValues)
        {
            var clrObject = thisObject is Undefined ? _owner : _ctx.ConvertToClr(thisObject);

            var methodIndex = _methods.IndexOf(x => x.GetParameters().IsAppropriate(argumentValues));

            if (methodIndex < 0)
            {
                return(null); //or throw exception;
            }
            var method = _methods[methodIndex];

            var converter = _paramConverters[methodIndex] ?? (_paramConverters[methodIndex] =
                                                                  ClrTypeConverter.GetParamsConverter(_ctx, method.GetParameters()));

            var clrArguments = converter(thisObject, argumentValues);

            try
            {
                var clrResult = method.Invoke(clrObject, clrArguments);
                return(_ctx.ConvertToJs(clrResult));
            }
            catch (Exception e)
            {
                throw new JavaScriptException(_ctx.Engine, ErrorType.Error, e.Message, e);
            }
        }
Esempio n. 2
0
        protected override object GetMissingPropertyValue(object key)
        {
            if (_array != null)
            {
                switch (key)
                {
                case int index: return(_ctx.ConvertToJs(_array.GetValue(index)));

                case string str:
                    return(int.TryParse(str, out var parsedIndex) && parsedIndex >= 0 && parsedIndex < _array.Length
                            ? _ctx.ConvertToJs(_array.GetValue(parsedIndex))
                            : base.GetMissingPropertyValue(key));

                default:
                    return(base.GetMissingPropertyValue(key));
                }
            }

            var clrKey = _ctx.ConvertToClr(key);

            var pi =
                clrKey == null
                    ? _indexProperties.FirstOrDefault(x => x.GetIndexParameters()[0].ParameterType.CanBeNull())
                    : _indexProperties.FirstOrDefault(x => x.GetIndexParameters()[0].ParameterType.IsInstanceOfType(clrKey));

            //converts string key to integer.
            if (pi == null && key is string stringKey)
            {
                pi = _indexProperties.FirstOrDefault(x => x.GetIndexParameters()[0].ParameterType == typeof(int));
                if (pi != null)
                {
                    if (int.TryParse(stringKey, out var idx))
                    {
                        clrKey = idx;
                    }
                    else
                    {
                        return(base.GetMissingPropertyValue(key));
                    }
                }
                else
                {
                    pi = _indexProperties.FirstOrDefault(x => x.GetIndexParameters()[0].ParameterType == typeof(ulong));
                    if (ulong.TryParse(stringKey, out var idx))
                    {
                        clrKey = idx;
                    }
                    else
                    {
                        return(base.GetMissingPropertyValue(key));
                    }
                }
            }

            return(pi != null
                ? _ctx.ConvertToJs(pi.GetValue(Target, new[] { clrKey }))
                : base.GetMissingPropertyValue(key));
        }
Esempio n. 3
0
        public override object CallLateBound(object thisObject, params object[] argumentValues)
        {
            var clrObject = thisObject is global::Jurassic.Undefined ?  _owner : _ctx.ConvertToClr(thisObject);

            //todo: investigate if the precompiled expression can be faster than reflection invoke.


            return(CallMethod(_ctx, _method, thisObject, argumentValues, clrObject));
        }
Esempio n. 4
0
        public object Evaluate(string code)
        {
	        try
	        {
		        return _typeConverter.ConvertToClr(Engine.Evaluate(Clean(code)));
	        }
	        catch (JavaScriptException e)
	        {
		        return new ScriptExecutingException(e.Message, e, code);
	        }
        }
Esempio n. 5
0
 public override object CallLateBound(object thisObject, params object[] argumentValues)
 {
     try
     {
         var clrThis = _ctx.ConvertToClr(thisObject);
         return(_doConvert ? _ctx.ConvertToJs(_func(clrThis)) : _func(clrThis));
     }
     catch (Exception e)
     {
         throw new JavaScriptException(_ctx.Engine, ErrorType.Error, e.Message, e);
     }
 }
Esempio n. 6
0
        public override object CallLateBound(object thisObject, params object[] argumentValues)
        {
            try
            {
                var clrThis = _ctx.ConvertToClr(thisObject);
                _act(clrThis, argumentValues);
            }
            catch (Exception e)
            {
                throw new JavaScriptException(Engine, ErrorType.Error, e.Message, e);
            }

            return(null);
        }
Esempio n. 7
0
        public static object[] ConvertParametersToClr(this ClrTypeConverter ctx, ParameterInfo[] methodParameters,
                                                      object thisObject,
                                                      object[] argumentValues)
        {
            var clrArguments = new object[methodParameters.Length];

            for (var idx = 0; idx < clrArguments.Length; idx++)
            {
                var par = methodParameters[idx];

                if (idx < argumentValues.Length)
                {
                    //todo: optimize
                    var expand = par.GetCustomAttribute <JsExpandArrayAttribute>() != null;

                    var jsArgument = argumentValues[idx];

                    if (!expand && (par.ParameterType.IsValueType))
                    {
                        clrArguments[idx] = ctx.GetConverter(par.ParameterType, par.GetDefaultValue())(jsArgument);
                    }
                    else
                    {
                        clrArguments[idx] =
                            ctx.ConvertToClr(
                                jsArgument,
                                par.ParameterType,
                                thisObject,
                                expand);
                    }
                }
                else
                {
                    if (par.GetCustomAttribute <ParamArrayAttribute>() != null)
                    {
                        clrArguments[idx] = Activator.CreateInstance(par.ParameterType, 0);
                    }
                    else if (par.HasDefaultValue)
                    {
                        clrArguments[idx] = par.DefaultValue;
                    }
                }
            }

            return(clrArguments);
        }
Esempio n. 8
0
        public static object[] ConvertParametersToClr(this ClrTypeConverter ctx, Type[] methodParameters,
                                                      object thisObject,
                                                      object[] argumentValues)
        {
            var clrArguments = new object[methodParameters.Length];

            for (var idx = 0; idx < clrArguments.Length; idx++)
            {
                if (idx < argumentValues.Length)
                {
                    var jsArgument = argumentValues[idx];
                    clrArguments[idx] = ctx.ConvertToClr(jsArgument, methodParameters[idx], thisObject);
                }
            }

            return(clrArguments);
        }
Esempio n. 9
0
        /// <summary>
        /// Adds properties to the specified js object from the specified clr object.
        /// </summary>
        public static void DefineProperties(this ObjectInstance jsObject, ClrTypeConverter ctx, Type type, object clrOwner = null)
        {
            var bindingFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly;

            //register properties
            foreach (var property in type.GetProperties(bindingFlags).Where(p => p.GetCustomAttribute <JsHiddenAttribute>() == null))
            {
                var name = property.GetName();

                //todo: compile delegate instead of reflection, research what is faster.

                var jsGetter =
                    property.GetMethod != null && property.GetMethod.IsPublic ? new FuncInst(ctx, clrThis => property.GetValue(clrThis)) : null;

                var jsSetter =
                    property.SetMethod != null && property.SetMethod.IsPublic ? new ActInst(ctx, (clrThis, objects) =>
                                                                                            property.SetValue(clrThis, ctx.ConvertToClr(objects[0], property.PropertyType, ctx.ConvertToJs(clrThis)))) : null;

                var jsProperty = new PropertyDescriptor(jsGetter, jsSetter, PropertyAttributes.Configurable);

                jsObject.DefineProperty(name, jsProperty, false);
            }

            //register methods
            foreach (var methods in type
                     .GetMethods(bindingFlags)
                     .Where(p => p.GetCustomAttribute <JsHiddenAttribute>() == null &&
                            p.GetCustomAttribute <JsCtorAttribute>() == null)
                     .GroupBy(p => p.GetName()))
            {
                var methodsArray = methods.ToArray();

                var firstMethod = methodsArray[0];

                if (firstMethod.IsSpecialName)
                {
                    continue;
                }

                if (firstMethod.DeclaringType == typeof(object))
                {
                    continue;
                }

                var name = methods.Key;

                var jsMethod =
                    methodsArray.Length == 1
                        ? new ClrMethodInstance(ctx, clrOwner, firstMethod, name)
                        : (FunctionInstance) new ClrOverloadMethodInstance(ctx, clrOwner, methodsArray, name);

                //todo: check the PropertyAttributes
                var jsProperty = new PropertyDescriptor(jsMethod, PropertyAttributes.Sealed);

                jsObject.DefineProperty(name, jsProperty, false);
            }

            //register events
            foreach (var evt in type.GetEvents(bindingFlags)
                     .Where(p => p.GetCustomAttribute <JsHiddenAttribute>() == null))
            {
                var name = evt.GetName().ToLowerInvariant();

                var jsGetter = new FuncInst(ctx, clrThis =>
                {
                    var attachedEvents = ctx.GetAttachedEventsFor(clrThis);
                    return(attachedEvents[evt]);
                }, false);

                var jsSetter = new ActInst(ctx,
                                           (clrThis, args) =>
                {
                    var jsThis = ctx.ConvertToJs(clrThis);

                    var attachedEvents = ctx.GetAttachedEventsFor(clrThis);

                    if (attachedEvents.TryGetValue(evt, out var existHandler))
                    {
                        var clrHandler = ctx.ConvertToClr(existHandler, evt.EventHandlerType, jsThis);
                        evt.RemoveMethod.Invoke(clrThis, new [] { clrHandler });
                        attachedEvents.Remove(evt);
                    }

                    if (args.Length != 0 && args[0] is FunctionInstance functionInstance)
                    {
                        var clrHandler = ctx.ConvertToClr(args[0], evt.EventHandlerType, jsThis);
                        evt.AddMethod.Invoke(clrThis, new[] { clrHandler });
                        attachedEvents[evt] = functionInstance;
                    }
                });

                var jsProperty = new PropertyDescriptor(jsGetter, jsSetter, PropertyAttributes.Configurable);

                jsObject.DefineProperty(name, jsProperty, false);
            }

            //Register static fields
            DefineStaticProperties(jsObject, ctx, type);
        }