зеркало из https://github.com/mozilla/gecko-dev.git
Determine functions that require activation during parsing and not in NodeTransformer
This commit is contained in:
Родитель
ac844241db
Коммит
d2ab61c277
|
@ -53,8 +53,8 @@ public class FunctionNode extends ScriptOrFnNode {
|
|||
return itsNeedsActivation;
|
||||
}
|
||||
|
||||
boolean setRequiresActivation(boolean b) {
|
||||
return itsNeedsActivation = b;
|
||||
void setRequiresActivation() {
|
||||
itsNeedsActivation = true;
|
||||
}
|
||||
|
||||
public boolean getCheckThis() {
|
||||
|
|
|
@ -106,6 +106,7 @@ class IRFactory
|
|||
*/
|
||||
Object createName(String name)
|
||||
{
|
||||
checkActivationName(name, Token.NAME);
|
||||
return Node.newString(Token.NAME, name);
|
||||
}
|
||||
|
||||
|
@ -220,7 +221,7 @@ class IRFactory
|
|||
int functionCount = fnNode.getFunctionCount();
|
||||
if (functionCount != 0) {
|
||||
// Functions containing other functions require activation objects
|
||||
fnNode.setRequiresActivation(true);
|
||||
fnNode.setRequiresActivation();
|
||||
for (int i = 0; i != functionCount; ++i) {
|
||||
FunctionNode fn = fnNode.getFunctionNode(i);
|
||||
// nested function expression statements overrides var
|
||||
|
@ -601,6 +602,7 @@ class IRFactory
|
|||
*/
|
||||
Object createWith(Object obj, Object body, int lineno)
|
||||
{
|
||||
setRequiresActivation();
|
||||
Node result = new Node(Token.BLOCK, lineno);
|
||||
result.addChildToBack(new Node(Token.ENTERWITH, (Node)obj));
|
||||
Node bodyNode = new Node(Token.WITH, (Node) body, lineno);
|
||||
|
@ -824,6 +826,32 @@ class IRFactory
|
|||
return new Node(nodeType, childNode);
|
||||
}
|
||||
|
||||
Object createCallOrNew(int nodeType, Object childNode)
|
||||
{
|
||||
Node child = (Node)childNode;
|
||||
int type = Node.NON_SPECIALCALL;
|
||||
if (child.getType() == Token.NAME) {
|
||||
String name = child.getString();
|
||||
if (name.equals("eval")) {
|
||||
type = Node.SPECIALCALL_EVAL;
|
||||
} else if (name.equals("With")) {
|
||||
type = Node.SPECIALCALL_WITH;
|
||||
}
|
||||
} else if (child.getType() == Token.GETPROP) {
|
||||
String name = child.getLastChild().getString();
|
||||
if (name.equals("eval")) {
|
||||
type = Node.SPECIALCALL_EVAL;
|
||||
}
|
||||
}
|
||||
Node node = new Node(nodeType, child);
|
||||
if (type != Node.NON_SPECIALCALL) {
|
||||
// Calls to these functions require activation objects.
|
||||
setRequiresActivation();
|
||||
node.putIntProp(Node.SPECIALCALL_PROP, type);
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
Object createIncDec(int nodeType, boolean post, Object child)
|
||||
{
|
||||
Node childNode = (Node)child;
|
||||
|
@ -902,6 +930,8 @@ class IRFactory
|
|||
Node result = new Node(nodeType, left);
|
||||
result.putIntProp(Node.SPECIAL_PROP_PROP, special);
|
||||
return result;
|
||||
} else {
|
||||
checkActivationName(id, Token.GETPROP);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -1186,6 +1216,37 @@ class IRFactory
|
|||
return false;
|
||||
}
|
||||
|
||||
private void checkActivationName(String name, int token)
|
||||
{
|
||||
boolean activation = false;
|
||||
if (parser.currentScriptOrFn.getType() == Token.FUNCTION) {
|
||||
if ("arguments".equals(name)
|
||||
|| (parser.compilerEnv.activationNames != null
|
||||
&& parser.compilerEnv.activationNames.containsKey(name)))
|
||||
{
|
||||
activation = true;
|
||||
} else if ("length".equals(name)) {
|
||||
if (token == Token.GETPROP
|
||||
&& parser.compilerEnv.getLanguageVersion()
|
||||
== Context.VERSION_1_2)
|
||||
{
|
||||
// Use of "length" in 1.2 requires an activation object.
|
||||
activation = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (activation) {
|
||||
((FunctionNode)parser.currentScriptOrFn).setRequiresActivation();
|
||||
}
|
||||
}
|
||||
|
||||
private void setRequiresActivation()
|
||||
{
|
||||
if (parser.currentScriptOrFn.getType() == Token.FUNCTION) {
|
||||
((FunctionNode)parser.currentScriptOrFn).setRequiresActivation();
|
||||
}
|
||||
}
|
||||
|
||||
// Only needed to call reportCurrentLineError.
|
||||
private Parser parser;
|
||||
|
||||
|
|
|
@ -185,10 +185,6 @@ public class NodeTransformer
|
|||
|
||||
case Token.WITH:
|
||||
{
|
||||
if (inFunction) {
|
||||
// With statements require an activation object.
|
||||
((FunctionNode) tree).setRequiresActivation(true);
|
||||
}
|
||||
loops.push(node);
|
||||
Node leave = node.getNext();
|
||||
if (leave.getType() != Token.LEAVEWITH) {
|
||||
|
@ -336,23 +332,13 @@ public class NodeTransformer
|
|||
break;
|
||||
}
|
||||
|
||||
case Token.CALL: {
|
||||
int callType = getSpecialCallType(tree, node);
|
||||
if (callType != Node.NON_SPECIALCALL) {
|
||||
node.putIntProp(Node.SPECIALCALL_PROP, callType);
|
||||
}
|
||||
case Token.CALL:
|
||||
visitCall(node, tree);
|
||||
break;
|
||||
}
|
||||
|
||||
case Token.NEW: {
|
||||
int callType = getSpecialCallType(tree, node);
|
||||
if (callType != Node.NON_SPECIALCALL) {
|
||||
node.putIntProp(Node.SPECIALCALL_PROP, callType);
|
||||
}
|
||||
case Token.NEW:
|
||||
visitNew(node, tree);
|
||||
break;
|
||||
}
|
||||
|
||||
case Token.DOT:
|
||||
{
|
||||
|
@ -396,10 +382,6 @@ public class NodeTransformer
|
|||
if (bind == null || bind.getType() != Token.BINDNAME)
|
||||
break;
|
||||
String name = bind.getString();
|
||||
if (isActivationNeeded(name)) {
|
||||
// use of "arguments" requires an activation object.
|
||||
((FunctionNode) tree).setRequiresActivation(true);
|
||||
}
|
||||
if (tree.hasParamOrVar(name)) {
|
||||
if (type == Token.SETNAME) {
|
||||
node.setType(Token.SETVAR);
|
||||
|
@ -413,31 +395,11 @@ public class NodeTransformer
|
|||
break;
|
||||
}
|
||||
|
||||
case Token.GETPROP:
|
||||
if (inFunction) {
|
||||
Node n = node.getFirstChild().getNext();
|
||||
String name = n == null ? "" : n.getString();
|
||||
if (isActivationNeeded(name)
|
||||
|| (name.equals("length")
|
||||
&& compilerEnv.getLanguageVersion()
|
||||
== Context.VERSION_1_2))
|
||||
{
|
||||
// Use of "arguments" or "length" in 1.2 requires
|
||||
// an activation object.
|
||||
((FunctionNode) tree).setRequiresActivation(true);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case Token.NAME:
|
||||
{
|
||||
if (!inFunction || inWithStatement())
|
||||
break;
|
||||
String name = node.getString();
|
||||
if (isActivationNeeded(name)) {
|
||||
// Use of "arguments" requires an activation object.
|
||||
((FunctionNode) tree).setRequiresActivation(true);
|
||||
}
|
||||
if (tree.hasParamOrVar(name)) {
|
||||
node.setType(Token.GETVAR);
|
||||
}
|
||||
|
@ -464,37 +426,6 @@ public class NodeTransformer
|
|||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the node is a call to a function that requires
|
||||
* access to the enclosing activation object.
|
||||
*/
|
||||
private static int getSpecialCallType(Node tree, Node node)
|
||||
{
|
||||
Node left = node.getFirstChild();
|
||||
int type = Node.NON_SPECIALCALL;
|
||||
if (left.getType() == Token.NAME) {
|
||||
String name = left.getString();
|
||||
if (name.equals("eval")) {
|
||||
type = Node.SPECIALCALL_EVAL;
|
||||
} else if (name.equals("With")) {
|
||||
type = Node.SPECIALCALL_WITH;
|
||||
}
|
||||
} else {
|
||||
if (left.getType() == Token.GETPROP) {
|
||||
String name = left.getLastChild().getString();
|
||||
if (name.equals("eval")) {
|
||||
type = Node.SPECIALCALL_EVAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (type != Node.NON_SPECIALCALL) {
|
||||
// Calls to these functions require activation objects.
|
||||
if (tree.getType() == Token.FUNCTION)
|
||||
((FunctionNode) tree).setRequiresActivation(true);
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
private static Node addBeforeCurrent(Node parent, Node previous,
|
||||
Node current, Node toAdd)
|
||||
{
|
||||
|
@ -531,18 +462,6 @@ public class NodeTransformer
|
|||
compilerEnv.reportSyntaxError(message, sourceName, lineno, null, 0);
|
||||
}
|
||||
|
||||
private boolean isActivationNeeded(String name)
|
||||
{
|
||||
if ("arguments".equals(name))
|
||||
return true;
|
||||
if (compilerEnv.activationNames != null
|
||||
&& compilerEnv.activationNames.containsKey(name))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private ObjArray loops;
|
||||
private ObjArray loopEnds;
|
||||
private boolean inFunction;
|
||||
|
|
|
@ -1249,7 +1249,7 @@ public class Parser
|
|||
|
||||
}
|
||||
|
||||
private Object argumentList(Object listNode)
|
||||
private void argumentList(Object listNode)
|
||||
throws IOException, ParserException
|
||||
{
|
||||
boolean matched;
|
||||
|
@ -1268,7 +1268,6 @@ public class Parser
|
|||
mustMatchToken(Token.RP, "msg.no.paren.arg");
|
||||
}
|
||||
decompiler.addToken(Token.RP);
|
||||
return listNode;
|
||||
}
|
||||
|
||||
private Object memberExpr(boolean allowCallSyntax)
|
||||
|
@ -1288,13 +1287,12 @@ public class Parser
|
|||
decompiler.addToken(Token.NEW);
|
||||
|
||||
/* Make a NEW node to append to. */
|
||||
pn = nf.createLeaf(Token.NEW);
|
||||
nf.addChildToBack(pn, memberExpr(false));
|
||||
pn = nf.createCallOrNew(Token.NEW, memberExpr(false));
|
||||
|
||||
if (ts.matchToken(Token.LP)) {
|
||||
decompiler.addToken(Token.LP);
|
||||
/* Add the arguments to pn, if any are supplied. */
|
||||
pn = argumentList(pn);
|
||||
argumentList(pn);
|
||||
}
|
||||
|
||||
/* XXX there's a check in the C source against
|
||||
|
@ -1341,12 +1339,11 @@ public class Parser
|
|||
decompiler.addToken(Token.RB);
|
||||
} else if (allowCallSyntax && tt == Token.LP) {
|
||||
/* make a call node */
|
||||
|
||||
pn = nf.createUnary(Token.CALL, pn);
|
||||
decompiler.addToken(Token.LP);
|
||||
pn = nf.createCallOrNew(Token.CALL, pn);
|
||||
|
||||
/* Add the arguments to pn, if any are supplied. */
|
||||
pn = argumentList(pn);
|
||||
argumentList(pn);
|
||||
} else {
|
||||
ts.ungetToken(tt);
|
||||
|
||||
|
@ -1533,7 +1530,7 @@ public class Parser
|
|||
|
||||
private boolean ok; // Did the parse encounter an error?
|
||||
|
||||
private ScriptOrFnNode currentScriptOrFn;
|
||||
ScriptOrFnNode currentScriptOrFn;
|
||||
|
||||
private int nestingOfWith;
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче