Determine functions that require activation during parsing and not in NodeTransformer

This commit is contained in:
igor%mir2.org 2004-05-10 13:39:14 +00:00
Родитель ac844241db
Коммит d2ab61c277
4 изменённых файлов: 72 добавлений и 95 удалений

Просмотреть файл

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