Dependent
This presentation is the property of its rightful owner.
Sponsored Links
1 / 90

Dependent Types for JavaScript PowerPoint PPT Presentation


  • 66 Views
  • Uploaded on
  • Presentation posted in: General

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 ;.

Download Presentation

Dependent Types for JavaScript

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


Dependent types for javascript

DependentTypes for JavaScript

Ravi ChughRanjitJhala

University of California, San Diego

David Herman

Mozilla Research


Dependent types for javascript

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


Dependent types for javascript

DependentTypes for JavaScript

Why

?

Isn’t the Language Terrible?


Dependent types for javascript

JavaScript

scope manipulation

implicit global object

var lifting

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


Dependent types for javascript

JavaScript

scope manipulation

prototypes

objects

implicit global object

lambdas

type-tests

var lifting

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


Dependent types for javascript

JavaScript

scope manipulation

“The Good Parts”

prototypes

objects

implicit global object

lambdas

type-tests

var lifting

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


Dependent types for javascript

JavaScript

“The Good Parts”

Our Approach

Key Idea:

Use Logic!

PriorTypeSystems


Dependent types for javascript

JavaScript

“The Good Parts”

DJS

Dependent JavaScript


Outline

Outline

  • Motivation

  • Our Approach: Logic!

  • Evaluation


Dependent types for javascript

typeof true // “boolean”

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

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


Dependent types for javascript

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”}


Dependent types for javascript

  • Tag-Tests

  • Duck Typing

  • Mutable Objects

  • Prototypes

  • Arrays


Dependent types for javascript

  • Tag-Tests

  • Duck Typing

  • Mutable Objects

  • Prototypes

  • Arrays

varnegate = function(x) {

if (typeofx==“boolean”)

return !x;

else

return0 - x;

}

!true

// false

true

negate()


Dependent types for javascript

  • Tag-Tests

  • Duck Typing

  • Mutable Objects

  • Prototypes

  • Arrays

varnegate = function(x) {

if (typeofx==“boolean”)

return !x;

else

return0 - x;

}

0 - 2

// -2

2

negate()


Dependent types for javascript

  • Tag-Tests

  • Duck Typing

  • Mutable Objects

  • Prototypes

  • Arrays

varnegate = function(x) {

if (typeofx==“boolean”)

return !x;

else

return0 - x;

}

  • WAT?!

0 - []

// 0

[]

negate()


Dependent types for javascript

  • 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


Dependent types for javascript

  • 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


Dependent types for javascript

  • 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


Dependent types for javascript

  • 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


Dependent types for javascript

  • Tag-Tests

  • Duck Typing

  • Mutable Objects

  • Prototypes

  • Arrays

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

varnegate = function(x) {

if (typeofx==“boolean”)

return !x;

else

return0 - x;

}


Dependent types for javascript

  • 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


Dependent types for javascript

  • 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


Dependent types for javascript

  • Tag-Tests

  • Duck Typing

  • Mutable Objects

  • Prototypes

  • Arrays

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

varnegate = function(x) {

if (typeofx==“boolean”)

return !x;

else

return0 - x;

}


Dependent types for javascript

  • 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


Dependent types for javascript

  • Tag-Tests

  • Duck Typing

  • Mutable Objects

  • Prototypes

  • Arrays

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

Programmer choosesdegree of precisionin specification


Dependent types for javascript

  • 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!”;


Dependent types for javascript

  • 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!”;


Dependent types for javascript

  • 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!”;


Dependent types for javascript

  • 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!”;


Dependent types for javascript

  • 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!”;


Dependent types for javascript

  • 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


Dependent types for javascript

  • 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


Dependent types for javascript

  • Tag-Tests

  • Duck Typing

  • Mutable Objects

  • Prototypes

  • Arrays


Dependent types for javascript

  • Tag-Tests

  • Duck Typing

  • Mutable Objects

  • Prototypes

  • Arrays

  • Typical“Dynamic”

  • Features


Dependent types for javascript

  • Tag-Tests

  • Duck Typing

  • Mutable Objects

  • Prototypes

  • Arrays

  • Typical“Dynamic”

  • Features

  • JavaScript

  • tl;dr

  • Harder, butDJS handles them


Dependent types for javascript

  • Tag-Tests

  • Duck Typing

  • Mutable Objects

  • Prototypes

  • Arrays

child

  • Upon construction, each object links to a prototype object

parent

grandpa

...

null


Dependent types for javascript

  • 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


Dependent types for javascript

  • 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


Dependent types for javascript

  • 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


Dependent types for javascript

  • 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


Dependent types for javascript

  • 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


Dependent types for javascript

  • 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


Dependent types for javascript

  • 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


Dependent types for javascript

  • Tag-Tests

  • Duck Typing

  • Mutable Objects

  • Prototypes

  • Arrays

  • Prototype Chain Unrolling

  • Key Idea:

  • Reduce prototypesemantics to decidable theory of arrays


Dependent types for javascript

  • Tag-Tests

  • Duck Typing

  • Mutable Objects

  • Prototypes

  • Arrays

  • A finite tuple…

varnums=[0,1,2]

while (…){

nums[nums.length] = 17

}

  • … extended to unbounded collection


Dependent types for javascript

  • 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”


Dependent types for javascript

  • 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


Dependent types for javascript

  • 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))}


Dependent types for javascript

  • 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|…}


Dependent types for javascript

  • Tag-Tests

  • Duck Typing

  • Mutable Objects

  • Prototypes

  • Arrays

DJS handlesotherquirks:

  • Speciallength property

  • Array.prototype

  • Non-integer keys


Dependent types for javascript

  • 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.


Dependent types for javascript

JavaScript

“The Good Parts”

DJS

Types via Logic!


Thanks

Thanks!

D

::

ravichugh.com/djs

PS: I’m on the Job Market


Extra slides

Extra Slides


Dependent types for javascript

  • 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

}


Dependent types for javascript

  • 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()


Dependent types for javascript

  • 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()


Dependent types for javascript

  • 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()


Dependent types for javascript

  • 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()


Dependent types for javascript

  • 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!”;


Dependent types for javascript

  • 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


Dependent types for javascript

  • 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


  • Login