DefineProperty() public method

Defines or redefines the value and attributes of a property. The prototype chain is not searched so if the property exists but only in the prototype chain a new property will be created.
public DefineProperty ( object key, PropertyDescriptor descriptor, bool throwOnError ) : bool
key object The property key of the property to modify.
descriptor PropertyDescriptor The property value and attributes.
throwOnError bool true to throw an exception if the property could not /// be set. This can happen if the property is not configurable or the object is sealed.
return bool
示例#1
0
        /// <summary>
        /// Defines or redefines the value and attributes of a property.  The prototype chain is
        /// not searched so if the property exists but only in the prototype chain a new property
        /// will be created.
        /// </summary>
        /// <param name="key"> The property key of the property to modify. </param>
        /// <param name="descriptor"> The property value and attributes. </param>
        /// <param name="throwOnError"> <c>true</c> to throw an exception if the property could not
        /// be set.  This can happen if the property is not configurable or the object is sealed. </param>
        /// <returns> <c>true</c> if the property was successfully modified; <c>false</c> otherwise. </returns>
        public override bool DefineProperty(object key, PropertyDescriptor descriptor, bool throwOnError)
        {
            // Check for revocation.
            if (target == null || handler == null)
            {
                throw new JavaScriptException(ErrorType.TypeError, "Cannot call 'defineProperty' on a proxy that has been revoked.");
            }

            // Call the handler, if one exists.
            var trap = handler.GetMethod("defineProperty");

            if (trap == null)
            {
                return(target.DefineProperty(key, descriptor, throwOnError));
            }
            var result = TypeConverter.ToBoolean(trap.CallLateBound(handler, target, key, descriptor.ToObject(Engine)));

            // Validate.
            if (!result)
            {
                if (throwOnError)
                {
                    throw new JavaScriptException(ErrorType.TypeError, $"'defineProperty' on proxy: trap returned falsish for property '{TypeConverter.ToString(key)}'.");
                }
                return(false);
            }
            var targetDescriptor = target.GetOwnPropertyDescriptor(key);

            if (targetDescriptor.Exists)
            {
                if (!IsCompatiblePropertyDescriptor(target.IsExtensible, descriptor, targetDescriptor))
                {
                    throw new JavaScriptException(ErrorType.TypeError, $"'defineProperty' on proxy: trap returned truish for adding property '{TypeConverter.ToString(key)}' that is incompatible with the existing property in the proxy target.");
                }
                if (descriptor.Exists && !descriptor.IsConfigurable && targetDescriptor.IsConfigurable)
                {
                    throw new JavaScriptException(ErrorType.TypeError, $"'defineProperty' on proxy: trap returned truish for defining non-configurable property '{TypeConverter.ToString(key)}' which is either non-existent or configurable in the proxy target.");
                }
                if (!targetDescriptor.IsAccessor && !targetDescriptor.IsConfigurable && targetDescriptor.IsWritable)
                {
                    if (descriptor.Exists && !descriptor.IsWritable)
                    {
                        throw new JavaScriptException(ErrorType.TypeError, $"'defineProperty' on proxy: trap returned truish for defining non-configurable property '{TypeConverter.ToString(key)}' which cannot be non-writable, unless there exists a corresponding non-configurable, non-writable own property of the target object.");
                    }
                }
            }
            else
            {
                if (!target.IsExtensible)
                {
                    throw new JavaScriptException(ErrorType.TypeError, $"'defineProperty' on proxy: trap returned truish for adding property '{TypeConverter.ToString(key)}' to the non-extensible proxy target.");
                }
                if (descriptor.Exists && !descriptor.IsConfigurable)
                {
                    throw new JavaScriptException(ErrorType.TypeError, $"'defineProperty' on proxy: trap returned truish for defining non-configurable property '{TypeConverter.ToString(key)}' which is either non-existent or configurable in the proxy target.");
                }
            }
            return(true);
        }
示例#2
0
        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);
        }
示例#3
0
        public static bool DefineProperty(ObjectInstance target, object propertyKey, object attributes)
        {
            propertyKey = TypeConverter.ToPropertyKey(propertyKey);
            var defaults = target.GetOwnPropertyDescriptor(propertyKey);

            if (!(attributes is ObjectInstance))
            {
                throw new JavaScriptException(ErrorType.TypeError, $"Invalid property descriptor '{attributes}'.");
            }
            var descriptor = PropertyDescriptor.FromObject((ObjectInstance)attributes, defaults);

            return(target.DefineProperty(propertyKey, descriptor, throwOnError: false));
        }
        public static ObjectInstance DefineProperty(ObjectInstance obj, object key, object attributes)
        {
            key = TypeConverter.ToPropertyKey(key);
            var defaults = obj.GetOwnPropertyDescriptor(key);

            if (!(attributes is ObjectInstance))
            {
                throw new JavaScriptException(obj.Engine, ErrorType.TypeError, "Invalid descriptor for property '{propertyName}'.");
            }
            var descriptor = PropertyDescriptor.FromObject((ObjectInstance)attributes, defaults);

            obj.DefineProperty(key, descriptor, true);
            return(obj);
        }
示例#5
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) == true)
                    {
                        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, overwriteAttributes: true);
            }
        }
示例#6
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) == true)
                            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, overwriteAttributes: true);
            }
        }
示例#7
0
 public static ObjectInstance DefineProperty(ObjectInstance obj, object key, object attributes)
 {
     key = TypeConverter.ToPropertyKey(key);
     var defaults = obj.GetOwnPropertyDescriptor(key);
     if (!(attributes is ObjectInstance))
         throw new JavaScriptException(obj.Engine, ErrorType.TypeError, "Invalid descriptor for property '{propertyName}'.");
     var descriptor = PropertyDescriptor.FromObject((ObjectInstance)attributes, defaults);
     obj.DefineProperty(key, descriptor, true);
     return obj;
 }
示例#8
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);
 }
示例#9
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);
 }