/// <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);
        }
Exemple #2
0
        /// <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);
        }
Exemple #3
0
        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;
 }