/// <summary>
 /// Creates a new instance of a user-defined function.
 /// </summary>
 /// <param name="prototype"> The next object in the prototype chain. </param>
 /// <param name="name"> The name of the function. </param>
 /// <param name="argumentNames"> The names of the arguments. </param>
 /// <param name="parentScope"> The scope at the point the function is declared. </param>
 /// <param name="bodyText"> The source code for the function body. </param>
 /// <param name="body"> A delegate which represents the body of the function. </param>
 /// <param name="strictMode"> <c>true</c> if the function body is strict mode; <c>false</c> otherwise. </param>
 /// <remarks> This is used by <c>arguments</c>. </remarks>
 internal UserDefinedFunction(ObjectInstance prototype, string name, IList <string> argumentNames, RuntimeScope parentScope, string bodyText, FunctionMethodGenerator.FunctionDelegate body, bool strictMode)
     : base(prototype)
 {
     this.ArgumentsText   = string.Join(", ", argumentNames);
     this.ArgumentNames   = argumentNames;
     this.BodyText        = bodyText;
     this.generatedMethod = new GeneratedMethod(body, null);
     this.body            = body;
     this.ParentScope     = parentScope;
     this.StrictMode      = strictMode;
     InitProperties(name, argumentNames.Count);
 }
 /// <summary>
 /// Creates a new instance of a user-defined function.
 /// </summary>
 /// <param name="prototype"> The next object in the prototype chain. </param>
 /// <param name="name"> The name of the function. </param>
 /// <param name="argumentNames"> The names of the arguments. </param>
 /// <param name="parentScope"> The scope at the point the function is declared. </param>
 /// <param name="bodyText"> The source code for the function body. </param>
 /// <param name="generatedMethod"> A delegate which represents the body of the function plus any dependencies. </param>
 /// <param name="strictMode"> <c>true</c> if the function body is strict mode; <c>false</c> otherwise. </param>
 /// <param name="container"> A reference to the containing class prototype or object literal (or <c>null</c>). </param>
 /// <remarks> This is used by functions declared in JavaScript code (including getters and setters). </remarks>
 internal UserDefinedFunction(ObjectInstance prototype, string name, IList <string> argumentNames, RuntimeScope parentScope, string bodyText, GeneratedMethod generatedMethod, bool strictMode, ObjectInstance container)
     : base(prototype)
 {
     this.ArgumentsText   = string.Join(", ", argumentNames);
     this.ArgumentNames   = argumentNames;
     this.BodyText        = bodyText;
     this.generatedMethod = generatedMethod;
     this.body            = (FunctionMethodGenerator.FunctionDelegate) this.generatedMethod.GeneratedDelegate;
     this.ParentScope     = parentScope;
     this.StrictMode      = strictMode;
     this.Container       = container;
     InitProperties(name, argumentNames.Count);
 }
        //     INITIALIZATION
        //_________________________________________________________________________________________

        /// <summary>
        /// Creates a new instance of a user-defined function.
        /// </summary>
        /// <param name="prototype"> The next object in the prototype chain. </param>
        /// <param name="name"> The name of the function. </param>
        /// <param name="argumentsText"> A comma-separated list of arguments. </param>
        /// <param name="bodyText"> The source code for the body of the function. </param>
        /// <remarks> This is used by <c>new Function()</c>. </remarks>
        internal UserDefinedFunction(ObjectInstance prototype, string name, string argumentsText, string bodyText)
            : base(prototype)
        {
            if (name == null)
            {
                throw new ArgumentNullException(nameof(name));
            }
            if (argumentsText == null)
            {
                throw new ArgumentNullException(nameof(argumentsText));
            }
            if (bodyText == null)
            {
                throw new ArgumentNullException(nameof(bodyText));
            }

            // Set up a new function scope.
            this.ParentScope = RuntimeScope.CreateGlobalScope(Engine);

            // Compile the code.
            var context = new FunctionMethodGenerator(name, argumentsText, bodyText, new CompilerOptions()
            {
                ForceStrictMode   = this.Engine.ForceStrictMode,
                EnableILAnalysis  = this.Engine.EnableILAnalysis,
                CompatibilityMode = this.Engine.CompatibilityMode
            });

            try
            {
                context.GenerateCode();
            }
            catch (SyntaxErrorException ex)
            {
                throw new JavaScriptException(ErrorType.SyntaxError, ex.Message, ex.LineNumber, ex.SourcePath);
            }

            this.ArgumentsText   = argumentsText;
            this.ArgumentNames   = context.Arguments.Select(a => a.Name).ToList();
            this.BodyText        = bodyText;
            this.generatedMethod = context.GeneratedMethod;
            this.body            = (FunctionMethodGenerator.FunctionDelegate) this.generatedMethod.GeneratedDelegate;
            this.StrictMode      = context.StrictMode;
            InitProperties(name, context.Arguments.Count);
        }