Slide 1

Slide 1 text

ECMAScript 2017 and beyond Axel Rauschmayer @rauschma The Rolling Scopes Conference Minsk, 19 February 2017 Slides: speakerdeck.com/rauschma

Slide 2

Slide 2 text

Dr. Axel Rauschmayer @rauschma Overview • How is JavaScript evolved? • What are the features of ECMAScript 2016? • What are the features of ECMAScript 2017? • What’s in store for JS after ES2017? 2

Slide 3

Slide 3 text

Evolving JavaScript: TC39 and the TC39 process © by Bryan Wright

Slide 4

Slide 4 text

Dr. Axel Rauschmayer @rauschma JavaScript vs. ECMAScript • Meaning: • JavaScript: the language • ECMAScript: the standard for the language • ECMAScript 6 etc.: language versions • Ecma: standards organisation hosting ECMAScript 4

Slide 5

Slide 5 text

Dr. Axel Rauschmayer @rauschma TC39 • Ecma Technical Committee 39 (TC39): the committee evolving JavaScript • Members – strictly speaking: companies (all major browser vendors etc.) • Bi-monthly meetings of delegates and invited experts 5

Slide 6

Slide 6 text

Dr. Axel Rauschmayer @rauschma Ecma Technical Committee 39 (TC39) github.com/hemanth/tc39-members { "members": { "Ordinary": [ "Adobe", "AMD", "eBay", "Google", "HewlettPackard", "Hitachi", "IBM", "Intel", "KonicaMinolta" ],
 "Associate": [ "Apple", "Canon", "Facebook", "Fujitsu", "JREastMechatronics", "Netflix", "NipponSignal", "NXP", "OMRONSocialSolutions", "Ricoh", "Sony", "Toshiba", "Twitter" ], ... 6

Slide 7

Slide 7 text

Dr. Axel Rauschmayer @rauschma Timeline of ECMAScript • ECMAScript 1 (June 1997): first version • ECMAScript 2 (June 1998): keep in sync with ISO standard • ECMAScript 3 (December 1999): many core features – “[…] regular expressions, better string handling, new control statements [do-while, switch], try/catch exception handling, […]” • ECMAScript 4 (abandoned in July 2008) • ECMAScript 5 (December 2009): minor improvements (standard library and strict mode) • ECMAScript 5.1 (June 2011): keep in sync with ISO standard • ECMAScript 6 (June 2015): many new features 7

Slide 8

Slide 8 text

Dr. Axel Rauschmayer @rauschma The TC39 process Problems with infrequent, large releases (such as ES6): • Features that are ready sooner have to wait. • Features that are not ready are under pressure to get finished. • Next release would be a long time away. • They may delay the release. 8

Slide 9

Slide 9 text

Dr. Axel Rauschmayer @rauschma The TC39 process New TC39 process: • Manage features individually (vs. one monolithic release). • Per feature: proposal that goes through maturity stages, numbered 0 (strawman) – 4 (finished). • Introduce features gradually. • Once a year, there is a new ECMAScript version. • Only features that are ready (=stage 4) are added. 9

Slide 10

Slide 10 text

Dr. Axel Rauschmayer @rauschma Stage 0: strawman What is it? • First sketch • Submitted by TC39 member or
 registered TC39 contributor What’s required? • Review at TC39 meeting 10

Slide 11

Slide 11 text

Dr. Axel Rauschmayer @rauschma Stage 1: proposal What is it? • Actual proposal of a feature • TC39 is willing to help with designing the feature What’s required? • Identify champion(s), one of them a TC39 member • Spec: prose, examples, API, semantics and algorithms • Implementation: polyfills and demos What’s next? • Major changes are still expected 11

Slide 12

Slide 12 text

Dr. Axel Rauschmayer @rauschma Stage 2: draft What is it? • First version of what will be in the spec • Eventual standardisation is likely What’s required? • Formal description of syntax and semantics (gaps are OK) • Two experimental implementations (incl. one transpiler) What’s next? • Only incremental changes are expected 12

Slide 13

Slide 13 text

Dr. Axel Rauschmayer @rauschma Stage 3: candidate What is it? • Proposal is mostly finished, now needs feedback from implementations What’s required? • Spec text is complete • Signed off by reviewers and ES spec editor • At least two spec-compliant implementations What’s next? • Changes only in response to critical issues. 13

Slide 14

Slide 14 text

Dr. Axel Rauschmayer @rauschma Stage 4: finished What is it? • Proposal ready to be included in the ES specification What’s required? • Test 262 acceptance tests • Two spec-compliant shipping implementations that pass the tests • Significant practical experience with the implementations • ECMAScript spec editor must sign off on the spec text What’s next? • Proposal will be added to spec as soon as possible • When spec is next ratified, the proposal becomes a standard 14

Slide 15

Slide 15 text

Dr. Axel Rauschmayer @rauschma Think in proposals & stages, not in ES versions • Before stage 4: proposals may be withdrawn. • Object.observe(): withdrawn at stage 2 • Stage 4: proposal will certainly become a part of ECMAScript. • But: don’t know when exactly. Tip: Ignore features before stage 3. 15

Slide 16

Slide 16 text

ECMAScript 2016 Standardised in June 2016 © by Ben Mason

Slide 17

Slide 17 text

Dr. Axel Rauschmayer @rauschma New features in ES2016 ES2016 has only two new features: • Array.prototype.includes (Domenic Denicola, Rick Waldron) • Exponentiation Operator (Rick Waldron) 17

Slide 18

Slide 18 text

Dr. Axel Rauschmayer @rauschma Array.prototype.includes > ['a', 'b', 'c'].includes('a') true > ['a', 'b', 'c'].includes('d') false > [NaN].includes(NaN) true > [NaN].indexOf(NaN) >= 0 false 18

Slide 19

Slide 19 text

Dr. Axel Rauschmayer @rauschma Exponentiation operator // x ** y is same as Math.pow(x, y) const squared = 3 ** 2; // 9 let num = 3; num **= 2; // same: num = num ** 2 console.log(num); // 9 19

Slide 20

Slide 20 text

ECMAScript 2017 © by TTFCA

Slide 21

Slide 21 text

Dr. Axel Rauschmayer @rauschma Features of ES2017 Major new features: • Async Functions (Brian Terlson) • Shared memory and atomics (Lars T. Hansen) Minor new features: • Object.values/Object.entries (Jordan Harband) • String padding (Jordan Harband, Rick Waldron) • Object.getOwnPropertyDescriptors() (Jordan Harband, Andrea Giammarchi) • Trailing commas in function parameter lists and calls (Jeff Morrison) 21

Slide 22

Slide 22 text

Dr. Axel Rauschmayer @rauschma Async Functions function fetchJsonViaPromises(url) { return fetch(url) // browser API, returns Promise .then(request => request.text()) // returns Promise .then(text => { return JSON.parse(text); }) .catch(error => { console.log(`ERROR: ${error.stack}`); }); } async function fetchJsonAsync(url) { try { const request = await fetch(url); const text = await request.text(); return JSON.parse(text); } catch (error) { console.log(`ERROR: ${error.stack}`); } } 22

Slide 23

Slide 23 text

Dr. Axel Rauschmayer @rauschma Async Functions Variants: // Async function declaration async function foo() {} // Async function expression const foo = async function () {}; // Async arrow function const foo = async () => {}; // Async method definition (in classes, too) const obj = { async foo() {} }; 23

Slide 24

Slide 24 text

Dr. Axel Rauschmayer @rauschma Fulfilling the Promise of an async function async function asyncFunc() { return 123; } asyncFunc() .then(x => console.log(x)); // 123 24

Slide 25

Slide 25 text

Dr. Axel Rauschmayer @rauschma Rejecting the Promise of an async function async function asyncFunc() { throw new Error('Problem!'); } asyncFunc() .catch(err => console.log(err)); // Error: Problem! 25

Slide 26

Slide 26 text

Dr. Axel Rauschmayer @rauschma Handling rejected Promises inside async functions async function asyncFunc() { try { await otherAsyncFunc(); } catch (err) { console.error(err); } } // Equivalent to: function asyncFunc() { return otherAsyncFunc() .catch(err => { console.error(err); }); } 26

Slide 27

Slide 27 text

Dr. Axel Rauschmayer @rauschma Async functions and Node.js Node.js 7.2+: $ node --harmony_async_await > async function f() { return 123 } > f().then(x => console.log(x)) 123 27

Slide 28

Slide 28 text

Dr. Axel Rauschmayer @rauschma History of concurrency in JavaScript • Single main thread + asynchronicity via callbacks • Web Workers • Originally: copy and send strings • Structured cloning: copy and send structured data • Transferables: move and send structured data • Failed experiment: PJS / River Trail • High-level support for data parallelism (map(), filter(), reduce()) 28

Slide 29

Slide 29 text

Dr. Axel Rauschmayer @rauschma Shared Array Buffers New – Shared Array Buffers: • A primitive building block for higher-level concurrency abstractions • Share data between workers • Let’s you compile threaded C++ code to JavaScript 29

Slide 30

Slide 30 text

Dr. Axel Rauschmayer @rauschma Creating and sending a Shared Array Buffer //----- main.js ----- const worker = new Worker('worker.js'); // To be shared const sharedBuffer = new SharedArrayBuffer( 10 * Int32Array.BYTES_PER_ELEMENT); // 10 elts // Share sharedBuffer with the worker worker.postMessage({sharedBuffer}); // clone // Local only const sharedArray = new Int32Array(sharedBuffer); 30

Slide 31

Slide 31 text

Dr. Axel Rauschmayer @rauschma Receiving a Shared Array Buffer //----- worker.js ----- self.addEventListener('message', event => { const {sharedBuf} = event.data; const sharedArr = new Int32Array(sharedBuf); // ··· }); 31

Slide 32

Slide 32 text

Dr. Axel Rauschmayer @rauschma Problem: compilers may rearrange reads // Source code while (sharedArray[0] === 1) ; // Rearranged by compiler let tmp = sharedArray[0]; while (tmp === 1) ; // runs never or forever 32

Slide 33

Slide 33 text

Dr. Axel Rauschmayer @rauschma Problem: writes may be reordered // main.js sharedArray[1] = 11; sharedArray[2] = 22; // worker.js while (sharedArray[2] !== 22) ; console.log(sharedArray[1]); // 0 or 11 33

Slide 34

Slide 34 text

Dr. Axel Rauschmayer @rauschma Solution: Atomics Atomics ensures: • Operations are non-interruptible (atomic) – think transactions in DBs • Order of writes and reads is fixed • No reads or writes get eliminated • Can be used to synchronise non-atomic reads and writes 34

Slide 35

Slide 35 text

Dr. Axel Rauschmayer @rauschma Using Atomics // main.js Atomics.store(sharedArray, 0, 2); // worker.js while (Atomics.load(sharedArray, 0) === 0) ; console.log(Atomics.load(sharedArray, 0)); // 2 35

Slide 36

Slide 36 text

Dr. Axel Rauschmayer @rauschma Atomics Loading and storing: • Atomics.load(ta : TypedArray, index) : T • Atomics.store(ta : TypedArray, index, value : T) : T • Atomics.exchange(ta : TypedArray, index, value : T) : T • Atomics.compareExchange(ta : TypedArray, index, expectedValue, replacementValue) : T Waiting and waking: • Atomics.wait(ta: Int32Array, index, value, timeout=Number.POSITIVE_INFINITY) : ('not-equal' | 'ok' | 'timed-out') • Atomics.wake(ta : Int32Array, index, count) 36

Slide 37

Slide 37 text

Dr. Axel Rauschmayer @rauschma Atomics Simple modifications of Typed Array elements (ta[index] op= value): • Atomics.add(ta : TypedArray, index, value) : T • Atomics.sub(ta : TypedArray, index, value) : T • Atomics.and(ta : TypedArray, index, value) : T • Atomics.or(ta : TypedArray, index, value) : T • Atomics.xor(ta : TypedArray, index, value) : T 37

Slide 38

Slide 38 text

Dr. Axel Rauschmayer @rauschma Object.entries() Object.entries() returns an Array of [key,value] pairs: > Object.entries({ one: 1, two: 2 }) [ [ 'one', 1 ], [ 'two', 2 ] ] 38

Slide 39

Slide 39 text

Dr. Axel Rauschmayer @rauschma Object.entries() Easier to iterate over properties: const obj = { one: 1, two: 2 }; for (const [k, v] of Object.entries(obj)) { console.log(k, v); } // Output // "one" 1 // "two" 2 39

Slide 40

Slide 40 text

Dr. Axel Rauschmayer @rauschma Object.values() Complements Object.keys() and Object.entries(): > Object.values({ one: 1, two: 2 }) [ 1, 2 ] 40

Slide 41

Slide 41 text

Dr. Axel Rauschmayer @rauschma String padding > '1'.padStart(3, '0') '001' > 'x'.padStart(3) ' x' > '1'.padEnd(3, '0') '100' > 'x'.padEnd(3) 'x ' 41

Slide 42

Slide 42 text

Dr. Axel Rauschmayer @rauschma String padding Use cases: • Displaying tabular data in a monospaced font. • Adding a count to a file name: 'file 001.txt' • Aligning console output: 'Test 001: ✓' • Printing hexadecimal or binary numbers that have a fixed number of digits: '0x00FF' 42

Slide 43

Slide 43 text

Dr. Axel Rauschmayer @rauschma Object. getOwnPropertyDescriptors() const obj = { [Symbol('foo')]: 123, get bar() { return 'abc' }, }; console.log(Object.getOwnPropertyDescriptors(obj)); // Output: // { [Symbol('foo')]: // { value: 123, // writable: true, // enumerable: true, // configurable: true }, // bar: // { get: [Function: bar], // set: undefined, // enumerable: true, // configurable: true } } 43

Slide 44

Slide 44 text

Dr. Axel Rauschmayer @rauschma Object. getOwnPropertyDescriptors() Object.assign() is limited: can’t copy getters and setters, etc. // Copying properties const target = {}; Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); // Cloning objects const clone = Object.create( Object.getPrototypeOf(orig), Object.getOwnPropertyDescriptors(orig)); 44

Slide 45

Slide 45 text

Dr. Axel Rauschmayer @rauschma Trailing commas in function parameter lists and calls Trailing commas are legal in object and Array literals: const obj = { first: 'Jane', last: 'Doe', }; const arr = [ 'red', 'green', 'blue', ]; console.log(arr.length); // 3 45

Slide 46

Slide 46 text

Dr. Axel Rauschmayer @rauschma Trailing commas in function parameter lists and calls Two benefits: • Rearranging items is simpler (no commas to add or remove) • Version control systems can track what really changed. Versus: // From: [ 'foo' ] // To: [ 'foo', 'bar' ] 46

Slide 47

Slide 47 text

Dr. Axel Rauschmayer @rauschma Trailing commas in function parameter definitions and calls The proposal: function foo( param1, param2, ) {} foo( 'abc', 'def', ); 47

Slide 48

Slide 48 text

After ES2017 © by JD Hancock

Slide 49

Slide 49 text

Dr. Axel Rauschmayer @rauschma Stage 3 features Soon: • import() (Domenic Denicola) • Asynchronous Iteration (Domenic Denicola) • Rest/Spread Properties (Sebastian Markbage) • Lifting Template Literal Restriction (Tim Disney) • Function.prototype.toString revision (Michael Ficarra) Later: • global (Jordan Harband) • SIMD.JS – SIMD APIs (John McCutchan, Peter Jensen, Dan Gohman, Daniel Ehrenberg) 49

Slide 50

Slide 50 text

Stage 3: soon

Slide 51

Slide 51 text

Dr. Axel Rauschmayer @rauschma import() So far, ES6 modules can only be loaded statically (in a fixed manner, specified at compile time). Load modules dynamically: import('./dir/someModule.js') .then(someModule => someModule.foo()); An operator, but used like a function. 51

Slide 52

Slide 52 text

Dr. Axel Rauschmayer @rauschma import() Use cases: • Code splitting: load parts of your program on demand. • Conditional loading of modules:
 if (cond) { import(···).then(···) } • Computed module specifiers:
 import('module'+count).then(···) 52

Slide 53

Slide 53 text

Dr. Axel Rauschmayer @rauschma Rest operator for properties (destructuring) const obj = {foo: 1, bar: 2, baz: 3}; const {foo, ...rest} = obj; // Same as: // const foo = 1; // const rest = {bar: 2, baz: 3}; function f({param1, param2, ...rest}) { // rest console.log('All parameters: ', {param1, param2, ...rest}); // spread return param1 + param2; } 53

Slide 54

Slide 54 text

Dr. Axel Rauschmayer @rauschma Spread operator for properties (object literals) > const obj = {foo: 1, bar: 2}; > {...obj, baz: 3} { foo: 1, bar: 2, baz: 3 } 54

Slide 55

Slide 55 text

Dr. Axel Rauschmayer @rauschma Spread properties use cases // Cloning objects const clone1 = {...obj}; // Merging objects const merged = {...obj1, ...obj2}; // Filling in defaults const data = {...DEFAULTS, ...userData}; // Non-destructively updating property `foo` const obj = {foo: 'a', bar: 'b'}; const obj2 = {...obj, foo: 1}; // {foo: 1, bar: 'b'} 55

Slide 56

Slide 56 text

Dr. Axel Rauschmayer @rauschma Function.prototype. toString revision Improved spec of toString() for functions: • Return source code whenever possible • Previously: optional • Otherwise: standardised placeholder • Previously: must cause SyntaxError (hard to guarantee!) 56

Slide 57

Slide 57 text

Dr. Axel Rauschmayer @rauschma Template literal revision Syntax rules after backslash: • \u starts a Unicode escape, which must look like \u{1F4A4} or \u004B • \x starts a hex escape, which must look like \x4B. • \ plus digit starts an octal escape (such as \141). Octal escapes are forbidden in template literals and strict mode string literals. Illegal: latex`\unicode` windowsPath`C:\uuu\xxx\111` 57

Slide 58

Slide 58 text

Dr. Axel Rauschmayer @rauschma Template literal revision function tagFunc(tmplObj, substs) { return { Cooked: tmplObj, Raw: tmplObj.raw, }; } tagFunc`\u{4B}`; // { Cooked: [ 'K' ], Raw: [ '\\u{4B}' ] } 58

Slide 59

Slide 59 text

Dr. Axel Rauschmayer @rauschma Template literal revision Solution: tagFunc`\uu ${1} \xx` // { Cooked: [ undefined, undefined ], // Raw: [ '\\uu ', ' \\xx' ] } 59

Slide 60

Slide 60 text

Dr. Axel Rauschmayer @rauschma Asynchronous iteration // Synchronous iteration: for (const l of readLinesSync(fileName)) { console.log(l); } Problem: readLinesSync() must be synchronous. 60

Slide 61

Slide 61 text

Dr. Axel Rauschmayer @rauschma Asynchronous iteration // Asynchronous iteration: for await (const l of readLinesAsync(fileName)) { console.log(l); } Works inside: • Async functions • Async generators (new, part of proposal) 61

Slide 62

Slide 62 text

Dr. Axel Rauschmayer @rauschma Asynchronous iteration async function f() { const aI = createAsyncIterable(['a', 'b']); for await (const x of aI) { console.log(x); } } // Output: // a // b 62

Slide 63

Slide 63 text

Dr. Axel Rauschmayer @rauschma Asynchronous generators: yield async function* createAsyncIterable(syncIterable) { for (const elem of syncIterable) { yield elem; } } 63

Slide 64

Slide 64 text

Dr. Axel Rauschmayer @rauschma Asynchronous generators: await async function* id(asyncIterable) { for await (const elem of asyncIterable) { yield elem; } } 64

Slide 65

Slide 65 text

Dr. Axel Rauschmayer @rauschma Asynchronous iteration interface AsyncIterable { [Symbol.asyncIterator]() : AsyncIterator; } interface AsyncIterator { next() : Promise; } interface IteratorResult { value: any; done: boolean; } 65

Slide 66

Slide 66 text

Dr. Axel Rauschmayer @rauschma Asynchronous iteration Possible to simplify? • Keep iteration protocol • Keep for-await-of • Maybe: drop async generators • Language complexity: AG function declarations, AG function expressions, AG method definitions • Communicating sequential processes (CSP) may be a simpler solution: github.com/dvlsg/async-csp 66

Slide 67

Slide 67 text

Stage 3: later

Slide 68

Slide 68 text

Dr. Axel Rauschmayer @rauschma global Accessing the global object: • Browsers (main thread): window • Browsers (main thread & workers): self • Node.js: global // In browsers console.log(global === window); // true 68

Slide 69

Slide 69 text

SIMD: single instruction, multiple data Aw Bw Cw Ax Bx Cx + = Ay By Cy Az Bz Cz Aw Bw Cw + = Ax Bx Cx + = Ay By Cy + = Az Bz Cz + = SISD SIMD

Slide 70

Slide 70 text

Dr. Axel Rauschmayer @rauschma SIMD.JS • SIMD.JS: SIMD support in JavaScript • Example target: Intel’s SSE (Streaming SIMD Extensions) • Speed-up: up to 4 times (sometimes even more) 70

Slide 71

Slide 71 text

Dr. Axel Rauschmayer @rauschma SIMD.JS • Operands – vectors of booleans, ints, floats:
 Bool8x16, Float32x4, Uint32x4 • Operations, e.g.: SIMD.Float32x4.abs(v) SIMD.Float32x4.neg(v) SIMD.Float32x4.sqrt(v) SIMD.Float32x4.add(v, w) SIMD.Float32x4.mul(v, w) SIMD.Float32x4.equal(v, w) 71

Slide 72

Slide 72 text

Dr. Axel Rauschmayer @rauschma SIMD.JS const a = SIMD.Float32x4(1.0, 2.0, 3.0, 4.0); const b = SIMD.Float32x4(5.0, 6.0, 7.0, 8.0); const c = SIMD.Float32x4.add(a,b); 72

Slide 73

Slide 73 text

Dr. Axel Rauschmayer @rauschma SIMD.JS: data types Always 128 bits: • Booleans: SIMD.Bool8x16, SIMD.Bool16x8, SIMD.Bool32x4, SIMD.Bool64x2 • Signed integers: SIMD.Int8x16, SIMD.Int16x8, SIMD.Int32x4 • Unsigned integers: SIMD.Uint8x16, SIMD.Uint16x8, SIMD.Uint32x4 • Floating point numbers: SIMD.Float32x4, SIMD.Float64x2 73

Slide 74

Slide 74 text

Dr. Axel Rauschmayer @rauschma Farther future: big integers // Takes a BigInt as argument, returns a BigInt function nthPrime(nth) { function isPrime(p) { for (let i = 2n; i < p; i++) { if (p % i === 0n) return false; } return true; } for (let i = 2n; ; i++) { if (isPrime(i)) { if (--nth === 0n) return i; } } } 74

Slide 75

Slide 75 text

Dr. Axel Rauschmayer @rauschma Big integers • Overloaded operators • No implicit conversions or mixed operands • Numbers and bigints are not subsets of each other (you always lose if you coerce) • Prepares for value types 75

Slide 76

Slide 76 text

Dr. Axel Rauschmayer @rauschma BigInt: Staying in 64 bits const x = BigInt.asUintN(64, 1234n); const y = BigInt.asUintN(64, 5678n); const result = BigInt.asUintN(64, x*y); 76

Slide 77

Slide 77 text

Dr. Axel Rauschmayer @rauschma Trying out new ES features 77

Slide 78

Slide 78 text

Dr. Axel Rauschmayer @rauschma Trying out new ES features 78

Slide 79

Slide 79 text

Thanks! Twitter: @rauschma Books by Axel (free online): ExploringJS.com These slides: speakerdeck.com/rauschma