libraries as languages: typechecking jquery programs

30
LIBRARIES AS LANGUAGES: TYPECHECKING JQUERY PROGRAMS Benjamin Lerner Liam Elberty Jincheng Li Shriram Krishnamurthi

Upload: moya

Post on 22-Mar-2016

37 views

Category:

Documents


2 download

DESCRIPTION

Libraries as Languages: Typechecking jQuery Programs. Benjamin Lerner Liam Elberty Jincheng Li Shriram Krishnamurthi. Programming Web Pages in JavaScript. Myth 1 : HTML documents are trees of pointers Reality: much more tightly linked. body. div. div. p. div. p. span. span. - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: Libraries as Languages: Typechecking jQuery  Programs

LIBRARIES AS LANGUAGES:TYPECHECKING JQUERY PROGRAMSBenjamin LernerLiam ElbertyJincheng LiShriram Krishnamurthi

Page 2: Libraries as Languages: Typechecking jQuery  Programs

Programming Web Pages in JavaScript

Myth 1: HTML documents are trees of pointers

• Reality: much more tightly linked

body

div div

p div

p

spanspan

Page 3: Libraries as Languages: Typechecking jQuery  Programs

Programming Web Pages in JavaScript

Myth 2: just walk pointers from node to node

function findAllP() { results = []; q = [body]; while ((cur = q.pop()) !== null) { if (cur.elementName == “p”) results.push(cur); q.push(cur.childNodes); }}

body

div div

p div

p

spanspan

Assembly

language for

trees

Page 4: Libraries as Languages: Typechecking jQuery  Programs

Programming Web Pages with Query Languages

• We have higher-level languages to express these ideas!

– Any intuitions you have from XQuery, CSS, XDuce/CDuce are appropriate here…

Page 5: Libraries as Languages: Typechecking jQuery  Programs

Programming with jQuery

• jQuery is a library for tree programming

• E.g. “Find all <p> nodes and turn them green”$(“p”).css(“color”, “green”)

Domain-specific language

Page 6: Libraries as Languages: Typechecking jQuery  Programs

What does this jQuery code do?

$(“.tweet span”).next().html()

Depends on the shape of the page!

Page 7: Libraries as Languages: Typechecking jQuery  Programs

$(“.tweet span”).next().html()

<Body>

<Div class=“main-content”>

<Div class=“sidebar”>

<Div class=“header-bar”>

<Div class=“stream”><Div class=“tweet”>

<Div class=“tweet”> …

<Span class=“Author”> Ben<Span class=“Time”> Now<Span class=“Content”> Hi

Page 8: Libraries as Languages: Typechecking jQuery  Programs

$(“.tweet span”).next().html()

<Body>

<Div class=“main-content”>

<Div class=“sidebar”>

<Div class=“header-bar”>

<Div class=“stream”><Div class=“tweet”>

<Div class=“tweet”> …

<Span class=“Author”> Ben<Span class=“Time”> Now<Span class=“Content”> Hi

Page 9: Libraries as Languages: Typechecking jQuery  Programs

$(“.tweet span”).next().html()

<Body>

<Div class=“main-content”>

<Div class=“sidebar”>

<Div class=“header-bar”>

<Div class=“stream”><Div class=“tweet”>

<Div class=“tweet”> …

<Span class=“Author”> Ben<Span class=“Time”> Now<Span class=“Content”> Hi

Page 10: Libraries as Languages: Typechecking jQuery  Programs

$(“.tweet span”).next().html()

<Body>

<Div class=“main-content”>

<Div class=“sidebar”>

<Div class=“header-bar”>

<Div class=“stream”><Div class=“tweet”>

<Div class=“tweet”> …

<Span class=“Author”> Ben<Span class=“Time”> Now<Span class=“Content”> Hi

Page 11: Libraries as Languages: Typechecking jQuery  Programs

$(“.tweet span”).next().html()

<Body>

<Div class=“main-content”>

<Div class=“sidebar”>

<Div class=“header-bar”>

<Div class=“stream”><Div class=“tweet”>

<Div class=“tweet”> …

<Span class=“Author”> Ben<Span class=“Time”> Now<Span class=“Content”> Hi“<Span class=“Time”> Now”

Page 12: Libraries as Languages: Typechecking jQuery  Programs

$(“.tweet span”).next().text()

<Body>

<Div class=“main-content”>

<Div class=“sidebar”>

<Div class=“header-bar”>

<Div class=“stream”><Div class=“tweet”>

<Div class=“tweet”> …

<Span class=“Author”> Ben<Span class=“Time”> Now<Span class=“Content”> Hi

“ Now Hi”

Page 13: Libraries as Languages: Typechecking jQuery  Programs

Query: Selects some nodes in the page

Navigate: Move to new nodes, relative to existing ones

Manipulate: Retrieve or modify data from node(s)

What’s going on here?

$(“.tweet span”).next().html()

Page 14: Libraries as Languages: Typechecking jQuery  Programs

DOMnodes

.map()

.html()

.next()

...

How jQuery works

NewDOMnodes

.map()

.html()

.next()

...prev

NewDOMnodes

.map()

.html()

.next()

...prev

“<div>...</div>”

$(“.tweet span”)

Page 15: Libraries as Languages: Typechecking jQuery  Programs

So what can go wrong?

• “Standard” type errors: – .map() a function over wrong types of elements

• Ambiguity:– Getting the .html() of one node, but have many

• Overshooting:– Asking for the .children() of a leaf node…

• Wrong selection:– $(“div.mispleling”)

Page 16: Libraries as Languages: Typechecking jQuery  Programs

How to catch these errors?

Working backwards:• x.html() is ok if x has exactly 1 node • x.next() is ok if x has at least 1 node• The $() function returns some number of

nodes, based on its argument…

Need more than just simple types:Need to track sizes

Page 17: Libraries as Languages: Typechecking jQuery  Programs

Catching “standard type errors”

jq = A recursive, parametric type of ...

html : [jq< 'e >] Str, text : [jq< 'e >] Str,

...

next : [jq< 'e >] ????

Page 18: Libraries as Languages: Typechecking jQuery  Programs

Catching ambiguity errors

jq = A recursive, parametric type of ...

html : [jq< 'e >] Str, text : [jq< 'e >] Str,

...

next : [jq< 'e >] ????

Page 19: Libraries as Languages: Typechecking jQuery  Programs

Catching ambiguity errors

jq = A recursive, parametric type of ...

html : [jq< 1<'e>>] Str, text : [jq<1+<'e>>] Str,

...

next : [jq<1+<'e>>] ????

Multiplicities: Lightweight sizes for containers

Page 20: Libraries as Languages: Typechecking jQuery  Programs

Multiplicities

• New kind MOnly allowed as arguments to type constructorsNo values have a type of kind M

• Simple, finite set of constructors: 0, 1, 01, 1+, 0+

• Intuition: interval arithmeticMultiplication: 01<1+<τ>> = 0+<τ>Addition: 0<τ1> ++ 1<τ2> <: 01<τ1 + τ2>

Page 21: Libraries as Languages: Typechecking jQuery  Programs

Catching ambiguity errors

jq = A recursive, parametric type of ...

html : [jq< 1<'e>>] Str, text : ([jq<1+<'e>>] Str) & ([jq[1+<'e>>] Str jq<1+<'e>>), ...

next : [jq<1+<'e>>] ????

Intersection types + multiplicities = precise getter/setter types

Page 22: Libraries as Languages: Typechecking jQuery  Programs

Catching overshoot errors

jq = A recursive, parametric type of ...

html : [jq< 1<'e>>] Str, text : ([jq<1+<'e>>] Str) & ([jq[1+<'e>>] Str jq<1+<'e>>), ...

next : [jq<1+<'e>>] jq<1+<@nextOf<'e>>>

• Type-level functions to figure out structure

Page 23: Libraries as Languages: Typechecking jQuery  Programs

How to get structure information?

• “Well, on this page, a Tweet is …”

(Tweet : Div classes = {tweet} optional = {starred} (Author : Span classes = {span}) (Time : Span classes = {time}) (Content : Span classes = {content}))

• Compute type functions from this local structure

Page 24: Libraries as Languages: Typechecking jQuery  Programs

One last piece: matching selectors

jq = A recursive, parametric type of ...

html : [jq< 1<'e>>] Str, text : ([jq<1+<'e>>] Str) & ([jq[1+<'e>>] Str jq<1+<'e>>), ...

next : [jq<1+<'e>>] jq<1+<@nextOf<'e>>>

$ : forall s <: String, s @selector<'s>

Page 25: Libraries as Languages: Typechecking jQuery  Programs

Matching selectors against local structure

(Tweet : Div classes = {tweet} optional = {starred} (Author : Span classes = {span}) (Time : Span classes = {time}) (Content : Span classes = {content}))

“*.tweet > *.time” 1+<Time>

“*.tweet > *.content + *” 0<Element>

Page 26: Libraries as Languages: Typechecking jQuery  Programs

Full recipe:

• “Standard type errors” standard types• Ambiguity errors multiplicities• Overshooting errors local structure• Wrong selection local structure

Page 27: Libraries as Languages: Typechecking jQuery  Programs

Evaluation

• Examined 12 examples from Learning JQuery and its accompanying blog– Manually derived local structure from text

descriptions• Type-checked example queries

All pass typechecking, with no extra annotations• Manually introduced bugs

All now fail

Page 28: Libraries as Languages: Typechecking jQuery  Programs

Evaluation: Typical example

$(“.tweet”).children().next().next().next().css(“color”)

$(“.tweet”).children().next().next().css(“color”)

$(“.tweet”).children().next().css(“color”)

û ‘css’ expects 1<Element>, got 0<Element>

û ‘css’ expects 1<Element>, got 1+<Author+Time>

ü

Page 29: Libraries as Languages: Typechecking jQuery  Programs

Subtleties

• DOM Mutation$(“.tweet”).findClass(“starred”) .removeClass(“starred”)$(“.tweet”).findClass(“starred”) how many??

• Overly broad queriesWhat should $(“div > p”) match?

• …See paper for more details

Page 30: Libraries as Languages: Typechecking jQuery  Programs

30

Try it out!

Implemented in TeJaS:Customizable, extensible type systems for JS

https://github.com/brownplt/TeJaShttp://www.jswebtools.org/