Testing tools and AI - ideas what to try with some tool examples
Splash
1. JavaScript World
The
Domination Plan at 16 Years
brendan@mozilla.org
• History
• Controversies
• Performance
• ES.next
• Demos
Thursday, October 27, 2011
3. 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
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
9. (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
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, 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
13. 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
14. 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
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
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-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
21. 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
22. 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
23. 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
24. Performance
mozilla
24
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 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
32. 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
33. 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
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
36. 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
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 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
39. 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
40. 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
41. 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
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
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 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
48. 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
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 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
52. Q&A
• @BrendanEich on twitter
• brendan@mozilla.org
• http://www.brendaneich.com/
• es-discuss@mozilla.org
mozilla
52
Thursday, October 27, 2011