What’s New in ECMAScript? Inside the Journey from Stage 0 to Stage 4 Proposals
This article reviews recent TC39 proposals—including Intl.Enumeration, Explicit Resource Management, Set Methods, Well‑Formed Unicode strings, ArrayBuffer transfer, and others—explaining their stage‑gate requirements, core API changes, example code, and how they advance the JavaScript language.
Stage 3 → Stage 4
Intl.Enumeration has reached Stage 4 after two and a half years, while proposals such as Explicit Resource Management and Set Methods have progressed to Stage 3.
All proposal features must have corresponding tc39/test262 tests that are merged into the test suite.
At least two implementations must pass those tests and ship in a formal release.
A pull request merging the proposal into the tc39/ecma262 standard text must be approved by the ECMAScript editor.
Intl.Enumeration
The proposal adds Intl.supportedValuesOf(key) to retrieve all supported values for a given internationalization option such as calendar, currency, or timeZone.
console.log(Intl.supportedValuesOf('calendar'));
// ['buddhist', 'chinese', 'coptic', 'dangi', ...]Stage 2 → Stage 3
Advancing from Stage 2 to Stage 3 requires a complete draft of the specification text reviewed and signed off by TC39 members, and the ECMAScript editor’s approval.
Set Methods
This proposal enriches the Set object with a suite of set‑theoretic operations:
Set.prototype.intersection(other) Set.prototype.union(other) Set.prototype.difference(other) Set.prototype.symmetricDifference(other) Set.prototype.isSubsetOf(other) Set.prototype.isSupersetOf(other) Set.prototype.isDisjointFrom(other)All methods accept another Set or any object implementing .size, .keys, and .has.
Well‑formed Unicode strings
The proposal introduces String.prototype.isWellFormed to check whether a string consists solely of valid Unicode scalar values (USV), and String.prototype.toWellFormed to convert an arbitrary string into a well‑formed USV string. Node.js also provides util.toUSVString. Polyfills are available under string.prototype.iswellformed and string.prototype.towellformed.
'\ud800'.isWellFormed(); // false
'\ud800\udc00'.isWellFormed(); // trueExplicit Resource Management
The proposal adds a using keyword to declare resources that are automatically disposed when the surrounding block exits, leveraging Symbol.disposable. It simplifies patterns previously expressed with generator return or manual finally calls.
function* g() {
using handle = acquireFileHandle(); // resource tied to block
}
{ using obj = g(); const r = obj.next(); } // automatic releaseNode.js FileHandle.close() and WHATWG StreamReader reader.releaseLock() can also be used with this syntax.
Stage 1 → Stage 2
Moving to Stage 2 requires a draft of the full specification text covering the proposal.
ArrayBuffer transfer
The ArrayBuffer.prototype.transfer method, derived from the ResizableArrayBuffer proposal, enables ownership transfer of an ArrayBuffer without copying, improving performance in scenarios such as Web Workers.
function validateAndWriteSafeAndFast(ab) {
const owned = ab.transfer();
assert(ab.detached);
await validate(owned);
await fs.writeFile('data.bin', owned);
}Stage 0 → Stage 1
Requirements include finding a TC39 champion, defining the problem and solution, providing examples, and discussing API shape, algorithms, semantics, and implementation risks.
Intl MessageResource
The proposal adds a static Intl.MessageFormat.parseResource method to parse an entire MF2 resource file at once, allowing simultaneous resolution of multiple messages.
const res = Intl.MessageFormat.parseResource(resource, ['en']);
const greeting = res.get('morning_greeting').resolveMessage({user: 'Alice'});
console.log(greeting.toString()); // 'Good morning, Alice'Intl era and monthCode
This ECMAScript 402 proposal refines era and month‑code handling for calendars beyond the ISO‑8601 baseline, complementing the Temporal proposal.
Mass Proxy Revocation
The proposal adds Proxy.createSignal and Proxy.finalizeSignal to revoke many proxies at once, even those created with new Proxy.
const s1 = Proxy.createSignal();
const p1 = new Proxy([], {}, {signal: s1});
const {proxy: p2, revoke} = Proxy.revocable({}, {}, {signal: s1});
Proxy.finalizeSignal(s1); // both p1 and p2 are revokedSummary
The JavaScript Chinese Interest Group (JSCIG) coordinated by He Shijun and the Alibaba Front‑End Standardization team hosts open discussions on these ECMAScript proposals on GitHub (esdiscuss), welcoming contributions from the community.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
