JavaScript 2 and the Open Web

Brendan Eich

Mozilla Corporation

Note how JS is paired with Flash -- poor, mundane HTML, CSS, DOM

Dilbert - the Big Time

I once described Doug Crockford as "the Yoda of Lambda JavaScript programming"

Yoda on ES4

Not good.

Yoda in Trouble

Anyway Doug's too tall for the part, even if it's a muppet. Let's try a taller wizard...

The Bridge of EcmaDoom

I can cast myself too (renegade veteran from the losing side of the last war against an evil empire...).

Mal, Latin for "Bad"

They'll swing back to the belief that they can make people... better. And I do not hold to that.
- Mal Reynolds, Serenity
Ok, enough mock flattery -- what's really going on with the ES4 fracas?

Cui Bono

Inevitable Evolution

Evolving Toward "Better"

Alternative Languages

Why JS2

Normal Distribution

Wait a Minute!

Perhaps you object (strenously):

OK, Granted

Why Not Evolve?

But... But...

You may still object:

What I Seek

In Particular

The Deeper Answer

Why JS2 as a major evolutionary jump matters:

Believe It

Non-Issues

Tracing JIT Benchmarks

Tracing JIT Benchmarks (2)

Non-Issues (2)

Integrity in JS2

Evolutionary Programming

Version 1 of a webmail client, in almost pure JS1

function send(msg) {
    validateMessage(msg);
    msg.id = sendToServer(JSON.encode(msg));
    database[msg.id] = msg;
}

function fetch() {
    handleMessage(-1);                  // -1 means "get new mail"
}

Evolutionary Programming (2)

function get(n) {
    if (uint(n) !== n)                  // JS1: n>>>0 === n
        throw new TypeError;
    if (n in database)
        return database[n];
    return handleMessage(n);
}

var database = [];

Evolutionary Programming (3)

function handleMessage(n) {
    let msg = JSON.decode(fetchFromServer(n));
    if (typeof msg != "object")
        throw new TypeError;
    if (msg.result == "no data")
        return null;
    validateMessage(msg);
    return database[msg.id] = msg;
}

Evolutionary Programming (4)

function validateMessage(msg) {
    function isAddress(a)
        typeof a == "object" && a != null &&
        typeof a.at == "object" && msg != null &&
        typeof a.at[0] == "string" && typeof a.at[1] == "string" &&
        typeof a.name == "string";
    if (!(typeof msg == "object" && msg != null &&
        typeof msg.id == "number" && uint(msg.id) === msg.id &&
        typeof msg.to == "object" && msg != null &&
        msg.to instanceof Array && msg.to.every(isAddress) &&
        isAddress(msg.from) && typeof msg.subject == "string" &&
        typeof msg.body == "string"))
        throw new TypeError;
}

Evolution, Second Stage

Version 2: Structural types for validation.

type Addr = { at: [string, string], name: string };
type Msg = {
    to: [Addr], from: Addr, subject: string, body: string, id: uint
};

function send(msg: like Msg) {
    msg.id = sendToServer(JSON.encode(msg));
    database[msg.id] = msg;
}

function fetch()
    handleMessage(-1);

Evolution, Second Stage (2)

function get(n: uint) {
    if (n in database)
        return database[n];
    return handleMessage(n);
}

function handleMessage(n) {
    let msg = JSON.decode(fetchFromServer(n));
    if (msg is like { result: string } && msg.result == "no data")
        return null;
    if (msg is like Msg)
        return database[msg.id] = msg;
    throw new TypeError;
}

Evolution, Third Stage

Version 3a: Integrity through structural type fixtures (other functions are unchanged since Version 2)

type MsgNoId = {
    to: [Addr], from: Addr, subject: string, body: string
};

function send(msg: like MsgNoId) {
    msg.id = sendToServer(JSON.encode(msg));
    database[msg.id] = copyMessage(msg);
}

Evolution, Third Stage (2)

function handleMessage(n) {
    let msg = JSON.decode(fetchFromServer(n));
    if (msg is like { result: string } && msg.result == "no data")
        return null;
    if (msg is like Msg)
        return database[id] = copyMessage(msg);
    throw new TypeError;
}

Evolution, Third Stage (3)

function copyMessage(msg) {
    function newAddr({ at: [user, host], name })
        new Addr([user, host]: [string, string], name);

    let { to, from, subject, body, id } = msg;
    return new Msg(to.map(newAddr), newAddr(from),
                                 subject, body, id);
}

Alternative Third Stage

Version 3b (other functions are unchanged since Version 3a)

function send(msg: like MsgNoId) {
    msg.id = sendToServer(JSON.encode(msg))
    database[msg.id] = msg wrap Msg
}

function handleMessage(n) {
    let msg = JSON.decode(fetchFromServer(n))
    if (msg is like { result: string } && msg.result == "no data")
        return null
    return database[msg.id] = msg wrap Msg
}

Observations on Evolution

Observations on Evolution (2)

Conclusions

What Else Is New?

Video Tag Demo

Canvas3D Demo

Finis