Testi ting an and Evol olving g TypeScr Script De Declaration on Files with P Progr ogram An Analysi sis s Erik Krogh Kristensen joint work with Anders Møller Π C ENTER FOR A DVANCED S OFTWARE A NALYSIS http://casa.au.dk/
• Microsoft’s extension of JavaScript • Adds optional types • optional type declarations • classes, modules, ... • Static type checking • Compiled to JavaScript 2
Using JavaScript libraries in TypeScript applications • Contains declarations for >4000 libraries • Hand-written, lots of bugs ⇒ mislead type checking and code completion! 3
An example: p2.js JavaScript library implementation TypeScript type declaration function Constraint(...) { class Constraint { /** constructor (...); * Equations to be solved in equeations : Equation[]; * this constraint ... * } * @property equations * @type {Array} */ this .equations = []; ... } ... 4 4
Another example: d3.js JavaScript library implementation TypeScript type declaration 5
Three research challenges 1. How to detect mismatches between library implementations and type declarations ? 2. How to infer type declarations for libraries ? 3. How to evolve type declarations, as the library code evolves ? 6
Three research challenges 1. How to detect mismatches between 1. How to detect mismatches between library implementations and type declarations ? library implementations and type declarations ? 2. How to infer type declarations for libraries ? Exi xisting approaches are re limited ed 3. How to evolve type declarations, • TSCheck (Feldthaus and Møller 2014) : Based on static analysis, imprecise as the library code evolves ? • TPD (Williams et al. 2017) : Require existing unit tests 7
TSTest – feedback-directed random testing TST [Type Test Scripts for TypeScript Testing, Kristensen & Møller, OOPSLA 2017] Based on automated testing (Randoop: Feedback-directed random test generation, Pacheco, Lahiri, Ernst, and Ball, ICSE'07) JavaScript library implementation TypeScript type declaration var Store = { declare var Store : { makeItem: function (n) { makeItem(n: number ): Item return { } print: function () { return n; interface Item { } print(): string } } } } How to adapt Randoop-style testing from Java to TypeScript? 8 (structural typing, higher-order functions, generics, …)
TST TSTest – how it works JavaScript TypeScript implementation declaration Type Test Script JavaScript interpreter Mismatches
TSTest – experimental results • 54 benchmarks • Running each type test script for 10 seconds results in 2804 found mismatches (many with same root cause) • Mismatches found in 49/54 benchmarks • Finds many mismatches that are missed by previous work (TSCheck) 10
Are the mismatches benign or serious? • Sampled 124 random mismatches benign 14 • No false positives error strict nulls 63 47
Benign gn? redux.d.ts e xp e xpor t or t f u f unc nc t i o t i on n bi ndAc t i onCr e a t or s <A e xt e nd e xt e nds s Ac t i onCr e a t or <a ny a ny>> ( a c t i onCr e a t or : A) : A; redux.js f unc t i f un c t i on on bi ndAc t i onCr e a t or s ( c r e a t or s ) { va r va r r e s ul t = {}; f or ( va r f or va r ke y i n i n c r e a t or s ) { va r va r c r e a t or = c r e a t or s [ ke y] ; i f ( t ype o i f t ype of c r e a t or === ' f unc ' f unc t i o t i on' n' ) { r e s ul t [ ke y] = bi ndAc t i onCr e a t or ( c r e a t or , di s pa t c h) ; } } r e t ur n r e t ur n r e s ul t ; }
Three research challenges 1. How to detect mismatches between library implementations and type declarations ? 2. How to infer type declarations for libraries ? 3. How to evolve type declarations, as the library code evolves ? 13
The Holy Grail Infer the same declaration that an expert human would write f unc t i on f unc t i on ge t ( obj , k) { r e t ur n r e t ur n obj [ k] ; } ? f unc t c t i on ge t ( obj : num be r [ ] , k: num be r ) : num be r f unc t c t i on ge t <T>( obj : T[ ] , k: num be r ) : T f unc t c t i on ge t <T>( obj : {[ i : s t r i n i ng] : T}, k: s t r i ng) : T f unc t c t i on ge t <T, K e xt e nds ke yof T>( obj : T, k: K) : T[ K] ; 14
TS TSInfer – a declaration file inference tool [FASE 2017] • Dynamically analyze library initialization Snapshot of heap after loading • Extract modules, classes, fields • Static analysis to infer function signatures 15
Static analysis in TSInfer • TSInfer must infer parameter types and return types! Also for methods that are never called within the library • Unification-based too imprecise • Instead: upper-bound and lower-bound à la Pottier A framework for type inference with subtyping, François Pottier, ICFP’98 • Unsound, flow-insensitive, context-insensitive • Analyze entire library once To get information about how the library uses itself 16
Upper-bound and lower-bound dataflow analysis à la Pottier x = ne w C( ) ; • Forward dataflow analysis (lower-bound) . . . “ what values may flow in? ” f oo( x) ; f unc t i on f oo( a ) { • Backward dataflow analysis (upper-bound) . . . “ how may the values be used? ” b = a . ne xt ; . . . } Both kinds of information give useful hints to types, when analyzing libraries without the applications! 17
Example output from running TSInfer on PixiJS 2.2 Our goal is to get close to what a human would write e xpor or t c l a s a s s Spr i t e e xt e n e nds PI XI . Cont a i ne r { c ons t r uc t or ( t e xt ur e : PI XI . Te xt ur e ) ; s t a t i c f r om Fr a m e : ( f r a m e I d: s t r i n i ng | num be be r ) => PI XI . Spr i t e ; s t a t i c f r om I m a ge : ( i m a ge I d: s t r i n i ng, c r os s or i gi n: a ny, s c a l e M ode : a ny) => PI XI . Spr i t e ; _he i ght : num be be r ; private ?: boolean _wi dt h: num be be r ; private ?: number a nc hor : PI XI . Poi nt ; bl e ndM ode : num be r ; onTe xt ur e Upda t e : ( ) => voi d; private s e t Te xt ur e : ( t e xt ur e : PI XI . Te xt ur e ) => voi d; s ha de r : a ny; PIXI.Shader t e xt ur e : PI XI . Te xt ur e ; t i nt : num be r ; } 18
Three research challenges 1. How to detect mismatches between library implementations and type declarations ? 2. How to infer type declarations for libraries ? 3. How to evolve type declarations, as the library code evolves ? 19
TSEv Evolve – a tool for fixing out-of-date declaration files old.d.ts old.js new.js TSInfer TSInfer old.gen.d.ts new.gen.d.ts Compare First naive approach Our approach Too many false positives, due to List of changes imprecise static analysis • intentional mismatches Filter • Filtered list of changes 20
TSEvolve: pull requests • Updated type declaration files for 6 different libraries • From 30 to 516 lines patched • No prior experience with the libraries • Done in about 1 day of work 21
Conclusion • Optional types have become popular • Need to interact with untyped libraries • Static/dynamic program analysis to the rescue! • TSTest [OOPSLA 2017] • TSInfer & TSEvolve [FASE 2017] Π C ENTER FOR A DVANCED S OFTWARE A NALYSIS http://casa.au.dk/ 22
Recommend
More recommend