/// <summary> /// Creates a new FunctionContext instance. /// </summary> /// <param name="engine"> The script engine. </param> /// <param name="scope"> The function scope. </param> /// <param name="functionName"> The name of the function. </param> /// <param name="argumentNames"> The names of the arguments. </param> /// <param name="body"> The source code for the body of the function. </param> /// <param name="options"> Options that influence the compiler. </param> public FunctionMethodGenerator(ScriptEngine engine, DeclarativeScope scope, string functionName, IList<string> argumentNames, string body, CompilerOptions options) : base(engine, scope, new StringScriptSource(body), options) { this.Name = functionName; this.ArgumentNames = argumentNames; this.BodyText = body; }
/// <summary> /// Creates a new FunctionMethodGenerator instance. /// </summary> /// <param name="engine"> The script engine. </param> /// <param name="scope"> The function scope. </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 of the function. </param> /// <param name="body"> The root of the abstract syntax tree for the body of the function. </param> /// <param name="scriptPath"> The URL or file system path that the script was sourced from. </param> /// <param name="options"> Options that influence the compiler. </param> public FunctionMethodGenerator(ScriptEngine engine, DeclarativeScope scope, string functionName, IList<string> argumentNames, string bodyText, Statement body, string scriptPath, CompilerOptions options) : base(engine, scope, new DummyScriptSource(scriptPath), options) { this.Name = functionName; this.ArgumentNames = argumentNames; this.BodyRoot = body; this.BodyText = bodyText; Validate(); }
/// <summary> /// Creates a new MethodGenerator instance. /// </summary> /// <param name="engine"> The script engine. </param> /// <param name="scope"> The initial scope. </param> /// <param name="source"> The source of javascript code. </param> /// <param name="options"> Options that influence the compiler. </param> protected MethodGenerator(ScriptEngine engine, Scope scope, ScriptSource source, CompilerOptions options) { if (engine == null) throw new ArgumentNullException("engine"); if (scope == null) throw new ArgumentNullException("scope"); if (source == null) throw new ArgumentNullException("source"); if (options == null) throw new ArgumentNullException("options"); this.Engine = engine; this.InitialScope = scope; this.Source = source; this.Options = options; this.StrictMode = this.Options.ForceStrictMode; }
// INITIALIZATION //_________________________________________________________________________________________ /// <summary> /// Creates a Parser instance with the given lexer supplying the tokens. /// </summary> /// <param name="engine"> The associated script engine. </param> /// <param name="lexer"> The lexical analyser that provides the tokens. </param> /// <param name="initialScope"> The initial variable scope. </param> /// <param name="options"> Options that influence the compiler. </param> /// <param name="context"> The context of the code (global, function or eval). </param> public Parser(ScriptEngine engine, Lexer lexer, Scope initialScope, CompilerOptions options, CodeContext context) { if (engine == null) throw new ArgumentNullException("engine"); if (lexer == null) throw new ArgumentNullException("lexer"); if (initialScope == null) throw new ArgumentNullException("initialScope"); this.engine = engine; this.lexer = lexer; this.lexer.ParserExpressionState = ParserExpressionState.Literal; this.currentScope = this.initialScope = initialScope; this.methodOptimizationHints = new MethodOptimizationHints(); this.options = options; this.context = context; this.StrictMode = options.ForceStrictMode; this.Consume(); }
// EVAL SUPPORT //_________________________________________________________________________________________ //private class EvalCacheKey //{ // public string Code; // public Compiler.Scope Scope; // public bool StrictMode; // public override int GetHashCode() // { // int bitValue = 1; // int hashCode = this.Code.GetHashCode(); // var scope = this.Scope; // do // { // if (scope is Compiler.DeclarativeScope) // hashCode ^= bitValue; // scope = scope.ParentScope; // bitValue *= 2; // } while (scope != null); // if (this.StrictMode == true) // hashCode ^= bitValue; // return hashCode; // } // public override bool Equals(object obj) // { // if ((obj is EvalCacheKey) == false) // return false; // var other = (EvalCacheKey) obj; // if (this.Code != other.Code || // this.StrictMode != other.StrictMode) // return false; // var scope1 = this.Scope; // var scope2 = other.Scope; // do // { // if (scope1.GetType() != scope2.GetType()) // return false; // scope1 = scope1.ParentScope; // scope2 = scope2.ParentScope; // if (scope1 == null && scope2 != null) // return false; // if (scope1 != null && scope2 == null) // return false; // } while (scope1 != null); // return true; // } //} //private Dictionary<EvalCacheKey, WeakReference> evalCache = // new Dictionary<EvalCacheKey, WeakReference>(); /// <summary> /// Evaluates the given javascript source code and returns the result. /// </summary> /// <param name="code"> The source code to evaluate. </param> /// <param name="scope"> The containing scope. </param> /// <param name="thisObject"> The value of the "this" keyword in the containing scope. </param> /// <param name="strictMode"> Indicates whether the eval statement is being called from /// strict mode code. </param> /// <returns> The value of the last statement that was executed, or <c>undefined</c> if /// there were no executed statements. </returns> internal object Eval(string code, Compiler.Scope scope, object thisObject, bool strictMode) { // Check if the cache contains the eval already. //var key = new EvalCacheKey() { Code = code, Scope = scope, StrictMode = strictMode }; //WeakReference cachedEvalGenRef; //if (evalCache.TryGetValue(key, out cachedEvalGenRef) == true) //{ // var cachedEvalGen = (Compiler.EvalMethodGenerator)cachedEvalGenRef.Target; // if (cachedEvalGen != null) // { // // Replace the "this object" before running. // cachedEvalGen.ThisObject = thisObject; // // Execute the cached code. // return ((Compiler.EvalMethodGenerator)cachedEvalGen).Execute(); // } //} // Parse the eval string into an AST. var options = new Compiler.CompilerOptions() { ForceStrictMode = strictMode }; var evalGen = new Jurassic.Compiler.EvalMethodGenerator( this, // The script engine. scope, // The scope to run the code in. new StringScriptSource(code), // The source code to execute. options, // Options. thisObject); // The value of the "this" keyword. // Make sure the eval cache doesn't get too big. TODO: add some sort of LRU strategy? //if (evalCache.Count > 100) // evalCache.Clear(); //// Add the eval method generator to the cache. //evalCache[key] = new WeakReference(evalGen); // Compile and run the eval code. return(evalGen.Execute()); }
/// <summary> /// Creates a new EvalMethodGenerator instance. /// </summary> /// <param name="engine"> The script engine. </param> /// <param name="parentScope"> The scope of the calling code. </param> /// <param name="source"> The script code to execute. </param> /// <param name="options"> Options that influence the compiler. </param> /// <param name="thisObject"> The value of the "this" keyword in the calling code. </param> public EvalMethodGenerator(ScriptEngine engine, Scope parentScope, ScriptSource source, CompilerOptions options, object thisObject) : base(engine, parentScope, source, options) { this.ThisObject = thisObject; }
/// <summary> /// Creates a new GlobalMethodGenerator instance. /// </summary> /// <param name="engine"> The script engine. </param> /// <param name="source"> The source of javascript code. </param> /// <param name="options"> Options that influence the compiler. </param> public GlobalMethodGenerator(ScriptEngine engine, ScriptSource source, CompilerOptions options) : base(engine, engine.CreateGlobalScope(), source, options) { }
/// <summary> /// Creates a new MethodGenerator instance. /// </summary> /// <param name="engine"> The script engine. </param> /// <param name="scope"> The initial scope. </param> /// <param name="source"> The source of javascript code. </param> /// <param name="options"> Options that influence the compiler. </param> protected MethodGenerator(ScriptEngine engine, Scope scope, ScriptSource source, CompilerOptions options) { if (engine == null) { throw new ArgumentNullException("engine"); } if (scope == null) { throw new ArgumentNullException("scope"); } if (source == null) { throw new ArgumentNullException("source"); } if (options == null) { throw new ArgumentNullException("options"); } this.Engine = engine; this.InitialScope = scope; this.Source = source; this.Options = options; this.StrictMode = this.Options.ForceStrictMode; }