How can I get call graph of multiple js files?
The wiki only has single-file api usage examples. I try to use the public static CallGraph makeScriptCG(SourceModule[] scripts, CGBuilderType builderType, IRFactory<IMethod> irFactory) api for multi-file call graph generation.
The complete code is as follows:
public static SourceURLModule getSourceURLModule(String path) {
try {
return new SourceURLModule(JSCallGraphBuilderUtil.getURLforFile("", String.valueOf(path)
, JSCallGraphBuilderUtil.class.getClassLoader()));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public static void generateCallGraph(String filePath) throws WalaException, IOException, CancelException {
Path path = Paths.get(filePath);
JSCallGraphUtil.setTranslatorFactory(new CAstRhinoTranslatorFactory());
LinkedList<SourceURLModule> sourceURLModules = new LinkedList<>();
Files.walk(path).filter(aPath -> aPath.toString().endsWith(".js"))
.forEach(apath -> sourceURLModules.add(getSourceURLModule(String.valueOf(apath))));
CallGraph cg = JSCallGraphBuilderUtil.makeScriptCG(sourceURLModules.toArray(new SourceURLModule[0]),
JSCallGraphBuilderUtil.CGBuilderType.ZERO_ONE_CFA,
AstIRFactory.makeDefaultFactory());
// CallGraph cg = JSCallGraphBuilderUtil.makeScriptCG(path.getParent().toString(), path.getFileName().toString());
System.out.println(CallGraphStats.getStats(cg));
System.out.println(cg);
}
The output results only contain the edge between the fake root and the file node under the filePath folder.
No other information is output, which is very different from the output of a single file.
Call graph stats:
Nodes: 14
Edges: 13
Methods: 14
Bytecode Bytes: 0
Node: synthetic < JavaScriptLoader, LFakeRoot, fakeRootMethod()V > Context: Everywhere
- JSCall@1
-> Node: <Code body of function L/D:/Project/JavaScriptCGUtil/src/test/js-benchmark1/apply.js> Context: Everywhere
- JSCall@3
-> Node: <Code body of function L/D:/Project/JavaScriptCGUtil/src/test/js-benchmark1/bind.js> Context: Everywhere
- JSCall@5
-> Node: <Code body of function L/D:/Project/JavaScriptCGUtil/src/test/js-benchmark1/call.js> Context: Everywhere
- JSCall@7
-> Node: <Code body of function L/D:/Project/JavaScriptCGUtil/src/test/js-benchmark1/callback.js> Context: Everywhere
- JSCall@9
-> Node: <Code body of function L/D:/Project/JavaScriptCGUtil/src/test/js-benchmark1/closure.js> Context: Everywhere
- JSCall@11
-> Node: <Code body of function L/D:/Project/JavaScriptCGUtil/src/test/js-benchmark1/dynamic_property.js> Context: Everywhere
- JSCall@13
-> Node: <Code body of function L/D:/Project/JavaScriptCGUtil/src/test/js-benchmark1/eval.js> Context: Everywhere
- JSCall@15
-> Node: <Code body of function L/D:/Project/JavaScriptCGUtil/src/test/js-benchmark1/helloworld.js> Context: Everywhere
- JSCall@17
-> Node: <Code body of function L/D:/Project/JavaScriptCGUtil/src/test/js-benchmark1/iife.js> Context: Everywhere
- JSCall@19
-> Node: <Code body of function L/D:/Project/JavaScriptCGUtil/src/test/js-benchmark1/prototype.js> Context: Everywhere
- JSCall@21
-> Node: <Code body of function L/D:/Project/JavaScriptCGUtil/src/test/js-benchmark1/prototype_chain.js> Context: Everywhere
- JSCall@23
-> Node: <Code body of function L/D:/Project/JavaScriptCGUtil/src/test/js-benchmark1/unknown_property.js> Context: Everywhere
- JSCall@25
-> Node: <Code body of function L/D:/Project/JavaScriptCGUtil/src/test/js-benchmark1/with.js> Context: Everywhere
Node: <Code body of function L/D:/Project/JavaScriptCGUtil/src/test/js-benchmark1/apply.js> Context: Everywhere
Node: <Code body of function L/D:/Project/JavaScriptCGUtil/src/test/js-benchmark1/bind.js> Context: Everywhere
Node: <Code body of function L/D:/Project/JavaScriptCGUtil/src/test/js-benchmark1/call.js> Context: Everywhere
Node: <Code body of function L/D:/Project/JavaScriptCGUtil/src/test/js-benchmark1/callback.js> Context: Everywhere
Node: <Code body of function L/D:/Project/JavaScriptCGUtil/src/test/js-benchmark1/closure.js> Context: Everywhere
Node: <Code body of function L/D:/Project/JavaScriptCGUtil/src/test/js-benchmark1/dynamic_property.js> Context: Everywhere
Node: <Code body of function L/D:/Project/JavaScriptCGUtil/src/test/js-benchmark1/eval.js> Context: Everywhere
Node: <Code body of function L/D:/Project/JavaScriptCGUtil/src/test/js-benchmark1/helloworld.js> Context: Everywhere
Node: <Code body of function L/D:/Project/JavaScriptCGUtil/src/test/js-benchmark1/iife.js> Context: Everywhere
Node: <Code body of function L/D:/Project/JavaScriptCGUtil/src/test/js-benchmark1/prototype.js> Context: Everywhere
Node: <Code body of function L/D:/Project/JavaScriptCGUtil/src/test/js-benchmark1/prototype_chain.js> Context: Everywhere
Node: <Code body of function L/D:/Project/JavaScriptCGUtil/src/test/js-benchmark1/unknown_property.js> Context: Everywhere
Node: <Code body of function L/D:/Project/JavaScriptCGUtil/src/test/js-benchmark1/with.js> Context: Everywhere
How can i get correct call graph of multiplejs files?
Sorry this is not better documented. I was looking at this code to create Modules when there is a single file:
https://github.com/wala/WALA/blob/130b92c444c206572682f2e007cca64670e3b03e/cast/js/src/main/java/com/ibm/wala/cast/js/util/JSCallGraphBuilderUtil.java#L143-L143
It also adds a Module for the prologue by calling this function:
https://github.com/wala/WALA/blob/130b92c444c206572682f2e007cca64670e3b03e/cast/js/src/main/java/com/ibm/wala/cast/js/ipa/callgraph/JSCallGraphUtil.java#L347-L347
Does that help to fix your case?