number of arguments supplied to methods calls is captured and
used to counter some of the loss of precision due to function
variadicity, by creating multiple distinct nodes in the call graph
for certain methods. Like ours, their analysis is unsound, but it
is likely to be less scalable than ours because of its reliance on
a traditional static pointer analysis. An in-depth comparison of
cost and accuracy of the two approaches is future work.
Agesen et al. presented a number of type inference tech-
niques [1–3] for Self, a language with many similarities to
JavaScript. They essentially compute highly context-sensitive
flow graphs (from which call graphs could be extracted) to
statically prove the absence of “message not understood”
errors, where a method is not found on the receiver object or
its prototypes. Our technique cannot do such reasoning, since
it does not track the flow of most objects. Tracking general
object flow for JavaScript leads to scalability and precision
issues due to heavy usage of reflective idioms that seem not
to be as frequently used in Self.
Grove and Chambers [8] present a general framework for
call-graph construction algorithms. Our analysis does not fit
directly in their framework since they do not discuss prototype-
based languages, but roughly speaking, our analysis can be
viewed as a variant of 0-CFA [17] where (1) only function
values are tracked, (2) field accesses are treated as accesses
to correspondingly-named global variables, and (3) all code is
assumed to be reachable. Our key contribution is in showing
that such an analysis works well for JavaScript in practice.
Previous work has studied the effectiveness of field-based flow
analysis for C [13] and Java [15, 18]. They exploit static type
information to distinguish identically named fields of different
struct/class types, which is impossible in JavaScript.
VI. CONCLUSIONS
We have presented a fast, practical flow analysis-based ap-
proach to call graph construction for JavaScript. Our analysis
(i) is field-based, i.e., identically named properties of different
objects are not distinguished; (ii) only tracks function values,
ignoring the flow of other objects; and (iii) ignores dynamic
property reads and writes. We have proposed two variants of
this analysis: a pessimistic variant that makes conservative
assumptions about interprocedural flow, and an optimistic
variant that iteratively builds an interprocedural flow graph.
Both analyses scale extremely well and can handle far larger
programs than any other static analysis for JavaScript that we
are aware of. While unsound in theory, they produce fairly
complete call graphs in practice. These properties make our
approach well-suited for use in an IDE.
In such a setting, it would be wasteful to build a call graph
from scratch every time it is needed, since large parts of
the program typically remain unchanged. Instead, flow graphs
could be precomputed and cached on a per-file basis, and then
combined into a graph for the whole program when needed.
As future work, we plan to apply our approach in other
settings besides IDEs, such as taint analysis [11]. Here, sound-
ness is much more important, so we need to handle dynamic
property accesses. Conservatively treating them as potentially
accessing all properties will in general result in too much
imprecision, so some form of string analysis for reasoning
about property names is likely needed. Introducing this and
other features (such as tracking of non-function objects) into
our analysis while still keeping it scalable is an interesting
challenge, which could provide valuable insights into the cost
and benefit of different analysis features for JavaScript.
REFERENCES
[1] O. Agesen. Constraint-Based Type Inference and Parametric
Polymorphism. In SAS, pages 78–100, 1994.
[2] O. Agesen. The Cartesian Product Algorithm: Simple and Pre-
cise Type Inference of Parametric Polymorphism. In ECOOP,
1995.
[3] O. Agesen and D. Ungar. Sifting out the Gold: Delivering
Compact Applications from an Exploratory Object-Oriented
Programming Environment. In OOPSLA, 1994.
[4] L. O. Andersen. Program Analysis and Specialization for the C
Programming Language. PhD thesis, University of Copenhagen,
DIKU, 1994.
[5] D. Bacon and P. Sweeney. Fast Static Analysis of C++ Virtual
Function Calls. In OOPSLA, 1996.
[6] J. Dean, D. Grove, and C. Chambers. Optimization of Object-
Oriented Programs Using Static Class Hierarchy Analysis. In
ECOOP, August 1995.
[7] A. Feldthaus, T. Millstein, A. Møller, M. Schäfer, and F. Tip.
Tool-supported Refactoring for JavaScript. In OOPSLA, 2011.
[8] D. Grove and C. Chambers. A Framework for Call Graph
Construction Algorithms. TOPLAS, 23(6), 2001.
[9] S. Guarnieri and V. B. Livshits. GATEKEEPER: Mostly Static
Enforcement of Security and Reliability Policies for JavaScript
Code. In USENIX Security Symposium, 2009.
[10] S. Guarnieri and V. B. Livshits. Gulfstream: Incremental Static
Analysis for Streaming JavaScript Applications. In WebApps,
2010.
[11] S. Guarnieri, M. Pistoia, O. Tripp, J. Dolby, S. Teilhet, and
R. Berg. Saving the World Wide Web from Vulnerable
JavaScript. In ISSTA, 2011.
[12] A. Guha, C. Saftoiu, and S. Krishnamurthi. Typing Local
Control and State Using Flow Analysis. In ESOP, 2011.
[13] N. Heintze and O. Tardieu. Ultra-fast Aliasing Analysis Using
CLA: A Million Lines of C Code in a Second. In PLDI, 2001.
[14] S. H. Jensen, A. Møller, and P. Thiemann. Type Analysis for
JavaScript. In SAS, 2009.
[15] O. Lhoták and L. Hendren. Scaling Java Points-to Analysis
Using Spark. In CC, April 2003.
[16] M. Madsen, B. Livshits, and M. Fanning. Practical Static Anal-
ysis of JavaScript Applications in the Presence of Frameworks
and Libraries. MSR TR 2012-66, Microsoft Research, 2012.
[17] O. Shivers. Control Flow Analysis in Scheme. In PLDI, 1988.
[18] M. Sridharan, D. Gopan, L. Shan, and R. Bodík. Demand-
Driven Points-To Analysis for Java. In OOPSLA, 2005.
[19] M. Sridharan, J. Dolby, S. Chandra, M. Schäfer, and F. Tip.
Correlation Tracking for Points-To Analysis of JavaScript. In
ECOOP, 2012.
[20] F. Tip and J. Palsberg. Scalable Propagation-Based Call Graph
Construction Algorithms. In OOPSLA, pages 281–293, 2000.
[21] D. Vardoulakis and O. Shivers. CFA2: A Context-Free Ap-
proach to Control-Flow Analysis. In ESOP, 2010.
[22] W
3
Techs. Usage of JavaScript Libraries for Websites.
http://w3techs.com/technologies/overview/javascript_library/all,
February 2013.
[23] S. Wei and B. G. Ryder. Practical Blended Taint Analysis for
JavaScript. Technical report, Virginia Tech, 2013.