text: (function (global, factory) {
      typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@lumino/algorithm')) :
      typeof define === 'function' && define.amd ? define(['exports', '@lumino/algorithm'], factory) :
      (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.lumino_signaling = {}, global.lumino_algorithm));
  }(this, (function (exports, algorithm) { 'use strict';
  
      // Copyright (c) Jupyter Development Team.
      /**
       * A concrete implementation of `ISignal`.
       *
       * #### Example
       * ```typescript
       * import { ISignal, Signal } from '@lumino/signaling';
       *
       * class SomeClass {
       *
       *   constructor(name: string) {
       *     this.name = name;
       *   }
       *
       *   readonly name: string;
       *
       *   get valueChanged: ISignal<this, number> {
       *     return this._valueChanged;
       *   }
       *
       *   get value(): number {
       *     return this._value;
       *   }
       *
       *   set value(value: number) {
       *     if (value === this._value) {
       *       return;
       *     }
       *     this._value = value;
       *     this._valueChanged.emit(value);
       *   }
       *
       *   private _value = 0;
       *   private _valueChanged = new Signal<this, number>(this);
       * }
       *
       * function logger(sender: SomeClass, value: number): void {
       *   console.log(sender.name, value);
       * }
       *
       * let m1 = new SomeClass('foo');
       * let m2 = new SomeClass('bar');
       *
       * m1.valueChanged.connect(logger);
       * m2.valueChanged.connect(logger);
       *
       * m1.value = 42;  // logs: foo 42
       * m2.value = 17;  // logs: bar 17
       * ```
       */
      exports.Signal = /** @class */ (function () {
          /**
           * Construct a new signal.
           *
           * @param sender - The sender which owns the signal.
           */
          function Signal(sender) {
              this.sender = sender;
          }
          /**
           * Connect a slot to the signal.
           *
           * @param slot - The slot to invoke when the signal is emitted.
           *
           * @param thisArg - The `this` context for the slot. If provided,
           *   this must be a non-primitive object.
           *
           * @returns `true` if the connection succeeds, `false` otherwise.
           */
          Signal.prototype.connect = function (slot, thisArg) {
              return Private.connect(this, slot, thisArg);
          };
          /**
           * Disconnect a slot from the signal.
           *
           * @param slot - The slot to disconnect from the signal.
           *
           * @param thisArg - The `this` context for the slot. If provided,
           *   this must be a non-primitive object.
           *
           * @returns `true` if the connection is removed, `false` otherwise.
           */
          Signal.prototype.disconnect = function (slot, thisArg) {
              return Private.disconnect(this, slot, thisArg);
          };
          /**
           * Emit the signal and invoke the connected slots.
           *
           * @param args - The args to pass to the connected slots.
           *
           * #### Notes
           * Slots are invoked synchronously in connection order.
           *
           * Exceptions thrown by connected slots will be caught and logged.
           */
          Signal.prototype.emit = function (args) {
              Private.emit(this, args);
          };
          return Signal;
      }());
      /**
       * The namespace for the `Signal` class statics.
       */
      (function (Signal) {
          /**
           * Remove all connections between a sender and receiver.
           *
           * @param sender - The sender object of interest.
           *
           * @param receiver - The receiver object of interest.
           *
           * #### Notes
           * If a `thisArg` is provided when connecting a signal, that object
           * is considered the receiver. Otherwise, the `slot` is considered
           * the receiver.
           */
          function disconnectBetween(sender, receiver) {
              Private.disconnectBetween(sender, receiver);
          }
          Signal.disconnectBetween = disconnectBetween;
          /**
           * Remove all connections where the given object is the sender.
           *
           * @param sender - The sender object of interest.
           */
          function disconnectSender(sender) {
              Private.disconnectSender(sender);
          }
          Signal.disconnectSender = disconnectSender;
          /**
           * Remove all connections where the given object is the receiver.
           *
           * @param receiver - The receiver object of interest.
           *
           * #### Notes
           * If a `thisArg` is provided when connecting a signal, that object
           * is considered the receiver. Otherwise, the `slot` is considered
           * the receiver.
           */
          function disconnectReceiver(receiver) {
              Private.disconnectReceiver(receiver);
          }
          Signal.disconnectReceiver = disconnectReceiver;
          /**
           * Remove all connections where an object is the sender or receiver.
           *
           * @param object - The object of interest.
           *
           * #### Notes
           * If a `thisArg` is provided when connecting a signal, that object
           * is considered the receiver. Otherwise, the `slot` is considered
           * the receiver.
           */
          function disconnectAll(object) {
              Private.disconnectAll(object);
          }
          Signal.disconnectAll = disconnectAll;
          /**
           * Clear all signal data associated with the given object.
           *
           * @param object - The object for which the data should be cleared.
           *
           * #### Notes
           * This removes all signal connections and any other signal data
           * associated with the object.
           */
          function clearData(object) {
              Private.disconnectAll(object);
          }
          Signal.clearData = clearData;
          /**
           * Get the signal exception handler.
           *
           * @returns The current exception handler.
           *
           * #### Notes
           * The default exception handler is `console.error`.
           */
          function getExceptionHandler() {
              return Private.exceptionHandler;
          }
          Signal.getExceptionHandler = getExceptionHandler;
          /**
           * Set the signal exception handler.
           *
           * @param handler - The function to use as the exception handler.
           *
           * @returns The old exception handler.
           *
           * #### Notes
           * The exception handler is invoked when a slot throws an exception.
           */
          function setExceptionHandler(handler) {
              var old = Private.exceptionHandler;
              Private.exceptionHandler = handler;
              return old;
          }
          Signal.setExceptionHandler = setExceptionHandler;
      })(exports.Signal || (exports.Signal = {}));
      /**
       * The namespace for the module implementation details.
       */
      var Private;
      (function (Private) {
          /**
           * The signal exception handler function.
           */
          Private.exceptionHandler = function (err) {
              console.error(err);
          };
          /**
           * Connect a slot to a signal.
           *
           * @param signal - The signal of interest.
           *
           * @param slot - The slot to invoke when the signal is emitted.
           *
           * @param thisArg - The `this` context for the slot. If provided,
           *   this must be a non-primitive object.
           *
           * @returns `true` if the connection succeeds, `false` otherwise.
           */
          function connect(signal, slot, thisArg) {
              // Coerce a `null` `thisArg` to `undefined`.
              thisArg = thisArg || undefined;
              // Ensure the sender's array of receivers is created.
              var receivers = receiversForSender.get(signal.sender);
              if (!receivers) {
                  receivers = [];
                  receiversForSender.set(signal.sender, receivers);
              }
              // Bail if a matching connection already exists.
              if (findConnection(receivers, signal, slot, thisArg)) {
                  return false;
              }
              // Choose the best object for the receiver.
              var receiver = thisArg || slot;
              // Ensure the receiver's array of senders is created.
              var senders = sendersForReceiver.get(receiver);
              if (!senders) {
                  senders = [];
                  sendersForReceiver.set(receiver, senders);
              }
              // Create a new connection and add it to the end of each array.
              var connection = { signal: signal, slot: slot, thisArg: thisArg };
              receivers.push(connection);
              senders.push(connection);
              // Indicate a successful connection.
              return true;
          }
          Private.connect = connect;
          /**
           * Disconnect a slot from a signal.
           *
           * @param signal - The signal of interest.
           *
           * @param slot - The slot to disconnect from the signal.
           *
           * @param thisArg - The `this` context for the slot. If provided,
           *   this must be a non-primitive object.
           *
           * @returns `true` if the connection is removed, `false` otherwise.
           */
          function disconnect(signal, slot, thisArg) {
              // Coerce a `null` `thisArg` to `undefined`.
              thisArg = thisArg || undefined;
              // Lookup the list of receivers, and bail if none exist.
              var receivers = receiversForSender.get(signal.sender);
              if (!receivers || receivers.length === 0) {
                  return false;
              }
              // Bail if no matching connection exits.
              var connection = findConnection(receivers, signal, slot, thisArg);
              if (!connection) {
                  return false;
              }
              // Choose the best object for the receiver.
              var receiver = thisArg || slot;
              // Lookup the array of senders, which is now known to exist.
              var senders = sendersForReceiver.get(receiver);
              // Clear the connection and schedule cleanup of the arrays.
              connection.signal = null;
              scheduleCleanup(receivers);
              scheduleCleanup(senders);
              // Indicate a successful disconnection.
              return true;
          }
          Private.disconnect = disconnect;
          /**
           * Remove all connections between a sender and receiver.
           *
           * @param sender - The sender object of interest.
           *
           * @param receiver - The receiver object of interest.
           */
          function disconnectBetween(sender, receiver) {
              // If there are no receivers, there is nothing to do.
              var receivers = receiversForSender.get(sender);
              if (!receivers || receivers.length === 0) {
                  return;
              }
              // If there are no senders, there is nothing to do.
              var senders = sendersForReceiver.get(receiver);
              if (!senders || senders.length === 0) {
                  return;
              }
              // Clear each connection between the sender and receiver.
              algorithm.each(senders, function (connection) {
                  // Skip connections which have already been cleared.
                  if (!connection.signal) {
                      return;
                  }
                  // Clear the connection if it matches the sender.
                  if (connection.signal.sender === sender) {
                      connection.signal = null;
                  }
              });
              // Schedule a cleanup of the senders and receivers.
              scheduleCleanup(receivers);
              scheduleCleanup(senders);
          }
          Private.disconnectBetween = disconnectBetween;
          /**
           * Remove all connections where the given object is the sender.
           *
           * @param sender - The sender object of interest.
           */
          function disconnectSender(sender) {
              // If there are no receivers, there is nothing to do.
              var receivers = receiversForSender.get(sender);
              if (!receivers || receivers.length === 0) {
                  return;
              }
              // Clear each receiver connection.
              algorithm.each(receivers, function (connection) {
                  // Skip connections which have already been cleared.
                  if (!connection.signal) {
                      return;
                  }
                  // Choose the best object for the receiver.
                  var receiver = connection.thisArg || connection.slot;
                  // Clear the connection.
                  connection.signal = null;
                  // Cleanup the array of senders, which is now known to exist.
                  scheduleCleanup(sendersForReceiver.get(receiver));
              });
              // Schedule a cleanup of the receivers.
              scheduleCleanup(receivers);
          }
          Private.disconnectSender = disconnectSender;
          /**
           * Remove all connections where the given object is the receiver.
           *
           * @param receiver - The receiver object of interest.
           */
          function disconnectReceiver(receiver) {
              // If there are no senders, there is nothing to do.
              var senders = sendersForReceiver.get(receiver);
              if (!senders || senders.length === 0) {
                  return;
              }
              // Clear each sender connection.
              algorithm.each(senders, function (connection) {
                  // Skip connections which have already been cleared.
                  if (!connection.signal) {
                      return;
                  }
                  // Lookup the sender for the connection.
                  var sender = connection.signal.sender;
                  // Clear the connection.
                  connection.signal = null;
                  // Cleanup the array of receivers, which is now known to exist.
                  scheduleCleanup(receiversForSender.get(sender));
              });
              // Schedule a cleanup of the list of senders.
              scheduleCleanup(senders);
          }
          Private.disconnectReceiver = disconnectReceiver;
          /**
           * Remove all connections where an object is the sender or receiver.
           *
           * @param object - The object of interest.
           */
          function disconnectAll(object) {
              // Remove all connections where the given object is the sender.
              disconnectSender(object);
              // Remove all connections where the given object is the receiver.
              disconnectReceiver(object);
          }
          Private.disconnectAll = disconnectAll;
          /**
           * Emit a signal and invoke its connected slots.
           *
           * @param signal - The signal of interest.
           *
           * @param args - The args to pass to the connected slots.
           *
           * #### Notes
           * Slots are invoked synchronously in connection order.
           *
           * Exceptions thrown by connected slots will be caught and logged.
           */
          function emit(signal, args) {
              // If there are no receivers, there is nothing to do.
              var receivers = receiversForSender.get(signal.sender);
              if (!receivers || receivers.length === 0) {
                  return;
              }
              // Invoke the slots for connections with a matching signal.
              // Any connections added during emission are not invoked.
              for (var i = 0, n = receivers.length; i < n; ++i) {
                  var connection = receivers[i];
                  if (connection.signal === signal) {
                      invokeSlot(connection, args);
                  }
              }
          }
          Private.emit = emit;
          /**
           * A weak mapping of sender to array of receiver connections.
           */
          var receiversForSender = new WeakMap();
          /**
           * A weak mapping of receiver to array of sender connections.
           */
          var sendersForReceiver = new WeakMap();
          /**
           * A set of connection arrays which are pending cleanup.
           */
          var dirtySet = new Set();
          /**
           * A function to schedule an event loop callback.
           */
          var schedule = (function () {
              var ok = typeof requestAnimationFrame === 'function';
              // @ts-ignore
              return ok ? requestAnimationFrame : setImmediate;
          })();
          /**
           * Find a connection which matches the given parameters.
           */
          function findConnection(connections, signal, slot, thisArg) {
              return algorithm.find(connections, function (connection) {
                  return connection.signal === signal &&
                      connection.slot === slot &&
                      connection.thisArg === thisArg;
              });
          }
          /**
           * Invoke a slot with the given parameters.
           *
           * The connection is assumed to be valid.
           *
           * Exceptions in the slot will be caught and logged.
           */
          function invokeSlot(connection, args) {
              var signal = connection.signal, slot = connection.slot, thisArg = connection.thisArg;
              try {
                  slot.call(thisArg, signal.sender, args);
              }
              catch (err) {
                  Private.exceptionHandler(err);
              }
          }
          /**
           * Schedule a cleanup of a connection array.
           *
           * This will add the array to the dirty set and schedule a deferred
           * cleanup of the array contents. On cleanup, any connection with a
           * `null` signal will be removed from the array.
           */
          function scheduleCleanup(array) {
              if (dirtySet.size === 0) {
                  schedule(cleanupDirtySet);
              }
              dirtySet.add(array);
          }
          /**
           * Cleanup the connection lists in the dirty set.
           *
           * This function should only be invoked asynchronously, when the
           * stack frame is guaranteed to not be on the path of user code.
           */
          function cleanupDirtySet() {
              dirtySet.forEach(cleanupConnections);
              dirtySet.clear();
          }
          /**
           * Cleanup the dirty connections in a connections array.
           *
           * This will remove any connection with a `null` signal.
           *
           * This function should only be invoked asynchronously, when the
           * stack frame is guaranteed to not be on the path of user code.
           */
          function cleanupConnections(connections) {
              algorithm.ArrayExt.removeAllWhere(connections, isDeadConnection);
          }
          /**
           * Test whether a connection is dead.
           *
           * A dead connection has a `null` signal.
           */
          function isDeadConnection(connection) {
              return connection.signal === null;
          }
      })(Private || (Private = {}));
  
      Object.defineProperty(exports, '__esModule', { value: true });
  
  })));
  //# sourceMappingURL=index.js.map
  