slide1
Download
Skip this Video
Download Presentation
Dependent Types for JavaScript

Loading in 2 Seconds...

play fullscreen
1 / 90

Dependent Types for JavaScript - PowerPoint PPT Presentation


  • 88 Views
  • Uploaded on

Dependent Types for JavaScript. Ravi Chugh Ranjit Jhala. University of California, San Diego. David Herman. Mozilla Research. Dependent Types for JavaScript. Why. ?. Pervasive Used at Massive Scale. Why Add Types?. var x = {}; x.f ; x.f.f ;.

loader
I am the owner, or an agent authorized to act on behalf of the owner, of the copyrighted work described.
capcha
Download Presentation

PowerPoint Slideshow about ' Dependent Types for JavaScript' - pravat


An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript
slide1

DependentTypes for JavaScript

Ravi ChughRanjitJhala

University of California, San Diego

David Herman

Mozilla Research

slide2

DependentTypes for JavaScript

Why

?

Pervasive

Used at Massive Scale

why add types
Why Add Types?

var x = {};

x.f;

x.f.f;

produces undefined rather than error…

… but this raises TypeError

why add types1
Why Add Types?

var x = {};

x.f;

x.f.f;

There Are Run-time Errorsreading from undefined, applying non-function values, …

Worse: Browsers Hide Them!

why add types2
Why Add Types?

Prevent Errors

Prevent the Unexpected

okay but who cares
Okay, But Who Cares?

ProgrammersJSLint, Closure Compiler, TypeScript, Dart

Browser VendorsCompete based on performance, security, reliability

Standards CommitteesActively evolving JavaScript and Web standards

slide7

DependentTypes for JavaScript

Why

?

Isn’t the Language Terrible?

slide8

JavaScript

scope manipulation

implicit global object

var lifting

‘,,,’ == new Array(4)

slide9

JavaScript

scope manipulation

prototypes

objects

implicit global object

lambdas

type-tests

var lifting

‘,,,’ == new Array(4)

slide10

JavaScript

scope manipulation

“The Good Parts”

prototypes

objects

implicit global object

lambdas

type-tests

var lifting

‘,,,’ == new Array(4)

slide11

JavaScript

“The Good Parts”

Our Approach

Key Idea:

Use Logic!

PriorTypeSystems

slide12

JavaScript

“The Good Parts”

DJS

Dependent JavaScript

outline
Outline
  • Motivation
  • Our Approach: Logic!
  • Evaluation
slide14

typeof true // “boolean”

typeof 0.1 // “number”typeof 0 // “number”

typeof {}// “object”typeof []// “object”typeof null// “object”

slide15

typeof returns run-time “tags”

Tags are very coarse-grained types

“undefined”

  • “boolean”
  • “string”
  • “number”
  • “object”
  • “function”
refinement types
Refinement Types

NumOrBool 

{x|p}

Num

Int

Any 

{v|tag(v)=“number”∨tag(v)=“boolean”}

{n|tag(n)=“number”}

{i|tag(i)=“number”integer(i)}

{x|true}

“set of values x s.t. formula p is true”

refinement types1
Refinement Types

NumOrBool 

Num

Int

Any 

{v|tag(v)=“number”∨tag(v)=“boolean”}

{n|tag(n)=“number”}

{i|tag(i)=“number”integer(i)}

{x|true}

  • Syntactic Sugarfor Common Types
refinement types2
Refinement Types

3::

{n|n=3}

3::

{n|n>0}

3::

{n|tag(n)=“number”integer(n)}

3::

{n|tag(n)=“number”}

refinement types3
Refinement Types
  • Subtyping is Implication

<:

{n|n=3}

<:

{n|n>0}

<:

{n|tag(n)=“number”integer(n)}

<:

{n|tag(n)=“number”}

refinement types4
Refinement Types
  • Subtyping is Implication

{n|n=3}

{n|n>0}

{n|tag(n)=“number”integer(n)}

{n|tag(n)=“number”}

slide21

Tag-Tests

  • Duck Typing
  • Mutable Objects
  • Prototypes
  • Arrays
slide22

Tag-Tests

  • Duck Typing
  • Mutable Objects
  • Prototypes
  • Arrays

varnegate = function(x) {

if (typeofx==“boolean”)

return !x;

else

return0 - x;

}

!true

// false

true

negate()

slide23

Tag-Tests

  • Duck Typing
  • Mutable Objects
  • Prototypes
  • Arrays

varnegate = function(x) {

if (typeofx==“boolean”)

return !x;

else

return0 - x;

}

0 - 2

// -2

2

negate()

slide24

Tag-Tests

  • Duck Typing
  • Mutable Objects
  • Prototypes
  • Arrays

varnegate = function(x) {

if (typeofx==“boolean”)

return !x;

else

return0 - x;

}

  • WAT?!

0 - []

// 0

[]

negate()

slide25

Tag-Tests

  • Duck Typing
  • Mutable Objects
  • Prototypes
  • Arrays

varnegate = function(x) {

if (typeofx==“boolean”)

return !x;

else

return0 - x;

}

  • Use types to prevent implicit coercion

(-) :: (Num,Num)Num

slide26

Tag-Tests

  • Duck Typing
  • Mutable Objects
  • Prototypes
  • Arrays

//: negate :: (x:Any)Any

varnegate = function(x) {

if (typeofx==“boolean”)

return !x;

else

return0 - x;

}

  • Function type annotation inside comments
slide27

Tag-Tests

  • Duck Typing
  • Mutable Objects
  • Prototypes
  • Arrays

//: negate :: (x:Any)Any

varnegate = function(x) {

if (typeofx==“boolean”)

return !x;

else

return0 - x;

}

x is boolean...

so negationis well-typed

  • DJS is Path Sensitive
slide28

Tag-Tests

  • Duck Typing
  • Mutable Objects
  • Prototypes
  • Arrays

//: negate :: (x:Any)Any

varnegate = function(x) {

if (typeofx==“boolean”)

return !x;

else

return0 - x;

}

x is arbitrarynon-boolean value…

so DJS signals error!

  • DJS is Path Sensitive
slide29

Tag-Tests

  • Duck Typing
  • Mutable Objects
  • Prototypes
  • Arrays

//: negate :: (x:NumOrBool)Any

varnegate = function(x) {

if (typeofx==“boolean”)

return !x;

else

return0 - x;

}

slide30

Tag-Tests

  • Duck Typing
  • Mutable Objects
  • Prototypes
  • Arrays

//: negate :: (x:NumOrBool)Any

varnegate = function(x) {

if (typeofx==“boolean”)

return !x;

else

return0 - x;

}

  • this time,x is a number…

so subtractionis well-typed

slide31

Tag-Tests

  • Duck Typing
  • Mutable Objects
  • Prototypes
  • Arrays

//: negate :: (x:NumOrBool)Any

varnegate = function(x) {

if (typeofx==“boolean”)

return !x;

else

return0 - x;

}

  • but returntype is imprecise
slide32

Tag-Tests

  • Duck Typing
  • Mutable Objects
  • Prototypes
  • Arrays

//: negate :: (x:NumOrBool)NumOrBool

varnegate = function(x) {

if (typeofx==“boolean”)

return !x;

else

return0 - x;

}

slide33

Tag-Tests

  • Duck Typing
  • Mutable Objects
  • Prototypes
  • Arrays

/*: negate :: (x:NumOrBool){v|tag(v)=tag(x)} */

varnegate = function(x) {

if (typeofx==“boolean”)

return !x;

else

return0 - x;

}

  • output type depends on input value
slide34

Tag-Tests

  • Duck Typing
  • Mutable Objects
  • Prototypes
  • Arrays

/*: negate :: (x:NumOrBool){v|tag(v)=tag(x)} */

Programmer choosesdegree of precisionin specification

slide35

Tag-Tests

  • Duck Typing
  • Mutable Objects
  • Prototypes
  • Arrays

What is “Duck Typing”?

if (duck.quack)

return“Duck says ” + duck.quack();

else

return“This duck can’t quack!”;

slide36

Tag-Tests

  • Duck Typing
  • Mutable Objects
  • Prototypes
  • Arrays

What is “Duck Typing”?

(+) :: (Num,Num)Num

(+) :: (Str,Str)Str

if (duck.quack)

return“Duck says ” + duck.quack();

else

return“This duck can’t quack!”;

slide37

Tag-Tests

  • Duck Typing
  • Mutable Objects
  • Prototypes
  • Arrays

What is “Duck Typing”?

  • Can dynamically testthe presence of a methodbut not its type

if (duck.quack)

return“Duck says ” + duck.quack();

else

return“This duck can’t quack!”;

slide38

Tag-Tests

  • Duck Typing
  • Mutable Objects
  • Prototypes
  • Arrays

{d|tag(d)=“Dict”∧

{v|has(d,“quack”) 

{v|sel(d,“quack”)::UnitStr}

  • Operators from McCarthy theory of arrays

if (duck.quack)

return“Duck says ” + duck.quack();

else

return“This duck can’t quack!”;

slide39

Tag-Tests

  • Duck Typing
  • Mutable Objects
  • Prototypes
  • Arrays

{d|tag(d)=“Dict”∧

{v|has(d,“quack”) 

{v|sel(d,“quack”)::UnitStr}

  • Call produces Str, so concat well-typed

if (duck.quack)

return“Duck says ” + duck.quack();

else

return“This duck can’t quack!”;

slide40

Tag-Tests

  • Duck Typing
  • Mutable Objects
  • Prototypes
  • Arrays
  • DJS is FlowSensitive

x1:{d|d=upd(x0,“f”,7)}

x0:Empty

var x = {};

x.f = 7;

x.f + 2;

  • McCarthy operator
  • DJS verifies that x.f is definitely a number
slide41

Tag-Tests

  • Duck Typing
  • Mutable Objects
  • Prototypes
  • Arrays
  • DJS is FlowSensitive

x1:{d|d=upd(x0,“f”,7)}

x0:Empty

var x = {};

x.f = 7;

x.f + 2;

Strong updates to singleton objects

Weak updates to collections of objects

slide42

Tag-Tests

  • Duck Typing
  • Mutable Objects
  • Prototypes
  • Arrays
slide43

Tag-Tests

  • Duck Typing
  • Mutable Objects
  • Prototypes
  • Arrays
  • Typical“Dynamic”
  • Features
slide44

Tag-Tests

  • Duck Typing
  • Mutable Objects
  • Prototypes
  • Arrays
  • Typical“Dynamic”
  • Features
  • JavaScript
  • tl;dr
  • Harder, butDJS handles them
slide45

Tag-Tests

  • Duck Typing
  • Mutable Objects
  • Prototypes
  • Arrays

child

  • Upon construction, each object links to a prototype object

parent

grandpa

...

null

slide46

Tag-Tests

  • Duck Typing
  • Mutable Objects
  • Prototypes
  • Arrays
  • Semantics of Key Lookup

var k = “first”; child[k];

child

If child contains k, then

Read k from child

Else if parent contains k, then

Read k from parent

Else if grandpa contains k, then

Read k from grandpa

Else if …

Else

Return undefined

parent

grandpa

...

null

slide47

Tag-Tests

  • Duck Typing
  • Mutable Objects
  • Prototypes
  • Arrays
  • Semantics of Key Lookup

var k = “first”; child[k];

child

If child contains k, then

Read k from child

Else if parent contains k, then

Read k from parent

Else if grandpa contains k, then

Read k from grandpa

Else if …

Else

Return undefined

{v|ifhas(child,k) then

{v|ifv=sel(child,k)

parent

grandpa

H(Rest of Heap)

...

null

slide48

Tag-Tests

  • Duck Typing
  • Mutable Objects
  • Prototypes
  • Arrays
  • Semantics of Key Lookup

var k = “first”; child[k];

child

If child contains k, then

Read k from child

Else if parent contains k, then

Read k from parent

Else if grandpa contains k, then

Read k from grandpa

Else if …

Else

Return undefined

{v|ifhas(child,k) then

{v|ifv=sel(child,k)

{v|else ifhas(parent,k) then

{v|ifv=sel(parent,k)

parent

grandpa

H(Rest of Heap)

...

null

slide49

Tag-Tests

  • Duck Typing
  • Mutable Objects
  • Prototypes
  • Arrays
  • Semantics of Key Lookup

var k = “first”; child[k];

child

If child contains k, then

Read k from child

Else if parent contains k, then

Read k from parent

Else if grandpa contains k, then

Read k from grandpa

Else if …

Else

Return undefined

{v|ifhas(child,k) then

{v|ifv=sel(child,k)

{v|else ifhas(parent,k) then

{v|ifv=sel(parent,k)

parent

grandpa

???

H(Rest of Heap)

...

null

slide50

Tag-Tests

  • Duck Typing
  • Mutable Objects
  • Prototypes
  • Arrays
  • Semantics of Key Lookup

var k = “first”; child[k];

child

{v|ifhas(child,k) then

{v|ifv=sel(child,k)

{v|else ifhas(parent,k) then

{v|ifv=sel(parent,k)

{v|else

{v|ifv=HeapSel(H,grandpa,k))}

parent

grandpa

???

  • Abstract predicateto summarize theunknown portionof the prototype chain

H(Rest of Heap)

...

null

slide51

Tag-Tests

  • Duck Typing
  • Mutable Objects
  • Prototypes
  • Arrays

var k = “first”; child[k];

child

{ “first” : “John” }

{v|ifhas(child,k) then

{v|ifv=sel(child,k)

{v|else ifhas(parent,k) then

{v|ifv=sel(parent,k)

{v|else

{v|ifv=HeapSel(H,grandpa,k))}

parent

grandpa

{ “first” : “Ida”, “last” : “McCarthy” }

???

<:

{v|v=“John”}

H(Rest of Heap)

...

null

slide52

Tag-Tests

  • Duck Typing
  • Mutable Objects
  • Prototypes
  • Arrays

var k = “last”; child[k];

child

{ “first” : “John” }

{v|ifhas(child,k) then

{v|ifv=sel(child,k)

{v|else ifhas(parent,k) then

{v|ifv=sel(parent,k)

{v|else

{v|ifv=HeapSel(H,grandpa,k))}

parent

grandpa

{ “first” : “Ida”, “last” : “McCarthy” }

???

<:

{v|v=“McCarthy”}

H(Rest of Heap)

...

null

slide53

Tag-Tests

  • Duck Typing
  • Mutable Objects
  • Prototypes
  • Arrays
  • Prototype Chain Unrolling
  • Key Idea:
  • Reduce prototypesemantics to decidable theory of arrays
slide54

Tag-Tests

  • Duck Typing
  • Mutable Objects
  • Prototypes
  • Arrays
  • A finite tuple…

varnums=[0,1,2]

while (…){

nums[nums.length] = 17

}

  • … extended to unbounded collection
slide55

Tag-Tests

  • Duck Typing
  • Mutable Objects
  • Prototypes
  • Arrays

varnums=[0,1,2]

while (…){

nums[nums.length] = 17

}

delete nums[1]

for(i=0; i<nums.length; i++)

sum += nums[i]

  • A “hole” in the array
  • Missing element within “length”
slide56

Tag-Tests

  • Duck Typing
  • Mutable Objects
  • Prototypes
  • Arrays

Track types, “packedness,” and lengthof arrays where possible

{a|a::Arr(T)

{a|packed(a)

{a|len(a)=10}

  • T?
  • -1
  • 0
  • T?
  • 1
  • T?
  • 2
  • T?
  • T?
  • len(a)
  • T?

T?{x|T(x)x=undefined}

X{x|x=undefined}

  • X
  • T
  • T
  • T
  • T
  • X
slide57

Tag-Tests

  • Duck Typing
  • Mutable Objects
  • Prototypes
  • Arrays

Encode tuplesas arrays

vartup= [17, “cacti”]

{a|a::Arr(Any)

{a|packed(a)len(a)=2

{a|Int(sel(a,0))

{a|Str(sel(a,1))}

slide58

Tag-Tests

  • Duck Typing
  • Mutable Objects
  • Prototypes
  • Arrays

vartup= [17, “cacti”]

tup[tup.length] = true

{a|a::Arr(Any)

{a|packed(a)len(a)=3

{a|…}

slide59

Tag-Tests

  • Duck Typing
  • Mutable Objects
  • Prototypes
  • Arrays

DJS handlesotherquirks:

  • Speciallength property
  • Array.prototype
  • Non-integer keys
slide60

Tag-Tests

  • Duck Typing
  • Mutable Objects
  • Prototypes
  • Arrays
what about eval
What About eval?

Old Types

eval(“…”);

  • Arbitrary code loading
what about eval1
What About eval?

Old Types

New Types

eval(“…”);

//: #assume

New Types

  • “Contract Checking” at Run-timeaka “Gradual Typing”
recap of djs techniques
Recap of DJS Techniques
  • Logic!
  • Path and Flow Sensitivity
  • Prototype Unrolling
  • Syntactic Sugar
outline1
Outline
  • Motivation
  • Our Approach: Logic!
  • Evaluation
13 benchmarks
13 Benchmarks

arrays

“The Good Parts”

prototypes

objects

lambdas

type-tests

13 benchmarks1
13 Benchmarks

arrays

“The Good Parts”

prototypes

objects

lambdas

type-tests

13 benchmarks2
13 Benchmarks

arrays

“The Good Parts”

prototypes

objects

lambdas

type-tests

  • Four inheritance patterns fromCrockford’s JS: The Good Parts
13 benchmarks3
13 Benchmarks

arrays

“The Good Parts”

prototypes

objects

lambdas

type-tests

  • Array-manipulating examplesfrom SunSpider
13 benchmarks4
13 Benchmarks

arrays

“The Good Parts”

prototypes

objects

lambdas

type-tests

  • typeOf() function to replace typeoffrom Closure Compiler
13 benchmarks5
13 Benchmarks

arrays

“The Good Parts”

prototypes

objects

lambdas

type-tests

  • Well-typed programsdon’t have run-time errors
implementation
Implementation

DJSProgram

DesugarerBased on Guha et al.[ECOOP 2010]

JavaScript  λ-Calculus + References + Prototypes

Desugared

Program

implementation1
Implementation

DJSProgram

  • Programmer Chooses Warnings or Errors
  • Local Type Inference
  • Subtyping w/o Z3 If Possible

DesugarerBased on Guha et al.[ECOOP 2010]

Z3 SMTSolver

Type

Checker

Desugared

Program

annotation burden
Annotation Burden

(Improved since paper)

  • += ~300 LOC to start
  • += ~100 LOC annotations
  • =+ ~400 LOC total
  • 33% Annotation Overhead
  • Common Cases Simplified via
  • Syntactic Sugar and Local Type Inference
performance
Performance

(Improved since paper)

  • Total benchmark suite:
  • ~10 seconds
  • ~1100 Z3 queries
  • 11/13 benchmarks in 0-1 s
  • Common Cases Fast via
  • Syntactic Reasoning When Possible
future work
Future Work

Syntax, Inference, Performance

Larger Examples

Type Checker in JS; Run in Browser

IDE Support for Refactoring, etc.

slide76

JavaScript

“The Good Parts”

DJS

Types via Logic!

thanks
Thanks!

D

::

ravichugh.com/djs

PS: I’m on the Job Market

slide79

DependentJavaScript[this paper]

  • System D[POPL ’12]

“Usability”

refinement types

F≤

∨, ∧

+ nested refinements

DJS

occurrence types

Coq

dependent types

syntactic types

JS

Expressivity

system d popl 2012
System D [POPL 2012]

+ Types for JS Primitives

+ Strong Updates

+ Quirky JS Arrays

+ Prototype Inheritance

Dependent JavaScript (DJS)

function types and objects

{p}{v|p}

Function Types and Objects

/*: x:NumOrBool {iteNum(x) Num(v) Bool(v)} */

function negate(x) {

x=(typeofx==“number”)? 0 – x : !x

returnx

}

/*: x:Any{vifffalsy(x)} */

function negate(x) {

x=(typeofx==“number”)? 0 – x : !x

returnx

}

function types and objects1
Function Types and Objects
  • x:T1/H1T2/H2

input type

output heap

input heap

output type

ObjHas(d,k,H,d’)has(d,k)HeapHas(H,d’,k)

/*: x:Ref / [x |-> d:Dict |> x.pro]

{viffObjHas(d,”f”,curHeap,x.pro)} / sameHeap */

function hasF(x) {

return“f”in x

}

function types and objects2
Function Types and Objects
  • x:T1/H1T2/H2

input type

output heap

input heap

output type

ObjSel(d,k,H,d’)

itehas(d,k) sel(d,k) HeapSel(H,d’,k)

/*: x:Ref / [x |-> d:Dict |> x.pro]

{v=ObjSel(d,”f”,curHeap,x.pro)} / sameHeap */

function readF(x) {

returnx.f

}

slide84

Tag-Tests

  • Duck Typing
  • Mutable Objects
  • Prototypes
  • Arrays

varnegate = function(x) {

if (typeofx==“boolean”)

return !x;

else

return0 - x;

}

  • Whoa, but perhaps okay…

0 - “2”

// -2

“2”

negate()

slide85

Tag-Tests

  • Duck Typing
  • Mutable Objects
  • Prototypes
  • Arrays

varnegate = function(x) {

if (typeofx==“boolean”)

return !x;

else

return0 - x;

}

0 - undefined

// NaN

  • Error would be nicer, but okay…

undefined

negate()

slide86

Tag-Tests

  • Duck Typing
  • Mutable Objects
  • Prototypes
  • Arrays

varnegate = function(x) {

if (typeofx==“boolean”)

return !x;

else

return0 - x;

}

  • Seems about right…

0 - {}

// NaN

{}

negate()

slide87

Tag-Tests

  • Duck Typing
  • Mutable Objects
  • Prototypes
  • Arrays

negate has good intentions

But too many corner cases in JS semantics!

varnegate = function(x) {

if (typeofx==“boolean”)

return !x;

else

return0 - x;

}

  • WAT?!

0 - []

// 0

[]

negate()

slide88

Tag-Tests

  • Duck Typing
  • Mutable Objects
  • Prototypes
  • Arrays

{d|tag(d)=“Dict”∧

{v|has(d,“quack”) 

{v|sel(d,“quack”)::Unit Str}

  • Function types nested inside refinements[POPL 2012]

if (duck.quack)

return“Duck says ” + duck.quack();

else

return“This duck can’t quack!”;

slide89

Tag-Tests

  • Duck Typing
  • Mutable Objects
  • Prototypes
  • Arrays

var x = {};

x.f;

x.f.f;

  • Programmer configures DJS to report either warnings or errors for:
  • 1)Possible unbound keys
slide90

Tag-Tests

  • Duck Typing
  • Mutable Objects
  • Prototypes
  • Arrays

var x = {};

x.f;

x.f.f;

  • Programmer configures DJS to report either warnings or errors for:
  • 1)Possible unbound keys
  • 2) Possible run-time errors
ad