/// <summary>
        /// Executes the script.
        /// </summary>
        /// <param name="engine"> The script engine to use to execute the script. </param>
        /// <param name="parentScope"> The scope of the calling code. </param>
        /// <param name="thisObject"> The value of the "this" keyword in the calling code. </param>
        /// <returns> The result of evaluating the script. </returns>
        public object Execute(ScriptEngine engine, RuntimeScope parentScope, object thisObject)
        {
            if (engine == null)
            {
                throw new ArgumentNullException("engine");
            }

            // Compile the code if it hasn't already been compiled.
            if (this.GeneratedMethod == null)
            {
                GenerateCode();
            }

            // Package up all the runtime state.
            var context = ExecutionContext.CreateGlobalOrEvalContext(engine, parentScope, thisObject);

            // Execute the compiled delegate and store the result.
            object result = ((GlobalCodeDelegate)this.GeneratedMethod.GeneratedDelegate)(context);

            if (result == null)
            {
                result = Undefined.Value;
            }

            // Ensure the abstract syntax tree is kept alive until the eval code finishes running.
            GC.KeepAlive(this);

            // Return the result.
            return(result);
        }
예제 #2
0
 /// <summary>
 /// Creates an execution context for code running as a result of a function call.
 /// </summary>
 /// <param name="engine"> A script engine. </param>
 /// <param name="parentScope"> The scope that was active when the function was declared
 /// (NOT when it was called). </param>
 /// <param name="thisValue"> The value of the 'this' keyword. </param>
 /// <param name="executingFunction"> The function that is being called. </param>
 /// <returns> A new execution context instance. </returns>
 internal static ExecutionContext CreateFunctionContext(ScriptEngine engine, RuntimeScope parentScope, object thisValue, UserDefinedFunction executingFunction)
 {
     if (thisValue == null)
     {
         throw new ArgumentNullException(nameof(thisValue));
     }
     if (executingFunction == null)
     {
         throw new ArgumentNullException(nameof(executingFunction));
     }
     return(new ExecutionContext(engine, parentScope, BindingStatus.Initialized, thisValue, executingFunction, null, executingFunction.Container));
 }
예제 #3
0
 private ExecutionContext(ScriptEngine engine, RuntimeScope parentScope,
                          BindingStatus thisBindingStatus, object thisValue,
                          UserDefinedFunction executingFunction, FunctionInstance newTarget,
                          ObjectInstance functionContainer)
 {
     this.Engine            = engine ?? throw new ArgumentNullException(nameof(engine));
     this.ParentScope       = parentScope;
     this.ThisBindingStatus = thisBindingStatus;
     this.thisValue         = thisValue;
     this.ExecutingFunction = executingFunction;
     this.NewTarget         = newTarget;
     this.FunctionContainer = functionContainer;
 }
예제 #4
0
        //     CODE-GEN METHODS
        //_________________________________________________________________________________________

        /// <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>
        public static UserDefinedFunction CreateFunction(ObjectInstance prototype, string name, IList <string> argumentNames,
                                                         RuntimeScope parentScope, string bodyText, GeneratedMethod generatedMethod, bool strictMode, ObjectInstance container)
        {
            return(new UserDefinedFunction(prototype, name, argumentNames, parentScope, bodyText, generatedMethod, strictMode, container));
        }
예제 #5
0
 /// <summary>
 /// Creates an execution context for code running as a result of the new operator. The
 /// 'this' value is unavailable.
 /// </summary>
 /// <param name="engine"> A script engine. </param>
 /// <param name="parentScope"> The scope that was active when the class was declared. </param>
 /// <param name="executingFunction"> A reference to the function that is being executed. </param>
 /// <param name="newTarget"> The target of the new operator. </param>
 /// <param name="functionContainer"> A reference to the object literal or class prototype
 /// the executing function was defined within. Used by the 'super' keyword. </param>
 /// <returns> A new execution context instance. </returns>
 internal static ExecutionContext CreateDerivedContext(ScriptEngine engine, RuntimeScope parentScope, UserDefinedFunction executingFunction, FunctionInstance newTarget, ObjectInstance functionContainer)
 {
     return(new ExecutionContext(engine, parentScope, BindingStatus.Uninitialized, null, executingFunction, newTarget, functionContainer));
 }
예제 #6
0
 /// <summary>
 /// Creates an execution context for code running as a result of the new operator.
 /// </summary>
 /// <param name="engine"> A script engine. </param>
 /// <param name="parentScope"> The scope that was active when the class was declared. </param>
 /// <param name="thisValue"> The value of the 'this' keyword. </param>
 /// <param name="executingFunction"> A reference to the function that is being executed. </param>
 /// <param name="newTarget"> The target of the new operator. </param>
 /// <param name="functionContainer"> A reference to the object literal or class prototype
 /// the executing function was defined within. Used by the 'super' keyword. </param>
 /// <returns> A new execution context instance. </returns>
 internal static ExecutionContext CreateConstructContext(ScriptEngine engine, RuntimeScope parentScope, object thisValue, UserDefinedFunction executingFunction, FunctionInstance newTarget, ObjectInstance functionContainer)
 {
     return(new ExecutionContext(engine, parentScope, BindingStatus.Initialized, thisValue, executingFunction, newTarget, functionContainer));
 }
예제 #7
0
 /// <summary>
 /// Creates a new RuntimeScope instance, which is used for passing captured variables
 /// between methods.
 /// </summary>
 /// <param name="parent"> The parent scope, or <c>null</c> to use the ParentScope from this
 /// execution context. </param>
 /// <param name="scopeType"></param>
 /// <param name="varNames"></param>
 /// <param name="letNames"></param>
 /// <param name="constNames"></param>
 /// <returns> A new RuntimeScope instance. </returns>
 public RuntimeScope CreateRuntimeScope(RuntimeScope parent, ScopeType scopeType, string[] varNames, string[] letNames, string[] constNames)
 {
     return(new RuntimeScope(Engine, parent ?? ParentScope, scopeType, varNames, letNames, constNames));
 }
예제 #8
0
 /// <summary>
 /// Creates a new instance of the 'arguments' object.
 /// </summary>
 /// <param name="functionScope"> The top-level scope for the function. </param>
 /// <param name="arguments"> The argument values that were passed to the function. </param>
 /// <returns> A new instance of the 'arguments' object. </returns>
 public ArgumentsInstance CreateArgumentsInstance(RuntimeScope functionScope, object[] arguments)
 {
     return(new ArgumentsInstance(Engine.Object.InstancePrototype, ExecutingFunction, functionScope, arguments));
 }
예제 #9
0
 /// <summary>
 /// Creates an execution context for code running in an eval() scope.
 /// </summary>
 /// <param name="engine"> A script engine. </param>
 /// <param name="parentScope"> The scope that was active when eval() was called. </param>
 /// <param name="thisValue"> The value of the 'this' keyword. </param>
 /// <returns> A new execution context instance. </returns>
 internal static ExecutionContext CreateGlobalOrEvalContext(ScriptEngine engine, RuntimeScope parentScope, object thisValue)
 {
     if (thisValue == null)
     {
         throw new ArgumentNullException(nameof(thisValue));
     }
     return(new ExecutionContext(engine, parentScope, BindingStatus.Initialized, thisValue, null, null, null));
 }
예제 #10
0
 /// <summary>
 /// Creates a new RuntimeScope instance.
 /// </summary>
 /// <param name="engine"> The script engine this scope is associated with. </param>
 /// <param name="parent"> The parent scope, or <c>null</c> if this is the root scope. </param>
 /// <param name="scopeType"></param>
 /// <param name="varNames"></param>
 /// <param name="letNames"></param>
 /// <param name="constNames"></param>
 internal RuntimeScope(ScriptEngine engine, RuntimeScope parent, ScopeType scopeType,
                       string[] varNames, string[] letNames, string[] constNames)
 {
     this.Engine    = engine ?? throw new ArgumentNullException(nameof(engine));
     this.Parent    = parent;
     this.ScopeType = scopeType;
     if (varNames != null && scopeType != ScopeType.TopLevelFunction && scopeType != ScopeType.EvalStrict)
     {
         var scope = this;
         while (scope != null && scope.ScopeObject == null &&
                scope.ScopeType != ScopeType.TopLevelFunction && scopeType != ScopeType.EvalStrict)
         {
             scope = scope.Parent;
         }
         if (scope != null)
         {
             if (scope.ScopeType == ScopeType.TopLevelFunction || scopeType == ScopeType.EvalStrict)
             {
                 foreach (var name in varNames)
                 {
                     if (!scope.values.ContainsKey(name))
                     {
                         scope.values[name] = new LocalValue {
                             Value = Undefined.Value, Flags = LocalFlags.Deletable
                         }
                     }
                 }
                 ;
             }
             else
             {
                 var attributes = scopeType == ScopeType.Eval ? PropertyAttributes.FullAccess : PropertyAttributes.Enumerable | PropertyAttributes.Writable;
                 foreach (var name in varNames)
                 {
                     scope.ScopeObject.InitializeMissingProperty(name, attributes);
                 }
             }
         }
         varNames = null;
     }
     if (varNames != null || letNames != null || constNames != null)
     {
         values = new Dictionary <string, LocalValue>(
             (varNames != null ? varNames.Length : 0) +
             (letNames != null ? letNames.Length : 0) +
             (constNames != null ? constNames.Length : 0));
     }
     if (varNames != null)
     {
         foreach (string variableName in varNames)
         {
             values[variableName] = new LocalValue {
                 Value = Undefined.Value
             }
         }
         ;
     }
     if (letNames != null)
     {
         foreach (string variableName in letNames)
         {
             values[variableName] = new LocalValue();
         }
     }
     if (constNames != null)
     {
         foreach (string variableName in constNames)
         {
             values[variableName] = new LocalValue {
                 Flags = LocalFlags.ReadOnly
             }
         }
         ;
     }
 }