From 40141571adfb546fb2732adb14d401db122e5821 Mon Sep 17 00:00:00 2001 From: Christian Sarnataro Date: Thu, 21 Apr 2022 11:47:35 +0200 Subject: [PATCH 1/5] Implemented connection/disconnection callbacks via messages in web serial daemon --- src/web-serial-daemon.js | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/web-serial-daemon.js b/src/web-serial-daemon.js index 90ceb6d..3c2ab04 100644 --- a/src/web-serial-daemon.js +++ b/src/web-serial-daemon.js @@ -46,32 +46,21 @@ export default class WebSerialDaemon extends Daemon { serial: message.ports, network: [] }); - // this.handleListMessage(message); } else if (message.supportedBoards) { this.supportedBoards.next(message.supportedBoards); } else if (message.connectedSerialPort) { - console.dir('******** BEGIN: web-serial-daemon:68 ********'); - console.dir(message.connectedSerialPort, { depth: null, colors: true }); - const port = this.uploader.getBoardInfoFromSerialPort(message.connectedSerialPort); this.connectedPorts.push(port); - console.dir(this.connectedPorts, { depth: null, colors: true }); - console.dir('******** END: web-serial-daemon:68 ********'); this.devicesList.next({ serial: this.connectedPorts, network: [] }); } else if (message.disconnectedSerialPort) { - console.dir('******** BEGIN: web-serial-daemon:79 ********'); - console.dir(message.disconnectedSerialPort, { depth: null, colors: true }); const port = this.uploader.getBoardInfoFromSerialPort(message.disconnectedSerialPort); this.connectedPorts = this.connectedPorts.filter(connectedPort => connectedPort.Name !== port.Name); - console.dir(this.connectedPorts, { depth: null, colors: true }); - console.dir('******** END: web-serial-daemon:79 ********'); - console.dir(this.connectedPorts, { depth: null, colors: true }); this.devicesList.next({ serial: this.connectedPorts, network: [] From 7b084f1c795711d298c172758bd4b2ab5abff00e Mon Sep 17 00:00:00 2001 From: Christian Sarnataro Date: Thu, 21 Apr 2022 14:53:44 +0200 Subject: [PATCH 2/5] Bumped version to 2.8.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2634fc6..ff99117 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "arduino-create-agent-js-client", - "version": "2.8.0", + "version": "2.8.1", "description": "JS module providing discovery of the Arduino Create Plugin and communication with it", "main": "lib/index.js", "module": "es/index.js", From 0c486b0db21f8d8022765d53f645f201f1b250f0 Mon Sep 17 00:00:00 2001 From: Christian Sarnataro Date: Thu, 21 Apr 2022 16:01:21 +0200 Subject: [PATCH 3/5] Temporarily adding bundles to be used from internal CI --- .gitignore | 6 +- dist/create-plugin.js | 15837 ++++++++++++++++++++++++++++++++++++ dist/create-plugin.js.map | 1 + dist/create-plugin.min.js | 1 + es/chrome-app-daemon.js | 375 + es/chrome-os-daemon.js | 64 + es/daemon.js | 310 + es/firmware-updater.js | 329 + es/index.js | 25 + es/signatures.js | 13 + es/socket-daemon.js | 787 ++ es/socket-daemon.v2.js | 80 + es/web-serial-daemon.js | 206 + lib/chrome-app-daemon.js | 368 + lib/chrome-os-daemon.js | 75 + lib/daemon.js | 300 + lib/firmware-updater.js | 341 + lib/index.js | 43 + lib/signatures.js | 21 + lib/socket-daemon.js | 784 ++ lib/socket-daemon.v2.js | 87 + lib/web-serial-daemon.js | 216 + 22 files changed, 20266 insertions(+), 3 deletions(-) create mode 100644 dist/create-plugin.js create mode 100644 dist/create-plugin.js.map create mode 100644 dist/create-plugin.min.js create mode 100644 es/chrome-app-daemon.js create mode 100644 es/chrome-os-daemon.js create mode 100644 es/daemon.js create mode 100644 es/firmware-updater.js create mode 100644 es/index.js create mode 100644 es/signatures.js create mode 100644 es/socket-daemon.js create mode 100644 es/socket-daemon.v2.js create mode 100644 es/web-serial-daemon.js create mode 100644 lib/chrome-app-daemon.js create mode 100644 lib/chrome-os-daemon.js create mode 100644 lib/daemon.js create mode 100644 lib/firmware-updater.js create mode 100644 lib/index.js create mode 100644 lib/signatures.js create mode 100644 lib/socket-daemon.js create mode 100644 lib/socket-daemon.v2.js create mode 100644 lib/web-serial-daemon.js diff --git a/.gitignore b/.gitignore index 22641d8..ce19272 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ node_modules -lib -dist -es +!lib +!dist +!es .tmp diff --git a/dist/create-plugin.js b/dist/create-plugin.js new file mode 100644 index 0000000..1bd3c3a --- /dev/null +++ b/dist/create-plugin.js @@ -0,0 +1,15837 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('tty'), require('util'), require('os'), require('fs'), require('url'), require('child_process'), require('http'), require('https'), require('events'), require('crypto'), require('net'), require('tls'), require('zlib'), require('bufferutil'), require('stream'), require('utf-8-validate')) : + typeof define === 'function' && define.amd ? define(['exports', 'tty', 'util', 'os', 'fs', 'url', 'child_process', 'http', 'https', 'events', 'crypto', 'net', 'tls', 'zlib', 'bufferutil', 'stream', 'utf-8-validate'], factory) : + (global = global || self, factory(global.CreatePlugin = {}, global.tty, global.util, global.os, global.fs, global.url$1, global.child_process, global.http, global.https, global.events, global.crypto, global.net, global.tls, global.zlib, global.bufferutil, global.stream, global.utf8Validate)); +}(this, (function (exports, tty, util, os, fs, url$1, child_process, http, https, events, crypto, net, tls, zlib, bufferutil, stream, utf8Validate) { 'use strict'; + + tty = tty && tty.hasOwnProperty('default') ? tty['default'] : tty; + util = util && util.hasOwnProperty('default') ? util['default'] : util; + os = os && os.hasOwnProperty('default') ? os['default'] : os; + fs = fs && fs.hasOwnProperty('default') ? fs['default'] : fs; + url$1 = url$1 && url$1.hasOwnProperty('default') ? url$1['default'] : url$1; + child_process = child_process && child_process.hasOwnProperty('default') ? child_process['default'] : child_process; + http = http && http.hasOwnProperty('default') ? http['default'] : http; + https = https && https.hasOwnProperty('default') ? https['default'] : https; + events = events && events.hasOwnProperty('default') ? events['default'] : events; + crypto = crypto && crypto.hasOwnProperty('default') ? crypto['default'] : crypto; + net = net && net.hasOwnProperty('default') ? net['default'] : net; + tls = tls && tls.hasOwnProperty('default') ? tls['default'] : tls; + zlib = zlib && zlib.hasOwnProperty('default') ? zlib['default'] : zlib; + bufferutil = bufferutil && bufferutil.hasOwnProperty('default') ? bufferutil['default'] : bufferutil; + stream = stream && stream.hasOwnProperty('default') ? stream['default'] : stream; + utf8Validate = utf8Validate && utf8Validate.hasOwnProperty('default') ? utf8Validate['default'] : utf8Validate; + + function ownKeys(object, enumerableOnly) { + var keys = Object.keys(object); + + if (Object.getOwnPropertySymbols) { + var symbols = Object.getOwnPropertySymbols(object); + enumerableOnly && (symbols = symbols.filter(function (sym) { + return Object.getOwnPropertyDescriptor(object, sym).enumerable; + })), keys.push.apply(keys, symbols); + } + + return keys; + } + + function _objectSpread2(target) { + for (var i = 1; i < arguments.length; i++) { + var source = null != arguments[i] ? arguments[i] : {}; + i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { + _defineProperty(target, key, source[key]); + }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { + Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); + }); + } + + return target; + } + + function _classCallCheck(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } + } + + function _defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); + } + } + + function _createClass(Constructor, protoProps, staticProps) { + if (protoProps) _defineProperties(Constructor.prototype, protoProps); + if (staticProps) _defineProperties(Constructor, staticProps); + Object.defineProperty(Constructor, "prototype", { + writable: false + }); + return Constructor; + } + + function _defineProperty(obj, key, value) { + if (key in obj) { + Object.defineProperty(obj, key, { + value: value, + enumerable: true, + configurable: true, + writable: true + }); + } else { + obj[key] = value; + } + + return obj; + } + + function _inherits(subClass, superClass) { + if (typeof superClass !== "function" && superClass !== null) { + throw new TypeError("Super expression must either be null or a function"); + } + + subClass.prototype = Object.create(superClass && superClass.prototype, { + constructor: { + value: subClass, + writable: true, + configurable: true + } + }); + Object.defineProperty(subClass, "prototype", { + writable: false + }); + if (superClass) _setPrototypeOf(subClass, superClass); + } + + function _getPrototypeOf(o) { + _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { + return o.__proto__ || Object.getPrototypeOf(o); + }; + return _getPrototypeOf(o); + } + + function _setPrototypeOf(o, p) { + _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { + o.__proto__ = p; + return o; + }; + + return _setPrototypeOf(o, p); + } + + function _isNativeReflectConstruct() { + if (typeof Reflect === "undefined" || !Reflect.construct) return false; + if (Reflect.construct.sham) return false; + if (typeof Proxy === "function") return true; + + try { + Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); + return true; + } catch (e) { + return false; + } + } + + function _assertThisInitialized(self) { + if (self === void 0) { + throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); + } + + return self; + } + + function _possibleConstructorReturn(self, call) { + if (call && (typeof call === "object" || typeof call === "function")) { + return call; + } else if (call !== void 0) { + throw new TypeError("Derived constructors may only return object or undefined"); + } + + return _assertThisInitialized(self); + } + + function _createSuper(Derived) { + var hasNativeReflectConstruct = _isNativeReflectConstruct(); + + return function _createSuperInternal() { + var Super = _getPrototypeOf(Derived), + result; + + if (hasNativeReflectConstruct) { + var NewTarget = _getPrototypeOf(this).constructor; + + result = Reflect.construct(Super, arguments, NewTarget); + } else { + result = Super.apply(this, arguments); + } + + return _possibleConstructorReturn(this, result); + }; + } + + function _slicedToArray(arr, i) { + return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); + } + + function _toConsumableArray(arr) { + return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); + } + + function _arrayWithoutHoles(arr) { + if (Array.isArray(arr)) return _arrayLikeToArray(arr); + } + + function _arrayWithHoles(arr) { + if (Array.isArray(arr)) return arr; + } + + function _iterableToArray(iter) { + if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); + } + + function _iterableToArrayLimit(arr, i) { + var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"]; + + if (_i == null) return; + var _arr = []; + var _n = true; + var _d = false; + + var _s, _e; + + try { + for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) { + _arr.push(_s.value); + + if (i && _arr.length === i) break; + } + } catch (err) { + _d = true; + _e = err; + } finally { + try { + if (!_n && _i["return"] != null) _i["return"](); + } finally { + if (_d) throw _e; + } + } + + return _arr; + } + + function _unsupportedIterableToArray(o, minLen) { + if (!o) return; + if (typeof o === "string") return _arrayLikeToArray(o, minLen); + var n = Object.prototype.toString.call(o).slice(8, -1); + if (n === "Object" && o.constructor) n = o.constructor.name; + if (n === "Map" || n === "Set") return Array.from(o); + if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); + } + + function _arrayLikeToArray(arr, len) { + if (len == null || len > arr.length) len = arr.length; + + for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; + + return arr2; + } + + function _nonIterableSpread() { + throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); + } + + function _nonIterableRest() { + throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); + } + + var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; + + function unwrapExports (x) { + return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x; + } + + function createCommonjsModule(fn, module) { + return module = { exports: {} }, fn(module, module.exports), module.exports; + } + + /** + * Parses an URI + * + * @author Steven Levithan (MIT license) + * @api private + */ + + var re = /^(?:(?![^:@]+:[^:@\/]*@)(http|https|ws|wss):\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?((?:[a-f0-9]{0,4}:){2,7}[a-f0-9]{0,4}|[^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/; + + var parts = [ + 'source', 'protocol', 'authority', 'userInfo', 'user', 'password', 'host', 'port', 'relative', 'path', 'directory', 'file', 'query', 'anchor' + ]; + + var parseuri = function parseuri(str) { + var src = str, + b = str.indexOf('['), + e = str.indexOf(']'); + + if (b != -1 && e != -1) { + str = str.substring(0, b) + str.substring(b, e).replace(/:/g, ';') + str.substring(e, str.length); + } + + var m = re.exec(str || ''), + uri = {}, + i = 14; + + while (i--) { + uri[parts[i]] = m[i] || ''; + } + + if (b != -1 && e != -1) { + uri.source = src; + uri.host = uri.host.substring(1, uri.host.length - 1).replace(/;/g, ':'); + uri.authority = uri.authority.replace('[', '').replace(']', '').replace(/;/g, ':'); + uri.ipv6uri = true; + } + + return uri; + }; + + /** + * Helpers. + */ + + var s = 1000; + var m = s * 60; + var h = m * 60; + var d = h * 24; + var w = d * 7; + var y = d * 365.25; + + /** + * Parse or format the given `val`. + * + * Options: + * + * - `long` verbose formatting [false] + * + * @param {String|Number} val + * @param {Object} [options] + * @throws {Error} throw an error if val is not a non-empty string or a number + * @return {String|Number} + * @api public + */ + + var ms = function (val, options) { + options = options || {}; + var type = typeof val; + if (type === 'string' && val.length > 0) { + return parse(val); + } else if (type === 'number' && isFinite(val)) { + return options.long ? fmtLong(val) : fmtShort(val); + } + throw new Error( + 'val is not a non-empty string or a valid number. val=' + + JSON.stringify(val) + ); + }; + + /** + * Parse the given `str` and return milliseconds. + * + * @param {String} str + * @return {Number} + * @api private + */ + + function parse(str) { + str = String(str); + if (str.length > 100) { + return; + } + var match = /^(-?(?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec( + str + ); + if (!match) { + return; + } + var n = parseFloat(match[1]); + var type = (match[2] || 'ms').toLowerCase(); + switch (type) { + case 'years': + case 'year': + case 'yrs': + case 'yr': + case 'y': + return n * y; + case 'weeks': + case 'week': + case 'w': + return n * w; + case 'days': + case 'day': + case 'd': + return n * d; + case 'hours': + case 'hour': + case 'hrs': + case 'hr': + case 'h': + return n * h; + case 'minutes': + case 'minute': + case 'mins': + case 'min': + case 'm': + return n * m; + case 'seconds': + case 'second': + case 'secs': + case 'sec': + case 's': + return n * s; + case 'milliseconds': + case 'millisecond': + case 'msecs': + case 'msec': + case 'ms': + return n; + default: + return undefined; + } + } + + /** + * Short format for `ms`. + * + * @param {Number} ms + * @return {String} + * @api private + */ + + function fmtShort(ms) { + var msAbs = Math.abs(ms); + if (msAbs >= d) { + return Math.round(ms / d) + 'd'; + } + if (msAbs >= h) { + return Math.round(ms / h) + 'h'; + } + if (msAbs >= m) { + return Math.round(ms / m) + 'm'; + } + if (msAbs >= s) { + return Math.round(ms / s) + 's'; + } + return ms + 'ms'; + } + + /** + * Long format for `ms`. + * + * @param {Number} ms + * @return {String} + * @api private + */ + + function fmtLong(ms) { + var msAbs = Math.abs(ms); + if (msAbs >= d) { + return plural(ms, msAbs, d, 'day'); + } + if (msAbs >= h) { + return plural(ms, msAbs, h, 'hour'); + } + if (msAbs >= m) { + return plural(ms, msAbs, m, 'minute'); + } + if (msAbs >= s) { + return plural(ms, msAbs, s, 'second'); + } + return ms + ' ms'; + } + + /** + * Pluralization helper. + */ + + function plural(ms, msAbs, n, name) { + var isPlural = msAbs >= n * 1.5; + return Math.round(ms / n) + ' ' + name + (isPlural ? 's' : ''); + } + + /** + * This is the common logic for both the Node.js and web browser + * implementations of `debug()`. + */ + + function setup(env) { + createDebug.debug = createDebug; + createDebug.default = createDebug; + createDebug.coerce = coerce; + createDebug.disable = disable; + createDebug.enable = enable; + createDebug.enabled = enabled; + createDebug.humanize = ms; + + Object.keys(env).forEach(key => { + createDebug[key] = env[key]; + }); + + /** + * Active `debug` instances. + */ + createDebug.instances = []; + + /** + * The currently active debug mode names, and names to skip. + */ + + createDebug.names = []; + createDebug.skips = []; + + /** + * Map of special "%n" handling functions, for the debug "format" argument. + * + * Valid key names are a single, lower or upper-case letter, i.e. "n" and "N". + */ + createDebug.formatters = {}; + + /** + * Selects a color for a debug namespace + * @param {String} namespace The namespace string for the for the debug instance to be colored + * @return {Number|String} An ANSI color code for the given namespace + * @api private + */ + function selectColor(namespace) { + let hash = 0; + + for (let i = 0; i < namespace.length; i++) { + hash = ((hash << 5) - hash) + namespace.charCodeAt(i); + hash |= 0; // Convert to 32bit integer + } + + return createDebug.colors[Math.abs(hash) % createDebug.colors.length]; + } + createDebug.selectColor = selectColor; + + /** + * Create a debugger with the given `namespace`. + * + * @param {String} namespace + * @return {Function} + * @api public + */ + function createDebug(namespace) { + let prevTime; + + function debug(...args) { + // Disabled? + if (!debug.enabled) { + return; + } + + const self = debug; + + // Set `diff` timestamp + const curr = Number(new Date()); + const ms = curr - (prevTime || curr); + self.diff = ms; + self.prev = prevTime; + self.curr = curr; + prevTime = curr; + + args[0] = createDebug.coerce(args[0]); + + if (typeof args[0] !== 'string') { + // Anything else let's inspect with %O + args.unshift('%O'); + } + + // Apply any `formatters` transformations + let index = 0; + args[0] = args[0].replace(/%([a-zA-Z%])/g, (match, format) => { + // If we encounter an escaped % then don't increase the array index + if (match === '%%') { + return match; + } + index++; + const formatter = createDebug.formatters[format]; + if (typeof formatter === 'function') { + const val = args[index]; + match = formatter.call(self, val); + + // Now we need to remove `args[index]` since it's inlined in the `format` + args.splice(index, 1); + index--; + } + return match; + }); + + // Apply env-specific formatting (colors, etc.) + createDebug.formatArgs.call(self, args); + + const logFn = self.log || createDebug.log; + logFn.apply(self, args); + } + + debug.namespace = namespace; + debug.enabled = createDebug.enabled(namespace); + debug.useColors = createDebug.useColors(); + debug.color = selectColor(namespace); + debug.destroy = destroy; + debug.extend = extend; + // Debug.formatArgs = formatArgs; + // debug.rawLog = rawLog; + + // env-specific initialization logic for debug instances + if (typeof createDebug.init === 'function') { + createDebug.init(debug); + } + + createDebug.instances.push(debug); + + return debug; + } + + function destroy() { + const index = createDebug.instances.indexOf(this); + if (index !== -1) { + createDebug.instances.splice(index, 1); + return true; + } + return false; + } + + function extend(namespace, delimiter) { + const newDebug = createDebug(this.namespace + (typeof delimiter === 'undefined' ? ':' : delimiter) + namespace); + newDebug.log = this.log; + return newDebug; + } + + /** + * Enables a debug mode by namespaces. This can include modes + * separated by a colon and wildcards. + * + * @param {String} namespaces + * @api public + */ + function enable(namespaces) { + createDebug.save(namespaces); + + createDebug.names = []; + createDebug.skips = []; + + let i; + const split = (typeof namespaces === 'string' ? namespaces : '').split(/[\s,]+/); + const len = split.length; + + for (i = 0; i < len; i++) { + if (!split[i]) { + // ignore empty strings + continue; + } + + namespaces = split[i].replace(/\*/g, '.*?'); + + if (namespaces[0] === '-') { + createDebug.skips.push(new RegExp('^' + namespaces.substr(1) + '$')); + } else { + createDebug.names.push(new RegExp('^' + namespaces + '$')); + } + } + + for (i = 0; i < createDebug.instances.length; i++) { + const instance = createDebug.instances[i]; + instance.enabled = createDebug.enabled(instance.namespace); + } + } + + /** + * Disable debug output. + * + * @return {String} namespaces + * @api public + */ + function disable() { + const namespaces = [ + ...createDebug.names.map(toNamespace), + ...createDebug.skips.map(toNamespace).map(namespace => '-' + namespace) + ].join(','); + createDebug.enable(''); + return namespaces; + } + + /** + * Returns true if the given mode name is enabled, false otherwise. + * + * @param {String} name + * @return {Boolean} + * @api public + */ + function enabled(name) { + if (name[name.length - 1] === '*') { + return true; + } + + let i; + let len; + + for (i = 0, len = createDebug.skips.length; i < len; i++) { + if (createDebug.skips[i].test(name)) { + return false; + } + } + + for (i = 0, len = createDebug.names.length; i < len; i++) { + if (createDebug.names[i].test(name)) { + return true; + } + } + + return false; + } + + /** + * Convert regexp to namespace + * + * @param {RegExp} regxep + * @return {String} namespace + * @api private + */ + function toNamespace(regexp) { + return regexp.toString() + .substring(2, regexp.toString().length - 2) + .replace(/\.\*\?$/, '*'); + } + + /** + * Coerce `val`. + * + * @param {Mixed} val + * @return {Mixed} + * @api private + */ + function coerce(val) { + if (val instanceof Error) { + return val.stack || val.message; + } + return val; + } + + createDebug.enable(createDebug.load()); + + return createDebug; + } + + var common = setup; + + var browser = createCommonjsModule(function (module, exports) { + /* eslint-env browser */ + + /** + * This is the web browser implementation of `debug()`. + */ + + exports.log = log; + exports.formatArgs = formatArgs; + exports.save = save; + exports.load = load; + exports.useColors = useColors; + exports.storage = localstorage(); + + /** + * Colors. + */ + + exports.colors = [ + '#0000CC', + '#0000FF', + '#0033CC', + '#0033FF', + '#0066CC', + '#0066FF', + '#0099CC', + '#0099FF', + '#00CC00', + '#00CC33', + '#00CC66', + '#00CC99', + '#00CCCC', + '#00CCFF', + '#3300CC', + '#3300FF', + '#3333CC', + '#3333FF', + '#3366CC', + '#3366FF', + '#3399CC', + '#3399FF', + '#33CC00', + '#33CC33', + '#33CC66', + '#33CC99', + '#33CCCC', + '#33CCFF', + '#6600CC', + '#6600FF', + '#6633CC', + '#6633FF', + '#66CC00', + '#66CC33', + '#9900CC', + '#9900FF', + '#9933CC', + '#9933FF', + '#99CC00', + '#99CC33', + '#CC0000', + '#CC0033', + '#CC0066', + '#CC0099', + '#CC00CC', + '#CC00FF', + '#CC3300', + '#CC3333', + '#CC3366', + '#CC3399', + '#CC33CC', + '#CC33FF', + '#CC6600', + '#CC6633', + '#CC9900', + '#CC9933', + '#CCCC00', + '#CCCC33', + '#FF0000', + '#FF0033', + '#FF0066', + '#FF0099', + '#FF00CC', + '#FF00FF', + '#FF3300', + '#FF3333', + '#FF3366', + '#FF3399', + '#FF33CC', + '#FF33FF', + '#FF6600', + '#FF6633', + '#FF9900', + '#FF9933', + '#FFCC00', + '#FFCC33' + ]; + + /** + * Currently only WebKit-based Web Inspectors, Firefox >= v31, + * and the Firebug extension (any Firefox version) are known + * to support "%c" CSS customizations. + * + * TODO: add a `localStorage` variable to explicitly enable/disable colors + */ + + // eslint-disable-next-line complexity + function useColors() { + // NB: In an Electron preload script, document will be defined but not fully + // initialized. Since we know we're in Chrome, we'll just detect this case + // explicitly + if (typeof window !== 'undefined' && window.process && (window.process.type === 'renderer' || window.process.__nwjs)) { + return true; + } + + // Internet Explorer and Edge do not support colors. + if (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/(edge|trident)\/(\d+)/)) { + return false; + } + + // Is webkit? http://stackoverflow.com/a/16459606/376773 + // document is undefined in react-native: https://github.com/facebook/react-native/pull/1632 + return (typeof document !== 'undefined' && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance) || + // Is firebug? http://stackoverflow.com/a/398120/376773 + (typeof window !== 'undefined' && window.console && (window.console.firebug || (window.console.exception && window.console.table))) || + // Is firefox >= v31? + // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages + (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31) || + // Double check webkit in userAgent just in case we are in a worker + (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/)); + } + + /** + * Colorize log arguments if enabled. + * + * @api public + */ + + function formatArgs(args) { + args[0] = (this.useColors ? '%c' : '') + + this.namespace + + (this.useColors ? ' %c' : ' ') + + args[0] + + (this.useColors ? '%c ' : ' ') + + '+' + module.exports.humanize(this.diff); + + if (!this.useColors) { + return; + } + + const c = 'color: ' + this.color; + args.splice(1, 0, c, 'color: inherit'); + + // The final "%c" is somewhat tricky, because there could be other + // arguments passed either before or after the %c, so we need to + // figure out the correct index to insert the CSS into + let index = 0; + let lastC = 0; + args[0].replace(/%[a-zA-Z%]/g, match => { + if (match === '%%') { + return; + } + index++; + if (match === '%c') { + // We only are interested in the *last* %c + // (the user may have provided their own) + lastC = index; + } + }); + + args.splice(lastC, 0, c); + } + + /** + * Invokes `console.log()` when available. + * No-op when `console.log` is not a "function". + * + * @api public + */ + function log(...args) { + // This hackery is required for IE8/9, where + // the `console.log` function doesn't have 'apply' + return typeof console === 'object' && + console.log && + console.log(...args); + } + + /** + * Save `namespaces`. + * + * @param {String} namespaces + * @api private + */ + function save(namespaces) { + try { + if (namespaces) { + exports.storage.setItem('debug', namespaces); + } else { + exports.storage.removeItem('debug'); + } + } catch (error) { + // Swallow + // XXX (@Qix-) should we be logging these? + } + } + + /** + * Load `namespaces`. + * + * @return {String} returns the previously persisted debug modes + * @api private + */ + function load() { + let r; + try { + r = exports.storage.getItem('debug'); + } catch (error) { + // Swallow + // XXX (@Qix-) should we be logging these? + } + + // If debug isn't set in LS, and we're in Electron, try to load $DEBUG + if (!r && typeof process !== 'undefined' && 'env' in process) { + r = process.env.DEBUG; + } + + return r; + } + + /** + * Localstorage attempts to return the localstorage. + * + * This is necessary because safari throws + * when a user disables cookies/localstorage + * and you attempt to access it. + * + * @return {LocalStorage} + * @api private + */ + + function localstorage() { + try { + // TVMLKit (Apple TV JS Runtime) does not have a window object, just localStorage in the global context + // The Browser also has localStorage in the global context. + return localStorage; + } catch (error) { + // Swallow + // XXX (@Qix-) should we be logging these? + } + } + + module.exports = common(exports); + + const {formatters} = module.exports; + + /** + * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default. + */ + + formatters.j = function (v) { + try { + return JSON.stringify(v); + } catch (error) { + return '[UnexpectedJSONParseError]: ' + error.message; + } + }; + }); + var browser_1 = browser.log; + var browser_2 = browser.formatArgs; + var browser_3 = browser.save; + var browser_4 = browser.load; + var browser_5 = browser.useColors; + var browser_6 = browser.storage; + var browser_7 = browser.colors; + + var hasFlag = (flag, argv) => { + argv = argv || process.argv; + const prefix = flag.startsWith('-') ? '' : (flag.length === 1 ? '-' : '--'); + const pos = argv.indexOf(prefix + flag); + const terminatorPos = argv.indexOf('--'); + return pos !== -1 && (terminatorPos === -1 ? true : pos < terminatorPos); + }; + + const env = process.env; + + let forceColor; + if (hasFlag('no-color') || + hasFlag('no-colors') || + hasFlag('color=false')) { + forceColor = false; + } else if (hasFlag('color') || + hasFlag('colors') || + hasFlag('color=true') || + hasFlag('color=always')) { + forceColor = true; + } + if ('FORCE_COLOR' in env) { + forceColor = env.FORCE_COLOR.length === 0 || parseInt(env.FORCE_COLOR, 10) !== 0; + } + + function translateLevel(level) { + if (level === 0) { + return false; + } + + return { + level, + hasBasic: true, + has256: level >= 2, + has16m: level >= 3 + }; + } + + function supportsColor(stream) { + if (forceColor === false) { + return 0; + } + + if (hasFlag('color=16m') || + hasFlag('color=full') || + hasFlag('color=truecolor')) { + return 3; + } + + if (hasFlag('color=256')) { + return 2; + } + + if (stream && !stream.isTTY && forceColor !== true) { + return 0; + } + + const min = forceColor ? 1 : 0; + + if (process.platform === 'win32') { + // Node.js 7.5.0 is the first version of Node.js to include a patch to + // libuv that enables 256 color output on Windows. Anything earlier and it + // won't work. However, here we target Node.js 8 at minimum as it is an LTS + // release, and Node.js 7 is not. Windows 10 build 10586 is the first Windows + // release that supports 256 colors. Windows 10 build 14931 is the first release + // that supports 16m/TrueColor. + const osRelease = os.release().split('.'); + if ( + Number(process.versions.node.split('.')[0]) >= 8 && + Number(osRelease[0]) >= 10 && + Number(osRelease[2]) >= 10586 + ) { + return Number(osRelease[2]) >= 14931 ? 3 : 2; + } + + return 1; + } + + if ('CI' in env) { + if (['TRAVIS', 'CIRCLECI', 'APPVEYOR', 'GITLAB_CI'].some(sign => sign in env) || env.CI_NAME === 'codeship') { + return 1; + } + + return min; + } + + if ('TEAMCITY_VERSION' in env) { + return /^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(env.TEAMCITY_VERSION) ? 1 : 0; + } + + if (env.COLORTERM === 'truecolor') { + return 3; + } + + if ('TERM_PROGRAM' in env) { + const version = parseInt((env.TERM_PROGRAM_VERSION || '').split('.')[0], 10); + + switch (env.TERM_PROGRAM) { + case 'iTerm.app': + return version >= 3 ? 3 : 2; + case 'Apple_Terminal': + return 2; + // No default + } + } + + if (/-256(color)?$/i.test(env.TERM)) { + return 2; + } + + if (/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(env.TERM)) { + return 1; + } + + if ('COLORTERM' in env) { + return 1; + } + + if (env.TERM === 'dumb') { + return min; + } + + return min; + } + + function getSupportLevel(stream) { + const level = supportsColor(stream); + return translateLevel(level); + } + + var supportsColor_1 = { + supportsColor: getSupportLevel, + stdout: getSupportLevel(process.stdout), + stderr: getSupportLevel(process.stderr) + }; + + var node = createCommonjsModule(function (module, exports) { + /** + * Module dependencies. + */ + + + + + /** + * This is the Node.js implementation of `debug()`. + */ + + exports.init = init; + exports.log = log; + exports.formatArgs = formatArgs; + exports.save = save; + exports.load = load; + exports.useColors = useColors; + + /** + * Colors. + */ + + exports.colors = [6, 2, 3, 4, 5, 1]; + + try { + // Optional dependency (as in, doesn't need to be installed, NOT like optionalDependencies in package.json) + // eslint-disable-next-line import/no-extraneous-dependencies + const supportsColor = supportsColor_1; + + if (supportsColor && (supportsColor.stderr || supportsColor).level >= 2) { + exports.colors = [ + 20, + 21, + 26, + 27, + 32, + 33, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 56, + 57, + 62, + 63, + 68, + 69, + 74, + 75, + 76, + 77, + 78, + 79, + 80, + 81, + 92, + 93, + 98, + 99, + 112, + 113, + 128, + 129, + 134, + 135, + 148, + 149, + 160, + 161, + 162, + 163, + 164, + 165, + 166, + 167, + 168, + 169, + 170, + 171, + 172, + 173, + 178, + 179, + 184, + 185, + 196, + 197, + 198, + 199, + 200, + 201, + 202, + 203, + 204, + 205, + 206, + 207, + 208, + 209, + 214, + 215, + 220, + 221 + ]; + } + } catch (error) { + // Swallow - we only care if `supports-color` is available; it doesn't have to be. + } + + /** + * Build up the default `inspectOpts` object from the environment variables. + * + * $ DEBUG_COLORS=no DEBUG_DEPTH=10 DEBUG_SHOW_HIDDEN=enabled node script.js + */ + + exports.inspectOpts = Object.keys(process.env).filter(key => { + return /^debug_/i.test(key); + }).reduce((obj, key) => { + // Camel-case + const prop = key + .substring(6) + .toLowerCase() + .replace(/_([a-z])/g, (_, k) => { + return k.toUpperCase(); + }); + + // Coerce string value into JS value + let val = process.env[key]; + if (/^(yes|on|true|enabled)$/i.test(val)) { + val = true; + } else if (/^(no|off|false|disabled)$/i.test(val)) { + val = false; + } else if (val === 'null') { + val = null; + } else { + val = Number(val); + } + + obj[prop] = val; + return obj; + }, {}); + + /** + * Is stdout a TTY? Colored output is enabled when `true`. + */ + + function useColors() { + return 'colors' in exports.inspectOpts ? + Boolean(exports.inspectOpts.colors) : + tty.isatty(process.stderr.fd); + } + + /** + * Adds ANSI color escape codes if enabled. + * + * @api public + */ + + function formatArgs(args) { + const {namespace: name, useColors} = this; + + if (useColors) { + const c = this.color; + const colorCode = '\u001B[3' + (c < 8 ? c : '8;5;' + c); + const prefix = ` ${colorCode};1m${name} \u001B[0m`; + + args[0] = prefix + args[0].split('\n').join('\n' + prefix); + args.push(colorCode + 'm+' + module.exports.humanize(this.diff) + '\u001B[0m'); + } else { + args[0] = getDate() + name + ' ' + args[0]; + } + } + + function getDate() { + if (exports.inspectOpts.hideDate) { + return ''; + } + return new Date().toISOString() + ' '; + } + + /** + * Invokes `util.format()` with the specified arguments and writes to stderr. + */ + + function log(...args) { + return process.stderr.write(util.format(...args) + '\n'); + } + + /** + * Save `namespaces`. + * + * @param {String} namespaces + * @api private + */ + function save(namespaces) { + if (namespaces) { + process.env.DEBUG = namespaces; + } else { + // If you set a process.env field to null or undefined, it gets cast to the + // string 'null' or 'undefined'. Just delete instead. + delete process.env.DEBUG; + } + } + + /** + * Load `namespaces`. + * + * @return {String} returns the previously persisted debug modes + * @api private + */ + + function load() { + return process.env.DEBUG; + } + + /** + * Init logic for `debug` instances. + * + * Create a new `inspectOpts` object in case `useColors` is set + * differently for a particular `debug` instance. + */ + + function init(debug) { + debug.inspectOpts = {}; + + const keys = Object.keys(exports.inspectOpts); + for (let i = 0; i < keys.length; i++) { + debug.inspectOpts[keys[i]] = exports.inspectOpts[keys[i]]; + } + } + + module.exports = common(exports); + + const {formatters} = module.exports; + + /** + * Map %o to `util.inspect()`, all on a single line. + */ + + formatters.o = function (v) { + this.inspectOpts.colors = this.useColors; + return util.inspect(v, this.inspectOpts) + .replace(/\s*\n\s*/g, ' '); + }; + + /** + * Map %O to `util.inspect()`, allowing multiple lines if needed. + */ + + formatters.O = function (v) { + this.inspectOpts.colors = this.useColors; + return util.inspect(v, this.inspectOpts); + }; + }); + var node_1 = node.init; + var node_2 = node.log; + var node_3 = node.formatArgs; + var node_4 = node.save; + var node_5 = node.load; + var node_6 = node.useColors; + var node_7 = node.colors; + var node_8 = node.inspectOpts; + + var src = createCommonjsModule(function (module) { + /** + * Detect Electron renderer / nwjs process, which is node, but we should + * treat as a browser. + */ + + if (typeof process === 'undefined' || process.type === 'renderer' || process.browser === true || process.__nwjs) { + module.exports = browser; + } else { + module.exports = node; + } + }); + + /** + * Module dependencies. + */ + + + var debug = src('socket.io-client:url'); + + /** + * Module exports. + */ + + var url_1 = url; + + /** + * URL parser. + * + * @param {String} url + * @param {Object} An object meant to mimic window.location. + * Defaults to window.location. + * @api public + */ + + function url (uri, loc) { + var obj = uri; + + // default to window.location + loc = loc || (typeof location !== 'undefined' && location); + if (null == uri) uri = loc.protocol + '//' + loc.host; + + // relative path support + if ('string' === typeof uri) { + if ('/' === uri.charAt(0)) { + if ('/' === uri.charAt(1)) { + uri = loc.protocol + uri; + } else { + uri = loc.host + uri; + } + } + + if (!/^(https?|wss?):\/\//.test(uri)) { + debug('protocol-less url %s', uri); + if ('undefined' !== typeof loc) { + uri = loc.protocol + '//' + uri; + } else { + uri = 'https://' + uri; + } + } + + // parse + debug('parse %s', uri); + obj = parseuri(uri); + } + + // make sure we treat `localhost:80` and `localhost` equally + if (!obj.port) { + if (/^(http|ws)$/.test(obj.protocol)) { + obj.port = '80'; + } else if (/^(http|ws)s$/.test(obj.protocol)) { + obj.port = '443'; + } + } + + obj.path = obj.path || '/'; + + var ipv6 = obj.host.indexOf(':') !== -1; + var host = ipv6 ? '[' + obj.host + ']' : obj.host; + + // define unique id + obj.id = obj.protocol + '://' + host + ':' + obj.port; + // define href + obj.href = obj.protocol + '://' + host + (loc && loc.port === obj.port ? '' : (':' + obj.port)); + + return obj; + } + + /** + * Helpers. + */ + + var s$1 = 1000; + var m$1 = s$1 * 60; + var h$1 = m$1 * 60; + var d$1 = h$1 * 24; + var y$1 = d$1 * 365.25; + + /** + * Parse or format the given `val`. + * + * Options: + * + * - `long` verbose formatting [false] + * + * @param {String|Number} val + * @param {Object} [options] + * @throws {Error} throw an error if val is not a non-empty string or a number + * @return {String|Number} + * @api public + */ + + var ms$1 = function(val, options) { + options = options || {}; + var type = typeof val; + if (type === 'string' && val.length > 0) { + return parse$1(val); + } else if (type === 'number' && isNaN(val) === false) { + return options.long ? fmtLong$1(val) : fmtShort$1(val); + } + throw new Error( + 'val is not a non-empty string or a valid number. val=' + + JSON.stringify(val) + ); + }; + + /** + * Parse the given `str` and return milliseconds. + * + * @param {String} str + * @return {Number} + * @api private + */ + + function parse$1(str) { + str = String(str); + if (str.length > 100) { + return; + } + var match = /^((?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|years?|yrs?|y)?$/i.exec( + str + ); + if (!match) { + return; + } + var n = parseFloat(match[1]); + var type = (match[2] || 'ms').toLowerCase(); + switch (type) { + case 'years': + case 'year': + case 'yrs': + case 'yr': + case 'y': + return n * y$1; + case 'days': + case 'day': + case 'd': + return n * d$1; + case 'hours': + case 'hour': + case 'hrs': + case 'hr': + case 'h': + return n * h$1; + case 'minutes': + case 'minute': + case 'mins': + case 'min': + case 'm': + return n * m$1; + case 'seconds': + case 'second': + case 'secs': + case 'sec': + case 's': + return n * s$1; + case 'milliseconds': + case 'millisecond': + case 'msecs': + case 'msec': + case 'ms': + return n; + default: + return undefined; + } + } + + /** + * Short format for `ms`. + * + * @param {Number} ms + * @return {String} + * @api private + */ + + function fmtShort$1(ms) { + if (ms >= d$1) { + return Math.round(ms / d$1) + 'd'; + } + if (ms >= h$1) { + return Math.round(ms / h$1) + 'h'; + } + if (ms >= m$1) { + return Math.round(ms / m$1) + 'm'; + } + if (ms >= s$1) { + return Math.round(ms / s$1) + 's'; + } + return ms + 'ms'; + } + + /** + * Long format for `ms`. + * + * @param {Number} ms + * @return {String} + * @api private + */ + + function fmtLong$1(ms) { + return plural$1(ms, d$1, 'day') || + plural$1(ms, h$1, 'hour') || + plural$1(ms, m$1, 'minute') || + plural$1(ms, s$1, 'second') || + ms + ' ms'; + } + + /** + * Pluralization helper. + */ + + function plural$1(ms, n, name) { + if (ms < n) { + return; + } + if (ms < n * 1.5) { + return Math.floor(ms / n) + ' ' + name; + } + return Math.ceil(ms / n) + ' ' + name + 's'; + } + + var debug$1 = createCommonjsModule(function (module, exports) { + /** + * This is the common logic for both the Node.js and web browser + * implementations of `debug()`. + * + * Expose `debug()` as the module. + */ + + exports = module.exports = createDebug.debug = createDebug['default'] = createDebug; + exports.coerce = coerce; + exports.disable = disable; + exports.enable = enable; + exports.enabled = enabled; + exports.humanize = ms$1; + + /** + * Active `debug` instances. + */ + exports.instances = []; + + /** + * The currently active debug mode names, and names to skip. + */ + + exports.names = []; + exports.skips = []; + + /** + * Map of special "%n" handling functions, for the debug "format" argument. + * + * Valid key names are a single, lower or upper-case letter, i.e. "n" and "N". + */ + + exports.formatters = {}; + + /** + * Select a color. + * @param {String} namespace + * @return {Number} + * @api private + */ + + function selectColor(namespace) { + var hash = 0, i; + + for (i in namespace) { + hash = ((hash << 5) - hash) + namespace.charCodeAt(i); + hash |= 0; // Convert to 32bit integer + } + + return exports.colors[Math.abs(hash) % exports.colors.length]; + } + + /** + * Create a debugger with the given `namespace`. + * + * @param {String} namespace + * @return {Function} + * @api public + */ + + function createDebug(namespace) { + + var prevTime; + + function debug() { + // disabled? + if (!debug.enabled) return; + + var self = debug; + + // set `diff` timestamp + var curr = +new Date(); + var ms = curr - (prevTime || curr); + self.diff = ms; + self.prev = prevTime; + self.curr = curr; + prevTime = curr; + + // turn the `arguments` into a proper Array + var args = new Array(arguments.length); + for (var i = 0; i < args.length; i++) { + args[i] = arguments[i]; + } + + args[0] = exports.coerce(args[0]); + + if ('string' !== typeof args[0]) { + // anything else let's inspect with %O + args.unshift('%O'); + } + + // apply any `formatters` transformations + var index = 0; + args[0] = args[0].replace(/%([a-zA-Z%])/g, function(match, format) { + // if we encounter an escaped % then don't increase the array index + if (match === '%%') return match; + index++; + var formatter = exports.formatters[format]; + if ('function' === typeof formatter) { + var val = args[index]; + match = formatter.call(self, val); + + // now we need to remove `args[index]` since it's inlined in the `format` + args.splice(index, 1); + index--; + } + return match; + }); + + // apply env-specific formatting (colors, etc.) + exports.formatArgs.call(self, args); + + var logFn = debug.log || exports.log || console.log.bind(console); + logFn.apply(self, args); + } + + debug.namespace = namespace; + debug.enabled = exports.enabled(namespace); + debug.useColors = exports.useColors(); + debug.color = selectColor(namespace); + debug.destroy = destroy; + + // env-specific initialization logic for debug instances + if ('function' === typeof exports.init) { + exports.init(debug); + } + + exports.instances.push(debug); + + return debug; + } + + function destroy () { + var index = exports.instances.indexOf(this); + if (index !== -1) { + exports.instances.splice(index, 1); + return true; + } else { + return false; + } + } + + /** + * Enables a debug mode by namespaces. This can include modes + * separated by a colon and wildcards. + * + * @param {String} namespaces + * @api public + */ + + function enable(namespaces) { + exports.save(namespaces); + + exports.names = []; + exports.skips = []; + + var i; + var split = (typeof namespaces === 'string' ? namespaces : '').split(/[\s,]+/); + var len = split.length; + + for (i = 0; i < len; i++) { + if (!split[i]) continue; // ignore empty strings + namespaces = split[i].replace(/\*/g, '.*?'); + if (namespaces[0] === '-') { + exports.skips.push(new RegExp('^' + namespaces.substr(1) + '$')); + } else { + exports.names.push(new RegExp('^' + namespaces + '$')); + } + } + + for (i = 0; i < exports.instances.length; i++) { + var instance = exports.instances[i]; + instance.enabled = exports.enabled(instance.namespace); + } + } + + /** + * Disable debug output. + * + * @api public + */ + + function disable() { + exports.enable(''); + } + + /** + * Returns true if the given mode name is enabled, false otherwise. + * + * @param {String} name + * @return {Boolean} + * @api public + */ + + function enabled(name) { + if (name[name.length - 1] === '*') { + return true; + } + var i, len; + for (i = 0, len = exports.skips.length; i < len; i++) { + if (exports.skips[i].test(name)) { + return false; + } + } + for (i = 0, len = exports.names.length; i < len; i++) { + if (exports.names[i].test(name)) { + return true; + } + } + return false; + } + + /** + * Coerce `val`. + * + * @param {Mixed} val + * @return {Mixed} + * @api private + */ + + function coerce(val) { + if (val instanceof Error) return val.stack || val.message; + return val; + } + }); + var debug_1 = debug$1.coerce; + var debug_2 = debug$1.disable; + var debug_3 = debug$1.enable; + var debug_4 = debug$1.enabled; + var debug_5 = debug$1.humanize; + var debug_6 = debug$1.instances; + var debug_7 = debug$1.names; + var debug_8 = debug$1.skips; + var debug_9 = debug$1.formatters; + + var browser$1 = createCommonjsModule(function (module, exports) { + /** + * This is the web browser implementation of `debug()`. + * + * Expose `debug()` as the module. + */ + + exports = module.exports = debug$1; + exports.log = log; + exports.formatArgs = formatArgs; + exports.save = save; + exports.load = load; + exports.useColors = useColors; + exports.storage = 'undefined' != typeof chrome + && 'undefined' != typeof chrome.storage + ? chrome.storage.local + : localstorage(); + + /** + * Colors. + */ + + exports.colors = [ + '#0000CC', '#0000FF', '#0033CC', '#0033FF', '#0066CC', '#0066FF', '#0099CC', + '#0099FF', '#00CC00', '#00CC33', '#00CC66', '#00CC99', '#00CCCC', '#00CCFF', + '#3300CC', '#3300FF', '#3333CC', '#3333FF', '#3366CC', '#3366FF', '#3399CC', + '#3399FF', '#33CC00', '#33CC33', '#33CC66', '#33CC99', '#33CCCC', '#33CCFF', + '#6600CC', '#6600FF', '#6633CC', '#6633FF', '#66CC00', '#66CC33', '#9900CC', + '#9900FF', '#9933CC', '#9933FF', '#99CC00', '#99CC33', '#CC0000', '#CC0033', + '#CC0066', '#CC0099', '#CC00CC', '#CC00FF', '#CC3300', '#CC3333', '#CC3366', + '#CC3399', '#CC33CC', '#CC33FF', '#CC6600', '#CC6633', '#CC9900', '#CC9933', + '#CCCC00', '#CCCC33', '#FF0000', '#FF0033', '#FF0066', '#FF0099', '#FF00CC', + '#FF00FF', '#FF3300', '#FF3333', '#FF3366', '#FF3399', '#FF33CC', '#FF33FF', + '#FF6600', '#FF6633', '#FF9900', '#FF9933', '#FFCC00', '#FFCC33' + ]; + + /** + * Currently only WebKit-based Web Inspectors, Firefox >= v31, + * and the Firebug extension (any Firefox version) are known + * to support "%c" CSS customizations. + * + * TODO: add a `localStorage` variable to explicitly enable/disable colors + */ + + function useColors() { + // NB: In an Electron preload script, document will be defined but not fully + // initialized. Since we know we're in Chrome, we'll just detect this case + // explicitly + if (typeof window !== 'undefined' && window.process && window.process.type === 'renderer') { + return true; + } + + // Internet Explorer and Edge do not support colors. + if (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/(edge|trident)\/(\d+)/)) { + return false; + } + + // is webkit? http://stackoverflow.com/a/16459606/376773 + // document is undefined in react-native: https://github.com/facebook/react-native/pull/1632 + return (typeof document !== 'undefined' && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance) || + // is firebug? http://stackoverflow.com/a/398120/376773 + (typeof window !== 'undefined' && window.console && (window.console.firebug || (window.console.exception && window.console.table))) || + // is firefox >= v31? + // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages + (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31) || + // double check webkit in userAgent just in case we are in a worker + (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/)); + } + + /** + * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default. + */ + + exports.formatters.j = function(v) { + try { + return JSON.stringify(v); + } catch (err) { + return '[UnexpectedJSONParseError]: ' + err.message; + } + }; + + + /** + * Colorize log arguments if enabled. + * + * @api public + */ + + function formatArgs(args) { + var useColors = this.useColors; + + args[0] = (useColors ? '%c' : '') + + this.namespace + + (useColors ? ' %c' : ' ') + + args[0] + + (useColors ? '%c ' : ' ') + + '+' + exports.humanize(this.diff); + + if (!useColors) return; + + var c = 'color: ' + this.color; + args.splice(1, 0, c, 'color: inherit'); + + // the final "%c" is somewhat tricky, because there could be other + // arguments passed either before or after the %c, so we need to + // figure out the correct index to insert the CSS into + var index = 0; + var lastC = 0; + args[0].replace(/%[a-zA-Z%]/g, function(match) { + if ('%%' === match) return; + index++; + if ('%c' === match) { + // we only are interested in the *last* %c + // (the user may have provided their own) + lastC = index; + } + }); + + args.splice(lastC, 0, c); + } + + /** + * Invokes `console.log()` when available. + * No-op when `console.log` is not a "function". + * + * @api public + */ + + function log() { + // this hackery is required for IE8/9, where + // the `console.log` function doesn't have 'apply' + return 'object' === typeof console + && console.log + && Function.prototype.apply.call(console.log, console, arguments); + } + + /** + * Save `namespaces`. + * + * @param {String} namespaces + * @api private + */ + + function save(namespaces) { + try { + if (null == namespaces) { + exports.storage.removeItem('debug'); + } else { + exports.storage.debug = namespaces; + } + } catch(e) {} + } + + /** + * Load `namespaces`. + * + * @return {String} returns the previously persisted debug modes + * @api private + */ + + function load() { + var r; + try { + r = exports.storage.debug; + } catch(e) {} + + // If debug isn't set in LS, and we're in Electron, try to load $DEBUG + if (!r && typeof process !== 'undefined' && 'env' in process) { + r = process.env.DEBUG; + } + + return r; + } + + /** + * Enable namespaces listed in `localStorage.debug` initially. + */ + + exports.enable(load()); + + /** + * Localstorage attempts to return the localstorage. + * + * This is necessary because safari throws + * when a user disables cookies/localstorage + * and you attempt to access it. + * + * @return {LocalStorage} + * @api private + */ + + function localstorage() { + try { + return window.localStorage; + } catch (e) {} + } + }); + var browser_1$1 = browser$1.log; + var browser_2$1 = browser$1.formatArgs; + var browser_3$1 = browser$1.save; + var browser_4$1 = browser$1.load; + var browser_5$1 = browser$1.useColors; + var browser_6$1 = browser$1.storage; + var browser_7$1 = browser$1.colors; + + var node$1 = createCommonjsModule(function (module, exports) { + /** + * Module dependencies. + */ + + + + + /** + * This is the Node.js implementation of `debug()`. + * + * Expose `debug()` as the module. + */ + + exports = module.exports = debug$1; + exports.init = init; + exports.log = log; + exports.formatArgs = formatArgs; + exports.save = save; + exports.load = load; + exports.useColors = useColors; + + /** + * Colors. + */ + + exports.colors = [ 6, 2, 3, 4, 5, 1 ]; + + try { + var supportsColor = supportsColor_1; + if (supportsColor && supportsColor.level >= 2) { + exports.colors = [ + 20, 21, 26, 27, 32, 33, 38, 39, 40, 41, 42, 43, 44, 45, 56, 57, 62, 63, 68, + 69, 74, 75, 76, 77, 78, 79, 80, 81, 92, 93, 98, 99, 112, 113, 128, 129, 134, + 135, 148, 149, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, + 172, 173, 178, 179, 184, 185, 196, 197, 198, 199, 200, 201, 202, 203, 204, + 205, 206, 207, 208, 209, 214, 215, 220, 221 + ]; + } + } catch (err) { + // swallow - we only care if `supports-color` is available; it doesn't have to be. + } + + /** + * Build up the default `inspectOpts` object from the environment variables. + * + * $ DEBUG_COLORS=no DEBUG_DEPTH=10 DEBUG_SHOW_HIDDEN=enabled node script.js + */ + + exports.inspectOpts = Object.keys(process.env).filter(function (key) { + return /^debug_/i.test(key); + }).reduce(function (obj, key) { + // camel-case + var prop = key + .substring(6) + .toLowerCase() + .replace(/_([a-z])/g, function (_, k) { return k.toUpperCase() }); + + // coerce string value into JS value + var val = process.env[key]; + if (/^(yes|on|true|enabled)$/i.test(val)) val = true; + else if (/^(no|off|false|disabled)$/i.test(val)) val = false; + else if (val === 'null') val = null; + else val = Number(val); + + obj[prop] = val; + return obj; + }, {}); + + /** + * Is stdout a TTY? Colored output is enabled when `true`. + */ + + function useColors() { + return 'colors' in exports.inspectOpts + ? Boolean(exports.inspectOpts.colors) + : tty.isatty(process.stderr.fd); + } + + /** + * Map %o to `util.inspect()`, all on a single line. + */ + + exports.formatters.o = function(v) { + this.inspectOpts.colors = this.useColors; + return util.inspect(v, this.inspectOpts) + .split('\n').map(function(str) { + return str.trim() + }).join(' '); + }; + + /** + * Map %o to `util.inspect()`, allowing multiple lines if needed. + */ + + exports.formatters.O = function(v) { + this.inspectOpts.colors = this.useColors; + return util.inspect(v, this.inspectOpts); + }; + + /** + * Adds ANSI color escape codes if enabled. + * + * @api public + */ + + function formatArgs(args) { + var name = this.namespace; + var useColors = this.useColors; + + if (useColors) { + var c = this.color; + var colorCode = '\u001b[3' + (c < 8 ? c : '8;5;' + c); + var prefix = ' ' + colorCode + ';1m' + name + ' ' + '\u001b[0m'; + + args[0] = prefix + args[0].split('\n').join('\n' + prefix); + args.push(colorCode + 'm+' + exports.humanize(this.diff) + '\u001b[0m'); + } else { + args[0] = getDate() + name + ' ' + args[0]; + } + } + + function getDate() { + if (exports.inspectOpts.hideDate) { + return ''; + } else { + return new Date().toISOString() + ' '; + } + } + + /** + * Invokes `util.format()` with the specified arguments and writes to stderr. + */ + + function log() { + return process.stderr.write(util.format.apply(util, arguments) + '\n'); + } + + /** + * Save `namespaces`. + * + * @param {String} namespaces + * @api private + */ + + function save(namespaces) { + if (null == namespaces) { + // If you set a process.env field to null or undefined, it gets cast to the + // string 'null' or 'undefined'. Just delete instead. + delete process.env.DEBUG; + } else { + process.env.DEBUG = namespaces; + } + } + + /** + * Load `namespaces`. + * + * @return {String} returns the previously persisted debug modes + * @api private + */ + + function load() { + return process.env.DEBUG; + } + + /** + * Init logic for `debug` instances. + * + * Create a new `inspectOpts` object in case `useColors` is set + * differently for a particular `debug` instance. + */ + + function init (debug) { + debug.inspectOpts = {}; + + var keys = Object.keys(exports.inspectOpts); + for (var i = 0; i < keys.length; i++) { + debug.inspectOpts[keys[i]] = exports.inspectOpts[keys[i]]; + } + } + + /** + * Enable namespaces listed in `process.env.DEBUG` initially. + */ + + exports.enable(load()); + }); + var node_1$1 = node$1.init; + var node_2$1 = node$1.log; + var node_3$1 = node$1.formatArgs; + var node_4$1 = node$1.save; + var node_5$1 = node$1.load; + var node_6$1 = node$1.useColors; + var node_7$1 = node$1.colors; + var node_8$1 = node$1.inspectOpts; + + var src$1 = createCommonjsModule(function (module) { + /** + * Detect Electron renderer process, which is node, but we should + * treat as a browser. + */ + + if (typeof process === 'undefined' || process.type === 'renderer') { + module.exports = browser$1; + } else { + module.exports = node$1; + } + }); + + var componentEmitter = createCommonjsModule(function (module) { + /** + * Expose `Emitter`. + */ + + { + module.exports = Emitter; + } + + /** + * Initialize a new `Emitter`. + * + * @api public + */ + + function Emitter(obj) { + if (obj) return mixin(obj); + } + /** + * Mixin the emitter properties. + * + * @param {Object} obj + * @return {Object} + * @api private + */ + + function mixin(obj) { + for (var key in Emitter.prototype) { + obj[key] = Emitter.prototype[key]; + } + return obj; + } + + /** + * Listen on the given `event` with `fn`. + * + * @param {String} event + * @param {Function} fn + * @return {Emitter} + * @api public + */ + + Emitter.prototype.on = + Emitter.prototype.addEventListener = function(event, fn){ + this._callbacks = this._callbacks || {}; + (this._callbacks['$' + event] = this._callbacks['$' + event] || []) + .push(fn); + return this; + }; + + /** + * Adds an `event` listener that will be invoked a single + * time then automatically removed. + * + * @param {String} event + * @param {Function} fn + * @return {Emitter} + * @api public + */ + + Emitter.prototype.once = function(event, fn){ + function on() { + this.off(event, on); + fn.apply(this, arguments); + } + + on.fn = fn; + this.on(event, on); + return this; + }; + + /** + * Remove the given callback for `event` or all + * registered callbacks. + * + * @param {String} event + * @param {Function} fn + * @return {Emitter} + * @api public + */ + + Emitter.prototype.off = + Emitter.prototype.removeListener = + Emitter.prototype.removeAllListeners = + Emitter.prototype.removeEventListener = function(event, fn){ + this._callbacks = this._callbacks || {}; + + // all + if (0 == arguments.length) { + this._callbacks = {}; + return this; + } + + // specific event + var callbacks = this._callbacks['$' + event]; + if (!callbacks) return this; + + // remove all handlers + if (1 == arguments.length) { + delete this._callbacks['$' + event]; + return this; + } + + // remove specific handler + var cb; + for (var i = 0; i < callbacks.length; i++) { + cb = callbacks[i]; + if (cb === fn || cb.fn === fn) { + callbacks.splice(i, 1); + break; + } + } + + // Remove event specific arrays for event types that no + // one is subscribed for to avoid memory leak. + if (callbacks.length === 0) { + delete this._callbacks['$' + event]; + } + + return this; + }; + + /** + * Emit `event` with the given args. + * + * @param {String} event + * @param {Mixed} ... + * @return {Emitter} + */ + + Emitter.prototype.emit = function(event){ + this._callbacks = this._callbacks || {}; + + var args = new Array(arguments.length - 1) + , callbacks = this._callbacks['$' + event]; + + for (var i = 1; i < arguments.length; i++) { + args[i - 1] = arguments[i]; + } + + if (callbacks) { + callbacks = callbacks.slice(0); + for (var i = 0, len = callbacks.length; i < len; ++i) { + callbacks[i].apply(this, args); + } + } + + return this; + }; + + /** + * Return array of callbacks for `event`. + * + * @param {String} event + * @return {Array} + * @api public + */ + + Emitter.prototype.listeners = function(event){ + this._callbacks = this._callbacks || {}; + return this._callbacks['$' + event] || []; + }; + + /** + * Check if this emitter has `event` handlers. + * + * @param {String} event + * @return {Boolean} + * @api public + */ + + Emitter.prototype.hasListeners = function(event){ + return !! this.listeners(event).length; + }; + }); + + var toString = {}.toString; + + var isarray = Array.isArray || function (arr) { + return toString.call(arr) == '[object Array]'; + }; + + var isBuffer = isBuf; + + var withNativeBuffer = typeof Buffer === 'function' && typeof Buffer.isBuffer === 'function'; + var withNativeArrayBuffer = typeof ArrayBuffer === 'function'; + + var isView = function (obj) { + return typeof ArrayBuffer.isView === 'function' ? ArrayBuffer.isView(obj) : (obj.buffer instanceof ArrayBuffer); + }; + + /** + * Returns true if obj is a buffer or an arraybuffer. + * + * @api private + */ + + function isBuf(obj) { + return (withNativeBuffer && Buffer.isBuffer(obj)) || + (withNativeArrayBuffer && (obj instanceof ArrayBuffer || isView(obj))); + } + + /*global Blob,File*/ + + /** + * Module requirements + */ + + + + var toString$1 = Object.prototype.toString; + var withNativeBlob = typeof Blob === 'function' || (typeof Blob !== 'undefined' && toString$1.call(Blob) === '[object BlobConstructor]'); + var withNativeFile = typeof File === 'function' || (typeof File !== 'undefined' && toString$1.call(File) === '[object FileConstructor]'); + + /** + * Replaces every Buffer | ArrayBuffer in packet with a numbered placeholder. + * Anything with blobs or files should be fed through removeBlobs before coming + * here. + * + * @param {Object} packet - socket.io event packet + * @return {Object} with deconstructed packet and list of buffers + * @api public + */ + + var deconstructPacket = function(packet) { + var buffers = []; + var packetData = packet.data; + var pack = packet; + pack.data = _deconstructPacket(packetData, buffers); + pack.attachments = buffers.length; // number of binary 'attachments' + return {packet: pack, buffers: buffers}; + }; + + function _deconstructPacket(data, buffers) { + if (!data) return data; + + if (isBuffer(data)) { + var placeholder = { _placeholder: true, num: buffers.length }; + buffers.push(data); + return placeholder; + } else if (isarray(data)) { + var newData = new Array(data.length); + for (var i = 0; i < data.length; i++) { + newData[i] = _deconstructPacket(data[i], buffers); + } + return newData; + } else if (typeof data === 'object' && !(data instanceof Date)) { + var newData = {}; + for (var key in data) { + newData[key] = _deconstructPacket(data[key], buffers); + } + return newData; + } + return data; + } + + /** + * Reconstructs a binary packet from its placeholder packet and buffers + * + * @param {Object} packet - event packet with placeholders + * @param {Array} buffers - binary buffers to put in placeholder positions + * @return {Object} reconstructed packet + * @api public + */ + + var reconstructPacket = function(packet, buffers) { + packet.data = _reconstructPacket(packet.data, buffers); + packet.attachments = undefined; // no longer useful + return packet; + }; + + function _reconstructPacket(data, buffers) { + if (!data) return data; + + if (data && data._placeholder) { + return buffers[data.num]; // appropriate buffer (should be natural order anyway) + } else if (isarray(data)) { + for (var i = 0; i < data.length; i++) { + data[i] = _reconstructPacket(data[i], buffers); + } + } else if (typeof data === 'object') { + for (var key in data) { + data[key] = _reconstructPacket(data[key], buffers); + } + } + + return data; + } + + /** + * Asynchronously removes Blobs or Files from data via + * FileReader's readAsArrayBuffer method. Used before encoding + * data as msgpack. Calls callback with the blobless data. + * + * @param {Object} data + * @param {Function} callback + * @api private + */ + + var removeBlobs = function(data, callback) { + function _removeBlobs(obj, curKey, containingObject) { + if (!obj) return obj; + + // convert any blob + if ((withNativeBlob && obj instanceof Blob) || + (withNativeFile && obj instanceof File)) { + pendingBlobs++; + + // async filereader + var fileReader = new FileReader(); + fileReader.onload = function() { // this.result == arraybuffer + if (containingObject) { + containingObject[curKey] = this.result; + } + else { + bloblessData = this.result; + } + + // if nothing pending its callback time + if(! --pendingBlobs) { + callback(bloblessData); + } + }; + + fileReader.readAsArrayBuffer(obj); // blob -> arraybuffer + } else if (isarray(obj)) { // handle array + for (var i = 0; i < obj.length; i++) { + _removeBlobs(obj[i], i, obj); + } + } else if (typeof obj === 'object' && !isBuffer(obj)) { // and object + for (var key in obj) { + _removeBlobs(obj[key], key, obj); + } + } + } + + var pendingBlobs = 0; + var bloblessData = data; + _removeBlobs(bloblessData); + if (!pendingBlobs) { + callback(bloblessData); + } + }; + + var binary = { + deconstructPacket: deconstructPacket, + reconstructPacket: reconstructPacket, + removeBlobs: removeBlobs + }; + + var socket_ioParser = createCommonjsModule(function (module, exports) { + /** + * Module dependencies. + */ + + var debug = src$1('socket.io-parser'); + + + + + + /** + * Protocol version. + * + * @api public + */ + + exports.protocol = 4; + + /** + * Packet types. + * + * @api public + */ + + exports.types = [ + 'CONNECT', + 'DISCONNECT', + 'EVENT', + 'ACK', + 'ERROR', + 'BINARY_EVENT', + 'BINARY_ACK' + ]; + + /** + * Packet type `connect`. + * + * @api public + */ + + exports.CONNECT = 0; + + /** + * Packet type `disconnect`. + * + * @api public + */ + + exports.DISCONNECT = 1; + + /** + * Packet type `event`. + * + * @api public + */ + + exports.EVENT = 2; + + /** + * Packet type `ack`. + * + * @api public + */ + + exports.ACK = 3; + + /** + * Packet type `error`. + * + * @api public + */ + + exports.ERROR = 4; + + /** + * Packet type 'binary event' + * + * @api public + */ + + exports.BINARY_EVENT = 5; + + /** + * Packet type `binary ack`. For acks with binary arguments. + * + * @api public + */ + + exports.BINARY_ACK = 6; + + /** + * Encoder constructor. + * + * @api public + */ + + exports.Encoder = Encoder; + + /** + * Decoder constructor. + * + * @api public + */ + + exports.Decoder = Decoder; + + /** + * A socket.io Encoder instance + * + * @api public + */ + + function Encoder() {} + + var ERROR_PACKET = exports.ERROR + '"encode error"'; + + /** + * Encode a packet as a single string if non-binary, or as a + * buffer sequence, depending on packet type. + * + * @param {Object} obj - packet object + * @param {Function} callback - function to handle encodings (likely engine.write) + * @return Calls callback with Array of encodings + * @api public + */ + + Encoder.prototype.encode = function(obj, callback){ + debug('encoding packet %j', obj); + + if (exports.BINARY_EVENT === obj.type || exports.BINARY_ACK === obj.type) { + encodeAsBinary(obj, callback); + } else { + var encoding = encodeAsString(obj); + callback([encoding]); + } + }; + + /** + * Encode packet as string. + * + * @param {Object} packet + * @return {String} encoded + * @api private + */ + + function encodeAsString(obj) { + + // first is type + var str = '' + obj.type; + + // attachments if we have them + if (exports.BINARY_EVENT === obj.type || exports.BINARY_ACK === obj.type) { + str += obj.attachments + '-'; + } + + // if we have a namespace other than `/` + // we append it followed by a comma `,` + if (obj.nsp && '/' !== obj.nsp) { + str += obj.nsp + ','; + } + + // immediately followed by the id + if (null != obj.id) { + str += obj.id; + } + + // json data + if (null != obj.data) { + var payload = tryStringify(obj.data); + if (payload !== false) { + str += payload; + } else { + return ERROR_PACKET; + } + } + + debug('encoded %j as %s', obj, str); + return str; + } + + function tryStringify(str) { + try { + return JSON.stringify(str); + } catch(e){ + return false; + } + } + + /** + * Encode packet as 'buffer sequence' by removing blobs, and + * deconstructing packet into object with placeholders and + * a list of buffers. + * + * @param {Object} packet + * @return {Buffer} encoded + * @api private + */ + + function encodeAsBinary(obj, callback) { + + function writeEncoding(bloblessData) { + var deconstruction = binary.deconstructPacket(bloblessData); + var pack = encodeAsString(deconstruction.packet); + var buffers = deconstruction.buffers; + + buffers.unshift(pack); // add packet info to beginning of data list + callback(buffers); // write all the buffers + } + + binary.removeBlobs(obj, writeEncoding); + } + + /** + * A socket.io Decoder instance + * + * @return {Object} decoder + * @api public + */ + + function Decoder() { + this.reconstructor = null; + } + + /** + * Mix in `Emitter` with Decoder. + */ + + componentEmitter(Decoder.prototype); + + /** + * Decodes an encoded packet string into packet JSON. + * + * @param {String} obj - encoded packet + * @return {Object} packet + * @api public + */ + + Decoder.prototype.add = function(obj) { + var packet; + if (typeof obj === 'string') { + packet = decodeString(obj); + if (exports.BINARY_EVENT === packet.type || exports.BINARY_ACK === packet.type) { // binary packet's json + this.reconstructor = new BinaryReconstructor(packet); + + // no attachments, labeled binary but no binary data to follow + if (this.reconstructor.reconPack.attachments === 0) { + this.emit('decoded', packet); + } + } else { // non-binary full packet + this.emit('decoded', packet); + } + } else if (isBuffer(obj) || obj.base64) { // raw binary data + if (!this.reconstructor) { + throw new Error('got binary data when not reconstructing a packet'); + } else { + packet = this.reconstructor.takeBinaryData(obj); + if (packet) { // received final buffer + this.reconstructor = null; + this.emit('decoded', packet); + } + } + } else { + throw new Error('Unknown type: ' + obj); + } + }; + + /** + * Decode a packet String (JSON data) + * + * @param {String} str + * @return {Object} packet + * @api private + */ + + function decodeString(str) { + var i = 0; + // look up type + var p = { + type: Number(str.charAt(0)) + }; + + if (null == exports.types[p.type]) { + return error('unknown packet type ' + p.type); + } + + // look up attachments if type binary + if (exports.BINARY_EVENT === p.type || exports.BINARY_ACK === p.type) { + var start = i + 1; + while (str.charAt(++i) !== '-' && i != str.length) {} + var buf = str.substring(start, i); + if (buf != Number(buf) || str.charAt(i) !== '-') { + throw new Error('Illegal attachments'); + } + p.attachments = Number(buf); + } + + // look up namespace (if any) + if ('/' === str.charAt(i + 1)) { + var start = i + 1; + while (++i) { + var c = str.charAt(i); + if (',' === c) break; + if (i === str.length) break; + } + p.nsp = str.substring(start, i); + } else { + p.nsp = '/'; + } + + // look up id + var next = str.charAt(i + 1); + if ('' !== next && Number(next) == next) { + var start = i + 1; + while (++i) { + var c = str.charAt(i); + if (null == c || Number(c) != c) { + --i; + break; + } + if (i === str.length) break; + } + p.id = Number(str.substring(start, i + 1)); + } + + // look up json data + if (str.charAt(++i)) { + var payload = tryParse(str.substr(i)); + var isPayloadValid = payload !== false && (p.type === exports.ERROR || isarray(payload)); + if (isPayloadValid) { + p.data = payload; + } else { + return error('invalid payload'); + } + } + + debug('decoded %s as %j', str, p); + return p; + } + + function tryParse(str) { + try { + return JSON.parse(str); + } catch(e){ + return false; + } + } + + /** + * Deallocates a parser's resources + * + * @api public + */ + + Decoder.prototype.destroy = function() { + if (this.reconstructor) { + this.reconstructor.finishedReconstruction(); + } + }; + + /** + * A manager of a binary event's 'buffer sequence'. Should + * be constructed whenever a packet of type BINARY_EVENT is + * decoded. + * + * @param {Object} packet + * @return {BinaryReconstructor} initialized reconstructor + * @api private + */ + + function BinaryReconstructor(packet) { + this.reconPack = packet; + this.buffers = []; + } + + /** + * Method to be called when binary data received from connection + * after a BINARY_EVENT packet. + * + * @param {Buffer | ArrayBuffer} binData - the raw binary data received + * @return {null | Object} returns null if more binary data is expected or + * a reconstructed packet object if all buffers have been received. + * @api private + */ + + BinaryReconstructor.prototype.takeBinaryData = function(binData) { + this.buffers.push(binData); + if (this.buffers.length === this.reconPack.attachments) { // done with buffer list + var packet = binary.reconstructPacket(this.reconPack, this.buffers); + this.finishedReconstruction(); + return packet; + } + return null; + }; + + /** + * Cleans up binary packet reconstruction variables. + * + * @api private + */ + + BinaryReconstructor.prototype.finishedReconstruction = function() { + this.reconPack = null; + this.buffers = []; + }; + + function error(msg) { + return { + type: exports.ERROR, + data: 'parser error: ' + msg + }; + } + }); + var socket_ioParser_1 = socket_ioParser.protocol; + var socket_ioParser_2 = socket_ioParser.types; + var socket_ioParser_3 = socket_ioParser.CONNECT; + var socket_ioParser_4 = socket_ioParser.DISCONNECT; + var socket_ioParser_5 = socket_ioParser.EVENT; + var socket_ioParser_6 = socket_ioParser.ACK; + var socket_ioParser_7 = socket_ioParser.ERROR; + var socket_ioParser_8 = socket_ioParser.BINARY_EVENT; + var socket_ioParser_9 = socket_ioParser.BINARY_ACK; + var socket_ioParser_10 = socket_ioParser.Encoder; + var socket_ioParser_11 = socket_ioParser.Decoder; + + /** + * Wrapper for built-in http.js to emulate the browser XMLHttpRequest object. + * + * This can be used with JS designed for browsers to improve reuse of code and + * allow the use of existing libraries. + * + * Usage: include("XMLHttpRequest.js") and use XMLHttpRequest per W3C specs. + * + * @author Dan DeFelippi + * @contributor David Ellis + * @license MIT + */ + + + + var spawn = child_process.spawn; + + /** + * Module exports. + */ + + var XMLHttpRequest_1 = XMLHttpRequest; + + // backwards-compat + XMLHttpRequest.XMLHttpRequest = XMLHttpRequest; + + /** + * `XMLHttpRequest` constructor. + * + * Supported options for the `opts` object are: + * + * - `agent`: An http.Agent instance; http.globalAgent may be used; if 'undefined', agent usage is disabled + * + * @param {Object} opts optional "options" object + */ + + function XMLHttpRequest(opts) { + + opts = opts || {}; + + /** + * Private variables + */ + var self = this; + var http$1 = http; + var https$1 = https; + + // Holds http.js objects + var request; + var response; + + // Request settings + var settings = {}; + + // Disable header blacklist. + // Not part of XHR specs. + var disableHeaderCheck = false; + + // Set some default headers + var defaultHeaders = { + "User-Agent": "node-XMLHttpRequest", + "Accept": "*/*" + }; + + var headers = Object.assign({}, defaultHeaders); + + // These headers are not user setable. + // The following are allowed but banned in the spec: + // * user-agent + var forbiddenRequestHeaders = [ + "accept-charset", + "accept-encoding", + "access-control-request-headers", + "access-control-request-method", + "connection", + "content-length", + "content-transfer-encoding", + "cookie", + "cookie2", + "date", + "expect", + "host", + "keep-alive", + "origin", + "referer", + "te", + "trailer", + "transfer-encoding", + "upgrade", + "via" + ]; + + // These request methods are not allowed + var forbiddenRequestMethods = [ + "TRACE", + "TRACK", + "CONNECT" + ]; + + // Send flag + var sendFlag = false; + // Error flag, used when errors occur or abort is called + var errorFlag = false; + + // Event listeners + var listeners = {}; + + /** + * Constants + */ + + this.UNSENT = 0; + this.OPENED = 1; + this.HEADERS_RECEIVED = 2; + this.LOADING = 3; + this.DONE = 4; + + /** + * Public vars + */ + + // Current state + this.readyState = this.UNSENT; + + // default ready state change handler in case one is not set or is set late + this.onreadystatechange = null; + + // Result & response + this.responseText = ""; + this.responseXML = ""; + this.status = null; + this.statusText = null; + + /** + * Private methods + */ + + /** + * Check if the specified header is allowed. + * + * @param string header Header to validate + * @return boolean False if not allowed, otherwise true + */ + var isAllowedHttpHeader = function(header) { + return disableHeaderCheck || (header && forbiddenRequestHeaders.indexOf(header.toLowerCase()) === -1); + }; + + /** + * Check if the specified method is allowed. + * + * @param string method Request method to validate + * @return boolean False if not allowed, otherwise true + */ + var isAllowedHttpMethod = function(method) { + return (method && forbiddenRequestMethods.indexOf(method) === -1); + }; + + /** + * Public methods + */ + + /** + * Open the connection. Currently supports local server requests. + * + * @param string method Connection method (eg GET, POST) + * @param string url URL for the connection. + * @param boolean async Asynchronous connection. Default is true. + * @param string user Username for basic authentication (optional) + * @param string password Password for basic authentication (optional) + */ + this.open = function(method, url, async, user, password) { + this.abort(); + errorFlag = false; + + // Check for valid request method + if (!isAllowedHttpMethod(method)) { + throw "SecurityError: Request method not allowed"; + } + + settings = { + "method": method, + "url": url.toString(), + "async": (typeof async !== "boolean" ? true : async), + "user": user || null, + "password": password || null + }; + + setState(this.OPENED); + }; + + /** + * Disables or enables isAllowedHttpHeader() check the request. Enabled by default. + * This does not conform to the W3C spec. + * + * @param boolean state Enable or disable header checking. + */ + this.setDisableHeaderCheck = function(state) { + disableHeaderCheck = state; + }; + + /** + * Sets a header for the request. + * + * @param string header Header name + * @param string value Header value + * @return boolean Header added + */ + this.setRequestHeader = function(header, value) { + if (this.readyState != this.OPENED) { + throw "INVALID_STATE_ERR: setRequestHeader can only be called when state is OPEN"; + } + if (!isAllowedHttpHeader(header)) { + console.warn('Refused to set unsafe header "' + header + '"'); + return false; + } + if (sendFlag) { + throw "INVALID_STATE_ERR: send flag is true"; + } + headers[header] = value; + return true; + }; + + /** + * Gets a header from the server response. + * + * @param string header Name of header to get. + * @return string Text of the header or null if it doesn't exist. + */ + this.getResponseHeader = function(header) { + if (typeof header === "string" + && this.readyState > this.OPENED + && response.headers[header.toLowerCase()] + && !errorFlag + ) { + return response.headers[header.toLowerCase()]; + } + + return null; + }; + + /** + * Gets all the response headers. + * + * @return string A string with all response headers separated by CR+LF + */ + this.getAllResponseHeaders = function() { + if (this.readyState < this.HEADERS_RECEIVED || errorFlag) { + return ""; + } + var result = ""; + + for (var i in response.headers) { + // Cookie headers are excluded + if (i !== "set-cookie" && i !== "set-cookie2") { + result += i + ": " + response.headers[i] + "\r\n"; + } + } + return result.substr(0, result.length - 2); + }; + + /** + * Gets a request header + * + * @param string name Name of header to get + * @return string Returns the request header or empty string if not set + */ + this.getRequestHeader = function(name) { + // @TODO Make this case insensitive + if (typeof name === "string" && headers[name]) { + return headers[name]; + } + + return ""; + }; + + /** + * Sends the request to the server. + * + * @param string data Optional data to send as request body. + */ + this.send = function(data) { + if (this.readyState != this.OPENED) { + throw "INVALID_STATE_ERR: connection must be opened before send() is called"; + } + + if (sendFlag) { + throw "INVALID_STATE_ERR: send has already been called"; + } + + var ssl = false, local = false; + var url = url$1.parse(settings.url); + var host; + // Determine the server + switch (url.protocol) { + case 'https:': + ssl = true; + // SSL & non-SSL both need host, no break here. + case 'http:': + host = url.hostname; + break; + + case 'file:': + local = true; + break; + + case undefined: + case '': + host = "localhost"; + break; + + default: + throw "Protocol not supported."; + } + + // Load files off the local filesystem (file://) + if (local) { + if (settings.method !== "GET") { + throw "XMLHttpRequest: Only GET method is supported"; + } + + if (settings.async) { + fs.readFile(url.pathname, 'utf8', function(error, data) { + if (error) { + self.handleError(error); + } else { + self.status = 200; + self.responseText = data; + setState(self.DONE); + } + }); + } else { + try { + this.responseText = fs.readFileSync(url.pathname, 'utf8'); + this.status = 200; + setState(self.DONE); + } catch(e) { + this.handleError(e); + } + } + + return; + } + + // Default to port 80. If accessing localhost on another port be sure + // to use http://localhost:port/path + var port = url.port || (ssl ? 443 : 80); + // Add query string if one is used + var uri = url.pathname + (url.search ? url.search : ''); + + // Set the Host header or the server may reject the request + headers["Host"] = host; + if (!((ssl && port === 443) || port === 80)) { + headers["Host"] += ':' + url.port; + } + + // Set Basic Auth if necessary + if (settings.user) { + if (typeof settings.password == "undefined") { + settings.password = ""; + } + var authBuf = new Buffer(settings.user + ":" + settings.password); + headers["Authorization"] = "Basic " + authBuf.toString("base64"); + } + + // Set content length header + if (settings.method === "GET" || settings.method === "HEAD") { + data = null; + } else if (data) { + headers["Content-Length"] = Buffer.isBuffer(data) ? data.length : Buffer.byteLength(data); + + if (!headers["Content-Type"]) { + headers["Content-Type"] = "text/plain;charset=UTF-8"; + } + } else if (settings.method === "POST") { + // For a post with no data set Content-Length: 0. + // This is required by buggy servers that don't meet the specs. + headers["Content-Length"] = 0; + } + + var agent = opts.agent || false; + var options = { + host: host, + port: port, + path: uri, + method: settings.method, + headers: headers, + agent: agent + }; + + if (ssl) { + options.pfx = opts.pfx; + options.key = opts.key; + options.passphrase = opts.passphrase; + options.cert = opts.cert; + options.ca = opts.ca; + options.ciphers = opts.ciphers; + options.rejectUnauthorized = opts.rejectUnauthorized; + } + + // Reset error flag + errorFlag = false; + + // Handle async requests + if (settings.async) { + // Use the proper protocol + var doRequest = ssl ? https$1.request : http$1.request; + + // Request is being sent, set send flag + sendFlag = true; + + // As per spec, this is called here for historical reasons. + self.dispatchEvent("readystatechange"); + + // Handler for the response + var responseHandler = function(resp) { + // Set response var to the response we got back + // This is so it remains accessable outside this scope + response = resp; + // Check for redirect + // @TODO Prevent looped redirects + if (response.statusCode === 302 || response.statusCode === 303 || response.statusCode === 307) { + // Change URL to the redirect location + settings.url = response.headers.location; + var url = url$1.parse(settings.url); + // Set host var in case it's used later + host = url.hostname; + // Options for the new request + var newOptions = { + hostname: url.hostname, + port: url.port, + path: url.path, + method: response.statusCode === 303 ? 'GET' : settings.method, + headers: headers + }; + + if (ssl) { + newOptions.pfx = opts.pfx; + newOptions.key = opts.key; + newOptions.passphrase = opts.passphrase; + newOptions.cert = opts.cert; + newOptions.ca = opts.ca; + newOptions.ciphers = opts.ciphers; + newOptions.rejectUnauthorized = opts.rejectUnauthorized; + } + + // Issue the new request + request = doRequest(newOptions, responseHandler).on('error', errorHandler); + request.end(); + // @TODO Check if an XHR event needs to be fired here + return; + } + + if (response && response.setEncoding) { + response.setEncoding("utf8"); + } + + setState(self.HEADERS_RECEIVED); + self.status = response.statusCode; + + response.on('data', function(chunk) { + // Make sure there's some data + if (chunk) { + self.responseText += chunk; + } + // Don't emit state changes if the connection has been aborted. + if (sendFlag) { + setState(self.LOADING); + } + }); + + response.on('end', function() { + if (sendFlag) { + // The sendFlag needs to be set before setState is called. Otherwise if we are chaining callbacks + // there can be a timing issue (the callback is called and a new call is made before the flag is reset). + sendFlag = false; + // Discard the 'end' event if the connection has been aborted + setState(self.DONE); + } + }); + + response.on('error', function(error) { + self.handleError(error); + }); + }; + + // Error handler for the request + var errorHandler = function(error) { + self.handleError(error); + }; + + // Create the request + request = doRequest(options, responseHandler).on('error', errorHandler); + + // Node 0.4 and later won't accept empty data. Make sure it's needed. + if (data) { + request.write(data); + } + + request.end(); + + self.dispatchEvent("loadstart"); + } else { // Synchronous + // Create a temporary file for communication with the other Node process + var contentFile = ".node-xmlhttprequest-content-" + process.pid; + var syncFile = ".node-xmlhttprequest-sync-" + process.pid; + fs.writeFileSync(syncFile, "", "utf8"); + // The async request the other Node process executes + var execString = "var http = require('http'), https = require('https'), fs = require('fs');" + + "var doRequest = http" + (ssl ? "s" : "") + ".request;" + + "var options = " + JSON.stringify(options) + ";" + + "var responseText = '';" + + "var req = doRequest(options, function(response) {" + + "response.setEncoding('utf8');" + + "response.on('data', function(chunk) {" + + " responseText += chunk;" + + "});" + + "response.on('end', function() {" + + "fs.writeFileSync('" + contentFile + "', 'NODE-XMLHTTPREQUEST-STATUS:' + response.statusCode + ',' + responseText, 'utf8');" + + "fs.unlinkSync('" + syncFile + "');" + + "});" + + "response.on('error', function(error) {" + + "fs.writeFileSync('" + contentFile + "', 'NODE-XMLHTTPREQUEST-ERROR:' + JSON.stringify(error), 'utf8');" + + "fs.unlinkSync('" + syncFile + "');" + + "});" + + "}).on('error', function(error) {" + + "fs.writeFileSync('" + contentFile + "', 'NODE-XMLHTTPREQUEST-ERROR:' + JSON.stringify(error), 'utf8');" + + "fs.unlinkSync('" + syncFile + "');" + + "});" + + (data ? "req.write('" + data.replace(/'/g, "\\'") + "');":"") + + "req.end();"; + // Start the other Node Process, executing this string + var syncProc = spawn(process.argv[0], ["-e", execString]); + while(fs.existsSync(syncFile)) { + // Wait while the sync file is empty + } + self.responseText = fs.readFileSync(contentFile, 'utf8'); + // Kill the child process once the file has data + syncProc.stdin.end(); + // Remove the temporary file + fs.unlinkSync(contentFile); + if (self.responseText.match(/^NODE-XMLHTTPREQUEST-ERROR:/)) { + // If the file returned an error, handle it + var errorObj = self.responseText.replace(/^NODE-XMLHTTPREQUEST-ERROR:/, ""); + self.handleError(errorObj); + } else { + // If the file returned okay, parse its data and move to the DONE state + self.status = self.responseText.replace(/^NODE-XMLHTTPREQUEST-STATUS:([0-9]*),.*/, "$1"); + self.responseText = self.responseText.replace(/^NODE-XMLHTTPREQUEST-STATUS:[0-9]*,(.*)/, "$1"); + setState(self.DONE); + } + } + }; + + /** + * Called when an error is encountered to deal with it. + */ + this.handleError = function(error) { + this.status = 503; + this.statusText = error; + this.responseText = error.stack; + errorFlag = true; + setState(this.DONE); + }; + + /** + * Aborts a request. + */ + this.abort = function() { + if (request) { + request.abort(); + request = null; + } + + headers = Object.assign({}, defaultHeaders); + this.responseText = ""; + this.responseXML = ""; + + errorFlag = true; + + if (this.readyState !== this.UNSENT + && (this.readyState !== this.OPENED || sendFlag) + && this.readyState !== this.DONE) { + sendFlag = false; + setState(this.DONE); + } + this.readyState = this.UNSENT; + }; + + /** + * Adds an event listener. Preferred method of binding to events. + */ + this.addEventListener = function(event, callback) { + if (!(event in listeners)) { + listeners[event] = []; + } + // Currently allows duplicate callbacks. Should it? + listeners[event].push(callback); + }; + + /** + * Remove an event callback that has already been bound. + * Only works on the matching funciton, cannot be a copy. + */ + this.removeEventListener = function(event, callback) { + if (event in listeners) { + // Filter will return a new array with the callback removed + listeners[event] = listeners[event].filter(function(ev) { + return ev !== callback; + }); + } + }; + + /** + * Dispatch any events, including both "on" methods and events attached using addEventListener. + */ + this.dispatchEvent = function(event) { + if (typeof self["on" + event] === "function") { + self["on" + event](); + } + if (event in listeners) { + for (var i = 0, len = listeners[event].length; i < len; i++) { + listeners[event][i].call(self); + } + } + }; + + /** + * Changes readyState and calls onreadystatechange. + * + * @param int state New state + */ + var setState = function(state) { + if (self.readyState !== state) { + self.readyState = state; + + if (settings.async || self.readyState < self.OPENED || self.readyState === self.DONE) { + self.dispatchEvent("readystatechange"); + } + + if (self.readyState === self.DONE && !errorFlag) { + self.dispatchEvent("load"); + // @TODO figure out InspectorInstrumentation::didLoadXHR(cookie) + self.dispatchEvent("loadend"); + } + } + }; + } + + /*! https://mths.be/utf8js v2.1.2 by @mathias */ + + var stringFromCharCode = String.fromCharCode; + + // Taken from https://mths.be/punycode + function ucs2decode(string) { + var output = []; + var counter = 0; + var length = string.length; + var value; + var extra; + while (counter < length) { + value = string.charCodeAt(counter++); + if (value >= 0xD800 && value <= 0xDBFF && counter < length) { + // high surrogate, and there is a next character + extra = string.charCodeAt(counter++); + if ((extra & 0xFC00) == 0xDC00) { // low surrogate + output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000); + } else { + // unmatched surrogate; only append this code unit, in case the next + // code unit is the high surrogate of a surrogate pair + output.push(value); + counter--; + } + } else { + output.push(value); + } + } + return output; + } + + // Taken from https://mths.be/punycode + function ucs2encode(array) { + var length = array.length; + var index = -1; + var value; + var output = ''; + while (++index < length) { + value = array[index]; + if (value > 0xFFFF) { + value -= 0x10000; + output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800); + value = 0xDC00 | value & 0x3FF; + } + output += stringFromCharCode(value); + } + return output; + } + + function checkScalarValue(codePoint, strict) { + if (codePoint >= 0xD800 && codePoint <= 0xDFFF) { + if (strict) { + throw Error( + 'Lone surrogate U+' + codePoint.toString(16).toUpperCase() + + ' is not a scalar value' + ); + } + return false; + } + return true; + } + /*--------------------------------------------------------------------------*/ + + function createByte(codePoint, shift) { + return stringFromCharCode(((codePoint >> shift) & 0x3F) | 0x80); + } + + function encodeCodePoint(codePoint, strict) { + if ((codePoint & 0xFFFFFF80) == 0) { // 1-byte sequence + return stringFromCharCode(codePoint); + } + var symbol = ''; + if ((codePoint & 0xFFFFF800) == 0) { // 2-byte sequence + symbol = stringFromCharCode(((codePoint >> 6) & 0x1F) | 0xC0); + } + else if ((codePoint & 0xFFFF0000) == 0) { // 3-byte sequence + if (!checkScalarValue(codePoint, strict)) { + codePoint = 0xFFFD; + } + symbol = stringFromCharCode(((codePoint >> 12) & 0x0F) | 0xE0); + symbol += createByte(codePoint, 6); + } + else if ((codePoint & 0xFFE00000) == 0) { // 4-byte sequence + symbol = stringFromCharCode(((codePoint >> 18) & 0x07) | 0xF0); + symbol += createByte(codePoint, 12); + symbol += createByte(codePoint, 6); + } + symbol += stringFromCharCode((codePoint & 0x3F) | 0x80); + return symbol; + } + + function utf8encode(string, opts) { + opts = opts || {}; + var strict = false !== opts.strict; + + var codePoints = ucs2decode(string); + var length = codePoints.length; + var index = -1; + var codePoint; + var byteString = ''; + while (++index < length) { + codePoint = codePoints[index]; + byteString += encodeCodePoint(codePoint, strict); + } + return byteString; + } + + /*--------------------------------------------------------------------------*/ + + function readContinuationByte() { + if (byteIndex >= byteCount) { + throw Error('Invalid byte index'); + } + + var continuationByte = byteArray[byteIndex] & 0xFF; + byteIndex++; + + if ((continuationByte & 0xC0) == 0x80) { + return continuationByte & 0x3F; + } + + // If we end up here, it’s not a continuation byte + throw Error('Invalid continuation byte'); + } + + function decodeSymbol(strict) { + var byte1; + var byte2; + var byte3; + var byte4; + var codePoint; + + if (byteIndex > byteCount) { + throw Error('Invalid byte index'); + } + + if (byteIndex == byteCount) { + return false; + } + + // Read first byte + byte1 = byteArray[byteIndex] & 0xFF; + byteIndex++; + + // 1-byte sequence (no continuation bytes) + if ((byte1 & 0x80) == 0) { + return byte1; + } + + // 2-byte sequence + if ((byte1 & 0xE0) == 0xC0) { + byte2 = readContinuationByte(); + codePoint = ((byte1 & 0x1F) << 6) | byte2; + if (codePoint >= 0x80) { + return codePoint; + } else { + throw Error('Invalid continuation byte'); + } + } + + // 3-byte sequence (may include unpaired surrogates) + if ((byte1 & 0xF0) == 0xE0) { + byte2 = readContinuationByte(); + byte3 = readContinuationByte(); + codePoint = ((byte1 & 0x0F) << 12) | (byte2 << 6) | byte3; + if (codePoint >= 0x0800) { + return checkScalarValue(codePoint, strict) ? codePoint : 0xFFFD; + } else { + throw Error('Invalid continuation byte'); + } + } + + // 4-byte sequence + if ((byte1 & 0xF8) == 0xF0) { + byte2 = readContinuationByte(); + byte3 = readContinuationByte(); + byte4 = readContinuationByte(); + codePoint = ((byte1 & 0x07) << 0x12) | (byte2 << 0x0C) | + (byte3 << 0x06) | byte4; + if (codePoint >= 0x010000 && codePoint <= 0x10FFFF) { + return codePoint; + } + } + + throw Error('Invalid UTF-8 detected'); + } + + var byteArray; + var byteCount; + var byteIndex; + function utf8decode(byteString, opts) { + opts = opts || {}; + var strict = false !== opts.strict; + + byteArray = ucs2decode(byteString); + byteCount = byteArray.length; + byteIndex = 0; + var codePoints = []; + var tmp; + while ((tmp = decodeSymbol(strict)) !== false) { + codePoints.push(tmp); + } + return ucs2encode(codePoints); + } + + var utf8 = { + version: '2.1.2', + encode: utf8encode, + decode: utf8decode + }; + + var toString$2 = {}.toString; + + var isarray$1 = Array.isArray || function (arr) { + return toString$2.call(arr) == '[object Array]'; + }; + + /* global Blob File */ + + /* + * Module requirements. + */ + + + + var toString$3 = Object.prototype.toString; + var withNativeBlob$1 = typeof Blob === 'function' || + typeof Blob !== 'undefined' && toString$3.call(Blob) === '[object BlobConstructor]'; + var withNativeFile$1 = typeof File === 'function' || + typeof File !== 'undefined' && toString$3.call(File) === '[object FileConstructor]'; + + /** + * Module exports. + */ + + var hasBinary2 = hasBinary; + + /** + * Checks for binary data. + * + * Supports Buffer, ArrayBuffer, Blob and File. + * + * @param {Object} anything + * @api public + */ + + function hasBinary (obj) { + if (!obj || typeof obj !== 'object') { + return false; + } + + if (isarray$1(obj)) { + for (var i = 0, l = obj.length; i < l; i++) { + if (hasBinary(obj[i])) { + return true; + } + } + return false; + } + + if ((typeof Buffer === 'function' && Buffer.isBuffer && Buffer.isBuffer(obj)) || + (typeof ArrayBuffer === 'function' && obj instanceof ArrayBuffer) || + (withNativeBlob$1 && obj instanceof Blob) || + (withNativeFile$1 && obj instanceof File) + ) { + return true; + } + + // see: https://github.com/Automattic/has-binary/pull/4 + if (obj.toJSON && typeof obj.toJSON === 'function' && arguments.length === 1) { + return hasBinary(obj.toJSON(), true); + } + + for (var key in obj) { + if (Object.prototype.hasOwnProperty.call(obj, key) && hasBinary(obj[key])) { + return true; + } + } + + return false; + } + + var after_1 = after; + + function after(count, callback, err_cb) { + var bail = false; + err_cb = err_cb || noop; + proxy.count = count; + + return (count === 0) ? callback() : proxy + + function proxy(err, result) { + if (proxy.count <= 0) { + throw new Error('after called too many times') + } + --proxy.count; + + // after first error, rest are passed to err_cb + if (err) { + bail = true; + callback(err); + // future error callbacks will go to error handler + callback = err_cb; + } else if (proxy.count === 0 && !bail) { + callback(null, result); + } + } + } + + function noop() {} + + /** + * Gets the keys for an object. + * + * @return {Array} keys + * @api private + */ + + var keys = Object.keys || function keys (obj){ + var arr = []; + var has = Object.prototype.hasOwnProperty; + + for (var i in obj) { + if (has.call(obj, i)) { + arr.push(i); + } + } + return arr; + }; + + var lib = createCommonjsModule(function (module, exports) { + /** + * Module dependencies. + */ + + + + + + + /** + * Current protocol version. + */ + exports.protocol = 3; + + /** + * Packet types. + */ + + var packets = exports.packets = { + open: 0 // non-ws + , close: 1 // non-ws + , ping: 2 + , pong: 3 + , message: 4 + , upgrade: 5 + , noop: 6 + }; + + var packetslist = keys(packets); + + /** + * Premade error packet. + */ + + var err = { type: 'error', data: 'parser error' }; + + const EMPTY_BUFFER = Buffer.concat([]); + + /** + * Encodes a packet. + * + * [ ] + * + * Example: + * + * 5hello world + * 3 + * 4 + * + * Binary is encoded in an identical principle + * + * @api private + */ + + exports.encodePacket = function (packet, supportsBinary, utf8encode, callback) { + if (typeof supportsBinary === 'function') { + callback = supportsBinary; + supportsBinary = null; + } + + if (typeof utf8encode === 'function') { + callback = utf8encode; + utf8encode = null; + } + + if (Buffer.isBuffer(packet.data)) { + return encodeBuffer(packet, supportsBinary, callback); + } else if (packet.data && (packet.data.buffer || packet.data) instanceof ArrayBuffer) { + return encodeBuffer({ type: packet.type, data: arrayBufferToBuffer(packet.data) }, supportsBinary, callback); + } + + // Sending data as a utf-8 string + var encoded = packets[packet.type]; + + // data fragment is optional + if (undefined !== packet.data) { + encoded += utf8encode ? utf8.encode(String(packet.data), { strict: false }) : String(packet.data); + } + + return callback('' + encoded); + }; + + /** + * Encode Buffer data + */ + + function encodeBuffer(packet, supportsBinary, callback) { + if (!supportsBinary) { + return exports.encodeBase64Packet(packet, callback); + } + + var data = packet.data; + var typeBuffer = Buffer.allocUnsafe(1); + typeBuffer[0] = packets[packet.type]; + return callback(Buffer.concat([typeBuffer, data])); + } + + /** + * Encodes a packet with binary data in a base64 string + * + * @param {Object} packet, has `type` and `data` + * @return {String} base64 encoded message + */ + + exports.encodeBase64Packet = function(packet, callback){ + var data = Buffer.isBuffer(packet.data) ? packet.data : arrayBufferToBuffer(packet.data); + var message = 'b' + packets[packet.type]; + message += data.toString('base64'); + return callback(message); + }; + + /** + * Decodes a packet. Data also available as an ArrayBuffer if requested. + * + * @return {Object} with `type` and `data` (if any) + * @api private + */ + + exports.decodePacket = function (data, binaryType, utf8decode) { + if (data === undefined) { + return err; + } + + var type; + + // String data + if (typeof data === 'string') { + + type = data.charAt(0); + + if (type === 'b') { + return exports.decodeBase64Packet(data.substr(1), binaryType); + } + + if (utf8decode) { + data = tryDecode(data); + if (data === false) { + return err; + } + } + + if (Number(type) != type || !packetslist[type]) { + return err; + } + + if (data.length > 1) { + return { type: packetslist[type], data: data.substring(1) }; + } else { + return { type: packetslist[type] }; + } + } + + // Binary data + if (binaryType === 'arraybuffer') { + // wrap Buffer/ArrayBuffer data into an Uint8Array + var intArray = new Uint8Array(data); + type = intArray[0]; + return { type: packetslist[type], data: intArray.buffer.slice(1) }; + } + + if (data instanceof ArrayBuffer) { + data = arrayBufferToBuffer(data); + } + type = data[0]; + return { type: packetslist[type], data: data.slice(1) }; + }; + + function tryDecode(data) { + try { + data = utf8.decode(data, { strict: false }); + } catch (e) { + return false; + } + return data; + } + + /** + * Decodes a packet encoded in a base64 string. + * + * @param {String} base64 encoded message + * @return {Object} with `type` and `data` (if any) + */ + + exports.decodeBase64Packet = function(msg, binaryType) { + var type = packetslist[msg.charAt(0)]; + var data = Buffer.from(msg.substr(1), 'base64'); + if (binaryType === 'arraybuffer') { + var abv = new Uint8Array(data.length); + for (var i = 0; i < abv.length; i++){ + abv[i] = data[i]; + } + data = abv.buffer; + } + return { type: type, data: data }; + }; + + /** + * Encodes multiple messages (payload). + * + * :data + * + * Example: + * + * 11:hello world2:hi + * + * If any contents are binary, they will be encoded as base64 strings. Base64 + * encoded strings are marked with a b before the length specifier + * + * @param {Array} packets + * @api private + */ + + exports.encodePayload = function (packets, supportsBinary, callback) { + if (typeof supportsBinary === 'function') { + callback = supportsBinary; + supportsBinary = null; + } + + if (supportsBinary && hasBinary2(packets)) { + return exports.encodePayloadAsBinary(packets, callback); + } + + if (!packets.length) { + return callback('0:'); + } + + function encodeOne(packet, doneCallback) { + exports.encodePacket(packet, supportsBinary, false, function(message) { + doneCallback(null, setLengthHeader(message)); + }); + } + + map(packets, encodeOne, function(err, results) { + return callback(results.join('')); + }); + }; + + function setLengthHeader(message) { + return message.length + ':' + message; + } + + /** + * Async array map using after + */ + + function map(ary, each, done) { + var result = new Array(ary.length); + var next = after_1(ary.length, done); + + for (var i = 0; i < ary.length; i++) { + each(ary[i], function(error, msg) { + result[i] = msg; + next(error, result); + }); + } + } + + /* + * Decodes data when a payload is maybe expected. Possible binary contents are + * decoded from their base64 representation + * + * @param {String} data, callback method + * @api public + */ + + exports.decodePayload = function (data, binaryType, callback) { + if (typeof data !== 'string') { + return exports.decodePayloadAsBinary(data, binaryType, callback); + } + + if (typeof binaryType === 'function') { + callback = binaryType; + binaryType = null; + } + + if (data === '') { + // parser error - ignoring payload + return callback(err, 0, 1); + } + + var length = '', n, msg, packet; + + for (var i = 0, l = data.length; i < l; i++) { + var chr = data.charAt(i); + + if (chr !== ':') { + length += chr; + continue; + } + + if (length === '' || (length != (n = Number(length)))) { + // parser error - ignoring payload + return callback(err, 0, 1); + } + + msg = data.substr(i + 1, n); + + if (length != msg.length) { + // parser error - ignoring payload + return callback(err, 0, 1); + } + + if (msg.length) { + packet = exports.decodePacket(msg, binaryType, false); + + if (err.type === packet.type && err.data === packet.data) { + // parser error in individual packet - ignoring payload + return callback(err, 0, 1); + } + + var more = callback(packet, i + n, l); + if (false === more) return; + } + + // advance cursor + i += n; + length = ''; + } + + if (length !== '') { + // parser error - ignoring payload + return callback(err, 0, 1); + } + + }; + + /** + * + * Converts a buffer to a utf8.js encoded string + * + * @api private + */ + + function bufferToString(buffer) { + var str = ''; + for (var i = 0, l = buffer.length; i < l; i++) { + str += String.fromCharCode(buffer[i]); + } + return str; + } + + /** + * + * Converts a utf8.js encoded string to a buffer + * + * @api private + */ + + function stringToBuffer(string) { + var buf = Buffer.allocUnsafe(string.length); + for (var i = 0, l = string.length; i < l; i++) { + buf.writeUInt8(string.charCodeAt(i), i); + } + return buf; + } + + /** + * + * Converts an ArrayBuffer to a Buffer + * + * @api private + */ + + function arrayBufferToBuffer(data) { + // data is either an ArrayBuffer or ArrayBufferView. + var length = data.byteLength || data.length; + var offset = data.byteOffset || 0; + + return Buffer.from(data.buffer || data, offset, length); + } + + /** + * Encodes multiple messages (payload) as binary. + * + * <1 = binary, 0 = string>[...] + * + * Example: + * 1 3 255 1 2 3, if the binary contents are interpreted as 8 bit integers + * + * @param {Array} packets + * @return {Buffer} encoded payload + * @api private + */ + + exports.encodePayloadAsBinary = function (packets, callback) { + if (!packets.length) { + return callback(EMPTY_BUFFER); + } + + map(packets, encodeOneBinaryPacket, function(err, results) { + return callback(Buffer.concat(results)); + }); + }; + + function encodeOneBinaryPacket(p, doneCallback) { + + function onBinaryPacketEncode(packet) { + + var encodingLength = '' + packet.length; + var sizeBuffer; + + if (typeof packet === 'string') { + sizeBuffer = Buffer.allocUnsafe(encodingLength.length + 2); + sizeBuffer[0] = 0; // is a string (not true binary = 0) + for (var i = 0; i < encodingLength.length; i++) { + sizeBuffer[i + 1] = parseInt(encodingLength[i], 10); + } + sizeBuffer[sizeBuffer.length - 1] = 255; + return doneCallback(null, Buffer.concat([sizeBuffer, stringToBuffer(packet)])); + } + + sizeBuffer = Buffer.allocUnsafe(encodingLength.length + 2); + sizeBuffer[0] = 1; // is binary (true binary = 1) + for (var i = 0; i < encodingLength.length; i++) { + sizeBuffer[i + 1] = parseInt(encodingLength[i], 10); + } + sizeBuffer[sizeBuffer.length - 1] = 255; + + doneCallback(null, Buffer.concat([sizeBuffer, packet])); + } + + exports.encodePacket(p, true, true, onBinaryPacketEncode); + + } + + + /* + * Decodes data when a payload is maybe expected. Strings are decoded by + * interpreting each byte as a key code for entries marked to start with 0. See + * description of encodePayloadAsBinary + + * @param {Buffer} data, callback method + * @api public + */ + + exports.decodePayloadAsBinary = function (data, binaryType, callback) { + if (typeof binaryType === 'function') { + callback = binaryType; + binaryType = null; + } + + var bufferTail = data; + var buffers = []; + var i; + + while (bufferTail.length > 0) { + var strLen = ''; + var isString = bufferTail[0] === 0; + for (i = 1; ; i++) { + if (bufferTail[i] === 255) break; + // 310 = char length of Number.MAX_VALUE + if (strLen.length > 310) { + return callback(err, 0, 1); + } + strLen += '' + bufferTail[i]; + } + bufferTail = bufferTail.slice(strLen.length + 1); + + var msgLength = parseInt(strLen, 10); + + var msg = bufferTail.slice(1, msgLength + 1); + if (isString) msg = bufferToString(msg); + buffers.push(msg); + bufferTail = bufferTail.slice(msgLength + 1); + } + + var total = buffers.length; + for (i = 0; i < total; i++) { + var buffer = buffers[i]; + callback(exports.decodePacket(buffer, binaryType, true), i, total); + } + }; + }); + var lib_1 = lib.protocol; + var lib_2 = lib.packets; + var lib_3 = lib.encodePacket; + var lib_4 = lib.encodeBase64Packet; + var lib_5 = lib.decodePacket; + var lib_6 = lib.decodeBase64Packet; + var lib_7 = lib.encodePayload; + var lib_8 = lib.decodePayload; + var lib_9 = lib.encodePayloadAsBinary; + var lib_10 = lib.decodePayloadAsBinary; + + var componentEmitter$1 = createCommonjsModule(function (module) { + /** + * Expose `Emitter`. + */ + + { + module.exports = Emitter; + } + + /** + * Initialize a new `Emitter`. + * + * @api public + */ + + function Emitter(obj) { + if (obj) return mixin(obj); + } + /** + * Mixin the emitter properties. + * + * @param {Object} obj + * @return {Object} + * @api private + */ + + function mixin(obj) { + for (var key in Emitter.prototype) { + obj[key] = Emitter.prototype[key]; + } + return obj; + } + + /** + * Listen on the given `event` with `fn`. + * + * @param {String} event + * @param {Function} fn + * @return {Emitter} + * @api public + */ + + Emitter.prototype.on = + Emitter.prototype.addEventListener = function(event, fn){ + this._callbacks = this._callbacks || {}; + (this._callbacks['$' + event] = this._callbacks['$' + event] || []) + .push(fn); + return this; + }; + + /** + * Adds an `event` listener that will be invoked a single + * time then automatically removed. + * + * @param {String} event + * @param {Function} fn + * @return {Emitter} + * @api public + */ + + Emitter.prototype.once = function(event, fn){ + function on() { + this.off(event, on); + fn.apply(this, arguments); + } + + on.fn = fn; + this.on(event, on); + return this; + }; + + /** + * Remove the given callback for `event` or all + * registered callbacks. + * + * @param {String} event + * @param {Function} fn + * @return {Emitter} + * @api public + */ + + Emitter.prototype.off = + Emitter.prototype.removeListener = + Emitter.prototype.removeAllListeners = + Emitter.prototype.removeEventListener = function(event, fn){ + this._callbacks = this._callbacks || {}; + + // all + if (0 == arguments.length) { + this._callbacks = {}; + return this; + } + + // specific event + var callbacks = this._callbacks['$' + event]; + if (!callbacks) return this; + + // remove all handlers + if (1 == arguments.length) { + delete this._callbacks['$' + event]; + return this; + } + + // remove specific handler + var cb; + for (var i = 0; i < callbacks.length; i++) { + cb = callbacks[i]; + if (cb === fn || cb.fn === fn) { + callbacks.splice(i, 1); + break; + } + } + + // Remove event specific arrays for event types that no + // one is subscribed for to avoid memory leak. + if (callbacks.length === 0) { + delete this._callbacks['$' + event]; + } + + return this; + }; + + /** + * Emit `event` with the given args. + * + * @param {String} event + * @param {Mixed} ... + * @return {Emitter} + */ + + Emitter.prototype.emit = function(event){ + this._callbacks = this._callbacks || {}; + + var args = new Array(arguments.length - 1) + , callbacks = this._callbacks['$' + event]; + + for (var i = 1; i < arguments.length; i++) { + args[i - 1] = arguments[i]; + } + + if (callbacks) { + callbacks = callbacks.slice(0); + for (var i = 0, len = callbacks.length; i < len; ++i) { + callbacks[i].apply(this, args); + } + } + + return this; + }; + + /** + * Return array of callbacks for `event`. + * + * @param {String} event + * @return {Array} + * @api public + */ + + Emitter.prototype.listeners = function(event){ + this._callbacks = this._callbacks || {}; + return this._callbacks['$' + event] || []; + }; + + /** + * Check if this emitter has `event` handlers. + * + * @param {String} event + * @return {Boolean} + * @api public + */ + + Emitter.prototype.hasListeners = function(event){ + return !! this.listeners(event).length; + }; + }); + + /** + * Module dependencies. + */ + + + + + /** + * Module exports. + */ + + var transport = Transport; + + /** + * Transport abstract constructor. + * + * @param {Object} options. + * @api private + */ + + function Transport (opts) { + this.path = opts.path; + this.hostname = opts.hostname; + this.port = opts.port; + this.secure = opts.secure; + this.query = opts.query; + this.timestampParam = opts.timestampParam; + this.timestampRequests = opts.timestampRequests; + this.readyState = ''; + this.agent = opts.agent || false; + this.socket = opts.socket; + this.enablesXDR = opts.enablesXDR; + this.withCredentials = opts.withCredentials; + + // SSL options for Node.js client + this.pfx = opts.pfx; + this.key = opts.key; + this.passphrase = opts.passphrase; + this.cert = opts.cert; + this.ca = opts.ca; + this.ciphers = opts.ciphers; + this.rejectUnauthorized = opts.rejectUnauthorized; + this.forceNode = opts.forceNode; + + // results of ReactNative environment detection + this.isReactNative = opts.isReactNative; + + // other options for Node.js client + this.extraHeaders = opts.extraHeaders; + this.localAddress = opts.localAddress; + } + + /** + * Mix in `Emitter`. + */ + + componentEmitter$1(Transport.prototype); + + /** + * Emits an error. + * + * @param {String} str + * @return {Transport} for chaining + * @api public + */ + + Transport.prototype.onError = function (msg, desc) { + var err = new Error(msg); + err.type = 'TransportError'; + err.description = desc; + this.emit('error', err); + return this; + }; + + /** + * Opens the transport. + * + * @api public + */ + + Transport.prototype.open = function () { + if ('closed' === this.readyState || '' === this.readyState) { + this.readyState = 'opening'; + this.doOpen(); + } + + return this; + }; + + /** + * Closes the transport. + * + * @api private + */ + + Transport.prototype.close = function () { + if ('opening' === this.readyState || 'open' === this.readyState) { + this.doClose(); + this.onClose(); + } + + return this; + }; + + /** + * Sends multiple packets. + * + * @param {Array} packets + * @api private + */ + + Transport.prototype.send = function (packets) { + if ('open' === this.readyState) { + this.write(packets); + } else { + throw new Error('Transport not open'); + } + }; + + /** + * Called upon open + * + * @api private + */ + + Transport.prototype.onOpen = function () { + this.readyState = 'open'; + this.writable = true; + this.emit('open'); + }; + + /** + * Called with data. + * + * @param {String} data + * @api private + */ + + Transport.prototype.onData = function (data) { + var packet = lib.decodePacket(data, this.socket.binaryType); + this.onPacket(packet); + }; + + /** + * Called with a decoded packet. + */ + + Transport.prototype.onPacket = function (packet) { + this.emit('packet', packet); + }; + + /** + * Called upon close. + * + * @api private + */ + + Transport.prototype.onClose = function () { + this.readyState = 'closed'; + this.emit('close'); + }; + + /** + * Compiles a querystring + * Returns string representation of the object + * + * @param {Object} + * @api private + */ + + var encode = function (obj) { + var str = ''; + + for (var i in obj) { + if (obj.hasOwnProperty(i)) { + if (str.length) str += '&'; + str += encodeURIComponent(i) + '=' + encodeURIComponent(obj[i]); + } + } + + return str; + }; + + /** + * Parses a simple querystring into an object + * + * @param {String} qs + * @api private + */ + + var decode = function(qs){ + var qry = {}; + var pairs = qs.split('&'); + for (var i = 0, l = pairs.length; i < l; i++) { + var pair = pairs[i].split('='); + qry[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1]); + } + return qry; + }; + + var parseqs = { + encode: encode, + decode: decode + }; + + var componentInherit = function(a, b){ + var fn = function(){}; + fn.prototype = b.prototype; + a.prototype = new fn; + a.prototype.constructor = a; + }; + + var alphabet = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_'.split('') + , length = 64 + , map = {} + , seed = 0 + , i = 0 + , prev; + + /** + * Return a string representing the specified number. + * + * @param {Number} num The number to convert. + * @returns {String} The string representation of the number. + * @api public + */ + function encode$1(num) { + var encoded = ''; + + do { + encoded = alphabet[num % length] + encoded; + num = Math.floor(num / length); + } while (num > 0); + + return encoded; + } + + /** + * Return the integer value specified by the given string. + * + * @param {String} str The string to convert. + * @returns {Number} The integer value represented by the string. + * @api public + */ + function decode$1(str) { + var decoded = 0; + + for (i = 0; i < str.length; i++) { + decoded = decoded * length + map[str.charAt(i)]; + } + + return decoded; + } + + /** + * Yeast: A tiny growing id generator. + * + * @returns {String} A unique id. + * @api public + */ + function yeast() { + var now = encode$1(+new Date()); + + if (now !== prev) return seed = 0, prev = now; + return now +'.'+ encode$1(seed++); + } + + // + // Map each character to its index. + // + for (; i < length; i++) map[alphabet[i]] = i; + + // + // Expose the `yeast`, `encode` and `decode` functions. + // + yeast.encode = encode$1; + yeast.decode = decode$1; + var yeast_1 = yeast; + + /** + * Module dependencies. + */ + + + + + + + var debug$2 = src$1('engine.io-client:polling'); + + /** + * Module exports. + */ + + var polling = Polling; + + /** + * Is XHR2 supported? + */ + + var hasXHR2 = (function () { + var XMLHttpRequest = XMLHttpRequest_1; + var xhr = new XMLHttpRequest({ xdomain: false }); + return null != xhr.responseType; + })(); + + /** + * Polling interface. + * + * @param {Object} opts + * @api private + */ + + function Polling (opts) { + var forceBase64 = (opts && opts.forceBase64); + if (!hasXHR2 || forceBase64) { + this.supportsBinary = false; + } + transport.call(this, opts); + } + + /** + * Inherits from Transport. + */ + + componentInherit(Polling, transport); + + /** + * Transport name. + */ + + Polling.prototype.name = 'polling'; + + /** + * Opens the socket (triggers polling). We write a PING message to determine + * when the transport is open. + * + * @api private + */ + + Polling.prototype.doOpen = function () { + this.poll(); + }; + + /** + * Pauses polling. + * + * @param {Function} callback upon buffers are flushed and transport is paused + * @api private + */ + + Polling.prototype.pause = function (onPause) { + var self = this; + + this.readyState = 'pausing'; + + function pause () { + debug$2('paused'); + self.readyState = 'paused'; + onPause(); + } + + if (this.polling || !this.writable) { + var total = 0; + + if (this.polling) { + debug$2('we are currently polling - waiting to pause'); + total++; + this.once('pollComplete', function () { + debug$2('pre-pause polling complete'); + --total || pause(); + }); + } + + if (!this.writable) { + debug$2('we are currently writing - waiting to pause'); + total++; + this.once('drain', function () { + debug$2('pre-pause writing complete'); + --total || pause(); + }); + } + } else { + pause(); + } + }; + + /** + * Starts polling cycle. + * + * @api public + */ + + Polling.prototype.poll = function () { + debug$2('polling'); + this.polling = true; + this.doPoll(); + this.emit('poll'); + }; + + /** + * Overloads onData to detect payloads. + * + * @api private + */ + + Polling.prototype.onData = function (data) { + var self = this; + debug$2('polling got data %s', data); + var callback = function (packet, index, total) { + // if its the first message we consider the transport open + if ('opening' === self.readyState) { + self.onOpen(); + } + + // if its a close packet, we close the ongoing requests + if ('close' === packet.type) { + self.onClose(); + return false; + } + + // otherwise bypass onData and handle the message + self.onPacket(packet); + }; + + // decode payload + lib.decodePayload(data, this.socket.binaryType, callback); + + // if an event did not trigger closing + if ('closed' !== this.readyState) { + // if we got data we're not polling + this.polling = false; + this.emit('pollComplete'); + + if ('open' === this.readyState) { + this.poll(); + } else { + debug$2('ignoring poll - transport state "%s"', this.readyState); + } + } + }; + + /** + * For polling, send a close packet. + * + * @api private + */ + + Polling.prototype.doClose = function () { + var self = this; + + function close () { + debug$2('writing close packet'); + self.write([{ type: 'close' }]); + } + + if ('open' === this.readyState) { + debug$2('transport open - closing'); + close(); + } else { + // in case we're trying to close while + // handshaking is in progress (GH-164) + debug$2('transport not open - deferring close'); + this.once('open', close); + } + }; + + /** + * Writes a packets payload. + * + * @param {Array} data packets + * @param {Function} drain callback + * @api private + */ + + Polling.prototype.write = function (packets) { + var self = this; + this.writable = false; + var callbackfn = function () { + self.writable = true; + self.emit('drain'); + }; + + lib.encodePayload(packets, this.supportsBinary, function (data) { + self.doWrite(data, callbackfn); + }); + }; + + /** + * Generates uri for connection. + * + * @api private + */ + + Polling.prototype.uri = function () { + var query = this.query || {}; + var schema = this.secure ? 'https' : 'http'; + var port = ''; + + // cache busting is forced + if (false !== this.timestampRequests) { + query[this.timestampParam] = yeast_1(); + } + + if (!this.supportsBinary && !query.sid) { + query.b64 = 1; + } + + query = parseqs.encode(query); + + // avoid port if default for schema + if (this.port && (('https' === schema && Number(this.port) !== 443) || + ('http' === schema && Number(this.port) !== 80))) { + port = ':' + this.port; + } + + // prepend ? to query + if (query.length) { + query = '?' + query; + } + + var ipv6 = this.hostname.indexOf(':') !== -1; + return schema + '://' + (ipv6 ? '[' + this.hostname + ']' : this.hostname) + port + this.path + query; + }; + + var globalThis$1 = commonjsGlobal; + + /* global attachEvent */ + + /** + * Module requirements. + */ + + + + + + var debug$3 = src$1('engine.io-client:polling-xhr'); + + + /** + * Module exports. + */ + + var pollingXhr = XHR; + var Request_1 = Request; + + /** + * Empty function + */ + + function empty () {} + + /** + * XHR Polling constructor. + * + * @param {Object} opts + * @api public + */ + + function XHR (opts) { + polling.call(this, opts); + this.requestTimeout = opts.requestTimeout; + this.extraHeaders = opts.extraHeaders; + + if (typeof location !== 'undefined') { + var isSSL = 'https:' === location.protocol; + var port = location.port; + + // some user agents have empty `location.port` + if (!port) { + port = isSSL ? 443 : 80; + } + + this.xd = (typeof location !== 'undefined' && opts.hostname !== location.hostname) || + port !== opts.port; + this.xs = opts.secure !== isSSL; + } + } + + /** + * Inherits from Polling. + */ + + componentInherit(XHR, polling); + + /** + * XHR supports binary + */ + + XHR.prototype.supportsBinary = true; + + /** + * Creates a request. + * + * @param {String} method + * @api private + */ + + XHR.prototype.request = function (opts) { + opts = opts || {}; + opts.uri = this.uri(); + opts.xd = this.xd; + opts.xs = this.xs; + opts.agent = this.agent || false; + opts.supportsBinary = this.supportsBinary; + opts.enablesXDR = this.enablesXDR; + opts.withCredentials = this.withCredentials; + + // SSL options for Node.js client + opts.pfx = this.pfx; + opts.key = this.key; + opts.passphrase = this.passphrase; + opts.cert = this.cert; + opts.ca = this.ca; + opts.ciphers = this.ciphers; + opts.rejectUnauthorized = this.rejectUnauthorized; + opts.requestTimeout = this.requestTimeout; + + // other options for Node.js client + opts.extraHeaders = this.extraHeaders; + + return new Request(opts); + }; + + /** + * Sends data. + * + * @param {String} data to send. + * @param {Function} called upon flush. + * @api private + */ + + XHR.prototype.doWrite = function (data, fn) { + var isBinary = typeof data !== 'string' && data !== undefined; + var req = this.request({ method: 'POST', data: data, isBinary: isBinary }); + var self = this; + req.on('success', fn); + req.on('error', function (err) { + self.onError('xhr post error', err); + }); + this.sendXhr = req; + }; + + /** + * Starts a poll cycle. + * + * @api private + */ + + XHR.prototype.doPoll = function () { + debug$3('xhr poll'); + var req = this.request(); + var self = this; + req.on('data', function (data) { + self.onData(data); + }); + req.on('error', function (err) { + self.onError('xhr poll error', err); + }); + this.pollXhr = req; + }; + + /** + * Request constructor + * + * @param {Object} options + * @api public + */ + + function Request (opts) { + this.method = opts.method || 'GET'; + this.uri = opts.uri; + this.xd = !!opts.xd; + this.xs = !!opts.xs; + this.async = false !== opts.async; + this.data = undefined !== opts.data ? opts.data : null; + this.agent = opts.agent; + this.isBinary = opts.isBinary; + this.supportsBinary = opts.supportsBinary; + this.enablesXDR = opts.enablesXDR; + this.withCredentials = opts.withCredentials; + this.requestTimeout = opts.requestTimeout; + + // SSL options for Node.js client + this.pfx = opts.pfx; + this.key = opts.key; + this.passphrase = opts.passphrase; + this.cert = opts.cert; + this.ca = opts.ca; + this.ciphers = opts.ciphers; + this.rejectUnauthorized = opts.rejectUnauthorized; + + // other options for Node.js client + this.extraHeaders = opts.extraHeaders; + + this.create(); + } + + /** + * Mix in `Emitter`. + */ + + componentEmitter$1(Request.prototype); + + /** + * Creates the XHR object and sends the request. + * + * @api private + */ + + Request.prototype.create = function () { + var opts = { agent: this.agent, xdomain: this.xd, xscheme: this.xs, enablesXDR: this.enablesXDR }; + + // SSL options for Node.js client + opts.pfx = this.pfx; + opts.key = this.key; + opts.passphrase = this.passphrase; + opts.cert = this.cert; + opts.ca = this.ca; + opts.ciphers = this.ciphers; + opts.rejectUnauthorized = this.rejectUnauthorized; + + var xhr = this.xhr = new XMLHttpRequest_1(opts); + var self = this; + + try { + debug$3('xhr open %s: %s', this.method, this.uri); + xhr.open(this.method, this.uri, this.async); + try { + if (this.extraHeaders) { + xhr.setDisableHeaderCheck && xhr.setDisableHeaderCheck(true); + for (var i in this.extraHeaders) { + if (this.extraHeaders.hasOwnProperty(i)) { + xhr.setRequestHeader(i, this.extraHeaders[i]); + } + } + } + } catch (e) {} + + if ('POST' === this.method) { + try { + if (this.isBinary) { + xhr.setRequestHeader('Content-type', 'application/octet-stream'); + } else { + xhr.setRequestHeader('Content-type', 'text/plain;charset=UTF-8'); + } + } catch (e) {} + } + + try { + xhr.setRequestHeader('Accept', '*/*'); + } catch (e) {} + + // ie6 check + if ('withCredentials' in xhr) { + xhr.withCredentials = this.withCredentials; + } + + if (this.requestTimeout) { + xhr.timeout = this.requestTimeout; + } + + if (this.hasXDR()) { + xhr.onload = function () { + self.onLoad(); + }; + xhr.onerror = function () { + self.onError(xhr.responseText); + }; + } else { + xhr.onreadystatechange = function () { + if (xhr.readyState === 2) { + try { + var contentType = xhr.getResponseHeader('Content-Type'); + if (self.supportsBinary && contentType === 'application/octet-stream' || contentType === 'application/octet-stream; charset=UTF-8') { + xhr.responseType = 'arraybuffer'; + } + } catch (e) {} + } + if (4 !== xhr.readyState) return; + if (200 === xhr.status || 1223 === xhr.status) { + self.onLoad(); + } else { + // make sure the `error` event handler that's user-set + // does not throw in the same tick and gets caught here + setTimeout(function () { + self.onError(typeof xhr.status === 'number' ? xhr.status : 0); + }, 0); + } + }; + } + + debug$3('xhr data %s', this.data); + xhr.send(this.data); + } catch (e) { + // Need to defer since .create() is called directly fhrom the constructor + // and thus the 'error' event can only be only bound *after* this exception + // occurs. Therefore, also, we cannot throw here at all. + setTimeout(function () { + self.onError(e); + }, 0); + return; + } + + if (typeof document !== 'undefined') { + this.index = Request.requestsCount++; + Request.requests[this.index] = this; + } + }; + + /** + * Called upon successful response. + * + * @api private + */ + + Request.prototype.onSuccess = function () { + this.emit('success'); + this.cleanup(); + }; + + /** + * Called if we have data. + * + * @api private + */ + + Request.prototype.onData = function (data) { + this.emit('data', data); + this.onSuccess(); + }; + + /** + * Called upon error. + * + * @api private + */ + + Request.prototype.onError = function (err) { + this.emit('error', err); + this.cleanup(true); + }; + + /** + * Cleans up house. + * + * @api private + */ + + Request.prototype.cleanup = function (fromError) { + if ('undefined' === typeof this.xhr || null === this.xhr) { + return; + } + // xmlhttprequest + if (this.hasXDR()) { + this.xhr.onload = this.xhr.onerror = empty; + } else { + this.xhr.onreadystatechange = empty; + } + + if (fromError) { + try { + this.xhr.abort(); + } catch (e) {} + } + + if (typeof document !== 'undefined') { + delete Request.requests[this.index]; + } + + this.xhr = null; + }; + + /** + * Called upon load. + * + * @api private + */ + + Request.prototype.onLoad = function () { + var data; + try { + var contentType; + try { + contentType = this.xhr.getResponseHeader('Content-Type'); + } catch (e) {} + if (contentType === 'application/octet-stream' || contentType === 'application/octet-stream; charset=UTF-8') { + data = this.xhr.response || this.xhr.responseText; + } else { + data = this.xhr.responseText; + } + } catch (e) { + this.onError(e); + } + if (null != data) { + this.onData(data); + } + }; + + /** + * Check if it has XDomainRequest. + * + * @api private + */ + + Request.prototype.hasXDR = function () { + return typeof XDomainRequest !== 'undefined' && !this.xs && this.enablesXDR; + }; + + /** + * Aborts the request. + * + * @api public + */ + + Request.prototype.abort = function () { + this.cleanup(); + }; + + /** + * Aborts pending requests when unloading the window. This is needed to prevent + * memory leaks (e.g. when using IE) and to ensure that no spurious error is + * emitted. + */ + + Request.requestsCount = 0; + Request.requests = {}; + + if (typeof document !== 'undefined') { + if (typeof attachEvent === 'function') { + attachEvent('onunload', unloadHandler); + } else if (typeof addEventListener === 'function') { + var terminationEvent = 'onpagehide' in globalThis$1 ? 'pagehide' : 'unload'; + addEventListener(terminationEvent, unloadHandler, false); + } + } + + function unloadHandler () { + for (var i in Request.requests) { + if (Request.requests.hasOwnProperty(i)) { + Request.requests[i].abort(); + } + } + } + pollingXhr.Request = Request_1; + + /** + * Module requirements. + */ + + + + + + /** + * Module exports. + */ + + var pollingJsonp = JSONPPolling; + + /** + * Cached regular expressions. + */ + + var rNewline = /\n/g; + var rEscapedNewline = /\\n/g; + + /** + * Global JSONP callbacks. + */ + + var callbacks; + + /** + * Noop. + */ + + function empty$1 () { } + + /** + * JSONP Polling constructor. + * + * @param {Object} opts. + * @api public + */ + + function JSONPPolling (opts) { + polling.call(this, opts); + + this.query = this.query || {}; + + // define global callbacks array if not present + // we do this here (lazily) to avoid unneeded global pollution + if (!callbacks) { + // we need to consider multiple engines in the same page + callbacks = globalThis$1.___eio = (globalThis$1.___eio || []); + } + + // callback identifier + this.index = callbacks.length; + + // add callback to jsonp global + var self = this; + callbacks.push(function (msg) { + self.onData(msg); + }); + + // append to query string + this.query.j = this.index; + + // prevent spurious errors from being emitted when the window is unloaded + if (typeof addEventListener === 'function') { + addEventListener('beforeunload', function () { + if (self.script) self.script.onerror = empty$1; + }, false); + } + } + + /** + * Inherits from Polling. + */ + + componentInherit(JSONPPolling, polling); + + /* + * JSONP only supports binary as base64 encoded strings + */ + + JSONPPolling.prototype.supportsBinary = false; + + /** + * Closes the socket. + * + * @api private + */ + + JSONPPolling.prototype.doClose = function () { + if (this.script) { + this.script.parentNode.removeChild(this.script); + this.script = null; + } + + if (this.form) { + this.form.parentNode.removeChild(this.form); + this.form = null; + this.iframe = null; + } + + polling.prototype.doClose.call(this); + }; + + /** + * Starts a poll cycle. + * + * @api private + */ + + JSONPPolling.prototype.doPoll = function () { + var self = this; + var script = document.createElement('script'); + + if (this.script) { + this.script.parentNode.removeChild(this.script); + this.script = null; + } + + script.async = true; + script.src = this.uri(); + script.onerror = function (e) { + self.onError('jsonp poll error', e); + }; + + var insertAt = document.getElementsByTagName('script')[0]; + if (insertAt) { + insertAt.parentNode.insertBefore(script, insertAt); + } else { + (document.head || document.body).appendChild(script); + } + this.script = script; + + var isUAgecko = 'undefined' !== typeof navigator && /gecko/i.test(navigator.userAgent); + + if (isUAgecko) { + setTimeout(function () { + var iframe = document.createElement('iframe'); + document.body.appendChild(iframe); + document.body.removeChild(iframe); + }, 100); + } + }; + + /** + * Writes with a hidden iframe. + * + * @param {String} data to send + * @param {Function} called upon flush. + * @api private + */ + + JSONPPolling.prototype.doWrite = function (data, fn) { + var self = this; + + if (!this.form) { + var form = document.createElement('form'); + var area = document.createElement('textarea'); + var id = this.iframeId = 'eio_iframe_' + this.index; + var iframe; + + form.className = 'socketio'; + form.style.position = 'absolute'; + form.style.top = '-1000px'; + form.style.left = '-1000px'; + form.target = id; + form.method = 'POST'; + form.setAttribute('accept-charset', 'utf-8'); + area.name = 'd'; + form.appendChild(area); + document.body.appendChild(form); + + this.form = form; + this.area = area; + } + + this.form.action = this.uri(); + + function complete () { + initIframe(); + fn(); + } + + function initIframe () { + if (self.iframe) { + try { + self.form.removeChild(self.iframe); + } catch (e) { + self.onError('jsonp polling iframe removal error', e); + } + } + + try { + // ie6 dynamic iframes with target="" support (thanks Chris Lambacher) + var html = '