Ejemplo n.º 1
0
        /// <summary>
        /// Sets the value of a class property to a getter.  If the value already has a
        /// setter then it will be retained.
        /// </summary>
        /// <param name="obj"> The object to set the property on. </param>
        /// <param name="key"> The property key (can be a string or a symbol). </param>
        /// <param name="getter"> The getter function. </param>
        public static void SetClassGetter(ObjectInstance obj, object key, UserDefinedFunction getter)
        {
            var descriptor = obj.GetOwnPropertyDescriptor(key);

            if (descriptor.Exists == false || !descriptor.IsAccessor)
            {
                obj.DefineProperty(key, new PropertyDescriptor(getter, null, Library.PropertyAttributes.NonEnumerable), throwOnError: false);
            }
            else
            {
                obj.DefineProperty(key, new PropertyDescriptor(getter, descriptor.Setter, Library.PropertyAttributes.NonEnumerable), throwOnError: false);
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Sets the value of a object literal property to a setter.  If the value already has a
        /// getter then it will be retained.
        /// </summary>
        /// <param name="obj"> The object to set the property on. </param>
        /// <param name="key"> The property key (can be a string or a symbol).</param>
        /// <param name="setter"> The setter function. </param>
        public static void SetObjectLiteralSetter(ObjectInstance obj, object key, UserDefinedFunction setter)
        {
            var descriptor = obj.GetOwnPropertyDescriptor(key);

            if (descriptor.Exists == false || !descriptor.IsAccessor)
            {
                obj.DefineProperty(key, new PropertyDescriptor(null, setter, Library.PropertyAttributes.FullAccess), throwOnError: false);
            }
            else
            {
                obj.DefineProperty(key, new PropertyDescriptor(descriptor.Getter, setter, Library.PropertyAttributes.FullAccess), throwOnError: false);
            }
        }
        public static ObjectInstance DefineProperty([JSParameter(JSParameterFlags.DoNotConvert)] ObjectInstance obj, string propertyName, [JSParameter(JSParameterFlags.DoNotConvert)] ObjectInstance attributes)
        {
            var defaults   = obj.GetOwnPropertyDescriptor(propertyName);
            var descriptor = PropertyDescriptor.FromObject(attributes, defaults);

            obj.DefineProperty(propertyName, descriptor, true);
            return(obj);
        }
Ejemplo n.º 4
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.º 5
0
        //     CODE GEN METHODS
        //_________________________________________________________________________________________

        /// <summary>
        /// Sets the value of a object literal property to a value.
        /// </summary>
        /// <param name="obj"> The object to set the property on. </param>
        /// <param name="key"> The property key (can be a string or a symbol). </param>
        /// <param name="value"> The value to set. </param>
        public static void SetObjectLiteralValue(ObjectInstance obj, object key, object value)
        {
            obj.DefineProperty(key, new PropertyDescriptor(value, Library.PropertyAttributes.FullAccess), throwOnError: false);
        }
Ejemplo n.º 6
0
 /// <summary>
 /// Sets the value of a class property to a value.
 /// </summary>
 /// <param name="obj"> The object to set the property on. </param>
 /// <param name="key"> The property key (can be a string or a symbol). </param>
 /// <param name="value"> The value to set. </param>
 public static void SetClassValue(ObjectInstance obj, object key, object value)
 {
     obj.DefineProperty(key, new PropertyDescriptor(value, Library.PropertyAttributes.NonEnumerable), throwOnError: false);
 }
Ejemplo n.º 7
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.º 8
0
        private static object ConvertValue(object src, ScriptEngine engine)
        {
            if (src == null)
            {
                return(null);
            }
            Type   type  = src.GetType();
            object value = null;

            if (type.IsEnum)
            {
                // convert to string
                value = src.ToString();
            }
            else if (type == typeof(string))
            {
                value = src;
            }
            else if (type == typeof(int) || type == typeof(short) || type == typeof(byte))
            {
                value = (int)src;
            }
            else if (type == typeof(double) || type == typeof(long) || type == typeof(float))
            {
                value = (double)src;
            }
            else if (type == typeof(bool))
            {
                value = (bool)src;
            }
            else if (type.IsSubclassOf(typeof(ValueType)))
            {
                value = value.ToString();
            }
            else if (typeof(IDictionary <string, object>).IsAssignableFrom(type))
            {
                IDictionary <string, object> dict = value as IDictionary <string, object>;
                ObjectInstance jsObj = engine.Object.Construct();
                foreach (string key in dict.Keys)
                {
                    jsObj.DefineProperty(key, new PropertyDescriptor(ConvertValue(dict[key], engine), Jurassic.Library.PropertyAttributes.Sealed | Jurassic.Library.PropertyAttributes.Enumerable), false);
                }

                value = jsObj;
            }
            else if (typeof(IDictionary).IsAssignableFrom(type))
            {
                IDictionary    dict  = src as IDictionary;
                ObjectInstance jsObj = engine.Object.Construct();
                foreach (object key in dict.Keys)
                {
                    if (key is string)
                    {
                        jsObj.DefineProperty(key as string, new PropertyDescriptor(ConvertValue(dict[key], engine), Jurassic.Library.PropertyAttributes.Enumerable | Jurassic.Library.PropertyAttributes.Sealed), false);
                    }
                    else
                    {
                        throw new NotSupportedException("Cannot have an object key in a dictionary.");
                    }
                }
                value = jsObj;
            }
            else if (type.IsArray || typeof(IEnumerable).IsAssignableFrom(type))
            {
                IEnumerable   collection       = src as IEnumerable;
                ArrayInstance collectionResult = engine.Array.Construct();
                foreach (object o in collection)
                {
                    collectionResult.Push(ConvertValue(o, engine));
                }

                value = collectionResult;
            }
            else
            {
                value = new JinxBotScriptObjectInstance(engine, src);
            }

            return(value);
        }
Ejemplo n.º 9
0
        //     METHODS
        //_________________________________________________________________________________________


        /// <summary>
        /// Populates the given object with properties, field and methods based on the given .NET
        /// type.
        /// </summary>
        /// <param name="target"> The object to populate. </param>
        /// <param name="type"> The .NET type to search for methods. </param>
        /// <param name="flags"> <c>BindingFlags.Static</c> to populate static methods;
        /// <c>BindingFlags.Instance</c> to populate instance methods. </param>
        internal static void PopulateMembers(ObjectInstance target, Type type, BindingFlags flags)
        {
            // Register static methods as functions.
            var methodGroups = new Dictionary <string, List <MethodBase> >();

            foreach (var member in type.GetMembers(BindingFlags.Public | BindingFlags.DeclaredOnly | flags))
            {
                switch (member.MemberType)
                {
                case MemberTypes.Method:
                    MethodInfo        method = (MethodInfo)member;
                    List <MethodBase> methodGroup;
                    if (methodGroups.TryGetValue(method.Name, out methodGroup))
                    {
                        methodGroup.Add(method);
                    }
                    else
                    {
                        methodGroups.Add(method.Name, new List <MethodBase> {
                            method
                        });
                    }
                    break;

                case MemberTypes.Property:
                    PropertyInfo property  = (PropertyInfo)member;
                    var          getMethod = property.GetGetMethod();
                    ClrFunction  getter    = getMethod == null ? null : new ClrFunction(target.Engine.Function.InstancePrototype, new ClrBinder(getMethod));
                    var          setMethod = property.GetSetMethod();
                    ClrFunction  setter    = setMethod == null ? null : new ClrFunction(target.Engine.Function.InstancePrototype, new ClrBinder(setMethod));
                    target.DefineProperty(property.Name, new PropertyDescriptor(getter, setter, PropertyAttributes.NonEnumerable), false);

                    // Property getters and setters also show up as methods, so remove them here.
                    // NOTE: only works if properties are enumerated after methods.
                    if (getMethod != null)
                    {
                        methodGroups.Remove(getMethod.Name);
                    }
                    if (setMethod != null)
                    {
                        methodGroups.Remove(setMethod.Name);
                    }
                    break;

                case MemberTypes.Field:
                    FieldInfo   field       = (FieldInfo)member;
                    ClrFunction fieldGetter = new ClrFunction(target.Engine.Function.InstancePrototype, new FieldGetterBinder(field));
                    ClrFunction fieldSetter = new ClrFunction(target.Engine.Function.InstancePrototype, new FieldSetterBinder(field));
                    target.DefineProperty(field.Name, new PropertyDescriptor(fieldGetter, fieldSetter, PropertyAttributes.NonEnumerable), false);
                    break;

                case MemberTypes.Constructor:
                case MemberTypes.NestedType:
                case MemberTypes.Event:
                case MemberTypes.TypeInfo:
                    // Support not yet implemented.
                    break;
                }
            }
            foreach (var methodGroup in methodGroups.Values)
            {
                var binder   = new ClrBinder(methodGroup);
                var function = new ClrFunction(target.Engine.Function.InstancePrototype, binder);
                target.FastSetProperty(binder.Name, function, PropertyAttributes.NonEnumerable, true);
            }
        }