Ecma International approves ECMAScript 2024: What’s new?

[2024-06-26] dev, javascript, es2024
(Ad, please don’t block)

On 26 June 2024, the 127th Ecma General Assembly approved the ECMAScript 2024 language specification (press release, GitHub release), which means that it’s officially a standard now.

This blog post explains what’s new.

The editors of ECMAScript 2024  

The editors of this release are:

  • Shu-yu Guo
  • Michael Ficarra
  • Kevin Gibbons

What’s new in ECMAScript 2024?  

Grouping synchronous iterables  

Map.groupBy() groups the items of an iterable into Map entries whose keys are provided by a callback:

assert.deepEqual(
  Map.groupBy([0, -5, 3, -4, 8, 9], x => Math.sign(x)),
  new Map()
    .set(0, [0])
    .set(-1, [-5,-4])
    .set(1, [3,8,9])
);

There is also Object.groupBy() which produces an object instead of a Map:

assert.deepEqual(
  Object.groupBy([0, -5, 3, -4, 8, 9], x => Math.sign(x)),
  {
    '0': [0],
    '-1': [-5,-4],
    '1': [3,8,9],
    __proto__: null,
  }
);

For tips on choosing between these two methods and more examples, see “Exploring JavaScript”.

Promise.withResolvers()  

Promise.withResolvers() provides a new way of creating Promises that we want to resolve:

const { promise, resolve, reject } = Promise.withResolvers();

Regular expression flag /v  

The new regular expression flag /v (.unicodeSets) enables these features:

  • Escapes for Unicode string properties (😵‍💫 consists of three code points):

    // Previously: Unicode code point property `Emoji` via /u
    assert.equal(
      /^\p{Emoji}$/u.test('😵‍💫'), false
    );
    // New: Unicode string property `RGI_Emoji` via /v
    assert.equal(
      /^\p{RGI_Emoji}$/v.test('😵‍💫'), true
    );
    
  • String literals via \q{} in character classes:

    > /^[\q{😵‍💫}]$/v.test('😵‍💫')
    true
    > /^[\q{abc|def}]$/v.test('abc')
    true
    
  • Set operations for character classes:

    > /^[\w--[a-g]]$/v.test('a')
    false
    > /^[\p{Number}--[0-9]]$/v.test('٣')
    true
    > /^[\p{RGI_Emoji}--\q{😵‍💫}]$/v.test('😵‍💫')
    false
    
  • Improved matching with /i if a Unicode property escape is negated via [^···]

New features for ArrayBuffers and SharedArrayBuffers  

ArrayBuffers get two new features:

  • They can be resized in place:
    const buf = new ArrayBuffer(2, {maxByteLength: 4});
    // `typedArray` starts at offset 2
    const typedArray = new Uint8Array(buf, 2);
    assert.equal(
      typedArray.length, 0
    );
    buf.resize(4);
    assert.equal(
      typedArray.length, 2
    );
    
  • They get a method .transfer() for transferring them.

SharedArrayBuffers can be resized, but they can only grow and never shrink. They are not transferrable and therefore don’t get the method .transfer() that ArrayBuffers got.

Ensuring that strings are well-formed  

Two new methods help us ensure that strings are well-formed (w.r.t. UTF-16 code units):

  • String method .isWellFormed() checks if a JavaScript string is well-formed and does not contain any lone surrogates.
  • String method .toWellFormed() returns a copy of the receiver where each lone surrogate is replaced with the code unit 0xFFFD (which represents the code point with the same number, whose name is “replacement character”). The result is therefore well-formed.

Atomics.waitAsync()  

Atomics.waitAsync() lets us wait asynchronously for a change to shared memory. See the MDN Web Docs for more information.

Free book on ECMAScript 2024  

My book “Exploring JavaScript (ES2024 Edition)” is free to read online. Two chapters are especially relevant: