Libraries as Languages: Typechecking jQuery Programs

Post on 22-Mar-2016

37 views 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 of Libraries as Languages: Typechecking jQuery Programs

LIBRARIES AS LANGUAGES:TYPECHECKING JQUERY PROGRAMSBenjamin LernerLiam ElbertyJincheng LiShriram 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

spanspan

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

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…

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

What does this jQuery code do?

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

Depends on the shape of the page!

$(“.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

$(“.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

$(“.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

$(“.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

$(“.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”

$(“.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”

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

DOMnodes

.map()

.html()

.next()

...

How jQuery works

NewDOMnodes

.map()

.html()

.next()

...prev

NewDOMnodes

.map()

.html()

.next()

...prev

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

$(“.tweet span”)

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

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

Catching “standard type errors”

jq = A recursive, parametric type of ...

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

...

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

Catching ambiguity errors

jq = A recursive, parametric type of ...

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

...

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

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

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>

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

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

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

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>

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>

Full recipe:

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

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

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>

ü

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

30

Try it out!

Implemented in TeJaS:Customizable, extensible type systems for JS

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