Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How can I get call graph of multiple js files? #1366

Open
SherlockNovitch opened this issue Jan 23, 2024 · 1 comment
Open

How can I get call graph of multiple js files? #1366

SherlockNovitch opened this issue Jan 23, 2024 · 1 comment

Comments

@SherlockNovitch
Copy link

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?

@msridhar
Copy link
Member

msridhar commented Feb 1, 2024

Sorry this is not better documented. I was looking at this code to create Modules when there is a single file:

public static Module[] makeSourceModules(String dir, String name, ClassLoader loader)

It also adds a Module for the prologue by calling this function:

public static Module getPrologueFile(final String name) {

Does that help to fix your case?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants