| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194 | 
							- /* Copyright 2012 Mozilla Foundation
 
-  *
 
-  * Licensed under the Apache License, Version 2.0 (the "License");
 
-  * you may not use this file except in compliance with the License.
 
-  * You may obtain a copy of the License at
 
-  *
 
-  *     http://www.apache.org/licenses/LICENSE-2.0
 
-  *
 
-  * Unless required by applicable law or agreed to in writing, software
 
-  * distributed under the License is distributed on an "AS IS" BASIS,
 
-  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
-  * See the License for the specific language governing permissions and
 
-  * limitations under the License.
 
-  */
 
- const WaitOnType = {
 
-   EVENT: "event",
 
-   TIMEOUT: "timeout",
 
- };
 
- /**
 
-  * @typedef {Object} WaitOnEventOrTimeoutParameters
 
-  * @property {Object} target - The event target, can for example be:
 
-  *   `window`, `document`, a DOM element, or an {EventBus} instance.
 
-  * @property {string} name - The name of the event.
 
-  * @property {number} delay - The delay, in milliseconds, after which the
 
-  *   timeout occurs (if the event wasn't already dispatched).
 
-  */
 
- /**
 
-  * Allows waiting for an event or a timeout, whichever occurs first.
 
-  * Can be used to ensure that an action always occurs, even when an event
 
-  * arrives late or not at all.
 
-  *
 
-  * @param {WaitOnEventOrTimeoutParameters}
 
-  * @returns {Promise} A promise that is resolved with a {WaitOnType} value.
 
-  */
 
- function waitOnEventOrTimeout({ target, name, delay = 0 }) {
 
-   return new Promise(function (resolve, reject) {
 
-     if (
 
-       typeof target !== "object" ||
 
-       !(name && typeof name === "string") ||
 
-       !(Number.isInteger(delay) && delay >= 0)
 
-     ) {
 
-       throw new Error("waitOnEventOrTimeout - invalid parameters.");
 
-     }
 
-     function handler(type) {
 
-       if (target instanceof EventBus) {
 
-         target._off(name, eventHandler);
 
-       } else {
 
-         target.removeEventListener(name, eventHandler);
 
-       }
 
-       if (timeout) {
 
-         clearTimeout(timeout);
 
-       }
 
-       resolve(type);
 
-     }
 
-     const eventHandler = handler.bind(null, WaitOnType.EVENT);
 
-     if (target instanceof EventBus) {
 
-       target._on(name, eventHandler);
 
-     } else {
 
-       target.addEventListener(name, eventHandler);
 
-     }
 
-     const timeoutHandler = handler.bind(null, WaitOnType.TIMEOUT);
 
-     const timeout = setTimeout(timeoutHandler, delay);
 
-   });
 
- }
 
- /**
 
-  * Simple event bus for an application. Listeners are attached using the `on`
 
-  * and `off` methods. To raise an event, the `dispatch` method shall be used.
 
-  */
 
- class EventBus {
 
-   #listeners = Object.create(null);
 
-   /**
 
-    * @param {string} eventName
 
-    * @param {function} listener
 
-    * @param {Object} [options]
 
-    */
 
-   on(eventName, listener, options = null) {
 
-     this._on(eventName, listener, {
 
-       external: true,
 
-       once: options?.once,
 
-     });
 
-   }
 
-   /**
 
-    * @param {string} eventName
 
-    * @param {function} listener
 
-    * @param {Object} [options]
 
-    */
 
-   off(eventName, listener, options = null) {
 
-     this._off(eventName, listener, {
 
-       external: true,
 
-       once: options?.once,
 
-     });
 
-   }
 
-   /**
 
-    * @param {string} eventName
 
-    * @param {Object} data
 
-    */
 
-   dispatch(eventName, data) {
 
-     const eventListeners = this.#listeners[eventName];
 
-     if (!eventListeners || eventListeners.length === 0) {
 
-       return;
 
-     }
 
-     let externalListeners;
 
-     // Making copy of the listeners array in case if it will be modified
 
-     // during dispatch.
 
-     for (const { listener, external, once } of eventListeners.slice(0)) {
 
-       if (once) {
 
-         this._off(eventName, listener);
 
-       }
 
-       if (external) {
 
-         (externalListeners ||= []).push(listener);
 
-         continue;
 
-       }
 
-       listener(data);
 
-     }
 
-     // Dispatch any "external" listeners *after* the internal ones, to give the
 
-     // viewer components time to handle events and update their state first.
 
-     if (externalListeners) {
 
-       for (const listener of externalListeners) {
 
-         listener(data);
 
-       }
 
-       externalListeners = null;
 
-     }
 
-   }
 
-   /**
 
-    * @ignore
 
-    */
 
-   _on(eventName, listener, options = null) {
 
-     const eventListeners = (this.#listeners[eventName] ||= []);
 
-     eventListeners.push({
 
-       listener,
 
-       external: options?.external === true,
 
-       once: options?.once === true,
 
-     });
 
-   }
 
-   /**
 
-    * @ignore
 
-    */
 
-   _off(eventName, listener, options = null) {
 
-     const eventListeners = this.#listeners[eventName];
 
-     if (!eventListeners) {
 
-       return;
 
-     }
 
-     for (let i = 0, ii = eventListeners.length; i < ii; i++) {
 
-       if (eventListeners[i].listener === listener) {
 
-         eventListeners.splice(i, 1);
 
-         return;
 
-       }
 
-     }
 
-   }
 
- }
 
- /**
 
-  * NOTE: Only used to support various PDF viewer tests in `mozilla-central`.
 
-  */
 
- class AutomationEventBus extends EventBus {
 
-   dispatch(eventName, data) {
 
-     if (typeof PDFJSDev !== "undefined" && !PDFJSDev.test("MOZCENTRAL")) {
 
-       throw new Error("Not implemented: AutomationEventBus.dispatch");
 
-     }
 
-     super.dispatch(eventName, data);
 
-     const details = Object.create(null);
 
-     if (data) {
 
-       for (const key in data) {
 
-         const value = data[key];
 
-         if (key === "source") {
 
-           if (value === window || value === document) {
 
-             return; // No need to re-dispatch (already) global events.
 
-           }
 
-           continue; // Ignore the `source` property.
 
-         }
 
-         details[key] = value;
 
-       }
 
-     }
 
-     const event = document.createEvent("CustomEvent");
 
-     event.initCustomEvent(eventName, true, true, details);
 
-     document.dispatchEvent(event);
 
-   }
 
- }
 
- export { AutomationEventBus, EventBus, waitOnEventOrTimeout, WaitOnType };
 
 
  |