JavaScript at 20
Brendan Eich
Standardization
"Things that are impossible just take longer." - Hixie
1995: Eich recruited to Netscape
"Come and put Scheme in the browser!"
2015: John Carmack put Racket in Oculus VR
@auradeluxe 1/ I did something once in ten days. Still paying, lol. If @ID_AA_Carmack gets Racket (née PLT Scheme) as metaverse JS, revenge
— BrendanEich (@BrendanEich) July 2, 2015
@auradeluxe @ID_AA_Carmack 2/ sweet revenge on "make it [JS] look like Java" order givers at Netscape. I came to do "Scheme in the browser".
— BrendanEich (@BrendanEich) July 2, 2015
@BrendanEich @ID_AA_Carmack @auradeluxe That order was the difference between a billion programmers and none :-).
— Marc Andreessen (@pmarca) July 2, 2015
What was it like to hack JS in 10 days?
Painful.
- Morrissey?
- Vince Vaughn?
Java was the big Web VM
JavaScript was "little brother"
Think back to 1995... what was on TV then?
I had my big break that year...
Even @pmarca roller-bladed then.
I'd go to a real library to read Computer Science papers.
John Doerr claims that even an idiot could have been a successful VC in the 1980s:
"All you had to do was hang around Margaret Jacks Hall."
Java's bytecode design influenced my work on JS.
Java is typed (or statically typed) and has mostly-typed bytecode
JS is untyped (or dynamically typed)
So in 10 days in May 1995, I wrote
- A lexical scanner and parser for early JS
- The parser emitted stack-machine bytecode
- Which ran in a bytecode interpreter
Function.prototype.toString
bytecode decompiler- The standard library was poor
Array
wasObject
with.length
propertyDate
hand-ported (h/t ksmith@netscape.com) fromjava.util.Date
Mistakes were made (WTFJS, WAT)
But enough was good that JS survived
http://whitetailbutte.com/ case study
Early DOM mattered as much as JS
Much progress since then
- asm.js was discovered
- ES6 is all but done
- typed arrays from WebGL are in ES6
- typed objects coming in ES7
- TypeScript, and now Flow
class vector {
constructor(n) { this.arr = new Int32Array(n); }
sum() {
let la = this.arr;
let S = 0;
for (let i = la.length|0; (i=(i-1)|0) >= 0;)
S = (S + la[i|0])|0;
return S;
}
}
JS is untyped (dynamically typed), however:
asm.js is typed "bytecode" with deterministic performance
JS, a dynamically typed language, is often written with latent static types
Especially when "written" by compilers
Compiling to JS is not new
- Remember GWT, and OpenLaszlo before it?
- CoffeeScript, now hundreds of compile-to-JS languages
- (including Dart)
- See the Solar System of JS
- For C++ to JS, Emscripten by Alon Zakai
JS VMs compile to the metal
(just like Java but without declaring all types)
And the Java VM supports dynamic languages too:
The circle is now complete
WebAssembly
- Consensus from Apple/Google/Microsoft/Mozilla that the design repo is approaching completeness
- An executable OCaml spec and test suite in a new spec repo
- Apple/Google/Mozilla are actively writing prototype wasm support in their engines' public repos
- WebAssembly means 1VM with 2 syntaxes, .js and .wasm
What does WebAssembly look like?
It is hard to see binary
enum class I32 : uint8_t {
LitPool, LitImm, GetLoc, GetGlo, SetLoc, SetGlo,
SLoad8, SLoadOff8, ULoad8, ULoadOff8,
SLoad16, SLoadOff16, ULoad16, ULoadOff16,
Load32, LoadOff32,
Store8, StoreOff8, Store16, StoreOff16, Store32, StoreOff32,
CallInt, CallInd, CallImp,
Cond, Comma,
FromF32, FromF64,
Neg, Add, Sub, Mul, SDiv, UDiv, SMod, UMod,
BitNot, BitOr, BitAnd, BitXor, Lsh, ArithRsh, LogicRsh,
Clz,
LogicNot,
EqI32, EqF32, EqF64, NEqI32, NEqF32, NEqF64,
SLeThI32, ULeThI32, LeThF32, LeThF64,
...
};
switch (i32) {
...
case I32::FromF32: ...(s, prec, ctx, Result::NoIsh, Ctx::Default, "~~"); break;
ak;
case I32::FromF64: ...(s, prec, ctx, Result::NoIsh, Ctx::Default, "~~"); break;
case I32::Neg: ...(s, prec, ctx, Result::Intish, Ctx::Default, "-"); break;
case I32::BitNot: ...(s, prec, ctx, Result::NoIsh, Ctx::ToI32, "~"); break;
...
}
ES6 well-covered by other speakers
ES6/2015, ES7/2016, ES8...
Rapid(er) standards release process
ES7 async functions
function chainAnimationsPromise(elem, animations) {
let ret = null;
let p = currentPromise;
for (let anim of animations) {
p = p.then(function(val) {
ret = val;
return anim(elem);
});
}
return p.catch(e => { /* ignore and keep going */ })
.then(() => { return ret; });
}
function chainAnimationsGenerator(elem, animations) {
return spawn(function*() {
let ret = null;
try {
for (let anim of animations) {
ret = yield anim(elem);
}
} catch(e) { /* ignore and keep going */ }
return ret;
});
}
async function chainAnimationsAsync(elem, animations) {
let ret = null;
try {
for (let anim of animations) {
ret = await anim(elem);
}
} catch(e) { /* ignore and keep going */ }
return ret;
}
More on board for ES7+
- SIMD
- typed objects
- value objects, including
int64
anduint64
- user-defined operators and literals
- async generators