1 of 81

ಸ್ವಾಗತ!

2 of 81

About Me

  • Ujjwal Sharma (ryzokuken)
  • from New Delhi, India
  • based out of A Coruña, Galiza
  • OSS zealot, open web maximalist
  • love dogs, (masochistic) videogames
  • work at Igalia

ECMAScript

3 of 81

About

  • An open-source consultancy
  • A worker-owned cooperative
  • Extensive work across major open source projects and ecosystems
  • Linux kernel, userspace and multimedia
  • Major contributor in the web platform and browser projects
  • Compilers (JS engines, LLVM) and PL design (WASM, JS)

@ryzokuken

4 of 81

@ryzokuken

5 of 81

Everybody asks �"What is JavaScript?"

Nobody asks �"How is JavaScript?"

@ryzokuken

6 of 81

Did you know that JavaScript is standardized?

@ryzokuken

7 of 81

What even is a

Standards Body?

1

@ryzokuken

8 of 81

Do you remember 🧀?

@ryzokuken

9 of 81

They’re venues for

unification & uniformization

  • WHATWG
  • W3C
  • ISO
  • ECMA
  • Unicode

@ryzokuken

10 of 81

TC39 is the Technical Committee that defines the JavaScript language

@ryzokuken

11 of 81

Delegates

  • Implementers (Apple, Google, Mozilla, Microsoft, …)
  • Companies (Sony, Netflix, Bloomberg, …)
  • Students and NPF (Universities, OpenJS F, …)

Invited Experts

  • Subject matter experts
  • Community representatives

Contributors, Editors, Reviewers & Community

Who participates?

@ryzokuken

12 of 81

Glossary …

  • ECMA
  • Technical Committee (TC39 , TC53, TC55)
  • TG2, TG3, TG4, TG5
  • ECMA-262 …
  • ECMAScript

@ryzokuken

13 of 81

How does

TC39 work?

2

@ryzokuken

14 of 81

Consensus-based decisions

Diverse set of people in the committee

Implementers, Practitioners, Community Experts, Academics

Objections and concerns to satisfy everyone

No stakeholder has more power than others, concerns must be rational

@ryzokuken

15 of 81

STAGES

Steps where proposal evolves and receives feedback

4 stages of maturity ← more on this later! 😉

@ryzokuken

16 of 81

TASK GROUPS

TC39 charters sub-groups to work on focus areas:

👷 TG1: The core ECMAScript specification�👷 TG2: Internationalisation�👷 TG3: Security�👷 TG4: Sourcemaps�👷 TG5: Research on Language Standardization 🆕

@ryzokuken

17 of 81

Where

18 of 81

Where

19 of 81

Where

20 of 81

When

6 Plenary Meetings a year

Online or In person

Focus Groups and Incubator Calls

Monthly or Biweekly

TG2 / Editors / Outreach / Proposals / Educators / Tools

Monthly or Biweekly

@ryzokuken

21 of 81

The Process

3

Stage-by-stage

2.7 &

@ryzokuken

22 of 81

STAGE 0

Strawperson

Just an Idea

Explainer, idea under discussion

Oversimplified proposal

23 of 81

24 of 81

STAGE 1

Describe the shape of a solution it’s an idea under discussion

Proposal

Devote time and have a “Champion”

Demos / Polyfills

Major changes

25 of 81

STAGE 1

Signals

Daniel Ehrenberg, Yehuda Katz, Jatin Ramanathan, Shay Lewis, Kristen Hewell Garrett, Dominic Gannaway, Preston Sego, Milo M, Rob Eisenberg

26 of 81

// A VanillaJS Counter

let counter = 0;

const setCounter = (value) => {

counter = value;

render();

};

const isEven = () => (counter & 1) == 0;

const parity = () => isEven() ? "even" : "odd";

const render = () => element.innerText = parity();

// Simulate external updates to counter...

setInterval(() => setCounter(counter + 1), 1000);

27 of 81

const counter = new Signal.State(0);

const isEven = new Signal.Computed(() => (counter.get() & 1) == 0);

const parity = new Signal.Computed(() => isEven.get() ? "even" : "odd");

28 of 81

STAGE 1

Decimal

Jesse Alama, Andrew Paprocki

29 of 81

0.1 + 0.2 === 0.3

30 of 81

Sync Imports

Pattern Matching

Stabilize

Type Annotations

STAGE 1 🧐

Iterator Unique

Object pick/omit

...and around 80 others

31 of 81

STAGE 2

Draft

Describe syntactic and semantic details

Form spec language - Initial Spec Text

Semantics and API are covered - not completed

TC39 Expects that feature would be developed in future

Experimental

32 of 81

STAGE 2

Async Context

Andreu Botella, Chengzhong Wu, Justin Ridgewell

33 of 81

const asyncVar = new AsyncContext.Variable();

let snapshot

asyncVar.run("A", () => {

snapshot = new AsyncContext.Snapshot();

});

34 of 81

STAGE 2

Iterator Chunking

Michael Ficarra

35 of 81

const digits = () => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9].values();

let chunksOf2 = Array.from(digits().chunks(2));

// [ [0, 1], [2, 3], [4, 5], [6, 7], [8, 9] ]

let windowsOf3 = Array.from(digits().windows(3));

// [ [0, 1, 2], [1, 2, 3], [2, 3, 4], [3, 4, 5], [4, 5, 6], [5, 6, 7], [6, 7, 8], [7, 8, 9] ]

36 of 81

STAGE 2

Extractors

Ron Buckton

37 of 81

const Foo(y) = x; // instance-array destructuring

const Foo([y]) = x; // nested array destructuring

const Foo({y}) = x; // nested object destructuring

const [Foo(y)] = x; // nesting

const { z: Foo(y) } = x; // ..

const Foo(Bar(y)) = x; // ..

const X.Foo(y) = x; // qualified names (i.e., a.b.c)

Foo(y) = x; // instance-array destructuring

Foo([y]) = x; // nestedarray destructuring

Foo({y}) = x; // nested object destructuring

[Foo(y)] = x; // nesting

({ z: Foo(y) } = x); // ..

Foo(Bar(y)) = x; // ..

X.Foo(y) = x; // qualified names (i.e., a.b.c)

38 of 81

After Stage 2 comes...

Stage 2.7!

@ryzokuken

39 of 81

Why introduce a new stage?

High quality implementations need tests

...but tests can be expensive to write and costly to iterate as the design changes

Test authors want to know when the design is stable ➡ Stage 2.7

Implementers want to know when the tests are ready ➡ Stage 3

🤔

@ryzokuken

40 of 81

STAGE 2.7

Candidate

🧪

Approved in principle but still needs feedback from testing and implementers

We have full spec text!

Reviewers and Editors have signed off the spec text

We will create test262 conformance tests

We might create spec-compliant implementations/polyfills

New!

41 of 81

test262.fyi

Test262(Github)

@ryzokuken

42 of 81

STAGE 2.7

Upsert

Daniel Minor

43 of 81

// Currently

let prefs = new getUserPrefs();

if (!prefs.has("useDarkmode")) {

prefs.set("useDarkmode", true); // default to true

}

// Using getOrInsert

let prefs = new getUserPrefs();

prefs.getOrInsert("useDarkmode", true); // default to true

44 of 81

STAGE 2.7

ShadowRealm

Dave Herman, Mark Miller, Caridy Patiño, Leo Balter, Rick Waldron, Chengzhong Wu

45 of 81

const shadowRealm = new ShadowRealm();

// pluginFramework and pluginScript become available in the ShadowRealm

const [ init, ready ] = await Promise.all([

shadowRealm.importValue('./pluginFramework.js', 'init'),

shadowRealm.importValue('./pluginScript.js', 'ready'),

]);

// The Plugin Script will execute within the ShadowRealm

init(ready);

46 of 81

STAGE 2.7

Math.sumPrecise

Kevin Gibbons

47 of 81

1e20 + 0.1 + -1e20 === 0

Math.sumPrecise([1e20, 0.1, -1e20]) === 0.1

48 of 81

STAGE 3

Recommended for implementation

🥉

Implementation and validation phase�(feedback from implementers, web-compatibility)

Tests have been created for test262

We will only change things if implementation reveals new information

Engines will begin implementing

Browsers may start shipping with or without a flag

49 of 81

STAGE 3

Deferred Evaluation

Yulia Startsev, Nicolò Ribaudo

50 of 81

// This fetches but does NOT evaluate "mod"

import defer * as ns from "mod";

function rarelyUsed () {

// "mod" is lazily evaluated on first use of `ns`

console.log(ns.prop);

}

...

New!

51 of 81

STAGE 3

Temporal

Philipp Dunkel , Maggie Johnson-Pint,

Matt Johnson-Pint, Brian Terlson,�Shane Carr, Ujjwal Sharma, Philip Chimento, Jason Williams, Justin Grant

52 of 81

53 of 81

const yearMonth = Temporal.PlainYearMonth.from({ year: 2020, month: 10 });

yearMonth.toString() // => 2020-10

yearMonth.daysInMonth; // => 31

yearMonth.daysInYear; // => 366

const monthDay = Temporal.PlainMonthDay.from({ month: 7, day: 14 });

const date = monthDay.toPlainDate({ year: 2030 });

date.dayOfWeek; // => 7

date.dayOfYear; // => 195

date.daysInMonth; // => 31

date.daysInYear; // => 365

date.inLeapYear; // => false

54 of 81

let calcDate = Temporal.Now.plainDateISO(); // => 2021-11-29

calcDate.add({ days : 15 }); // => 2021-12-14

calcDate.subtract({ days : 15 }); // => 2021-11-14

calcDate.equals(calcDate); // => true

calcDate.equals(calcDate.add({ days : 2})); // => false

55 of 81

const time = Temporal.Instant.fromEpochSeconds(new Date);

Temporal.TimeZone.from('Europe/Berlin').getOffsetStringFor(time);

// => +01:00

Temporal.TimeZone.from('America/Vancouver').getOffsetStringFor(time)

// => -08:00

Temporal.TimeZone.from('Europe/Moscow').getOffsetStringFor(time);

// => +03:00

56 of 81

STAGE 3

Decorators

Kristen Hewell Garrett

57 of 81

function bound(value, { name, addInitializer }) {

addInitializer(function () {

this[name] = this[name].bind(this);

});

}

class C {

message = "hello!";

@bound

m() {

console.log(this.message);

}

}

let { m } = new C();

m(); // hello!

58 of 81

STAGE 4

Finished

About to be include in the upcoming edition of ECMAScript®

We have two implementations that pass the acceptance tests

We have real-life experience of shipping the feature

We have merged the feature into the Spec��It might not yet be shipping in all mainstream engines

The feature will be included in the next yearly edition, e.g. ES2024

59 of 81

STAGE 4

ArrayBuffer transfer

Shu-yu Guo, Jordan Harband, Yagiz Nizipli

60 of 81

function validateAndWriteSafeAndFast(arrayBuffer) {

// Transfer to take ownership, which implementations can choose to

// implement as a zero-copy move.

const owned = arrayBuffer.transfer();

// arrayBuffer is detached after this point.

assert(arrayBuffer.detached);

await validate(owned);

await fs.writeFile("data.bin", owned);

}

61 of 81

STAGE 4

Set Methods

Kevin Gibbons

62 of 81

let odds = new Set([1, 3, 5, 7, 9, 11, 13]);

let primes = new Set([2, 3, 5, 7, 11, 13]);

let oddPrimes = primes.intersection(odds);

// Set { 3, 5, 7, 11, 13 }

let evenPrimes = primes.difference(odds);

// Set { 2 }

63 of 81

Array Grouping

Atomics.waitAsync

Promise.withResolvers

Well-Formed Unicode Strings

RegExp v flag�+ set notation�+ properties of strings

Resizable & growable ArrayBuffers

STAGE 4 🎉

ArrayBuffer transfer

64 of 81

ECMAScript 2025

ES.next

25th June

esbuild

65 of 81

Case Study

4

@ryzokuken

66 of 81

Problem

  • Date is broken in ways that cannot be fixed without breaking the web.
  • Included in the original 10-day JavaScript engine hack Based on java.util.Date, which itself was deprecated in 1997 due to being a terrible API
  • For all of JavaScript's history, the built-in Date has remained very hard to work with directly.

@ryzokuken

67 of 81

Moment.js

  • Many ecosystem solutions exist, out of which Moment.js is perhaps the most popular.
  • Developers who use these libraries pay a “data tax” which can only be avoided by compiling Date DSLs into actual code which is still problematic.

@ryzokuken

68 of 81

69 of 81

70 of 81

Hobbyists/Tinkerers

⬇️

Subject Matter Experts

PL Designers

@ryzokuken

71 of 81

72 of 81

73 of 81

Hobbyists/Tinkerers

⬇️

Subject Matter Experts

PL Designers

⬇️

Implementers

Security Researchers

@ryzokuken

74 of 81

Hobbyists/Tinkerers

⬇️

Subject Matter Experts

PL Designers

⬇️

Implementers

Security Researchers

@ryzokuken

Students!?

75 of 81

76 of 81

77 of 81

Hobbyists/Tinkerers

⬇️

Experts and PL Designers

⬇️

Implementers

Students and Researchers

⬇️

Users

@ryzokuken

78 of 81

Collaboration & Help

Get involved!

5

@ryzokuken

79 of 81

Write test262 conformance tests

Refine proposals in GitHub issues

Write documentation and educational materials

Provide feedback on GitHub

@ryzokuken

80 of 81

  • BigInt
  • Class Fields
  • Private Methods
  • Top-Level await
  • Intl
    • DisplayNames
    • NumberFormat
    • Segmenter
  • String#replaceAll

What did Igalia achieve anyway?

  • Temporal
  • Import Assertions
  • Decimal
  • Type Annotations
  • Source Maps

@ryzokuken

81 of 81

🙏

ಧನ್ಯವಾದಗಳು