Minimal event emitter with once listeners

JavaScript
// Tiny event emitter: on/once/off/emit, with unsubscribe handles.
class Emitter {
  #listeners = new Map();

  on(event, listener) {
    const list = this.#listeners.get(event) ?? new Set();
    list.add(listener);
    this.#listeners.set(event, list);
    return () => this.off(event, listener);
  }

  once(event, listener) {
    const wrapped = (...args) => {
      this.off(event, wrapped);
      listener(...args);
    };
    return this.on(event, wrapped);
  }

  off(event, listener) {
    this.#listeners.get(event)?.delete(listener);
  }

  emit(event, ...args) {
    for (const listener of [...(this.#listeners.get(event) ?? [])]) {
      listener(...args);
    }
  }
}

// Usage
const bus = new Emitter();
const stop = bus.on('save', (file) => console.log('saved', file));
bus.once('save', () => console.log('first save only'));
bus.emit('save', 'notes.md');
bus.emit('save', 'todo.md');
stop();