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:
parent
62a1089c41
commit
9979d0899c
|
@ -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!");
|
||||
}
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
var standalone = false;
|
||||
try {
|
||||
document; // ReferenceError
|
||||
} catch(error) {
|
||||
standalone = true;
|
||||
}
|
||||
assert(standalone);
|
|
@ -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);
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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";
|
||||
|
|
Loading…
Reference in New Issue