{"version":3,"file":"MatsSocket.umd.cjs","sources":["../lib/AuthorizationRequiredEvent.js","../lib/ConnectionState.js","../lib/ConnectionEvent.js","../lib/MessageType.js","../lib/ReceivedEvent.js","../lib/MessageEvent.js","../lib/SubscriptionEvent.js","../lib/InitiationProcessedEvent.js","../lib/PingPong.js","../lib/MatsSocketCloseCodes.js","../lib/ErrorEvent.js","../lib/DebugInformation.js","../lib/MatsSocket.js"],"sourcesContent":["import './typedefs.js';\n// Repeating typedefs here, since 'tsc' otherwise don't create the 'export type FractionalMillis = number;' line.\n/**\n * Fractional milliseconds for high-res timing.\n * @typedef {number} FractionalMillis\n */\n\n/**\n * Timestamp, millis-since-epoch.\n * @typedef {number} Timestamp\n */\n\nexport { AuthorizationRequiredEvent, AuthorizationRequiredEventType }\n\n/**\n * Sent by the MatsSocket, via the {@link MatsSocket#setAuthorizationExpiredCallback}, when it requires new or\n * revalidated authentication by the client.\n *\n * @param {AuthorizationRequiredEventType} type - {@link AuthorizationRequiredEvent#type}\n * @param {Timestamp} currentExpirationTimestamp - {@link AuthorizationRequiredEvent#currentExpirationTimestamp}\n * @class\n */\nfunction AuthorizationRequiredEvent(type, currentExpirationTimestamp) {\n    /**\n     * Type of the event, one of {@link AuthorizationRequiredEventType}.\n     *\n     * @type {AuthorizationRequiredEventType}\n     */\n    this.type = type;\n\n    /**\n     * Millis-since-epoch when the current Authorization expires - note that this might well still be in the future,\n     * but the \"slack\" left before expiration is used up.\n     *\n     * @type {Timestamp}\n     */\n    this.currentExpirationTimestamp = currentExpirationTimestamp;\n}\n\n/**\n * Type of {@link AuthorizationRequiredEvent}.\n *\n * @enum {string}\n * @readonly\n */\nconst AuthorizationRequiredEventType = {\n    /**\n     * Initial state, if auth not already set by app.\n     */\n    NOT_PRESENT: \"notpresent\",\n\n    /**\n     * The authentication is expired - note that this might well still be in the future,\n     * but the \"slack\" left before expiration is not long enough.\n     */\n    EXPIRED: \"expired\",\n\n    /**\n     * The server has requested that the app provides fresh auth to proceed - this needs to be fully fresh, even\n     * though there might still be \"slack\" enough left on the current authorization to proceed. (The server side\n     * might want the full expiry to proceed, or wants to ensure that the app can still produce new auth - i.e.\n     * it might suspect that the current authentication session has been invalidated, and need proof that the app\n     * can still produce new authorizations/tokens).\n     */\n    REAUTHENTICATE: \"reauthenticate\"\n};\nObject.freeze(AuthorizationRequiredEventType);","export { ConnectionState }\n\n/**\n * States for MatsSocket's {@link MatsSocket#state state}.\n *\n * @enum {string}\n * @readonly\n */\nconst ConnectionState = {\n    /**\n     * This is the initial State of a MatsSocket. Also, the MatsSocket is re-set back to this State in a\n     * Session-Closed-from-Server situation (which is communicated via listeners registered with\n     * {@link MatsSocket#addSessionClosedEventListener}), OR if you have explicitly performed a\n     * {@link MatsSocket#close}.\n     * <p/>\n     * Only transition out of this state is into {@link ConnectionState.CONNECTING}.\n     */\n    NO_SESSION: \"nosession\",\n\n    /**\n     * Read doc at {@link ConnectionEventType.CONNECTING}.\n     */\n    CONNECTING: \"connecting\",\n\n    /**\n     * Read doc at {@link ConnectionEventType.WAITING}.\n     */\n    WAITING: \"waiting\",\n\n    /**\n     * Read doc at {@link ConnectionEventType.CONNECTED}.\n     */\n    CONNECTED: \"connected\",\n\n    /**\n     * Read doc at {@link ConnectionEventType.SESSION_ESTABLISHED}.\n     */\n    SESSION_ESTABLISHED: \"sessionestablished\"\n};\nObject.freeze(ConnectionState);\n","import { ConnectionState } from \"./ConnectionState.js\";\n\nexport { ConnectionEvent, ConnectionEventType }\n\n/**\n * Event object for {@link MatsSocket#addConnectionEventListener}.\n * <p />\n * <b>Note on event ordering</b>: {@link ConnectionEvent}s are delivered ASAP. This means that for events that the\n * client controls, they are issued <i/>before</i> the operation they describe commences:\n * {@link ConnectionEventType#CONNECTING CONNECTING} and\n * {@link ConnectionEventType#SESSION_ESTABLISHED SESSION_ESTABLISHED}. However, for events where the client is\n * \"reacting\", e.g. when the WebSocket connects, or abruptly closes, they are issued ASAP when the Client gets to know about it:\n * {@link ConnectionEventType#CONNECTED CONNECTED}, {@link ConnectionEventType#LOST_CONNECTION LOST_CONNECTION},\n * {@link ConnectionEventType#CONNECTION_ERROR CONNECTION_ERROR} and {@link ConnectionEventType#WAITING WAITING}.\n * For {@link ConnectionEventType#COUNTDOWN COUNTDOWN}, there is not much to say wrt. timing, other than you won't typically\n * get a 'countdown'-event with 0 seconds left, as that is when we transition into 'connecting' again. For events\n * that also describe {@link ConnectionState}s, the {@link MatsSocket.state} is updated before the event is fired.\n *\n * @param {ConnectionEventType} type - {@link ConnectionEvent#type}\n * @param {string} webSocketUrl - {@link ConnectionEvent#webSocketUrl}\n * @param {Event} webSocketEvent - {@link ConnectionEvent#webSocketEvent}\n * @param {number} timeoutSeconds - {@link ConnectionEvent#timeoutSeconds}\n * @param {number} countdownSeconds - {@link ConnectionEvent#countdownSeconds}\n * @param {number} connectionAttempt - {@link ConnectionEvent#connectionAttempt}\n * @class\n */\nfunction ConnectionEvent(type, webSocketUrl, webSocketEvent, timeoutSeconds, countdownSeconds, connectionAttempt) {\n    /**\n     * The type of the <code>ConnectionEvent</code>, returns an enum value of {@link ConnectionEventType}.\n     *\n     * @type {ConnectionEventType}\n     */\n    this.type = type;\n\n    /**\n     * Holds the current URL we're either connected to, was connected to, or trying to connect to.\n     *\n     * @type {string}\n     */\n    this.webSocketUrl = webSocketUrl;\n\n    /**\n     * For several of the events (enumerated in {@link ConnectionEventType}), there is an underlying WebSocket event\n     * that caused it. This field holds that.\n     * <ul>\n     *     <li>{@link ConnectionEventType#WAITING}: WebSocket {@link CloseEvent} that caused this transition.</li>\n     *     <li>{@link ConnectionEventType#CONNECTED}: WebSocket {@link Event} that caused this transition.</li>\n     *     <li>{@link ConnectionEventType#CONNECTION_ERROR}: WebSocket {@link Event} that caused this transition.</li>\n     *     <li>{@link ConnectionEventType#LOST_CONNECTION}: WebSocket {@link CloseEvent} that caused it.</li>\n     * </ul>\n     *\n     * @type {Event}\n     */\n    this.webSocketEvent = webSocketEvent;\n\n    /**\n     * For {@link ConnectionEventType#CONNECTING}, {@link ConnectionEventType#WAITING} and {@link ConnectionEventType#COUNTDOWN},\n     * tells how long the timeout for this attempt is, i.e. what the COUNTDOWN events start out with. Together with\n     * {@link #countdownSeconds} of the COUNTDOWN events, this can be used to calculate a fraction if you want to\n     * make a \"progress bar\" of sorts.\n     * <p/>\n     * The timeouts starts at 500 ms (unless there is only 1 URL configured, in which case 5 seconds), and then\n     * increases exponentially, but maxes out at 15 seconds.\n     *\n     * @type {number}\n     */\n    this.timeoutSeconds = timeoutSeconds;\n\n    /**\n     * For {@link ConnectionEventType#CONNECTING}, {@link ConnectionEventType#WAITING} and {@link ConnectionEventType#COUNTDOWN},\n     * tells how many seconds there are left for this attempt (of the {@link #timeoutSeconds} it started with),\n     * with a tenth of a second as precision. With the COUNTDOWN events, these come in each 100 ms (1/10 second),\n     * and show how long time there is left before trying again (if MatsSocket is configured with multiple URLs,\n     * the next attempt will be a different URL).\n     * <p/>\n     * The countdown is started when the state transitions to {@link ConnectionEventType#CONNECTING}, and\n     * stops either when {@link ConnectionEventType#CONNECTED} or the timeout reaches zero. If the\n     * state is still CONNECTING when the countdown reaches zero, implying that the \"new WebSocket(..)\" call still\n     * has not either opened or closed, the connection attempt is aborted by calling webSocket.close(). It then\n     * tries again, possibly with a different URL - and the countdown starts over.\n     * <p/>\n     * Notice that the countdown is not affected by any state transition into {@link ConnectionEventType#WAITING} -\n     * such transition only means that the \"new WebSocket(..)\" call failed and emitted a close-event, but we will\n     * still wait out the countdown before trying again.\n     * <p/>\n     * Notice that you will most probably not get an event with 0 seconds, as that is when we transition into\n     * {@link ConnectionEventType#CONNECTING} and the countdown starts over (possibly with a larger timeout).\n     * <p/>\n     * Truncated exponential backoff: The timeouts starts at 500 ms (unless there is only 1 URL configured, in which\n     * case 5 seconds), and then increases exponentially, but maxes out at 15 seconds.\n     *\n     * @type {number}\n     */\n    this.countdownSeconds = countdownSeconds;\n\n    /**\n     * The connection attempt count, starts at 0th attempt and increases for each time the connection attempt fails.\n     *\n     * @type {number}\n     */\n    this.connectionAttempt = connectionAttempt;\n}\n\n\n/**\n * The event types of {@link ConnectionEvent} - four of the event types are state-transitions into different states\n * of {@link ConnectionState}.\n *\n * @enum {string}\n * @readonly\n */\nconst ConnectionEventType = {\n    /**\n     * State, and fires as ConnectionEvent when we transition into this state, which is when the WebSocket is literally trying to connect.\n     * This is between <code>new WebSocket(url)</code> (or the {@link MatsSocket#preconnectoperation \"PreConnectOperation\"} if configured),\n     * and either webSocket.onopen or webSocket.onclose is fired, or countdown reaches 0. If webSocket.onopen,\n     * we transition into {@link ConnectionEventType.CONNECTED}, if webSocket.onclose, we transition into\n     * {@link ConnectionEventType.WAITING}. If we reach countdown 0 while in CONNECTING, we will \"re-transition\" to the same state, and\n     * thus get one more event of CONNECTING.\n     * <p/>\n     * User Info Tip: Show a info-box, stating \"Connecting! <4.0 seconds..>\", countdown in \"grayed out\" style, box is\n     * some neutral information color, e.g. yellow (fading over to this color if already red or orange due to\n     * {@link ConnectionEventType.CONNECTION_ERROR} or {@link ConnectionEventType.LOST_CONNECTION}).\n     * Each time it transitions into CONNECTING, it will start a new countdown. Let's say it starts from say 4\n     * seconds: If this connection attempt fails after 1 second, it will transition into WAITING and continue the\n     * countdown with 3 seconds remaining.\n     */\n    CONNECTING: ConnectionState.CONNECTING,\n\n    /**\n     * State, and fires as ConnectionEvent when we transition into this state, which is when {@link ConnectionEventType.CONNECTING} fails.\n     * The only transition out of this state is {@link ConnectionEventType.CONNECTING}, when the {@link ConnectionEventType.COUNTDOWN} reaches 0.\n     * <p/>\n     * Notice that the {@link ConnectionEvent} contains the {@link Event} that came with webSocket.close (while CONNECTING).\n     * <p/>\n     * User Info Tip: Show a info-box, stating \"Waiting! <2.9 seconds..>\", countdown in normal visibility, box is\n     * some neutral information color, e.g. yellow (keeping the box color fading if in progress).\n     * It will come into this state from {@link ConnectionEventType.CONNECTING}, and have the time remaining from the initial countdown.\n     * So if the attempt countdown started from 4 seconds, and it took 1 second before the connection attempt failed,\n     * then there will be 3 seconds left in WAITING state.\n     */\n    WAITING: ConnectionState.WAITING,\n\n    /**\n     * State, and fires as ConnectionEvent when we transition into this state, which is when WebSocket.onopen is fired.\n     * Notice that the MatsSocket is still not fully established, as we have not yet exchanged HELLO and WELCOME -\n     * the MatsSocket is fully established at {@link ConnectionEventType.SESSION_ESTABLISHED}.\n     * <p/>\n     * Notice that the {@link ConnectionEvent} contains the WebSocket 'onopen' {@link Event} that was issued when\n     * the WebSocket opened.\n     * <p/>\n     * User Info Tip: Show a info-box, stating \"Connected!\", happy-color, e.g. green, with no countdown.\n     */\n    CONNECTED: ConnectionState.CONNECTED,\n\n    /**\n     * State, and fires as ConnectionEvent when we transition into this state, which is when when the WELCOME MatsSocket message comes\n     * from the Server, also implying that it has been authenticated: The MatsSocket is now fully established, and\n     * actual messages can be exchanged.\n     * <p/>\n     * User Info Tip: Show a info-box, stating \"Session OK!\", happy-color, e.g. green, with no countdown - and the\n     * entire info-box fades away fast, e.g. after 1 second.\n     */\n    SESSION_ESTABLISHED: ConnectionState.SESSION_ESTABLISHED,\n\n    /**\n     * This is a pretty worthless event. It comes from WebSocket.onerror. It will <i>always</i> be trailed by a\n     * WebSocket.onclose, which gives the event {@link ConnectionEventType.LOST_CONNECTION}.\n     * <p/>\n     * Notice that the {@link ConnectionEvent} contains the {@link Event} that caused the error.\n     * <p/>\n     * User Info Tip: Show a info-box, which is some reddish color (no need for text since next event {@link ConnectionEventType.LOST_CONNECTION}) comes immediately).\n     */\n    CONNECTION_ERROR: \"connectionerror\",\n\n    /**\n     * This comes when WebSocket.onclose is fired \"unexpectedly\", <b>and the reason for this close is NOT a SessionClosed Event</b> (The latter will\n     * instead invoke the listeners registered with {@link MatsSocket#addSessionClosedEventListener}).\n     * A LOST_CONNECTION will start a reconnection attempt after a very brief delay (couple of hundred milliseconds),\n     * and the next state transition and thus event is {@link ConnectionEventType.CONNECTING}.\n     * <p/>\n     * Notice that the {@link ConnectionEvent} contains the {@link CloseEvent} that caused the lost connection.\n     * <p/>\n     * User Info Tip: Show a info-box, stating \"Connection broken!\", which is some orange color (unless it already\n     * is red due to {@link ConnectionEventType.CONNECTION_ERROR}), fading over to the next color when next event ({@link ConnectionEventType.CONNECTING}\n     * comes in.\n     */\n    LOST_CONNECTION: \"lostconnection\",\n\n    /**\n     * Events fired every 100ms while in state {@link ConnectionEventType.CONNECTING}, possibly continuing over to {@link ConnectionEventType.WAITING}.\n     * Notice that you will most probably not get an event with 0 seconds left, as that is when we (re-)transition to\n     * {@link ConnectionEventType.CONNECTING} and the countdown starts over (possibly with a larger timeout). Read more at\n     * {@link ConnectionEvent#countdownSeconds}.\n     * <p/>\n     * User Info Tip: Read more at {@link ConnectionEventType.CONNECTING} and {@link ConnectionEventType.WAITING}.\n     */\n    COUNTDOWN: \"countdown\"\n\n};\nObject.freeze(ConnectionEventType);\n","export { MessageType }\n\n/**\n * <b>Copied directly from MatsSocketServer.java</b>:\n * All Message Types (aka MatsSocket Envelope Types) used in the wire-protocol of MatsSocket.\n *\n * @enum {string}\n * @readonly\n */\nconst MessageType = {\n    /**\n     * A HELLO message must be part of the first Pipeline of messages, preferably alone. One of the messages in the\n     * first Pipeline must have the \"auth\" field set, and it might as well be the HELLO.\n     */\n    HELLO: \"HELLO\",\n\n    /**\n     * The reply to a {@link #HELLO}, where the MatsSocketSession is established, and the MatsSocketSessionId is\n     * returned. If you included a MatsSocketSessionId in the HELLO, signifying that you want to reconnect to an\n     * existing session, and you actually get a WELCOME back, it will be the same as what you provided - otherwise\n     * the connection is closed with {@link MatsSocketCloseCodes#SESSION_LOST}.\n     */\n    WELCOME: \"WELCOME\",\n\n    /**\n     * The sender sends a \"fire and forget\" style message.\n     */\n    SEND: \"SEND\",\n\n    /**\n     * The sender initiates a request, to which a {@link #RESOLVE} or {@link #REJECT} message is expected.\n     */\n    REQUEST: \"REQUEST\",\n\n    /**\n     * The sender should retry the message (the receiver could not handle it right now, but a Retry might fix it).\n     */\n    RETRY: \"RETRY\",\n\n    /**\n     * The specified message was Received, and acknowledged positively - i.e. the other party has decided to process\n     * it.\n     * <p/>\n     * The sender of the ACK has now taken over responsibility of the specified message, put it (at least the\n     * reference ClientMessageId) in its <i>Inbox</i>, and possibly started processing it. The reason for the Inbox\n     * is so that if it Receives the message again, it may just insta-ACK/NACK it and toss this copy out the window\n     * (since it has already handled it).\n     * <p/>\n     * When an ACK is received, the receiver may safely delete the acknowledged message from its <i>Outbox</i>.\n     */\n    ACK: \"ACK\",\n\n    /**\n     * The specified message was Received, but it did not acknowledge it - i.e. the other party has decided to NOT\n     * process it.\n     * <p/>\n     * The sender of the NACK has now taken over responsibility of the specified message, put it (at least the\n     * reference Client/Server MessageId) in its <i>Inbox</i> - but has evidently decided not to process it. The\n     * reason for the Inbox is so that if it Receives the message again, it may just insta-ACK/NACK it and toss this\n     * copy out the window (since it has already handled it).\n     * <p/>\n     * When an NACK is received, the receiver may safely delete the acknowledged message from its <i>Outbox</i>.\n     */\n    NACK: \"NACK\",\n\n    /**\n     * An \"Acknowledge ^ 2\", i.e. an acknowledge of the {@link #ACK} or {@link #NACK}. When the receiver gets this,\n     * it may safely delete the entry it has for the specified message from its <i>Inbox</i>.\n     * <p/>\n     * The message is now fully transferred from one side to the other, and both parties again has no reference to\n     * this message in their Inbox and Outbox.\n     */\n    ACK2: \"ACK2\",\n\n    /**\n     * A RESOLVE-reply to a previous {@link #REQUEST} - if the Client did the {@code REQUEST}, the Server will\n     * answer with either a RESOLVE or {@link #REJECT}.\n     */\n    RESOLVE: \"RESOLVE\",\n\n    /**\n     * A REJECT-reply to a previous {@link #REQUEST} - if the Client did the {@code REQUEST}, the Server will answer\n     * with either a REJECT or {@link #RESOLVE}.\n     */\n    REJECT: \"REJECT\",\n\n    /**\n     * Request from Client: The Client want to subscribe to a Topic, the TopicId is specified in 'eid'.\n     */\n    SUB: \"SUB\",\n\n    /**\n     * Request from Client: The Client want to unsubscribe to a Topic, the TopicId is specified in 'eid'.\n     */\n    UNSUB: \"UNSUB\",\n\n    /**\n     * Reply from Server: Subscription was OK. If this is a reconnect, this indicates that any messages that was\n     * lost \"while offline\" will now be delivered/\"replayed\".\n     */\n    SUB_OK: \"SUB_OK\",\n\n    /**\n     * Reply from Server: Subscription went OK, but you've lost messages: The messageId that was referenced in the\n     * {@link #SUB} was not known to the server, implying that there are at least one message that has expired, and\n     * as such it can be many - so you won't get any \"replayed\".\n     */\n    SUB_LOST: \"SUB_LOST\",\n\n    /**\n     * Reply from Server: Subscription was not authorized - no messages for this Topic will be delivered.\n     */\n    SUB_NO_AUTH: \"SUB_NO_AUTH\",\n\n    /**\n     * Topic message from Server: A message is issued on Topic, the TopicId is specified in 'eid', while the message\n     * is in 'msg'.\n     */\n    PUB: \"PUB\",\n\n    /**\n     * The server requests that the Client re-authenticates, where the Client should immediately get a fresh\n     * authentication and send it back using either any message it has pending, or in a separate {@link #AUTH}\n     * message. Message processing - both processing of received messages, and sending of outgoing messages (i.e.\n     * Replies to REQUESTs, or Server-initiated SENDs and REQUESTs) will be stalled until such auth is gotten.\n     */\n    REAUTH: \"REAUTH\",\n\n    /**\n     * From Client: The client can use a separate AUTH message to send over the requested {@link #REAUTH} (it could\n     * just as well put the 'auth' in a PING or any other message it had pending).\n     */\n    AUTH: \"AUTH\",\n\n    /**\n     * A PING, to which a {@link #PONG} is expected.\n     */\n    PING: \"PING\",\n\n    /**\n     * A Reply to a {@link #PING}.\n     */\n    PONG: \"PONG\"\n};\nObject.freeze(MessageType);\n","import './typedefs.js';\n// Repeating typedefs here, since 'tsc' otherwise don't create the 'export type FractionalMillis = number;' line.\n/**\n * Fractional milliseconds for high-res timing.\n * @typedef {number} FractionalMillis\n */\n\n/**\n * Timestamp, millis-since-epoch.\n * @typedef {number} Timestamp\n */\n\nexport { ReceivedEvent, ReceivedEventType }\n\n/**\n * Message Received on Server event: \"acknowledge\" or \"negative acknowledge\" - these are the events which the\n * returned Promise of a send(..) is settled with (i.e. then() and catch()), and which\n * {@link MatsSocket#request request}'s receivedCallback function are invoked with.\n *\n * @param {ReceivedEventType} type - {@link ReceivedEvent#type}\n * @param {string} traceId - {@link ReceivedEvent#traceId}\n * @param {Timestamp} sentTimestamp - {@link ReceivedEvent#sentTimestamp}\n * @param {Timestamp} receivedTimestamp - {@link ReceivedEvent#receivedTimestamp}\n * @param {Timestamp} roundTripMillis - {@link ReceivedEvent#roundTripMillis}\n * @param {string} description - {@link ReceivedEvent#description}\n * @class\n */\nfunction ReceivedEvent(type, traceId, sentTimestamp, receivedTimestamp, roundTripMillis, description) {\n    /**\n     * Values are from {@link ReceivedEventType}: Type of received event, either {@link ReceivedEventType#ACK \"ack\"},\n     * {@link ReceivedEventType#NACK \"nack\"} - <b>or {@link ReceivedEventType#SESSION_CLOSED \"sessionclosed\"} if the\n     * session was closed with outstanding initiations and MatsSocket therefore \"clears out\" these initiations.</b>\n     *s\n     * @type {ReceivedEventType}\n     */\n    this.type = type;\n\n    /**\n     * TraceId for this call / message.\n     *\n     * @type {string}\n     */\n    this.traceId = traceId;\n\n    /**\n     * Millis-since-epoch when the message was sent from the Client.\n     *\n     * @type {Timestamp}\n     */\n    this.sentTimestamp = sentTimestamp;\n\n    /**\n     * Millis-since-epoch when the ACK or NACK was received on the Client, millis-since-epoch.\n     *\n     * @type {Timestamp}\n     */\n    this.receivedTimestamp = receivedTimestamp;\n\n    /**\n     * Round-trip time in milliseconds from Initiation of flow (send, request, requestReplyTo) to Received\n     * acknowledgement (ACK/NACK) was received, basically <code>{@link #receivedTimestamp}\n     * - {@link #sentTimestamp}</code>, but depending on the browser/runtime, you might get higher resolution\n     * than integer milliseconds (i.e. fractions of milliseconds, a floating point number) - it depends on\n     * the resolution of <code>performance.now()</code>.\n     * <p/>\n     * Notice that Received-events might be de-prioritized on the Server side (batched up, with micro-delays\n     * to get multiple into the same batch), so this number should not be taken as the \"ping time\".\n     *\n     * @type {FractionalMillis}\n     */\n    this.roundTripMillis = roundTripMillis;\n\n    /**\n     * Sometimes, typically on Server NACKs (e.g. targetting non-existing Endpoint), the Server supplies a\n     * description to why this was no good.\n     *\n     * @type {string}\n     */\n    this.description = description;\n}\n\n/**\n * Types of {@link ReceivedEvent}.\n *\n * @enum {string}\n * @readonly\n */\nconst ReceivedEventType = {\n    /**\n     * If the Server-side MatsSocketEndpoint/Terminator accepted the message for handling (and if relevant,\n     * forwarded it to the Mats fabric). The returned Promise of send() is <i>resolved</i> with this type of event.\n     * The 'receivedCallback' of a request() will get both \"ack\" and {@link #NACK \"nack\"}, thus must check on\n     * the type if it makes a difference.\n     */\n    ACK: \"ack\",\n\n    /**\n     * If the Server-side MatsSocketEndpoint/Terminator dit NOT accept the message, either explicitly with\n     * context.deny(), or by failing with Exception. The returned Promise of send() is <i>rejected</i> with this\n     * type of event. The 'receivedCallback' of a request() will get both \"nack\" and {@link #ACK \"ack\"}, thus must\n     * check on the type if it makes a difference.\n     * <p/>\n     * Notice that a for a Client-initiated Request which is insta-rejected in the incomingHandler by invocation of\n     * context.reject(..), this implies <i>acknowledge</i> of the <i>reception</i> of the message, but <i>reject</i>\n     * as with regard to the </i>reply</i> (the Promise returned from request(..)).\n     */\n    NACK: \"nack\",\n\n    /**\n     * \"Synthetic\" event in that it is not a message from Server: A Client-to-Server\n     * {@link MatsSocket#request() Request} was not ACKed or NACKed by the server within the\n     * {@link MatsSocket#requestTimeoutMillis default request timeout} - or a specific timeout specified in the request\n     * invocation. In these situations, any nack- or receivedCallback will be invoked with a {@link ReceivedEvent}\n     * of this type.\n     */\n    TIMEOUT: \"timeout\",\n\n    /**\n     * \"Synthetic\" event in that it is not a message from Server: This only happens if the MatsSocketSession is\n     * closed with outstanding Initiations not yet Received on Server. In these situations, any nack- or\n     * receivedCallback will be invoked with a {@link ReceivedEvent} of this type.\n     */\n    SESSION_CLOSED: \"sessionclosed\"\n};\nObject.freeze(ReceivedEventType);\n","import './typedefs.js';\n// Repeating typedefs here, since 'tsc' otherwise don't create the 'export type FractionalMillis = number;' line.\n/**\n * Fractional milliseconds for high-res timing.\n * @typedef {number} FractionalMillis\n */\n\n/**\n * Timestamp, millis-since-epoch.\n * @typedef {number} Timestamp\n */\n\nexport { MessageEvent, MessageEventType }\n\n/**\n * Message Event - the event emitted for a {@link MatsSocket#request() Requests}'s Promise resolve() and reject()\n * (i.e. then() and catch()), and to a {@link MatsSocket#terminator() Terminator}'s resolveCallback and\n * rejectCallback functions for replies due to {@link MatsSocket#requestReplyTo() requestReplyTo}, and for Server\n * initiated Sends (to Terminators), and for the event to a {@link MatsSocket#endpoint() Endpoint} upon a Server\n * initiated Request, and for the event sent to a {@link MatsSocket#subscribe() Subscription}.\n *\n * @param {MessageEventType} type - {@link MessageEvent#type}\n * @param {object} data - {@link MessageEvent#data}\n * @param {string} traceId - {@link MessageEvent#traceId}\n * @param {string} messageId - {@link MessageEvent#messageId}\n * @param {Timestamp} receivedTimestamp - {@link MessageEvent#receivedTimestamp}\n * @class\n */\nfunction MessageEvent(type, data, traceId, messageId, receivedTimestamp) {\n    /**\n     * Values are from {@link MessageEventType}: Either {@link MessageEventType#SEND \"send\"} (for a Client\n     * Terminator when targeted for a Server initiated Send); {@link MessageEventType#REQUEST \"request\"} (for a\n     * Client Endpoint when targeted for a Server initiated Request); or {@link MessageEventType#RESOLVE \"resolve\"}\n     * or {@link MessageEventType#REJECT \"reject\"} (for settling of Promise from a Client-initiated Request, and\n     * for a Client Terminator when targeted as the reply-endpoint for a Client initiated Request) - <b>or\n     * {@link MessageEventType#SESSION_CLOSED \"sessionclosed\"} if the session was closed with outstanding Requests\n     * and MatsSocket therefore \"clears out\" these Requests.</b>\n     * <p/>\n     * Notice: In the face of {@link MessageType#SESSION_CLOSED \"sessionclosed\"} or {@link MessageType#TIMEOUT \"timeout\"},\n     * the {@link #data} property (i.e. the actual message from the server) will be <code>undefined</code>.\n     * Wrt. \"sessionclosed\", this is <i>by definition</i>: The Request was outstanding, meaning that an answer from the\n     * Server had yet to come. This is opposed to a normal REJECT settling from the Server-side MatsSocketEndpoint,\n     * which may choose to include data with a rejection. The same basically goes wrt. \"timeout\", as the Server\n     * has not replied yet.\n     *\n     * @type {MessageEventType}\n     */\n    this.type = type;\n\n    /**\n     * The actual data from the other peer.\n     * <p/>\n     * Notice: In the face of {@link MessageType#SESSION_CLOSED \"sessionclosed\"} or {@link MessageType#TIMEOUT \"timeout\"},\n     * this value will be <code>undefined</code>.\n     * Wrt. \"sessionclosed\", this is <i>by definition</i>: The Request was outstanding, meaning that an answer from the\n     * Server had yet to come. This is opposed to a normal REJECT settling from the Server-side MatsSocketEndpoint,\n     * which may choose to include data with a rejection. The same basically goes wrt. \"timeout\", as the Server\n     * has not replied yet.\n     *\n     * @type {object}\n     */\n    this.data = data;\n\n    /**\n     * When a Terminator gets invoked to handle a Reply due to a Client initiated {@link MatsSocket#requestReplyTo},\n     * this holds the 'correlationInformation' object that was supplied in the requestReplyTo(..) invocation.\n     *\n     * @type {object}\n     */\n    this.correlationInformation = undefined;\n\n    /**\n     * The TraceId for this call / message.\n     *\n     * @type {string}\n     */\n    this.traceId = traceId;\n\n    /**\n     * Either the ClientMessageId if this message is a Reply to a Client-initiated Request (i.e. this message is a\n     * RESOLVE or REJECT), or ServerMessageId if this originated from the Server (i.e. SEND or REQUEST);\n     *\n     * @type {string}\n     */\n    this.messageId = messageId;\n\n    /**\n     * millis-since-epoch when the Request, for which this message is a Reply, was sent from the\n     * Client. If this message is not a Reply to a Client-initiated Request, it is undefined.\n     *\n     * @type {Timestamp}\n     */\n    this.clientRequestTimestamp = undefined;\n\n    /**\n     * When the message was received on the Client, millis-since-epoch.\n     *\n     * @type {Timestamp}\n     */\n    this.receivedTimestamp = receivedTimestamp;\n\n    /**\n     * For {@link MatsSocket#request()} and {@link MatsSocket#requestReplyTo()} Requests: Round-trip time in\n     * milliseconds from Request was performed to Reply was received, basically <code>{@link #receivedTimestamp} -\n     * {@link #clientRequestTimestamp}</code>, but depending on the browser/runtime, you might get higher resolution\n     * than integer milliseconds (i.e. fractions of milliseconds, a floating point number) - it depends on the\n     * resolution of <code>performance.now()</code>.\n\n     * @type {FractionalMillis}\n     */\n    this.roundTripMillis = undefined;\n\n    /**\n     * If debugging is requested, by means of {@link MatsSocket#debug} or the config object in the send, request and\n     * requestReplyTo, this will contain a {@link DebugInformation} instance. However, the contents of that object\n     * is decided by what you request, and what the authorized user is allowed to get as decided by the\n     * AuthenticationPlugin when authenticating the user.\n     */\n    this.debug = undefined;\n}\n\n/**\n * Types of {@link MessageEvent}.\n *\n * @enum {string}\n * @readonly\n */\nconst MessageEventType = {\n    /** Message sent from Server to Client as a resolve for a previous request. */\n    RESOLVE: \"resolve\",\n\n    /** Message sent from Server to Client as a reject for a previous request. */\n    REJECT: \"reject\",\n\n    /** Message sent from Server to a Client Terminator. */\n    SEND: \"send\",\n\n    /** Message sent from Server to a Client Endpoint (expecting a reply). */\n    REQUEST: \"request\",\n\n    /** Message sent from Server to a Client Topic. */\n    PUB: \"pub\",\n\n    /**\n     * \"Synthetic\" event in that it is not a message from Server: A Client-to-Server\n     * {@link MatsSocket#request() Request} was not replied to by the server within the\n     * {@link MatsSocket#requestTimeout default request timeout} - or a specific timeout specified in the request\n     * invocation. In these situations, the Request Promise is rejected with a {@link MessageEvent} of this type,\n     * and the {@link MessageEvent#data} value is undefined.\n     */\n    TIMEOUT: \"timeout\",\n\n    /**\n     * \"Synthetic\" event in that it is not a message from Server: This only happens if the MatsSocketSession is\n     * closed with outstanding Client-to-Server {@link MatsSocket#request() Requests} not yet replied to by the\n     * server. In these situations, the Request Promise is rejected with a {@link MessageEvent} of this type, and\n     * the {@link MessageEvent#data} value is undefined.\n     */\n    SESSION_CLOSED: \"sessionclosed\"\n};\nObject.freeze(MessageEventType);\n","export { SubscriptionEvent, SubscriptionEventType }\n\n/**\n * Information about how a subscription went on the server side. If you do two subscriptions to the same Topic,\n * you will still only get one such message - thus if you want one for each, you'd better add two listeners too,\n * <i>before</i> doing any of the subscribes.\n * <p />\n * Note: this also fires upon every reconnect. <b>Make note of the {@link SubscriptionEventType#LOST_MESSAGES}!</b>\n *\n * @param type {SubscriptionEventType} - {@link SubscriptionEvent#type}\n * @param topicId {string} - {@link SubscriptionEvent#topicId}\n * @class\n */\nfunction SubscriptionEvent(type, topicId) {\n    /**\n     * How the subscription fared.\n     *\n     * @type {SubscriptionEventType}\n     */\n    this.type = type;\n\n    /**\n     * What TopicIc this relates to.\n     *\n     * @type {string}\n     */\n    this.topicId = topicId;\n\n}\n\n/**\n * Type of {@link SubscriptionEvent}.\n *\n * @enum {string}\n * @readonly\n */\nconst SubscriptionEventType = {\n    /**\n     * The subscription on the server side went ok. If reconnect, any missing messages are now being sent.\n     */\n    OK: \"ok\",\n\n    /**\n     * You were not authorized to subscribe to this Topic.\n     */\n    NOT_AUTHORIZED: \"notauthorized\",\n\n    /**\n     * Upon reconnect, the \"last message Id\" was not known to the server, implying that there are lost messages.\n     * Since you will now have to handle this situation by other means anyway (e.g. do a request for all stock ticks\n     * between the last know timestamp and now), you will thus not get any of the lost messages even if the server\n     * has some.\n     */\n    LOST_MESSAGES: \"lostmessages\"\n};\nObject.freeze(SubscriptionEventType);\n","import './typedefs.js';\n// Repeating typedefs here, since 'tsc' otherwise don't create the 'export type FractionalMillis = number;' line.\n/**\n * Fractional milliseconds for high-res timing.\n * @typedef {number} FractionalMillis\n */\n\n/**\n * Timestamp, millis-since-epoch.\n * @typedef {number} Timestamp\n */\n\nimport { MessageEvent, MessageEventType } from './MessageEvent.js';\n\nexport { InitiationProcessedEvent, InitiationProcessedEventType }\n\n\n/**\n * (Metrics) Information about Client-to-Server SENDs and REQUESTs (aka <i>Client Initiations</i>), including\n * experienced round-trip times for both Received acknowledgement, and for Requests, the Request-to-Reply time.\n * <p />\n * For each message that, for sends, has been acknowledged received, and for requests, has been replied to, gives\n * this information:\n * <ul>\n *     <li>Client MessageId  (envelope's 'cmid').</li>\n *     <li>Timestamp of when message was sent.</li>\n *     <li>Target MatsSocket Endpoint or Terminator Id  (envelope's 'eid').</li>\n *     <li>TraceId for the SEND or REQUEST  (envelope's 'tid').</li>\n *     <li>The outgoing message, i.e. the SEND or the REQUEST message  (envelope's 'msg').</li>\n *     <li>Experienced Received Acknowledge round-trip time.</li>\n *     <li>For {@link MatsSocket#request() Requests}, the Reply's {@link MessageEventType}</li>\n *     <li>For {@link MatsSocket#requestReplyTo() requestReplyTo} Requests, the replyToTerminatorId.</li>\n *     <li>For Requests, the total experienced Request-to-Reply time.</li>\n *     <li>For Requests, the Reply {@link MessageEvent} object.</li>\n * </ul>\n * You may \"subscribe\" to <code>InitiationProcessedEvents</code> using\n * {@link MatsSocket#addInitiationProcessedEventListener()}, and you may get the latest such events from the\n * property {@link MatsSocket#initiations}.\n * <p />\n * <b>Note on event ordering</b>:\n * <ul>\n *     <li>send: First {@link ReceivedEvent} is issued. Then an {@link InitiationProcessedEvent} is added to\n *         {@link MatsSocket#initiations}, and then all {@link InitiationProcessedEvent} listeners are invoked</li>\n *     <li>request/requestReplyTo: First {@link ReceivedEvent} is issued (i.e. ack/nack), then when the reply\n *     comes back to the server, an {@link InitiationProcessedEvent} is added to {@link MatsSocket#initiations}, and\n *     then all {@link InitiationProcessedEvent} listeners are invoked, and finally the {@link MessageEvent} is\n *     delivered, either as settling of the return Reply-Promise (for 'request'), or invocation of the Terminator's\n *     message- or rejectCallbacks (for 'requestReplyTo').\n * </ul>\n *\n * @param {string} endpointId\n * @param {string} clientMessageId\n * @param {Timestamp} sentTimestamp\n * @param {FractionalMillis} sessionEstablishedOffsetMillis\n * @param {string} traceId\n * @param {Object} initiationMessage\n * @param {FractionalMillis} acknowledgeRoundTripMillis\n * @param {MessageEventType} replyMessageEventType\n * @param {string} replyToTerminatorId\n * @param {FractionalMillis} requestRoundTripMillis\n * @param {MessageEvent} replyMessageEvent\n * @class\n */\nfunction InitiationProcessedEvent(endpointId, clientMessageId, sentTimestamp, sessionEstablishedOffsetMillis, traceId, initiationMessage, acknowledgeRoundTripMillis, replyMessageEventType, replyToTerminatorId, requestRoundTripMillis, replyMessageEvent) {\n    /**\n     * Which initiation type of this flow, enum of {@link InitiationProcessedEventType}.\n     *\n     * @type {InitiationProcessedEventType}\n     */\n    this.type = ((replyToTerminatorId ? InitiationProcessedEventType.REQUEST_REPLY_TO : (replyMessageEventType ? InitiationProcessedEventType.REQUEST : InitiationProcessedEventType.SEND)));\n\n    /**\n     * Target Server MatsSocket Endpoint or Terminator Id  (envelope's 'eid').\n     *\n     * @type {string}\n     */\n    this.endpointId = endpointId;\n\n    /**\n     * The Client MessageId of the Initiation  (envelope's 'cmid'). For this particular MatsSocket library, this\n     * is currently an integer sequence id.\n     *\n     * @type {string}\n     */\n    this.clientMessageId = clientMessageId;\n\n    /**\n     * Millis-from-epoch when this initiation was sent.\n     *\n     * @type {Timestamp}\n     */\n    this.sentTimestamp = sentTimestamp;\n\n    /**\n     * The number of milliseconds offset for sending this message from the initial {@link ConnectionEventType#SESSION_ESTABLISHED} event for\n     * this MatsSocket - <b>this number will typically be negative for the first messages</b>: A negative number\n     * implies that the message was sent before the WELCOME was received, which again implies that the very first\n     * message will by definition have a negative offset since it is this message that starts the HELLO/WELCOME\n     * handshake and is thus enqueued before the WELCOME has been received. This is desirable: Upon application\n     * startup, stack up all requests that you need answer for to show the initial screen, and they will all be\n     * sent in a single pipeline, directly trailing the HELLO, their answers coming in as soon as possible after\n     * the WELCOME.\n     *\n     * @type {FractionalMillis}\n     */\n    this.sessionEstablishedOffsetMillis = sessionEstablishedOffsetMillis;\n\n    /**\n     * TraceId for the initiation - which follows through all parts of the processing  (envelope's 'tid').\n     *\n     * @type {string}\n     */\n    this.traceId = traceId;\n\n    /**\n     * The message object that was sent with the initiation, i.e. on send(), request() or requestReplyTo()  (outgoing envelope's 'msg').\n     *\n     * @type {Object}\n     */\n    this.initiationMessage = initiationMessage;\n\n    /**\n     * The experienced round-trip time for the Received Acknowledgement - this is the time back-and-forth.\n     *\n     * <b>Note that this number can be a float, not necessarily integer</b>.\n     *\n     * @type {FractionalMillis}\n     */\n    this.acknowledgeRoundTripMillis = acknowledgeRoundTripMillis;\n\n    // === For Requests.\n\n    /**\n     * The {@link MessageEventType} for Replies to Request Initiations.\n     *\n     * @type {string}\n     */\n    this.replyMessageEventType = replyMessageEventType;\n\n    /**\n     * The 'replyToTerminatorId' for {@link MatsSocket#requestReplyTo()}-Requests.\n     *\n     * @type {string}\n     */\n    this.replyToTerminatorId = replyToTerminatorId;\n\n    /**\n     * The experienced round-trip time from a Request initiation to the Reply (RESOLVE or REJECT) comes back.\n     *\n     * @type {FractionalMillis}\n     */\n    this.requestReplyRoundTripMillis = requestRoundTripMillis;\n\n    /**\n     * The Reply {@link MessageEvent} that was supplied to the Promise (on resolve/then or reject/catch) or ReplyTo\n     * Client {@link #terminator() Terminator}.\n     *\n     * @type {MessageEvent}\n     */\n    this.replyMessageEvent = replyMessageEvent;\n}\n\n/**\n * Type of {@link InitiationProcessedEvent} - the type of the <i>initiation</i> of a flow, which also\n * determines which fields of the <code>InitiationProcessedEvent</code> are set.\n *\n * @enum {string}\n * @readonly\n */\nconst InitiationProcessedEventType = {\n    /**\n     * Flow initiated with {@link MatsSocket#send()}. Fields whose name does not start with \"reply\" or \"request\"\n     * will be set.\n     */\n    SEND: \"send\",\n\n    /**\n     * Flow initiated with {@link MatsSocket#request()}. Will have all fields except\n     * {@link InitiationProcessedEvent#replyToTerminatorId} set.\n     */\n    REQUEST: \"request\",\n\n    /**\n     * Flow initiated with {@link MatsSocket#requestReplyTo()}. Will have <i>all</i> fields set.\n     */\n    REQUEST_REPLY_TO: \"requestreplyto\"\n};\nObject.freeze(InitiationProcessedEventType);\n","import './typedefs.js';\n// Repeating typedefs here, since 'tsc' otherwise don't create the 'export type FractionalMillis = number;' line.\n/**\n * Fractional milliseconds for high-res timing.\n * @typedef {number} FractionalMillis\n */\n\n/**\n * Timestamp, millis-since-epoch.\n * @typedef {number} Timestamp\n */\n\nexport { PingPong }\n\n/**\n * (Metric) A \"holding struct\" for pings and their experienced round-trip times - you may \"subscribe\" to ping results\n * using {@link MatsSocket#addPingPongListener()}, and you may get the latest pings from the property\n * {@link MatsSocket#pings}.\n *\n * @param {number} pingId\n * @param {Timestamp} sentTimestamp\n * @class\n */\nfunction PingPong(pingId, sentTimestamp) {\n    /**\n     * Sequence of the ping.\n     *\n     * @type {number}\n     */\n    this.pingId = pingId;\n\n    /**\n     * Millis-from-epoch when this ping was sent.\n     *\n     * @type {Timestamp}\n     */\n    this.sentTimestamp = sentTimestamp;\n\n    /**\n     * The experienced round-trip time for this ping-pong - this is the time back-and-forth.\n     *\n     * @type {FractionalMillis}\n     */\n    this.roundTripMillis = undefined;\n}\n","export { MatsSocketCloseCodes, MatsSocketCloseCodesUtil }\n\n/**\n * <b>Copied directly from MatsSocketServer.java</b>:\n * WebSocket CloseCodes used in MatsSocket, and for what. Using both standard codes, and MatsSocket-specific/defined\n * codes.\n * <p/>\n * Note: Plural \"Codes\" since that is what the JSR 356 Java WebSocket API {@link CloseCodes does..!}\n *\n * @enum {number}\n * @readonly\n */\nconst MatsSocketCloseCodes = {\n    /**\n     * Standard code 1008 - From Server side, Client should REJECT all outstanding and \"crash\"/reboot application:\n     * used when the we cannot authenticate.\n     */\n    VIOLATED_POLICY: 1008,\n\n    /**\n     * Standard code 1011 - From Server side, Client should REJECT all outstanding and \"crash\"/reboot application.\n     * This is the default close code if the MatsSocket \"onMessage\"-handler throws anything, and may also explicitly\n     * be used by the implementation if it encounters a situation it cannot recover from.\n     */\n    UNEXPECTED_CONDITION: 1011,\n\n    /**\n     * Standard code 1012 - From Server side, Client should REISSUE all outstanding upon reconnect: used when\n     * {@link MatsSocketServer#stop(int)} is invoked. Please reconnect.\n     */\n    SERVICE_RESTART: 1012,\n\n    /**\n     * Standard code 1001 - From Client/Browser side, client should have REJECTed all outstanding: Synonym for\n     * {@link #CLOSE_SESSION}, as the WebSocket documentation states <i>\"indicates that an endpoint is \"going away\",\n     * such as a server going down <b>or a browser having navigated away from a page.</b>\"</i>, the latter point\n     * being pretty much exactly correct wrt. when to close a session. So, if a browser decides to use this code\n     * when the user navigates away and the client MatsSocket library or employing application does not catch it,\n     * we'd want to catch this as a Close Session. Notice that I've not experienced a browser that actually utilizes\n     * this close code yet, though!\n     * <p/>\n     * <b>Notice that if a close with this close code <i>is initiated from the Server-side</i>, this should NOT be\n     * considered a CLOSE_SESSION by the neither the client nor the server!</b> At least Jetty's implementation of\n     * JSR 356 WebSocket API for Java sends GOING_AWAY upon socket close due to timeout. Since a timeout can happen\n     * if we loose connection and thus can't convey PINGs, the MatsSocketServer must not interpret Jetty's\n     * timeout-close as Close Session. Likewise, if the client just experienced massive lag on the connection, and\n     * thus didn't get the PING over to the server in a timely fashion, but then suddenly gets Jetty's timeout close\n     * with GOING_AWAY, this should not be interpreted by the client as the server wants to close the session.\n     */\n    GOING_AWAY: 1001,\n\n    /**\n     * 4000: Both from Server side and Client/Browser side, client should REJECT all outstanding:\n     * <ul>\n     * <li>From Browser: Used when the browser closes WebSocket \"on purpose\", wanting to close the session -\n     * typically when the user explicitly logs out, or navigates away from web page. All traces of the\n     * MatsSocketSession are effectively deleted from the server, including any undelivered replies and messages\n     * (\"push\") from server.</li>\n     * <li>From Server: {@link MatsSocketServer#closeSession(String)} was invoked, and the WebSocket to that client\n     * was still open, so we close it.</li>\n     * </ul>\n     */\n    CLOSE_SESSION: 4000,\n\n    /**\n     * 4001: From Server side, Client should REJECT all outstanding and \"crash\"/reboot application: A\n     * HELLO:RECONNECT was attempted, but the session was gone. A considerable amount of time has probably gone by\n     * since it last was connected. The client application must get its state synchronized with the server side's\n     * view of the world, thus the suggestion of \"reboot\".\n     */\n    SESSION_LOST: 4001,\n\n    /**\n     * 4002: Both from Server side and from Client/Browser side: REISSUE all outstanding upon reconnect:\n     * <ul>\n     * <li>From Client: The client just fancied a little break (just as if lost connection in a tunnel), used from\n     * integration tests.</li>\n     * <li>From Server: We ask that the client reconnects. This gets us a clean state and in particular new\n     * authentication (In case of using OAuth/OIDC tokens, the client is expected to fetch a fresh token from token\n     * server).</li>\n     * </ul>\n     */\n    RECONNECT: 4002,\n\n    /**\n     * 4003: From Server side: Currently used in the specific situation where a MatsSocket client connects with\n     * the same MatsSocketSessionId as an existing WebSocket connection. This could happen if the client has\n     * realized that a connection is wonky and wants to ditch it, but the server has not realized the same yet.\n     * When the server then gets the new connect, it'll see that there is an active WebSocket already. It needs\n     * to close that. But the client \"must not do anything\" other than what it already is doing - reconnecting.\n     */\n    DISCONNECT: 4003,\n\n    /**\n     * 4004: From Server side: Client should REJECT all outstanding and \"crash\"/reboot application: Used when the\n     * client does not speak the MatsSocket protocol correctly. Session is closed.\n     */\n    MATS_SOCKET_PROTOCOL_ERROR: 4004,\n};\nObject.freeze(MatsSocketCloseCodes);\n\n/**\n * Utility functions for {@link MatsSocketCloseCodes}.\n * @namespace\n */\nconst MatsSocketCloseCodesUtil = (() => {\n    // Build a reverse lookup once, O(1) lookups later.\n    const REVERSE = new Map(\n        Object.entries(MatsSocketCloseCodes).map(([k, v]) => [v, k])\n    );\n\n    return {\n        /**\n         * Resolve numeric code -> enum key name, or \"UNKNOWN(<code>)\".\n         * @param {number} code\n         * @returns {string}\n         */\n        nameFor(code) {\n            const name = REVERSE.get(code);\n            return name ?? `UNKNOWN(${code})`;\n        },\n    };\n})();","export { ErrorEvent }\n\n/**\n * The Event object supplied to listeners added via {@link MatsSocket#addErrorEventListener()}.\n *\n * @param type {string}\n * @param message {string}\n * @param object {Object}\n * @class\n */\nfunction ErrorEvent(type, message, object) {\n    /**\n     * Type of error - describes the situation where the error occurred. Currently has no event-type enum.\n     *\n     * @type {string}\n     */\n    this.type = type;\n\n    /**\n     * The error message\n     *\n     * @type {string}\n     */\n    this.message = message;\n\n    /**\n     * Some errors supply a relevant object: Event for WebSocket errors, The attempted processed MatsSocket Envelope\n     * when envelope processing fails, or the caught Error in a try-catch (typically when invoking event listeners).\n     * <b>For submitting errors back to the home server, check out {@link ErrorEvent#referenceAsString}.</b>\n     *\n     * @type {Object}\n     */\n    this.reference = object;\n\n    /**\n     * Makes a string (<b>chopped the specified max number of characters, default 1024 chars</b>) out of the\n     * {@link ErrorEvent#reference} Object, which might be useful if you want to send this back over HTTP - consider\n     * <code>encodeURIComponent(referenceAsString)</code> if you want to send it over the URL. First tries to use\n     * <code>JSON.stringify(reference)</code>, failing that, it uses <code>\"\"+reference</code>. Then chops to max\n     * 1024, using \"...\" to denote the chop.\n     *\n     * @param {number} maxLength the max number of characters that will be returned, with any chop denoted by \"...\".\n     * @returns {string}\n     */\n    this.referenceAsString = function (maxLength = 1024) {\n        let result;\n        try {\n            result = JSON.stringify(this.reference);\n        } catch (err) {\n            /* no-op */\n        }\n        if (typeof result !== 'string') {\n            result = \"\" + this.reference;\n        }\n        return (result.length > maxLength ? result.substring(0, maxLength - 3) + \"...\" : result);\n    };\n}\n","import './typedefs.js';\n// Repeating typedefs here, since 'tsc' otherwise don't create the 'export type FractionalMillis = number;' line.\n/**\n * Fractional milliseconds for high-res timing.\n * @typedef {number} FractionalMillis\n */\n\n/**\n * Timestamp, millis-since-epoch.\n * @typedef {number} Timestamp\n */\n\n\nexport { DebugInformation, DebugOption }\n\n/**\n * Meta-information for the call, availability depends on the allowed debug options for the authenticated user,\n * and which information is requested in client. Notice that Client side and Server side might have wildly differing\n * ideas of what the time is, which means that timestamps comparison between Server and Client must be evaluated\n * with massive interpretation.\n *\n * @param {Timestamp} clientMessageSent\n * @param {number} requestedDebugOptions\n * @param {object} envelope\n * @param {Timestamp} receivedTimestamp\n * @class\n */\nfunction DebugInformation(clientMessageSent, requestedDebugOptions, envelope, receivedTimestamp) {\n    /**\n     * From client: When the message was sent, millis-from-epoch.\n     * @type {Timestamp}\n     */\n    this.clientMessageSent = clientMessageSent;\n\n    /**\n     * From client: What {@link DebugOption}s (bitfield) was requested by the client of when message was sent.\n     * @type {number}\n     */\n    this.requestedDebugOptions = requestedDebugOptions;\n\n    /**\n     * From server: Description if anything didn't go as expected.\n     * @type {string}\n     */\n    this.description = envelope.desc;\n\n    /**\n     * When this message was received by the client.\n     * @type {Timestamp}\n     */\n    this.messageReceived = receivedTimestamp;\n\n    /**\n     * (Only if debug) From server: What {@link DebugOption}s (bitfield) was resolved/given by the server, based on the\n     * {@link DebugInformation#requestedDebugOptions} and authorization.\n     * @type {number}\n     */\n    this.resolvedDebugOptions = 0; // default to 0 if no debug object in the envelope\n\n    /**\n     * (Only if debug) When the MatsSocket message from the client was received by the MatsSocketServer.\n     * @type {Timestamp}\n     */\n    this.clientMessageReceived = undefined;\n    /**\n     * (Only if debug) Which MatsSocketServer node received (and thus initial-processed) the MatsSocket message.\n     * @type {string}\n     */\n    this.clientMessageReceivedNodename = undefined;\n\n    /**\n     * (Only if debug) When the Mats3 message was sent onto the Mats3 Fabric on server side.\n     * @type {Timestamp}\n     */\n    this.matsMessageSent = undefined;\n\n    /**\n     * (Only if debug) When the Mats3 reply was received by the MatsSocketServer.\n     * @type {Timestamp}\n     */\n    this.matsMessageReplyReceived = undefined;\n    /**\n     * (Only if debug) Which MatsSocketServer node received the reply for the Mats3 message (might not be the same that sent it).\n     * @type {string}\n     */\n    this.matsMessageReplyReceivedNodename = undefined;\n\n    /**\n     * (Only if debug) When the MatsSocket message was produced on the server side.\n     * @type {Timestamp}\n     */\n    this.serverMessageCreated = undefined;\n    /**\n     * (Only if debug) Which MatsSocketServer node created the MatsSocket message.\n     * @type {string}\n     */\n    this.serverMessageCreatedNodename = undefined;\n\n    /**\n     * (Only if debug) When the MatsSocket message was sent from server to client.\n     * @type {Timestamp}\n     */\n    this.messageSentToClient = undefined;\n    /**\n     * (Only if debug) Which MatsSocketServer node sent the MatsSocket message to the client (the one that held the\n     * MatsSocket session at the sending time. This might be different from the MatsSocketServer node that held the\n     * session at the receiving time).\n     * @type {string}\n     */\n    this.messageSentToClientNodename = undefined;\n\n    if (envelope.debug) {\n        this.resolvedDebugOptions = envelope.debug.resd;\n\n        this.clientMessageReceived = envelope.debug.cmrts;\n        this.clientMessageReceivedNodename = envelope.debug.cmrnn;\n\n        this.matsMessageSent = envelope.debug.mmsts;\n        this.matsMessageReplyReceived = envelope.debug.mmrrts;\n        this.matsMessageReplyReceivedNodename = envelope.debug.mmrrnn;\n\n        this.serverMessageCreated = envelope.debug.smcts;\n        this.serverMessageCreatedNodename = envelope.debug.smcnn;\n\n        this.messageSentToClient = envelope.debug.mscts;\n        this.messageSentToClientNodename = envelope.debug.mscnn;\n    }\n}\n\n/**\n * <b>Copied directly from AuthenticationPlugin.java</b>:\n * Types of debug information you can request, read more at {@link MatsSocket#debug} and {@link MessageEvent#debug}.\n *\n * @enum {number}\n * @readonly\n */\nconst DebugOption = {\n    /**\n     * Timing info of the separate phases. Note that time-skew between different nodes must be taken into account.\n     */\n    TIMESTAMPS: 1, // was 0b0000_0001 (changed due to underscores and possibly binary being a bit too edgy for JS in 2021)\n\n    /**\n     * Node-name of the handling nodes of the separate phases.\n     */\n    NODES: 2, // was 0b0000_0010\n\n    /**\n     * <code>AuthenticationPlugin</code>-specific \"Option A\" - this is not used by MatsSocket itself, but can be employed\n     * and given a meaning by the <code>AuthenticationPlugin</code>.\n     * <p/>\n     * Notice: You might be just as well off by implementing such functionality on the <code>Principal</code> returned by\n     * the <code>AuthenticationPlugin</code> (\"this user is allowed to request these things\") - and on the request DTOs\n     * from the Client (\"I would like to request these things\").\n     */\n    CUSTOM_A: 64, // was 0b0100_0000\n\n    /**\n     * <code>AuthenticationPlugin</code>-specific \"Option B\" - this is not used by MatsSocket itself, but can be employed\n     * and given a meaning by the <code>AuthenticationPlugin</code>.\n     * <p/>\n     * Notice: You might be just as well off by implementing such functionality on the <code>Principal</code> returned by\n     * the <code>AuthenticationPlugin</code> (\"this user is allowed to request these things\") - and on the request DTOs\n     * from the Client (\"I would like to request these things\").\n     */\n    CUSTOM_B: 128 // was 0b1000_0000\n};\nObject.freeze(DebugOption);\n","import {AuthorizationRequiredEvent, AuthorizationRequiredEventType} from './AuthorizationRequiredEvent.js';\nimport {ConnectionState} from './ConnectionState.js';\nimport {ConnectionEvent, ConnectionEventType} from './ConnectionEvent.js';\nimport {MessageType} from './MessageType.js';\nimport {ReceivedEvent, ReceivedEventType} from './ReceivedEvent.js';\nimport {MessageEvent, MessageEventType} from './MessageEvent.js';\nimport {SubscriptionEvent, SubscriptionEventType} from \"./SubscriptionEvent.js\";\nimport {InitiationProcessedEvent, InitiationProcessedEventType} from './InitiationProcessedEvent.js';\nimport {PingPong} from './PingPong.js';\nimport {MatsSocketCloseCodes, MatsSocketCloseCodesUtil} from './MatsSocketCloseCodes.js';\nimport {ErrorEvent} from './ErrorEvent.js';\nimport {DebugInformation, DebugOption} from \"./DebugInformation.js\";\n\nexport {\n    MatsSocket,\n    AuthorizationRequiredEvent, AuthorizationRequiredEventType,\n    ConnectionState,\n    ConnectionEvent, ConnectionEventType,\n    MessageType,\n    ReceivedEvent, ReceivedEventType,\n    MessageEvent, MessageEventType,\n    SubscriptionEvent, SubscriptionEventType,\n    InitiationProcessedEvent, InitiationProcessedEventType,\n    PingPong,\n    MatsSocketCloseCodes,\n    ErrorEvent,\n    DebugOption, DebugInformation\n}\n\n/**\n * Creates a MatsSocket, requiring the using Application's name and version, and which URLs to connect to.\n * <p/>\n * Note: Public, Private and Privileged modelled after\n * <a href=\"http://crockford.com/javascript/private.html\">http://crockford.com/javascript/private.html</a>\n *\n * @param {string} appName the name of the application using this MatsSocket.js client library\n * @param {string} appVersion the version of the application using this MatsSocket.js client library\n * @param {array} urls an array of WebSocket URLs speaking 'matssocket' protocol, or a single string URL.\n * @param {object} config an optional object carrying extra configuration. Current sole key: 'webSocketFactory': how to\n * make WebSockets, not required in a browser setting as it will use window.WebSocket if not set.\n * @class\n */\nfunction MatsSocket(appName, appVersion, urls, config = null) {\n    let CLIENT_LIB_VERSION = \"1.0.0-2025-10-27\";\n    let CLIENT_LIB_NAME_AND_VERSION = \"MatsSocket.js,\" + CLIENT_LIB_VERSION;\n\n    // :: Validate primary arguments\n    if (typeof appName !== \"string\") {\n        throw new Error(\"appName must be a string, was: [\" + appName + \"]\");\n    }\n    if (typeof appVersion !== \"string\") {\n        throw new Error(\"appVersion must be a string, was: [\" + appVersion + \"]\");\n    }\n    // 'urls' must either be a string, String, or an Array that is not 0 elements.\n    let urlsOk = ((typeof urls === 'string') || (urls instanceof String)) || (Array.isArray(urls) && urls.length > 0);\n    if (!urlsOk) {\n        throw new Error(\"urls must have at least 1 url set, got: [\" + urls + \"]\");\n    }\n\n    // If we haven't gotten 'webSocketFactory', and we're in Node.js env, this field is set to true, and an attempt to\n    // import('ws') is performed. When the import has gone either OK or not OK, this field is set to false, and the the\n    // next field's value will be invoked.\n    let _nodeJsTryingToImportWebSocketModule = false;\n    // If !undefined, will be invoked once import of WebSocket module is either OK or Not OK.\n    // If the 'webSocketFactory' is !undefined, it went OK. If the above field is false, it went to hell.\n    let _nodeJsCallbackOnceWebSocketModuleResolved = undefined;\n    // Note: Alternative would be main vs. browser in package.json, e.g. here: https://stackoverflow.com/a/67393553/39334\n\n    // :: Provide default for socket factory if not defined.\n    let webSocketFactory = undefined;\n    if (config) {\n        if (config.webSocketFactory) {\n            if (typeof config.webSocketFactory !== \"function\") {\n                throw new Error(\"config.webSocketFactory should be a function, instead got [\" + (typeof config.webSocketFactory) + \"].\");\n            }\n            webSocketFactory = config.webSocketFactory;\n        } else if (config.webSocket) {\n            if (typeof config.webSocket !== \"function\") {\n                throw new Error(\"config.webSocket should be a function (constructor), instead got [\" + (typeof config.webSocket) + \"].\");\n            }\n            webSocketFactory = function (url, protocol) {\n                return new config.webSocket(url, protocol);\n            };\n        }\n    }\n    // ?: Did we get webSocketFactory from 'config'?\n    if (!webSocketFactory) {\n        // -> No, so try for global WebSocket\n        if (typeof WebSocket === \"function\") {\n            webSocketFactory = (url, protocol) => new WebSocket(url, protocol);\n        } else if (_isNodeJs()) {\n            _nodeJsTryingToImportWebSocketModule = true;\n            // -> Seemingly Node.js environment, try to dynamically import the 'ws' library.\n            // NOTE: Such import is specified as an asynchronous operation, albeit it seems synchronous when running in Node.\n            // However, we'll have to treat it as async, so a bit of handling both here and in the WebSocket creation\n            // code below, by means of \"stop process and restart once import resolved\" logic.\n\n            _importWsLazy()\n                .then((ws) => {\n                    log(\"Constructor: NodeJs import('ws') went OK: Got WebSocket module\");\n                    const {default: WebSocket} = ws;\n                    setTimeout(() => {\n                        webSocketFactory = (url, protocol) => new WebSocket(url, protocol);\n                        log(\"Constructor: 'webSocketFactory' is now set.\");\n                        _nodeJsTryingToImportWebSocketModule = false;\n                        if (typeof _nodeJsCallbackOnceWebSocketModuleResolved === 'function') {\n                            log(\"Constructor: Invoking callback-method to restart WebSocket creation attempt.\");\n                            _nodeJsCallbackOnceWebSocketModuleResolved();\n                        }\n                    }, 0)\n                })\n                .catch(reason => {\n                    _nodeJsTryingToImportWebSocketModule = false;\n                    error(\"Import of WebSocket module failed\", \"In Node.js environment, the import('ws') failed\", reason);\n                });\n        }\n        else {\n            throw new Error(\"Missing config.webSocket, config.webSocketFactory, global WebSocket (window.WebSocket),\" +\n                \" and seemingly not Node.js so cannot dynamically import 'ws' module: Cannot create MatsSocket.\");\n        }\n    }\n\n    // :: Polyfill performance.now() for Node.js: if window.performance is present, use this.\n    let performance = ((typeof (window) === \"object\" && window.performance) || {\n        now: function now() {\n            return Date.now();\n        }\n    });\n\n    const that = this;\n    const userAgent = (typeof (self) === 'object' && typeof (self.navigator) === 'object') ? self.navigator.userAgent : \"Unknown\";\n\n    // Ensure that 'urls' is an array or 1 or several URLs.\n    urls = [].concat(urls);\n\n\n    // ==============================================================================================\n    // PUBLIC:\n    // ==============================================================================================\n\n    /**\n     * 'sessionId' is set when we get the SessionId from WELCOME, set back to undefined on SessionClose\n     * (along with _matsSocketOpen = false)\n     *\n     * @type {string}\n     */\n    this.sessionId = undefined;\n\n    /**\n     * Whether to log via console.log. The logging is quite extensive. <b>Default <code>false</code></b>.\n     *\n     * @type {boolean}\n     */\n    this.logging = false;\n\n    /**\n     * Whether to log errors via console.error. <b>Default <code>true</code></b>.\n     *\n     * @type {boolean}\n     */\n    this.errorLogging = true;\n\n    /**\n     * \"Out-of-band Close\" refers to a small hack to notify the server about a MatsSocketSession being Closed even\n     * if the WebSocket is not live anymore: When {@link MatsSocket#close} is invoked, an attempt is done to close\n     * the WebSocket with CloseCode {@link MatsSocketCloseCodes.CLOSE_SESSION} - but whether the WebSocket is open\n     * or not, this \"Out-of-band Close\" will also be invoked if enabled and MatsSocket SessionId is present.\n     * <p/>\n     * Values:\n     * <ul>\n     *     <li>\"Falsy\", e.g. <code>false</code>: Disables this functionality</li>\n     *     <li>A <code>function</code>: The function is invoked when close(..) is invoked, the\n     *         single parameter being an object with two keys: <code>'webSocketUrl'</code> is the current WebSocket\n     *         url, i.e. the URL that the WebSocket was connected to, e.g. \"wss://example.com/matssocket\".\n     *         <code>'sessionId'</code> is the current MatsSocket SessionId - the one we're trying to close.</li>\n     *     <li>\"Truthy\", e.g. <code>true</code> <b>(default)</b>: When this MatsSocket library is used in\n     *         a web browser context, the following code is executed:\n     *         <code>navigator.sendBeacon(webSocketUrl.replace('ws', 'http')+\"/close_session?sessionId={sessionId}\")</code>.\n     *         Note that replace is replace-first, and that an extra 's' in 'wss' thus results in 'https'.</li>\n     * </ul>\n     * The default is <code>true</code>.\n     * <p/>\n     * Note: A 'beforeunload' listener invoking {@link MatsSocket#close} is attached when running in a web browser,\n     * so that if the user navigates away, the current MatsSocketSession is closed.\n     *\n     * @type {(function|boolean)}\n     */\n    this.outofbandclose = true;\n\n    /**\n     * \"Pre Connection Operation\" refers to a hack whereby the MatsSocket performs a specified operation - by default\n     * a {@link XMLHttpRequest} to the same URL as the WebSocket will be connected to - before initiating the\n     * WebSocket connection. The goal of this solution is to overcome a deficiency with the WebSocket Web API\n     * where it is impossible to add headers, in particular \"Authorization\": The XHR adds the Authorization header\n     * as normal, and the server side can transfer this header value over to a Cookie (e.g. named \"MatsSocketAuthCookie\").\n     * When the WebSocket connect is performed, the cookies will be transferred along with the initial \"handshake\"\n     * HTTP Request - and the AuthenticationPlugin on the server side can then validate the Authorization header -\n     * now present in a cookie. <i>Note: One could of course have supplied it in the URL of the WebSocket HTTP Handshake,\n     * but this is very far from ideal, as a live authentication then could be stored in several ACCESS LOG style\n     * logging systems along the path of the WebSocket HTTP Handshake Request call.</i>\n     * <p/>\n     * Values:\n     * <ul>\n     *     <li>\"Falsy\", e.g. <code>false</code> <b>(default)</b>: Disables this functionality.</li>\n     *     <li>A <code>string</code>: Performs a <code>XMLHttpRequest</code> with the URL set to the specified string, with the\n     *     HTTP Header \"<code>Authorization</code>\" set to the current AuthorizationValue. Expects 200, 202 or 204\n     *     as returned status code to go on.</li>\n     *     <li>A <code>function</code>: Invokes the function with a parameter object containing <code>'webSocketUrl'</code>,\n     *     which is the current WebSocket URL that we will connect to when this PreConnectionOperation has gone through,\n     *     and <code>'authorization'</code>, which is the current Authorization Value. <b>Expects\n     *     a two-element array returned</b>: [abortFunction, requestPromise]. The abortFunction is invoked when\n     *     the connection-retry system deems the current attempt to have taken too long time. The requestPromise must\n     *     be resolved by your code when the request has been successfully performed, or rejected if it didn't go through.\n     *     In the latter case, a new invocation of the 'preconnectoperation' will be performed after a countdown,\n     *     possibly with a different 'webSocketUrl' value if the MatsSocket is configured with multiple URLs.</li>\n     *     <li>\"Truthy\", e.g. <code>true</code>: Performs a <code>XMLHttpRequest</code> to the same URL as\n     *     the WebSocket URL, with \"ws\" replaced with \"http\", similar to {@link MatsSocket#outofbandclose}, and the HTTP\n     *     Header \"<code>Authorization</code>\" set to the current Authorization Value. Expects 200, 202 or 204 as\n     *     returned status code to go on.</li>\n     * </ul>\n     * The default is <code>false</code>.\n     * <p/>\n     * Note: For inspiration for the function-style value of this config, look in the source for the method\n     * <code>w_defaultXhrPromiseFactory(params)</code>.\n     * <p/>\n     * Note: A WebSocket is set up with a single HTTP Request, called the \"Upgrade\" or \"Handshake\" request. The\n     * point about being able to send Authorization along with the WebSocket connect only refers to this initial\n     * HTTP Request. Subsequent updates of the Authorization by means of invocation of\n     * {@link MatsSocket#setCurrentAuthorization} will not result in new HTTP calls - these new Authorization\n     * strings are sent in-band with WebSocket messages (MatsSocket envelopes).\n     *\n     * @type {(boolean|string|function)}\n     */\n    this.preconnectoperation = false;\n\n    /**\n     * A bit field requesting different types of debug information from the server - the flags/bits are defined in\n     * {@link DebugOption}. The information concerns timings and which server nodes have handled the messages.\n     * <p/>\n     * This field is used as the default for requests sent to the server, but individual requests may also set\n     * the debug flags explicitly (i.e. override) by use of the optional \"config\" object on\n     * {@link MatsSocket#requestReplyTo} or {@link MatsSocket#request}.\n     * <p/>\n     * To facilitate debug information also on Server initiated messages, the <i>last sent</i> debug flags is\n     * also stored on the server and used when messages originate there (i.e. Server-to-Client SENDs and REQUESTs).\n     * This goes both if the default was used (this flag), or overridden-per-request config: The last flag sent over\n     * is used for any subsequent server-initiated message. This is arguably a pretty annoying way to control the server\n     * initiated debug flags - vote for <a href=\"https://github.com/centiservice/matssocket/issues/13\">Issue 13</a>\n     * if you want something more explicit.\n     * <p/>\n     * The value is a bit field (values in {@link DebugOption}), so you bitwise-or (or simply add) together the\n     * different things you want.\n     * <p/>\n     * The value from the client is bitwise-and'ed together with the debug capabilities the authenticated user has\n     * gotten by the AuthenticationPlugin on the Server side. This means that the AuthenticationPlugin ultimately\n     * controls how much info the accessing user is allowed to get.\n     * <p/>\n     * Default is <code>0</code>, i.e. no debug.\n     *\n     * @type {number}\n     */\n    this.debug = 0;\n\n    /**\n     * When performing a {@link MatsSocket#request Request} and {@link MatsSocket#requestReplyTo RequestReplyTo},\n     * you may not always get a (timely) answer: Either you can lose the connection, thus lagging potentially forever -\n     * or, depending on the Mats message handling on the server (i.e. using \"non-persistent messaging\" for blazing fast\n     * performance for non-state changing operations), there is a minuscule chance that the message may be lost - or, if\n     * there is a massive backlog of messages for the particular Mats endpoint that is interfaced, you might not get an\n     * answer for 20 minutes. This setting controls the default timeout in milliseconds for Requests, and is default\n     * 45000 milliseconds (45 seconds), but you may override this per Request by specifying a different timeout in the\n     * config object for the request. When the timeout is hit, the Promise of a {@link MatsSocket#request} - or the\n     * specified ReplyTo Terminator for a {@link MatsSocket#requestReplyTo} - will be rejected with a\n     * {@link MessageEvent} of type {@link MessageEventType.TIMEOUT}. In addition, if the Received acknowledgement has\n     * not gotten in either, this will also (<i>before</i> the Promise reject!) be NACK'ed with\n     * {@link ReceivedEventType.TIMEOUT}\n     *\n     * @type {number}\n     */\n    this.requestTimeout = 45000;\n\n    /**\n     * Way to let integration tests checking failed connections take a bit less time..! Default is 'undefined', which\n     * yields a small number (60ish x 15 seconds) when we do not have SessionId (i.e. trying to connect, we have still\n     * not started the app), and a rather large one (a full day) if we do have a SessionId (implying that we're trying\n     * to reconnect).\n     *\n     * @type {number}\n     */\n    this.maxConnectionAttempts = undefined;\n\n    /**\n     * Default is 3-7 seconds for the initial ping delay, and then 15 seconds for subsequent pings. Can be overridden\n     * for tests.\n     *\n     * @type {number}\n     */\n    this.initialPingDelay = 3000 + Math.random() * 4000\n\n    /**\n     * Callback function for {@link MatsSocket#addSessionClosedEventListener}.\n     *\n     * @callback sessionClosedEventCallback\n     * @param {CloseEvent} closeEvent the WebSocket's {@link CloseEvent}.\n     */\n\n    /**\n     * <b>Note: You <i>should</i> register a SessionClosedEvent listener, as any invocation of this listener by this\n     * client library means that you've either not managed to do initial authentication, or lost sync with the\n     * server, and you should crash or \"reboot\" the application employing the library to regain sync.</b>\n     * <p />\n     * The registered event listener functions are called when the Server kicks us off the socket and the session is\n     * closed due to a multitude of reasons, where most should never happen if you use the library correctly, in\n     * particular wrt. authentication. <b>It is NOT invoked when you explicitly invoke matsSocket.close() from\n     * the client yourself!</b>\n     * <p />\n     * The event object is the WebSocket's {@link CloseEvent}, adorned with properties 'codeName', giving the\n     * <i>key name</i> of the {@link MatsSocketCloseCodes} (as provided by {@link MatsSocketCloseCodes#nameFor}),\n     * and 'outstandingInitiations', giving the number of outstanding initiations when the session was closed.\n     * You can use the 'code' to \"enum-compare\" to <code>MatsSocketCloseCodes</code>, the enum keys are listed here:\n     * <ul>\n     *   <li>{@link MatsSocketCloseCodes.UNEXPECTED_CONDITION UNEXPECTED_CONDITION}: Error on the Server side,\n     *   typically that the data store (DB) was unavailable, and the MatsSocketServer could not reliably recover\n     *   the processing of your message.</li>\n     *   <li>{@link MatsSocketCloseCodes.MATS_SOCKET_PROTOCOL_ERROR MATS_SOCKET_PROTOCOL_ERROR}: This client library\n     *   has a bug!</li>\n     *   <li>{@link MatsSocketCloseCodes.VIOLATED_POLICY VIOLATED_POLICY}: Initial Authorization was wrong. Always\n     *   supply a correct and non-expired Authorization value, which has sufficient 'roomForLatency' wrt.\n     *   the expiry time.</li>\n     *   <li>{@link MatsSocketCloseCodes.CLOSE_SESSION CLOSE_SESSION}:\n     *   <code>MatsSocketServer.closeSession(sessionId)</code> was invoked Server side for this MatsSocketSession</li>\n     *   <li>{@link MatsSocketCloseCodes.SESSION_LOST SESSION_LOST}: A reconnect attempt was performed, but the\n     *   MatsSocketSession was timed out on the Server. The Session will never time out if the WebSocket connection\n     *   is open. Only if the Client has lost connection, the timer will start. The Session timeout is measured in\n     *   hours or days. This could conceivably happen if you close the lid of a laptop, and open it again days later\n     *   - but one would think that the Authentication session (the one giving you Authorization headers) had timed\n     *   out long before.</li>\n     * </ul>\n     * Again, note: No such error should happen if this client is used properly, and the server does not get\n     * problems with its data store.\n     * <p />\n     * Note that when this event listener is invoked, the MatsSocketSession is just as closed as if you invoked\n     * {@link MatsSocket#close} on it: All outstanding send/requests are NACK'ed (with\n     * {@link ReceivedEventType.SESSION_CLOSED}), all request Promises are rejected\n     * (with {@link MessageEventType.SESSION_CLOSED}), and the MatsSocket object is as if just constructed and\n     * configured. You may \"boot it up again\" by sending a new message where you then will get a new MatsSocket\n     * SessionId. However, you should consider restarting the application if this happens, or otherwise \"reboot\"\n     * it as if it just started up (gather all required state and null out any other that uses lazy fetching).\n     * Realize that any outstanding \"addOrder\" request's Promise will now have been rejected - and you don't really\n     * know whether the order was placed or not, so you should get the entire order list. On the received event,\n     * the property 'outstandingInitiations' details the number of outstanding send/requests and Promises that was\n     * rejected: If this is zero, you <i>might</i> actually be in sync (barring failed/missing Server-to-Client\n     * SENDs or REQUESTs), and could <i>consider</i> to just \"act as if nothing happened\" - by sending a new message\n     * and thus get a new MatsSocket Session going.\n     *\n     * @param {sessionClosedEventCallback} sessionClosedEventListener a function that is invoked when the library gets the current\n     * MatsSocketSession closed from the server. The event object is the WebSocket's {@link CloseEvent}.\n     */\n    this.addSessionClosedEventListener = function (sessionClosedEventListener) {\n        if (!(typeof sessionClosedEventListener === 'function')) {\n            throw Error(\"SessionClosedEvent listener must be a function\");\n        }\n        _sessionClosedEventListeners.push(sessionClosedEventListener);\n    };\n\n    /**\n     * Callback function for {@link MatsSocket#addConnectionEventListener}.\n     *\n     * @callback connectionEventCallback\n     * @param {ConnectionEvent} connectionEvent giving information about what happened.\n     */\n\n    /**\n     * <b>Note: You <i>could</i> register a ConnectionEvent listener, as these are only informational messages\n     * about the state of the Connection.</b> It is nice if the user gets a small notification about <i>\"Connection\n     * Lost, trying to reconnect in 2 seconds\"</i> to keep him in the loop of why the application's data fetching\n     * seems to be lagging. There are suggestions of how to approach this with each of the enum values of\n     * {@link ConnectionEventType}.\n     * <p />\n     * The registered event listener functions are called when this client library performs WebSocket connection\n     * operations, including connection closed events that are not \"Session Close\" style. This includes the simple\n     * situation of \"lost connection, reconnecting\" because you passed through an area with limited or no\n     * connectivity.\n     * <p />\n     * Read more at {@link ConnectionEvent} and {@link ConnectionEventType}.\n     *\n     * @param {connectionEventCallback} connectionEventListener a function that is invoked when the library issues\n     * {@link ConnectionEvent}s.\n     */\n    this.addConnectionEventListener = function (connectionEventListener) {\n        if (!(typeof connectionEventListener === 'function')) {\n            throw Error(\"SessionClosedEvent listener must be a function\");\n        }\n        _connectionEventListeners.push(connectionEventListener);\n    };\n\n    /**\n     * Callback function for {@link MatsSocket#addSubscriptionEventListener}.\n     *\n     * @callback subscriptionEventCallback\n     * @param {SubscriptionEvent} subscriptionEvent giving information about what the server had to say about\n     * subscriptions.\n     */\n\n    /**\n     * <b>Note: If you use {@link #subscribe subscriptions}, you <i>should</i> register a\n     * {@link SubscriptionEvent} listener, as you should be concerned about {@link SubscriptionEventType.NOT_AUTHORIZED}\n     * and {@link SubscriptionEventType.LOST_MESSAGES}.</b>\n     * <p />\n     * Read more at {@link SubscriptionEvent} and {@link SubscriptionEventType}.\n     *\n     * @param {subscriptionEventCallback} subscriptionEventListener a function that is invoked when the library\n     * gets information from the Server wrt. subscriptions.\n     */\n    this.addSubscriptionEventListener = function (subscriptionEventListener) {\n        if (!(typeof subscriptionEventListener === 'function')) {\n            throw Error(\"SubscriptionEvent listener must be a function\");\n        }\n        _subscriptionEventListeners.push(subscriptionEventListener);\n    };\n\n    /**\n     * Callback function for {@link MatsSocket#addErrorEventListener}.\n     *\n     * @callback errorEventCallback\n     * @param {ErrorEvent} errorEvent information about what error happened.\n     */\n\n    /**\n     * Some 25 places within the MatsSocket client catches errors of different kinds, typically where listeners\n     * cough up errors, or if the library catches mistakes with the protocol, or if the WebSocket emits an error.\n     * Add a ErrorEvent listener to get hold of these, and send them back to your server for\n     * inspection - it is best to do this via out-of-band means, e.g. via HTTP. For browsers, consider\n     * <code>navigator.sendBeacon(..)</code>.\n     * <p />\n     * The event object is {@link ErrorEvent}.\n     *\n     * @param {errorEventCallback} errorEventListener\n     */\n    this.addErrorEventListener = function (errorEventListener) {\n        if (!(typeof errorEventListener === 'function')) {\n            throw Error(\"ErrorEvent listener must be a function\");\n        }\n        _errorEventListeners.push(errorEventListener);\n    };\n\n    /**\n     * Callback function for {@link MatsSocket#setAuthorizationExpiredCallback}.\n     *\n     * @callback authorizationExpiredCallback\n     * @param {AuthorizationRequiredEvent} authorizationRequiredEvent information about why authorization information\n     * is requested.\n     */\n\n    /**\n     * If this MatsSockets client realizes that the expiration time (minus the room for latency) of the authorization\n     * has passed when about to send a message, it will invoke this callback function. A new authorization must then\n     * be provided by invoking the 'setCurrentAuthorization' function - only when this is invoked, the MatsSocket\n     * will send messages. The MatsSocket will queue up any messages that are initiated while waiting for new\n     * authorization, and send them all at once in a single pipeline when the new authorization is in.\n     *\n     * @param {authorizationExpiredCallback} authorizationExpiredCallback function which will be invoked\n     * when about to send a new message <i>if</i>\n     * '<code>Date.now() > (expirationTimeMillisSinceEpoch - roomForLatencyMillis)</code>' from the paramaters of\n     * the last invocation of {@link MatsSocket#setCurrentAuthorization}.\n     */\n    this.setAuthorizationExpiredCallback = function (authorizationExpiredCallback) {\n        if (!(typeof authorizationExpiredCallback === 'function')) {\n            throw Error(\"AuthorizationExpiredCallback must be a function\");\n        }\n        _authorizationExpiredCallback = authorizationExpiredCallback;\n\n        // Evaluate whether there are stuff in the pipeline that should be sent now.\n        // (Not-yet-sent HELLO does not count..)\n        that.flush();\n    };\n\n    /**\n     * Sets an authorization String, which for several types of authorization must be invoked on a regular basis with\n     * fresh authorization - this holds for a OAuth/JWT/OIDC-type system where an access token will expire within a short time\n     * frame (e.g. expires within minutes). For an Oauth2-style authorization scheme, this could be \"Bearer: ......\".\n     * This must correspond to what the server side authorization plugin expects.\n     * <p />\n     * <b>NOTE: This SHALL NOT be used to CHANGE the user!</b> It should only refresh an existing authorization for the\n     * initially authenticated user. One MatsSocket (Session) shall only be used by a single user: If changing\n     * user, you should ditch the existing MatsSocket after invoking {@link MatsSocket#close} to properly clean up the\n     * current MatsSocketSession on the server side too, and then make a new MatsSocket thus getting a new Session.\n     * <p />\n     * Note: If the underlying WebSocket has not been established and HELLO sent, then invoking this method will NOT\n     * do that - only the first actual MatsSocket message will start the WebSocket and perform the HELLO/WELCOME\n     * handshake.\n     *\n     * @param {string} authorizationValue the string Value which will be transfered to the Server and there resolved\n     *        to a Principal and UserId on the server side by the AuthorizationPlugin. Note that this value potentially\n     *        also will be forwarded to other resources that requires authorization.\n     * @param {number} expirationTimestamp the millis-since-epoch at which this authorization expires\n     *        (in case of OAuth-style tokens), or -1 if it never expires or otherwise has no defined expiration mechanism.\n     *        <i>Notice that in a JWT token, the expiration time is in seconds, not millis: Multiply by 1000.</i>\n     * @param {number} roomForLatencyMillis the number of millis which is subtracted from the 'expirationTimestamp' to\n     *        find the point in time where the MatsSocket will refuse to use the authorization and instead invoke the\n     *        {@link #setAuthorizationExpiredCallback AuthorizationExpiredCallback} and wait for a new authorization\n     *        being set by invocation of the present method. Depending on what the usage of the Authorization string\n     *        is on server side is, this should probably <b>at least</b> be 10000, i.e. 10 seconds - but if the Mats\n     *        endpoints uses the Authorization string to do further accesses, both latency and queue time must be\n     *        taken into account (e.g. for calling into another API that also needs a valid token). If\n     *        expirationTimestamp is '-1', then this parameter is not used. <i>Default value is 30000 (30 seconds).</i>\n     */\n    this.setCurrentAuthorization = function (authorizationValue, expirationTimestamp= -1, roomForLatencyMillis = 30000) {\n        if (this.logging) log(\"Got Authorization which \"\n            + (expirationTimestamp !== -1 ? \"Expires in [\" + (expirationTimestamp - Date.now()) + \" ms]\" : \"[Never expires]\")\n            + \", roomForLatencyMillis: \" + roomForLatencyMillis);\n\n        _authorization = authorizationValue;\n        _expirationTimestamp = expirationTimestamp;\n        _roomForLatencyMillis = roomForLatencyMillis;\n        // ?: Should we send it now?\n        if (_authExpiredCallbackInvoked_EventType === AuthorizationRequiredEventType.REAUTHENTICATE) {\n            log(\"Immediate send of new authentication due to REAUTHENTICATE\");\n            _forcePipelineProcessing = true;\n        }\n        // We're now back to \"normal\", i.e. not outstanding authorization request.\n        _authExpiredCallbackInvoked_EventType = undefined;\n\n        // Evaluate whether there are stuff in the pipeline that should be sent now.\n        // (Not-yet-sent HELLO does not count..)\n        that.flush();\n    };\n\n    /**\n     * Millis-since-epoch of last message enqueued. This can be used by the mechanism invoking\n     * {@link MatsSocket#setCurrentAuthorization} to decide whether it should keep the\n     * authorization fresh (i.e. no latency waiting for new authorization is introduced when a new message is\n     * enqueued), or fall back to relying on the 'authorizationExpiredCallback' being invoked when a new message needs\n     * it (thus introducing latency while waiting for authorization). One could envision keeping fresh auth for 5\n     * minutes, but if the user has not done anything requiring authentication (i.e. sending information bearing\n     * messages SEND, REQUEST or Replies) in that timespan, you stop doing continuous authentication refresh, falling\n     * back to the \"on demand\" based logic, where when a message is enqueued, the\n     * {@link MatsSocket#setAuthorizationExpiredCallback} is invoked if the authentication is expired.\n     *\n     * @member {number} lastMessageEnqueuedTimestamp\n     * @memberOf MatsSocket\n     * @readonly\n     */\n    Object.defineProperty(this, \"lastMessageEnqueuedTimestamp\", {\n        get: function () {\n            return _lastMessageEnqueuedTimestamp;\n        }\n    });\n\n    /**\n     * Returns whether this MatsSocket <i>currently</i> have a WebSocket connection open. It can both go down\n     * by lost connection (driving through a tunnel), where it will start to do reconnection attempts, or because\n     * you (the Client) have {@link MatsSocket#close closed} this MatsSocketSession, or because the <i>Server</i> has\n     * closed the MatsSocketSession.\n     * <p/>\n     * Pretty much the same as <code>({@link MatsSocket.state} === {@link ConnectionState.CONNECTED})\n     * || ({@link MatsSocket.state} === {@link ConnectionState.SESSION_ESTABLISHED})</code> - however, in the face of\n     * {@link MessageType.DISCONNECT}, the state will not change, but the connection is dead ('connected' returns\n     * false).\n     *\n     * @member {string} connected\n     * @memberOf MatsSocket\n     * @readonly\n     */\n    Object.defineProperty(this, \"connected\", {\n        get: function () {\n            return _webSocket != null;\n        }\n    });\n\n    /**\n     * Returns which one of the {@link ConnectionState} state enums the MatsSocket is in.\n     * <ul>\n     *     <li>NO_SESSION - initial state, and after Session Close (both from client and server side)</li>\n     *     <li>CONNECTING - when we're actively trying to connect, i.e. \"new WebSocket(..)\" has been invoked, but not yet either opened or closed.</li>\n     *     <li>WAITING - if the \"new WebSocket(..)\" invocation ended in the socket closing, i.e. connection failed, but we're still counting down to next (re)connection attempt.</li>\n     *     <li>CONNECTED - if the \"new WebSocket(..)\" resulted in the socket opening. We still have not established the MatsSocketSession with the server, though.</li>\n     *     <li>SESSION_ESTABLISHED - when we're open for business: Connected, authenticated, and established MatsSocketSession with the server.</li>\n     * </ul>\n     *\n     * @member {string} state\n     * @memberOf MatsSocket\n     * @readonly\n     */\n    Object.defineProperty(this, \"state\", {\n        get: function () {\n            return _state;\n        }\n    });\n\n    /**\n     * Metrics/Introspection: Returns an array of the 100 latest {@link PingPong}s. Note that a PingPong entry\n     * is added to this array <i>before</i> it gets the Pong, thus the latest may not have its\n     * {@link PingPong#roundTripMillis} set yet. Also, if a ping is performed right before the connection goes down,\n     * it will never get the Pong, thus there might be entries in the middle of the list too that does not have\n     * roundTripMillis set. This is opposed to the {@link #addPingPongListener}, which only gets invoked when\n     * the pong has arrived.\n     *\n     * @see MatsSocket#addPingPongListener\n     *\n     * @member {array<PingPong>}\n     * @memberOf MatsSocket\n     * @readonly\n     */\n    Object.defineProperty(this, \"pings\", {\n        get: function () {\n            return _pings;\n        }\n    });\n\n    /**\n     * Callback function for {@link MatsSocket#addPingPongListener}.\n     *\n     * @callback addPingPongCallback\n     * @param {PingPong} pingPong information about the ping and the pong.\n     */\n\n    /**\n     * A {@link PingPong} listener is invoked each time a {@link MessageType#PONG} message comes in, giving you\n     * information about the experienced {@link PingPong#roundTripMillis round-trip time}. The PINGs and PONGs are\n     * handled slightly special in that they always are handled ASAP with short-path code routes, and should thus\n     * give a good indication about experienced latency from the network. That said, they are sent on the same\n     * connection as all data, so if there is a gigabyte document \"in the pipe\", the PING will come behind that\n     * and thus get a big hit. Thus, you should consider this when interpreting the results - a high outlier should\n     * be seen in conjunction with a message that was sent at the same time.\n     *\n     * @param {addPingPongCallback} pingPongListener a function that is invoked when the library issues\n     */\n    this.addPingPongListener = function (pingPongListener) {\n        if (!(typeof pingPongListener === 'function')) {\n            throw Error(\"PingPong listener must be a function\");\n        }\n        _pingPongListeners.push(pingPongListener);\n    };\n\n    /**\n     * Metrics/Introspection: Returns an array of the {@link #numberOfInitiationsKept} latest\n     * {@link InitiationProcessedEvent}s.\n     * <p />\n     * Note: These objects will always have the {@link InitiationProcessedEvent#initiationMessage} and (if Request)\n     * {@link InitiationProcessedEvent#replyMessageEvent} set, as opposed to the events issued to\n     * {@link #addInitiationProcessedEventListener}, which can decide whether to include them.\n     *\n     * @see MatsSocket#addInitiationProcessedEventListener\n     *\n     * @member {InitiationProcessedEvent<InitiationProcessedEvent>}\n     * @memberOf MatsSocket\n     * @readonly\n     */\n    Object.defineProperty(this, \"initiations\", {\n        get: function () {\n            return _initiationProcessedEvents;\n        }\n    });\n\n    /**\n     * Metrics/Introspection: How many {@link InitiationProcessedEvent}s to keep in {@link #initiations}.\n     * If the current number of initiations is more than what you set it to, it will be culled.\n     * You can use this to \"reset\" the {@link #initiations array of initiations} by setting it to 0, then right\n     * back up to whatever you fancy.\n     * <p />\n     * Default is 10.\n     *\n     * @member {number}\n     * @memberOf MatsSocket\n     * @readonly\n     */\n    Object.defineProperty(this, \"numberOfInitiationsKept\", {\n        get: function () {\n            return _numberOfInitiationsKept;\n        },\n        set: function (numberOfInitiationsKept) {\n            if (numberOfInitiationsKept < 0) {\n                throw new Error(\"numberOfInitiationsKept must be >= 0\");\n            }\n            _numberOfInitiationsKept = numberOfInitiationsKept;\n            while (_initiationProcessedEvents.length > numberOfInitiationsKept) {\n                _initiationProcessedEvents.shift();\n            }\n        }\n    });\n\n    /**\n     * Callback function for {@link MatsSocket#addInitiationProcessedEventListener}.\n     *\n     * @callback initiationProcessedEventCallback\n     * @param {InitiationProcessedEvent} initiationProcessedEvent information about the processing of the initiation.\n     */\n\n    /**\n     * Registering an {@link InitiationProcessedEvent} listener will give you meta information about each Send\n     * and Request that is performed through the library when it is fully processed, thus also containing\n     * information about experienced round-trip times. The idea is that you thus can gather metrics of\n     * performance as experienced out on the client, by e.g. periodically sending this gathering to the Server.\n     * <b>Make sure that you understand that if you send to the server each time this listener is invoked, using\n     * the MatsSocket itself, you WILL end up in a tight loop!</b> This is because the sending of the statistics\n     * message itself will again trigger a new invocation of this listener. This can be avoided in two ways: Either\n     * instead send periodically - in which case you can include the statistics message itself, OR specify that\n     * you do NOT want a listener-invocation of these messages by use of the config object on the send, request\n     * and requestReplyTo methods.\n     * <p />\n     * Note: Each listener gets its own instance of {@link InitiationProcessedEvent}, which also is different from\n     * the ones in the {@link MatsSocket.initiations} array.\n     *\n     * @param {initiationProcessedEventCallback} initiationProcessedEventListener a function that is invoked when\n     * the library issues {@link InitiationProcessedEvent}s.\n     * @param {boolean} includeInitiationMessage whether to include the {@link InitiationProcessedEvent#initiationMessage}\n     * @param {boolean} includeReplyMessageEvent whether to include the {@link InitiationProcessedEvent#replyMessageEvent}\n     * Reply {@link MessageEvent}s.\n     */\n    this.addInitiationProcessedEventListener = function (initiationProcessedEventListener, includeInitiationMessage, includeReplyMessageEvent) {\n        if (!(typeof initiationProcessedEventListener === 'function')) {\n            throw Error(\"InitiationProcessedEvent listener must be a function\");\n        }\n        _initiationProcessedEventListeners.push({\n            listener: initiationProcessedEventListener,\n            includeInitiationMessage: includeInitiationMessage,\n            includeReplyMessageEvent: includeReplyMessageEvent\n        });\n    };\n\n    // ========== Terminator and Endpoint registration ==========\n\n    /**\n     * Registers a Terminator, on the specified terminatorId, and with the specified callbacks. A Terminator is\n     * the target for Server-to-Client SENDs, and the Server's REPLYs from invocations of\n     * <code>requestReplyTo(terminatorId ..)</code> where the terminatorId points to this Terminator.\n     * <p />\n     * Note: You cannot register any Terminators, Endpoints or Subscriptions starting with \"MatsSocket\".\n     *\n     * @param terminatorId the id of this client side Terminator.\n     * @param messageCallback receives an Event when everything went OK, containing the message on the \"data\" property.\n     * @param rejectCallback is relevant if this endpoint is set as the replyTo-target on a requestReplyTo(..) invocation, and will\n     * get invoked with the Event if the corresponding Promise-variant would have been rejected.\n     */\n    this.terminator = function (terminatorId, messageCallback, rejectCallback) {\n        // :: Assert for double-registrations\n        if (_terminators[terminatorId] !== undefined) {\n            throw new Error(\"Cannot register more than one Terminator to same terminatorId [\" + terminatorId + \"], existing: \" + _terminators[terminatorId]);\n        }\n        if (_endpoints[terminatorId] !== undefined) {\n            throw new Error(\"Cannot register a Terminator to same terminatorId [\" + terminatorId + \"] as an Endpoint's endpointId, existing: \" + _endpoints[terminatorId]);\n        }\n        // :: Assert that the namespace \"MatsSocket\" is not used\n        if (terminatorId.startsWith(\"MatsSocket\")) {\n            throw new Error('The namespace \"MatsSocket\" is reserved, terminatorId [' + terminatorId + '] is illegal.');\n        }\n        // :: Assert that the messageCallback is a function\n        if (typeof messageCallback !== 'function') {\n            throw new Error(\"The 'messageCallback' must be a function.\");\n        }\n        // :: Assert that the rejectCallback is either undefined or a function\n        if ((rejectCallback !== undefined) && (typeof rejectCallback !== 'function')) {\n            throw new Error(\"The 'rejectCallback' must either be undefined or a function.\");\n        }\n        log(\"Registering Terminator on id [\" + terminatorId + \"]:\\n #messageCallback: \" + messageCallback + \"\\n #rejectCallback: \" + rejectCallback);\n        _terminators[terminatorId] = {\n            resolve: messageCallback,\n            reject: rejectCallback\n        };\n    };\n\n    /**\n     * Registers an Endpoint, on the specified endpointId, with the specified \"promiseProducer\". An Endpoint is\n     * the target for Server-to-Client REQUESTs. The promiseProducer is a function that takes a message event\n     * (the incoming REQUEST) and produces a Promise, whose return (resolve or reject) is the return value of the\n     * endpoint.\n     * <p />\n     * Note: You cannot register any Terminators, Endpoints or Subscriptions starting with \"MatsSocket\".\n     *\n     * @param endpointId the id of this client side Endpoint.\n     * @param {function} promiseProducer a function that takes a Message Event and returns a Promise which when\n     * later either Resolve or Reject will be the return value of the endpoint call.\n     */\n    this.endpoint = function (endpointId, promiseProducer) {\n        // :: Assert for double-registrations\n        if (_endpoints[endpointId] !== undefined) {\n            throw new Error(\"Cannot register more than one Endpoint to same endpointId [\" + endpointId + \"], existing: \" + _endpoints[endpointId]);\n        }\n        if (_terminators[endpointId] !== undefined) {\n            throw new Error(\"Cannot register an Endpoint to same endpointId [\" + endpointId + \"] as a Terminator, existing: \" + _terminators[endpointId]);\n        }\n        // :: Assert that the namespace \"MatsSocket\" is not used\n        if (endpointId.startsWith(\"MatsSocket\")) {\n            throw new Error('The namespace \"MatsSocket\" is reserved, EndpointId [' + endpointId + '] is illegal.');\n        }\n        // :: Assert that the promiseProducer is a function\n        if (typeof promiseProducer !== 'function') {\n            throw new Error(\"The 'promiseProducer' must be a function.\");\n        }\n        log(\"Registering Endpoint on id [\" + endpointId + \"]:\\n #promiseProducer: \" + promiseProducer);\n        _endpoints[endpointId] = promiseProducer;\n    };\n\n    /**\n     * Subscribes to a Topic. The Server may do an authorization check for the subscription. If you are not allowed,\n     * a {@link SubscriptionEvent} of type {@link SubscriptionEventType.NOT_AUTHORIZED} is issued, and the callback\n     * will not get any messages. Otherwise, the event type is {@link SubscriptionEventType.OK}.\n     * <p />\n     * Note: If the 'messageCallback' was already registered, an error is emitted, but the method otherwise returns\n     * silently.\n     * <p />\n     * Note: You will not get messages that was issued before the subscription initially is registered with the\n     * server, which means that you by definition cannot get any messages issued earlier than the initial\n     * {@link ConnectionEventType.SESSION_ESTABLISHED}. Code accordingly. <i>Tip for a \"ticker stream\" or \"cache\n     * update stream\" or similar: Make sure you have some concept of event sequence number on updates. Do the MatsSocket\n     * connect with the Subscription in place, but for now just queue up any updates. Do the request for \"full initial load\", whose reply\n     * contains the last applied sequence number. Now process the queued events that arrived while getting the\n     * initial load (i.e. in front, or immediately after), taking into account which event sequence numbers that\n     * already was applied in the initial load: Discard the earlier and same, apply the later. Finally, go over to\n     * immediate processing of the events. If you get a reconnect telling you that messages was lost (next \"Note\"!),\n     * you could start this process over.</i>\n     * <p />\n     * Note: Reconnects are somewhat catered for, in that a \"re-subscription\" after re-establishing the session will\n     * contain the latest messageId the client has received, and the server will then send along all the messages\n     * <i>after</i> this that was lost - up to some limit specified on the server. If the messageId is not known by the server,\n     * implying that the client has been gone for too long time, a {@link SubscriptionEvent} of type\n     * {@link SubscriptionEventType.LOST_MESSAGES} is issued. Otherwise, the event type is\n     * {@link SubscriptionEventType.OK}.\n     * <p />\n     * Note: You should preferably add all \"static\" subscriptions in the \"configuration phase\" while setting up\n     * your MatsSocket, before starting it (i.e. sending first message). However, dynamic adding and\n     * {@link MatsSocket#deleteSubscription deleting} is also supported.\n     * <p />\n     * Note: Pub/sub is not designed to be as reliable as send/request - but it should be pretty ok anyway!\n     * <p />\n     * Wrt. to how many topics a client can subscribe to: Mainly bandwidth constrained wrt. to the total number of\n     * messages, although there is a slight memory and CPU usage to consider too (several hundred should not really\n     * be a problem). In addition, the client needs to send over the actual subscriptions, and if these number in\n     * the thousands, the connect and any reconnects could end up with tens or hundreds of kilobytes of \"system\n     * information\" passed over the WebSocket.\n     * <p />\n     * Wrt. to how many topics that can exist: Mainly memory constrained on the server based on the number of topics\n     * multiplied by the number of subscriptions per topic, in addition to the number of messages passed in total\n     * as each node in the cluster will have to listen to either the full total of messages, or at least a\n     * substantial subset of the messages - and it will also retain these messages for hours to allow for client\n     * reconnects.\n     * <p />\n     * Note: You cannot register any Terminators, Endpoints or Subscriptions starting with \"MatsSocket\".\n     */\n    this.subscribe = function (topicId, messageCallback) {\n        // :: Assert that the namespace \"MatsSocket\" is not used\n        if (topicId.startsWith(\"MatsSocket\")) {\n            throw new Error('The namespace \"MatsSocket\" is reserved, Topic [' + topicId + '] is illegal.');\n        }\n        if (topicId.startsWith(\"!\")) {\n            throw new Error('Topic cannot start with \"!\" (and why would you use chars like that anyway?!), Topic [' + topicId + '] is illegal.');\n        }\n        // :: Assert that the messageCallback is a function\n        if (typeof messageCallback !== 'function') {\n            throw new Error(\"The 'messageCallback' must be a function.\");\n        }\n        log(\"Registering Subscription on Topic [\" + topicId + \"]:\\n #messageCallback: \" + messageCallback);\n        // ?: Check if we have an active subscription holder here already\n        let subs = _subscriptions[topicId];\n        if (!subs) {\n            // -> No, we do not have subscription holder going\n            // Add a holder\n            subs = {\n                listeners: [],\n                lastSmid: undefined,\n                subscriptionSentToServer: false\n            };\n            _subscriptions[topicId] = subs;\n        }\n        // :: Assert that the messageCallback is not already there\n        for (let i = 0; i < subs.listeners.length; i++) {\n            if (subs.listeners[i] === messageCallback) {\n                error(\"subscription_already_exists\", \"The specified messageCallback [\" + messageCallback + \"] was already subscribed to Topic [\" + topicId + \"].\");\n                return;\n            }\n        }\n        // Add the present messageCallback to the subscription holder\n        subs.listeners.push(messageCallback);\n\n        // ?: Have we NOT already subscribed with Server?\n        if (!subs.subscriptionSentToServer) {\n            // ?: Has HELLO already been sent?\n            // (If socket is NOT hello'ed, subs will be done when doing HELLO.)\n            if (_helloSent) {\n                // -> Yes, HELLO sent, so handle \"dynamic subscription\", i.e. subscribing while the socket is open.\n                // Send message to subscribe this TopicId with the server\n                // - using PRE-pipeline to get it done in front of any e.g send or request that potentially could\n                // trigger a publish (on the server side) which we should now get.\n                _addEnvelopeToPipeline_EvaluatePipelineLater({\n                    t: MessageType.SUB,\n                    eid: topicId\n                }, true);\n                // The subscription must now be assumed sent to the server (ref unsubscription)\n                subs.subscriptionSentToServer = true;\n            }\n            else {\n                // -> No, HELLO not yet sent. Make it happen Real Soon Now.\n                // HELLO handling will do the subscription\n                // We must however force pipeline processing since there might be nothing in the pipelines.\n                _forcePipelineProcessing = true;\n                // We must also \"force open\" the MatsSocket, i.e. \"emulate\" that an information bearing message is enqueued.\n                _matsSocketOpen = true;\n                // Run the pipeline (use \"later\", there might be more subs or messages to come from client)\n                _evaluatePipelineLater();\n            }\n        }\n    };\n\n    /**\n     * Removes a previously added {@link MatsSocket#subscribe subscription}. If there are no more listeners for this topic,\n     * it is de-subscribed from the server. If the 'messageCallback' was not already registered, an error is\n     * emitted, but the method otherwise returns silently.\n     *\n     * @param topicId\n     * @param messageCallback\n     */\n    this.deleteSubscription = function (topicId, messageCallback) {\n        let subs = _subscriptions[topicId];\n        if (!subs) {\n            throw new Error(\"The topicId [\" + topicId + \"] had no subscriptions! (thus this message callback is not subscribed! [\" + messageCallback + \"].\");\n        }\n        let found = false;\n        for (let i = 0; i < subs.listeners.length; i++) {\n            if (subs.listeners[i] === messageCallback) {\n                found = true;\n                subs.listeners = subs.listeners.splice(i, 1);\n                break;\n            }\n        }\n        if (!found) {\n            error(\"subscription_not_found\", \"The specified messageCallback [\" + messageCallback + \"] was not subscribed with Topic [\" + topicId + \"].\");\n            return;\n        }\n\n        // :: Only need to send unsubscription if we already are subscribed\n\n        // ?: Are we empty of listeners, AND we are already subscribed with Server?\n        if ((subs.listeners.length === 0) && subs.subscriptionSentToServer) {\n            // -> Yes, we are empty of listeners, and the subscription is already sent\n            // Send message to unsubscribe this TopicId with the server\n            // - using PRE-pipeline since subscriptions are using that, and we need subs and de-subs in sequential correct order\n            _addEnvelopeToPipeline_EvaluatePipelineLater({\n                t: MessageType.UNSUB,\n                eid: topicId\n            }, true);\n            // Remove locally\n            delete _subscriptions[topicId];\n        }\n    };\n\n    /**\n     * \"Fire-and-forget\"-style send-a-message. The returned promise is Resolved when the Server receives and accepts\n     * the message for processing, while it is Rejected if the Server denies it.\n     * <p/>\n     * The config object has a single key - <i>which is optional</i>:\n     * <ul>\n     *     <li>suppressInitiationProcessedEvent: If <code>true</code>, no event will be sent to listeners added\n     *         using {@link MatsSocket#addInitiationProcessedEventListener}.</li>\n     * </ul>\n     *\n     * @param endpointId the Server MatsSocket Endpoint/Terminator that this message should go to.\n     * @param traceId the TraceId for this message - will go through all parts of the call, including the Mats flow.\n     * @param message the actual message for the Server MatsSocket Endpoint.\n     * @param {object} config an optional configuration object - read JSDoc.\n     * @returns {Promise<ReceivedEvent>}\n     */\n    this.send = function (endpointId, traceId, message, config = undefined) {\n        return new Promise(function (resolve, reject) {\n            // Make lambda for what happens when it has been RECEIVED on server.\n            let initiation = Object.create(null);\n            // Set the Sends's returned Promise's settle functions for ACK and NACK.\n            initiation.ack = resolve;\n            initiation.nack = reject;\n\n            // Parse config object\n            if (config) {\n                if (typeof (config) !== 'object') {\n                    throw new Error(\"The 'config' parameter wasn't an object.\");\n                }\n                // ?: 'suppressInitiationProcessedEvent' setting?\n                if (config.suppressInitiationProcessedEvent) {\n                    initiation.suppressInitiationProcessedEvent = true;\n                }\n            }\n\n            let envelope = Object.create(null);\n            envelope.t = MessageType.SEND;\n            envelope.eid = endpointId;\n            envelope.msg = message;\n\n            _addInformationBearingEnvelopeToPipeline(envelope, traceId, initiation, undefined);\n        });\n    };\n\n\n    /**\n     * Perform a Request, and have the reply come back via the returned Promise. As opposed to Send, where the\n     * returned Promise is resolved when the server accepts the message, the Promise is now resolved by the Reply.\n     * To get information of whether the server accepted or did not accept the message, you can provide either\n     * a receivedCallback function (set the 'config' parameter to this function) or set the two config properties\n     * 'ackCallback' and 'nackCallback' to functions. If you supply the single function variant, this is equivalent\n     * to setting both ack- and nackCallback to the same function. The {@link ReceivedEvent}'s type will distinguish\n     * between {@link ReceivedEventType.ACK ACK} or {@link ReceivedEventType.NACK NACK}.\n     * <p/>\n     * The config object has keys as such - <i>all are optional</i>:\n     * <ul>\n     *     <li><b><code>receivedCallback</code></b>: {function} invoked when the Server receives the event and either ACK or NACKs it\n     *         - or when {@link MessageEventType.TIMEOUT} or {@link MessageEventType.SESSION_CLOSED} happens.\n     *         This overrides the ack- and nackCallbacks.</li>\n     *     <li><b><code>ackCallback</code></b>: {function} invoked when the Server receives the event and ACKs it.</li>\n     *     <li><b><code>nackCallback</code></b>: {function} invoked when the Server receives the event and NACKs it\n     *         - or when {@link MessageEventType.TIMEOUT} or {@link MessageEventType.SESSION_CLOSED} happens.</li>\n     *     <li><b><code>timeout</code></b>: number of milliseconds before the Client times out the Server reply. When this happens,\n     *         the 'nackCallback' (or receivedCallback if this is used) is invoked with a {@link ReceivedEvent} of\n     *         type {@link ReceivedEventType.TIMEOUT}, and the Request's Promise will be <i>rejected</i> with a\n     *         {@link MessageEvent} of type {@link MessageEventType.TIMEOUT}.</li>\n     *     <li><b><code>suppressInitiationProcessedEvent</code></b>: if <code>true</code>, no event will be sent to listeners added\n     *         using {@link MatsSocket#addInitiationProcessedEventListener}.</li>\n     *     <li><b><code>debug</code></b>: If set, this specific call flow overrides the global {@link MatsSocket#debug} setting, read\n     *         more about debug and {@link DebugOption}s there.</li>\n     * </ul>\n     * <p />\n     * <b>Note on event ordering:</b> {@link ReceivedEvent}s shall always be delivered <i>before</i> {@link MessageEvent}s.\n     * This means that for a <i>request</i>, if receivedCallback (or ack- or nackCallback) is provided, it shall be\n     * invoked <i>before</i> the return Reply-Promise will be settled. For more on event ordering wrt. message\n     * processing, read {@link InitiationProcessedEvent}.\n     *\n     * @param endpointId the Server MatsSocket Endpoint that this message should go to.\n     * @param traceId the TraceId for this message - will go through all parts of the call, including the Mats flow.\n     * @param message the actual message for the Server MatsSocket Endpoint.\n     * @param {function|object} configOrCallback (optional) either directly a \"receivedCallback\" function as\n     *        described in the config object, or a config object - read JSDoc above.\n     * @returns {Promise<MessageEvent>}\n     */\n    this.request = function (endpointId, traceId, message, configOrCallback = undefined) {\n        return new Promise(function (resolve, reject) {\n            // Default Timeout is MatsSocket's default\n            let timeout = that.requestTimeout;\n\n            // Make lambda for what happens when it has been RECEIVED on server.\n            let initiation = Object.create(null);\n\n            // :: Handle the different configOrCallback situations\n\n            // ?: Is the 'configOrCallback' a function?\n            if (typeof (configOrCallback) === 'function') {\n                // -> Yes, function, so then it is a receivedCallback: Set both ACN and NACK to the this function\n                initiation.ack = configOrCallback;\n                initiation.nack = configOrCallback;\n\n                // ?: Is the 'configOrCallback' an object?\n            } else if (typeof (configOrCallback) === 'object') {\n                // -> Yes, object, so then it is a config object\n\n                // ?: Do we have a 'receivedCallback' defined?\n                if (configOrCallback.receivedCallback) {\n                    // -> Yes, we have a 'receivedCallback': Set both ACN and NACK to the this function\n                    if (typeof (configOrCallback.receivedCallback) !== 'function') {\n                        throw new Error(\"The 'configOrCallback.receivedCallback' is not a function.\");\n                    }\n                    // Set both ACN and NACK to the 'receivedCallback'\n                    initiation.ack = configOrCallback.receivedCallback;\n                    initiation.nack = configOrCallback.receivedCallback;\n                } else {\n                    // -> No, no 'receivedCallback', so then handle if we have ack- or nackCallback\n                    // ?: Do we have 'ackCallback'?\n                    if (configOrCallback.ackCallback) {\n                        // -> Yes, 'ackCallback' present - assert that it is a function, and then set it.\n                        if (typeof (configOrCallback.ackCallback) !== 'function') {\n                            throw new Error(\"The 'configOrCallback.ackCallback' is not a function.\");\n                        }\n                        initiation.ack = configOrCallback.ackCallback;\n                    }\n                    // ?: Do we have 'nackCallback'?\n                    if (configOrCallback.nackCallback) {\n                        // -> Yes, 'nackCallback' present - assert that it is a function, and then set it.\n                        if (typeof (configOrCallback.nackCallback) !== 'function') {\n                            throw new Error(\"The 'configOrCallback.nackCallback' is not a function.\");\n                        }\n                        initiation.nack = configOrCallback.nackCallback;\n                    }\n                }\n\n                // ?: Do we have a timeout configured?\n                if (configOrCallback.timeout !== undefined) {\n                    // -> Yes, there was a timeout configured - assert that it is a number, then override default.\n                    if (typeof (configOrCallback.timeout) !== 'number') {\n                        throw new Error(\"The 'configOrCallback.timeout' is not a number.\");\n                    }\n                    timeout = configOrCallback.timeout;\n                }\n\n                // ?: 'suppressInitiationProcessedEvent' setting?\n                if (configOrCallback.suppressInitiationProcessedEvent) {\n                    initiation.suppressInitiationProcessedEvent = true;\n                }\n\n                // ?: 'debug' setting?\n                if (configOrCallback.debug !== undefined) {\n                    initiation.debug = configOrCallback.debug;\n                }\n\n                // ?: Is the 'configOrCallback' /undefined/?\n            } else if (typeof (configOrCallback) === 'undefined') {\n                // -> Yes, undefined - which is default, and legal!\n                /* n/a */\n\n            } else {\n                // -> It is something else than 'function', 'object' or /undefined/ -> illegal!\n                throw new Error(\"The 'configOrCallback' parameter was neither a function or an object.\");\n            }\n\n            // Make Request for the Reply\n            let request = Object.create(null);\n            request.resolve = resolve;\n            request.reject = reject;\n            request.timeout = timeout;\n\n            // Make the MatsSocket Envelope that will be sent.\n            let envelope = Object.create(null);\n            envelope.t = MessageType.REQUEST;\n            envelope.eid = endpointId;\n            envelope.msg = message;\n            envelope.to = timeout;\n\n            _addInformationBearingEnvelopeToPipeline(envelope, traceId, initiation, request);\n        });\n    };\n\n    /**\n     * Perform a Request, but send the reply to a specific client terminator registered on this MatsSocket instance.\n     * The returned Promise functions as for Send, since the reply will not go to the Promise, but to the\n     * terminator. Notice that you can set any CorrelationInformation object which will be available for the Client\n     * terminator when it receives the reply - this is kept on the client (not serialized and sent along with\n     * request and reply), so it can be any object: An identifier, some object to apply the result on, or even a\n     * function.\n     * <p/>\n     * The config object has keys as such - <i>all are optional</i>:\n     * <ul>\n     *     <li><b><code>timeout</code></b>: number of milliseconds before the Client times out the Server reply. When this happens,\n     *         the returned Promise is <i>rejected</i> with a {@link ReceivedEvent} of\n     *         type {@link ReceivedEventType.TIMEOUT}, and the specified Client Terminator will have its\n     *         rejectCallback invoked with a {@link MessageEvent} of type {@link MessageEventType.TIMEOUT}.</li>\n     *     <li><b><code>suppressInitiationProcessedEvent</code></b>: if <code>true</code>, no event will be sent to listeners added\n     *         using {@link MatsSocket#addInitiationProcessedEventListener}.</li>\n     *     <li><b><code>debug</code></b>: If set, this specific call flow overrides the global {@link MatsSocket#debug} setting, read\n     *         more about debug and {@link DebugOption}s there.</li>\n     * </ul>\n     * <p />\n     * <b>Note on event ordering:</b> {@link ReceivedEvent}s shall always be delivered before {@link MessageEvent}s. This means\n     * that for a <i>requestReplyTo</i>, the returned Received-Promise shall be settled <i>before</i> the\n     * Terminator gets its resolve- or rejectCallback invoked. For more on event ordering wrt. message\n     * processing, read {@link InitiationProcessedEvent}.\n     *\n     * @param endpointId the Server MatsSocket Endpoint that this message should go to.\n     * @param traceId the TraceId for this message - will go through all parts of the call, including the Mats flow.\n     * @param message the actual message for the Server MatsSocket Endpoint.\n     * @param replyToTerminatorId which Client Terminator the reply should go to\n     * @param correlationInformation information that will be available to the Client Terminator\n     *        (in {@link MessageEvent#correlationInformation}) when the reply comes back.\n     * @param {object} config an optional configuration object - the one parameter you can set is 'timeout', which\n     *        works like it does for {@link MatsSocket#request}.\n     * @returns {Promise<ReceivedEvent>}\n     */\n    this.requestReplyTo = function (endpointId, traceId, message, replyToTerminatorId, correlationInformation, config = undefined) {\n        // ?: Do we have the Terminator the client requests reply should go to?\n        if (!_terminators[replyToTerminatorId]) {\n            // -> No, we do not have this. Programming error from app.\n            throw new Error(\"The Client Terminator [\" + replyToTerminatorId + \"] is not present, !\");\n        }\n\n        return new Promise(function (resolve, reject) {\n            // Make lambda for what happens when it has been RECEIVED on server.\n            let initiation = Object.create(null);\n            // Set the RequestReplyTop's returned Promise's settle functions for ACK and NACK.\n            initiation.ack = resolve;\n            initiation.nack = reject;\n\n            // :: Find which timeout to use\n            let timeout = that.requestTimeout;\n\n            // Parse config object\n            if (config) {\n                if (typeof (config) !== 'object') {\n                    throw new Error(\"The 'config' parameter wasn't an object.\");\n                }\n\n                // ?: Do we have a timeout configured?\n                if (config.timeout !== undefined) {\n                    // -> Yes, there was a timeout configured - assert that it is a number, then override default.\n                    if (typeof (config.timeout) !== 'number') {\n                        throw new Error(\"The 'config.timeout' is not a number.\");\n                    }\n                    timeout = config.timeout;\n                }\n\n                // ?: 'suppressInitiationProcessedEvent' setting?\n                if (config.suppressInitiationProcessedEvent) {\n                    initiation.suppressInitiationProcessedEvent = true;\n                }\n\n                // ?: 'debug' setting?\n                if (config.debug !== undefined) {\n                    initiation.debug = config.debug;\n                }\n            }\n\n            // Make Request for the Reply\n            let request = Object.create(null);\n            request.replyToTerminatorId = replyToTerminatorId;\n            request.correlationInformation = correlationInformation;\n            request.timeout = timeout;\n\n            // Make the MatsSocket Envelope that will be sent.\n            let envelope = Object.create(null);\n            envelope.t = MessageType.REQUEST;\n            envelope.eid = endpointId;\n            envelope.msg = message;\n            envelope.to = timeout;\n\n            _addInformationBearingEnvelopeToPipeline(envelope, traceId, initiation, request);\n        });\n    };\n\n    /**\n     * Synchronously flush any pipelined messages, i.e. when the method exits, webSocket.send(..) has been invoked\n     * with the serialized pipelined messages, <i>unless</i> the authorization had expired (read more at\n     * {@link MatsSocket#setCurrentAuthorization} and {@link MatsSocket#setAuthorizationExpiredCallback}).\n     */\n    this.flush = function () {\n        // ?: Are we currently doing \"auto-pipelining\"?\n        if (_evaluatePipelineLater_timeoutId) {\n            // -> Yes, so clear this timeout, since we're flushing now.\n            clearTimeout(_evaluatePipelineLater_timeoutId);\n            _evaluatePipelineLater_timeoutId = undefined;\n        }\n        // Do flush\n        _evaluatePipelineSend();\n    };\n\n    /**\n     * Closes any currently open WebSocket with MatsSocket-specific CloseCode CLOSE_SESSION (4000). Depending\n     * of the value of {@link MatsSocket#outofbandclose}, it <i>also</i> uses <code>navigator.sendBeacon(..)</code>\n     * (if present, i.e. web browser context) to send an out-of-band Close Session HTTP POST, or, if\n     * 'outofbancclose' is a function, this is invoked (if 'outofbandclose' is <code>false</code>, this\n     * functionality is disabled). Upon receiving the WebSocket close, the server terminates the MatsSocketSession.\n     * The MatsSocket instance's SessionId is made undefined. If there currently is a pipeline,\n     * this will be dropped (i.e. messages deleted), any outstanding receiveCallbacks\n     * (from Requests) are invoked, and received Promises (from sends) are rejected, with type\n     * {@link ReceivedEventType.SESSION_CLOSED}, outstanding Reply Promises (from Requests)\n     * are rejected with {@link MessageEventType.SESSION_CLOSED}. The effect is to cleanly shut down the\n     * MatsSocketSession (all session data removed from server), and also clean the MatsSocket instance.\n     * <p />\n     * Afterwards, the MatsSocket can be started up again by sending a message - keeping its configuration wrt.\n     * terminators, endpoints and listeners. As The SessionId on this client MatsSocket was cleared (and the\n     * previous Session on the server is deleted), this will result in a new server side Session. If you want a\n     * totally clean MatsSocket instance, then just ditch the current instance and make a new one (which then will\n     * have to be configured with terminators etc).\n     * <p />\n     * <b>Note: A 'beforeunload' event handler is automatically registered on 'window' (if present, i.e. MatsSocket is\n     * running in a web browser), which invokes this method</b>, so that if the user navigates away, the session will\n     * be closed.\n     *\n     * @param {string} reason short descriptive string. Will be supplied with the webSocket close reason string,\n     * and must therefore be quite short (max 123 chars).\n     */\n    this.close = function (reason) {\n        // Fetch properties we need before clearing state\n        let existingWebSocketUrl = _currentWebSocketUrl;\n        let existingSessionId = that.sessionId;\n        log(\"close(): Closing MatsSocketSession, id:[\" + existingSessionId + \"] due to [\" + reason\n            + \"], currently connected: [\" + (_webSocket ? _webSocket.url : \"not connected\") + \"]\");\n\n        // :: In-band Session Close: Close the WebSocket itself with CLOSE_SESSION Close Code.\n        // ?: Do we have _webSocket?\n        if (_webSocket) {\n            // -> Yes, so close WebSocket with MatsSocket-specific CloseCode CLOSE_SESSION 4000.\n            log(\" \\\\-> WebSocket is open, so we perform in-band Session Close by closing the WebSocket with MatsSocketCloseCode.CLOSE_SESSION (4000).\");\n            // Perform the close\n            _webSocket.close(MatsSocketCloseCodes.CLOSE_SESSION, \"From client: \" + reason);\n        }\n\n        // Close Session and clear all state of this MatsSocket.\n        _closeSessionAndClearStateAndPipelineAndFuturesAndOutstandingMessages();\n\n        // :: Out-of-band Session Close\n        // ?: Do we have a sessionId?\n        if (existingSessionId) {\n            // ?: Is the out-of-band close function defined?\n            if (typeof (this.outofbandclose) === \"function\") {\n                // -> Yes, function, so invoke it\n                this.outofbandclose({\n                    webSocketUrl: existingWebSocketUrl,\n                    sessionId: existingSessionId\n                });\n                // ?: Is the out-of-band close 'truthy'?\n            } else if (this.outofbandclose) {\n                // -> Yes, truthy, so perform default logic\n                // ?: Do we have 'navigator'?\n                if ((typeof window !== 'undefined') && (typeof window.navigator !== 'undefined')) {\n                    // -> Yes, navigator present, so then we can fire off the out-of-band close too\n                    // Fire off a \"close\" over HTTP using navigator.sendBeacon(), so that even if the socket is closed, it is possible to terminate the MatsSocket SessionId.\n                    let closeSesionUrl = existingWebSocketUrl.replace(\"ws\", \"http\") + \"/close_session?session_id=\" + existingSessionId;\n                    log(\"  \\\\- Send an out-of-band (i.e. HTTP) close_session, using navigator.sendBeacon('\" + closeSesionUrl + \"').\");\n                    let success = window.navigator.sendBeacon(closeSesionUrl);\n                    log(\"    \\\\- Result: \" + (success ? \"Enqueued POST, but do not know whether anyone received it - check Network tab of Dev Tools.\" : \"Did NOT manage to enqueue a POST.\"));\n                }\n            }\n        }\n    };\n\n    /**\n     * Effectively emulates \"lost connection\". Used in testing.\n     * <p />\n     * If the \"disconnect\" parameter is true, it will disconnect with {@link MatsSocketCloseCodes.DISCONNECT}\n     * instead of {@link MatsSocketCloseCodes.RECONNECT}, which will result in the MatsSocket not immediately\n     * starting the reconnection procedure until a new message is added.\n     *\n     * @param reason {String} a string saying why.\n     * @param disconnect {Boolean} whether to close with {@link MatsSocketCloseCodes.DISCONNECT} instead of\n     * {@link MatsSocketCloseCodes.RECONNECT} - default <code>false</code>. AFAIK, only useful in testing..!\n     */\n    this.reconnect = function (reason, disconnect = false) {\n        let closeCode = disconnect ? MatsSocketCloseCodes.DISCONNECT : MatsSocketCloseCodes.RECONNECT;\n        if (that.logging) log(\"reconnect(): Closing WebSocket with CloseCode '\" + MatsSocketCloseCodesUtil.nameFor(closeCode) + \" (\" + closeCode + \")',\" +\n            \" MatsSocketSessionId:[\" + that.sessionId + \"] due to [\" + reason + \"], currently connected: [\" + (_webSocket ? _webSocket.url : \"not connected\") + \"]\");\n        if (!_webSocket) {\n            throw new Error(\"There is no live WebSocket to close with \" + MatsSocketCloseCodesUtil.nameFor(closeCode) + \" closeCode!\");\n        }\n        // Hack for Node: Node is too fast wrt. handling the reply message, so one of the integration tests fails.\n        // The test in question reconnect in face of having the test RESOLVE in the incomingHandler, which exercises\n        // the double-delivery catching when getting a direct RESOLVE instead of an ACK from the server.\n        // However, the following RECONNECT-close is handled /after/ the RESOLVE message comes in, and ok's the test.\n        // So then, MatsSocket dutifully starts reconnecting - /after/ the test is finished. Thus, Node sees the\n        // outstanding timeout \"thread\" which pings, and never exits. To better emulate an actual lost connection,\n        // we /first/ unset the 'onmessage' handler (so that any pending messages surely will be lost), before we\n        // close the socket. Notice that a \"_matsSocketOpen\" guard was also added, so that it shall explicitly stop\n        // such reconnecting in face of an actual .close(..) invocation.\n\n        // First unset message handler so that we do not receive any more WebSocket messages (but NOT unset 'onclose', nor 'onerror')\n        _webSocket.onmessage = undefined;\n        // Now closing the WebSocket (thus getting the 'onclose' handler invoked - just as if we'd lost connection, or got this RECONNECT close from Server).\n        _webSocket.close(closeCode, reason);\n    };\n\n    /**\n     * Convenience method for making random strings meant for user reading, e.g. as a part of a good TraceIds, since this\n     * alphabet only consists of lower and upper case letters, and digits. To make a traceId \"unique enough\" for\n     * finding it in a log system, a length of 6 should be plenty. The alphabet is 62 chars.\n     *\n     * @param {number} length how long the string should be, default is 6.\n     * @returns {string} a random string consisting of characters from from digits, lower and upper case letters\n     * (62 chars).\n     */\n    this.randomId = function (length= 6) {\n        let result = '';\n        for (let i = 0; i < length; i++) {\n            result += _alphabet[Math.floor(Math.random() * _alphabet.length)];\n        }\n        return result;\n    };\n\n    /**\n     * Convenience method for making random strings for correlationIds, not meant for human reading as the alphabet\n     * consist of all visible ACSII chars that won't be quoted in a JSON string. Should you want to make actual Session\n     * cookies or similar, that is, ids being very unique and hard to brute force, you would want to have a longer length,\n     * use e.g. length=16. The alphabet is 92 chars.\n     * @param {number} length how long the string should be, default is 10.\n     * @returns {string} a random string consisting of characters from all visible and non-JSON-quoted chars of\n     * ASCII (92 chars).\n     */\n    this.randomCId = function (length= 10) {\n        let result = '';\n        for (let i = 0; i < length; i++) {\n            result += _jsonAlphabet[Math.floor(Math.random() * _jsonAlphabet.length)];\n        }\n        return result;\n    };\n\n    // ==============================================================================================\n    // PRIVATE\n    // ==============================================================================================\n\n    const start = Date.now();\n\n    function log(msg, object) {\n        if (that.logging) {\n            if (object) {\n                console.log(_matsSocketInstanceId + \"/\" + that.sessionId + \"{\" + (Date.now() - start) + \"}: \" + msg, object);\n            } else {\n                console.log(_matsSocketInstanceId + \"/\" + that.sessionId + \"{\" + (Date.now() - start) + \"}: \" + msg);\n            }\n        }\n    }\n\n    function error(type, msg, err) {\n        let event = new ErrorEvent(type, msg, err);\n        // Notify ErrorEvent listeners, synchronously.\n        for (let i = 0; i < _errorEventListeners.length; i++) {\n            try {\n                _errorEventListeners[i](event);\n            } catch (err) {\n                // NOTICE! NOT using error(..) - THIS method - to notify about errors, in fear of ending up with infinite recursion\n                console.error(\"Caught error when notifying one of the [\" + _errorEventListeners.length + \"] ErrorEvent listeners - NOT notifying using ErrorEvent in fear of creating infinite recursion.\", err);\n            }\n        }\n\n        if (that.errorLogging) {\n            if (err) {\n                console.error(type + \": \" + msg, err);\n            } else {\n                console.error(type + \": \" + msg);\n            }\n        }\n    }\n\n    // ==== Fields\n\n    // Simple Alphabet: All digits, lower and upper ASCII chars: 10 + 26 x 2 = 62 chars.\n    const _alphabet = \"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\";\n    // Alphabet of JSON-non-quoted and visible chars: 92 chars.\n    const _jsonAlphabet = \"!#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~\";\n\n    // The URLs to use - will be shuffled. Can be reset to not randomized by this.disableUrlRandomize()\n    let _useUrls = [].concat(urls);\n    // Shuffle the URLs\n    _shuffleArray(_useUrls);\n\n    const _matsSocketInstanceId = that.randomId(3);\n    let _lastMessageEnqueuedTimestamp = Date.now(); // Start by assuming that it was just used.\n    let _initialSessionEstablished_PerformanceNow = undefined;\n\n    // If true, we're currently already trying to get a WebSocket\n    let _webSocketConnecting = false;\n    // If NOT undefined, we have an open WebSocket available.\n    let _webSocket = undefined; // NOTE: It is set upon \"onopen\", and unset upon \"onclose\".\n    // If false, we should not accidentally try to reconnect or similar\n    let _matsSocketOpen = false; // NOTE: Set to true upon enqueuing of information-bearing message.\n\n    let _prePipeline = [];\n    let _pipeline = [];\n    let _terminators = Object.create(null);\n    let _endpoints = Object.create(null);\n    let _subscriptions = Object.create(null);\n\n    let _sessionClosedEventListeners = [];\n    let _connectionEventListeners = [];\n    let _subscriptionEventListeners = [];\n    let _pingPongListeners = [];\n    let _initiationProcessedEventListeners = [];\n    let _errorEventListeners = [];\n\n    let _state = ConnectionState.NO_SESSION;\n\n    let _helloSent = false;\n    let _forcePipelineProcessing = false;\n\n    let _authorization = undefined;\n    let _lastAuthorizationSentToServer = undefined;\n    let _lastDebugOptionsSentToServer = undefined;\n    let _expirationTimestamp = undefined;\n    let _roomForLatencyMillis = undefined;\n    let _authorizationExpiredCallback = undefined;\n\n    let _messageSequenceId = 0; // Increases for each SEND, REQUEST and REPLY\n\n    // When we've informed the app that we need auth, we do not need to do it again until it has set it.\n    let _authExpiredCallbackInvoked_EventType = undefined;\n\n    // Outstanding Pings\n    const _outstandingPings = Object.create(null);\n    // Outstanding Request \"futures\", i.e. the resolve() and reject() functions of the returned Promise.\n    const _outstandingRequests = Object.create(null);\n    // Outbox for SEND and REQUEST messages waiting for Received ACK/NACK\n    const _outboxInitiations = Object.create(null);\n    // .. \"guard object\" to avoid having to retransmit messages sent /before/ the WELCOME is received for the HELLO handshake\n    let _outboxInitiations_RetransmitGuard = this.randomCId(5);\n    // Outbox for REPLYs\n    const _outboxReplies = Object.create(null);\n    // The Inbox - to be able to catch double deliveries from Server\n    let _inbox = Object.create(null);\n\n    // :: STATS\n    // Last 100 PingPong instances\n    const _pings = [];\n    // Last X InitationProcessedEvent instances.\n    let _numberOfInitiationsKept = 10;\n    const _initiationProcessedEvents = [];\n\n    // ==== Register \"system\" endpoints\n\n    _endpoints['MatsSocket.renewAuth'] = function (messageEvent) {\n        return new Promise(function (resolve, _) {\n            // Immediately ask for new Authorization\n            _requestNewAuthorizationFromApp(\"MatsSocket.renewAuth was invoked\", new AuthorizationRequiredEvent(AuthorizationRequiredEventType.REAUTHENTICATE, undefined));\n            // .. then immediately resolve the server side request.\n            // This will add a message to the pipeline, but the pipeline will not be sent until new auth present.\n            // When the new auth comes in, the message will be sent, and resolve on the server side - and new auth\n            // is then \"magically\" present on the incoming-context.\n            resolve({});\n        });\n    };\n\n    // ==== Implementation ====\n\n    // Hack to get past Next's server-side compilation error: \"Module not found: Can't resolve 'ws'\".\n    function _importWsLazy() {\n        // Note: Never executed in the browser\n        return import(\n            /* webpackIgnore: true */\n            /* @vite-ignore */\n            // @ts-expect-error TS2307: (Cannot find module) it is up to the user to provide 'ws' when used in node.\n            'ws'\n            );\n    }\n\n    function _isNodeJs() {\n        // @ts-expect-error TS2580: (Cannot find name process): This is node-only, and this is the point.\n        const proc = process;\n        return proc && proc.versions && (typeof proc.versions.node !== 'undefined');\n    }\n\n    function _invokeLater(that) {\n        setTimeout(that, 0);\n    }\n\n    // https://stackoverflow.com/a/12646864/39334\n    function _shuffleArray(array) {\n        for (let i = array.length - 1; i > 0; i--) {\n            let j = Math.floor(Math.random() * (i + 1));\n            let temp = array[i];\n            array[i] = array[j];\n            array[j] = temp;\n        }\n    }\n\n    function _beforeunloadHandler() {\n        that.close(CLIENT_LIB_NAME_AND_VERSION + \" window.onbeforeunload close\");\n    }\n\n    function _registerBeforeunload() {\n        // ?: Is the self object an EventTarget (ie. window in a Browser context)\n        if (typeof (self) === 'object' && typeof (self.addEventListener) === 'function') {\n            // Yes -> Add \"onbeforeunload\" event listener to shut down the MatsSocket cleanly (closing session) when user navigates away from page.\n            self.addEventListener(\"beforeunload\", _beforeunloadHandler);\n        }\n    }\n\n    function _deregisterBeforeunload() {\n        if (typeof (self) === 'object' && typeof (self.addEventListener) === 'function') {\n            self.removeEventListener(\"beforeunload\", _beforeunloadHandler);\n        }\n    }\n\n    function _clearWebSocketStateAndInfrastructure() {\n        log(\"clearWebSocketStateAndInfrastructure(). Current WebSocket:\" + _webSocket);\n        // Stop pinger\n        _stopPinger();\n        // Remove beforeunload eventlistener\n        _deregisterBeforeunload();\n        // Reset Reconnect state vars\n        _resetReconnectStateVars();\n        // Make new RetransmitGuard - so that any previously \"guarded\" messages now will be retransmitted.\n        _outboxInitiations_RetransmitGuard = that.randomCId(5);\n        // :: Clear out _webSocket;\n        if (_webSocket) {\n            // We don't want the onclose callback invoked from this event that we initiated ourselves.\n            _webSocket.onclose = undefined;\n            // We don't want any messages either\n            _webSocket.onmessage = undefined;\n            // Also drop onerror for good measure.\n            _webSocket.onerror = undefined;\n        }\n        _webSocket = undefined;\n    }\n\n    function _closeSessionAndClearStateAndPipelineAndFuturesAndOutstandingMessages() {\n        log(\"closeSessionAndClearStateAndPipelineAndFuturesAndOutstandingMessages(). Current WebSocket:\" + _webSocket);\n        // Clear state\n        that.sessionId = undefined;\n        _state = ConnectionState.NO_SESSION;\n\n        _clearWebSocketStateAndInfrastructure();\n\n        // :: Clear pipeline\n        _pipeline.length = 0;\n\n        // Were now also NOT open, until a new message is enqueued.\n        _matsSocketOpen = false;\n\n        // :: NACK all outstanding messages\n        for (let cmid in _outboxInitiations) {\n            let initiation = _outboxInitiations[cmid];\n            delete _outboxInitiations[cmid];\n\n            if (that.logging) log(\"Close Session: Clearing outstanding Initiation [\" + initiation.envelope.t + \"] to [\" + initiation.envelope.eid + \"], cmid:[\" + initiation.envelope.cmid + \"], TraceId:[\" + initiation.envelope.tid + \"].\");\n            _completeReceived(ReceivedEventType.SESSION_CLOSED, initiation, Date.now());\n        }\n\n        // :: Reject all Requests\n        for (let cmid in _outstandingRequests) {\n            let request = _outstandingRequests[cmid];\n            delete _outstandingRequests[cmid];\n\n            if (that.logging) log(\"Close Session: Clearing outstanding REQUEST to [\" + request.envelope.eid + \"], cmid:[\" + request.envelope.cmid + \"], TraceId:[\" + request.envelope.tid + \"].\", request);\n            _completeRequest(request, MessageEventType.SESSION_CLOSED, {}, Date.now());\n        }\n    }\n\n    function _addInformationBearingEnvelopeToPipeline(envelope, traceId, initiation, request) {\n        // This is an information-bearing message, so now this MatsSocket instance is open.\n        _matsSocketOpen = true;\n        let now = Date.now();\n        let performanceNow = performance.now();\n\n        // Add the traceId to the message\n        envelope.tid = traceId;\n        // Add next message Sequence Id\n        let thisMessageSequenceId = _messageSequenceId++;\n        envelope.cmid = thisMessageSequenceId;\n\n        // :: Debug\n        // Set to either specific override, or global default.\n        initiation.debug = (initiation.debug !== undefined ? initiation.debug : (that.debug ? that.debug : 0));\n        // ?: Is the debug not 0?\n        if (initiation.debug !== 0) {\n            // -> Yes, not 0 - so send it in request.\n            envelope.rd = initiation.debug;\n        }\n        // ?: If the last transferred was /something/, while now it is 0, then we must send it over to reset\n        if ((initiation.debug === 0) && (_lastDebugOptionsSentToServer !== 0)) {\n            // -> Yes, was reset to 0 - so must send to server.\n            envelope.rd = 0;\n        }\n        // This is the last debug option the server knows.\n        _lastDebugOptionsSentToServer = initiation.debug;\n\n        // Update timestamp of last \"information bearing message\" sent.\n        _lastMessageEnqueuedTimestamp = now;\n\n        // Make lambda for what happens when it has been RECEIVED on server.\n        // Store the outgoing envelope\n        initiation.envelope = envelope;\n        // Store which \"retransmitGuard\" we were at when sending this (look up usage for why)\n        initiation.retransmitGuard = _outboxInitiations_RetransmitGuard;\n        // Start the attempt counter. We start at 1, as we immediately will enqueue this envelope..\n        initiation.attempt = 1;\n        // Store the sent timestamp.\n        initiation.sentTimestamp = now;\n        // Store performance.now for round-trip timing\n        initiation.messageSent_PerformanceNow = performanceNow;\n        // Make a (mental) slot for the messageAcked_PerformanceNow (set at ACK processing)\n        initiation.messageAcked_PerformanceNow = undefined;\n\n        // Initiation state created - store the outstanding Send or Request\n        _outboxInitiations[thisMessageSequenceId] = initiation;\n\n        // ?: Do we have a request?\n        if (request) {\n            // -> Yes, this is a REQUEST!\n            // Store the initiation\n            request.initiation = initiation;\n            // Store the outgoing envelope (could have gotten it through request.initiation, but too much hassle too many places)\n            request.envelope = envelope;\n\n            // Make timeouter\n            request.timeoutId = setTimeout(function () {\n                // :: The Request timeout was hit.\n                let performanceNow = performance.now();\n                if (that.logging) log(\"TIMEOUT! Request with TraceId:[\" + request.envelope.tid + \"], cmid:[\" + request.envelope.cmid + \"] overshot timeout [\" + (performanceNow - request.initiation.messageSent_PerformanceNow) + \" ms of \" + request.timeout + \"]\");\n                // Check if we've gotten the ACK/NACK\n                let initiation = _outboxInitiations[thisMessageSequenceId];\n                // ?: Was the initiation still present?\n                if (initiation) {\n                    // -> Yes, still present, so we have not gotten the ACK/NACK from Server yet, thus NACK it with ReceivedEventType.TIMEOUT\n                    delete _outboxInitiations[thisMessageSequenceId];\n                    _completeReceived(ReceivedEventType.TIMEOUT, initiation, Date.now());\n                }\n\n                // :: Complete the Request with MessageEventType.TIMEOUT\n\n                /*\n                 * NOTICE!! HACK-ALERT! The ordering of events wrt. Requests is as such:\n                 * 1. ReceivedEvent (receivedCallback for requests, and Received-Promise for requestReplyTo)\n                 * 2. InitiationProcessedEvent stored on matsSocket.initiations\n                 * 3. InitiationProcessedEvent listeners\n                 * 4. MessageEvent (Reply-Promise for requests, Terminator callbacks for requestReplyTo)\n                 *\n                 * WITH a requestReplyTo, the ReceivedEvent becomes async in nature, since requestReplyTo returns\n                 * a Promise<ReceivedEvent>. Also, with a requestReplyTo, the completing of the requestReplyTo is\n                 * then done on a Terminator, using its specified callbacks - and this is done using\n                 * setTimeout(.., 0) to \"emulate\" the same async-ness as a Reply-Promise with ordinary requests.\n                 * However, the timing between the ReceivedEvent and InitiationProcessedEvent then becomes\n                 * rather shaky. Therefore, IF the initiation is still in place (ReceivedEvent not yet issued),\n                 * AND this is a requestReplyTo, THEN we delay the completion of the Request (i.e. issue\n                 * InitiationProcessedEvent and MessageEvent) to be more certain that the ReceivedEvent is\n                 * processed before the rest.\n                 */\n                // ?: Did we still have the initiation in place, AND this is a requestReplyTo?\n                if (initiation && request.replyToTerminatorId) {\n                    // -> Yes, the initiation was still in place (i.e. ReceivedEvent not issued), and this was\n                    // a requestReplyTo:\n                    // Therefore we delay the entire completion of the request (InitiationProcessedEvent and\n                    // MessageEvent), to be sure that they happen AFTER the ReceivedEvent issued above.\n                    setTimeout(function () {\n                        _completeRequest(request, MessageEventType.TIMEOUT, {}, Date.now());\n                    }, 50);\n                } else {\n                    // -> No, either the initiation was already gone (ReceivedEvent already issued), OR it was\n                    // not a requestReplyTo:\n                    // Therefore, we run the completion right away (InitiationProcessedEvent is sync, while\n                    // MessageEvent is a Promise settling).\n                    _completeRequest(request, MessageEventType.TIMEOUT, {}, Date.now());\n                }\n            }, request.timeout);\n\n            // Request state created - store this outstanding Request.\n            _outstandingRequests[thisMessageSequenceId] = request;\n        }\n\n        _addEnvelopeToPipeline_EvaluatePipelineLater(envelope);\n    }\n\n    /**\n     * Unconditionally adds the supplied envelope to the pipeline, and then evaluates the pipeline,\n     * invokeLater-style so as to get \"auth-pipelining\". Use flush() to get sync send.\n     */\n    function _addEnvelopeToPipeline_EvaluatePipelineLater(envelope, prePipeline = false) {\n        // ?: Should we add it to the pre-pipeline, or the ordinary?\n        if (prePipeline) {\n            // -> To pre-pipeline\n            if (that.logging) log(\"ENQUEUE: Envelope of type [\" + envelope.t + \"] enqueued to PRE-pipeline: \" + JSON.stringify(envelope));\n            _prePipeline.push(envelope);\n        } else {\n            // -> To ordinary pipeline.\n            if (that.logging) log(\"ENQUEUE: Envelope of type [\" + envelope.t + \"] enqueued to pipeline: \" + JSON.stringify(envelope));\n            _pipeline.push(envelope);\n        }\n        // Perform \"auto-pipelining\", by waiting a minimal amount of time before actually sending.\n        _evaluatePipelineLater();\n    }\n\n    let _evaluatePipelineLater_timeoutId = undefined;\n\n    function _evaluatePipelineLater() {\n        if (_evaluatePipelineLater_timeoutId) {\n            clearTimeout(_evaluatePipelineLater_timeoutId);\n        }\n        _evaluatePipelineLater_timeoutId = setTimeout(function () {\n            _evaluatePipelineLater_timeoutId = undefined;\n            _evaluatePipelineSend();\n        }, 10);\n    }\n\n    /**\n     * Sends pipelined messages\n     */\n    function _evaluatePipelineSend() {\n        // ?: Are there any messages in pipeline or PRE-pipeline,\n        // or should we force pipeline processing (either to get HELLO, SUB or AUTH over)\n        if ((_pipeline.length === 0) && (_prePipeline.length === 0) && !_forcePipelineProcessing) {\n            // -> No, no message in pipeline, and we should not force processing to get HELLO or AUTH over\n            // Nothing to do, drop out.\n            return;\n        }\n        // ?: Is the MatsSocket open yet? (I.e. an information-bearing message has been enqueued)\n        if (!_matsSocketOpen) {\n            // -> No, so ignore this invocation - come back when there is something to send!\n            log(\"evaluatePipelineSend(), but MatsSocket is not open - ignoring.\");\n            return;\n        }\n        // ?: Do we have authorization?!\n        if (_authorization === undefined) {\n            // -> No, authorization not present.\n            _requestNewAuthorizationFromApp(\"Authorization not present\", new AuthorizationRequiredEvent(AuthorizationRequiredEventType.NOT_PRESENT, undefined));\n            return;\n        }\n        // ?: Check whether we have expired authorization\n        if ((_expirationTimestamp !== undefined) && (_expirationTimestamp !== -1)\n            && ((_expirationTimestamp - _roomForLatencyMillis) < Date.now())) {\n            // -> Yes, authorization is expired.\n            _requestNewAuthorizationFromApp(\"Authorization is expired\", new AuthorizationRequiredEvent(AuthorizationRequiredEventType.EXPIRED, _expirationTimestamp));\n            return;\n        }\n        // ?: Check that we are not already waiting for new auth\n        // (This is needed here since we might actually have valid authentication, but server has still asked us, via \"REAUTH\", to get new)\n        if (_authExpiredCallbackInvoked_EventType) {\n            log(\"We have asked app for new authorization, and still waiting for it.\");\n            return;\n        }\n\n        // ----- We have good authentication, and should send pipeline.\n\n        // ?: Are we trying to open websocket?\n        if (_webSocketConnecting) {\n            log(\"evaluatePipelineSend(): WebSocket is currently connecting. Cannot send yet.\");\n            // -> Yes, so then the socket is not open yet, but we are in the process.\n            // Return now, as opening is async. When the socket opens, it will re-run 'evaluatePipelineSend()'.\n            return;\n        }\n\n        // ?: Is the WebSocket present?\n        if (_webSocket === undefined) {\n            log(\"evaluatePipelineSend(): WebSocket is not present, so initiate creation. Cannot send yet.\");\n            // -> No, so go get it.\n            _initiateWebSocketCreation();\n            // Returning now, as opening is async. When the socket opens, it will re-run 'evaluatePipelineSend()'.\n            return;\n        }\n\n        // ----- WebSocket is open, so send any outstanding messages!!\n\n        // ?: Have we sent HELLO?\n        if (!_helloSent) {\n            // -> No, HELLO not sent, so we create it now (auth is present, check above)\n            let helloMessage = {\n                t: MessageType.HELLO,\n                clv: CLIENT_LIB_NAME_AND_VERSION + \"; User-Agent: \" + userAgent,\n                ts: Date.now(),\n                an: appName,\n                av: appVersion,\n                auth: _authorization,  // This is guaranteed to be in place and valid, see above\n                cid: that.randomId(10)\n            };\n            // ?: Have we requested a reconnect?\n            if (that.sessionId !== undefined) {\n                log(\"HELLO not send, adding to pre-pipeline. HELLO (\\\"Reconnect\\\") to MatsSocketSessionId:[\" + that.sessionId + \"]\");\n                // -> Evidently yes, so add the requested reconnect-to-sessionId.\n                helloMessage.sid = that.sessionId;\n            } else {\n                // -> We want a new session (which is default anyway)\n                log(\"HELLO not sent, adding to pre-pipeline. HELLO (\\\"New\\\"), we will get assigned a MatsSocketSessionId upon WELCOME.\");\n            }\n            // Add the HELLO to the prePipeline\n            _prePipeline.unshift(helloMessage);\n            // We will now have sent the HELLO, so do not send it again.\n            _helloSent = true;\n            // We've sent the current auth\n            _lastAuthorizationSentToServer = _authorization;\n\n            // :: Handle subscriptions\n            for (let topicId in _subscriptions) {\n                let subs = _subscriptions[topicId];\n                // ?: Do we have subscribers, but not sent to server?\n                if ((subs.listeners.length > 0) && (!subs.subscriptionSentToServer)) {\n                    // -> Yes, so we need to subscribe\n                    _prePipeline.push({\n                        t: MessageType.SUB,\n                        eid: topicId,\n                        smid: subs.lastSmid\n                    });\n                }\n                // ?: Do we NOT have subscribers, but sub is sent to Server?\n                if ((subs.listeners.length === 0) && (subs.subscriptionSentToServer)) {\n                    // -> Yes, so we need to unsubscribe - and delete the subscription\n                    _prePipeline.push({\n                        t: MessageType.UNSUB,\n                        eid: topicId\n                    });\n                    // Delete this local subscription.\n                    delete _subscriptions[topicId];\n                }\n            }\n        }\n\n        // ?: Have we sent HELLO, i.e. session is \"active\", but the authorization has changed since last we sent over authorization?\n        if (_helloSent && (_lastAuthorizationSentToServer !== _authorization)) {\n            // -> Yes, it has changed, so add it to some envelope - either last in pipeline, or if empty pipe, then make an AUTH message.\n            if (_pipeline.length > 0) {\n                let lastEnvelope = _pipeline[_pipeline.length - 1];\n                if (that.logging) log(\"Authorization has changed, and there is a message in pipeline of type [\" + lastEnvelope.t + \"], so so we add 'auth' to it.\");\n                lastEnvelope.auth = _authorization;\n            } else {\n                if (that.logging) log(\"Authorization has changed, but there is no message in pipeline, so we add an AUTH message now.\");\n                _pipeline.push({t: MessageType.AUTH, auth: _authorization});\n            }\n            // The current authorization is now sent\n            _lastAuthorizationSentToServer = _authorization;\n        }\n\n        // We're now doing a round of pipeline processing, so turn of forcing.\n        _forcePipelineProcessing = false;\n\n        // :: Send PRE-pipeline messages, if there are any\n        // (Before the HELLO is sent and sessionId is established, the max size of message is low on the server)\n        if (_prePipeline.length > 0) {\n            if (that.logging) log(\"Flushing prePipeline of [\" + _prePipeline.length + \"] messages: \" + JSON.stringify(_prePipeline));\n            _webSocket.send(JSON.stringify(_prePipeline));\n            // Clear prePipeline\n            _prePipeline.length = 0;\n        }\n        // :: Send any pipelined messages.\n        if (_pipeline.length > 0) {\n            if (that.logging) log(\"Flushing pipeline of [\" + _pipeline.length + \"] messages: \" + JSON.stringify(_pipeline));\n            _webSocket.send(JSON.stringify(_pipeline));\n            // Clear pipeline\n            _pipeline.length = 0;\n        }\n    }\n\n    function _requestNewAuthorizationFromApp(what, event) {\n        // ?: Have we already asked app for new auth?\n        if (_authExpiredCallbackInvoked_EventType) {\n            // -> Yes, so just return.\n            log(what + \", but we've already asked app for it due to: [\" + _authExpiredCallbackInvoked_EventType + \"].\");\n            return;\n        }\n        // E-> No, not asked for auth - so do it.\n        log(what + \". Will not send pipeline until gotten. Invoking 'authorizationExpiredCallback', type:[\" + event.type + \"].\");\n        // We will have asked for auth after this.\n        _authExpiredCallbackInvoked_EventType = event.type;\n        // Assert that we have callback\n        if (!_authorizationExpiredCallback) {\n            // -> We do not have callback! This is actually disaster.\n            let reason = \"From Client: Need new authorization, but missing 'authorizationExpiredCallback'. This is fatal, cannot continue.\";\n            error(\"missingauthcallback\", reason);\n            // !! We need to close down\n            if (_webSocket) {\n                // -> Yes, so close WebSocket with MatsSocket-specific CloseCode CLOSE_SESSION 4000.\n                log(\" \\\\-> WebSocket is open, so we perform in-band Session Close by closing the WebSocket with MatsSocketCloseCode.CLOSE_SESSION (4000).\");\n                // Perform the close\n                _webSocket.close(MatsSocketCloseCodes.CLOSE_SESSION, reason);\n            }\n            let outstandingInitiations = Object.keys(_outboxInitiations).length;\n            // Close Session and clear all state of this MatsSocket.\n            _closeSessionAndClearStateAndPipelineAndFuturesAndOutstandingMessages();\n            // Notify SessionClosedEventListeners - with a fake CloseEvent\n            _notifySessionClosedEventListeners({\n                type: \"close\",\n                code: MatsSocketCloseCodes.VIOLATED_POLICY,\n                codeName: \"VIOLATED_POLICY\",\n                reason: reason,\n                outstandingInitiations: outstandingInitiations\n            });\n\n            return;\n        }\n        // E-> We do have 'authorizationExpiredCallback', so ask app for new auth\n        _authorizationExpiredCallback(event);\n    }\n\n    let _connectionAttempt = 0; // A counter of how many times a connection attempt has been performed, starts at 0th attempt.\n\n    let _urlIndexCurrentlyConnecting = 0; // Cycles through the URLs\n    let _connectionAttemptRound = 0; // When cycled one time through URLs, this increases.\n    let _currentWebSocketUrl = undefined;\n\n    let _connectionTimeoutBase = 500; // Base timout, milliseconds. Doubles, up to max defined below.\n    let _connectionTimeoutMinIfSingleUrl = 5000; // Min timeout if single-URL configured, milliseconds.\n    // Based on whether there is multiple URLs, or just a single one, we choose the short \"timeout base\", or a longer one, as minimum.\n    let _connectionTimeoutMin = _useUrls.length > 1 ? _connectionTimeoutBase : _connectionTimeoutMinIfSingleUrl;\n    let _connectionTimeoutMax = 15000; // Milliseconds max between connection attempts.\n\n    function _maxConnectionAttempts() {\n        // ?: Have maxConnectionAttempts been set?\n        if (that.maxConnectionAttempts !== undefined) {\n            // -> Yes, so use this.\n            return that.maxConnectionAttempts;\n        }\n        return that.sessionId !== null\n            ? 5760 // The default should be about a day..! 15 sec per attempt: 5760*15 sec = 60*60*24 sec\n            : 60; // Way fewer attempts if no session ID is present.\n    }\n\n    function _increaseReconnectStateVars() {\n        _connectionAttempt++;\n        _urlIndexCurrentlyConnecting++;\n        if (_urlIndexCurrentlyConnecting >= _useUrls.length) {\n            _urlIndexCurrentlyConnecting = 0;\n            _connectionAttemptRound++;\n        }\n        _currentWebSocketUrl = _useUrls[_urlIndexCurrentlyConnecting];\n        log(\"## _increaseReconnectStateVars(): round:[\" + _connectionAttemptRound + \"], urlIndex:[\" + _urlIndexCurrentlyConnecting + \"] = \" + _currentWebSocketUrl);\n    }\n\n    function _resetReconnectStateVars() {\n        _connectionAttempt = 0;\n        _urlIndexCurrentlyConnecting = 0;\n        _connectionAttemptRound = 0;\n        _currentWebSocketUrl = _useUrls[_urlIndexCurrentlyConnecting];\n        log(\"## _resetReconnectStateVars(): round:[\" + _connectionAttemptRound + \"], urlIndex:[\" + _urlIndexCurrentlyConnecting + \"] = \" + _currentWebSocketUrl);\n    }\n\n    // .. Invoke resetConnectStateVars() right away to get URL set.\n    _resetReconnectStateVars();\n\n    function _secondsTenths(milliseconds) {\n        // Rounds to tenth of second, e.g. 2730 -> 2.7.\n        return Math.round(milliseconds / 100) / 10;\n    }\n\n    function _updateStateAndNotifyConnectionEventListeners(connectionEvent) {\n        // ?: Should we log? Logging is on, AND (either NOT CountDown, OR CountDown == initialSeconds, OR Countdown == whole second).\n        if (that.logging && ((connectionEvent.type !== ConnectionEventType.COUNTDOWN)\n            || (connectionEvent.countdownSeconds === connectionEvent.timeoutSeconds)\n            || (Math.round(connectionEvent.countdownSeconds) === connectionEvent.countdownSeconds))) {\n            log(\"Sending ConnectionEvent to listeners\", connectionEvent);\n        }\n        // ?: Is this a state?\n        let result = Object.keys(ConnectionState).filter(function (key) {\n            return ConnectionState[key] === connectionEvent.type;\n        });\n        if (result.length === 1) {\n            // -> Yes, this is a state - so update the state..!\n            _state = ConnectionState[result[0]];\n            log(\"The ConnectionEventType [\" + result[0] + \"] is also a ConnectionState - setting MatsSocket state [\" + _state + \"].\");\n        }\n\n        // :: Notify all ConnectionEvent listeners.\n        for (let i = 0; i < _connectionEventListeners.length; i++) {\n            try {\n                _connectionEventListeners[i](connectionEvent);\n            } catch (err) {\n                error(\"notify ConnectionEvent listeners\", \"Caught error when notifying one of the [\" + _connectionEventListeners.length + \"] ConnectionEvent listeners about [\" + connectionEvent.type + \"].\", err);\n            }\n        }\n    }\n\n    function _notifySessionClosedEventListeners(closeEvent) {\n        if (that.logging) log(\"Sending SessionClosedEvent to listeners\", closeEvent);\n        for (let i = 0; i < _sessionClosedEventListeners.length; i++) {\n            try {\n                _sessionClosedEventListeners[i](closeEvent);\n            } catch (err) {\n                error(\"notify SessionClosedEvent listeners\", \"Caught error when notifying one of the [\" + _sessionClosedEventListeners.length + \"] SessionClosedEvent listeners.\", err);\n            }\n        }\n    }\n\n    function _initiateWebSocketCreation() {\n        // ?: Assert that we do not have the WebSocket already\n        if (_webSocket !== undefined) {\n            // -> Damn, we did have a WebSocket. Why are we here?!\n            throw (new Error(\"Should not be here, as WebSocket is already in place!\"));\n        }\n        // ?: Verify that we are actually open - we should not be trying to connect otherwise.\n        if (!_matsSocketOpen) {\n            // -> We've been asynchronously closed - bail out from opening WebSocket\n            throw (new Error(\"The MatsSocket instance is closed, so we should not open WebSocket\"));\n        }\n\n        // ----- We do not already have a WebSocket and the MatsSocket instance is Open!\n\n        // :: First need to check whether we have OK Authorization - if not, we must terminate entire connection procedure, ask for new, and start over.\n        // Note: The start-over will happen when new auth comes in, _evaluatePipelineSend(..) is invoked, and there is no WebSocket there.\n        // ?: Check whether we have expired authorization\n        if ((_expirationTimestamp !== undefined) && (_expirationTimestamp !== -1)\n            && ((_expirationTimestamp - _roomForLatencyMillis) < Date.now())) {\n            // -> Yes, authorization is expired.\n            log(\"InitiateWebSocketCreation: Authorization is expired, we need new to continue.\");\n            // We are not connecting anymore\n            _webSocketConnecting = false;\n            // Request new auth\n            _requestNewAuthorizationFromApp(\"Authorization is expired\", new AuthorizationRequiredEvent(AuthorizationRequiredEventType.EXPIRED, _expirationTimestamp));\n            return;\n        }\n\n        // ------ We have a valid, unexpired authorization token ready to use for connection\n\n        if (! webSocketFactory) {\n            if (_nodeJsTryingToImportWebSocketModule) {\n                log(\"InitiateWebSocketCreation: Missing matsSocketFactory, but import in progress! Wait for result of import attempt.\")\n                _nodeJsCallbackOnceWebSocketModuleResolved = function() {\n                    log(\"InitiateWebSocketCreation: Was missing matsSocketFactory, but matsSocketFactory should now be in place. Attempting again.\")\n                    _initiateWebSocketCreation();\n                }\n                return;\n            }\n            else {\n                error(\"Missing WebSocket implementation\", \"InitiateWebSocketCreation: Missing matsSocketFactory, and there is no attempt in progress to get it. Fatal.\")\n                throw new Error(\"Missing matsSocketFactory!\");\n            }\n        }\n\n        // :: We are currently trying to connect! (This will be set to true repeatedly while in the process of opening)\n        _webSocketConnecting = true;\n\n        // Timeout: LESSER of \"max\" and \"timeoutBase * (2^round)\", which should lead to timeoutBase x1, x2, x4, x8 - but capped at max.\n        // .. but at least '_connectionTimeoutMin', which also handles the special case of longer minimum if just 1 URL.\n        // Shortcut exponential if we guaranteed would be at max, to avoid pow-overflow\n        let timeout = _connectionAttemptRound > 10\n            ? _connectionTimeoutMax\n            : Math.max(_connectionTimeoutMin, Math.min(_connectionTimeoutMax, _connectionTimeoutBase * Math.pow(2, _connectionAttemptRound)));\n        let currentCountdownTargetTimestamp = Date.now();\n        let targetTimeoutTimestamp = currentCountdownTargetTimestamp + timeout;\n        let secondsLeft = function () {\n            return Math.round(((targetTimeoutTimestamp - Date.now()) / 100)) / 10;\n        };\n\n        // About to create WebSocket, so notify our listeners about this.\n        _updateStateAndNotifyConnectionEventListeners(new ConnectionEvent(ConnectionEventType.CONNECTING, _currentWebSocketUrl, undefined, _secondsTenths(timeout), secondsLeft(), _connectionAttempt));\n\n        let preConnectOperationAbortFunction = undefined;\n        let websocketAttempt = undefined;\n        let countdownId = undefined;\n\n        /*\n         * Make a \"connection timeout\" countdown,\n         * This will re-invoke itself every 100 ms to create the COUNTDOWN events - until either cancelled by connect going through,\n         *  or it reaches targetTimeoutTimestamp (timeout), where it aborts the attempt, bumps the state vars,\n         *  and then re-runs the '_initiateWebSocketCreation' method.\n         */\n        function w_countDownTimer() {\n            // ?: Assert that we're still open\n            if (!_matsSocketOpen) {\n                log(\"When doing countdown rounds, we realize that this MatsSocket instance is closed! - stopping right here.\");\n                w_abortAttempt();\n                return;\n            }\n            // :: Find next target\n            while (currentCountdownTargetTimestamp <= Date.now()) {\n                currentCountdownTargetTimestamp += 100;\n            }\n            // ?: Have we now hit or overshot the target?\n            if (currentCountdownTargetTimestamp >= targetTimeoutTimestamp) {\n                // -> Yes, we've hit target, so this did not work out - abort attempt, bump state vars, and reschedule the entire show.\n                w_connectTimeout_AbortAttemptAndReschedule();\n            } else {\n                // -> No, we've NOT hit timeout-target, so sleep till next countdown-target, where we re-invoke ourselves (this w_countDownTimer())\n                // Notify ConnectionEvent listeners about this COUNTDOWN event.\n                _updateStateAndNotifyConnectionEventListeners(new ConnectionEvent(ConnectionEventType.COUNTDOWN, _currentWebSocketUrl, undefined, _secondsTenths(timeout), secondsLeft(), _connectionAttempt));\n                let sleep = Math.max(5, currentCountdownTargetTimestamp - Date.now());\n                countdownId = setTimeout(function () {\n                    w_countDownTimer();\n                }, sleep);\n            }\n        }\n\n        function w_abortAttempt() {\n            // ?: Are we in progress with the PreConnectionOperation?\n            if (preConnectOperationAbortFunction) {\n                // -> Evidently still doing PreConnectionRequest - kill it.\n                log(\"  \\\\- Within PreConnectionOperation phase - invoking preConnectOperationFunction's abort() function.\");\n                // null out the 'preConnectOperationAbortFunction', as this is used for indication for whether the preConnectRequestPromise's resolve&reject should act.\n                let abortFunctionTemp = preConnectOperationAbortFunction;\n                // Clear out\n                preConnectOperationAbortFunction = undefined;\n                // Invoke the abort.\n                abortFunctionTemp();\n            }\n\n            // ?: Are we in progress with opening WebSocket?\n            if (websocketAttempt) {\n                // -> Evidently still trying to connect WebSocket - kill it.\n                log(\"  \\\\- Within WebSocket connect phase - clearing handlers and invoking webSocket.close().\");\n                websocketAttempt.onopen = undefined;\n                websocketAttempt.onerror = function (closeEvent) {\n                    if (that.logging) log(\"!! websocketAttempt.onerror: Forced close by timeout, instanceId:[\" + closeEvent.target.webSocketInstanceId + \"]\", closeEvent);\n                };\n                websocketAttempt.onclose = function (closeEvent) {\n                    if (that.logging) log(\"!! websocketAttempt.onclose: Forced close by timeout, instanceId:[\" + closeEvent.target.webSocketInstanceId + \"]\", closeEvent);\n                };\n                // Close the current WebSocket connection attempt (i.e. abort connect if still trying).\n                websocketAttempt.close(MatsSocketCloseCodes.CLOSE_SESSION, \"WebSocket connect aborted\");\n                // Clear out the attempt\n                websocketAttempt = undefined;\n            }\n        }\n\n        function w_defaultXhrPromiseFactory(params) {\n            let xhr = new XMLHttpRequest();\n            let abort = function () {\n                xhr.abort();\n            };\n            let preConnectPromise = new Promise(function (resolve, reject) {\n                    xhr.addEventListener(\"loadend\", function (event) {\n                        // Get XHR's status\n                        let status = xhr.status;\n                        // ?: Was it a GOOD return?\n                        if ((status === 200) || (status === 202) || (status === 204)) {\n                            // -> Yes, it was good - supplying the status code\n                            resolve(status);\n                        } else {\n                            // -> Not, it was BAD - supplying the status code\n                            reject(status);\n                        }\n                    });\n                    xhr.withCredentials = true;\n                    // Note: 'params.directUrl' is only relevant for this internal code, look at the usage of this method.\n                    xhr.open(\"GET\", (params.directUrl ? params.directUrl : params.webSocketUrl.replace(\"ws\", \"http\")));\n                    xhr.setRequestHeader(\"Authorization\", params.authorization);\n                    xhr.send();\n                }\n            );\n            return [abort, preConnectPromise];\n        }\n\n        function w_attemptPreConnectionOperation() {\n            // :: Decide based on type of 'preconnectoperation' how to do the .. PreConnectOperation..!\n            let abortAndPromise;\n            let params = {\n                webSocketUrl: _currentWebSocketUrl,\n                authorization: _authorization\n            };\n            if (typeof (that.preconnectoperation) === 'function') {\n                // -> Function, so invoke it, with contract-specified params object containing 'webSocketUrl'.\n                abortAndPromise = that.preconnectoperation(params);\n            } else if (typeof (that.preconnectoperation) === 'string') {\n                // -> String, so invoke our default promise factory with special 'directUrl' property, which overrides 'webSocketUrl'.\n                params.directUrl = that.preconnectoperation;\n                abortAndPromise = w_defaultXhrPromiseFactory(params);\n            } else {\n                // -> Truthy, so invoke our default promise factory with params object containing 'webSocketUrl'.\n                abortAndPromise = w_defaultXhrPromiseFactory(params);\n            }\n\n            // Deconstruct the return\n            preConnectOperationAbortFunction = abortAndPromise[0];\n            let preConnectRequestPromise = abortAndPromise[1];\n\n            // Handle the resolve or reject from the preConnectionOperation\n            preConnectRequestPromise\n                .then(function (statusMessage) {\n                    // -> Yes, good return - so go onto next phase, which is creating the WebSocket\n                    // ?: Are we still trying to perform the preConnectOperation? (not timed out)\n                    if (preConnectOperationAbortFunction) {\n                        // -> Yes, not timed out, so then we're good to go with the next phase\n                        log(\"PreConnectionOperation went OK [\" + statusMessage + \"], going on to create WebSocket.\");\n                        // Create the WebSocket\n                        w_attemptWebSocket();\n                    }\n                })\n                .catch(function (statusMessage) {\n                    // -> No, bad return - so go for next\n                    // ?: Are we still trying to perform the preConnectOperation? (not timed out)\n                    if (preConnectOperationAbortFunction) {\n                        // -> Yes, not timed out, so then we'll notify about our failed attempt\n                        log(\"PreConnectionOperation failed [\" + statusMessage + \"] - retrying.\");\n                        // Go for next retry\n                        w_connectFailed_RetryOrWaitForTimeout();\n                    }\n                });\n        }\n\n        function w_attemptWebSocket() {\n            // We're not trying to perform the preConnectOperation anymore, so clear it.\n            preConnectOperationAbortFunction = undefined;\n            // ?: Assert that we're not already trying to make a WebSocket\n            if (websocketAttempt) {\n                throw Error(\"When going for attempt on creating WebSocket, there was already an attempt in place.\");\n            }\n\n            // ?: Assert that we're still open\n            if (!_matsSocketOpen) {\n                log(\"Upon WebSocket.open, we realize that this MatsSocket instance is closed! - stopping right here.\");\n                w_abortAttempt();\n                return;\n            }\n\n            // :: Actually create the WebSocket instance\n            let url = _currentWebSocketUrl + (that.preconnectoperation ? \"?preconnect=true\" : \"\");\n            const webSocketInstanceId = that.randomId(6);\n            if (that.logging) log(\"INSTANTIATING new WebSocket(\\\"\" + url + \"\\\", \\\"matssocket\\\") - InstanceId:[\" + webSocketInstanceId + \"]\");\n            websocketAttempt = webSocketFactory(url, \"matssocket\");\n            websocketAttempt.webSocketInstanceId = webSocketInstanceId;\n\n            // :: Add the handlers for this \"trying to acquire\" procedure.\n\n            // Note: On failure, some environments will call error, then close, and some just error. We set up so that we\n            // handle any order, and both, by removing handlers after getting the first.\n\n            // Error: Log, updateState/notifyListeners, and start retry/wait.\n            websocketAttempt.onerror = function (errorEvent) {\n                if (that.logging) log(\"Create WebSocket: error. InstanceId:[\" + errorEvent.target.webSocketInstanceId + \"]\", errorEvent);\n                // Some environments will call onClose afterward, and some not. We'll remove all handlers to be sure.\n                websocketAttempt.onerror = undefined;\n                websocketAttempt.onclose = undefined;\n                websocketAttempt.onopen = undefined;\n                _updateStateAndNotifyConnectionEventListeners(new ConnectionEvent(ConnectionEventType.WAITING, _currentWebSocketUrl, errorEvent, _secondsTenths(timeout), secondsLeft(), _connectionAttempt));\n                w_connectFailed_RetryOrWaitForTimeout();\n            };\n\n            // Close: .. same as Error\n            websocketAttempt.onclose = function (closeEvent) {\n                if (that.logging) log(\"Create WebSocket: close. InstanceId:[\" + closeEvent.target.webSocketInstanceId + \"], Code:\" + closeEvent.code + \", Reason:\" + closeEvent.reason, closeEvent);\n                // We'll remove all handlers now, since any other event would be bad at this time.\n                websocketAttempt.onerror = undefined;\n                websocketAttempt.onclose = undefined;\n                websocketAttempt.onopen = undefined;\n                _updateStateAndNotifyConnectionEventListeners(new ConnectionEvent(ConnectionEventType.WAITING, _currentWebSocketUrl, closeEvent, _secondsTenths(timeout), secondsLeft(), _connectionAttempt));\n                w_connectFailed_RetryOrWaitForTimeout();\n            };\n\n            // Open: Success! Cancel countdown timer, and set WebSocket in MatsSocket, clear flags, set proper WebSocket event handlers including onMessage.\n            websocketAttempt.onopen = function (openEvent) {\n                // First and foremost: Cancel the \"connection timeout\" thingy - we're done!\n                clearTimeout(countdownId);\n\n                // ?: Assert that we're still open\n                if (!_matsSocketOpen) {\n                    log(\"Upon WebSocket.open, we realize that this MatsSocket instance is closed! - stopping right here.\");\n                    w_abortAttempt();\n                    return;\n                }\n\n                log(\"Create WebSocket: opened! InstanceId:[\" + openEvent.target.webSocketInstanceId + \"].\", openEvent);\n\n                // Store our brand new, soon-ready-for-business WebSocket.\n                _webSocket = websocketAttempt;\n                // We're not /trying/ to connect anymore.. (Because, *hell yeah!*, we /have/ connected!!)\n                _webSocketConnecting = false;\n                // Since we've just established this WebSocket, we have obviously not sent HELLO yet.\n                _helloSent = false;\n\n                // Set our proper handlers\n                _webSocket.onopen = undefined; // No need for 'onopen', it is already open. Also, node.js evidently immediately fires it again, even though it was already fired.\n                _webSocket.onerror = _onerror;\n                _webSocket.onclose = _onclose;\n                _webSocket.onmessage = _onmessage;\n\n                _registerBeforeunload();\n\n                _updateStateAndNotifyConnectionEventListeners(new ConnectionEvent(ConnectionEventType.CONNECTED, _currentWebSocketUrl, openEvent, _secondsTenths(timeout), secondsLeft(), _connectionAttempt));\n\n                // Fire off any waiting messages, next tick\n                _invokeLater(function () {\n                    log(\"WebSocket is open! Running evaluatePipelineSend() to start HELLO/WELCOME handshake.\");\n                    _evaluatePipelineSend();\n                });\n            };\n        }\n\n        function w_connectFailed_RetryOrWaitForTimeout() {\n            // :: Attempt failed, either immediate retry or wait for timeout\n            log(\"Create WebSocket: Attempt failed, URL [\" + _currentWebSocketUrl + \"] didn't work out.\");\n            // ?: Assert that we're still open\n            if (!_matsSocketOpen) {\n                log(\"After failed attempt, we realize that this MatsSocket instance is closed! - stopping right here.\");\n                // Abort connecting\n                w_abortAttempt();\n                // Cancel the \"reconnect scheduler\" thingy.\n                clearTimeout(countdownId);\n                return;\n            }\n            // ?: Have we had WAY too many connection attempts?\n            if (_connectionAttempt >= _maxConnectionAttempts()) {\n                // -> Yes, too much fails or errors - stop nagging server.\n                let reason = \"Trying to create WebSocket: Too many consecutive connection attempts [\" + _connectionAttempt + \"]\";\n                error(\"too many connection attempts\", reason);\n                // Hold on to how many outstanding initiations there are now\n                let outstandingInitiations = Object.keys(_outboxInitiations).length;\n                // Abort connecting\n                w_abortAttempt();\n                // Cancel the \"reconnect scheduler\" thingy.\n                clearTimeout(countdownId);\n                // Close Session\n                _closeSessionAndClearStateAndPipelineAndFuturesAndOutstandingMessages();\n                // Notify SessionClosedEventListeners - with a fake CloseEvent\n                _notifySessionClosedEventListeners({\n                    type: \"close\",\n                    code: MatsSocketCloseCodes.VIOLATED_POLICY,\n                    codeName: \"VIOLATED_POLICY\",\n                    reason: reason,\n                    outstandingInitiations: outstandingInitiations\n                });\n                return;\n            }\n            // Clear out the attempt instances\n            preConnectOperationAbortFunction = undefined;\n            websocketAttempt = undefined;\n            // ?: If we are on the FIRST (0th) round of trying out the different URLs, then immediately try the next\n            // .. But only if there are multiple URLs configured.\n            if ((_connectionAttemptRound === 0) && (_useUrls.length > 1)) {\n                // -> YES, we are on the 0th round of connection attempts, and there are multiple URLs, so immediately try the next.\n                // Cancel the \"reconnect scheduler\" thingy.\n                clearTimeout(countdownId);\n\n                // Invoke on next tick: Bump state vars, re-run _initiateWebSocketCreation\n                _invokeLater(function () {\n                    _increaseReconnectStateVars();\n                    _initiateWebSocketCreation();\n                });\n            }\n            // E-> NO, we are either not on the 0th round of attempts, OR there is just a single URL.\n            // Therefore, let the countdown timer do its stuff.\n        }\n\n        function w_connectTimeout_AbortAttemptAndReschedule() {\n            // :: Attempt timed out, clear this WebSocket out\n            log(\"Create WebSocket: Attempt timeout exceeded [\" + timeout + \" ms], URL [\" + _currentWebSocketUrl + \"] didn't work out.\");\n            // Abort the attempt.\n            w_abortAttempt();\n            // ?: Assert that we're still open\n            if (!_matsSocketOpen) {\n                log(\"After timed out attempt, we realize that this MatsSocket instance is closed! - stopping right here.\");\n                return;\n            }\n            // Invoke after a small random number of millis: Bump reconnect state vars, re-run _initiateWebSocketCreation\n            setTimeout(function () {\n                _increaseReconnectStateVars();\n                _initiateWebSocketCreation();\n            }, Math.round(Math.random() * 200));\n        }\n\n        // Start the countdown-timer.\n        // NOTICE! Order here is important - as the 'w_attemptPreConnectionOperation' right below may cancel it!\n        w_countDownTimer();\n\n        // :: Start the actual connection attempt!\n        // ?: Should we do a PreConnectionOperation?\n        if (that.preconnectoperation) {\n            // -> function, string URL or 'true': Attempt tp perform the PreConnectionOperation - which upon success goes on to invoke 'w_attemptWebSocket()'.\n            w_attemptPreConnectionOperation();\n        } else {\n            // -> Falsy: No PreConnectionOperation, attempt to create the WebSocket directly.\n            w_attemptWebSocket();\n        }\n    }\n\n    function _onerror(errorEvent) {\n        error(\"websocket.onerror\", \"Got 'onerror' event from WebSocket, instanceId:[\" + errorEvent.target.webSocketInstanceId + \"].\", errorEvent);\n        // :: Synchronously notify our ConnectionEvent listeners.\n        _updateStateAndNotifyConnectionEventListeners(new ConnectionEvent(ConnectionEventType.CONNECTION_ERROR, _currentWebSocketUrl, errorEvent, undefined, undefined, _connectionAttempt));\n    }\n\n    function _onclose(closeEvent) {\n        log(\"websocket.onclose, instanceId:[\" + closeEvent.target.webSocketInstanceId + \"]\", closeEvent);\n\n        // Note: Here (as opposed to matsSocket.close()) the WebSocket is already closed, so we don't have to close it..!\n\n        // ?: Special codes, that signifies that we should close (terminate) the MatsSocketSession.\n        if ((closeEvent.code === MatsSocketCloseCodes.UNEXPECTED_CONDITION)\n            || (closeEvent.code === MatsSocketCloseCodes.MATS_SOCKET_PROTOCOL_ERROR)\n            || (closeEvent.code === MatsSocketCloseCodes.VIOLATED_POLICY)\n            || (closeEvent.code === MatsSocketCloseCodes.CLOSE_SESSION)\n            || (closeEvent.code === MatsSocketCloseCodes.SESSION_LOST)) {\n            // -> One of the specific \"Session is closed\" CloseCodes -> Reject all outstanding, this MatsSocket is trashed.\n            error(\"session closed from server\", \"The WebSocket was closed with a CloseCode [\" + MatsSocketCloseCodesUtil.nameFor(closeEvent.code) + \"] signifying that our MatsSocketSession is closed, reason:[\" + closeEvent.reason + \"].\", closeEvent);\n\n            // Hold on to how many outstanding initiations there are now\n            let outstandingInitiations = Object.keys(_outboxInitiations).length;\n\n            // Close Session, Clear all state.\n            _closeSessionAndClearStateAndPipelineAndFuturesAndOutstandingMessages();\n\n            // :: Synchronously notify our SessionClosedEvent listeners\n            // NOTE: This shall only happen if Close Session is from ServerSide (that is, here), otherwise, if the app invoked matsSocket.close(), one would think the app knew about the close itself..!\n            closeEvent.codeName = MatsSocketCloseCodesUtil.nameFor(closeEvent.code);\n            closeEvent.outstandingInitiations = outstandingInitiations;\n            _notifySessionClosedEventListeners(closeEvent);\n\n        } else {\n            // -> NOT one of the specific \"Session is closed\" CloseCodes -> Reconnect and Reissue all outstanding..\n            if (closeEvent.code !== MatsSocketCloseCodes.DISCONNECT) {\n                log(\"We were closed with a CloseCode [\" + MatsSocketCloseCodesUtil.nameFor(closeEvent.code) + \"] that does NOT denote that we should close the session. Initiate reconnect and reissue all outstanding.\");\n            } else {\n                log(\"We were closed with the special DISCONNECT close code - act as we lost connection, but do NOT start to reconnect.\");\n            }\n\n            // Clear out WebSocket \"infrastructure\", i.e. state and \"pinger thread\".\n            _clearWebSocketStateAndInfrastructure();\n\n            // :: This is a reconnect - so we should do pipeline processing right away, to get the HELLO over.\n            _forcePipelineProcessing = true;\n\n            // :: Synchronously notify our ConnectionEvent listeners.\n            _updateStateAndNotifyConnectionEventListeners(new ConnectionEvent(ConnectionEventType.LOST_CONNECTION, _currentWebSocketUrl, closeEvent, undefined, undefined, _connectionAttempt));\n\n            // ?: Is this the special DISCONNECT that asks us to NOT start reconnecting?\n            if (closeEvent.code !== MatsSocketCloseCodes.DISCONNECT) {\n                // -> No, not special DISCONNECT - so start reconnecting.\n                // :: Start reconnecting, but give the server a little time to settle, and a tad randomness to handle any reconnect floods.\n                setTimeout(function () {\n                    // ?: Have we already gotten a new WebSocket, or started the process of creating one (due to a new\n                    // message having been sent in the meantime, having started the WebSocket creation process)?\n                    if ((_webSocket !== undefined) || _webSocketConnecting) {\n                        // -> Yes, so we should not start again (the _initiateWebSocketCreation asserts these states)\n                        log(\"Start reconnect after LOST_CONNECTION: Already gotten WebSocket, or started creation process. Bail out.\");\n                        return;\n                    }\n                    // ?: Has the MatsSocket been closed in the meantime?\n                    if (!_matsSocketOpen) {\n                        // -> We've been asynchronously closed - bail out from creating WebSocket  (the _initiateWebSocketCreation asserts this state)\n                        log(\"Start reconnect after LOST_CONNECTION: MatsSocket is closed. Bail out.\");\n                        return;\n                    }\n                    // E-> We should start creation process.\n                    _initiateWebSocketCreation();\n                }, 250 + Math.random() * 750);\n            }\n        }\n    }\n\n    function _onmessage(messageEvent) {\n        let receivedTimestamp = Date.now();\n        let data = messageEvent.data;\n        let envelopes = JSON.parse(data);\n\n        let numEnvelopes = envelopes.length;\n        if (that.logging) log(\"websocket.onmessage, instanceId:[\" + messageEvent.target.webSocketInstanceId + \"]: Got \" + numEnvelopes + \" messages.\");\n\n        for (let i = 0; i < numEnvelopes; i++) {\n            let envelope = envelopes[i];\n            try {\n                if (that.logging) log(\" \\\\- onmessage: handling message \" + i + \": \" + envelope.t + \", envelope:\" + JSON.stringify(envelope));\n\n                if (envelope.t === MessageType.WELCOME) {\n                    // Fetch our assigned MatsSocketSessionId\n                    that.sessionId = envelope.sid;\n                    if (that.logging) log(\"We're WELCOME! SessionId:\" + that.sessionId + \", there are [\" + Object.keys(_outboxInitiations).length + \"] outstanding sends-or-requests, and [\" + Object.keys(_outboxReplies).length + \"] outstanding replies.\");\n                    // If this is the very first time we get SESSION_ESTABLISHED, then record time (can happen again due to reconnects)\n                    if (!_initialSessionEstablished_PerformanceNow) {\n                        _initialSessionEstablished_PerformanceNow = performance.now();\n                    }\n                    // :: Synchronously notify our ConnectionEvent listeners.\n                    _updateStateAndNotifyConnectionEventListeners(new ConnectionEvent(ConnectionEventType.SESSION_ESTABLISHED, _currentWebSocketUrl, undefined, undefined, undefined, _connectionAttempt));\n                    // Start pinger (AFTER having set ConnectionState to SESSION_ESTABLISHED, otherwise it'll exit!)\n                    _startPinger();\n\n                    // TODO: Test this outstanding-stuff! Both that they are actually sent again, and that server handles the (quite possible) double-delivery.\n\n                    // ::: RETRANSMIT: If we have stuff in our outboxes, we might have to send them again (we send unless \"RetransmitGuard\" tells otherwise).\n\n                    // :: Outstanding SENDs and REQUESTs\n                    for (let key in _outboxInitiations) {\n                        let initiation = _outboxInitiations[key];\n                        let initiationEnvelope = initiation.envelope;\n                        // ?: Is the RetransmitGuard the same as we currently have?\n                        if (initiation.retransmitGuard === _outboxInitiations_RetransmitGuard) {\n                            // -> Yes, so it makes little sense in sending these messages again just yet.\n                            if (that.logging) log(\"RetransmitGuard: The outstanding Initiation [\" + initiationEnvelope.t + \"] with cmid:[\" + initiationEnvelope.cmid + \"] and TraceId:[\" + initiationEnvelope.tid\n                                + \"] was created with the same RetransmitGuard as we currently have [\" + _outboxInitiations_RetransmitGuard + \"] - they were sent directly trailing HELLO, before WELCOME came back in. No use in sending again.\");\n                            continue;\n                        }\n                        initiation.attempt++;\n                        if (initiation.attempt > 10) {\n                            error(\"toomanyretries\", \"Upon reconnect: Too many attempts at sending Initiation [\" + initiationEnvelope.t + \"] with cmid:[\" + initiationEnvelope.cmid + \"], TraceId[\" + initiationEnvelope.tid + \"], size:[\" + JSON.stringify(initiationEnvelope).length + \"].\", initiationEnvelope);\n                            continue;\n                        }\n                        // NOTICE: Won't delete it here - that is done when we process the ACK from server\n                        _addEnvelopeToPipeline_EvaluatePipelineLater(initiationEnvelope);\n                        // Flush for each message, in case the size of the message was of issue why we closed (maybe pipeline was too big).\n                        that.flush();\n                    }\n\n                    // :: Outstanding Replies\n                    // NOTICE: Since we cannot possibly have replied to a Server Request BEFORE we get the WELCOME, we do not need RetransmitGuard for Replies\n                    // (Point is that the RetransmitGuard guards against sending again messages that we sent \"along with\" the HELLO, before we got the WELCOME.\n                    // A Request from the Server cannot possibly come in before WELCOME (as that is by protcol definition the first message we get from the Server),\n                    // so there will \"axiomatically\" not be any outstanding Replies with the same RetransmitGuard as we currently have: Therefore, /all should be retransmitted/).\n                    for (let key in _outboxReplies) {\n                        let reply = _outboxReplies[key];\n                        let replyEnvelope = reply.envelope;\n                        reply.attempt++;\n                        if (reply.attempt > 10) {\n                            error(\"toomanyretries\", \"Upon reconnect: Too many attempts at sending Reply [\" + replyEnvelope.t + \"] with smid:[\" + replyEnvelope.smid + \"], TraceId[\" + replyEnvelope.tid + \"], size:[\" + JSON.stringify(replyEnvelope).length + \"].\", replyEnvelope);\n                            continue;\n                        }\n                        // NOTICE: Won't delete it here - that is done when we process the ACK from server\n                        _addEnvelopeToPipeline_EvaluatePipelineLater(replyEnvelope);\n                        // Flush for each message, in case the size of the message was of issue why we closed (maybe pipeline was too big).\n                        that.flush();\n                    }\n\n                } else if (envelope.t === MessageType.REAUTH) {\n                    // -> Server asks us to get new Authentication, as the one he has \"on hand\" is too old to send us outgoing messages\n                    _requestNewAuthorizationFromApp(\"Server demands new Authorization\", new AuthorizationRequiredEvent(AuthorizationRequiredEventType.REAUTHENTICATE, undefined));\n\n\n                } else if (envelope.t === MessageType.RETRY) {\n                    // -> Server asks us to RETRY the information-bearing-message\n\n                    // TODO: Test RETRY!\n\n                    // ?: Is it an outstanding Send or Request\n                    let initiation = _outboxInitiations[envelope.cmid];\n                    if (initiation) {\n                        let initiationEnvelope = initiation.envelope;\n                        initiation.attempt++;\n                        if (initiation.attempt > 10) {\n                            error(\"toomanyretries\", \"Upon RETRY-request: Too many attempts at sending [\" + initiationEnvelope.t + \"] with cmid:[\" + initiationEnvelope.cmid + \"], TraceId[\" + initiationEnvelope.tid + \"], size:[\" + JSON.stringify(initiationEnvelope).length + \"].\", initiationEnvelope);\n                            continue;\n                        }\n                        // Note: the retry-cycles will start at attempt=2, since we initialize it with 1, and have already increased it by now.\n                        let retryDelay = Math.pow(2, (initiation.attempt - 2)) * 500 + Math.round(Math.random() * 1000);\n                        setTimeout(function () {\n                            _addEnvelopeToPipeline_EvaluatePipelineLater(initiationEnvelope);\n                        }, retryDelay);\n                        continue;\n                    }\n                    // E-> Was not outstanding Send or Request\n\n                    // ?: Is it an outstanding Reply, i.e. Resolve or Reject?\n                    let reply = _outboxReplies[envelope.cmid];\n                    if (reply) {\n                        let replyEnvelope = reply.envelope;\n                        reply.attempt++;\n                        if (reply.attempt > 10) {\n                            error(\"toomanyretries\", \"Upon RETRY-request: Too many attempts at sending [\" + replyEnvelope.t + \"] with smid:[\" + replyEnvelope.smid + \"], TraceId[\" + replyEnvelope.tid + \"], size:[\" + JSON.stringify(replyEnvelope).length + \"].\", replyEnvelope);\n                            continue;\n                        }\n                        // Note: the retry-cycles will start at attempt=2, since we initialize it with 1, and have already increased it by now.\n                        let retryDelay = Math.pow(2, (initiation.attempt - 2)) * 500 + Math.round(Math.random() * 1000);\n                        setTimeout(function () {\n                            _addEnvelopeToPipeline_EvaluatePipelineLater(replyEnvelope);\n                        }, retryDelay);\n                    }\n                } else if ((envelope.t === MessageType.ACK) || (envelope.t === MessageType.NACK)) {\n                    // -> Server Acknowledges information-bearing message from Client.\n\n                    if ((envelope.cmid === undefined) && (envelope.ids === undefined)) {\n                        // -> No, we do not have this. Programming error from Server.\n                        error(\"ack missing ids\", \"The ACK/NACK envelope is missing 'cmid' or 'ids'.\", envelope);\n                        continue;\n                    }\n\n                    let ids = [];\n                    if (envelope.cmid !== undefined) ids.push(envelope.cmid);\n                    if (envelope.ids !== undefined) ids = ids.concat(envelope.ids);\n\n                    _sendAck2Later(ids);\n\n                    // :: Handling if this was an ACK for outstanding SEND or REQUEST\n                    for (let i = 0; i < ids.length; i++) {\n                        let cmid = ids[i];\n                        let initiation = _outboxInitiations[cmid];\n                        // ?: Check that we found it.\n                        if (initiation === undefined) {\n                            // -> No, NOT initiation. Assume it was a for a Reply (RESOLVE or REJECT), delete the outbox entry.\n                            delete _outboxReplies[cmid];\n                            continue;\n                        }\n                        // E-> ----- Yes, we had an outstanding Initiation (SEND or REQUEST).\n\n                        initiation.messageAcked_PerformanceNow = performance.now();\n\n                        // Fetch Request, if any.\n\n                        let receivedEventType = (envelope.t === MessageType.ACK ? ReceivedEventType.ACK : ReceivedEventType.NACK);\n                        _completeReceived(receivedEventType, initiation, receivedTimestamp, envelope.desc);\n\n                        let request = _outstandingRequests[cmid];\n                        // ?: If this was a REQUEST, and it is a !ACK - it will never get a Reply..\n                        if (request && (envelope.t !== MessageType.ACK)) {\n                            // -> Yes, this was a REQUEST that got an !ACK\n                            // We have to reject the REQUEST too - it was never processed, and will thus never get a Reply\n                            // (Note: This is either a reject for a Promise, or errorCallback on Endpoint).\n                            _completeRequest(request, MessageEventType.REJECT, {}, receivedTimestamp);\n                        }\n                    }\n\n                } else if (envelope.t === MessageType.ACK2) {\n                    // -> ACKNOWLEDGE of the RECEIVED: We can delete from our inbox\n                    if ((envelope.smid === undefined) && (envelope.ids === undefined)) {\n                        // -> No, we do not have this. Programming error from Server.\n                        error(\"ack2 missing ids\", \"The ACK2 envelope is missing 'smid' or 'ids'\", envelope);\n                        continue;\n                    }\n                    // Delete it from inbox - that is what ACK2 means: Other side has now deleted it from outbox,\n                    // and can thus not ever deliver it again (so we can delete the guard against double delivery).\n                    if (envelope.smid) {\n                        delete _inbox[envelope.smid];\n                    }\n                    if (envelope.ids) {\n                        for (let i = 0; i < envelope.ids.length; i++) {\n                            delete _inbox[envelope.ids[i]];\n                        }\n                    }\n\n                } else if ((envelope.t === MessageType.SEND) || (envelope.t === MessageType.REQUEST)) {\n                    // -> SEND or REQUEST: Sever-to-Client Send or Request to client terminatorOrEndpoint\n\n                    let termOrEndp = envelope.t === MessageType.SEND ? \"Terminator\" : \"Endpoint\";\n\n                    if (envelope.smid === undefined) {\n                        // -> No, we do not have this. Programming error from Server.\n                        error(envelope.t.toLowerCase() + \" missing smid\", \"The \" + envelope.t + \" envelope is missing 'smid'\", envelope);\n                        continue;\n                    }\n\n                    // Find the (client) Terminator/Endpoint which the Send should go to\n                    let terminatorOrEndpoint = (envelope.t === MessageType.SEND ? _terminators[envelope.eid] : _endpoints[envelope.eid]);\n\n                    // :: Send receipt unconditionally\n                    _sendAckLater((terminatorOrEndpoint ? MessageType.ACK : MessageType.NACK), envelope.smid, terminatorOrEndpoint ? undefined : \"The Client \" + termOrEndp + \" [\" + envelope.eid + \"] does not exist!\");\n\n\n                    // ?: Do we have the desired Terminator?\n                    if (terminatorOrEndpoint === undefined) {\n                        // -> No, we do not have this. Programming error from app.\n                        error(\"client \" + termOrEndp.toLowerCase() + \" does not exist\", \"The Client \" + termOrEndp + \" [\" + envelope.eid + \"] does not exist!!\", envelope);\n                        continue;\n                    }\n                    // E-> We found the Terminator to tell\n\n                    // ?: Have we already gotten this message? (Double delivery)\n                    if (_inbox[envelope.smid]) {\n                        // -> Yes, so this was a double delivery. Drop processing, we've already done it.\n                        if (that.logging) log(\"Caught double delivery of \" + envelope.t + \" with smid:[\" + envelope.smid + \"], sending ACK, but won't process again.\", envelope);\n                        continue;\n                    }\n\n                    // Add the message to inbox\n                    _inbox[envelope.smid] = envelope;\n\n                    // :: Handle the SEND or REQUEST\n\n                    // ?: Is this a SEND?\n                    if (envelope.t === MessageType.SEND) {\n                        // Yes, SEND, so invoke the Terminator\n                        let messageEvent = _createMessageEventForIncoming(envelope, receivedTimestamp);\n                        terminatorOrEndpoint.resolve(messageEvent);\n                    } else {\n                        // No, this is REQUEST - so invoke the Endpoint to get a Promise, and send its settling using RESOLVE or REJECT.\n                        // :: Create a Resolve and Reject handler\n                        let fulfilled = function (resolveReject, msg) {\n                            // Update timestamp of last \"information bearing message\" sent.\n                            _lastMessageEnqueuedTimestamp = Date.now();\n                            // Create the Reply message\n                            let replyEnvelope = {\n                                t: resolveReject,\n                                smid: envelope.smid,\n                                tid: envelope.tid,\n                                msg: msg\n                            };\n                            // Add the message Sequence Id\n                            replyEnvelope.cmid = _messageSequenceId++;\n                            // Add it to outbox\n                            _outboxReplies[replyEnvelope.cmid] = {\n                                attempt: 1,\n                                envelope: replyEnvelope\n                            };\n                            // Send it down the wire\n                            _addEnvelopeToPipeline_EvaluatePipelineLater(replyEnvelope);\n                        };\n\n                        // :: Invoke the Endpoint, getting a Promise back.\n                        let messageEvent = _createMessageEventForIncoming(envelope, receivedTimestamp);\n                        let promise = terminatorOrEndpoint(messageEvent);\n\n                        // :: Finally attach the Resolve and Reject handler\n                        promise.then(function (resolveMessage) {\n                            fulfilled(MessageType.RESOLVE, resolveMessage);\n                        }).catch(function (rejectMessage) {\n                            fulfilled(MessageType.REJECT, rejectMessage);\n                        });\n                    }\n\n                } else if ((envelope.t === MessageType.RESOLVE) || (envelope.t === MessageType.REJECT)) {\n                    // -> Reply to REQUEST\n                    // ?: Do server want receipt, indicated by the message having 'smid' property?\n                    // (NOTE: Reply (RESOLVE/REJECT) directly in IncomingHandler will not set 'smid', as the message has never been in the outbox, so won't need deletion).\n                    if (envelope.smid) {\n                        // -> Yes, so send ACK to server\n                        _sendAckLater(MessageType.ACK, envelope.smid);\n                    }\n                    // It is physically possible that the Reply comes before the ACK (I've observed it!).\n                    // .. Such a situation could potentially be annoying for the using application (Reply before Ack)..\n                    // ALSO, for Replies that are produced in the incomingHandler, there will be no separate ACK message - this is a combined ACK+Reply.\n                    // Handle this by checking whether the initiation is still in place, and handle it as \"ACK Received\" if so.\n                    let initiation = _outboxInitiations[envelope.cmid];\n                    // ?: Was the initiation still present?\n                    if (initiation) {\n                        // -> Yes, still present - this means that this is effectively a /combined/ ACK+Reply, so must also handle the ACK-part.\n                        // Send ACK2 for the \"ACK-part\" of this Reply (the Client-to-Server REQUEST was stored in Server's inbox - he may now delete it).\n                        _sendAck2Later(envelope.cmid);\n                        // Complete any Received-callbacks for the \"ACK-part\" of this Reply.\n                        _completeReceived(ReceivedEventType.ACK, initiation, receivedTimestamp);\n                    }\n\n                    let request = _outstandingRequests[envelope.cmid];\n                    if (!request) {\n                        if (that.logging) log(\"Double delivery: Evidently we've already completed the Request for cmid:[\" + envelope.cmid + \"], traiceId: [\" + envelope.tid + \"], ignoring.\");\n                        continue;\n                    }\n\n                    // Ensure that the timeout is killed now. NOTICE: MUST do this here, since we might delay the delivery even more, check crazy stuff below.\n                    clearTimeout(request.timeoutId);\n\n                    // Complete the Promise on a REQUEST-with-Promise, or messageCallback/errorCallback on Endpoint for REQUEST-with-ReplyTo\n                    let messageEventType = (envelope.t === MessageType.RESOLVE ? MessageEventType.RESOLVE : MessageEventType.REJECT);\n\n                    /*\n                     * NOTICE!! HACK-ALERT! The ordering of events wrt. Requests is as such:\n                     * 1. ReceivedEvent (receivedCallback for requests, and Received-Promise for requestReplyTo)\n                     * 2. InitiationProcessedEvent stored on matsSocket.initiations\n                     * 3. InitiationProcessedEvent listeners\n                     * 4. MessageEvent (Reply-Promise for requests, Terminator callbacks for requestReplyTo)\n                     *\n                     * WITH a requestReplyTo, the ReceivedEvent becomes async in nature, since requestReplyTo returns\n                     * a Promise<ReceivedEvent>. Also, with a requestReplyTo, the completing of the requestReplyTo is\n                     * then done on a Terminator, using its specified callbacks - and this is done using\n                     * setTimeout(.., 0) to \"emulate\" the same async-ness as a Reply-Promise with ordinary requests.\n                     * However, the timing between the ReceivedEvent and InitiationProcessedEvent then becomes\n                     * rather shaky. Therefore, IF the initiation is still in place (ReceivedEvent not yet issued),\n                     * AND this is a requestReplyTo, THEN we delay the completion of the Request (i.e. issue\n                     * InitiationProcessedEvent and MessageEvent) to be more certain that the ReceivedEvent is\n                     * processed before the rest.\n                     */\n                    // ?: Did we still have the initiation in place, AND this is a requestReplyTo?\n                    if (initiation && request.replyToTerminatorId) {\n                        // -> Yes, the initiation was still in place (i.e. ReceivedEvent not issued), and this was\n                        // a requestReplyTo:\n                        // Therefore we delay the entire completion of the request (InitiationProcessedEvent and\n                        // MessageEvent), to be sure that they happen AFTER the ReceivedEvent issued above.\n                        setTimeout(function () {\n                            _completeRequest(request, messageEventType, envelope, receivedTimestamp);\n                        }, 20);\n                    } else {\n                        // -> No, either the initiation was already gone (ReceivedEvent already issued), OR it was\n                        // not a requestReplyTo:\n                        // Therefore, we run the completion right away (InitiationProcessedEvent is sync, while\n                        // MessageEvent is a Promise settling).\n                        _completeRequest(request, messageEventType, envelope, receivedTimestamp);\n                    }\n\n\n                } else if (envelope.t === MessageType.PING) {\n                    // -> PING request, respond with a PONG\n                    // Add the PONG reply to pipeline\n                    _addEnvelopeToPipeline_EvaluatePipelineLater({\n                        t: MessageType.PONG,\n                        x: envelope.x\n                    });\n                    // Send it immediately, since pings might be used to establish roundtrip timings.\n                    that.flush();\n\n                } else if ((envelope.t === MessageType.SUB_OK) || (envelope.t === MessageType.SUB_LOST) || (envelope.t === MessageType.SUB_NO_AUTH)) {\n                    // -> Result of SUB\n                    // Notify PingPong listeners, synchronously.\n                    let eventType;\n                    if (envelope.t === MessageType.SUB_OK) {\n                        eventType = SubscriptionEventType.OK;\n                    } else if (envelope.t === MessageType.SUB_LOST) {\n                        eventType = SubscriptionEventType.LOST_MESSAGES;\n                    } else {\n                        eventType = SubscriptionEventType.NOT_AUTHORIZED;\n                    }\n                    let event = new SubscriptionEvent(eventType, envelope.eid);\n                    for (let i = 0; i < _subscriptionEventListeners.length; i++) {\n                        try {\n                            _subscriptionEventListeners[i](event);\n                        } catch (err) {\n                            error(\"notify SubscriptionEvent listeners\", \"Caught error when notifying one of the [\" + _subscriptionEventListeners.length + \"] SubscriptionEvent listeners.\", err);\n                        }\n                    }\n\n                } else if (envelope.t === MessageType.PUB) {\n                    // -> Server publishes a Topic message\n                    let event = new MessageEvent(MessageEventType.PUB, envelope.msg, envelope.tid, envelope.smid, receivedTimestamp);\n\n                    let subs = _subscriptions[envelope.eid];\n                    // ?: Did we find any listeners?\n                    if (!subs) {\n                        // -> No. Strange.\n                        error(\"message for unwanted topic\", \"We got a PUB message for Topic [\" + envelope.eid + \"], but we have no subscribers for it.\");\n                        continue;\n                    }\n\n                    // Issue message to all listeners for this Topic.\n                    for (let i = 0; i < subs.listeners.length; i++) {\n                        try {\n                            subs.listeners[i](event);\n                        } catch (err) {\n                            error(\"dispatch topic message\", \"Caught error when notifying one of the [\" + subs.listeners.length + \"] subscription listeners for Topic [\" + envelope.eid + \"].\", err);\n                        }\n                    }\n\n                    // Make note of the latest message id processed for this Topic\n                    subs.lastSmid = envelope.smid;\n\n                } else if (envelope.t === MessageType.PONG) {\n                    // -> Response to a PING\n                    let pingPongHolder = _outstandingPings[envelope.x];\n                    delete _outstandingPings[envelope.x];\n                    // Calculate the round-trip time, using performanceNow stored along with the PingPong instance.\n                    let pingPong = pingPongHolder[1];\n                    let performanceThen = pingPongHolder[0];\n                    pingPong.roundTripMillis = _roundTiming(performance.now() - performanceThen);\n\n                    // Notify PingPong listeners, synchronously.\n                    for (let i = 0; i < _pingPongListeners.length; i++) {\n                        try {\n                            _pingPongListeners[i](pingPong);\n                        } catch (err) {\n                            error(\"notify pingpongevent listeners\", \"Caught error when notifying one of the [\" + _pingPongListeners.length + \"] PingPongEvent listeners.\", err);\n                        }\n                    }\n                }\n            } catch (err) {\n                let stringified = JSON.stringify(envelope);\n                error(\"envelope processing\", \"Got unexpected error while handling incoming envelope of type '\" + envelope.t + \"': \" + (stringified.length > 1024 ? stringified.substring(0, 1021) + \"...\" : stringified), err);\n            }\n        }\n    }\n\n    let _laterAcks = [];\n    let _laterNacks = [];\n    let _laterAckTimeoutId = undefined;\n\n    function _sendAckLater(type, smid, description) {\n        // ?: Do we have description?\n        if (description) {\n            // -> Yes, description - so then we need to send it by itself\n            _addEnvelopeToPipeline_EvaluatePipelineLater({\n                t: type,\n                smid: smid,\n                desc: description\n            });\n            return;\n        }\n        // ?: Was it ACK or NACK?\n        if (type === MessageType.ACK) {\n            _laterAcks.push(smid);\n        } else {\n            _laterNacks.push(smid);\n        }\n        // Send them now or later\n        clearTimeout(_laterAckTimeoutId);\n        if ((_laterAcks.length + _laterNacks.length) > 10) {\n            _sendAcksAndNacksNow();\n        } else {\n            _laterAckTimeoutId = setTimeout(_sendAcksAndNacksNow, 20);\n        }\n    }\n\n    function _sendAcksAndNacksNow() {\n        // ACKs\n        if (_laterAcks.length > 1) {\n            _addEnvelopeToPipeline_EvaluatePipelineLater({\n                t: MessageType.ACK,\n                ids: _laterAcks\n            });\n            _laterAcks = [];\n        } else if (_laterAcks.length === 1) {\n            _addEnvelopeToPipeline_EvaluatePipelineLater({\n                t: MessageType.ACK,\n                smid: _laterAcks[0]\n            });\n            _laterAcks.length = 0;\n        }\n        // NACKs\n        if (_laterNacks.length > 1) {\n            _addEnvelopeToPipeline_EvaluatePipelineLater({\n                t: MessageType.NACK,\n                ids: _laterNacks\n            });\n            _laterNacks = [];\n        } else if (_laterNacks.length === 1) {\n            _addEnvelopeToPipeline_EvaluatePipelineLater({\n                t: MessageType.NACK,\n                smid: _laterNacks[0]\n            });\n            _laterNacks.length = 0;\n        }\n    }\n\n    let _laterAck2s = [];\n    let _laterAck2TimeoutId = undefined;\n\n    function _sendAck2Later(ids) {\n        _laterAck2s = _laterAck2s.concat(ids);\n        // Send them now or later\n        clearTimeout(_laterAck2TimeoutId);\n        if (_laterAck2s.length > 10) {\n            _sendAck2sNow();\n        } else {\n            _laterAck2TimeoutId = setTimeout(_sendAck2sNow, 50);\n        }\n    }\n\n    function _sendAck2sNow() {\n        // ACK2s\n        if (_laterAck2s.length > 1) {\n            _addEnvelopeToPipeline_EvaluatePipelineLater({\n                t: MessageType.ACK2,\n                ids: _laterAck2s\n            });\n            _laterAck2s = [];\n        } else if (_laterAck2s.length === 1) {\n            _addEnvelopeToPipeline_EvaluatePipelineLater({\n                t: MessageType.ACK2,\n                cmid: _laterAck2s[0]\n            });\n            _laterAck2s.length = 0;\n        }\n    }\n\n    function _completeReceived(receivedEventType, initiation, receivedTimestamp, description = undefined) {\n        let performanceNow = performance.now();\n        initiation.messageAcked_PerformanceNow = performanceNow;\n\n        // NOTICE! We do this SYNCHRONOUSLY, to ensure that we come in front of Request Promise settling (specifically, Promise /rejection/ if NACK).\n        delete _outboxInitiations[initiation.envelope.cmid];\n        let receivedEvent = new ReceivedEvent(receivedEventType, initiation.envelope.tid, initiation.sentTimestamp, receivedTimestamp, _roundTiming(performanceNow - initiation.messageSent_PerformanceNow), description);\n        // ?: Was it a ACK (not NACK)?\n        if (receivedEventType === ReceivedEventType.ACK) {\n            // -> Yes, it was \"ACK\" - so Server was happy.\n            if (initiation.ack) {\n                try {\n                    initiation.ack(receivedEvent);\n                } catch (err) {\n                    error(\"received ack\", \"When trying to ACK the initiation with ReceivedEvent [\" + receivedEventType + \"], we got error.\", err);\n                }\n            }\n        } else {\n            // -> No, it was !ACK, so message has not been forwarded to Mats\n            if (initiation.nack) {\n                try {\n                    initiation.nack(receivedEvent);\n                } catch (err) {\n                    error(\"received nack\", \"When trying to NACK the initiation with ReceivedEvent [\" + receivedEventType + \"], we got error.\", err);\n                }\n            }\n        }\n\n        // ?: Should we issue InitiationProcessedEvent? (SEND is finished processed at ACK time, while REQUEST waits for REPLY from server before finished processing)\n        if (initiation.envelope.t === MessageType.SEND) {\n            // -> Yes, we should issue - and to get this in a order where \"Received is always invoked before\n            // InitiationProcessedEvents\", we'll have to delay it, as the Promise settling above is async)\n            setTimeout(function () {\n                _issueInitiationProcessedEvent(initiation);\n            }, 50);\n        }\n    }\n\n    function _createMessageEventForIncoming(envelope, receivedTimestamp) {\n        let messageEvent = new MessageEvent(envelope.t, envelope.msg, envelope.tid, envelope.smid, receivedTimestamp);\n        // ?: Do we have a debug object in the envelope?\n        if (envelope.debug) {\n            // -> Yes, so then created it for MessageEvent too.\n            messageEvent.debug = new DebugInformation(undefined, undefined, envelope, receivedTimestamp);\n        }\n        return messageEvent;\n    }\n\n    function _completeRequest(request, messageEventType, incomingEnvelope, receivedTimestamp) {\n        // We're finishing it now, so it shall not be timed out.\n        clearTimeout(request.timeoutId);\n\n        // Make note of performance.now() at this point in time\n        let performanceNow = performance.now();\n\n        delete _outstandingRequests[request.envelope.cmid];\n\n        // Create the event\n        let event = new MessageEvent(messageEventType, incomingEnvelope.msg, request.envelope.tid, request.envelope.cmid, receivedTimestamp);\n        event.clientRequestTimestamp = request.initiation.sentTimestamp;\n        event.roundTripMillis = performanceNow - request.initiation.messageSent_PerformanceNow;\n        // .. add CorrelationInformation from request if requestReplyTo\n        event.correlationInformation = request.correlationInformation;\n        // Add DebugInformation if relevant\n        if (request.initiation.debug !== 0) {\n            event.debug = new DebugInformation(request.initiation.sentTimestamp, request.initiation.debug, incomingEnvelope, receivedTimestamp);\n        }\n\n        // Invoke InitiationProcessedEvent listeners (Both adding to matsSocket.initiations and firing of listeners is done sync, thus done before settling).\n        _issueInitiationProcessedEvent(request.initiation, request.replyToTerminatorId, event);\n\n        // ?: Is this a RequestReplyTo, as indicated by the request having a replyToEndpoint?\n        if (request.replyToTerminatorId) {\n            // -> Yes, this is a REQUEST-with-ReplyTo\n            // Find the (client) Terminator which the Reply should go to\n            let terminator = _terminators[request.replyToTerminatorId];\n            // \"Emulate\" asyncness as if with Promise settling with setTimeout(.., 0).\n            setTimeout(function () {\n                if (messageEventType === MessageEventType.RESOLVE) {\n                    try {\n                        terminator.resolve(event);\n                    } catch (err) {\n                        error(\"replytoterminator resolve\", \"When trying to pass a RESOLVE to Terminator [\" + request.replyToTerminatorId + \"], an exception was raised.\", err);\n                    }\n                } else {\n                    // ?: Do we actually have a Reject-function (not necessarily, app decides whether to register it)\n                    if (terminator.reject) {\n                        // -> Yes, so reject it.\n                        try {\n                            terminator.reject(event);\n                        } catch (err) {\n                            error(\"replytoterminator reject\", \"When trying to pass a [\" + messageEventType + \"] to Terminator [\" + request.replyToTerminatorId + \"], an exception was raised.\", err);\n                        }\n                    }\n                }\n            }, 0);\n        } else {\n            // -> No, this is a REQUEST-with-Promise (missing (client) EndpointId)\n            // Delete the outstanding request, as we will complete it now.\n            delete _outstandingRequests[request.envelope.cmid];\n            // :: Note, resolving/rejecting a Promise is always async (happens \"next tick\").\n            // ?: Was it RESOLVE or REJECT?\n            if (messageEventType === MessageEventType.RESOLVE) {\n                request.resolve(event);\n            } else {\n                request.reject(event);\n            }\n        }\n    }\n\n    function _roundTiming(millis) {\n        return Math.round(millis * 100) / 100;\n    }\n\n    function _issueInitiationProcessedEvent(initiation, replyToTerminatorId = undefined, replyMessageEvent = undefined) {\n        // Handle when initationProcessed /before/ session established: Setting to 0. (Can realistically only happen in testing.)\n        let sessionEstablishedOffsetMillis = (_initialSessionEstablished_PerformanceNow ? _roundTiming(initiation.messageSent_PerformanceNow - _initialSessionEstablished_PerformanceNow) : 0);\n        let acknowledgeRoundTripTime = _roundTiming(initiation.messageAcked_PerformanceNow - initiation.messageSent_PerformanceNow);\n        let requestRoundTripTime = (replyMessageEvent ? _roundTiming(performance.now() - initiation.messageSent_PerformanceNow) : undefined);\n        let replyMessageEventType = (replyMessageEvent ? replyMessageEvent.type : undefined);\n        if (_numberOfInitiationsKept > 0) {\n            let initiationProcessedEvent = new InitiationProcessedEvent(initiation.envelope.eid, initiation.envelope.cmid, initiation.sentTimestamp,\n                sessionEstablishedOffsetMillis, initiation.envelope.tid, initiation.envelope.msg, acknowledgeRoundTripTime, replyMessageEventType, replyToTerminatorId, requestRoundTripTime, replyMessageEvent);\n            _initiationProcessedEvents.push(initiationProcessedEvent);\n            while (_initiationProcessedEvents.length > _numberOfInitiationsKept) {\n                _initiationProcessedEvents.shift();\n            }\n        }\n\n        if (initiation.suppressInitiationProcessedEvent) {\n            log(\"InitiationProcessedEvent is suppressed, so NOT notifying listeners.\");\n            return;\n        }\n\n        // Firing to listeners, synchronous.\n        for (let i = 0; i < _initiationProcessedEventListeners.length; i++) {\n            try {\n                let registration = _initiationProcessedEventListeners[i];\n                let initiationMessageIncluded = (registration.includeInitiationMessage ? initiation.envelope.msg : undefined);\n                let replyMessageEventIncluded = (registration.includeReplyMessageEvent ? replyMessageEvent : undefined);\n                let initiationProcessedEvent = new InitiationProcessedEvent(initiation.envelope.eid, initiation.envelope.cmid, initiation.sentTimestamp, sessionEstablishedOffsetMillis,\n                    initiation.envelope.tid, initiationMessageIncluded, acknowledgeRoundTripTime, replyMessageEventType, replyToTerminatorId, requestRoundTripTime, replyMessageEventIncluded);\n                if (that.logging) log(\"Sending InitiationProcessedEvent to listener [\" + (i + 1) + \"/\" + _initiationProcessedEventListeners.length + \"]\", initiationProcessedEvent);\n                registration.listener(initiationProcessedEvent);\n            } catch (err) {\n                error(\"notify InitiationProcessedEvent listeners\", \"Caught error when notifying one of the [\" + _initiationProcessedEventListeners.length + \"] InitiationProcessedEvent listeners.\", err);\n            }\n        }\n    }\n\n    function _startPinger() {\n        log(\"Starting PING'er!\");\n        // Start the pinger with a random 5 +/-2 seconds, in case of mass reconnect.\n        // Notice the \"magic property\" here, used in integration tests\n        _pingLater(that.initialPingDelay);\n    }\n\n    function _stopPinger() {\n        log(\"Cancelling PINGer\");\n        if (_pinger_TimeoutId) {\n            clearTimeout(_pinger_TimeoutId);\n            _pinger_TimeoutId = undefined;\n        }\n    }\n\n    let _pinger_TimeoutId;\n    let _pingId = 0;\n\n    function _pingLater(initialPingDelay) {\n        _pinger_TimeoutId = setTimeout(function () {\n            // @ts-expect-error TS2339: 'state' is defined via defineProperty; we only read it here.\n            const state= that.state;\n            if (that.logging) log(\"Ping-'thread': About to send ping. ConnectionState:[\" + state + \"], matsSocketOpen:[\" + _matsSocketOpen + \"].\");\n            if ((state === ConnectionState.SESSION_ESTABLISHED) && _matsSocketOpen) {\n                let pingId = _pingId++;\n                let pingPong = new PingPong(pingId, Date.now());\n                _pings.push(pingPong);\n                if (_pings.length > 100) {\n                    _pings.shift();\n                }\n                _outstandingPings[pingId] = [performance.now(), pingPong];\n                _webSocket.send(\"[{\\\"t\\\":\\\"\" + MessageType.PING + \"\\\",\\\"x\\\":\\\"\" + pingId + \"\\\"}]\");\n                // Reschedule\n                _pingLater(15000);\n            } else {\n                log(\"Ping-'thread': NOT sending Ping and NOT Rescheduling due to state!=SESSION_ESTABLISHED or !connected - exiting 'thread'.\");\n            }\n        }, initialPingDelay);\n    }\n}\n"],"names":[],"mappings":";;;;;;IAcA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA,SAAS,0BAA0B,CAAC,IAAI,EAAE,0BAA0B,EAAE;IACtE;IACA;IACA;IACA;IACA;IACA,IAAI,IAAI,CAAC,IAAI,GAAG,IAAI;;IAEpB;IACA;IACA;IACA;IACA;IACA;IACA,IAAI,IAAI,CAAC,0BAA0B,GAAG,0BAA0B;IAChE;;IAEA;IACA;IACA;IACA;IACA;IACA;AACK,UAAC,8BAA8B,GAAG;IACvC;IACA;IACA;IACA,IAAI,WAAW,EAAE,YAAY;;IAE7B;IACA;IACA;IACA;IACA,IAAI,OAAO,EAAE,SAAS;;IAEtB;IACA;IACA;IACA;IACA;IACA;IACA;IACA,IAAI,cAAc,EAAE;IACpB;IACA,MAAM,CAAC,MAAM,CAAC,8BAA8B,CAAC;;IChE7C;IACA;IACA;IACA;IACA;IACA;AACK,UAAC,eAAe,GAAG;IACxB;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA,IAAI,UAAU,EAAE,WAAW;;IAE3B;IACA;IACA;IACA,IAAI,UAAU,EAAE,YAAY;;IAE5B;IACA;IACA;IACA,IAAI,OAAO,EAAE,SAAS;;IAEtB;IACA;IACA;IACA,IAAI,SAAS,EAAE,WAAW;;IAE1B;IACA;IACA;IACA,IAAI,mBAAmB,EAAE;IACzB;IACA,MAAM,CAAC,MAAM,CAAC,eAAe,CAAC;;ICnC9B;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA,SAAS,eAAe,CAAC,IAAI,EAAE,YAAY,EAAE,cAAc,EAAE,cAAc,EAAE,gBAAgB,EAAE,iBAAiB,EAAE;IAClH;IACA;IACA;IACA;IACA;IACA,IAAI,IAAI,CAAC,IAAI,GAAG,IAAI;;IAEpB;IACA;IACA;IACA;IACA;IACA,IAAI,IAAI,CAAC,YAAY,GAAG,YAAY;;IAEpC;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA,IAAI,IAAI,CAAC,cAAc,GAAG,cAAc;;IAExC;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA,IAAI,IAAI,CAAC,cAAc,GAAG,cAAc;;IAExC;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA,IAAI,IAAI,CAAC,gBAAgB,GAAG,gBAAgB;;IAE5C;IACA;IACA;IACA;IACA;IACA,IAAI,IAAI,CAAC,iBAAiB,GAAG,iBAAiB;IAC9C;;;IAGA;IACA;IACA;IACA;IACA;IACA;IACA;AACK,UAAC,mBAAmB,GAAG;IAC5B;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA,IAAI,UAAU,EAAE,eAAe,CAAC,UAAU;;IAE1C;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA,IAAI,OAAO,EAAE,eAAe,CAAC,OAAO;;IAEpC;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA,IAAI,SAAS,EAAE,eAAe,CAAC,SAAS;;IAExC;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA,IAAI,mBAAmB,EAAE,eAAe,CAAC,mBAAmB;;IAE5D;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA,IAAI,gBAAgB,EAAE,iBAAiB;;IAEvC;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA,IAAI,eAAe,EAAE,gBAAgB;;IAErC;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA,IAAI,SAAS,EAAE;;IAEf;IACA,MAAM,CAAC,MAAM,CAAC,mBAAmB,CAAC;;ICtMlC;IACA;IACA;IACA;IACA;IACA;IACA;AACK,UAAC,WAAW,GAAG;IACpB;IACA;IACA;IACA;IACA,IAAI,KAAK,EAAE,OAAO;;IAElB;IACA;IACA;IACA;IACA;IACA;IACA,IAAI,OAAO,EAAE,SAAS;;IAEtB;IACA;IACA;IACA,IAAI,IAAI,EAAE,MAAM;;IAEhB;IACA;IACA;IACA,IAAI,OAAO,EAAE,SAAS;;IAEtB;IACA;IACA;IACA,IAAI,KAAK,EAAE,OAAO;;IAElB;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA,IAAI,GAAG,EAAE,KAAK;;IAEd;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA,IAAI,IAAI,EAAE,MAAM;;IAEhB;IACA;IACA;IACA;IACA;IACA;IACA;IACA,IAAI,IAAI,EAAE,MAAM;;IAEhB;IACA;IACA;IACA;IACA,IAAI,OAAO,EAAE,SAAS;;IAEtB;IACA;IACA;IACA;IACA,IAAI,MAAM,EAAE,QAAQ;;IAEpB;IACA;IACA;IACA,IAAI,GAAG,EAAE,KAAK;;IAEd;IACA;IACA;IACA,IAAI,KAAK,EAAE,OAAO;;IAElB;IACA;IACA;IACA;IACA,IAAI,MAAM,EAAE,QAAQ;;IAEpB;IACA;IACA;IACA;IACA;IACA,IAAI,QAAQ,EAAE,UAAU;;IAExB;IACA;IACA;IACA,IAAI,WAAW,EAAE,aAAa;;IAE9B;IACA;IACA;IACA;IACA,IAAI,GAAG,EAAE,KAAK;;IAEd;IACA;IACA;IACA;IACA;IACA;IACA,IAAI,MAAM,EAAE,QAAQ;;IAEpB;IACA;IACA;IACA;IACA,IAAI,IAAI,EAAE,MAAM;;IAEhB;IACA;IACA;IACA,IAAI,IAAI,EAAE,MAAM;;IAEhB;IACA;IACA;IACA,IAAI,IAAI,EAAE;IACV;IACA,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC;;IClI1B;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA,SAAS,aAAa,CAAC,IAAI,EAAE,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,eAAe,EAAE,WAAW,EAAE;IACtG;IACA;IACA;IACA;IACA;IACA;IACA;IACA,IAAI,IAAI,CAAC,IAAI,GAAG,IAAI;;IAEpB;IACA;IACA;IACA;IACA;IACA,IAAI,IAAI,CAAC,OAAO,GAAG,OAAO;;IAE1B;IACA;IACA;IACA;IACA;IACA,IAAI,IAAI,CAAC,aAAa,GAAG,aAAa;;IAEtC;IACA;IACA;IACA;IACA;IACA,IAAI,IAAI,CAAC,iBAAiB,GAAG,iBAAiB;;IAE9C;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA,IAAI,IAAI,CAAC,eAAe,GAAG,eAAe;;IAE1C;IACA;IACA;IACA;IACA;IACA;IACA,IAAI,IAAI,CAAC,WAAW,GAAG,WAAW;IAClC;;IAEA;IACA;IACA;IACA;IACA;IACA;AACK,UAAC,iBAAiB,GAAG;IAC1B;IACA;IACA;IACA;IACA;IACA;IACA,IAAI,GAAG,EAAE,KAAK;;IAEd;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA,IAAI,IAAI,EAAE,MAAM;;IAEhB;IACA;IACA;IACA;IACA;IACA;IACA;IACA,IAAI,OAAO,EAAE,SAAS;;IAEtB;IACA;IACA;IACA;IACA;IACA,IAAI,cAAc,EAAE;IACpB;IACA,MAAM,CAAC,MAAM,CAAC,iBAAiB,CAAC;;IC9GhC;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA,SAAS,YAAY,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,iBAAiB,EAAE;IACzE;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA,IAAI,IAAI,CAAC,IAAI,GAAG,IAAI;;IAEpB;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA,IAAI,IAAI,CAAC,IAAI,GAAG,IAAI;;IAEpB;IACA;IACA;IACA;IACA;IACA;IACA,IAAI,IAAI,CAAC,sBAAsB,GAAG,SAAS;;IAE3C;IACA;IACA;IACA;IACA;IACA,IAAI,IAAI,CAAC,OAAO,GAAG,OAAO;;IAE1B;IACA;IACA;IACA;IACA;IACA;IACA,IAAI,I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A;IACA,IAAI,IAAI,CAAC,iBAAiB,GAAG,iBAAiB;IAC9C;;IAEA;IACA;IACA;IACA;IACA;IACA;IACA;AACK,UAAC,4BAA4B,GAAG;IACrC;IACA;IACA;IACA;IACA,IAAI,IAAI,EAAE,MAAM;;IAEhB;IACA;IACA;IACA;IACA,IAAI,OAAO,EAAE,SAAS;;IAEtB;IACA;IACA;IACA,IAAI,gBAAgB,EAAE;IACtB;IACA,MAAM,CAAC,MAAM,CAAC,4BAA4B,CAAC;;IC7K3C;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA,SAAS,QAAQ,CAAC,MAAM,EAAE,aAAa,EAAE;IACzC;IACA;IACA;IACA;IACA;IACA,IAAI,IAAI,CAAC,MAAM,GAAG,MAAM;;IAExB;IACA;IACA;IACA;IACA;IACA,IAAI,IAAI,CAAC,aAAa,GAAG,aAAa;;IAEtC;IACA;IACA;IACA;IACA;IACA,IAAI,IAAI,CAAC,eAAe,GAAG,SAAS;IACpC;;IC1CA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;AACK,UAAC,oBAAoB,GAAG;IAC7B;IACA;IACA;IACA;IACA,IAAI,eAAe,EAAE,IAAI;;IAEzB;IACA;IACA;IACA;IACA;IACA,IAAI,oBAAoB,EAAE,IAAI;;IAE9B;IACA;IACA;IACA;IACA,IAAI,eAAe,EAAE,IAAI;;IAEzB;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA,IAAI,UAAU,EAAE,IAAI;;IAEpB;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA,IAAI,aAAa,EAAE,IAAI;;IAEvB;IACA;IACA;IACA;IACA;IACA;IACA,IAAI,YAAY,EAAE,IAAI;;IAEtB;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA,IAAI,SAAS,EAAE,IAAI;;IAEnB;IACA;IACA;IACA;IACA;IACA;IACA;IACA,IAAI,UAAU,EAAE,IAAI;;IAEpB;IACA;IACA;IACA;IACA,IAA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AS;;IAEjI;IACA,IAAI,IAAI,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC;;;IAG1B;IACA;IACA;;IAEA;IACA;IACA;IACA;IACA;IACA;IACA,IAAI,IAAI,CAAC,SAAS,GAAG,SAAS;;IAE9B;IACA;IACA;IACA;IACA;IACA,IAAI,IAAI,CAAC,OAAO,GAAG,KAAK;;IAExB;IACA;IACA;IACA;IACA;IACA,IAAI,IAAI,CAAC,YAAY,GAAG,IAAI;;IAE5B;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA,IAAI,IAAI,CAAC,cAAc,GAAG,IAAI;;IAE9B;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA,IAAI,IAAI,CAAC,mBAAmB,GAAG,KAAK;;IAEpC;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA,IAAI,IAAI,CAAC,KAAK,GAAG,CAAC;;IAElB;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA,IAAI,IAAI,CAAC,cAAc,GAAG,KAAK;;IAE/B;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA,IAAI,IAAI,CAAC,qBAAqB,GAAG,SAAS;;IAE1C;IACA;IACA;IACA;IACA;IACA;IACA,IAAI,IAAI,CAAC,gBAAgB,GAAG,IAAI,GAAG,IAAI,CAAC,MAAM,EAAE,GAAG;;IAEnD;IACA;IACA;IACA;IACA;IACA;;IAEA;IACA;IACA;I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"}