52
The JavaScript World Domination Plan at 16 Years [email protected] History Controversies Performance ES.next Demos Thursday, October 27, 2011

Splash

Embed Size (px)

DESCRIPTION

My SPLASH Keynote on "the JavaScript World Domination Plan at 16 Years."

Citation preview

Page 1: Splash

The JavaScript World Domination Plan at 16 Years

[email protected]

• History

• Controversies

• Performance

• ES.next

• Demos

Thursday, October 27, 2011

Page 2: Splash

mozilla

History

2

Thursday, October 27, 2011

Page 3: Splash

mozilla

A very brief history

• Ten days in May 1995: “Mocha”, form validation, img rollovers, scripting of Java

• September 1995: “LiveScript” (did Netscape marketing go to Microsoft after?)

• December 1995: “JavaScript”, thanks to Bill Joy (a Sun Founder)

• 1996-1997: ECMA-262 Ed. 1, aka ES1, thanks to ECMA (now Ecma) TC39

• 1999: ES3: function expressions, RegExp, try/catch/finally, switch, do-while

• 2005: the Ajax revolution, followed by “The Ajax Experience”

• 2008: ES4 RIP, Harmony founded in July at the Oslo TC39 meeting

• 2009: ES5: “use strict”, JSON, Object.create, etc.

3

Thursday, October 27, 2011

Page 4: Splash

mozilla

Netscape in 1995

• Netscape had 50-80% browser share during explosive early Web growth

• Microsoft low-ball buy-out attempt in late 1994 rebuffed

• Threat to Windows made explicit by Java and too much hype

• “Worse is Better!” - @pmarca channeling @rpg

• “We are doomed!” - engineering refrain

• Very narrow window in which to innovate and “get on first”

4

Thursday, October 27, 2011

Page 5: Splash

mozilla

Pitch to me: come do “Scheme in the browser”

• One-shot opportunity to create the “HTML scripting language”

• By the time I joined, the Netscape/Sun “Java deal” cast long shadow

• Engineering VP: “make it look like Java” (I made it look like C and AWK)

• Argument by code demonstration became necessary

• I hacked the “Mocha” prototype in 10 days in May 1995

• And it showed. Mistakes (some recapitulating LISP) were frozen early

• I spent the rest of 1995 embedding in the browser, creating the DOM

5

Thursday, October 27, 2011

Page 6: Splash

Primordial DOM

• Netscape lacked a persistent DOM tree model; it had only a flattened display list

• To avoid slowing page load performance, I built the primordial DOM lazily from the display list

• Hence, document.write

Thursday, October 27, 2011

Page 7: Splash

mozilla

7

Thursday, October 27, 2011

Page 8: Splash

mozilla

8

Thursday, October 27, 2011

Page 9: Splash

mozilla

(credit for last two slides)

• Kleber & Jain, "Don't Let Third Parties Slow You Down" (Velocity 2010)

• Upshot: incremental/progressive/asynchronous code loading required for speed with responsiveness (Java class loading counterexample)

9

Thursday, October 27, 2011

Page 10: Splash

mozilla

Initial design goals

• Make it easy for non-experts to copy/paste snippets of code into HTML

• Tolerate “minor” errors (e.g., missing semicolons)

• Simplified onclick, onmousedown, etc., event handling, inspired by HyperCard

• Pick a few hard-working, powerful primitives

• First class functions for procedural abstraction (AWK more than Scheme)

• Objects everywhere, prototype-based (Self, but only one parent per object)

• Leave all else out!

10

Thursday, October 27, 2011

Page 11: Splash

mozilla

Marketing, sigh

• Netscape management fretted: “Why two programming languages?”

• Answer: division of labor, specialization

• Java for high-priced components/widgets (applet/plugin model)

• “Mocha” for mass market web designers (glue between components)

• Primitive types vs. objects patterned after Java with LiveConnect in mind

• “Object-based”, not object-oriented (no class) -- cannot have JS/Robin-the-boy-hostage encroaching on Java/Batman...

11

Thursday, October 27, 2011

Page 12: Splash

mozilla

Name games, the J word

• Then Netscape changed the name to “LiveScript”

• Finally, with Bill’s help on behalf of Sun, to “JavaScript” in December 1995

• Mostly a marketing scam

• Engineering pressure to “be like Java” did cause us to follow Java into some dead ends (Date inherited y2k bugs from java.util.Date)

• In the last decade Java has almost disappeared on the client side of the Web

• Java is top moneymaker as malware kit vector (per Brian Krebs)

• Now behind a click-to-activate barrier/whitelist in Chrome

12

Thursday, October 27, 2011

Page 13: Splash

mozilla

JS in two slides

• Objects map strings to values (properties):

var obj = new Object;obj[“prop”] = 42;!! ! // => obj.propobj[“0”] = “hello”;! ! // => obj[0]

other = {prop: 99, 0: “goodbye”}; // an object literalarray = [0, 1, 2, 3, 4, 5, 6, 7]; // array.length == 8

• Functions are first-class objects:

function fact(n) { return (n <= 2) ? n : n * fact(n-1);}fact.desc = “Factorial function”;result = array.map(fact);

13

Thursday, October 27, 2011

Page 14: Splash

mozilla

JS in two slides (2)

• Methods are function-valued properties:

obj.frob = function (n) { this.prop += n;};

obj.frob(6);! ! // => obj.prop == 48

• Top-level scope is an object. Implicit conversion. Oops.

grob = obj.frob;! // => assign a global method, grobgrob(6);!! ! ! // => undefined + 6 == NaNprop = “hello”;! // => reset global prop to stringgrob(6);!! ! ! // => prop == “hello6”

14

Thursday, October 27, 2011

Page 15: Splash

mozilla

Closures

• function Y(g) { return function (f) {return f(f);}( function (f) {return g(function (x) { return f(f)(x); }); });}

• var fact = Y(function (fact) { return function (n) { return (n <= 2) ? n : n * fact(n-1); }});

alert(fact(5));! => 120

15

Thursday, October 27, 2011

Page 16: Splash

mozilla

Prototypes

• All user-defined functions can construct:

function Car(make, model) { this.make = make; this.model = model;}myCar = new Car(“Honda”, “Fit”);

• All user-defined functions have a prototype property:

Car.prototype.color = “black”;!// default colorold = new Car(“Ford”, “T”);!! // black Model TmyCar.color = “silver”;!! ! // silver Honda Fit

• Powerful when combined with closures

16

Thursday, October 27, 2011

Page 17: Splash

mozilla

Controversies

17

Thursday, October 27, 2011

Page 18: Splash

mozilla

Why no bytecode?

• Top engine implementors won't agree on one bytecode

• Lowering JS semantics too far from source is future-hostile

• Versioning is anathema on the web (JVM, Flash counterexamples)

• JS with a few evolutionary steps is already a decent “bytecode”

• TypedArrays, binary data: machine storage types

• Type inference, runtime type/value profiling, proposed runtime guards

• Compressed AST encoding a la JSZap [Livshits, Zorn] is likelier

18

Thursday, October 27, 2011

Page 19: Splash

mozilla

Why no multi-VM browser integration

• Advantage: use canonical implementations, e.g., CPython for Python

• Drawbacks: those canonical implementations are not ready for the web

• Versioning independent of browser releases => dynamic linking/update

• OS-specific low-level APIs, toolchain-specific FFIs

• Insufficient fuzz-testing and web security engineering

• Proxies among disjoint heaps require non-distributed garbage-cycle collection

• Proxies among different languages a tall order otherwise

19

Thursday, October 27, 2011

Page 20: Splash

mozilla

20

Thursday, October 27, 2011

Page 21: Splash

mozilla

No browser wins by taking overlarge risks

• Previous slide from Collin Jackson’s USENIX Security 2011 invited talk, titled “Crossing the Chasm: Pitching Security Research to Mainstream Browser Vendors” [slides]

• Features are not free

• Mozilla commissioned optional CPython integration work by Mark Hammond

• Used by only one embedder

• No CPython distribution for Windows or Mac OS X

• High sunk and recurring engineering costs

21

Thursday, October 27, 2011

Page 22: Splash

mozilla

Why no single multi-language VM?

• IPR, NIH bad reasons, but...

• Such VMs always build in advantages for one “lead language” (e.g., Java)

• Rest of pack are incomplete copies of canonical implementations (Jython)

• Large companies can perhaps afford to strive for completeness over time, other browser vendors cannot

• See previous slide

• JS as compiler target dramatically on the rise -- are we already here?

22

Thursday, October 27, 2011

Page 23: Splash

mozilla

JS has awful warts!

• So use JSLint, JSHint, ADsafe, or better

• Two example from primordial JS:

• function f(o,x) { with (o) return x; } -- o.x or parameter x?

• function g(s) { eval(s); return function(){ return x; } } cannot be analyzed to decide that s != “var x = ‘ha ha’”

• Fixed in ES5 strict mode, which removes with and gives eval its own scope

• ES.next (likely ES6) removes global object from scope chain: pure lexical scope

• == and != are not equivalance relations (so use === and !==)

23

Thursday, October 27, 2011

Page 24: Splash

mozilla

Performance

24

Thursday, October 27, 2011

Page 25: Splash

mozilla

Performance progress - V8

25

Thursday, October 27, 2011

Page 26: Splash

mozilla

Tuning for SunSpider [Richards, Vitek, et al.]

26

Thursday, October 27, 2011

Page 27: Splash

mozilla

Recent progress - SpiderMonkey Type Inference

27

Thursday, October 27, 2011

Page 28: Splash

mozilla

ES.next

28

Thursday, October 27, 2011

Page 29: Splash

mozilla

The Harmony goals

• Be a better language for writing:

• complex applications

• libraries (including the DOM) shared by those applications

• code generators targeting the new edition

• Better tests, if not a testable (executable) specification

• Adopt de facto standards where possible

• Keep versioning as simple and linear as possible

• Support a statically verifiable, object-capability subset

29

Thursday, October 27, 2011

Page 30: Splash

mozilla

Approved for ES.next

• let, const, function in block scope

f(“outer”);function f(x) { { let x = “inner”; print(x); } // prints “inner” print(x); // prints “outer”}

• destructuring: let {x, y} = pt; let [s, v, o] = triple()

• parameter default values: function f(x, y=1, {z=2, w=3}) {...}

• rest, spread: function g(i, j, ...r) { return r.slice(i, j); } let a = [0, 1, 2, 3], b = [...a, 4, 5, 6, 7], o = new anyConstructor(...a), z = variadic(...a, -1, ...b);

30

Thursday, October 27, 2011

Page 31: Splash

mozilla

More approved for ES.next

• proxies, weak maps: Proxy.create(handler, proto), new WeakMap

• modules:

module NewMath { export function sin(x) {...} }

module Prefetch = “http://your/url/here”;

• iterators, generators:

function* gen() { yield 1; yield 2; }

for (let i of gen()) print(i); // prints 1 and 2

• array comprehensions: return [x+y for x of a for y of b]

• generator expressions: let g = (x+y for x of a for y of b)

31

Thursday, October 27, 2011

Page 32: Splash

mozilla

Yet more approved for ES.next

• Binary data:

• const Point2D = new StructType({ x: uint32, y: uint32 }), Color = new StructType({ r: uint8, g: uint8, b: uint8 }), Pixel = new StructType({ point: Point2D, color: Color });

• const Triangle = new ArrayType(Pixel, 3);

• new Triangle([{ point: { x: 0, y: 0 }, color: { r: 255, g: 255, b: 255 } }, { point: { x: 5, y: 5 }, color: { r: 128, g: 0, b: 0 } }, { point: { x: 10, y: 0 }, color: { r: 0, g: 0, b: 128 } }]);

32

Thursday, October 27, 2011

Page 33: Splash

mozilla

String interpolation and templating

• Injection-safer string interpolation and domain-specific languages

• Backtick-quoted string desugars to a function call that operates on the literal portions and substitution results:

• quasi`literalPart1${substitution}literalPart2` desugars to

• quasi({raw: ["literalPart1", "literalPart1"], cooked: ["literalPart1", "literalPart1"]}, substitution)

• Multiline string literals w/o prefix: `literalPart1${substitution} (yes, that was a newline!) literalPart2`

• Multiline regexp literals: re`literalPart1${substitution} (yes, that was a newline!) \w+ literalPart2`

33

Thursday, October 27, 2011

Page 34: Splash

mozilla

Classes squeaked by, but face existential doubt

• Sugar for prototypal object pattern, also supports closure patterns:

• const px = Name.create(‘x’), py = Name.create(‘y’);

class Point extends Base { constructor(x, y) { super(); this[px] = x, this[py] = y; this.r = function() { return Math.sqrt(x*x + y*y); } } get x() { return this[px]; } get y() { return this[py]; } proto_r() { return Math.sqrt(this[px] * this[px] + this[py] * this[py]); } equals(p) { return this[px] === p[px] && this[py] === p[py]; }}

34

Thursday, October 27, 2011

Page 35: Splash

mozilla

(tentative syntax ahead, work in progress...)

35

Thursday, October 27, 2011

Page 36: Splash

mozilla

Triangle (the proto operator)

• Instead of var obj = {__proto__: base, a: 1, b: 2}, use let obj = base <| {a: 1, b: 2}

• Works for other literal object forms: let arr = base <| [p, q, r] let fun = base <| function (...args) { ... } let re = base <| /(\w+)\s+(\w)+/g

36

Thursday, October 27, 2011

Page 37: Splash

mozilla

The monocle-mustache operator

• Inspired by PrototypeJS’s Object.extend

base.{a:1, b:2} // warning: updates base

• Copies all “own” right-hand-side properties (including private names) to base

• Should it generate a fresh value instead of mutating?

let obj = base.{a:1, b:2}

• Or if we want Prototype-style update, should it look like an assignment op?

base .= {a:1, b:2}

37

Thursday, October 27, 2011

Page 38: Splash

mozilla

Class pattern using triangle-monocle-mustache

• const px = Name.create(‘x’), py = Name.create(‘y’);

let Point = Base <| function (x, y) { super(); this[px] = x, this[py] = y; this.r = function() { return Math.sqrt(x*x + y*y); }}.prototype.{ get x() { return this[px]; }, get y() { return this[py]; }, proto_r() { return Math.sqrt(this[px] * this[px] + this[py] * this[py]); }, equals(p) { return this[px] === p[px] && this[py] === p[py]; }}.constructor.{ allPoints: [] // class “static” property}

38

Thursday, October 27, 2011

Page 39: Splash

mozilla

Not yet in Harmony: arrow function syntax

• Arrow function syntax, instead of λ, ƒ, or # (want to save # for later)

• Just like CoffeeScript: let identity = (x) -> x

• Expression body: const square = (x) -> (x * x)

• Statement body: let countUsed = (str) -> { if (str in usedWords) usedWords[str]++; else usedWords[str] = 1; }

• Fat arrow too: callback = (msg) => ( this.vmail.push(msg) )

• Binding forms: let f() -> “writable” const K() -> “readonly”

39

Thursday, October 27, 2011

Page 40: Splash

mozilla

Not yet in Harmony: block lambda revival

• Inspired by Smalltalk via Ruby

let empty = {||}; // no need for space between bars

assert(empty() === undefined); assert(typeof empty === "function"); // native and implements [[Call]] assert(empty.length === 0);  let identity = {|x| x}; // completion is return value  assert(identity(42) === 42); assert(identity.length === 1);  let a = [1, 2, 3, 4]; let b = a.map {|e| e * e} // paren-free call with block is // idiomatic control structure so // no semicolon at end

print(b); // [1, 4, 9, 16]

40

Thursday, October 27, 2011

Page 41: Splash

mozilla

More block lambda revival

• Paren-free calls, control effects: you know you want it...

41

b = a.map {|e| // newline in block ok e * e * e} // newline after ends call function find_first_odd(a) { a.forEach { |e, i| if (e & 1) return i; } // returns from function return -1;} function escape_return() { return {|e| return e};}b = escape_return();try { b(42); } catch (e) {} // error, return from // inactive function

Thursday, October 27, 2011

Page 42: Splash

mozilla

Good news

• ES.next is being drafted

• It has many usability and be-a-better-compiler-target improvements already

• Prototyping in SpiderMonkey and V8 is ongoing, so we’ll actually implementor- and user-test before finalizing the specification

• Even if we cut a few things -- still good progress

• Help wanted on the implementor- and user-testing fronts

42

Thursday, October 27, 2011

Page 43: Splash

mozilla

Languages targeting JS today

• CoffeeScript Family (& Friends): CoffeeScript Coco Parsec Contracts.coffee Uberscript ToffeeScript JS11 Kaffeine Jack move

• JavaScript Parsers and Extensions: Narcissus Traceur es-lab qfox reflect.js bdParse parse-js ZeParser

• Javascript Optimizers: Closure UglifyJS

• Security enforcing JavaScript: Caja ADsafe FBJS Jacaranda etc.

• Static or optional typing: Dart JavaScript++ SafeJS MileScript Mascara Roy

• Synchronous to Asynchronous JavaScript Compilers (CPS): Streamline.js mobl StratifiedJS NarrativeJS jwacs Jscex TameJS

• JavaScript Language Extensions: ContextJS Objective-J JS2 jangaroo Flapjax jLang RestrictMode TIScript

• Ruby: HotRuby rb2js RubyJS Red Quby Opal 8ball

• Python: PYXC-PJ Pyjamas Pyjs Skulpt PyCow PyvaScript

• Java: GWT Java2Script j2js

• Scala: scalagwt

• C#, .NET: jsc JSIL Script# Prefix

• Lisp, Scheme: BiwaScheme ClojureScript clojurejs EdgeLisp Fargo MobyScheme nconc Parenscript Ralph scheme2js Scriptjure Sibilant Spock

• OCaml: Ocamljs O'Browser Js_of_ocaml

• Haskell: ghcjs jmacro

• Smalltalk: Amber Clamato SilverSmalltalk LivelyKernel

• C/C++: Emscripten mala Clue

• Basic: NS Basic/App Studio, qb.js

• Multitarget: Haxe Fantom LZX Clue

• Tierless languages (produce both client & server): Fun Ur WebSharper mobl E Sugar Opa

• Visual, Blocks-based Languages: Waterbear JsMorphic ScriptBlocks

• Others: Oia Quixe Gnusto Logo p2js Reb2Static RPN phype OP4JS jsForth wForth

43

Thursday, October 27, 2011

Page 44: Splash

mozilla

Demos

44

Thursday, October 27, 2011

Page 45: Splash

mozilla

Emscripten [Alon Zakai]

45

Thursday, October 27, 2011

Page 46: Splash

mozilla

RiverTrail: Parallel JS

• A ParallelArray library, like typed arrays but immutable.

• map, reduce, combine, filter, partition, scan, scatter -- all produce fresh ParallelArray results

• Relies on associativity to parallelize arithmetic operations (this does inject some f.p. non-determinism).

• A Firefox add-on that runs a Narcissus-based JS-to-OpenCL compiler over ParallelArray code

• Source: github.com/RiverTrail/RiverTrail (user id should’ve been IntelLabs)

• Demo code contains a "DO NOT use strict”; directive!

46

Thursday, October 27, 2011

Page 47: Splash

mozilla

RiverTrail demo sample code

• the ParallelArray constructor builds on typed arrays:

NBody.private.initVel = new Array(numBodies);

NBody.private.initVelTA = new Float32Array(numBodies * 4);

var initAsteroidPos = new Array(50);

for (i = 0; i < 50; i++) {    initAsteroidPos[i] = new ParallelArray([                                            NBody.private.posTA[i * 3 + 0],     // x                                            NBody.private.posTA[i * 3 + 1],                                            NBody.private.posTA[i * 3 + 2],                                            ]); }  . . . NBody.private.asteroidPos = new ParallelArray(Float32Array, initAsteroidPos);  . . . NBody.private.vel = new ParallelArray(Float32Array, NBody.private.initVel);

47

Thursday, October 27, 2011

Page 48: Splash

mozilla

ParallelArray methods in action

• combine method is a workhorse (takes variable number of args)

"animateTickParallel": function animateTickParallel() {

    // increment (+=) velocity by acceleration    var newVel = NBody.private.vel.combine(                  1,                     low_precision(NBody.bodyVelocityLoopified),                     NBody.private.pos,                     numBodies,                     NBody.Constant.deltaTime,                     NBody.Constant.epsSqr,                     NBody.time,                     NBody.private.asteroidPos                 );  . . .

48

Thursday, October 27, 2011

Page 49: Splash

mozilla

River Trail [Intel Labs]

49

Thursday, October 27, 2011

Page 50: Splash

mozilla

Conclusions

• JS is everywhere, it’s evolving, and it will die hard

• JS is not the bad guy

• No world domination by (under-funded) force -- not Dr. Evil

• Developers have learned how to use it well

• More like the good guy in the wrong place at the wrong time

• Bruce Willis in the Die Hard series...

• or current inspiration: classic Wesley Snipes

50

Thursday, October 27, 2011

Page 51: Splash

Always bet on JS• First they said JS couldn’t be useful

for building “rich Internet apps”

• Then they said it couldn’t be fast

• Then they said it couldn’t be fixed

• Then it couldn’t do multicore/GPU

• Wrong every time!

• My advice: always bet on JS

Thursday, October 27, 2011