Fixed bugs in the front end handling esoteric cases of weird control

flow.

added support for JavaScript projects read from Eclipse that are based
on HTML files as well as JavaScript files
This commit is contained in:
Julian Dolby 2013-07-30 14:04:08 -04:00
parent de6b644e8c
commit beab92e359
21 changed files with 418 additions and 58 deletions

View File

@ -15,5 +15,6 @@ Require-Bundle: com.ibm.wala.cast.js.rhino;bundle-version="1.0.0",
org.junit;bundle-version="4.0.0"
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Bundle-ActivationPolicy: lazy
Export-Package: com.ibm.wala.cast.js.rhino.test,
Export-Package: com.ibm.wala.cast.js.rhino.callgraph.fieldbased.test,
com.ibm.wala.cast.js.rhino.test,
com.ibm.wala.cast.js.test

View File

@ -74,7 +74,12 @@ public class TestSimpleCallGraphShapeRhino extends TestSimpleCallGraphShape {
public void testNonLoopBreakLabel() throws IllegalArgumentException, IOException, CancelException, WalaException {
JSCallGraphBuilderUtil.makeScriptCG("tests", "non_loop_break.js");
}
@Test
public void testForInName() throws IllegalArgumentException, IOException, CancelException, WalaException {
JSCallGraphBuilderUtil.makeScriptCG("tests", "for_in_name.js");
}
@Test(expected = WalaException.class)
public void testParseError() throws IllegalArgumentException, IOException, CancelException, WalaException {
PropagationCallGraphBuilder B = JSCallGraphBuilderUtil.makeScriptCGBuilder("tests", "portal-example-simple.html");

View File

@ -8,6 +8,7 @@
</listAttribute>
<booleanAttribute key="org.eclipse.debug.core.appendEnvironmentVariables" value="true"/>
<mapAttribute key="org.eclipse.debug.core.preferred_launchers">
<mapEntry key="[debug]" value="org.eclipse.jdt.junit.launchconfig"/>
<mapEntry key="[run]" value="org.eclipse.jdt.junit.launchconfig"/>
</mapAttribute>
<stringAttribute key="org.eclipse.debug.ui.ATTR_CAPTURE_IN_FILE" value="/tmp/console.txt"/>

View File

@ -294,7 +294,7 @@ public class RhinoToAstTranslator {
}
private CAstNode handleNew(WalkContext context, String globalName, CAstNode arguments[]) {
return handleNew(context, readName(context, globalName), arguments);
return handleNew(context, readName(context, null, globalName), arguments);
}
private CAstNode handleNew(WalkContext context, CAstNode value, CAstNode arguments[]) {
@ -557,9 +557,13 @@ public class RhinoToAstTranslator {
return n;
}
private CAstNode readName(WalkContext context, String name) {
private CAstNode readName(WalkContext context, AstNode node, String name) {
CAstNode cn = makeVarRef(name);
context.cfg().map(cn, cn);
if (node != null) {
context.cfg().map(node, cn);
} else {
context.cfg().map(cn, cn);
}
CAstNode target = context.getCatchTarget();
if (target != null) {
context.cfg().add(cn, target, JavaScriptTypes.ReferenceError);
@ -729,14 +733,16 @@ public class RhinoToAstTranslator {
public CAstNode visitContinueStatement(ContinueStatement node,
WalkContext arg) {
CAstNode continueStmt;
Node target;
if (node.getLabel() != null) {
continueStmt = Ast.makeNode(CAstNode.GOTO, Ast.makeConstant(node.getLabel().getIdentifier()));
target = arg.getContinueFor(node.getLabel().getIdentifier());
} else {
continueStmt = Ast.makeNode(CAstNode.GOTO);
target = arg.getContinueFor(null);
}
arg.cfg().map(node, continueStmt);
Node target = node.getTarget();
arg.cfg().add(node, target, null);
return continueStmt;
@ -805,15 +811,15 @@ public class RhinoToAstTranslator {
}
@Override
public CAstNode visitForInLoop(ForInLoop node, WalkContext arg) {
String tempName = "for in loop temp";
public CAstNode visitForInLoop(ForInLoop node, WalkContext arg) {
// set up
AstNode object = node.getIteratedObject();
CAstNode loopTemp =
Ast.makeNode(CAstNode.DECL_STMT, Ast.makeConstant(new CAstSymbolImpl(tempName)),
visit(object, arg));
CAstNode object = visit(node.getIteratedObject(), arg);
String tempName = "for in loop temp";
CAstNode[] loopHeader = new CAstNode[]{
Ast.makeNode(CAstNode.DECL_STMT, Ast.makeConstant(new CAstSymbolImpl(tempName))),
Ast.makeNode(CAstNode.ASSIGN, Ast.makeNode(CAstNode.VAR, Ast.makeConstant(tempName)), object)
};
CAstNode initNode;
AstNode var = node.getIterator();
assert var instanceof Name || var instanceof VariableDeclaration || var instanceof LetNode : var.getClass() + " " + var;
@ -844,7 +850,7 @@ public class RhinoToAstTranslator {
} else {
arg.addNameDecl(
Ast.makeNode(CAstNode.DECL_STMT, Ast.makeConstant(new CAstSymbolImpl(init.getTarget().getString())),
readName(arg, "$$undefined")));
readName(arg, null, "$$undefined")));
initNode =
Ast.makeNode(CAstNode.ASSIGN,
@ -858,15 +864,21 @@ public class RhinoToAstTranslator {
CAstNode breakLabel = visit(breakStmt, arg);
AstNode contStmt = makeEmptyLabelStmt("contLabel");
CAstNode contLabel = visit(contStmt, arg);
// TODO: Figure out why this is needed to make the correlation extraction tests pass
// TODO: remove this silly label
AstNode garbageStmt = makeEmptyLabelStmt("garbageLabel");
CAstNode garbageLabel = visit(garbageStmt, arg);
WalkContext loopContext = makeLoopContext(node, arg, breakStmt, contStmt);
CAstNode body = Ast.makeNode(CAstNode.BLOCK_STMT,
initNode,
visit(node.getBody(), loopContext),
contLabel);
garbageLabel);
CAstNode loop = Ast.makeNode(CAstNode.LOCAL_SCOPE,
Ast.makeNode(CAstNode.BLOCK_STMT,
loopTemp,
loopHeader[0],
loopHeader[1],
contLabel,
Ast.makeNode(CAstNode.LOOP,
Ast.makeNode(CAstNode.EACH_ELEMENT_HAS_NEXT,
Ast.makeNode(CAstNode.VAR, Ast.makeConstant(tempName))),
@ -885,9 +897,10 @@ public class RhinoToAstTranslator {
WalkContext loopContext = makeLoopContext(node, arg, breakStmt, contStmt);
CAstNode loop = Ast.makeNode(CAstNode.BLOCK_STMT,
CAstNode loop;
CAstNode top = Ast.makeNode(CAstNode.BLOCK_STMT,
visit(node.getInitializer(), arg),
Ast.makeNode(CAstNode.LOOP,
loop = Ast.makeNode(CAstNode.LOOP,
visit(node.getCondition(), arg),
Ast.makeNode(CAstNode.BLOCK_STMT,
visit(node.getBody(), loopContext),
@ -895,7 +908,7 @@ public class RhinoToAstTranslator {
visit(node.getIncrement(), arg))),
breakLabel);
arg.cfg().map(node, loop);
return loop;
return top;
}
private CAstNode[] gatherCallArguments(Node call, WalkContext context) {
@ -912,7 +925,7 @@ public class RhinoToAstTranslator {
public CAstNode visitFunctionCall(FunctionCall n, WalkContext context) {
if (!isPrimitiveCall(context, n)) {
AstNode callee = n.getTarget();
int thisBaseVarNum = ++baseVarNum;
int thisBaseVarNum = ++tempVarNum;
WalkContext child = new MemberDestructuringContext(context, callee, thisBaseVarNum);
CAstNode fun = visit(callee, child);
@ -1107,7 +1120,7 @@ public class RhinoToAstTranslator {
@Override
public CAstNode visitName(Name n, WalkContext context) {
return readName(context, n.getString());
return readName(context, n, n.getString());
}
@Override
@ -1345,7 +1358,7 @@ public class RhinoToAstTranslator {
noteSourcePosition(
arg,
Ast.makeNode(CAstNode.DECL_STMT, Ast.makeConstant(new CAstSymbolImpl(init.getTarget().getString())),
readName(arg, "$$undefined")),
readName(arg, null, "$$undefined")),
node));
if (init.getInitializer() == null) {
@ -1380,11 +1393,10 @@ public class RhinoToAstTranslator {
WalkContext loopContext = makeLoopContext(node, arg, breakStmt, contStmt);
CAstNode loop = Ast.makeNode(CAstNode.BLOCK_STMT,
contLabel,
Ast.makeNode(CAstNode.LOOP,
visit(node.getCondition(), arg),
Ast.makeNode(CAstNode.BLOCK_STMT,
visit(node.getBody(), loopContext),
contLabel)),
visit(node.getBody(), loopContext)),
breakLabel);
arg.cfg().map(node, loop);
@ -2337,7 +2349,7 @@ private CAstNode[] walkChildren(final Node n, WalkContext context) {
final private Reader sourceReader;
private int baseVarNum = 0;
private int tempVarNum = 0;
private final DoLoopTranslator doLoopTranslator;

View File

@ -0,0 +1,10 @@
var f = function for_in_with_assign(b) {
var a,d,n,e;
n=1;
for(e=arguments.length;n<e;n+=1)
for(a in d=arguments[n],d)
Object.prototype.hasOwnProperty.call(d,a)&&(b[a]=d[a]);
return b;
}
f(new Object());

View File

@ -0,0 +1,74 @@
var f = function(arrangedSSIDs,accessPointSpecs,exactLocation)
{
for (var i=0; i < accessPointSpecs.length; i++)
{
var definedSSID = accessPointSpecs[i].SSID;
var definedMAC = accessPointSpecs[i].MAC;
if (arrangedSSIDs[definedSSID])
{
if (definedMAC)
{
if (arrangedSSIDs[definedSSID][definedMAC])
{
arrangedSSIDs[definedSSID][definedMAC].checked = true;
continue;
}
return false;
}
arrangedSSIDs[definedSSID].checked = true;
continue;
}
return false;
}
if (exactLocation)
{
for (var key in arrangedSSIDs)
{
var SSID = arrangedSSIDs[key];
if (!SSID.checked)
{
var checkedMACs = false;
for (var MAC in SSID)
{
checkedMACs = true;
var obj = SSID[MAC];
if (!obj.checked) return false;
}
if (!checkedMACs) return false;
}
}
}
return true;
};
var g = function(transactionId) {
var obj,http,i;
try
{
http = new XMLHttpRequest();
obj = { conn:http, tId:transactionId, xhr: true };
}
catch(e)
{
for(i=0; i<this._msxml_progid.length; ++i){
try
{
http = new ActiveXObject(this._msxml_progid[i]);
obj = { conn:http, tId:transactionId, xhr: true };
break;
}
catch(e1){}
}
}
finally
{
return obj;
}
}
f();
g();

View File

@ -16,6 +16,7 @@ import java.io.IOException;
import java.util.regex.Pattern;
import org.junit.Assert;
import org.junit.ComparisonFailure;
import org.junit.Ignore;
import org.junit.Test;
@ -50,20 +51,27 @@ public abstract class TestForInBodyExtraction {
public void testRewriter(String testName, String in, String out) {
File tmp = null;
String expected = null;
String actual = null;
try {
tmp = File.createTempFile("test", ".js");
FileUtil.writeFile(tmp, in);
CAstImpl ast = new CAstImpl();
String actual = new CAstDumper().dump(new ClosureExtractor(ast, ForInBodyExtractionPolicy.FACTORY).rewrite(parseJS(tmp, ast)));
actual = new CAstDumper().dump(new ClosureExtractor(ast, ForInBodyExtractionPolicy.FACTORY).rewrite(parseJS(tmp, ast)));
actual = eraseGeneratedNames(actual);
FileUtil.writeFile(tmp, out);
String expected = new CAstDumper().dump(parseJS(tmp, ast));
expected = new CAstDumper().dump(parseJS(tmp, ast));
expected = eraseGeneratedNames(expected);
Assert.assertEquals(testName, expected, actual);
} catch (IOException e) {
e.printStackTrace();
} catch (ComparisonFailure e) {
System.err.println("Comparison Failure in " + testName + "!");
System.err.println(expected);
System.err.println(actual);
throw e;
} finally {
if(tmp != null && tmp.exists())
tmp.delete();

View File

@ -671,6 +671,11 @@ public abstract class TestSimpleCallGraphShape extends TestJSCallGraphShape {
JSCallGraphBuilderUtil.makeScriptCG("tests", "dead_catch.js");
}
@Test
public void testUglyLoopCrash() throws IllegalArgumentException, IOException, CancelException, WalaException {
JSCallGraphBuilderUtil.makeScriptCG("tests", "ssa-crash.js");
}
@Ignore("need a bug fix")
@Test
public void testTryFinallyCrash() throws IllegalArgumentException, IOException, CancelException, WalaException {

View File

@ -69,6 +69,7 @@ import com.ibm.wala.shrikeBT.IUnaryOpInstruction;
import com.ibm.wala.shrikeBT.ShiftInstruction;
import com.ibm.wala.ssa.SSAAbstractInvokeInstruction;
import com.ibm.wala.ssa.SSAGetCaughtExceptionInstruction;
import com.ibm.wala.ssa.SSAGotoInstruction;
import com.ibm.wala.ssa.SSAInstruction;
import com.ibm.wala.ssa.SSAInstructionFactory;
import com.ibm.wala.ssa.SSAMonitorInstruction;
@ -603,7 +604,7 @@ public abstract class AstTranslator extends CAstVisitor<AstTranslator.WalkContex
return "PreBB" + number + ":" + firstIndex + ".." + lastIndex;
}
List<SSAInstruction> instructions() {
private List<SSAInstruction> instructions() {
return instructions;
}
@ -1062,6 +1063,9 @@ public abstract class AstTranslator extends CAstVisitor<AstTranslator.WalkContex
if (currentBlock.instructions().size() == 0) {
currentBlock.setFirstIndex(inst);
} else {
for(SSAInstruction priorInst : currentBlock.instructions()) {
assert ! (priorInst instanceof SSAGotoInstruction);
}
assert !(n instanceof SSAGetCaughtExceptionInstruction);
}
@ -1114,13 +1118,34 @@ public abstract class AstTranslator extends CAstVisitor<AstTranslator.WalkContex
}
}
AstCFG(CAstEntity n, IncipientCFG icfg, SymbolTable symtab) {
private boolean checkBlockBoundaries(IncipientCFG icfg) {
MutableIntSet boundaries = IntSetUtil.make();
for(PreBasicBlock b : icfg) {
if (b.getFirstInstructionIndex() >= 0) {
if (boundaries.contains(b.getFirstInstructionIndex())) {
return false;
}
boundaries.add(b.getFirstInstructionIndex());
}
if (b.getLastInstructionIndex() >= 0 && b.getLastInstructionIndex() != b.getFirstInstructionIndex()) {
if (boundaries.contains(b.getLastInstructionIndex())) {
return false;
}
boundaries.add(b.getLastInstructionIndex());
}
}
return true;
}
AstCFG(CAstEntity n, IncipientCFG icfg, SymbolTable symtab, SSAInstructionFactory insts) {
super(null);
Set<PreBasicBlock> liveBlocks = DFS.getReachableNodes(icfg, Collections.singleton(icfg.entryBlock));
List<PreBasicBlock> blocks = icfg.blocks;
boolean hasDeadBlocks = blocks.size() > liveBlocks.size();
assert checkBlockBoundaries(icfg);
this.symtab = symtab;
functionName = n.getName();
instructionToBlockMap = new int[liveBlocks.size()];
@ -1149,11 +1174,15 @@ public abstract class AstTranslator extends CAstVisitor<AstTranslator.WalkContex
});
}
int instruction = 0;
for (int i = 0, blockNumber = 0; i < blocks.size(); i++) {
PreBasicBlock pb = blocks.get(i);
PreBasicBlock block = blocks.get(i);
block.setGraphNodeId(-1);
if (liveBlocks.contains(pb)) {
if (liveBlocks.contains(block)) {
if (block.getFirstInstructionIndex() >= 0) {
block.setFirstIndex(instruction);
block.setLastIndex((instruction += block.instructions().size()) - 1);
}
instructionToBlockMap[blockNumber] = block.getLastInstructionIndex();
this.addNode(block);
@ -1209,7 +1238,14 @@ public abstract class AstTranslator extends CAstVisitor<AstTranslator.WalkContex
if (liveBlocks.contains(blocks.get(i))) {
List<SSAInstruction> bi = blocks.get(i).instructions();
for (int j = 0; j < bi.size(); j++) {
instructions[x++] = bi.get(j);
SSAInstruction inst = bi.get(j);
if (inst instanceof SSAGetCaughtExceptionInstruction) {
SSAGetCaughtExceptionInstruction ci = (SSAGetCaughtExceptionInstruction) inst;
if (ci.getBasicBlockNumber() != blocks.get(i).getNumber()) {
inst = insts.GetCaughtExceptionInstruction(blocks.get(i).getNumber(), ci.getException());
}
}
instructions[x++] = inst;
}
}
}
@ -3107,7 +3143,7 @@ public abstract class AstTranslator extends CAstVisitor<AstTranslator.WalkContex
// create code entry stuff for this entity
SymbolTable symtab = ((AbstractScope) functionContext.currentScope()).getUnderlyingSymtab();
Map<IBasicBlock,TypeReference[]> catchTypes = functionContext.getCatchTypes();
AstCFG cfg = new AstCFG(n, functionContext.cfg(), symtab);
AstCFG cfg = new AstCFG(n, functionContext.cfg(), symtab, insts);
Position[] line = functionContext.cfg().getLinePositionMap();
boolean katch = functionContext.cfg().hasCatchBlock();
boolean monitor = functionContext.cfg().hasMonitorOp();
@ -3526,13 +3562,13 @@ public abstract class AstTranslator extends CAstVisitor<AstTranslator.WalkContex
WalkContext context = (WalkContext) c;
if (!context.cfg().isDeadBlock(context.cfg().getCurrentBlock())) {
context.cfg().addPreNode(n, context.getUnwindState());
context.cfg().addInstruction(insts.GotoInstruction());
context.cfg().newBlock(false);
context.cfg().addPreEdge(n, context.getControlFlow().getTarget(n, null), false);
context.cfg().addInstruction(insts.GotoInstruction());
if (context.getControlFlow().getTarget(n, null) == null) {
assert context.getControlFlow().getTarget(n, null) != null : context.getControlFlow() + " does not map " + n + " ("
+ context.getSourceMap().getPosition(n) + ")";
}
context.cfg().addPreEdge(n, context.getControlFlow().getTarget(n, null), false);
context.cfg().newBlock(false);
}
}

View File

@ -185,7 +185,7 @@ public abstract class CAstAbstractModuleLoader extends CAstAbstractLoader {
* in topLevelEntities
*/
private void translateModuleToCAst(Module module, CAst ast, Set<Pair<CAstEntity, ModuleEntry>> topLevelEntities) {
for (Iterator<ModuleEntry> mes = module.getEntries(); mes.hasNext();) {
for (Iterator<? extends ModuleEntry> mes = module.getEntries(); mes.hasNext();) {
translateModuleEntryToCAst(mes.next(), ast, topLevelEntities);
}
}

View File

@ -43,8 +43,8 @@ public abstract class DirectoryTreeModule implements Module {
protected abstract boolean includeFile(File file);
private Set<ModuleEntry> getEntriesRecursive(File dir) {
Set<ModuleEntry> result = HashSetFactory.make();
private Set<FileModule> getEntriesRecursive(File dir) {
Set<FileModule> result = HashSetFactory.make();
File[] files = dir.listFiles();
if (files != null) {
for (int i = 0; i < files.length; i++) {
@ -67,7 +67,7 @@ public abstract class DirectoryTreeModule implements Module {
}
@Override
public Iterator<ModuleEntry> getEntries() {
public Iterator<FileModule> getEntries() {
return getEntriesRecursive(root).iterator();
}

View File

@ -23,5 +23,5 @@ public interface Module {
/**
* @return an Iterator of the ModuleEntries in this Module.
*/
Iterator<ModuleEntry> getEntries();
Iterator<? extends ModuleEntry> getEntries();
}

View File

@ -16,3 +16,4 @@ Require-Bundle: com.ibm.wala.core;bundle-version="1.1.3",
org.junit;bundle-version="4.0.0"
Bundle-ActivationPolicy: lazy
Bundle-Activator: com.ibm.wala.ide.jsdt.tests.Activator
Export-Package: com.ibm.wala.ide.jsdt.tests

View File

@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<launchConfiguration type="org.eclipse.pde.ui.JunitLaunchConfig">
<booleanAttribute key="append.args" value="true"/>
<booleanAttribute key="askclear" value="false"/>
<booleanAttribute key="automaticAdd" value="true"/>
<booleanAttribute key="automaticValidate" value="false"/>
<stringAttribute key="bootstrap" value=""/>
<stringAttribute key="checked" value="[NONE]"/>
<booleanAttribute key="clearConfig" value="true"/>
<booleanAttribute key="clearws" value="true"/>
<booleanAttribute key="clearwslog" value="false"/>
<stringAttribute key="configLocation" value="${workspace_loc}/.metadata/.plugins/org.eclipse.pde.core/pde-junit"/>
<booleanAttribute key="default" value="true"/>
<booleanAttribute key="includeOptional" value="true"/>
<stringAttribute key="location" value="${workspace_loc}/../junit-workspace"/>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
<listEntry value="/com.ibm.wala.ide.jsdt.tests/src/com/ibm/wala/ide/jsdt/tests/WLProjectWebScopeTest.java"/>
</listAttribute>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
<listEntry value="1"/>
</listAttribute>
<stringAttribute key="org.eclipse.debug.ui.ATTR_CAPTURE_IN_FILE" value="/tmp/jswebcgtest.txt"/>
<stringAttribute key="org.eclipse.jdt.junit.CONTAINER" value=""/>
<booleanAttribute key="org.eclipse.jdt.junit.KEEPRUNNING_ATTR" value="false"/>
<stringAttribute key="org.eclipse.jdt.junit.TESTNAME" value=""/>
<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.ide.jsdt.tests.WLProjectWebScopeTest"/>
<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-os ${target.os} -ws ${target.ws} -arch ${target.arch} -nl ${target.nl} -consoleLog"/>
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="com.ibm.wala.ide.jsdt.tests"/>
<stringAttribute key="org.eclipse.jdt.launching.SOURCE_PATH_PROVIDER" value="org.eclipse.pde.ui.workbenchClasspathProvider"/>
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Xms40m -XX:MaxPermSize=512m -Xmx2048m -Xdock:icon=../Resources/Eclipse.icns -XstartOnFirstThread -Dorg.eclipse.swt.internal.carbon.smallFonts"/>
<stringAttribute key="pde.version" value="3.3"/>
<stringAttribute key="product" value="org.eclipse.sdk.ide"/>
<booleanAttribute key="run_in_ui_thread" value="true"/>
<booleanAttribute key="show_selected_only" value="false"/>
<booleanAttribute key="tracing" value="false"/>
<booleanAttribute key="useCustomFeatures" value="false"/>
<booleanAttribute key="useDefaultConfig" value="true"/>
<booleanAttribute key="useDefaultConfigArea" value="false"/>
<booleanAttribute key="useProduct" value="true"/>
</launchConfiguration>

File diff suppressed because one or more lines are too long

View File

@ -36,7 +36,7 @@ import com.ibm.wala.ipa.callgraph.CallGraph;
import com.ibm.wala.ipa.cha.IClassHierarchy;
import com.ibm.wala.util.CancelException;
public class AbstractJSProjectScopeTest {
public abstract class AbstractJSProjectScopeTest {
protected final ZippedProjectData project;
@ -55,12 +55,16 @@ public class AbstractJSProjectScopeTest {
public void testProjectScope() throws IOException, CoreException {
IJavaScriptProject p = JavaScriptHeadlessUtil.getJavaScriptProjectFromWorkspace(project.projectName);
JSCallGraphUtil.setTranslatorFactory(new CAstRhinoTranslatorFactory());
AnalysisScope s = JavaScriptEclipseProjectPath.make(p).toAnalysisScope(new CAstAnalysisScope(JSCallGraphUtil.makeLoaders(), Collections.singleton(JavaScriptLoader.JS)));
AnalysisScope s = makeProjectPath(p).toAnalysisScope(new CAstAnalysisScope(JSCallGraphUtil.makeLoaders(), Collections.singleton(JavaScriptLoader.JS)));
System.err.println(s);
Assert.assertTrue("cannot make scope", s != null);
Assert.assertFalse("cannot find files", s.getModules(JavaScriptTypes.jsLoader).isEmpty());
}
protected JavaScriptEclipseProjectPath makeProjectPath(IJavaScriptProject p) throws IOException, CoreException {
return JavaScriptEclipseProjectPath.make(p);
}
@Test
public void testParsing() throws IOException, CoreException {
Set<ModuleEntry> mes = JsdtUtil.getJavaScriptCodeFromProject(project.projectName);
@ -77,7 +81,7 @@ public class AbstractJSProjectScopeTest {
@Test
public void testEngine() throws IOException, CoreException, IllegalArgumentException, CancelException {
IJavaScriptProject p = JavaScriptHeadlessUtil.getJavaScriptProjectFromWorkspace(project.projectName);
EclipseJavaScriptAnalysisEngine e = new EclipseJavaScriptAnalysisEngine(p);
EclipseJavaScriptAnalysisEngine e = makeAnalysisEngine(p);
JSCallGraphUtil.setTranslatorFactory(new CAstRhinoTranslatorFactory());
e.buildAnalysisScope();
IClassHierarchy cha = e.getClassHierarchy();
@ -85,16 +89,8 @@ public class AbstractJSProjectScopeTest {
Assert.assertTrue(cha != null);
}
@Test
public void testFieldBasedCG() throws IOException, CoreException, IllegalArgumentException, CancelException {
IJavaScriptProject p = JavaScriptHeadlessUtil.getJavaScriptProjectFromWorkspace(project.projectName);
EclipseJavaScriptAnalysisEngine e = new EclipseJavaScriptAnalysisEngine(p);
JSCallGraphUtil.setTranslatorFactory(new CAstRhinoTranslatorFactory());
e.buildAnalysisScope();
CallGraph CG = e.getFieldBasedCallGraph();
System.err.println(CG);
Assert.assertTrue(CG.getNumberOfNodes() > 0);
Assert.assertTrue(CG != null);
protected EclipseJavaScriptAnalysisEngine makeAnalysisEngine(IJavaScriptProject p) throws IOException, CoreException {
return new EclipseJavaScriptAnalysisEngine(p);
}
}

View File

@ -0,0 +1,26 @@
package com.ibm.wala.ide.jsdt.tests;
import java.io.IOException;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.wst.jsdt.core.IJavaScriptProject;
import com.ibm.wala.cast.js.client.EclipseJavaScriptAnalysisEngine;
import com.ibm.wala.cast.js.client.EclipseWebAnalysisEngine;
import com.ibm.wala.ide.util.EclipseWebProjectPath;
import com.ibm.wala.ide.util.JavaScriptEclipseProjectPath;
public class WLProjectWebScopeTest extends WLProjectScopeTest {
@Override
protected JavaScriptEclipseProjectPath makeProjectPath(IJavaScriptProject p) throws IOException, CoreException {
return new EclipseWebProjectPath(p);
}
@Override
protected EclipseJavaScriptAnalysisEngine makeAnalysisEngine(IJavaScriptProject p) throws IOException, CoreException {
return new EclipseWebAnalysisEngine(p);
}
}

View File

@ -0,0 +1,40 @@
package com.ibm.wala.cast.js.client;
import java.io.IOException;
import java.util.Collections;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.wst.jsdt.core.IJavaScriptProject;
import com.ibm.wala.cast.ipa.callgraph.CAstAnalysisScope;
import com.ibm.wala.cast.js.html.WebPageLoaderFactory;
import com.ibm.wala.cast.js.loader.JavaScriptLoader;
import com.ibm.wala.cast.js.translator.CAstRhinoTranslatorFactory;
import com.ibm.wala.classLoader.ClassLoaderFactory;
import com.ibm.wala.ide.util.EclipseWebProjectPath;
import com.ibm.wala.ide.util.JavaScriptEclipseProjectPath;
import com.ibm.wala.ipa.callgraph.AnalysisScope;
import com.ibm.wala.ipa.callgraph.impl.SetOfClasses;
public class EclipseWebAnalysisEngine extends EclipseJavaScriptAnalysisEngine {
public EclipseWebAnalysisEngine(IJavaScriptProject project) throws IOException, CoreException {
super(project);
}
@Override
protected ClassLoaderFactory makeClassLoaderFactory(SetOfClasses exclusions) {
return new WebPageLoaderFactory(new CAstRhinoTranslatorFactory());
}
@Override
protected AnalysisScope makeAnalysisScope() {
return new CAstAnalysisScope(new WebPageLoaderFactory(new CAstRhinoTranslatorFactory()), Collections.singleton(JavaScriptLoader.JS));
}
@Override
protected JavaScriptEclipseProjectPath createProjectPath(IJavaScriptProject project) throws IOException, CoreException {
return new EclipseWebProjectPath(project);
}
}

View File

@ -0,0 +1,46 @@
package com.ibm.wala.ide.util;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.wst.jsdt.core.IJavaScriptProject;
import com.ibm.wala.cast.ir.translator.TranslatorToCAst.Error;
import com.ibm.wala.cast.js.html.MappedSourceModule;
import com.ibm.wala.cast.js.html.WebUtil;
import com.ibm.wala.classLoader.FileModule;
import com.ibm.wala.classLoader.Module;
import com.ibm.wala.ide.classloader.EclipseSourceDirectoryTreeModule;
import com.ibm.wala.util.collections.MapUtil;
public class EclipseWebProjectPath extends JavaScriptEclipseProjectPath {
public EclipseWebProjectPath(IJavaScriptProject p) throws IOException, CoreException {
super(p);
}
@Override
protected void resolveSourcePathEntry(com.ibm.wala.ide.util.EclipseProjectPath.ILoader loader, boolean includeSource, boolean cpeFromMainProject, IPath p, IPath o, String fileExtension) {
List<Module> s = MapUtil.findOrCreateList(modules, loader);
Iterator<FileModule> htmlPages = new EclipseSourceDirectoryTreeModule(p, "html").getEntries();
while (htmlPages.hasNext()) {
FileModule htmlPage = htmlPages.next();
Set<MappedSourceModule> scripts;
String urlString = "file://" + htmlPage.getAbsolutePath();
try {
scripts = WebUtil.extractScriptFromHTML(new URL(urlString)).fst;
s.addAll(scripts);
} catch (MalformedURLException e1) {
assert false : "internal error constructing URL " + urlString;
} catch (Error e1) {
System.err.print("skipping " + htmlPage.getAbsolutePath() + ": " + e1.warning);
}
}
}
}

View File

@ -11,7 +11,12 @@
package com.ibm.wala.ide.util;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
@ -20,8 +25,18 @@ import org.eclipse.wst.jsdt.core.IJavaScriptProject;
import org.eclipse.wst.jsdt.core.JavaScriptCore;
import org.eclipse.wst.jsdt.core.JavaScriptModelException;
import com.ibm.wala.cast.ir.translator.TranslatorToCAst.Error;
import com.ibm.wala.cast.js.html.MappedSourceModule;
import com.ibm.wala.cast.js.html.WebUtil;
import com.ibm.wala.cast.js.types.JavaScriptTypes;
import com.ibm.wala.cast.loader.CAstAbstractLoader;
import com.ibm.wala.classLoader.FileModule;
import com.ibm.wala.classLoader.Module;
import com.ibm.wala.classLoader.SourceModule;
import com.ibm.wala.classLoader.SourceURLModule;
import com.ibm.wala.ide.classloader.EclipseSourceDirectoryTreeModule;
import com.ibm.wala.types.ClassLoaderReference;
import com.ibm.wala.util.collections.MapUtil;
public class JavaScriptEclipseProjectPath extends EclipseProjectPath<IIncludePathEntry, IJavaScriptProject> {

View File

@ -72,7 +72,7 @@ public class JsdtUtil {
List<Module> modules = s.getModules(JavaScriptTypes.jsLoader);
Set<ModuleEntry> mes = HashSetFactory.make();
for(Module m : modules) {
for(Iterator<ModuleEntry> mm = m.getEntries(); mm.hasNext(); ) {
for(Iterator<? extends ModuleEntry> mm = m.getEntries(); mm.hasNext(); ) {
mes.add(mm.next());
}
}