Fundamentals 11 min read

What’s New in TC39? Exploring Array.fromAsync, Unicode Validation, and Extractors

The article reviews the latest TC39 meeting outcomes, explains the criteria for advancing proposals to higher stages, and dives into three key proposals—Array.fromAsync for async iteration, String.prototype.isWellFormed for Unicode scalar validation, and extractors for pattern matching—complete with code examples and usage notes.

Alibaba Terminal Technology
Alibaba Terminal Technology
Alibaba Terminal Technology
What’s New in TC39? Exploring Array.fromAsync, Unicode Validation, and Extractors

At the recent TC39 meeting held in the Tokyo time zone, only a few proposals were submitted and three made progress, but none reached Stage 4.

Stage 2 → Stage 3

To move a proposal from Stage 2 to Stage 3 it must:

Provide a complete standard text reviewed and signed by designated TC39 members.

Obtain a signed endorsement from the ECMAScript editor.

Array.fromAsync

Proposal link: proposal-array-from-async.

In JavaScript, Array.from creates an array from an iterable object. For async iterables, developers currently use for await … of. The Array.fromAsync proposal introduces a method that returns a Promise resolving to an array built from an async iterable.

const arr = [];
for (const v of iterable) {
  arr.push(v);
}
// equivalent to
const arr = Array.from(iterable);
const arr = [];
for await (const v of asyncIterable) {
  arr.push(v);
}
function sleep() {
  return new Promise(res => setTimeout(res, 1000));
};
Array.fromAsync = async (source) => {
  const arr = [];
  for await (const entry of source) {
    arr.push(entry);
  }
  return arr;
};
const arr = [1, 2, 3, 4];
async function* asyncGen() {
  for (const i of arr) {
    await sleep();
    yield i;
  }
}
function* syncGen() {
  for (const i of arr) {
    yield i;
  }
}
(async () => {
  console.log(Array.fromAsync(syncGen()));
  console.log(Array.fromAsync(asyncGen()));
})();

Both calls immediately produce two pending promises. Awaiting them resolves the async iterator sequentially, while a synchronous iterator that yields promises resolves each promise in order.

// from syncGenWithPromise using Array.from
function* syncGenWithPromise() {
  for (const i of arr) {
    yield sleep().then(() => i);
  }
}
(async () => {
  console.log(await Array.fromAsync(syncGenWithPromise()));
  console.log(await Array.fromAsync(asyncGen()));
})();

Using Array.from on a sync iterable that yields promises runs the promises in parallel, unlike Array.fromAsync which waits sequentially.

function* syncGenWithPromise() {
  for (const i of arr) {
    // later items resolve faster
    yield sleep(2000 - i * 100).then(() => {
      console.log(`${i} resolved`);
      return i;
    });
  }
}
(async () => {
  console.log(await Promise.all(Array.from(syncGenWithPromise())));
})();

Stage 1 → Stage 2

Advancing to Stage 2 requires a draft of the full standard text.

Well‑formed Unicode strings

Proposal link: proposal-is-usv-string.

JavaScript strings are UTF‑16, but they may contain unpaired surrogate code units, which are not valid Unicode scalar values (USV). The proposal adds String.prototype.isWellFormed to test for well‑formedness and String.prototype.toWellFormed (or Node’s util.toUSVString) to convert to a valid USV string.

'\ud800'.isWellFormed(); // => false
'\ud800\udc00'.isWellFormed(); // => true

Extractor Objects

Proposal link: proposal-extractors.

Extractors, inspired by Scala’s pattern‑matching syntax, allow custom deconstruction of values. In JavaScript they can be used with binding patterns or assignment patterns.

class Foo {
  constructor(foo, bar, baz) {
    this.foo = foo;
    this.bar = bar;
    this.baz = baz;
  }
}
const foo = new Foo();
// binding pattern
const Foo(arg1, arg2) = foo;
const Foo{foo, baz} = foo;
// assignment pattern
Foo(arg1, arg2) = foo;
Foo{foo, baz} = foo;

Extractors can cooperate with pattern matching. An example shows an InstantExtractor that matches dates, Temporal.Instant values, or ISO strings, converting them to a Temporal.Instant during object destructuring.

const InstantExtractor = {
  [Symbol.matcher]: value =>
    value instanceof Temporal.Instant ? { matched: true, value: [value] } :
    value instanceof Date ? { matched: true, value: [Temporal.Instant.fromEpochMilliseconds(value.getTime())] } :
    typeof value === "string" ? { matched: true, value: [Temporal.Instant.from(value)] } :
    { matched: false }
};
class Book {
  constructor({
    title,
    createdAt: InstantExtractor(createdAt) = Temporal.Now.instant(),
    modifiedAt: InstantExtractor(modifiedAt) = createdAt
  }) {
    this.title = title;
    this.createdAt = createdAt;
    this.modifiedAt = modifiedAt;
  }
}

These proposals aim to enrich JavaScript’s core language capabilities, offering more expressive and safer ways to handle async data, Unicode strings, and pattern‑based deconstruction.

Conclusion

The JavaScript Chinese Interest Group (JSCIG) invites developers to discuss these and other ECMAScript proposals on GitHub at the esdiscuss repository.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

UnicodeTC39Array.fromAsyncExtractors
Alibaba Terminal Technology
Written by

Alibaba Terminal Technology

Official public account of Alibaba Terminal

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.