JavaScript World
                               The

                      Domination Plan at 16 Years
                                             brendan@mozilla.org


                   •         History

                   •         Controversies

                   •         Performance

                   •         ES.next

                   •         Demos

Thursday, October 27, 2011
History




                             mozilla

          2


Thursday, October 27, 2011
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
                                                                                      mozilla
          • 2009: ES5: “use strict”, JSON, Object.create, etc.

          3


Thursday, October 27, 2011
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”


                                                                                  mozilla

          4


Thursday, October 27, 2011
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              mozilla

          5


Thursday, October 27, 2011
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
mozilla

          7


Thursday, October 27, 2011
mozilla

          8


Thursday, October 27, 2011
(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)




                                                                                     mozilla

          9


Thursday, October 27, 2011
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!                                                         mozilla

          10


Thursday, October 27, 2011
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...
                                                                                        mozilla

          11


Thursday, October 27, 2011
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)
                                                                                           mozilla
                • Now behind a click-to-activate barrier/whitelist in Chrome

          12


Thursday, October 27, 2011
JS in two slides

          • Objects map strings to values (properties):


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

               other = {prop: 99, 0: “goodbye”}; // an object literal
               array = [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”;                        mozilla
               result = array.map(fact);

          13


Thursday, October 27, 2011
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, grob
               grob(6);! ! !
                       !            //   =>   undefined + 6 == NaN
               prop = “hello”;!     //   =>   reset global prop to string
               grob(6);! ! !
                       !            //   =>   prop == “hello6”
                                                                             mozilla

          14


Thursday, October 27, 2011
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
                                                        mozilla

          15


Thursday, October 27, 2011
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 color
               old = new Car(“Ford”, “T”);!
                                          ! // black Model T
               myCar.color = “silver”;! ! ! // silver Honda Fit

                                                                   mozilla
          • Powerful when combined with closures

          16


Thursday, October 27, 2011
Controversies




                             mozilla

          17


Thursday, October 27, 2011
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              mozilla

          18


Thursday, October 27, 2011
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                     mozilla

          19


Thursday, October 27, 2011
mozilla

          20


Thursday, October 27, 2011
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                            mozilla

          21


Thursday, October 27, 2011
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?

                                                                                       mozilla

          22


Thursday, October 27, 2011
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
                                                                                      mozilla
          • == and != are not equivalance relations (so use === and !==)

          23


Thursday, October 27, 2011
Performance




                             mozilla

          24


Thursday, October 27, 2011
Performance progress - V8




                                      mozilla

          25


Thursday, October 27, 2011
Tuning for SunSpider [Richards, Vitek, et al.]




                                                           mozilla

          26


Thursday, October 27, 2011
Recent progress - SpiderMonkey Type Inference




                                                          mozilla

          27


Thursday, October 27, 2011
ES.next




                             mozilla

          28


Thursday, October 27, 2011
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           mozilla

          29


Thursday, October 27, 2011
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);                  mozilla

          30


Thursday, October 27, 2011
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)   mozilla

          31


Thursday, October 27, 2011
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 } }]);     mozilla

          32


Thursday, October 27, 2011
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`
                                                                                        mozilla
          • Multiline regexp literals: re`literalPart1${substitution}
             (yes, that was a newline!) w+ literalPart2`
          33


Thursday, October 27, 2011
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]; }                     mozilla
                   }

          34


Thursday, October 27, 2011
(tentative syntax ahead, work in progress...)




                                                          mozilla

          35


Thursday, October 27, 2011
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




                                                                      mozilla

          36


Thursday, October 27, 2011
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}
                                                                                      mozilla

          37


Thursday, October 27, 2011
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
               }                                                         mozilla

          38


Thursday, October 27, 2011
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”                                     mozilla

          39


Thursday, October 27, 2011
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
                                                                                  mozilla
               print(b);                              // [1, 4, 9, 16]


          40


Thursday, October 27, 2011
More block lambda revival

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

                 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
                                                                                    mozilla

          41


Thursday, October 27, 2011
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




                                                                                    mozilla

          42


Thursday, October 27, 2011
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
                                                                                                                                                        mozilla
          •    Others: Oia Quixe Gnusto Logo p2js Reb2Static RPN phype OP4JS jsForth wForth




          43


Thursday, October 27, 2011
Demos




                             mozilla

          44


Thursday, October 27, 2011
Emscripten [Alon Zakai]




                                    mozilla

          45


Thursday, October 27, 2011
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!                             mozilla

          46


Thursday, October 27, 2011
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);
                                                                                             mozilla

          47


Thursday, October 27, 2011
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
                           );
            . . .                                                           mozilla

          48


Thursday, October 27, 2011
River Trail [Intel Labs]




                                     mozilla

          49


Thursday, October 27, 2011
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                 mozilla

          50


Thursday, October 27, 2011
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
Q&A

          • @BrendanEich on twitter


          • brendan@mozilla.org


          • http://www.brendaneich.com/


          • es-discuss@mozilla.org




                                          mozilla

          52


Thursday, October 27, 2011

Splash

  • 1.
    JavaScript World The Domination Plan at 16 Years brendan@mozilla.org • History • Controversies • Performance • ES.next • Demos Thursday, October 27, 2011
  • 2.
    History mozilla 2 Thursday, October 27, 2011
  • 3.
    A very briefhistory • 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 mozilla • 2009: ES5: “use strict”, JSON, Object.create, etc. 3 Thursday, October 27, 2011
  • 4.
    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” mozilla 4 Thursday, October 27, 2011
  • 5.
    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 mozilla 5 Thursday, October 27, 2011
  • 6.
    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
  • 7.
    mozilla 7 Thursday, October 27, 2011
  • 8.
    mozilla 8 Thursday, October 27, 2011
  • 9.
    (credit for lasttwo 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) mozilla 9 Thursday, October 27, 2011
  • 10.
    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! mozilla 10 Thursday, October 27, 2011
  • 11.
    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... mozilla 11 Thursday, October 27, 2011
  • 12.
    Name games, theJ 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) mozilla • Now behind a click-to-activate barrier/whitelist in Chrome 12 Thursday, October 27, 2011
  • 13.
    JS in twoslides • Objects map strings to values (properties): var obj = new Object; obj[“prop”] = 42;!! ! // => obj.prop obj[“0”] = “hello”;! ! // => obj[0] other = {prop: 99, 0: “goodbye”}; // an object literal array = [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”; mozilla result = array.map(fact); 13 Thursday, October 27, 2011
  • 14.
    JS in twoslides (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, grob grob(6);! ! ! ! // => undefined + 6 == NaN prop = “hello”;! // => reset global prop to string grob(6);! ! ! ! // => prop == “hello6” mozilla 14 Thursday, October 27, 2011
  • 15.
    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 mozilla 15 Thursday, October 27, 2011
  • 16.
    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 color old = new Car(“Ford”, “T”);! ! // black Model T myCar.color = “silver”;! ! ! // silver Honda Fit mozilla • Powerful when combined with closures 16 Thursday, October 27, 2011
  • 17.
    Controversies mozilla 17 Thursday, October 27, 2011
  • 18.
    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 mozilla 18 Thursday, October 27, 2011
  • 19.
    Why no multi-VMbrowser 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 mozilla 19 Thursday, October 27, 2011
  • 20.
    mozilla 20 Thursday, October 27, 2011
  • 21.
    No browser winsby 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 mozilla 21 Thursday, October 27, 2011
  • 22.
    Why no singlemulti-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? mozilla 22 Thursday, October 27, 2011
  • 23.
    JS has awfulwarts! • 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 mozilla • == and != are not equivalance relations (so use === and !==) 23 Thursday, October 27, 2011
  • 24.
    Performance mozilla 24 Thursday, October 27, 2011
  • 25.
    Performance progress -V8 mozilla 25 Thursday, October 27, 2011
  • 26.
    Tuning for SunSpider[Richards, Vitek, et al.] mozilla 26 Thursday, October 27, 2011
  • 27.
    Recent progress -SpiderMonkey Type Inference mozilla 27 Thursday, October 27, 2011
  • 28.
    ES.next mozilla 28 Thursday, October 27, 2011
  • 29.
    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 mozilla 29 Thursday, October 27, 2011
  • 30.
    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); mozilla 30 Thursday, October 27, 2011
  • 31.
    More approved forES.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) mozilla 31 Thursday, October 27, 2011
  • 32.
    Yet more approvedfor 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 } }]); mozilla 32 Thursday, October 27, 2011
  • 33.
    String interpolation andtemplating • 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` mozilla • Multiline regexp literals: re`literalPart1${substitution} (yes, that was a newline!) w+ literalPart2` 33 Thursday, October 27, 2011
  • 34.
    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]; } mozilla } 34 Thursday, October 27, 2011
  • 35.
    (tentative syntax ahead,work in progress...) mozilla 35 Thursday, October 27, 2011
  • 36.
    Triangle (the protooperator) • 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 mozilla 36 Thursday, October 27, 2011
  • 37.
    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} mozilla 37 Thursday, October 27, 2011
  • 38.
    Class pattern usingtriangle-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 } mozilla 38 Thursday, October 27, 2011
  • 39.
    Not yet inHarmony: 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” mozilla 39 Thursday, October 27, 2011
  • 40.
    Not yet inHarmony: 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 mozilla print(b); // [1, 4, 9, 16] 40 Thursday, October 27, 2011
  • 41.
    More block lambdarevival • Paren-free calls, control effects: you know you want it... 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 mozilla 41 Thursday, October 27, 2011
  • 42.
    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 mozilla 42 Thursday, October 27, 2011
  • 43.
    Languages targeting JStoday • 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 mozilla • Others: Oia Quixe Gnusto Logo p2js Reb2Static RPN phype OP4JS jsForth wForth 43 Thursday, October 27, 2011
  • 44.
    Demos mozilla 44 Thursday, October 27, 2011
  • 45.
    Emscripten [Alon Zakai] mozilla 45 Thursday, October 27, 2011
  • 46.
    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! mozilla 46 Thursday, October 27, 2011
  • 47.
    RiverTrail demo samplecode • 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); mozilla 47 Thursday, October 27, 2011
  • 48.
    ParallelArray methods inaction • 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                  );   . . . mozilla 48 Thursday, October 27, 2011
  • 49.
    River Trail [IntelLabs] mozilla 49 Thursday, October 27, 2011
  • 50.
    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 mozilla 50 Thursday, October 27, 2011
  • 51.
    Always bet onJS • 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
  • 52.
    Q&A • @BrendanEich on twitter • brendan@mozilla.org • http://www.brendaneich.com/ • es-discuss@mozilla.org mozilla 52 Thursday, October 27, 2011