more fixes to lexical scoping for JavaScript

git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@3196 f5eafffb-2e1d-0410-98e4-8ec43c5233c4
This commit is contained in:
dolby-oss 2009-01-30 16:33:22 +00:00
parent 62a1089c41
commit 9979d0899c
10 changed files with 77 additions and 32 deletions

View File

@ -143,7 +143,7 @@ public class JavaCAst2IRTranslator extends AstTranslator {
}
}
protected void doMaterializeFunction(WalkContext context, int result, int exception, CAstEntity fn) {
protected void doMaterializeFunction(CAstNode n, WalkContext context, int result, int exception, CAstEntity fn) {
// Not possible in Java (no free-standing functions)
Assertions.UNREACHABLE("Real functions in Java??? I don't think so!");
}

View File

@ -0,0 +1,7 @@
var standalone = false;
try {
document; // ReferenceError
} catch(error) {
standalone = true;
}
assert(standalone);

View File

@ -0,0 +1,8 @@
function im_with_stupid(stupid, x) {
with (stupid) {
return x+3;
}
}
var foo = new Object();
var bar = im_with_stupid(foo, 7);

View File

@ -208,10 +208,27 @@ public class TestSimpleCallGraphShape extends TestJSCallGraphShape {
CallGraph CG = B.makeCallGraph(B.getOptions());
verifyGraphAssertions(CG, assertionsForInstanceof);
}
/*
private static final Object[][] assertionsForWith = new Object[][] {
new Object[] { ROOT, new String[] { "tests/with.js" } }
};
public void testWith() throws IOException, IllegalArgumentException, CancelException {
PropagationCallGraphBuilder B = Util.makeScriptCGBuilder("tests", "with.js");
CallGraph CG = B.makeCallGraph(B.getOptions());
verifyGraphAssertions(CG, assertionsForWith);
}
*/
public void testCrash1() throws IOException, IllegalArgumentException, CancelException {
CallGraph CG = Util.makeScriptCG("tests", "crash1.js");
verifyGraphAssertions(CG, null);
}
public void testCrash2() throws IOException, IllegalArgumentException, CancelException {
CallGraph CG = Util.makeScriptCG("tests", "crash2.js");
verifyGraphAssertions(CG, null);
}
}

View File

@ -13,5 +13,5 @@
<stringAttribute key="org.eclipse.jdt.junit.TEST_KIND" value="org.eclipse.jdt.junit.loader.junit3"/>
<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="com.ibm.wala.cast.js.test.TestSimpleCallGraphShape"/>
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="com.ibm.wala.cast.js.test"/>
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Xmx256M -Dcom.ibm.wala.tracefile=/tmp/jssimplecg.out"/>
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Xmx256M -Dcom.ibm.wala.tracefile=/tmp/jssimplecg.out -ea"/>
</launchConfiguration>

View File

@ -82,20 +82,30 @@ public class JSAstTranslator extends AstTranslator {
return null;
}
protected int doLexicallyScopedRead(CAstNode n, WalkContext context, String name) {
int readVn = super.doLexicallyScopedRead(n, context, name);
private void addDefinedCheck(CAstNode n, WalkContext context, int readVn) {
context.cfg().addPreNode(n);
context.cfg().addInstruction(new JavaScriptCheckReference(readVn));
CAstNode target = context.getControlFlow().getTarget(n, JavaScriptTypes.ReferenceError);
assert target != null;
context.cfg().addPreEdge(n, target, true);
context.cfg().newBlock(true);
context.cfg().newBlock(true);
}
protected int doLexicallyScopedRead(CAstNode n, WalkContext context, String name) {
int readVn = super.doLexicallyScopedRead(n, context, name);
addDefinedCheck(n, context, readVn);
return readVn;
}
protected int doGlobalRead(CAstNode n, WalkContext context, String name) {
int readVn = super.doGlobalRead(n, context, name);
if (! "undefined".equals(name)) {
addDefinedCheck(n, context, readVn);
}
return readVn;
}
protected void defineType(CAstEntity type, WalkContext wc) {
Assertions.UNREACHABLE("JavaScript doesn't have types. I suggest you look elsewhere for your amusement.");
}
@ -184,9 +194,9 @@ public class JSAstTranslator extends AstTranslator {
typeRef)));
}
protected void doMaterializeFunction(WalkContext context, int result, int exception, CAstEntity fn) {
protected void doMaterializeFunction(CAstNode n, WalkContext context, int result, int exception, CAstEntity fn) {
int nm = context.currentScope().getConstantValue("L"+composeEntityName(context, fn));
int tmp = doGlobalRead(context, "Function");
int tmp = super.doGlobalRead(n, context, "Function");
context.cfg().addInstruction(
new JavaScriptInvoke(tmp, result, new int[]{ nm }, exception,
new JSCallSiteReference(

View File

@ -462,7 +462,7 @@ public class RhinoToAstTranslator {
}
private CAstNode handleNew(WalkContext context, String globalName, Node arguments) {
return handleNew(context, Ast.makeNode(CAstNode.VAR, Ast.makeConstant(globalName)), arguments);
return handleNew(context, readName(context, globalName), arguments);
}
private CAstNode handleNew(WalkContext context, CAstNode value, Node arguments) {
@ -712,6 +712,18 @@ public class RhinoToAstTranslator {
return n;
}
private CAstNode readName(WalkContext context, String name) {
CAstNode cn = Ast.makeNode(CAstNode.VAR, Ast.makeConstant(name));
context.cfg().map(cn, cn);
CAstNode target = context.getCatchTarget();
if (target != null) {
context.cfg().add(cn, target, JavaScriptTypes.ReferenceError);
} else {
context.cfg().add(cn, CAstControlFlowMap.EXCEPTION_TO_EXIT, JavaScriptTypes.ReferenceError);
}
return cn;
}
private CAstNode walkNodesInternal(final Node n, WalkContext context) {
int NT = n.getType();
switch (NT) {
@ -947,17 +959,10 @@ public class RhinoToAstTranslator {
}
}
case Token.BINDNAME:
case Token.NAME: {
CAstNode cn = Ast.makeNode(CAstNode.VAR, Ast.makeConstant(n.getString()));
context.cfg().map(n, cn);
CAstNode target = context.getCatchTarget();
if (target != null) {
context.cfg().add(n, target, JavaScriptTypes.ReferenceError);
} else {
context.cfg().add(n, CAstControlFlowMap.EXCEPTION_TO_EXIT, JavaScriptTypes.ReferenceError);
}
return cn;
}
return readName(context, n.getString());
}
case Token.THIS: {
return Ast.makeNode(CAstNode.VAR, Ast.makeConstant("this"));
@ -1024,8 +1029,8 @@ public class RhinoToAstTranslator {
case Token.VAR: {
Node nm = n.getFirstChild();
context.addInitializer(Ast.makeNode(CAstNode.DECL_STMT, Ast.makeConstant(new CAstSymbolImpl(nm.getString())), Ast.makeNode(
CAstNode.VAR, Ast.makeConstant("undefined"))));
context.addInitializer(Ast.makeNode(CAstNode.DECL_STMT, Ast.makeConstant(new CAstSymbolImpl(nm.getString())),
readName(context, "undefined")));
if (nm.getFirstChild() != null) {
WalkContext child = new ExpressionContext(context);
@ -1083,10 +1088,6 @@ public class RhinoToAstTranslator {
return Ast.makeNode(CAstNode.ASSIGN, walkNodes(nm, context), walkNodes(nm.getNext(), context));
}
case Token.BINDNAME: {
return Ast.makeNode(CAstNode.VAR, Ast.makeConstant(n.getString()));
}
case Token.IFNE:
case Token.IFEQ: {
context.cfg().add(n, ((Node.Jump) n).target, Boolean.TRUE);

View File

@ -84,7 +84,7 @@ public abstract class AstTranslator extends CAstVisitor implements ArrayOpHandle
protected abstract void doFieldWrite(WalkContext context, int receiver, CAstNode elt, CAstNode parent, int rval);
protected abstract void doMaterializeFunction(WalkContext context, int result, int exception, CAstEntity fn);
protected abstract void doMaterializeFunction(CAstNode node, WalkContext context, int result, int exception, CAstEntity fn);
protected abstract void doNewObject(WalkContext context, CAstNode newNode, int result, Object type, int[] arguments);
@ -192,7 +192,7 @@ public abstract class AstTranslator extends CAstVisitor implements ArrayOpHandle
}
}
protected int doGlobalRead(WalkContext context, String name) {
protected int doGlobalRead(CAstNode node, WalkContext context, String name) {
Symbol S = context.currentScope().lookup(name);
// Global variables can be treated as lexicals defined in the CG root, or
@ -2445,7 +2445,7 @@ public abstract class AstTranslator extends CAstVisitor implements ArrayOpHandle
declareFunction(fn, context);
int result = context.currentScope().allocateTempValue();
int ex = context.currentScope().allocateTempValue();
doMaterializeFunction(context, result, ex, fn);
doMaterializeFunction(n, context, result, ex, fn);
return result;
}
@ -2596,7 +2596,7 @@ public abstract class AstTranslator extends CAstVisitor implements ArrayOpHandle
Symbol s = context.currentScope().lookup(nm);
assert s != null : "cannot find symbol for " + nm + " at " + CAstPrinter.print(n, context.getSourceMap());
if (context.currentScope().isGlobal(s)) {
setValue(n, doGlobalRead(context, nm));
setValue(n, doGlobalRead(n, context, nm));
} else if (context.currentScope().isLexicallyScoped(s)) {
setValue(n, doLexicallyScopedRead(n, context, nm));
} else {
@ -3078,7 +3078,7 @@ public abstract class AstTranslator extends CAstVisitor implements ArrayOpHandle
int temp;
if (context.currentScope().isGlobal(ls))
temp = doGlobalRead(context, nm);
temp = doGlobalRead(n, context, nm);
else if (context.currentScope().isLexicallyScoped(ls)) {
temp = doLexicallyScopedRead(n, context, nm);
} else {

View File

@ -137,6 +137,8 @@ public class CAstControlFlowRecorder implements CAstControlFlowMap {
* using this call.
*/
public void map(Object node, CAstNode ast) {
assert node != null;
assert ast != null;
assert ! nodeToCAst.containsKey(node) : node + " already mapped:\n" + this;
assert ! CAstToNode.containsKey(ast) : ast + " already mapped:\n" + this;
nodeToCAst.put(node, ast);

View File

@ -72,7 +72,7 @@ public class CAstPrinter {
case CAstNode.ANDOR_EXPR: return "ANDOR_EXPR";
case CAstNode.NEW: return "NEW";
case CAstNode.NEW_ENCLOSING: return "NEW_ENCLOSING";
case CAstNode.OBJECT_LITERAL: return "LITERAL";
case CAstNode.OBJECT_LITERAL: return "OBJECT_LITERAL";
case CAstNode.VAR: return "VAR";
case CAstNode.OBJECT_REF: return "OBJECT_REF";
case CAstNode.CHOICE_EXPR: return "CHOICE_EXPR";