'use strict';

Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });

/**
 * A wrapper around a `RemoteConnection` that batches mutations. By default, this
 * all calls are flushed in a queued microtask, but this can be customized by passing
 * a custom `batch` option.
 */
class BatchingRemoteConnection {
  #connection;
  #queued;
  #batch;
  constructor(connection, {
    batch = createDefaultBatchFunction()
  } = {}) {
    this.#connection = connection;
    this.#batch = batch;
  }
  call(id, method, ...args) {
    this.#connection.call(id, method, ...args);
  }
  mutate(records) {
    const queued = this.#queued;
    this.#queued ??= [];
    this.#queued.push(...records);
    if (queued) {
      return;
    }
    this.#batch(() => {
      this.flush();
    });
  }
  flush() {
    if (!this.#queued) {
      return;
    }
    this.#connection.mutate(this.#queued);
    this.#queued = undefined;
  }
}
function createDefaultBatchFunction() {
  let channel;
  return queue => {
    // In environments without a `MessageChannel`, use a `setTimeout` fallback.
    if (typeof MessageChannel !== 'function') {
      setTimeout(() => {
        queue();
      }, 0);
      return;
    }

    // `MessageChannel` trick that forces the code to run on the next task.
    channel ??= new MessageChannel();
    channel.port1.onmessage = () => {
      queue();
    };
    channel.port2.postMessage(null);
  };
}

exports.BatchingRemoteConnection = BatchingRemoteConnection;
