//     INITIALIZATION
        //_________________________________________________________________________________________

        /// <summary>
        /// Creates a new instance of a built-in constructor function.
        /// </summary>
        /// <param name="prototype"> The next object in the prototype chain. </param>
        /// <param name="name"> The name of the function. </param>
        /// <param name="instancePrototype">  </param>
        protected ClrFunction(ObjectInstance prototype, string name, ObjectInstance instancePrototype)
            : base(prototype)
        {
            if (name == null)
                throw new ArgumentNullException("name");
            if (instancePrototype == null)
                throw new ArgumentNullException("instancePrototype");

            // This is a constructor so ignore the "this" parameter when the function is called.
            thisBinding = this;

            // Search through every method in this type looking for [JSCallFunction] and [JSConstructorFunction] attributes.
            var callBinderMethods = new List<JSBinderMethod>(1);
            var constructBinderMethods = new List<JSBinderMethod>(1);
            var methods = this.GetType().GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly);
            foreach (var method in methods)
            {
                // Search for the [JSCallFunction] and [JSConstructorFunction] attributes.
                var callAttribute = (JSCallFunctionAttribute) Attribute.GetCustomAttribute(method, typeof(JSCallFunctionAttribute));
                var constructorAttribute = (JSConstructorFunctionAttribute)Attribute.GetCustomAttribute(method, typeof(JSConstructorFunctionAttribute));

                // Can't declare both attributes.
                if (callAttribute != null && constructorAttribute != null)
                    throw new InvalidOperationException("Methods cannot be marked with both [JSCallFunction] and [JSConstructorFunction].");

                if (callAttribute != null)
                {
                    // Method is marked with [JSCallFunction]
                    callBinderMethods.Add(new JSBinderMethod(method, callAttribute.Flags));
                }
                else if (constructorAttribute != null)
                {
                    var binderMethod = new JSBinderMethod(method, constructorAttribute.Flags);
                    constructBinderMethods.Add(binderMethod);
                    
                    // Constructors must return ObjectInstance or a derived type.
                    if (typeof(ObjectInstance).IsAssignableFrom(binderMethod.ReturnType) == false)
                        throw new InvalidOperationException(string.Format("Constructors must return {0} (or a derived type).", typeof(ObjectInstance).Name));
                }
            }

            // Initialize the Call function.
            if (callBinderMethods.Count > 0)
                this.callBinder = new JSBinder(callBinderMethods);
            else
                this.callBinder = new JSBinder(new JSBinderMethod(new Func<object>(() => Undefined.Value).Method));

            // Initialize the Construct function.
            if (constructBinderMethods.Count > 0)
                this.constructBinder = new JSBinder(constructBinderMethods);
            else
                this.constructBinder = new JSBinder(new JSBinderMethod(new Func<ObjectInstance>(() => this.Engine.Object.Construct()).Method));

            // Add function properties.
            this.FastSetProperty("name", name);
            this.FastSetProperty("length", this.callBinder.FunctionLength);
            this.FastSetProperty("prototype", instancePrototype);
            instancePrototype.FastSetProperty("constructor", this, PropertyAttributes.NonEnumerable);
        }
        /// <summary>
        /// Creates a new instance of a function which calls the given binder.
        /// </summary>
        /// <param name="prototype"> The next object in the prototype chain. </param>
        /// <param name="binder"> An object representing a collection of methods to bind to. </param>
        internal ClrFunction(ObjectInstance prototype, Binder binder)
            : base(prototype)
        {
            m_callBinder = binder;

            // Add function properties.
            FastSetProperty("name", binder.Name, PropertyAttributes.Sealed, false);
            FastSetProperty("length", binder.FunctionLength, PropertyAttributes.Sealed, false);
            //this.FastSetProperty("prototype", this.Engine.Object.Construct());
            //this.InstancePrototype.FastSetProperty("constructor", this, PropertyAttributes.NonEnumerable);
        }
        /// <summary>
        /// Creates a new instance of a function which calls one or more provided methods.
        /// </summary>
        /// <param name="prototype"> The next object in the prototype chain. </param>
        /// <param name="methods"> An enumerable collection of methods that logically comprise a
        /// single method group. </param>
        /// <param name="name"> The name of the function.  Pass <c>null</c> to use the name of the
        /// provided methods for the function name (in this case all the provided methods must have
        /// the same name). </param>
        /// <param name="length"> The "typical" number of arguments expected by the function.  Pass
        /// <c>-1</c> to use the maximum of arguments expected by any of the provided methods. </param>
        internal ClrFunction(ObjectInstance prototype, IEnumerable <JSBinderMethod> methods, string name, int length)
            : base(prototype)
        {
            m_callBinder = new JSBinder(methods);

            // Add function properties.
            FastSetProperty("name", name ?? m_callBinder.Name, PropertyAttributes.Sealed, false);
            FastSetProperty("length", length >= 0 ? length : m_callBinder.FunctionLength, PropertyAttributes.Sealed, false);
            //this.FastSetProperty("prototype", this.Engine.Object.Construct());
            //this.InstancePrototype.FastSetProperty("constructor", this, PropertyAttributes.NonEnumerable);
        }
Exemple #4
0
        /// <summary>
        /// Creates a new instance of a function which calls the given binder.
        /// </summary>
        /// <param name="prototype"> The next object in the prototype chain. </param>
        /// <param name="binder"> An object representing a collection of methods to bind to. </param>
        internal ClrFunction(ObjectInstance prototype, Binder binder)
            : base(prototype)
        {
            this.callBinder = binder;

            // Add function properties.
            this.FastSetProperty("name", binder.Name);
            this.FastSetProperty("length", binder.FunctionLength);
            //this.FastSetProperty("prototype", this.Engine.Object.Construct());
            //this.InstancePrototype.FastSetProperty("constructor", this, PropertyAttributes.NonEnumerable);
        }
Exemple #5
0
        /// <summary>
        /// Creates a new instance of a function which calls one or more provided methods.
        /// </summary>
        /// <param name="prototype"> The next object in the prototype chain. </param>
        /// <param name="methods"> An enumerable collection of methods that logically comprise a
        /// single method group. </param>
        /// <param name="name"> The name of the function.  Pass <c>null</c> to use the name of the
        /// provided methods for the function name (in this case all the provided methods must have
        /// the same name). </param>
        /// <param name="length"> The "typical" number of arguments expected by the function.  Pass
        /// <c>-1</c> to use the maximum of arguments expected by any of the provided methods. </param>
        internal ClrFunction(ObjectInstance prototype, IEnumerable<JSBinderMethod> methods, string name = null, int length = -1)
            : base(prototype)
        {
            this.callBinder = new JSBinder(methods);

            // Add function properties.
            this.FastSetProperty("name", name == null ? this.callBinder.Name : name);
            this.FastSetProperty("length", length >= 0 ? length : this.callBinder.FunctionLength);
            //this.FastSetProperty("prototype", this.Engine.Object.Construct());
            //this.InstancePrototype.FastSetProperty("constructor", this, PropertyAttributes.NonEnumerable);
        }
Exemple #6
0
        /// <summary>
        /// Creates a new instance of a function which calls one or more provided methods.
        /// </summary>
        /// <param name="prototype"> The next object in the prototype chain. </param>
        /// <param name="methods"> An enumerable collection of methods that logically comprise a
        /// single method group. </param>
        /// <param name="name"> The name of the function.  Pass <c>null</c> to use the name of the
        /// provided methods for the function name (in this case all the provided methods must have
        /// the same name). </param>
        /// <param name="length"> The "typical" number of arguments expected by the function.  Pass
        /// <c>-1</c> to use the maximum of arguments expected by any of the provided methods. </param>
        internal ClrFunction(ObjectInstance prototype, IEnumerable <JSBinderMethod> methods, string name = null, int length = -1)
            : base(prototype)
        {
            this.callBinder = new JSBinder(methods);

            // Add function properties.
            this.FastSetProperty("name", name == null ? this.callBinder.Name : name);
            this.FastSetProperty("length", length >= 0 ? length : this.callBinder.FunctionLength);
            //this.FastSetProperty("prototype", this.Engine.Object.Construct());
            //this.InstancePrototype.FastSetProperty("constructor", this, PropertyAttributes.NonEnumerable);
        }
        /// <summary>
        /// Creates a new instance of a function which calls the given delegate.
        /// </summary>
        /// <param name="prototype"> The next object in the prototype chain. </param>
        /// <param name="delegateToCall"> The delegate to call. </param>
        /// <param name="name"> The name of the function.  Pass <c>null</c> to use the name of the
        /// delegate for the function name. </param>
        /// <param name="length"> The "typical" number of arguments expected by the function.  Pass
        /// <c>-1</c> to use the number of arguments expected by the delegate. </param>
        internal ClrFunction(ObjectInstance prototype, Delegate delegateToCall, string name, int length)
            : base(prototype)
        {
            // Initialize the [[Call]] method.
            m_callBinder = new JSBinder(new JSBinderMethod(delegateToCall.Method, JSFunctionFlags.None));

            // If the delegate has a class instance, use that to call the method.
            m_thisBinding = delegateToCall.Target;

            // Add function properties.
            FastSetProperty("name", name ?? m_callBinder.Name, PropertyAttributes.Sealed, false);
            FastSetProperty("length", length >= 0 ? length : m_callBinder.FunctionLength, PropertyAttributes.Sealed, false);
            //this.FastSetProperty("prototype", this.Engine.Object.Construct());
            //this.InstancePrototype.FastSetProperty("constructor", this, PropertyAttributes.NonEnumerable);
        }
Exemple #8
0
        /// <summary>
        /// Creates a new instance of a function which calls the given delegate.
        /// </summary>
        /// <param name="prototype"> The next object in the prototype chain. </param>
        /// <param name="delegateToCall"> The delegate to call. </param>
        /// <param name="name"> The name of the function.  Pass <c>null</c> to use the name of the
        /// delegate for the function name. </param>
        /// <param name="length"> The "typical" number of arguments expected by the function.  Pass
        /// <c>-1</c> to use the number of arguments expected by the delegate. </param>
        internal ClrFunction(ObjectInstance prototype, Delegate delegateToCall, string name = null, int length = -1)
            : base(prototype)
        {
            // Initialize the [[Call]] method.
            this.callBinder = new JSBinder(new JSBinderMethod(delegateToCall.Method));

            // If the delegate has a class instance, use that to call the method.
            this.thisBinding = delegateToCall.Target;

            // Add function properties.
            this.FastSetProperty("name", name != null ? name : this.callBinder.Name);
            this.FastSetProperty("length", length >= 0 ? length : this.callBinder.FunctionLength);
            //this.FastSetProperty("prototype", this.Engine.Object.Construct());
            //this.InstancePrototype.FastSetProperty("constructor", this, PropertyAttributes.NonEnumerable);
        }
Exemple #9
0
        /// <summary>
        /// Creates a new instance of a function which calls the given delegate.
        /// </summary>
        /// <param name="prototype"> The next object in the prototype chain. </param>
        /// <param name="delegateToCall"> The delegate to call. </param>
        /// <param name="name"> The name of the function.  Pass <c>null</c> to use the name of the
        /// delegate for the function name. </param>
        /// <param name="length"> The "typical" number of arguments expected by the function.  Pass
        /// <c>-1</c> to use the number of arguments expected by the delegate. </param>
        internal ClrFunction(ObjectInstance prototype, Delegate delegateToCall, string name = null, int length = -1)
            : base(prototype)
        {
            // Initialize the [[Call]] method.
            this.callBinder = new JSBinder(new JSBinderMethod(delegateToCall.Method));

            // If the delegate has a class instance, use that to call the method.
            this.thisBinding = delegateToCall.Target;

            // Add function properties.
            this.FastSetProperty("name", name != null ? name : this.callBinder.Name, PropertyAttributes.Configurable);
            this.FastSetProperty("length", length >= 0 ? length : this.callBinder.FunctionLength, PropertyAttributes.Configurable);
            //this.FastSetProperty("prototype", this.Engine.Object.Construct());
            //this.InstancePrototype.FastSetProperty("constructor", this, PropertyAttributes.NonEnumerable);
        }
        //     INITIALIZATION
        //_________________________________________________________________________________________

        /// <summary>
        /// Creates a new instance of a built-in constructor function.
        /// </summary>
        /// <param name="prototype"> The next object in the prototype chain. </param>
        /// <param name="name"> The name of the function. </param>
        /// <param name="instancePrototype">  </param>
        protected ClrFunction(ObjectInstance prototype, string name, ObjectInstance instancePrototype)
            : base(prototype)
        {
            if (name == null)
            {
                throw new ArgumentNullException("name");
            }
            if (instancePrototype == null)
            {
                throw new ArgumentNullException("instancePrototype");
            }

            // This is a constructor so ignore the "this" parameter when the function is called.
            m_thisBinding = this;

            // Search through every method in this type looking for [JSCallFunction] and [JSConstructorFunction] attributes.
            var callBinderMethods      = new List <JSBinderMethod>(1);
            var constructBinderMethods = new List <JSBinderMethod>(1);
            var methods = GetType().GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly);

            foreach (var method in methods)
            {
                // Search for the [JSCallFunction] and [JSConstructorFunction] attributes.
                var callAttribute        = (JSCallFunctionAttribute)Attribute.GetCustomAttribute(method, typeof(JSCallFunctionAttribute));
                var constructorAttribute = (JSConstructorFunctionAttribute)Attribute.GetCustomAttribute(method, typeof(JSConstructorFunctionAttribute));

                // Can't declare both attributes.
                if (callAttribute != null && constructorAttribute != null)
                {
                    throw new InvalidOperationException("Methods cannot be marked with both [JSCallFunction] and [JSConstructorFunction].");
                }

                if (callAttribute != null)
                {
                    // Method is marked with [JSCallFunction]
                    callBinderMethods.Add(new JSBinderMethod(method, callAttribute.Flags));
                }
                else if (constructorAttribute != null)
                {
                    var binderMethod = new JSBinderMethod(method, constructorAttribute.Flags);
                    constructBinderMethods.Add(binderMethod);

                    // Constructors must return ObjectInstance or a derived type.
                    if (typeof(ObjectInstance).IsAssignableFrom(binderMethod.ReturnType) == false)
                    {
                        throw new InvalidOperationException(string.Format("Constructors must return {0} (or a derived type).", typeof(ObjectInstance).Name));
                    }
                }
            }

            // Initialize the Call function.
            m_callBinder = callBinderMethods.Count > 0
              ? new JSBinder(callBinderMethods)
              : new JSBinder(new JSBinderMethod(new Func <object>(() => Undefined.Value).Method, JSFunctionFlags.None));

            // Initialize the Construct function.
            m_constructBinder = constructBinderMethods.Count > 0
              ? new JSBinder(constructBinderMethods)
              : new JSBinder(new JSBinderMethod(new Func <ObjectInstance>(() => Engine.Object.Construct()).Method, JSFunctionFlags.None));

            // Add function properties.
            FastSetProperty("name", name, PropertyAttributes.Sealed, false);
            FastSetProperty("length", m_callBinder.FunctionLength, PropertyAttributes.Sealed, false);
            FastSetProperty("prototype", instancePrototype, PropertyAttributes.Sealed, false);
            instancePrototype.FastSetProperty("constructor", this, PropertyAttributes.NonEnumerable, false);
        }