
Recency Types for Dynamically-Typed, Object-Based Languages Strong Updates for JavaScript Phillip Heidegger Peter Thiemann Universitat¨ Freiburg, Germany {heidegger,thiemann}@informatik.uni-freiburg.de Abstract ent implementations of the browser API by different vendors. Al- Object-based languages with dynamic type systems are popular though the latter problems are equally severe from a practical point because they accelerate the development of short programs. As of view, this paper concentrates on the typing problems. As many larger programs are built with those languages, static analyses other scripting languages (like Python, Ruby, PHP, Lua, Perl, Tcl) become important tools for detecting programming errors. are dynamically typed and object based, any progress in analyzing We define such an analysis as a type system for an imperative JavaScript programs can find fruitful application to the analysis of object-based calculus and prove its type soundness. The calculus properties for other scripting languages as well. models essential features of the JavaScript language, as an example of a typical and widely used dynamically-typed, object-based lan- 1.1 Problems with Typing JavaScript guage. The model includes objects as property maps, type change Weak, dynamic typing means in JavaScript that values are subject during object initialization, and precise support for JavaScript’s to extensive type conversion rules at run time. While each value is prototype mechanism. created at a certain type and keeps the type during its lifetime, a As a more general technical contribution, our work demon- use of the value can convert it implicitly into almost any other type. strates that the idea of recency abstraction can be transferred from Only a few of these conversions are forbidden and yield run-time abstract interpretation to a type system. We model recency infor- errors.2 Of the remaining legal conversions, quite a few are coun- mation with a notion of precise object pointers that enables strong, terintuitive or outright undesirable [27]. Thus, an analysis should type changing updates of object types during a generalized initial- be able to generate warnings for conversions that give unexpected ization phase. The same precise object pointers allow for an ac- results or have unexpected side effects. curate treatment of the prototype mechanism. Unlike linear types, As in many scripting languages, an object in JavaScript is rep- precise object pointers can be nested and mixed arbitrarily with or- resented by a property map that associates a value to a property dinary, imprecise object pointers in the type of a data structure. name. If this value happens to be a function, then the property is a method, otherwise it is a field of the object. Creating an object 1. Introduction amounts to allocating a new, empty property map and running a constructor method on this map. The constructor method enters val- Modern web applications are abundant with dynamic features ues into the property map, thus creating fields and methods of the like animations, pop-down menus, drag-and-drop, and wysiwyg- object. However, the creation of fields and methods is not restricted editors, just to name a few. While there are a number of toolkits at to the constructor, but it may happen at any time during execution. various degrees of abstraction to develop such applications (GWT An entry in a property map does not obey any type discipline. [15], dojo [7], scriptaculous [23], and many more), there is still a The type of the value assigned to a property can change with ev- number of significant applications written directly in JavaScript. ery assignment. Moreover, as long as a property is not yet as- Despite tremendous efforts and progress in IDEs and debug- signed, accessing it returns the value undefined, which is a reg- gers, the development of such native JavaScript applications still ular JavaScript value. This feature makes it very hard for a flow- suffers from numerous problems. One source of these problems insensitive type system to infer a precise type for a JavaScript ob- is the weak, dynamic type system of JavaScript and its prototype- ject: each property is initially undefined, so that the type of a based nature.1 Another host of problems is introduced by differ- property would have to be a union type which always includes an undefined participant. 1 This paper does not address features or problems of the upcoming 4th edi- While such a type system has its merits, its typings yield a very tion (ES4) of the language [9]. Instead, it discusses the JavaScript language crude approximation of the true type of a property. One particular as it is shipped with current browsers, which is roughly in line with the application of such a type system is the test whether the conversion ECMAScript standard [8]. Due to the installed browser base, this language of a field value to some type fails or may give unexpected results. will remain in the focus of web developers for some years to come. The This test raises too many false positives if the type of the property is not sufficiently precise. An essential feature of JavaScript is its prototype mechanism. It implements a delegation mechanism, which simulates some no- tion of single inheritance. Each object has an associated prototype core features of our analysis, in particular the tracking of prototype links, Copyright is held by the author/owner(s). will also be useful for analyzing ES4 programs. FOOL ’09. 24 January 2009, Savannah, Georgia, USA. 2 For example, only a function can be converted to a function and the value ACM. undefined cannot be converted to an object. 1 var proto = { a : ”foo” }; ject has been allocated at the same new expression. If recency 2 function Make () {}; Make.prototype = proto; information is part of a type (an abstraction), then the type (ab- 3 var obj = new Make (); obj.b = ”gnu”; straction) of a recent object can be subject to strong updating. 4 obj.b; // returns ”gnu” • Recency has been discovered and formalized in the context of 5 obj.a; // returns ”foo” abstract interpretation for a first-order imperative language (see Figure 1: Using a prototype in JavaScript. Line 1 creates a new Sec. 2). We show that recency can also be expressed with a object with property a set to "foo" and binds it to variable proto. type system by defining a recency-aware calculus. This calculus Line 2 defines a function Make with no arguments and no body; has objects and first-class functions, thus our work extends the it always returns undefined and sets the prototype property of notion of recency to object-based and higher-order languages. function Make to proto. Line 3 creates a new object using Make as The calculus can be considered a core language of JavaScript. a constructor. Because of Make’s prototype property, the resulting • We prove type soundness for the recency-aware calculus. object obj is internally linked to proto as its prototype object. The remaining lines write and read the b and a properties of obj. Section 2 provides some background information by explaining the ideas underlying recency abstraction. Section 3 informally rephrases recency abstraction in terms of object that is set by the constructor. The prototype object provides a type system and provides motivating examples. The subsequent default values for properties of the original object. If a property is Section 4 contains the formal definitions for the recency-aware not present in the original object, then JavaScript recursively at- calculus (syntax, dynamic semantics, static semantics). tempts to access the property in the prototype object until it hits Next, we establish the metatheory of the recency-aware type an undefined prototype. However, write accesses directly affect the system via a syntactic type soundness proof in Section 5. The tech- original object, not the prototype. niques used are standard but involved because recency-awareness For example, let proto be an object with property a defined to requires a novel way of setting up the operational semantics includ- be "foo" and obj be an object with prototype proto and property 3 ing a non-standard substitution. b set to "gnu", as defined in Fig. 1. Accessing obj.b immediately Section 6 considers extensions, Section 7 discusses related returns the value of the b property whereas obj.a first delegates work, and Section 8 concludes. the property access to the prototype object proto, which has the property a and directly returns its value. 2. Recency Abstraction 1.2 Desiderata for Typing JavaScript Balakrishnan and Reps [3] present an analysis that they call In a dynamically-typed language, each update of a property may “Recency-Abstraction for Heap-Allocated Storage”. Their goal is change the type of the property in the object. A type analysis can to obtain precise abstractions for pointers to objects in executables. keep up with this type change in two ways. Either the analysis is They exploit this information to optimize dynamic dispatch in C++ flow insensitive and assigns a summary type to the property (weak binaries to static function calls where possible. update) or the analysis is flow sensitive and assigns different types Their general framework is abstract interpretation. They start to the property at different points in the program (strong update). off with the standard approach where the analysis associates each The exact choice of summary type can range from a simple top type pointer-typed variable with a set of object creation sites. The ab- to a sophisticated union type. stract interpretation of a property access then yields the least upper The type-based analysis that we are proposing attempts to pro- bound of the abstract values associated with the property at each vide the best of both worlds.
Details
-
File Typepdf
-
Upload Time-
-
Content LanguagesEnglish
-
Upload UserAnonymous/Not logged-in
-
File Pages14 Page
-
File Size-