EcmaScript 2026 (17th edition) is out now | Plamen Stoev / Personal Blog
Photo by Christian GAFENESCH on Unsplash
Overview
Ecma-262 has just been released in July 1st. I’m eager to dive in the features most of which have already been implemented.
Math.sumPrecise()
Motivation:
The sum of numbers is one of the last common reasons to reach for Array.prototype.reduce, so this release features a dedicated function (Math.sumPrecise) to sum all values in an array/iterable of numbers using Shewchuk ’96 algorithm. Yet, no luck summing 0.1 + 0.2
Proposal:
let values = [1e20, 0.1, -1e20];<br>values.reduce((a, b) => a + b, 0); // 0<br>Math.sumPrecise(values); // 0.1
Iterator.concat(…iterators)
Motivation:
More declarative way to consume two or more iterators in sequence as if they were one.
Proposal:
let lows = Iterator.from([0, 1, 2, 3]);<br>let highs = Iterator.from([6, 7, 8, 9]);<br>let digits = Iterator.concat(lows, [4, 5], highs);<br>Array.from(digits); // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Array.fromAsync()
Motivation:
The Array.from() async counterpart where an async iterator can be dumped instead of the usual for await loop. Demand is proven it-all npm package has 200K+ weekly downloads.
Proposal:
// Replace:<br>const result = [];<br>for await (const element of items) {<br>result.push(element);
// With:<br>Array.fromAsync(items)
Error.isError
Motivation:
There is no reliable way to test whether a value is genuine Error:<br>instanceof Error returns false negatives<br>Object.prototype.toString.call(x) === '[object Error]' is spoofable since Symbol.toStringTag was introduced
Proposal:
Error.isError(errorInstance); // returns true or false (analogous to Array.isArray(value)
Note: MDN warns this is not fully compatible yet for Safari (desktop and mobile) as of today.
Upsert (i.e. Map/WeakMap.getOrInsert())
Motivation:
A common problem when using Map or WeakMap is how to handle doing an update when you’re not sure if the key already exists in the map. This is currently handled by checking if the key is present and then inserting or updating depending on the case. This is suboptimal and this feature exists to fix that.
Proposal:
// Currently<br>let prefs = getUserPrefsMap();<br>if (!prefs.has("useDarkmode")) {<br>prefs.set("useDarkmode", true); // default to true
// Using getOrInsert<br>let prefs = getUserPrefsMap();<br>prefs.getOrInsert("useDarkmode", true); // default to true
This proposal features another addition. The addition of getOrInsertComputed() for some specific cases:
// Using getOrInsertComputed<br>let grouped = new Map();<br>for (let [key, ...values] of data) {<br>grouped.getOrInsertComputed(key, () => []).push(...values);
Uint8Array to/from base64 and hex
Motivation:
There is no specialized way to encode and decode to and from base64 and hex. This feature addresses that.
Proposal:
// Basic API:
let arr = new Uint8Array([72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100]);<br>console.log(arr.toBase64());<br>// 'SGVsbG8gV29ybGQ='<br>console.log(arr.toHex());<br>// '48656c6c6f20576f726c64'
let string = 'SGVsbG8gV29ybGQ=';<br>console.log(Uint8Array.fromBase64(string));<br>// Uint8Array([72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100])
string = '48656c6c6f20576f726c64';<br>console.log(Uint8Array.fromHex(string));<br>// Uint8Array([72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100])
Check out this MDN article for additional toBase64() options.
JSON.parse source text access
Motivation:
Addresses a decades old problem of parsing a JSON strings. Transformation between ECMAScript values and JSON text is lossy. This is most obvious in the case of deserializing numbers (e.g., "999999999999999999", "999999999999999999.0", and "1000000000000000000" all parse to 1000000000000000000), but also comes up when attempting to round-tripping non-primitive values such as Date objects (e.g., JSON.parse(JSON.stringify(new Date("2018-09-25T14:00:00Z"))) yields a string "2018-09-25T14:00:00.000Z").
Proposal:
// Illustrative examples:
const digitsToBigInt = (key, val, {source}) =><br>/^[0-9]+$/.test(source) ? BigInt(source) : val;
const bigIntToRawJSON = (key, val) =><br>typeof val === "bigint" ? JSON.rawJSON(String(val)) : val;
const tooBigForNumber = BigInt(Number.MAX_SAFE_INTEGER) + 2n;<br>JSON.parse(String(tooBigForNumber), digitsToBigInt) === tooBigForNumber;<br>// → true
const wayTooBig = BigInt("1" + "0".repeat(1000));<br>JSON.parse(String(wayTooBig), digitsToBigInt) === wayTooBig;<br>// → true
const embedded = JSON.stringify({ tooBigForNumber }, bigIntToRawJSON);<br>embedded === '{"tooBigForNumber":9007199254740993}';<br>// → true
JSON.rawJSON()
The JSON.rawJSON() static method creates a "raw JSON" object containing a piece of JSON text. When serialized to JSON, the raw JSON object is treated as if it is already a piece of JSON. This text is required to be valid JSON.
I didn’t find that in the proposals list, hence I cannot provide motivation for this change. More information can be found on the JSON.rawJSON MDN page.
Sneak peek at ECMAScript 2027:
Temporal –...