A JavaScript function declaration or expression.

Node type is Rhino.Token.FUNCTION .

FunctionDeclaration : function Identifier ( FormalParameterListopt ) { FunctionBody } FunctionExpression : function Identifieropt ( FormalParameterListopt ) { FunctionBody } FormalParameterList : Identifier FormalParameterList , Identifier FunctionBody : SourceElements Program : SourceElements SourceElements : SourceElement SourceElements SourceElement SourceElement : Statement FunctionDeclaration
JavaScript 1.8 introduces "function closures" of the form
function ([params] ) Expression
In this case the FunctionNode node will have no body but will have an expression.
Inheritance: ScriptNode
Beispiel #1
0
		/// <summary>
		/// Adds a
		/// <see cref="FunctionNode">FunctionNode</see>
		/// to the functions table for codegen.
		/// Does not set the parent of the node.
		/// </summary>
		/// <returns>the index of the function within its parent</returns>
		public virtual int AddFunction(FunctionNode fnNode)
		{
			if (fnNode == null)
			{
				CodeBug();
			}
			if (functions == null)
			{
				functions = new List<FunctionNode>();
			}
			functions.Add(fnNode);
			return functions.Count - 1;
		}
Beispiel #2
0
		private Node TransformGenExpr(GeneratorExpression node)
		{
			Node pn;
			FunctionNode fn = new FunctionNode();
			fn.SetSourceName(currentScriptOrFn.GetNextTempName());
			fn.SetIsGenerator();
			fn.SetFunctionType(FunctionNode.FUNCTION_EXPRESSION);
			fn.SetRequiresActivation();
			int functionType = fn.GetFunctionType();
			int start = decompiler.MarkFunctionStart(functionType);
			Node mexpr = DecompileFunctionHeader(fn);
			int index = currentScriptOrFn.AddFunction(fn);
			Parser.PerFunctionVariables savedVars = new Parser.PerFunctionVariables(this, fn);
			try
			{
				// If we start needing to record much more codegen metadata during
				// function parsing, we should lump it all into a helper class.
				Node destructuring = (Node)fn.GetProp(Node.DESTRUCTURING_PARAMS);
				fn.RemoveProp(Node.DESTRUCTURING_PARAMS);
				int lineno = node.lineno;
				++nestingOfFunction;
				// only for body, not params
				Node body = GenExprTransformHelper(node);
				if (!fn.IsExpressionClosure())
				{
					decompiler.AddToken(Token.RC);
				}
				fn.SetEncodedSourceBounds(start, decompiler.MarkFunctionEnd(start));
				if (functionType != FunctionNode.FUNCTION_EXPRESSION && !fn.IsExpressionClosure())
				{
					// Add EOL only if function is not part of expression
					// since it gets SEMI + EOL from Statement in that case
					decompiler.AddToken(Token.EOL);
				}
				if (destructuring != null)
				{
					body.AddChildToFront(new Node(Token.EXPR_VOID, destructuring, lineno));
				}
				int syntheticType = fn.GetFunctionType();
				pn = InitFunction(fn, index, body, syntheticType);
				if (mexpr != null)
				{
					pn = CreateAssignment(Token.ASSIGN, mexpr, pn);
					if (syntheticType != FunctionNode.FUNCTION_EXPRESSION)
					{
						pn = CreateExprStatementNoReturn(pn, fn.GetLineno());
					}
				}
			}
			finally
			{
				--nestingOfFunction;
				savedVars.Restore();
			}
			Node call = CreateCallOrNew(Token.CALL, pn);
			call.SetLineno(node.GetLineno());
			decompiler.AddToken(Token.LP);
			decompiler.AddToken(Token.RP);
			return call;
		}
Beispiel #3
0
		private Node InitFunction(FunctionNode fnNode, int functionIndex, Node statements, int functionType)
		{
			fnNode.SetFunctionType(functionType);
			fnNode.AddChildToBack(statements);
			int functionCount = fnNode.GetFunctionCount();
			if (functionCount != 0)
			{
				// Functions containing other functions require activation objects
				fnNode.SetRequiresActivation();
			}
			if (functionType == FunctionNode.FUNCTION_EXPRESSION)
			{
				Name name = fnNode.GetFunctionName();
				if (name != null && name.Length() != 0 && fnNode.GetSymbol(name.GetIdentifier()) == null)
				{
					// A function expression needs to have its name as a
					// variable (if it isn't already allocated as a variable).
					// See ECMA Ch. 13.  We add code to the beginning of the
					// function to initialize a local variable of the
					// function's name to the function value, but only if the
					// function doesn't already define a formal parameter, var,
					// or nested function with the same name.
					fnNode.PutSymbol(new Symbol(Token.FUNCTION, name.GetIdentifier()));
					Node setFn = new Node(Token.EXPR_VOID, new Node(Token.SETNAME, Node.NewString(Token.BINDNAME, name.GetIdentifier()), new Node(Token.THISFN)));
					statements.AddChildrenToFront(setFn);
				}
			}
			// Add return to end if needed.
			Node lastStmt = statements.GetLastChild();
			if (lastStmt == null || lastStmt.GetType() != Token.RETURN)
			{
				statements.AddChildToBack(new Node(Token.RETURN));
			}
			Node result = Node.NewString(Token.FUNCTION, fnNode.GetName());
			result.PutIntProp(Node.FUNCTION_PROP, functionIndex);
			return result;
		}
Beispiel #4
0
		internal Node DecompileFunctionHeader(FunctionNode fn)
		{
			Node mexpr = null;
			if (fn.GetFunctionName() != null)
			{
				decompiler.AddName(fn.GetName());
			}
			else
			{
				if (fn.GetMemberExprNode() != null)
				{
					mexpr = Transform(fn.GetMemberExprNode());
				}
			}
			decompiler.AddToken(Token.LP);
			IList<AstNode> @params = fn.GetParams();
			for (int i = 0; i < @params.Count; i++)
			{
				Decompile(@params[i]);
				if (i < @params.Count - 1)
				{
					decompiler.AddToken(Token.COMMA);
				}
			}
			decompiler.AddToken(Token.RP);
			if (!fn.IsExpressionClosure())
			{
				decompiler.AddEOL(Token.LC);
			}
			return mexpr;
		}
Beispiel #5
0
		internal OptFunctionNode(FunctionNode fnode)
		{
			this.fnode = fnode;
			fnode.SetCompilerData(this);
		}