ES2025 Features
Set methods, sync iterator helpers, Iterator.from, RegExp.escape, RegExp inline modifiers, duplicate named capture groups, Promise.try, import attributes + JSON modules, Float16 (Float16Array, Math.f16round, DataView methods). Plus Intl.DurationFormat (ECMA-402).
Moved out of this file because they are not ES2025: Array.fromAsync and Error.isError are ES2026 (see ES2026.md); using/await using is Stage 4 for ES2027 (see UPCOMING.md).
Contents
- Set Methods
- Iterator Helpers
- Iterator.from()
- RegExp.escape()
- RegExp Pattern Modifiers (Inline Flags)
- Duplicate Named Capture Groups
- Promise.try()
- Import Attributes and JSON Modules
- Float16 Support
- Intl.DurationFormat (ECMA-402)
- Browser/Node.js Support
Set Methods
Mathematical set operations. Arguments can be any "set-like" (has size, has, keys), not just a Set.
const setA = new Set([1, 2, 3, 4]);
const setB = new Set([3, 4, 5, 6]);
// Union: elements in either set
setA.union(setB);
// Set {1, 2, 3, 4, 5, 6}
// Intersection: elements in both sets
setA.intersection(setB);
// Set {3, 4}
// Difference: elements in A but not B
setA.difference(setB);
// Set {1, 2}
// Symmetric difference: elements in either but not both
setA.symmetricDifference(setB);
// Set {1, 2, 5, 6}
// Subset check
const setC = new Set([1, 2]);
setC.isSubsetOf(setA); // true
setA.isSupersetOf(setC); // true
// Disjoint check (no common elements)
const setD = new Set([7, 8]);
setA.isDisjointFrom(setD); // trueAll of these return new Sets (or booleans); the originals are never mutated.
Practical example:
const userPermissions = new Set(['read', 'write']);
const requiredPermissions = new Set(['read', 'delete']);
// Check what's missing
const missing = requiredPermissions.difference(userPermissions);
// Set {'delete'}
// Check if has all required
const hasAll = requiredPermissions.isSubsetOf(userPermissions);
// falseIterator Helpers
Process iterators lazily without converting to arrays. These live on the shared Iterator.prototype used by array iterators, generators, and Map/Set iterators — they are not array methods, and they consume the iterator.
// Create iterator
const numbers = [1, 2, 3, 4, 5].values();
// map() on iterator
const doubled = numbers.map(n => n * 2);
// Iterator yielding 2, 4, 6, 8, 10
// filter() on iterator
const evens = [1, 2, 3, 4, 5].values().filter(n => n % 2 === 0);
// Iterator yielding 2, 4
// take() - limit results
const firstThree = [1, 2, 3, 4, 5].values().take(3);
// Iterator yielding 1, 2, 3
// drop() - skip results
const afterTwo = [1, 2, 3, 4, 5].values().drop(2);
// Iterator yielding 3, 4, 5
// flatMap()
const flattened = [[1, 2], [3, 4]].values().flatMap(arr => arr);
// Iterator yielding 1, 2, 3, 4
// reduce()
const sum = [1, 2, 3, 4, 5].values().reduce((a, b) => a + b, 0);
// 15
// toArray() - convert to array
const arr = [1, 2, 3].values().map(n => n * 2).toArray();
// [2, 4, 6]
// forEach()
[1, 2, 3].values().forEach(n => console.log(n));
// some() / every()
[1, 2, 3].values().some(n => n > 2); // true
[1, 2, 3].values().every(n => n > 0); // true
// find()
[1, 2, 3, 4].values().find(n => n > 2); // 3Lazy evaluation benefits:
// Process large datasets without materializing intermediate arrays
function* generateLargeDataset() {
for (let i = 0; i < 1000000; i++) {
yield { id: i, value: Math.random() };
}
}
// Stops pulling from the generator after 10 matches
const firstTen = generateLargeDataset()
.filter(item => item.value > 0.9)
.take(10)
.toArray();These are the sync iterator helpers. Async iterator helpers (AsyncIterator.prototype.map etc.) are a separate proposal that has not reached Stage 4 — for async sources use for await...of or Array.fromAsync (ES2026).
Iterator.from()
Create iterators from any iterable or iterator-like object.
// Convert iterable to iterator with helpers
const setIterator = Iterator.from(new Set([1, 2, 3]));
// Now has all iterator helper methods
setIterator
.filter(n => n > 1)
.map(n => n * 2)
.toArray();
// [4, 6]
// Works with any iterable
const mapIter = Iterator.from(new Map([['a', 1], ['b', 2]]));
const stringIter = Iterator.from('hello');Built-in iterables (arrays, Maps, Sets, generators) already inherit the helpers — Iterator.from is mainly for third-party "iterator protocol" objects that don't extend Iterator.prototype.
RegExp.escape()
Safely escape strings for use in dynamically built regexes.
const userInput = 'price: $100 (USD)';
// ❌ Before: Manual escaping (error-prone, misses edge cases)
const escapedManually = userInput.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
// ✅ After: Built-in escape
const escaped = RegExp.escape(userInput);
// '\\x70rice\\x3a\\x20\\$100\\x20\\(USD\\)'
// Leading ASCII alphanumerics, spaces, and punctuators become hex
// escapes so the result is safe in ANY regex context (even inside
// character classes) — it looks odd but matches the original string
// exactly.
const pattern = new RegExp(escaped);
pattern.test('price: $100 (USD)'); // truePractical example: Safe search:
function createSearchPattern(searchTerm) {
return new RegExp(RegExp.escape(searchTerm), 'gi');
}
const query = 'C++ (language)';
const searchPattern = createSearchPattern(query);
// Safely matches "C++ (language)" in textRegExp.escape only accepts strings — it throws a TypeError for anything else (no implicit coercion), which catches bugs like passing a number.
RegExp Pattern Modifiers (Inline Flags)
Apply i, m, or s to part of a pattern instead of the whole thing.
// Apply case-insensitivity only to part of pattern
const pattern = /^(?i:hello) world$/;
pattern.test('hello world'); // true
pattern.test('HELLO world'); // true
pattern.test('Hello World'); // false (World not modified)
// Remove a flag for part of a pattern
const mixed = /(?i:abc)(?-i:DEF)/;
// abc is case-insensitive, DEF must be exact case
// Useful for partial matching
const filePattern = /(?i:readme)\.md$/;
filePattern.test('README.md'); // true
filePattern.test('ReadMe.md'); // true
filePattern.test('readme.MD'); // false (.md must be lowercase)Only i, m, and s can be toggled inline; flags like g, u, v, y apply to the whole regex by nature.
Duplicate Named Capture Groups
Reuse a capture group name across different | alternatives (previously a SyntaxError).
// ✅ Same names allowed in different alternatives
const datePattern = /(?<year>\d{4})-(?<month>\d{2})|(?<month>\d{2})\/(?<year>\d{4})/;
// Both formats produce the same group names
'2024-03'.match(datePattern).groups;
// { year: '2024', month: '03' }
'03/2024'.match(datePattern).groups;
// { year: '2024', month: '03' }The same name still cannot appear twice within one alternative. Only the groups of the alternative that matched are populated; the duplicates from the other branch are undefined.
Promise.try()
Start a promise chain from a function that might throw synchronously — sync exceptions become rejections instead of escaping.
// ❌ Before: Wrap in Promise.resolve().then()
const result = await Promise.resolve().then(() => {
return riskyOperation(); // Might throw synchronously
});// ✅ After: Direct wrapping
const result = await Promise.try(() => {
return riskyOperation(); // Sync throws become rejections
});
// Handles both sync and async functions uniformly
Promise.try(() => syncOrAsyncFunction())
.then(result => console.log(result))
.catch(error => console.error(error));
// Extra arguments are forwarded to the callback
Promise.try(fetchUser, userId).then(user => console.log(user));Unlike Promise.resolve().then(fn), Promise.try(fn) calls fn synchronously (its side effects happen immediately); only the settlement is async.
Import Attributes and JSON Modules
Specify module type explicitly with with. ES2025 standardizes both the syntax and JSON modules. The older assert { type: 'json' } spelling is not in the current standard; some older runtimes accept it, but new code should use with.
// Import JSON (part of ES2025)
import config from './config.json' with { type: 'json' };
// Dynamic import with attributes
const data = await import('./data.json', { with: { type: 'json' } });
// Re-export with attributes
export { default as settings } from './settings.json' with { type: 'json' };CSS module scripts (with { type: 'css' }) are an HTML-spec feature for browsers, not part of ECMAScript, and are not supported in Node.js.
Float16 Support
Half-precision floating point, useful for GPU/ML interop and pixel data.
// Float16Array
const f16 = new Float16Array([1.5, 2.5, 3.5]);
// Math.f16round()
Math.f16round(1.337); // 1.3369140625 (nearest float16 value)
// DataView methods
const buffer = new ArrayBuffer(2);
const view = new DataView(buffer);
view.setFloat16(0, 1.5);
view.getFloat16(0); // 1.5Intl.DurationFormat (ECMA-402)
Format time durations with locale support. Technically part of the Intl (ECMA-402) spec rather than ECMA-262, finalized in the same era.
const duration = { hours: 1, minutes: 46, seconds: 40 };
// Different styles
new Intl.DurationFormat('en', { style: 'long' }).format(duration);
// "1 hour, 46 minutes, 40 seconds"
new Intl.DurationFormat('en', { style: 'short' }).format(duration);
// "1 hr, 46 min, 40 sec"
new Intl.DurationFormat('en', { style: 'narrow' }).format(duration);
// "1h 46m 40s"
new Intl.DurationFormat('en', { style: 'digital' }).format(duration);
// "1:46:40"
// Localized
new Intl.DurationFormat('fr', { style: 'long' }).format(duration);
// "1 heure, 46 minutes et 40 secondes"Browser/Node.js Support
First versions with unflagged support (source: MDN browser-compat-data, 2026):
| Feature | Chrome | Firefox | Safari | Node.js |
|---|---|---|---|---|
| Set methods | 122+ | 127+ | 17+ | 22+ |
| Iterator helpers / Iterator.from | 122+ | 131+ | 18.4+ | 22+ |
| RegExp.escape | 136+ | 134+ | 18.2+ | 24+ |
| RegExp inline modifiers | 125+ | 132+ | 26+ | 23+ |
| Duplicate named capture groups | 125+ | 129+ | 17+ | 23+ |
| Promise.try | 128+ | 134+ | 18.2+ | 23+ |
Import attributes (with) |
123+ | 138+ | 17.2+ | 20.10+ |
| Float16Array / Math.f16round | 135+ | 129+ | 18.2+ | 24+ |
| Intl.DurationFormat | 129+ | 136+ | 16.4+ | 23+ |
Practical baseline: Node 24 LTS and current evergreen browsers cover all of ES2025. On Node 22, RegExp.escape, Float16, inline modifiers, duplicate named groups, and Promise.try are missing. Re-check MDN Browser Compatibility Data against the project's targets.