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; }
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; }