Skip to content
Web Development10 min read2025-06-12

JavaScript ES2024Features

The latest JavaScript features and their practical application – a comprehensive guide for modern JavaScript development with ES2024.

JavaScriptES2024Modern JSECMAScriptWeb APIs

JavaScript ES2024 Overview

ECMAScript 2024 (ES15) introduces new features that make JavaScript development more efficient and expressive. This version focuses on array manipulation, RegExp improvements, and new Promise methods.

  • New Array Methods: groupBy, toSorted, toReversed, toSpliced
  • RegExp Improvements: Named Capture Groups, Unicode Sets
  • Promise.withResolvers(): New Promise constructor alternative
  • Performance: Optimized implementations for better performance

New Array Methods

Array.prototype.toSorted():

// Non-mutating sort
const numbers = [3, 1, 4, 1, 5, 9];

// Old: Mutates the original array
const sortedOld = numbers.sort(); // numbers is changed!

// New: Returns a new array
const sortedNew = numbers.toSorted(); // numbers remains unchanged
console.log(numbers);    // [3, 1, 4, 1, 5, 9] (unchanged)
console.log(sortedNew);  // [1, 1, 3, 4, 5, 9]

// With custom comparator
const users = [
  { name: 'Alice', age: 30 },
  { name: 'Bob', age: 25 },
  { name: 'Charlie', age: 35 }
];

const sortedByAge = users.toSorted((a, b) => a.age - b.age);
console.log(sortedByAge);
// [{ name: 'Bob', age: 25 }, { name: 'Alice', age: 30 }, { name: 'Charlie', age: 35 }]

// Functional chaining
const processedData = data
  .filter(item => item.active)
  .toSorted((a, b) => a.priority - b.priority)
  .map(item => ({ ...item, processed: true }));

Array.prototype.toReversed():

// Non-mutating reverse
const items = ['a', 'b', 'c', 'd'];

// Old: Mutates the original array
const reversedOld = items.reverse(); // items is changed!

// New: Returns a new array
const reversedNew = items.toReversed(); // items remains unchanged
console.log(items);        // ['a', 'b', 'c', 'd'] (unchanged)
console.log(reversedNew);  // ['d', 'c', 'b', 'a']

// Practical example: Breadcrumb navigation
function createBreadcrumb(path) {
  return path
    .split('/')
    .filter(Boolean)
    .toReversed()
    .map((segment, index) => ({
      name: segment,
      isLast: index === 0
    }));
}

console.log(createBreadcrumb('/wiki/javascript/es2024'));
// [
//   { name: 'es2024', isLast: true },
//   { name: 'javascript', isLast: false },
//   { name: 'wiki', isLast: false }
// ]

Array.prototype.toSpliced():

// Non-mutating splice operation
const items = ['apple', 'banana', 'cherry', 'date'];

// Old: Mutates the original array
const splicedOld = items.splice(1, 2, 'orange', 'grape'); // items is changed!

// New: Returns a new array
const splicedNew = items.toSpliced(1, 2, 'orange', 'grape'); // items remains unchanged
console.log(items);      // ['apple', 'banana', 'cherry', 'date'] (unchanged)
console.log(splicedNew); // ['apple', 'orange', 'grape', 'date']

// Practical example: Todo list update
class TodoList {
  constructor() {
    this.todos = [];
  }
  
  addTodo(todo, index = this.todos.length) {
    this.todos = this.todos.toSpliced(index, 0, todo);
    return this;
  }
  
  removeTodo(index) {
    this.todos = this.todos.toSpliced(index, 1);
    return this;
  }
  
  updateTodo(index, updatedTodo) {
    this.todos = this.todos.toSpliced(index, 1, updatedTodo);
    return this;
  }
}

const todoList = new TodoList();
todoList
  .addTodo({ id: 1, text: 'Learn ES2024', done: false })
  .addTodo({ id: 2, text: 'Write article', done: false })
  .updateTodo(0, { id: 1, text: 'Learn ES2024', done: true });

Array.prototype.with():

// Non-mutating index-based replacement
const fruits = ['apple', 'banana', 'cherry'];

// Old: Mutation via index assignment
fruits[1] = 'orange'; // fruits is changed!

// New: Returns a new array
const newFruits = fruits.with(1, 'orange'); // fruits remains unchanged
console.log(fruits);     // ['apple', 'banana', 'cherry'] (unchanged)
console.log(newFruits);  // ['apple', 'orange', 'cherry']

// Negative indices supported
const lastChanged = fruits.with(-1, 'grape');
console.log(lastChanged); // ['apple', 'banana', 'grape']

// Practical example: State update in React
function useArrayState(initialArray) {
  const [array, setArray] = useState(initialArray);
  
  const updateItem = useCallback((index, newValue) => {
    setArray(prevArray => prevArray.with(index, newValue));
  }, []);
  
  const updateLastItem = useCallback((newValue) => {
    setArray(prevArray => prevArray.with(-1, newValue));
  }, []);
  
  return [array, { updateItem, updateLastItem }];
}

RegExp Improvements

Unicode Set Notation (v-Flag):

// New v-flag for extended Unicode support
// Replaces the u-flag with more features

// Character class subtraction
const asciiLettersOnly = /^[p{ASCII}--p{Cc}]+$/v;
console.log(asciiLettersOnly.test('Hello')); // true
console.log(asciiLettersOnly.test('Hëllo')); // false

// String literals in character classes
const emojiPattern = /[q{||}]/v;
console.log(emojiPattern.test('')); // true
console.log(emojiPattern.test('')); // true

// Intersection of character classes
const hexDigits = /[p{ASCII_Hex_Digit}&&[0-9A-F]]/v;
console.log(hexDigits.test('A')); // true
console.log(hexDigits.test('G')); // false

// Practical example: Email validation
const emailPattern = /^[p{L}p{N}._%-]+@[p{L}p{N}.-]+.[p{L}]{2,}$/v;

function validateEmail(email) {
  return emailPattern.test(email);
}

console.log(validateEmail('user@example.com')); // true
console.log(validateEmail('üser@dömail.com')); // true (Unicode support)

// Extended Unicode property escapes
const modernTextPattern = /^[p{L}p{N}p{M}p{Z}p{P}&&[^p{Cc}]]+$/v;

function isValidModernText(text) {
  return modernTextPattern.test(text);
}

Named Capture Groups Enhancements:

// Enhanced named capture groups
const datePattern = /(?<year>d{4})-(?<month>d{2})-(?<day>d{2})/;
const urlPattern = /^(?<protocol>https?)://(?<host>[^/]+)(?<path>/.*)?$/;

// Destructuring with named groups
function parseDate(dateString) {
  const match = dateString.match(datePattern);
  if (!match) return null;
  
  const { year, month, day } = match.groups;
  return new Date(parseInt(year), parseInt(month) - 1, parseInt(day));
}

console.log(parseDate('2024-06-12')); // Date object

// URL parser with named groups
function parseURL(url) {
  const match = url.match(urlPattern);
  if (!match) return null;
  
  return {
    protocol: match.groups.protocol,
    host: match.groups.host,
    path: match.groups.path || '/',
    port: match.groups.host.includes(':') ? 
      match.groups.host.split(':')[1] : 
      (match.groups.protocol === 'https' ? '443' : '80')
  };
}

console.log(parseURL('https://example.com/path'));
// { protocol: 'https', host: 'example.com', path: '/path', port: '443' }

// Template string replacement with named groups
const template = 'Hello {{name}}, you have {{count}} messages';
const templatePattern = /{{(?<key>w+)}}/g;

function renderTemplate(template, data) {
  return template.replace(templatePattern, (match, key) => {
    return data[key] || match;
  });
}

console.log(renderTemplate(template, { name: 'Alice', count: 5 }));
// "Hello Alice, you have 5 messages"

Promise.withResolvers()

Promise.withResolvers() Basics:

// New way to create Promises with external resolve/reject
// Replaces the usual Promise constructor pattern

// Old: Promise constructor pattern
function createPromiseOld() {
  let resolve, reject;
  const promise = new Promise((res, rej) => {
    resolve = res;
    reject = rej;
  });
  return { promise, resolve, reject };
}

// New: Promise.withResolvers()
function createPromiseNew() {
  return Promise.withResolvers();
}

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

// Resolve promise later
setTimeout(() => {
  resolve('Success!');
}, 1000);
promise.then(console.log); // "Success!" after 1 second

Practical Applications:

// Event-based promise resolution
class EventPromise {
  constructor() {
    this.promises = new Map();
  }
  
  waitFor(eventName) {
    if (!this.promises.has(eventName)) {
      const { promise, resolve } = Promise.withResolvers();
      this.promises.set(eventName, { promise, resolve });
    }
    return this.promises.get(eventName).promise;
  }
  
  emit(eventName, data) {
    if (this.promises.has(eventName)) {
      const { resolve } = this.promises.get(eventName);
      resolve(data);
      this.promises.delete(eventName);
    }
  }
}

const eventManager = new EventPromise();

// Wait for event
eventManager.waitFor('user-login').then(user => {
  console.log('User logged in:', user);
});

// Trigger event later
setTimeout(() => {
  eventManager.emit('user-login', { id: 1, name: 'Alice' });
}, 2000);

// Async/await resource loader
class ResourceLoader {
  constructor() {
    this.cache = new Map();
    this.loading = new Map();
  }
  
  async load(url) {
    // Cache hit
    if (this.cache.has(url)) {
      return this.cache.get(url);
    }
    
    // Already loading
    if (this.loading.has(url)) {
      return this.loading.get(url).promise;
    }
    
    // Start loading
    const { promise, resolve, reject } = Promise.withResolvers();
    this.loading.set(url, { promise, resolve, reject });
    
    try {
      const response = await fetch(url);
      const data = await response.json();
      
      this.cache.set(url, data);
      this.loading.delete(url);
      resolve(data);
      
      return data;
    } catch (error) {
      this.loading.delete(url);
      reject(error);
      throw error;
    }
  }
}

const loader = new ResourceLoader();

// Multiple concurrent requests for the same resource
// are automatically deduplicated
Promise.all([
  loader.load('/api/users'),
  loader.load('/api/users'), // Uses the same promise
  loader.load('/api/users')  // Uses the same promise
]).then(results => {
  console.log('All loaded:', results);
});

// WebSocket promise wrapper
class WebSocketPromise {
  constructor(url) {
    this.ws = new WebSocket(url);
    this.pendingRequests = new Map();
    
    this.ws.onmessage = (event) => {
      const { id, data, error } = JSON.parse(event.data);
      
      if (this.pendingRequests.has(id)) {
        const { resolve, reject } = this.pendingRequests.get(id);
        this.pendingRequests.delete(id);
        
        if (error) {
          reject(new Error(error));
        } else {
          resolve(data);
        }
      }
    };
  }
  
  send(data) {
    const id = Math.random().toString(36).substr(2, 9);
    const { promise, resolve, reject } = Promise.withResolvers();
    
    this.pendingRequests.set(id, { resolve, reject });
    this.ws.send(JSON.stringify({ id, data }));
    
    return promise;
  }
}

const wsClient = new WebSocketPromise('ws://localhost:8080');

// WebSocket request as promise
wsClient.send({ action: 'getUser', userId: 123 })
  .then(user => console.log('User:', user))
  .catch(error => console.error('Error:', error));

Temporal API (Preview)

The Temporal API is still in Stage 3 but is expected to be finalized soon. It solves many issues with the Date object.

Temporal Basics:

// Temporal API (when available)
// Modern, immutable Date/Time API

// PlainDate for date operations without time
const today = Temporal.PlainDate.from('2024-06-12');
const tomorrow = today.add({ days: 1 });
const lastWeek = today.subtract({ weeks: 1 });

console.log(today.toString());     // "2024-06-12"
console.log(tomorrow.toString());  // "2024-06-13"
console.log(lastWeek.toString());  // "2024-06-05"

// PlainTime for time without date
const noon = Temporal.PlainTime.from('12:00:00');
const inOneHour = noon.add({ hours: 1 });

console.log(noon.toString());     // "12:00:00"
console.log(inOneHour.toString()); // "13:00:00"

// ZonedDateTime for full date/time with timezone
const meeting = Temporal.ZonedDateTime.from({
  year: 2024,
  month: 6,
  day: 12,
  hour: 14,
  minute: 30,
  timeZone: 'Europe/Berlin'
});

const meetingInNY = meeting.withTimeZone('America/New_York');
console.log(meeting.toString());    // "2024-06-12T14:30:00+02:00[Europe/Berlin]"
console.log(meetingInNY.toString()); // "2024-06-12T08:30:00-04:00[America/New_York]"

// Duration for time spans
const duration = Temporal.Duration.from({ hours: 2, minutes: 30 });
const endTime = meeting.add(duration);

console.log(endTime.toString()); // "2024-06-12T17:00:00+02:00[Europe/Berlin]"

// Comparisons are easier and more reliable
const date1 = Temporal.PlainDate.from('2024-06-12');
const date2 = Temporal.PlainDate.from('2024-06-13');

console.log(Temporal.PlainDate.compare(date1, date2)); // -1 (date1 < date2)
console.log(date1.equals(date2)); // false
console.log(date1.since(date2).toString()); // "-P1D" (1 day less)

Practical Temporal Applications:

// Business logic with Temporal
class BusinessCalendar {
  constructor(timeZone = 'Europe/Berlin') {
    this.timeZone = timeZone;
    this.workingHours = {
      start: Temporal.PlainTime.from('09:00'),
      end: Temporal.PlainTime.from('17:00')
    };
    this.workingDays = [1, 2, 3, 4, 5]; // Mon-Fri
  }
  
  isWorkingDay(date) {
    const plainDate = Temporal.PlainDate.from(date);
    return this.workingDays.includes(plainDate.dayOfWeek);
  }
  
  getNextWorkingDay(date) {
    let nextDay = Temporal.PlainDate.from(date).add({ days: 1 });
    
    while (!this.isWorkingDay(nextDay)) {
      nextDay = nextDay.add({ days: 1 });
    }
    
    return nextDay;
  }
  
  scheduleDelivery(orderDate, deliveryDays = 3) {
    let currentDate = Temporal.PlainDate.from(orderDate);
    let workingDaysAdded = 0;
    
    while (workingDaysAdded < deliveryDays) {
      currentDate = this.getNextWorkingDay(currentDate);
      workingDaysAdded++;
    }
    
    return currentDate;
  }
  
  getWorkingHoursInTimeZone(date, targetTimeZone) {
    const startDateTime = date.toZonedDateTime({
      timeZone: this.timeZone,
      plainTime: this.workingHours.start
    });
    
    const endDateTime = date.toZonedDateTime({
      timeZone: this.timeZone,
      plainTime: this.workingHours.end
    });
    
    return {
      start: startDateTime.withTimeZone(targetTimeZone),
      end: endDateTime.withTimeZone(targetTimeZone)
    };
  }
}

const calendar = new BusinessCalendar('Europe/Berlin');
const orderDate = Temporal.PlainDate.from('2024-06-12');
const deliveryDate = calendar.scheduleDelivery(orderDate, 3);

console.log(`Order: ${orderDate}, Delivery: ${deliveryDate}`);

// Recurring events
class RecurringEvent {
  constructor(startDate, pattern) {
    this.startDate = Temporal.PlainDate.from(startDate);
    this.pattern = pattern; // { type: 'weekly', interval: 2 }
  }
  
  getOccurrences(count = 10) {
    const occurrences = [this.startDate];
    let currentDate = this.startDate;
    
    for (let i = 1; i < count; i++) {
      switch (this.pattern.type) {
        case 'daily':
          currentDate = currentDate.add({ days: this.pattern.interval || 1 });
          break;
        case 'weekly':
          currentDate = currentDate.add({ weeks: this.pattern.interval || 1 });
          break;
        case 'monthly':
          currentDate = currentDate.add({ months: this.pattern.interval || 1 });
          break;
      }
      occurrences.push(currentDate);
    }
    
    return occurrences;
  }
}

const weeklyMeeting = new RecurringEvent('2024-06-12', { type: 'weekly', interval: 1 });
const meetings = weeklyMeeting.getOccurrences(5);

console.log('Weekly meetings:', meetings.map(d => d.toString()));

Atomics.waitAsync()

Asynchronous Atomic Operations:

// Atomics.waitAsync() for non-blocking wait operations
// Useful for SharedArrayBuffer and worker communication

// Shared memory setup
const sharedBuffer = new SharedArrayBuffer(1024);
const sharedArray = new Int32Array(sharedBuffer);

// Worker script (worker.js)
// In worker:
self.onmessage = async function(e) {
  const { sharedBuffer, index, expectedValue, timeout } = e.data;
  const sharedArray = new Int32Array(sharedBuffer);
  
  // Asynchronously wait for value change
  const result = Atomics.waitAsync(sharedArray, index, expectedValue, timeout);
  
  if (result.async) {
    // Promise-based waiting
    const waitResult = await result.value;
    
    if (waitResult === 'ok') {
      self.postMessage({ 
        type: 'value-changed', 
        newValue: Atomics.load(sharedArray, index) 
      });
    } else if (waitResult === 'timed-out') {
      self.postMessage({ type: 'timeout' });
    }
  } else {
    // Immediate return
    self.postMessage({ 
      type: 'immediate', 
      result: result.value 
    });
  }
};

// Main thread
class SharedCounter {
  constructor() {
    this.sharedBuffer = new SharedArrayBuffer(16);
    this.sharedArray = new Int32Array(this.sharedBuffer);
    this.workers = [];
    
    // Initialize counter
    Atomics.store(this.sharedArray, 0, 0);
  }
  
  addWorker() {
    const worker = new Worker('counter-worker.js');
    
    worker.onmessage = (e) => {
      const { type, newValue } = e.data;
      
      if (type === 'value-changed') {
        console.log(`Counter changed to: ${newValue}`);
        this.notifyListeners(newValue);
      }
    };
    
    this.workers.push(worker);
    return worker;
  }
  
  waitForValue(expectedValue, timeout = 5000) {
    return new Promise((resolve, reject) => {
      const worker = this.addWorker();
      
      worker.postMessage({
        sharedBuffer: this.sharedBuffer,
        index: 0,
        expectedValue,
        timeout
      });
      
      worker.onmessage = (e) => {
        const { type, newValue, result } = e.data;
        
        if (type === 'value-changed') {
          resolve(newValue);
        } else if (type === 'timeout') {
          reject(new Error('Timeout waiting for value'));
        } else if (type === 'immediate') {
          resolve(result);
        }
        
        worker.terminate();
      };
    });
  }
  
  increment() {
    const oldValue = Atomics.load(this.sharedArray, 0);
    const newValue = Atomics.add(this.sharedArray, 0, 1) + 1;
    
    // Notify all waiting workers
    Atomics.notify(this.sharedArray, 0);
    
    return newValue;
  }
  
  getValue() {
    return Atomics.load(this.sharedArray, 0);
  }
}

// Usage
const counter = new SharedCounter();

// Wait for counter to reach 5
counter.waitForValue(5).then(value => {
  console.log(`Counter reached ${value}!`);
});

// Increment counter in intervals
setInterval(() => {
  const newValue = counter.increment();
  console.log(`Counter incremented to: ${newValue}`);
}, 1000);

Well-formed Unicode Strings

String.prototype.isWellFormed() and toWellFormed():

// New methods for Unicode validation and correction

// isWellFormed() - Checks for valid Unicode sequences
const validString = 'Hello World';
const invalidString = 'Hello � World'; // Lone surrogate

console.log(validString.isWellFormed());   // true
console.log(invalidString.isWellFormed()); // false

// toWellFormed() - Fixes invalid Unicode sequences
const correctedString = invalidString.toWellFormed();
console.log(correctedString); // "Hello � World" (replacement character)

// Practical application: Secure string processing
class UnicodeValidator {
  static validateInput(input) {
    if (typeof input !== 'string') {
      throw new TypeError('Input must be a string');
    }
    
    if (!input.isWellFormed()) {
      console.warn('Invalid Unicode sequence detected, auto-correcting...');
      return input.toWellFormed();
    }
    
    return input;
  }
  
  static safeStringify(obj) {
    const jsonString = JSON.stringify(obj);
    
    if (!jsonString.isWellFormed()) {
      return jsonString.toWellFormed();
    }
    
    return jsonString;
  }
  
  static safeDatabaseInsert(data) {
    // Ensure all string values are well-formed before database insertion
    const cleanData = {};
    
    for (const [key, value] of Object.entries(data)) {
      if (typeof value === 'string') {
        cleanData[key] = UnicodeValidator.validateInput(value);
      } else {
        cleanData[key] = value;
      }
    }
    
    return cleanData;
  }
}

// Usage examples
const userInput = 'User comment with invalid � surrogate';
const safeInput = UnicodeValidator.validateInput(userInput);

const userData = {
  name: 'John Doe',
  comment: 'Invalid unicode ��',
  email: 'john@example.com'
};

const safeUserData = UnicodeValidator.safeDatabaseInsert(userData);
console.log(safeUserData);
// { name: 'John Doe', comment: 'Invalid unicode ��', email: 'john@example.com' }

// Web API integration
class SafeWebAPI {
  static async post(url, data) {
    // Ensure all string data is well-formed before sending
    const safeData = {};
    
    for (const [key, value] of Object.entries(data)) {
      if (typeof value === 'string') {
        safeData[key] = value.isWellFormed() ? value : value.toWellFormed();
      } else {
        safeData[key] = value;
      }
    }
    
    return fetch(url, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(safeData)
    });
  }
  
  static async processResponse(response) {
    const text = await response.text();
    
    if (!text.isWellFormed()) {
      console.warn('Response contains invalid Unicode, correcting...');
      return text.toWellFormed();
    }
    
    return text;
  }
}

Resizable ArrayBuffers

Resizable ArrayBuffer and SharedArrayBuffer:

// Resizable ArrayBuffer - can be resized at runtime
const buffer = new ArrayBuffer(1024, { maxByteLength: 4096 });
const view = new Uint8Array(buffer);

console.log(buffer.byteLength);    // 1024
console.log(buffer.maxByteLength); // 4096
console.log(buffer.resizable);     // true

// Resize buffer
buffer.resize(2048);
console.log(buffer.byteLength);    // 2048

// New view on resized buffer
const newView = new Uint8Array(buffer);
console.log(newView.length);       // 2048

// Practical application: Dynamic data buffer
class DynamicBuffer {
  constructor(initialSize = 1024, maxSize = 1024 * 1024) {
    this.buffer = new ArrayBuffer(initialSize, { maxByteLength: maxSize });
    this.view = new Uint8Array(this.buffer);
    this.position = 0;
  }
  
  ensureCapacity(additionalBytes) {
    const requiredSize = this.position + additionalBytes;
    
    if (requiredSize > this.buffer.byteLength) {
      const newSize = Math.min(
        Math.max(this.buffer.byteLength * 2, requiredSize),
        this.buffer.maxByteLength
      );
      
      if (newSize > this.buffer.maxByteLength) {
        throw new Error('Buffer would exceed maximum size');
      }
      
      this.buffer.resize(newSize);
      this.view = new Uint8Array(this.buffer);
    }
  }
  
  writeBytes(data) {
    this.ensureCapacity(data.length);
    this.view.set(data, this.position);
    this.position += data.length;
  }
  
  writeString(str) {
    const encoder = new TextEncoder();
    const encoded = encoder.encode(str);
    this.writeBytes(encoded);
  }
  
  writeUint32(value) {
    this.ensureCapacity(4);
    const dataView = new DataView(this.buffer);
    dataView.setUint32(this.position, value, true); // little endian
    this.position += 4;
  }
  
  toArrayBuffer() {
    return this.buffer.slice(0, this.position);
  }
  
  reset() {
    this.position = 0;
  }
  
  get size() {
    return this.position;
  }
  
  get capacity() {
    return this.buffer.byteLength;
  }
}

// Usage
const dynBuffer = new DynamicBuffer(64, 1024);

dynBuffer.writeString('Hello ');
dynBuffer.writeString('World!');
dynBuffer.writeUint32(42);

console.log(`Used: ${dynBuffer.size}, Capacity: ${dynBuffer.capacity}`);

// SharedArrayBuffer resizable (for workers)
class SharedDynamicBuffer {
  constructor(initialSize = 1024, maxSize = 1024 * 1024) {
    this.sharedBuffer = new SharedArrayBuffer(initialSize, { maxByteLength: maxSize });
    this.header = new Int32Array(this.sharedBuffer, 0, 2); // [position, capacity]
    this.data = new Uint8Array(this.sharedBuffer, 8); // Data after header
    
    // Initialize header
    Atomics.store(this.header, 0, 0); // position
    Atomics.store(this.header, 1, initialSize - 8); // capacity
  }
  
  ensureCapacity(additionalBytes) {
    const currentPosition = Atomics.load(this.header, 0);
    const currentCapacity = Atomics.load(this.header, 1);
    const requiredSize = currentPosition + additionalBytes;
    
    if (requiredSize > currentCapacity) {
      const newSize = Math.min(
        Math.max(this.sharedBuffer.byteLength * 2, requiredSize + 8),
        this.sharedBuffer.maxByteLength
      );
      
      this.sharedBuffer.resize(newSize);
      this.data = new Uint8Array(this.sharedBuffer, 8);
      Atomics.store(this.header, 1, newSize - 8);
    }
  }
  
  atomicWrite(data) {
    this.ensureCapacity(data.length);
    const position = Atomics.load(this.header, 0);
    
    // Write data
    this.data.set(data, position);
    
    // Update position atomically
    Atomics.store(this.header, 0, position + data.length);
    
    return position;
  }
  
  getSharedBuffer() {
    return this.sharedBuffer;
  }
}

// Usage with workers
const sharedDynBuffer = new SharedDynamicBuffer(128, 2048);

// In worker
const worker = new Worker(`
  const sharedBuffer = self.sharedBuffer;
  const header = new Int32Array(sharedBuffer, 0, 2);
  const data = new Uint8Array(sharedBuffer, 8);
  
  self.postMessage({
    position: Atomics.load(header, 0),
    capacity: Atomics.load(header, 1)
  });
`);

Practical Applications

Combined ES2024 Features:

// Practical Example: Advanced Data Processing Pipeline
class DataProcessor {
  constructor() {
    this.cache = new Map();
    this.processors = [];
  }
  
  // Using Array.prototype.toSorted() and with()
  processArray(data, sortKey) {
    return data
      .toSorted((a, b) => a[sortKey] - b[sortKey]) // Non-mutating sort
      .with(0, { ...data[0], processed: true });   // Mark first item
  }
  
  // Using Promise.withResolvers() for async processing
  createProcessor() {
    const { promise, resolve, reject } = Promise.withResolvers();
    
    const processor = {
      id: Math.random().toString(36).substr(2, 9),
      promise,
      resolve,
      reject,
      start: Date.now()
    };
    
    this.processors.push(processor);
    return processor;
  }
  
  // Using RegExp v-flag for validation
  validateEmailList(emails) {
    const emailPattern = /^[\p{L}\p{N}._%-]+@[\p{L}\p{N}.-]+\.[\p{L}]{2,}$/v;
    
    return emails
      .filter(email => email.isWellFormed()) // Well-formed Unicode
      .filter(email => emailPattern.test(email))
      .toSorted(); // Sort alphabetically
  }
  
  // Comprehensive example
  async processUserData(users) {
    const processor = this.createProcessor();
    
    try {
      // Validate and clean user data
      const validUsers = users
        .filter(user => user.email.isWellFormed())
        .map(user => ({
          ...user,
          email: user.email.toWellFormed()
        }));
      
      // Sort by registration date (non-mutating)
      const sortedUsers = validUsers.toSorted((a, b) => 
        new Date(a.registeredAt) - new Date(b.registeredAt)
      );
      
      // Mark VIP users (non-mutating update)
      const processedUsers = sortedUsers.map((user, index) => {
        if (user.purchases > 1000) {
          return sortedUsers.with(index, { ...user, vip: true });
        }
        return user;
      });
      
      processor.resolve(processedUsers);
      return processor.promise;
      
    } catch (error) {
      processor.reject(error);
      throw error;
    }
  }
}

// Modern Email Validator using ES2024 features
class EmailValidator {
  constructor() {
    // Using Unicode Sets (v-flag)
    this.patterns = {
      basic: /^[\p{L}\p{N}._%-]+@[\p{L}\p{N}.-]+\.[\p{L}]{2,}$/v,
      strict: /^[\p{ASCII}&&[^\p{Cc}\p{Z}]]+@[\p{ASCII}&&[^\p{Cc}\p{Z}]]+\.[\p{L}]{2,}$/v
    };
  }
  
  validateBatch(emails) {
    const results = emails.map(email => ({
      email: email.isWellFormed() ? email : email.toWellFormed(),
      valid: false,
      errors: []
    }));
    
    return results
      .map((result, index) => {
        const email = result.email;
        
        if (!email.isWellFormed()) {
          return results.with(index, {
            ...result,
            errors: [...result.errors, 'Invalid Unicode sequence']
          });
        }
        
        if (!this.patterns.basic.test(email)) {
          return results.with(index, {
            ...result,
            errors: [...result.errors, 'Invalid email format']
          });
        }
        
        return results.with(index, { ...result, valid: true });
      });
  }
  
  getValidEmails(emails) {
    return this.validateBatch(emails)
      .filter(result => result.valid)
      .map(result => result.email)
      .toSorted(); // Sort alphabetically
  }
}

// Usage
const processor = new DataProcessor();
const validator = new EmailValidator();

const userData = [
  { name: 'Alice', email: 'alice@example.com', purchases: 1500, registeredAt: '2024-01-15' },
  { name: 'Bob', email: 'bob@test.com', purchases: 500, registeredAt: '2024-02-20' },
  { name: 'Charlie', email: 'charlie@demo.org', purchases: 2000, registeredAt: '2024-01-10' }
];

processor.processUserData(userData).then(users => {
  console.log('Processed users:', users);
});

const emails = ['alice@example.com', 'invalid-email', 'bob@test.com\uD800'];
const validEmails = validator.getValidEmails(emails);
console.log('Valid emails:', validEmails);

Performance Tips:

  • Use toSorted(), toReversed(), with() for immutable operations
  • RegExp v-flag offers better Unicode performance
  • Promise.withResolvers() avoids nested Promise constructors
  • isWellFormed() check before string operations
  • Use resizable buffers for dynamic data structures