Ejemplo n.º 1
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));
        }
Ejemplo n.º 2
0
        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);
            }
        }
Ejemplo n.º 3
0
        public object CallMethod(ClrTypeConverter ctx, MethodInfo method, object thisObject,
                                 object[] argumentValues, object clrObject)
        {
            if (thisObject is ClrPrototype proto)
            {
                if (method.Name == "ToString")
                {
                    return($"[object {proto.Name}]");
                }

                throw new JavaScriptException(ctx.Engine, ErrorType.Error, "Illegal method invocation.");
            }

            var clrArguments = _paramsConverter(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);
            }
        }
Ejemplo n.º 4
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);
     }
 }
Ejemplo n.º 5
0
        public static void DefineStaticProperties(this ObjectInstance jsObject, ClrTypeConverter ctx, Type type)
        {
            foreach (var staticField in type.GetFields(BindingFlags.Public | BindingFlags.Static)
                     .Where(p => p.GetCustomAttribute <JsHiddenAttribute>() == null))
            {
                var clrValue = staticField.GetValue(null);
                var prop     = new PropertyDescriptor(ctx.ConvertToJs(clrValue), PropertyAttributes.Sealed);

                var name = staticField.GetCustomAttribute <JsNameAttribute>()?.Name ?? staticField.Name;

                jsObject.DefineProperty(name, prop, false);
            }
        }
Ejemplo n.º 6
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);
        }
Ejemplo n.º 7
0
 public void AddGlobalGetter(string name, Func<object> getter)
 {
     var jsGetter = (FunctionInstance)_typeConverter.ConvertToJs(getter); 
     var property = new PropertyDescriptor(jsGetter, null, PropertyAttributes.Configurable);
     Engine.Global.DefineProperty(name, property, true);
 }
Ejemplo n.º 8
0
 public override ObjectInstance ConstructLateBound(params object[] argumentValues)
 {
     var inst = (ObjectInstance) _ctx.ConvertToJs(_creator(argumentValues));
     return inst;
 }