/// <summary> /// Creates a new declarative scope for use inside a function body. /// </summary> /// <param name="parentScope"> A reference to the parent scope. Can not be <c>null</c>. </param> /// <param name="functionName"> The name of the function. Can be empty for an anonymous function. </param> /// <param name="argumentNames"> The names of each of the function arguments. </param> /// <returns> A new DeclarativeScope instance. </returns> internal static DeclarativeScope CreateFunctionScope(Scope parentScope, string functionName, List <ArgVariable> args) { if (functionName == null) { throw new ArgumentNullException("functionName"); } if (args == null) { throw new ArgumentNullException("args"); } DeclarativeScope result = new DeclarativeScope(parentScope, 0); if (string.IsNullOrEmpty(functionName) == false) { result.AddVariable(functionName); } // At this point, the 'this' keyword is already in args. result.AddVariable("arguments"); foreach (ArgVariable arg in args) { result.Declare(arg); arg.Scope = result; } return(result); }
/// <summary> /// Generates code to push the "this" value for a function call. /// </summary> /// <param name="generator"> The generator to output the CIL to. </param> public void GenerateThis(ILGenerator generator) { // Optimization: if there are no with scopes, simply emit undefined. bool scopeChainHasWithScope = false; var scope = this.Scope; do { if (scope is ObjectScope && ((ObjectScope)scope).ProvidesImplicitThisValue == true) { scopeChainHasWithScope = true; break; } scope = scope.ParentScope; } while (scope != null); if (scopeChainHasWithScope == false) { // No with scopes in the scope chain, use undefined as the "this" value. EmitHelpers.EmitUndefined(generator); return; } scope = this.Scope; do { DeclarativeScope dScope = scope as DeclarativeScope; if (dScope != null) { if (dScope.HasDeclaredVariable(this.Name)) { // The variable exists but declarative scopes always produce undefined for // the "this" value. EmitHelpers.EmitUndefined(generator); break; } } else { // Object scope - what object type is it for? Prototype proto = (scope as ObjectScope).ScopePrototype; _Variable = proto.GetProperty(Name); if (_Variable != null) { // Output a get now: _Variable.Get(generator); break; } } scope = scope.ParentScope; } while (scope != null); }
public override Statement ParseNoNewContext(Parser parser) { var result = new TryCatchFinallyStatement(); var labelled = parser.Labels(result); // Consume the try keyword. parser.Expect(KeywordToken.Try); // Parse the try block. result.TryBlock = parser.ParseBlock(); // The next token is either 'catch' or 'finally'. if (parser.nextToken == KeywordToken.Catch) { // Consume the catch token. parser.Expect(KeywordToken.Catch); // Read the left parenthesis. parser.Expect(PunctuatorToken.LeftParenthesis); // Read the name of the variable to assign the exception to. result.CatchVariableName = parser.ExpectIdentifier(); parser.ValidateVariableName(result.CatchVariableName); // Read the right parenthesis. parser.Expect(PunctuatorToken.RightParenthesis); // Create a new scope for the catch variable. result.CatchScope = DeclarativeScope.CreateCatchScope(parser.currentLetScope, result.CatchVariableName); using (parser.CreateScopeContext(result.CatchScope, result.CatchScope)) { // Parse the statements inside the catch block. result.CatchBlock = parser.ParseBlock(); } } if (parser.nextToken == KeywordToken.Finally) { // Consume the finally token. parser.Expect(KeywordToken.Finally); // Read the finally statements. result.FinallyBlock = parser.ParseBlock(); } // There must be a catch or finally block. if (result.CatchBlock == null && result.FinallyBlock == null) { throw new JavaScriptException(parser.engine, "SyntaxError", "Missing catch or finally after try", parser.LineNumber, parser.SourcePath); } return(labelled); }
/// <summary> /// Creates a new FunctionMethodGenerator 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="includeNameInScope"> Indicates whether the name should be included in the function scope. </param> /// <param name="args"> 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, bool includeNameInScope, List <ArgVariable> args, Statement body, string scriptPath, CompilerOptions options) : base(engine, scope, new DummyScriptSource(scriptPath), options) { this.Name = functionName; this.IncludeNameInScope = includeNameInScope; this.Arguments = args; this.BodyRoot = body; // Claim an ID: MethodID = MethodLookup.GetNextID(); // Store the generated method in the cache: MethodLookup.SaveAs(MethodID, this); Validate(); }
/// <summary> /// Creates a new declarative scope for use inside a catch statement. /// </summary> /// <param name="parentScope"> A reference to the parent scope. Can not be <c>null</c>. </param> /// <param name="catchVariableName"> The name of the catch variable. </param> /// <returns> A new DeclarativeScope instance. </returns> internal static DeclarativeScope CreateCatchScope(Scope parentScope, string catchVariableName) { if (parentScope == null) { throw new ArgumentNullException("parentScope", "Catch scopes must have a parent scope."); } if (catchVariableName == null) { throw new ArgumentNullException("catchVariableName"); } DeclarativeScope result = new DeclarativeScope(parentScope, 0); result.AddVariable(catchVariableName); result.CanDeclareVariables = false; // Only the catch variable can be declared in this scope. return(result); }
/// <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="args"> 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, List <ArgVariable> args, string body, CompilerOptions options) : base(engine, scope, new StringScriptSource(body), options) { this.Name = functionName; this.Arguments = args; }