Upgrade to Pro — share decks privately, control downloads, hide ads and more …

TC39, ECMAScript, and the Future of JavaScript

TC39, ECMAScript, and the Future of JavaScript

We’ll start by glancing at the TC39 proposal revision process – how new features are proposed, how proposals move through revision stages, and why some make the cut while others don’t. Then we’ll have a look at a few proposals in the pipeline – like object spread, async iterators, async generators, and *import()*. Last, we’ll move to more exciting stuff – automated code style fixes, compile-time startup optimizations, and the future of writing JavaScript code.

Nicolás Bevacqua

June 24, 2017
Tweet

More Decks by Nicolás Bevacqua

Other Decks in Programming

Transcript

  1. TC39, ECMAScript, and the Future of JavaScript

  2. ponyfoo.com twitter.com/nzgb

  3. ponyfoo.com/books

  4. What’s TC39?

  5. isNaN(NaN) // true isNaN(“A”) // true “A” == NaN //

    false “A” === NaN // false NaN === NaN // false … Solution: Number.isNaN(“A”) // false Number.isNaN(NaN) // true
  6. isNaN(NaN) // true isNaN(“A”) // true “A” == NaN //

    false “A” === NaN // false NaN === NaN // false … Solution: Number.isNaN(“A”) // false Number.isNaN(NaN) // true
  7. isNaN(NaN) // true isNaN(“A”) // true “A” == NaN //

    false “A” === NaN // false NaN === NaN // false … Solution: Number.isNaN(“A”) // false Number.isNaN(NaN) // true
  8. isNaN(NaN) // true isNaN(“A”) // true “A” == NaN //

    false “A” === NaN // false NaN === NaN // false … Solution: Number.isNaN(“A”) // false Number.isNaN(NaN) // true
  9. +0 == -0 // true +0 === -0 // true

    1/+0 === 1/-0 // false
  10. Write valid JavaScript with only +!()[] jsfuck.com

  11. Specification Development Process

  12. Living Standard tc39.github.io/ecma262 github.com/tc39/proposals

  13. Stage 0

  14. Stage 1

  15. Stage 2

  16. Stage 3

  17. Stage 4

  18. prop-tc39.now.sh

  19. Release Cadence

  20. Proposals

  21. Array#includes (Stage 4) [1,2].indexOf(2) !== -1 // true [1,2].indexOf(3) !==

    -1 // false [1,2].includes(2) // true [1,2].includes(3) // false
  22. Array#includes (Stage 4) [1,2].indexOf(2) !== -1 // true [1,2].indexOf(3) !==

    -1 // false [1,2].includes(2) // true [1,2].includes(3) // false
  23. Async Functions (Stage 4) fetch(‘/api/products’) .then(res => res.json()) .then(data =>

    {
 updateView(data) }) .catch(err => { console.log(‘Update failed’, err) })
  24. Async Functions (Stage 4) fetch(‘/api/products’) .then(res => res.json()) .then(data =>

    {
 updateView(data) }) .catch(err => { console.log(‘Update failed’, err) })
  25. Async Functions (Stage 4) fetch(‘/api/products’) .then(res => res.json()) .then(data =>

    {
 updateView(data) }) .catch(err => { console.log(‘Update failed’, err) })
  26. Async Functions (Stage 4) fetch(‘/api/products’) .then(res => res.json()) .then(data =>

    {
 updateView(data) }) .catch(err => { console.log(‘Update failed’, err) })
  27. Async Functions (Stage 4) await fetch(‘/api/products’) .then(res => res.json()) .then(data

    => {
 updateView(data) }) .catch(err => { console.log(‘Update failed’, err) })
  28. Async Functions (Stage 4) const res = await fetch(‘/api/products’) .then(res

    => res.json()) .then(data => {
 updateView(data) }) .catch(err => { console.log(‘Update failed’, err) })
  29. Async Functions (Stage 4) const res = await fetch(‘/api/products’) const

    data = await res.json() .then(data => {
 updateView(data) }) .catch(err => { console.log(‘Update failed’, err) })
  30. Async Functions (Stage 4) const res = await fetch(‘/api/products’) const

    data = await res.json()
 updateView(data) .catch(err => { console.log(‘Update failed’, err) })
  31. Async Functions (Stage 4) try { const res = await

    fetch(‘/api/products’) const data = await res.json()
 updateView(data) } catch(err) { console.log(‘Update failed’, err) }
  32. Async Functions (Stage 4) async function main() { try {

    const res = await fetch(‘/api/products’) const data = await res.json()
 updateView(data) } catch(err) { console.log(‘Update failed’, err) } }
  33. Async Functions (Stage 4) (async () => { try {

    const res = await fetch(‘/api/products’) const data = await res.json()
 updateView(data) } catch(err) { console.log(‘Update failed’, err) } })()
  34. Async Functions (Stage 4) (async () => { try {

    const res = await fetch(‘/api/products’) const data = await res.json()
 updateView(data) } catch(err) { console.log(‘Update failed’, err) } })() await (2 + 3)
  35. Async Functions (Stage 4) (async () => { try {

    const res = await fetch(‘/api/products’) const data = await res.json()
 updateView(data) } catch(err) { console.log(‘Update failed’, err) } })() `Price: ${ await getPrice() }`
  36. Async Functions (Stage 4) (async () => { try {

    const res = await fetch(‘/api/products’) const data = await res.json()
 updateView(data) } catch(err) { console.log(‘Update failed’, err) } })() renderView(await getPrice())
  37. Async Functions (Stage 4) (async () => { try {

    const res = await fetch(‘/api/products’) const data = await res.json()
 updateView(data) } catch(err) { console.log(‘Update failed’, err) } })() 2 * (await getPrice())
  38. Async Functions (Stage 4) const sleep = delay => new

    Promise(resolve => setTimeout(resolve, delay) ) const slowLog = async (...terms) => { await sleep(2000) console.log(...terms) } slowLog(‘Well that was underwhelming’) .then(() => console.log(‘Nailed it!’)) .catch(reason => console.error(‘Failed’, reason))
  39. Async Iteration (Stage 3) const list = { [Symbol.iterator]() {

    let i = 0 return { next: () => ({ value: i++, done: i > 5 }) } } } [...list] // <- [0, 1, 2, 3, 4] Array.from(list) // <- [0, 1, 2, 3, 4] for (const i of list) { // <- 0, 1, 2, 3, 4 }
  40. Async Iteration (Stage 3) const list = { [Symbol.iterator]() {

    let i = 0 return { next: () => ({ value: i++, done: i > 5 }) } } } [...list] // <- [0, 1, 2, 3, 4] Array.from(list) // <- [0, 1, 2, 3, 4] for (const i of list) { // <- 0, 1, 2, 3, 4 }
  41. Async Iteration (Stage 3) const list = { [Symbol.iterator]() {

    let i = 0 return { next: () => ({ value: i++, done: i > 5 }) } } } [...list] // <- [0, 1, 2, 3, 4] Array.from(list) // <- [0, 1, 2, 3, 4] for (const i of list) { // <- 0, 1, 2, 3, 4 }
  42. Async Iteration (Stage 3) const list = { [Symbol.asyncIterator]() {

    let i = 0 return { next: () => Promise.resolve({ value: i++, done: i > 5 }) } } }
  43. Async Iteration (Stage 3) const list = { [Symbol.asyncIterator]() {

    let i = 0 return { next: () => Promise.resolve({ value: i++, done: i > 5 }) } } } for await (const i of items) { // <- 0, 1, 2, 3, 4 }
  44. Async Iteration (Stage 3) const list = { [Symbol.asyncIterator]() {

    let i = 0 return { next: () => Promise.resolve({ value: i++, done: i > 5 }) } } } async function readItems() { for await (const i of items) { // <- 0, 1, 2, 3, 4 } }
  45. Async Iteration (Stage 3) async function* getProducts(categoryUrl) { const listReq

    = await fetch(categoryUrl) const list = await listReq.json() for (const product of list) { const productReq = await product.url const product = await productReq.json() yield product } }
  46. Async Iteration (Stage 3) async function* getProducts(categoryUrl) { const listReq

    = await fetch(categoryUrl) const list = await listReq.json() for (const product of list) { const productReq = await product.url const product = await productReq.json() yield product } } async function readProducts() { const g = getProducts(category) for await (const product of g) { // use product details } }
  47. Rest/Spread Properties (Stage 3) Object.assign( {}, { a: "a" },

    { b: "b" }, { a: "c" } ) { ...{ a: "a" }, ...{ b: "b" }, ...{ a: "c" } } // <- { a: "c", b: "b"}
  48. Rest/Spread Properties (Stage 3) Object.assign( {}, { a: "a" },

    { b: "b" }, { a: "c" } ) { ...{ a: "a" }, ...{ b: "b" }, ...{ a: "c" } } // <- { a: "c", b: "b"}
  49. Rest/Spread Properties (Stage 3) Object.assign( {}, { a: "a" },

    { b: "b" }, { a: "c" } ) { ...{ a: "a" }, ...{ b: "b" }, ...{ a: "c" } } // <- { a: "c", b: "b"}
  50. Rest/Spread Properties (Stage 3) const item = { id: '4fe09c27',

    name: 'Banana', amount: 3 } const { id, ...rest } = item // <- { name: 'Banana', amount: 3 }
  51. Rest/Spread Properties (Stage 3) function print({ id, ...rest }) {

    console.log(rest) } print({ id: '4fe09c27', name: 'Banana' }) // <- { name: 'Banana'}
  52. Dynamic import() (Stage 3) import markdown from './markdown' // ...

    export default compile
  53. Dynamic import() (Stage 3) import(`./i18n.${ navigator.language }.js`) .then(module => console.log(module.messages))

    .catch(reason => console.error(reason))
  54. Named Captures (Stage 3) const urlRegExp = /^(?: (http[s]?|ftp):\/)?\/?([^:\/ \s]+)((?:\/\w+)*\/)([\w\-\.]+

    [^#?\s]+)([^#]*)?(#[\w\-]+)?$/
  55. Named Captures (Stage 3) const urlRegExp = /^(?:(? <protocol>http[s]?|ftp):\/)? \/?(?<host>[^:\/\s]+)(?

    <path>(?:\/\w+)*\/)(? <file>[\w\-\.]+[^#?\s]+)(? <query>[^#]*)?(?<hash>#[\w\-] +)?$/u
  56. Named Captures (Stage 3) const urlRegExp = /^(?<url>(? <protocol>http[s]?|ftp):\/)? \/?(?<host>[^:\/\s]+)(?

    <path>(?:\/\w+)*\/)(? <file>[\w\-\.]+[^#?\s]+)(? <query>.*)?(?<hash>#[\w\-]+)? $/ const url = 'https://commits.com/8b48e3/diff?w=1#readme' const { groups } = urlRegExp.exec(url) console.log(groups) { protocol: 'https', host: 'commits.com', path: '/8b48e3/', file: 'diff', query: '?w=1', hash: '#readme' }
  57. Named Captures (Stage 3) const urlRegExp = /^(?<url>(? <protocol>http[s]?|ftp):\/)? \/?(?<host>[^:\/\s]+)(?

    <path>(?:\/\w+)*\/)(? <file>[\w\-\.]+[^#?\s]+)(? <query>.*)?(?<hash>#[\w\-]+)? $/ const url = 'https://commits.com/8b48e3/diff?w=1#readme' const pattern = '$<protocol>://github.com/$<file>' const replaced = url.replace(urlRegExp, pattern) console.log(replaced) // <- 'https://github.com/diff'
  58. Named Captures (Stage 3) const urlRegExp = /^(?<url>(? <protocol>http[s]?|ftp):\/)? \/?(?<host>[^:\/\s]+)(?

    <path>(?:\/\w+)*\/)(? <file>[\w\-\.]+[^#?\s]+)(? <query>.*)?(?<hash>#[\w\-]+)? $/ const duplicateRegExp = /^(.*)=\1$/ const duplicateRegExp = /^(?<thing>.*)=\k<thing>$/u duplicateRegExp.test('a=b') // <- false duplicateRegExp.test('a=a') // <- true duplicateRegExp.test('aa=a') // <- false duplicateRegExp.test('bbb=bbb') // <- true
  59. Unicode Escapes (Stage 3) /^\p{Script=Greek}$/u.test('π') // <- true /^\P{Script=Greek}$/u.test('π') //

    <- false
  60. Lookbehind Assertions (Stage 3) /\d+/.test('¥1245') // <- true /(?<!¥)\d+/.test('¥1245') //

    <- false /(?<!¥)\d+/.test('$1245') // <- true
  61. Lookbehind Assertions (Stage 3) /\d+/.test('¥1245') // <- true /(?<!¥)\d+/.test('¥1245') //

    <- false /(?<!¥)\d+/.test('$1245') // <- true /(?<=¥)\d+/.test('¥1245') // <- true /(?<=¥)\d+/.test('$1245') // <- false
  62. Class Decorators (Stage 2) @pure @decorators.elastic() class View { @throttle(200)

    reconcile() { } }
  63. Class Decorators (Stage 2) @pure @decorators.elastic() class View { @throttle(200)

    reconcile() { } } function readonly({ descriptor, ...rest }) { return { ...rest, descriptor: { ...descriptor, writable: false } } }
  64. Promise#finally (Stage 2) showSpinner() fetch(productUrl) .then(renderProduct) .then( hideSpinner, hideSpinner )

  65. Promise#finally (Stage 2) showSpinner() fetch(productUrl) .then(renderProduct) .finally( hideSpinner )

  66. Future of JavaScript

  67. None
  68. None
  69. None
  70. None
  71. None
  72. None
  73. None
  74. None
  75. None
  76. None
  77. Prepack

  78. Resources ponyfoo.com/articles/es6 ponyfoo.com/articles/understanding-javascript-async-await ponyfoo.com/articles/regular-expressions-post-es6 ponyfoo.com/articles/standard ponyfoo.com/articles/javascript-asynchronous-iteration-proposal ponyfoo.com/books/practical-modern-javascript/chapters prop-tc39.now.sh github.com/tc39/proposals twitter.com/nzgb

  79. Thanks!