diff --git a/js/rhino/src/org/mozilla/javascript/FunctionNode.java b/js/rhino/src/org/mozilla/javascript/FunctionNode.java index 8466bec99fc8..2f37458d76cf 100644 --- a/js/rhino/src/org/mozilla/javascript/FunctionNode.java +++ b/js/rhino/src/org/mozilla/javascript/FunctionNode.java @@ -53,7 +53,7 @@ public class FunctionNode extends ScriptOrFnNode { return itsNeedsActivation; } - public boolean setRequiresActivation(boolean b) { + boolean setRequiresActivation(boolean b) { return itsNeedsActivation = b; } @@ -61,7 +61,7 @@ public class FunctionNode extends ScriptOrFnNode { return itsCheckThis; } - public void setCheckThis() { + void setCheckThis() { itsCheckThis = true; } @@ -69,7 +69,7 @@ public class FunctionNode extends ScriptOrFnNode { return itsIgnoreDynamicScope; } - public void setIgnoreDynamicScope() { + void setIgnoreDynamicScope() { itsIgnoreDynamicScope = true; } @@ -96,55 +96,10 @@ public class FunctionNode extends ScriptOrFnNode { return itsFunctionType; } - public void setFunctionType(int functionType) { + void setFunctionType(int functionType) { itsFunctionType = functionType; } - protected void finishParsing(IRFactory irFactory) { - super.finishParsing(irFactory); - int functionCount = getFunctionCount(); - if (functionCount != 0) { - for (int i = 0; i != functionCount; ++i) { - FunctionNode fn = getFunctionNode(i); - - // nested function expression statements overrides var - if (fn.getFunctionType() == FUNCTION_EXPRESSION_STATEMENT) { - String name = fn.getFunctionName(); - if (name != null && name.length() != 0) { - removeParamOrVar(name); - } - } - } - - // Functions containing other functions require activation objects - setRequiresActivation(true); - } - - Node stmts = getLastChild(); - if (getFunctionType() == FUNCTION_EXPRESSION) { - String name = getFunctionName(); - if (name != null && name.length() != 0 && !hasParamOrVar(name)) - { - // 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. - addVar(name); - Node setFn = new Node(Token.POP, - new Node(Token.SETVAR, Node.newString(name), - new Node(Token.THISFN))); - stmts.addChildrenToFront(setFn); - } - } - - // Add return to end if needed. - Node lastStmt = stmts.getLastChild(); - if (lastStmt == null || lastStmt.getType() != Token.RETURN) { - stmts.addChildToBack(new Node(Token.RETURN)); - } - } - private String functionName; private boolean itsNeedsActivation; private boolean itsCheckThis; diff --git a/js/rhino/src/org/mozilla/javascript/IRFactory.java b/js/rhino/src/org/mozilla/javascript/IRFactory.java index 2e9483e47294..a1e686cadbc8 100644 --- a/js/rhino/src/org/mozilla/javascript/IRFactory.java +++ b/js/rhino/src/org/mozilla/javascript/IRFactory.java @@ -61,7 +61,6 @@ public class IRFactory { { Node children = ((Node) body).getFirstChild(); if (children != null) { scriptNode.addChildrenToBack(children); } - scriptNode.finishParsing(this); } /** @@ -200,9 +199,51 @@ public class IRFactory { public Object initFunction(FunctionNode fnNode, int functionIndex, Object statements, int functionType) { + Node stmts = (Node)statements; fnNode.setFunctionType(functionType); - fnNode.addChildToBack((Node)statements); - fnNode.finishParsing(this); + fnNode.addChildToBack(stmts); + + int functionCount = fnNode.getFunctionCount(); + if (functionCount != 0) { + // Functions containing other functions require activation objects + fnNode.setRequiresActivation(true); + for (int i = 0; i != functionCount; ++i) { + FunctionNode fn = fnNode.getFunctionNode(i); + // nested function expression statements overrides var + if (fn.getFunctionType() + == FunctionNode.FUNCTION_EXPRESSION_STATEMENT) + { + String name = fn.getFunctionName(); + if (name != null && name.length() != 0) { + fnNode.removeParamOrVar(name); + } + } + } + } + + if (functionType == FunctionNode.FUNCTION_EXPRESSION) { + String name = fnNode.getFunctionName(); + if (name != null && name.length() != 0 + && !fnNode.hasParamOrVar(name)) + { + // 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. + fnNode.addVar(name); + Node setFn = new Node(Token.POP, + new Node(Token.SETVAR, Node.newString(name), + new Node(Token.THISFN))); + stmts.addChildrenToFront(setFn); + } + } + + // Add return to end if needed. + Node lastStmt = stmts.getLastChild(); + if (lastStmt == null || lastStmt.getType() != Token.RETURN) { + stmts.addChildToBack(new Node(Token.RETURN)); + } Node result = Node.newString(Token.FUNCTION, fnNode.getFunctionName()); @@ -1123,10 +1164,8 @@ public class IRFactory { private Interpreter compiler; - // Only needed to call reportSyntaxError. Could create an interface - // that TokenStream implements if we want to make the connection less - // direct. - TokenStream ts; + // Only needed to call reportCurrentLineError. + private TokenStream ts; private static final int LOOP_DO_WHILE = 0; private static final int LOOP_WHILE = 1; diff --git a/js/rhino/src/org/mozilla/javascript/ScriptOrFnNode.java b/js/rhino/src/org/mozilla/javascript/ScriptOrFnNode.java index 53d1b4a92662..5e0b6ac63609 100644 --- a/js/rhino/src/org/mozilla/javascript/ScriptOrFnNode.java +++ b/js/rhino/src/org/mozilla/javascript/ScriptOrFnNode.java @@ -174,8 +174,6 @@ public class ScriptOrFnNode extends Node { } } - protected void finishParsing(IRFactory irFactory) { } - private int encodedSourceStart; private int encodedSourceEnd; private String sourceName; diff --git a/js/rhino/src/org/mozilla/javascript/optimizer/Codegen.java b/js/rhino/src/org/mozilla/javascript/optimizer/Codegen.java index 25c1211ff03e..73237c93c1f2 100644 --- a/js/rhino/src/org/mozilla/javascript/optimizer/Codegen.java +++ b/js/rhino/src/org/mozilla/javascript/optimizer/Codegen.java @@ -77,6 +77,7 @@ public class Codegen extends Interpreter { public ScriptOrFnNode transform(Context cx, ScriptOrFnNode tree) { + initOptFunctions_r(tree); int optLevel = cx.getOptimizationLevel(); Hashtable possibleDirectCalls = null; if (optLevel > 0) { @@ -120,6 +121,15 @@ public class Codegen extends Interpreter { return tree; } + private static void initOptFunctions_r(ScriptOrFnNode scriptOrFn) + { + for (int i = 0, N = scriptOrFn.getFunctionCount(); i != N; ++i) { + OptFunctionNode fn = (OptFunctionNode)scriptOrFn.getFunctionNode(i); + fn.init(); + initOptFunctions_r(fn); + } + } + public Object compile(Context cx, Scriptable scope, ScriptOrFnNode scriptOrFn, SecurityController securityController, @@ -301,8 +311,6 @@ public class Codegen extends Interpreter { for (int i = 0; i != count; ++i) { ScriptOrFnNode n = scriptOrFnNodes[i]; - boolean isFunction = (n.getType() == Token.FUNCTION); - BodyCodegen bodygen = new BodyCodegen(); bodygen.cfw = cfw; bodygen.codegen = this; diff --git a/js/rhino/src/org/mozilla/javascript/optimizer/OptFunctionNode.java b/js/rhino/src/org/mozilla/javascript/optimizer/OptFunctionNode.java index ad646fed179d..a2fb3f21bf05 100644 --- a/js/rhino/src/org/mozilla/javascript/optimizer/OptFunctionNode.java +++ b/js/rhino/src/org/mozilla/javascript/optimizer/OptFunctionNode.java @@ -39,14 +39,14 @@ package org.mozilla.javascript.optimizer; import org.mozilla.javascript.*; import java.util.*; -class OptFunctionNode extends FunctionNode { +final class OptFunctionNode extends FunctionNode { OptFunctionNode(String name) { super(name); } - protected void finishParsing(IRFactory irFactory) { - super.finishParsing(irFactory); + void init() + { int N = getParamAndVarCount(); int parameterCount = getParamCount(); optVars = new OptLocalVariable[N];