From 5cc83430c34777955daf02796b4ea7af3e550774 Mon Sep 17 00:00:00 2001 From: Laur Sisask <49899951+laurglia@users.noreply.github.com> Date: Fri, 14 Oct 2022 22:30:11 +0300 Subject: [PATCH] Fix reconnecting websockets on heartbeat timeout (#4921) In Google Chrome, when network connection is interrupted, the websocket connections break but they do not properly close. The following happens: - The `error` and `close` events are not triggered - Sending data with `WebSocket#send` works without errors even though the data is not actually sent - When calling `WebSocket#close`, the websocket is not closed. That is expected, as closing a websocket includes sending a closing handshake which cannot be done when the underlying connection is broken. The closing handshake is documented in the [WebSockets Standard][websockets-standard]. Because of the behavior described above, Phoenix failed to reconnect sockets with WebSocket transport. When heartbeat timed out, `WebSocket#close` was used to close the connection but since the connection was broken, sending the closing handshake failed, and the close event was not triggered. It seems like that after some time, after around 2--3 minutes, the WebSocket finally closes (the `close` event triggers) but that is too long period for our use case. To demonstrate the issue I have created a toy Phoenix project which sets up a WebSocket connection and displays Phoenix Socket logs on the page. The project is here: https://github.com/laurglia/phoenix-reconnection-issue To reproduce the problem: 1. Clone that repository 2. Run the Phoenix server with `mix phx.server` in somewhere other than your local network 3. Open the index route in Google Chrome 4. Interrupt the network, for example, connect to another WiFi 5. Observe that the Phoenix heartbeat fails and says that it is going to reconnect but in reality it does not immediately reconnect. You can use the "Ping" button on top of the page to also try to push a "ping" packet and observe that it is not sent. 6. Only after around 1-3 minutes, the WebSocket connection is reestablished To make testing easier, I have set up a server which runs the toy project. You can access the server at http://34.219.19.64:4000/. Here is also a video of me reproducing the issue: https://youtu.be/BP3rK06p0Ww This commit fixes the issue by "tearing down" the WebSocket connection after heartbeat timeout instead of just attempting to close it. The teardown functionality does not necessarily close the connection but it will remove all references to it, allowing a new one to be created in place of the current one. I also needed to make some changes to the teardown functionality. Previously, it was not necessary to remove listeners from the connections because once a connection was closed, it was not able for it to emit any events. However, now since the connection may actually stay open for some time and emit a close event after a few minutes, then that could cause problems if the connection was replaced with a new connection. That is why we now we set `this.conn.onopen`, `this.conn.onerror` and other listeners to no-ops when tearing down the connection. On my test server, I am running the updated version of Phoenix on my toy project. You can access the updated version here: http://34.219.19.64:4001/ Here is a video of me showing that the issue has been fixed in the updated version: https://youtu.be/3t4nckli07k [websockets-standard]: https://websockets.spec.whatwg.org/#dom-websocket-close --- assets/js/phoenix/socket.js | 12 ++++++------ assets/test/socket_test.js | 26 ++++++++++++++++++++++++++ priv/static/phoenix.cjs.js | 16 +++++++++------- priv/static/phoenix.cjs.js.map | 4 ++-- priv/static/phoenix.js | 16 +++++++++------- priv/static/phoenix.min.js | 2 +- priv/static/phoenix.mjs | 16 +++++++++------- priv/static/phoenix.mjs.map | 4 ++-- 8 files changed, 64 insertions(+), 32 deletions(-) diff --git a/assets/js/phoenix/socket.js b/assets/js/phoenix/socket.js index 24cad7093b..554b7b8e76 100644 --- a/assets/js/phoenix/socket.js +++ b/assets/js/phoenix/socket.js @@ -335,7 +335,9 @@ export default class Socket { if(this.pendingHeartbeatRef){ this.pendingHeartbeatRef = null if(this.hasLogger()){ this.log("transport", "heartbeat timeout. Attempting to re-establish connection") } - this.abnormalClose("heartbeat timeout") + this.triggerChanError() + this.closeWasClean = false + this.teardown(() => this.reconnectTimer.scheduleTimeout(), WS_CLOSE_NORMAL, "heartbeat timeout") } } @@ -358,6 +360,9 @@ export default class Socket { this.waitForSocketClosed(() => { if(this.conn){ + this.conn.onopen = function (){ } // noop + this.conn.onerror = function (){ } // noop + this.conn.onmessage = function (){ } // noop this.conn.onclose = function (){ } // noop this.conn = null } @@ -514,11 +519,6 @@ export default class Socket { this.heartbeatTimer = setTimeout(() => this.heartbeatTimeout(), this.heartbeatIntervalMs) } - abnormalClose(reason){ - this.closeWasClean = false - if(this.isConnected()){ this.conn.close(WS_CLOSE_NORMAL, reason) } - } - flushSendBuffer(){ if(this.isConnected() && this.sendBuffer.length > 0){ this.sendBuffer.forEach(callback => callback()) diff --git a/assets/test/socket_test.js b/assets/test/socket_test.js index 1daa894eed..eeb6e78d0f 100644 --- a/assets/test/socket_test.js +++ b/assets/test/socket_test.js @@ -691,6 +691,32 @@ describe("with transports", function(){ assert.ok(!spy.calledWith("phx_error")) }) +<<<<<<< HEAD +======= + + it("does not send heartbeat after explicit disconnect", function(done){ + let clock = sinon.useFakeTimers() + const spy = sinon.spy(socket, "sendHeartbeat") + socket.onConnOpen() + socket.disconnect() + clock.tick(30000) + assert.ok(spy.notCalled) + clock.restore() + done() + }) + + it("does not timeout the heartbeat after explicit disconnect", function(done){ + let clock = sinon.useFakeTimers() + const spy = sinon.spy(socket, "heartbeatTimeout") + socket.onConnOpen() + socket.disconnect() + clock.tick(30000) + clock.tick(30000) + assert.ok(spy.notCalled) + clock.restore() + done() + }) +>>>>>>> 1a0e70a7 (Fix reconnecting websockets on heartbeat timeout (#4921)) }) describe("onConnError", function(){ diff --git a/priv/static/phoenix.cjs.js b/priv/static/phoenix.cjs.js index 0ba2027d68..5306da2976 100644 --- a/priv/static/phoenix.cjs.js +++ b/priv/static/phoenix.cjs.js @@ -957,7 +957,9 @@ var Socket = class { if (this.hasLogger()) { this.log("transport", "heartbeat timeout. Attempting to re-establish connection"); } - this.abnormalClose("heartbeat timeout"); + this.triggerChanError(); + this.closeWasClean = false; + this.teardown(() => this.reconnectTimer.scheduleTimeout(), WS_CLOSE_NORMAL, "heartbeat timeout"); } } resetHeartbeat() { @@ -982,6 +984,12 @@ var Socket = class { } this.waitForSocketClosed(() => { if (this.conn) { + this.conn.onopen = function() { + }; + this.conn.onerror = function() { + }; + this.conn.onmessage = function() { + }; this.conn.onclose = function() { }; this.conn = null; @@ -1097,12 +1105,6 @@ var Socket = class { this.push({ topic: "phoenix", event: "heartbeat", payload: {}, ref: this.pendingHeartbeatRef }); this.heartbeatTimer = setTimeout(() => this.heartbeatTimeout(), this.heartbeatIntervalMs); } - abnormalClose(reason) { - this.closeWasClean = false; - if (this.isConnected()) { - this.conn.close(WS_CLOSE_NORMAL, reason); - } - } flushSendBuffer() { if (this.isConnected() && this.sendBuffer.length > 0) { this.sendBuffer.forEach((callback) => callback()); diff --git a/priv/static/phoenix.cjs.js.map b/priv/static/phoenix.cjs.js.map index c076d4e77e..9d6e09ae9f 100644 --- a/priv/static/phoenix.cjs.js.map +++ b/priv/static/phoenix.cjs.js.map @@ -1,7 +1,7 @@ { "version": 3, "sources": ["../../assets/js/phoenix/index.js", "../../assets/js/phoenix/utils.js", "../../assets/js/phoenix/constants.js", "../../assets/js/phoenix/push.js", "../../assets/js/phoenix/timer.js", "../../assets/js/phoenix/channel.js", "../../assets/js/phoenix/ajax.js", "../../assets/js/phoenix/longpoll.js", "../../assets/js/phoenix/presence.js", "../../assets/js/phoenix/serializer.js", "../../assets/js/phoenix/socket.js"], - "sourcesContent": ["/**\n * Phoenix Channels JavaScript client\n *\n * ## Socket Connection\n *\n * A single connection is established to the server and\n * channels are multiplexed over the connection.\n * Connect to the server using the `Socket` class:\n *\n * ```javascript\n * let socket = new Socket(\"/socket\", {params: {userToken: \"123\"}})\n * socket.connect()\n * ```\n *\n * The `Socket` constructor takes the mount point of the socket,\n * the authentication params, as well as options that can be found in\n * the Socket docs, such as configuring the `LongPoll` transport, and\n * heartbeat.\n *\n * ## Channels\n *\n * Channels are isolated, concurrent processes on the server that\n * subscribe to topics and broker events between the client and server.\n * To join a channel, you must provide the topic, and channel params for\n * authorization. Here's an example chat room example where `\"new_msg\"`\n * events are listened for, messages are pushed to the server, and\n * the channel is joined with ok/error/timeout matches:\n *\n * ```javascript\n * let channel = socket.channel(\"room:123\", {token: roomToken})\n * channel.on(\"new_msg\", msg => console.log(\"Got message\", msg) )\n * $input.onEnter( e => {\n * channel.push(\"new_msg\", {body: e.target.val}, 10000)\n * .receive(\"ok\", (msg) => console.log(\"created message\", msg) )\n * .receive(\"error\", (reasons) => console.log(\"create failed\", reasons) )\n * .receive(\"timeout\", () => console.log(\"Networking issue...\") )\n * })\n *\n * channel.join()\n * .receive(\"ok\", ({messages}) => console.log(\"catching up\", messages) )\n * .receive(\"error\", ({reason}) => console.log(\"failed join\", reason) )\n * .receive(\"timeout\", () => console.log(\"Networking issue. Still waiting...\"))\n *```\n *\n * ## Joining\n *\n * Creating a channel with `socket.channel(topic, params)`, binds the params to\n * `channel.params`, which are sent up on `channel.join()`.\n * Subsequent rejoins will send up the modified params for\n * updating authorization params, or passing up last_message_id information.\n * Successful joins receive an \"ok\" status, while unsuccessful joins\n * receive \"error\".\n *\n * With the default serializers and WebSocket transport, JSON text frames are\n * used for pushing a JSON object literal. If an `ArrayBuffer` instance is provided,\n * binary encoding will be used and the message will be sent with the binary\n * opcode.\n *\n * *Note*: binary messages are only supported on the WebSocket transport.\n *\n * ## Duplicate Join Subscriptions\n *\n * While the client may join any number of topics on any number of channels,\n * the client may only hold a single subscription for each unique topic at any\n * given time. When attempting to create a duplicate subscription,\n * the server will close the existing channel, log a warning, and\n * spawn a new channel for the topic. The client will have their\n * `channel.onClose` callbacks fired for the existing channel, and the new\n * channel join will have its receive hooks processed as normal.\n *\n * ## Pushing Messages\n *\n * From the previous example, we can see that pushing messages to the server\n * can be done with `channel.push(eventName, payload)` and we can optionally\n * receive responses from the push. Additionally, we can use\n * `receive(\"timeout\", callback)` to abort waiting for our other `receive` hooks\n * and take action after some period of waiting. The default timeout is 10000ms.\n *\n *\n * ## Socket Hooks\n *\n * Lifecycle events of the multiplexed connection can be hooked into via\n * `socket.onError()` and `socket.onClose()` events, ie:\n *\n * ```javascript\n * socket.onError( () => console.log(\"there was an error with the connection!\") )\n * socket.onClose( () => console.log(\"the connection dropped\") )\n * ```\n *\n *\n * ## Channel Hooks\n *\n * For each joined channel, you can bind to `onError` and `onClose` events\n * to monitor the channel lifecycle, ie:\n *\n * ```javascript\n * channel.onError( () => console.log(\"there was an error!\") )\n * channel.onClose( () => console.log(\"the channel has gone away gracefully\") )\n * ```\n *\n * ### onError hooks\n *\n * `onError` hooks are invoked if the socket connection drops, or the channel\n * crashes on the server. In either case, a channel rejoin is attempted\n * automatically in an exponential backoff manner.\n *\n * ### onClose hooks\n *\n * `onClose` hooks are invoked only in two cases. 1) the channel explicitly\n * closed on the server, or 2). The client explicitly closed, by calling\n * `channel.leave()`\n *\n *\n * ## Presence\n *\n * The `Presence` object provides features for syncing presence information\n * from the server with the client and handling presences joining and leaving.\n *\n * ### Syncing state from the server\n *\n * To sync presence state from the server, first instantiate an object and\n * pass your channel in to track lifecycle events:\n *\n * ```javascript\n * let channel = socket.channel(\"some:topic\")\n * let presence = new Presence(channel)\n * ```\n *\n * Next, use the `presence.onSync` callback to react to state changes\n * from the server. For example, to render the list of users every time\n * the list changes, you could write:\n *\n * ```javascript\n * presence.onSync(() => {\n * myRenderUsersFunction(presence.list())\n * })\n * ```\n *\n * ### Listing Presences\n *\n * `presence.list` is used to return a list of presence information\n * based on the local state of metadata. By default, all presence\n * metadata is returned, but a `listBy` function can be supplied to\n * allow the client to select which metadata to use for a given presence.\n * For example, you may have a user online from different devices with\n * a metadata status of \"online\", but they have set themselves to \"away\"\n * on another device. In this case, the app may choose to use the \"away\"\n * status for what appears on the UI. The example below defines a `listBy`\n * function which prioritizes the first metadata which was registered for\n * each user. This could be the first tab they opened, or the first device\n * they came online from:\n *\n * ```javascript\n * let listBy = (id, {metas: [first, ...rest]}) => {\n * first.count = rest.length + 1 // count of this user's presences\n * first.id = id\n * return first\n * }\n * let onlineUsers = presence.list(listBy)\n * ```\n *\n * ### Handling individual presence join and leave events\n *\n * The `presence.onJoin` and `presence.onLeave` callbacks can be used to\n * react to individual presences joining and leaving the app. For example:\n *\n * ```javascript\n * let presence = new Presence(channel)\n *\n * // detect if user has joined for the 1st time or from another tab/device\n * presence.onJoin((id, current, newPres) => {\n * if(!current){\n * console.log(\"user has entered for the first time\", newPres)\n * } else {\n * console.log(\"user additional presence\", newPres)\n * }\n * })\n *\n * // detect if user has left from all tabs/devices, or is still present\n * presence.onLeave((id, current, leftPres) => {\n * if(current.metas.length === 0){\n * console.log(\"user has left from all devices\", leftPres)\n * } else {\n * console.log(\"user left from a device\", leftPres)\n * }\n * })\n * // receive presence data from server\n * presence.onSync(() => {\n * displayUsers(presence.list())\n * })\n * ```\n * @module phoenix\n */\n\nimport Channel from \"./channel\"\nimport LongPoll from \"./longpoll\"\nimport Presence from \"./presence\"\nimport Serializer from \"./serializer\"\nimport Socket from \"./socket\"\n\nexport {\n Channel,\n LongPoll,\n Presence,\n Serializer,\n Socket\n}\n", "// wraps value in closure or returns closure\nexport let closure = (value) => {\n if(typeof value === \"function\"){\n return value\n } else {\n let closure = function (){ return value }\n return closure\n }\n}\n", "export const globalSelf = typeof self !== \"undefined\" ? self : null\nexport const phxWindow = typeof window !== \"undefined\" ? window : null\nexport const global = globalSelf || phxWindow || global\nexport const DEFAULT_VSN = \"2.0.0\"\nexport const SOCKET_STATES = {connecting: 0, open: 1, closing: 2, closed: 3}\nexport const DEFAULT_TIMEOUT = 10000\nexport const WS_CLOSE_NORMAL = 1000\nexport const CHANNEL_STATES = {\n closed: \"closed\",\n errored: \"errored\",\n joined: \"joined\",\n joining: \"joining\",\n leaving: \"leaving\",\n}\nexport const CHANNEL_EVENTS = {\n close: \"phx_close\",\n error: \"phx_error\",\n join: \"phx_join\",\n reply: \"phx_reply\",\n leave: \"phx_leave\"\n}\n\nexport const TRANSPORTS = {\n longpoll: \"longpoll\",\n websocket: \"websocket\"\n}\nexport const XHR_STATES = {\n complete: 4\n}\n", "/**\n * Initializes the Push\n * @param {Channel} channel - The Channel\n * @param {string} event - The event, for example `\"phx_join\"`\n * @param {Object} payload - The payload, for example `{user_id: 123}`\n * @param {number} timeout - The push timeout in milliseconds\n */\nexport default class Push {\n constructor(channel, event, payload, timeout){\n this.channel = channel\n this.event = event\n this.payload = payload || function (){ return {} }\n this.receivedResp = null\n this.timeout = timeout\n this.timeoutTimer = null\n this.recHooks = []\n this.sent = false\n }\n\n /**\n *\n * @param {number} timeout\n */\n resend(timeout){\n this.timeout = timeout\n this.reset()\n this.send()\n }\n\n /**\n *\n */\n send(){\n if(this.hasReceived(\"timeout\")){ return }\n this.startTimeout()\n this.sent = true\n this.channel.socket.push({\n topic: this.channel.topic,\n event: this.event,\n payload: this.payload(),\n ref: this.ref,\n join_ref: this.channel.joinRef()\n })\n }\n\n /**\n *\n * @param {*} status\n * @param {*} callback\n */\n receive(status, callback){\n if(this.hasReceived(status)){\n callback(this.receivedResp.response)\n }\n\n this.recHooks.push({status, callback})\n return this\n }\n\n /**\n * @private\n */\n reset(){\n this.cancelRefEvent()\n this.ref = null\n this.refEvent = null\n this.receivedResp = null\n this.sent = false\n }\n\n /**\n * @private\n */\n matchReceive({status, response, _ref}){\n this.recHooks.filter(h => h.status === status)\n .forEach(h => h.callback(response))\n }\n\n /**\n * @private\n */\n cancelRefEvent(){\n if(!this.refEvent){ return }\n this.channel.off(this.refEvent)\n }\n\n /**\n * @private\n */\n cancelTimeout(){\n clearTimeout(this.timeoutTimer)\n this.timeoutTimer = null\n }\n\n /**\n * @private\n */\n startTimeout(){\n if(this.timeoutTimer){ this.cancelTimeout() }\n this.ref = this.channel.socket.makeRef()\n this.refEvent = this.channel.replyEventName(this.ref)\n\n this.channel.on(this.refEvent, payload => {\n this.cancelRefEvent()\n this.cancelTimeout()\n this.receivedResp = payload\n this.matchReceive(payload)\n })\n\n this.timeoutTimer = setTimeout(() => {\n this.trigger(\"timeout\", {})\n }, this.timeout)\n }\n\n /**\n * @private\n */\n hasReceived(status){\n return this.receivedResp && this.receivedResp.status === status\n }\n\n /**\n * @private\n */\n trigger(status, response){\n this.channel.trigger(this.refEvent, {status, response})\n }\n}\n", "/**\n *\n * Creates a timer that accepts a `timerCalc` function to perform\n * calculated timeout retries, such as exponential backoff.\n *\n * @example\n * let reconnectTimer = new Timer(() => this.connect(), function(tries){\n * return [1000, 5000, 10000][tries - 1] || 10000\n * })\n * reconnectTimer.scheduleTimeout() // fires after 1000\n * reconnectTimer.scheduleTimeout() // fires after 5000\n * reconnectTimer.reset()\n * reconnectTimer.scheduleTimeout() // fires after 1000\n *\n * @param {Function} callback\n * @param {Function} timerCalc\n */\nexport default class Timer {\n constructor(callback, timerCalc){\n this.callback = callback\n this.timerCalc = timerCalc\n this.timer = null\n this.tries = 0\n }\n\n reset(){\n this.tries = 0\n clearTimeout(this.timer)\n }\n\n /**\n * Cancels any previous scheduleTimeout and schedules callback\n */\n scheduleTimeout(){\n clearTimeout(this.timer)\n\n this.timer = setTimeout(() => {\n this.tries = this.tries + 1\n this.callback()\n }, this.timerCalc(this.tries + 1))\n }\n}\n", "import {closure} from \"./utils\"\nimport {\n CHANNEL_EVENTS,\n CHANNEL_STATES,\n} from \"./constants\"\n\nimport Push from \"./push\"\nimport Timer from \"./timer\"\n\n/**\n *\n * @param {string} topic\n * @param {(Object|function)} params\n * @param {Socket} socket\n */\nexport default class Channel {\n constructor(topic, params, socket){\n this.state = CHANNEL_STATES.closed\n this.topic = topic\n this.params = closure(params || {})\n this.socket = socket\n this.bindings = []\n this.bindingRef = 0\n this.timeout = this.socket.timeout\n this.joinedOnce = false\n this.joinPush = new Push(this, CHANNEL_EVENTS.join, this.params, this.timeout)\n this.pushBuffer = []\n this.stateChangeRefs = []\n\n this.rejoinTimer = new Timer(() => {\n if(this.socket.isConnected()){ this.rejoin() }\n }, this.socket.rejoinAfterMs)\n this.stateChangeRefs.push(this.socket.onError(() => this.rejoinTimer.reset()))\n this.stateChangeRefs.push(this.socket.onOpen(() => {\n this.rejoinTimer.reset()\n if(this.isErrored()){ this.rejoin() }\n })\n )\n this.joinPush.receive(\"ok\", () => {\n this.state = CHANNEL_STATES.joined\n this.rejoinTimer.reset()\n this.pushBuffer.forEach(pushEvent => pushEvent.send())\n this.pushBuffer = []\n })\n this.joinPush.receive(\"error\", () => {\n this.state = CHANNEL_STATES.errored\n if(this.socket.isConnected()){ this.rejoinTimer.scheduleTimeout() }\n })\n this.onClose(() => {\n this.rejoinTimer.reset()\n if(this.socket.hasLogger()) this.socket.log(\"channel\", `close ${this.topic} ${this.joinRef()}`)\n this.state = CHANNEL_STATES.closed\n this.socket.remove(this)\n })\n this.onError(reason => {\n if(this.socket.hasLogger()) this.socket.log(\"channel\", `error ${this.topic}`, reason)\n if(this.isJoining()){ this.joinPush.reset() }\n this.state = CHANNEL_STATES.errored\n if(this.socket.isConnected()){ this.rejoinTimer.scheduleTimeout() }\n })\n this.joinPush.receive(\"timeout\", () => {\n if(this.socket.hasLogger()) this.socket.log(\"channel\", `timeout ${this.topic} (${this.joinRef()})`, this.joinPush.timeout)\n let leavePush = new Push(this, CHANNEL_EVENTS.leave, closure({}), this.timeout)\n leavePush.send()\n this.state = CHANNEL_STATES.errored\n this.joinPush.reset()\n if(this.socket.isConnected()){ this.rejoinTimer.scheduleTimeout() }\n })\n this.on(CHANNEL_EVENTS.reply, (payload, ref) => {\n this.trigger(this.replyEventName(ref), payload)\n })\n }\n\n /**\n * Join the channel\n * @param {integer} timeout\n * @returns {Push}\n */\n join(timeout = this.timeout){\n if(this.joinedOnce){\n throw new Error(\"tried to join multiple times. 'join' can only be called a single time per channel instance\")\n } else {\n this.timeout = timeout\n this.joinedOnce = true\n this.rejoin()\n return this.joinPush\n }\n }\n\n /**\n * Hook into channel close\n * @param {Function} callback\n */\n onClose(callback){\n this.on(CHANNEL_EVENTS.close, callback)\n }\n\n /**\n * Hook into channel errors\n * @param {Function} callback\n */\n onError(callback){\n return this.on(CHANNEL_EVENTS.error, reason => callback(reason))\n }\n\n /**\n * Subscribes on channel events\n *\n * Subscription returns a ref counter, which can be used later to\n * unsubscribe the exact event listener\n *\n * @example\n * const ref1 = channel.on(\"event\", do_stuff)\n * const ref2 = channel.on(\"event\", do_other_stuff)\n * channel.off(\"event\", ref1)\n * // Since unsubscription, do_stuff won't fire,\n * // while do_other_stuff will keep firing on the \"event\"\n *\n * @param {string} event\n * @param {Function} callback\n * @returns {integer} ref\n */\n on(event, callback){\n let ref = this.bindingRef++\n this.bindings.push({event, ref, callback})\n return ref\n }\n\n /**\n * Unsubscribes off of channel events\n *\n * Use the ref returned from a channel.on() to unsubscribe one\n * handler, or pass nothing for the ref to unsubscribe all\n * handlers for the given event.\n *\n * @example\n * // Unsubscribe the do_stuff handler\n * const ref1 = channel.on(\"event\", do_stuff)\n * channel.off(\"event\", ref1)\n *\n * // Unsubscribe all handlers from event\n * channel.off(\"event\")\n *\n * @param {string} event\n * @param {integer} ref\n */\n off(event, ref){\n this.bindings = this.bindings.filter((bind) => {\n return !(bind.event === event && (typeof ref === \"undefined\" || ref === bind.ref))\n })\n }\n\n /**\n * @private\n */\n canPush(){ return this.socket.isConnected() && this.isJoined() }\n\n /**\n * Sends a message `event` to phoenix with the payload `payload`.\n * Phoenix receives this in the `handle_in(event, payload, socket)`\n * function. if phoenix replies or it times out (default 10000ms),\n * then optionally the reply can be received.\n *\n * @example\n * channel.push(\"event\")\n * .receive(\"ok\", payload => console.log(\"phoenix replied:\", payload))\n * .receive(\"error\", err => console.log(\"phoenix errored\", err))\n * .receive(\"timeout\", () => console.log(\"timed out pushing\"))\n * @param {string} event\n * @param {Object} payload\n * @param {number} [timeout]\n * @returns {Push}\n */\n push(event, payload, timeout = this.timeout){\n payload = payload || {}\n if(!this.joinedOnce){\n throw new Error(`tried to push '${event}' to '${this.topic}' before joining. Use channel.join() before pushing events`)\n }\n let pushEvent = new Push(this, event, function (){ return payload }, timeout)\n if(this.canPush()){\n pushEvent.send()\n } else {\n pushEvent.startTimeout()\n this.pushBuffer.push(pushEvent)\n }\n\n return pushEvent\n }\n\n /** Leaves the channel\n *\n * Unsubscribes from server events, and\n * instructs channel to terminate on server\n *\n * Triggers onClose() hooks\n *\n * To receive leave acknowledgements, use the `receive`\n * hook to bind to the server ack, ie:\n *\n * @example\n * channel.leave().receive(\"ok\", () => alert(\"left!\") )\n *\n * @param {integer} timeout\n * @returns {Push}\n */\n leave(timeout = this.timeout){\n this.rejoinTimer.reset()\n this.joinPush.cancelTimeout()\n\n this.state = CHANNEL_STATES.leaving\n let onClose = () => {\n if(this.socket.hasLogger()) this.socket.log(\"channel\", `leave ${this.topic}`)\n this.trigger(CHANNEL_EVENTS.close, \"leave\")\n }\n let leavePush = new Push(this, CHANNEL_EVENTS.leave, closure({}), timeout)\n leavePush.receive(\"ok\", () => onClose())\n .receive(\"timeout\", () => onClose())\n leavePush.send()\n if(!this.canPush()){ leavePush.trigger(\"ok\", {}) }\n\n return leavePush\n }\n\n /**\n * Overridable message hook\n *\n * Receives all events for specialized message handling\n * before dispatching to the channel callbacks.\n *\n * Must return the payload, modified or unmodified\n * @param {string} event\n * @param {Object} payload\n * @param {integer} ref\n * @returns {Object}\n */\n onMessage(_event, payload, _ref){ return payload }\n\n /**\n * @private\n */\n isMember(topic, event, payload, joinRef){\n if(this.topic !== topic){ return false }\n\n if(joinRef && joinRef !== this.joinRef()){\n if(this.socket.hasLogger()) this.socket.log(\"channel\", \"dropping outdated message\", {topic, event, payload, joinRef})\n return false\n } else {\n return true\n }\n }\n\n /**\n * @private\n */\n joinRef(){ return this.joinPush.ref }\n\n /**\n * @private\n */\n rejoin(timeout = this.timeout){\n if(this.isLeaving()){ return }\n this.socket.leaveOpenTopic(this.topic)\n this.state = CHANNEL_STATES.joining\n this.joinPush.resend(timeout)\n }\n\n /**\n * @private\n */\n trigger(event, payload, ref, joinRef){\n let handledPayload = this.onMessage(event, payload, ref, joinRef)\n if(payload && !handledPayload){ throw new Error(\"channel onMessage callbacks must return the payload, modified or unmodified\") }\n\n let eventBindings = this.bindings.filter(bind => bind.event === event)\n\n for(let i = 0; i < eventBindings.length; i++){\n let bind = eventBindings[i]\n bind.callback(handledPayload, ref, joinRef || this.joinRef())\n }\n }\n\n /**\n * @private\n */\n replyEventName(ref){ return `chan_reply_${ref}` }\n\n /**\n * @private\n */\n isClosed(){ return this.state === CHANNEL_STATES.closed }\n\n /**\n * @private\n */\n isErrored(){ return this.state === CHANNEL_STATES.errored }\n\n /**\n * @private\n */\n isJoined(){ return this.state === CHANNEL_STATES.joined }\n\n /**\n * @private\n */\n isJoining(){ return this.state === CHANNEL_STATES.joining }\n\n /**\n * @private\n */\n isLeaving(){ return this.state === CHANNEL_STATES.leaving }\n}\n", "import {\n global,\n XHR_STATES\n} from \"./constants\"\n\nexport default class Ajax {\n\n static request(method, endPoint, accept, body, timeout, ontimeout, callback){\n if(global.XDomainRequest){\n let req = new global.XDomainRequest() // IE8, IE9\n return this.xdomainRequest(req, method, endPoint, body, timeout, ontimeout, callback)\n } else {\n let req = new global.XMLHttpRequest() // IE7+, Firefox, Chrome, Opera, Safari\n return this.xhrRequest(req, method, endPoint, accept, body, timeout, ontimeout, callback)\n }\n }\n\n static xdomainRequest(req, method, endPoint, body, timeout, ontimeout, callback){\n req.timeout = timeout\n req.open(method, endPoint)\n req.onload = () => {\n let response = this.parseJSON(req.responseText)\n callback && callback(response)\n }\n if(ontimeout){ req.ontimeout = ontimeout }\n\n // Work around bug in IE9 that requires an attached onprogress handler\n req.onprogress = () => { }\n\n req.send(body)\n return req\n }\n\n static xhrRequest(req, method, endPoint, accept, body, timeout, ontimeout, callback){\n req.open(method, endPoint, true)\n req.timeout = timeout\n req.setRequestHeader(\"Content-Type\", accept)\n req.onerror = () => callback && callback(null)\n req.onreadystatechange = () => {\n if(req.readyState === XHR_STATES.complete && callback){\n let response = this.parseJSON(req.responseText)\n callback(response)\n }\n }\n if(ontimeout){ req.ontimeout = ontimeout }\n\n req.send(body)\n return req\n }\n\n static parseJSON(resp){\n if(!resp || resp === \"\"){ return null }\n\n try {\n return JSON.parse(resp)\n } catch (e){\n console && console.log(\"failed to parse JSON response\", resp)\n return null\n }\n }\n\n static serialize(obj, parentKey){\n let queryStr = []\n for(var key in obj){\n if(!Object.prototype.hasOwnProperty.call(obj, key)){ continue }\n let paramKey = parentKey ? `${parentKey}[${key}]` : key\n let paramVal = obj[key]\n if(typeof paramVal === \"object\"){\n queryStr.push(this.serialize(paramVal, paramKey))\n } else {\n queryStr.push(encodeURIComponent(paramKey) + \"=\" + encodeURIComponent(paramVal))\n }\n }\n return queryStr.join(\"&\")\n }\n\n static appendParams(url, params){\n if(Object.keys(params).length === 0){ return url }\n\n let prefix = url.match(/\\?/) ? \"&\" : \"?\"\n return `${url}${prefix}${this.serialize(params)}`\n }\n}\n", "import {\n SOCKET_STATES,\n TRANSPORTS\n} from \"./constants\"\n\nimport Ajax from \"./ajax\"\n\nexport default class LongPoll {\n\n constructor(endPoint){\n this.endPoint = null\n this.token = null\n this.skipHeartbeat = true\n this.reqs = new Set()\n this.onopen = function (){ } // noop\n this.onerror = function (){ } // noop\n this.onmessage = function (){ } // noop\n this.onclose = function (){ } // noop\n this.pollEndpoint = this.normalizeEndpoint(endPoint)\n this.readyState = SOCKET_STATES.connecting\n this.poll()\n }\n\n normalizeEndpoint(endPoint){\n return (endPoint\n .replace(\"ws://\", \"http://\")\n .replace(\"wss://\", \"https://\")\n .replace(new RegExp(\"(.*)\\/\" + TRANSPORTS.websocket), \"$1/\" + TRANSPORTS.longpoll))\n }\n\n endpointURL(){\n return Ajax.appendParams(this.pollEndpoint, {token: this.token})\n }\n\n closeAndRetry(code, reason, wasClean){\n this.close(code, reason, wasClean)\n this.readyState = SOCKET_STATES.connecting\n }\n\n ontimeout(){\n this.onerror(\"timeout\")\n this.closeAndRetry(1005, \"timeout\", false)\n }\n\n isActive(){ return this.readyState === SOCKET_STATES.open || this.readyState === SOCKET_STATES.connecting }\n\n poll(){\n this.ajax(\"GET\", null, () => this.ontimeout(), resp => {\n if(resp){\n var {status, token, messages} = resp\n this.token = token\n } else {\n status = 0\n }\n\n switch(status){\n case 200:\n messages.forEach(msg => {\n // Tasks are what things like event handlers, setTimeout callbacks,\n // promise resolves and more are run within.\n // In modern browsers, there are two different kinds of tasks,\n // microtasks and macrotasks.\n // Microtasks are mainly used for Promises, while macrotasks are\n // used for everything else.\n // Microtasks always have priority over macrotasks. If the JS engine\n // is looking for a task to run, it will always try to empty the\n // microtask queue before attempting to run anything from the\n // macrotask queue.\n //\n // For the WebSocket transport, messages always arrive in their own\n // event. This means that if any promises are resolved from within,\n // their callbacks will always finish execution by the time the\n // next message event handler is run.\n //\n // In order to emulate this behaviour, we need to make sure each\n // onmessage handler is run within it's own macrotask.\n setTimeout(() => this.onmessage({data: msg}), 0)\n })\n this.poll()\n break\n case 204:\n this.poll()\n break\n case 410:\n this.readyState = SOCKET_STATES.open\n this.onopen({})\n this.poll()\n break\n case 403:\n this.onerror(403)\n this.close(1008, \"forbidden\", false)\n break\n case 0:\n case 500:\n this.onerror(500)\n this.closeAndRetry(1011, \"internal server error\", 500)\n break\n default: throw new Error(`unhandled poll status ${status}`)\n }\n })\n }\n\n send(body){\n this.ajax(\"POST\", body, () => this.onerror(\"timeout\"), resp => {\n if(!resp || resp.status !== 200){\n this.onerror(resp && resp.status)\n this.closeAndRetry(1011, \"internal server error\", false)\n }\n })\n }\n\n close(code, reason, wasClean){\n for(let req of this.reqs){ req.abort() }\n this.readyState = SOCKET_STATES.closed\n let opts = Object.assign({code: 1000, reason: undefined, wasClean: true}, {code, reason, wasClean})\n if(typeof(CloseEvent) !== \"undefined\"){\n this.onclose(new CloseEvent(\"close\", opts))\n } else {\n this.onclose(opts)\n }\n }\n\n ajax(method, body, onCallerTimeout, callback){\n let req\n let ontimeout = () => {\n this.reqs.delete(req)\n onCallerTimeout()\n }\n req = Ajax.request(method, this.endpointURL(), \"application/json\", body, this.timeout, ontimeout, resp => {\n this.reqs.delete(req)\n if(this.isActive()){ callback(resp) }\n })\n this.reqs.add(req)\n }\n}\n", "/**\n * Initializes the Presence\n * @param {Channel} channel - The Channel\n * @param {Object} opts - The options,\n * for example `{events: {state: \"state\", diff: \"diff\"}}`\n */\nexport default class Presence {\n\n constructor(channel, opts = {}){\n let events = opts.events || {state: \"presence_state\", diff: \"presence_diff\"}\n this.state = {}\n this.pendingDiffs = []\n this.channel = channel\n this.joinRef = null\n this.caller = {\n onJoin: function (){ },\n onLeave: function (){ },\n onSync: function (){ }\n }\n\n this.channel.on(events.state, newState => {\n let {onJoin, onLeave, onSync} = this.caller\n\n this.joinRef = this.channel.joinRef()\n this.state = Presence.syncState(this.state, newState, onJoin, onLeave)\n\n this.pendingDiffs.forEach(diff => {\n this.state = Presence.syncDiff(this.state, diff, onJoin, onLeave)\n })\n this.pendingDiffs = []\n onSync()\n })\n\n this.channel.on(events.diff, diff => {\n let {onJoin, onLeave, onSync} = this.caller\n\n if(this.inPendingSyncState()){\n this.pendingDiffs.push(diff)\n } else {\n this.state = Presence.syncDiff(this.state, diff, onJoin, onLeave)\n onSync()\n }\n })\n }\n\n onJoin(callback){ this.caller.onJoin = callback }\n\n onLeave(callback){ this.caller.onLeave = callback }\n\n onSync(callback){ this.caller.onSync = callback }\n\n list(by){ return Presence.list(this.state, by) }\n\n inPendingSyncState(){\n return !this.joinRef || (this.joinRef !== this.channel.joinRef())\n }\n\n // lower-level public static API\n\n /**\n * Used to sync the list of presences on the server\n * with the client's state. An optional `onJoin` and `onLeave` callback can\n * be provided to react to changes in the client's local presences across\n * disconnects and reconnects with the server.\n *\n * @returns {Presence}\n */\n static syncState(currentState, newState, onJoin, onLeave){\n let state = this.clone(currentState)\n let joins = {}\n let leaves = {}\n\n this.map(state, (key, presence) => {\n if(!newState[key]){\n leaves[key] = presence\n }\n })\n this.map(newState, (key, newPresence) => {\n let currentPresence = state[key]\n if(currentPresence){\n let newRefs = newPresence.metas.map(m => m.phx_ref)\n let curRefs = currentPresence.metas.map(m => m.phx_ref)\n let joinedMetas = newPresence.metas.filter(m => curRefs.indexOf(m.phx_ref) < 0)\n let leftMetas = currentPresence.metas.filter(m => newRefs.indexOf(m.phx_ref) < 0)\n if(joinedMetas.length > 0){\n joins[key] = newPresence\n joins[key].metas = joinedMetas\n }\n if(leftMetas.length > 0){\n leaves[key] = this.clone(currentPresence)\n leaves[key].metas = leftMetas\n }\n } else {\n joins[key] = newPresence\n }\n })\n return this.syncDiff(state, {joins: joins, leaves: leaves}, onJoin, onLeave)\n }\n\n /**\n *\n * Used to sync a diff of presence join and leave\n * events from the server, as they happen. Like `syncState`, `syncDiff`\n * accepts optional `onJoin` and `onLeave` callbacks to react to a user\n * joining or leaving from a device.\n *\n * @returns {Presence}\n */\n static syncDiff(state, diff, onJoin, onLeave){\n let {joins, leaves} = this.clone(diff)\n if(!onJoin){ onJoin = function (){ } }\n if(!onLeave){ onLeave = function (){ } }\n\n this.map(joins, (key, newPresence) => {\n let currentPresence = state[key]\n state[key] = this.clone(newPresence)\n if(currentPresence){\n let joinedRefs = state[key].metas.map(m => m.phx_ref)\n let curMetas = currentPresence.metas.filter(m => joinedRefs.indexOf(m.phx_ref) < 0)\n state[key].metas.unshift(...curMetas)\n }\n onJoin(key, currentPresence, newPresence)\n })\n this.map(leaves, (key, leftPresence) => {\n let currentPresence = state[key]\n if(!currentPresence){ return }\n let refsToRemove = leftPresence.metas.map(m => m.phx_ref)\n currentPresence.metas = currentPresence.metas.filter(p => {\n return refsToRemove.indexOf(p.phx_ref) < 0\n })\n onLeave(key, currentPresence, leftPresence)\n if(currentPresence.metas.length === 0){\n delete state[key]\n }\n })\n return state\n }\n\n /**\n * Returns the array of presences, with selected metadata.\n *\n * @param {Object} presences\n * @param {Function} chooser\n *\n * @returns {Presence}\n */\n static list(presences, chooser){\n if(!chooser){ chooser = function (key, pres){ return pres } }\n\n return this.map(presences, (key, presence) => {\n return chooser(key, presence)\n })\n }\n\n // private\n\n static map(obj, func){\n return Object.getOwnPropertyNames(obj).map(key => func(key, obj[key]))\n }\n\n static clone(obj){ return JSON.parse(JSON.stringify(obj)) }\n}\n", "/* The default serializer for encoding and decoding messages */\nimport {\n CHANNEL_EVENTS\n} from \"./constants\"\n\nexport default {\n HEADER_LENGTH: 1,\n META_LENGTH: 4,\n KINDS: {push: 0, reply: 1, broadcast: 2},\n\n encode(msg, callback){\n if(msg.payload.constructor === ArrayBuffer){\n return callback(this.binaryEncode(msg))\n } else {\n let payload = [msg.join_ref, msg.ref, msg.topic, msg.event, msg.payload]\n return callback(JSON.stringify(payload))\n }\n },\n\n decode(rawPayload, callback){\n if(rawPayload.constructor === ArrayBuffer){\n return callback(this.binaryDecode(rawPayload))\n } else {\n let [join_ref, ref, topic, event, payload] = JSON.parse(rawPayload)\n return callback({join_ref, ref, topic, event, payload})\n }\n },\n\n // private\n\n binaryEncode(message){\n let {join_ref, ref, event, topic, payload} = message\n let metaLength = this.META_LENGTH + join_ref.length + ref.length + topic.length + event.length\n let header = new ArrayBuffer(this.HEADER_LENGTH + metaLength)\n let view = new DataView(header)\n let offset = 0\n\n view.setUint8(offset++, this.KINDS.push) // kind\n view.setUint8(offset++, join_ref.length)\n view.setUint8(offset++, ref.length)\n view.setUint8(offset++, topic.length)\n view.setUint8(offset++, event.length)\n Array.from(join_ref, char => view.setUint8(offset++, char.charCodeAt(0)))\n Array.from(ref, char => view.setUint8(offset++, char.charCodeAt(0)))\n Array.from(topic, char => view.setUint8(offset++, char.charCodeAt(0)))\n Array.from(event, char => view.setUint8(offset++, char.charCodeAt(0)))\n\n var combined = new Uint8Array(header.byteLength + payload.byteLength)\n combined.set(new Uint8Array(header), 0)\n combined.set(new Uint8Array(payload), header.byteLength)\n\n return combined.buffer\n },\n\n binaryDecode(buffer){\n let view = new DataView(buffer)\n let kind = view.getUint8(0)\n let decoder = new TextDecoder()\n switch(kind){\n case this.KINDS.push: return this.decodePush(buffer, view, decoder)\n case this.KINDS.reply: return this.decodeReply(buffer, view, decoder)\n case this.KINDS.broadcast: return this.decodeBroadcast(buffer, view, decoder)\n }\n },\n\n decodePush(buffer, view, decoder){\n let joinRefSize = view.getUint8(1)\n let topicSize = view.getUint8(2)\n let eventSize = view.getUint8(3)\n let offset = this.HEADER_LENGTH + this.META_LENGTH - 1 // pushes have no ref\n let joinRef = decoder.decode(buffer.slice(offset, offset + joinRefSize))\n offset = offset + joinRefSize\n let topic = decoder.decode(buffer.slice(offset, offset + topicSize))\n offset = offset + topicSize\n let event = decoder.decode(buffer.slice(offset, offset + eventSize))\n offset = offset + eventSize\n let data = buffer.slice(offset, buffer.byteLength)\n return {join_ref: joinRef, ref: null, topic: topic, event: event, payload: data}\n },\n\n decodeReply(buffer, view, decoder){\n let joinRefSize = view.getUint8(1)\n let refSize = view.getUint8(2)\n let topicSize = view.getUint8(3)\n let eventSize = view.getUint8(4)\n let offset = this.HEADER_LENGTH + this.META_LENGTH\n let joinRef = decoder.decode(buffer.slice(offset, offset + joinRefSize))\n offset = offset + joinRefSize\n let ref = decoder.decode(buffer.slice(offset, offset + refSize))\n offset = offset + refSize\n let topic = decoder.decode(buffer.slice(offset, offset + topicSize))\n offset = offset + topicSize\n let event = decoder.decode(buffer.slice(offset, offset + eventSize))\n offset = offset + eventSize\n let data = buffer.slice(offset, buffer.byteLength)\n let payload = {status: event, response: data}\n return {join_ref: joinRef, ref: ref, topic: topic, event: CHANNEL_EVENTS.reply, payload: payload}\n },\n\n decodeBroadcast(buffer, view, decoder){\n let topicSize = view.getUint8(1)\n let eventSize = view.getUint8(2)\n let offset = this.HEADER_LENGTH + 2\n let topic = decoder.decode(buffer.slice(offset, offset + topicSize))\n offset = offset + topicSize\n let event = decoder.decode(buffer.slice(offset, offset + eventSize))\n offset = offset + eventSize\n let data = buffer.slice(offset, buffer.byteLength)\n\n return {join_ref: null, ref: null, topic: topic, event: event, payload: data}\n }\n}\n", "import {\n global,\n phxWindow,\n CHANNEL_EVENTS,\n DEFAULT_TIMEOUT,\n DEFAULT_VSN,\n SOCKET_STATES,\n TRANSPORTS,\n WS_CLOSE_NORMAL\n} from \"./constants\"\n\nimport {\n closure\n} from \"./utils\"\n\nimport Ajax from \"./ajax\"\nimport Channel from \"./channel\"\nimport LongPoll from \"./longpoll\"\nimport Serializer from \"./serializer\"\nimport Timer from \"./timer\"\n\n/** Initializes the Socket *\n *\n * For IE8 support use an ES5-shim (https://github.com/es-shims/es5-shim)\n *\n * @param {string} endPoint - The string WebSocket endpoint, ie, `\"ws://example.com/socket\"`,\n * `\"wss://example.com\"`\n * `\"/socket\"` (inherited host & protocol)\n * @param {Object} [opts] - Optional configuration\n * @param {Function} [opts.transport] - The Websocket Transport, for example WebSocket or Phoenix.LongPoll.\n *\n * Defaults to WebSocket with automatic LongPoll fallback.\n * @param {Function} [opts.encode] - The function to encode outgoing messages.\n *\n * Defaults to JSON encoder.\n *\n * @param {Function} [opts.decode] - The function to decode incoming messages.\n *\n * Defaults to JSON:\n *\n * ```javascript\n * (payload, callback) => callback(JSON.parse(payload))\n * ```\n *\n * @param {number} [opts.timeout] - The default timeout in milliseconds to trigger push timeouts.\n *\n * Defaults `DEFAULT_TIMEOUT`\n * @param {number} [opts.heartbeatIntervalMs] - The millisec interval to send a heartbeat message\n * @param {number} [opts.reconnectAfterMs] - The optional function that returns the millsec\n * socket reconnect interval.\n *\n * Defaults to stepped backoff of:\n *\n * ```javascript\n * function(tries){\n * return [10, 50, 100, 150, 200, 250, 500, 1000, 2000][tries - 1] || 5000\n * }\n * ````\n *\n * @param {number} [opts.rejoinAfterMs] - The optional function that returns the millsec\n * rejoin interval for individual channels.\n *\n * ```javascript\n * function(tries){\n * return [1000, 2000, 5000][tries - 1] || 10000\n * }\n * ````\n *\n * @param {Function} [opts.logger] - The optional function for specialized logging, ie:\n *\n * ```javascript\n * function(kind, msg, data) {\n * console.log(`${kind}: ${msg}`, data)\n * }\n * ```\n *\n * @param {number} [opts.longpollerTimeout] - The maximum timeout of a long poll AJAX request.\n *\n * Defaults to 20s (double the server long poll timer).\n *\n * @param {(Object|function)} [opts.params] - The optional params to pass when connecting\n * @param {string} [opts.binaryType] - The binary type to use for binary WebSocket frames.\n *\n * Defaults to \"arraybuffer\"\n *\n * @param {vsn} [opts.vsn] - The serializer's protocol version to send on connect.\n *\n * Defaults to DEFAULT_VSN.\n*/\nexport default class Socket {\n constructor(endPoint, opts = {}){\n this.stateChangeCallbacks = {open: [], close: [], error: [], message: []}\n this.channels = []\n this.sendBuffer = []\n this.ref = 0\n this.timeout = opts.timeout || DEFAULT_TIMEOUT\n this.transport = opts.transport || global.WebSocket || LongPoll\n this.establishedConnections = 0\n this.defaultEncoder = Serializer.encode.bind(Serializer)\n this.defaultDecoder = Serializer.decode.bind(Serializer)\n this.closeWasClean = false\n this.binaryType = opts.binaryType || \"arraybuffer\"\n this.connectClock = 1\n if(this.transport !== LongPoll){\n this.encode = opts.encode || this.defaultEncoder\n this.decode = opts.decode || this.defaultDecoder\n } else {\n this.encode = this.defaultEncoder\n this.decode = this.defaultDecoder\n }\n let awaitingConnectionOnPageShow = null\n if(phxWindow && phxWindow.addEventListener){\n phxWindow.addEventListener(\"pagehide\", _e => {\n if(this.conn){\n this.disconnect()\n awaitingConnectionOnPageShow = this.connectClock\n }\n })\n phxWindow.addEventListener(\"pageshow\", _e => {\n if(awaitingConnectionOnPageShow === this.connectClock){\n awaitingConnectionOnPageShow = null\n this.connect()\n }\n })\n }\n this.heartbeatIntervalMs = opts.heartbeatIntervalMs || 30000\n this.rejoinAfterMs = (tries) => {\n if(opts.rejoinAfterMs){\n return opts.rejoinAfterMs(tries)\n } else {\n return [1000, 2000, 5000][tries - 1] || 10000\n }\n }\n this.reconnectAfterMs = (tries) => {\n if(opts.reconnectAfterMs){\n return opts.reconnectAfterMs(tries)\n } else {\n return [10, 50, 100, 150, 200, 250, 500, 1000, 2000][tries - 1] || 5000\n }\n }\n this.logger = opts.logger || null\n this.longpollerTimeout = opts.longpollerTimeout || 20000\n this.params = closure(opts.params || {})\n this.endPoint = `${endPoint}/${TRANSPORTS.websocket}`\n this.vsn = opts.vsn || DEFAULT_VSN\n this.heartbeatTimer = null\n this.pendingHeartbeatRef = null\n this.reconnectTimer = new Timer(() => {\n this.teardown(() => this.connect())\n }, this.reconnectAfterMs)\n }\n\n /**\n * Returns the LongPoll transport reference\n */\n getLongPollTransport(){ return LongPoll }\n\n /**\n * Disconnects and replaces the active transport\n *\n * @param {Function} newTransport - The new transport class to instantiate\n *\n */\n replaceTransport(newTransport){\n this.connectClock++\n this.closeWasClean = true\n this.reconnectTimer.reset()\n this.sendBuffer = []\n if(this.conn){\n this.conn.close()\n this.conn = null\n }\n this.transport = newTransport\n }\n\n /**\n * Returns the socket protocol\n *\n * @returns {string}\n */\n protocol(){ return location.protocol.match(/^https/) ? \"wss\" : \"ws\" }\n\n /**\n * The fully qualifed socket url\n *\n * @returns {string}\n */\n endPointURL(){\n let uri = Ajax.appendParams(\n Ajax.appendParams(this.endPoint, this.params()), {vsn: this.vsn})\n if(uri.charAt(0) !== \"/\"){ return uri }\n if(uri.charAt(1) === \"/\"){ return `${this.protocol()}:${uri}` }\n\n return `${this.protocol()}://${location.host}${uri}`\n }\n\n /**\n * Disconnects the socket\n *\n * See https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent#Status_codes for valid status codes.\n *\n * @param {Function} callback - Optional callback which is called after socket is disconnected.\n * @param {integer} code - A status code for disconnection (Optional).\n * @param {string} reason - A textual description of the reason to disconnect. (Optional)\n */\n disconnect(callback, code, reason){\n this.connectClock++\n this.closeWasClean = true\n this.reconnectTimer.reset()\n this.teardown(callback, code, reason)\n }\n\n /**\n *\n * @param {Object} params - The params to send when connecting, for example `{user_id: userToken}`\n *\n * Passing params to connect is deprecated; pass them in the Socket constructor instead:\n * `new Socket(\"/socket\", {params: {user_id: userToken}})`.\n */\n connect(params){\n if(params){\n console && console.log(\"passing params to connect is deprecated. Instead pass :params to the Socket constructor\")\n this.params = closure(params)\n }\n if(this.conn){ return }\n\n this.connectClock++\n this.closeWasClean = false\n this.conn = new this.transport(this.endPointURL())\n this.conn.binaryType = this.binaryType\n this.conn.timeout = this.longpollerTimeout\n this.conn.onopen = () => this.onConnOpen()\n this.conn.onerror = error => this.onConnError(error)\n this.conn.onmessage = event => this.onConnMessage(event)\n this.conn.onclose = event => this.onConnClose(event)\n }\n\n /**\n * Logs the message. Override `this.logger` for specialized logging. noops by default\n * @param {string} kind\n * @param {string} msg\n * @param {Object} data\n */\n log(kind, msg, data){ this.logger(kind, msg, data) }\n\n /**\n * Returns true if a logger has been set on this socket.\n */\n hasLogger(){ return this.logger !== null }\n\n /**\n * Registers callbacks for connection open events\n *\n * @example socket.onOpen(function(){ console.info(\"the socket was opened\") })\n *\n * @param {Function} callback\n */\n onOpen(callback){\n let ref = this.makeRef()\n this.stateChangeCallbacks.open.push([ref, callback])\n return ref\n }\n\n /**\n * Registers callbacks for connection close events\n * @param {Function} callback\n */\n onClose(callback){\n let ref = this.makeRef()\n this.stateChangeCallbacks.close.push([ref, callback])\n return ref\n }\n\n /**\n * Registers callbacks for connection error events\n *\n * @example socket.onError(function(error){ alert(\"An error occurred\") })\n *\n * @param {Function} callback\n */\n onError(callback){\n let ref = this.makeRef()\n this.stateChangeCallbacks.error.push([ref, callback])\n return ref\n }\n\n /**\n * Registers callbacks for connection message events\n * @param {Function} callback\n */\n onMessage(callback){\n let ref = this.makeRef()\n this.stateChangeCallbacks.message.push([ref, callback])\n return ref\n }\n\n /**\n * Pings the server and invokes the callback with the RTT in milliseconds\n * @param {Function} callback\n *\n * Returns true if the ping was pushed or false if unable to be pushed.\n */\n ping(callback){\n if(!this.isConnected()){ return false }\n let ref = this.makeRef()\n let startTime = Date.now()\n this.push({topic: \"phoenix\", event: \"heartbeat\", payload: {}, ref: ref})\n let onMsgRef = this.onMessage(msg => {\n if(msg.ref === ref){\n this.off([onMsgRef])\n callback(Date.now() - startTime)\n }\n })\n return true\n }\n\n /**\n * @private\n */\n onConnOpen(){\n if(this.hasLogger()) this.log(\"transport\", `connected to ${this.endPointURL()}`)\n this.closeWasClean = false\n this.establishedConnections++\n this.flushSendBuffer()\n this.reconnectTimer.reset()\n this.resetHeartbeat()\n this.stateChangeCallbacks.open.forEach(([, callback]) => callback())\n }\n\n /**\n * @private\n */\n\n heartbeatTimeout(){\n if(this.pendingHeartbeatRef){\n this.pendingHeartbeatRef = null\n if(this.hasLogger()){ this.log(\"transport\", \"heartbeat timeout. Attempting to re-establish connection\") }\n this.abnormalClose(\"heartbeat timeout\")\n }\n }\n\n resetHeartbeat(){\n if(this.conn && this.conn.skipHeartbeat){ return }\n this.pendingHeartbeatRef = null\n clearTimeout(this.heartbeatTimer)\n setTimeout(() => this.sendHeartbeat(), this.heartbeatIntervalMs)\n }\n\n teardown(callback, code, reason){\n if(!this.conn){\n return callback && callback()\n }\n\n this.waitForBufferDone(() => {\n if(this.conn){\n if(code){ this.conn.close(code, reason || \"\") } else { this.conn.close() }\n }\n\n this.waitForSocketClosed(() => {\n if(this.conn){\n this.conn.onclose = function (){ } // noop\n this.conn = null\n }\n\n callback && callback()\n })\n })\n }\n\n waitForBufferDone(callback, tries = 1){\n if(tries === 5 || !this.conn || !this.conn.bufferedAmount){\n callback()\n return\n }\n\n setTimeout(() => {\n this.waitForBufferDone(callback, tries + 1)\n }, 150 * tries)\n }\n\n waitForSocketClosed(callback, tries = 1){\n if(tries === 5 || !this.conn || this.conn.readyState === SOCKET_STATES.closed){\n callback()\n return\n }\n\n setTimeout(() => {\n this.waitForSocketClosed(callback, tries + 1)\n }, 150 * tries)\n }\n\n onConnClose(event){\n let closeCode = event && event.code\n if(this.hasLogger()) this.log(\"transport\", \"close\", event)\n this.triggerChanError()\n clearTimeout(this.heartbeatTimer)\n if(!this.closeWasClean && closeCode !== 1000){\n this.reconnectTimer.scheduleTimeout()\n }\n this.stateChangeCallbacks.close.forEach(([, callback]) => callback(event))\n }\n\n /**\n * @private\n */\n onConnError(error){\n if(this.hasLogger()) this.log(\"transport\", error)\n let transportBefore = this.transport\n let establishedBefore = this.establishedConnections\n this.stateChangeCallbacks.error.forEach(([, callback]) => {\n callback(error, transportBefore, establishedBefore)\n })\n if(transportBefore === this.transport || establishedBefore > 0){\n this.triggerChanError()\n }\n }\n\n /**\n * @private\n */\n triggerChanError(){\n this.channels.forEach(channel => {\n if(!(channel.isErrored() || channel.isLeaving() || channel.isClosed())){\n channel.trigger(CHANNEL_EVENTS.error)\n }\n })\n }\n\n /**\n * @returns {string}\n */\n connectionState(){\n switch(this.conn && this.conn.readyState){\n case SOCKET_STATES.connecting: return \"connecting\"\n case SOCKET_STATES.open: return \"open\"\n case SOCKET_STATES.closing: return \"closing\"\n default: return \"closed\"\n }\n }\n\n /**\n * @returns {boolean}\n */\n isConnected(){ return this.connectionState() === \"open\" }\n\n /**\n * @private\n *\n * @param {Channel}\n */\n remove(channel){\n this.off(channel.stateChangeRefs)\n this.channels = this.channels.filter(c => c.joinRef() !== channel.joinRef())\n }\n\n /**\n * Removes `onOpen`, `onClose`, `onError,` and `onMessage` registrations.\n *\n * @param {refs} - list of refs returned by calls to\n * `onOpen`, `onClose`, `onError,` and `onMessage`\n */\n off(refs){\n for(let key in this.stateChangeCallbacks){\n this.stateChangeCallbacks[key] = this.stateChangeCallbacks[key].filter(([ref]) => {\n return refs.indexOf(ref) === -1\n })\n }\n }\n\n /**\n * Initiates a new channel for the given topic\n *\n * @param {string} topic\n * @param {Object} chanParams - Parameters for the channel\n * @returns {Channel}\n */\n channel(topic, chanParams = {}){\n let chan = new Channel(topic, chanParams, this)\n this.channels.push(chan)\n return chan\n }\n\n /**\n * @param {Object} data\n */\n push(data){\n if(this.hasLogger()){\n let {topic, event, payload, ref, join_ref} = data\n this.log(\"push\", `${topic} ${event} (${join_ref}, ${ref})`, payload)\n }\n\n if(this.isConnected()){\n this.encode(data, result => this.conn.send(result))\n } else {\n this.sendBuffer.push(() => this.encode(data, result => this.conn.send(result)))\n }\n }\n\n /**\n * Return the next message ref, accounting for overflows\n * @returns {string}\n */\n makeRef(){\n let newRef = this.ref + 1\n if(newRef === this.ref){ this.ref = 0 } else { this.ref = newRef }\n\n return this.ref.toString()\n }\n\n sendHeartbeat(){\n if(this.pendingHeartbeatRef && !this.isConnected()){ return }\n this.pendingHeartbeatRef = this.makeRef()\n this.push({topic: \"phoenix\", event: \"heartbeat\", payload: {}, ref: this.pendingHeartbeatRef})\n this.heartbeatTimer = setTimeout(() => this.heartbeatTimeout(), this.heartbeatIntervalMs)\n }\n\n abnormalClose(reason){\n this.closeWasClean = false\n if(this.isConnected()){ this.conn.close(WS_CLOSE_NORMAL, reason) }\n }\n\n flushSendBuffer(){\n if(this.isConnected() && this.sendBuffer.length > 0){\n this.sendBuffer.forEach(callback => callback())\n this.sendBuffer = []\n }\n }\n\n onConnMessage(rawMessage){\n this.decode(rawMessage.data, msg => {\n let {topic, event, payload, ref, join_ref} = msg\n if(ref && ref === this.pendingHeartbeatRef){\n clearTimeout(this.heartbeatTimer)\n this.pendingHeartbeatRef = null\n setTimeout(() => this.sendHeartbeat(), this.heartbeatIntervalMs)\n }\n\n if(this.hasLogger()) this.log(\"receive\", `${payload.status || \"\"} ${topic} ${event} ${ref && \"(\" + ref + \")\" || \"\"}`, payload)\n\n for(let i = 0; i < this.channels.length; i++){\n const channel = this.channels[i]\n if(!channel.isMember(topic, event, payload, join_ref)){ continue }\n channel.trigger(event, payload, ref, join_ref)\n }\n\n for(let i = 0; i < this.stateChangeCallbacks.message.length; i++){\n let [, callback] = this.stateChangeCallbacks.message[i]\n callback(msg)\n }\n })\n }\n\n leaveOpenTopic(topic){\n let dupChannel = this.channels.find(c => c.topic === topic && (c.isJoined() || c.isJoining()))\n if(dupChannel){\n if(this.hasLogger()) this.log(\"transport\", `leaving duplicate topic \"${topic}\"`)\n dupChannel.leave()\n }\n }\n}\n"], - "mappings": "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", + "sourcesContent": ["/**\n * Phoenix Channels JavaScript client\n *\n * ## Socket Connection\n *\n * A single connection is established to the server and\n * channels are multiplexed over the connection.\n * Connect to the server using the `Socket` class:\n *\n * ```javascript\n * let socket = new Socket(\"/socket\", {params: {userToken: \"123\"}})\n * socket.connect()\n * ```\n *\n * The `Socket` constructor takes the mount point of the socket,\n * the authentication params, as well as options that can be found in\n * the Socket docs, such as configuring the `LongPoll` transport, and\n * heartbeat.\n *\n * ## Channels\n *\n * Channels are isolated, concurrent processes on the server that\n * subscribe to topics and broker events between the client and server.\n * To join a channel, you must provide the topic, and channel params for\n * authorization. Here's an example chat room example where `\"new_msg\"`\n * events are listened for, messages are pushed to the server, and\n * the channel is joined with ok/error/timeout matches:\n *\n * ```javascript\n * let channel = socket.channel(\"room:123\", {token: roomToken})\n * channel.on(\"new_msg\", msg => console.log(\"Got message\", msg) )\n * $input.onEnter( e => {\n * channel.push(\"new_msg\", {body: e.target.val}, 10000)\n * .receive(\"ok\", (msg) => console.log(\"created message\", msg) )\n * .receive(\"error\", (reasons) => console.log(\"create failed\", reasons) )\n * .receive(\"timeout\", () => console.log(\"Networking issue...\") )\n * })\n *\n * channel.join()\n * .receive(\"ok\", ({messages}) => console.log(\"catching up\", messages) )\n * .receive(\"error\", ({reason}) => console.log(\"failed join\", reason) )\n * .receive(\"timeout\", () => console.log(\"Networking issue. Still waiting...\"))\n *```\n *\n * ## Joining\n *\n * Creating a channel with `socket.channel(topic, params)`, binds the params to\n * `channel.params`, which are sent up on `channel.join()`.\n * Subsequent rejoins will send up the modified params for\n * updating authorization params, or passing up last_message_id information.\n * Successful joins receive an \"ok\" status, while unsuccessful joins\n * receive \"error\".\n *\n * With the default serializers and WebSocket transport, JSON text frames are\n * used for pushing a JSON object literal. If an `ArrayBuffer` instance is provided,\n * binary encoding will be used and the message will be sent with the binary\n * opcode.\n *\n * *Note*: binary messages are only supported on the WebSocket transport.\n *\n * ## Duplicate Join Subscriptions\n *\n * While the client may join any number of topics on any number of channels,\n * the client may only hold a single subscription for each unique topic at any\n * given time. When attempting to create a duplicate subscription,\n * the server will close the existing channel, log a warning, and\n * spawn a new channel for the topic. The client will have their\n * `channel.onClose` callbacks fired for the existing channel, and the new\n * channel join will have its receive hooks processed as normal.\n *\n * ## Pushing Messages\n *\n * From the previous example, we can see that pushing messages to the server\n * can be done with `channel.push(eventName, payload)` and we can optionally\n * receive responses from the push. Additionally, we can use\n * `receive(\"timeout\", callback)` to abort waiting for our other `receive` hooks\n * and take action after some period of waiting. The default timeout is 10000ms.\n *\n *\n * ## Socket Hooks\n *\n * Lifecycle events of the multiplexed connection can be hooked into via\n * `socket.onError()` and `socket.onClose()` events, ie:\n *\n * ```javascript\n * socket.onError( () => console.log(\"there was an error with the connection!\") )\n * socket.onClose( () => console.log(\"the connection dropped\") )\n * ```\n *\n *\n * ## Channel Hooks\n *\n * For each joined channel, you can bind to `onError` and `onClose` events\n * to monitor the channel lifecycle, ie:\n *\n * ```javascript\n * channel.onError( () => console.log(\"there was an error!\") )\n * channel.onClose( () => console.log(\"the channel has gone away gracefully\") )\n * ```\n *\n * ### onError hooks\n *\n * `onError` hooks are invoked if the socket connection drops, or the channel\n * crashes on the server. In either case, a channel rejoin is attempted\n * automatically in an exponential backoff manner.\n *\n * ### onClose hooks\n *\n * `onClose` hooks are invoked only in two cases. 1) the channel explicitly\n * closed on the server, or 2). The client explicitly closed, by calling\n * `channel.leave()`\n *\n *\n * ## Presence\n *\n * The `Presence` object provides features for syncing presence information\n * from the server with the client and handling presences joining and leaving.\n *\n * ### Syncing state from the server\n *\n * To sync presence state from the server, first instantiate an object and\n * pass your channel in to track lifecycle events:\n *\n * ```javascript\n * let channel = socket.channel(\"some:topic\")\n * let presence = new Presence(channel)\n * ```\n *\n * Next, use the `presence.onSync` callback to react to state changes\n * from the server. For example, to render the list of users every time\n * the list changes, you could write:\n *\n * ```javascript\n * presence.onSync(() => {\n * myRenderUsersFunction(presence.list())\n * })\n * ```\n *\n * ### Listing Presences\n *\n * `presence.list` is used to return a list of presence information\n * based on the local state of metadata. By default, all presence\n * metadata is returned, but a `listBy` function can be supplied to\n * allow the client to select which metadata to use for a given presence.\n * For example, you may have a user online from different devices with\n * a metadata status of \"online\", but they have set themselves to \"away\"\n * on another device. In this case, the app may choose to use the \"away\"\n * status for what appears on the UI. The example below defines a `listBy`\n * function which prioritizes the first metadata which was registered for\n * each user. This could be the first tab they opened, or the first device\n * they came online from:\n *\n * ```javascript\n * let listBy = (id, {metas: [first, ...rest]}) => {\n * first.count = rest.length + 1 // count of this user's presences\n * first.id = id\n * return first\n * }\n * let onlineUsers = presence.list(listBy)\n * ```\n *\n * ### Handling individual presence join and leave events\n *\n * The `presence.onJoin` and `presence.onLeave` callbacks can be used to\n * react to individual presences joining and leaving the app. For example:\n *\n * ```javascript\n * let presence = new Presence(channel)\n *\n * // detect if user has joined for the 1st time or from another tab/device\n * presence.onJoin((id, current, newPres) => {\n * if(!current){\n * console.log(\"user has entered for the first time\", newPres)\n * } else {\n * console.log(\"user additional presence\", newPres)\n * }\n * })\n *\n * // detect if user has left from all tabs/devices, or is still present\n * presence.onLeave((id, current, leftPres) => {\n * if(current.metas.length === 0){\n * console.log(\"user has left from all devices\", leftPres)\n * } else {\n * console.log(\"user left from a device\", leftPres)\n * }\n * })\n * // receive presence data from server\n * presence.onSync(() => {\n * displayUsers(presence.list())\n * })\n * ```\n * @module phoenix\n */\n\nimport Channel from \"./channel\"\nimport LongPoll from \"./longpoll\"\nimport Presence from \"./presence\"\nimport Serializer from \"./serializer\"\nimport Socket from \"./socket\"\n\nexport {\n Channel,\n LongPoll,\n Presence,\n Serializer,\n Socket\n}\n", "// wraps value in closure or returns closure\nexport let closure = (value) => {\n if(typeof value === \"function\"){\n return value\n } else {\n let closure = function (){ return value }\n return closure\n }\n}\n", "export const globalSelf = typeof self !== \"undefined\" ? self : null\nexport const phxWindow = typeof window !== \"undefined\" ? window : null\nexport const global = globalSelf || phxWindow || global\nexport const DEFAULT_VSN = \"2.0.0\"\nexport const SOCKET_STATES = {connecting: 0, open: 1, closing: 2, closed: 3}\nexport const DEFAULT_TIMEOUT = 10000\nexport const WS_CLOSE_NORMAL = 1000\nexport const CHANNEL_STATES = {\n closed: \"closed\",\n errored: \"errored\",\n joined: \"joined\",\n joining: \"joining\",\n leaving: \"leaving\",\n}\nexport const CHANNEL_EVENTS = {\n close: \"phx_close\",\n error: \"phx_error\",\n join: \"phx_join\",\n reply: \"phx_reply\",\n leave: \"phx_leave\"\n}\n\nexport const TRANSPORTS = {\n longpoll: \"longpoll\",\n websocket: \"websocket\"\n}\nexport const XHR_STATES = {\n complete: 4\n}\n", "/**\n * Initializes the Push\n * @param {Channel} channel - The Channel\n * @param {string} event - The event, for example `\"phx_join\"`\n * @param {Object} payload - The payload, for example `{user_id: 123}`\n * @param {number} timeout - The push timeout in milliseconds\n */\nexport default class Push {\n constructor(channel, event, payload, timeout){\n this.channel = channel\n this.event = event\n this.payload = payload || function (){ return {} }\n this.receivedResp = null\n this.timeout = timeout\n this.timeoutTimer = null\n this.recHooks = []\n this.sent = false\n }\n\n /**\n *\n * @param {number} timeout\n */\n resend(timeout){\n this.timeout = timeout\n this.reset()\n this.send()\n }\n\n /**\n *\n */\n send(){\n if(this.hasReceived(\"timeout\")){ return }\n this.startTimeout()\n this.sent = true\n this.channel.socket.push({\n topic: this.channel.topic,\n event: this.event,\n payload: this.payload(),\n ref: this.ref,\n join_ref: this.channel.joinRef()\n })\n }\n\n /**\n *\n * @param {*} status\n * @param {*} callback\n */\n receive(status, callback){\n if(this.hasReceived(status)){\n callback(this.receivedResp.response)\n }\n\n this.recHooks.push({status, callback})\n return this\n }\n\n /**\n * @private\n */\n reset(){\n this.cancelRefEvent()\n this.ref = null\n this.refEvent = null\n this.receivedResp = null\n this.sent = false\n }\n\n /**\n * @private\n */\n matchReceive({status, response, _ref}){\n this.recHooks.filter(h => h.status === status)\n .forEach(h => h.callback(response))\n }\n\n /**\n * @private\n */\n cancelRefEvent(){\n if(!this.refEvent){ return }\n this.channel.off(this.refEvent)\n }\n\n /**\n * @private\n */\n cancelTimeout(){\n clearTimeout(this.timeoutTimer)\n this.timeoutTimer = null\n }\n\n /**\n * @private\n */\n startTimeout(){\n if(this.timeoutTimer){ this.cancelTimeout() }\n this.ref = this.channel.socket.makeRef()\n this.refEvent = this.channel.replyEventName(this.ref)\n\n this.channel.on(this.refEvent, payload => {\n this.cancelRefEvent()\n this.cancelTimeout()\n this.receivedResp = payload\n this.matchReceive(payload)\n })\n\n this.timeoutTimer = setTimeout(() => {\n this.trigger(\"timeout\", {})\n }, this.timeout)\n }\n\n /**\n * @private\n */\n hasReceived(status){\n return this.receivedResp && this.receivedResp.status === status\n }\n\n /**\n * @private\n */\n trigger(status, response){\n this.channel.trigger(this.refEvent, {status, response})\n }\n}\n", "/**\n *\n * Creates a timer that accepts a `timerCalc` function to perform\n * calculated timeout retries, such as exponential backoff.\n *\n * @example\n * let reconnectTimer = new Timer(() => this.connect(), function(tries){\n * return [1000, 5000, 10000][tries - 1] || 10000\n * })\n * reconnectTimer.scheduleTimeout() // fires after 1000\n * reconnectTimer.scheduleTimeout() // fires after 5000\n * reconnectTimer.reset()\n * reconnectTimer.scheduleTimeout() // fires after 1000\n *\n * @param {Function} callback\n * @param {Function} timerCalc\n */\nexport default class Timer {\n constructor(callback, timerCalc){\n this.callback = callback\n this.timerCalc = timerCalc\n this.timer = null\n this.tries = 0\n }\n\n reset(){\n this.tries = 0\n clearTimeout(this.timer)\n }\n\n /**\n * Cancels any previous scheduleTimeout and schedules callback\n */\n scheduleTimeout(){\n clearTimeout(this.timer)\n\n this.timer = setTimeout(() => {\n this.tries = this.tries + 1\n this.callback()\n }, this.timerCalc(this.tries + 1))\n }\n}\n", "import {closure} from \"./utils\"\nimport {\n CHANNEL_EVENTS,\n CHANNEL_STATES,\n} from \"./constants\"\n\nimport Push from \"./push\"\nimport Timer from \"./timer\"\n\n/**\n *\n * @param {string} topic\n * @param {(Object|function)} params\n * @param {Socket} socket\n */\nexport default class Channel {\n constructor(topic, params, socket){\n this.state = CHANNEL_STATES.closed\n this.topic = topic\n this.params = closure(params || {})\n this.socket = socket\n this.bindings = []\n this.bindingRef = 0\n this.timeout = this.socket.timeout\n this.joinedOnce = false\n this.joinPush = new Push(this, CHANNEL_EVENTS.join, this.params, this.timeout)\n this.pushBuffer = []\n this.stateChangeRefs = []\n\n this.rejoinTimer = new Timer(() => {\n if(this.socket.isConnected()){ this.rejoin() }\n }, this.socket.rejoinAfterMs)\n this.stateChangeRefs.push(this.socket.onError(() => this.rejoinTimer.reset()))\n this.stateChangeRefs.push(this.socket.onOpen(() => {\n this.rejoinTimer.reset()\n if(this.isErrored()){ this.rejoin() }\n })\n )\n this.joinPush.receive(\"ok\", () => {\n this.state = CHANNEL_STATES.joined\n this.rejoinTimer.reset()\n this.pushBuffer.forEach(pushEvent => pushEvent.send())\n this.pushBuffer = []\n })\n this.joinPush.receive(\"error\", () => {\n this.state = CHANNEL_STATES.errored\n if(this.socket.isConnected()){ this.rejoinTimer.scheduleTimeout() }\n })\n this.onClose(() => {\n this.rejoinTimer.reset()\n if(this.socket.hasLogger()) this.socket.log(\"channel\", `close ${this.topic} ${this.joinRef()}`)\n this.state = CHANNEL_STATES.closed\n this.socket.remove(this)\n })\n this.onError(reason => {\n if(this.socket.hasLogger()) this.socket.log(\"channel\", `error ${this.topic}`, reason)\n if(this.isJoining()){ this.joinPush.reset() }\n this.state = CHANNEL_STATES.errored\n if(this.socket.isConnected()){ this.rejoinTimer.scheduleTimeout() }\n })\n this.joinPush.receive(\"timeout\", () => {\n if(this.socket.hasLogger()) this.socket.log(\"channel\", `timeout ${this.topic} (${this.joinRef()})`, this.joinPush.timeout)\n let leavePush = new Push(this, CHANNEL_EVENTS.leave, closure({}), this.timeout)\n leavePush.send()\n this.state = CHANNEL_STATES.errored\n this.joinPush.reset()\n if(this.socket.isConnected()){ this.rejoinTimer.scheduleTimeout() }\n })\n this.on(CHANNEL_EVENTS.reply, (payload, ref) => {\n this.trigger(this.replyEventName(ref), payload)\n })\n }\n\n /**\n * Join the channel\n * @param {integer} timeout\n * @returns {Push}\n */\n join(timeout = this.timeout){\n if(this.joinedOnce){\n throw new Error(\"tried to join multiple times. 'join' can only be called a single time per channel instance\")\n } else {\n this.timeout = timeout\n this.joinedOnce = true\n this.rejoin()\n return this.joinPush\n }\n }\n\n /**\n * Hook into channel close\n * @param {Function} callback\n */\n onClose(callback){\n this.on(CHANNEL_EVENTS.close, callback)\n }\n\n /**\n * Hook into channel errors\n * @param {Function} callback\n */\n onError(callback){\n return this.on(CHANNEL_EVENTS.error, reason => callback(reason))\n }\n\n /**\n * Subscribes on channel events\n *\n * Subscription returns a ref counter, which can be used later to\n * unsubscribe the exact event listener\n *\n * @example\n * const ref1 = channel.on(\"event\", do_stuff)\n * const ref2 = channel.on(\"event\", do_other_stuff)\n * channel.off(\"event\", ref1)\n * // Since unsubscription, do_stuff won't fire,\n * // while do_other_stuff will keep firing on the \"event\"\n *\n * @param {string} event\n * @param {Function} callback\n * @returns {integer} ref\n */\n on(event, callback){\n let ref = this.bindingRef++\n this.bindings.push({event, ref, callback})\n return ref\n }\n\n /**\n * Unsubscribes off of channel events\n *\n * Use the ref returned from a channel.on() to unsubscribe one\n * handler, or pass nothing for the ref to unsubscribe all\n * handlers for the given event.\n *\n * @example\n * // Unsubscribe the do_stuff handler\n * const ref1 = channel.on(\"event\", do_stuff)\n * channel.off(\"event\", ref1)\n *\n * // Unsubscribe all handlers from event\n * channel.off(\"event\")\n *\n * @param {string} event\n * @param {integer} ref\n */\n off(event, ref){\n this.bindings = this.bindings.filter((bind) => {\n return !(bind.event === event && (typeof ref === \"undefined\" || ref === bind.ref))\n })\n }\n\n /**\n * @private\n */\n canPush(){ return this.socket.isConnected() && this.isJoined() }\n\n /**\n * Sends a message `event` to phoenix with the payload `payload`.\n * Phoenix receives this in the `handle_in(event, payload, socket)`\n * function. if phoenix replies or it times out (default 10000ms),\n * then optionally the reply can be received.\n *\n * @example\n * channel.push(\"event\")\n * .receive(\"ok\", payload => console.log(\"phoenix replied:\", payload))\n * .receive(\"error\", err => console.log(\"phoenix errored\", err))\n * .receive(\"timeout\", () => console.log(\"timed out pushing\"))\n * @param {string} event\n * @param {Object} payload\n * @param {number} [timeout]\n * @returns {Push}\n */\n push(event, payload, timeout = this.timeout){\n payload = payload || {}\n if(!this.joinedOnce){\n throw new Error(`tried to push '${event}' to '${this.topic}' before joining. Use channel.join() before pushing events`)\n }\n let pushEvent = new Push(this, event, function (){ return payload }, timeout)\n if(this.canPush()){\n pushEvent.send()\n } else {\n pushEvent.startTimeout()\n this.pushBuffer.push(pushEvent)\n }\n\n return pushEvent\n }\n\n /** Leaves the channel\n *\n * Unsubscribes from server events, and\n * instructs channel to terminate on server\n *\n * Triggers onClose() hooks\n *\n * To receive leave acknowledgements, use the `receive`\n * hook to bind to the server ack, ie:\n *\n * @example\n * channel.leave().receive(\"ok\", () => alert(\"left!\") )\n *\n * @param {integer} timeout\n * @returns {Push}\n */\n leave(timeout = this.timeout){\n this.rejoinTimer.reset()\n this.joinPush.cancelTimeout()\n\n this.state = CHANNEL_STATES.leaving\n let onClose = () => {\n if(this.socket.hasLogger()) this.socket.log(\"channel\", `leave ${this.topic}`)\n this.trigger(CHANNEL_EVENTS.close, \"leave\")\n }\n let leavePush = new Push(this, CHANNEL_EVENTS.leave, closure({}), timeout)\n leavePush.receive(\"ok\", () => onClose())\n .receive(\"timeout\", () => onClose())\n leavePush.send()\n if(!this.canPush()){ leavePush.trigger(\"ok\", {}) }\n\n return leavePush\n }\n\n /**\n * Overridable message hook\n *\n * Receives all events for specialized message handling\n * before dispatching to the channel callbacks.\n *\n * Must return the payload, modified or unmodified\n * @param {string} event\n * @param {Object} payload\n * @param {integer} ref\n * @returns {Object}\n */\n onMessage(_event, payload, _ref){ return payload }\n\n /**\n * @private\n */\n isMember(topic, event, payload, joinRef){\n if(this.topic !== topic){ return false }\n\n if(joinRef && joinRef !== this.joinRef()){\n if(this.socket.hasLogger()) this.socket.log(\"channel\", \"dropping outdated message\", {topic, event, payload, joinRef})\n return false\n } else {\n return true\n }\n }\n\n /**\n * @private\n */\n joinRef(){ return this.joinPush.ref }\n\n /**\n * @private\n */\n rejoin(timeout = this.timeout){\n if(this.isLeaving()){ return }\n this.socket.leaveOpenTopic(this.topic)\n this.state = CHANNEL_STATES.joining\n this.joinPush.resend(timeout)\n }\n\n /**\n * @private\n */\n trigger(event, payload, ref, joinRef){\n let handledPayload = this.onMessage(event, payload, ref, joinRef)\n if(payload && !handledPayload){ throw new Error(\"channel onMessage callbacks must return the payload, modified or unmodified\") }\n\n let eventBindings = this.bindings.filter(bind => bind.event === event)\n\n for(let i = 0; i < eventBindings.length; i++){\n let bind = eventBindings[i]\n bind.callback(handledPayload, ref, joinRef || this.joinRef())\n }\n }\n\n /**\n * @private\n */\n replyEventName(ref){ return `chan_reply_${ref}` }\n\n /**\n * @private\n */\n isClosed(){ return this.state === CHANNEL_STATES.closed }\n\n /**\n * @private\n */\n isErrored(){ return this.state === CHANNEL_STATES.errored }\n\n /**\n * @private\n */\n isJoined(){ return this.state === CHANNEL_STATES.joined }\n\n /**\n * @private\n */\n isJoining(){ return this.state === CHANNEL_STATES.joining }\n\n /**\n * @private\n */\n isLeaving(){ return this.state === CHANNEL_STATES.leaving }\n}\n", "import {\n global,\n XHR_STATES\n} from \"./constants\"\n\nexport default class Ajax {\n\n static request(method, endPoint, accept, body, timeout, ontimeout, callback){\n if(global.XDomainRequest){\n let req = new global.XDomainRequest() // IE8, IE9\n return this.xdomainRequest(req, method, endPoint, body, timeout, ontimeout, callback)\n } else {\n let req = new global.XMLHttpRequest() // IE7+, Firefox, Chrome, Opera, Safari\n return this.xhrRequest(req, method, endPoint, accept, body, timeout, ontimeout, callback)\n }\n }\n\n static xdomainRequest(req, method, endPoint, body, timeout, ontimeout, callback){\n req.timeout = timeout\n req.open(method, endPoint)\n req.onload = () => {\n let response = this.parseJSON(req.responseText)\n callback && callback(response)\n }\n if(ontimeout){ req.ontimeout = ontimeout }\n\n // Work around bug in IE9 that requires an attached onprogress handler\n req.onprogress = () => { }\n\n req.send(body)\n return req\n }\n\n static xhrRequest(req, method, endPoint, accept, body, timeout, ontimeout, callback){\n req.open(method, endPoint, true)\n req.timeout = timeout\n req.setRequestHeader(\"Content-Type\", accept)\n req.onerror = () => callback && callback(null)\n req.onreadystatechange = () => {\n if(req.readyState === XHR_STATES.complete && callback){\n let response = this.parseJSON(req.responseText)\n callback(response)\n }\n }\n if(ontimeout){ req.ontimeout = ontimeout }\n\n req.send(body)\n return req\n }\n\n static parseJSON(resp){\n if(!resp || resp === \"\"){ return null }\n\n try {\n return JSON.parse(resp)\n } catch (e){\n console && console.log(\"failed to parse JSON response\", resp)\n return null\n }\n }\n\n static serialize(obj, parentKey){\n let queryStr = []\n for(var key in obj){\n if(!Object.prototype.hasOwnProperty.call(obj, key)){ continue }\n let paramKey = parentKey ? `${parentKey}[${key}]` : key\n let paramVal = obj[key]\n if(typeof paramVal === \"object\"){\n queryStr.push(this.serialize(paramVal, paramKey))\n } else {\n queryStr.push(encodeURIComponent(paramKey) + \"=\" + encodeURIComponent(paramVal))\n }\n }\n return queryStr.join(\"&\")\n }\n\n static appendParams(url, params){\n if(Object.keys(params).length === 0){ return url }\n\n let prefix = url.match(/\\?/) ? \"&\" : \"?\"\n return `${url}${prefix}${this.serialize(params)}`\n }\n}\n", "import {\n SOCKET_STATES,\n TRANSPORTS\n} from \"./constants\"\n\nimport Ajax from \"./ajax\"\n\nexport default class LongPoll {\n\n constructor(endPoint){\n this.endPoint = null\n this.token = null\n this.skipHeartbeat = true\n this.reqs = new Set()\n this.onopen = function (){ } // noop\n this.onerror = function (){ } // noop\n this.onmessage = function (){ } // noop\n this.onclose = function (){ } // noop\n this.pollEndpoint = this.normalizeEndpoint(endPoint)\n this.readyState = SOCKET_STATES.connecting\n this.poll()\n }\n\n normalizeEndpoint(endPoint){\n return (endPoint\n .replace(\"ws://\", \"http://\")\n .replace(\"wss://\", \"https://\")\n .replace(new RegExp(\"(.*)\\/\" + TRANSPORTS.websocket), \"$1/\" + TRANSPORTS.longpoll))\n }\n\n endpointURL(){\n return Ajax.appendParams(this.pollEndpoint, {token: this.token})\n }\n\n closeAndRetry(code, reason, wasClean){\n this.close(code, reason, wasClean)\n this.readyState = SOCKET_STATES.connecting\n }\n\n ontimeout(){\n this.onerror(\"timeout\")\n this.closeAndRetry(1005, \"timeout\", false)\n }\n\n isActive(){ return this.readyState === SOCKET_STATES.open || this.readyState === SOCKET_STATES.connecting }\n\n poll(){\n this.ajax(\"GET\", null, () => this.ontimeout(), resp => {\n if(resp){\n var {status, token, messages} = resp\n this.token = token\n } else {\n status = 0\n }\n\n switch(status){\n case 200:\n messages.forEach(msg => {\n // Tasks are what things like event handlers, setTimeout callbacks,\n // promise resolves and more are run within.\n // In modern browsers, there are two different kinds of tasks,\n // microtasks and macrotasks.\n // Microtasks are mainly used for Promises, while macrotasks are\n // used for everything else.\n // Microtasks always have priority over macrotasks. If the JS engine\n // is looking for a task to run, it will always try to empty the\n // microtask queue before attempting to run anything from the\n // macrotask queue.\n //\n // For the WebSocket transport, messages always arrive in their own\n // event. This means that if any promises are resolved from within,\n // their callbacks will always finish execution by the time the\n // next message event handler is run.\n //\n // In order to emulate this behaviour, we need to make sure each\n // onmessage handler is run within it's own macrotask.\n setTimeout(() => this.onmessage({data: msg}), 0)\n })\n this.poll()\n break\n case 204:\n this.poll()\n break\n case 410:\n this.readyState = SOCKET_STATES.open\n this.onopen({})\n this.poll()\n break\n case 403:\n this.onerror(403)\n this.close(1008, \"forbidden\", false)\n break\n case 0:\n case 500:\n this.onerror(500)\n this.closeAndRetry(1011, \"internal server error\", 500)\n break\n default: throw new Error(`unhandled poll status ${status}`)\n }\n })\n }\n\n send(body){\n this.ajax(\"POST\", body, () => this.onerror(\"timeout\"), resp => {\n if(!resp || resp.status !== 200){\n this.onerror(resp && resp.status)\n this.closeAndRetry(1011, \"internal server error\", false)\n }\n })\n }\n\n close(code, reason, wasClean){\n for(let req of this.reqs){ req.abort() }\n this.readyState = SOCKET_STATES.closed\n let opts = Object.assign({code: 1000, reason: undefined, wasClean: true}, {code, reason, wasClean})\n if(typeof(CloseEvent) !== \"undefined\"){\n this.onclose(new CloseEvent(\"close\", opts))\n } else {\n this.onclose(opts)\n }\n }\n\n ajax(method, body, onCallerTimeout, callback){\n let req\n let ontimeout = () => {\n this.reqs.delete(req)\n onCallerTimeout()\n }\n req = Ajax.request(method, this.endpointURL(), \"application/json\", body, this.timeout, ontimeout, resp => {\n this.reqs.delete(req)\n if(this.isActive()){ callback(resp) }\n })\n this.reqs.add(req)\n }\n}\n", "/**\n * Initializes the Presence\n * @param {Channel} channel - The Channel\n * @param {Object} opts - The options,\n * for example `{events: {state: \"state\", diff: \"diff\"}}`\n */\nexport default class Presence {\n\n constructor(channel, opts = {}){\n let events = opts.events || {state: \"presence_state\", diff: \"presence_diff\"}\n this.state = {}\n this.pendingDiffs = []\n this.channel = channel\n this.joinRef = null\n this.caller = {\n onJoin: function (){ },\n onLeave: function (){ },\n onSync: function (){ }\n }\n\n this.channel.on(events.state, newState => {\n let {onJoin, onLeave, onSync} = this.caller\n\n this.joinRef = this.channel.joinRef()\n this.state = Presence.syncState(this.state, newState, onJoin, onLeave)\n\n this.pendingDiffs.forEach(diff => {\n this.state = Presence.syncDiff(this.state, diff, onJoin, onLeave)\n })\n this.pendingDiffs = []\n onSync()\n })\n\n this.channel.on(events.diff, diff => {\n let {onJoin, onLeave, onSync} = this.caller\n\n if(this.inPendingSyncState()){\n this.pendingDiffs.push(diff)\n } else {\n this.state = Presence.syncDiff(this.state, diff, onJoin, onLeave)\n onSync()\n }\n })\n }\n\n onJoin(callback){ this.caller.onJoin = callback }\n\n onLeave(callback){ this.caller.onLeave = callback }\n\n onSync(callback){ this.caller.onSync = callback }\n\n list(by){ return Presence.list(this.state, by) }\n\n inPendingSyncState(){\n return !this.joinRef || (this.joinRef !== this.channel.joinRef())\n }\n\n // lower-level public static API\n\n /**\n * Used to sync the list of presences on the server\n * with the client's state. An optional `onJoin` and `onLeave` callback can\n * be provided to react to changes in the client's local presences across\n * disconnects and reconnects with the server.\n *\n * @returns {Presence}\n */\n static syncState(currentState, newState, onJoin, onLeave){\n let state = this.clone(currentState)\n let joins = {}\n let leaves = {}\n\n this.map(state, (key, presence) => {\n if(!newState[key]){\n leaves[key] = presence\n }\n })\n this.map(newState, (key, newPresence) => {\n let currentPresence = state[key]\n if(currentPresence){\n let newRefs = newPresence.metas.map(m => m.phx_ref)\n let curRefs = currentPresence.metas.map(m => m.phx_ref)\n let joinedMetas = newPresence.metas.filter(m => curRefs.indexOf(m.phx_ref) < 0)\n let leftMetas = currentPresence.metas.filter(m => newRefs.indexOf(m.phx_ref) < 0)\n if(joinedMetas.length > 0){\n joins[key] = newPresence\n joins[key].metas = joinedMetas\n }\n if(leftMetas.length > 0){\n leaves[key] = this.clone(currentPresence)\n leaves[key].metas = leftMetas\n }\n } else {\n joins[key] = newPresence\n }\n })\n return this.syncDiff(state, {joins: joins, leaves: leaves}, onJoin, onLeave)\n }\n\n /**\n *\n * Used to sync a diff of presence join and leave\n * events from the server, as they happen. Like `syncState`, `syncDiff`\n * accepts optional `onJoin` and `onLeave` callbacks to react to a user\n * joining or leaving from a device.\n *\n * @returns {Presence}\n */\n static syncDiff(state, diff, onJoin, onLeave){\n let {joins, leaves} = this.clone(diff)\n if(!onJoin){ onJoin = function (){ } }\n if(!onLeave){ onLeave = function (){ } }\n\n this.map(joins, (key, newPresence) => {\n let currentPresence = state[key]\n state[key] = this.clone(newPresence)\n if(currentPresence){\n let joinedRefs = state[key].metas.map(m => m.phx_ref)\n let curMetas = currentPresence.metas.filter(m => joinedRefs.indexOf(m.phx_ref) < 0)\n state[key].metas.unshift(...curMetas)\n }\n onJoin(key, currentPresence, newPresence)\n })\n this.map(leaves, (key, leftPresence) => {\n let currentPresence = state[key]\n if(!currentPresence){ return }\n let refsToRemove = leftPresence.metas.map(m => m.phx_ref)\n currentPresence.metas = currentPresence.metas.filter(p => {\n return refsToRemove.indexOf(p.phx_ref) < 0\n })\n onLeave(key, currentPresence, leftPresence)\n if(currentPresence.metas.length === 0){\n delete state[key]\n }\n })\n return state\n }\n\n /**\n * Returns the array of presences, with selected metadata.\n *\n * @param {Object} presences\n * @param {Function} chooser\n *\n * @returns {Presence}\n */\n static list(presences, chooser){\n if(!chooser){ chooser = function (key, pres){ return pres } }\n\n return this.map(presences, (key, presence) => {\n return chooser(key, presence)\n })\n }\n\n // private\n\n static map(obj, func){\n return Object.getOwnPropertyNames(obj).map(key => func(key, obj[key]))\n }\n\n static clone(obj){ return JSON.parse(JSON.stringify(obj)) }\n}\n", "/* The default serializer for encoding and decoding messages */\nimport {\n CHANNEL_EVENTS\n} from \"./constants\"\n\nexport default {\n HEADER_LENGTH: 1,\n META_LENGTH: 4,\n KINDS: {push: 0, reply: 1, broadcast: 2},\n\n encode(msg, callback){\n if(msg.payload.constructor === ArrayBuffer){\n return callback(this.binaryEncode(msg))\n } else {\n let payload = [msg.join_ref, msg.ref, msg.topic, msg.event, msg.payload]\n return callback(JSON.stringify(payload))\n }\n },\n\n decode(rawPayload, callback){\n if(rawPayload.constructor === ArrayBuffer){\n return callback(this.binaryDecode(rawPayload))\n } else {\n let [join_ref, ref, topic, event, payload] = JSON.parse(rawPayload)\n return callback({join_ref, ref, topic, event, payload})\n }\n },\n\n // private\n\n binaryEncode(message){\n let {join_ref, ref, event, topic, payload} = message\n let metaLength = this.META_LENGTH + join_ref.length + ref.length + topic.length + event.length\n let header = new ArrayBuffer(this.HEADER_LENGTH + metaLength)\n let view = new DataView(header)\n let offset = 0\n\n view.setUint8(offset++, this.KINDS.push) // kind\n view.setUint8(offset++, join_ref.length)\n view.setUint8(offset++, ref.length)\n view.setUint8(offset++, topic.length)\n view.setUint8(offset++, event.length)\n Array.from(join_ref, char => view.setUint8(offset++, char.charCodeAt(0)))\n Array.from(ref, char => view.setUint8(offset++, char.charCodeAt(0)))\n Array.from(topic, char => view.setUint8(offset++, char.charCodeAt(0)))\n Array.from(event, char => view.setUint8(offset++, char.charCodeAt(0)))\n\n var combined = new Uint8Array(header.byteLength + payload.byteLength)\n combined.set(new Uint8Array(header), 0)\n combined.set(new Uint8Array(payload), header.byteLength)\n\n return combined.buffer\n },\n\n binaryDecode(buffer){\n let view = new DataView(buffer)\n let kind = view.getUint8(0)\n let decoder = new TextDecoder()\n switch(kind){\n case this.KINDS.push: return this.decodePush(buffer, view, decoder)\n case this.KINDS.reply: return this.decodeReply(buffer, view, decoder)\n case this.KINDS.broadcast: return this.decodeBroadcast(buffer, view, decoder)\n }\n },\n\n decodePush(buffer, view, decoder){\n let joinRefSize = view.getUint8(1)\n let topicSize = view.getUint8(2)\n let eventSize = view.getUint8(3)\n let offset = this.HEADER_LENGTH + this.META_LENGTH - 1 // pushes have no ref\n let joinRef = decoder.decode(buffer.slice(offset, offset + joinRefSize))\n offset = offset + joinRefSize\n let topic = decoder.decode(buffer.slice(offset, offset + topicSize))\n offset = offset + topicSize\n let event = decoder.decode(buffer.slice(offset, offset + eventSize))\n offset = offset + eventSize\n let data = buffer.slice(offset, buffer.byteLength)\n return {join_ref: joinRef, ref: null, topic: topic, event: event, payload: data}\n },\n\n decodeReply(buffer, view, decoder){\n let joinRefSize = view.getUint8(1)\n let refSize = view.getUint8(2)\n let topicSize = view.getUint8(3)\n let eventSize = view.getUint8(4)\n let offset = this.HEADER_LENGTH + this.META_LENGTH\n let joinRef = decoder.decode(buffer.slice(offset, offset + joinRefSize))\n offset = offset + joinRefSize\n let ref = decoder.decode(buffer.slice(offset, offset + refSize))\n offset = offset + refSize\n let topic = decoder.decode(buffer.slice(offset, offset + topicSize))\n offset = offset + topicSize\n let event = decoder.decode(buffer.slice(offset, offset + eventSize))\n offset = offset + eventSize\n let data = buffer.slice(offset, buffer.byteLength)\n let payload = {status: event, response: data}\n return {join_ref: joinRef, ref: ref, topic: topic, event: CHANNEL_EVENTS.reply, payload: payload}\n },\n\n decodeBroadcast(buffer, view, decoder){\n let topicSize = view.getUint8(1)\n let eventSize = view.getUint8(2)\n let offset = this.HEADER_LENGTH + 2\n let topic = decoder.decode(buffer.slice(offset, offset + topicSize))\n offset = offset + topicSize\n let event = decoder.decode(buffer.slice(offset, offset + eventSize))\n offset = offset + eventSize\n let data = buffer.slice(offset, buffer.byteLength)\n\n return {join_ref: null, ref: null, topic: topic, event: event, payload: data}\n }\n}\n", "import {\n global,\n phxWindow,\n CHANNEL_EVENTS,\n DEFAULT_TIMEOUT,\n DEFAULT_VSN,\n SOCKET_STATES,\n TRANSPORTS,\n WS_CLOSE_NORMAL\n} from \"./constants\"\n\nimport {\n closure\n} from \"./utils\"\n\nimport Ajax from \"./ajax\"\nimport Channel from \"./channel\"\nimport LongPoll from \"./longpoll\"\nimport Serializer from \"./serializer\"\nimport Timer from \"./timer\"\n\n/** Initializes the Socket *\n *\n * For IE8 support use an ES5-shim (https://github.com/es-shims/es5-shim)\n *\n * @param {string} endPoint - The string WebSocket endpoint, ie, `\"ws://example.com/socket\"`,\n * `\"wss://example.com\"`\n * `\"/socket\"` (inherited host & protocol)\n * @param {Object} [opts] - Optional configuration\n * @param {Function} [opts.transport] - The Websocket Transport, for example WebSocket or Phoenix.LongPoll.\n *\n * Defaults to WebSocket with automatic LongPoll fallback.\n * @param {Function} [opts.encode] - The function to encode outgoing messages.\n *\n * Defaults to JSON encoder.\n *\n * @param {Function} [opts.decode] - The function to decode incoming messages.\n *\n * Defaults to JSON:\n *\n * ```javascript\n * (payload, callback) => callback(JSON.parse(payload))\n * ```\n *\n * @param {number} [opts.timeout] - The default timeout in milliseconds to trigger push timeouts.\n *\n * Defaults `DEFAULT_TIMEOUT`\n * @param {number} [opts.heartbeatIntervalMs] - The millisec interval to send a heartbeat message\n * @param {number} [opts.reconnectAfterMs] - The optional function that returns the millsec\n * socket reconnect interval.\n *\n * Defaults to stepped backoff of:\n *\n * ```javascript\n * function(tries){\n * return [10, 50, 100, 150, 200, 250, 500, 1000, 2000][tries - 1] || 5000\n * }\n * ````\n *\n * @param {number} [opts.rejoinAfterMs] - The optional function that returns the millsec\n * rejoin interval for individual channels.\n *\n * ```javascript\n * function(tries){\n * return [1000, 2000, 5000][tries - 1] || 10000\n * }\n * ````\n *\n * @param {Function} [opts.logger] - The optional function for specialized logging, ie:\n *\n * ```javascript\n * function(kind, msg, data) {\n * console.log(`${kind}: ${msg}`, data)\n * }\n * ```\n *\n * @param {number} [opts.longpollerTimeout] - The maximum timeout of a long poll AJAX request.\n *\n * Defaults to 20s (double the server long poll timer).\n *\n * @param {(Object|function)} [opts.params] - The optional params to pass when connecting\n * @param {string} [opts.binaryType] - The binary type to use for binary WebSocket frames.\n *\n * Defaults to \"arraybuffer\"\n *\n * @param {vsn} [opts.vsn] - The serializer's protocol version to send on connect.\n *\n * Defaults to DEFAULT_VSN.\n*/\nexport default class Socket {\n constructor(endPoint, opts = {}){\n this.stateChangeCallbacks = {open: [], close: [], error: [], message: []}\n this.channels = []\n this.sendBuffer = []\n this.ref = 0\n this.timeout = opts.timeout || DEFAULT_TIMEOUT\n this.transport = opts.transport || global.WebSocket || LongPoll\n this.establishedConnections = 0\n this.defaultEncoder = Serializer.encode.bind(Serializer)\n this.defaultDecoder = Serializer.decode.bind(Serializer)\n this.closeWasClean = false\n this.binaryType = opts.binaryType || \"arraybuffer\"\n this.connectClock = 1\n if(this.transport !== LongPoll){\n this.encode = opts.encode || this.defaultEncoder\n this.decode = opts.decode || this.defaultDecoder\n } else {\n this.encode = this.defaultEncoder\n this.decode = this.defaultDecoder\n }\n let awaitingConnectionOnPageShow = null\n if(phxWindow && phxWindow.addEventListener){\n phxWindow.addEventListener(\"pagehide\", _e => {\n if(this.conn){\n this.disconnect()\n awaitingConnectionOnPageShow = this.connectClock\n }\n })\n phxWindow.addEventListener(\"pageshow\", _e => {\n if(awaitingConnectionOnPageShow === this.connectClock){\n awaitingConnectionOnPageShow = null\n this.connect()\n }\n })\n }\n this.heartbeatIntervalMs = opts.heartbeatIntervalMs || 30000\n this.rejoinAfterMs = (tries) => {\n if(opts.rejoinAfterMs){\n return opts.rejoinAfterMs(tries)\n } else {\n return [1000, 2000, 5000][tries - 1] || 10000\n }\n }\n this.reconnectAfterMs = (tries) => {\n if(opts.reconnectAfterMs){\n return opts.reconnectAfterMs(tries)\n } else {\n return [10, 50, 100, 150, 200, 250, 500, 1000, 2000][tries - 1] || 5000\n }\n }\n this.logger = opts.logger || null\n this.longpollerTimeout = opts.longpollerTimeout || 20000\n this.params = closure(opts.params || {})\n this.endPoint = `${endPoint}/${TRANSPORTS.websocket}`\n this.vsn = opts.vsn || DEFAULT_VSN\n this.heartbeatTimer = null\n this.pendingHeartbeatRef = null\n this.reconnectTimer = new Timer(() => {\n this.teardown(() => this.connect())\n }, this.reconnectAfterMs)\n }\n\n /**\n * Returns the LongPoll transport reference\n */\n getLongPollTransport(){ return LongPoll }\n\n /**\n * Disconnects and replaces the active transport\n *\n * @param {Function} newTransport - The new transport class to instantiate\n *\n */\n replaceTransport(newTransport){\n this.connectClock++\n this.closeWasClean = true\n this.reconnectTimer.reset()\n this.sendBuffer = []\n if(this.conn){\n this.conn.close()\n this.conn = null\n }\n this.transport = newTransport\n }\n\n /**\n * Returns the socket protocol\n *\n * @returns {string}\n */\n protocol(){ return location.protocol.match(/^https/) ? \"wss\" : \"ws\" }\n\n /**\n * The fully qualifed socket url\n *\n * @returns {string}\n */\n endPointURL(){\n let uri = Ajax.appendParams(\n Ajax.appendParams(this.endPoint, this.params()), {vsn: this.vsn})\n if(uri.charAt(0) !== \"/\"){ return uri }\n if(uri.charAt(1) === \"/\"){ return `${this.protocol()}:${uri}` }\n\n return `${this.protocol()}://${location.host}${uri}`\n }\n\n /**\n * Disconnects the socket\n *\n * See https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent#Status_codes for valid status codes.\n *\n * @param {Function} callback - Optional callback which is called after socket is disconnected.\n * @param {integer} code - A status code for disconnection (Optional).\n * @param {string} reason - A textual description of the reason to disconnect. (Optional)\n */\n disconnect(callback, code, reason){\n this.connectClock++\n this.closeWasClean = true\n this.reconnectTimer.reset()\n this.teardown(callback, code, reason)\n }\n\n /**\n *\n * @param {Object} params - The params to send when connecting, for example `{user_id: userToken}`\n *\n * Passing params to connect is deprecated; pass them in the Socket constructor instead:\n * `new Socket(\"/socket\", {params: {user_id: userToken}})`.\n */\n connect(params){\n if(params){\n console && console.log(\"passing params to connect is deprecated. Instead pass :params to the Socket constructor\")\n this.params = closure(params)\n }\n if(this.conn){ return }\n\n this.connectClock++\n this.closeWasClean = false\n this.conn = new this.transport(this.endPointURL())\n this.conn.binaryType = this.binaryType\n this.conn.timeout = this.longpollerTimeout\n this.conn.onopen = () => this.onConnOpen()\n this.conn.onerror = error => this.onConnError(error)\n this.conn.onmessage = event => this.onConnMessage(event)\n this.conn.onclose = event => this.onConnClose(event)\n }\n\n /**\n * Logs the message. Override `this.logger` for specialized logging. noops by default\n * @param {string} kind\n * @param {string} msg\n * @param {Object} data\n */\n log(kind, msg, data){ this.logger(kind, msg, data) }\n\n /**\n * Returns true if a logger has been set on this socket.\n */\n hasLogger(){ return this.logger !== null }\n\n /**\n * Registers callbacks for connection open events\n *\n * @example socket.onOpen(function(){ console.info(\"the socket was opened\") })\n *\n * @param {Function} callback\n */\n onOpen(callback){\n let ref = this.makeRef()\n this.stateChangeCallbacks.open.push([ref, callback])\n return ref\n }\n\n /**\n * Registers callbacks for connection close events\n * @param {Function} callback\n */\n onClose(callback){\n let ref = this.makeRef()\n this.stateChangeCallbacks.close.push([ref, callback])\n return ref\n }\n\n /**\n * Registers callbacks for connection error events\n *\n * @example socket.onError(function(error){ alert(\"An error occurred\") })\n *\n * @param {Function} callback\n */\n onError(callback){\n let ref = this.makeRef()\n this.stateChangeCallbacks.error.push([ref, callback])\n return ref\n }\n\n /**\n * Registers callbacks for connection message events\n * @param {Function} callback\n */\n onMessage(callback){\n let ref = this.makeRef()\n this.stateChangeCallbacks.message.push([ref, callback])\n return ref\n }\n\n /**\n * Pings the server and invokes the callback with the RTT in milliseconds\n * @param {Function} callback\n *\n * Returns true if the ping was pushed or false if unable to be pushed.\n */\n ping(callback){\n if(!this.isConnected()){ return false }\n let ref = this.makeRef()\n let startTime = Date.now()\n this.push({topic: \"phoenix\", event: \"heartbeat\", payload: {}, ref: ref})\n let onMsgRef = this.onMessage(msg => {\n if(msg.ref === ref){\n this.off([onMsgRef])\n callback(Date.now() - startTime)\n }\n })\n return true\n }\n\n /**\n * @private\n */\n onConnOpen(){\n if(this.hasLogger()) this.log(\"transport\", `connected to ${this.endPointURL()}`)\n this.closeWasClean = false\n this.establishedConnections++\n this.flushSendBuffer()\n this.reconnectTimer.reset()\n this.resetHeartbeat()\n this.stateChangeCallbacks.open.forEach(([, callback]) => callback())\n }\n\n /**\n * @private\n */\n\n heartbeatTimeout(){\n if(this.pendingHeartbeatRef){\n this.pendingHeartbeatRef = null\n if(this.hasLogger()){ this.log(\"transport\", \"heartbeat timeout. Attempting to re-establish connection\") }\n this.triggerChanError()\n this.closeWasClean = false\n this.teardown(() => this.reconnectTimer.scheduleTimeout(), WS_CLOSE_NORMAL, \"heartbeat timeout\")\n }\n }\n\n resetHeartbeat(){\n if(this.conn && this.conn.skipHeartbeat){ return }\n this.pendingHeartbeatRef = null\n clearTimeout(this.heartbeatTimer)\n setTimeout(() => this.sendHeartbeat(), this.heartbeatIntervalMs)\n }\n\n teardown(callback, code, reason){\n if(!this.conn){\n return callback && callback()\n }\n\n this.waitForBufferDone(() => {\n if(this.conn){\n if(code){ this.conn.close(code, reason || \"\") } else { this.conn.close() }\n }\n\n this.waitForSocketClosed(() => {\n if(this.conn){\n this.conn.onopen = function (){ } // noop\n this.conn.onerror = function (){ } // noop\n this.conn.onmessage = function (){ } // noop\n this.conn.onclose = function (){ } // noop\n this.conn = null\n }\n\n callback && callback()\n })\n })\n }\n\n waitForBufferDone(callback, tries = 1){\n if(tries === 5 || !this.conn || !this.conn.bufferedAmount){\n callback()\n return\n }\n\n setTimeout(() => {\n this.waitForBufferDone(callback, tries + 1)\n }, 150 * tries)\n }\n\n waitForSocketClosed(callback, tries = 1){\n if(tries === 5 || !this.conn || this.conn.readyState === SOCKET_STATES.closed){\n callback()\n return\n }\n\n setTimeout(() => {\n this.waitForSocketClosed(callback, tries + 1)\n }, 150 * tries)\n }\n\n onConnClose(event){\n let closeCode = event && event.code\n if(this.hasLogger()) this.log(\"transport\", \"close\", event)\n this.triggerChanError()\n clearTimeout(this.heartbeatTimer)\n if(!this.closeWasClean && closeCode !== 1000){\n this.reconnectTimer.scheduleTimeout()\n }\n this.stateChangeCallbacks.close.forEach(([, callback]) => callback(event))\n }\n\n /**\n * @private\n */\n onConnError(error){\n if(this.hasLogger()) this.log(\"transport\", error)\n let transportBefore = this.transport\n let establishedBefore = this.establishedConnections\n this.stateChangeCallbacks.error.forEach(([, callback]) => {\n callback(error, transportBefore, establishedBefore)\n })\n if(transportBefore === this.transport || establishedBefore > 0){\n this.triggerChanError()\n }\n }\n\n /**\n * @private\n */\n triggerChanError(){\n this.channels.forEach(channel => {\n if(!(channel.isErrored() || channel.isLeaving() || channel.isClosed())){\n channel.trigger(CHANNEL_EVENTS.error)\n }\n })\n }\n\n /**\n * @returns {string}\n */\n connectionState(){\n switch(this.conn && this.conn.readyState){\n case SOCKET_STATES.connecting: return \"connecting\"\n case SOCKET_STATES.open: return \"open\"\n case SOCKET_STATES.closing: return \"closing\"\n default: return \"closed\"\n }\n }\n\n /**\n * @returns {boolean}\n */\n isConnected(){ return this.connectionState() === \"open\" }\n\n /**\n * @private\n *\n * @param {Channel}\n */\n remove(channel){\n this.off(channel.stateChangeRefs)\n this.channels = this.channels.filter(c => c.joinRef() !== channel.joinRef())\n }\n\n /**\n * Removes `onOpen`, `onClose`, `onError,` and `onMessage` registrations.\n *\n * @param {refs} - list of refs returned by calls to\n * `onOpen`, `onClose`, `onError,` and `onMessage`\n */\n off(refs){\n for(let key in this.stateChangeCallbacks){\n this.stateChangeCallbacks[key] = this.stateChangeCallbacks[key].filter(([ref]) => {\n return refs.indexOf(ref) === -1\n })\n }\n }\n\n /**\n * Initiates a new channel for the given topic\n *\n * @param {string} topic\n * @param {Object} chanParams - Parameters for the channel\n * @returns {Channel}\n */\n channel(topic, chanParams = {}){\n let chan = new Channel(topic, chanParams, this)\n this.channels.push(chan)\n return chan\n }\n\n /**\n * @param {Object} data\n */\n push(data){\n if(this.hasLogger()){\n let {topic, event, payload, ref, join_ref} = data\n this.log(\"push\", `${topic} ${event} (${join_ref}, ${ref})`, payload)\n }\n\n if(this.isConnected()){\n this.encode(data, result => this.conn.send(result))\n } else {\n this.sendBuffer.push(() => this.encode(data, result => this.conn.send(result)))\n }\n }\n\n /**\n * Return the next message ref, accounting for overflows\n * @returns {string}\n */\n makeRef(){\n let newRef = this.ref + 1\n if(newRef === this.ref){ this.ref = 0 } else { this.ref = newRef }\n\n return this.ref.toString()\n }\n\n sendHeartbeat(){\n if(this.pendingHeartbeatRef && !this.isConnected()){ return }\n this.pendingHeartbeatRef = this.makeRef()\n this.push({topic: \"phoenix\", event: \"heartbeat\", payload: {}, ref: this.pendingHeartbeatRef})\n this.heartbeatTimer = setTimeout(() => this.heartbeatTimeout(), this.heartbeatIntervalMs)\n }\n\n flushSendBuffer(){\n if(this.isConnected() && this.sendBuffer.length > 0){\n this.sendBuffer.forEach(callback => callback())\n this.sendBuffer = []\n }\n }\n\n onConnMessage(rawMessage){\n this.decode(rawMessage.data, msg => {\n let {topic, event, payload, ref, join_ref} = msg\n if(ref && ref === this.pendingHeartbeatRef){\n clearTimeout(this.heartbeatTimer)\n this.pendingHeartbeatRef = null\n setTimeout(() => this.sendHeartbeat(), this.heartbeatIntervalMs)\n }\n\n if(this.hasLogger()) this.log(\"receive\", `${payload.status || \"\"} ${topic} ${event} ${ref && \"(\" + ref + \")\" || \"\"}`, payload)\n\n for(let i = 0; i < this.channels.length; i++){\n const channel = this.channels[i]\n if(!channel.isMember(topic, event, payload, join_ref)){ continue }\n channel.trigger(event, payload, ref, join_ref)\n }\n\n for(let i = 0; i < this.stateChangeCallbacks.message.length; i++){\n let [, callback] = this.stateChangeCallbacks.message[i]\n callback(msg)\n }\n })\n }\n\n leaveOpenTopic(topic){\n let dupChannel = this.channels.find(c => c.topic === topic && (c.isJoined() || c.isJoining()))\n if(dupChannel){\n if(this.hasLogger()) this.log(\"transport\", `leaving duplicate topic \"${topic}\"`)\n dupChannel.leave()\n }\n }\n}\n"], + "mappings": "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", "names": [] } diff --git a/priv/static/phoenix.js b/priv/static/phoenix.js index d5ea8025df..d424f773bc 100644 --- a/priv/static/phoenix.js +++ b/priv/static/phoenix.js @@ -957,7 +957,9 @@ var Phoenix = (() => { if (this.hasLogger()) { this.log("transport", "heartbeat timeout. Attempting to re-establish connection"); } - this.abnormalClose("heartbeat timeout"); + this.triggerChanError(); + this.closeWasClean = false; + this.teardown(() => this.reconnectTimer.scheduleTimeout(), WS_CLOSE_NORMAL, "heartbeat timeout"); } } resetHeartbeat() { @@ -982,6 +984,12 @@ var Phoenix = (() => { } this.waitForSocketClosed(() => { if (this.conn) { + this.conn.onopen = function() { + }; + this.conn.onerror = function() { + }; + this.conn.onmessage = function() { + }; this.conn.onclose = function() { }; this.conn = null; @@ -1097,12 +1105,6 @@ var Phoenix = (() => { this.push({ topic: "phoenix", event: "heartbeat", payload: {}, ref: this.pendingHeartbeatRef }); this.heartbeatTimer = setTimeout(() => this.heartbeatTimeout(), this.heartbeatIntervalMs); } - abnormalClose(reason) { - this.closeWasClean = false; - if (this.isConnected()) { - this.conn.close(WS_CLOSE_NORMAL, reason); - } - } flushSendBuffer() { if (this.isConnected() && this.sendBuffer.length > 0) { this.sendBuffer.forEach((callback) => callback()); diff --git a/priv/static/phoenix.min.js b/priv/static/phoenix.min.js index f4a11903db..203a5be243 100644 --- a/priv/static/phoenix.min.js +++ b/priv/static/phoenix.min.js @@ -1 +1 @@ -var Phoenix=(()=>{var w=Object.defineProperty;var U=Object.getOwnPropertyDescriptor;var M=Object.getOwnPropertyNames;var P=Object.prototype.hasOwnProperty;var $=(h,e)=>{for(var t in e)w(h,t,{get:e[t],enumerable:!0})},B=(h,e,t,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of M(e))!P.call(h,s)&&s!==t&&w(h,s,{get:()=>e[s],enumerable:!(i=U(e,s))||i.enumerable});return h};var J=h=>B(w({},"__esModule",{value:!0}),h);var I={};$(I,{Channel:()=>A,LongPoll:()=>T,Presence:()=>m,Serializer:()=>j,Socket:()=>x});var v=h=>typeof h=="function"?h:function(){return h};var z=typeof self!="undefined"?self:null,b=typeof window!="undefined"?window:null,R=z||b||R,N="2.0.0",d={connecting:0,open:1,closing:2,closed:3},O=1e4,H=1e3,u={closed:"closed",errored:"errored",joined:"joined",joining:"joining",leaving:"leaving"},p={close:"phx_close",error:"phx_error",join:"phx_join",reply:"phx_reply",leave:"phx_leave"},L={longpoll:"longpoll",websocket:"websocket"},D={complete:4};var S=class{constructor(e,t,i,s){this.channel=e,this.event=t,this.payload=i||function(){return{}},this.receivedResp=null,this.timeout=s,this.timeoutTimer=null,this.recHooks=[],this.sent=!1}resend(e){this.timeout=e,this.reset(),this.send()}send(){this.hasReceived("timeout")||(this.startTimeout(),this.sent=!0,this.channel.socket.push({topic:this.channel.topic,event:this.event,payload:this.payload(),ref:this.ref,join_ref:this.channel.joinRef()}))}receive(e,t){return this.hasReceived(e)&&t(this.receivedResp.response),this.recHooks.push({status:e,callback:t}),this}reset(){this.cancelRefEvent(),this.ref=null,this.refEvent=null,this.receivedResp=null,this.sent=!1}matchReceive({status:e,response:t,_ref:i}){this.recHooks.filter(s=>s.status===e).forEach(s=>s.callback(t))}cancelRefEvent(){!this.refEvent||this.channel.off(this.refEvent)}cancelTimeout(){clearTimeout(this.timeoutTimer),this.timeoutTimer=null}startTimeout(){this.timeoutTimer&&this.cancelTimeout(),this.ref=this.channel.socket.makeRef(),this.refEvent=this.channel.replyEventName(this.ref),this.channel.on(this.refEvent,e=>{this.cancelRefEvent(),this.cancelTimeout(),this.receivedResp=e,this.matchReceive(e)}),this.timeoutTimer=setTimeout(()=>{this.trigger("timeout",{})},this.timeout)}hasReceived(e){return this.receivedResp&&this.receivedResp.status===e}trigger(e,t){this.channel.trigger(this.refEvent,{status:e,response:t})}};var y=class{constructor(e,t){this.callback=e,this.timerCalc=t,this.timer=null,this.tries=0}reset(){this.tries=0,clearTimeout(this.timer)}scheduleTimeout(){clearTimeout(this.timer),this.timer=setTimeout(()=>{this.tries=this.tries+1,this.callback()},this.timerCalc(this.tries+1))}};var A=class{constructor(e,t,i){this.state=u.closed,this.topic=e,this.params=v(t||{}),this.socket=i,this.bindings=[],this.bindingRef=0,this.timeout=this.socket.timeout,this.joinedOnce=!1,this.joinPush=new S(this,p.join,this.params,this.timeout),this.pushBuffer=[],this.stateChangeRefs=[],this.rejoinTimer=new y(()=>{this.socket.isConnected()&&this.rejoin()},this.socket.rejoinAfterMs),this.stateChangeRefs.push(this.socket.onError(()=>this.rejoinTimer.reset())),this.stateChangeRefs.push(this.socket.onOpen(()=>{this.rejoinTimer.reset(),this.isErrored()&&this.rejoin()})),this.joinPush.receive("ok",()=>{this.state=u.joined,this.rejoinTimer.reset(),this.pushBuffer.forEach(s=>s.send()),this.pushBuffer=[]}),this.joinPush.receive("error",()=>{this.state=u.errored,this.socket.isConnected()&&this.rejoinTimer.scheduleTimeout()}),this.onClose(()=>{this.rejoinTimer.reset(),this.socket.hasLogger()&&this.socket.log("channel",`close ${this.topic} ${this.joinRef()}`),this.state=u.closed,this.socket.remove(this)}),this.onError(s=>{this.socket.hasLogger()&&this.socket.log("channel",`error ${this.topic}`,s),this.isJoining()&&this.joinPush.reset(),this.state=u.errored,this.socket.isConnected()&&this.rejoinTimer.scheduleTimeout()}),this.joinPush.receive("timeout",()=>{this.socket.hasLogger()&&this.socket.log("channel",`timeout ${this.topic} (${this.joinRef()})`,this.joinPush.timeout),new S(this,p.leave,v({}),this.timeout).send(),this.state=u.errored,this.joinPush.reset(),this.socket.isConnected()&&this.rejoinTimer.scheduleTimeout()}),this.on(p.reply,(s,o)=>{this.trigger(this.replyEventName(o),s)})}join(e=this.timeout){if(this.joinedOnce)throw new Error("tried to join multiple times. 'join' can only be called a single time per channel instance");return this.timeout=e,this.joinedOnce=!0,this.rejoin(),this.joinPush}onClose(e){this.on(p.close,e)}onError(e){return this.on(p.error,t=>e(t))}on(e,t){let i=this.bindingRef++;return this.bindings.push({event:e,ref:i,callback:t}),i}off(e,t){this.bindings=this.bindings.filter(i=>!(i.event===e&&(typeof t=="undefined"||t===i.ref)))}canPush(){return this.socket.isConnected()&&this.isJoined()}push(e,t,i=this.timeout){if(t=t||{},!this.joinedOnce)throw new Error(`tried to push '${e}' to '${this.topic}' before joining. Use channel.join() before pushing events`);let s=new S(this,e,function(){return t},i);return this.canPush()?s.send():(s.startTimeout(),this.pushBuffer.push(s)),s}leave(e=this.timeout){this.rejoinTimer.reset(),this.joinPush.cancelTimeout(),this.state=u.leaving;let t=()=>{this.socket.hasLogger()&&this.socket.log("channel",`leave ${this.topic}`),this.trigger(p.close,"leave")},i=new S(this,p.leave,v({}),e);return i.receive("ok",()=>t()).receive("timeout",()=>t()),i.send(),this.canPush()||i.trigger("ok",{}),i}onMessage(e,t,i){return t}isMember(e,t,i,s){return this.topic!==e?!1:s&&s!==this.joinRef()?(this.socket.hasLogger()&&this.socket.log("channel","dropping outdated message",{topic:e,event:t,payload:i,joinRef:s}),!1):!0}joinRef(){return this.joinPush.ref}rejoin(e=this.timeout){this.isLeaving()||(this.socket.leaveOpenTopic(this.topic),this.state=u.joining,this.joinPush.resend(e))}trigger(e,t,i,s){let o=this.onMessage(e,t,i,s);if(t&&!o)throw new Error("channel onMessage callbacks must return the payload, modified or unmodified");let r=this.bindings.filter(n=>n.event===e);for(let n=0;n{let a=this.parseJSON(e.responseText);n&&n(a)},r&&(e.ontimeout=r),e.onprogress=()=>{},e.send(s),e}static xhrRequest(e,t,i,s,o,r,n,a){return e.open(t,i,!0),e.timeout=r,e.setRequestHeader("Content-Type",s),e.onerror=()=>a&&a(null),e.onreadystatechange=()=>{if(e.readyState===D.complete&&a){let l=this.parseJSON(e.responseText);a(l)}},n&&(e.ontimeout=n),e.send(o),e}static parseJSON(e){if(!e||e==="")return null;try{return JSON.parse(e)}catch(t){return console&&console.log("failed to parse JSON response",e),null}}static serialize(e,t){let i=[];for(var s in e){if(!Object.prototype.hasOwnProperty.call(e,s))continue;let o=t?`${t}[${s}]`:s,r=e[s];typeof r=="object"?i.push(this.serialize(r,o)):i.push(encodeURIComponent(o)+"="+encodeURIComponent(r))}return i.join("&")}static appendParams(e,t){if(Object.keys(t).length===0)return e;let i=e.match(/\?/)?"&":"?";return`${e}${i}${this.serialize(t)}`}};var T=class{constructor(e){this.endPoint=null,this.token=null,this.skipHeartbeat=!0,this.reqs=new Set,this.onopen=function(){},this.onerror=function(){},this.onmessage=function(){},this.onclose=function(){},this.pollEndpoint=this.normalizeEndpoint(e),this.readyState=d.connecting,this.poll()}normalizeEndpoint(e){return e.replace("ws://","http://").replace("wss://","https://").replace(new RegExp("(.*)/"+L.websocket),"$1/"+L.longpoll)}endpointURL(){return g.appendParams(this.pollEndpoint,{token:this.token})}closeAndRetry(e,t,i){this.close(e,t,i),this.readyState=d.connecting}ontimeout(){this.onerror("timeout"),this.closeAndRetry(1005,"timeout",!1)}isActive(){return this.readyState===d.open||this.readyState===d.connecting}poll(){this.ajax("GET",null,()=>this.ontimeout(),e=>{if(e){var{status:t,token:i,messages:s}=e;this.token=i}else t=0;switch(t){case 200:s.forEach(o=>{setTimeout(()=>this.onmessage({data:o}),0)}),this.poll();break;case 204:this.poll();break;case 410:this.readyState=d.open,this.onopen({}),this.poll();break;case 403:this.onerror(403),this.close(1008,"forbidden",!1);break;case 0:case 500:this.onerror(500),this.closeAndRetry(1011,"internal server error",500);break;default:throw new Error(`unhandled poll status ${t}`)}})}send(e){this.ajax("POST",e,()=>this.onerror("timeout"),t=>{(!t||t.status!==200)&&(this.onerror(t&&t.status),this.closeAndRetry(1011,"internal server error",!1))})}close(e,t,i){for(let o of this.reqs)o.abort();this.readyState=d.closed;let s=Object.assign({code:1e3,reason:void 0,wasClean:!0},{code:e,reason:t,wasClean:i});typeof CloseEvent!="undefined"?this.onclose(new CloseEvent("close",s)):this.onclose(s)}ajax(e,t,i,s){let o,r=()=>{this.reqs.delete(o),i()};o=g.request(e,this.endpointURL(),"application/json",t,this.timeout,r,n=>{this.reqs.delete(o),this.isActive()&&s(n)}),this.reqs.add(o)}};var m=class{constructor(e,t={}){let i=t.events||{state:"presence_state",diff:"presence_diff"};this.state={},this.pendingDiffs=[],this.channel=e,this.joinRef=null,this.caller={onJoin:function(){},onLeave:function(){},onSync:function(){}},this.channel.on(i.state,s=>{let{onJoin:o,onLeave:r,onSync:n}=this.caller;this.joinRef=this.channel.joinRef(),this.state=m.syncState(this.state,s,o,r),this.pendingDiffs.forEach(a=>{this.state=m.syncDiff(this.state,a,o,r)}),this.pendingDiffs=[],n()}),this.channel.on(i.diff,s=>{let{onJoin:o,onLeave:r,onSync:n}=this.caller;this.inPendingSyncState()?this.pendingDiffs.push(s):(this.state=m.syncDiff(this.state,s,o,r),n())})}onJoin(e){this.caller.onJoin=e}onLeave(e){this.caller.onLeave=e}onSync(e){this.caller.onSync=e}list(e){return m.list(this.state,e)}inPendingSyncState(){return!this.joinRef||this.joinRef!==this.channel.joinRef()}static syncState(e,t,i,s){let o=this.clone(e),r={},n={};return this.map(o,(a,l)=>{t[a]||(n[a]=l)}),this.map(t,(a,l)=>{let f=o[a];if(f){let c=l.metas.map(E=>E.phx_ref),C=f.metas.map(E=>E.phx_ref),k=l.metas.filter(E=>C.indexOf(E.phx_ref)<0),_=f.metas.filter(E=>c.indexOf(E.phx_ref)<0);k.length>0&&(r[a]=l,r[a].metas=k),_.length>0&&(n[a]=this.clone(f),n[a].metas=_)}else r[a]=l}),this.syncDiff(o,{joins:r,leaves:n},i,s)}static syncDiff(e,t,i,s){let{joins:o,leaves:r}=this.clone(t);return i||(i=function(){}),s||(s=function(){}),this.map(o,(n,a)=>{let l=e[n];if(e[n]=this.clone(a),l){let f=e[n].metas.map(C=>C.phx_ref),c=l.metas.filter(C=>f.indexOf(C.phx_ref)<0);e[n].metas.unshift(...c)}i(n,l,a)}),this.map(r,(n,a)=>{let l=e[n];if(!l)return;let f=a.metas.map(c=>c.phx_ref);l.metas=l.metas.filter(c=>f.indexOf(c.phx_ref)<0),s(n,l,a),l.metas.length===0&&delete e[n]}),e}static list(e,t){return t||(t=function(i,s){return s}),this.map(e,(i,s)=>t(i,s))}static map(e,t){return Object.getOwnPropertyNames(e).map(i=>t(i,e[i]))}static clone(e){return JSON.parse(JSON.stringify(e))}};var j={HEADER_LENGTH:1,META_LENGTH:4,KINDS:{push:0,reply:1,broadcast:2},encode(h,e){if(h.payload.constructor===ArrayBuffer)return e(this.binaryEncode(h));{let t=[h.join_ref,h.ref,h.topic,h.event,h.payload];return e(JSON.stringify(t))}},decode(h,e){if(h.constructor===ArrayBuffer)return e(this.binaryDecode(h));{let[t,i,s,o,r]=JSON.parse(h);return e({join_ref:t,ref:i,topic:s,event:o,payload:r})}},binaryEncode(h){let{join_ref:e,ref:t,event:i,topic:s,payload:o}=h,r=this.META_LENGTH+e.length+t.length+s.length+i.length,n=new ArrayBuffer(this.HEADER_LENGTH+r),a=new DataView(n),l=0;a.setUint8(l++,this.KINDS.push),a.setUint8(l++,e.length),a.setUint8(l++,t.length),a.setUint8(l++,s.length),a.setUint8(l++,i.length),Array.from(e,c=>a.setUint8(l++,c.charCodeAt(0))),Array.from(t,c=>a.setUint8(l++,c.charCodeAt(0))),Array.from(s,c=>a.setUint8(l++,c.charCodeAt(0))),Array.from(i,c=>a.setUint8(l++,c.charCodeAt(0)));var f=new Uint8Array(n.byteLength+o.byteLength);return f.set(new Uint8Array(n),0),f.set(new Uint8Array(o),n.byteLength),f.buffer},binaryDecode(h){let e=new DataView(h),t=e.getUint8(0),i=new TextDecoder;switch(t){case this.KINDS.push:return this.decodePush(h,e,i);case this.KINDS.reply:return this.decodeReply(h,e,i);case this.KINDS.broadcast:return this.decodeBroadcast(h,e,i)}},decodePush(h,e,t){let i=e.getUint8(1),s=e.getUint8(2),o=e.getUint8(3),r=this.HEADER_LENGTH+this.META_LENGTH-1,n=t.decode(h.slice(r,r+i));r=r+i;let a=t.decode(h.slice(r,r+s));r=r+s;let l=t.decode(h.slice(r,r+o));r=r+o;let f=h.slice(r,h.byteLength);return{join_ref:n,ref:null,topic:a,event:l,payload:f}},decodeReply(h,e,t){let i=e.getUint8(1),s=e.getUint8(2),o=e.getUint8(3),r=e.getUint8(4),n=this.HEADER_LENGTH+this.META_LENGTH,a=t.decode(h.slice(n,n+i));n=n+i;let l=t.decode(h.slice(n,n+s));n=n+s;let f=t.decode(h.slice(n,n+o));n=n+o;let c=t.decode(h.slice(n,n+r));n=n+r;let C=h.slice(n,h.byteLength),k={status:c,response:C};return{join_ref:a,ref:l,topic:f,event:p.reply,payload:k}},decodeBroadcast(h,e,t){let i=e.getUint8(1),s=e.getUint8(2),o=this.HEADER_LENGTH+2,r=t.decode(h.slice(o,o+i));o=o+i;let n=t.decode(h.slice(o,o+s));o=o+s;let a=h.slice(o,h.byteLength);return{join_ref:null,ref:null,topic:r,event:n,payload:a}}};var x=class{constructor(e,t={}){this.stateChangeCallbacks={open:[],close:[],error:[],message:[]},this.channels=[],this.sendBuffer=[],this.ref=0,this.timeout=t.timeout||O,this.transport=t.transport||R.WebSocket||T,this.establishedConnections=0,this.defaultEncoder=j.encode.bind(j),this.defaultDecoder=j.decode.bind(j),this.closeWasClean=!1,this.binaryType=t.binaryType||"arraybuffer",this.connectClock=1,this.transport!==T?(this.encode=t.encode||this.defaultEncoder,this.decode=t.decode||this.defaultDecoder):(this.encode=this.defaultEncoder,this.decode=this.defaultDecoder);let i=null;b&&b.addEventListener&&(b.addEventListener("pagehide",s=>{this.conn&&(this.disconnect(),i=this.connectClock)}),b.addEventListener("pageshow",s=>{i===this.connectClock&&(i=null,this.connect())})),this.heartbeatIntervalMs=t.heartbeatIntervalMs||3e4,this.rejoinAfterMs=s=>t.rejoinAfterMs?t.rejoinAfterMs(s):[1e3,2e3,5e3][s-1]||1e4,this.reconnectAfterMs=s=>t.reconnectAfterMs?t.reconnectAfterMs(s):[10,50,100,150,200,250,500,1e3,2e3][s-1]||5e3,this.logger=t.logger||null,this.longpollerTimeout=t.longpollerTimeout||2e4,this.params=v(t.params||{}),this.endPoint=`${e}/${L.websocket}`,this.vsn=t.vsn||N,this.heartbeatTimer=null,this.pendingHeartbeatRef=null,this.reconnectTimer=new y(()=>{this.teardown(()=>this.connect())},this.reconnectAfterMs)}getLongPollTransport(){return T}replaceTransport(e){this.connectClock++,this.closeWasClean=!0,this.reconnectTimer.reset(),this.sendBuffer=[],this.conn&&(this.conn.close(),this.conn=null),this.transport=e}protocol(){return location.protocol.match(/^https/)?"wss":"ws"}endPointURL(){let e=g.appendParams(g.appendParams(this.endPoint,this.params()),{vsn:this.vsn});return e.charAt(0)!=="/"?e:e.charAt(1)==="/"?`${this.protocol()}:${e}`:`${this.protocol()}://${location.host}${e}`}disconnect(e,t,i){this.connectClock++,this.closeWasClean=!0,this.reconnectTimer.reset(),this.teardown(e,t,i)}connect(e){e&&(console&&console.log("passing params to connect is deprecated. Instead pass :params to the Socket constructor"),this.params=v(e)),!this.conn&&(this.connectClock++,this.closeWasClean=!1,this.conn=new this.transport(this.endPointURL()),this.conn.binaryType=this.binaryType,this.conn.timeout=this.longpollerTimeout,this.conn.onopen=()=>this.onConnOpen(),this.conn.onerror=t=>this.onConnError(t),this.conn.onmessage=t=>this.onConnMessage(t),this.conn.onclose=t=>this.onConnClose(t))}log(e,t,i){this.logger(e,t,i)}hasLogger(){return this.logger!==null}onOpen(e){let t=this.makeRef();return this.stateChangeCallbacks.open.push([t,e]),t}onClose(e){let t=this.makeRef();return this.stateChangeCallbacks.close.push([t,e]),t}onError(e){let t=this.makeRef();return this.stateChangeCallbacks.error.push([t,e]),t}onMessage(e){let t=this.makeRef();return this.stateChangeCallbacks.message.push([t,e]),t}ping(e){if(!this.isConnected())return!1;let t=this.makeRef(),i=Date.now();this.push({topic:"phoenix",event:"heartbeat",payload:{},ref:t});let s=this.onMessage(o=>{o.ref===t&&(this.off([s]),e(Date.now()-i))});return!0}onConnOpen(){this.hasLogger()&&this.log("transport",`connected to ${this.endPointURL()}`),this.closeWasClean=!1,this.establishedConnections++,this.flushSendBuffer(),this.reconnectTimer.reset(),this.resetHeartbeat(),this.stateChangeCallbacks.open.forEach(([,e])=>e())}heartbeatTimeout(){this.pendingHeartbeatRef&&(this.pendingHeartbeatRef=null,this.hasLogger()&&this.log("transport","heartbeat timeout. Attempting to re-establish connection"),this.abnormalClose("heartbeat timeout"))}resetHeartbeat(){this.conn&&this.conn.skipHeartbeat||(this.pendingHeartbeatRef=null,clearTimeout(this.heartbeatTimer),setTimeout(()=>this.sendHeartbeat(),this.heartbeatIntervalMs))}teardown(e,t,i){if(!this.conn)return e&&e();this.waitForBufferDone(()=>{this.conn&&(t?this.conn.close(t,i||""):this.conn.close()),this.waitForSocketClosed(()=>{this.conn&&(this.conn.onclose=function(){},this.conn=null),e&&e()})})}waitForBufferDone(e,t=1){if(t===5||!this.conn||!this.conn.bufferedAmount){e();return}setTimeout(()=>{this.waitForBufferDone(e,t+1)},150*t)}waitForSocketClosed(e,t=1){if(t===5||!this.conn||this.conn.readyState===d.closed){e();return}setTimeout(()=>{this.waitForSocketClosed(e,t+1)},150*t)}onConnClose(e){let t=e&&e.code;this.hasLogger()&&this.log("transport","close",e),this.triggerChanError(),clearTimeout(this.heartbeatTimer),!this.closeWasClean&&t!==1e3&&this.reconnectTimer.scheduleTimeout(),this.stateChangeCallbacks.close.forEach(([,i])=>i(e))}onConnError(e){this.hasLogger()&&this.log("transport",e);let t=this.transport,i=this.establishedConnections;this.stateChangeCallbacks.error.forEach(([,s])=>{s(e,t,i)}),(t===this.transport||i>0)&&this.triggerChanError()}triggerChanError(){this.channels.forEach(e=>{e.isErrored()||e.isLeaving()||e.isClosed()||e.trigger(p.error)})}connectionState(){switch(this.conn&&this.conn.readyState){case d.connecting:return"connecting";case d.open:return"open";case d.closing:return"closing";default:return"closed"}}isConnected(){return this.connectionState()==="open"}remove(e){this.off(e.stateChangeRefs),this.channels=this.channels.filter(t=>t.joinRef()!==e.joinRef())}off(e){for(let t in this.stateChangeCallbacks)this.stateChangeCallbacks[t]=this.stateChangeCallbacks[t].filter(([i])=>e.indexOf(i)===-1)}channel(e,t={}){let i=new A(e,t,this);return this.channels.push(i),i}push(e){if(this.hasLogger()){let{topic:t,event:i,payload:s,ref:o,join_ref:r}=e;this.log("push",`${t} ${i} (${r}, ${o})`,s)}this.isConnected()?this.encode(e,t=>this.conn.send(t)):this.sendBuffer.push(()=>this.encode(e,t=>this.conn.send(t)))}makeRef(){let e=this.ref+1;return e===this.ref?this.ref=0:this.ref=e,this.ref.toString()}sendHeartbeat(){this.pendingHeartbeatRef&&!this.isConnected()||(this.pendingHeartbeatRef=this.makeRef(),this.push({topic:"phoenix",event:"heartbeat",payload:{},ref:this.pendingHeartbeatRef}),this.heartbeatTimer=setTimeout(()=>this.heartbeatTimeout(),this.heartbeatIntervalMs))}abnormalClose(e){this.closeWasClean=!1,this.isConnected()&&this.conn.close(H,e)}flushSendBuffer(){this.isConnected()&&this.sendBuffer.length>0&&(this.sendBuffer.forEach(e=>e()),this.sendBuffer=[])}onConnMessage(e){this.decode(e.data,t=>{let{topic:i,event:s,payload:o,ref:r,join_ref:n}=t;r&&r===this.pendingHeartbeatRef&&(clearTimeout(this.heartbeatTimer),this.pendingHeartbeatRef=null,setTimeout(()=>this.sendHeartbeat(),this.heartbeatIntervalMs)),this.hasLogger()&&this.log("receive",`${o.status||""} ${i} ${s} ${r&&"("+r+")"||""}`,o);for(let a=0;ai.topic===e&&(i.isJoined()||i.isJoining()));t&&(this.hasLogger()&&this.log("transport",`leaving duplicate topic "${e}"`),t.leave())}};return J(I);})(); +var Phoenix=(()=>{var w=Object.defineProperty;var U=Object.getOwnPropertyDescriptor;var M=Object.getOwnPropertyNames;var P=Object.prototype.hasOwnProperty;var $=(h,e)=>{for(var t in e)w(h,t,{get:e[t],enumerable:!0})},B=(h,e,t,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of M(e))!P.call(h,s)&&s!==t&&w(h,s,{get:()=>e[s],enumerable:!(i=U(e,s))||i.enumerable});return h};var J=h=>B(w({},"__esModule",{value:!0}),h);var I={};$(I,{Channel:()=>A,LongPoll:()=>T,Presence:()=>m,Serializer:()=>j,Socket:()=>x});var v=h=>typeof h=="function"?h:function(){return h};var z=typeof self!="undefined"?self:null,y=typeof window!="undefined"?window:null,R=z||y||R,N="2.0.0",d={connecting:0,open:1,closing:2,closed:3},O=1e4,H=1e3,u={closed:"closed",errored:"errored",joined:"joined",joining:"joining",leaving:"leaving"},p={close:"phx_close",error:"phx_error",join:"phx_join",reply:"phx_reply",leave:"phx_leave"},L={longpoll:"longpoll",websocket:"websocket"},D={complete:4};var S=class{constructor(e,t,i,s){this.channel=e,this.event=t,this.payload=i||function(){return{}},this.receivedResp=null,this.timeout=s,this.timeoutTimer=null,this.recHooks=[],this.sent=!1}resend(e){this.timeout=e,this.reset(),this.send()}send(){this.hasReceived("timeout")||(this.startTimeout(),this.sent=!0,this.channel.socket.push({topic:this.channel.topic,event:this.event,payload:this.payload(),ref:this.ref,join_ref:this.channel.joinRef()}))}receive(e,t){return this.hasReceived(e)&&t(this.receivedResp.response),this.recHooks.push({status:e,callback:t}),this}reset(){this.cancelRefEvent(),this.ref=null,this.refEvent=null,this.receivedResp=null,this.sent=!1}matchReceive({status:e,response:t,_ref:i}){this.recHooks.filter(s=>s.status===e).forEach(s=>s.callback(t))}cancelRefEvent(){!this.refEvent||this.channel.off(this.refEvent)}cancelTimeout(){clearTimeout(this.timeoutTimer),this.timeoutTimer=null}startTimeout(){this.timeoutTimer&&this.cancelTimeout(),this.ref=this.channel.socket.makeRef(),this.refEvent=this.channel.replyEventName(this.ref),this.channel.on(this.refEvent,e=>{this.cancelRefEvent(),this.cancelTimeout(),this.receivedResp=e,this.matchReceive(e)}),this.timeoutTimer=setTimeout(()=>{this.trigger("timeout",{})},this.timeout)}hasReceived(e){return this.receivedResp&&this.receivedResp.status===e}trigger(e,t){this.channel.trigger(this.refEvent,{status:e,response:t})}};var b=class{constructor(e,t){this.callback=e,this.timerCalc=t,this.timer=null,this.tries=0}reset(){this.tries=0,clearTimeout(this.timer)}scheduleTimeout(){clearTimeout(this.timer),this.timer=setTimeout(()=>{this.tries=this.tries+1,this.callback()},this.timerCalc(this.tries+1))}};var A=class{constructor(e,t,i){this.state=u.closed,this.topic=e,this.params=v(t||{}),this.socket=i,this.bindings=[],this.bindingRef=0,this.timeout=this.socket.timeout,this.joinedOnce=!1,this.joinPush=new S(this,p.join,this.params,this.timeout),this.pushBuffer=[],this.stateChangeRefs=[],this.rejoinTimer=new b(()=>{this.socket.isConnected()&&this.rejoin()},this.socket.rejoinAfterMs),this.stateChangeRefs.push(this.socket.onError(()=>this.rejoinTimer.reset())),this.stateChangeRefs.push(this.socket.onOpen(()=>{this.rejoinTimer.reset(),this.isErrored()&&this.rejoin()})),this.joinPush.receive("ok",()=>{this.state=u.joined,this.rejoinTimer.reset(),this.pushBuffer.forEach(s=>s.send()),this.pushBuffer=[]}),this.joinPush.receive("error",()=>{this.state=u.errored,this.socket.isConnected()&&this.rejoinTimer.scheduleTimeout()}),this.onClose(()=>{this.rejoinTimer.reset(),this.socket.hasLogger()&&this.socket.log("channel",`close ${this.topic} ${this.joinRef()}`),this.state=u.closed,this.socket.remove(this)}),this.onError(s=>{this.socket.hasLogger()&&this.socket.log("channel",`error ${this.topic}`,s),this.isJoining()&&this.joinPush.reset(),this.state=u.errored,this.socket.isConnected()&&this.rejoinTimer.scheduleTimeout()}),this.joinPush.receive("timeout",()=>{this.socket.hasLogger()&&this.socket.log("channel",`timeout ${this.topic} (${this.joinRef()})`,this.joinPush.timeout),new S(this,p.leave,v({}),this.timeout).send(),this.state=u.errored,this.joinPush.reset(),this.socket.isConnected()&&this.rejoinTimer.scheduleTimeout()}),this.on(p.reply,(s,o)=>{this.trigger(this.replyEventName(o),s)})}join(e=this.timeout){if(this.joinedOnce)throw new Error("tried to join multiple times. 'join' can only be called a single time per channel instance");return this.timeout=e,this.joinedOnce=!0,this.rejoin(),this.joinPush}onClose(e){this.on(p.close,e)}onError(e){return this.on(p.error,t=>e(t))}on(e,t){let i=this.bindingRef++;return this.bindings.push({event:e,ref:i,callback:t}),i}off(e,t){this.bindings=this.bindings.filter(i=>!(i.event===e&&(typeof t=="undefined"||t===i.ref)))}canPush(){return this.socket.isConnected()&&this.isJoined()}push(e,t,i=this.timeout){if(t=t||{},!this.joinedOnce)throw new Error(`tried to push '${e}' to '${this.topic}' before joining. Use channel.join() before pushing events`);let s=new S(this,e,function(){return t},i);return this.canPush()?s.send():(s.startTimeout(),this.pushBuffer.push(s)),s}leave(e=this.timeout){this.rejoinTimer.reset(),this.joinPush.cancelTimeout(),this.state=u.leaving;let t=()=>{this.socket.hasLogger()&&this.socket.log("channel",`leave ${this.topic}`),this.trigger(p.close,"leave")},i=new S(this,p.leave,v({}),e);return i.receive("ok",()=>t()).receive("timeout",()=>t()),i.send(),this.canPush()||i.trigger("ok",{}),i}onMessage(e,t,i){return t}isMember(e,t,i,s){return this.topic!==e?!1:s&&s!==this.joinRef()?(this.socket.hasLogger()&&this.socket.log("channel","dropping outdated message",{topic:e,event:t,payload:i,joinRef:s}),!1):!0}joinRef(){return this.joinPush.ref}rejoin(e=this.timeout){this.isLeaving()||(this.socket.leaveOpenTopic(this.topic),this.state=u.joining,this.joinPush.resend(e))}trigger(e,t,i,s){let o=this.onMessage(e,t,i,s);if(t&&!o)throw new Error("channel onMessage callbacks must return the payload, modified or unmodified");let r=this.bindings.filter(n=>n.event===e);for(let n=0;n{let a=this.parseJSON(e.responseText);n&&n(a)},r&&(e.ontimeout=r),e.onprogress=()=>{},e.send(s),e}static xhrRequest(e,t,i,s,o,r,n,a){return e.open(t,i,!0),e.timeout=r,e.setRequestHeader("Content-Type",s),e.onerror=()=>a&&a(null),e.onreadystatechange=()=>{if(e.readyState===D.complete&&a){let l=this.parseJSON(e.responseText);a(l)}},n&&(e.ontimeout=n),e.send(o),e}static parseJSON(e){if(!e||e==="")return null;try{return JSON.parse(e)}catch(t){return console&&console.log("failed to parse JSON response",e),null}}static serialize(e,t){let i=[];for(var s in e){if(!Object.prototype.hasOwnProperty.call(e,s))continue;let o=t?`${t}[${s}]`:s,r=e[s];typeof r=="object"?i.push(this.serialize(r,o)):i.push(encodeURIComponent(o)+"="+encodeURIComponent(r))}return i.join("&")}static appendParams(e,t){if(Object.keys(t).length===0)return e;let i=e.match(/\?/)?"&":"?";return`${e}${i}${this.serialize(t)}`}};var T=class{constructor(e){this.endPoint=null,this.token=null,this.skipHeartbeat=!0,this.reqs=new Set,this.onopen=function(){},this.onerror=function(){},this.onmessage=function(){},this.onclose=function(){},this.pollEndpoint=this.normalizeEndpoint(e),this.readyState=d.connecting,this.poll()}normalizeEndpoint(e){return e.replace("ws://","http://").replace("wss://","https://").replace(new RegExp("(.*)/"+L.websocket),"$1/"+L.longpoll)}endpointURL(){return g.appendParams(this.pollEndpoint,{token:this.token})}closeAndRetry(e,t,i){this.close(e,t,i),this.readyState=d.connecting}ontimeout(){this.onerror("timeout"),this.closeAndRetry(1005,"timeout",!1)}isActive(){return this.readyState===d.open||this.readyState===d.connecting}poll(){this.ajax("GET",null,()=>this.ontimeout(),e=>{if(e){var{status:t,token:i,messages:s}=e;this.token=i}else t=0;switch(t){case 200:s.forEach(o=>{setTimeout(()=>this.onmessage({data:o}),0)}),this.poll();break;case 204:this.poll();break;case 410:this.readyState=d.open,this.onopen({}),this.poll();break;case 403:this.onerror(403),this.close(1008,"forbidden",!1);break;case 0:case 500:this.onerror(500),this.closeAndRetry(1011,"internal server error",500);break;default:throw new Error(`unhandled poll status ${t}`)}})}send(e){this.ajax("POST",e,()=>this.onerror("timeout"),t=>{(!t||t.status!==200)&&(this.onerror(t&&t.status),this.closeAndRetry(1011,"internal server error",!1))})}close(e,t,i){for(let o of this.reqs)o.abort();this.readyState=d.closed;let s=Object.assign({code:1e3,reason:void 0,wasClean:!0},{code:e,reason:t,wasClean:i});typeof CloseEvent!="undefined"?this.onclose(new CloseEvent("close",s)):this.onclose(s)}ajax(e,t,i,s){let o,r=()=>{this.reqs.delete(o),i()};o=g.request(e,this.endpointURL(),"application/json",t,this.timeout,r,n=>{this.reqs.delete(o),this.isActive()&&s(n)}),this.reqs.add(o)}};var m=class{constructor(e,t={}){let i=t.events||{state:"presence_state",diff:"presence_diff"};this.state={},this.pendingDiffs=[],this.channel=e,this.joinRef=null,this.caller={onJoin:function(){},onLeave:function(){},onSync:function(){}},this.channel.on(i.state,s=>{let{onJoin:o,onLeave:r,onSync:n}=this.caller;this.joinRef=this.channel.joinRef(),this.state=m.syncState(this.state,s,o,r),this.pendingDiffs.forEach(a=>{this.state=m.syncDiff(this.state,a,o,r)}),this.pendingDiffs=[],n()}),this.channel.on(i.diff,s=>{let{onJoin:o,onLeave:r,onSync:n}=this.caller;this.inPendingSyncState()?this.pendingDiffs.push(s):(this.state=m.syncDiff(this.state,s,o,r),n())})}onJoin(e){this.caller.onJoin=e}onLeave(e){this.caller.onLeave=e}onSync(e){this.caller.onSync=e}list(e){return m.list(this.state,e)}inPendingSyncState(){return!this.joinRef||this.joinRef!==this.channel.joinRef()}static syncState(e,t,i,s){let o=this.clone(e),r={},n={};return this.map(o,(a,l)=>{t[a]||(n[a]=l)}),this.map(t,(a,l)=>{let f=o[a];if(f){let c=l.metas.map(C=>C.phx_ref),E=f.metas.map(C=>C.phx_ref),k=l.metas.filter(C=>E.indexOf(C.phx_ref)<0),_=f.metas.filter(C=>c.indexOf(C.phx_ref)<0);k.length>0&&(r[a]=l,r[a].metas=k),_.length>0&&(n[a]=this.clone(f),n[a].metas=_)}else r[a]=l}),this.syncDiff(o,{joins:r,leaves:n},i,s)}static syncDiff(e,t,i,s){let{joins:o,leaves:r}=this.clone(t);return i||(i=function(){}),s||(s=function(){}),this.map(o,(n,a)=>{let l=e[n];if(e[n]=this.clone(a),l){let f=e[n].metas.map(E=>E.phx_ref),c=l.metas.filter(E=>f.indexOf(E.phx_ref)<0);e[n].metas.unshift(...c)}i(n,l,a)}),this.map(r,(n,a)=>{let l=e[n];if(!l)return;let f=a.metas.map(c=>c.phx_ref);l.metas=l.metas.filter(c=>f.indexOf(c.phx_ref)<0),s(n,l,a),l.metas.length===0&&delete e[n]}),e}static list(e,t){return t||(t=function(i,s){return s}),this.map(e,(i,s)=>t(i,s))}static map(e,t){return Object.getOwnPropertyNames(e).map(i=>t(i,e[i]))}static clone(e){return JSON.parse(JSON.stringify(e))}};var j={HEADER_LENGTH:1,META_LENGTH:4,KINDS:{push:0,reply:1,broadcast:2},encode(h,e){if(h.payload.constructor===ArrayBuffer)return e(this.binaryEncode(h));{let t=[h.join_ref,h.ref,h.topic,h.event,h.payload];return e(JSON.stringify(t))}},decode(h,e){if(h.constructor===ArrayBuffer)return e(this.binaryDecode(h));{let[t,i,s,o,r]=JSON.parse(h);return e({join_ref:t,ref:i,topic:s,event:o,payload:r})}},binaryEncode(h){let{join_ref:e,ref:t,event:i,topic:s,payload:o}=h,r=this.META_LENGTH+e.length+t.length+s.length+i.length,n=new ArrayBuffer(this.HEADER_LENGTH+r),a=new DataView(n),l=0;a.setUint8(l++,this.KINDS.push),a.setUint8(l++,e.length),a.setUint8(l++,t.length),a.setUint8(l++,s.length),a.setUint8(l++,i.length),Array.from(e,c=>a.setUint8(l++,c.charCodeAt(0))),Array.from(t,c=>a.setUint8(l++,c.charCodeAt(0))),Array.from(s,c=>a.setUint8(l++,c.charCodeAt(0))),Array.from(i,c=>a.setUint8(l++,c.charCodeAt(0)));var f=new Uint8Array(n.byteLength+o.byteLength);return f.set(new Uint8Array(n),0),f.set(new Uint8Array(o),n.byteLength),f.buffer},binaryDecode(h){let e=new DataView(h),t=e.getUint8(0),i=new TextDecoder;switch(t){case this.KINDS.push:return this.decodePush(h,e,i);case this.KINDS.reply:return this.decodeReply(h,e,i);case this.KINDS.broadcast:return this.decodeBroadcast(h,e,i)}},decodePush(h,e,t){let i=e.getUint8(1),s=e.getUint8(2),o=e.getUint8(3),r=this.HEADER_LENGTH+this.META_LENGTH-1,n=t.decode(h.slice(r,r+i));r=r+i;let a=t.decode(h.slice(r,r+s));r=r+s;let l=t.decode(h.slice(r,r+o));r=r+o;let f=h.slice(r,h.byteLength);return{join_ref:n,ref:null,topic:a,event:l,payload:f}},decodeReply(h,e,t){let i=e.getUint8(1),s=e.getUint8(2),o=e.getUint8(3),r=e.getUint8(4),n=this.HEADER_LENGTH+this.META_LENGTH,a=t.decode(h.slice(n,n+i));n=n+i;let l=t.decode(h.slice(n,n+s));n=n+s;let f=t.decode(h.slice(n,n+o));n=n+o;let c=t.decode(h.slice(n,n+r));n=n+r;let E=h.slice(n,h.byteLength),k={status:c,response:E};return{join_ref:a,ref:l,topic:f,event:p.reply,payload:k}},decodeBroadcast(h,e,t){let i=e.getUint8(1),s=e.getUint8(2),o=this.HEADER_LENGTH+2,r=t.decode(h.slice(o,o+i));o=o+i;let n=t.decode(h.slice(o,o+s));o=o+s;let a=h.slice(o,h.byteLength);return{join_ref:null,ref:null,topic:r,event:n,payload:a}}};var x=class{constructor(e,t={}){this.stateChangeCallbacks={open:[],close:[],error:[],message:[]},this.channels=[],this.sendBuffer=[],this.ref=0,this.timeout=t.timeout||O,this.transport=t.transport||R.WebSocket||T,this.establishedConnections=0,this.defaultEncoder=j.encode.bind(j),this.defaultDecoder=j.decode.bind(j),this.closeWasClean=!1,this.binaryType=t.binaryType||"arraybuffer",this.connectClock=1,this.transport!==T?(this.encode=t.encode||this.defaultEncoder,this.decode=t.decode||this.defaultDecoder):(this.encode=this.defaultEncoder,this.decode=this.defaultDecoder);let i=null;y&&y.addEventListener&&(y.addEventListener("pagehide",s=>{this.conn&&(this.disconnect(),i=this.connectClock)}),y.addEventListener("pageshow",s=>{i===this.connectClock&&(i=null,this.connect())})),this.heartbeatIntervalMs=t.heartbeatIntervalMs||3e4,this.rejoinAfterMs=s=>t.rejoinAfterMs?t.rejoinAfterMs(s):[1e3,2e3,5e3][s-1]||1e4,this.reconnectAfterMs=s=>t.reconnectAfterMs?t.reconnectAfterMs(s):[10,50,100,150,200,250,500,1e3,2e3][s-1]||5e3,this.logger=t.logger||null,this.longpollerTimeout=t.longpollerTimeout||2e4,this.params=v(t.params||{}),this.endPoint=`${e}/${L.websocket}`,this.vsn=t.vsn||N,this.heartbeatTimer=null,this.pendingHeartbeatRef=null,this.reconnectTimer=new b(()=>{this.teardown(()=>this.connect())},this.reconnectAfterMs)}getLongPollTransport(){return T}replaceTransport(e){this.connectClock++,this.closeWasClean=!0,this.reconnectTimer.reset(),this.sendBuffer=[],this.conn&&(this.conn.close(),this.conn=null),this.transport=e}protocol(){return location.protocol.match(/^https/)?"wss":"ws"}endPointURL(){let e=g.appendParams(g.appendParams(this.endPoint,this.params()),{vsn:this.vsn});return e.charAt(0)!=="/"?e:e.charAt(1)==="/"?`${this.protocol()}:${e}`:`${this.protocol()}://${location.host}${e}`}disconnect(e,t,i){this.connectClock++,this.closeWasClean=!0,this.reconnectTimer.reset(),this.teardown(e,t,i)}connect(e){e&&(console&&console.log("passing params to connect is deprecated. Instead pass :params to the Socket constructor"),this.params=v(e)),!this.conn&&(this.connectClock++,this.closeWasClean=!1,this.conn=new this.transport(this.endPointURL()),this.conn.binaryType=this.binaryType,this.conn.timeout=this.longpollerTimeout,this.conn.onopen=()=>this.onConnOpen(),this.conn.onerror=t=>this.onConnError(t),this.conn.onmessage=t=>this.onConnMessage(t),this.conn.onclose=t=>this.onConnClose(t))}log(e,t,i){this.logger(e,t,i)}hasLogger(){return this.logger!==null}onOpen(e){let t=this.makeRef();return this.stateChangeCallbacks.open.push([t,e]),t}onClose(e){let t=this.makeRef();return this.stateChangeCallbacks.close.push([t,e]),t}onError(e){let t=this.makeRef();return this.stateChangeCallbacks.error.push([t,e]),t}onMessage(e){let t=this.makeRef();return this.stateChangeCallbacks.message.push([t,e]),t}ping(e){if(!this.isConnected())return!1;let t=this.makeRef(),i=Date.now();this.push({topic:"phoenix",event:"heartbeat",payload:{},ref:t});let s=this.onMessage(o=>{o.ref===t&&(this.off([s]),e(Date.now()-i))});return!0}onConnOpen(){this.hasLogger()&&this.log("transport",`connected to ${this.endPointURL()}`),this.closeWasClean=!1,this.establishedConnections++,this.flushSendBuffer(),this.reconnectTimer.reset(),this.resetHeartbeat(),this.stateChangeCallbacks.open.forEach(([,e])=>e())}heartbeatTimeout(){this.pendingHeartbeatRef&&(this.pendingHeartbeatRef=null,this.hasLogger()&&this.log("transport","heartbeat timeout. Attempting to re-establish connection"),this.triggerChanError(),this.closeWasClean=!1,this.teardown(()=>this.reconnectTimer.scheduleTimeout(),H,"heartbeat timeout"))}resetHeartbeat(){this.conn&&this.conn.skipHeartbeat||(this.pendingHeartbeatRef=null,clearTimeout(this.heartbeatTimer),setTimeout(()=>this.sendHeartbeat(),this.heartbeatIntervalMs))}teardown(e,t,i){if(!this.conn)return e&&e();this.waitForBufferDone(()=>{this.conn&&(t?this.conn.close(t,i||""):this.conn.close()),this.waitForSocketClosed(()=>{this.conn&&(this.conn.onopen=function(){},this.conn.onerror=function(){},this.conn.onmessage=function(){},this.conn.onclose=function(){},this.conn=null),e&&e()})})}waitForBufferDone(e,t=1){if(t===5||!this.conn||!this.conn.bufferedAmount){e();return}setTimeout(()=>{this.waitForBufferDone(e,t+1)},150*t)}waitForSocketClosed(e,t=1){if(t===5||!this.conn||this.conn.readyState===d.closed){e();return}setTimeout(()=>{this.waitForSocketClosed(e,t+1)},150*t)}onConnClose(e){let t=e&&e.code;this.hasLogger()&&this.log("transport","close",e),this.triggerChanError(),clearTimeout(this.heartbeatTimer),!this.closeWasClean&&t!==1e3&&this.reconnectTimer.scheduleTimeout(),this.stateChangeCallbacks.close.forEach(([,i])=>i(e))}onConnError(e){this.hasLogger()&&this.log("transport",e);let t=this.transport,i=this.establishedConnections;this.stateChangeCallbacks.error.forEach(([,s])=>{s(e,t,i)}),(t===this.transport||i>0)&&this.triggerChanError()}triggerChanError(){this.channels.forEach(e=>{e.isErrored()||e.isLeaving()||e.isClosed()||e.trigger(p.error)})}connectionState(){switch(this.conn&&this.conn.readyState){case d.connecting:return"connecting";case d.open:return"open";case d.closing:return"closing";default:return"closed"}}isConnected(){return this.connectionState()==="open"}remove(e){this.off(e.stateChangeRefs),this.channels=this.channels.filter(t=>t.joinRef()!==e.joinRef())}off(e){for(let t in this.stateChangeCallbacks)this.stateChangeCallbacks[t]=this.stateChangeCallbacks[t].filter(([i])=>e.indexOf(i)===-1)}channel(e,t={}){let i=new A(e,t,this);return this.channels.push(i),i}push(e){if(this.hasLogger()){let{topic:t,event:i,payload:s,ref:o,join_ref:r}=e;this.log("push",`${t} ${i} (${r}, ${o})`,s)}this.isConnected()?this.encode(e,t=>this.conn.send(t)):this.sendBuffer.push(()=>this.encode(e,t=>this.conn.send(t)))}makeRef(){let e=this.ref+1;return e===this.ref?this.ref=0:this.ref=e,this.ref.toString()}sendHeartbeat(){this.pendingHeartbeatRef&&!this.isConnected()||(this.pendingHeartbeatRef=this.makeRef(),this.push({topic:"phoenix",event:"heartbeat",payload:{},ref:this.pendingHeartbeatRef}),this.heartbeatTimer=setTimeout(()=>this.heartbeatTimeout(),this.heartbeatIntervalMs))}flushSendBuffer(){this.isConnected()&&this.sendBuffer.length>0&&(this.sendBuffer.forEach(e=>e()),this.sendBuffer=[])}onConnMessage(e){this.decode(e.data,t=>{let{topic:i,event:s,payload:o,ref:r,join_ref:n}=t;r&&r===this.pendingHeartbeatRef&&(clearTimeout(this.heartbeatTimer),this.pendingHeartbeatRef=null,setTimeout(()=>this.sendHeartbeat(),this.heartbeatIntervalMs)),this.hasLogger()&&this.log("receive",`${o.status||""} ${i} ${s} ${r&&"("+r+")"||""}`,o);for(let a=0;ai.topic===e&&(i.isJoined()||i.isJoining()));t&&(this.hasLogger()&&this.log("transport",`leaving duplicate topic "${e}"`),t.leave())}};return J(I);})(); diff --git a/priv/static/phoenix.mjs b/priv/static/phoenix.mjs index 7767f03d06..82ea5853cc 100644 --- a/priv/static/phoenix.mjs +++ b/priv/static/phoenix.mjs @@ -928,7 +928,9 @@ var Socket = class { if (this.hasLogger()) { this.log("transport", "heartbeat timeout. Attempting to re-establish connection"); } - this.abnormalClose("heartbeat timeout"); + this.triggerChanError(); + this.closeWasClean = false; + this.teardown(() => this.reconnectTimer.scheduleTimeout(), WS_CLOSE_NORMAL, "heartbeat timeout"); } } resetHeartbeat() { @@ -953,6 +955,12 @@ var Socket = class { } this.waitForSocketClosed(() => { if (this.conn) { + this.conn.onopen = function() { + }; + this.conn.onerror = function() { + }; + this.conn.onmessage = function() { + }; this.conn.onclose = function() { }; this.conn = null; @@ -1068,12 +1076,6 @@ var Socket = class { this.push({ topic: "phoenix", event: "heartbeat", payload: {}, ref: this.pendingHeartbeatRef }); this.heartbeatTimer = setTimeout(() => this.heartbeatTimeout(), this.heartbeatIntervalMs); } - abnormalClose(reason) { - this.closeWasClean = false; - if (this.isConnected()) { - this.conn.close(WS_CLOSE_NORMAL, reason); - } - } flushSendBuffer() { if (this.isConnected() && this.sendBuffer.length > 0) { this.sendBuffer.forEach((callback) => callback()); diff --git a/priv/static/phoenix.mjs.map b/priv/static/phoenix.mjs.map index 27167c91b5..ce923e97e3 100644 --- a/priv/static/phoenix.mjs.map +++ b/priv/static/phoenix.mjs.map @@ -1,7 +1,7 @@ { "version": 3, "sources": ["../../assets/js/phoenix/utils.js", "../../assets/js/phoenix/constants.js", "../../assets/js/phoenix/push.js", "../../assets/js/phoenix/timer.js", "../../assets/js/phoenix/channel.js", "../../assets/js/phoenix/ajax.js", "../../assets/js/phoenix/longpoll.js", "../../assets/js/phoenix/presence.js", "../../assets/js/phoenix/serializer.js", "../../assets/js/phoenix/socket.js"], - "sourcesContent": ["// wraps value in closure or returns closure\nexport let closure = (value) => {\n if(typeof value === \"function\"){\n return value\n } else {\n let closure = function (){ return value }\n return closure\n }\n}\n", "export const globalSelf = typeof self !== \"undefined\" ? self : null\nexport const phxWindow = typeof window !== \"undefined\" ? window : null\nexport const global = globalSelf || phxWindow || global\nexport const DEFAULT_VSN = \"2.0.0\"\nexport const SOCKET_STATES = {connecting: 0, open: 1, closing: 2, closed: 3}\nexport const DEFAULT_TIMEOUT = 10000\nexport const WS_CLOSE_NORMAL = 1000\nexport const CHANNEL_STATES = {\n closed: \"closed\",\n errored: \"errored\",\n joined: \"joined\",\n joining: \"joining\",\n leaving: \"leaving\",\n}\nexport const CHANNEL_EVENTS = {\n close: \"phx_close\",\n error: \"phx_error\",\n join: \"phx_join\",\n reply: \"phx_reply\",\n leave: \"phx_leave\"\n}\n\nexport const TRANSPORTS = {\n longpoll: \"longpoll\",\n websocket: \"websocket\"\n}\nexport const XHR_STATES = {\n complete: 4\n}\n", "/**\n * Initializes the Push\n * @param {Channel} channel - The Channel\n * @param {string} event - The event, for example `\"phx_join\"`\n * @param {Object} payload - The payload, for example `{user_id: 123}`\n * @param {number} timeout - The push timeout in milliseconds\n */\nexport default class Push {\n constructor(channel, event, payload, timeout){\n this.channel = channel\n this.event = event\n this.payload = payload || function (){ return {} }\n this.receivedResp = null\n this.timeout = timeout\n this.timeoutTimer = null\n this.recHooks = []\n this.sent = false\n }\n\n /**\n *\n * @param {number} timeout\n */\n resend(timeout){\n this.timeout = timeout\n this.reset()\n this.send()\n }\n\n /**\n *\n */\n send(){\n if(this.hasReceived(\"timeout\")){ return }\n this.startTimeout()\n this.sent = true\n this.channel.socket.push({\n topic: this.channel.topic,\n event: this.event,\n payload: this.payload(),\n ref: this.ref,\n join_ref: this.channel.joinRef()\n })\n }\n\n /**\n *\n * @param {*} status\n * @param {*} callback\n */\n receive(status, callback){\n if(this.hasReceived(status)){\n callback(this.receivedResp.response)\n }\n\n this.recHooks.push({status, callback})\n return this\n }\n\n /**\n * @private\n */\n reset(){\n this.cancelRefEvent()\n this.ref = null\n this.refEvent = null\n this.receivedResp = null\n this.sent = false\n }\n\n /**\n * @private\n */\n matchReceive({status, response, _ref}){\n this.recHooks.filter(h => h.status === status)\n .forEach(h => h.callback(response))\n }\n\n /**\n * @private\n */\n cancelRefEvent(){\n if(!this.refEvent){ return }\n this.channel.off(this.refEvent)\n }\n\n /**\n * @private\n */\n cancelTimeout(){\n clearTimeout(this.timeoutTimer)\n this.timeoutTimer = null\n }\n\n /**\n * @private\n */\n startTimeout(){\n if(this.timeoutTimer){ this.cancelTimeout() }\n this.ref = this.channel.socket.makeRef()\n this.refEvent = this.channel.replyEventName(this.ref)\n\n this.channel.on(this.refEvent, payload => {\n this.cancelRefEvent()\n this.cancelTimeout()\n this.receivedResp = payload\n this.matchReceive(payload)\n })\n\n this.timeoutTimer = setTimeout(() => {\n this.trigger(\"timeout\", {})\n }, this.timeout)\n }\n\n /**\n * @private\n */\n hasReceived(status){\n return this.receivedResp && this.receivedResp.status === status\n }\n\n /**\n * @private\n */\n trigger(status, response){\n this.channel.trigger(this.refEvent, {status, response})\n }\n}\n", "/**\n *\n * Creates a timer that accepts a `timerCalc` function to perform\n * calculated timeout retries, such as exponential backoff.\n *\n * @example\n * let reconnectTimer = new Timer(() => this.connect(), function(tries){\n * return [1000, 5000, 10000][tries - 1] || 10000\n * })\n * reconnectTimer.scheduleTimeout() // fires after 1000\n * reconnectTimer.scheduleTimeout() // fires after 5000\n * reconnectTimer.reset()\n * reconnectTimer.scheduleTimeout() // fires after 1000\n *\n * @param {Function} callback\n * @param {Function} timerCalc\n */\nexport default class Timer {\n constructor(callback, timerCalc){\n this.callback = callback\n this.timerCalc = timerCalc\n this.timer = null\n this.tries = 0\n }\n\n reset(){\n this.tries = 0\n clearTimeout(this.timer)\n }\n\n /**\n * Cancels any previous scheduleTimeout and schedules callback\n */\n scheduleTimeout(){\n clearTimeout(this.timer)\n\n this.timer = setTimeout(() => {\n this.tries = this.tries + 1\n this.callback()\n }, this.timerCalc(this.tries + 1))\n }\n}\n", "import {closure} from \"./utils\"\nimport {\n CHANNEL_EVENTS,\n CHANNEL_STATES,\n} from \"./constants\"\n\nimport Push from \"./push\"\nimport Timer from \"./timer\"\n\n/**\n *\n * @param {string} topic\n * @param {(Object|function)} params\n * @param {Socket} socket\n */\nexport default class Channel {\n constructor(topic, params, socket){\n this.state = CHANNEL_STATES.closed\n this.topic = topic\n this.params = closure(params || {})\n this.socket = socket\n this.bindings = []\n this.bindingRef = 0\n this.timeout = this.socket.timeout\n this.joinedOnce = false\n this.joinPush = new Push(this, CHANNEL_EVENTS.join, this.params, this.timeout)\n this.pushBuffer = []\n this.stateChangeRefs = []\n\n this.rejoinTimer = new Timer(() => {\n if(this.socket.isConnected()){ this.rejoin() }\n }, this.socket.rejoinAfterMs)\n this.stateChangeRefs.push(this.socket.onError(() => this.rejoinTimer.reset()))\n this.stateChangeRefs.push(this.socket.onOpen(() => {\n this.rejoinTimer.reset()\n if(this.isErrored()){ this.rejoin() }\n })\n )\n this.joinPush.receive(\"ok\", () => {\n this.state = CHANNEL_STATES.joined\n this.rejoinTimer.reset()\n this.pushBuffer.forEach(pushEvent => pushEvent.send())\n this.pushBuffer = []\n })\n this.joinPush.receive(\"error\", () => {\n this.state = CHANNEL_STATES.errored\n if(this.socket.isConnected()){ this.rejoinTimer.scheduleTimeout() }\n })\n this.onClose(() => {\n this.rejoinTimer.reset()\n if(this.socket.hasLogger()) this.socket.log(\"channel\", `close ${this.topic} ${this.joinRef()}`)\n this.state = CHANNEL_STATES.closed\n this.socket.remove(this)\n })\n this.onError(reason => {\n if(this.socket.hasLogger()) this.socket.log(\"channel\", `error ${this.topic}`, reason)\n if(this.isJoining()){ this.joinPush.reset() }\n this.state = CHANNEL_STATES.errored\n if(this.socket.isConnected()){ this.rejoinTimer.scheduleTimeout() }\n })\n this.joinPush.receive(\"timeout\", () => {\n if(this.socket.hasLogger()) this.socket.log(\"channel\", `timeout ${this.topic} (${this.joinRef()})`, this.joinPush.timeout)\n let leavePush = new Push(this, CHANNEL_EVENTS.leave, closure({}), this.timeout)\n leavePush.send()\n this.state = CHANNEL_STATES.errored\n this.joinPush.reset()\n if(this.socket.isConnected()){ this.rejoinTimer.scheduleTimeout() }\n })\n this.on(CHANNEL_EVENTS.reply, (payload, ref) => {\n this.trigger(this.replyEventName(ref), payload)\n })\n }\n\n /**\n * Join the channel\n * @param {integer} timeout\n * @returns {Push}\n */\n join(timeout = this.timeout){\n if(this.joinedOnce){\n throw new Error(\"tried to join multiple times. 'join' can only be called a single time per channel instance\")\n } else {\n this.timeout = timeout\n this.joinedOnce = true\n this.rejoin()\n return this.joinPush\n }\n }\n\n /**\n * Hook into channel close\n * @param {Function} callback\n */\n onClose(callback){\n this.on(CHANNEL_EVENTS.close, callback)\n }\n\n /**\n * Hook into channel errors\n * @param {Function} callback\n */\n onError(callback){\n return this.on(CHANNEL_EVENTS.error, reason => callback(reason))\n }\n\n /**\n * Subscribes on channel events\n *\n * Subscription returns a ref counter, which can be used later to\n * unsubscribe the exact event listener\n *\n * @example\n * const ref1 = channel.on(\"event\", do_stuff)\n * const ref2 = channel.on(\"event\", do_other_stuff)\n * channel.off(\"event\", ref1)\n * // Since unsubscription, do_stuff won't fire,\n * // while do_other_stuff will keep firing on the \"event\"\n *\n * @param {string} event\n * @param {Function} callback\n * @returns {integer} ref\n */\n on(event, callback){\n let ref = this.bindingRef++\n this.bindings.push({event, ref, callback})\n return ref\n }\n\n /**\n * Unsubscribes off of channel events\n *\n * Use the ref returned from a channel.on() to unsubscribe one\n * handler, or pass nothing for the ref to unsubscribe all\n * handlers for the given event.\n *\n * @example\n * // Unsubscribe the do_stuff handler\n * const ref1 = channel.on(\"event\", do_stuff)\n * channel.off(\"event\", ref1)\n *\n * // Unsubscribe all handlers from event\n * channel.off(\"event\")\n *\n * @param {string} event\n * @param {integer} ref\n */\n off(event, ref){\n this.bindings = this.bindings.filter((bind) => {\n return !(bind.event === event && (typeof ref === \"undefined\" || ref === bind.ref))\n })\n }\n\n /**\n * @private\n */\n canPush(){ return this.socket.isConnected() && this.isJoined() }\n\n /**\n * Sends a message `event` to phoenix with the payload `payload`.\n * Phoenix receives this in the `handle_in(event, payload, socket)`\n * function. if phoenix replies or it times out (default 10000ms),\n * then optionally the reply can be received.\n *\n * @example\n * channel.push(\"event\")\n * .receive(\"ok\", payload => console.log(\"phoenix replied:\", payload))\n * .receive(\"error\", err => console.log(\"phoenix errored\", err))\n * .receive(\"timeout\", () => console.log(\"timed out pushing\"))\n * @param {string} event\n * @param {Object} payload\n * @param {number} [timeout]\n * @returns {Push}\n */\n push(event, payload, timeout = this.timeout){\n payload = payload || {}\n if(!this.joinedOnce){\n throw new Error(`tried to push '${event}' to '${this.topic}' before joining. Use channel.join() before pushing events`)\n }\n let pushEvent = new Push(this, event, function (){ return payload }, timeout)\n if(this.canPush()){\n pushEvent.send()\n } else {\n pushEvent.startTimeout()\n this.pushBuffer.push(pushEvent)\n }\n\n return pushEvent\n }\n\n /** Leaves the channel\n *\n * Unsubscribes from server events, and\n * instructs channel to terminate on server\n *\n * Triggers onClose() hooks\n *\n * To receive leave acknowledgements, use the `receive`\n * hook to bind to the server ack, ie:\n *\n * @example\n * channel.leave().receive(\"ok\", () => alert(\"left!\") )\n *\n * @param {integer} timeout\n * @returns {Push}\n */\n leave(timeout = this.timeout){\n this.rejoinTimer.reset()\n this.joinPush.cancelTimeout()\n\n this.state = CHANNEL_STATES.leaving\n let onClose = () => {\n if(this.socket.hasLogger()) this.socket.log(\"channel\", `leave ${this.topic}`)\n this.trigger(CHANNEL_EVENTS.close, \"leave\")\n }\n let leavePush = new Push(this, CHANNEL_EVENTS.leave, closure({}), timeout)\n leavePush.receive(\"ok\", () => onClose())\n .receive(\"timeout\", () => onClose())\n leavePush.send()\n if(!this.canPush()){ leavePush.trigger(\"ok\", {}) }\n\n return leavePush\n }\n\n /**\n * Overridable message hook\n *\n * Receives all events for specialized message handling\n * before dispatching to the channel callbacks.\n *\n * Must return the payload, modified or unmodified\n * @param {string} event\n * @param {Object} payload\n * @param {integer} ref\n * @returns {Object}\n */\n onMessage(_event, payload, _ref){ return payload }\n\n /**\n * @private\n */\n isMember(topic, event, payload, joinRef){\n if(this.topic !== topic){ return false }\n\n if(joinRef && joinRef !== this.joinRef()){\n if(this.socket.hasLogger()) this.socket.log(\"channel\", \"dropping outdated message\", {topic, event, payload, joinRef})\n return false\n } else {\n return true\n }\n }\n\n /**\n * @private\n */\n joinRef(){ return this.joinPush.ref }\n\n /**\n * @private\n */\n rejoin(timeout = this.timeout){\n if(this.isLeaving()){ return }\n this.socket.leaveOpenTopic(this.topic)\n this.state = CHANNEL_STATES.joining\n this.joinPush.resend(timeout)\n }\n\n /**\n * @private\n */\n trigger(event, payload, ref, joinRef){\n let handledPayload = this.onMessage(event, payload, ref, joinRef)\n if(payload && !handledPayload){ throw new Error(\"channel onMessage callbacks must return the payload, modified or unmodified\") }\n\n let eventBindings = this.bindings.filter(bind => bind.event === event)\n\n for(let i = 0; i < eventBindings.length; i++){\n let bind = eventBindings[i]\n bind.callback(handledPayload, ref, joinRef || this.joinRef())\n }\n }\n\n /**\n * @private\n */\n replyEventName(ref){ return `chan_reply_${ref}` }\n\n /**\n * @private\n */\n isClosed(){ return this.state === CHANNEL_STATES.closed }\n\n /**\n * @private\n */\n isErrored(){ return this.state === CHANNEL_STATES.errored }\n\n /**\n * @private\n */\n isJoined(){ return this.state === CHANNEL_STATES.joined }\n\n /**\n * @private\n */\n isJoining(){ return this.state === CHANNEL_STATES.joining }\n\n /**\n * @private\n */\n isLeaving(){ return this.state === CHANNEL_STATES.leaving }\n}\n", "import {\n global,\n XHR_STATES\n} from \"./constants\"\n\nexport default class Ajax {\n\n static request(method, endPoint, accept, body, timeout, ontimeout, callback){\n if(global.XDomainRequest){\n let req = new global.XDomainRequest() // IE8, IE9\n return this.xdomainRequest(req, method, endPoint, body, timeout, ontimeout, callback)\n } else {\n let req = new global.XMLHttpRequest() // IE7+, Firefox, Chrome, Opera, Safari\n return this.xhrRequest(req, method, endPoint, accept, body, timeout, ontimeout, callback)\n }\n }\n\n static xdomainRequest(req, method, endPoint, body, timeout, ontimeout, callback){\n req.timeout = timeout\n req.open(method, endPoint)\n req.onload = () => {\n let response = this.parseJSON(req.responseText)\n callback && callback(response)\n }\n if(ontimeout){ req.ontimeout = ontimeout }\n\n // Work around bug in IE9 that requires an attached onprogress handler\n req.onprogress = () => { }\n\n req.send(body)\n return req\n }\n\n static xhrRequest(req, method, endPoint, accept, body, timeout, ontimeout, callback){\n req.open(method, endPoint, true)\n req.timeout = timeout\n req.setRequestHeader(\"Content-Type\", accept)\n req.onerror = () => callback && callback(null)\n req.onreadystatechange = () => {\n if(req.readyState === XHR_STATES.complete && callback){\n let response = this.parseJSON(req.responseText)\n callback(response)\n }\n }\n if(ontimeout){ req.ontimeout = ontimeout }\n\n req.send(body)\n return req\n }\n\n static parseJSON(resp){\n if(!resp || resp === \"\"){ return null }\n\n try {\n return JSON.parse(resp)\n } catch (e){\n console && console.log(\"failed to parse JSON response\", resp)\n return null\n }\n }\n\n static serialize(obj, parentKey){\n let queryStr = []\n for(var key in obj){\n if(!Object.prototype.hasOwnProperty.call(obj, key)){ continue }\n let paramKey = parentKey ? `${parentKey}[${key}]` : key\n let paramVal = obj[key]\n if(typeof paramVal === \"object\"){\n queryStr.push(this.serialize(paramVal, paramKey))\n } else {\n queryStr.push(encodeURIComponent(paramKey) + \"=\" + encodeURIComponent(paramVal))\n }\n }\n return queryStr.join(\"&\")\n }\n\n static appendParams(url, params){\n if(Object.keys(params).length === 0){ return url }\n\n let prefix = url.match(/\\?/) ? \"&\" : \"?\"\n return `${url}${prefix}${this.serialize(params)}`\n }\n}\n", "import {\n SOCKET_STATES,\n TRANSPORTS\n} from \"./constants\"\n\nimport Ajax from \"./ajax\"\n\nexport default class LongPoll {\n\n constructor(endPoint){\n this.endPoint = null\n this.token = null\n this.skipHeartbeat = true\n this.reqs = new Set()\n this.onopen = function (){ } // noop\n this.onerror = function (){ } // noop\n this.onmessage = function (){ } // noop\n this.onclose = function (){ } // noop\n this.pollEndpoint = this.normalizeEndpoint(endPoint)\n this.readyState = SOCKET_STATES.connecting\n this.poll()\n }\n\n normalizeEndpoint(endPoint){\n return (endPoint\n .replace(\"ws://\", \"http://\")\n .replace(\"wss://\", \"https://\")\n .replace(new RegExp(\"(.*)\\/\" + TRANSPORTS.websocket), \"$1/\" + TRANSPORTS.longpoll))\n }\n\n endpointURL(){\n return Ajax.appendParams(this.pollEndpoint, {token: this.token})\n }\n\n closeAndRetry(code, reason, wasClean){\n this.close(code, reason, wasClean)\n this.readyState = SOCKET_STATES.connecting\n }\n\n ontimeout(){\n this.onerror(\"timeout\")\n this.closeAndRetry(1005, \"timeout\", false)\n }\n\n isActive(){ return this.readyState === SOCKET_STATES.open || this.readyState === SOCKET_STATES.connecting }\n\n poll(){\n this.ajax(\"GET\", null, () => this.ontimeout(), resp => {\n if(resp){\n var {status, token, messages} = resp\n this.token = token\n } else {\n status = 0\n }\n\n switch(status){\n case 200:\n messages.forEach(msg => {\n // Tasks are what things like event handlers, setTimeout callbacks,\n // promise resolves and more are run within.\n // In modern browsers, there are two different kinds of tasks,\n // microtasks and macrotasks.\n // Microtasks are mainly used for Promises, while macrotasks are\n // used for everything else.\n // Microtasks always have priority over macrotasks. If the JS engine\n // is looking for a task to run, it will always try to empty the\n // microtask queue before attempting to run anything from the\n // macrotask queue.\n //\n // For the WebSocket transport, messages always arrive in their own\n // event. This means that if any promises are resolved from within,\n // their callbacks will always finish execution by the time the\n // next message event handler is run.\n //\n // In order to emulate this behaviour, we need to make sure each\n // onmessage handler is run within it's own macrotask.\n setTimeout(() => this.onmessage({data: msg}), 0)\n })\n this.poll()\n break\n case 204:\n this.poll()\n break\n case 410:\n this.readyState = SOCKET_STATES.open\n this.onopen({})\n this.poll()\n break\n case 403:\n this.onerror(403)\n this.close(1008, \"forbidden\", false)\n break\n case 0:\n case 500:\n this.onerror(500)\n this.closeAndRetry(1011, \"internal server error\", 500)\n break\n default: throw new Error(`unhandled poll status ${status}`)\n }\n })\n }\n\n send(body){\n this.ajax(\"POST\", body, () => this.onerror(\"timeout\"), resp => {\n if(!resp || resp.status !== 200){\n this.onerror(resp && resp.status)\n this.closeAndRetry(1011, \"internal server error\", false)\n }\n })\n }\n\n close(code, reason, wasClean){\n for(let req of this.reqs){ req.abort() }\n this.readyState = SOCKET_STATES.closed\n let opts = Object.assign({code: 1000, reason: undefined, wasClean: true}, {code, reason, wasClean})\n if(typeof(CloseEvent) !== \"undefined\"){\n this.onclose(new CloseEvent(\"close\", opts))\n } else {\n this.onclose(opts)\n }\n }\n\n ajax(method, body, onCallerTimeout, callback){\n let req\n let ontimeout = () => {\n this.reqs.delete(req)\n onCallerTimeout()\n }\n req = Ajax.request(method, this.endpointURL(), \"application/json\", body, this.timeout, ontimeout, resp => {\n this.reqs.delete(req)\n if(this.isActive()){ callback(resp) }\n })\n this.reqs.add(req)\n }\n}\n", "/**\n * Initializes the Presence\n * @param {Channel} channel - The Channel\n * @param {Object} opts - The options,\n * for example `{events: {state: \"state\", diff: \"diff\"}}`\n */\nexport default class Presence {\n\n constructor(channel, opts = {}){\n let events = opts.events || {state: \"presence_state\", diff: \"presence_diff\"}\n this.state = {}\n this.pendingDiffs = []\n this.channel = channel\n this.joinRef = null\n this.caller = {\n onJoin: function (){ },\n onLeave: function (){ },\n onSync: function (){ }\n }\n\n this.channel.on(events.state, newState => {\n let {onJoin, onLeave, onSync} = this.caller\n\n this.joinRef = this.channel.joinRef()\n this.state = Presence.syncState(this.state, newState, onJoin, onLeave)\n\n this.pendingDiffs.forEach(diff => {\n this.state = Presence.syncDiff(this.state, diff, onJoin, onLeave)\n })\n this.pendingDiffs = []\n onSync()\n })\n\n this.channel.on(events.diff, diff => {\n let {onJoin, onLeave, onSync} = this.caller\n\n if(this.inPendingSyncState()){\n this.pendingDiffs.push(diff)\n } else {\n this.state = Presence.syncDiff(this.state, diff, onJoin, onLeave)\n onSync()\n }\n })\n }\n\n onJoin(callback){ this.caller.onJoin = callback }\n\n onLeave(callback){ this.caller.onLeave = callback }\n\n onSync(callback){ this.caller.onSync = callback }\n\n list(by){ return Presence.list(this.state, by) }\n\n inPendingSyncState(){\n return !this.joinRef || (this.joinRef !== this.channel.joinRef())\n }\n\n // lower-level public static API\n\n /**\n * Used to sync the list of presences on the server\n * with the client's state. An optional `onJoin` and `onLeave` callback can\n * be provided to react to changes in the client's local presences across\n * disconnects and reconnects with the server.\n *\n * @returns {Presence}\n */\n static syncState(currentState, newState, onJoin, onLeave){\n let state = this.clone(currentState)\n let joins = {}\n let leaves = {}\n\n this.map(state, (key, presence) => {\n if(!newState[key]){\n leaves[key] = presence\n }\n })\n this.map(newState, (key, newPresence) => {\n let currentPresence = state[key]\n if(currentPresence){\n let newRefs = newPresence.metas.map(m => m.phx_ref)\n let curRefs = currentPresence.metas.map(m => m.phx_ref)\n let joinedMetas = newPresence.metas.filter(m => curRefs.indexOf(m.phx_ref) < 0)\n let leftMetas = currentPresence.metas.filter(m => newRefs.indexOf(m.phx_ref) < 0)\n if(joinedMetas.length > 0){\n joins[key] = newPresence\n joins[key].metas = joinedMetas\n }\n if(leftMetas.length > 0){\n leaves[key] = this.clone(currentPresence)\n leaves[key].metas = leftMetas\n }\n } else {\n joins[key] = newPresence\n }\n })\n return this.syncDiff(state, {joins: joins, leaves: leaves}, onJoin, onLeave)\n }\n\n /**\n *\n * Used to sync a diff of presence join and leave\n * events from the server, as they happen. Like `syncState`, `syncDiff`\n * accepts optional `onJoin` and `onLeave` callbacks to react to a user\n * joining or leaving from a device.\n *\n * @returns {Presence}\n */\n static syncDiff(state, diff, onJoin, onLeave){\n let {joins, leaves} = this.clone(diff)\n if(!onJoin){ onJoin = function (){ } }\n if(!onLeave){ onLeave = function (){ } }\n\n this.map(joins, (key, newPresence) => {\n let currentPresence = state[key]\n state[key] = this.clone(newPresence)\n if(currentPresence){\n let joinedRefs = state[key].metas.map(m => m.phx_ref)\n let curMetas = currentPresence.metas.filter(m => joinedRefs.indexOf(m.phx_ref) < 0)\n state[key].metas.unshift(...curMetas)\n }\n onJoin(key, currentPresence, newPresence)\n })\n this.map(leaves, (key, leftPresence) => {\n let currentPresence = state[key]\n if(!currentPresence){ return }\n let refsToRemove = leftPresence.metas.map(m => m.phx_ref)\n currentPresence.metas = currentPresence.metas.filter(p => {\n return refsToRemove.indexOf(p.phx_ref) < 0\n })\n onLeave(key, currentPresence, leftPresence)\n if(currentPresence.metas.length === 0){\n delete state[key]\n }\n })\n return state\n }\n\n /**\n * Returns the array of presences, with selected metadata.\n *\n * @param {Object} presences\n * @param {Function} chooser\n *\n * @returns {Presence}\n */\n static list(presences, chooser){\n if(!chooser){ chooser = function (key, pres){ return pres } }\n\n return this.map(presences, (key, presence) => {\n return chooser(key, presence)\n })\n }\n\n // private\n\n static map(obj, func){\n return Object.getOwnPropertyNames(obj).map(key => func(key, obj[key]))\n }\n\n static clone(obj){ return JSON.parse(JSON.stringify(obj)) }\n}\n", "/* The default serializer for encoding and decoding messages */\nimport {\n CHANNEL_EVENTS\n} from \"./constants\"\n\nexport default {\n HEADER_LENGTH: 1,\n META_LENGTH: 4,\n KINDS: {push: 0, reply: 1, broadcast: 2},\n\n encode(msg, callback){\n if(msg.payload.constructor === ArrayBuffer){\n return callback(this.binaryEncode(msg))\n } else {\n let payload = [msg.join_ref, msg.ref, msg.topic, msg.event, msg.payload]\n return callback(JSON.stringify(payload))\n }\n },\n\n decode(rawPayload, callback){\n if(rawPayload.constructor === ArrayBuffer){\n return callback(this.binaryDecode(rawPayload))\n } else {\n let [join_ref, ref, topic, event, payload] = JSON.parse(rawPayload)\n return callback({join_ref, ref, topic, event, payload})\n }\n },\n\n // private\n\n binaryEncode(message){\n let {join_ref, ref, event, topic, payload} = message\n let metaLength = this.META_LENGTH + join_ref.length + ref.length + topic.length + event.length\n let header = new ArrayBuffer(this.HEADER_LENGTH + metaLength)\n let view = new DataView(header)\n let offset = 0\n\n view.setUint8(offset++, this.KINDS.push) // kind\n view.setUint8(offset++, join_ref.length)\n view.setUint8(offset++, ref.length)\n view.setUint8(offset++, topic.length)\n view.setUint8(offset++, event.length)\n Array.from(join_ref, char => view.setUint8(offset++, char.charCodeAt(0)))\n Array.from(ref, char => view.setUint8(offset++, char.charCodeAt(0)))\n Array.from(topic, char => view.setUint8(offset++, char.charCodeAt(0)))\n Array.from(event, char => view.setUint8(offset++, char.charCodeAt(0)))\n\n var combined = new Uint8Array(header.byteLength + payload.byteLength)\n combined.set(new Uint8Array(header), 0)\n combined.set(new Uint8Array(payload), header.byteLength)\n\n return combined.buffer\n },\n\n binaryDecode(buffer){\n let view = new DataView(buffer)\n let kind = view.getUint8(0)\n let decoder = new TextDecoder()\n switch(kind){\n case this.KINDS.push: return this.decodePush(buffer, view, decoder)\n case this.KINDS.reply: return this.decodeReply(buffer, view, decoder)\n case this.KINDS.broadcast: return this.decodeBroadcast(buffer, view, decoder)\n }\n },\n\n decodePush(buffer, view, decoder){\n let joinRefSize = view.getUint8(1)\n let topicSize = view.getUint8(2)\n let eventSize = view.getUint8(3)\n let offset = this.HEADER_LENGTH + this.META_LENGTH - 1 // pushes have no ref\n let joinRef = decoder.decode(buffer.slice(offset, offset + joinRefSize))\n offset = offset + joinRefSize\n let topic = decoder.decode(buffer.slice(offset, offset + topicSize))\n offset = offset + topicSize\n let event = decoder.decode(buffer.slice(offset, offset + eventSize))\n offset = offset + eventSize\n let data = buffer.slice(offset, buffer.byteLength)\n return {join_ref: joinRef, ref: null, topic: topic, event: event, payload: data}\n },\n\n decodeReply(buffer, view, decoder){\n let joinRefSize = view.getUint8(1)\n let refSize = view.getUint8(2)\n let topicSize = view.getUint8(3)\n let eventSize = view.getUint8(4)\n let offset = this.HEADER_LENGTH + this.META_LENGTH\n let joinRef = decoder.decode(buffer.slice(offset, offset + joinRefSize))\n offset = offset + joinRefSize\n let ref = decoder.decode(buffer.slice(offset, offset + refSize))\n offset = offset + refSize\n let topic = decoder.decode(buffer.slice(offset, offset + topicSize))\n offset = offset + topicSize\n let event = decoder.decode(buffer.slice(offset, offset + eventSize))\n offset = offset + eventSize\n let data = buffer.slice(offset, buffer.byteLength)\n let payload = {status: event, response: data}\n return {join_ref: joinRef, ref: ref, topic: topic, event: CHANNEL_EVENTS.reply, payload: payload}\n },\n\n decodeBroadcast(buffer, view, decoder){\n let topicSize = view.getUint8(1)\n let eventSize = view.getUint8(2)\n let offset = this.HEADER_LENGTH + 2\n let topic = decoder.decode(buffer.slice(offset, offset + topicSize))\n offset = offset + topicSize\n let event = decoder.decode(buffer.slice(offset, offset + eventSize))\n offset = offset + eventSize\n let data = buffer.slice(offset, buffer.byteLength)\n\n return {join_ref: null, ref: null, topic: topic, event: event, payload: data}\n }\n}\n", "import {\n global,\n phxWindow,\n CHANNEL_EVENTS,\n DEFAULT_TIMEOUT,\n DEFAULT_VSN,\n SOCKET_STATES,\n TRANSPORTS,\n WS_CLOSE_NORMAL\n} from \"./constants\"\n\nimport {\n closure\n} from \"./utils\"\n\nimport Ajax from \"./ajax\"\nimport Channel from \"./channel\"\nimport LongPoll from \"./longpoll\"\nimport Serializer from \"./serializer\"\nimport Timer from \"./timer\"\n\n/** Initializes the Socket *\n *\n * For IE8 support use an ES5-shim (https://github.com/es-shims/es5-shim)\n *\n * @param {string} endPoint - The string WebSocket endpoint, ie, `\"ws://example.com/socket\"`,\n * `\"wss://example.com\"`\n * `\"/socket\"` (inherited host & protocol)\n * @param {Object} [opts] - Optional configuration\n * @param {Function} [opts.transport] - The Websocket Transport, for example WebSocket or Phoenix.LongPoll.\n *\n * Defaults to WebSocket with automatic LongPoll fallback.\n * @param {Function} [opts.encode] - The function to encode outgoing messages.\n *\n * Defaults to JSON encoder.\n *\n * @param {Function} [opts.decode] - The function to decode incoming messages.\n *\n * Defaults to JSON:\n *\n * ```javascript\n * (payload, callback) => callback(JSON.parse(payload))\n * ```\n *\n * @param {number} [opts.timeout] - The default timeout in milliseconds to trigger push timeouts.\n *\n * Defaults `DEFAULT_TIMEOUT`\n * @param {number} [opts.heartbeatIntervalMs] - The millisec interval to send a heartbeat message\n * @param {number} [opts.reconnectAfterMs] - The optional function that returns the millsec\n * socket reconnect interval.\n *\n * Defaults to stepped backoff of:\n *\n * ```javascript\n * function(tries){\n * return [10, 50, 100, 150, 200, 250, 500, 1000, 2000][tries - 1] || 5000\n * }\n * ````\n *\n * @param {number} [opts.rejoinAfterMs] - The optional function that returns the millsec\n * rejoin interval for individual channels.\n *\n * ```javascript\n * function(tries){\n * return [1000, 2000, 5000][tries - 1] || 10000\n * }\n * ````\n *\n * @param {Function} [opts.logger] - The optional function for specialized logging, ie:\n *\n * ```javascript\n * function(kind, msg, data) {\n * console.log(`${kind}: ${msg}`, data)\n * }\n * ```\n *\n * @param {number} [opts.longpollerTimeout] - The maximum timeout of a long poll AJAX request.\n *\n * Defaults to 20s (double the server long poll timer).\n *\n * @param {(Object|function)} [opts.params] - The optional params to pass when connecting\n * @param {string} [opts.binaryType] - The binary type to use for binary WebSocket frames.\n *\n * Defaults to \"arraybuffer\"\n *\n * @param {vsn} [opts.vsn] - The serializer's protocol version to send on connect.\n *\n * Defaults to DEFAULT_VSN.\n*/\nexport default class Socket {\n constructor(endPoint, opts = {}){\n this.stateChangeCallbacks = {open: [], close: [], error: [], message: []}\n this.channels = []\n this.sendBuffer = []\n this.ref = 0\n this.timeout = opts.timeout || DEFAULT_TIMEOUT\n this.transport = opts.transport || global.WebSocket || LongPoll\n this.establishedConnections = 0\n this.defaultEncoder = Serializer.encode.bind(Serializer)\n this.defaultDecoder = Serializer.decode.bind(Serializer)\n this.closeWasClean = false\n this.binaryType = opts.binaryType || \"arraybuffer\"\n this.connectClock = 1\n if(this.transport !== LongPoll){\n this.encode = opts.encode || this.defaultEncoder\n this.decode = opts.decode || this.defaultDecoder\n } else {\n this.encode = this.defaultEncoder\n this.decode = this.defaultDecoder\n }\n let awaitingConnectionOnPageShow = null\n if(phxWindow && phxWindow.addEventListener){\n phxWindow.addEventListener(\"pagehide\", _e => {\n if(this.conn){\n this.disconnect()\n awaitingConnectionOnPageShow = this.connectClock\n }\n })\n phxWindow.addEventListener(\"pageshow\", _e => {\n if(awaitingConnectionOnPageShow === this.connectClock){\n awaitingConnectionOnPageShow = null\n this.connect()\n }\n })\n }\n this.heartbeatIntervalMs = opts.heartbeatIntervalMs || 30000\n this.rejoinAfterMs = (tries) => {\n if(opts.rejoinAfterMs){\n return opts.rejoinAfterMs(tries)\n } else {\n return [1000, 2000, 5000][tries - 1] || 10000\n }\n }\n this.reconnectAfterMs = (tries) => {\n if(opts.reconnectAfterMs){\n return opts.reconnectAfterMs(tries)\n } else {\n return [10, 50, 100, 150, 200, 250, 500, 1000, 2000][tries - 1] || 5000\n }\n }\n this.logger = opts.logger || null\n this.longpollerTimeout = opts.longpollerTimeout || 20000\n this.params = closure(opts.params || {})\n this.endPoint = `${endPoint}/${TRANSPORTS.websocket}`\n this.vsn = opts.vsn || DEFAULT_VSN\n this.heartbeatTimer = null\n this.pendingHeartbeatRef = null\n this.reconnectTimer = new Timer(() => {\n this.teardown(() => this.connect())\n }, this.reconnectAfterMs)\n }\n\n /**\n * Returns the LongPoll transport reference\n */\n getLongPollTransport(){ return LongPoll }\n\n /**\n * Disconnects and replaces the active transport\n *\n * @param {Function} newTransport - The new transport class to instantiate\n *\n */\n replaceTransport(newTransport){\n this.connectClock++\n this.closeWasClean = true\n this.reconnectTimer.reset()\n this.sendBuffer = []\n if(this.conn){\n this.conn.close()\n this.conn = null\n }\n this.transport = newTransport\n }\n\n /**\n * Returns the socket protocol\n *\n * @returns {string}\n */\n protocol(){ return location.protocol.match(/^https/) ? \"wss\" : \"ws\" }\n\n /**\n * The fully qualifed socket url\n *\n * @returns {string}\n */\n endPointURL(){\n let uri = Ajax.appendParams(\n Ajax.appendParams(this.endPoint, this.params()), {vsn: this.vsn})\n if(uri.charAt(0) !== \"/\"){ return uri }\n if(uri.charAt(1) === \"/\"){ return `${this.protocol()}:${uri}` }\n\n return `${this.protocol()}://${location.host}${uri}`\n }\n\n /**\n * Disconnects the socket\n *\n * See https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent#Status_codes for valid status codes.\n *\n * @param {Function} callback - Optional callback which is called after socket is disconnected.\n * @param {integer} code - A status code for disconnection (Optional).\n * @param {string} reason - A textual description of the reason to disconnect. (Optional)\n */\n disconnect(callback, code, reason){\n this.connectClock++\n this.closeWasClean = true\n this.reconnectTimer.reset()\n this.teardown(callback, code, reason)\n }\n\n /**\n *\n * @param {Object} params - The params to send when connecting, for example `{user_id: userToken}`\n *\n * Passing params to connect is deprecated; pass them in the Socket constructor instead:\n * `new Socket(\"/socket\", {params: {user_id: userToken}})`.\n */\n connect(params){\n if(params){\n console && console.log(\"passing params to connect is deprecated. Instead pass :params to the Socket constructor\")\n this.params = closure(params)\n }\n if(this.conn){ return }\n\n this.connectClock++\n this.closeWasClean = false\n this.conn = new this.transport(this.endPointURL())\n this.conn.binaryType = this.binaryType\n this.conn.timeout = this.longpollerTimeout\n this.conn.onopen = () => this.onConnOpen()\n this.conn.onerror = error => this.onConnError(error)\n this.conn.onmessage = event => this.onConnMessage(event)\n this.conn.onclose = event => this.onConnClose(event)\n }\n\n /**\n * Logs the message. Override `this.logger` for specialized logging. noops by default\n * @param {string} kind\n * @param {string} msg\n * @param {Object} data\n */\n log(kind, msg, data){ this.logger(kind, msg, data) }\n\n /**\n * Returns true if a logger has been set on this socket.\n */\n hasLogger(){ return this.logger !== null }\n\n /**\n * Registers callbacks for connection open events\n *\n * @example socket.onOpen(function(){ console.info(\"the socket was opened\") })\n *\n * @param {Function} callback\n */\n onOpen(callback){\n let ref = this.makeRef()\n this.stateChangeCallbacks.open.push([ref, callback])\n return ref\n }\n\n /**\n * Registers callbacks for connection close events\n * @param {Function} callback\n */\n onClose(callback){\n let ref = this.makeRef()\n this.stateChangeCallbacks.close.push([ref, callback])\n return ref\n }\n\n /**\n * Registers callbacks for connection error events\n *\n * @example socket.onError(function(error){ alert(\"An error occurred\") })\n *\n * @param {Function} callback\n */\n onError(callback){\n let ref = this.makeRef()\n this.stateChangeCallbacks.error.push([ref, callback])\n return ref\n }\n\n /**\n * Registers callbacks for connection message events\n * @param {Function} callback\n */\n onMessage(callback){\n let ref = this.makeRef()\n this.stateChangeCallbacks.message.push([ref, callback])\n return ref\n }\n\n /**\n * Pings the server and invokes the callback with the RTT in milliseconds\n * @param {Function} callback\n *\n * Returns true if the ping was pushed or false if unable to be pushed.\n */\n ping(callback){\n if(!this.isConnected()){ return false }\n let ref = this.makeRef()\n let startTime = Date.now()\n this.push({topic: \"phoenix\", event: \"heartbeat\", payload: {}, ref: ref})\n let onMsgRef = this.onMessage(msg => {\n if(msg.ref === ref){\n this.off([onMsgRef])\n callback(Date.now() - startTime)\n }\n })\n return true\n }\n\n /**\n * @private\n */\n onConnOpen(){\n if(this.hasLogger()) this.log(\"transport\", `connected to ${this.endPointURL()}`)\n this.closeWasClean = false\n this.establishedConnections++\n this.flushSendBuffer()\n this.reconnectTimer.reset()\n this.resetHeartbeat()\n this.stateChangeCallbacks.open.forEach(([, callback]) => callback())\n }\n\n /**\n * @private\n */\n\n heartbeatTimeout(){\n if(this.pendingHeartbeatRef){\n this.pendingHeartbeatRef = null\n if(this.hasLogger()){ this.log(\"transport\", \"heartbeat timeout. Attempting to re-establish connection\") }\n this.abnormalClose(\"heartbeat timeout\")\n }\n }\n\n resetHeartbeat(){\n if(this.conn && this.conn.skipHeartbeat){ return }\n this.pendingHeartbeatRef = null\n clearTimeout(this.heartbeatTimer)\n setTimeout(() => this.sendHeartbeat(), this.heartbeatIntervalMs)\n }\n\n teardown(callback, code, reason){\n if(!this.conn){\n return callback && callback()\n }\n\n this.waitForBufferDone(() => {\n if(this.conn){\n if(code){ this.conn.close(code, reason || \"\") } else { this.conn.close() }\n }\n\n this.waitForSocketClosed(() => {\n if(this.conn){\n this.conn.onclose = function (){ } // noop\n this.conn = null\n }\n\n callback && callback()\n })\n })\n }\n\n waitForBufferDone(callback, tries = 1){\n if(tries === 5 || !this.conn || !this.conn.bufferedAmount){\n callback()\n return\n }\n\n setTimeout(() => {\n this.waitForBufferDone(callback, tries + 1)\n }, 150 * tries)\n }\n\n waitForSocketClosed(callback, tries = 1){\n if(tries === 5 || !this.conn || this.conn.readyState === SOCKET_STATES.closed){\n callback()\n return\n }\n\n setTimeout(() => {\n this.waitForSocketClosed(callback, tries + 1)\n }, 150 * tries)\n }\n\n onConnClose(event){\n let closeCode = event && event.code\n if(this.hasLogger()) this.log(\"transport\", \"close\", event)\n this.triggerChanError()\n clearTimeout(this.heartbeatTimer)\n if(!this.closeWasClean && closeCode !== 1000){\n this.reconnectTimer.scheduleTimeout()\n }\n this.stateChangeCallbacks.close.forEach(([, callback]) => callback(event))\n }\n\n /**\n * @private\n */\n onConnError(error){\n if(this.hasLogger()) this.log(\"transport\", error)\n let transportBefore = this.transport\n let establishedBefore = this.establishedConnections\n this.stateChangeCallbacks.error.forEach(([, callback]) => {\n callback(error, transportBefore, establishedBefore)\n })\n if(transportBefore === this.transport || establishedBefore > 0){\n this.triggerChanError()\n }\n }\n\n /**\n * @private\n */\n triggerChanError(){\n this.channels.forEach(channel => {\n if(!(channel.isErrored() || channel.isLeaving() || channel.isClosed())){\n channel.trigger(CHANNEL_EVENTS.error)\n }\n })\n }\n\n /**\n * @returns {string}\n */\n connectionState(){\n switch(this.conn && this.conn.readyState){\n case SOCKET_STATES.connecting: return \"connecting\"\n case SOCKET_STATES.open: return \"open\"\n case SOCKET_STATES.closing: return \"closing\"\n default: return \"closed\"\n }\n }\n\n /**\n * @returns {boolean}\n */\n isConnected(){ return this.connectionState() === \"open\" }\n\n /**\n * @private\n *\n * @param {Channel}\n */\n remove(channel){\n this.off(channel.stateChangeRefs)\n this.channels = this.channels.filter(c => c.joinRef() !== channel.joinRef())\n }\n\n /**\n * Removes `onOpen`, `onClose`, `onError,` and `onMessage` registrations.\n *\n * @param {refs} - list of refs returned by calls to\n * `onOpen`, `onClose`, `onError,` and `onMessage`\n */\n off(refs){\n for(let key in this.stateChangeCallbacks){\n this.stateChangeCallbacks[key] = this.stateChangeCallbacks[key].filter(([ref]) => {\n return refs.indexOf(ref) === -1\n })\n }\n }\n\n /**\n * Initiates a new channel for the given topic\n *\n * @param {string} topic\n * @param {Object} chanParams - Parameters for the channel\n * @returns {Channel}\n */\n channel(topic, chanParams = {}){\n let chan = new Channel(topic, chanParams, this)\n this.channels.push(chan)\n return chan\n }\n\n /**\n * @param {Object} data\n */\n push(data){\n if(this.hasLogger()){\n let {topic, event, payload, ref, join_ref} = data\n this.log(\"push\", `${topic} ${event} (${join_ref}, ${ref})`, payload)\n }\n\n if(this.isConnected()){\n this.encode(data, result => this.conn.send(result))\n } else {\n this.sendBuffer.push(() => this.encode(data, result => this.conn.send(result)))\n }\n }\n\n /**\n * Return the next message ref, accounting for overflows\n * @returns {string}\n */\n makeRef(){\n let newRef = this.ref + 1\n if(newRef === this.ref){ this.ref = 0 } else { this.ref = newRef }\n\n return this.ref.toString()\n }\n\n sendHeartbeat(){\n if(this.pendingHeartbeatRef && !this.isConnected()){ return }\n this.pendingHeartbeatRef = this.makeRef()\n this.push({topic: \"phoenix\", event: \"heartbeat\", payload: {}, ref: this.pendingHeartbeatRef})\n this.heartbeatTimer = setTimeout(() => this.heartbeatTimeout(), this.heartbeatIntervalMs)\n }\n\n abnormalClose(reason){\n this.closeWasClean = false\n if(this.isConnected()){ this.conn.close(WS_CLOSE_NORMAL, reason) }\n }\n\n flushSendBuffer(){\n if(this.isConnected() && this.sendBuffer.length > 0){\n this.sendBuffer.forEach(callback => callback())\n this.sendBuffer = []\n }\n }\n\n onConnMessage(rawMessage){\n this.decode(rawMessage.data, msg => {\n let {topic, event, payload, ref, join_ref} = msg\n if(ref && ref === this.pendingHeartbeatRef){\n clearTimeout(this.heartbeatTimer)\n this.pendingHeartbeatRef = null\n setTimeout(() => this.sendHeartbeat(), this.heartbeatIntervalMs)\n }\n\n if(this.hasLogger()) this.log(\"receive\", `${payload.status || \"\"} ${topic} ${event} ${ref && \"(\" + ref + \")\" || \"\"}`, payload)\n\n for(let i = 0; i < this.channels.length; i++){\n const channel = this.channels[i]\n if(!channel.isMember(topic, event, payload, join_ref)){ continue }\n channel.trigger(event, payload, ref, join_ref)\n }\n\n for(let i = 0; i < this.stateChangeCallbacks.message.length; i++){\n let [, callback] = this.stateChangeCallbacks.message[i]\n callback(msg)\n }\n })\n }\n\n leaveOpenTopic(topic){\n let dupChannel = this.channels.find(c => c.topic === topic && (c.isJoined() || c.isJoining()))\n if(dupChannel){\n if(this.hasLogger()) this.log(\"transport\", `leaving duplicate topic \"${topic}\"`)\n dupChannel.leave()\n }\n }\n}\n"], - "mappings": "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", + "sourcesContent": ["// wraps value in closure or returns closure\nexport let closure = (value) => {\n if(typeof value === \"function\"){\n return value\n } else {\n let closure = function (){ return value }\n return closure\n }\n}\n", "export const globalSelf = typeof self !== \"undefined\" ? self : null\nexport const phxWindow = typeof window !== \"undefined\" ? window : null\nexport const global = globalSelf || phxWindow || global\nexport const DEFAULT_VSN = \"2.0.0\"\nexport const SOCKET_STATES = {connecting: 0, open: 1, closing: 2, closed: 3}\nexport const DEFAULT_TIMEOUT = 10000\nexport const WS_CLOSE_NORMAL = 1000\nexport const CHANNEL_STATES = {\n closed: \"closed\",\n errored: \"errored\",\n joined: \"joined\",\n joining: \"joining\",\n leaving: \"leaving\",\n}\nexport const CHANNEL_EVENTS = {\n close: \"phx_close\",\n error: \"phx_error\",\n join: \"phx_join\",\n reply: \"phx_reply\",\n leave: \"phx_leave\"\n}\n\nexport const TRANSPORTS = {\n longpoll: \"longpoll\",\n websocket: \"websocket\"\n}\nexport const XHR_STATES = {\n complete: 4\n}\n", "/**\n * Initializes the Push\n * @param {Channel} channel - The Channel\n * @param {string} event - The event, for example `\"phx_join\"`\n * @param {Object} payload - The payload, for example `{user_id: 123}`\n * @param {number} timeout - The push timeout in milliseconds\n */\nexport default class Push {\n constructor(channel, event, payload, timeout){\n this.channel = channel\n this.event = event\n this.payload = payload || function (){ return {} }\n this.receivedResp = null\n this.timeout = timeout\n this.timeoutTimer = null\n this.recHooks = []\n this.sent = false\n }\n\n /**\n *\n * @param {number} timeout\n */\n resend(timeout){\n this.timeout = timeout\n this.reset()\n this.send()\n }\n\n /**\n *\n */\n send(){\n if(this.hasReceived(\"timeout\")){ return }\n this.startTimeout()\n this.sent = true\n this.channel.socket.push({\n topic: this.channel.topic,\n event: this.event,\n payload: this.payload(),\n ref: this.ref,\n join_ref: this.channel.joinRef()\n })\n }\n\n /**\n *\n * @param {*} status\n * @param {*} callback\n */\n receive(status, callback){\n if(this.hasReceived(status)){\n callback(this.receivedResp.response)\n }\n\n this.recHooks.push({status, callback})\n return this\n }\n\n /**\n * @private\n */\n reset(){\n this.cancelRefEvent()\n this.ref = null\n this.refEvent = null\n this.receivedResp = null\n this.sent = false\n }\n\n /**\n * @private\n */\n matchReceive({status, response, _ref}){\n this.recHooks.filter(h => h.status === status)\n .forEach(h => h.callback(response))\n }\n\n /**\n * @private\n */\n cancelRefEvent(){\n if(!this.refEvent){ return }\n this.channel.off(this.refEvent)\n }\n\n /**\n * @private\n */\n cancelTimeout(){\n clearTimeout(this.timeoutTimer)\n this.timeoutTimer = null\n }\n\n /**\n * @private\n */\n startTimeout(){\n if(this.timeoutTimer){ this.cancelTimeout() }\n this.ref = this.channel.socket.makeRef()\n this.refEvent = this.channel.replyEventName(this.ref)\n\n this.channel.on(this.refEvent, payload => {\n this.cancelRefEvent()\n this.cancelTimeout()\n this.receivedResp = payload\n this.matchReceive(payload)\n })\n\n this.timeoutTimer = setTimeout(() => {\n this.trigger(\"timeout\", {})\n }, this.timeout)\n }\n\n /**\n * @private\n */\n hasReceived(status){\n return this.receivedResp && this.receivedResp.status === status\n }\n\n /**\n * @private\n */\n trigger(status, response){\n this.channel.trigger(this.refEvent, {status, response})\n }\n}\n", "/**\n *\n * Creates a timer that accepts a `timerCalc` function to perform\n * calculated timeout retries, such as exponential backoff.\n *\n * @example\n * let reconnectTimer = new Timer(() => this.connect(), function(tries){\n * return [1000, 5000, 10000][tries - 1] || 10000\n * })\n * reconnectTimer.scheduleTimeout() // fires after 1000\n * reconnectTimer.scheduleTimeout() // fires after 5000\n * reconnectTimer.reset()\n * reconnectTimer.scheduleTimeout() // fires after 1000\n *\n * @param {Function} callback\n * @param {Function} timerCalc\n */\nexport default class Timer {\n constructor(callback, timerCalc){\n this.callback = callback\n this.timerCalc = timerCalc\n this.timer = null\n this.tries = 0\n }\n\n reset(){\n this.tries = 0\n clearTimeout(this.timer)\n }\n\n /**\n * Cancels any previous scheduleTimeout and schedules callback\n */\n scheduleTimeout(){\n clearTimeout(this.timer)\n\n this.timer = setTimeout(() => {\n this.tries = this.tries + 1\n this.callback()\n }, this.timerCalc(this.tries + 1))\n }\n}\n", "import {closure} from \"./utils\"\nimport {\n CHANNEL_EVENTS,\n CHANNEL_STATES,\n} from \"./constants\"\n\nimport Push from \"./push\"\nimport Timer from \"./timer\"\n\n/**\n *\n * @param {string} topic\n * @param {(Object|function)} params\n * @param {Socket} socket\n */\nexport default class Channel {\n constructor(topic, params, socket){\n this.state = CHANNEL_STATES.closed\n this.topic = topic\n this.params = closure(params || {})\n this.socket = socket\n this.bindings = []\n this.bindingRef = 0\n this.timeout = this.socket.timeout\n this.joinedOnce = false\n this.joinPush = new Push(this, CHANNEL_EVENTS.join, this.params, this.timeout)\n this.pushBuffer = []\n this.stateChangeRefs = []\n\n this.rejoinTimer = new Timer(() => {\n if(this.socket.isConnected()){ this.rejoin() }\n }, this.socket.rejoinAfterMs)\n this.stateChangeRefs.push(this.socket.onError(() => this.rejoinTimer.reset()))\n this.stateChangeRefs.push(this.socket.onOpen(() => {\n this.rejoinTimer.reset()\n if(this.isErrored()){ this.rejoin() }\n })\n )\n this.joinPush.receive(\"ok\", () => {\n this.state = CHANNEL_STATES.joined\n this.rejoinTimer.reset()\n this.pushBuffer.forEach(pushEvent => pushEvent.send())\n this.pushBuffer = []\n })\n this.joinPush.receive(\"error\", () => {\n this.state = CHANNEL_STATES.errored\n if(this.socket.isConnected()){ this.rejoinTimer.scheduleTimeout() }\n })\n this.onClose(() => {\n this.rejoinTimer.reset()\n if(this.socket.hasLogger()) this.socket.log(\"channel\", `close ${this.topic} ${this.joinRef()}`)\n this.state = CHANNEL_STATES.closed\n this.socket.remove(this)\n })\n this.onError(reason => {\n if(this.socket.hasLogger()) this.socket.log(\"channel\", `error ${this.topic}`, reason)\n if(this.isJoining()){ this.joinPush.reset() }\n this.state = CHANNEL_STATES.errored\n if(this.socket.isConnected()){ this.rejoinTimer.scheduleTimeout() }\n })\n this.joinPush.receive(\"timeout\", () => {\n if(this.socket.hasLogger()) this.socket.log(\"channel\", `timeout ${this.topic} (${this.joinRef()})`, this.joinPush.timeout)\n let leavePush = new Push(this, CHANNEL_EVENTS.leave, closure({}), this.timeout)\n leavePush.send()\n this.state = CHANNEL_STATES.errored\n this.joinPush.reset()\n if(this.socket.isConnected()){ this.rejoinTimer.scheduleTimeout() }\n })\n this.on(CHANNEL_EVENTS.reply, (payload, ref) => {\n this.trigger(this.replyEventName(ref), payload)\n })\n }\n\n /**\n * Join the channel\n * @param {integer} timeout\n * @returns {Push}\n */\n join(timeout = this.timeout){\n if(this.joinedOnce){\n throw new Error(\"tried to join multiple times. 'join' can only be called a single time per channel instance\")\n } else {\n this.timeout = timeout\n this.joinedOnce = true\n this.rejoin()\n return this.joinPush\n }\n }\n\n /**\n * Hook into channel close\n * @param {Function} callback\n */\n onClose(callback){\n this.on(CHANNEL_EVENTS.close, callback)\n }\n\n /**\n * Hook into channel errors\n * @param {Function} callback\n */\n onError(callback){\n return this.on(CHANNEL_EVENTS.error, reason => callback(reason))\n }\n\n /**\n * Subscribes on channel events\n *\n * Subscription returns a ref counter, which can be used later to\n * unsubscribe the exact event listener\n *\n * @example\n * const ref1 = channel.on(\"event\", do_stuff)\n * const ref2 = channel.on(\"event\", do_other_stuff)\n * channel.off(\"event\", ref1)\n * // Since unsubscription, do_stuff won't fire,\n * // while do_other_stuff will keep firing on the \"event\"\n *\n * @param {string} event\n * @param {Function} callback\n * @returns {integer} ref\n */\n on(event, callback){\n let ref = this.bindingRef++\n this.bindings.push({event, ref, callback})\n return ref\n }\n\n /**\n * Unsubscribes off of channel events\n *\n * Use the ref returned from a channel.on() to unsubscribe one\n * handler, or pass nothing for the ref to unsubscribe all\n * handlers for the given event.\n *\n * @example\n * // Unsubscribe the do_stuff handler\n * const ref1 = channel.on(\"event\", do_stuff)\n * channel.off(\"event\", ref1)\n *\n * // Unsubscribe all handlers from event\n * channel.off(\"event\")\n *\n * @param {string} event\n * @param {integer} ref\n */\n off(event, ref){\n this.bindings = this.bindings.filter((bind) => {\n return !(bind.event === event && (typeof ref === \"undefined\" || ref === bind.ref))\n })\n }\n\n /**\n * @private\n */\n canPush(){ return this.socket.isConnected() && this.isJoined() }\n\n /**\n * Sends a message `event` to phoenix with the payload `payload`.\n * Phoenix receives this in the `handle_in(event, payload, socket)`\n * function. if phoenix replies or it times out (default 10000ms),\n * then optionally the reply can be received.\n *\n * @example\n * channel.push(\"event\")\n * .receive(\"ok\", payload => console.log(\"phoenix replied:\", payload))\n * .receive(\"error\", err => console.log(\"phoenix errored\", err))\n * .receive(\"timeout\", () => console.log(\"timed out pushing\"))\n * @param {string} event\n * @param {Object} payload\n * @param {number} [timeout]\n * @returns {Push}\n */\n push(event, payload, timeout = this.timeout){\n payload = payload || {}\n if(!this.joinedOnce){\n throw new Error(`tried to push '${event}' to '${this.topic}' before joining. Use channel.join() before pushing events`)\n }\n let pushEvent = new Push(this, event, function (){ return payload }, timeout)\n if(this.canPush()){\n pushEvent.send()\n } else {\n pushEvent.startTimeout()\n this.pushBuffer.push(pushEvent)\n }\n\n return pushEvent\n }\n\n /** Leaves the channel\n *\n * Unsubscribes from server events, and\n * instructs channel to terminate on server\n *\n * Triggers onClose() hooks\n *\n * To receive leave acknowledgements, use the `receive`\n * hook to bind to the server ack, ie:\n *\n * @example\n * channel.leave().receive(\"ok\", () => alert(\"left!\") )\n *\n * @param {integer} timeout\n * @returns {Push}\n */\n leave(timeout = this.timeout){\n this.rejoinTimer.reset()\n this.joinPush.cancelTimeout()\n\n this.state = CHANNEL_STATES.leaving\n let onClose = () => {\n if(this.socket.hasLogger()) this.socket.log(\"channel\", `leave ${this.topic}`)\n this.trigger(CHANNEL_EVENTS.close, \"leave\")\n }\n let leavePush = new Push(this, CHANNEL_EVENTS.leave, closure({}), timeout)\n leavePush.receive(\"ok\", () => onClose())\n .receive(\"timeout\", () => onClose())\n leavePush.send()\n if(!this.canPush()){ leavePush.trigger(\"ok\", {}) }\n\n return leavePush\n }\n\n /**\n * Overridable message hook\n *\n * Receives all events for specialized message handling\n * before dispatching to the channel callbacks.\n *\n * Must return the payload, modified or unmodified\n * @param {string} event\n * @param {Object} payload\n * @param {integer} ref\n * @returns {Object}\n */\n onMessage(_event, payload, _ref){ return payload }\n\n /**\n * @private\n */\n isMember(topic, event, payload, joinRef){\n if(this.topic !== topic){ return false }\n\n if(joinRef && joinRef !== this.joinRef()){\n if(this.socket.hasLogger()) this.socket.log(\"channel\", \"dropping outdated message\", {topic, event, payload, joinRef})\n return false\n } else {\n return true\n }\n }\n\n /**\n * @private\n */\n joinRef(){ return this.joinPush.ref }\n\n /**\n * @private\n */\n rejoin(timeout = this.timeout){\n if(this.isLeaving()){ return }\n this.socket.leaveOpenTopic(this.topic)\n this.state = CHANNEL_STATES.joining\n this.joinPush.resend(timeout)\n }\n\n /**\n * @private\n */\n trigger(event, payload, ref, joinRef){\n let handledPayload = this.onMessage(event, payload, ref, joinRef)\n if(payload && !handledPayload){ throw new Error(\"channel onMessage callbacks must return the payload, modified or unmodified\") }\n\n let eventBindings = this.bindings.filter(bind => bind.event === event)\n\n for(let i = 0; i < eventBindings.length; i++){\n let bind = eventBindings[i]\n bind.callback(handledPayload, ref, joinRef || this.joinRef())\n }\n }\n\n /**\n * @private\n */\n replyEventName(ref){ return `chan_reply_${ref}` }\n\n /**\n * @private\n */\n isClosed(){ return this.state === CHANNEL_STATES.closed }\n\n /**\n * @private\n */\n isErrored(){ return this.state === CHANNEL_STATES.errored }\n\n /**\n * @private\n */\n isJoined(){ return this.state === CHANNEL_STATES.joined }\n\n /**\n * @private\n */\n isJoining(){ return this.state === CHANNEL_STATES.joining }\n\n /**\n * @private\n */\n isLeaving(){ return this.state === CHANNEL_STATES.leaving }\n}\n", "import {\n global,\n XHR_STATES\n} from \"./constants\"\n\nexport default class Ajax {\n\n static request(method, endPoint, accept, body, timeout, ontimeout, callback){\n if(global.XDomainRequest){\n let req = new global.XDomainRequest() // IE8, IE9\n return this.xdomainRequest(req, method, endPoint, body, timeout, ontimeout, callback)\n } else {\n let req = new global.XMLHttpRequest() // IE7+, Firefox, Chrome, Opera, Safari\n return this.xhrRequest(req, method, endPoint, accept, body, timeout, ontimeout, callback)\n }\n }\n\n static xdomainRequest(req, method, endPoint, body, timeout, ontimeout, callback){\n req.timeout = timeout\n req.open(method, endPoint)\n req.onload = () => {\n let response = this.parseJSON(req.responseText)\n callback && callback(response)\n }\n if(ontimeout){ req.ontimeout = ontimeout }\n\n // Work around bug in IE9 that requires an attached onprogress handler\n req.onprogress = () => { }\n\n req.send(body)\n return req\n }\n\n static xhrRequest(req, method, endPoint, accept, body, timeout, ontimeout, callback){\n req.open(method, endPoint, true)\n req.timeout = timeout\n req.setRequestHeader(\"Content-Type\", accept)\n req.onerror = () => callback && callback(null)\n req.onreadystatechange = () => {\n if(req.readyState === XHR_STATES.complete && callback){\n let response = this.parseJSON(req.responseText)\n callback(response)\n }\n }\n if(ontimeout){ req.ontimeout = ontimeout }\n\n req.send(body)\n return req\n }\n\n static parseJSON(resp){\n if(!resp || resp === \"\"){ return null }\n\n try {\n return JSON.parse(resp)\n } catch (e){\n console && console.log(\"failed to parse JSON response\", resp)\n return null\n }\n }\n\n static serialize(obj, parentKey){\n let queryStr = []\n for(var key in obj){\n if(!Object.prototype.hasOwnProperty.call(obj, key)){ continue }\n let paramKey = parentKey ? `${parentKey}[${key}]` : key\n let paramVal = obj[key]\n if(typeof paramVal === \"object\"){\n queryStr.push(this.serialize(paramVal, paramKey))\n } else {\n queryStr.push(encodeURIComponent(paramKey) + \"=\" + encodeURIComponent(paramVal))\n }\n }\n return queryStr.join(\"&\")\n }\n\n static appendParams(url, params){\n if(Object.keys(params).length === 0){ return url }\n\n let prefix = url.match(/\\?/) ? \"&\" : \"?\"\n return `${url}${prefix}${this.serialize(params)}`\n }\n}\n", "import {\n SOCKET_STATES,\n TRANSPORTS\n} from \"./constants\"\n\nimport Ajax from \"./ajax\"\n\nexport default class LongPoll {\n\n constructor(endPoint){\n this.endPoint = null\n this.token = null\n this.skipHeartbeat = true\n this.reqs = new Set()\n this.onopen = function (){ } // noop\n this.onerror = function (){ } // noop\n this.onmessage = function (){ } // noop\n this.onclose = function (){ } // noop\n this.pollEndpoint = this.normalizeEndpoint(endPoint)\n this.readyState = SOCKET_STATES.connecting\n this.poll()\n }\n\n normalizeEndpoint(endPoint){\n return (endPoint\n .replace(\"ws://\", \"http://\")\n .replace(\"wss://\", \"https://\")\n .replace(new RegExp(\"(.*)\\/\" + TRANSPORTS.websocket), \"$1/\" + TRANSPORTS.longpoll))\n }\n\n endpointURL(){\n return Ajax.appendParams(this.pollEndpoint, {token: this.token})\n }\n\n closeAndRetry(code, reason, wasClean){\n this.close(code, reason, wasClean)\n this.readyState = SOCKET_STATES.connecting\n }\n\n ontimeout(){\n this.onerror(\"timeout\")\n this.closeAndRetry(1005, \"timeout\", false)\n }\n\n isActive(){ return this.readyState === SOCKET_STATES.open || this.readyState === SOCKET_STATES.connecting }\n\n poll(){\n this.ajax(\"GET\", null, () => this.ontimeout(), resp => {\n if(resp){\n var {status, token, messages} = resp\n this.token = token\n } else {\n status = 0\n }\n\n switch(status){\n case 200:\n messages.forEach(msg => {\n // Tasks are what things like event handlers, setTimeout callbacks,\n // promise resolves and more are run within.\n // In modern browsers, there are two different kinds of tasks,\n // microtasks and macrotasks.\n // Microtasks are mainly used for Promises, while macrotasks are\n // used for everything else.\n // Microtasks always have priority over macrotasks. If the JS engine\n // is looking for a task to run, it will always try to empty the\n // microtask queue before attempting to run anything from the\n // macrotask queue.\n //\n // For the WebSocket transport, messages always arrive in their own\n // event. This means that if any promises are resolved from within,\n // their callbacks will always finish execution by the time the\n // next message event handler is run.\n //\n // In order to emulate this behaviour, we need to make sure each\n // onmessage handler is run within it's own macrotask.\n setTimeout(() => this.onmessage({data: msg}), 0)\n })\n this.poll()\n break\n case 204:\n this.poll()\n break\n case 410:\n this.readyState = SOCKET_STATES.open\n this.onopen({})\n this.poll()\n break\n case 403:\n this.onerror(403)\n this.close(1008, \"forbidden\", false)\n break\n case 0:\n case 500:\n this.onerror(500)\n this.closeAndRetry(1011, \"internal server error\", 500)\n break\n default: throw new Error(`unhandled poll status ${status}`)\n }\n })\n }\n\n send(body){\n this.ajax(\"POST\", body, () => this.onerror(\"timeout\"), resp => {\n if(!resp || resp.status !== 200){\n this.onerror(resp && resp.status)\n this.closeAndRetry(1011, \"internal server error\", false)\n }\n })\n }\n\n close(code, reason, wasClean){\n for(let req of this.reqs){ req.abort() }\n this.readyState = SOCKET_STATES.closed\n let opts = Object.assign({code: 1000, reason: undefined, wasClean: true}, {code, reason, wasClean})\n if(typeof(CloseEvent) !== \"undefined\"){\n this.onclose(new CloseEvent(\"close\", opts))\n } else {\n this.onclose(opts)\n }\n }\n\n ajax(method, body, onCallerTimeout, callback){\n let req\n let ontimeout = () => {\n this.reqs.delete(req)\n onCallerTimeout()\n }\n req = Ajax.request(method, this.endpointURL(), \"application/json\", body, this.timeout, ontimeout, resp => {\n this.reqs.delete(req)\n if(this.isActive()){ callback(resp) }\n })\n this.reqs.add(req)\n }\n}\n", "/**\n * Initializes the Presence\n * @param {Channel} channel - The Channel\n * @param {Object} opts - The options,\n * for example `{events: {state: \"state\", diff: \"diff\"}}`\n */\nexport default class Presence {\n\n constructor(channel, opts = {}){\n let events = opts.events || {state: \"presence_state\", diff: \"presence_diff\"}\n this.state = {}\n this.pendingDiffs = []\n this.channel = channel\n this.joinRef = null\n this.caller = {\n onJoin: function (){ },\n onLeave: function (){ },\n onSync: function (){ }\n }\n\n this.channel.on(events.state, newState => {\n let {onJoin, onLeave, onSync} = this.caller\n\n this.joinRef = this.channel.joinRef()\n this.state = Presence.syncState(this.state, newState, onJoin, onLeave)\n\n this.pendingDiffs.forEach(diff => {\n this.state = Presence.syncDiff(this.state, diff, onJoin, onLeave)\n })\n this.pendingDiffs = []\n onSync()\n })\n\n this.channel.on(events.diff, diff => {\n let {onJoin, onLeave, onSync} = this.caller\n\n if(this.inPendingSyncState()){\n this.pendingDiffs.push(diff)\n } else {\n this.state = Presence.syncDiff(this.state, diff, onJoin, onLeave)\n onSync()\n }\n })\n }\n\n onJoin(callback){ this.caller.onJoin = callback }\n\n onLeave(callback){ this.caller.onLeave = callback }\n\n onSync(callback){ this.caller.onSync = callback }\n\n list(by){ return Presence.list(this.state, by) }\n\n inPendingSyncState(){\n return !this.joinRef || (this.joinRef !== this.channel.joinRef())\n }\n\n // lower-level public static API\n\n /**\n * Used to sync the list of presences on the server\n * with the client's state. An optional `onJoin` and `onLeave` callback can\n * be provided to react to changes in the client's local presences across\n * disconnects and reconnects with the server.\n *\n * @returns {Presence}\n */\n static syncState(currentState, newState, onJoin, onLeave){\n let state = this.clone(currentState)\n let joins = {}\n let leaves = {}\n\n this.map(state, (key, presence) => {\n if(!newState[key]){\n leaves[key] = presence\n }\n })\n this.map(newState, (key, newPresence) => {\n let currentPresence = state[key]\n if(currentPresence){\n let newRefs = newPresence.metas.map(m => m.phx_ref)\n let curRefs = currentPresence.metas.map(m => m.phx_ref)\n let joinedMetas = newPresence.metas.filter(m => curRefs.indexOf(m.phx_ref) < 0)\n let leftMetas = currentPresence.metas.filter(m => newRefs.indexOf(m.phx_ref) < 0)\n if(joinedMetas.length > 0){\n joins[key] = newPresence\n joins[key].metas = joinedMetas\n }\n if(leftMetas.length > 0){\n leaves[key] = this.clone(currentPresence)\n leaves[key].metas = leftMetas\n }\n } else {\n joins[key] = newPresence\n }\n })\n return this.syncDiff(state, {joins: joins, leaves: leaves}, onJoin, onLeave)\n }\n\n /**\n *\n * Used to sync a diff of presence join and leave\n * events from the server, as they happen. Like `syncState`, `syncDiff`\n * accepts optional `onJoin` and `onLeave` callbacks to react to a user\n * joining or leaving from a device.\n *\n * @returns {Presence}\n */\n static syncDiff(state, diff, onJoin, onLeave){\n let {joins, leaves} = this.clone(diff)\n if(!onJoin){ onJoin = function (){ } }\n if(!onLeave){ onLeave = function (){ } }\n\n this.map(joins, (key, newPresence) => {\n let currentPresence = state[key]\n state[key] = this.clone(newPresence)\n if(currentPresence){\n let joinedRefs = state[key].metas.map(m => m.phx_ref)\n let curMetas = currentPresence.metas.filter(m => joinedRefs.indexOf(m.phx_ref) < 0)\n state[key].metas.unshift(...curMetas)\n }\n onJoin(key, currentPresence, newPresence)\n })\n this.map(leaves, (key, leftPresence) => {\n let currentPresence = state[key]\n if(!currentPresence){ return }\n let refsToRemove = leftPresence.metas.map(m => m.phx_ref)\n currentPresence.metas = currentPresence.metas.filter(p => {\n return refsToRemove.indexOf(p.phx_ref) < 0\n })\n onLeave(key, currentPresence, leftPresence)\n if(currentPresence.metas.length === 0){\n delete state[key]\n }\n })\n return state\n }\n\n /**\n * Returns the array of presences, with selected metadata.\n *\n * @param {Object} presences\n * @param {Function} chooser\n *\n * @returns {Presence}\n */\n static list(presences, chooser){\n if(!chooser){ chooser = function (key, pres){ return pres } }\n\n return this.map(presences, (key, presence) => {\n return chooser(key, presence)\n })\n }\n\n // private\n\n static map(obj, func){\n return Object.getOwnPropertyNames(obj).map(key => func(key, obj[key]))\n }\n\n static clone(obj){ return JSON.parse(JSON.stringify(obj)) }\n}\n", "/* The default serializer for encoding and decoding messages */\nimport {\n CHANNEL_EVENTS\n} from \"./constants\"\n\nexport default {\n HEADER_LENGTH: 1,\n META_LENGTH: 4,\n KINDS: {push: 0, reply: 1, broadcast: 2},\n\n encode(msg, callback){\n if(msg.payload.constructor === ArrayBuffer){\n return callback(this.binaryEncode(msg))\n } else {\n let payload = [msg.join_ref, msg.ref, msg.topic, msg.event, msg.payload]\n return callback(JSON.stringify(payload))\n }\n },\n\n decode(rawPayload, callback){\n if(rawPayload.constructor === ArrayBuffer){\n return callback(this.binaryDecode(rawPayload))\n } else {\n let [join_ref, ref, topic, event, payload] = JSON.parse(rawPayload)\n return callback({join_ref, ref, topic, event, payload})\n }\n },\n\n // private\n\n binaryEncode(message){\n let {join_ref, ref, event, topic, payload} = message\n let metaLength = this.META_LENGTH + join_ref.length + ref.length + topic.length + event.length\n let header = new ArrayBuffer(this.HEADER_LENGTH + metaLength)\n let view = new DataView(header)\n let offset = 0\n\n view.setUint8(offset++, this.KINDS.push) // kind\n view.setUint8(offset++, join_ref.length)\n view.setUint8(offset++, ref.length)\n view.setUint8(offset++, topic.length)\n view.setUint8(offset++, event.length)\n Array.from(join_ref, char => view.setUint8(offset++, char.charCodeAt(0)))\n Array.from(ref, char => view.setUint8(offset++, char.charCodeAt(0)))\n Array.from(topic, char => view.setUint8(offset++, char.charCodeAt(0)))\n Array.from(event, char => view.setUint8(offset++, char.charCodeAt(0)))\n\n var combined = new Uint8Array(header.byteLength + payload.byteLength)\n combined.set(new Uint8Array(header), 0)\n combined.set(new Uint8Array(payload), header.byteLength)\n\n return combined.buffer\n },\n\n binaryDecode(buffer){\n let view = new DataView(buffer)\n let kind = view.getUint8(0)\n let decoder = new TextDecoder()\n switch(kind){\n case this.KINDS.push: return this.decodePush(buffer, view, decoder)\n case this.KINDS.reply: return this.decodeReply(buffer, view, decoder)\n case this.KINDS.broadcast: return this.decodeBroadcast(buffer, view, decoder)\n }\n },\n\n decodePush(buffer, view, decoder){\n let joinRefSize = view.getUint8(1)\n let topicSize = view.getUint8(2)\n let eventSize = view.getUint8(3)\n let offset = this.HEADER_LENGTH + this.META_LENGTH - 1 // pushes have no ref\n let joinRef = decoder.decode(buffer.slice(offset, offset + joinRefSize))\n offset = offset + joinRefSize\n let topic = decoder.decode(buffer.slice(offset, offset + topicSize))\n offset = offset + topicSize\n let event = decoder.decode(buffer.slice(offset, offset + eventSize))\n offset = offset + eventSize\n let data = buffer.slice(offset, buffer.byteLength)\n return {join_ref: joinRef, ref: null, topic: topic, event: event, payload: data}\n },\n\n decodeReply(buffer, view, decoder){\n let joinRefSize = view.getUint8(1)\n let refSize = view.getUint8(2)\n let topicSize = view.getUint8(3)\n let eventSize = view.getUint8(4)\n let offset = this.HEADER_LENGTH + this.META_LENGTH\n let joinRef = decoder.decode(buffer.slice(offset, offset + joinRefSize))\n offset = offset + joinRefSize\n let ref = decoder.decode(buffer.slice(offset, offset + refSize))\n offset = offset + refSize\n let topic = decoder.decode(buffer.slice(offset, offset + topicSize))\n offset = offset + topicSize\n let event = decoder.decode(buffer.slice(offset, offset + eventSize))\n offset = offset + eventSize\n let data = buffer.slice(offset, buffer.byteLength)\n let payload = {status: event, response: data}\n return {join_ref: joinRef, ref: ref, topic: topic, event: CHANNEL_EVENTS.reply, payload: payload}\n },\n\n decodeBroadcast(buffer, view, decoder){\n let topicSize = view.getUint8(1)\n let eventSize = view.getUint8(2)\n let offset = this.HEADER_LENGTH + 2\n let topic = decoder.decode(buffer.slice(offset, offset + topicSize))\n offset = offset + topicSize\n let event = decoder.decode(buffer.slice(offset, offset + eventSize))\n offset = offset + eventSize\n let data = buffer.slice(offset, buffer.byteLength)\n\n return {join_ref: null, ref: null, topic: topic, event: event, payload: data}\n }\n}\n", "import {\n global,\n phxWindow,\n CHANNEL_EVENTS,\n DEFAULT_TIMEOUT,\n DEFAULT_VSN,\n SOCKET_STATES,\n TRANSPORTS,\n WS_CLOSE_NORMAL\n} from \"./constants\"\n\nimport {\n closure\n} from \"./utils\"\n\nimport Ajax from \"./ajax\"\nimport Channel from \"./channel\"\nimport LongPoll from \"./longpoll\"\nimport Serializer from \"./serializer\"\nimport Timer from \"./timer\"\n\n/** Initializes the Socket *\n *\n * For IE8 support use an ES5-shim (https://github.com/es-shims/es5-shim)\n *\n * @param {string} endPoint - The string WebSocket endpoint, ie, `\"ws://example.com/socket\"`,\n * `\"wss://example.com\"`\n * `\"/socket\"` (inherited host & protocol)\n * @param {Object} [opts] - Optional configuration\n * @param {Function} [opts.transport] - The Websocket Transport, for example WebSocket or Phoenix.LongPoll.\n *\n * Defaults to WebSocket with automatic LongPoll fallback.\n * @param {Function} [opts.encode] - The function to encode outgoing messages.\n *\n * Defaults to JSON encoder.\n *\n * @param {Function} [opts.decode] - The function to decode incoming messages.\n *\n * Defaults to JSON:\n *\n * ```javascript\n * (payload, callback) => callback(JSON.parse(payload))\n * ```\n *\n * @param {number} [opts.timeout] - The default timeout in milliseconds to trigger push timeouts.\n *\n * Defaults `DEFAULT_TIMEOUT`\n * @param {number} [opts.heartbeatIntervalMs] - The millisec interval to send a heartbeat message\n * @param {number} [opts.reconnectAfterMs] - The optional function that returns the millsec\n * socket reconnect interval.\n *\n * Defaults to stepped backoff of:\n *\n * ```javascript\n * function(tries){\n * return [10, 50, 100, 150, 200, 250, 500, 1000, 2000][tries - 1] || 5000\n * }\n * ````\n *\n * @param {number} [opts.rejoinAfterMs] - The optional function that returns the millsec\n * rejoin interval for individual channels.\n *\n * ```javascript\n * function(tries){\n * return [1000, 2000, 5000][tries - 1] || 10000\n * }\n * ````\n *\n * @param {Function} [opts.logger] - The optional function for specialized logging, ie:\n *\n * ```javascript\n * function(kind, msg, data) {\n * console.log(`${kind}: ${msg}`, data)\n * }\n * ```\n *\n * @param {number} [opts.longpollerTimeout] - The maximum timeout of a long poll AJAX request.\n *\n * Defaults to 20s (double the server long poll timer).\n *\n * @param {(Object|function)} [opts.params] - The optional params to pass when connecting\n * @param {string} [opts.binaryType] - The binary type to use for binary WebSocket frames.\n *\n * Defaults to \"arraybuffer\"\n *\n * @param {vsn} [opts.vsn] - The serializer's protocol version to send on connect.\n *\n * Defaults to DEFAULT_VSN.\n*/\nexport default class Socket {\n constructor(endPoint, opts = {}){\n this.stateChangeCallbacks = {open: [], close: [], error: [], message: []}\n this.channels = []\n this.sendBuffer = []\n this.ref = 0\n this.timeout = opts.timeout || DEFAULT_TIMEOUT\n this.transport = opts.transport || global.WebSocket || LongPoll\n this.establishedConnections = 0\n this.defaultEncoder = Serializer.encode.bind(Serializer)\n this.defaultDecoder = Serializer.decode.bind(Serializer)\n this.closeWasClean = false\n this.binaryType = opts.binaryType || \"arraybuffer\"\n this.connectClock = 1\n if(this.transport !== LongPoll){\n this.encode = opts.encode || this.defaultEncoder\n this.decode = opts.decode || this.defaultDecoder\n } else {\n this.encode = this.defaultEncoder\n this.decode = this.defaultDecoder\n }\n let awaitingConnectionOnPageShow = null\n if(phxWindow && phxWindow.addEventListener){\n phxWindow.addEventListener(\"pagehide\", _e => {\n if(this.conn){\n this.disconnect()\n awaitingConnectionOnPageShow = this.connectClock\n }\n })\n phxWindow.addEventListener(\"pageshow\", _e => {\n if(awaitingConnectionOnPageShow === this.connectClock){\n awaitingConnectionOnPageShow = null\n this.connect()\n }\n })\n }\n this.heartbeatIntervalMs = opts.heartbeatIntervalMs || 30000\n this.rejoinAfterMs = (tries) => {\n if(opts.rejoinAfterMs){\n return opts.rejoinAfterMs(tries)\n } else {\n return [1000, 2000, 5000][tries - 1] || 10000\n }\n }\n this.reconnectAfterMs = (tries) => {\n if(opts.reconnectAfterMs){\n return opts.reconnectAfterMs(tries)\n } else {\n return [10, 50, 100, 150, 200, 250, 500, 1000, 2000][tries - 1] || 5000\n }\n }\n this.logger = opts.logger || null\n this.longpollerTimeout = opts.longpollerTimeout || 20000\n this.params = closure(opts.params || {})\n this.endPoint = `${endPoint}/${TRANSPORTS.websocket}`\n this.vsn = opts.vsn || DEFAULT_VSN\n this.heartbeatTimer = null\n this.pendingHeartbeatRef = null\n this.reconnectTimer = new Timer(() => {\n this.teardown(() => this.connect())\n }, this.reconnectAfterMs)\n }\n\n /**\n * Returns the LongPoll transport reference\n */\n getLongPollTransport(){ return LongPoll }\n\n /**\n * Disconnects and replaces the active transport\n *\n * @param {Function} newTransport - The new transport class to instantiate\n *\n */\n replaceTransport(newTransport){\n this.connectClock++\n this.closeWasClean = true\n this.reconnectTimer.reset()\n this.sendBuffer = []\n if(this.conn){\n this.conn.close()\n this.conn = null\n }\n this.transport = newTransport\n }\n\n /**\n * Returns the socket protocol\n *\n * @returns {string}\n */\n protocol(){ return location.protocol.match(/^https/) ? \"wss\" : \"ws\" }\n\n /**\n * The fully qualifed socket url\n *\n * @returns {string}\n */\n endPointURL(){\n let uri = Ajax.appendParams(\n Ajax.appendParams(this.endPoint, this.params()), {vsn: this.vsn})\n if(uri.charAt(0) !== \"/\"){ return uri }\n if(uri.charAt(1) === \"/\"){ return `${this.protocol()}:${uri}` }\n\n return `${this.protocol()}://${location.host}${uri}`\n }\n\n /**\n * Disconnects the socket\n *\n * See https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent#Status_codes for valid status codes.\n *\n * @param {Function} callback - Optional callback which is called after socket is disconnected.\n * @param {integer} code - A status code for disconnection (Optional).\n * @param {string} reason - A textual description of the reason to disconnect. (Optional)\n */\n disconnect(callback, code, reason){\n this.connectClock++\n this.closeWasClean = true\n this.reconnectTimer.reset()\n this.teardown(callback, code, reason)\n }\n\n /**\n *\n * @param {Object} params - The params to send when connecting, for example `{user_id: userToken}`\n *\n * Passing params to connect is deprecated; pass them in the Socket constructor instead:\n * `new Socket(\"/socket\", {params: {user_id: userToken}})`.\n */\n connect(params){\n if(params){\n console && console.log(\"passing params to connect is deprecated. Instead pass :params to the Socket constructor\")\n this.params = closure(params)\n }\n if(this.conn){ return }\n\n this.connectClock++\n this.closeWasClean = false\n this.conn = new this.transport(this.endPointURL())\n this.conn.binaryType = this.binaryType\n this.conn.timeout = this.longpollerTimeout\n this.conn.onopen = () => this.onConnOpen()\n this.conn.onerror = error => this.onConnError(error)\n this.conn.onmessage = event => this.onConnMessage(event)\n this.conn.onclose = event => this.onConnClose(event)\n }\n\n /**\n * Logs the message. Override `this.logger` for specialized logging. noops by default\n * @param {string} kind\n * @param {string} msg\n * @param {Object} data\n */\n log(kind, msg, data){ this.logger(kind, msg, data) }\n\n /**\n * Returns true if a logger has been set on this socket.\n */\n hasLogger(){ return this.logger !== null }\n\n /**\n * Registers callbacks for connection open events\n *\n * @example socket.onOpen(function(){ console.info(\"the socket was opened\") })\n *\n * @param {Function} callback\n */\n onOpen(callback){\n let ref = this.makeRef()\n this.stateChangeCallbacks.open.push([ref, callback])\n return ref\n }\n\n /**\n * Registers callbacks for connection close events\n * @param {Function} callback\n */\n onClose(callback){\n let ref = this.makeRef()\n this.stateChangeCallbacks.close.push([ref, callback])\n return ref\n }\n\n /**\n * Registers callbacks for connection error events\n *\n * @example socket.onError(function(error){ alert(\"An error occurred\") })\n *\n * @param {Function} callback\n */\n onError(callback){\n let ref = this.makeRef()\n this.stateChangeCallbacks.error.push([ref, callback])\n return ref\n }\n\n /**\n * Registers callbacks for connection message events\n * @param {Function} callback\n */\n onMessage(callback){\n let ref = this.makeRef()\n this.stateChangeCallbacks.message.push([ref, callback])\n return ref\n }\n\n /**\n * Pings the server and invokes the callback with the RTT in milliseconds\n * @param {Function} callback\n *\n * Returns true if the ping was pushed or false if unable to be pushed.\n */\n ping(callback){\n if(!this.isConnected()){ return false }\n let ref = this.makeRef()\n let startTime = Date.now()\n this.push({topic: \"phoenix\", event: \"heartbeat\", payload: {}, ref: ref})\n let onMsgRef = this.onMessage(msg => {\n if(msg.ref === ref){\n this.off([onMsgRef])\n callback(Date.now() - startTime)\n }\n })\n return true\n }\n\n /**\n * @private\n */\n onConnOpen(){\n if(this.hasLogger()) this.log(\"transport\", `connected to ${this.endPointURL()}`)\n this.closeWasClean = false\n this.establishedConnections++\n this.flushSendBuffer()\n this.reconnectTimer.reset()\n this.resetHeartbeat()\n this.stateChangeCallbacks.open.forEach(([, callback]) => callback())\n }\n\n /**\n * @private\n */\n\n heartbeatTimeout(){\n if(this.pendingHeartbeatRef){\n this.pendingHeartbeatRef = null\n if(this.hasLogger()){ this.log(\"transport\", \"heartbeat timeout. Attempting to re-establish connection\") }\n this.triggerChanError()\n this.closeWasClean = false\n this.teardown(() => this.reconnectTimer.scheduleTimeout(), WS_CLOSE_NORMAL, \"heartbeat timeout\")\n }\n }\n\n resetHeartbeat(){\n if(this.conn && this.conn.skipHeartbeat){ return }\n this.pendingHeartbeatRef = null\n clearTimeout(this.heartbeatTimer)\n setTimeout(() => this.sendHeartbeat(), this.heartbeatIntervalMs)\n }\n\n teardown(callback, code, reason){\n if(!this.conn){\n return callback && callback()\n }\n\n this.waitForBufferDone(() => {\n if(this.conn){\n if(code){ this.conn.close(code, reason || \"\") } else { this.conn.close() }\n }\n\n this.waitForSocketClosed(() => {\n if(this.conn){\n this.conn.onopen = function (){ } // noop\n this.conn.onerror = function (){ } // noop\n this.conn.onmessage = function (){ } // noop\n this.conn.onclose = function (){ } // noop\n this.conn = null\n }\n\n callback && callback()\n })\n })\n }\n\n waitForBufferDone(callback, tries = 1){\n if(tries === 5 || !this.conn || !this.conn.bufferedAmount){\n callback()\n return\n }\n\n setTimeout(() => {\n this.waitForBufferDone(callback, tries + 1)\n }, 150 * tries)\n }\n\n waitForSocketClosed(callback, tries = 1){\n if(tries === 5 || !this.conn || this.conn.readyState === SOCKET_STATES.closed){\n callback()\n return\n }\n\n setTimeout(() => {\n this.waitForSocketClosed(callback, tries + 1)\n }, 150 * tries)\n }\n\n onConnClose(event){\n let closeCode = event && event.code\n if(this.hasLogger()) this.log(\"transport\", \"close\", event)\n this.triggerChanError()\n clearTimeout(this.heartbeatTimer)\n if(!this.closeWasClean && closeCode !== 1000){\n this.reconnectTimer.scheduleTimeout()\n }\n this.stateChangeCallbacks.close.forEach(([, callback]) => callback(event))\n }\n\n /**\n * @private\n */\n onConnError(error){\n if(this.hasLogger()) this.log(\"transport\", error)\n let transportBefore = this.transport\n let establishedBefore = this.establishedConnections\n this.stateChangeCallbacks.error.forEach(([, callback]) => {\n callback(error, transportBefore, establishedBefore)\n })\n if(transportBefore === this.transport || establishedBefore > 0){\n this.triggerChanError()\n }\n }\n\n /**\n * @private\n */\n triggerChanError(){\n this.channels.forEach(channel => {\n if(!(channel.isErrored() || channel.isLeaving() || channel.isClosed())){\n channel.trigger(CHANNEL_EVENTS.error)\n }\n })\n }\n\n /**\n * @returns {string}\n */\n connectionState(){\n switch(this.conn && this.conn.readyState){\n case SOCKET_STATES.connecting: return \"connecting\"\n case SOCKET_STATES.open: return \"open\"\n case SOCKET_STATES.closing: return \"closing\"\n default: return \"closed\"\n }\n }\n\n /**\n * @returns {boolean}\n */\n isConnected(){ return this.connectionState() === \"open\" }\n\n /**\n * @private\n *\n * @param {Channel}\n */\n remove(channel){\n this.off(channel.stateChangeRefs)\n this.channels = this.channels.filter(c => c.joinRef() !== channel.joinRef())\n }\n\n /**\n * Removes `onOpen`, `onClose`, `onError,` and `onMessage` registrations.\n *\n * @param {refs} - list of refs returned by calls to\n * `onOpen`, `onClose`, `onError,` and `onMessage`\n */\n off(refs){\n for(let key in this.stateChangeCallbacks){\n this.stateChangeCallbacks[key] = this.stateChangeCallbacks[key].filter(([ref]) => {\n return refs.indexOf(ref) === -1\n })\n }\n }\n\n /**\n * Initiates a new channel for the given topic\n *\n * @param {string} topic\n * @param {Object} chanParams - Parameters for the channel\n * @returns {Channel}\n */\n channel(topic, chanParams = {}){\n let chan = new Channel(topic, chanParams, this)\n this.channels.push(chan)\n return chan\n }\n\n /**\n * @param {Object} data\n */\n push(data){\n if(this.hasLogger()){\n let {topic, event, payload, ref, join_ref} = data\n this.log(\"push\", `${topic} ${event} (${join_ref}, ${ref})`, payload)\n }\n\n if(this.isConnected()){\n this.encode(data, result => this.conn.send(result))\n } else {\n this.sendBuffer.push(() => this.encode(data, result => this.conn.send(result)))\n }\n }\n\n /**\n * Return the next message ref, accounting for overflows\n * @returns {string}\n */\n makeRef(){\n let newRef = this.ref + 1\n if(newRef === this.ref){ this.ref = 0 } else { this.ref = newRef }\n\n return this.ref.toString()\n }\n\n sendHeartbeat(){\n if(this.pendingHeartbeatRef && !this.isConnected()){ return }\n this.pendingHeartbeatRef = this.makeRef()\n this.push({topic: \"phoenix\", event: \"heartbeat\", payload: {}, ref: this.pendingHeartbeatRef})\n this.heartbeatTimer = setTimeout(() => this.heartbeatTimeout(), this.heartbeatIntervalMs)\n }\n\n flushSendBuffer(){\n if(this.isConnected() && this.sendBuffer.length > 0){\n this.sendBuffer.forEach(callback => callback())\n this.sendBuffer = []\n }\n }\n\n onConnMessage(rawMessage){\n this.decode(rawMessage.data, msg => {\n let {topic, event, payload, ref, join_ref} = msg\n if(ref && ref === this.pendingHeartbeatRef){\n clearTimeout(this.heartbeatTimer)\n this.pendingHeartbeatRef = null\n setTimeout(() => this.sendHeartbeat(), this.heartbeatIntervalMs)\n }\n\n if(this.hasLogger()) this.log(\"receive\", `${payload.status || \"\"} ${topic} ${event} ${ref && \"(\" + ref + \")\" || \"\"}`, payload)\n\n for(let i = 0; i < this.channels.length; i++){\n const channel = this.channels[i]\n if(!channel.isMember(topic, event, payload, join_ref)){ continue }\n channel.trigger(event, payload, ref, join_ref)\n }\n\n for(let i = 0; i < this.stateChangeCallbacks.message.length; i++){\n let [, callback] = this.stateChangeCallbacks.message[i]\n callback(msg)\n }\n })\n }\n\n leaveOpenTopic(topic){\n let dupChannel = this.channels.find(c => c.topic === topic && (c.isJoined() || c.isJoining()))\n if(dupChannel){\n if(this.hasLogger()) this.log(\"transport\", `leaving duplicate topic \"${topic}\"`)\n dupChannel.leave()\n }\n }\n}\n"], + "mappings": ";AACO,IAAI,UAAU,CAAC,UAAU;AAC9B,MAAG,OAAO,UAAU,YAAW;AAC7B,WAAO;AAAA,EACT,OAAO;AACL,QAAI,WAAU,WAAW;AAAE,aAAO;AAAA,IAAM;AACxC,WAAO;AAAA,EACT;AACF;;;ACRO,IAAM,aAAa,OAAO,SAAS,cAAc,OAAO;AACxD,IAAM,YAAY,OAAO,WAAW,cAAc,SAAS;AAC3D,IAAM,SAAS,cAAc,aAAa;AAC1C,IAAM,cAAc;AACpB,IAAM,gBAAgB,EAAC,YAAY,GAAG,MAAM,GAAG,SAAS,GAAG,QAAQ,EAAC;AACpE,IAAM,kBAAkB;AACxB,IAAM,kBAAkB;AACxB,IAAM,iBAAiB;AAAA,EAC5B,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,SAAS;AACX;AACO,IAAM,iBAAiB;AAAA,EAC5B,OAAO;AAAA,EACP,OAAO;AAAA,EACP,MAAM;AAAA,EACN,OAAO;AAAA,EACP,OAAO;AACT;AAEO,IAAM,aAAa;AAAA,EACxB,UAAU;AAAA,EACV,WAAW;AACb;AACO,IAAM,aAAa;AAAA,EACxB,UAAU;AACZ;;;ACrBA,iBAA0B;AAAA,EACxB,YAAY,SAAS,OAAO,SAAS,SAAQ;AAC3C,SAAK,UAAU;AACf,SAAK,QAAQ;AACb,SAAK,UAAU,WAAW,WAAW;AAAE,aAAO,CAAC;AAAA,IAAE;AACjD,SAAK,eAAe;AACpB,SAAK,UAAU;AACf,SAAK,eAAe;AACpB,SAAK,WAAW,CAAC;AACjB,SAAK,OAAO;AAAA,EACd;AAAA,EAMA,OAAO,SAAQ;AACb,SAAK,UAAU;AACf,SAAK,MAAM;AACX,SAAK,KAAK;AAAA,EACZ;AAAA,EAKA,OAAM;AACJ,QAAG,KAAK,YAAY,SAAS,GAAE;AAAE;AAAA,IAAO;AACxC,SAAK,aAAa;AAClB,SAAK,OAAO;AACZ,SAAK,QAAQ,OAAO,KAAK;AAAA,MACvB,OAAO,KAAK,QAAQ;AAAA,MACpB,OAAO,KAAK;AAAA,MACZ,SAAS,KAAK,QAAQ;AAAA,MACtB,KAAK,KAAK;AAAA,MACV,UAAU,KAAK,QAAQ,QAAQ;AAAA,IACjC,CAAC;AAAA,EACH;AAAA,EAOA,QAAQ,QAAQ,UAAS;AACvB,QAAG,KAAK,YAAY,MAAM,GAAE;AAC1B,eAAS,KAAK,aAAa,QAAQ;AAAA,IACrC;AAEA,SAAK,SAAS,KAAK,EAAC,QAAQ,SAAQ,CAAC;AACrC,WAAO;AAAA,EACT;AAAA,EAKA,QAAO;AACL,SAAK,eAAe;AACpB,SAAK,MAAM;AACX,SAAK,WAAW;AAChB,SAAK,eAAe;AACpB,SAAK,OAAO;AAAA,EACd;AAAA,EAKA,aAAa,EAAC,QAAQ,UAAU,QAAM;AACpC,SAAK,SAAS,OAAO,OAAK,EAAE,WAAW,MAAM,EAC1C,QAAQ,OAAK,EAAE,SAAS,QAAQ,CAAC;AAAA,EACtC;AAAA,EAKA,iBAAgB;AACd,QAAG,CAAC,KAAK,UAAS;AAAE;AAAA,IAAO;AAC3B,SAAK,QAAQ,IAAI,KAAK,QAAQ;AAAA,EAChC;AAAA,EAKA,gBAAe;AACb,iBAAa,KAAK,YAAY;AAC9B,SAAK,eAAe;AAAA,EACtB;AAAA,EAKA,eAAc;AACZ,QAAG,KAAK,cAAa;AAAE,WAAK,cAAc;AAAA,IAAE;AAC5C,SAAK,MAAM,KAAK,QAAQ,OAAO,QAAQ;AACvC,SAAK,WAAW,KAAK,QAAQ,eAAe,KAAK,GAAG;AAEpD,SAAK,QAAQ,GAAG,KAAK,UAAU,aAAW;AACxC,WAAK,eAAe;AACpB,WAAK,cAAc;AACnB,WAAK,eAAe;AACpB,WAAK,aAAa,OAAO;AAAA,IAC3B,CAAC;AAED,SAAK,eAAe,WAAW,MAAM;AACnC,WAAK,QAAQ,WAAW,CAAC,CAAC;AAAA,IAC5B,GAAG,KAAK,OAAO;AAAA,EACjB;AAAA,EAKA,YAAY,QAAO;AACjB,WAAO,KAAK,gBAAgB,KAAK,aAAa,WAAW;AAAA,EAC3D;AAAA,EAKA,QAAQ,QAAQ,UAAS;AACvB,SAAK,QAAQ,QAAQ,KAAK,UAAU,EAAC,QAAQ,SAAQ,CAAC;AAAA,EACxD;AACF;;;AC9GA,kBAA2B;AAAA,EACzB,YAAY,UAAU,WAAU;AAC9B,SAAK,WAAW;AAChB,SAAK,YAAY;AACjB,SAAK,QAAQ;AACb,SAAK,QAAQ;AAAA,EACf;AAAA,EAEA,QAAO;AACL,SAAK,QAAQ;AACb,iBAAa,KAAK,KAAK;AAAA,EACzB;AAAA,EAKA,kBAAiB;AACf,iBAAa,KAAK,KAAK;AAEvB,SAAK,QAAQ,WAAW,MAAM;AAC5B,WAAK,QAAQ,KAAK,QAAQ;AAC1B,WAAK,SAAS;AAAA,IAChB,GAAG,KAAK,UAAU,KAAK,QAAQ,CAAC,CAAC;AAAA,EACnC;AACF;;;AC1BA,oBAA6B;AAAA,EAC3B,YAAY,OAAO,QAAQ,QAAO;AAChC,SAAK,QAAQ,eAAe;AAC5B,SAAK,QAAQ;AACb,SAAK,SAAS,QAAQ,UAAU,CAAC,CAAC;AAClC,SAAK,SAAS;AACd,SAAK,WAAW,CAAC;AACjB,SAAK,aAAa;AAClB,SAAK,UAAU,KAAK,OAAO;AAC3B,SAAK,aAAa;AAClB,SAAK,WAAW,IAAI,KAAK,MAAM,eAAe,MAAM,KAAK,QAAQ,KAAK,OAAO;AAC7E,SAAK,aAAa,CAAC;AACnB,SAAK,kBAAkB,CAAC;AAExB,SAAK,cAAc,IAAI,MAAM,MAAM;AACjC,UAAG,KAAK,OAAO,YAAY,GAAE;AAAE,aAAK,OAAO;AAAA,MAAE;AAAA,IAC/C,GAAG,KAAK,OAAO,aAAa;AAC5B,SAAK,gBAAgB,KAAK,KAAK,OAAO,QAAQ,MAAM,KAAK,YAAY,MAAM,CAAC,CAAC;AAC7E,SAAK,gBAAgB,KAAK,KAAK,OAAO,OAAO,MAAM;AACjD,WAAK,YAAY,MAAM;AACvB,UAAG,KAAK,UAAU,GAAE;AAAE,aAAK,OAAO;AAAA,MAAE;AAAA,IACtC,CAAC,CACD;AACA,SAAK,SAAS,QAAQ,MAAM,MAAM;AAChC,WAAK,QAAQ,eAAe;AAC5B,WAAK,YAAY,MAAM;AACvB,WAAK,WAAW,QAAQ,eAAa,UAAU,KAAK,CAAC;AACrD,WAAK,aAAa,CAAC;AAAA,IACrB,CAAC;AACD,SAAK,SAAS,QAAQ,SAAS,MAAM;AACnC,WAAK,QAAQ,eAAe;AAC5B,UAAG,KAAK,OAAO,YAAY,GAAE;AAAE,aAAK,YAAY,gBAAgB;AAAA,MAAE;AAAA,IACpE,CAAC;AACD,SAAK,QAAQ,MAAM;AACjB,WAAK,YAAY,MAAM;AACvB,UAAG,KAAK,OAAO,UAAU;AAAG,aAAK,OAAO,IAAI,WAAW,SAAS,KAAK,SAAS,KAAK,QAAQ,GAAG;AAC9F,WAAK,QAAQ,eAAe;AAC5B,WAAK,OAAO,OAAO,IAAI;AAAA,IACzB,CAAC;AACD,SAAK,QAAQ,YAAU;AACrB,UAAG,KAAK,OAAO,UAAU;AAAG,aAAK,OAAO,IAAI,WAAW,SAAS,KAAK,SAAS,MAAM;AACpF,UAAG,KAAK,UAAU,GAAE;AAAE,aAAK,SAAS,MAAM;AAAA,MAAE;AAC5C,WAAK,QAAQ,eAAe;AAC5B,UAAG,KAAK,OAAO,YAAY,GAAE;AAAE,aAAK,YAAY,gBAAgB;AAAA,MAAE;AAAA,IACpE,CAAC;AACD,SAAK,SAAS,QAAQ,WAAW,MAAM;AACrC,UAAG,KAAK,OAAO,UAAU;AAAG,aAAK,OAAO,IAAI,WAAW,WAAW,KAAK,UAAU,KAAK,QAAQ,MAAM,KAAK,SAAS,OAAO;AACzH,UAAI,YAAY,IAAI,KAAK,MAAM,eAAe,OAAO,QAAQ,CAAC,CAAC,GAAG,KAAK,OAAO;AAC9E,gBAAU,KAAK;AACf,WAAK,QAAQ,eAAe;AAC5B,WAAK,SAAS,MAAM;AACpB,UAAG,KAAK,OAAO,YAAY,GAAE;AAAE,aAAK,YAAY,gBAAgB;AAAA,MAAE;AAAA,IACpE,CAAC;AACD,SAAK,GAAG,eAAe,OAAO,CAAC,SAAS,QAAQ;AAC9C,WAAK,QAAQ,KAAK,eAAe,GAAG,GAAG,OAAO;AAAA,IAChD,CAAC;AAAA,EACH;AAAA,EAOA,KAAK,UAAU,KAAK,SAAQ;AAC1B,QAAG,KAAK,YAAW;AACjB,YAAM,IAAI,MAAM,4FAA4F;AAAA,IAC9G,OAAO;AACL,WAAK,UAAU;AACf,WAAK,aAAa;AAClB,WAAK,OAAO;AACZ,aAAO,KAAK;AAAA,IACd;AAAA,EACF;AAAA,EAMA,QAAQ,UAAS;AACf,SAAK,GAAG,eAAe,OAAO,QAAQ;AAAA,EACxC;AAAA,EAMA,QAAQ,UAAS;AACf,WAAO,KAAK,GAAG,eAAe,OAAO,YAAU,SAAS,MAAM,CAAC;AAAA,EACjE;AAAA,EAmBA,GAAG,OAAO,UAAS;AACjB,QAAI,MAAM,KAAK;AACf,SAAK,SAAS,KAAK,EAAC,OAAO,KAAK,SAAQ,CAAC;AACzC,WAAO;AAAA,EACT;AAAA,EAoBA,IAAI,OAAO,KAAI;AACb,SAAK,WAAW,KAAK,SAAS,OAAO,CAAC,SAAS;AAC7C,aAAO,CAAE,MAAK,UAAU,SAAU,QAAO,QAAQ,eAAe,QAAQ,KAAK;AAAA,IAC/E,CAAC;AAAA,EACH;AAAA,EAKA,UAAS;AAAE,WAAO,KAAK,OAAO,YAAY,KAAK,KAAK,SAAS;AAAA,EAAE;AAAA,EAkB/D,KAAK,OAAO,SAAS,UAAU,KAAK,SAAQ;AAC1C,cAAU,WAAW,CAAC;AACtB,QAAG,CAAC,KAAK,YAAW;AAClB,YAAM,IAAI,MAAM,kBAAkB,cAAc,KAAK,iEAAiE;AAAA,IACxH;AACA,QAAI,YAAY,IAAI,KAAK,MAAM,OAAO,WAAW;AAAE,aAAO;AAAA,IAAQ,GAAG,OAAO;AAC5E,QAAG,KAAK,QAAQ,GAAE;AAChB,gBAAU,KAAK;AAAA,IACjB,OAAO;AACL,gBAAU,aAAa;AACvB,WAAK,WAAW,KAAK,SAAS;AAAA,IAChC;AAEA,WAAO;AAAA,EACT;AAAA,EAkBA,MAAM,UAAU,KAAK,SAAQ;AAC3B,SAAK,YAAY,MAAM;AACvB,SAAK,SAAS,cAAc;AAE5B,SAAK,QAAQ,eAAe;AAC5B,QAAI,UAAU,MAAM;AAClB,UAAG,KAAK,OAAO,UAAU;AAAG,aAAK,OAAO,IAAI,WAAW,SAAS,KAAK,OAAO;AAC5E,WAAK,QAAQ,eAAe,OAAO,OAAO;AAAA,IAC5C;AACA,QAAI,YAAY,IAAI,KAAK,MAAM,eAAe,OAAO,QAAQ,CAAC,CAAC,GAAG,OAAO;AACzE,cAAU,QAAQ,MAAM,MAAM,QAAQ,CAAC,EACpC,QAAQ,WAAW,MAAM,QAAQ,CAAC;AACrC,cAAU,KAAK;AACf,QAAG,CAAC,KAAK,QAAQ,GAAE;AAAE,gBAAU,QAAQ,MAAM,CAAC,CAAC;AAAA,IAAE;AAEjD,WAAO;AAAA,EACT;AAAA,EAcA,UAAU,QAAQ,SAAS,MAAK;AAAE,WAAO;AAAA,EAAQ;AAAA,EAKjD,SAAS,OAAO,OAAO,SAAS,SAAQ;AACtC,QAAG,KAAK,UAAU,OAAM;AAAE,aAAO;AAAA,IAAM;AAEvC,QAAG,WAAW,YAAY,KAAK,QAAQ,GAAE;AACvC,UAAG,KAAK,OAAO,UAAU;AAAG,aAAK,OAAO,IAAI,WAAW,6BAA6B,EAAC,OAAO,OAAO,SAAS,QAAO,CAAC;AACpH,aAAO;AAAA,IACT,OAAO;AACL,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAKA,UAAS;AAAE,WAAO,KAAK,SAAS;AAAA,EAAI;AAAA,EAKpC,OAAO,UAAU,KAAK,SAAQ;AAC5B,QAAG,KAAK,UAAU,GAAE;AAAE;AAAA,IAAO;AAC7B,SAAK,OAAO,eAAe,KAAK,KAAK;AACrC,SAAK,QAAQ,eAAe;AAC5B,SAAK,SAAS,OAAO,OAAO;AAAA,EAC9B;AAAA,EAKA,QAAQ,OAAO,SAAS,KAAK,SAAQ;AACnC,QAAI,iBAAiB,KAAK,UAAU,OAAO,SAAS,KAAK,OAAO;AAChE,QAAG,WAAW,CAAC,gBAAe;AAAE,YAAM,IAAI,MAAM,6EAA6E;AAAA,IAAE;AAE/H,QAAI,gBAAgB,KAAK,SAAS,OAAO,UAAQ,KAAK,UAAU,KAAK;AAErE,aAAQ,IAAI,GAAG,IAAI,cAAc,QAAQ,KAAI;AAC3C,UAAI,OAAO,cAAc;AACzB,WAAK,SAAS,gBAAgB,KAAK,WAAW,KAAK,QAAQ,CAAC;AAAA,IAC9D;AAAA,EACF;AAAA,EAKA,eAAe,KAAI;AAAE,WAAO,cAAc;AAAA,EAAM;AAAA,EAKhD,WAAU;AAAE,WAAO,KAAK,UAAU,eAAe;AAAA,EAAO;AAAA,EAKxD,YAAW;AAAE,WAAO,KAAK,UAAU,eAAe;AAAA,EAAQ;AAAA,EAK1D,WAAU;AAAE,WAAO,KAAK,UAAU,eAAe;AAAA,EAAO;AAAA,EAKxD,YAAW;AAAE,WAAO,KAAK,UAAU,eAAe;AAAA,EAAQ;AAAA,EAK1D,YAAW;AAAE,WAAO,KAAK,UAAU,eAAe;AAAA,EAAQ;AAC5D;;;ACjTA,iBAA0B;AAAA,SAEjB,QAAQ,QAAQ,UAAU,QAAQ,MAAM,SAAS,WAAW,UAAS;AAC1E,QAAG,OAAO,gBAAe;AACvB,UAAI,MAAM,IAAI,OAAO,eAAe;AACpC,aAAO,KAAK,eAAe,KAAK,QAAQ,UAAU,MAAM,SAAS,WAAW,QAAQ;AAAA,IACtF,OAAO;AACL,UAAI,MAAM,IAAI,OAAO,eAAe;AACpC,aAAO,KAAK,WAAW,KAAK,QAAQ,UAAU,QAAQ,MAAM,SAAS,WAAW,QAAQ;AAAA,IAC1F;AAAA,EACF;AAAA,SAEO,eAAe,KAAK,QAAQ,UAAU,MAAM,SAAS,WAAW,UAAS;AAC9E,QAAI,UAAU;AACd,QAAI,KAAK,QAAQ,QAAQ;AACzB,QAAI,SAAS,MAAM;AACjB,UAAI,WAAW,KAAK,UAAU,IAAI,YAAY;AAC9C,kBAAY,SAAS,QAAQ;AAAA,IAC/B;AACA,QAAG,WAAU;AAAE,UAAI,YAAY;AAAA,IAAU;AAGzC,QAAI,aAAa,MAAM;AAAA,IAAE;AAEzB,QAAI,KAAK,IAAI;AACb,WAAO;AAAA,EACT;AAAA,SAEO,WAAW,KAAK,QAAQ,UAAU,QAAQ,MAAM,SAAS,WAAW,UAAS;AAClF,QAAI,KAAK,QAAQ,UAAU,IAAI;AAC/B,QAAI,UAAU;AACd,QAAI,iBAAiB,gBAAgB,MAAM;AAC3C,QAAI,UAAU,MAAM,YAAY,SAAS,IAAI;AAC7C,QAAI,qBAAqB,MAAM;AAC7B,UAAG,IAAI,eAAe,WAAW,YAAY,UAAS;AACpD,YAAI,WAAW,KAAK,UAAU,IAAI,YAAY;AAC9C,iBAAS,QAAQ;AAAA,MACnB;AAAA,IACF;AACA,QAAG,WAAU;AAAE,UAAI,YAAY;AAAA,IAAU;AAEzC,QAAI,KAAK,IAAI;AACb,WAAO;AAAA,EACT;AAAA,SAEO,UAAU,MAAK;AACpB,QAAG,CAAC,QAAQ,SAAS,IAAG;AAAE,aAAO;AAAA,IAAK;AAEtC,QAAI;AACF,aAAO,KAAK,MAAM,IAAI;AAAA,IACxB,SAAS,GAAP;AACA,iBAAW,QAAQ,IAAI,iCAAiC,IAAI;AAC5D,aAAO;AAAA,IACT;AAAA,EACF;AAAA,SAEO,UAAU,KAAK,WAAU;AAC9B,QAAI,WAAW,CAAC;AAChB,aAAQ,OAAO,KAAI;AACjB,UAAG,CAAC,OAAO,UAAU,eAAe,KAAK,KAAK,GAAG,GAAE;AAAE;AAAA,MAAS;AAC9D,UAAI,WAAW,YAAY,GAAG,aAAa,SAAS;AACpD,UAAI,WAAW,IAAI;AACnB,UAAG,OAAO,aAAa,UAAS;AAC9B,iBAAS,KAAK,KAAK,UAAU,UAAU,QAAQ,CAAC;AAAA,MAClD,OAAO;AACL,iBAAS,KAAK,mBAAmB,QAAQ,IAAI,MAAM,mBAAmB,QAAQ,CAAC;AAAA,MACjF;AAAA,IACF;AACA,WAAO,SAAS,KAAK,GAAG;AAAA,EAC1B;AAAA,SAEO,aAAa,KAAK,QAAO;AAC9B,QAAG,OAAO,KAAK,MAAM,EAAE,WAAW,GAAE;AAAE,aAAO;AAAA,IAAI;AAEjD,QAAI,SAAS,IAAI,MAAM,IAAI,IAAI,MAAM;AACrC,WAAO,GAAG,MAAM,SAAS,KAAK,UAAU,MAAM;AAAA,EAChD;AACF;;;AC3EA,qBAA8B;AAAA,EAE5B,YAAY,UAAS;AACnB,SAAK,WAAW;AAChB,SAAK,QAAQ;AACb,SAAK,gBAAgB;AACrB,SAAK,OAAO,oBAAI,IAAI;AACpB,SAAK,SAAS,WAAW;AAAA,IAAE;AAC3B,SAAK,UAAU,WAAW;AAAA,IAAE;AAC5B,SAAK,YAAY,WAAW;AAAA,IAAE;AAC9B,SAAK,UAAU,WAAW;AAAA,IAAE;AAC5B,SAAK,eAAe,KAAK,kBAAkB,QAAQ;AACnD,SAAK,aAAa,cAAc;AAChC,SAAK,KAAK;AAAA,EACZ;AAAA,EAEA,kBAAkB,UAAS;AACzB,WAAQ,SACL,QAAQ,SAAS,SAAS,EAC1B,QAAQ,UAAU,UAAU,EAC5B,QAAQ,IAAI,OAAO,UAAW,WAAW,SAAS,GAAG,QAAQ,WAAW,QAAQ;AAAA,EACrF;AAAA,EAEA,cAAa;AACX,WAAO,KAAK,aAAa,KAAK,cAAc,EAAC,OAAO,KAAK,MAAK,CAAC;AAAA,EACjE;AAAA,EAEA,cAAc,MAAM,QAAQ,UAAS;AACnC,SAAK,MAAM,MAAM,QAAQ,QAAQ;AACjC,SAAK,aAAa,cAAc;AAAA,EAClC;AAAA,EAEA,YAAW;AACT,SAAK,QAAQ,SAAS;AACtB,SAAK,cAAc,MAAM,WAAW,KAAK;AAAA,EAC3C;AAAA,EAEA,WAAU;AAAE,WAAO,KAAK,eAAe,cAAc,QAAQ,KAAK,eAAe,cAAc;AAAA,EAAW;AAAA,EAE1G,OAAM;AACJ,SAAK,KAAK,OAAO,MAAM,MAAM,KAAK,UAAU,GAAG,UAAQ;AACrD,UAAG,MAAK;AACN,YAAI,EAAC,QAAQ,OAAO,aAAY;AAChC,aAAK,QAAQ;AAAA,MACf,OAAO;AACL,iBAAS;AAAA,MACX;AAEA,cAAO;AAAA,aACA;AACH,mBAAS,QAAQ,SAAO;AAmBtB,uBAAW,MAAM,KAAK,UAAU,EAAC,MAAM,IAAG,CAAC,GAAG,CAAC;AAAA,UACjD,CAAC;AACD,eAAK,KAAK;AACV;AAAA,aACG;AACH,eAAK,KAAK;AACV;AAAA,aACG;AACH,eAAK,aAAa,cAAc;AAChC,eAAK,OAAO,CAAC,CAAC;AACd,eAAK,KAAK;AACV;AAAA,aACG;AACH,eAAK,QAAQ,GAAG;AAChB,eAAK,MAAM,MAAM,aAAa,KAAK;AACnC;AAAA,aACG;AAAA,aACA;AACH,eAAK,QAAQ,GAAG;AAChB,eAAK,cAAc,MAAM,yBAAyB,GAAG;AACrD;AAAA;AACO,gBAAM,IAAI,MAAM,yBAAyB,QAAQ;AAAA;AAAA,IAE9D,CAAC;AAAA,EACH;AAAA,EAEA,KAAK,MAAK;AACR,SAAK,KAAK,QAAQ,MAAM,MAAM,KAAK,QAAQ,SAAS,GAAG,UAAQ;AAC7D,UAAG,CAAC,QAAQ,KAAK,WAAW,KAAI;AAC9B,aAAK,QAAQ,QAAQ,KAAK,MAAM;AAChC,aAAK,cAAc,MAAM,yBAAyB,KAAK;AAAA,MACzD;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,MAAM,QAAQ,UAAS;AAC3B,aAAQ,OAAO,KAAK,MAAK;AAAE,UAAI,MAAM;AAAA,IAAE;AACvC,SAAK,aAAa,cAAc;AAChC,QAAI,OAAO,OAAO,OAAO,EAAC,MAAM,KAAM,QAAQ,QAAW,UAAU,KAAI,GAAG,EAAC,MAAM,QAAQ,SAAQ,CAAC;AAClG,QAAG,OAAO,eAAgB,aAAY;AACpC,WAAK,QAAQ,IAAI,WAAW,SAAS,IAAI,CAAC;AAAA,IAC5C,OAAO;AACL,WAAK,QAAQ,IAAI;AAAA,IACnB;AAAA,EACF;AAAA,EAEA,KAAK,QAAQ,MAAM,iBAAiB,UAAS;AAC3C,QAAI;AACJ,QAAI,YAAY,MAAM;AACpB,WAAK,KAAK,OAAO,GAAG;AACpB,sBAAgB;AAAA,IAClB;AACA,UAAM,KAAK,QAAQ,QAAQ,KAAK,YAAY,GAAG,oBAAoB,MAAM,KAAK,SAAS,WAAW,UAAQ;AACxG,WAAK,KAAK,OAAO,GAAG;AACpB,UAAG,KAAK,SAAS,GAAE;AAAE,iBAAS,IAAI;AAAA,MAAE;AAAA,IACtC,CAAC;AACD,SAAK,KAAK,IAAI,GAAG;AAAA,EACnB;AACF;;;AChIA,qBAA8B;AAAA,EAE5B,YAAY,SAAS,OAAO,CAAC,GAAE;AAC7B,QAAI,SAAS,KAAK,UAAU,EAAC,OAAO,kBAAkB,MAAM,gBAAe;AAC3E,SAAK,QAAQ,CAAC;AACd,SAAK,eAAe,CAAC;AACrB,SAAK,UAAU;AACf,SAAK,UAAU;AACf,SAAK,SAAS;AAAA,MACZ,QAAQ,WAAW;AAAA,MAAE;AAAA,MACrB,SAAS,WAAW;AAAA,MAAE;AAAA,MACtB,QAAQ,WAAW;AAAA,MAAE;AAAA,IACvB;AAEA,SAAK,QAAQ,GAAG,OAAO,OAAO,cAAY;AACxC,UAAI,EAAC,QAAQ,SAAS,WAAU,KAAK;AAErC,WAAK,UAAU,KAAK,QAAQ,QAAQ;AACpC,WAAK,QAAQ,SAAS,UAAU,KAAK,OAAO,UAAU,QAAQ,OAAO;AAErE,WAAK,aAAa,QAAQ,UAAQ;AAChC,aAAK,QAAQ,SAAS,SAAS,KAAK,OAAO,MAAM,QAAQ,OAAO;AAAA,MAClE,CAAC;AACD,WAAK,eAAe,CAAC;AACrB,aAAO;AAAA,IACT,CAAC;AAED,SAAK,QAAQ,GAAG,OAAO,MAAM,UAAQ;AACnC,UAAI,EAAC,QAAQ,SAAS,WAAU,KAAK;AAErC,UAAG,KAAK,mBAAmB,GAAE;AAC3B,aAAK,aAAa,KAAK,IAAI;AAAA,MAC7B,OAAO;AACL,aAAK,QAAQ,SAAS,SAAS,KAAK,OAAO,MAAM,QAAQ,OAAO;AAChE,eAAO;AAAA,MACT;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,OAAO,UAAS;AAAE,SAAK,OAAO,SAAS;AAAA,EAAS;AAAA,EAEhD,QAAQ,UAAS;AAAE,SAAK,OAAO,UAAU;AAAA,EAAS;AAAA,EAElD,OAAO,UAAS;AAAE,SAAK,OAAO,SAAS;AAAA,EAAS;AAAA,EAEhD,KAAK,IAAG;AAAE,WAAO,SAAS,KAAK,KAAK,OAAO,EAAE;AAAA,EAAE;AAAA,EAE/C,qBAAoB;AAClB,WAAO,CAAC,KAAK,WAAY,KAAK,YAAY,KAAK,QAAQ,QAAQ;AAAA,EACjE;AAAA,SAYO,UAAU,cAAc,UAAU,QAAQ,SAAQ;AACvD,QAAI,QAAQ,KAAK,MAAM,YAAY;AACnC,QAAI,QAAQ,CAAC;AACb,QAAI,SAAS,CAAC;AAEd,SAAK,IAAI,OAAO,CAAC,KAAK,aAAa;AACjC,UAAG,CAAC,SAAS,MAAK;AAChB,eAAO,OAAO;AAAA,MAChB;AAAA,IACF,CAAC;AACD,SAAK,IAAI,UAAU,CAAC,KAAK,gBAAgB;AACvC,UAAI,kBAAkB,MAAM;AAC5B,UAAG,iBAAgB;AACjB,YAAI,UAAU,YAAY,MAAM,IAAI,OAAK,EAAE,OAAO;AAClD,YAAI,UAAU,gBAAgB,MAAM,IAAI,OAAK,EAAE,OAAO;AACtD,YAAI,cAAc,YAAY,MAAM,OAAO,OAAK,QAAQ,QAAQ,EAAE,OAAO,IAAI,CAAC;AAC9E,YAAI,YAAY,gBAAgB,MAAM,OAAO,OAAK,QAAQ,QAAQ,EAAE,OAAO,IAAI,CAAC;AAChF,YAAG,YAAY,SAAS,GAAE;AACxB,gBAAM,OAAO;AACb,gBAAM,KAAK,QAAQ;AAAA,QACrB;AACA,YAAG,UAAU,SAAS,GAAE;AACtB,iBAAO,OAAO,KAAK,MAAM,eAAe;AACxC,iBAAO,KAAK,QAAQ;AAAA,QACtB;AAAA,MACF,OAAO;AACL,cAAM,OAAO;AAAA,MACf;AAAA,IACF,CAAC;AACD,WAAO,KAAK,SAAS,OAAO,EAAC,OAAc,OAAc,GAAG,QAAQ,OAAO;AAAA,EAC7E;AAAA,SAWO,SAAS,OAAO,MAAM,QAAQ,SAAQ;AAC3C,QAAI,EAAC,OAAO,WAAU,KAAK,MAAM,IAAI;AACrC,QAAG,CAAC,QAAO;AAAE,eAAS,WAAW;AAAA,MAAE;AAAA,IAAE;AACrC,QAAG,CAAC,SAAQ;AAAE,gBAAU,WAAW;AAAA,MAAE;AAAA,IAAE;AAEvC,SAAK,IAAI,OAAO,CAAC,KAAK,gBAAgB;AACpC,UAAI,kBAAkB,MAAM;AAC5B,YAAM,OAAO,KAAK,MAAM,WAAW;AACnC,UAAG,iBAAgB;AACjB,YAAI,aAAa,MAAM,KAAK,MAAM,IAAI,OAAK,EAAE,OAAO;AACpD,YAAI,WAAW,gBAAgB,MAAM,OAAO,OAAK,WAAW,QAAQ,EAAE,OAAO,IAAI,CAAC;AAClF,cAAM,KAAK,MAAM,QAAQ,GAAG,QAAQ;AAAA,MACtC;AACA,aAAO,KAAK,iBAAiB,WAAW;AAAA,IAC1C,CAAC;AACD,SAAK,IAAI,QAAQ,CAAC,KAAK,iBAAiB;AACtC,UAAI,kBAAkB,MAAM;AAC5B,UAAG,CAAC,iBAAgB;AAAE;AAAA,MAAO;AAC7B,UAAI,eAAe,aAAa,MAAM,IAAI,OAAK,EAAE,OAAO;AACxD,sBAAgB,QAAQ,gBAAgB,MAAM,OAAO,OAAK;AACxD,eAAO,aAAa,QAAQ,EAAE,OAAO,IAAI;AAAA,MAC3C,CAAC;AACD,cAAQ,KAAK,iBAAiB,YAAY;AAC1C,UAAG,gBAAgB,MAAM,WAAW,GAAE;AACpC,eAAO,MAAM;AAAA,MACf;AAAA,IACF,CAAC;AACD,WAAO;AAAA,EACT;AAAA,SAUO,KAAK,WAAW,SAAQ;AAC7B,QAAG,CAAC,SAAQ;AAAE,gBAAU,SAAU,KAAK,MAAK;AAAE,eAAO;AAAA,MAAK;AAAA,IAAE;AAE5D,WAAO,KAAK,IAAI,WAAW,CAAC,KAAK,aAAa;AAC5C,aAAO,QAAQ,KAAK,QAAQ;AAAA,IAC9B,CAAC;AAAA,EACH;AAAA,SAIO,IAAI,KAAK,MAAK;AACnB,WAAO,OAAO,oBAAoB,GAAG,EAAE,IAAI,SAAO,KAAK,KAAK,IAAI,IAAI,CAAC;AAAA,EACvE;AAAA,SAEO,MAAM,KAAI;AAAE,WAAO,KAAK,MAAM,KAAK,UAAU,GAAG,CAAC;AAAA,EAAE;AAC5D;;;AC5JA,IAAO,qBAAQ;AAAA,EACb,eAAe;AAAA,EACf,aAAa;AAAA,EACb,OAAO,EAAC,MAAM,GAAG,OAAO,GAAG,WAAW,EAAC;AAAA,EAEvC,OAAO,KAAK,UAAS;AACnB,QAAG,IAAI,QAAQ,gBAAgB,aAAY;AACzC,aAAO,SAAS,KAAK,aAAa,GAAG,CAAC;AAAA,IACxC,OAAO;AACL,UAAI,UAAU,CAAC,IAAI,UAAU,IAAI,KAAK,IAAI,OAAO,IAAI,OAAO,IAAI,OAAO;AACvE,aAAO,SAAS,KAAK,UAAU,OAAO,CAAC;AAAA,IACzC;AAAA,EACF;AAAA,EAEA,OAAO,YAAY,UAAS;AAC1B,QAAG,WAAW,gBAAgB,aAAY;AACxC,aAAO,SAAS,KAAK,aAAa,UAAU,CAAC;AAAA,IAC/C,OAAO;AACL,UAAI,CAAC,UAAU,KAAK,OAAO,OAAO,WAAW,KAAK,MAAM,UAAU;AAClE,aAAO,SAAS,EAAC,UAAU,KAAK,OAAO,OAAO,QAAO,CAAC;AAAA,IACxD;AAAA,EACF;AAAA,EAIA,aAAa,SAAQ;AACnB,QAAI,EAAC,UAAU,KAAK,OAAO,OAAO,YAAW;AAC7C,QAAI,aAAa,KAAK,cAAc,SAAS,SAAS,IAAI,SAAS,MAAM,SAAS,MAAM;AACxF,QAAI,SAAS,IAAI,YAAY,KAAK,gBAAgB,UAAU;AAC5D,QAAI,OAAO,IAAI,SAAS,MAAM;AAC9B,QAAI,SAAS;AAEb,SAAK,SAAS,UAAU,KAAK,MAAM,IAAI;AACvC,SAAK,SAAS,UAAU,SAAS,MAAM;AACvC,SAAK,SAAS,UAAU,IAAI,MAAM;AAClC,SAAK,SAAS,UAAU,MAAM,MAAM;AACpC,SAAK,SAAS,UAAU,MAAM,MAAM;AACpC,UAAM,KAAK,UAAU,UAAQ,KAAK,SAAS,UAAU,KAAK,WAAW,CAAC,CAAC,CAAC;AACxE,UAAM,KAAK,KAAK,UAAQ,KAAK,SAAS,UAAU,KAAK,WAAW,CAAC,CAAC,CAAC;AACnE,UAAM,KAAK,OAAO,UAAQ,KAAK,SAAS,UAAU,KAAK,WAAW,CAAC,CAAC,CAAC;AACrE,UAAM,KAAK,OAAO,UAAQ,KAAK,SAAS,UAAU,KAAK,WAAW,CAAC,CAAC,CAAC;AAErE,QAAI,WAAW,IAAI,WAAW,OAAO,aAAa,QAAQ,UAAU;AACpE,aAAS,IAAI,IAAI,WAAW,MAAM,GAAG,CAAC;AACtC,aAAS,IAAI,IAAI,WAAW,OAAO,GAAG,OAAO,UAAU;AAEvD,WAAO,SAAS;AAAA,EAClB;AAAA,EAEA,aAAa,QAAO;AAClB,QAAI,OAAO,IAAI,SAAS,MAAM;AAC9B,QAAI,OAAO,KAAK,SAAS,CAAC;AAC1B,QAAI,UAAU,IAAI,YAAY;AAC9B,YAAO;AAAA,WACA,KAAK,MAAM;AAAM,eAAO,KAAK,WAAW,QAAQ,MAAM,OAAO;AAAA,WAC7D,KAAK,MAAM;AAAO,eAAO,KAAK,YAAY,QAAQ,MAAM,OAAO;AAAA,WAC/D,KAAK,MAAM;AAAW,eAAO,KAAK,gBAAgB,QAAQ,MAAM,OAAO;AAAA;AAAA,EAEhF;AAAA,EAEA,WAAW,QAAQ,MAAM,SAAQ;AAC/B,QAAI,cAAc,KAAK,SAAS,CAAC;AACjC,QAAI,YAAY,KAAK,SAAS,CAAC;AAC/B,QAAI,YAAY,KAAK,SAAS,CAAC;AAC/B,QAAI,SAAS,KAAK,gBAAgB,KAAK,cAAc;AACrD,QAAI,UAAU,QAAQ,OAAO,OAAO,MAAM,QAAQ,SAAS,WAAW,CAAC;AACvE,aAAS,SAAS;AAClB,QAAI,QAAQ,QAAQ,OAAO,OAAO,MAAM,QAAQ,SAAS,SAAS,CAAC;AACnE,aAAS,SAAS;AAClB,QAAI,QAAQ,QAAQ,OAAO,OAAO,MAAM,QAAQ,SAAS,SAAS,CAAC;AACnE,aAAS,SAAS;AAClB,QAAI,OAAO,OAAO,MAAM,QAAQ,OAAO,UAAU;AACjD,WAAO,EAAC,UAAU,SAAS,KAAK,MAAM,OAAc,OAAc,SAAS,KAAI;AAAA,EACjF;AAAA,EAEA,YAAY,QAAQ,MAAM,SAAQ;AAChC,QAAI,cAAc,KAAK,SAAS,CAAC;AACjC,QAAI,UAAU,KAAK,SAAS,CAAC;AAC7B,QAAI,YAAY,KAAK,SAAS,CAAC;AAC/B,QAAI,YAAY,KAAK,SAAS,CAAC;AAC/B,QAAI,SAAS,KAAK,gBAAgB,KAAK;AACvC,QAAI,UAAU,QAAQ,OAAO,OAAO,MAAM,QAAQ,SAAS,WAAW,CAAC;AACvE,aAAS,SAAS;AAClB,QAAI,MAAM,QAAQ,OAAO,OAAO,MAAM,QAAQ,SAAS,OAAO,CAAC;AAC/D,aAAS,SAAS;AAClB,QAAI,QAAQ,QAAQ,OAAO,OAAO,MAAM,QAAQ,SAAS,SAAS,CAAC;AACnE,aAAS,SAAS;AAClB,QAAI,QAAQ,QAAQ,OAAO,OAAO,MAAM,QAAQ,SAAS,SAAS,CAAC;AACnE,aAAS,SAAS;AAClB,QAAI,OAAO,OAAO,MAAM,QAAQ,OAAO,UAAU;AACjD,QAAI,UAAU,EAAC,QAAQ,OAAO,UAAU,KAAI;AAC5C,WAAO,EAAC,UAAU,SAAS,KAAU,OAAc,OAAO,eAAe,OAAO,QAAgB;AAAA,EAClG;AAAA,EAEA,gBAAgB,QAAQ,MAAM,SAAQ;AACpC,QAAI,YAAY,KAAK,SAAS,CAAC;AAC/B,QAAI,YAAY,KAAK,SAAS,CAAC;AAC/B,QAAI,SAAS,KAAK,gBAAgB;AAClC,QAAI,QAAQ,QAAQ,OAAO,OAAO,MAAM,QAAQ,SAAS,SAAS,CAAC;AACnE,aAAS,SAAS;AAClB,QAAI,QAAQ,QAAQ,OAAO,OAAO,MAAM,QAAQ,SAAS,SAAS,CAAC;AACnE,aAAS,SAAS;AAClB,QAAI,OAAO,OAAO,MAAM,QAAQ,OAAO,UAAU;AAEjD,WAAO,EAAC,UAAU,MAAM,KAAK,MAAM,OAAc,OAAc,SAAS,KAAI;AAAA,EAC9E;AACF;;;ACtBA,mBAA4B;AAAA,EAC1B,YAAY,UAAU,OAAO,CAAC,GAAE;AAC9B,SAAK,uBAAuB,EAAC,MAAM,CAAC,GAAG,OAAO,CAAC,GAAG,OAAO,CAAC,GAAG,SAAS,CAAC,EAAC;AACxE,SAAK,WAAW,CAAC;AACjB,SAAK,aAAa,CAAC;AACnB,SAAK,MAAM;AACX,SAAK,UAAU,KAAK,WAAW;AAC/B,SAAK,YAAY,KAAK,aAAa,OAAO,aAAa;AACvD,SAAK,yBAAyB;AAC9B,SAAK,iBAAiB,mBAAW,OAAO,KAAK,kBAAU;AACvD,SAAK,iBAAiB,mBAAW,OAAO,KAAK,kBAAU;AACvD,SAAK,gBAAgB;AACrB,SAAK,aAAa,KAAK,cAAc;AACrC,SAAK,eAAe;AACpB,QAAG,KAAK,cAAc,UAAS;AAC7B,WAAK,SAAS,KAAK,UAAU,KAAK;AAClC,WAAK,SAAS,KAAK,UAAU,KAAK;AAAA,IACpC,OAAO;AACL,WAAK,SAAS,KAAK;AACnB,WAAK,SAAS,KAAK;AAAA,IACrB;AACA,QAAI,+BAA+B;AACnC,QAAG,aAAa,UAAU,kBAAiB;AACzC,gBAAU,iBAAiB,YAAY,QAAM;AAC3C,YAAG,KAAK,MAAK;AACX,eAAK,WAAW;AAChB,yCAA+B,KAAK;AAAA,QACtC;AAAA,MACF,CAAC;AACD,gBAAU,iBAAiB,YAAY,QAAM;AAC3C,YAAG,iCAAiC,KAAK,cAAa;AACpD,yCAA+B;AAC/B,eAAK,QAAQ;AAAA,QACf;AAAA,MACF,CAAC;AAAA,IACH;AACA,SAAK,sBAAsB,KAAK,uBAAuB;AACvD,SAAK,gBAAgB,CAAC,UAAU;AAC9B,UAAG,KAAK,eAAc;AACpB,eAAO,KAAK,cAAc,KAAK;AAAA,MACjC,OAAO;AACL,eAAO,CAAC,KAAM,KAAM,GAAI,EAAE,QAAQ,MAAM;AAAA,MAC1C;AAAA,IACF;AACA,SAAK,mBAAmB,CAAC,UAAU;AACjC,UAAG,KAAK,kBAAiB;AACvB,eAAO,KAAK,iBAAiB,KAAK;AAAA,MACpC,OAAO;AACL,eAAO,CAAC,IAAI,IAAI,KAAK,KAAK,KAAK,KAAK,KAAK,KAAM,GAAI,EAAE,QAAQ,MAAM;AAAA,MACrE;AAAA,IACF;AACA,SAAK,SAAS,KAAK,UAAU;AAC7B,SAAK,oBAAoB,KAAK,qBAAqB;AACnD,SAAK,SAAS,QAAQ,KAAK,UAAU,CAAC,CAAC;AACvC,SAAK,WAAW,GAAG,YAAY,WAAW;AAC1C,SAAK,MAAM,KAAK,OAAO;AACvB,SAAK,iBAAiB;AACtB,SAAK,sBAAsB;AAC3B,SAAK,iBAAiB,IAAI,MAAM,MAAM;AACpC,WAAK,SAAS,MAAM,KAAK,QAAQ,CAAC;AAAA,IACpC,GAAG,KAAK,gBAAgB;AAAA,EAC1B;AAAA,EAKA,uBAAsB;AAAE,WAAO;AAAA,EAAS;AAAA,EAQxC,iBAAiB,cAAa;AAC5B,SAAK;AACL,SAAK,gBAAgB;AACrB,SAAK,eAAe,MAAM;AAC1B,SAAK,aAAa,CAAC;AACnB,QAAG,KAAK,MAAK;AACX,WAAK,KAAK,MAAM;AAChB,WAAK,OAAO;AAAA,IACd;AACA,SAAK,YAAY;AAAA,EACnB;AAAA,EAOA,WAAU;AAAE,WAAO,SAAS,SAAS,MAAM,QAAQ,IAAI,QAAQ;AAAA,EAAK;AAAA,EAOpE,cAAa;AACX,QAAI,MAAM,KAAK,aACb,KAAK,aAAa,KAAK,UAAU,KAAK,OAAO,CAAC,GAAG,EAAC,KAAK,KAAK,IAAG,CAAC;AAClE,QAAG,IAAI,OAAO,CAAC,MAAM,KAAI;AAAE,aAAO;AAAA,IAAI;AACtC,QAAG,IAAI,OAAO,CAAC,MAAM,KAAI;AAAE,aAAO,GAAG,KAAK,SAAS,KAAK;AAAA,IAAM;AAE9D,WAAO,GAAG,KAAK,SAAS,OAAO,SAAS,OAAO;AAAA,EACjD;AAAA,EAWA,WAAW,UAAU,MAAM,QAAO;AAChC,SAAK;AACL,SAAK,gBAAgB;AACrB,SAAK,eAAe,MAAM;AAC1B,SAAK,SAAS,UAAU,MAAM,MAAM;AAAA,EACtC;AAAA,EASA,QAAQ,QAAO;AACb,QAAG,QAAO;AACR,iBAAW,QAAQ,IAAI,yFAAyF;AAChH,WAAK,SAAS,QAAQ,MAAM;AAAA,IAC9B;AACA,QAAG,KAAK,MAAK;AAAE;AAAA,IAAO;AAEtB,SAAK;AACL,SAAK,gBAAgB;AACrB,SAAK,OAAO,IAAI,KAAK,UAAU,KAAK,YAAY,CAAC;AACjD,SAAK,KAAK,aAAa,KAAK;AAC5B,SAAK,KAAK,UAAU,KAAK;AACzB,SAAK,KAAK,SAAS,MAAM,KAAK,WAAW;AACzC,SAAK,KAAK,UAAU,WAAS,KAAK,YAAY,KAAK;AACnD,SAAK,KAAK,YAAY,WAAS,KAAK,cAAc,KAAK;AACvD,SAAK,KAAK,UAAU,WAAS,KAAK,YAAY,KAAK;AAAA,EACrD;AAAA,EAQA,IAAI,MAAM,KAAK,MAAK;AAAE,SAAK,OAAO,MAAM,KAAK,IAAI;AAAA,EAAE;AAAA,EAKnD,YAAW;AAAE,WAAO,KAAK,WAAW;AAAA,EAAK;AAAA,EASzC,OAAO,UAAS;AACd,QAAI,MAAM,KAAK,QAAQ;AACvB,SAAK,qBAAqB,KAAK,KAAK,CAAC,KAAK,QAAQ,CAAC;AACnD,WAAO;AAAA,EACT;AAAA,EAMA,QAAQ,UAAS;AACf,QAAI,MAAM,KAAK,QAAQ;AACvB,SAAK,qBAAqB,MAAM,KAAK,CAAC,KAAK,QAAQ,CAAC;AACpD,WAAO;AAAA,EACT;AAAA,EASA,QAAQ,UAAS;AACf,QAAI,MAAM,KAAK,QAAQ;AACvB,SAAK,qBAAqB,MAAM,KAAK,CAAC,KAAK,QAAQ,CAAC;AACpD,WAAO;AAAA,EACT;AAAA,EAMA,UAAU,UAAS;AACjB,QAAI,MAAM,KAAK,QAAQ;AACvB,SAAK,qBAAqB,QAAQ,KAAK,CAAC,KAAK,QAAQ,CAAC;AACtD,WAAO;AAAA,EACT;AAAA,EAQA,KAAK,UAAS;AACZ,QAAG,CAAC,KAAK,YAAY,GAAE;AAAE,aAAO;AAAA,IAAM;AACtC,QAAI,MAAM,KAAK,QAAQ;AACvB,QAAI,YAAY,KAAK,IAAI;AACzB,SAAK,KAAK,EAAC,OAAO,WAAW,OAAO,aAAa,SAAS,CAAC,GAAG,IAAQ,CAAC;AACvE,QAAI,WAAW,KAAK,UAAU,SAAO;AACnC,UAAG,IAAI,QAAQ,KAAI;AACjB,aAAK,IAAI,CAAC,QAAQ,CAAC;AACnB,iBAAS,KAAK,IAAI,IAAI,SAAS;AAAA,MACjC;AAAA,IACF,CAAC;AACD,WAAO;AAAA,EACT;AAAA,EAKA,aAAY;AACV,QAAG,KAAK,UAAU;AAAG,WAAK,IAAI,aAAa,gBAAgB,KAAK,YAAY,GAAG;AAC/E,SAAK,gBAAgB;AACrB,SAAK;AACL,SAAK,gBAAgB;AACrB,SAAK,eAAe,MAAM;AAC1B,SAAK,eAAe;AACpB,SAAK,qBAAqB,KAAK,QAAQ,CAAC,CAAC,EAAE,cAAc,SAAS,CAAC;AAAA,EACrE;AAAA,EAMA,mBAAkB;AAChB,QAAG,KAAK,qBAAoB;AAC1B,WAAK,sBAAsB;AAC3B,UAAG,KAAK,UAAU,GAAE;AAAE,aAAK,IAAI,aAAa,0DAA0D;AAAA,MAAE;AACxG,WAAK,iBAAiB;AACtB,WAAK,gBAAgB;AACrB,WAAK,SAAS,MAAM,KAAK,eAAe,gBAAgB,GAAG,iBAAiB,mBAAmB;AAAA,IACjG;AAAA,EACF;AAAA,EAEA,iBAAgB;AACd,QAAG,KAAK,QAAQ,KAAK,KAAK,eAAc;AAAE;AAAA,IAAO;AACjD,SAAK,sBAAsB;AAC3B,iBAAa,KAAK,cAAc;AAChC,eAAW,MAAM,KAAK,cAAc,GAAG,KAAK,mBAAmB;AAAA,EACjE;AAAA,EAEA,SAAS,UAAU,MAAM,QAAO;AAC9B,QAAG,CAAC,KAAK,MAAK;AACZ,aAAO,YAAY,SAAS;AAAA,IAC9B;AAEA,SAAK,kBAAkB,MAAM;AAC3B,UAAG,KAAK,MAAK;AACX,YAAG,MAAK;AAAE,eAAK,KAAK,MAAM,MAAM,UAAU,EAAE;AAAA,QAAE,OAAO;AAAE,eAAK,KAAK,MAAM;AAAA,QAAE;AAAA,MAC3E;AAEA,WAAK,oBAAoB,MAAM;AAC7B,YAAG,KAAK,MAAK;AACX,eAAK,KAAK,SAAS,WAAW;AAAA,UAAE;AAChC,eAAK,KAAK,UAAU,WAAW;AAAA,UAAE;AACjC,eAAK,KAAK,YAAY,WAAW;AAAA,UAAE;AACnC,eAAK,KAAK,UAAU,WAAW;AAAA,UAAE;AACjC,eAAK,OAAO;AAAA,QACd;AAEA,oBAAY,SAAS;AAAA,MACvB,CAAC;AAAA,IACH,CAAC;AAAA,EACH;AAAA,EAEA,kBAAkB,UAAU,QAAQ,GAAE;AACpC,QAAG,UAAU,KAAK,CAAC,KAAK,QAAQ,CAAC,KAAK,KAAK,gBAAe;AACxD,eAAS;AACT;AAAA,IACF;AAEA,eAAW,MAAM;AACf,WAAK,kBAAkB,UAAU,QAAQ,CAAC;AAAA,IAC5C,GAAG,MAAM,KAAK;AAAA,EAChB;AAAA,EAEA,oBAAoB,UAAU,QAAQ,GAAE;AACtC,QAAG,UAAU,KAAK,CAAC,KAAK,QAAQ,KAAK,KAAK,eAAe,cAAc,QAAO;AAC5E,eAAS;AACT;AAAA,IACF;AAEA,eAAW,MAAM;AACf,WAAK,oBAAoB,UAAU,QAAQ,CAAC;AAAA,IAC9C,GAAG,MAAM,KAAK;AAAA,EAChB;AAAA,EAEA,YAAY,OAAM;AAChB,QAAI,YAAY,SAAS,MAAM;AAC/B,QAAG,KAAK,UAAU;AAAG,WAAK,IAAI,aAAa,SAAS,KAAK;AACzD,SAAK,iBAAiB;AACtB,iBAAa,KAAK,cAAc;AAChC,QAAG,CAAC,KAAK,iBAAiB,cAAc,KAAK;AAC3C,WAAK,eAAe,gBAAgB;AAAA,IACtC;AACA,SAAK,qBAAqB,MAAM,QAAQ,CAAC,CAAC,EAAE,cAAc,SAAS,KAAK,CAAC;AAAA,EAC3E;AAAA,EAKA,YAAY,OAAM;AAChB,QAAG,KAAK,UAAU;AAAG,WAAK,IAAI,aAAa,KAAK;AAChD,QAAI,kBAAkB,KAAK;AAC3B,QAAI,oBAAoB,KAAK;AAC7B,SAAK,qBAAqB,MAAM,QAAQ,CAAC,CAAC,EAAE,cAAc;AACxD,eAAS,OAAO,iBAAiB,iBAAiB;AAAA,IACpD,CAAC;AACD,QAAG,oBAAoB,KAAK,aAAa,oBAAoB,GAAE;AAC7D,WAAK,iBAAiB;AAAA,IACxB;AAAA,EACF;AAAA,EAKA,mBAAkB;AAChB,SAAK,SAAS,QAAQ,aAAW;AAC/B,UAAG,CAAE,SAAQ,UAAU,KAAK,QAAQ,UAAU,KAAK,QAAQ,SAAS,IAAG;AACrE,gBAAQ,QAAQ,eAAe,KAAK;AAAA,MACtC;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAKA,kBAAiB;AACf,YAAO,KAAK,QAAQ,KAAK,KAAK;AAAA,WACvB,cAAc;AAAY,eAAO;AAAA,WACjC,cAAc;AAAM,eAAO;AAAA,WAC3B,cAAc;AAAS,eAAO;AAAA;AAC1B,eAAO;AAAA;AAAA,EAEpB;AAAA,EAKA,cAAa;AAAE,WAAO,KAAK,gBAAgB,MAAM;AAAA,EAAO;AAAA,EAOxD,OAAO,SAAQ;AACb,SAAK,IAAI,QAAQ,eAAe;AAChC,SAAK,WAAW,KAAK,SAAS,OAAO,OAAK,EAAE,QAAQ,MAAM,QAAQ,QAAQ,CAAC;AAAA,EAC7E;AAAA,EAQA,IAAI,MAAK;AACP,aAAQ,OAAO,KAAK,sBAAqB;AACvC,WAAK,qBAAqB,OAAO,KAAK,qBAAqB,KAAK,OAAO,CAAC,CAAC,SAAS;AAChF,eAAO,KAAK,QAAQ,GAAG,MAAM;AAAA,MAC/B,CAAC;AAAA,IACH;AAAA,EACF;AAAA,EASA,QAAQ,OAAO,aAAa,CAAC,GAAE;AAC7B,QAAI,OAAO,IAAI,QAAQ,OAAO,YAAY,IAAI;AAC9C,SAAK,SAAS,KAAK,IAAI;AACvB,WAAO;AAAA,EACT;AAAA,EAKA,KAAK,MAAK;AACR,QAAG,KAAK,UAAU,GAAE;AAClB,UAAI,EAAC,OAAO,OAAO,SAAS,KAAK,aAAY;AAC7C,WAAK,IAAI,QAAQ,GAAG,SAAS,UAAU,aAAa,QAAQ,OAAO;AAAA,IACrE;AAEA,QAAG,KAAK,YAAY,GAAE;AACpB,WAAK,OAAO,MAAM,YAAU,KAAK,KAAK,KAAK,MAAM,CAAC;AAAA,IACpD,OAAO;AACL,WAAK,WAAW,KAAK,MAAM,KAAK,OAAO,MAAM,YAAU,KAAK,KAAK,KAAK,MAAM,CAAC,CAAC;AAAA,IAChF;AAAA,EACF;AAAA,EAMA,UAAS;AACP,QAAI,SAAS,KAAK,MAAM;AACxB,QAAG,WAAW,KAAK,KAAI;AAAE,WAAK,MAAM;AAAA,IAAE,OAAO;AAAE,WAAK,MAAM;AAAA,IAAO;AAEjE,WAAO,KAAK,IAAI,SAAS;AAAA,EAC3B;AAAA,EAEA,gBAAe;AACb,QAAG,KAAK,uBAAuB,CAAC,KAAK,YAAY,GAAE;AAAE;AAAA,IAAO;AAC5D,SAAK,sBAAsB,KAAK,QAAQ;AACxC,SAAK,KAAK,EAAC,OAAO,WAAW,OAAO,aAAa,SAAS,CAAC,GAAG,KAAK,KAAK,oBAAmB,CAAC;AAC5F,SAAK,iBAAiB,WAAW,MAAM,KAAK,iBAAiB,GAAG,KAAK,mBAAmB;AAAA,EAC1F;AAAA,EAEA,kBAAiB;AACf,QAAG,KAAK,YAAY,KAAK,KAAK,WAAW,SAAS,GAAE;AAClD,WAAK,WAAW,QAAQ,cAAY,SAAS,CAAC;AAC9C,WAAK,aAAa,CAAC;AAAA,IACrB;AAAA,EACF;AAAA,EAEA,cAAc,YAAW;AACvB,SAAK,OAAO,WAAW,MAAM,SAAO;AAClC,UAAI,EAAC,OAAO,OAAO,SAAS,KAAK,aAAY;AAC7C,UAAG,OAAO,QAAQ,KAAK,qBAAoB;AACzC,qBAAa,KAAK,cAAc;AAChC,aAAK,sBAAsB;AAC3B,mBAAW,MAAM,KAAK,cAAc,GAAG,KAAK,mBAAmB;AAAA,MACjE;AAEA,UAAG,KAAK,UAAU;AAAG,aAAK,IAAI,WAAW,GAAG,QAAQ,UAAU,MAAM,SAAS,SAAS,OAAO,MAAM,MAAM,OAAO,MAAM,OAAO;AAE7H,eAAQ,IAAI,GAAG,IAAI,KAAK,SAAS,QAAQ,KAAI;AAC3C,cAAM,UAAU,KAAK,SAAS;AAC9B,YAAG,CAAC,QAAQ,SAAS,OAAO,OAAO,SAAS,QAAQ,GAAE;AAAE;AAAA,QAAS;AACjE,gBAAQ,QAAQ,OAAO,SAAS,KAAK,QAAQ;AAAA,MAC/C;AAEA,eAAQ,IAAI,GAAG,IAAI,KAAK,qBAAqB,QAAQ,QAAQ,KAAI;AAC/D,YAAI,CAAC,EAAE,YAAY,KAAK,qBAAqB,QAAQ;AACrD,iBAAS,GAAG;AAAA,MACd;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,eAAe,OAAM;AACnB,QAAI,aAAa,KAAK,SAAS,KAAK,OAAK,EAAE,UAAU,SAAU,GAAE,SAAS,KAAK,EAAE,UAAU,EAAE;AAC7F,QAAG,YAAW;AACZ,UAAG,KAAK,UAAU;AAAG,aAAK,IAAI,aAAa,4BAA4B,QAAQ;AAC/E,iBAAW,MAAM;AAAA,IACnB;AAAA,EACF;AACF;", "names": [] }