示例#1
0
        //     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("name");
            }
            if (argumentsText == null)
            {
                throw new ArgumentNullException("argumentsText");
            }
            if (bodyText == null)
            {
                throw new ArgumentNullException("bodyText");
            }

            // Set up a new function scope.
            var scope = DeclarativeScope.CreateFunctionScope(this.Engine.CreateGlobalScope(), name, null);

            // Compile the code.
            var context = new FunctionMethodGenerator(this.Engine, scope, name, argumentsText, bodyText, new CompilerOptions());

            context.GenerateCode();

            this.ArgumentsText   = argumentsText;
            this.ArgumentNames   = context.Arguments.Select(a => a.Name).ToList();
            this.BodyText        = bodyText;
            this.generatedMethod = context.GeneratedMethod;
            this.body            = (FunctionDelegate)this.generatedMethod.GeneratedDelegate;
            this.ParentScope     = this.Engine.CreateGlobalScope();
            this.StrictMode      = context.StrictMode;
            InitProperties(name, context.Arguments.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="args"> The names of the arguments. MUST include 'this'.</param>
        /// <param name="bodyText"> The source code for the body of the function. </param>
        internal static UserDefinedFunction Create(ScriptEngine engine, string name, List <ArgVariable> args, string bodyText)
        {
            if (args == null)
            {
                args = new List <ArgVariable>();
                args.Add(new ArgVariable("this"));
            }

            if (name == null)
            {
                throw new ArgumentNullException("name");
            }
            if (args == null)
            {
                throw new ArgumentNullException("args");
            }
            if (bodyText == null)
            {
                throw new ArgumentNullException("bodyText");
            }

            // Set up a new function scope.
            var scope = DeclarativeScope.CreateFunctionScope(engine.GlobalScope, name, args);

            // Compile the code.
            var context = new FunctionMethodGenerator(engine, scope, name, args, bodyText, new CompilerOptions());

            context.GenerateCode(new OptimizationInfo(engine));

            return(context.GeneratedMethods[0]);
        }
示例#3
0
        //     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="argumentNames"> The names of the arguments. </param>
        /// <param name="bodyText"> The source code for the body of the function. </param>
        internal UserDefinedFunction(ObjectInstance prototype, string name, IList <string> argumentNames, string bodyText)
            : base(prototype)
        {
            if (name == null)
            {
                throw new ArgumentNullException("name");
            }
            if (argumentNames == null)
            {
                throw new ArgumentNullException("argumentNames");
            }
            if (bodyText == null)
            {
                throw new ArgumentNullException("bodyText");
            }

            // Set up a new function scope.
            var scope = DeclarativeScope.CreateFunctionScope(this.Engine.CreateGlobalScope(), name, argumentNames);

            // Compile the code.
            var context = new FunctionMethodGenerator(this.Engine, scope, name, argumentNames, bodyText, new CompilerOptions());

            context.GenerateCode();

            // Create a new user defined function.
            Init(name, argumentNames, this.Engine.CreateGlobalScope(), bodyText, context.GeneratedMethod, context.StrictMode, true);
        }
示例#4
0
        public object InstallBundle(Jurassic.ScriptEngine engine)
        {
            var baristaInstance = engine.GetGlobalValue("barista") as BaristaGlobal;

            if (baristaInstance == null)
            {
                throw new InvalidOperationException("Barista Global bundle could not be obtained.");
            }

            var dependencyResultObj = engine.Object.Construct();

            //Require all dependencies..
            foreach (var dependency in m_dependencies)
            {
                var result = baristaInstance.Common.Require(dependency.Key, null);
                dependencyResultObj.SetPropertyValue(dependency.Value, result, false);
            }

            //If it's a function dependency, execute that.
            if (this.ScriptFunction != null)
            {
                var args = new List <object>();
                if (this.ScriptFunction is UserDefinedFunction)
                {
                    var udf = this.ScriptFunction as UserDefinedFunction;

                    args.AddRange(udf.ArgumentNames.Select(argumentName => dependencyResultObj.HasProperty(argumentName) ? dependencyResultObj.GetPropertyValue(argumentName) : Null.Value));
                }

                return(this.ScriptFunction.Call(engine.Global, args.ToArray()));
            }

            //Use the implemented "include" function to include the scripts.
            //this promotes loose coupling between the script bundle and the include.
            var variableNames = dependencyResultObj.Properties.Select(pn => pn.Name).ToArray();
            var resultArray   = engine.Array.Construct();

            foreach (var scriptReference in m_scriptReferences)
            {
                //Create a new scope, and eval the script within the new scope.
                var scope = DeclarativeScope.CreateRuntimeScope(engine.CreateGlobalScope(), variableNames);
                foreach (var property in dependencyResultObj.Properties)
                {
                    if (property.Value == Undefined.Value || property.Value == Null.Value || property.Value == null)
                    {
                        continue;
                    }

                    scope.SetValue(property.Name, property.Value);
                }

                var result = baristaInstance.Include(scriptReference, scope, engine.Global, engine.ForceStrictMode);

                ArrayInstance.Push(resultArray, result);
            }

            return(resultArray.Length == 1
        ? resultArray[0]
        : resultArray);
        }
示例#5
0
 /// <summary>
 /// Compiles the function (if it hasn't already been compiled) and returns a delegate
 /// representing the compiled function.
 /// </summary>
 private FunctionDelegate Compile()
 {
     if (this.m_body == null)
     {
         // Compile the function.
         var scope             = DeclarativeScope.CreateFunctionScope(this.Engine.CreateGlobalScope(), this.Name, this.ArgumentNames);
         var functionGenerator = new FunctionMethodGenerator(this.Engine, scope, this.Name, this.ArgumentNames, this.BodyText, new CompilerOptions());
         functionGenerator.GenerateCode();
         this.m_generatedMethod = functionGenerator.GeneratedMethod;
         this.m_body            = (FunctionDelegate)this.m_generatedMethod.GeneratedDelegate;
     }
     return(this.m_body);
 }
示例#6
0
        //     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.Scope = DeclarativeScope.CreateFunctionScope(ObjectScope.CreateGlobalScope(this.Engine.Global), name, null);

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

            try
            {
                context.GenerateCode();
            }
            catch (SyntaxErrorException ex)
            {
                throw new JavaScriptException(this.Engine, 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            = (FunctionDelegate)this.generatedMethod.GeneratedDelegate;
            this.ParentScope     = ObjectScope.CreateGlobalScope(this.Engine.Global);
            this.StrictMode      = context.StrictMode;
            InitProperties(name, context.Arguments.Count);
        }
        //     INITIALIZATION
        //_________________________________________________________________________________________

        /// <summary>
        /// Creates a new Arguments instance.
        /// </summary>
        /// <param name="prototype"> The next object in the prototype chain. </param>
        /// <param name="callee"> The function that was called. </param>
        /// <param name="scope"> The function scope. </param>
        /// <param name="argumentValues"> The argument values that were passed to the function. </param>
        public ArgumentsInstance(ObjectInstance prototype, UserDefinedFunction callee, DeclarativeScope scope, object[] argumentValues)
            : base(prototype)
        {
            if (callee == null)
            {
                throw new ArgumentNullException("callee");
            }
            if (scope == null)
            {
                throw new ArgumentNullException("scope");
            }
            if (argumentValues == null)
            {
                throw new ArgumentNullException("argumentValues");
            }
            this.m_callee = callee;
            this.m_scope  = scope;
            this.FastSetProperty("length", argumentValues.Length, PropertyAttributes.NonEnumerable, false);

            if (this.m_callee.StrictMode == false)
            {
                this.FastSetProperty("callee", callee, PropertyAttributes.NonEnumerable, false);


                // Create an array mappedArguments where mappedArguments[i] = true means a mapping is
                // maintained between arguments[i] and the corresponding variable.
                this.m_mappedArguments = new bool[argumentValues.Length];
                var mappedNames = new Dictionary <string, int>(); // maps argument name -> index
                for (int i = 0; i < argumentValues.Length; i++)
                {
                    if (i < callee.ArgumentNames.Count)
                    {
                        // Check if the argument name appeared previously in the argument list.
                        int previousIndex;
                        if (mappedNames.TryGetValue(callee.ArgumentNames[i], out previousIndex))
                        {
                            // The argument name has appeared before.  Remove the getter/setter.
                            this.DefineProperty(previousIndex.ToString(), new PropertyDescriptor(argumentValues[previousIndex], PropertyAttributes.FullAccess), false);

                            // The argument is no longer mapped.
                            this.m_mappedArguments[previousIndex] = false;
                        }

                        // Add the argument name and index to the hashtable.
                        mappedNames[callee.ArgumentNames[i]] = i;

                        // The argument is mapped by default.
                        this.m_mappedArguments[i] = true;

                        // Define a getter and setter so that the property value reflects that of the argument.
                        var getter = new UserDefinedFunction(this.Engine.Function.InstancePrototype, "ArgumentGetter", new string[0], this.m_scope, "return " + callee.ArgumentNames[i], ArgumentGetter, true);
                        getter.SetPropertyValue("argumentIndex", i, false);
                        var setter = new UserDefinedFunction(this.Engine.Function.InstancePrototype, "ArgumentSetter", new[] { "value" }, this.m_scope, callee.ArgumentNames[i] + " = value", ArgumentSetter, true);
                        setter.SetPropertyValue("argumentIndex", i, false);
                        this.DefineProperty(i.ToString(), new PropertyDescriptor(getter, setter, PropertyAttributes.FullAccess), false);
                    }
                    else
                    {
                        // This argument is unnamed - no mapping needs to happen.
                        this[(uint)i] = argumentValues[i];
                    }
                }
            }
            else
            {
                // In strict mode, arguments items are not connected to the variables.
                for (int i = 0; i < argumentValues.Length; i++)
                {
                    this[(uint)i] = argumentValues[i];
                }

                // In strict mode, accessing caller or callee is illegal.
                var throwErrorFunction = new ThrowTypeErrorFunction(this.Engine.Function.InstancePrototype);
                this.DefineProperty("caller", new PropertyDescriptor(throwErrorFunction, throwErrorFunction, PropertyAttributes.Sealed), false);
                this.DefineProperty("callee", new PropertyDescriptor(throwErrorFunction, throwErrorFunction, PropertyAttributes.Sealed), false);
            }
        }