Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
   *
   * This Source Code Form is subject to the terms of the Mozilla Public
   * License, v. 2.0. If a copy of the MPL was not distributed with this
   * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  
  package org.mozilla.javascript.ast;
  
 
 import java.util.List;
 import java.util.Map;

A JavaScript function declaration or expression.

Node type is org.mozilla.javascript.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.
 
 public class FunctionNode extends ScriptNode {

    
There are three types of functions that can be defined. The first is a function statement. This is a function appearing as a top-level statement (i.e., not nested inside some other statement) in either a script or a function.

The second is a function expression, which is a function appearing in an expression except for the third type, which is...

The third type is a function expression where the expression is the top-level expression in an expression statement.

The three types of functions have different treatment and must be distinguished.

 
     public static final int FUNCTION_STATEMENT            = 1;
     public static final int FUNCTION_EXPRESSION           = 2;
     public static final int FUNCTION_EXPRESSION_STATEMENT = 3;
 
     public static enum Form { FUNCTION, GETTER, SETTER }
 
     private static final List<AstNodeNO_PARAMS =
         Collections.unmodifiableList(new ArrayList<AstNode>());
 
     private Name functionName;
     private List<AstNodeparams;
     private AstNode body;
     private boolean isExpressionClosure;
     private Form functionForm = .;
     private int lp = -1;
     private int rp = -1;
 
     // codegen variables
     private int functionType;
     private boolean needsActivation;
     private boolean isGenerator;
     private List<NodegeneratorResumePoints;
     private Map<Node,int[]> liveLocals;
     private AstNode memberExprNode;
 
     {
          = .;
     }
 
     public FunctionNode() {
     }
 
     public FunctionNode(int pos) {
         super(pos);
     }
 
     public FunctionNode(int posName name) {
        super(pos);
        setFunctionName(name);
    }

    
Returns function name

Returns:
function name, null for anonymous functions
    public Name getFunctionName() {
        return ;
    }

    
Sets function name, and sets its parent to this node.

Parameters:
name function name, null for anonymous functions
    public void setFunctionName(Name name) {
         = name;
        if (name != null)
            name.setParent(this);
    }

    
Returns the function name as a string

Returns:
the function name, "" if anonymous
    public String getName() {
        return  != null ? .getIdentifier() : "";
    }

    
Returns the function parameter list

Returns:
the function parameter list. Returns an immutable empty list if there are no parameters.
    public List<AstNodegetParams() {
        return  != null ?  : ;
    }

    
Sets the function parameter list, and sets the parent for each element of the list.

Parameters:
params the function parameter list, or null if no params
    public void setParams(List<AstNodeparams) {
        if (params == null) {
            this. = null;
        } else {
            if (this. != null)
                this..clear();
            for (AstNode param : params)
                addParam(param);
        }
    }

    
Adds a parameter to the function parameter list. Sets the parent of the param node to this node.

Parameters:
param the parameter
Throws:
java.lang.IllegalArgumentException if param is null
    public void addParam(AstNode param) {
        assertNotNull(param);
        if ( == null) {
             = new ArrayList<AstNode>();
        }
        .add(param);
        param.setParent(this);
    }

    
Returns true if the specified AstNode node is a parameter of this Function node. This provides a way during AST traversal to disambiguate the function name node from the parameter nodes.
    public boolean isParam(AstNode node) {
        return  == null ? false : .contains(node);
    }

    
Returns function body. Normally a Block, but can be a plain AstNode if it's a function closure.

Returns:
the body. Can be null only if the AST is malformed.
    public AstNode getBody() {
        return ;
    }

    
Sets function body, and sets its parent to this node. Also sets the encoded source bounds based on the body bounds. Assumes the function node absolute position has already been set, and the body node's absolute position and length are set.

Parameters:
body function body. Its parent is set to this node, and its position is updated to be relative to this node.
Throws:
java.lang.IllegalArgumentException if body is null
    public void setBody(AstNode body) {
        assertNotNull(body);
        this. = body;
        if (..equals(body.getProp(.))) {
            setIsExpressionClosure(true);
        }
        int absEnd = body.getPosition() + body.getLength();
        body.setParent(this);
        this.setLength(absEnd - this.);
        setEncodedSourceBounds(this.absEnd);
    }

    
Returns left paren position, -1 if missing
    public int getLp() {
        return ;
    }

    
Sets left paren position
    public void setLp(int lp) {
        this. = lp;
    }

    
Returns right paren position, -1 if missing
    public int getRp() {
        return ;
    }

    
Sets right paren position
    public void setRp(int rp) {
        this. = rp;
    }

    
Sets both paren positions
    public void setParens(int lpint rp) {
        this. = lp;
        this. = rp;
    }

    
Returns whether this is a 1.8 function closure
    public boolean isExpressionClosure() {
        return ;
    }

    
Sets whether this is a 1.8 function closure
    public void setIsExpressionClosure(boolean isExpressionClosure) {
        this. = isExpressionClosure;
    }

    
Return true if this function requires an Ecma-262 Activation object. The Activation object is implemented by org.mozilla.javascript.NativeCall, and is fairly expensive to create, so when possible, the interpreter attempts to use a plain call frame instead.

Returns:
true if this function needs activation. It could be needed if there is a lexical closure, or in a number of other situations.
    public boolean requiresActivation() {
        return ;
    }
    public void setRequiresActivation() {
         = true;
    }
    public boolean isGenerator() {
      return ;
    }
    public void setIsGenerator() {
         = true;
    }
    public void addResumptionPoint(Node target) {
        if ( == null)
             = new ArrayList<Node>();
        .add(target);
    }
    public List<NodegetResumptionPoints() {
        return ;
    }
    public Map<Node,int[]> getLiveLocals() {
        return ;
    }
    public void addLiveLocals(Node nodeint[] locals) {
        if ( == null)
             = new HashMap<Node,int[]>();
        .put(nodelocals);
    }
    @Override
    public int addFunction(FunctionNode fnNode) {
        int result = super.addFunction(fnNode);
        if (getFunctionCount() > 0) {
             = true;
        }
        return result;
    }

    
Returns the function type (statement, expr, statement expr)
    public int getFunctionType() {
        return ;
    }
    public void setFunctionType(int type) {
         = type;
    }
    public boolean isGetterOrSetter() {
        return  == . ||  == .;
    }
    public boolean isGetter() {
        return  == .;
    }
    public boolean isSetter() {
        return  == .;
    }
    public void setFunctionIsGetter() {
         = .;
    }
    public void setFunctionIsSetter() {
         = .;
    }

    
Rhino supports a nonstandard Ecma extension that allows you to say, for instance, function a.b.c(arg1, arg) {...}, and it will be rewritten at codegen time to: a.b.c = function(arg1, arg2) {...} If we detect an expression other than a simple Name in the position where a function name was expected, we record that expression here.

This extension is only available by setting the CompilerEnv option "isAllowMemberExprAsFunctionName" in the Parser.

    public void setMemberExprNode(AstNode node) {
         = node;
        if (node != null)
            node.setParent(this);
    }
    public AstNode getMemberExprNode() {
        return ;
    }
    @Override
    public String toSource(int depth) {
        StringBuilder sb = new StringBuilder();
        if (!isGetterOrSetter()) {
            sb.append(makeIndent(depth));
            sb.append("function");
        }
        if ( != null) {
            sb.append(" ");
            sb.append(.toSource(0));
        }
        if ( == null) {
            sb.append("() ");
        } else {
            sb.append("(");
            printList(sb);
            sb.append(") ");
        }
        if () {
            AstNode body = getBody();
            if (body.getLastChild() instanceof ReturnStatement) {
                // omit "return" keyword, just print the expression
                body = ((ReturnStatementbody.getLastChild()).getReturnValue();
                sb.append(body.toSource(0));
                if ( == ) {
                    sb.append(";");
                }
            } else {
                // should never happen
                sb.append(" ");
                sb.append(body.toSource(0));
            }
        } else {
            sb.append(getBody().toSource(depth).trim());
        }
        if ( ==  || isGetterOrSetter()) {
            sb.append("\n");
        }
        return sb.toString();
    }

    
Visits this node, the function name node if supplied, the parameters, and the body. If there is a member-expr node, it is visited last.
    @Override
    public void visit(NodeVisitor v) {
        if (v.visit(this)) {
            if ( != null) {
                .visit(v);
            }
            for (AstNode param : getParams()) {
                param.visit(v);
            }
            getBody().visit(v);
            if (!) {
                if ( != null) {
                    .visit(v);
                }
            }
        }
    }
New to GrepCode? Check out our FAQ X