Merge branch 'github_master' into internal_merge

This commit is contained in:
Manu Sridharan 2012-08-21 16:57:27 -07:00
commit bb2c45803c
342 changed files with 16092 additions and 18247 deletions

1
.gitignore vendored
View File

@ -10,3 +10,4 @@ com.ibm.wala.core.testdata/@dot/
com.ibm.wala.core.testdata/lib/ com.ibm.wala.core.testdata/lib/
com.ibm.wala.core/dat/wala.properties com.ibm.wala.core/dat/wala.properties
com.ibm.wala.cast.js.html.nu_validator/lib/ com.ibm.wala.cast.js.html.nu_validator/lib/
com.ibm.wala.cast.java.test/testdata/

View File

@ -1,5 +1,2 @@
This is a mirror of the <a This is the main source repository for WALA. For more details on WALA, see <a
href="http://wala.svn.sourceforge.net/viewvc/wala/">WALA SVN repository</a>. It href="http://wala.sourceforge.net">the WALA home page</a>.
is maintained manually for now, but more official support may be added in the
future. For more details on WALA, see <a href="http://wala.sourceforge.net">the
WALA home page</a>.

View File

@ -5,18 +5,18 @@ Bundle-SymbolicName: com.ibm.wala.cast.java.jdt.test
Bundle-Version: 1.0.0 Bundle-Version: 1.0.0
Bundle-Activator: com.ibm.wala.cast.java.jdt.test.Activator Bundle-Activator: com.ibm.wala.cast.java.jdt.test.Activator
Bundle-Vendor: IBM Bundle-Vendor: IBM
Require-Bundle: com.ibm.wala.cast;bundle-version="1.0.0", Require-Bundle: com.ibm.wala.cast.java.test;bundle-version="1.0.0",
com.ibm.wala.cast.java;bundle-version="1.0.0",
com.ibm.wala.cast.java.test;bundle-version="1.0.0",
com.ibm.wala.cast.test;bundle-version="1.0.0", com.ibm.wala.cast.test;bundle-version="1.0.0",
com.ibm.wala.core;bundle-version="1.1.3", com.ibm.wala.ide.tests;bundle-version="1.1.3",
com.ibm.wala.core.tests;bundle-version="1.1.3", com.ibm.wala.core.tests;bundle-version="1.1.3",
com.ibm.wala.cast.java.jdt;bundle-version="1.0.0", com.ibm.wala.cast.java.jdt;bundle-version="1.0.0",
org.eclipse.core.runtime, com.ibm.wala.cast.java;bundle-version="1.0.0",
com.ibm.wala.cast;bundle-version="1.0.0",
com.ibm.wala.ide;bundle-version="1.1.3", com.ibm.wala.ide;bundle-version="1.1.3",
com.ibm.wala.core;bundle-version="1.1.3",
org.eclipse.core.resources;bundle-version="3.4.1", org.eclipse.core.resources;bundle-version="3.4.1",
com.ibm.wala.ide.tests;bundle-version="1.1.3",
org.eclipse.jdt.core;bundle-version="3.4.2", org.eclipse.jdt.core;bundle-version="3.4.2",
org.junit4;bundle-version="4.3.1" org.junit4;bundle-version="4.8.1",
org.eclipse.core.runtime
Bundle-ActivationPolicy: lazy Bundle-ActivationPolicy: lazy
Bundle-RequiredExecutionEnvironment: J2SE-1.5 Bundle-RequiredExecutionEnvironment: J2SE-1.5

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -24,11 +24,11 @@ import com.ibm.wala.cast.java.test.ide.IDEIRTestUtil;
import com.ibm.wala.core.tests.callGraph.CallGraphTestUtil; import com.ibm.wala.core.tests.callGraph.CallGraphTestUtil;
import com.ibm.wala.core.tests.plugin.CoreTestsPlugin; import com.ibm.wala.core.tests.plugin.CoreTestsPlugin;
import com.ibm.wala.ide.tests.util.EclipseTestUtil; import com.ibm.wala.ide.tests.util.EclipseTestUtil;
import com.ibm.wala.ide.util.EclipseFileProvider;
import com.ibm.wala.ipa.callgraph.AnalysisScope; import com.ibm.wala.ipa.callgraph.AnalysisScope;
import com.ibm.wala.ipa.callgraph.Entrypoint; import com.ibm.wala.ipa.callgraph.Entrypoint;
import com.ibm.wala.ipa.callgraph.impl.Util; import com.ibm.wala.ipa.callgraph.impl.Util;
import com.ibm.wala.ipa.cha.IClassHierarchy; import com.ibm.wala.ipa.cha.IClassHierarchy;
import com.ibm.wala.util.io.FileProvider;
public class JDTJava15IRTests extends IRTests { public class JDTJava15IRTests extends IRTests {
@ -62,7 +62,7 @@ public class JDTJava15IRTests extends IRTests {
}; };
try { try {
engine.setExclusionsFile(FileProvider engine.setExclusionsFile((new EclipseFileProvider())
.getFileFromPlugin(CoreTestsPlugin.getDefault(), CallGraphTestUtil.REGRESSION_EXCLUSIONS).getAbsolutePath()); .getFileFromPlugin(CoreTestsPlugin.getDefault(), CallGraphTestUtil.REGRESSION_EXCLUSIONS).getAbsolutePath());
} catch (IOException e) { } catch (IOException e) {
Assert.assertFalse("Cannot find exclusions file", true); Assert.assertFalse("Cannot find exclusions file", true);

View File

@ -54,11 +54,11 @@ import com.ibm.wala.cast.java.test.ide.IDEIRTestUtil;
import com.ibm.wala.core.tests.callGraph.CallGraphTestUtil; import com.ibm.wala.core.tests.callGraph.CallGraphTestUtil;
import com.ibm.wala.core.tests.plugin.CoreTestsPlugin; import com.ibm.wala.core.tests.plugin.CoreTestsPlugin;
import com.ibm.wala.ide.tests.util.EclipseTestUtil; import com.ibm.wala.ide.tests.util.EclipseTestUtil;
import com.ibm.wala.ide.util.EclipseFileProvider;
import com.ibm.wala.ipa.callgraph.AnalysisScope; import com.ibm.wala.ipa.callgraph.AnalysisScope;
import com.ibm.wala.ipa.callgraph.Entrypoint; import com.ibm.wala.ipa.callgraph.Entrypoint;
import com.ibm.wala.ipa.callgraph.impl.Util; import com.ibm.wala.ipa.callgraph.impl.Util;
import com.ibm.wala.ipa.cha.IClassHierarchy; import com.ibm.wala.ipa.cha.IClassHierarchy;
import com.ibm.wala.util.io.FileProvider;
public class JDTJavaIRTests extends JavaIRTests { public class JDTJavaIRTests extends JavaIRTests {
@ -96,7 +96,7 @@ public class JDTJavaIRTests extends JavaIRTests {
}; };
try { try {
engine.setExclusionsFile(FileProvider engine.setExclusionsFile((new EclipseFileProvider())
.getFileFromPlugin(CoreTestsPlugin.getDefault(), CallGraphTestUtil.REGRESSION_EXCLUSIONS).getAbsolutePath()); .getFileFromPlugin(CoreTestsPlugin.getDefault(), CallGraphTestUtil.REGRESSION_EXCLUSIONS).getAbsolutePath());
} catch (IOException e) { } catch (IOException e) {
Assert.assertFalse("Cannot find exclusions file", true); Assert.assertFalse("Cannot find exclusions file", true);

View File

@ -128,10 +128,11 @@ import org.eclipse.jdt.core.dom.VariableDeclarationStatement;
import org.eclipse.jdt.core.dom.WhileStatement; import org.eclipse.jdt.core.dom.WhileStatement;
import com.ibm.wala.cast.ir.translator.AstTranslator.InternalCAstSymbol; import com.ibm.wala.cast.ir.translator.AstTranslator.InternalCAstSymbol;
import com.ibm.wala.cast.ir.translator.TranslatorToCAst;
import com.ibm.wala.cast.ir.translator.TranslatorToCAst.DoLoopTranslator;
import com.ibm.wala.cast.java.loader.JavaSourceLoaderImpl; import com.ibm.wala.cast.java.loader.JavaSourceLoaderImpl;
import com.ibm.wala.cast.java.loader.Util; import com.ibm.wala.cast.java.loader.Util;
import com.ibm.wala.cast.java.translator.JavaProcedureEntity; import com.ibm.wala.cast.java.translator.JavaProcedureEntity;
import com.ibm.wala.cast.java.translator.TranslatorToCAst;
import com.ibm.wala.cast.tree.CAst; import com.ibm.wala.cast.tree.CAst;
import com.ibm.wala.cast.tree.CAstControlFlowMap; import com.ibm.wala.cast.tree.CAstControlFlowMap;
import com.ibm.wala.cast.tree.CAstEntity; import com.ibm.wala.cast.tree.CAstEntity;
@ -175,7 +176,7 @@ import com.ibm.wala.util.debug.Assertions;
// * enums (probably in simplename or something. but using resolveConstantExpressionValue() possible) // * enums (probably in simplename or something. but using resolveConstantExpressionValue() possible)
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public class JDTJava2CAstTranslator implements TranslatorToCAst { public class JDTJava2CAstTranslator {
protected final CAst fFactory = new CAstImpl(); protected final CAst fFactory = new CAstImpl();
// /////////////////////////////////////////// // ///////////////////////////////////////////
@ -203,6 +204,8 @@ public class JDTJava2CAstTranslator implements TranslatorToCAst {
protected ITypeBinding OutOfMemoryError; protected ITypeBinding OutOfMemoryError;
protected DoLoopTranslator doLoopTranslator;
private String fullPath; private String fullPath;
private CompilationUnit cu; private CompilationUnit cu;
@ -211,20 +214,7 @@ public class JDTJava2CAstTranslator implements TranslatorToCAst {
// COMPILATION UNITS & TYPES // COMPILATION UNITS & TYPES
// //
public JDTJava2CAstTranslator(JavaSourceLoaderImpl sourceLoader) { public JDTJava2CAstTranslator(JavaSourceLoaderImpl sourceLoader, CompilationUnit astRoot, String fullPath, boolean replicateForDoLoops) {
this.fSourceLoader = sourceLoader;
}
public CAstEntity translate(Object astRoot, String fullPath) {
this.cu = (CompilationUnit) astRoot;
this.fullPath = fullPath;
ast = cu.getAST();
// FIXME: we might need one AST (-> "Object" class) for all files.
fIdentityMapper = new JDTIdentityMapper(fSourceLoader.getReference(), ast);
fTypeDict = new JDTTypeDictionary(ast, fIdentityMapper);
fDivByZeroExcType = FakeExceptionTypeBinding.arithmetic; fDivByZeroExcType = FakeExceptionTypeBinding.arithmetic;
fNullPointerExcType = FakeExceptionTypeBinding.nullPointer; fNullPointerExcType = FakeExceptionTypeBinding.nullPointer;
fClassCastExcType = FakeExceptionTypeBinding.classCast; fClassCastExcType = FakeExceptionTypeBinding.classCast;
@ -232,12 +222,27 @@ public class JDTJava2CAstTranslator implements TranslatorToCAst {
ExceptionInInitializerError = FakeExceptionTypeBinding.initException; ExceptionInInitializerError = FakeExceptionTypeBinding.initException;
OutOfMemoryError = FakeExceptionTypeBinding.outOfMemory; OutOfMemoryError = FakeExceptionTypeBinding.outOfMemory;
this.fSourceLoader = sourceLoader;
this.cu = astRoot;
this.fullPath = fullPath;
ast = cu.getAST();
this.doLoopTranslator = new DoLoopTranslator(replicateForDoLoops, fFactory);
// FIXME: we might need one AST (-> "Object" class) for all files.
fIdentityMapper = new JDTIdentityMapper(fSourceLoader.getReference(), ast);
fTypeDict = new JDTTypeDictionary(ast, fIdentityMapper);
fRuntimeExcType = ast.resolveWellKnownType("java.lang.RuntimeException"); fRuntimeExcType = ast.resolveWellKnownType("java.lang.RuntimeException");
assert fRuntimeExcType != null; assert fRuntimeExcType != null;
}
public CAstEntity translateToCAst() {
List<CAstEntity> declEntities = new ArrayList<CAstEntity>(); List<CAstEntity> declEntities = new ArrayList<CAstEntity>();
for (Iterator iter = cu.types().iterator(); iter.hasNext();) { for (Iterator<CAstEntity> iter = cu.types().iterator(); iter.hasNext();) {
AbstractTypeDeclaration decl = (AbstractTypeDeclaration) iter.next(); AbstractTypeDeclaration decl = (AbstractTypeDeclaration) iter.next();
// can be of type AnnotationTypeDeclaration, EnumDeclaration, TypeDeclaration // can be of type AnnotationTypeDeclaration, EnumDeclaration, TypeDeclaration
declEntities.add(visit(decl, new RootContext())); declEntities.add(visit(decl, new RootContext()));
@ -2095,7 +2100,6 @@ public class JDTJava2CAstTranslator implements TranslatorToCAst {
// //////////////// // ////////////////
private CAstNode visit(LabeledStatement n, WalkContext context) { private CAstNode visit(LabeledStatement n, WalkContext context) {
ASTNode breakTarget = makeBreakOrContinueTarget(n, n.getLabel().getIdentifier());
// find the first non-block statement ant set-up the label map (useful for breaking many fors) // find the first non-block statement ant set-up the label map (useful for breaking many fors)
ASTNode stmt = n.getBody(); ASTNode stmt = n.getBody();
@ -2108,10 +2112,12 @@ public class JDTJava2CAstTranslator implements TranslatorToCAst {
CAstNode result; CAstNode result;
if (!(n.getBody() instanceof EmptyStatement)) { if (!(n.getBody() instanceof EmptyStatement)) {
ASTNode breakTarget = makeBreakOrContinueTarget(n, n.getLabel().getIdentifier());
CAstNode breakNode = visitNode(breakTarget, context);
WalkContext child = new BreakContext(context, n.getLabel().getIdentifier(), breakTarget); WalkContext child = new BreakContext(context, n.getLabel().getIdentifier(), breakTarget);
result = makeNode(context, fFactory, n, CAstNode.BLOCK_STMT, makeNode(context, fFactory, n, CAstNode.LABEL_STMT, fFactory result = makeNode(context, fFactory, n, CAstNode.BLOCK_STMT, makeNode(context, fFactory, n, CAstNode.LABEL_STMT, fFactory
.makeConstant(n.getLabel().getIdentifier()), visitNode(n.getBody(), child)), visitNode(breakTarget, context)); .makeConstant(n.getLabel().getIdentifier()), visitNode(n.getBody(), child)), breakNode);
} else { } else {
result = makeNode(context, fFactory, n, CAstNode.LABEL_STMT, fFactory.makeConstant(n.getLabel().getIdentifier()), visitNode(n result = makeNode(context, fFactory, n, CAstNode.LABEL_STMT, fFactory.makeConstant(n.getLabel().getIdentifier()), visitNode(n
.getBody(), context)); .getBody(), context));
@ -2163,7 +2169,10 @@ public class JDTJava2CAstTranslator implements TranslatorToCAst {
Statement body = n.getBody(); Statement body = n.getBody();
ASTNode breakTarget = makeBreakOrContinueTarget(n, "breakLabel" + n.getStartPosition()); ASTNode breakTarget = makeBreakOrContinueTarget(n, "breakLabel" + n.getStartPosition());
CAstNode breakNode = visitNode(breakTarget, context);
ASTNode continueTarget = makeBreakOrContinueTarget(n, "continueLabel" + n.getStartPosition()); ASTNode continueTarget = makeBreakOrContinueTarget(n, "continueLabel" + n.getStartPosition());
CAstNode continueNode = visitNode(continueTarget, context);
String loopLabel = (String) context.getLabelMap().get(n); String loopLabel = (String) context.getLabelMap().get(n);
LoopContext lc = new LoopContext(context, loopLabel, breakTarget, continueTarget); LoopContext lc = new LoopContext(context, loopLabel, breakTarget, continueTarget);
@ -2172,8 +2181,8 @@ public class JDTJava2CAstTranslator implements TranslatorToCAst {
* The following loop is created sligtly differently than in jscore. It doesn't have a specific target for continue. * The following loop is created sligtly differently than in jscore. It doesn't have a specific target for continue.
*/ */
return makeNode(context, fFactory, n, CAstNode.BLOCK_STMT, makeNode(context, fFactory, n, CAstNode.LOOP, visitNode(cond, return makeNode(context, fFactory, n, CAstNode.BLOCK_STMT, makeNode(context, fFactory, n, CAstNode.LOOP, visitNode(cond,
context), makeNode(context, fFactory, n, CAstNode.BLOCK_STMT, visitNode(body, lc), visitNode(continueTarget, context))), context), makeNode(context, fFactory, n, CAstNode.BLOCK_STMT, visitNode(body, lc), continueNode)),
visitNode(breakTarget, context)); breakNode);
} }
private CAstNode getSwitchCaseConstant(SwitchCase n, WalkContext context) { private CAstNode getSwitchCaseConstant(SwitchCase n, WalkContext context) {
@ -2282,22 +2291,21 @@ public class JDTJava2CAstTranslator implements TranslatorToCAst {
} }
private CAstNode visit(DoStatement n, WalkContext context) { private CAstNode visit(DoStatement n, WalkContext context) {
ASTNode header = ast.newEmptyStatement();
ASTNode breakTarget = makeBreakOrContinueTarget(n, "breakLabel" + n.getStartPosition());
ASTNode continueTarget = makeBreakOrContinueTarget(n, "continue" + "Label" + n.getStartPosition());
CAstNode loopGoto = makeNode(context, fFactory, n, CAstNode.IFGOTO, visitNode(n.getExpression(), context));
context.cfg().map(loopGoto, loopGoto);
context.cfg().add(loopGoto, header, Boolean.TRUE);
String loopLabel = (String) context.getLabelMap().get(n); // set by visit(LabeledStatement) String loopLabel = (String) context.getLabelMap().get(n); // set by visit(LabeledStatement)
WalkContext loopContext = new LoopContext(context, loopLabel, breakTarget, continueTarget); String token = loopLabel==null? "at_" + n.getStartPosition(): loopLabel;
ASTNode breakTarget = makeBreakOrContinueTarget(n, "breakLabel_" + token);
CAstNode breakNode = visitNode(breakTarget, context);
ASTNode continueTarget = makeBreakOrContinueTarget(n, "continueLabel_" + token);
CAstNode continueNode = visitNode(continueTarget, context); CAstNode continueNode = visitNode(continueTarget, context);
return makeNode(context, fFactory, n, CAstNode.BLOCK_STMT, visitNode(header, context), makeNode(context, fFactory, n, CAstNode loopTest = visitNode(n.getExpression(), context);
CAstNode.BLOCK_STMT, visitNode(n.getBody(), loopContext), continueNode), loopGoto, visitNode(breakTarget, context));
WalkContext loopContext = new LoopContext(context, loopLabel, breakTarget, continueTarget);
CAstNode loopBody = visitNode(n.getBody(), loopContext);
return doLoopTranslator.translateDoLoop(loopTest, loopBody, continueNode, breakNode, context);
} }
/** /**
@ -2861,7 +2869,6 @@ public class JDTJava2CAstTranslator implements TranslatorToCAst {
} }
public CAstSourcePositionMap.Position getPosition() { public CAstSourcePositionMap.Position getPosition() {
Assertions.UNREACHABLE("CompilationUnitEntity.getPosition()");
return null; return null;
} }
@ -2889,24 +2896,12 @@ public class JDTJava2CAstTranslator implements TranslatorToCAst {
* Contains things needed by in the visit() of some nodes to process the nodes. For example, pos() contains the source position * Contains things needed by in the visit() of some nodes to process the nodes. For example, pos() contains the source position
* mapping which each node registers * mapping which each node registers
*/ */
public static interface WalkContext { public static interface WalkContext extends TranslatorToCAst.WalkContext<WalkContext, ASTNode> {
// LEFTOUT: plenty of stuff
public CAstControlFlowRecorder cfg();
public void addScopedEntity(CAstNode newNode, CAstEntity visit);
public Collection<Pair<ITypeBinding, Object>> getCatchTargets(ITypeBinding type); public Collection<Pair<ITypeBinding, Object>> getCatchTargets(ITypeBinding type);
public CAstSourcePositionRecorder pos();
public CAstNodeTypeMapRecorder getNodeTypeMap();
public Map<ASTNode, String> getLabelMap(); public Map<ASTNode, String> getLabelMap();
public ASTNode getContinueFor(String label);
public ASTNode getBreakFor(String label);
public boolean needLValue(); public boolean needLValue();
} }
@ -2914,45 +2909,20 @@ public class JDTJava2CAstTranslator implements TranslatorToCAst {
* Default context functions. When one context doesn't handle something, it the next one up does. For example, there is only one * Default context functions. When one context doesn't handle something, it the next one up does. For example, there is only one
* source pos. mapping per MethodContext, so loop contexts delegate it up. * source pos. mapping per MethodContext, so loop contexts delegate it up.
*/ */
public static class DelegatingContext implements WalkContext { public static class DelegatingContext extends TranslatorToCAst.DelegatingContext<WalkContext, ASTNode> implements WalkContext {
protected WalkContext parent;
public DelegatingContext(WalkContext parent) { public DelegatingContext(WalkContext parent) {
this.parent = parent; super(parent);
}
public CAstControlFlowRecorder cfg() {
return parent.cfg();
}
public CAstSourcePositionRecorder pos() {
return parent.pos();
}
public CAstNodeTypeMapRecorder getNodeTypeMap() {
return parent.getNodeTypeMap();
} }
public Collection<Pair<ITypeBinding, Object>> getCatchTargets(ITypeBinding type) { public Collection<Pair<ITypeBinding, Object>> getCatchTargets(ITypeBinding type) {
return parent.getCatchTargets(type); return parent.getCatchTargets(type);
} }
public void addScopedEntity(CAstNode newNode, CAstEntity visit) {
parent.addScopedEntity(newNode, visit);
}
public Map<ASTNode, String> getLabelMap() { public Map<ASTNode, String> getLabelMap() {
return parent.getLabelMap(); return parent.getLabelMap();
} }
public ASTNode getContinueFor(String label) {
return parent.getContinueFor(label);
}
public ASTNode getBreakFor(String label) {
return parent.getBreakFor(label);
}
public boolean needLValue() { public boolean needLValue() {
return parent.needLValue(); return parent.needLValue();
} }
@ -2961,26 +2931,7 @@ public class JDTJava2CAstTranslator implements TranslatorToCAst {
/* /*
* Root context. Doesn't do anything. * Root context. Doesn't do anything.
*/ */
public static class RootContext implements WalkContext { public static class RootContext extends TranslatorToCAst.RootContext<WalkContext, ASTNode> implements WalkContext {
public void addScopedEntity(CAstNode newNode, CAstEntity visit) {
Assertions.UNREACHABLE("Rootcontext.addScopedEntity()");
}
public CAstControlFlowRecorder cfg() {
Assertions.UNREACHABLE("RootContext.cfg()");
return null;
}
public CAstSourcePositionRecorder pos() {
Assertions.UNREACHABLE("RootContext.pos()");
return null;
}
public CAstNodeTypeMapRecorder getNodeTypeMap() {
Assertions.UNREACHABLE("RootContext.getNodeTypeMap()");
return null;
}
public Collection<Pair<ITypeBinding, Object>> getCatchTargets(ITypeBinding type) { public Collection<Pair<ITypeBinding, Object>> getCatchTargets(ITypeBinding type) {
Assertions.UNREACHABLE("RootContext.getCatchTargets()"); Assertions.UNREACHABLE("RootContext.getCatchTargets()");
return null; return null;
@ -2991,16 +2942,6 @@ public class JDTJava2CAstTranslator implements TranslatorToCAst {
return null; return null;
} }
public ASTNode getBreakFor(String label) {
Assertions.UNREACHABLE("RootContext.getBreakFor()");
return null;
}
public ASTNode getContinueFor(String label) {
Assertions.UNREACHABLE("RootContext.getContinueFor()");
return null;
}
public boolean needLValue() { public boolean needLValue() {
Assertions.UNREACHABLE("Rootcontext.needLValue()"); Assertions.UNREACHABLE("Rootcontext.needLValue()");
return false; return false;

View File

@ -115,8 +115,6 @@ public class JDTSourceModuleTranslator implements SourceModuleTranslator {
public void loadAllSources(Set<ModuleEntry> modules) { public void loadAllSources(Set<ModuleEntry> modules) {
// TODO: we might need one AST (-> "Object" class) for all files. // TODO: we might need one AST (-> "Object" class) for all files.
// TODO: group by project and send 'em in // TODO: group by project and send 'em in
JDTJava2CAstTranslator jdt2cast = makeCAstTranslator();
final Java2IRTranslator java2ir = makeIRTranslator(jdt2cast);
System.out.println(modules); System.out.println(modules);
@ -143,7 +141,9 @@ public class JDTSourceModuleTranslator implements SourceModuleTranslator {
public void acceptAST(ICompilationUnit source, CompilationUnit ast) { public void acceptAST(ICompilationUnit source, CompilationUnit ast) {
try { try {
java2ir.translate(proj.getValue().get(source), ast, source.getUnderlyingResource().getLocation().toOSString()); JDTJava2CAstTranslator jdt2cast = makeCAstTranslator(ast, source.getUnderlyingResource().getLocation().toOSString());
final Java2IRTranslator java2ir = makeIRTranslator();
java2ir.translate(proj.getValue().get(source), jdt2cast.translateToCAst());
} catch (JavaModelException e) { } catch (JavaModelException e) {
e.printStackTrace(); e.printStackTrace();
} }
@ -165,12 +165,12 @@ public class JDTSourceModuleTranslator implements SourceModuleTranslator {
} }
} }
protected Java2IRTranslator makeIRTranslator(JDTJava2CAstTranslator jdt2cast) { protected Java2IRTranslator makeIRTranslator() {
return new Java2IRTranslator(jdt2cast, sourceLoader); return new Java2IRTranslator(sourceLoader);
} }
protected JDTJava2CAstTranslator makeCAstTranslator() { protected JDTJava2CAstTranslator makeCAstTranslator(CompilationUnit cu, String fullPath) {
return new JDTJava2CAstTranslator(sourceLoader); return new JDTJava2CAstTranslator(sourceLoader, cu, fullPath, false);
} }
} }

View File

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<classpath> <classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/> <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="src" path="source"/> <classpathentry kind="src" path="source"/>
<classpathentry kind="lib" path="/com.ibm.wala.cast.java.polyglot/lib/polyglot.jar"/> <classpathentry kind="lib" path="/com.ibm.wala.cast.java.polyglot/lib/polyglot.jar"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="output" path="bin"/> <classpathentry kind="output" path="bin"/>
</classpath> </classpath>

View File

@ -1,10 +1,5 @@
#Thu Feb 03 10:12:26 EST 2011 #Mon Jul 02 13:01:58 EDT 2012
eclipse.preferences.version=1 eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
org.eclipse.jdt.core.compiler.compliance=1.5
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.source=1.5
org.eclipse.jdt.core.formatter.align_type_members_on_columns=false org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<launchConfiguration type="org.eclipse.jdt.junit.launchconfig"> <launchConfiguration type="org.eclipse.jdt.junit.launchconfig">
<stringAttribute key="bad_container_name" value="/com.ibm.wala.cast.java.polyglottest/launchers"/> <stringAttribute key="bad_container_name" value="/com.ibm.wala.cast.java.polyglottest/launchers"/>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS"> <listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
@ -13,5 +13,6 @@
<stringAttribute key="org.eclipse.jdt.junit.TEST_KIND" value="org.eclipse.jdt.junit.loader.junit4"/> <stringAttribute key="org.eclipse.jdt.junit.TEST_KIND" value="org.eclipse.jdt.junit.loader.junit4"/>
<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="com.ibm.wala.cast.java.test.PolyglotJavaIRTests"/> <stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="com.ibm.wala.cast.java.test.PolyglotJavaIRTests"/>
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="com.ibm.wala.cast.java.polyglot.test"/> <stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="com.ibm.wala.cast.java.polyglot.test"/>
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-ea -Xmx512M"/>
<stringAttribute key="org.eclipse.jdt.launching.WORKING_DIRECTORY" value="${workspace_loc:com.ibm.wala.cast.java.test.data}"/> <stringAttribute key="org.eclipse.jdt.launching.WORKING_DIRECTORY" value="${workspace_loc:com.ibm.wala.cast.java.test.data}"/>
</launchConfiguration> </launchConfiguration>

View File

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<classpath> <classpath>
<classpathentry kind="src" path="source"/> <classpathentry kind="src" path="source"/>
<classpathentry exported="true" kind="lib" path="lib/polyglot.jar"/> <classpathentry kind="lib" path="lib/polyglot.jar"/>
<classpathentry exported="true" kind="lib" path="lib/java_cup.jar"/> <classpathentry kind="lib" path="lib/java_cup.jar"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/> <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/> <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
<classpathentry kind="output" path="bin"/> <classpathentry kind="output" path="bin"/>

View File

@ -1,10 +1,5 @@
#Mon Apr 13 15:38:50 EDT 2009 #Mon Apr 16 10:59:09 EDT 2012
eclipse.preferences.version=1 eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
org.eclipse.jdt.core.compiler.compliance=1.5
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.source=1.5
org.eclipse.jdt.core.formatter.align_type_members_on_columns=false org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16

View File

@ -25,7 +25,8 @@ import com.ibm.wala.classLoader.BinaryDirectoryTreeModule;
import com.ibm.wala.classLoader.ClassLoaderFactory; import com.ibm.wala.classLoader.ClassLoaderFactory;
import com.ibm.wala.classLoader.Module; import com.ibm.wala.classLoader.Module;
import com.ibm.wala.classLoader.SourceDirectoryTreeModule; import com.ibm.wala.classLoader.SourceDirectoryTreeModule;
import com.ibm.wala.core.plugin.CorePlugin; import com.ibm.wala.ide.plugin.CorePlugin;
import com.ibm.wala.ide.util.EclipseFileProvider;
import com.ibm.wala.ide.util.EclipseProjectPath; import com.ibm.wala.ide.util.EclipseProjectPath;
import com.ibm.wala.ide.util.EclipseProjectPath.Loader; import com.ibm.wala.ide.util.EclipseProjectPath.Loader;
import com.ibm.wala.ipa.callgraph.AnalysisCache; import com.ibm.wala.ipa.callgraph.AnalysisCache;
@ -64,7 +65,7 @@ public class EclipseProjectSourceAnalysisEngine extends EclipseProjectAnalysisEn
super(project); super(project);
this.fileExt = fileExt; this.fileExt = fileExt;
try { try {
setExclusionsFile(FileProvider.getFileFromPlugin(CorePlugin.getDefault(), "J2SEClassHierarchyExclusions.txt") setExclusionsFile((new EclipseFileProvider()).getFileFromPlugin(CorePlugin.getDefault(), "J2SEClassHierarchyExclusions.txt")
.getAbsolutePath()); .getAbsolutePath());
} catch (IOException e) { } catch (IOException e) {
Assertions.UNREACHABLE("Cannot find exclusions file"); Assertions.UNREACHABLE("Cannot find exclusions file");

View File

@ -51,16 +51,18 @@ public class IRGoal extends SourceGoal_c /* PORT1.7 removed 'implements EndGoal'
ExtensionInfo extInfo= job.extensionInfo(); ExtensionInfo extInfo= job.extensionInfo();
fTranslator= new Java2IRTranslator( fTranslator= new Java2IRTranslator(
fSourceLoader,
((IRTranslatorExtension)extInfo).getCAstRewriterFactory());
ModuleSource src = (ModuleSource) job.source();
fTranslator.translate(
src.getModule(),
new PolyglotJava2CAstTranslator( new PolyglotJava2CAstTranslator(
job.ast(),
fSourceLoader.getReference(), fSourceLoader.getReference(),
extInfo.nodeFactory(), extInfo.nodeFactory(),
extInfo.typeSystem(), extInfo.typeSystem(),
new PolyglotIdentityMapper(fSourceLoader.getReference()), new PolyglotIdentityMapper(fSourceLoader.getReference()),
((IRTranslatorExtension)extInfo).getReplicateForDoLoops()), ((IRTranslatorExtension)extInfo).getReplicateForDoLoops()).translateToCAst());
fSourceLoader,
((IRTranslatorExtension)extInfo).getCAstRewriterFactory());
ModuleSource src = (ModuleSource) job.source();
fTranslator.translate(src.getModule(),job.ast(), src.name());
return true; return true;
} }

View File

@ -20,6 +20,7 @@ import java.net.URL;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
@ -34,6 +35,7 @@ import polyglot.ast.ArrayTypeNode;
import polyglot.ast.Assert; import polyglot.ast.Assert;
import polyglot.ast.Assign; import polyglot.ast.Assign;
import polyglot.ast.Binary; import polyglot.ast.Binary;
import polyglot.ast.Binary.Operator;
import polyglot.ast.Block; import polyglot.ast.Block;
import polyglot.ast.BooleanLit; import polyglot.ast.BooleanLit;
import polyglot.ast.Branch; import polyglot.ast.Branch;
@ -49,6 +51,7 @@ import polyglot.ast.ClassLit;
import polyglot.ast.ClassMember; import polyglot.ast.ClassMember;
import polyglot.ast.Conditional; import polyglot.ast.Conditional;
import polyglot.ast.ConstructorCall; import polyglot.ast.ConstructorCall;
import polyglot.ast.ConstructorCall.Kind;
import polyglot.ast.ConstructorDecl; import polyglot.ast.ConstructorDecl;
import polyglot.ast.Do; import polyglot.ast.Do;
import polyglot.ast.Empty; import polyglot.ast.Empty;
@ -94,8 +97,6 @@ import polyglot.ast.TopLevelDecl;
import polyglot.ast.Try; import polyglot.ast.Try;
import polyglot.ast.Unary; import polyglot.ast.Unary;
import polyglot.ast.While; import polyglot.ast.While;
import polyglot.ast.Binary.Operator;
import polyglot.ast.ConstructorCall.Kind;
import polyglot.types.ArrayType; import polyglot.types.ArrayType;
import polyglot.types.ClassType; import polyglot.types.ClassType;
import polyglot.types.CodeInstance; import polyglot.types.CodeInstance;
@ -117,9 +118,11 @@ import polyglot.types.Types;
import polyglot.util.Position; import polyglot.util.Position;
import com.ibm.wala.cast.ir.translator.AstTranslator.InternalCAstSymbol; import com.ibm.wala.cast.ir.translator.AstTranslator.InternalCAstSymbol;
import com.ibm.wala.cast.ir.translator.TranslatorToCAst;
import com.ibm.wala.cast.ir.translator.TranslatorToCAst.DoLoopTranslator;
import com.ibm.wala.cast.ir.translator.TranslatorToCAst.WalkContext;
import com.ibm.wala.cast.java.loader.Util; import com.ibm.wala.cast.java.loader.Util;
import com.ibm.wala.cast.java.translator.JavaProcedureEntity; import com.ibm.wala.cast.java.translator.JavaProcedureEntity;
import com.ibm.wala.cast.java.translator.TranslatorToCAst;
import com.ibm.wala.cast.java.types.JavaType; import com.ibm.wala.cast.java.types.JavaType;
import com.ibm.wala.cast.tree.CAst; import com.ibm.wala.cast.tree.CAst;
import com.ibm.wala.cast.tree.CAstControlFlowMap; import com.ibm.wala.cast.tree.CAstControlFlowMap;
@ -132,12 +135,10 @@ import com.ibm.wala.cast.tree.CAstSymbol;
import com.ibm.wala.cast.tree.CAstType; import com.ibm.wala.cast.tree.CAstType;
import com.ibm.wala.cast.tree.CAstTypeDictionary; import com.ibm.wala.cast.tree.CAstTypeDictionary;
import com.ibm.wala.cast.tree.impl.AbstractSourcePosition; import com.ibm.wala.cast.tree.impl.AbstractSourcePosition;
import com.ibm.wala.cast.tree.impl.CAstCloner;
import com.ibm.wala.cast.tree.impl.CAstControlFlowRecorder; import com.ibm.wala.cast.tree.impl.CAstControlFlowRecorder;
import com.ibm.wala.cast.tree.impl.CAstImpl; import com.ibm.wala.cast.tree.impl.CAstImpl;
import com.ibm.wala.cast.tree.impl.CAstNodeTypeMapRecorder; import com.ibm.wala.cast.tree.impl.CAstNodeTypeMapRecorder;
import com.ibm.wala.cast.tree.impl.CAstOperator; import com.ibm.wala.cast.tree.impl.CAstOperator;
import com.ibm.wala.cast.tree.impl.CAstRewriter;
import com.ibm.wala.cast.tree.impl.CAstSourcePositionRecorder; import com.ibm.wala.cast.tree.impl.CAstSourcePositionRecorder;
import com.ibm.wala.cast.tree.impl.CAstSymbolImpl; import com.ibm.wala.cast.tree.impl.CAstSymbolImpl;
import com.ibm.wala.classLoader.CallSiteReference; import com.ibm.wala.classLoader.CallSiteReference;
@ -155,8 +156,7 @@ import com.ibm.wala.util.collections.IteratorPlusOne;
import com.ibm.wala.util.collections.Pair; import com.ibm.wala.util.collections.Pair;
import com.ibm.wala.util.debug.Assertions; import com.ibm.wala.util.debug.Assertions;
@SuppressWarnings("unchecked") public class PolyglotJava2CAstTranslator {
public class PolyglotJava2CAstTranslator implements TranslatorToCAst {
protected final CAst fFactory = new CAstImpl(); protected final CAst fFactory = new CAstImpl();
protected final NodeFactory fNodeFactory; protected final NodeFactory fNodeFactory;
@ -179,10 +179,12 @@ public class PolyglotJava2CAstTranslator implements TranslatorToCAst {
protected PolyglotIdentityMapper fIdentityMapper; protected PolyglotIdentityMapper fIdentityMapper;
protected boolean replicateForDoLoops = false; protected final DoLoopTranslator doLoopTranslator;
protected final boolean DEBUG = true; protected final boolean DEBUG = true;
private final Node ast;
final protected TranslatingVisitor getTranslator() { final protected TranslatingVisitor getTranslator() {
if (fTranslator == null) if (fTranslator == null)
fTranslator = createTranslator(); fTranslator = createTranslator();
@ -1133,42 +1135,17 @@ public class PolyglotJava2CAstTranslator implements TranslatorToCAst {
String loopLabel = (String) wc.getLabelMap().get(d); String loopLabel = (String) wc.getLabelMap().get(d);
CAstNode continueNode = walkNodes(continueTarget, wc); CAstNode continueNode = walkNodes(continueTarget, wc);
CAstNode breakBody = walkNodes(breakTarget, wc); CAstNode breakNode = walkNodes(breakTarget, wc);
WalkContext lc = new LoopContext(wc, loopLabel, breakTarget, continueTarget); WalkContext lc = new LoopContext(wc, loopLabel, breakTarget, continueTarget);
CAstNode loopExpr = walkNodes(d.cond(), wc);
CAstNode loopBody = walkNodes(d.body(), lc); CAstNode loopBody = walkNodes(d.body(), lc);
if (replicateForDoLoops) { return doLoopTranslator.translateDoLoop(loopExpr, loopBody, continueNode, breakNode, wc);
CAstRewriter.Rewrite x = (new CAstCloner(fFactory, false)).copy(loopBody, wc.cfg(), wc.pos(), wc.getNodeTypeMap(), null);
CAstNode otherBody = x.newRoot();
wc.cfg().addAll(x.newCfg());
wc.pos().addAll(x.newPos());
wc.getNodeTypeMap().addAll(x.newTypes());
return makeNode(wc, fFactory, d, CAstNode.BLOCK_STMT,
loopBody,
makeNode(wc, fFactory, d, CAstNode.LOOP,
walkNodes(d.cond(), wc),
makeNode(wc, fFactory, d, CAstNode.BLOCK_STMT, otherBody, continueNode)),
breakBody);
} else {
Node header = fNodeFactory.Empty(Position.COMPILER_GENERATED);
CAstNode loopGoto = makeNode(wc, fFactory, d, CAstNode.IFGOTO, walkNodes(d.cond(), wc));
wc.cfg().map(loopGoto, loopGoto);
wc.cfg().add(loopGoto, header, Boolean.TRUE);
return makeNode(wc, fFactory, d, CAstNode.BLOCK_STMT,
walkNodes(header, wc),
makeNode(wc, fFactory, d, CAstNode.BLOCK_STMT, loopBody, continueNode),
loopGoto,
breakBody);
}
} }
public CAstNode visit(For f, WalkContext wc) { public CAstNode visit(For f, WalkContext wc) {
Node breakTarget = makeBreakTarget(f); Node breakTarget = makeBreakTarget(f);
Node continueTarget = makeContinueTarget(f); Node continueTarget = makeContinueTarget(f);
@ -1434,7 +1411,6 @@ public class PolyglotJava2CAstTranslator implements TranslatorToCAst {
} }
public CAstSourcePositionMap.Position getPosition() { public CAstSourcePositionMap.Position getPosition() {
Assertions.UNREACHABLE("CompilationUnitEntity.getPosition()");
return null; return null;
} }
@ -1529,12 +1505,8 @@ public class PolyglotJava2CAstTranslator implements TranslatorToCAst {
protected abstract static class CodeBodyEntity implements CAstEntity { protected abstract static class CodeBodyEntity implements CAstEntity {
private final Map<CAstNode, Collection<CAstEntity>> fEntities; private final Map<CAstNode, Collection<CAstEntity>> fEntities;
public CodeBodyEntity(Map<CAstNode, CAstEntity> entities) { public CodeBodyEntity(Map<CAstNode, Collection<CAstEntity>> entities) {
fEntities = new LinkedHashMap<CAstNode, Collection<CAstEntity>>(); fEntities = new LinkedHashMap<CAstNode, Collection<CAstEntity>>(entities);
for (Iterator<CAstNode> keys = entities.keySet().iterator(); keys.hasNext();) {
CAstNode key = keys.next();
fEntities.put(key, Collections.singleton(entities.get(key)));
}
} }
public Map<CAstNode, Collection<CAstEntity>> getAllScopedEntities() { public Map<CAstNode, Collection<CAstEntity>> getAllScopedEntities() {
@ -1674,7 +1646,7 @@ public class PolyglotJava2CAstTranslator implements TranslatorToCAst {
private final String[] argumentNames; private final String[] argumentNames;
public ProcedureEntity(CAstNode pdast, TypeSystem system, CodeInstance pd, Type declaringType, String[] argumentNames, public ProcedureEntity(CAstNode pdast, TypeSystem system, CodeInstance pd, Type declaringType, String[] argumentNames,
Map<CAstNode, CAstEntity> entities, MethodContext mc) { Map<CAstNode, Collection<CAstEntity>> entities, MethodContext mc) {
super(entities); super(entities);
fPdast = pdast; fPdast = pdast;
fSystem = system; fSystem = system;
@ -1685,7 +1657,7 @@ public class PolyglotJava2CAstTranslator implements TranslatorToCAst {
} }
public ProcedureEntity(CAstNode pdast, TypeSystem system, CodeInstance pd, String[] argumentNames, public ProcedureEntity(CAstNode pdast, TypeSystem system, CodeInstance pd, String[] argumentNames,
Map<CAstNode, CAstEntity> entities, MethodContext mc) { Map<CAstNode, Collection<CAstEntity>> entities, MethodContext mc) {
//PORT1.7 used to be this(pdast, system, pd, ((MemberInstance) pd).container(), argumentNames, entities, mc); //PORT1.7 used to be this(pdast, system, pd, ((MemberInstance) pd).container(), argumentNames, entities, mc);
this(pdast, system, pd, ((MemberDef) pd.def()).container().get(), argumentNames, entities, mc); this(pdast, system, pd, ((MemberDef) pd.def()).container().get(), argumentNames, entities, mc);
} }
@ -1916,21 +1888,9 @@ public class PolyglotJava2CAstTranslator implements TranslatorToCAst {
} }
} }
public interface WalkContext { public interface WalkContext extends TranslatorToCAst.WalkContext<WalkContext, Node> {
void addScopedEntity(CAstNode node, CAstEntity e);
CAstControlFlowRecorder cfg();
CAstSourcePositionRecorder pos();
CAstNodeTypeMapRecorder getNodeTypeMap();
Collection<Pair<Type, Object>> getCatchTargets(Type label); Collection<Pair<Type, Object>> getCatchTargets(Type label);
Node getContinueFor(String label);
Node getBreakFor(String label);
Node getFinally(); Node getFinally();
CodeInstance getEnclosingMethod(); CodeInstance getEnclosingMethod();
@ -1948,49 +1908,15 @@ public class PolyglotJava2CAstTranslator implements TranslatorToCAst {
boolean needLVal(); boolean needLVal();
} }
protected static class DelegatingContext implements WalkContext { protected static class DelegatingContext extends TranslatorToCAst.DelegatingContext<WalkContext, Node> implements WalkContext {
private final WalkContext parent;
public WalkContext getParent() {
return parent;
}
protected DelegatingContext(WalkContext parent) { protected DelegatingContext(WalkContext parent) {
this.parent = parent; super(parent);
}
public void addScopedEntity(CAstNode node, CAstEntity e) {
parent.addScopedEntity(node, e);
}
// public Map/*<CAstNode,CAstEntity>*/ getScopedEntities() {
// return parent.getScopedEntities();
// }
public CAstControlFlowRecorder cfg() {
return parent.cfg();
}
public CAstSourcePositionRecorder pos() {
return parent.pos();
}
public CAstNodeTypeMapRecorder getNodeTypeMap() {
return parent.getNodeTypeMap();
} }
public Collection<Pair<Type, Object>> getCatchTargets(Type label) { public Collection<Pair<Type, Object>> getCatchTargets(Type label) {
return parent.getCatchTargets(label); return parent.getCatchTargets(label);
} }
public Node getContinueFor(String label) {
return parent.getContinueFor(label);
}
public Node getBreakFor(String label) {
return parent.getBreakFor(label);
}
public Node getFinally() { public Node getFinally() {
return parent.getFinally(); return parent.getFinally();
} }
@ -2121,9 +2047,9 @@ public class PolyglotJava2CAstTranslator implements TranslatorToCAst {
private final Map<Node, String> labelMap = HashMapFactory.make(2); private final Map<Node, String> labelMap = HashMapFactory.make(2);
private final Map<CAstNode, CAstEntity> fEntities; private final Map<CAstNode, Collection<CAstEntity>> fEntities;
public CodeBodyContext(WalkContext parent, Map<CAstNode, CAstEntity> entities) { public CodeBodyContext(WalkContext parent, Map<CAstNode, Collection<CAstEntity>> entities) {
super(parent); super(parent);
fEntities = entities; fEntities = entities;
} }
@ -2141,10 +2067,11 @@ public class PolyglotJava2CAstTranslator implements TranslatorToCAst {
} }
public void addScopedEntity(CAstNode node, CAstEntity entity) { public void addScopedEntity(CAstNode node, CAstEntity entity) {
fEntities.put(node, entity); if (! fEntities.containsKey(node)) { fEntities.put(node, new HashSet<CAstEntity>(1)); }
fEntities.get(node).add(entity);
} }
public Map/* <CAstNode,CAstEntity> */<CAstNode, CAstEntity> getScopedEntities() { public Map<CAstNode, Collection<CAstEntity>> getScopedEntities() {
return fEntities; return fEntities;
} }
@ -2160,7 +2087,7 @@ public class PolyglotJava2CAstTranslator implements TranslatorToCAst {
public class MethodContext extends CodeBodyContext { public class MethodContext extends CodeBodyContext {
final CodeInstance fPI; final CodeInstance fPI;
public MethodContext(CodeInstance pi, Map<CAstNode, CAstEntity> entities, WalkContext parent) { public MethodContext(CodeInstance pi, Map<CAstNode, Collection<CAstEntity>> entities, WalkContext parent) {
super(parent, entities); super(parent, entities);
fPI = pi; fPI = pi;
} }
@ -2188,8 +2115,8 @@ public class PolyglotJava2CAstTranslator implements TranslatorToCAst {
this.tryNode = tryNode; this.tryNode = tryNode;
this.context = context; this.context = context;
for (Iterator catchIter = tryNode.catchBlocks().iterator(); catchIter.hasNext();) { for (Iterator<Catch> catchIter = tryNode.catchBlocks().iterator(); catchIter.hasNext();) {
Catch c = (Catch) catchIter.next(); Catch c = catchIter.next();
Pair<Type,Object> p = Pair.make(c.catchType(), (Object)c); Pair<Type,Object> p = Pair.make(c.catchType(), (Object)c);
fCatchNodes.add(p); fCatchNodes.add(p);
@ -2217,7 +2144,7 @@ public class PolyglotJava2CAstTranslator implements TranslatorToCAst {
continue; continue;
} }
} }
catchNodes.addAll(getParent().getCatchTargets(label)); catchNodes.addAll(parent.getCatchTargets(label));
return catchNodes; return catchNodes;
} }
@ -2230,53 +2157,23 @@ public class PolyglotJava2CAstTranslator implements TranslatorToCAst {
} }
} }
protected static class RootContext implements WalkContext { protected static class RootContext extends TranslatorToCAst.RootContext<WalkContext, Node> implements WalkContext {
final CAstTypeDictionary fTypeDict; final CAstTypeDictionary fTypeDict;
public RootContext(CAstTypeDictionary typeDict) { public RootContext(CAstTypeDictionary typeDict) {
fTypeDict = typeDict; fTypeDict = typeDict;
} }
public void addScopedEntity(CAstNode node, CAstEntity e) {
Assertions.UNREACHABLE("Attempt to call addScopedEntity() on a RootContext.");
}
public CAstControlFlowRecorder cfg() {
Assertions.UNREACHABLE("RootContext.cfg()");
return null;
}
public Collection<Pair<Type, Object>> getCatchTargets(Type label) { public Collection<Pair<Type, Object>> getCatchTargets(Type label) {
Assertions.UNREACHABLE("RootContext.getCatchTargets()"); Assertions.UNREACHABLE("RootContext.getCatchTargets()");
return null; return null;
} }
public CAstNodeTypeMapRecorder getNodeTypeMap() {
Assertions.UNREACHABLE("RootContext.getNodeTypeMap()");
return null;
}
public Node getFinally() { public Node getFinally() {
Assertions.UNREACHABLE("RootContext.getFinally()"); Assertions.UNREACHABLE("RootContext.getFinally()");
return null; return null;
} }
public CAstSourcePositionRecorder pos() {
// No AST, so no AST map
Assertions.UNREACHABLE("RootContext.pos()");
return null;
}
public Node getContinueFor(String label) {
Assertions.UNREACHABLE("RootContext.getContinueFor()");
return null;
}
public Node getBreakFor(String label) {
Assertions.UNREACHABLE("RootContext.getBreakFor()");
return null;
}
public CodeInstance getEnclosingMethod() { public CodeInstance getEnclosingMethod() {
Assertions.UNREACHABLE("RootContext.getEnclosingMethod()"); Assertions.UNREACHABLE("RootContext.getEnclosingMethod()");
return null; return null;
@ -2360,12 +2257,13 @@ public class PolyglotJava2CAstTranslator implements TranslatorToCAst {
} }
} }
public PolyglotJava2CAstTranslator(ClassLoaderReference clr, NodeFactory nf, TypeSystem ts, PolyglotIdentityMapper identityMapper, boolean replicateForDoLoops) { public PolyglotJava2CAstTranslator(Node ast, ClassLoaderReference clr, NodeFactory nf, TypeSystem ts, PolyglotIdentityMapper identityMapper, boolean replicateForDoLoops) {
this.ast = ast;
fClassLoaderRef = clr; fClassLoaderRef = clr;
fTypeSystem = ts; fTypeSystem = ts;
fNodeFactory = nf; fNodeFactory = nf;
fIdentityMapper = identityMapper; fIdentityMapper = identityMapper;
this.replicateForDoLoops = replicateForDoLoops; doLoopTranslator = new DoLoopTranslator(replicateForDoLoops, fFactory);
fNPEType = fTypeSystem.NullPointerException(); fNPEType = fTypeSystem.NullPointerException();
fCCEType = fTypeSystem.ClassCastException(); fCCEType = fTypeSystem.ClassCastException();
fREType = fTypeSystem.RuntimeException(); fREType = fTypeSystem.RuntimeException();
@ -2530,8 +2428,8 @@ public class PolyglotJava2CAstTranslator implements TranslatorToCAst {
return cn; return cn;
} }
public CAstEntity translate(Object ast, String fileName) { public CAstEntity translateToCAst() {
return walkEntity((Node) ast, new RootContext(getTypeDict())); return walkEntity(ast, new RootContext(getTypeDict()));
} }
/** /**
@ -2623,7 +2521,7 @@ public class PolyglotJava2CAstTranslator implements TranslatorToCAst {
InitializerDef initDef = fTypeSystem.initializerDef(n.position(), Types.ref(classType), Flags.STATIC); InitializerDef initDef = fTypeSystem.initializerDef(n.position(), Types.ref(classType), Flags.STATIC);
InitializerInstance initInstance = fTypeSystem.createInitializerInstance(n.position(), Types.ref(initDef)); InitializerInstance initInstance = fTypeSystem.createInitializerInstance(n.position(), Types.ref(initDef));
Map<CAstNode, CAstEntity> childEntities = HashMapFactory.make(); Map<CAstNode, Collection<CAstEntity>> childEntities = HashMapFactory.make();
final MethodContext mc = new MethodContext(initInstance, childEntities, classContext); final MethodContext mc = new MethodContext(initInstance, childEntities, classContext);
List inits = classContext.getStaticInitializers(); List inits = classContext.getStaticInitializers();
@ -2644,7 +2542,7 @@ public class PolyglotJava2CAstTranslator implements TranslatorToCAst {
for (Iterator iter = superConstructors.iterator(); iter.hasNext();) { for (Iterator iter = superConstructors.iterator(); iter.hasNext();) {
ConstructorInstance superCtor = (ConstructorInstance) iter.next(); ConstructorInstance superCtor = (ConstructorInstance) iter.next();
Map<CAstNode, CAstEntity> childEntities = HashMapFactory.make(); Map<CAstNode, Collection<CAstEntity>> childEntities = HashMapFactory.make();
final MethodContext mc = new MethodContext(superCtor, childEntities, classContext); final MethodContext mc = new MethodContext(superCtor, childEntities, classContext);
String[] fakeArguments = new String[superCtor.formalTypes().size() + 1]; String[] fakeArguments = new String[superCtor.formalTypes().size() + 1];
@ -2713,7 +2611,7 @@ public class PolyglotJava2CAstTranslator implements TranslatorToCAst {
return new ClassEntity(classContext, memberEntities, anonType, anonTypeName, n.position()); return new ClassEntity(classContext, memberEntities, anonType, anonTypeName, n.position());
} else if (rootNode instanceof ProcedureDecl) { } else if (rootNode instanceof ProcedureDecl) {
final ProcedureDecl pd = (ProcedureDecl) rootNode; final ProcedureDecl pd = (ProcedureDecl) rootNode;
final Map<CAstNode, CAstEntity> memberEntities = new LinkedHashMap<CAstNode, CAstEntity>(); final Map<CAstNode, Collection<CAstEntity>> memberEntities = HashMapFactory.make();
final MethodContext mc = new MethodContext(pd.procedureInstance().asInstance(), memberEntities, context); final MethodContext mc = new MethodContext(pd.procedureInstance().asInstance(), memberEntities, context);
CAstNode pdAST = null; CAstNode pdAST = null;

View File

@ -0,0 +1,103 @@
/p
/A.class
/AnonymousClass.class
/AnonymousClass.java
/AnonymousClass$1.class
/AnonymousClass$1FooImpl.class
/AnonymousClass$2.class
/AnonymousClass$Foo.class
/Array1.class
/Array1.java
/ArrayLiteral1.class
/ArrayLiteral1.java
/ArrayLiteral2.class
/ArrayLiteral2.java
/B.class
/BadLanguageExceptionEx1.class
/BadLanguageExceptionF1.class
/Bar.class
/Base.class
/Breaks.class
/Breaks.java
/Breaks$1.class
/Breaks$Ref.class
/CastFromNull.class
/CastFromNull.java
/Casts.class
/Casts.java
/Derived.class
/Exception1.class
/Exception1.java
/Exception2.class
/Exception2.java
/Finally1.class
/Finally1.java
/FooEx1.class
/FooEx2.class
/FooF1.class
/FooIT1.class
/FooQ.class
/IFoo.class
/Inheritance1.class
/Inheritance1.java
/InheritedField.class
/InheritedField.java
/InnerClass.class
/InnerClass.java
/InnerClass$WhatsIt.class
/InnerClass$WhatsIt$NotAgain.class
/InnerClass$WhatsThat.class
/InnerClassA.class
/InnerClassA.java
/InnerClassA$AA.class
/InnerClassA$AB.class
/InnerClassA$AB$ABA.class
/InnerClassA$AB$ABA$ABAA.class
/InnerClassA$AB$ABA$ABAB.class
/InnerClassA$AB$ABSubA.class
/InnerClassA$AB$ABSubA$ABSubAA.class
/InnerClassSuper.class
/InnerClassSuper.java
/InnerClassSuper$SuperOuter.class
/InterfaceTest1.class
/InterfaceTest1.java
/IntWrapper.class
/LocalClass.class
/LocalClass.java
/LocalClass$1Foo.class
/LocalClass$2Foo.class
/MiniaturList.class
/MiniaturList.java
/MiniaturSliceBug.class
/MiniaturSliceBug.java
/Monitor.class
/Monitor.java
/NullArrayInit.class
/NullArrayInit.java
/PrimitiveWrapper.class
/QualifiedStatic.class
/QualifiedStatic.java
/R.class
/Scoping1.class
/Scoping1.java
/Scoping2.class
/Scoping2.java
/Scoping2$1.class
/Simple1.class
/Simple1.java
/StaticInitializers.class
/StaticInitializers.java
/StaticInitializers$X.class
/StaticNesting.class
/StaticNesting.java
/StaticNesting$WhatsIt.class
/Sub.class
/Sub$SubInner.class
/Switch1.class
/Switch1.java
/Thread1.class
/Thread1.java
/TwoClasses.class
/TwoClasses.java
/WhileTest1.class
/WhileTest1.java

View File

@ -48,6 +48,25 @@
<target name="getSources" depends="fetchJLex" /> <target name="getSources" depends="fetchJLex" />
<target name="testdatadir" depends="init,testdata.exists" unless="testdatadir.present">
<mkdir dir="${basedir}/../com.ibm.wala.cast.java.test/testdata"/>
</target>
<target name="testdata.exists" depends="init">
<available file="${basedir}/../com.ibm.wala.cast.java.test/testdata"
type="dir"
property="testdatadir.present"/>
</target>
<target name="compile" depends="getSources">
<javac srcdir="${basedir}/src"
destdir="${basedir}/bin"
excludes="**/Activator.java"/>
</target>
<target name="jar" depends="compile,testdatadir">
<jar destfile="${basedir}/../com.ibm.wala.cast.java.test/testdata/test_project.zip" basedir="${basedir}"/>
</target>
<target name="init" depends="properties"> <target name="init" depends="properties">
<condition property="pluginTemp" value="${buildTempFolder}/plugins"> <condition property="pluginTemp" value="${buildTempFolder}/plugins">

View File

@ -186,7 +186,7 @@ public class SynchronizedBlockDuplicator extends
return null; return null;
} }
protected CAstNode copyNodes(CAstNode n, RewriteContext<UnwindKey> c, Map<Pair<CAstNode, UnwindKey>, CAstNode> nodeMap) { protected CAstNode copyNodes(CAstNode n, final CAstControlFlowMap cfg, RewriteContext<UnwindKey> c, Map<Pair<CAstNode, UnwindKey>, CAstNode> nodeMap) {
String varName; String varName;
// don't copy operators or constants (presumably since they are immutable?) // don't copy operators or constants (presumably since they are immutable?)
if (n instanceof CAstOperator) { if (n instanceof CAstOperator) {
@ -204,15 +204,15 @@ public class SynchronizedBlockDuplicator extends
Ast.makeNode(CAstNode.VAR, Ast.makeConstant(varName))); Ast.makeNode(CAstNode.VAR, Ast.makeConstant(varName)));
// the new if conditional // the new if conditional
return Ast.makeNode(CAstNode.IF_STMT, test, copyNodes(n, new SyncContext(true, n, c), nodeMap), return Ast.makeNode(CAstNode.IF_STMT, test, copyNodes(n, cfg, new SyncContext(true, n, c), nodeMap),
copyNodes(n, new SyncContext(false, n, c), nodeMap)); copyNodes(n, cfg, new SyncContext(false, n, c), nodeMap));
} else { } else {
// invoke copyNodes() on the children with context c, ensuring, e.g., that // invoke copyNodes() on the children with context c, ensuring, e.g., that
// the body of a synchronized block gets cloned // the body of a synchronized block gets cloned
CAstNode[] newChildren = new CAstNode[n.getChildCount()]; CAstNode[] newChildren = new CAstNode[n.getChildCount()];
for (int i = 0; i < newChildren.length; i++) for (int i = 0; i < newChildren.length; i++)
newChildren[i] = copyNodes(n.getChild(i), c, nodeMap); newChildren[i] = copyNodes(n.getChild(i), cfg, c, nodeMap);
CAstNode newN = Ast.makeNode(n.getKind(), newChildren); CAstNode newN = Ast.makeNode(n.getKind(), newChildren);

View File

@ -272,7 +272,7 @@ public class AstJavaSSAPropagationCallGraphBuilder extends AstSSAPropagationCall
} }
public void visitJavaInvoke(AstJavaInvokeInstruction instruction) { public void visitJavaInvoke(AstJavaInvokeInstruction instruction) {
visitInvokeInternal(instruction); visitInvokeInternal(instruction, new DefaultInvariantComputer());
} }
} }

View File

@ -10,21 +10,26 @@
*****************************************************************************/ *****************************************************************************/
package com.ibm.wala.cast.java.ipa.callgraph; package com.ibm.wala.cast.java.ipa.callgraph;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator; import java.util.Iterator;
import java.util.Set; import java.util.Set;
import com.ibm.wala.cast.ipa.callgraph.ScopeMappingInstanceKeys; import com.ibm.wala.cast.ipa.callgraph.ScopeMappingInstanceKeys;
import com.ibm.wala.cast.ipa.callgraph.ScopeMappingInstanceKeys.ScopeMappingInstanceKey;
import com.ibm.wala.cast.ir.translator.AstTranslator; import com.ibm.wala.cast.ir.translator.AstTranslator;
import com.ibm.wala.cast.java.loader.JavaSourceLoaderImpl.JavaClass; import com.ibm.wala.cast.java.loader.JavaSourceLoaderImpl.JavaClass;
import com.ibm.wala.cast.loader.AstMethod; import com.ibm.wala.cast.loader.AstMethod;
import com.ibm.wala.cast.loader.AstMethod.LexicalParent; import com.ibm.wala.cast.loader.AstMethod.LexicalParent;
import com.ibm.wala.classLoader.IClass; import com.ibm.wala.classLoader.IClass;
import com.ibm.wala.classLoader.IMethod; import com.ibm.wala.classLoader.IMethod;
import com.ibm.wala.ipa.callgraph.CGNode;
import com.ibm.wala.ipa.callgraph.propagation.InstanceKey; import com.ibm.wala.ipa.callgraph.propagation.InstanceKey;
import com.ibm.wala.ipa.callgraph.propagation.InstanceKeyFactory; import com.ibm.wala.ipa.callgraph.propagation.InstanceKeyFactory;
import com.ibm.wala.ipa.callgraph.propagation.PropagationCallGraphBuilder; import com.ibm.wala.ipa.callgraph.propagation.PropagationCallGraphBuilder;
import com.ibm.wala.ipa.cha.IClassHierarchy; import com.ibm.wala.ipa.cha.IClassHierarchy;
import com.ibm.wala.util.collections.HashSetFactory; import com.ibm.wala.util.collections.HashSetFactory;
import com.ibm.wala.util.collections.Pair;
public class JavaScopeMappingInstanceKeys extends ScopeMappingInstanceKeys { public class JavaScopeMappingInstanceKeys extends ScopeMappingInstanceKeys {
@ -75,4 +80,11 @@ public class JavaScopeMappingInstanceKeys extends ScopeMappingInstanceKeys {
return result; return result;
} }
@Override
protected Collection<CGNode> getConstructorCallers(ScopeMappingInstanceKey smik, Pair<String, String> name) {
// for Java, the creator node is exactly what we want
return Collections.singleton(smik.getCreator());
}
} }

View File

@ -15,6 +15,7 @@ package com.ibm.wala.cast.java.translator;
import java.io.PrintWriter; import java.io.PrintWriter;
import com.ibm.wala.cast.ir.translator.TranslatorToCAst;
import com.ibm.wala.cast.java.loader.JavaSourceLoaderImpl; import com.ibm.wala.cast.java.loader.JavaSourceLoaderImpl;
import com.ibm.wala.cast.tree.CAst; import com.ibm.wala.cast.tree.CAst;
import com.ibm.wala.cast.tree.CAstEntity; import com.ibm.wala.cast.tree.CAstEntity;
@ -29,34 +30,29 @@ public class Java2IRTranslator {
protected final JavaSourceLoaderImpl fLoader; protected final JavaSourceLoaderImpl fLoader;
protected final TranslatorToCAst fSourceTranslator;
CAstRewriterFactory castRewriterFactory = null; CAstRewriterFactory castRewriterFactory = null;
public Java2IRTranslator(TranslatorToCAst sourceTranslator, JavaSourceLoaderImpl srcLoader) { public Java2IRTranslator(JavaSourceLoaderImpl srcLoader) {
this(sourceTranslator, srcLoader, false); this(srcLoader, false);
} }
public Java2IRTranslator(TranslatorToCAst sourceTranslator, JavaSourceLoaderImpl srcLoader, boolean debug) { public Java2IRTranslator(JavaSourceLoaderImpl srcLoader, boolean debug) {
this(sourceTranslator, srcLoader, null, debug); this(srcLoader, null, debug);
} }
public Java2IRTranslator(TranslatorToCAst sourceTranslator, JavaSourceLoaderImpl srcLoader, public Java2IRTranslator(JavaSourceLoaderImpl srcLoader,
CAstRewriterFactory castRewriterFactory) { CAstRewriterFactory castRewriterFactory) {
this(sourceTranslator, srcLoader, castRewriterFactory, false); this(srcLoader, castRewriterFactory, false);
} }
public Java2IRTranslator(TranslatorToCAst sourceTranslator, JavaSourceLoaderImpl srcLoader, public Java2IRTranslator(JavaSourceLoaderImpl srcLoader,
CAstRewriterFactory castRewriterFactory, boolean debug) { CAstRewriterFactory castRewriterFactory, boolean debug) {
DEBUG = debug; DEBUG = debug;
fLoader = srcLoader; fLoader = srcLoader;
fSourceTranslator = sourceTranslator;
this.castRewriterFactory = castRewriterFactory; this.castRewriterFactory = castRewriterFactory;
} }
public void translate(ModuleEntry module, Object ast, String N) { public void translate(ModuleEntry module, CAstEntity ce) {
CAstEntity ce = fSourceTranslator.translate(ast, N);
if (DEBUG) { if (DEBUG) {
PrintWriter printWriter = new PrintWriter(System.out); PrintWriter printWriter = new PrintWriter(System.out);
CAstPrinter.printTo(ce, printWriter); CAstPrinter.printTo(ce, printWriter);

View File

@ -304,26 +304,24 @@ public class JavaCAst2IRTranslator extends AstTranslator {
return ((JavaSourceLoaderImpl) loader).defineType(type, type.getType().getName(), parentType) != null; return ((JavaSourceLoaderImpl) loader).defineType(type, type.getType().getName(), parentType) != null;
} }
protected void leaveThis(CAstNode n, Context c, CAstVisitor visitor) { protected void leaveThis(CAstNode n, WalkContext c, CAstVisitor<WalkContext> visitor) {
if (n.getChildCount() == 0) { if (n.getChildCount() == 0) {
super.leaveThis(n, c, visitor); super.leaveThis(n, c, visitor);
} else { } else {
WalkContext wc = (WalkContext) c; int result = c.currentScope().allocateTempValue();
int result = wc.currentScope().allocateTempValue(); c.setValue(n, result);
setValue(n, result); c.cfg().addInstruction(new EnclosingObjectReference(result, (TypeReference) n.getChild(0).getValue()));
wc.cfg().addInstruction(new EnclosingObjectReference(result, (TypeReference) n.getChild(0).getValue()));
} }
} }
protected boolean visitCast(CAstNode n, Context c, CAstVisitor visitor) { protected boolean visitCast(CAstNode n, WalkContext context, CAstVisitor<WalkContext> visitor) {
WalkContext context = (WalkContext)c;
int result = context.currentScope().allocateTempValue(); int result = context.currentScope().allocateTempValue();
setValue(n, result); context.setValue(n, result);
return false; return false;
} }
protected void leaveCast(CAstNode n, Context c, CAstVisitor visitor) {
WalkContext context = (WalkContext)c; protected void leaveCast(CAstNode n, WalkContext context, CAstVisitor<WalkContext> visitor) {
int result = getValue(n); int result = context.getValue(n);
CAstType toType = (CAstType) n.getChild(0).getValue(); CAstType toType = (CAstType) n.getChild(0).getValue();
TypeReference toRef = makeType(toType); TypeReference toRef = makeType(toType);
@ -334,7 +332,7 @@ public class JavaCAst2IRTranslator extends AstTranslator {
context.cfg().addInstruction( context.cfg().addInstruction(
insts.ConversionInstruction( insts.ConversionInstruction(
result, result,
getValue(n.getChild(1)), context.getValue(n.getChild(1)),
fromRef, fromRef,
toRef, toRef,
false)); false));
@ -343,43 +341,42 @@ public class JavaCAst2IRTranslator extends AstTranslator {
context.cfg().addInstruction( context.cfg().addInstruction(
insts.CheckCastInstruction( insts.CheckCastInstruction(
result, result,
getValue(n.getChild(1)), context.getValue(n.getChild(1)),
toRef, toRef,
true)); true));
processExceptions(n, context); processExceptions(n, context);
} }
} }
protected boolean visitInstanceOf(CAstNode n, Context c, CAstVisitor visitor) {
WalkContext context = (WalkContext)c; protected boolean visitInstanceOf(CAstNode n, WalkContext context, CAstVisitor<WalkContext> visitor) {
int result = context.currentScope().allocateTempValue(); int result = context.currentScope().allocateTempValue();
setValue(n, result); context.setValue(n, result);
return false; return false;
} }
protected void leaveInstanceOf(CAstNode n, Context c, CAstVisitor visitor) {
WalkContext context = (WalkContext)c; protected void leaveInstanceOf(CAstNode n, WalkContext context, CAstVisitor<WalkContext> visitor) {
int result = getValue(n); int result = context.getValue(n);
CAstType type = (CAstType) n.getChild(0).getValue(); CAstType type = (CAstType) n.getChild(0).getValue();
TypeReference ref = makeType( type ); TypeReference ref = makeType( type );
context.cfg().addInstruction( context.cfg().addInstruction(
insts.InstanceofInstruction( insts.InstanceofInstruction(
result, result,
getValue(n.getChild(1)), context.getValue(n.getChild(1)),
ref)); ref));
} }
protected boolean doVisit(CAstNode n, Context context, CAstVisitor visitor) { protected boolean doVisit(CAstNode n, WalkContext wc, CAstVisitor<WalkContext> visitor) {
WalkContext wc = (WalkContext) context;
if (n.getKind() == CAstNode.MONITOR_ENTER) { if (n.getKind() == CAstNode.MONITOR_ENTER) {
visitor.visit(n.getChild(0), wc, visitor); visitor.visit(n.getChild(0), wc, visitor);
wc.cfg().addInstruction(insts.MonitorInstruction(getValue(n.getChild(0)), true)); wc.cfg().addInstruction(insts.MonitorInstruction(wc.getValue(n.getChild(0)), true));
processExceptions(n, wc); processExceptions(n, wc);
return true; return true;
} else if (n.getKind() == CAstNode.MONITOR_EXIT) { } else if (n.getKind() == CAstNode.MONITOR_EXIT) {
visitor.visit(n.getChild(0), wc, visitor); visitor.visit(n.getChild(0), wc, visitor);
wc.cfg().addInstruction(insts.MonitorInstruction(getValue(n.getChild(0)), false)); wc.cfg().addInstruction(insts.MonitorInstruction(wc.getValue(n.getChild(0)), false));
processExceptions(n, wc); processExceptions(n, wc);
return true; return true;
} else { } else {
@ -387,4 +384,6 @@ processExceptions(n, context);
} }
} }
} }

View File

@ -1,19 +0,0 @@
/******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
package com.ibm.wala.cast.java.translator;
import com.ibm.wala.cast.tree.CAstEntity;
public interface TranslatorToCAst {
public CAstEntity translate(Object astRoot, String unitName);
}

View File

@ -2,8 +2,8 @@
<classpath> <classpath>
<classpathentry kind="src" path="src"/> <classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="tests"/> <classpathentry kind="src" path="tests"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="lib" path="lib/htmlparser-1.3.1.jar"/> <classpathentry kind="lib" path="lib/htmlparser-1.3.1.jar"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
<classpathentry kind="output" path="bin"/> <classpathentry kind="output" path="bin"/>
</classpath> </classpath>

View File

@ -8,5 +8,7 @@ Require-Bundle: com.ibm.wala.cast.js;bundle-version="1.0.0",
com.ibm.wala.cast.js.rhino.test;bundle-version="1.0.0", com.ibm.wala.cast.js.rhino.test;bundle-version="1.0.0",
com.ibm.wala.cast.js.test;bundle-version="1.0.0", com.ibm.wala.cast.js.test;bundle-version="1.0.0",
com.ibm.wala.cast.test;bundle-version="1.0.0", com.ibm.wala.cast.test;bundle-version="1.0.0",
com.ibm.wala.cast;bundle-version="1.0.0",
com.ibm.wala.core.tests;bundle-version="1.1.3", com.ibm.wala.core.tests;bundle-version="1.1.3",
com.ibm.wala.core;bundle-version="1.1.3" com.ibm.wala.core;bundle-version="1.1.3",
org.junit;bundle-version="4.8.1"

View File

@ -14,6 +14,8 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.LineNumberReader; import java.io.LineNumberReader;
import java.io.StringReader; import java.io.StringReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.AbstractMap; import java.util.AbstractMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Map; import java.util.Map;
@ -32,10 +34,21 @@ import org.xml.sax.SAXException;
import com.ibm.wala.cast.js.html.IHtmlCallback; import com.ibm.wala.cast.js.html.IHtmlCallback;
import com.ibm.wala.cast.js.html.IHtmlParser; import com.ibm.wala.cast.js.html.IHtmlParser;
import com.ibm.wala.cast.js.html.ITag; import com.ibm.wala.cast.js.html.ITag;
import com.ibm.wala.cast.tree.CAstSourcePositionMap.Position;
import com.ibm.wala.cast.tree.impl.LineNumberPosition;
import com.ibm.wala.util.collections.Pair;
public class NuValidatorHtmlParser implements IHtmlParser { public class NuValidatorHtmlParser implements IHtmlParser {
public void parse(final InputStream reader, final IHtmlCallback handler, String fileName) { public void parse(final URL url, final InputStream reader, final IHtmlCallback handler, final String fileName) {
URL xx = null;
try {
xx = new URL("file://" + fileName);
} catch (MalformedURLException e1) {
e1.printStackTrace();
}
final URL localFileName = xx;
HtmlParser parser = new HtmlParser(); HtmlParser parser = new HtmlParser();
parser.setXmlPolicy(XmlViolationPolicy.ALLOW); parser.setXmlPolicy(XmlViolationPolicy.ALLOW);
parser.setContentHandler(new ContentHandler() { parser.setContentHandler(new ContentHandler() {
@ -57,38 +70,46 @@ public class NuValidatorHtmlParser implements IHtmlParser {
} }
public void startElement(String uri, final String localName, String qName, final Attributes atts) throws SAXException { public void startElement(String uri, final String localName, String qName, final Attributes atts) throws SAXException {
final int line = locator.getLineNumber(); final Position line = new LineNumberPosition(url, localFileName, locator.getLineNumber());
tags.push(new ITag() { tags.push(new ITag() {
public String getName() { public String getName() {
return localName; return localName;
} }
public String getAttributeByName(String name) { public Pair<String,Position> getAttributeByName(String name) {
return atts.getValue(name); if (atts.getValue(name) != null) {
return Pair.make(atts.getValue(name), line);
} else {
return null;
}
} }
public Map<String, String> getAllAttributes() { public Map<String, Pair<String,Position>> getAllAttributes() {
return new AbstractMap<String,String>() { return new AbstractMap<String,Pair<String,Position>>() {
private Set<Map.Entry<String,String>> es = null; private Set<Map.Entry<String,Pair<String,Position>>> es = null;
@Override @Override
public Set<java.util.Map.Entry<String, String>> entrySet() { public Set<java.util.Map.Entry<String, Pair<String,Position>>> entrySet() {
if (es == null) { if (es == null) {
es = new HashSet<Map.Entry<String,String>>(); es = new HashSet<Map.Entry<String,Pair<String,Position>>>();
for(int i = 0; i < atts.getLength(); i++) { for(int i = 0; i < atts.getLength(); i++) {
final int index = i; final int index = i;
es.add(new Map.Entry<String,String>() { es.add(new Map.Entry<String,Pair<String,Position>>() {
public String getKey() { public String getKey() {
return atts.getLocalName(index); return atts.getLocalName(index).toLowerCase();
} }
public String getValue() { public Pair<String,Position> getValue() {
return atts.getValue(index); if (atts.getValue(index) != null) {
return Pair.make(atts.getValue(index), line);
} else {
return null;
}
} }
public String setValue(String value) { public Pair<String,Position> setValue(Pair<String,Position> value) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
}); });
@ -99,10 +120,15 @@ public class NuValidatorHtmlParser implements IHtmlParser {
}; };
} }
public int getStartingLineNum() { public Position getElementPosition() {
return line;
}
public Position getContentPosition() {
return line; return line;
} }
}); });
handler.handleStartTag(tags.peek()); handler.handleStartTag(tags.peek());
} }
@ -111,11 +137,11 @@ public class NuValidatorHtmlParser implements IHtmlParser {
} }
public void characters(char[] ch, int start, int length) throws SAXException { public void characters(char[] ch, int start, int length) throws SAXException {
handler.handleText(locator.getLineNumber() - countLines(ch, start, length), new String(ch, start, length)); handler.handleText(new LineNumberPosition(url, localFileName, locator.getLineNumber() - countLines(ch, start, length)), new String(ch, start, length));
} }
public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException { public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException {
handler.handleText(locator.getLineNumber(), new String(ch, start, length)); handler.handleText(new LineNumberPosition(url, localFileName, locator.getLineNumber()), new String(ch, start, length));
} }
public void startDocument() throws SAXException { public void startDocument() throws SAXException {

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<classpath> <classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/> <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/> <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="src" path="harness-src"/> <classpathentry kind="src" path="harness-src"/>
<classpathentry kind="output" path="bin"/> <classpathentry kind="output" path="bin"/>

View File

@ -0,0 +1,17 @@
/apollo-example.html
/crawl.html
/iframeTest2.html
/list.html
/nojs.html
/page1.html
/page11.html
/page11b.html
/page12.html
/page13.html
/page15.html
/page16.html
/page17.html
/page2.html
/page3.html
/page4.html
/windowx.html

View File

@ -13,7 +13,8 @@ Require-Bundle: org.eclipse.core.runtime,
com.ibm.wala.cast.js.test;bundle-version="1.0.0", com.ibm.wala.cast.js.test;bundle-version="1.0.0",
com.ibm.wala.cast.test;bundle-version="1.0.0", com.ibm.wala.cast.test;bundle-version="1.0.0",
com.ibm.wala.core.tests;bundle-version="1.1.3", com.ibm.wala.core.tests;bundle-version="1.1.3",
org.junit4;bundle-version="4.3.1" org.junit4;bundle-version="4.3.1",
com.ibm.wala.ide;bundle-version="1.1.3"
Bundle-RequiredExecutionEnvironment: J2SE-1.5 Bundle-RequiredExecutionEnvironment: J2SE-1.5
Bundle-ActivationPolicy: lazy Bundle-ActivationPolicy: lazy
Export-Package: com.ibm.wala.cast.js.test Export-Package: com.ibm.wala.cast.js.test

View File

@ -0,0 +1,206 @@
/*******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package com.ibm.wala.cast.js.rhino.test;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Properties;
import junit.framework.Assert;
import org.eclipse.core.runtime.NullProgressMonitor;
import com.ibm.wala.cast.ir.translator.AstTranslator;
import com.ibm.wala.cast.js.ipa.callgraph.ForInContextSelector;
import com.ibm.wala.cast.js.ipa.callgraph.JSCFABuilder;
import com.ibm.wala.cast.js.ipa.callgraph.JavaScriptFunctionDotCallTargetSelector;
import com.ibm.wala.cast.js.ipa.callgraph.RecursionCheckContextSelector;
import com.ibm.wala.cast.js.ipa.callgraph.correlations.extraction.CorrelatedPairExtractorFactory;
import com.ibm.wala.cast.js.test.JSCallGraphBuilderUtil;
import com.ibm.wala.cast.js.test.JSCallGraphBuilderUtil.CGBuilderType;
import com.ibm.wala.cast.js.translator.CAstRhinoTranslatorFactory;
import com.ibm.wala.ide.util.ProgressMaster;
import com.ibm.wala.ide.util.ProgressMonitorDelegate;
import com.ibm.wala.ipa.callgraph.CGNode;
import com.ibm.wala.ipa.callgraph.CallGraph;
import com.ibm.wala.ipa.callgraph.CallGraphBuilderCancelException;
import com.ibm.wala.ipa.callgraph.propagation.PointerAnalysis;
import com.ibm.wala.ipa.cha.ClassHierarchyException;
import com.ibm.wala.util.collections.Iterator2Iterable;
import com.ibm.wala.util.io.CommandLine;
import com.ibm.wala.util.io.FileProvider;
/**
* Utility class for building call graphs of HTML pages.
*
* @author mschaefer
*
*/
public class HTMLCGBuilder {
public static final int DEFAULT_TIMEOUT = 120;
/**
* Simple struct-like type to hold results of call graph construction.
*
* @author mschaefer
*
*/
public static class CGBuilderResult {
/** time it took to build the call graph; {@code -1} if timeout occurred */
public long construction_time;
/** builder responsible for building the call graph*/
public JSCFABuilder builder;
/** pointer analysis results; partial if {@link #construction_time} is {@code -1} */
public PointerAnalysis pa;
/** call graph; partial if {@link #construction_time} is {@code -1} */
public CallGraph cg;
}
/**
* Build a call graph for an HTML page, optionally with a timeout.
*
* @param src
* the HTML page to analyse, can either be a path to a local file or a URL
* @param timeout
* analysis timeout in seconds, -1 means no timeout
* @param automated_extraction
* whether to automatically extract correlated pairs
* @throws IOException
* @throws ClassHierarchyException
*/
public static CGBuilderResult buildHTMLCG(String src, int timeout, boolean automated_extraction, CGBuilderType builderType)
throws ClassHierarchyException, IOException {
CGBuilderResult res = new CGBuilderResult();
URL url = null;
try {
url = toUrl(src);
} catch (MalformedURLException e1) {
Assert.fail("Could not find page to analyse: " + src);
}
com.ibm.wala.cast.js.ipa.callgraph.JSCallGraphUtil.setTranslatorFactory(new CAstRhinoTranslatorFactory());
if(automated_extraction)
com.ibm.wala.cast.js.ipa.callgraph.JSCallGraphUtil.setPreprocessor(new CorrelatedPairExtractorFactory(new CAstRhinoTranslatorFactory(), url));
JSCFABuilder builder = null;
try {
builder = JSCallGraphBuilderUtil.makeHTMLCGBuilder(url, builderType);
builder.setContextSelector(new ForInContextSelector(2, builder.getContextSelector()));
builder.setContextSelector(new ForInContextSelector(3, builder.getContextSelector()));
// TODO we need to find a better way to do this ContextSelector delegation;
// the code below belongs somewhere else!!!
// the bound of 4 is what is needed to pass our current framework tests
if (AstTranslator.NEW_LEXICAL) {
// builder.setContextSelector(new RecursionBoundContextSelector(builder.getContextSelector(), 4));
builder.setContextSelector(new RecursionCheckContextSelector(builder.getContextSelector()));
}
ProgressMaster master = ProgressMaster.make(new NullProgressMonitor());
if (timeout > 0) {
master.setMillisPerWorkItem(timeout * 1000);
master.beginTask("runSolver", 1);
}
long start = System.currentTimeMillis();
CallGraph cg = timeout > 0 ? builder.makeCallGraph(builder.getOptions(),
ProgressMonitorDelegate.createProgressMonitorDelegate(master)) : builder.makeCallGraph(builder.getOptions());
long end = System.currentTimeMillis();
master.done();
res.construction_time = (end - start);
res.cg = cg;
res.pa = builder.getPointerAnalysis();
res.builder = builder;
return res;
} catch (CallGraphBuilderCancelException e) {
res.construction_time = -1;
res.cg = e.getPartialCallGraph();
res.pa = e.getPartialPointerAnalysis();
res.builder = builder;
return res;
} catch (Exception e) {
throw new Error(e);
}
}
private static URL toUrl(String src) throws MalformedURLException {
// first try interpreting as local file name, if that doesn't work just
// assume it's a URL
try {
File f = (new FileProvider()).getFileFromClassLoader(src, HTMLCGBuilder.class.getClassLoader());
URL url = f.toURI().toURL();
return url;
} catch (FileNotFoundException fnfe) {
return new URL(src);
}
}
/**
* Usage: HTMLCGBuilder -src path_to_html_file -timeout timeout_in_seconds -reachable function_name
* timeout argument is optional and defaults to {@link #DEFAULT_TIMEOUT}.
* reachable argument is optional. if provided, and some reachable function name contains function_name,
* will print "REACHABLE"
* @throws IOException
* @throws ClassHierarchyException
*
*/
public static void main(String[] args) throws ClassHierarchyException, IOException {
Properties parsedArgs = CommandLine.parse(args);
String src = parsedArgs.getProperty("src");
if (src == null) {
throw new IllegalArgumentException("-src argument is required");
}
int timeout;
if (parsedArgs.containsKey("timeout")) {
timeout = Integer.parseInt(parsedArgs.getProperty("timeout"));
} else {
timeout = DEFAULT_TIMEOUT;
}
String reachableName = null;
if (parsedArgs.containsKey("reachable")) {
reachableName = parsedArgs.getProperty("reachable");
}
String srcNode = null, dstNode = null;
if (parsedArgs.containsKey("edgeExists")) {
String[] nodes = parsedArgs.getProperty("edgeExists").split(":");
srcNode = nodes[0];
dstNode = nodes[1];
}
// suppress debug output
JavaScriptFunctionDotCallTargetSelector.WARN_ABOUT_IMPRECISE_CALLGRAPH = false;
CGBuilderResult res = buildHTMLCG(src, timeout, true, AstTranslator.NEW_LEXICAL ? CGBuilderType.ONE_CFA_PRECISE_LEXICAL : CGBuilderType.ZERO_ONE_CFA);
if(res.construction_time == -1)
System.out.println("TIMED OUT");
else
System.out.println("Call graph construction took " + res.construction_time/1000.0 + " seconds");
if (reachableName != null) {
for (CGNode node : res.cg) {
if (node.getMethod().getDeclaringClass().getName().toString().contains(reachableName)) {
System.out.println("REACHABLE");
break;
}
}
}
if (srcNode != null) {
for (CGNode node : res.cg) {
if (node.getMethod().getDeclaringClass().getName().toString().endsWith(srcNode)) {
for (CGNode callee : Iterator2Iterable.make(res.cg.getSuccNodes(node))) {
if (callee.getMethod().getDeclaringClass().getName().toString().endsWith(dstNode)) {
System.out.println("EDGE EXISTS");
}
}
}
}
}
}
}

View File

@ -22,7 +22,7 @@ public class TestAjaxsltCallGraphShapeRhino extends TestAjaxsltCallGraphShape {
@Before @Before
public void setUp() { public void setUp() {
com.ibm.wala.cast.js.ipa.callgraph.Util.setTranslatorFactory(new CAstRhinoTranslatorFactory()); com.ibm.wala.cast.js.ipa.callgraph.JSCallGraphUtil.setTranslatorFactory(new CAstRhinoTranslatorFactory());
} }

View File

@ -0,0 +1,16 @@
package com.ibm.wala.cast.js.test;
import org.junit.Before;
import com.ibm.wala.cast.js.ipa.callgraph.JSCallGraphUtil;
import com.ibm.wala.cast.js.translator.CAstRhinoTranslatorFactory;
public class TestArgumentSensitivityRhino extends TestArgumentSensitivity {
@Before
public void setUp() {
JSCallGraphUtil.setTranslatorFactory(new CAstRhinoTranslatorFactory());
}
}

View File

@ -15,10 +15,10 @@ import java.io.IOException;
import com.ibm.wala.cast.js.ipa.callgraph.correlations.CorrelationFinder; import com.ibm.wala.cast.js.ipa.callgraph.correlations.CorrelationFinder;
import com.ibm.wala.cast.js.translator.CAstRhinoTranslatorFactory; import com.ibm.wala.cast.js.translator.CAstRhinoTranslatorFactory;
import com.ibm.wala.cast.js.translator.RhinoToAstTranslator;
import com.ibm.wala.cast.tree.CAstEntity; import com.ibm.wala.cast.tree.CAstEntity;
import com.ibm.wala.cast.tree.impl.CAstImpl; import com.ibm.wala.cast.tree.impl.CAstImpl;
import com.ibm.wala.classLoader.SourceModule; import com.ibm.wala.classLoader.SourceModule;
import org.mozilla.javascript.RhinoToAstTranslator;
public class TestCorrelatedPairExtractionRhino extends TestCorrelatedPairExtraction { public class TestCorrelatedPairExtractionRhino extends TestCorrelatedPairExtraction {
protected CorrelationFinder makeCorrelationFinder() { protected CorrelationFinder makeCorrelationFinder() {
@ -26,9 +26,8 @@ public class TestCorrelatedPairExtractionRhino extends TestCorrelatedPairExtract
} }
protected CAstEntity parseJS(CAstImpl ast, SourceModule module) throws IOException { protected CAstEntity parseJS(CAstImpl ast, SourceModule module) throws IOException {
RhinoToAstTranslator.resetGensymCounters(); RhinoToAstTranslator translator = new RhinoToAstTranslator(ast, module, module.getName(), false);
RhinoToAstTranslator translator = new RhinoToAstTranslator(ast, module, module.getName()); CAstEntity entity = translator.translateToCAst();
CAstEntity entity = translator.translate();
return entity; return entity;
} }
} }

View File

@ -13,17 +13,16 @@ package com.ibm.wala.cast.js.test;
import java.io.IOException; import java.io.IOException;
import org.mozilla.javascript.RhinoToAstTranslator;
import com.ibm.wala.cast.js.translator.RhinoToAstTranslator;
import com.ibm.wala.cast.tree.CAstEntity; import com.ibm.wala.cast.tree.CAstEntity;
import com.ibm.wala.cast.tree.impl.CAstImpl; import com.ibm.wala.cast.tree.impl.CAstImpl;
import com.ibm.wala.classLoader.SourceModule; import com.ibm.wala.classLoader.SourceModule;
public class TestForInBodyExtractionRhino extends TestForInBodyExtraction { public class TestForInBodyExtractionRhino extends TestForInBodyExtraction {
protected CAstEntity parseJS(CAstImpl ast, SourceModule module) throws IOException { protected CAstEntity parseJS(CAstImpl ast, SourceModule module) throws IOException {
RhinoToAstTranslator.resetGensymCounters(); RhinoToAstTranslator translator = new RhinoToAstTranslator(ast, module, module.getName(), false);
RhinoToAstTranslator translator = new RhinoToAstTranslator(ast, module, module.getName()); CAstEntity entity = translator.translateToCAst();
CAstEntity entity = translator.translate();
return entity; return entity;
} }
} }

View File

@ -8,7 +8,7 @@ public class TestForInLoopHackRhino extends TestForInLoopHack {
@Before @Before
public void setUp() { public void setUp() {
com.ibm.wala.cast.js.ipa.callgraph.Util.setTranslatorFactory(new CAstRhinoTranslatorFactory()); com.ibm.wala.cast.js.ipa.callgraph.JSCallGraphUtil.setTranslatorFactory(new CAstRhinoTranslatorFactory());
} }
} }

View File

@ -0,0 +1,19 @@
package com.ibm.wala.cast.js.test;
import org.junit.Before;
import com.ibm.wala.cast.js.ipa.callgraph.JSCallGraphUtil;
import com.ibm.wala.cast.js.translator.CAstRhinoTranslatorFactory;
public class TestJQueryExamplesRhino extends TestJQueryExamples {
public static void main(String[] args) {
justThisTest(TestJQueryExamplesRhino.class);
}
@Before
public void setUp() {
JSCallGraphUtil.setTranslatorFactory(new CAstRhinoTranslatorFactory());
}
}

View File

@ -22,7 +22,7 @@ public class TestMediawikiCallGraphShapeRhino extends TestMediawikiCallGraphShap
@Before @Before
public void setUp() { public void setUp() {
com.ibm.wala.cast.js.ipa.callgraph.Util.setTranslatorFactory(new CAstRhinoTranslatorFactory()); com.ibm.wala.cast.js.ipa.callgraph.JSCallGraphUtil.setTranslatorFactory(new CAstRhinoTranslatorFactory());
} }
} }

View File

@ -12,7 +12,7 @@ public class TestMozillaBugPagesRhino extends TestMozillaBugPages {
@Before @Before
public void setUp() { public void setUp() {
com.ibm.wala.cast.js.ipa.callgraph.Util.setTranslatorFactory(new CAstRhinoTranslatorFactory()); com.ibm.wala.cast.js.ipa.callgraph.JSCallGraphUtil.setTranslatorFactory(new CAstRhinoTranslatorFactory());
} }
} }

View File

@ -0,0 +1,170 @@
package com.ibm.wala.cast.js.test;
import static com.ibm.wala.cast.js.ipa.callgraph.JSCallGraphUtil.makeHierarchy;
import static com.ibm.wala.cast.js.ipa.callgraph.JSCallGraphUtil.makeLoaders;
import static com.ibm.wala.cast.js.ipa.callgraph.JSCallGraphUtil.setTranslatorFactory;
import static com.ibm.wala.cast.js.test.JSCallGraphBuilderUtil.makeScriptScope;
import java.io.IOException;
import java.util.Map;
import junit.framework.Assert;
import org.junit.Before;
import org.junit.Test;
import com.ibm.wala.cast.js.loader.JavaScriptLoaderFactory;
import com.ibm.wala.cast.js.translator.CAstRhinoTranslatorFactory;
import com.ibm.wala.cast.loader.AstMethod;
import com.ibm.wala.cast.types.AstMethodReference;
import com.ibm.wala.cast.util.SourceBuffer;
import com.ibm.wala.classLoader.IClass;
import com.ibm.wala.ipa.callgraph.AnalysisScope;
import com.ibm.wala.ipa.cha.ClassHierarchyException;
import com.ibm.wala.ipa.cha.IClassHierarchy;
import com.ibm.wala.util.CancelException;
import com.ibm.wala.util.collections.HashMapFactory;
public class TestRhinoSourceMap {
@Before
public void setUp() {
setTranslatorFactory(new CAstRhinoTranslatorFactory());
}
private static final String[][] jquery_spec_testSource = new String[][]{
new String[]{
"Ltests/jquery_spec_test.js/anonymous__0/isEmptyDataObject",
"function isEmptyDataObject(obj) {\n" +
" for (var name in obj) {\n" +
" if (name !== \"toJSON\") {\n" +
" return false;\n" +
" }\n" +
" }\n" +
" return true;\n" +
" }"
},
new String[]{
"Ltests/jquery_spec_test.js/anonymous__0/anonymous__59/anonymous__62/anonymous__63/anonymous__64/anonymous__65",
"function anonymous__65() {\n" +
" returned = fn.apply(this, arguments);\n" +
" if (returned && jQuery.isFunction(returned.promise)) {\n" +
" returned.promise().then(newDefer.resolve, newDefer.reject);\n" +
" } else {\n" +
" newDefer[action](returned);\n" +
" }\n" +
" }"
},
new String[]{
"Ltests/jquery_spec_test.js/anonymous__0/anonymous__386/anonymous__392",
"function anonymous__392(map) {\n" +
" if (map) {\n" +
" var tmp;\n" +
" if (state < 2) {\n" +
" for (tmp in map) {\n" +
" statusCode[tmp] = [ statusCode[tmp], map[tmp] ];\n" +
" }\n" +
" } else {\n" +
" tmp = map[jqXHR.status];\n" +
" jqXHR.then(tmp, tmp);\n" +
" }\n" +
" }\n" +
" return this;\n" +
" }"
},
new String[]{
"Ltests/jquery_spec_test.js/anonymous__0/getWindow",
"function getWindow(elem) {\n" +
" return jQuery.isWindow(elem) ? elem : elem.nodeType === 9 ? elem.defaultView || elem.parentWindow : false;\n" +
" }"
},
new String[]{
"Ltests/jquery_spec_test.js/anonymous__0/anonymous__1/anonymous__7",
"function anonymous__7(elems, name, selector) {\n" +
" var ret = this.constructor();\n" +
" if (jQuery.isArray(elems)) {\n" +
" push.apply(ret, elems);\n" +
" } else {\n" +
" jQuery.merge(ret, elems);\n" +
" }\n" +
" ret.prevObject = this;\n" +
" ret.context = this.context;\n" +
" if (name === \"find\") {\n" +
" ret.selector = this.selector + (this.selector ? \" \" : \"\") + selector;\n" +
" } else if (name) {\n" +
" ret.selector = this.selector + \".\" + name + \"(\" + selector + \")\";\n" +
" }\n" +
" return ret;\n" +
" }"
},
new String[]{
"Ltests/jquery_spec_test.js/anonymous__0/anonymous__1/anonymous__17",
"function anonymous__17() {\n" +
" var options, name, src, copy, copyIsArray, clone, target = arguments[0] || {}, i = 1, length = arguments.length, deep = false;\n" +
" if (typeof target === \"boolean\") {\n" +
" deep = target;\n" +
" target = arguments[1] || {};\n" +
" i = 2;\n" +
" }\n" +
" if (typeof target !== \"object\" && !jQuery.isFunction(target)) {\n" +
" target = {};\n" +
" }\n" +
" if (length === i) {\n" +
" target = this;\n" +
" --i;\n" +
" }\n" +
" for (; i < length; i++) {\n" +
" if ((options = arguments[i]) != null) {\n" +
" for (name in options) {\n" +
" (function _forin_body_extra_1(name) { var src = target[name];\n" +
" var copy = options[name];\n" +
" if (target === copy) {\n" +
" return; //continue;\n" +
" }\n" +
" if (deep && copy && (jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)))) {\n" +
" if (copyIsArray) {\n" +
" copyIsArray = false;\n" +
" clone = src && jQuery.isArray(src) ? src : [];\n" +
" } else {\n" +
" clone = src && jQuery.isPlainObject(src) ? src : {};\n" +
" }\n" +
" target[name] = jQuery.extend(deep, clone, copy);\n" +
" } else if (copy !== undefined) {\n" +
" target[name] = copy;\n" +
" } })(name);\n" +
" }\n" +
" }\n" +
" }\n" +
" return target;\n" +
" }"}
};
@Test
public void testJquerySpecTestSourceMappings() throws IllegalArgumentException, IOException, CancelException, ClassHierarchyException {
checkFunctionBodies("jquery_spec_test.js", jquery_spec_testSource);
}
private void checkFunctionBodies(String fileName, String[][] assertions) throws IOException, ClassHierarchyException {
Map<String, String> sources = HashMapFactory.make();
for(String[] assertion : assertions) {
sources.put(assertion[0], assertion[1]);
}
JavaScriptLoaderFactory loaders = makeLoaders();
AnalysisScope scope = makeScriptScope("tests", fileName, loaders);
IClassHierarchy cha = makeHierarchy(scope, loaders);
for(IClass cls : cha) {
if (cls.getName().toString().contains(fileName)) {
AstMethod fun = (AstMethod)cls.getMethod(AstMethodReference.fnSelector);
//System.err.println(fun.getDeclaringClass().getName() + " " + fun.getSourcePosition());
SourceBuffer sb = new SourceBuffer(fun.getSourcePosition());
//System.err.println(sb);
if (sources.containsKey(fun.getDeclaringClass().getName().toString())) {
System.err.println("checking source of " + fun.getDeclaringClass().getName() + " at " + fun.getSourcePosition());
Assert.assertEquals(sources.get(fun.getDeclaringClass().getName().toString()), sb.toString());
}
}
}
}
}

View File

@ -28,12 +28,12 @@ public class TestSimpleCallGraphShapeRhino extends TestSimpleCallGraphShape {
@Before @Before
public void setUp() { public void setUp() {
com.ibm.wala.cast.js.ipa.callgraph.Util.setTranslatorFactory(new CAstRhinoTranslatorFactory()); com.ibm.wala.cast.js.ipa.callgraph.JSCallGraphUtil.setTranslatorFactory(new CAstRhinoTranslatorFactory());
} }
@Test @Test
public void test214631() throws IOException, IllegalArgumentException, CancelException { public void test214631() throws IOException, IllegalArgumentException, CancelException {
JSCFABuilder b = Util.makeScriptCGBuilder("tests", "214631.js"); JSCFABuilder b = JSCallGraphBuilderUtil.makeScriptCGBuilder("tests", "214631.js");
b.makeCallGraph(b.getOptions()); b.makeCallGraph(b.getOptions());
PointerAnalysis PA = b.getPointerAnalysis(); PointerAnalysis PA = b.getPointerAnalysis();
// just make sure this does not crash // just make sure this does not crash
@ -42,22 +42,27 @@ public class TestSimpleCallGraphShapeRhino extends TestSimpleCallGraphShape {
@Test @Test
public void testRewriterDoesNotChangeLablesBug() throws IOException, IllegalArgumentException, CancelException { public void testRewriterDoesNotChangeLablesBug() throws IOException, IllegalArgumentException, CancelException {
Util.makeScriptCG("tests", "rewrite_does_not_change_lables_bug.js"); JSCallGraphBuilderUtil.makeScriptCG("tests", "rewrite_does_not_change_lables_bug.js");
// all we need is for it to finish building CG successfully. // all we need is for it to finish building CG successfully.
} }
@Test @Test
public void testRepr() throws IllegalArgumentException, IOException, CancelException { public void testRepr() throws IllegalArgumentException, IOException, CancelException {
Util.makeScriptCG("tests", "repr.js"); JSCallGraphBuilderUtil.makeScriptCG("tests", "repr.js");
} }
@Test @Test
public void testTranslateToCAstCrash1() throws IllegalArgumentException, IOException, CancelException { public void testTranslateToCAstCrash1() throws IllegalArgumentException, IOException, CancelException {
Util.makeScriptCG("tests", "rhino_crash1.js"); JSCallGraphBuilderUtil.makeScriptCG("tests", "rhino_crash1.js");
} }
@Test @Test
public void testTranslateToCAstCrash2() throws IllegalArgumentException, IOException, CancelException { public void testTranslateToCAstCrash2() throws IllegalArgumentException, IOException, CancelException {
Util.makeScriptCG("tests", "rhino_crash2.js"); JSCallGraphBuilderUtil.makeScriptCG("tests", "rhino_crash2.js");
}
@Test
public void testTranslateToCAstCrash3() throws IllegalArgumentException, IOException, CancelException {
JSCallGraphBuilderUtil.makeScriptCG("tests", "rhino_crash3.js");
} }
} }

View File

@ -32,7 +32,7 @@ public abstract class TestSimplePageCallGraphShapeRhino extends TestSimplePageCa
@Test public void testPage3() throws IOException, IllegalArgumentException, CancelException { @Test public void testPage3() throws IOException, IllegalArgumentException, CancelException {
URL url = getClass().getClassLoader().getResource("pages/page3.html"); URL url = getClass().getClassLoader().getResource("pages/page3.html");
CallGraph CG = Util.makeHTMLCG(url); CallGraph CG = JSCallGraphBuilderUtil.makeHTMLCG(url);
verifyGraphAssertions(CG, assertionsForPage3); verifyGraphAssertions(CG, assertionsForPage3);
} }
@ -44,7 +44,7 @@ public abstract class TestSimplePageCallGraphShapeRhino extends TestSimplePageCa
@Before @Before
public void setUp() { public void setUp() {
com.ibm.wala.cast.js.ipa.callgraph.Util.setTranslatorFactory(new CAstRhinoTranslatorFactory()); com.ibm.wala.cast.js.ipa.callgraph.JSCallGraphUtil.setTranslatorFactory(new CAstRhinoTranslatorFactory());
WebUtil.setFactory(new IHtmlParserFactory() { WebUtil.setFactory(new IHtmlParserFactory() {
public IHtmlParser getParser() { public IHtmlParser getParser() {
return TestSimplePageCallGraphShapeRhino.this.getParser(); return TestSimplePageCallGraphShapeRhino.this.getParser();

View File

@ -15,7 +15,7 @@ public class TestSimplePageCallGraphShapeRhinoJericho extends TestSimplePageCall
@Test public void testCrawl() throws IOException, IllegalArgumentException, CancelException { @Test public void testCrawl() throws IOException, IllegalArgumentException, CancelException {
URL url = getClass().getClassLoader().getResource("pages/crawl.html"); URL url = getClass().getClassLoader().getResource("pages/crawl.html");
CallGraph CG = Util.makeHTMLCG(url); CallGraph CG = JSCallGraphBuilderUtil.makeHTMLCG(url);
verifyGraphAssertions(CG, null); verifyGraphAssertions(CG, null);
} }

View File

@ -4,6 +4,7 @@ import java.io.IOException;
import java.net.URL; import java.net.URL;
import java.util.Set; import java.util.Set;
import com.ibm.wala.cast.ir.ssa.AstIRFactory;
import com.ibm.wala.cast.js.html.DefaultSourceExtractor; import com.ibm.wala.cast.js.html.DefaultSourceExtractor;
import com.ibm.wala.cast.js.html.DomLessSourceExtractor; import com.ibm.wala.cast.js.html.DomLessSourceExtractor;
import com.ibm.wala.cast.js.html.IdentityUrlResolver; import com.ibm.wala.cast.js.html.IdentityUrlResolver;
@ -14,7 +15,7 @@ import com.ibm.wala.cast.js.html.WebUtil;
import com.ibm.wala.cast.js.html.jericho.JerichoHtmlParser; import com.ibm.wala.cast.js.html.jericho.JerichoHtmlParser;
import com.ibm.wala.cast.js.ipa.callgraph.JSCFABuilder; import com.ibm.wala.cast.js.ipa.callgraph.JSCFABuilder;
import com.ibm.wala.cast.js.loader.JavaScriptLoader; import com.ibm.wala.cast.js.loader.JavaScriptLoader;
import com.ibm.wala.cast.js.test.Util; import com.ibm.wala.cast.js.test.JSCallGraphBuilderUtil;
import com.ibm.wala.cast.js.translator.CAstRhinoTranslatorFactory; import com.ibm.wala.cast.js.translator.CAstRhinoTranslatorFactory;
import com.ibm.wala.classLoader.SourceFileModule; import com.ibm.wala.classLoader.SourceFileModule;
import com.ibm.wala.classLoader.SourceModule; import com.ibm.wala.classLoader.SourceModule;
@ -23,7 +24,7 @@ import com.ibm.wala.ipa.callgraph.propagation.PointerAnalysis;
import com.ibm.wala.ipa.cha.ClassHierarchyException; import com.ibm.wala.ipa.cha.ClassHierarchyException;
import com.ibm.wala.util.CancelException; import com.ibm.wala.util.CancelException;
public class JsViewerDriver extends Util { public class JsViewerDriver extends JSCallGraphBuilderUtil {
public static void main(String args[]) throws ClassHierarchyException, IllegalArgumentException, IOException, CancelException { public static void main(String args[]) throws ClassHierarchyException, IllegalArgumentException, IOException, CancelException {
if (args.length != 1){ if (args.length != 1){
@ -35,12 +36,12 @@ public class JsViewerDriver extends Util {
URL url = new URL(args[0]); URL url = new URL(args[0]);
// computing CG + PA // computing CG + PA
Util.setTranslatorFactory(new CAstRhinoTranslatorFactory()); JSCallGraphBuilderUtil.setTranslatorFactory(new CAstRhinoTranslatorFactory());
JavaScriptLoader.addBootstrapFile(WebUtil.preamble); JavaScriptLoader.addBootstrapFile(WebUtil.preamble);
SourceModule[] sources = getSources(domless, url); SourceModule[] sources = getSources(domless, url);
JSCFABuilder builder = makeCGBuilder(new WebPageLoaderFactory(translatorFactory), sources, false, true); JSCFABuilder builder = makeCGBuilder(new WebPageLoaderFactory(translatorFactory), sources, CGBuilderType.ZERO_ONE_CFA, AstIRFactory.makeDefaultFactory());
builder.setBaseURL(url); builder.setBaseURL(url);
CallGraph cg = builder.makeCallGraph(builder.getOptions()); CallGraph cg = builder.makeCallGraph(builder.getOptions());

View File

@ -39,9 +39,9 @@
<target name="fetchRhino" depends="RhinoPresent" unless="rhino.present"> <target name="fetchRhino" depends="RhinoPresent" unless="rhino.present">
<delete dir="${temp.folder}"/> <delete dir="${temp.folder}"/>
<mkdir dir="${temp.folder}"/> <mkdir dir="${temp.folder}"/>
<get src="ftp://ftp.mozilla.org/pub/mozilla.org/js/rhino1_7R2.zip" dest="${temp.folder}/rhino1_7R2.zip" /> <get src="http://ftp.mozilla.org/pub/mozilla.org/js/rhino1_7R3.zip" dest="${temp.folder}/rhino1_7R3.zip" />
<unzip src="${temp.folder}/rhino1_7R2.zip" dest="${temp.folder}"/> <unzip src="${temp.folder}/rhino1_7R3.zip" dest="${temp.folder}"/>
<copy file="${temp.folder}/rhino1_7R2/js.jar" tofile="${plugin.destination}/lib/js.jar" /> <copy file="${temp.folder}/rhino1_7R3/js.jar" tofile="${plugin.destination}/lib/js.jar" />
<delete dir="${temp.folder}"/> <delete dir="${temp.folder}"/>
</target> </target>

View File

@ -14,14 +14,9 @@ import java.io.IOException;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import org.mozilla.javascript.RhinoToAstTranslator;
import com.ibm.wala.cast.ir.translator.TranslatorToCAst; import com.ibm.wala.cast.ir.translator.TranslatorToCAst;
import com.ibm.wala.cast.js.translator.PropertyReadExpander.ExpanderKey;
import com.ibm.wala.cast.tree.CAst;
import com.ibm.wala.cast.tree.CAstEntity; import com.ibm.wala.cast.tree.CAstEntity;
import com.ibm.wala.cast.tree.impl.CAstImpl; import com.ibm.wala.cast.tree.impl.CAstImpl;
import com.ibm.wala.cast.tree.impl.CAstRewriter;
import com.ibm.wala.cast.tree.impl.CAstRewriter.CopyKey; import com.ibm.wala.cast.tree.impl.CAstRewriter.CopyKey;
import com.ibm.wala.cast.tree.impl.CAstRewriter.RewriteContext; import com.ibm.wala.cast.tree.impl.CAstRewriter.RewriteContext;
import com.ibm.wala.cast.tree.impl.CAstRewriterFactory; import com.ibm.wala.cast.tree.impl.CAstRewriterFactory;
@ -31,14 +26,11 @@ import com.ibm.wala.classLoader.SourceModule;
public class CAstRhinoTranslator implements TranslatorToCAst { public class CAstRhinoTranslator implements TranslatorToCAst {
private final List<CAstRewriterFactory> rewriters = new LinkedList<CAstRewriterFactory>(); private final List<CAstRewriterFactory> rewriters = new LinkedList<CAstRewriterFactory>();
private final SourceModule M; private final SourceModule M;
private final boolean replicateForDoLoops;
public CAstRhinoTranslator(SourceModule M) { public CAstRhinoTranslator(SourceModule M, boolean replicateForDoLoops) {
this.M = M; this.M = M;
this.addRewriter(new CAstRewriterFactory<PropertyReadExpander.RewriteContext, ExpanderKey>() { this.replicateForDoLoops = replicateForDoLoops;
public CAstRewriter<PropertyReadExpander.RewriteContext, ExpanderKey> createCAstRewriter(CAst ast) {
return new PropertyReadExpander(ast);
}
}, true);
} }
public <C extends RewriteContext<K>, K extends CopyKey<K>> void addRewriter(CAstRewriterFactory<C, K> factory, boolean prepend) { public <C extends RewriteContext<K>, K extends CopyKey<K>> void addRewriter(CAstRewriterFactory<C, K> factory, boolean prepend) {
@ -57,9 +49,10 @@ public class CAstRhinoTranslator implements TranslatorToCAst {
} }
CAstImpl Ast = new CAstImpl(); CAstImpl Ast = new CAstImpl();
CAstEntity entity = new RhinoToAstTranslator(Ast, M, N).translate(); CAstEntity entity = new RhinoToAstTranslator(Ast, M, N, replicateForDoLoops).translateToCAst();
for(CAstRewriterFactory rwf : rewriters) for(CAstRewriterFactory rwf : rewriters)
entity = rwf.createCAstRewriter(Ast).rewrite(entity); entity = rwf.createCAstRewriter(Ast).rewrite(entity);
return entity; return entity;
} }
} }

View File

@ -7,7 +7,7 @@ import com.ibm.wala.classLoader.SourceModule;
public class CAstRhinoTranslatorFactory implements JavaScriptTranslatorFactory { public class CAstRhinoTranslatorFactory implements JavaScriptTranslatorFactory {
public TranslatorToCAst make(CAst ast, SourceModule M) { public TranslatorToCAst make(CAst ast, SourceModule M) {
return new CAstRhinoTranslator(M); return new CAstRhinoTranslator(M, false);
} }
} }

View File

@ -0,0 +1,303 @@
package com.ibm.wala.cast.js.translator;
import org.mozilla.javascript.ast.ArrayComprehension;
import org.mozilla.javascript.ast.ArrayComprehensionLoop;
import org.mozilla.javascript.ast.ArrayLiteral;
import org.mozilla.javascript.ast.Assignment;
import org.mozilla.javascript.ast.AstNode;
import org.mozilla.javascript.ast.AstRoot;
import org.mozilla.javascript.ast.Block;
import org.mozilla.javascript.ast.BreakStatement;
import org.mozilla.javascript.ast.CatchClause;
import org.mozilla.javascript.ast.Comment;
import org.mozilla.javascript.ast.ConditionalExpression;
import org.mozilla.javascript.ast.ContinueStatement;
import org.mozilla.javascript.ast.DoLoop;
import org.mozilla.javascript.ast.ElementGet;
import org.mozilla.javascript.ast.EmptyExpression;
import org.mozilla.javascript.ast.ErrorNode;
import org.mozilla.javascript.ast.ExpressionStatement;
import org.mozilla.javascript.ast.ForInLoop;
import org.mozilla.javascript.ast.ForLoop;
import org.mozilla.javascript.ast.FunctionCall;
import org.mozilla.javascript.ast.FunctionNode;
import org.mozilla.javascript.ast.IfStatement;
import org.mozilla.javascript.ast.InfixExpression;
import org.mozilla.javascript.ast.Jump;
import org.mozilla.javascript.ast.KeywordLiteral;
import org.mozilla.javascript.ast.Label;
import org.mozilla.javascript.ast.LabeledStatement;
import org.mozilla.javascript.ast.LetNode;
import org.mozilla.javascript.ast.Name;
import org.mozilla.javascript.ast.NewExpression;
import org.mozilla.javascript.ast.NumberLiteral;
import org.mozilla.javascript.ast.ObjectLiteral;
import org.mozilla.javascript.ast.ObjectProperty;
import org.mozilla.javascript.ast.ParenthesizedExpression;
import org.mozilla.javascript.ast.PropertyGet;
import org.mozilla.javascript.ast.RegExpLiteral;
import org.mozilla.javascript.ast.ReturnStatement;
import org.mozilla.javascript.ast.Scope;
import org.mozilla.javascript.ast.ScriptNode;
import org.mozilla.javascript.ast.StringLiteral;
import org.mozilla.javascript.ast.SwitchCase;
import org.mozilla.javascript.ast.SwitchStatement;
import org.mozilla.javascript.ast.Symbol;
import org.mozilla.javascript.ast.ThrowStatement;
import org.mozilla.javascript.ast.TryStatement;
import org.mozilla.javascript.ast.UnaryExpression;
import org.mozilla.javascript.ast.VariableDeclaration;
import org.mozilla.javascript.ast.VariableInitializer;
import org.mozilla.javascript.ast.WhileLoop;
import org.mozilla.javascript.ast.WithStatement;
import org.mozilla.javascript.ast.XmlDotQuery;
import org.mozilla.javascript.ast.XmlElemRef;
import org.mozilla.javascript.ast.XmlExpression;
import org.mozilla.javascript.ast.XmlFragment;
import org.mozilla.javascript.ast.XmlLiteral;
import org.mozilla.javascript.ast.XmlMemberGet;
import org.mozilla.javascript.ast.XmlPropRef;
import org.mozilla.javascript.ast.XmlRef;
import org.mozilla.javascript.ast.XmlString;
import org.mozilla.javascript.ast.Yield;
public abstract class TypedNodeVisitor<R,A> {
public R visit(AstNode node, A arg) {
if (node instanceof ArrayComprehension) {
return visitArrayComprehension((ArrayComprehension) node, arg);
} else if (node instanceof WhileLoop) {
return visitWhileLoop((WhileLoop) node, arg);
} else if (node instanceof ArrayComprehensionLoop) {
return visitArrayComprehensionLoop((ArrayComprehensionLoop) node, arg);
} else if (node instanceof ArrayLiteral) {
return visitArrayLiteral((ArrayLiteral) node, arg);
} else if (node instanceof Assignment) {
return visitAssignment((Assignment) node, arg);
} else if (node instanceof AstRoot) {
return visitAstRoot((AstRoot) node, arg);
} else if (node instanceof Block) {
return visitBlock((Block) node, arg);
} else if (node instanceof BreakStatement) {
return visitBreakStatement((BreakStatement) node, arg);
} else if (node instanceof CatchClause) {
return visitCatchClause((CatchClause) node, arg);
} else if (node instanceof Comment) {
return visitComment((Comment) node, arg);
} else if (node instanceof ConditionalExpression) {
return visitConditionalExpression((ConditionalExpression) node, arg);
} else if (node instanceof ContinueStatement) {
return visitContinueStatement((ContinueStatement) node, arg);
} else if (node instanceof DoLoop) {
return visitDoLoop((DoLoop) node, arg);
} else if (node instanceof ElementGet) {
return visitElementGet((ElementGet) node, arg);
} else if (node instanceof EmptyExpression) {
return visitEmptyExpression((EmptyExpression) node, arg);
} else if (node instanceof ErrorNode) {
return visitErrorNode((ErrorNode) node, arg);
} else if (node instanceof ExpressionStatement) {
return visitExpressionStatement((ExpressionStatement) node, arg);
} else if (node instanceof ForInLoop) {
return visitForInLoop((ForInLoop) node, arg);
} else if (node instanceof ForLoop) {
return visitForLoop((ForLoop) node, arg);
} else if (node instanceof NewExpression) {
return visitNewExpression((NewExpression) node, arg);
} else if (node instanceof FunctionCall) {
return visitFunctionCall((FunctionCall) node, arg);
} else if (node instanceof FunctionNode) {
return visitFunctionNode((FunctionNode) node, arg);
} else if (node instanceof IfStatement) {
return visitIfStatement((IfStatement) node, arg);
} else if (node instanceof KeywordLiteral) {
return visitKeywordLiteral((KeywordLiteral) node, arg);
} else if (node instanceof Label) {
return visitLabel((Label) node, arg);
} else if (node instanceof LabeledStatement) {
return visitLabeledStatement((LabeledStatement) node, arg);
} else if (node instanceof LetNode) {
return visitLetNode((LetNode) node, arg);
} else if (node instanceof Name) {
return visitName((Name) node, arg);
} else if (node instanceof NumberLiteral) {
return visitNumberLiteral((NumberLiteral) node, arg);
} else if (node instanceof ObjectLiteral) {
return visitObjectLiteral((ObjectLiteral) node, arg);
} else if (node instanceof ObjectProperty) {
return visitObjectProperty((ObjectProperty) node, arg);
} else if (node instanceof ParenthesizedExpression) {
return visitParenthesizedExpression((ParenthesizedExpression) node, arg);
} else if (node instanceof PropertyGet) {
return visitPropertyGet((PropertyGet) node, arg);
} else if (node instanceof RegExpLiteral) {
return visitRegExpLiteral((RegExpLiteral) node, arg);
} else if (node instanceof ReturnStatement) {
return visitReturnStatement((ReturnStatement) node, arg);
} else if (node instanceof Scope) {
return visitScope((Scope) node, arg);
} else if (node instanceof ScriptNode) {
return visitScriptNode((ScriptNode) node, arg);
} else if (node instanceof StringLiteral) {
return visitStringLiteral((StringLiteral) node, arg);
} else if (node instanceof SwitchCase) {
return visitSwitchCase((SwitchCase) node, arg);
} else if (node instanceof SwitchStatement) {
return visitSwitchStatement((SwitchStatement) node, arg);
} else if (node instanceof ThrowStatement) {
return visitThrowStatement((ThrowStatement) node, arg);
} else if (node instanceof TryStatement) {
return visitTryStatement((TryStatement) node, arg);
} else if (node instanceof UnaryExpression) {
return visitUnaryExpression((UnaryExpression) node, arg);
} else if (node instanceof VariableDeclaration) {
return visitVariableDeclaration((VariableDeclaration) node, arg);
} else if (node instanceof VariableInitializer) {
return visitVariableInitializer((VariableInitializer) node, arg);
} else if (node instanceof WithStatement) {
return visitWithStatement((WithStatement) node, arg);
} else if (node instanceof XmlDotQuery) {
return visitXmlDotQuery((XmlDotQuery) node, arg);
} else if (node instanceof XmlElemRef) {
return visitXmlElemRef((XmlElemRef) node, arg);
} else if (node instanceof XmlExpression) {
return visitXmlExpression((XmlExpression) node, arg);
} else if (node instanceof XmlLiteral) {
return visitXmlLiteral((XmlLiteral) node, arg);
} else if (node instanceof XmlMemberGet) {
return visitXmlMemberGet((XmlMemberGet) node, arg);
} else if (node instanceof XmlPropRef) {
return visitXmlPropRef((XmlPropRef) node, arg);
} else if (node instanceof XmlString) {
return visitXmlString((XmlString) node, arg);
} else if (node instanceof Yield) {
return visitYield((Yield) node, arg);
} else if (node instanceof InfixExpression) {
return visitInfixExpression((InfixExpression) node, arg);
} else if (node instanceof Jump) {
return visitJump((Jump) node, arg);
} else {
throw new Error("unexpected node type " + node.getClass().getName());
}
}
public abstract R visitArrayComprehension(ArrayComprehension node, A arg) ;
public abstract R visitArrayComprehensionLoop(ArrayComprehensionLoop node, A arg) ;
public abstract R visitArrayLiteral(ArrayLiteral node, A arg) ;
public abstract R visitAssignment(Assignment node, A arg) ;
public abstract R visitAstRoot(AstRoot node, A arg) ;
public abstract R visitBlock(Block node, A arg) ;
public abstract R visitBreakStatement(BreakStatement node, A arg) ;
public abstract R visitCatchClause(CatchClause node, A arg) ;
public abstract R visitComment(Comment node, A arg) ;
public abstract R visitConditionalExpression(ConditionalExpression node, A arg) ;
public abstract R visitContinueStatement(ContinueStatement node, A arg) ;
public abstract R visitDoLoop(DoLoop node, A arg) ;
public abstract R visitElementGet(ElementGet node, A arg) ;
public abstract R visitEmptyExpression(EmptyExpression node, A arg) ;
public abstract R visitErrorNode(ErrorNode node, A arg) ;
public abstract R visitExpressionStatement(ExpressionStatement node, A arg) ;
public abstract R visitForInLoop(ForInLoop node, A arg) ;
public abstract R visitForLoop(ForLoop node, A arg) ;
public abstract R visitFunctionCall(FunctionCall node, A arg) ;
public abstract R visitFunctionNode(FunctionNode node, A arg) ;
public abstract R visitIfStatement(IfStatement node, A arg) ;
public abstract R visitInfixExpression(InfixExpression node, A arg) ;
public abstract R visitJump(Jump node, A arg) ;
public abstract R visitKeywordLiteral(KeywordLiteral node, A arg) ;
public abstract R visitLabel(Label node, A arg) ;
public abstract R visitLabeledStatement(LabeledStatement node, A arg) ;
public abstract R visitLetNode(LetNode node, A arg) ;
public abstract R visitName(Name node, A arg) ;
public abstract R visitNewExpression(NewExpression node, A arg) ;
public abstract R visitNumberLiteral(NumberLiteral node, A arg) ;
public abstract R visitObjectLiteral(ObjectLiteral node, A arg) ;
public abstract R visitObjectProperty(ObjectProperty node, A arg) ;
public abstract R visitParenthesizedExpression(ParenthesizedExpression node, A arg) ;
public abstract R visitPropertyGet(PropertyGet node, A arg) ;
public abstract R visitRegExpLiteral(RegExpLiteral node, A arg) ;
public abstract R visitReturnStatement(ReturnStatement node, A arg) ;
public abstract R visitScope(Scope node, A arg) ;
public abstract R visitScriptNode(ScriptNode node, A arg) ;
public abstract R visitStringLiteral(StringLiteral node, A arg) ;
public abstract R visitSwitchCase(SwitchCase node, A arg) ;
public abstract R visitSwitchStatement(SwitchStatement node, A arg) ;
public abstract R visitSymbol(Symbol node, A arg) ;
public abstract R visitThrowStatement(ThrowStatement node, A arg) ;
public abstract R visitTryStatement(TryStatement node, A arg) ;
public abstract R visitUnaryExpression(UnaryExpression node, A arg) ;
public abstract R visitVariableDeclaration(VariableDeclaration node, A arg) ;
public abstract R visitVariableInitializer(VariableInitializer node, A arg) ;
public abstract R visitWhileLoop(WhileLoop node, A arg) ;
public abstract R visitWithStatement(WithStatement node, A arg) ;
public abstract R visitXmlDotQuery(XmlDotQuery node, A arg) ;
public abstract R visitXmlElemRef(XmlElemRef node, A arg) ;
public abstract R visitXmlExpression(XmlExpression node, A arg) ;
public abstract R visitXmlFragment(XmlFragment node, A arg) ;
public abstract R visitXmlLiteral(XmlLiteral node, A arg) ;
public abstract R visitXmlMemberGet(XmlMemberGet node, A arg) ;
public abstract R visitXmlPropRef(XmlPropRef node, A arg) ;
public abstract R visitXmlRef(XmlRef node, A arg) ;
public abstract R visitXmlString(XmlString node, A arg) ;
public abstract R visitYield(Yield node, A arg) ;
}

View File

@ -0,0 +1,16 @@
<html>
<head>
<script type="text/javascript" src="http://code.jquery.com/jquery-1.7.1.js"></script>
<script type="text/javascript">
$(document).ready(function(){
$("button").click(function(){
$(this).hide();
});
});
</script>
</head>
<body>
<button>Click me</button>
</body>
</html>

View File

@ -0,0 +1,28 @@
function a() {
if (arguments.length >= 1) {
arguments[0]();
if (arguments.length >= 2) {
arguments[1]();
}
}
}
function x() {
print("x");
}
function y() {
print("y");
}
function z() {
print("z");
}
function wrong() {
print("wrong");
}
a(x);
a(y, z, wrong);

View File

@ -1,5 +1,6 @@
function f() { function f() {
arguments[0].g(); for(var p in arguments)
arguments[p].g();
} }
f.g = function g1() {}; f.g = function g1() {};
@ -12,4 +13,10 @@ var oo = {
g: function g3() { } g: function g3() { }
} }
// at the IR level, this call has three arguments: (1) the function object for f, (2) o, (3), oo
// however, only the last one ends up in the arguments array
o.f(oo); o.f(oo);
// make g1 and g2 reachable so we can check assertions
f.g();
o.g();

View File

@ -0,0 +1,21 @@
function copyObjRec(to, from) {
for (var p in from) {
(function _forin_body(name) {
to[name] = from[name];
copyObjRec(to,from[name]);
})(p);
}
}
var obj = {
foo: function testForIn1() { return 7; },
bar: function testForIn2() { return "whatever"; }
}
obj.baz = obj;
var copy = new Object();
copyObjRec(copy, obj);

View File

@ -0,0 +1,33 @@
var left = {
inner: function left_inner(x) {
return x+1;
},
outer: function left_outer(x) {
return this.inner(x+1);
}
};
var right = {
inner: function right_inner(x) {
return Math.abs(x);
},
outer: function right_outer(x) {
return this.inner(-x);
}
};
var x = 3;
if (x > Math.random()) {
x = left;
} else {
x = right;
}
x.outer(7);

View File

@ -1,8 +1,11 @@
function() { (function(x) {
switch(0) { switch(x) {
case Ext.Date: case Ext.Date:
return 1;
break;
} }
} return -1;
})(0);

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,10 @@
function foo(x) {
function bar() {
x = function i_am_reachable() {}
}
bar();
return x;
}
var y = foo(null);
y();

View File

@ -44,3 +44,7 @@ var foo = strObj.toLowerCase();
var whatnot = [ , , , 7, numObj, arg2, strObj ]; var whatnot = [ , , , 7, numObj, arg2, strObj ];
whatnot[ 5 ].otherMethod( 7 ); whatnot[ 5 ].otherMethod( 7 );
delete arg2.bar();
delete whatnot[ 5 ];
delete arg2;

View File

@ -0,0 +1,9 @@
function f() {
switch (0) {
default:
break;
}
oParsedResponse || 0;
}
f();

View File

@ -0,0 +1,10 @@
function f() {
switch (0) {
default:
break;
}
oParsedResponse || 0;
}
f();

View File

@ -0,0 +1,13 @@
function foo() {
function baz() {
return function f1() {};
}
function boo() {
baz = function biz() { return function i_am_reachable() {}; }
}
boo();
return baz();
}
var x = foo();
x();

View File

@ -11,6 +11,11 @@
package com.ibm.wala.cast.js.test; package com.ibm.wala.cast.js.test;
import static com.ibm.wala.cast.tree.CAstNode.ASSIGN;
import static com.ibm.wala.cast.tree.CAstNode.BLOCK_EXPR;
import static com.ibm.wala.cast.tree.CAstNode.BLOCK_STMT;
import static com.ibm.wala.cast.tree.CAstNode.EMPTY;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
@ -38,6 +43,7 @@ import com.ibm.wala.util.collections.HashMapFactory;
* *
*/ */
public class CAstDumper { public class CAstDumper {
private static final boolean NORMALISE = false;
private final NodeLabeller labeller; private final NodeLabeller labeller;
public CAstDumper() { public CAstDumper() {
@ -112,10 +118,37 @@ public class CAstDumper {
return scopedEntities; return scopedEntities;
} }
private boolean isTrivial(CAstNode node) {
switch(node.getKind()) {
case ASSIGN:
return node.getChild(0).getKind() == CAstNode.VAR && isTrivial(node.getChild(1));
case EMPTY:
return true;
case BLOCK_EXPR:
case BLOCK_STMT:
return getNonTrivialChildCount(node) == 0;
default:
return false;
}
}
private int getNonTrivialChildCount(CAstNode node) {
int cnt = 0;
for(int i=0;i<node.getChildCount();++i)
if(!isTrivial(node.getChild(i)))
++cnt;
return cnt;
}
@SuppressWarnings("unused")
private void dump(CAstNode node, int indent, StringBuilder buf, CAstControlFlowMap cfg) { private void dump(CAstNode node, int indent, StringBuilder buf, CAstControlFlowMap cfg) {
if(isTrivial(node))
return;
// normalise away single-child block expressions // normalise away single-child block expressions
if(node.getKind() == CAstNode.BLOCK_EXPR && node.getChildCount() == 1) { if(NORMALISE && node.getKind() == CAstNode.BLOCK_EXPR && getNonTrivialChildCount(node) == 1) {
dump(node.getChild(0), indent, buf, cfg); for(int i=0;i<node.getChildCount();++i)
if(!isTrivial(node.getChild(i)))
dump(node.getChild(i), indent, buf, cfg);
} else { } else {
buf.append(indent(indent) + labeller.addNode(node) + ": "); buf.append(indent(indent) + labeller.addNode(node) + ": ");
if(node.getKind() == CAstNode.CONSTANT) { if(node.getKind() == CAstNode.CONSTANT) {
@ -153,7 +186,7 @@ public class CAstDumper {
for(int i=0;i<node.getChildCount();++i) { for(int i=0;i<node.getChildCount();++i) {
CAstNode child = node.getChild(i); CAstNode child = node.getChild(i);
// omit empty statements in a block // omit empty statements in a block
if(node.getKind() == CAstNode.BLOCK_STMT && child != null && child.getKind() == CAstNode.EMPTY) if(NORMALISE && node.getKind() == CAstNode.BLOCK_STMT && child != null && child.getKind() == CAstNode.EMPTY)
continue; continue;
dump(child, indent+2, buf, cfg); dump(child, indent+2, buf, cfg);
} }

View File

@ -18,6 +18,7 @@ import java.util.Set;
import junit.framework.Assert; import junit.framework.Assert;
import com.ibm.wala.cast.ir.ssa.AstIRFactory;
import com.ibm.wala.cast.js.html.MappedSourceModule; import com.ibm.wala.cast.js.html.MappedSourceModule;
import com.ibm.wala.cast.js.html.WebPageLoaderFactory; import com.ibm.wala.cast.js.html.WebPageLoaderFactory;
import com.ibm.wala.cast.js.html.WebUtil; import com.ibm.wala.cast.js.html.WebUtil;
@ -36,19 +37,55 @@ import com.ibm.wala.ipa.callgraph.propagation.PropagationCallGraphBuilder;
import com.ibm.wala.ipa.callgraph.propagation.cfa.ZeroXInstanceKeys; import com.ibm.wala.ipa.callgraph.propagation.cfa.ZeroXInstanceKeys;
import com.ibm.wala.ipa.cha.ClassHierarchyException; import com.ibm.wala.ipa.cha.ClassHierarchyException;
import com.ibm.wala.ipa.cha.IClassHierarchy; import com.ibm.wala.ipa.cha.IClassHierarchy;
import com.ibm.wala.ssa.IRFactory;
import com.ibm.wala.util.CancelException; import com.ibm.wala.util.CancelException;
/** /**
* TODO this class is a mess. rewrite. * TODO this class is a mess. rewrite.
*/ */
public class Util extends com.ibm.wala.cast.js.ipa.callgraph.Util { public class JSCallGraphBuilderUtil extends com.ibm.wala.cast.js.ipa.callgraph.JSCallGraphUtil {
public static JSCFABuilder makeScriptCGBuilder(String dir, String name, boolean useOneCFA) throws IOException { public static enum CGBuilderType {
JavaScriptLoaderFactory loaders = Util.makeLoaders(); ZERO_ONE_CFA(false, false, true), ZERO_ONE_CFA_NO_CALL_APPLY(false, false, false), ZERO_ONE_CFA_PRECISE_LEXICAL(false, true,
true), ONE_CFA(true, false, true), ONE_CFA_PRECISE_LEXICAL(true, true, true);
URL script = Util.class.getClassLoader().getResource(dir + File.separator + name); private final boolean useOneCFA;
private final boolean usePreciseLexical;
private final boolean handleCallApply;
private CGBuilderType(boolean useOneCFA, boolean usePreciseLexical, boolean handleCallApply) {
this.useOneCFA = useOneCFA;
this.usePreciseLexical = usePreciseLexical;
this.handleCallApply = handleCallApply;
}
public boolean useOneCFA() {
return useOneCFA;
}
public boolean usePreciseLexical() {
return usePreciseLexical;
}
public boolean handleCallApply() {
return handleCallApply;
}
}
public static JSCFABuilder makeScriptCGBuilder(String dir, String name, CGBuilderType builderType) throws IOException {
JavaScriptLoaderFactory loaders = JSCallGraphBuilderUtil.makeLoaders();
AnalysisScope scope = makeScriptScope(dir, name, loaders);
return makeCG(loaders, scope, builderType, AstIRFactory.makeDefaultFactory());
}
static AnalysisScope makeScriptScope(String dir, String name, JavaScriptLoaderFactory loaders) throws IOException {
URL script = JSCallGraphBuilderUtil.class.getClassLoader().getResource(dir + File.separator + name);
if (script == null) { if (script == null) {
script = Util.class.getClassLoader().getResource(dir + "/" + name); script = JSCallGraphBuilderUtil.class.getClassLoader().getResource(dir + "/" + name);
} }
assert script != null : "cannot find " + dir + " and " + name; assert script != null : "cannot find " + dir + " and " + name;
@ -59,40 +96,41 @@ public class Util extends com.ibm.wala.cast.js.ipa.callgraph.Util {
scope = makeScope(new SourceFileModule[] { makeSourceModule(script, dir, name) }, loaders, JavaScriptLoader.JS); scope = makeScope(new SourceFileModule[] { makeSourceModule(script, dir, name) }, loaders, JavaScriptLoader.JS);
} }
return makeCG(loaders, scope, useOneCFA, true); return scope;
} }
public static JSCFABuilder makeScriptCGBuilder(String dir, String name) throws IOException { public static JSCFABuilder makeScriptCGBuilder(String dir, String name) throws IOException {
return makeScriptCGBuilder(dir, name, false); return makeScriptCGBuilder(dir, name, CGBuilderType.ZERO_ONE_CFA);
} }
public static CallGraph makeScriptCG(String dir, String name) throws IOException, IllegalArgumentException, CancelException { public static CallGraph makeScriptCG(String dir, String name) throws IOException, IllegalArgumentException, CancelException {
return makeScriptCG(dir, name, false); return makeScriptCG(dir, name, CGBuilderType.ZERO_ONE_CFA);
} }
public static CallGraph makeScriptCG(String dir, String name, boolean useOneCFA) throws IOException, IllegalArgumentException, public static CallGraph makeScriptCG(String dir, String name, CGBuilderType builderType) throws IOException,
CancelException { IllegalArgumentException, CancelException {
PropagationCallGraphBuilder b = makeScriptCGBuilder(dir, name, useOneCFA); PropagationCallGraphBuilder b = makeScriptCGBuilder(dir, name, builderType);
CallGraph CG = b.makeCallGraph(b.getOptions()); CallGraph CG = b.makeCallGraph(b.getOptions());
dumpCG(b.getPointerAnalysis(), CG); // dumpCG(b.getPointerAnalysis(), CG);
return CG; return CG;
} }
public static CallGraph makeScriptCG(SourceModule[] scripts, boolean useOneCFA) throws IOException, IllegalArgumentException, public static CallGraph makeScriptCG(SourceModule[] scripts, CGBuilderType builderType, IRFactory irFactory) throws IOException, IllegalArgumentException,
CancelException { CancelException {
PropagationCallGraphBuilder b = makeCGBuilder(makeLoaders(), scripts, useOneCFA, true); PropagationCallGraphBuilder b = makeCGBuilder(makeLoaders(), scripts, builderType, irFactory);
CallGraph CG = b.makeCallGraph(b.getOptions()); CallGraph CG = b.makeCallGraph(b.getOptions());
dumpCG(b.getPointerAnalysis(), CG); // dumpCG(b.getPointerAnalysis(), CG);
return CG; return CG;
} }
public static JSCFABuilder makeHTMLCGBuilder(URL url) throws IOException { public static JSCFABuilder makeHTMLCGBuilder(URL url) throws IOException {
return makeHTMLCGBuilder(url, true); return makeHTMLCGBuilder(url, CGBuilderType.ZERO_ONE_CFA);
} }
public static JSCFABuilder makeHTMLCGBuilder(URL url, boolean handleCallApply) throws IOException {
public static JSCFABuilder makeHTMLCGBuilder(URL url, CGBuilderType builderType) throws IOException {
JavaScriptLoader.addBootstrapFile(WebUtil.preamble); JavaScriptLoader.addBootstrapFile(WebUtil.preamble);
Set<MappedSourceModule> script = WebUtil.extractScriptFromHTML(url); Set<MappedSourceModule> script = WebUtil.extractScriptFromHTML(url);
JSCFABuilder builder = makeCGBuilder(new WebPageLoaderFactory(translatorFactory, preprocessor), script.toArray(new SourceModule[script.size()]), false, handleCallApply); JSCFABuilder builder = makeCGBuilder(new WebPageLoaderFactory(translatorFactory, preprocessor), script.toArray(new SourceModule[script.size()]), builderType, AstIRFactory.makeDefaultFactory());
builder.setBaseURL(url); builder.setBaseURL(url);
return builder; return builder;
} }
@ -100,32 +138,33 @@ public class Util extends com.ibm.wala.cast.js.ipa.callgraph.Util {
public static CallGraph makeHTMLCG(URL url) throws IOException, IllegalArgumentException, CancelException { public static CallGraph makeHTMLCG(URL url) throws IOException, IllegalArgumentException, CancelException {
PropagationCallGraphBuilder b = makeHTMLCGBuilder(url); PropagationCallGraphBuilder b = makeHTMLCGBuilder(url);
CallGraph CG = b.makeCallGraph(b.getOptions()); CallGraph CG = b.makeCallGraph(b.getOptions());
//dumpCG(b.getPointerAnalysis(), CG); dumpCG(b.getPointerAnalysis(), CG);
return CG; return CG;
} }
public static CallGraph makeHTMLCG(URL url, boolean handleCallApply) throws IOException, IllegalArgumentException, public static CallGraph makeHTMLCG(URL url, CGBuilderType builderType) throws IOException, IllegalArgumentException,
CancelException { CancelException {
PropagationCallGraphBuilder b = makeHTMLCGBuilder(url, handleCallApply); PropagationCallGraphBuilder b = makeHTMLCGBuilder(url, builderType);
CallGraph CG = b.makeCallGraph(b.getOptions()); CallGraph CG = b.makeCallGraph(b.getOptions());
return CG; return CG;
} }
public static JSCFABuilder makeCGBuilder(JavaScriptLoaderFactory loaders, SourceModule[] scripts, boolean useOneCFA, boolean handleCallApply) throws IOException { public static JSCFABuilder makeCGBuilder(JavaScriptLoaderFactory loaders, SourceModule[] scripts, CGBuilderType builderType, IRFactory irFactory) throws IOException {
AnalysisScope scope = makeScope(scripts, loaders, JavaScriptLoader.JS); AnalysisScope scope = makeScope(scripts, loaders, JavaScriptLoader.JS);
return makeCG(loaders, scope, useOneCFA, handleCallApply); return makeCG(loaders, scope, builderType, irFactory);
} }
protected static JSCFABuilder makeCG(JavaScriptLoaderFactory loaders, AnalysisScope scope, boolean useOneCFA, boolean handleCallApply) throws IOException { protected static JSCFABuilder makeCG(JavaScriptLoaderFactory loaders, AnalysisScope scope, CGBuilderType builderType, IRFactory irFactory) throws IOException {
try { try {
IClassHierarchy cha = makeHierarchy(scope, loaders); IClassHierarchy cha = makeHierarchy(scope, loaders);
com.ibm.wala.cast.js.util.Util.checkForFrontEndErrors(cha); com.ibm.wala.cast.js.util.Util.checkForFrontEndErrors(cha);
Iterable<Entrypoint> roots = makeScriptRoots(cha); Iterable<Entrypoint> roots = makeScriptRoots(cha);
JSAnalysisOptions options = makeOptions(scope, cha, roots); JSAnalysisOptions options = makeOptions(scope, cha, roots);
options.setHandleCallApply(handleCallApply); options.setHandleCallApply(builderType.handleCallApply());
AnalysisCache cache = makeCache(); options.setUsePreciseLexical(builderType.usePreciseLexical());
AnalysisCache cache = makeCache(irFactory);
JSCFABuilder builder = new JSZeroOrOneXCFABuilder(cha, options, cache, null, null, ZeroXInstanceKeys.ALLOCATIONS, useOneCFA); JSCFABuilder builder = new JSZeroOrOneXCFABuilder(cha, options, cache, null, null, ZeroXInstanceKeys.ALLOCATIONS,
builderType.useOneCFA());
return builder; return builder;
} catch (ClassHierarchyException e) { } catch (ClassHierarchyException e) {

View File

@ -15,6 +15,7 @@ import java.net.URL;
import org.junit.Test; import org.junit.Test;
import com.ibm.wala.cast.js.test.JSCallGraphBuilderUtil.CGBuilderType;
import com.ibm.wala.ipa.callgraph.CallGraph; import com.ibm.wala.ipa.callgraph.CallGraph;
import com.ibm.wala.util.CancelException; import com.ibm.wala.util.CancelException;
@ -31,7 +32,7 @@ public abstract class TestAjaxsltCallGraphShape extends TestJSCallGraphShape {
@Test public void testAjaxslt() throws IOException, IllegalArgumentException, CancelException { @Test public void testAjaxslt() throws IOException, IllegalArgumentException, CancelException {
URL url = getClass().getClassLoader().getResource("ajaxslt/test/xslt.html"); URL url = getClass().getClassLoader().getResource("ajaxslt/test/xslt.html");
// don't handle call / apply; it makes things blow up // don't handle call / apply; it makes things blow up
CallGraph CG = Util.makeHTMLCG(url, false); CallGraph CG = JSCallGraphBuilderUtil.makeHTMLCG(url, CGBuilderType.ZERO_ONE_CFA_NO_CALL_APPLY);
verifyGraphAssertions(CG, assertionsForAjaxslt); verifyGraphAssertions(CG, assertionsForAjaxslt);
} }
@ -42,7 +43,7 @@ public abstract class TestAjaxsltCallGraphShape extends TestJSCallGraphShape {
@Test public void testAjaxpath() throws IOException, IllegalArgumentException, CancelException { @Test public void testAjaxpath() throws IOException, IllegalArgumentException, CancelException {
URL url = getClass().getClassLoader().getResource("ajaxslt/test/xpath.html"); URL url = getClass().getClassLoader().getResource("ajaxslt/test/xpath.html");
CallGraph CG = Util.makeHTMLCG(url); CallGraph CG = JSCallGraphBuilderUtil.makeHTMLCG(url);
verifyGraphAssertions(CG, assertionsForAjaxpath); verifyGraphAssertions(CG, assertionsForAjaxpath);
} }

View File

@ -0,0 +1,54 @@
package com.ibm.wala.cast.js.test;
import java.io.IOException;
import org.junit.Test;
import com.ibm.wala.cast.ipa.callgraph.CAstCallGraphUtil;
import com.ibm.wala.cast.js.ipa.callgraph.ArgumentSpecialization;
import com.ibm.wala.cast.js.ipa.callgraph.JSAnalysisOptions;
import com.ibm.wala.cast.js.ipa.callgraph.JSCFABuilder;
import com.ibm.wala.cast.js.ipa.callgraph.JSZeroOrOneXCFABuilder;
import com.ibm.wala.cast.js.loader.JavaScriptLoaderFactory;
import com.ibm.wala.ipa.callgraph.AnalysisCache;
import com.ibm.wala.ipa.callgraph.AnalysisScope;
import com.ibm.wala.ipa.callgraph.CallGraph;
import com.ibm.wala.ipa.callgraph.Entrypoint;
import com.ibm.wala.ipa.callgraph.propagation.cfa.ZeroXInstanceKeys;
import com.ibm.wala.ipa.cha.ClassHierarchyException;
import com.ibm.wala.ipa.cha.IClassHierarchy;
import com.ibm.wala.util.CancelException;
public abstract class TestArgumentSensitivity extends TestJSCallGraphShape {
protected static final Object[][] assertionsForArgs = new Object[][] {
new Object[] { ROOT, new String[] { "tests/args.js" } },
new Object[] {
"tests/args.js",
new String[] { "tests/args.js/a" } },
new Object[] { "tests/args.js/a", new String[] { "tests/args.js/x"} },
new Object[] { "tests/args.js/a", new String[] { "tests/args.js/y", "tests/args.js/z", "!tests/args.js/wrong" } } };
@Test public void testArgs() throws IOException, IllegalArgumentException, CancelException, ClassHierarchyException {
JavaScriptLoaderFactory loaders = JSCallGraphBuilderUtil.makeLoaders();
AnalysisScope scope = JSCallGraphBuilderUtil.makeScriptScope("tests", "args.js", loaders);
IClassHierarchy cha = JSCallGraphBuilderUtil.makeHierarchy(scope, loaders);
com.ibm.wala.cast.js.util.Util.checkForFrontEndErrors(cha);
Iterable<Entrypoint> roots = JSCallGraphBuilderUtil.makeScriptRoots(cha);
JSAnalysisOptions options = JSCallGraphBuilderUtil.makeOptions(scope, cha, roots);
AnalysisCache cache = JSCallGraphBuilderUtil.makeCache(new ArgumentSpecialization.ArgumentCountIRFactory(options.getSSAOptions()));
JSCFABuilder builder = new JSZeroOrOneXCFABuilder(cha, options, cache, null, null, ZeroXInstanceKeys.ALLOCATIONS, false);
builder.setContextSelector(new ArgumentSpecialization.ArgumentCountContextSelector(builder.getContextSelector()));
builder.setContextInterpreter(new ArgumentSpecialization.ArgumentSpecializationContextIntepreter(options, cache));
CallGraph CG = builder.makeCallGraph(options);
// CAstCallGraphUtil.AVOID_DUMP = false;
CAstCallGraphUtil.dumpCG(builder.getPointerAnalysis(), CG);
verifyGraphAssertions(CG, assertionsForArgs);
}
}

View File

@ -227,6 +227,7 @@ public abstract class TestCorrelatedPairExtraction {
} }
// another example with "this" // another example with "this"
// fails since variables from enclosing functions are no longer in SSA form, hence no correlation is found
@Test @Test
public void test9() { public void test9() {
testRewriter("function defglobals(globals) {\n" + testRewriter("function defglobals(globals) {\n" +
@ -413,7 +414,7 @@ public abstract class TestCorrelatedPairExtraction {
} }
// fails since the assignment to "value" in the extracted version gets a (spurious) reference error CFG edge // fails since the assignment to "value" in the extracted version gets a (spurious) reference error CFG edge
@Test @Ignore @Test
public void test18() { public void test18() {
testRewriter("function addMethods(source) {\n" + testRewriter("function addMethods(source) {\n" +
" var properties = Object.keys(source);\n" + " var properties = Object.keys(source);\n" +
@ -426,8 +427,50 @@ public abstract class TestCorrelatedPairExtraction {
"function addMethods(source) {\n" + "function addMethods(source) {\n" +
" var properties = Object.keys(source);\n" + " var properties = Object.keys(source);\n" +
" for (var i = 0, length = properties.length; i < length; i++) {\n" + " for (var i = 0, length = properties.length; i < length; i++) {\n" +
" var property = properties[i], value; (function _forin_body_0(property, thi$) { value = source[property];\n" + " var property = properties[i], value; value = (function _forin_body_0(property, thi$) { var value; value = source[property];\n" +
" thi$.prototype[property] = value; })(property, this);\n" + " thi$.prototype[property] = value; return value; })(property, this);\n" +
" }\n" +
" return this;\n" +
"}");
}
// slight variation of test18
@Test
public void test18_b() {
testRewriter("function addMethods(source) {\n" +
" var properties = Object.keys(source);\n" +
" for (var i = 0, length = properties.length; i < length; i++) {\n" +
" var property = properties[i], foo = 23, value = source[property];\n" +
" this.prototype[property] = value;\n" +
" }\n" +
" return this;\n" +
"}",
"function addMethods(source) {\n" +
" var properties = Object.keys(source);\n" +
" for (var i = 0, length = properties.length; i < length; i++) {\n" +
" var property = properties[i], foo = 23, value; value = (function _forin_body_0(property, thi$) { var value; value = source[property];\n" +
" thi$.prototype[property] = value; return value; })(property, this);\n" +
" }\n" +
" return this;\n" +
"}");
}
// fails since the assignment to "value" in the extracted version gets a (spurious) reference error CFG edge
@Test
public void test18_c() {
testRewriter("function addMethods(source) {\n" +
" var properties = Object.keys(source);\n" +
" for (var i = 0, length = properties.length; i < length; i++) {\n" +
" var property = properties[i], foo = 23, value = source[property], bar = 42;\n" +
" this.prototype[property] = value;\n" +
" }\n" +
" return this;\n" +
"}",
"function addMethods(source) {\n" +
" var properties = Object.keys(source);\n" +
" for (var i = 0, length = properties.length; i < length; i++) {\n" +
" var property = properties[i], foo = 23, value, bar; value = (function _forin_body_0(property, thi$) { var value; value = source[property], bar = 42;\n" +
" thi$.prototype[property] = value; return value; })(property, this);\n" +
" }\n" + " }\n" +
" return this;\n" + " return this;\n" +
"}"); "}");
@ -442,11 +485,12 @@ public abstract class TestCorrelatedPairExtraction {
"function write(p, v) { this[p] = v; }", "function write(p, v) { this[p] = v; }",
"function extend(dest, src) {\n" + "function extend(dest, src) {\n" +
" for(var p in src)\n" + " for(var p in src)\n" +
" if(foo(p)) (function _forin_body_0(p) { write.call(dest, p, src[p]); })(p);\n" + " (function _forin_body_0(p) { if(foo(p)) write.call(dest, p, src[p]); })(p);\n" +
"}\n" + "}\n" +
"function write(p, v) { this[p] = v; }"); "function write(p, v) { this[p] = v; }");
} }
// fails due to a missing LOCAL_SCOPE node
@Test @Test
public void test20() { public void test20() {
testRewriter("function every(object, fn, bind) {\n" + testRewriter("function every(object, fn, bind) {\n" +
@ -476,10 +520,69 @@ public abstract class TestCorrelatedPairExtraction {
"function extend(dest, src) {\n" + "function extend(dest, src) {\n" +
" var x, y;\n" + " var x, y;\n" +
" for(var name in src) {\n" + " for(var name in src) {\n" +
" (function _forin_body_0(name) { { x = dest[name];\n" + " (function _forin_body_0(name) { x = dest[name];\n" +
" y = src[name];\n" + " y = src[name];\n" +
" dest[name] = join(x,y); } })(name);\n" + " dest[name] = join(x,y); })(name);\n" +
" }\n" + " }\n" +
"}"); "}");
} }
@Test
public void test22() {
testRewriter("function(object, keys){\n" +
" var results = {};\n" +
" for (var i = 0, l = keys.length; i < l; i++){\n" +
" var k = keys[i];\n" +
" if (k in object) results[k] = object[k];\n" +
" }\n" +
" return results;\n" +
"}",
"function(object, keys){\n" +
" var results = {};\n" +
" for (var i = 0, l = keys.length; i < l; i++){\n" +
" var k = keys[i];\n" +
" (function _forin_body_0(k) { if (k in object) results[k] = object[k]; })(k);\n" +
" }\n" +
" return results;\n" +
"}");
}
// variant of test1
@Test
public void test23() {
testRewriter("function extend(dest, src) {\n" +
" var s;\n" +
" for(var p in src) {\n" +
" s = src[p];\n" +
" dest[p] = s;\n" +
" }\n" +
"}",
"function extend(dest, src) {\n" +
" var s;\n" +
" for(var p in src) {\n" +
" s = (function _forin_body_0(p) {\n" +
" var s;" +
" s = src[p];\n" +
" dest[p] = s;\n" +
" return s;" +
" })(p);\n" +
" }\n" +
"}");
}
// cannot extract for-in body referring to "arguments"
@Test
public void test24() {
testRewriter("function extend(dest, src) {" +
" for(var p in src) {" +
" arguments[0][p] = src[p];" +
" }" +
"}",
"function extend(dest, src) {" +
" for(var p in src) {" +
" arguments[0][p] = src[p];" +
" }" +
"}");
}
} }

View File

@ -587,7 +587,7 @@ public abstract class TestForInBodyExtraction {
} }
// this test fails since the rewritten CAst contains one more level of blocks // this test fails since the rewritten CAst contains one more level of blocks
@Test @Ignore @Test
public void test24() { public void test24() {
testRewriter("var addSlickPseudos = function() {" + testRewriter("var addSlickPseudos = function() {" +
" for(var name in pseudos)" + " for(var name in pseudos)" +
@ -759,4 +759,19 @@ public abstract class TestForInBodyExtraction {
" }" + " }" +
"} catch(_) {}"); "} catch(_) {}");
} }
// cannot extract for-in body referring to "arguments"
@Test
public void test31() {
testRewriter("function extend(dest, src) {" +
" for(var p in src) {" +
" arguments[0][p] = src[p];" +
" }" +
"}",
"function extend(dest, src) {" +
" for(var p in src) {" +
" arguments[0][p] = src[p];" +
" }" +
"}");
}
} }

View File

@ -24,26 +24,26 @@ public abstract class TestForInLoopHack extends TestJSCallGraphShape {
@Test public void testPage3WithoutHack() throws IOException, IllegalArgumentException, CancelException { @Test public void testPage3WithoutHack() throws IOException, IllegalArgumentException, CancelException {
URL url = getClass().getClassLoader().getResource("pages/page3.html"); URL url = getClass().getClassLoader().getResource("pages/page3.html");
JSCFABuilder builder = Util.makeHTMLCGBuilder(url); JSCFABuilder builder = JSCallGraphBuilderUtil.makeHTMLCGBuilder(url);
CallGraph CG = builder.makeCallGraph(builder.getOptions()); CallGraph CG = builder.makeCallGraph(builder.getOptions());
Util.dumpCG(builder.getPointerAnalysis(), CG); JSCallGraphBuilderUtil.dumpCG(builder.getPointerAnalysis(), CG);
} }
@Test public void testPage3WithHack() throws IOException, IllegalArgumentException, CancelException { @Test public void testPage3WithHack() throws IOException, IllegalArgumentException, CancelException {
URL url = getClass().getClassLoader().getResource("pages/page3.html"); URL url = getClass().getClassLoader().getResource("pages/page3.html");
JSCFABuilder builder = Util.makeHTMLCGBuilder(url); JSCFABuilder builder = JSCallGraphBuilderUtil.makeHTMLCGBuilder(url);
addHackedForInLoopSensitivity(builder); addHackedForInLoopSensitivity(builder);
CallGraph CG = builder.makeCallGraph(builder.getOptions()); CallGraph CG = builder.makeCallGraph(builder.getOptions());
Util.dumpCG(builder.getPointerAnalysis(), CG); JSCallGraphBuilderUtil.dumpCG(builder.getPointerAnalysis(), CG);
} }
@Ignore("This test now blows up due to proper handling of the || construct, used in extend(). Should handle this eventually.") @Ignore("This test now blows up due to proper handling of the || construct, used in extend(). Should handle this eventually.")
@Test public void testJQueryWithHack() throws IOException, IllegalArgumentException, CancelException { @Test public void testJQueryWithHack() throws IOException, IllegalArgumentException, CancelException {
URL url = getClass().getClassLoader().getResource("pages/jquery_hacked.html"); URL url = getClass().getClassLoader().getResource("pages/jquery_hacked.html");
JSCFABuilder builder = Util.makeHTMLCGBuilder(url); JSCFABuilder builder = JSCallGraphBuilderUtil.makeHTMLCGBuilder(url);
addHackedForInLoopSensitivity(builder); addHackedForInLoopSensitivity(builder);
CallGraph CG = builder.makeCallGraph(builder.getOptions()); CallGraph CG = builder.makeCallGraph(builder.getOptions());
Util.dumpCG(builder.getPointerAnalysis(), CG); JSCallGraphBuilderUtil.dumpCG(builder.getPointerAnalysis(), CG);
} }
/* /*
@ -74,9 +74,9 @@ public abstract class TestForInLoopHack extends TestJSCallGraphShape {
}; };
@Test public void testBadForInWithoutHack() throws IOException, IllegalArgumentException, CancelException { @Test public void testBadForInWithoutHack() throws IOException, IllegalArgumentException, CancelException {
JSCFABuilder B = Util.makeScriptCGBuilder("tests", "badforin.js"); JSCFABuilder B = JSCallGraphBuilderUtil.makeScriptCGBuilder("tests", "badforin.js");
CallGraph CG = B.makeCallGraph(B.getOptions()); CallGraph CG = B.makeCallGraph(B.getOptions());
Util.dumpCG(B.getPointerAnalysis(), CG); JSCallGraphBuilderUtil.dumpCG(B.getPointerAnalysis(), CG);
verifyGraphAssertions(CG, assertionsForBadForin); verifyGraphAssertions(CG, assertionsForBadForin);
} }
@ -92,10 +92,10 @@ public abstract class TestForInLoopHack extends TestJSCallGraphShape {
}; };
@Test public void testBadForInWithHack() throws IOException, IllegalArgumentException, CancelException { @Test public void testBadForInWithHack() throws IOException, IllegalArgumentException, CancelException {
JSCFABuilder B = Util.makeScriptCGBuilder("tests", "badforin.js"); JSCFABuilder B = JSCallGraphBuilderUtil.makeScriptCGBuilder("tests", "badforin.js");
addHackedForInLoopSensitivity(B); addHackedForInLoopSensitivity(B);
CallGraph CG = B.makeCallGraph(B.getOptions()); CallGraph CG = B.makeCallGraph(B.getOptions());
Util.dumpCG(B.getPointerAnalysis(), CG); JSCallGraphBuilderUtil.dumpCG(B.getPointerAnalysis(), CG);
verifyGraphAssertions(CG, assertionsForBadForin); verifyGraphAssertions(CG, assertionsForBadForin);
verifyGraphAssertions(CG, assertionsForBadForinHackPrecision); verifyGraphAssertions(CG, assertionsForBadForinHackPrecision);
} }
@ -118,9 +118,9 @@ public abstract class TestForInLoopHack extends TestJSCallGraphShape {
}; };
@Test public void testbadforin2WithoutHack() throws IOException, IllegalArgumentException, CancelException { @Test public void testbadforin2WithoutHack() throws IOException, IllegalArgumentException, CancelException {
JSCFABuilder B = Util.makeScriptCGBuilder("tests", "badforin2.js"); JSCFABuilder B = JSCallGraphBuilderUtil.makeScriptCGBuilder("tests", "badforin2.js");
CallGraph CG = B.makeCallGraph(B.getOptions()); CallGraph CG = B.makeCallGraph(B.getOptions());
Util.dumpCG(B.getPointerAnalysis(), CG); JSCallGraphBuilderUtil.dumpCG(B.getPointerAnalysis(), CG);
verifyGraphAssertions(CG, assertionsForbadforin2); verifyGraphAssertions(CG, assertionsForbadforin2);
} }
@ -136,14 +136,22 @@ public abstract class TestForInLoopHack extends TestJSCallGraphShape {
}; };
@Test public void testbadforin2WithHack() throws IOException, IllegalArgumentException, CancelException { @Test public void testbadforin2WithHack() throws IOException, IllegalArgumentException, CancelException {
JSCFABuilder B = Util.makeScriptCGBuilder("tests", "badforin2.js"); JSCFABuilder B = JSCallGraphBuilderUtil.makeScriptCGBuilder("tests", "badforin2.js");
addHackedForInLoopSensitivity(B); addHackedForInLoopSensitivity(B);
CallGraph CG = B.makeCallGraph(B.getOptions()); CallGraph CG = B.makeCallGraph(B.getOptions());
Util.dumpCG(B.getPointerAnalysis(), CG); JSCallGraphBuilderUtil.dumpCG(B.getPointerAnalysis(), CG);
verifyGraphAssertions(CG, assertionsForbadforin2); verifyGraphAssertions(CG, assertionsForbadforin2);
verifyGraphAssertions(CG, assertionsForbadforin2HackPrecision); verifyGraphAssertions(CG, assertionsForbadforin2HackPrecision);
} }
@Test public void testForInRecursion() throws IOException, IllegalArgumentException, CancelException {
JSCFABuilder B = JSCallGraphBuilderUtil.makeScriptCGBuilder("tests", "badforin3.js");
addHackedForInLoopSensitivity(B);
CallGraph CG = B.makeCallGraph(B.getOptions());
JSCallGraphBuilderUtil.dumpCG(B.getPointerAnalysis(), CG);
}
/* /*
@Test public void testYahooWithoutHack() throws IOException, IllegalArgumentException, CancelException { @Test public void testYahooWithoutHack() throws IOException, IllegalArgumentException, CancelException {
JSCFABuilder B = Util.makeScriptCGBuilder("frameworks", "yahoo.js"); JSCFABuilder B = Util.makeScriptCGBuilder("frameworks", "yahoo.js");

View File

@ -0,0 +1,35 @@
package com.ibm.wala.cast.js.test;
import java.io.IOException;
import java.net.URL;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import com.ibm.wala.cast.ipa.callgraph.CAstCallGraphUtil;
import com.ibm.wala.cast.js.html.JSSourceExtractor;
import com.ibm.wala.cast.js.ipa.callgraph.JSCFABuilder;
import com.ibm.wala.ipa.callgraph.CallGraph;
import com.ibm.wala.util.CancelException;
public class TestJQueryExamples extends TestJSCallGraphShape {
public static void main(String[] args) {
justThisTest(TestJQueryExamples.class);
}
@Before
public void config() {
JSSourceExtractor.USE_TEMP_NAME = false;
JSSourceExtractor.DELETE_UPON_EXIT = false;
}
@Ignore("This tries to analyze unmodified jquery, which we can't do yet")
@Test public void testEx1() throws IOException, IllegalArgumentException, CancelException {
URL url = getClass().getClassLoader().getResource("pages/jquery/ex1.html");
JSCFABuilder builder = JSCallGraphBuilderUtil.makeHTMLCGBuilder(url);
CallGraph CG = builder.makeCallGraph(builder.getOptions());
CAstCallGraphUtil.dumpCG(builder.getPointerAnalysis(), CG);
}
}

View File

@ -18,7 +18,7 @@ import com.ibm.wala.ipa.callgraph.CallGraph;
public abstract class TestJSCallGraphShape extends TestCallGraphShape { public abstract class TestJSCallGraphShape extends TestCallGraphShape {
protected Collection getNodes(CallGraph CG, String functionIdentifier) { protected Collection getNodes(CallGraph CG, String functionIdentifier) {
return Util.getNodes(CG, functionIdentifier); return JSCallGraphBuilderUtil.getNodes(CG, functionIdentifier);
} }
} }

View File

@ -13,6 +13,7 @@ package com.ibm.wala.cast.js.test;
import java.io.IOException; import java.io.IOException;
import java.net.URL; import java.net.URL;
import org.junit.Ignore;
import org.junit.Test; import org.junit.Test;
import com.ibm.wala.ipa.callgraph.CallGraph; import com.ibm.wala.ipa.callgraph.CallGraph;
@ -28,9 +29,10 @@ public abstract class TestMediawikiCallGraphShape extends TestJSCallGraphShape {
}; };
@Ignore("not terminating; Julian, take a look?")
@Test public void testSwineFlu() throws IOException, IllegalArgumentException, CancelException { @Test public void testSwineFlu() throws IOException, IllegalArgumentException, CancelException {
URL url = new URL("http://en.wikipedia.org/wiki/2009_swine_flu_outbreak"); URL url = new URL("http://en.wikipedia.org/wiki/2009_swine_flu_outbreak");
CallGraph CG = Util.makeHTMLCG(url); CallGraph CG = JSCallGraphBuilderUtil.makeHTMLCG(url);
verifyGraphAssertions(CG, assertionsForSwineFlu); verifyGraphAssertions(CG, assertionsForSwineFlu);
} }

View File

@ -25,30 +25,30 @@ public abstract class TestMozillaBugPages extends TestJSCallGraphShape {
@Test public void testMozilla439164() throws IOException, IllegalArgumentException, CancelException { @Test public void testMozilla439164() throws IOException, IllegalArgumentException, CancelException {
URL url = getClass().getClassLoader().getResource("pages/mochitest/mozillaBug439164.html"); URL url = getClass().getClassLoader().getResource("pages/mochitest/mozillaBug439164.html");
JSCFABuilder builder = Util.makeHTMLCGBuilder(url); JSCFABuilder builder = JSCallGraphBuilderUtil.makeHTMLCGBuilder(url);
CallGraph CG = builder.makeCallGraph(builder.getOptions()); CallGraph CG = builder.makeCallGraph(builder.getOptions());
Util.dumpCG(builder.getPointerAnalysis(), CG); JSCallGraphBuilderUtil.dumpCG(builder.getPointerAnalysis(), CG);
} }
@Test public void testMozilla488233() throws IOException, IllegalArgumentException, CancelException { @Test public void testMozilla488233() throws IOException, IllegalArgumentException, CancelException {
URL url = getClass().getClassLoader().getResource("pages/mochitest/mozillaBug488233NoExtJS.html"); URL url = getClass().getClassLoader().getResource("pages/mochitest/mozillaBug488233NoExtJS.html");
JSCFABuilder builder = Util.makeHTMLCGBuilder(url); JSCFABuilder builder = JSCallGraphBuilderUtil.makeHTMLCGBuilder(url);
CallGraph CG = builder.makeCallGraph(builder.getOptions()); CallGraph CG = builder.makeCallGraph(builder.getOptions());
Util.dumpCG(builder.getPointerAnalysis(), CG); JSCallGraphBuilderUtil.dumpCG(builder.getPointerAnalysis(), CG);
} }
@Test public void testMozilla490152() throws IOException, IllegalArgumentException, CancelException { @Test public void testMozilla490152() throws IOException, IllegalArgumentException, CancelException {
URL url = getClass().getClassLoader().getResource("pages/mochitest/mozillaBug490152NoExtJS.html"); URL url = getClass().getClassLoader().getResource("pages/mochitest/mozillaBug490152NoExtJS.html");
JSCFABuilder builder = Util.makeHTMLCGBuilder(url); JSCFABuilder builder = JSCallGraphBuilderUtil.makeHTMLCGBuilder(url);
CallGraph CG = builder.makeCallGraph(builder.getOptions()); CallGraph CG = builder.makeCallGraph(builder.getOptions());
Util.dumpCG(builder.getPointerAnalysis(), CG); JSCallGraphBuilderUtil.dumpCG(builder.getPointerAnalysis(), CG);
} }
@Test public void testMozilla625562() throws IOException, IllegalArgumentException, CancelException { @Test public void testMozilla625562() throws IOException, IllegalArgumentException, CancelException {
URL url = getClass().getClassLoader().getResource("pages/mochitest/mozillaBug625562NoExtJS.html"); URL url = getClass().getClassLoader().getResource("pages/mochitest/mozillaBug625562NoExtJS.html");
JSCFABuilder builder = Util.makeHTMLCGBuilder(url); JSCFABuilder builder = JSCallGraphBuilderUtil.makeHTMLCGBuilder(url);
CallGraph CG = builder.makeCallGraph(builder.getOptions()); CallGraph CG = builder.makeCallGraph(builder.getOptions());
Util.dumpCG(builder.getPointerAnalysis(), CG); JSCallGraphBuilderUtil.dumpCG(builder.getPointerAnalysis(), CG);
} }
} }

View File

@ -19,6 +19,8 @@ import junit.framework.Assert;
import org.junit.Test; import org.junit.Test;
import com.ibm.wala.cast.js.ipa.callgraph.JSCFABuilder;
import com.ibm.wala.cast.js.ipa.callgraph.JSCallGraphUtil;
import com.ibm.wala.ipa.callgraph.CGNode; import com.ibm.wala.ipa.callgraph.CGNode;
import com.ibm.wala.ipa.callgraph.CallGraph; import com.ibm.wala.ipa.callgraph.CallGraph;
import com.ibm.wala.ipa.callgraph.propagation.InstanceKey; import com.ibm.wala.ipa.callgraph.propagation.InstanceKey;
@ -42,6 +44,18 @@ public abstract class TestSimpleCallGraphShape extends TestJSCallGraphShape {
justThisTest(TestSimpleCallGraphShape.class); justThisTest(TestSimpleCallGraphShape.class);
} }
protected static final Object[][] assertionsForArgs = new Object[][] {
new Object[] { ROOT, new String[] { "tests/args.js" } },
new Object[] {
"tests/args.js",
new String[] { "tests/args.js/a" } },
new Object[] { "tests/args.js/a", new String[] { "tests/args.js/x", "tests/args.js/y" } } };
@Test public void testArgs() throws IOException, IllegalArgumentException, CancelException {
CallGraph CG = JSCallGraphBuilderUtil.makeScriptCG("tests", "args.js");
verifyGraphAssertions(CG, assertionsForArgs);
}
protected static final Object[][] assertionsForSimple = new Object[][] { protected static final Object[][] assertionsForSimple = new Object[][] {
new Object[] { ROOT, new String[] { "tests/simple.js" } }, new Object[] { ROOT, new String[] { "tests/simple.js" } },
new Object[] { new Object[] {
@ -56,7 +70,7 @@ public abstract class TestSimpleCallGraphShape extends TestJSCallGraphShape {
@Test @Test
public void testSimple() throws IOException, IllegalArgumentException, CancelException { public void testSimple() throws IOException, IllegalArgumentException, CancelException {
CallGraph CG = Util.makeScriptCG("tests", "simple.js"); CallGraph CG = JSCallGraphBuilderUtil.makeScriptCG("tests", "simple.js");
verifyGraphAssertions(CG, assertionsForSimple); verifyGraphAssertions(CG, assertionsForSimple);
} }
@ -70,7 +84,7 @@ public abstract class TestSimpleCallGraphShape extends TestJSCallGraphShape {
@Test @Test
public void testObjects() throws IOException, IllegalArgumentException, CancelException { public void testObjects() throws IOException, IllegalArgumentException, CancelException {
CallGraph CG = Util.makeScriptCG("tests", "objects.js"); CallGraph CG = JSCallGraphBuilderUtil.makeScriptCG("tests", "objects.js");
verifyGraphAssertions(CG, assertionsForObjects); verifyGraphAssertions(CG, assertionsForObjects);
} }
@ -91,7 +105,7 @@ public abstract class TestSimpleCallGraphShape extends TestJSCallGraphShape {
@Test @Test
public void testInherit() throws IOException, IllegalArgumentException, CancelException { public void testInherit() throws IOException, IllegalArgumentException, CancelException {
CallGraph CG = Util.makeScriptCG("tests", "inherit.js"); CallGraph CG = JSCallGraphBuilderUtil.makeScriptCG("tests", "inherit.js");
verifyGraphAssertions(CG, assertionsForInherit); verifyGraphAssertions(CG, assertionsForInherit);
} }
@ -102,7 +116,7 @@ public abstract class TestSimpleCallGraphShape extends TestJSCallGraphShape {
@Test @Test
public void testNewfn() throws IOException, IllegalArgumentException, CancelException { public void testNewfn() throws IOException, IllegalArgumentException, CancelException {
CallGraph CG = Util.makeScriptCG("tests", "newfn.js"); CallGraph CG = JSCallGraphBuilderUtil.makeScriptCG("tests", "newfn.js");
verifyGraphAssertions(CG, assertionsForNewfn); verifyGraphAssertions(CG, assertionsForNewfn);
} }
@ -115,7 +129,7 @@ public abstract class TestSimpleCallGraphShape extends TestJSCallGraphShape {
@Test @Test
public void testControlflow() throws IOException, IllegalArgumentException, CancelException { public void testControlflow() throws IOException, IllegalArgumentException, CancelException {
CallGraph CG = Util.makeScriptCG("tests", "control-flow.js"); CallGraph CG = JSCallGraphBuilderUtil.makeScriptCG("tests", "control-flow.js");
verifyGraphAssertions(CG, assertionsForControlflow); verifyGraphAssertions(CG, assertionsForControlflow);
} }
@ -129,7 +143,7 @@ public abstract class TestSimpleCallGraphShape extends TestJSCallGraphShape {
@Test @Test
public void testMoreControlflow() throws IOException, IllegalArgumentException, CancelException { public void testMoreControlflow() throws IOException, IllegalArgumentException, CancelException {
CallGraph CG = Util.makeScriptCG("tests", "more-control-flow.js"); CallGraph CG = JSCallGraphBuilderUtil.makeScriptCG("tests", "more-control-flow.js");
verifyGraphAssertions(CG, assertionsForMoreControlflow); verifyGraphAssertions(CG, assertionsForMoreControlflow);
} }
@ -139,7 +153,10 @@ public abstract class TestSimpleCallGraphShape extends TestJSCallGraphShape {
@Test @Test
public void testForin() throws IOException, IllegalArgumentException, CancelException { public void testForin() throws IOException, IllegalArgumentException, CancelException {
CallGraph CG = Util.makeScriptCG("tests", "forin.js"); JSCFABuilder B = JSCallGraphBuilderUtil.makeScriptCGBuilder("tests", "forin.js");
CallGraph CG = B.makeCallGraph(B.getOptions());
// JSCallGraphUtil.AVOID_DUMP = false;
JSCallGraphUtil.dumpCG(B.getPointerAnalysis(), CG);
verifyGraphAssertions(CG, assertionsForForin); verifyGraphAssertions(CG, assertionsForForin);
} }
@ -157,14 +174,14 @@ public abstract class TestSimpleCallGraphShape extends TestJSCallGraphShape {
@Test @Test
public void testSimpleLexical() throws IOException, IllegalArgumentException, CancelException { public void testSimpleLexical() throws IOException, IllegalArgumentException, CancelException {
CallGraph CG = Util.makeScriptCG("tests", "simple-lexical.js"); CallGraph CG = JSCallGraphBuilderUtil.makeScriptCG("tests", "simple-lexical.js");
verifyGraphAssertions(CG, assertionsForSimpleLexical); verifyGraphAssertions(CG, assertionsForSimpleLexical);
} }
@Test @Test
public void testRecursiveLexical() throws IOException, IllegalArgumentException, CancelException { public void testRecursiveLexical() throws IOException, IllegalArgumentException, CancelException {
// just checking that we have a sufficient bailout to ensure termination // just checking that we have a sufficient bailout to ensure termination
Util.makeScriptCG("tests", "recursive_lexical.js"); JSCallGraphBuilderUtil.makeScriptCG("tests", "recursive_lexical.js");
} }
private static final Object[][] assertionsForLexicalMultiple = new Object[][] { private static final Object[][] assertionsForLexicalMultiple = new Object[][] {
@ -174,7 +191,7 @@ public abstract class TestSimpleCallGraphShape extends TestJSCallGraphShape {
@Test @Test
public void testLexicalMultiple() throws IOException, IllegalArgumentException, CancelException { public void testLexicalMultiple() throws IOException, IllegalArgumentException, CancelException {
CallGraph CG = Util.makeScriptCG("tests", "lexical_multiple_calls.js"); CallGraph CG = JSCallGraphBuilderUtil.makeScriptCG("tests", "lexical_multiple_calls.js");
verifyGraphAssertions(CG, assertionsForLexicalMultiple); verifyGraphAssertions(CG, assertionsForLexicalMultiple);
} }
@ -192,7 +209,7 @@ public abstract class TestSimpleCallGraphShape extends TestJSCallGraphShape {
@Test @Test
public void testTry() throws IOException, IllegalArgumentException, CancelException { public void testTry() throws IOException, IllegalArgumentException, CancelException {
CallGraph CG = Util.makeScriptCG("tests", "try.js", true); CallGraph CG = JSCallGraphBuilderUtil.makeScriptCG("tests", "try.js");
verifyGraphAssertions(CG, assertionsForTry); verifyGraphAssertions(CG, assertionsForTry);
} }
@ -202,7 +219,7 @@ public abstract class TestSimpleCallGraphShape extends TestJSCallGraphShape {
@Test @Test
public void testStringOp() throws IOException, IllegalArgumentException, CancelException { public void testStringOp() throws IOException, IllegalArgumentException, CancelException {
PropagationCallGraphBuilder B = Util.makeScriptCGBuilder("tests", "string-op.js"); PropagationCallGraphBuilder B = JSCallGraphBuilderUtil.makeScriptCGBuilder("tests", "string-op.js");
B.getOptions().setTraceStringConstants(true); B.getOptions().setTraceStringConstants(true);
CallGraph CG = B.makeCallGraph(B.getOptions()); CallGraph CG = B.makeCallGraph(B.getOptions());
verifyGraphAssertions(CG, assertionsForStringOp); verifyGraphAssertions(CG, assertionsForStringOp);
@ -217,7 +234,7 @@ public abstract class TestSimpleCallGraphShape extends TestJSCallGraphShape {
@Test @Test
public void testUpward() throws IOException, IllegalArgumentException, CancelException { public void testUpward() throws IOException, IllegalArgumentException, CancelException {
CallGraph CG = Util.makeScriptCG("tests", "upward.js"); CallGraph CG = JSCallGraphBuilderUtil.makeScriptCG("tests", "upward.js");
verifyGraphAssertions(CG, assertionsForUpward); verifyGraphAssertions(CG, assertionsForUpward);
} }
@ -227,9 +244,11 @@ public abstract class TestSimpleCallGraphShape extends TestJSCallGraphShape {
@Test @Test
public void testStringPrims() throws IOException, IllegalArgumentException, CancelException { public void testStringPrims() throws IOException, IllegalArgumentException, CancelException {
PropagationCallGraphBuilder B = Util.makeScriptCGBuilder("tests", "string-prims.js"); PropagationCallGraphBuilder B = JSCallGraphBuilderUtil.makeScriptCGBuilder("tests", "string-prims.js");
B.getOptions().setTraceStringConstants(true); B.getOptions().setTraceStringConstants(true);
CallGraph CG = B.makeCallGraph(B.getOptions()); CallGraph CG = B.makeCallGraph(B.getOptions());
// JSCallGraphUtil.AVOID_DUMP = false;
JSCallGraphUtil.dumpCG(B.getPointerAnalysis(), CG);
verifyGraphAssertions(CG, assertionsForStringPrims); verifyGraphAssertions(CG, assertionsForStringPrims);
} }
@ -238,7 +257,7 @@ public abstract class TestSimpleCallGraphShape extends TestJSCallGraphShape {
@Test @Test
public void testNested() throws IOException, IllegalArgumentException, CancelException { public void testNested() throws IOException, IllegalArgumentException, CancelException {
PropagationCallGraphBuilder B = Util.makeScriptCGBuilder("tests", "nested.js"); PropagationCallGraphBuilder B = JSCallGraphBuilderUtil.makeScriptCGBuilder("tests", "nested.js");
CallGraph CG = B.makeCallGraph(B.getOptions()); CallGraph CG = B.makeCallGraph(B.getOptions());
verifyGraphAssertions(CG, assertionsForNested); verifyGraphAssertions(CG, assertionsForNested);
} }
@ -248,7 +267,7 @@ public abstract class TestSimpleCallGraphShape extends TestJSCallGraphShape {
@Test @Test
public void testInstanceof() throws IOException, IllegalArgumentException, CancelException { public void testInstanceof() throws IOException, IllegalArgumentException, CancelException {
PropagationCallGraphBuilder B = Util.makeScriptCGBuilder("tests", "instanceof.js"); PropagationCallGraphBuilder B = JSCallGraphBuilderUtil.makeScriptCGBuilder("tests", "instanceof.js");
CallGraph CG = B.makeCallGraph(B.getOptions()); CallGraph CG = B.makeCallGraph(B.getOptions());
verifyGraphAssertions(CG, assertionsForInstanceof); verifyGraphAssertions(CG, assertionsForInstanceof);
} }
@ -266,19 +285,19 @@ public abstract class TestSimpleCallGraphShape extends TestJSCallGraphShape {
@Test @Test
public void testCrash1() throws IOException, IllegalArgumentException, CancelException { public void testCrash1() throws IOException, IllegalArgumentException, CancelException {
CallGraph CG = Util.makeScriptCG("tests", "crash1.js"); CallGraph CG = JSCallGraphBuilderUtil.makeScriptCG("tests", "crash1.js");
verifyGraphAssertions(CG, null); verifyGraphAssertions(CG, null);
} }
@Test @Test
public void testCrash2() throws IOException, IllegalArgumentException, CancelException { public void testCrash2() throws IOException, IllegalArgumentException, CancelException {
CallGraph CG = Util.makeScriptCG("tests", "crash2.js"); CallGraph CG = JSCallGraphBuilderUtil.makeScriptCG("tests", "crash2.js");
verifyGraphAssertions(CG, null); verifyGraphAssertions(CG, null);
} }
@Test @Test
public void testLexicalCtor() throws IOException, IllegalArgumentException, CancelException { public void testLexicalCtor() throws IOException, IllegalArgumentException, CancelException {
CallGraph CG = Util.makeScriptCG("tests", "lexical-ctor.js"); CallGraph CG = JSCallGraphBuilderUtil.makeScriptCG("tests", "lexical-ctor.js");
verifyGraphAssertions(CG, null); verifyGraphAssertions(CG, null);
} }
@ -288,7 +307,7 @@ public abstract class TestSimpleCallGraphShape extends TestJSCallGraphShape {
@Test @Test
public void testMultivar() throws IOException, IllegalArgumentException, CancelException { public void testMultivar() throws IOException, IllegalArgumentException, CancelException {
CallGraph CG = Util.makeScriptCG("tests", "multivar.js"); CallGraph CG = JSCallGraphBuilderUtil.makeScriptCG("tests", "multivar.js");
verifyGraphAssertions(CG, assertionsForMultivar); verifyGraphAssertions(CG, assertionsForMultivar);
} }
@ -299,7 +318,7 @@ public abstract class TestSimpleCallGraphShape extends TestJSCallGraphShape {
@Test @Test
public void testProtoypeContamination() throws IOException, IllegalArgumentException, CancelException { public void testProtoypeContamination() throws IOException, IllegalArgumentException, CancelException {
CallGraph CG = Util.makeScriptCG("tests", "prototype_contamination_bug.js"); CallGraph CG = JSCallGraphBuilderUtil.makeScriptCG("tests", "prototype_contamination_bug.js");
verifyGraphAssertions(CG, assertionsForPrototypeContamination); verifyGraphAssertions(CG, assertionsForPrototypeContamination);
verifyNoEdges(CG, "suffix:test1", "suffix:foo_of_B"); verifyNoEdges(CG, "suffix:test1", "suffix:foo_of_B");
verifyNoEdges(CG, "suffix:test2", "suffix:foo_of_A"); verifyNoEdges(CG, "suffix:test2", "suffix:foo_of_A");
@ -307,20 +326,20 @@ public abstract class TestSimpleCallGraphShape extends TestJSCallGraphShape {
@Test @Test
public void testStackOverflowOnSsaConversionBug() throws IOException, IllegalArgumentException, CancelException { public void testStackOverflowOnSsaConversionBug() throws IOException, IllegalArgumentException, CancelException {
Util.makeScriptCG("tests", "stack_overflow_on_ssa_conversion.js"); JSCallGraphBuilderUtil.makeScriptCG("tests", "stack_overflow_on_ssa_conversion.js");
// all we need is for it to finish building CG successfully. // all we need is for it to finish building CG successfully.
} }
@Test @Test
public void testExtJSSwitch() throws IOException, IllegalArgumentException, CancelException { public void testExtJSSwitch() throws IOException, IllegalArgumentException, CancelException {
Util.makeScriptCG("tests", "extjs_switch.js"); JSCallGraphBuilderUtil.makeScriptCG("tests", "extjs_switch.js");
// all we need is for it to finish building CG successfully. // all we need is for it to finish building CG successfully.
} }
@Test @Test
public void testFunctionDotCall() throws IOException, IllegalArgumentException, CancelException { public void testFunctionDotCall() throws IOException, IllegalArgumentException, CancelException {
CallGraph cg = Util.makeScriptCG("tests", "function_call.js"); CallGraph cg = JSCallGraphBuilderUtil.makeScriptCG("tests", "function_call.js");
for (CGNode n : cg) { for (CGNode n : cg) {
if (n.getMethod().getName().toString().equals("call4")) { if (n.getMethod().getName().toString().equals("call4")) {
Assert.assertEquals(2, cg.getSuccNodeCount(n)); Assert.assertEquals(2, cg.getSuccNodeCount(n));
@ -342,7 +361,7 @@ public abstract class TestSimpleCallGraphShape extends TestJSCallGraphShape {
@Test @Test
public void testFunctionDotApply() throws IOException, IllegalArgumentException, CancelException { public void testFunctionDotApply() throws IOException, IllegalArgumentException, CancelException {
CallGraph CG = Util.makeScriptCG("tests", "function_apply.js"); CallGraph CG = JSCallGraphBuilderUtil.makeScriptCG("tests", "function_apply.js");
verifyGraphAssertions(CG, assertionsForFunctionApply); verifyGraphAssertions(CG, assertionsForFunctionApply);
} }
@ -352,7 +371,7 @@ public abstract class TestSimpleCallGraphShape extends TestJSCallGraphShape {
@Test @Test
public void testFunctionDotApply2() throws IOException, IllegalArgumentException, CancelException { public void testFunctionDotApply2() throws IOException, IllegalArgumentException, CancelException {
CallGraph CG = Util.makeScriptCG("tests", "function_apply2.js"); CallGraph CG = JSCallGraphBuilderUtil.makeScriptCG("tests", "function_apply2.js");
verifyGraphAssertions(CG, assertionsForFunctionApply2); verifyGraphAssertions(CG, assertionsForFunctionApply2);
} }
@ -362,7 +381,7 @@ public abstract class TestSimpleCallGraphShape extends TestJSCallGraphShape {
@Test @Test
public void testWrap1() throws IllegalArgumentException, IOException, CancelException { public void testWrap1() throws IllegalArgumentException, IOException, CancelException {
CallGraph CG = Util.makeScriptCG("tests", "wrap1.js"); CallGraph CG = JSCallGraphBuilderUtil.makeScriptCG("tests", "wrap1.js");
verifyGraphAssertions(CG, assertionsForWrap1); verifyGraphAssertions(CG, assertionsForWrap1);
} }
@ -372,7 +391,7 @@ public abstract class TestSimpleCallGraphShape extends TestJSCallGraphShape {
@Test @Test
public void testWrap2() throws IllegalArgumentException, IOException, CancelException { public void testWrap2() throws IllegalArgumentException, IOException, CancelException {
CallGraph CG = Util.makeScriptCG("tests", "wrap2.js"); CallGraph CG = JSCallGraphBuilderUtil.makeScriptCG("tests", "wrap2.js");
verifyGraphAssertions(CG, assertionsForWrap2); verifyGraphAssertions(CG, assertionsForWrap2);
} }
@ -382,7 +401,7 @@ public abstract class TestSimpleCallGraphShape extends TestJSCallGraphShape {
@Test @Test
public void testWrap3() throws IllegalArgumentException, IOException, CancelException { public void testWrap3() throws IllegalArgumentException, IOException, CancelException {
CallGraph CG = Util.makeScriptCG("tests", "wrap3.js"); CallGraph CG = JSCallGraphBuilderUtil.makeScriptCG("tests", "wrap3.js");
verifyGraphAssertions(CG, assertionsForWrap3); verifyGraphAssertions(CG, assertionsForWrap3);
} }
@ -392,7 +411,7 @@ public abstract class TestSimpleCallGraphShape extends TestJSCallGraphShape {
@Test @Test
public void testComplexCall() throws IOException, IllegalArgumentException, CancelException { public void testComplexCall() throws IOException, IllegalArgumentException, CancelException {
CallGraph CG = Util.makeScriptCG("tests", "complex_call.js"); CallGraph CG = JSCallGraphBuilderUtil.makeScriptCG("tests", "complex_call.js");
for(CGNode nd : CG) for(CGNode nd : CG)
System.out.println(nd); System.out.println(nd);
verifyGraphAssertions(CG, assertionsForComplexCall); verifyGraphAssertions(CG, assertionsForComplexCall);
@ -405,7 +424,7 @@ public abstract class TestSimpleCallGraphShape extends TestJSCallGraphShape {
@Test @Test
public void testGlobalObjPassing() throws IOException, IllegalArgumentException, CancelException { public void testGlobalObjPassing() throws IOException, IllegalArgumentException, CancelException {
CallGraph CG = Util.makeScriptCG("tests", "global_object.js"); CallGraph CG = JSCallGraphBuilderUtil.makeScriptCG("tests", "global_object.js");
verifyGraphAssertions(CG, assertionsForGlobalObj); verifyGraphAssertions(CG, assertionsForGlobalObj);
} }
@ -415,7 +434,7 @@ public abstract class TestSimpleCallGraphShape extends TestJSCallGraphShape {
@Test @Test
public void testGlobalObj2() throws IOException, IllegalArgumentException, CancelException { public void testGlobalObj2() throws IOException, IllegalArgumentException, CancelException {
CallGraph CG = Util.makeScriptCG("tests", "global_object2.js"); CallGraph CG = JSCallGraphBuilderUtil.makeScriptCG("tests", "global_object2.js");
verifyGraphAssertions(CG, assertionsForGlobalObj2); verifyGraphAssertions(CG, assertionsForGlobalObj2);
} }
@ -427,7 +446,10 @@ public abstract class TestSimpleCallGraphShape extends TestJSCallGraphShape {
@Test @Test
public void testReturnThis() throws IOException, IllegalArgumentException, CancelException { public void testReturnThis() throws IOException, IllegalArgumentException, CancelException {
CallGraph CG = Util.makeScriptCG("tests", "return_this.js"); PropagationCallGraphBuilder B = JSCallGraphBuilderUtil.makeScriptCGBuilder("tests", "return_this.js");
CallGraph CG = B.makeCallGraph(B.getOptions());
// JSCallGraphUtil.AVOID_DUMP = false;
JSCallGraphUtil.dumpCG(B.getPointerAnalysis(), CG);
verifyGraphAssertions(CG, assertionsForReturnThis); verifyGraphAssertions(CG, assertionsForReturnThis);
} }
@ -445,19 +467,19 @@ public abstract class TestSimpleCallGraphShape extends TestJSCallGraphShape {
@Test @Test
public void testReturnThis2() throws IOException, IllegalArgumentException, CancelException { public void testReturnThis2() throws IOException, IllegalArgumentException, CancelException {
CallGraph CG = Util.makeScriptCG("tests", "return_this2.js"); CallGraph CG = JSCallGraphBuilderUtil.makeScriptCG("tests", "return_this2.js");
verifyGraphAssertions(CG, assertionsForReturnThis2); verifyGraphAssertions(CG, assertionsForReturnThis2);
} }
private static final Object[][] assertionsForArguments = new Object[][] { private static final Object[][] assertionsForArguments = new Object[][] {
new Object[] { ROOT, new String[] { "tests/arguments.js" } }, new Object[] { ROOT, new String[] { "tests/arguments.js" } },
new Object[] { "suffix:arguments.js", new String[] { "suffix:f" } }, new Object[] { "suffix:arguments.js", new String[] { "suffix:f" } },
new Object[] { "suffix:f", new String[] { "suffix:g3" } } // but neither "suffix:g1" nor "suffix:g2" new Object[] { "suffix:f", new String[] { "!suffix:g1", "!suffix:g2", "suffix:g3", } }
}; };
@Test @Test
public void testArguments() throws IOException, IllegalArgumentException, CancelException { public void testArguments() throws IOException, IllegalArgumentException, CancelException {
CallGraph CG = Util.makeScriptCG("tests", "arguments.js"); CallGraph CG = JSCallGraphBuilderUtil.makeScriptCG("tests", "arguments.js");
verifyGraphAssertions(CG, assertionsForArguments); verifyGraphAssertions(CG, assertionsForArguments);
} }
@ -467,7 +489,7 @@ public abstract class TestSimpleCallGraphShape extends TestJSCallGraphShape {
@Test @Test
public void testFunctionIsAFunction() throws IOException, IllegalArgumentException, CancelException { public void testFunctionIsAFunction() throws IOException, IllegalArgumentException, CancelException {
CallGraph CG = Util.makeScriptCG("tests", "Function_is_a_function.js"); CallGraph CG = JSCallGraphBuilderUtil.makeScriptCG("tests", "Function_is_a_function.js");
verifyGraphAssertions(CG, assertionsForFunctionIsAFunction); verifyGraphAssertions(CG, assertionsForFunctionIsAFunction);
} }
@ -479,13 +501,51 @@ public abstract class TestSimpleCallGraphShape extends TestJSCallGraphShape {
@Test @Test
public void testLexicalBroken() throws IOException, IllegalArgumentException, CancelException { public void testLexicalBroken() throws IOException, IllegalArgumentException, CancelException {
CallGraph CG = Util.makeScriptCG("tests", "lexical_broken.js"); CallGraph CG = JSCallGraphBuilderUtil.makeScriptCG("tests", "lexical_broken.js");
verifyGraphAssertions(CG, assertionsForLexicalBroken); verifyGraphAssertions(CG, assertionsForLexicalBroken);
} }
@Test @Test
public void testDeadPhi() throws IllegalArgumentException, IOException, CancelException { public void testDeadPhi() throws IllegalArgumentException, IOException, CancelException {
Util.makeScriptCG("tests", "dead_phi.js"); JSCallGraphBuilderUtil.makeScriptCG("tests", "dead_phi.js");
}
private static final Object[][] assertionsForScopingOverwriteFunction = new Object[][] {
new Object[] { ROOT, new String[] { "tests/scoping_test.js" } },
new Object[] { "suffix:scoping_test.js", new String[] { "suffix:i_am_reachable" } }
};
@Test
public void testScopingOverwriteFunction() throws IllegalArgumentException, IOException, CancelException {
CallGraph CG = JSCallGraphBuilderUtil.makeScriptCG("tests", "scoping_test.js");
verifyGraphAssertions(CG, assertionsForScopingOverwriteFunction);
}
private static final Object[][] assertionsForNestedParamAssign = new Object[][] {
new Object[] { ROOT, new String[] { "tests/nested_assign_to_param.js" } },
new Object[] { "suffix:nested_assign_to_param.js", new String[] { "suffix:i_am_reachable" } }
};
@Test
public void testNestedAssignToParam() throws IllegalArgumentException, IOException, CancelException {
CallGraph CG = JSCallGraphBuilderUtil.makeScriptCG("tests", "nested_assign_to_param.js");
verifyGraphAssertions(CG, assertionsForNestedParamAssign);
}
private static final Object[][] assertionsForDispatch = new Object[][] {
new Object[] { ROOT, new String[] { "tests/dispatch.js" } },
new Object[] { "tests/dispatch.js", new String[] { "tests/dispatch.js/left_outer", "tests/dispatch.js/right_outer" } },
new Object[] { "tests/dispatch.js/left_outer", new String[]{ "tests/dispatch.js/left_inner" } },
new Object[] { "tests/dispatch.js/right_outer", new String[]{ "tests/dispatch.js/right_inner" } }
};
@Test
public void testDispatch() throws IOException, IllegalArgumentException, CancelException {
PropagationCallGraphBuilder B = JSCallGraphBuilderUtil.makeScriptCGBuilder("tests", "dispatch.js");
CallGraph CG = B.makeCallGraph(B.getOptions());
// JSCallGraphUtil.AVOID_DUMP = false;
JSCallGraphUtil.dumpCG(B.getPointerAnalysis(), CG);
verifyGraphAssertions(CG, assertionsForDispatch);
} }
protected IVector<Set<Pair<CGNode, Integer>>> computeIkIdToVns(PointerAnalysis pa) { protected IVector<Set<Pair<CGNode, Integer>>> computeIkIdToVns(PointerAnalysis pa) {

View File

@ -41,12 +41,6 @@ public abstract class TestSimplePageCallGraphShape extends TestJSCallGraphShape
}); });
} }
@Before
public void config() {
JSSourceExtractor.USE_TEMP_NAME = false;
JSSourceExtractor.DELETE_UPON_EXIT = true;
}
private static final Object[][] assertionsForPage1 = new Object[][] { private static final Object[][] assertionsForPage1 = new Object[][] {
new Object[] { ROOT, new String[] { "page1.html" } }, new Object[] { ROOT, new String[] { "page1.html" } },
new Object[] { "page1.html", new String[] { "page1.html/__WINDOW_MAIN__" } }, new Object[] { "page1.html", new String[] { "page1.html/__WINDOW_MAIN__" } },
@ -61,7 +55,7 @@ public abstract class TestSimplePageCallGraphShape extends TestJSCallGraphShape
@Test public void testPage1() throws IOException, IllegalArgumentException, CancelException { @Test public void testPage1() throws IOException, IllegalArgumentException, CancelException {
URL url = getClass().getClassLoader().getResource("pages/page1.html"); URL url = getClass().getClassLoader().getResource("pages/page1.html");
CallGraph CG = Util.makeHTMLCG(url); CallGraph CG = JSCallGraphBuilderUtil.makeHTMLCG(url);
verifyGraphAssertions(CG, assertionsForPage1); verifyGraphAssertions(CG, assertionsForPage1);
} }
@ -72,7 +66,7 @@ public abstract class TestSimplePageCallGraphShape extends TestJSCallGraphShape
@Test public void testPage2() throws IOException, IllegalArgumentException, CancelException { @Test public void testPage2() throws IOException, IllegalArgumentException, CancelException {
URL url = getClass().getClassLoader().getResource("pages/page2.html"); URL url = getClass().getClassLoader().getResource("pages/page2.html");
CallGraph CG = Util.makeHTMLCG(url); CallGraph CG = JSCallGraphBuilderUtil.makeHTMLCG(url);
verifyGraphAssertions(CG, assertionsForPage2); verifyGraphAssertions(CG, assertionsForPage2);
} }
@ -89,7 +83,7 @@ public abstract class TestSimplePageCallGraphShape extends TestJSCallGraphShape
@Test public void testCrawlPage11() throws IOException, IllegalArgumentException, CancelException { @Test public void testCrawlPage11() throws IOException, IllegalArgumentException, CancelException {
URL url = getClass().getClassLoader().getResource("pages/crawl/page11.html"); URL url = getClass().getClassLoader().getResource("pages/crawl/page11.html");
CallGraph CG = Util.makeHTMLCG(url); CallGraph CG = JSCallGraphBuilderUtil.makeHTMLCG(url);
verifyGraphAssertions(CG, assertionsForPage11); verifyGraphAssertions(CG, assertionsForPage11);
} }
@ -106,7 +100,7 @@ public abstract class TestSimplePageCallGraphShape extends TestJSCallGraphShape
@Test public void testCrawlPage11b() throws IOException, IllegalArgumentException, CancelException { @Test public void testCrawlPage11b() throws IOException, IllegalArgumentException, CancelException {
URL url = getClass().getClassLoader().getResource("pages/crawl/page11b.html"); URL url = getClass().getClassLoader().getResource("pages/crawl/page11b.html");
CallGraph CG = Util.makeHTMLCG(url); CallGraph CG = JSCallGraphBuilderUtil.makeHTMLCG(url);
verifyGraphAssertions(CG, assertionsForPage11b); verifyGraphAssertions(CG, assertionsForPage11b);
} }
@ -138,7 +132,7 @@ public abstract class TestSimplePageCallGraphShape extends TestJSCallGraphShape
@Test public void testCrawlPage12() throws IOException, IllegalArgumentException, CancelException { @Test public void testCrawlPage12() throws IOException, IllegalArgumentException, CancelException {
URL url = getClass().getClassLoader().getResource("pages/crawl/page12.html"); URL url = getClass().getClassLoader().getResource("pages/crawl/page12.html");
CallGraph CG = Util.makeHTMLCG(url); CallGraph CG = JSCallGraphBuilderUtil.makeHTMLCG(url);
verifyGraphAssertions(CG, assertionsForPage12); verifyGraphAssertions(CG, assertionsForPage12);
} }
@ -171,7 +165,7 @@ public abstract class TestSimplePageCallGraphShape extends TestJSCallGraphShape
@Test public void testCrawlPage13() throws IOException, IllegalArgumentException, CancelException { @Test public void testCrawlPage13() throws IOException, IllegalArgumentException, CancelException {
URL url = getClass().getClassLoader().getResource("pages/crawl/page13.html"); URL url = getClass().getClassLoader().getResource("pages/crawl/page13.html");
CallGraph CG = Util.makeHTMLCG(url); CallGraph CG = JSCallGraphBuilderUtil.makeHTMLCG(url);
verifyGraphAssertions(CG, assertionsForPage13); verifyGraphAssertions(CG, assertionsForPage13);
} }
@ -189,7 +183,7 @@ public abstract class TestSimplePageCallGraphShape extends TestJSCallGraphShape
@Test public void testCrawlPage15() throws IOException, IllegalArgumentException, CancelException { @Test public void testCrawlPage15() throws IOException, IllegalArgumentException, CancelException {
URL url = getClass().getClassLoader().getResource("pages/crawl/page15.html"); URL url = getClass().getClassLoader().getResource("pages/crawl/page15.html");
CallGraph CG = Util.makeHTMLCG(url); CallGraph CG = JSCallGraphBuilderUtil.makeHTMLCG(url);
verifyGraphAssertions(CG, assertionsForPage15); verifyGraphAssertions(CG, assertionsForPage15);
} }
@ -207,7 +201,7 @@ public abstract class TestSimplePageCallGraphShape extends TestJSCallGraphShape
@Test public void testCrawlPage16() throws IOException, IllegalArgumentException, CancelException { @Test public void testCrawlPage16() throws IOException, IllegalArgumentException, CancelException {
URL url = getClass().getClassLoader().getResource("pages/crawl/page16.html"); URL url = getClass().getClassLoader().getResource("pages/crawl/page16.html");
CallGraph CG = Util.makeHTMLCG(url); CallGraph CG = JSCallGraphBuilderUtil.makeHTMLCG(url);
verifyGraphAssertions(CG, assertionsForPage16); verifyGraphAssertions(CG, assertionsForPage16);
} }
@ -230,7 +224,7 @@ public abstract class TestSimplePageCallGraphShape extends TestJSCallGraphShape
@Test public void testCrawlPage17() throws IOException, IllegalArgumentException, CancelException { @Test public void testCrawlPage17() throws IOException, IllegalArgumentException, CancelException {
URL url = getClass().getClassLoader().getResource("pages/crawl/page17.html"); URL url = getClass().getClassLoader().getResource("pages/crawl/page17.html");
CallGraph CG = Util.makeHTMLCG(url); CallGraph CG = JSCallGraphBuilderUtil.makeHTMLCG(url);
verifyGraphAssertions(CG, assertionsForPage17); verifyGraphAssertions(CG, assertionsForPage17);
} }
@ -243,25 +237,25 @@ public abstract class TestSimplePageCallGraphShape extends TestJSCallGraphShape
@Test public void testApolloExample() throws IOException, IllegalArgumentException, CancelException { @Test public void testApolloExample() throws IOException, IllegalArgumentException, CancelException {
URL url = getClass().getClassLoader().getResource("pages/apollo-example.html"); URL url = getClass().getClassLoader().getResource("pages/apollo-example.html");
CallGraph CG = Util.makeHTMLCG(url); CallGraph CG = JSCallGraphBuilderUtil.makeHTMLCG(url);
verifyGraphAssertions(CG, assertionsForApolloExample); verifyGraphAssertions(CG, assertionsForApolloExample);
} }
@Test public void testNojs() throws IOException, IllegalArgumentException, CancelException { @Test public void testNojs() throws IOException, IllegalArgumentException, CancelException {
URL url = getClass().getClassLoader().getResource("pages/nojs.html"); URL url = getClass().getClassLoader().getResource("pages/nojs.html");
// all we need is for it to finish building CG successfully. // all we need is for it to finish building CG successfully.
Util.makeHTMLCG(url); JSCallGraphBuilderUtil.makeHTMLCG(url);
} }
@Test public void testPage4() throws IOException, IllegalArgumentException, CancelException { @Test public void testPage4() throws IOException, IllegalArgumentException, CancelException {
URL url = getClass().getClassLoader().getResource("pages/page4.html"); URL url = getClass().getClassLoader().getResource("pages/page4.html");
Util.makeHTMLCG(url); JSCallGraphBuilderUtil.makeHTMLCG(url);
} }
private static final Object[][] sourceAssertionsForList = new Object[][] { private static final Object[][] sourceAssertionsForList = new Object[][] {
new Object[]{ "suffix:update_display", "list.html", 9, 18 }, new Object[]{ "suffix:update_display", "list.html#2", 4, 13 },
new Object[]{ "suffix:update_with_item", "list.html", 14, 16 }, new Object[]{ "suffix:update_with_item", "list.html#2", 9, 11 },
new Object[]{ "suffix:add_item", "list.html", 20, 25 }, new Object[]{ "suffix:add_item", "list.html#2", 15, 20 },
new Object[]{ "suffix:collection", "pages/collection.js", 2, 14 }, new Object[]{ "suffix:collection", "pages/collection.js", 2, 14 },
new Object[]{ "suffix:collection_add", "pages/collection.js", 7, 13 }, new Object[]{ "suffix:collection_add", "pages/collection.js", 7, 13 },
new Object[]{ "suffix:forall_elt", "pages/collection.js", 9, 12 }, new Object[]{ "suffix:forall_elt", "pages/collection.js", 9, 12 },
@ -270,15 +264,16 @@ public abstract class TestSimplePageCallGraphShape extends TestJSCallGraphShape
@Test public void testList() throws IOException, IllegalArgumentException, CancelException { @Test public void testList() throws IOException, IllegalArgumentException, CancelException {
URL url = getClass().getClassLoader().getResource("pages/list.html"); URL url = getClass().getClassLoader().getResource("pages/list.html");
JSCFABuilder builder = Util.makeHTMLCGBuilder(url); JSCFABuilder builder = JSCallGraphBuilderUtil.makeHTMLCGBuilder(url);
CallGraph CG = builder.makeCallGraph(builder.getOptions()); CallGraph CG = builder.makeCallGraph(builder.getOptions());
Util.dumpCG(builder.getPointerAnalysis(), CG); // JSCallGraphBuilderUtil.AVOID_DUMP = false;
JSCallGraphBuilderUtil.dumpCG(builder.getPointerAnalysis(), CG);
verifySourceAssertions(CG, sourceAssertionsForList); verifySourceAssertions(CG, sourceAssertionsForList);
} }
@Test public void testIframeTest2() throws IOException, IllegalArgumentException, CancelException { @Test public void testIframeTest2() throws IOException, IllegalArgumentException, CancelException {
URL url = getClass().getClassLoader().getResource("pages/iframeTest2.html"); URL url = getClass().getClassLoader().getResource("pages/iframeTest2.html");
Util.makeHTMLCG(url); JSCallGraphBuilderUtil.makeHTMLCG(url);
} }
private static final Object[][] assertionsForWindowx = new Object[][] { private static final Object[][] assertionsForWindowx = new Object[][] {
@ -292,9 +287,9 @@ public abstract class TestSimplePageCallGraphShape extends TestJSCallGraphShape
@Test public void testWindowx() throws IOException, IllegalArgumentException, CancelException { @Test public void testWindowx() throws IOException, IllegalArgumentException, CancelException {
URL url = getClass().getClassLoader().getResource("pages/windowx.html"); URL url = getClass().getClassLoader().getResource("pages/windowx.html");
JSCFABuilder builder = Util.makeHTMLCGBuilder(url); JSCFABuilder builder = JSCallGraphBuilderUtil.makeHTMLCGBuilder(url);
CallGraph CG = builder.makeCallGraph(builder.getOptions()); CallGraph CG = builder.makeCallGraph(builder.getOptions());
Util.dumpCG(builder.getPointerAnalysis(), CG); JSCallGraphBuilderUtil.dumpCG(builder.getPointerAnalysis(), CG);
verifyGraphAssertions(CG, assertionsForWindowx); verifyGraphAssertions(CG, assertionsForWindowx);
} }

File diff suppressed because it is too large Load Diff

View File

@ -2,8 +2,8 @@
<classpath> <classpath>
<classpathentry kind="src" path="source"/> <classpathentry kind="src" path="source"/>
<classpathentry kind="src" path="dat"/> <classpathentry kind="src" path="dat"/>
<classpathentry kind="lib" path="lib/jericho-html-3.2.jar"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/> <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/> <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
<classpathentry kind="lib" path="lib/jericho-html-3.2.jar"/>
<classpathentry kind="output" path="bin"/> <classpathentry kind="output" path="bin"/>
</classpath> </classpath>

View File

@ -3,11 +3,16 @@ primitive = new Primitives();
// core definitions needed to make anything work, even what follows // core definitions needed to make anything work, even what follows
Object = primitive("NewObject"); Object = primitive("NewObject");
Function = primitive("NewFunction"); var local_function = primitive("NewFunction");
Array = primitive("NewArray"); Function = local_function;
String = primitive("NewString"); var local_array = primitive("NewArray");
Number = primitive("NewNumber"); Array = local_array;
RegExp = primitive("NewRegExp"); var local_string = primitive("NewString");
String = local_string;
var local_number = primitive("NewNumber");
Number = local_number;
var local_regexp = primitive("NewRegExp");
RegExp = local_regexp;
/************************************************************************/ /************************************************************************/
/* Global properties, see spec 15.1 */ /* Global properties, see spec 15.1 */
@ -104,7 +109,7 @@ Object.prototype = {
/* Function properties, see spec 15.3 */ /* Function properties, see spec 15.3 */
/************************************************************************/ /************************************************************************/
Function.prototype = { local_function.prototype = {
constructor: Function, constructor: Function,
@ -124,15 +129,15 @@ Function.prototype = {
} }
}; };
Function.__proto__ = Function.prototype; local_function.__proto__ = Function.prototype;
/************************************************************************/ /************************************************************************/
/* Array properties, see spec 15.4 */ /* Array properties, see spec 15.4 */
/************************************************************************/ /************************************************************************/
Array.__proto__ = Function.prototype; local_array.__proto__ = Function.prototype;
Array.prototype = { local_array.prototype = {
__proto__: Object.prototype, __proto__: Object.prototype,
@ -251,9 +256,9 @@ Array.prototype = {
/* String properties, see spec 15.4 */ /* String properties, see spec 15.4 */
/************************************************************************/ /************************************************************************/
String.__proto__ = Function.prototype; local_string.__proto__ = Function.prototype;
String.prototype = { local_string.prototype = {
__proto__: Object.prototype, __proto__: Object.prototype,
@ -329,9 +334,9 @@ String.prototype = {
/* Number properties, see spec 15.7 */ /* Number properties, see spec 15.7 */
/************************************************************************/ /************************************************************************/
Number.__proto__ = Function.prototype; local_number.__proto__ = Function.prototype;
Number.prototype = { local_number.prototype = {
__proto__: Object.prototype, __proto__: Object.prototype,
@ -419,9 +424,9 @@ Math = {
/* RegExp properties, see spec 15.10 */ /* RegExp properties, see spec 15.10 */
/************************************************************************/ /************************************************************************/
RegExp.__proto__ = Function.prototype; local_regexp.__proto__ = Function.prototype;
RegExp.prototype = { local_regexp.prototype = {
__proto__: Object.prototype, __proto__: Object.prototype,

View File

@ -22,6 +22,8 @@ import com.ibm.wala.cast.js.ssa.JavaScriptPropertyRead;
import com.ibm.wala.cast.js.ssa.JavaScriptPropertyWrite; import com.ibm.wala.cast.js.ssa.JavaScriptPropertyWrite;
import com.ibm.wala.cast.js.ssa.JavaScriptTypeOfInstruction; import com.ibm.wala.cast.js.ssa.JavaScriptTypeOfInstruction;
import com.ibm.wala.cast.js.ssa.JavaScriptWithRegion; import com.ibm.wala.cast.js.ssa.JavaScriptWithRegion;
import com.ibm.wala.cast.js.ssa.PrototypeLookup;
import com.ibm.wala.cast.js.ssa.SetPrototype;
import com.ibm.wala.cast.js.types.JavaScriptTypes; import com.ibm.wala.cast.js.types.JavaScriptTypes;
import com.ibm.wala.fixpoint.IVariable; import com.ibm.wala.fixpoint.IVariable;
import com.ibm.wala.ipa.cha.IClassHierarchy; import com.ibm.wala.ipa.cha.IClassHierarchy;
@ -36,7 +38,7 @@ public class JSTypeInference extends AstTypeInference {
} }
protected void initialize() { protected void initialize() {
class JSTypeOperatorFactory extends AstTypeOperatorFactory implements com.ibm.wala.cast.js.ssa.InstructionVisitor { class JSTypeOperatorFactory extends AstTypeOperatorFactory implements com.ibm.wala.cast.js.ssa.JSInstructionVisitor {
public void visitJavaScriptInvoke(JavaScriptInvoke inst) { public void visitJavaScriptInvoke(JavaScriptInvoke inst) {
result = new DeclaredTypeOperator(new ConeType(cha.getRootClass())); result = new DeclaredTypeOperator(new ConeType(cha.getRootClass()));
} }
@ -61,6 +63,15 @@ public class JSTypeInference extends AstTypeInference {
public void visitWithRegion(JavaScriptWithRegion instruction) { public void visitWithRegion(JavaScriptWithRegion instruction) {
} }
@Override
public void visitSetPrototype(SetPrototype instruction) {
}
@Override
public void visitPrototypeLookup(PrototypeLookup instruction) {
result = new DeclaredTypeOperator(new ConeType(cha.getRootClass()));
}
} }
; ;

View File

@ -11,7 +11,7 @@
package com.ibm.wala.cast.js.cfg; package com.ibm.wala.cast.js.cfg;
import com.ibm.wala.cast.ir.cfg.AstInducedCFG; import com.ibm.wala.cast.ir.cfg.AstInducedCFG;
import com.ibm.wala.cast.js.ssa.InstructionVisitor; import com.ibm.wala.cast.js.ssa.JSInstructionVisitor;
import com.ibm.wala.cast.js.ssa.JavaScriptCheckReference; import com.ibm.wala.cast.js.ssa.JavaScriptCheckReference;
import com.ibm.wala.cast.js.ssa.JavaScriptInstanceOf; import com.ibm.wala.cast.js.ssa.JavaScriptInstanceOf;
import com.ibm.wala.cast.js.ssa.JavaScriptInvoke; import com.ibm.wala.cast.js.ssa.JavaScriptInvoke;
@ -19,6 +19,8 @@ import com.ibm.wala.cast.js.ssa.JavaScriptPropertyRead;
import com.ibm.wala.cast.js.ssa.JavaScriptPropertyWrite; import com.ibm.wala.cast.js.ssa.JavaScriptPropertyWrite;
import com.ibm.wala.cast.js.ssa.JavaScriptTypeOfInstruction; import com.ibm.wala.cast.js.ssa.JavaScriptTypeOfInstruction;
import com.ibm.wala.cast.js.ssa.JavaScriptWithRegion; import com.ibm.wala.cast.js.ssa.JavaScriptWithRegion;
import com.ibm.wala.cast.js.ssa.PrototypeLookup;
import com.ibm.wala.cast.js.ssa.SetPrototype;
import com.ibm.wala.classLoader.IMethod; import com.ibm.wala.classLoader.IMethod;
import com.ibm.wala.ipa.callgraph.Context; import com.ibm.wala.ipa.callgraph.Context;
import com.ibm.wala.ssa.SSAInstruction; import com.ibm.wala.ssa.SSAInstruction;
@ -29,7 +31,7 @@ public class JSInducedCFG extends AstInducedCFG {
super(instructions, method, context); super(instructions, method, context);
} }
class JSPEIVisitor extends AstPEIVisitor implements InstructionVisitor { class JSPEIVisitor extends AstPEIVisitor implements JSInstructionVisitor {
JSPEIVisitor(boolean[] r) { JSPEIVisitor(boolean[] r) {
super(r); super(r);
@ -59,9 +61,17 @@ public class JSInducedCFG extends AstInducedCFG {
public void visitWithRegion(JavaScriptWithRegion instruction) { public void visitWithRegion(JavaScriptWithRegion instruction) {
} }
@Override
public void visitSetPrototype(SetPrototype instruction) {
} }
class JSBranchVisitor extends AstBranchVisitor implements InstructionVisitor { @Override
public void visitPrototypeLookup(PrototypeLookup instruction) {
}
}
class JSBranchVisitor extends AstBranchVisitor implements JSInstructionVisitor {
JSBranchVisitor(boolean[] r) { JSBranchVisitor(boolean[] r) {
super(r); super(r);
@ -87,6 +97,14 @@ public class JSInducedCFG extends AstInducedCFG {
public void visitWithRegion(JavaScriptWithRegion instruction) { public void visitWithRegion(JavaScriptWithRegion instruction) {
} }
@Override
public void visitSetPrototype(SetPrototype instruction) {
}
@Override
public void visitPrototypeLookup(PrototypeLookup instruction) {
}
} }
protected BranchVisitor makeBranchVisitor(boolean[] r) { protected BranchVisitor makeBranchVisitor(boolean[] r) {

View File

@ -0,0 +1,35 @@
package com.ibm.wala.cast.js.html;
import java.io.PrintStream;
import com.ibm.wala.cast.tree.CAstSourcePositionMap.Position;
public class CompositeFileMapping implements FileMapping {
private final FileMapping a;
private final FileMapping b;
public CompositeFileMapping(FileMapping a, FileMapping b) {
this.a = a;
this.b = b;
}
@Override
public IncludedPosition getIncludedPosition(Position line) {
IncludedPosition p = a.getIncludedPosition(line);
if (p != null) {
return p;
} else {
return b.getIncludedPosition(line);
}
}
@Override
public void dump(PrintStream ps) {
// TODO Auto-generated method stub
}
public String toString() {
return a + "," + b;
}
}

View File

@ -11,19 +11,22 @@
package com.ibm.wala.cast.js.html; package com.ibm.wala.cast.js.html;
import java.net.MalformedURLException;
import java.net.URL; import java.net.URL;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry;
import java.util.Set; import java.util.Set;
import java.util.Stack; import java.util.Stack;
import com.ibm.wala.cast.tree.CAstSourcePositionMap.Position;
import com.ibm.wala.util.collections.HashMapFactory; import com.ibm.wala.util.collections.HashMapFactory;
import com.ibm.wala.util.collections.Pair; import com.ibm.wala.util.collections.Pair;
public class DefaultSourceExtractor extends DomLessSourceExtractor{ public class DefaultSourceExtractor extends DomLessSourceExtractor{
private static class HtmlCallBack extends DomLessSourceExtractor.HtmlCallback{ protected static class HtmlCallBack extends DomLessSourceExtractor.HtmlCallback{
private final HashMap<String, String> constructors = HashMapFactory.make(); private final HashMap<String, String> constructors = HashMapFactory.make();
@ -45,9 +48,15 @@ public class DefaultSourceExtractor extends DomLessSourceExtractor{
if (tag.getName().equalsIgnoreCase("FORM")) { if (tag.getName().equalsIgnoreCase("FORM")) {
forms.pop(); forms.pop();
} }
for(String v : tag.getAllAttributes().values()) { for(Entry<String,Pair<String, Position>> e : tag.getAllAttributes().entrySet()) {
String a = e.getKey();
String v = e.getValue().fst;
if (v != null && v.startsWith("javascript:")) { if (v != null && v.startsWith("javascript:")) {
entrypointRegion.println(v.substring(11), makePos(tag.getStartingLineNum(), tag)); try {
entrypointRegion.println(" " + v.substring(11), e.getValue().snd, new URL(tag.getElementPosition().getURL().toString() + "#" + a));
} catch (MalformedURLException ex) {
entrypointRegion.println(v.substring(11), e.getValue().snd, entrypointUrl);
}
} }
} }
} }
@ -62,16 +71,20 @@ public class DefaultSourceExtractor extends DomLessSourceExtractor{
} }
private void printlnIndented(String line, ITag relatedTag){ private void printlnIndented(String line, ITag relatedTag){
printlnIndented(line, relatedTag==null? null: relatedTag.getElementPosition());
}
private void printlnIndented(String line, Position pos){
StringBuilder indentedLine = new StringBuilder(); StringBuilder indentedLine = new StringBuilder();
for (int i = 0 ; i < stack.size() ; i++){ for (int i = 0 ; i < stack.size() ; i++){
indentedLine.append(" "); indentedLine.append(" ");
} }
indentedLine.append(line); indentedLine.append(line);
if (relatedTag == null){ if (pos == null){
domRegion.println(indentedLine.toString()); domRegion.println(indentedLine.toString());
} else { } else {
domRegion.println(indentedLine.toString(), makePos(relatedTag.getStartingLineNum(), relatedTag)); domRegion.println(indentedLine.toString(), pos, entrypointUrl);
} }
} }
@ -80,16 +93,17 @@ public class DefaultSourceExtractor extends DomLessSourceExtractor{
} }
protected void writeElement(ITag tag, String cons, String varName){ protected void writeElement(ITag tag, String cons, String varName){
Map<String, Pair<String, Position>> attrs = tag.getAllAttributes();
printlnIndented("function make_" + varName + "(parent) {", tag); printlnIndented("function make_" + varName + "(parent) {", tag);
stack.push(varName); stack.push(varName);
printlnIndented("this.temp = " + cons + ";", tag); printlnIndented("this.temp = " + cons + ";", tag);
printlnIndented("this.temp(\"" + tag.getName() + "\");", tag); printlnIndented("this.temp(\"" + tag.getName() + "\");", tag);
for (Map.Entry<String, String> e : tag.getAllAttributes().entrySet()){ for (Map.Entry<String, Pair<String, Position>> e : attrs.entrySet()){
String attr = e.getKey(); String attr = e.getKey();
String value = e.getValue(); String value = e.getValue().fst;
writeAttribute(tag, attr, value, "this", varName); writeAttribute(tag, e.getValue().snd, attr, value, "this", varName);
} }
if (tag.getName().equalsIgnoreCase("FORM")) { if (tag.getName().equalsIgnoreCase("FORM")) {
@ -97,15 +111,8 @@ public class DefaultSourceExtractor extends DomLessSourceExtractor{
printlnIndented(" document.forms[document.formCount++] = this;", tag); printlnIndented(" document.forms[document.formCount++] = this;", tag);
printlnIndented(" var currentForm = this;", tag); printlnIndented(" var currentForm = this;", tag);
} if (tag.getName().equalsIgnoreCase("INPUT")) { } if (tag.getName().equalsIgnoreCase("INPUT")) {
String prop = tag.getAttributeByName("NAME"); String prop = attrs.containsKey("name") ? attrs.get("name").fst : null;
if (prop == null) { String type = attrs.containsKey("type") ? attrs.get("type").fst : null;
prop = tag.getAttributeByName("name");
}
String type = tag.getAttributeByName("TYPE");
if (type == null) {
type = tag.getAttributeByName("type");
}
if (type != null && prop != null) { if (type != null && prop != null) {
if (type.equalsIgnoreCase("RADIO")) { if (type.equalsIgnoreCase("RADIO")) {
@ -126,15 +133,15 @@ public class DefaultSourceExtractor extends DomLessSourceExtractor{
printlnIndented("parent.appendChild(this);", tag); printlnIndented("parent.appendChild(this);", tag);
} }
protected void writeAttribute(ITag tag, String attr, String value, String varName, String varName2) { protected void writeAttribute(ITag tag, Position pos, String attr, String value, String varName, String varName2) {
writePortletAttribute(tag, attr, value, varName); writePortletAttribute(tag, attr, value, varName);
writeEventAttribute(tag, attr, value, varName, varName2); writeEventAttribute(tag, pos, attr, value, varName, varName2);
} }
protected void writeEventAttribute(ITag tag, String attr, String value, String varName, String varName2){ protected void writeEventAttribute(ITag tag, Position pos, String attr, String value, String varName, String varName2){
if(attr.substring(0,2).equals("on")) { if(attr.substring(0,2).equals("on")) {
printlnIndented(varName + "." + attr + " = function " + tag.getName().toLowerCase() + "_" + attr + "(event) {" + value + "};", tag); printlnIndented(varName + "." + attr + " = function " + tag.getName().toLowerCase() + "_" + attr + "(event) {" + value + "};", tag);
entrypointRegion.println(varName2 + "." + attr + "(null);", makePos(tag.getStartingLineNum(), tag)); entrypointRegion.println(varName2 + "." + attr + "(null);", tag.getElementPosition(), entrypointUrl);
} else if (value != null) { } else if (value != null) {
if (value.indexOf('\'') > 0) { if (value.indexOf('\'') > 0) {
value = value.replaceAll("\\'", "\\\\'"); value = value.replaceAll("\\'", "\\\\'");
@ -162,11 +169,11 @@ public class DefaultSourceExtractor extends DomLessSourceExtractor{
} }
protected void endElement(String name) { protected void endElement(String name) {
printlnIndented("};", null); printlnIndented("};", (Position)null);
if (stack.isEmpty()) { if (stack.isEmpty()) {
printlnIndented("new make_" + name + "(document);\n\n", null); printlnIndented("new make_" + name + "(document);\n\n", (Position)null);
} else { } else {
printlnIndented("new make_" + name + "(this);\n", null); printlnIndented("new make_" + name + "(this);\n", (Position)null);
} }
} }
} }

View File

@ -24,13 +24,13 @@ import java.util.Set;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import com.ibm.wala.cast.js.html.jericho.JerichoHtmlParser; import com.ibm.wala.cast.js.html.jericho.JerichoHtmlParser;
import com.ibm.wala.cast.tree.impl.LineNumberPosition; import com.ibm.wala.cast.tree.CAstSourcePositionMap.Position;
import com.ibm.wala.util.functions.Function; import com.ibm.wala.util.collections.Pair;
public class DomLessSourceExtractor extends JSSourceExtractor { public class DomLessSourceExtractor extends JSSourceExtractor {
private static final Pattern LEGAL_JS_IDENTIFIER_REGEXP = Pattern.compile("[a-zA-Z$_][a-zA-Z\\d$_]*"); private static final Pattern LEGAL_JS_IDENTIFIER_REGEXP = Pattern.compile("[a-zA-Z$_][a-zA-Z\\d$_]*");
interface IGeneratorCallback extends IHtmlCallback { protected interface IGeneratorCallback extends IHtmlCallback {
void writeToFinalRegion(SourceRegion finalRegion); void writeToFinalRegion(SourceRegion finalRegion);
} }
@ -44,7 +44,8 @@ public class DomLessSourceExtractor extends JSSourceExtractor {
private ITag currentScriptTag; private ITag currentScriptTag;
private int counter = 0; private int nodeCounter = 0;
private int scriptNodeCounter = 0;
public HtmlCallback(URL entrypointUrl, IUrlResolver urlResolver) { public HtmlCallback(URL entrypointUrl, IUrlResolver urlResolver) {
this.entrypointUrl = entrypointUrl; this.entrypointUrl = entrypointUrl;
@ -54,17 +55,12 @@ public class DomLessSourceExtractor extends JSSourceExtractor {
this.entrypointRegion = new SourceRegion(); this.entrypointRegion = new SourceRegion();
} }
protected Function<Integer,IncludedPosition> makePos(int lineNumber, ITag governingTag) { protected Position makePos(int lineNumber, ITag governingTag) {
return makePos(entrypointUrl, lineNumber, governingTag); return makePos(entrypointUrl, lineNumber, governingTag);
} }
protected Function<Integer,IncludedPosition> makePos(final URL url, final int lineNumber, ITag governingTag) { protected Position makePos(final URL url, final int lineNumber, ITag governingTag) {
final LineNumberPosition includePos = new LineNumberPosition(entrypointUrl, entrypointUrl, governingTag.getStartingLineNum()); return governingTag.getElementPosition();
return new Function<Integer,IncludedPosition>() {
public IncludedPosition apply(Integer object) {
return new IncludedLineNumberPosition(url, url, lineNumber + object.intValue(), includePos);
}
};
} }
public void handleEndTag(ITag tag) { public void handleEndTag(ITag tag) {
@ -74,14 +70,22 @@ public class DomLessSourceExtractor extends JSSourceExtractor {
} }
} }
public void handleText(Position p, String text) {
public void handleText(final int lineNumber, String text) {
if (currentScriptTag != null) { if (currentScriptTag != null) {
if (text.startsWith("<![CDATA[")) { if (text.startsWith("<![CDATA[")) {
assert text.endsWith("]]>"); assert text.endsWith("]]>");
text = text.substring(9, text.length()-11); text = text.substring(9, text.length()-11);
} }
scriptRegion.println(text, makePos(lineNumber, currentScriptTag));
URL url = entrypointUrl;
try {
url = new URL(entrypointUrl, "#" + scriptNodeCounter);
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
scriptRegion.println(text, currentScriptTag.getContentPosition(), url);
} }
} }
@ -90,6 +94,7 @@ public class DomLessSourceExtractor extends JSSourceExtractor {
handleScript(tag); handleScript(tag);
assert currentScriptTag == null; assert currentScriptTag == null;
currentScriptTag = tag; currentScriptTag = tag;
scriptNodeCounter++;
} }
handleDOM(tag); handleDOM(tag);
} }
@ -103,44 +108,47 @@ public class DomLessSourceExtractor extends JSSourceExtractor {
protected void handleDOM(ITag tag) { protected void handleDOM(ITag tag) {
// Get the name of the modeling function either from the id attribute or a // Get the name of the modeling function either from the id attribute or a
// running counter // running counter
String idAttribute = tag.getAttributeByName("id"); Pair<String,Position> idAttribute = tag.getAttributeByName("id");
String funcName; String funcName;
if (idAttribute != null && LEGAL_JS_IDENTIFIER_REGEXP.matcher(idAttribute).matches()) { if (idAttribute != null && LEGAL_JS_IDENTIFIER_REGEXP.matcher(idAttribute.fst).matches()) {
funcName = idAttribute; funcName = idAttribute.fst;
} else { } else {
funcName = "node" + (counter++); funcName = "node" + (nodeCounter++);
} }
handleDOM(tag, funcName); handleDOM(tag, funcName);
} }
protected void handleDOM(ITag tag, String funcName) { protected void handleDOM(ITag tag, String funcName) {
Map<String, String> attributeSet = tag.getAllAttributes(); Map<String, Pair<String,Position>> attributeSet = tag.getAllAttributes();
for (Entry<String, String> a : attributeSet.entrySet()) { for (Entry<String, Pair<String, Position>> a : attributeSet.entrySet()) {
handleAttribute(a, funcName, tag); handleAttribute(a, funcName, tag);
} }
} }
private void handleAttribute(Entry<String, String> a, String funcName, ITag tag) { private void handleAttribute(Entry<String, Pair<String,Position>> a, String funcName, ITag tag) {
int lineNum = tag.getStartingLineNum(); URL url = entrypointUrl;
try {
url = new URL(entrypointUrl, "#" + tag.getElementPosition().getFirstOffset());
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Position pos = a.getValue().snd;
String attName = a.getKey(); String attName = a.getKey();
String attValue = a.getValue(); String attValue = a.getValue().fst;
if (attName.toLowerCase().startsWith("on") || (attValue != null && attValue.toLowerCase().startsWith("javascript:"))) { if (attName.toLowerCase().startsWith("on") || (attValue != null && attValue.toLowerCase().startsWith("javascript:"))) {
String fName = tag.getName().toLowerCase() + "_" + attName + "_" + funcName; String fName = tag.getName().toLowerCase() + "_" + attName + "_" + funcName;
String signatureLine = "function " + fName + "(event) {"; String signatureLine = "function " + fName + "(event) {";
domRegion.println(signatureLine, makePos(lineNum, tag));// Defines the function // Defines the function
int offset = 0; domRegion.println(signatureLine + "\n" + extructJS(attValue) + "\n}", pos, url);
for (String eventContentLine : extructJS(attValue)){ // Run it
domRegion.println("\t" + eventContentLine, makePos(lineNum + (offset++), tag)); entrypointRegion.println("\t" + fName + "(null);", pos, url);
}
domRegion.println("}", makePos(lineNum, tag));// Defines the function
entrypointRegion.println("\t" + fName + "(null);", makePos(lineNum, tag));// Run it
} }
} }
private String[] extructJS(String attValue) { private String extructJS(String attValue) {
if (attValue == null){ if (attValue == null){
return new String[] {}; return "";
} }
String content; String content;
if (attValue.toLowerCase().equals("javascript:")) { if (attValue.toLowerCase().equals("javascript:")) {
@ -149,17 +157,17 @@ public class DomLessSourceExtractor extends JSSourceExtractor {
content = attValue; content = attValue;
} }
return content.split("\\n"); return content;
} }
protected void handleScript(ITag tag) { protected void handleScript(ITag tag) {
String value = tag.getAttributeByName("src"); Pair<String,Position> value = tag.getAttributeByName("src");
try { try {
if (value != null) { if (value != null) {
// script is out-of-line // script is out-of-line
getScriptFromUrl(value, tag); getScriptFromUrl(value.fst, tag);
} }
} catch (IOException e) { } catch (IOException e) {
@ -176,13 +184,15 @@ public class DomLessSourceExtractor extends JSSourceExtractor {
InputStream scriptInputStream = scriptSrc.openConnection().getInputStream(); InputStream scriptInputStream = scriptSrc.openConnection().getInputStream();
try{ try{
int lineNum = 1;
String line; String line;
BufferedReader scriptReader = new BufferedReader(new UnicodeReader(scriptInputStream, "UTF8")); BufferedReader scriptReader = new BufferedReader(new UnicodeReader(scriptInputStream, "UTF8"));
StringBuffer x = new StringBuffer();
while ((line = scriptReader.readLine()) != null) { while ((line = scriptReader.readLine()) != null) {
scriptRegion.println(line, makePos(scriptSrc, lineNum++, scriptTag)); x.append(line).append("\n");
} }
scriptRegion.println(x.toString(), scriptTag.getElementPosition(), scriptSrc);
} finally { } finally {
scriptInputStream.close(); scriptInputStream.close();
} }
@ -219,7 +229,7 @@ public class DomLessSourceExtractor extends JSSourceExtractor {
InputStream inputStreamReader = WebUtil.getStream(entrypointUrl); InputStream inputStreamReader = WebUtil.getStream(entrypointUrl);
IGeneratorCallback htmlCallback = createHtmlCallback(entrypointUrl, urlResolver); IGeneratorCallback htmlCallback = createHtmlCallback(entrypointUrl, urlResolver);
htmlParser.parse(inputStreamReader, htmlCallback, entrypointUrl.getFile()); htmlParser.parse(entrypointUrl, inputStreamReader, htmlCallback, entrypointUrl.getFile());
SourceRegion finalRegion = new SourceRegion(); SourceRegion finalRegion = new SourceRegion();
htmlCallback.writeToFinalRegion(finalRegion); htmlCallback.writeToFinalRegion(finalRegion);

View File

@ -1,43 +1,17 @@
/******************************************************************************
* Copyright (c) 2002 - 2011 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
package com.ibm.wala.cast.js.html; package com.ibm.wala.cast.js.html;
import java.io.PrintStream; import java.io.PrintStream;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import com.ibm.wala.cast.tree.CAstSourcePositionMap.Position; import com.ibm.wala.cast.tree.CAstSourcePositionMap.Position;
import com.ibm.wala.util.collections.HashMapFactory;
/** public interface FileMapping {
* Maps line numbers to lines of other files (fileName + line).
*/
public class FileMapping{
protected Map<Integer, IncludedPosition> lineNumberToFileAndLine = HashMapFactory.make();
/** /**
* @param line * @param line
* @return Null if no mapping for the given line. * @return Null if no mapping for the given line.
*/ */
public IncludedPosition getAssociatedFileAndLine(int line){ public abstract IncludedPosition getIncludedPosition(Position line);
return lineNumberToFileAndLine.get(line);
}
public void dump(PrintStream ps){ public abstract void dump(PrintStream ps);
Set<Integer> lines = new TreeSet<Integer>(lineNumberToFileAndLine.keySet());
for (Integer line : lines){
Position fnAndln = lineNumberToFileAndLine.get(line);
ps.println(line + ": " + fnAndln);
}
}
} }

View File

@ -10,6 +10,8 @@
*****************************************************************************/ *****************************************************************************/
package com.ibm.wala.cast.js.html; package com.ibm.wala.cast.js.html;
import com.ibm.wala.cast.tree.CAstSourcePositionMap.Position;
/** /**
@ -22,7 +24,7 @@ public interface IHtmlCallback {
void handleStartTag(ITag tag); void handleStartTag(ITag tag);
void handleText(int lineNumber, String text); void handleText(Position pos, String text);
void handleEndTag(ITag tag); void handleEndTag(ITag tag);

View File

@ -11,6 +11,7 @@
package com.ibm.wala.cast.js.html; package com.ibm.wala.cast.js.html;
import java.io.InputStream; import java.io.InputStream;
import java.net.URL;
/** /**
* @author danielk * @author danielk
@ -25,6 +26,6 @@ public interface IHtmlParser {
* @param callback * @param callback
* @param fileName * @param fileName
*/ */
public void parse(InputStream reader, IHtmlCallback callback, String fileName); public void parse(URL url, InputStream reader, IHtmlCallback callback, String fileName);
} }

View File

@ -12,6 +12,9 @@ package com.ibm.wala.cast.js.html;
*****************************************************************************/ *****************************************************************************/
import java.util.Map; import java.util.Map;
import com.ibm.wala.cast.tree.CAstSourcePositionMap.Position;
import com.ibm.wala.util.collections.Pair;
/** /**
* @author danielk * @author danielk
* Data structure representing an HTML tag, with its attributes and content. Used by the HTML parser when calling the callback. * Data structure representing an HTML tag, with its attributes and content. Used by the HTML parser when calling the callback.
@ -28,13 +31,15 @@ public interface ITag {
* @param name * @param name
* @return null if there is no such attribute * @return null if there is no such attribute
*/ */
public String getAttributeByName(String name); public Pair<String, Position> getAttributeByName(String name);
public Map<String, String> getAllAttributes(); public Map<String, Pair<String, Position>> getAllAttributes();
/** /**
* Returns the starting line number of the tag. * Returns the starting line number of the tag.
* @return null if no known * @return null if no known
*/ */
public int getStartingLineNum(); public Position getElementPosition();
public Position getContentPosition();
} }

View File

@ -1,33 +0,0 @@
/******************************************************************************
* Copyright (c) 2002 - 2011 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
package com.ibm.wala.cast.js.html;
import java.net.URL;
import com.ibm.wala.cast.tree.CAstSourcePositionMap.Position;
import com.ibm.wala.cast.tree.impl.LineNumberPosition;
public class IncludedLineNumberPosition extends LineNumberPosition implements IncludedPosition {
private final Position includePosition;
public IncludedLineNumberPosition(URL url, URL localFile, int lineNumber, Position includePosition) {
super(url, localFile, lineNumber);
this.includePosition = includePosition;
}
public Position getIncludePosition() {
return includePosition;
}
public String toString() {
return super.toString() + "(from " + includePosition +")";
}
}

View File

@ -23,9 +23,9 @@ import java.util.Set;
*/ */
public abstract class JSSourceExtractor { public abstract class JSSourceExtractor {
public static boolean DELETE_UPON_EXIT = true; public static boolean DELETE_UPON_EXIT = false;
public static boolean USE_TEMP_NAME = true; public static boolean USE_TEMP_NAME = false;
public abstract Set<MappedSourceModule> extractSources(URL entrypointUrl, IHtmlParser htmlParser, IUrlResolver urlResolver) throws IOException; public abstract Set<MappedSourceModule> extractSources(URL entrypointUrl, IHtmlParser htmlParser, IUrlResolver urlResolver) throws IOException;

View File

@ -1,19 +0,0 @@
/******************************************************************************
* Copyright (c) 2002 - 2011 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
package com.ibm.wala.cast.js.html;
public class MutableFileMapping extends FileMapping {
void map(int line, IncludedPosition originalPos){
lineNumberToFileAndLine.put(line, originalPos);
}
}

View File

@ -0,0 +1,81 @@
package com.ibm.wala.cast.js.html;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.net.URL;
import com.ibm.wala.cast.js.html.RangeFileMapping.Range;
import com.ibm.wala.cast.tree.CAstSourcePositionMap.Position;
import com.ibm.wala.cast.tree.impl.AbstractSourcePosition;
public class NestedRangeMapping implements FileMapping {
private final Range range;
private final FileMapping innerMapping;
public NestedRangeMapping(int rangeStart, int rangeEnd, int rangeStartingLine, int rangeEndingLine, FileMapping innerMapping) {
assert innerMapping != null;
this.range = new Range(rangeStart, rangeEnd, rangeStartingLine, rangeEndingLine);
this.innerMapping = innerMapping;
}
@Override
public IncludedPosition getIncludedPosition(final Position pos) {
if (range.includes(pos)) {
return innerMapping.getIncludedPosition(
new AbstractSourcePosition() {
@Override
public int getFirstLine() {
return pos.getFirstLine()-range.getStartingLine()+1;
}
@Override
public int getLastLine() {
return pos.getLastLine()==-1? -1: (pos.getLastLine()-range.getStartingLine()+1);
}
@Override
public int getFirstCol() {
return pos.getFirstCol();
}
@Override
public int getLastCol() {
return pos.getLastCol();
}
@Override
public int getFirstOffset() {
return pos.getFirstOffset()==-1? -1: (pos.getFirstOffset()-range.getStart());
}
@Override
public int getLastOffset() {
return pos.getLastOffset()==-1? -1: (pos.getLastOffset()-range.getStart());
}
@Override
public URL getURL() {
return pos.getURL();
}
@Override
public InputStream getInputStream() throws IOException {
return pos.getInputStream();
}
});
} else {
return null;
}
}
@Override
public void dump(PrintStream ps) {
// TODO Auto-generated method stub
}
public String toString() {
return range + "(" + innerMapping + ")";
}
}

View File

@ -0,0 +1,129 @@
package com.ibm.wala.cast.js.html;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.net.URL;
import com.ibm.wala.cast.tree.CAstSourcePositionMap.Position;
import com.ibm.wala.cast.tree.impl.AbstractSourcePosition;
public class RangeFileMapping implements FileMapping {
public static class Range {
private final int rangeStart;
private final int rangeEnd;
private final int rangeStartingLine;
private final int rangeEndingLine;
public boolean includes(Position offset) {
return
offset.getFirstOffset() != -1?
rangeStart <= offset.getFirstOffset() && offset.getLastOffset() <= rangeEnd:
rangeStartingLine <= offset.getFirstLine() &&
(offset.getLastLine() == -1? offset.getFirstLine(): offset.getLastLine()) <= rangeEndingLine;
}
public Range(int rangeStart, int rangeEnd, int rangeStartingLine, int rangeEndingLine) {
super();
this.rangeStart = rangeStart;
this.rangeEnd = rangeEnd;
this.rangeStartingLine = rangeStartingLine;
this.rangeEndingLine = rangeEndingLine;
}
public int getStart() {
return rangeStart;
}
public int getEnd() {
return rangeEnd;
}
public int getStartingLine() {
return rangeStartingLine;
}
public int getEndingLine() {
return rangeEndingLine;
}
public String toString() {
return "{"+rangeStart+"->"+rangeEnd+"}";
}
}
private final Range range;
private final URL includedURL;
private final Position includePosition;
public RangeFileMapping(int rangeStart, int rangeEnd, int rangeStartingLine, int rangeEndingLine, Position parentPosition, URL url) {
assert parentPosition != null;
this.range = new Range(rangeStart, rangeEnd, rangeStartingLine, rangeEndingLine);
this.includePosition = parentPosition;
includedURL = url;
}
public String toString() {
return range + ":" + includePosition;
}
@Override
public IncludedPosition getIncludedPosition(final Position offset) {
if (range.includes(offset)) {
class Pos extends AbstractSourcePosition implements IncludedPosition {
@Override
public int getFirstLine() {
// line numbers are decreed to start at 1, rather than 0
return offset.getFirstLine() - range.getStartingLine() + 1;
}
@Override
public int getLastLine() {
return offset.getLastLine() == -1? -1: offset.getLastLine()-range.getStartingLine()+1;
}
@Override
public int getFirstCol() {
return offset.getFirstCol();
}
@Override
public int getLastCol() {
return offset.getLastCol();
}
@Override
public int getFirstOffset() {
return offset.getFirstOffset() == -1? -1: offset.getFirstOffset()-range.getStart();
}
@Override
public int getLastOffset() {
return offset.getLastOffset() == -1? -1: offset.getLastOffset()-range.getStart();
}
@Override
public URL getURL() {
return includedURL;
}
@Override
public InputStream getInputStream() throws IOException {
return includedURL.openConnection().getInputStream();
}
@Override
public Position getIncludePosition() {
return includePosition;
}
public String toString() {
return "[include:"+includePosition+"]"+super.toString();
}
};
return new Pos();
} else {
return null;
}
}
@Override
public void dump(PrintStream ps) {
// TODO Auto-generated method stub
}
}

View File

@ -10,46 +10,45 @@
*****************************************************************************/ *****************************************************************************/
package com.ibm.wala.cast.js.html; package com.ibm.wala.cast.js.html;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintStream; import java.io.PrintStream;
import java.io.StringReader; import java.net.URL;
import java.util.StringTokenizer;
import com.ibm.wala.cast.tree.CAstSourcePositionMap.Position; import com.ibm.wala.cast.tree.CAstSourcePositionMap.Position;
import com.ibm.wala.util.functions.Function;
public class SourceRegion { public class SourceRegion {
private final StringBuilder source = new StringBuilder(); private final StringBuilder source = new StringBuilder();
private final MutableFileMapping fileMapping = new MutableFileMapping(); private FileMapping fileMapping;
private int currentLine = 1; private int currentLine = 1;
public SourceRegion() { public SourceRegion() {
} }
public void print(String text, Function<Integer,IncludedPosition> originalPos){ public void print(String text, Position originalPos, URL url){
int startOffset = source.length();
source.append(text); source.append(text);
int ln = 0; int endOffset = source.length();
int numberOfLineDrops = getNumberOfLineDrops(text); int numberOfLineDrops = getNumberOfLineDrops(text);
if (originalPos != null){
for (int i = 0; i < numberOfLineDrops; i++){ if (originalPos != null) {
fileMapping.map(currentLine++, originalPos.apply(ln++)); RangeFileMapping map = new RangeFileMapping(startOffset, endOffset, currentLine, currentLine+numberOfLineDrops, originalPos, url);
} if (fileMapping == null) {
if (! text.endsWith("\n")){ // avoid mapping one line too much fileMapping = map;
fileMapping.map(currentLine, originalPos.apply(ln)); // required for handling text with no CRs.
}
} else { } else {
currentLine += numberOfLineDrops; fileMapping = new CompositeFileMapping(map, fileMapping);
} }
} }
public void println(String text, Function<Integer,IncludedPosition> originalPos){ currentLine += numberOfLineDrops;
print(text + "\n", originalPos); }
public void println(String text, Position originalPos, URL url){
print(text + "\n", originalPos, url);
} }
public void print(String text){ public void print(String text){
print(text, null); print(text, null, null);
} }
public void println(String text){ public void println(String text){
@ -62,42 +61,27 @@ public class SourceRegion {
} }
public void write(SourceRegion otherRegion){ public void write(SourceRegion otherRegion){
BufferedReader br = new BufferedReader(new StringReader(otherRegion.source.toString())); int rangeStart = source.length();
int lineNum = 0; String text = otherRegion.source.toString();
String line; source.append(text);
try { int rangeEnd = source.length();
while ((line = br.readLine()) != null){
lineNum++;
IncludedPosition fileAndLine = otherRegion.fileMapping.getAssociatedFileAndLine(lineNum); int numberOfLineDrops = getNumberOfLineDrops(text);
if (fileAndLine!= null){
fileMapping.map(currentLine, fileAndLine); if (otherRegion.fileMapping != null) {
FileMapping map = new NestedRangeMapping(rangeStart, rangeEnd, currentLine, currentLine+numberOfLineDrops, otherRegion.fileMapping);
if (fileMapping == null) {
fileMapping = map;
} else {
fileMapping = new CompositeFileMapping(map, fileMapping);
}
} }
this.println(line); currentLine += numberOfLineDrops;
}
} catch (IOException e) {
e.printStackTrace();
assert false;
}
} }
public void dump(PrintStream ps){ public void dump(PrintStream ps){
StringTokenizer st = new StringTokenizer(source.toString(),"\n"); ps.println(source.toString());
int lineNum = 0;
while (st.hasMoreElements()){
String line = (String) st.nextElement();
lineNum++;
Position fileAndLine = fileMapping.getAssociatedFileAndLine(lineNum);
if (fileAndLine!= null){
ps.print(fileAndLine + "\t:");
} else {
ps.print("N/A \t\t:");
}
ps.println(line);
}
} }
private static int getNumberOfLineDrops(String text) { private static int getNumberOfLineDrops(String text) {

View File

@ -12,6 +12,7 @@ package com.ibm.wala.cast.js.html.jericho;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.net.URL;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
@ -20,7 +21,6 @@ import net.htmlparser.jericho.Element;
import net.htmlparser.jericho.LoggerProvider; import net.htmlparser.jericho.LoggerProvider;
import net.htmlparser.jericho.Source; import net.htmlparser.jericho.Source;
import com.ibm.wala.cast.js.html.IHtmlCallback; import com.ibm.wala.cast.js.html.IHtmlCallback;
import com.ibm.wala.cast.js.html.IHtmlParser; import com.ibm.wala.cast.js.html.IHtmlParser;
@ -34,7 +34,7 @@ public class JerichoHtmlParser implements IHtmlParser{
Config.LoggerProvider = LoggerProvider.STDERR; Config.LoggerProvider = LoggerProvider.STDERR;
} }
public void parse(InputStream reader, IHtmlCallback callback, String fileName) { public void parse(URL url, InputStream reader, IHtmlCallback callback, String fileName) {
Parser parser = new Parser(callback, fileName); Parser parser = new Parser(callback, fileName);
Source src; Source src;
try { try {
@ -64,7 +64,7 @@ public class JerichoHtmlParser implements IHtmlParser{
private void parse(Element root) { private void parse(Element root) {
JerichoTag tag = new JerichoTag(root, fileName); JerichoTag tag = new JerichoTag(root, fileName);
handler.handleStartTag(tag); handler.handleStartTag(tag);
handler.handleText(tag.getStartingLineNum(), tag.getBodyText().snd); handler.handleText(tag.getElementPosition(), tag.getBodyText().snd);
List<Element> childElements = root.getChildElements(); List<Element> childElements = root.getChildElements();
for (Iterator<Element> nodeIterator = childElements.iterator(); nodeIterator.hasNext();) { for (Iterator<Element> nodeIterator = childElements.iterator(); nodeIterator.hasNext();) {
Element child = nodeIterator.next(); Element child = nodeIterator.next();

View File

@ -10,14 +10,20 @@
*****************************************************************************/ *****************************************************************************/
package com.ibm.wala.cast.js.html.jericho; package com.ibm.wala.cast.js.html.jericho;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Map; import java.util.Map;
import net.htmlparser.jericho.Attributes; import net.htmlparser.jericho.Attribute;
import net.htmlparser.jericho.Element; import net.htmlparser.jericho.Element;
import net.htmlparser.jericho.Segment; import net.htmlparser.jericho.Segment;
import com.ibm.wala.cast.js.html.ITag; import com.ibm.wala.cast.js.html.ITag;
import com.ibm.wala.cast.tree.CAstSourcePositionMap.Position;
import com.ibm.wala.cast.tree.impl.AbstractSourcePosition;
import com.ibm.wala.util.collections.HashMapFactory; import com.ibm.wala.util.collections.HashMapFactory;
import com.ibm.wala.util.collections.Pair; import com.ibm.wala.util.collections.Pair;
@ -29,24 +35,86 @@ public class JerichoTag implements ITag {
private final Element innerElement; private final Element innerElement;
private final String sourceFile; private final String sourceFile;
private Map<String, String> attributesMap; private Map<String, Pair<String, Position>> allAttributes = null;
public JerichoTag(Element root, String sourceFile) { public JerichoTag(Element root, String sourceFile) {
this.innerElement = root; this.innerElement = root;
Attributes attributes = innerElement.getStartTag().getAttributes();
attributesMap = HashMapFactory.make();
if (attributes != null) {
attributesMap = attributes.populateMap(attributesMap, true);
}
this.sourceFile = sourceFile; this.sourceFile = sourceFile;
} }
public Map<String, String> getAllAttributes() { private Position getPosition(final Segment e) {
return attributesMap; return new AbstractSourcePosition() {
@Override
public int getFirstLine() {
return e.getSource().getRowColumnVector(e.getBegin()).getRow();
} }
public String getAttributeByName(String name) { @Override
return attributesMap.get(name.toLowerCase()); public int getLastLine() {
return e.getSource().getRowColumnVector(e.getEnd()).getRow();
}
@Override
public int getFirstCol() {
return e.getSource().getRowColumnVector(e.getBegin()).getColumn();
}
@Override
public int getLastCol() {
return e.getSource().getRowColumnVector(e.getEnd()).getColumn();
}
@Override
public int getFirstOffset() {
return e.getBegin();
}
@Override
public int getLastOffset() {
return e.getEnd();
}
@Override
public URL getURL() {
try {
return new URL("file://" + sourceFile);
} catch (MalformedURLException e) {
return null;
}
}
@Override
public InputStream getInputStream() throws IOException {
return new FileInputStream(sourceFile);
}
};
}
private Map<String, Pair<String, Position>> makeAllAttributes() {
Map<String, Pair<String, Position>> result = HashMapFactory.make();
if (innerElement.getStartTag().getAttributes() != null) {
for (Attribute a : innerElement.getStartTag().getAttributes()) {
result.put(
a.getName().toLowerCase(),
Pair.make(a.getValue(), getPosition(a.getValueSegment())));
}
}
return result;
}
public Map<String, Pair<String, Position>> getAllAttributes() {
if (allAttributes == null) {
allAttributes = makeAllAttributes();
}
return allAttributes;
}
public Pair<String, Position> getAttributeByName(String name) {
if (allAttributes == null) {
allAttributes = makeAllAttributes();
}
return allAttributes.get(name.toLowerCase());
} }
public Pair<Integer, String> getBodyText() { public Pair<Integer, String> getBodyText() {
@ -69,7 +137,11 @@ public class JerichoTag implements ITag {
return innerElement.toString(); return innerElement.toString();
} }
public int getStartingLineNum() { public Position getElementPosition() {
return innerElement.getSource().getRow(innerElement.getStartTag().getBegin()); return getPosition(innerElement);
}
public Position getContentPosition() {
return getPosition(innerElement.getContent());
} }
} }

View File

@ -0,0 +1,328 @@
package com.ibm.wala.cast.js.ipa.callgraph;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import com.ibm.wala.cast.ipa.callgraph.AstContextInsensitiveSSAContextInterpreter;
import com.ibm.wala.cast.ir.ssa.AstIRFactory;
import com.ibm.wala.cast.js.loader.JavaScriptLoader;
import com.ibm.wala.cast.js.translator.JSAstTranslator;
import com.ibm.wala.cast.js.translator.JSConstantFoldingRewriter;
import com.ibm.wala.cast.loader.AstMethod.DebuggingInformation;
import com.ibm.wala.cast.loader.AstMethod.Retranslatable;
import com.ibm.wala.cast.tree.CAst;
import com.ibm.wala.cast.tree.CAstControlFlowMap;
import com.ibm.wala.cast.tree.CAstEntity;
import com.ibm.wala.cast.tree.CAstNode;
import com.ibm.wala.cast.tree.impl.CAstBasicRewriter;
import com.ibm.wala.cast.tree.impl.CAstImpl;
import com.ibm.wala.cast.util.CAstPattern;
import com.ibm.wala.cast.util.CAstPattern.Segments;
import com.ibm.wala.cfg.AbstractCFG;
import com.ibm.wala.cfg.ControlFlowGraph;
import com.ibm.wala.classLoader.CallSiteReference;
import com.ibm.wala.classLoader.IMethod;
import com.ibm.wala.ipa.callgraph.AnalysisCache;
import com.ibm.wala.ipa.callgraph.AnalysisOptions;
import com.ibm.wala.ipa.callgraph.CGNode;
import com.ibm.wala.ipa.callgraph.Context;
import com.ibm.wala.ipa.callgraph.ContextItem;
import com.ibm.wala.ipa.callgraph.ContextItem.Value;
import com.ibm.wala.ipa.callgraph.ContextKey;
import com.ibm.wala.ipa.callgraph.ContextSelector;
import com.ibm.wala.ipa.callgraph.propagation.InstanceKey;
import com.ibm.wala.ssa.DefUse;
import com.ibm.wala.ssa.IR;
import com.ibm.wala.ssa.SSAAbstractInvokeInstruction;
import com.ibm.wala.ssa.SSAOptions;
import com.ibm.wala.ssa.SymbolTable;
import com.ibm.wala.types.TypeReference;
import com.ibm.wala.util.collections.HashMapFactory;
import com.ibm.wala.util.collections.Pair;
import com.ibm.wala.util.intset.IntSet;
public class ArgumentSpecialization {
public static class ArgumentSpecializationContextIntepreter extends AstContextInsensitiveSSAContextInterpreter {
public ArgumentSpecializationContextIntepreter(AnalysisOptions options, AnalysisCache cache) {
super(options, cache);
}
@Override
public IR getIR(CGNode node) {
if (node.getMethod() instanceof Retranslatable) {
return getAnalysisCache().getSSACache().findOrCreateIR(node.getMethod(), node.getContext(), options.getSSAOptions());
} else {
return super.getIR(node);
}
}
public DefUse getDU(CGNode node) {
if (node.getMethod() instanceof Retranslatable) {
return getAnalysisCache().getSSACache().findOrCreateDU(node.getMethod(), node.getContext(), options.getSSAOptions());
} else {
return super.getDU(node);
}
}
}
public static class ArgumentCountContext implements Context {
private final Context base;
private final int argumentCount;
public static ContextKey ARGUMENT_COUNT = new ContextKey() {
public String toString() {
return "argument count key";
}
};
public int hashCode() {
return base.hashCode() + (argumentCount * 4073);
}
public boolean equals(Object o) {
return
o.getClass() == this.getClass() &&
base.equals(((ArgumentCountContext)o).base) &&
argumentCount == ((ArgumentCountContext)o).argumentCount;
}
public ArgumentCountContext(int argumentCount, Context base) {
this.argumentCount = argumentCount;
this.base = base;
}
public ContextItem get(ContextKey name) {
return (name == ARGUMENT_COUNT)? ContextItem.Value.make(argumentCount): base.get(name);
}
public String toString() {
return base.toString() + "(nargs:" + argumentCount + ")";
}
}
public static class ArgumentCountContextSelector implements ContextSelector, ContextKey {
private final ContextSelector base;
public ArgumentCountContextSelector(ContextSelector base) {
this.base = base;
}
public Context getCalleeTarget(CGNode caller, CallSiteReference site, IMethod callee, InstanceKey[] actualParameters) {
Context baseContext = base.getCalleeTarget(caller, site, callee, actualParameters);
if (caller.getMethod() instanceof Retranslatable) {
int v = -1;
for (SSAAbstractInvokeInstruction x : caller.getIR().getCalls(site)) {
if (v == -1) {
v = x.getNumberOfParameters();
} else {
if (v != x.getNumberOfParameters()) {
return baseContext;
}
}
}
return new ArgumentCountContext(v, baseContext);
} else {
return baseContext;
}
}
public IntSet getRelevantParameters(CGNode caller, CallSiteReference site) {
return base.getRelevantParameters(caller, site);
}
}
public static class ArgumentCountIRFactory extends AstIRFactory.AstDefaultIRFactory {
private static final CAstPattern directAccessPattern = CAstPattern.parse("|(ARRAY_REF(VAR(\"arguments\"),<value>*)||OBJECT_REF(VAR(\"arguments\"),<value>*))|");
private static final CAstPattern destructuredAccessPattern = CAstPattern.parse("BLOCK_EXPR(ASSIGN(VAR(/[$][$]destructure[$]rcvr[0-9]+/),VAR(\"arguments\")),ASSIGN(VAR(<name>/[$][$]destructure[$]elt[0-9]+/),<value>*))");
private static final CAstPattern destructuredCallPattern = CAstPattern.parse("CALL(VAR(<name>/[$][$]destructure[$]elt[0-9]+/),\"dispatch\",VAR(<thisptr>/[$][$]destructure[$]rcvr[0-9]+/),<args>**)");
private final SSAOptions defaultOptions;
public ArgumentCountIRFactory(SSAOptions defaultOptions) {
this.defaultOptions = defaultOptions;
}
@Override
public boolean contextIsIrrelevant(IMethod method) {
return method instanceof Retranslatable? false: super.contextIsIrrelevant(method);
}
@Override
public IR makeIR(final IMethod method, Context context, SSAOptions options) {
if (method instanceof Retranslatable) {
@SuppressWarnings("unchecked")
final Value<Integer> v = (Value<Integer>) context.get(ArgumentCountContext.ARGUMENT_COUNT);
final Retranslatable m = (Retranslatable)method;
if (v != null) {
final JavaScriptLoader myloader = (JavaScriptLoader) method.getDeclaringClass().getClassLoader();
class FixedArgumentsRewriter extends CAstBasicRewriter {
private final CAstEntity e;
Map<String, CAstNode> argRefs = HashMapFactory.make();
public FixedArgumentsRewriter(CAst Ast) {
super(Ast, false);
this.e = m.getEntity();
for(Segments s : CAstPattern.findAll(destructuredAccessPattern, m.getEntity())) {
argRefs.put(s.getSingle("name").getValue().toString(), s.getSingle("value"));
}
}
private CAstNode handleArgumentRef(CAstNode n) {
Object x = n.getValue();
if (x != null) {
if (x instanceof Number && ((Number)x).intValue() < v.getValue()-2) {
int arg = ((Number)x).intValue() + 2;
if (arg < e.getArgumentCount()) {
return Ast.makeNode(CAstNode.VAR, Ast.makeConstant(e.getArgumentNames()[arg]));
} else {
return Ast.makeNode(CAstNode.VAR, Ast.makeConstant("$arg" + arg));
}
} else if (x instanceof String && "length".equals(x)) {
return Ast.makeConstant(v.getValue());
}
}
return null;
}
@Override
protected CAstNode copyNodes(CAstNode root,
CAstControlFlowMap cfg,
NonCopyingContext context,
Map<Pair<CAstNode, NoKey>, CAstNode> nodeMap)
{
CAstNode result = null;
Segments s;
if ((s = CAstPattern.match(directAccessPattern, root)) != null) {
result = handleArgumentRef(s.getSingle("value"));
} else if ((s = CAstPattern.match(destructuredCallPattern, root)) != null) {
if (argRefs.containsKey(s.getSingle("name").getValue().toString())) {
List<CAstNode> x = new ArrayList<CAstNode>();
CAstNode ref = handleArgumentRef(argRefs.get(s.getSingle("name").getValue().toString()));
if (ref != null) {
x.add(ref);
x.add(Ast.makeConstant("do"));
x.add(Ast.makeNode(CAstNode.VAR, Ast.makeConstant("arguments")));
for (CAstNode c : s.getMultiple("args")) {
x.add(copyNodes(c, cfg, context, nodeMap));
}
result = Ast.makeNode(CAstNode.CALL, x.toArray(new CAstNode[ x.size() ]));
}
}
} else if (root.getKind() == CAstNode.CONSTANT) {
result = Ast.makeConstant(root.getValue());
} else if (root.getKind() == CAstNode.OPERATOR) {
result = root;
}
if (result == null) {
CAstNode children[] = new CAstNode[root.getChildCount()];
for (int i = 0; i < children.length; i++) {
children[i] = copyNodes(root.getChild(i), cfg, context, nodeMap);
}
for(Object label: cfg.getTargetLabels(root)) {
if (label instanceof CAstNode) {
copyNodes((CAstNode)label, cfg, context, nodeMap);
}
}
CAstNode copy = Ast.makeNode(root.getKind(), children);
result = copy;
}
nodeMap.put(Pair.make(root, context.key()), result);
return result;
}
}
final FixedArgumentsRewriter args = new FixedArgumentsRewriter(new CAstImpl());
final JSConstantFoldingRewriter fold = new JSConstantFoldingRewriter(new CAstImpl());
class ArgumentativeTranslator extends JSAstTranslator {
public ArgumentativeTranslator(JavaScriptLoader loader) {
super(loader);
}
private CAstEntity codeBodyEntity;
private IMethod specializedCode;
@Override
protected int getArgumentCount(CAstEntity f) {
return Math.max(super.getArgumentCount(f), v.getValue());
}
@Override
protected String[] getArgumentNames(CAstEntity f) {
if (super.getArgumentCount(f) >= v.getValue()) {
return super.getArgumentNames(f);
} else {
String[] argNames = new String[ v.getValue() ];
System.arraycopy(super.getArgumentNames(f), 0, argNames, 0, super.getArgumentCount(f));
for(int i = super.getArgumentCount(f); i < argNames.length; i++) {
argNames[i] = "$arg" + i;
}
return argNames;
}
}
@Override
protected String composeEntityName(WalkContext parent, CAstEntity f) {
if (f == codeBodyEntity) {
return super.composeEntityName(parent, f) + "_" + v.getValue().intValue();
} else {
return super.composeEntityName(parent, f);
}
}
@Override
protected void defineFunction(CAstEntity N, WalkContext definingContext, AbstractCFG cfg, SymbolTable symtab,
boolean hasCatchBlock, TypeReference[][] caughtTypes, boolean hasMonitorOp, AstLexicalInformation LI,
DebuggingInformation debugInfo) {
if (N == codeBodyEntity) {
specializedCode = myloader.makeCodeBodyCode(cfg, symtab, hasCatchBlock, caughtTypes, hasMonitorOp, LI, debugInfo, method.getDeclaringClass());
} else {
super.defineFunction(N, definingContext, cfg, symtab, hasCatchBlock, caughtTypes, hasMonitorOp, LI, debugInfo);
}
}
@Override
public void translate(CAstEntity N, WalkContext context) {
if (N == m.getEntity()) {
codeBodyEntity = fold.rewrite(args.rewrite(N));
super.translate(codeBodyEntity, context);
} else {
super.translate(N, context);
}
}
}
ArgumentativeTranslator a = new ArgumentativeTranslator(myloader);
m.retranslate(a);
return super.makeIR(a.specializedCode, context, options);
}
}
return super.makeIR(method, context, options);
}
@Override
public ControlFlowGraph makeCFG(IMethod method, Context context) {
return makeIR(method, context, defaultOptions).getControlFlowGraph();
}
}
}

View File

@ -31,8 +31,8 @@ import com.ibm.wala.ipa.callgraph.impl.Everywhere;
import com.ibm.wala.ipa.callgraph.propagation.ConcreteTypeKey; import com.ibm.wala.ipa.callgraph.propagation.ConcreteTypeKey;
import com.ibm.wala.ipa.callgraph.propagation.ConstantKey; import com.ibm.wala.ipa.callgraph.propagation.ConstantKey;
import com.ibm.wala.ipa.callgraph.propagation.FilteredPointerKey; import com.ibm.wala.ipa.callgraph.propagation.FilteredPointerKey;
import com.ibm.wala.ipa.callgraph.propagation.FilteredPointerKey.SingleInstanceFilter;
import com.ibm.wala.ipa.callgraph.propagation.InstanceKey; import com.ibm.wala.ipa.callgraph.propagation.InstanceKey;
import com.ibm.wala.ipa.callgraph.propagation.cfa.OneLevelSiteContextSelector;
import com.ibm.wala.ipa.cha.IClassHierarchy; import com.ibm.wala.ipa.cha.IClassHierarchy;
import com.ibm.wala.ssa.DefUse; import com.ibm.wala.ssa.DefUse;
import com.ibm.wala.ssa.IR; import com.ibm.wala.ssa.IR;
@ -50,8 +50,8 @@ import com.ibm.wala.util.intset.IntSetUtil;
import com.ibm.wala.util.intset.MutableIntSet; import com.ibm.wala.util.intset.MutableIntSet;
public class ForInContextSelector implements ContextSelector { public class ForInContextSelector implements ContextSelector {
public final static ContextKey FORIN_KEY = new ContextKey() { }; public final static ContextKey FORIN_KEY = new ContextKey() { };
public final static ContextKey FORIN_PARM_INDEX = new ContextKey() { };
public static final ContextItem FORIN_MARKER = new ContextItem() { }; public static final ContextItem FORIN_MARKER = new ContextItem() { };
@ -63,7 +63,7 @@ public class ForInContextSelector implements ContextSelector {
public static boolean USE_CPA_IN_BODIES = false; public static boolean USE_CPA_IN_BODIES = false;
public static boolean USE_1LEVEL_IN_BODIES = false; public static boolean USE_1LEVEL_IN_BODIES = true;
public static boolean DEPENDENT_THRU_READS = true; public static boolean DEPENDENT_THRU_READS = true;
@ -108,6 +108,9 @@ public class ForInContextSelector implements ContextSelector {
@Override @Override
public boolean equals(Object other) { public boolean equals(Object other) {
if (this == other) {
return true;
}
return other != null && return other != null &&
getClass().equals(other.getClass()) && getClass().equals(other.getClass()) &&
base.equals(((SelectiveCPAContext)other).base) && base.equals(((SelectiveCPAContext)other).base) &&
@ -126,6 +129,8 @@ public class ForInContextSelector implements ContextSelector {
public ContextItem get(ContextKey key) { public ContextItem get(ContextKey key) {
if (FORIN_KEY.equals(key)) { if (FORIN_KEY.equals(key)) {
return FORIN_MARKER; return FORIN_MARKER;
} else if(FORIN_PARM_INDEX.equals(key)) {
return ContextItem.Value.make(index);
} else { } else {
return super.get(key); return super.get(key);
} }
@ -136,10 +141,51 @@ public class ForInContextSelector implements ContextSelector {
return "for in hack filter for " + get(ContextKey.PARAMETERS[index]) + " over " + this.base; return "for in hack filter for " + get(ContextKey.PARAMETERS[index]) + " over " + this.base;
} }
/**
* get the {@link InstanceKey} used to distinguish this context
*/
public InstanceKey getInstanceKey() {
return ((SingleInstanceFilter)get(ContextKey.PARAMETERS[index])).getInstance();
}
} }
/**
* A "dummy" for-in context used for callees of a method analyzed in a real
* {@link ForInContext}. The purpose of this class is to clone callees based
* on the same {@link InstanceKey} used for the caller context, but without
* returning a {@link SingleInstanceFilter} {@link ContextItem} that filters
* possible parameter values.
*/
class MarkerForInContext extends ForInContext {
MarkerForInContext(Context base, InstanceKey obj) {
super(base, obj);
}
/**
* Like {@link ForInContext#get(ContextKey)}, but don't return a
* {@link SingleInstanceFilter} for the distinguishing {@link InstanceKey}
*/
@Override
public ContextItem get(ContextKey key) {
final ContextItem contextItem = super.get(key);
return (contextItem instanceof SingleInstanceFilter) ? null : contextItem;
}
/**
* we need to override this method since
* {@link MarkerForInContext#get(ContextKey)} does not return the
* {@link SingleInstanceFilter} containing the {@link InstanceKey}. Instead,
* we invoke {@link ForInContext#get(ContextKey)} from the superclass.
*/
@Override
public InstanceKey getInstanceKey() {
return ((SingleInstanceFilter)super.get(ContextKey.PARAMETERS[index])).getInstance();
}
}
private final ContextSelector base; private final ContextSelector base;
private final ContextSelector oneLevel; // private final ContextSelector oneLevel;
private final int index; private final int index;
private void collectValues(DefUse du, SSAInstruction inst, MutableIntSet values) { private void collectValues(DefUse du, SSAInstruction inst, MutableIntSet values) {
@ -168,7 +214,7 @@ public class ForInContextSelector implements ContextSelector {
if (DEPENDENT_THRU_READS) { if (DEPENDENT_THRU_READS) {
collectValues(du, du.getDef(inst.getUse(i)), values); collectValues(du, du.getDef(inst.getUse(i)), values);
} }
if (values.contains(3)) { if (values.contains(index+1)) {
dependentParameters.add(i); dependentParameters.add(i);
} }
} }
@ -182,14 +228,15 @@ public class ForInContextSelector implements ContextSelector {
public ForInContextSelector(int index, ContextSelector base) { public ForInContextSelector(int index, ContextSelector base) {
this.index = index; this.index = index;
this.base = base; this.base = base;
this.oneLevel = new OneLevelSiteContextSelector(base); // this.oneLevel = new OneLevelSiteContextSelector(base);
} }
private final HashMap<MethodReference, Boolean> forInOnFirstArg_cache = HashMapFactory.make(); private final HashMap<MethodReference, Boolean> forInOnFirstArg_cache = HashMapFactory.make();
public static final HashMap<MethodReference, DefUse> du_cache = HashMapFactory.make(); private final HashMap<MethodReference, DefUse> du_cache = HashMapFactory.make();
public static final IRFactory<IMethod> factory = AstIRFactory.makeDefaultFactory(); private final IRFactory<IMethod> factory = AstIRFactory.makeDefaultFactory();
// determine whether the method performs a for-in loop over the properties of its index'th argument // determine whether the method performs a for-in loop over the properties of its index'th argument
@SuppressWarnings("unused")
private boolean forInOnFirstArg(IMethod method) { private boolean forInOnFirstArg(IMethod method) {
MethodReference mref = method.getReference(); MethodReference mref = method.getReference();
if(method.getNumberOfParameters() < index) if(method.getNumberOfParameters() < index)
@ -198,7 +245,7 @@ public class ForInContextSelector implements ContextSelector {
if(b != null) if(b != null)
return b; return b;
DefUse du = getDefUse(method); DefUse du = getDefUse(method);
for(SSAInstruction use : Iterator2Iterable.make(du.getUses(3))) { for(SSAInstruction use : Iterator2Iterable.make(du.getUses(index+1))) {
if(use instanceof EachElementGetInstruction) { if(use instanceof EachElementGetInstruction) {
forInOnFirstArg_cache.put(mref, true); forInOnFirstArg_cache.put(mref, true);
return true; return true;
@ -208,7 +255,7 @@ public class ForInContextSelector implements ContextSelector {
return false; return false;
} }
public static DefUse getDefUse(IMethod method) { private DefUse getDefUse(IMethod method) {
MethodReference mref = method.getReference(); MethodReference mref = method.getReference();
DefUse du = du_cache.get(mref); DefUse du = du_cache.get(mref);
if(du == null) { if(du == null) {
@ -231,16 +278,16 @@ public class ForInContextSelector implements ContextSelector {
return f; return f;
boolean usedAsPropertyName = false, usedAsSomethingElse = false; boolean usedAsPropertyName = false, usedAsSomethingElse = false;
DefUse du = getDefUse(method); DefUse du = getDefUse(method);
for(SSAInstruction use : Iterator2Iterable.make(du.getUses(3))) { for(SSAInstruction use : Iterator2Iterable.make(du.getUses(index+1))) {
if(use instanceof ReflectiveMemberAccess) { if(use instanceof ReflectiveMemberAccess) {
ReflectiveMemberAccess rma = (ReflectiveMemberAccess)use; ReflectiveMemberAccess rma = (ReflectiveMemberAccess)use;
if(rma.getMemberRef() == 3) { if(rma.getMemberRef() == index+1) {
usedAsPropertyName = true; usedAsPropertyName = true;
continue; continue;
} }
} else if(use instanceof AstIsDefinedInstruction) { } else if(use instanceof AstIsDefinedInstruction) {
AstIsDefinedInstruction aidi = (AstIsDefinedInstruction)use; AstIsDefinedInstruction aidi = (AstIsDefinedInstruction)use;
if(aidi.getNumberOfUses() > 1 && aidi.getUse(1) == 3) { if(aidi.getNumberOfUses() > 1 && aidi.getUse(1) == index+1) {
usedAsPropertyName = true; usedAsPropertyName = true;
continue; continue;
} }
@ -293,7 +340,7 @@ public class ForInContextSelector implements ContextSelector {
Frequency f = usesFirstArgAsPropertyName(callee); Frequency f = usesFirstArgAsPropertyName(callee);
if(f == Frequency.ALWAYS) { if(f == Frequency.ALWAYS) {
return new ForInContext(baseContext, simulateToString(caller.getClassHierarchy(), receiver[index])); return new ForInContext(baseContext, simulateToString(caller.getClassHierarchy(), receiver[index]));
} else if(f == Frequency.SOMETIMES || forInOnFirstArg(callee)) { } else if(f == Frequency.SOMETIMES) {
if(receiver[index] == null) { if(receiver[index] == null) {
IClass undef = caller.getClassHierarchy().lookupClass(JavaScriptTypes.Undefined); IClass undef = caller.getClassHierarchy().lookupClass(JavaScriptTypes.Undefined);
return new ForInContext(baseContext, new ConcreteTypeKey(undef)); return new ForInContext(baseContext, new ConcreteTypeKey(undef));
@ -306,7 +353,15 @@ public class ForInContextSelector implements ContextSelector {
return new SelectiveCPAContext(baseContext, receiver); return new SelectiveCPAContext(baseContext, receiver);
} else if (USE_1LEVEL_IN_BODIES && FORIN_MARKER.equals(caller.getContext().get(FORIN_KEY))) { } else if (USE_1LEVEL_IN_BODIES && FORIN_MARKER.equals(caller.getContext().get(FORIN_KEY))) {
if (! identifyDependentParameters(caller, site).isEmpty()) { if (! identifyDependentParameters(caller, site).isEmpty()) {
return oneLevel.getCalleeTarget(caller, site, callee, receiver); // final Context calleeTarget = oneLevel.getCalleeTarget(caller, site, callee, receiver);
// // RECURSION CHECK: only add one level of caller-site contexts if the caller and callee methods are distinct
// if (!RecursionCheckContextSelector.recursiveContext(calleeTarget, callee)) {
// return calleeTarget;
// }
// use a MarkerForInContext to clone based on the InstanceKey used in the caller context
// TODO the cast below isn't safe; fix
InstanceKey callerIk = ((ForInContext)caller.getContext()).getInstanceKey();
return new MarkerForInContext(baseContext, callerIk);
} else { } else {
return baseContext; return baseContext;
} }
@ -314,8 +369,10 @@ public class ForInContextSelector implements ContextSelector {
return baseContext; return baseContext;
} }
public IntSet getRelevantParameters(CGNode caller, CallSiteReference site) { public IntSet getRelevantParameters(CGNode caller, CallSiteReference site) {
if (USE_CPA_IN_BODIES && FORIN_MARKER.equals(caller.getContext().get(FORIN_KEY))) { if (USE_CPA_IN_BODIES && FORIN_MARKER.equals(caller.getContext().get(FORIN_KEY))) {
// what about base.getRelevantParameters() here?
return identifyDependentParameters(caller, site); return identifyDependentParameters(caller, site);
} else if (caller.getIR().getCalls(site)[0].getNumberOfUses() > index) { } else if (caller.getIR().getCalls(site)[0].getNumberOfUses() > index) {
return IntSetUtil.make(new int[]{index}).union(base.getRelevantParameters(caller, site)); return IntSetUtil.make(new int[]{index}).union(base.getRelevantParameters(caller, site));

View File

@ -16,7 +16,6 @@ public class GlobalObjectKey implements InstanceKey {
this.concreteType = concreteType; this.concreteType = concreteType;
} }
@Override
public IClass getConcreteType() { public IClass getConcreteType() {
return concreteType; return concreteType;
} }

Some files were not shown because too many files have changed in this diff Show More