  Building sound and precise static call graphs for real-world JavaScript
applications poses an enormous challenge, due to many hard-to-analyze language
features. Further, the relative importance of these features may vary depending
on the call graph algorithm being used and the class of applications being
analyzed. In this paper, we present a technique to automatically quantify the
relative importance of different root causes of call graph unsoundness for a
set of target applications. The technique works by identifying the dynamic
function data flows relevant to each call edge missed by the static analysis,
correctly handling cases with multiple root causes and inter-dependent calls.
We apply our approach to perform a detailed study of the recall of a
state-of-the-art call graph construction technique on a set of framework-based
web applications. The study yielded a number of useful insights. We found that
while dynamic property accesses were the most common root cause of missed edges
across the benchmarks, other root causes varied in importance depending on the
benchmark, potentially useful information for an analysis designer. Further,
with our approach, we could quickly identify and fix a recall issue in the call
graph builder we studied, and also quickly assess whether a recent analysis
technique for Node.js-based applications would be helpful for browser-based
code. All of our code and data is publicly available, and many components of
our technique can be re-used to facilitate future studies.
