From a4ba0d5d8719bd5d4de51d50e167e10d09a6a0c4 Mon Sep 17 00:00:00 2001 From: Daniel Tsvetkov Date: Fri, 20 Mar 2020 12:44:42 +0100 Subject: [PATCH] own worker and follower --- oshipka.sh | 2 +- oshipka/persistance/__init__.py | 3 +- oshipka/webapp/__init__.py | 8 +- oshipka/webapp/async_routes.py | 132 + oshipka/webapp/static/js/socket.io.js | 6620 ----------------- oshipka/webapp/tasks_routes.py | 156 - oshipka/webapp/templates/test/navigation.html | 1 - oshipka/webapp/templates/test/task.html | 45 - .../webapp/templates/test/task_status.html | 25 + oshipka/webapp/templates/test/tasks.html | 4 +- oshipka/webapp/templates/test/websockets.html | 19 - oshipka/webapp/websockets_routes.py | 17 - oshipka/worker.py | 134 +- requirements.txt | 23 +- 14 files changed, 281 insertions(+), 6908 deletions(-) create mode 100644 oshipka/webapp/async_routes.py delete mode 100644 oshipka/webapp/static/js/socket.io.js delete mode 100644 oshipka/webapp/tasks_routes.py delete mode 100644 oshipka/webapp/templates/test/task.html create mode 100644 oshipka/webapp/templates/test/task_status.html delete mode 100644 oshipka/webapp/templates/test/websockets.html delete mode 100644 oshipka/webapp/websockets_routes.py diff --git a/oshipka.sh b/oshipka.sh index 00336c9..d998a95 100755 --- a/oshipka.sh +++ b/oshipka.sh @@ -16,7 +16,7 @@ Usage $0 [ bootstrap | worker | web ] " worker () { - celery worker --app=tasks.worker.worker_app --concurrency=1 --loglevel=INFO + python worker.py } web () { diff --git a/oshipka/persistance/__init__.py b/oshipka/persistance/__init__.py index 517eb51..4f44ad6 100644 --- a/oshipka/persistance/__init__.py +++ b/oshipka/persistance/__init__.py @@ -11,8 +11,9 @@ def init_db(app): app.config["SQLALCHEMY_DATABASE_URI"] = SQLALCHEMY_DATABASE_URI app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False - from oshipka.webapp import test_bp + from oshipka.webapp import test_bp, oshipka_bp app.register_blueprint(test_bp) + app.register_blueprint(oshipka_bp) db.init_app(app) for dir in MAKEDIRS: diff --git a/oshipka/webapp/__init__.py b/oshipka/webapp/__init__.py index cfd7760..36bb164 100644 --- a/oshipka/webapp/__init__.py +++ b/oshipka/webapp/__init__.py @@ -15,5 +15,9 @@ test_bp = Blueprint('test_bp', __name__, static_folder='static', ) -import oshipka.webapp.tasks_routes -import oshipka.webapp.websockets_routes +oshipka_bp = Blueprint('oshipka_bp', __name__, + template_folder='templates', + static_folder='static', + ) + +import oshipka.webapp.async_routes diff --git a/oshipka/webapp/async_routes.py b/oshipka/webapp/async_routes.py new file mode 100644 index 0000000..4deb3ef --- /dev/null +++ b/oshipka/webapp/async_routes.py @@ -0,0 +1,132 @@ +import itertools +import json +import os +import subprocess +import time +from uuid import uuid4 + +from flask import render_template, request, Response, redirect, url_for, jsonify +from flask_table import Table, LinkCol, Col + +from oshipka.persistance import db +from oshipka.webapp import test_bp, oshipka_bp + +from config import TASKS_BUF_DIR + +TASKS = {} + + +def register_task(task_name, task_func, *args, **kwargs): + TASKS[task_name] = task_func + + +def stateless_task(): + for i, c in enumerate(itertools.cycle('\|/-')): + yield "data: %s %d\n\n" % (c, i) + time.sleep(.1) # an artificial delay + + +register_task("stateless_task", stateless_task) + + +def stateful_task(*args, **kwargs): + n = 100 + for i in range(0, n + 1): + print(i) + time.sleep(1) + + +register_task("stateful_task", stateful_task) + + +class Task(db.Model): + id = db.Column(db.Integer, primary_key=True) + + name = db.Column(db.Unicode) + uuid = db.Column(db.Unicode) + status = db.Column(db.Unicode, default="NOT_STARTED") + + func_name = db.Column(db.Unicode) + args = db.Column(db.Unicode, default="[]") + kwargs = db.Column(db.Unicode, default="{}") + + def serialize(self): + return dict( + name=self.name, uuid=self.uuid, kwargs=json.loads(self.kwargs), + status=self.status, + ) + + +class TasksTable(Table): + uuid = LinkCol('Task', "test_bp.get_task_status", url_kwargs=dict(task_uuid='uuid')) + name = Col('name') + + +@test_bp.route("/tasks", methods=["GET"]) +def list_tasks(): + tasks = Task.query.all() + tasks_table = TasksTable(tasks) + return render_template("test/tasks.html", + runnable_tasks=TASKS.keys(), + tasks_table=tasks_table) + + +def tail(filename): + process = subprocess.Popen(['tail', '-F', filename], + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + universal_newlines=True, + ) + for line in iter(process.stdout.readline, b''): + line = line.strip() + # print("sending s_tail: {}".format(line)) + yield "data: {}\n\n".format(line) + # print("sent s_tail: {}".format((line))) + + +def worker_start_task(task_name, func_name, task_kwargs): + uuid = str(uuid4()) + task = Task(name=task_name, + uuid=uuid, + kwargs=json.dumps(task_kwargs), + func_name=func_name + ) + db.session.add(task) + db.session.commit() + return uuid + + +@test_bp.route('/tasks//start', methods=['GET', 'POST']) +def start_task(task_name): + task_kwargs = {k: v for k, v in request.form.items() if k != 'csrf_token'} + func_name = "oshipka.webapp.async_routes.{}".format(TASKS.get(task_name).__name__) + async_task_id = worker_start_task(task_name, func_name, task_kwargs) + return redirect(url_for('test_bp.get_task_status', task_uuid=async_task_id)) + + +def get_task_ctx(task_uuid): + ctx = {} + task = Task.query.filter_by(uuid=task_uuid).first() + ctx['task'] = task.serialize() + out_filename = os.path.join(TASKS_BUF_DIR, task_uuid) + if os.path.exists(out_filename): + with open(out_filename) as f: + ctx['stdout'] = f.read() + return ctx + + +@test_bp.route('/task_status/') +def get_task_status(task_uuid): + ctx = get_task_ctx(task_uuid) + return render_template("test/task_status.html", **ctx) + + +@oshipka_bp.route('/stream/') +def stream(task_uuid): + if request.headers.get('accept') == 'text/event-stream': + task = Task.query.filter_by(uuid=task_uuid).first() + if not task: + return jsonify({"error": "no task with uuid {}".format(task_uuid)}), 404 + # return Response(stateless_task(), content_type='text/event-stream') + return Response(tail(os.path.join(TASKS_BUF_DIR, task_uuid)), content_type='text/event-stream') + return jsonify({"error": "Request has to contain 'Accept: text/event-stream' header"}), 400 diff --git a/oshipka/webapp/static/js/socket.io.js b/oshipka/webapp/static/js/socket.io.js deleted file mode 100644 index d146d60..0000000 --- a/oshipka/webapp/static/js/socket.io.js +++ /dev/null @@ -1,6620 +0,0 @@ -/*! - * Socket.IO v2.2.0 - * (c) 2014-2018 Guillermo Rauch - * Released under the MIT License. - */ -(function webpackUniversalModuleDefinition(root, factory) { - if(typeof exports === 'object' && typeof module === 'object') - module.exports = factory(); - else if(typeof define === 'function' && define.amd) - define([], factory); - else if(typeof exports === 'object') - exports["io"] = factory(); - else - root["io"] = factory(); -})(this, function() { -return /******/ (function(modules) { // webpackBootstrap -/******/ // The module cache -/******/ var installedModules = {}; -/******/ -/******/ // The require function -/******/ function __webpack_require__(moduleId) { -/******/ -/******/ // Check if module is in cache -/******/ if(installedModules[moduleId]) -/******/ return installedModules[moduleId].exports; -/******/ -/******/ // Create a new module (and put it into the cache) -/******/ var module = installedModules[moduleId] = { -/******/ exports: {}, -/******/ id: moduleId, -/******/ loaded: false -/******/ }; -/******/ -/******/ // Execute the module function -/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); -/******/ -/******/ // Flag the module as loaded -/******/ module.loaded = true; -/******/ -/******/ // Return the exports of the module -/******/ return module.exports; -/******/ } -/******/ -/******/ -/******/ // expose the modules object (__webpack_modules__) -/******/ __webpack_require__.m = modules; -/******/ -/******/ // expose the module cache -/******/ __webpack_require__.c = installedModules; -/******/ -/******/ // __webpack_public_path__ -/******/ __webpack_require__.p = ""; -/******/ -/******/ // Load entry module and return exports -/******/ return __webpack_require__(0); -/******/ }) -/************************************************************************/ -/******/ ([ -/* 0 */ -/***/ (function(module, exports, __webpack_require__) { - - 'use strict'; - - var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; - - /** - * Module dependencies. - */ - - var url = __webpack_require__(1); - var parser = __webpack_require__(7); - var Manager = __webpack_require__(12); - var debug = __webpack_require__(3)('socket.io-client'); - - /** - * Module exports. - */ - - module.exports = exports = lookup; - - /** - * Managers cache. - */ - - var cache = exports.managers = {}; - - /** - * Looks up an existing `Manager` for multiplexing. - * If the user summons: - * - * `io('http://localhost/a');` - * `io('http://localhost/b');` - * - * We reuse the existing instance based on same scheme/port/host, - * and we initialize sockets for each namespace. - * - * @api public - */ - - function lookup(uri, opts) { - if ((typeof uri === 'undefined' ? 'undefined' : _typeof(uri)) === 'object') { - opts = uri; - uri = undefined; - } - - opts = opts || {}; - - var parsed = url(uri); - var source = parsed.source; - var id = parsed.id; - var path = parsed.path; - var sameNamespace = cache[id] && path in cache[id].nsps; - var newConnection = opts.forceNew || opts['force new connection'] || false === opts.multiplex || sameNamespace; - - var io; - - if (newConnection) { - debug('ignoring socket cache for %s', source); - io = Manager(source, opts); - } else { - if (!cache[id]) { - debug('new io instance for %s', source); - cache[id] = Manager(source, opts); - } - io = cache[id]; - } - if (parsed.query && !opts.query) { - opts.query = parsed.query; - } - return io.socket(parsed.path, opts); - } - - /** - * Protocol version. - * - * @api public - */ - - exports.protocol = parser.protocol; - - /** - * `connect`. - * - * @param {String} uri - * @api public - */ - - exports.connect = lookup; - - /** - * Expose constructors for standalone build. - * - * @api public - */ - - exports.Manager = __webpack_require__(12); - exports.Socket = __webpack_require__(36); - -/***/ }), -/* 1 */ -/***/ (function(module, exports, __webpack_require__) { - - 'use strict'; - - /** - * Module dependencies. - */ - - var parseuri = __webpack_require__(2); - var debug = __webpack_require__(3)('socket.io-client:url'); - - /** - * Module exports. - */ - - module.exports = 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; - } - -/***/ }), -/* 2 */ -/***/ (function(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' - ]; - - module.exports = 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; - }; - - -/***/ }), -/* 3 */ -/***/ (function(module, exports, __webpack_require__) { - - /* WEBPACK VAR INJECTION */(function(process) {/** - * This is the web browser implementation of `debug()`. - * - * Expose `debug()` as the module. - */ - - exports = module.exports = __webpack_require__(5); - 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) {} - } - - /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(4))) - -/***/ }), -/* 4 */ -/***/ (function(module, exports) { - - // shim for using process in browser - var process = module.exports = {}; - - // cached from whatever global is present so that test runners that stub it - // don't break things. But we need to wrap it in a try catch in case it is - // wrapped in strict mode code which doesn't define any globals. It's inside a - // function because try/catches deoptimize in certain engines. - - var cachedSetTimeout; - var cachedClearTimeout; - - function defaultSetTimout() { - throw new Error('setTimeout has not been defined'); - } - function defaultClearTimeout () { - throw new Error('clearTimeout has not been defined'); - } - (function () { - try { - if (typeof setTimeout === 'function') { - cachedSetTimeout = setTimeout; - } else { - cachedSetTimeout = defaultSetTimout; - } - } catch (e) { - cachedSetTimeout = defaultSetTimout; - } - try { - if (typeof clearTimeout === 'function') { - cachedClearTimeout = clearTimeout; - } else { - cachedClearTimeout = defaultClearTimeout; - } - } catch (e) { - cachedClearTimeout = defaultClearTimeout; - } - } ()) - function runTimeout(fun) { - if (cachedSetTimeout === setTimeout) { - //normal enviroments in sane situations - return setTimeout(fun, 0); - } - // if setTimeout wasn't available but was latter defined - if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) { - cachedSetTimeout = setTimeout; - return setTimeout(fun, 0); - } - try { - // when when somebody has screwed with setTimeout but no I.E. maddness - return cachedSetTimeout(fun, 0); - } catch(e){ - try { - // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally - return cachedSetTimeout.call(null, fun, 0); - } catch(e){ - // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error - return cachedSetTimeout.call(this, fun, 0); - } - } - - - } - function runClearTimeout(marker) { - if (cachedClearTimeout === clearTimeout) { - //normal enviroments in sane situations - return clearTimeout(marker); - } - // if clearTimeout wasn't available but was latter defined - if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) { - cachedClearTimeout = clearTimeout; - return clearTimeout(marker); - } - try { - // when when somebody has screwed with setTimeout but no I.E. maddness - return cachedClearTimeout(marker); - } catch (e){ - try { - // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally - return cachedClearTimeout.call(null, marker); - } catch (e){ - // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error. - // Some versions of I.E. have different rules for clearTimeout vs setTimeout - return cachedClearTimeout.call(this, marker); - } - } - - - - } - var queue = []; - var draining = false; - var currentQueue; - var queueIndex = -1; - - function cleanUpNextTick() { - if (!draining || !currentQueue) { - return; - } - draining = false; - if (currentQueue.length) { - queue = currentQueue.concat(queue); - } else { - queueIndex = -1; - } - if (queue.length) { - drainQueue(); - } - } - - function drainQueue() { - if (draining) { - return; - } - var timeout = runTimeout(cleanUpNextTick); - draining = true; - - var len = queue.length; - while(len) { - currentQueue = queue; - queue = []; - while (++queueIndex < len) { - if (currentQueue) { - currentQueue[queueIndex].run(); - } - } - queueIndex = -1; - len = queue.length; - } - currentQueue = null; - draining = false; - runClearTimeout(timeout); - } - - process.nextTick = function (fun) { - var args = new Array(arguments.length - 1); - if (arguments.length > 1) { - for (var i = 1; i < arguments.length; i++) { - args[i - 1] = arguments[i]; - } - } - queue.push(new Item(fun, args)); - if (queue.length === 1 && !draining) { - runTimeout(drainQueue); - } - }; - - // v8 likes predictible objects - function Item(fun, array) { - this.fun = fun; - this.array = array; - } - Item.prototype.run = function () { - this.fun.apply(null, this.array); - }; - process.title = 'browser'; - process.browser = true; - process.env = {}; - process.argv = []; - process.version = ''; // empty string to avoid regexp issues - process.versions = {}; - - function noop() {} - - process.on = noop; - process.addListener = noop; - process.once = noop; - process.off = noop; - process.removeListener = noop; - process.removeAllListeners = noop; - process.emit = noop; - process.prependListener = noop; - process.prependOnceListener = noop; - - process.listeners = function (name) { return [] } - - process.binding = function (name) { - throw new Error('process.binding is not supported'); - }; - - process.cwd = function () { return '/' }; - process.chdir = function (dir) { - throw new Error('process.chdir is not supported'); - }; - process.umask = function() { return 0; }; - - -/***/ }), -/* 5 */ -/***/ (function(module, exports, __webpack_require__) { - - - /** - * 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 = __webpack_require__(6); - - /** - * 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; - } - - -/***/ }), -/* 6 */ -/***/ (function(module, exports) { - - /** - * Helpers. - */ - - var s = 1000; - var m = s * 60; - var h = m * 60; - var d = h * 24; - 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 - */ - - module.exports = function(val, options) { - options = options || {}; - var type = typeof val; - if (type === 'string' && val.length > 0) { - return parse(val); - } else if (type === 'number' && isNaN(val) === false) { - 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|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 '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) { - if (ms >= d) { - return Math.round(ms / d) + 'd'; - } - if (ms >= h) { - return Math.round(ms / h) + 'h'; - } - if (ms >= m) { - return Math.round(ms / m) + 'm'; - } - if (ms >= s) { - return Math.round(ms / s) + 's'; - } - return ms + 'ms'; - } - - /** - * Long format for `ms`. - * - * @param {Number} ms - * @return {String} - * @api private - */ - - function fmtLong(ms) { - return plural(ms, d, 'day') || - plural(ms, h, 'hour') || - plural(ms, m, 'minute') || - plural(ms, s, 'second') || - ms + ' ms'; - } - - /** - * Pluralization helper. - */ - - function plural(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'; - } - - -/***/ }), -/* 7 */ -/***/ (function(module, exports, __webpack_require__) { - - - /** - * Module dependencies. - */ - - var debug = __webpack_require__(3)('socket.io-parser'); - var Emitter = __webpack_require__(8); - var binary = __webpack_require__(9); - var isArray = __webpack_require__(10); - var isBuf = __webpack_require__(11); - - /** - * 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. - */ - - Emitter(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 (isBuf(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 buf = ''; - while (str.charAt(++i) !== '-') { - buf += str.charAt(i); - if (i == str.length) break; - } - 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)) { - p.nsp = ''; - while (++i) { - var c = str.charAt(i); - if (',' === c) break; - p.nsp += c; - if (i === str.length) break; - } - } else { - p.nsp = '/'; - } - - // look up id - var next = str.charAt(i + 1); - if ('' !== next && Number(next) == next) { - p.id = ''; - while (++i) { - var c = str.charAt(i); - if (null == c || Number(c) != c) { - --i; - break; - } - p.id += str.charAt(i); - if (i === str.length) break; - } - p.id = Number(p.id); - } - - // 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 - }; - } - - -/***/ }), -/* 8 */ -/***/ (function(module, exports, __webpack_require__) { - - - /** - * Expose `Emitter`. - */ - - if (true) { - 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; - } - } - 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 = [].slice.call(arguments, 1) - , callbacks = this._callbacks['$' + event]; - - 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; - }; - - -/***/ }), -/* 9 */ -/***/ (function(module, exports, __webpack_require__) { - - /*global Blob,File*/ - - /** - * Module requirements - */ - - var isArray = __webpack_require__(10); - var isBuf = __webpack_require__(11); - var toString = Object.prototype.toString; - var withNativeBlob = typeof Blob === 'function' || (typeof Blob !== 'undefined' && toString.call(Blob) === '[object BlobConstructor]'); - var withNativeFile = typeof File === 'function' || (typeof File !== 'undefined' && toString.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 - */ - - exports.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 (isBuf(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 - */ - - exports.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 - */ - - exports.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' && !isBuf(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); - } - }; - - -/***/ }), -/* 10 */ -/***/ (function(module, exports) { - - var toString = {}.toString; - - module.exports = Array.isArray || function (arr) { - return toString.call(arr) == '[object Array]'; - }; - - -/***/ }), -/* 11 */ -/***/ (function(module, exports) { - - - module.exports = 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))); - } - - -/***/ }), -/* 12 */ -/***/ (function(module, exports, __webpack_require__) { - - 'use strict'; - - var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; - - /** - * Module dependencies. - */ - - var eio = __webpack_require__(13); - var Socket = __webpack_require__(36); - var Emitter = __webpack_require__(8); - var parser = __webpack_require__(7); - var on = __webpack_require__(38); - var bind = __webpack_require__(39); - var debug = __webpack_require__(3)('socket.io-client:manager'); - var indexOf = __webpack_require__(35); - var Backoff = __webpack_require__(40); - - /** - * IE6+ hasOwnProperty - */ - - var has = Object.prototype.hasOwnProperty; - - /** - * Module exports - */ - - module.exports = Manager; - - /** - * `Manager` constructor. - * - * @param {String} engine instance or engine uri/opts - * @param {Object} options - * @api public - */ - - function Manager(uri, opts) { - if (!(this instanceof Manager)) return new Manager(uri, opts); - if (uri && 'object' === (typeof uri === 'undefined' ? 'undefined' : _typeof(uri))) { - opts = uri; - uri = undefined; - } - opts = opts || {}; - - opts.path = opts.path || '/socket.io'; - this.nsps = {}; - this.subs = []; - this.opts = opts; - this.reconnection(opts.reconnection !== false); - this.reconnectionAttempts(opts.reconnectionAttempts || Infinity); - this.reconnectionDelay(opts.reconnectionDelay || 1000); - this.reconnectionDelayMax(opts.reconnectionDelayMax || 5000); - this.randomizationFactor(opts.randomizationFactor || 0.5); - this.backoff = new Backoff({ - min: this.reconnectionDelay(), - max: this.reconnectionDelayMax(), - jitter: this.randomizationFactor() - }); - this.timeout(null == opts.timeout ? 20000 : opts.timeout); - this.readyState = 'closed'; - this.uri = uri; - this.connecting = []; - this.lastPing = null; - this.encoding = false; - this.packetBuffer = []; - var _parser = opts.parser || parser; - this.encoder = new _parser.Encoder(); - this.decoder = new _parser.Decoder(); - this.autoConnect = opts.autoConnect !== false; - if (this.autoConnect) this.open(); - } - - /** - * Propagate given event to sockets and emit on `this` - * - * @api private - */ - - Manager.prototype.emitAll = function () { - this.emit.apply(this, arguments); - for (var nsp in this.nsps) { - if (has.call(this.nsps, nsp)) { - this.nsps[nsp].emit.apply(this.nsps[nsp], arguments); - } - } - }; - - /** - * Update `socket.id` of all sockets - * - * @api private - */ - - Manager.prototype.updateSocketIds = function () { - for (var nsp in this.nsps) { - if (has.call(this.nsps, nsp)) { - this.nsps[nsp].id = this.generateId(nsp); - } - } - }; - - /** - * generate `socket.id` for the given `nsp` - * - * @param {String} nsp - * @return {String} - * @api private - */ - - Manager.prototype.generateId = function (nsp) { - return (nsp === '/' ? '' : nsp + '#') + this.engine.id; - }; - - /** - * Mix in `Emitter`. - */ - - Emitter(Manager.prototype); - - /** - * Sets the `reconnection` config. - * - * @param {Boolean} true/false if it should automatically reconnect - * @return {Manager} self or value - * @api public - */ - - Manager.prototype.reconnection = function (v) { - if (!arguments.length) return this._reconnection; - this._reconnection = !!v; - return this; - }; - - /** - * Sets the reconnection attempts config. - * - * @param {Number} max reconnection attempts before giving up - * @return {Manager} self or value - * @api public - */ - - Manager.prototype.reconnectionAttempts = function (v) { - if (!arguments.length) return this._reconnectionAttempts; - this._reconnectionAttempts = v; - return this; - }; - - /** - * Sets the delay between reconnections. - * - * @param {Number} delay - * @return {Manager} self or value - * @api public - */ - - Manager.prototype.reconnectionDelay = function (v) { - if (!arguments.length) return this._reconnectionDelay; - this._reconnectionDelay = v; - this.backoff && this.backoff.setMin(v); - return this; - }; - - Manager.prototype.randomizationFactor = function (v) { - if (!arguments.length) return this._randomizationFactor; - this._randomizationFactor = v; - this.backoff && this.backoff.setJitter(v); - return this; - }; - - /** - * Sets the maximum delay between reconnections. - * - * @param {Number} delay - * @return {Manager} self or value - * @api public - */ - - Manager.prototype.reconnectionDelayMax = function (v) { - if (!arguments.length) return this._reconnectionDelayMax; - this._reconnectionDelayMax = v; - this.backoff && this.backoff.setMax(v); - return this; - }; - - /** - * Sets the connection timeout. `false` to disable - * - * @return {Manager} self or value - * @api public - */ - - Manager.prototype.timeout = function (v) { - if (!arguments.length) return this._timeout; - this._timeout = v; - return this; - }; - - /** - * Starts trying to reconnect if reconnection is enabled and we have not - * started reconnecting yet - * - * @api private - */ - - Manager.prototype.maybeReconnectOnOpen = function () { - // Only try to reconnect if it's the first time we're connecting - if (!this.reconnecting && this._reconnection && this.backoff.attempts === 0) { - // keeps reconnection from firing twice for the same reconnection loop - this.reconnect(); - } - }; - - /** - * Sets the current transport `socket`. - * - * @param {Function} optional, callback - * @return {Manager} self - * @api public - */ - - Manager.prototype.open = Manager.prototype.connect = function (fn, opts) { - debug('readyState %s', this.readyState); - if (~this.readyState.indexOf('open')) return this; - - debug('opening %s', this.uri); - this.engine = eio(this.uri, this.opts); - var socket = this.engine; - var self = this; - this.readyState = 'opening'; - this.skipReconnect = false; - - // emit `open` - var openSub = on(socket, 'open', function () { - self.onopen(); - fn && fn(); - }); - - // emit `connect_error` - var errorSub = on(socket, 'error', function (data) { - debug('connect_error'); - self.cleanup(); - self.readyState = 'closed'; - self.emitAll('connect_error', data); - if (fn) { - var err = new Error('Connection error'); - err.data = data; - fn(err); - } else { - // Only do this if there is no fn to handle the error - self.maybeReconnectOnOpen(); - } - }); - - // emit `connect_timeout` - if (false !== this._timeout) { - var timeout = this._timeout; - debug('connect attempt will timeout after %d', timeout); - - // set timer - var timer = setTimeout(function () { - debug('connect attempt timed out after %d', timeout); - openSub.destroy(); - socket.close(); - socket.emit('error', 'timeout'); - self.emitAll('connect_timeout', timeout); - }, timeout); - - this.subs.push({ - destroy: function destroy() { - clearTimeout(timer); - } - }); - } - - this.subs.push(openSub); - this.subs.push(errorSub); - - return this; - }; - - /** - * Called upon transport open. - * - * @api private - */ - - Manager.prototype.onopen = function () { - debug('open'); - - // clear old subs - this.cleanup(); - - // mark as open - this.readyState = 'open'; - this.emit('open'); - - // add new subs - var socket = this.engine; - this.subs.push(on(socket, 'data', bind(this, 'ondata'))); - this.subs.push(on(socket, 'ping', bind(this, 'onping'))); - this.subs.push(on(socket, 'pong', bind(this, 'onpong'))); - this.subs.push(on(socket, 'error', bind(this, 'onerror'))); - this.subs.push(on(socket, 'close', bind(this, 'onclose'))); - this.subs.push(on(this.decoder, 'decoded', bind(this, 'ondecoded'))); - }; - - /** - * Called upon a ping. - * - * @api private - */ - - Manager.prototype.onping = function () { - this.lastPing = new Date(); - this.emitAll('ping'); - }; - - /** - * Called upon a packet. - * - * @api private - */ - - Manager.prototype.onpong = function () { - this.emitAll('pong', new Date() - this.lastPing); - }; - - /** - * Called with data. - * - * @api private - */ - - Manager.prototype.ondata = function (data) { - this.decoder.add(data); - }; - - /** - * Called when parser fully decodes a packet. - * - * @api private - */ - - Manager.prototype.ondecoded = function (packet) { - this.emit('packet', packet); - }; - - /** - * Called upon socket error. - * - * @api private - */ - - Manager.prototype.onerror = function (err) { - debug('error', err); - this.emitAll('error', err); - }; - - /** - * Creates a new socket for the given `nsp`. - * - * @return {Socket} - * @api public - */ - - Manager.prototype.socket = function (nsp, opts) { - var socket = this.nsps[nsp]; - if (!socket) { - socket = new Socket(this, nsp, opts); - this.nsps[nsp] = socket; - var self = this; - socket.on('connecting', onConnecting); - socket.on('connect', function () { - socket.id = self.generateId(nsp); - }); - - if (this.autoConnect) { - // manually call here since connecting event is fired before listening - onConnecting(); - } - } - - function onConnecting() { - if (!~indexOf(self.connecting, socket)) { - self.connecting.push(socket); - } - } - - return socket; - }; - - /** - * Called upon a socket close. - * - * @param {Socket} socket - */ - - Manager.prototype.destroy = function (socket) { - var index = indexOf(this.connecting, socket); - if (~index) this.connecting.splice(index, 1); - if (this.connecting.length) return; - - this.close(); - }; - - /** - * Writes a packet. - * - * @param {Object} packet - * @api private - */ - - Manager.prototype.packet = function (packet) { - debug('writing packet %j', packet); - var self = this; - if (packet.query && packet.type === 0) packet.nsp += '?' + packet.query; - - if (!self.encoding) { - // encode, then write to engine with result - self.encoding = true; - this.encoder.encode(packet, function (encodedPackets) { - for (var i = 0; i < encodedPackets.length; i++) { - self.engine.write(encodedPackets[i], packet.options); - } - self.encoding = false; - self.processPacketQueue(); - }); - } else { - // add packet to the queue - self.packetBuffer.push(packet); - } - }; - - /** - * If packet buffer is non-empty, begins encoding the - * next packet in line. - * - * @api private - */ - - Manager.prototype.processPacketQueue = function () { - if (this.packetBuffer.length > 0 && !this.encoding) { - var pack = this.packetBuffer.shift(); - this.packet(pack); - } - }; - - /** - * Clean up transport subscriptions and packet buffer. - * - * @api private - */ - - Manager.prototype.cleanup = function () { - debug('cleanup'); - - var subsLength = this.subs.length; - for (var i = 0; i < subsLength; i++) { - var sub = this.subs.shift(); - sub.destroy(); - } - - this.packetBuffer = []; - this.encoding = false; - this.lastPing = null; - - this.decoder.destroy(); - }; - - /** - * Close the current socket. - * - * @api private - */ - - Manager.prototype.close = Manager.prototype.disconnect = function () { - debug('disconnect'); - this.skipReconnect = true; - this.reconnecting = false; - if ('opening' === this.readyState) { - // `onclose` will not fire because - // an open event never happened - this.cleanup(); - } - this.backoff.reset(); - this.readyState = 'closed'; - if (this.engine) this.engine.close(); - }; - - /** - * Called upon engine close. - * - * @api private - */ - - Manager.prototype.onclose = function (reason) { - debug('onclose'); - - this.cleanup(); - this.backoff.reset(); - this.readyState = 'closed'; - this.emit('close', reason); - - if (this._reconnection && !this.skipReconnect) { - this.reconnect(); - } - }; - - /** - * Attempt a reconnection. - * - * @api private - */ - - Manager.prototype.reconnect = function () { - if (this.reconnecting || this.skipReconnect) return this; - - var self = this; - - if (this.backoff.attempts >= this._reconnectionAttempts) { - debug('reconnect failed'); - this.backoff.reset(); - this.emitAll('reconnect_failed'); - this.reconnecting = false; - } else { - var delay = this.backoff.duration(); - debug('will wait %dms before reconnect attempt', delay); - - this.reconnecting = true; - var timer = setTimeout(function () { - if (self.skipReconnect) return; - - debug('attempting reconnect'); - self.emitAll('reconnect_attempt', self.backoff.attempts); - self.emitAll('reconnecting', self.backoff.attempts); - - // check again for the case socket closed in above events - if (self.skipReconnect) return; - - self.open(function (err) { - if (err) { - debug('reconnect attempt error'); - self.reconnecting = false; - self.reconnect(); - self.emitAll('reconnect_error', err.data); - } else { - debug('reconnect success'); - self.onreconnect(); - } - }); - }, delay); - - this.subs.push({ - destroy: function destroy() { - clearTimeout(timer); - } - }); - } - }; - - /** - * Called upon successful reconnect. - * - * @api private - */ - - Manager.prototype.onreconnect = function () { - var attempt = this.backoff.attempts; - this.reconnecting = false; - this.backoff.reset(); - this.updateSocketIds(); - this.emitAll('reconnect', attempt); - }; - -/***/ }), -/* 13 */ -/***/ (function(module, exports, __webpack_require__) { - - - module.exports = __webpack_require__(14); - - /** - * Exports parser - * - * @api public - * - */ - module.exports.parser = __webpack_require__(21); - - -/***/ }), -/* 14 */ -/***/ (function(module, exports, __webpack_require__) { - - /** - * Module dependencies. - */ - - var transports = __webpack_require__(15); - var Emitter = __webpack_require__(8); - var debug = __webpack_require__(3)('engine.io-client:socket'); - var index = __webpack_require__(35); - var parser = __webpack_require__(21); - var parseuri = __webpack_require__(2); - var parseqs = __webpack_require__(29); - - /** - * Module exports. - */ - - module.exports = Socket; - - /** - * Socket constructor. - * - * @param {String|Object} uri or options - * @param {Object} options - * @api public - */ - - function Socket (uri, opts) { - if (!(this instanceof Socket)) return new Socket(uri, opts); - - opts = opts || {}; - - if (uri && 'object' === typeof uri) { - opts = uri; - uri = null; - } - - if (uri) { - uri = parseuri(uri); - opts.hostname = uri.host; - opts.secure = uri.protocol === 'https' || uri.protocol === 'wss'; - opts.port = uri.port; - if (uri.query) opts.query = uri.query; - } else if (opts.host) { - opts.hostname = parseuri(opts.host).host; - } - - this.secure = null != opts.secure ? opts.secure - : (typeof location !== 'undefined' && 'https:' === location.protocol); - - if (opts.hostname && !opts.port) { - // if no port is specified manually, use the protocol default - opts.port = this.secure ? '443' : '80'; - } - - this.agent = opts.agent || false; - this.hostname = opts.hostname || - (typeof location !== 'undefined' ? location.hostname : 'localhost'); - this.port = opts.port || (typeof location !== 'undefined' && location.port - ? location.port - : (this.secure ? 443 : 80)); - this.query = opts.query || {}; - if ('string' === typeof this.query) this.query = parseqs.decode(this.query); - this.upgrade = false !== opts.upgrade; - this.path = (opts.path || '/engine.io').replace(/\/$/, '') + '/'; - this.forceJSONP = !!opts.forceJSONP; - this.jsonp = false !== opts.jsonp; - this.forceBase64 = !!opts.forceBase64; - this.enablesXDR = !!opts.enablesXDR; - this.timestampParam = opts.timestampParam || 't'; - this.timestampRequests = opts.timestampRequests; - this.transports = opts.transports || ['polling', 'websocket']; - this.transportOptions = opts.transportOptions || {}; - this.readyState = ''; - this.writeBuffer = []; - this.prevBufferLen = 0; - this.policyPort = opts.policyPort || 843; - this.rememberUpgrade = opts.rememberUpgrade || false; - this.binaryType = null; - this.onlyBinaryUpgrades = opts.onlyBinaryUpgrades; - this.perMessageDeflate = false !== opts.perMessageDeflate ? (opts.perMessageDeflate || {}) : false; - - if (true === this.perMessageDeflate) this.perMessageDeflate = {}; - if (this.perMessageDeflate && null == this.perMessageDeflate.threshold) { - this.perMessageDeflate.threshold = 1024; - } - - // SSL options for Node.js client - this.pfx = opts.pfx || null; - this.key = opts.key || null; - this.passphrase = opts.passphrase || null; - this.cert = opts.cert || null; - this.ca = opts.ca || null; - this.ciphers = opts.ciphers || null; - this.rejectUnauthorized = opts.rejectUnauthorized === undefined ? true : opts.rejectUnauthorized; - this.forceNode = !!opts.forceNode; - - // detect ReactNative environment - this.isReactNative = (typeof navigator !== 'undefined' && typeof navigator.product === 'string' && navigator.product.toLowerCase() === 'reactnative'); - - // other options for Node.js or ReactNative client - if (typeof self === 'undefined' || this.isReactNative) { - if (opts.extraHeaders && Object.keys(opts.extraHeaders).length > 0) { - this.extraHeaders = opts.extraHeaders; - } - - if (opts.localAddress) { - this.localAddress = opts.localAddress; - } - } - - // set on handshake - this.id = null; - this.upgrades = null; - this.pingInterval = null; - this.pingTimeout = null; - - // set on heartbeat - this.pingIntervalTimer = null; - this.pingTimeoutTimer = null; - - this.open(); - } - - Socket.priorWebsocketSuccess = false; - - /** - * Mix in `Emitter`. - */ - - Emitter(Socket.prototype); - - /** - * Protocol version. - * - * @api public - */ - - Socket.protocol = parser.protocol; // this is an int - - /** - * Expose deps for legacy compatibility - * and standalone browser access. - */ - - Socket.Socket = Socket; - Socket.Transport = __webpack_require__(20); - Socket.transports = __webpack_require__(15); - Socket.parser = __webpack_require__(21); - - /** - * Creates transport of the given type. - * - * @param {String} transport name - * @return {Transport} - * @api private - */ - - Socket.prototype.createTransport = function (name) { - debug('creating transport "%s"', name); - var query = clone(this.query); - - // append engine.io protocol identifier - query.EIO = parser.protocol; - - // transport name - query.transport = name; - - // per-transport options - var options = this.transportOptions[name] || {}; - - // session id if we already have one - if (this.id) query.sid = this.id; - - var transport = new transports[name]({ - query: query, - socket: this, - agent: options.agent || this.agent, - hostname: options.hostname || this.hostname, - port: options.port || this.port, - secure: options.secure || this.secure, - path: options.path || this.path, - forceJSONP: options.forceJSONP || this.forceJSONP, - jsonp: options.jsonp || this.jsonp, - forceBase64: options.forceBase64 || this.forceBase64, - enablesXDR: options.enablesXDR || this.enablesXDR, - timestampRequests: options.timestampRequests || this.timestampRequests, - timestampParam: options.timestampParam || this.timestampParam, - policyPort: options.policyPort || this.policyPort, - pfx: options.pfx || this.pfx, - key: options.key || this.key, - passphrase: options.passphrase || this.passphrase, - cert: options.cert || this.cert, - ca: options.ca || this.ca, - ciphers: options.ciphers || this.ciphers, - rejectUnauthorized: options.rejectUnauthorized || this.rejectUnauthorized, - perMessageDeflate: options.perMessageDeflate || this.perMessageDeflate, - extraHeaders: options.extraHeaders || this.extraHeaders, - forceNode: options.forceNode || this.forceNode, - localAddress: options.localAddress || this.localAddress, - requestTimeout: options.requestTimeout || this.requestTimeout, - protocols: options.protocols || void (0), - isReactNative: this.isReactNative - }); - - return transport; - }; - - function clone (obj) { - var o = {}; - for (var i in obj) { - if (obj.hasOwnProperty(i)) { - o[i] = obj[i]; - } - } - return o; - } - - /** - * Initializes transport to use and starts probe. - * - * @api private - */ - Socket.prototype.open = function () { - var transport; - if (this.rememberUpgrade && Socket.priorWebsocketSuccess && this.transports.indexOf('websocket') !== -1) { - transport = 'websocket'; - } else if (0 === this.transports.length) { - // Emit error on next tick so it can be listened to - var self = this; - setTimeout(function () { - self.emit('error', 'No transports available'); - }, 0); - return; - } else { - transport = this.transports[0]; - } - this.readyState = 'opening'; - - // Retry with the next transport if the transport is disabled (jsonp: false) - try { - transport = this.createTransport(transport); - } catch (e) { - this.transports.shift(); - this.open(); - return; - } - - transport.open(); - this.setTransport(transport); - }; - - /** - * Sets the current transport. Disables the existing one (if any). - * - * @api private - */ - - Socket.prototype.setTransport = function (transport) { - debug('setting transport %s', transport.name); - var self = this; - - if (this.transport) { - debug('clearing existing transport %s', this.transport.name); - this.transport.removeAllListeners(); - } - - // set up transport - this.transport = transport; - - // set up transport listeners - transport - .on('drain', function () { - self.onDrain(); - }) - .on('packet', function (packet) { - self.onPacket(packet); - }) - .on('error', function (e) { - self.onError(e); - }) - .on('close', function () { - self.onClose('transport close'); - }); - }; - - /** - * Probes a transport. - * - * @param {String} transport name - * @api private - */ - - Socket.prototype.probe = function (name) { - debug('probing transport "%s"', name); - var transport = this.createTransport(name, { probe: 1 }); - var failed = false; - var self = this; - - Socket.priorWebsocketSuccess = false; - - function onTransportOpen () { - if (self.onlyBinaryUpgrades) { - var upgradeLosesBinary = !this.supportsBinary && self.transport.supportsBinary; - failed = failed || upgradeLosesBinary; - } - if (failed) return; - - debug('probe transport "%s" opened', name); - transport.send([{ type: 'ping', data: 'probe' }]); - transport.once('packet', function (msg) { - if (failed) return; - if ('pong' === msg.type && 'probe' === msg.data) { - debug('probe transport "%s" pong', name); - self.upgrading = true; - self.emit('upgrading', transport); - if (!transport) return; - Socket.priorWebsocketSuccess = 'websocket' === transport.name; - - debug('pausing current transport "%s"', self.transport.name); - self.transport.pause(function () { - if (failed) return; - if ('closed' === self.readyState) return; - debug('changing transport and sending upgrade packet'); - - cleanup(); - - self.setTransport(transport); - transport.send([{ type: 'upgrade' }]); - self.emit('upgrade', transport); - transport = null; - self.upgrading = false; - self.flush(); - }); - } else { - debug('probe transport "%s" failed', name); - var err = new Error('probe error'); - err.transport = transport.name; - self.emit('upgradeError', err); - } - }); - } - - function freezeTransport () { - if (failed) return; - - // Any callback called by transport should be ignored since now - failed = true; - - cleanup(); - - transport.close(); - transport = null; - } - - // Handle any error that happens while probing - function onerror (err) { - var error = new Error('probe error: ' + err); - error.transport = transport.name; - - freezeTransport(); - - debug('probe transport "%s" failed because of error: %s', name, err); - - self.emit('upgradeError', error); - } - - function onTransportClose () { - onerror('transport closed'); - } - - // When the socket is closed while we're probing - function onclose () { - onerror('socket closed'); - } - - // When the socket is upgraded while we're probing - function onupgrade (to) { - if (transport && to.name !== transport.name) { - debug('"%s" works - aborting "%s"', to.name, transport.name); - freezeTransport(); - } - } - - // Remove all listeners on the transport and on self - function cleanup () { - transport.removeListener('open', onTransportOpen); - transport.removeListener('error', onerror); - transport.removeListener('close', onTransportClose); - self.removeListener('close', onclose); - self.removeListener('upgrading', onupgrade); - } - - transport.once('open', onTransportOpen); - transport.once('error', onerror); - transport.once('close', onTransportClose); - - this.once('close', onclose); - this.once('upgrading', onupgrade); - - transport.open(); - }; - - /** - * Called when connection is deemed open. - * - * @api public - */ - - Socket.prototype.onOpen = function () { - debug('socket open'); - this.readyState = 'open'; - Socket.priorWebsocketSuccess = 'websocket' === this.transport.name; - this.emit('open'); - this.flush(); - - // we check for `readyState` in case an `open` - // listener already closed the socket - if ('open' === this.readyState && this.upgrade && this.transport.pause) { - debug('starting upgrade probes'); - for (var i = 0, l = this.upgrades.length; i < l; i++) { - this.probe(this.upgrades[i]); - } - } - }; - - /** - * Handles a packet. - * - * @api private - */ - - Socket.prototype.onPacket = function (packet) { - if ('opening' === this.readyState || 'open' === this.readyState || - 'closing' === this.readyState) { - debug('socket receive: type "%s", data "%s"', packet.type, packet.data); - - this.emit('packet', packet); - - // Socket is live - any packet counts - this.emit('heartbeat'); - - switch (packet.type) { - case 'open': - this.onHandshake(JSON.parse(packet.data)); - break; - - case 'pong': - this.setPing(); - this.emit('pong'); - break; - - case 'error': - var err = new Error('server error'); - err.code = packet.data; - this.onError(err); - break; - - case 'message': - this.emit('data', packet.data); - this.emit('message', packet.data); - break; - } - } else { - debug('packet received with socket readyState "%s"', this.readyState); - } - }; - - /** - * Called upon handshake completion. - * - * @param {Object} handshake obj - * @api private - */ - - Socket.prototype.onHandshake = function (data) { - this.emit('handshake', data); - this.id = data.sid; - this.transport.query.sid = data.sid; - this.upgrades = this.filterUpgrades(data.upgrades); - this.pingInterval = data.pingInterval; - this.pingTimeout = data.pingTimeout; - this.onOpen(); - // In case open handler closes socket - if ('closed' === this.readyState) return; - this.setPing(); - - // Prolong liveness of socket on heartbeat - this.removeListener('heartbeat', this.onHeartbeat); - this.on('heartbeat', this.onHeartbeat); - }; - - /** - * Resets ping timeout. - * - * @api private - */ - - Socket.prototype.onHeartbeat = function (timeout) { - clearTimeout(this.pingTimeoutTimer); - var self = this; - self.pingTimeoutTimer = setTimeout(function () { - if ('closed' === self.readyState) return; - self.onClose('ping timeout'); - }, timeout || (self.pingInterval + self.pingTimeout)); - }; - - /** - * Pings server every `this.pingInterval` and expects response - * within `this.pingTimeout` or closes connection. - * - * @api private - */ - - Socket.prototype.setPing = function () { - var self = this; - clearTimeout(self.pingIntervalTimer); - self.pingIntervalTimer = setTimeout(function () { - debug('writing ping packet - expecting pong within %sms', self.pingTimeout); - self.ping(); - self.onHeartbeat(self.pingTimeout); - }, self.pingInterval); - }; - - /** - * Sends a ping packet. - * - * @api private - */ - - Socket.prototype.ping = function () { - var self = this; - this.sendPacket('ping', function () { - self.emit('ping'); - }); - }; - - /** - * Called on `drain` event - * - * @api private - */ - - Socket.prototype.onDrain = function () { - this.writeBuffer.splice(0, this.prevBufferLen); - - // setting prevBufferLen = 0 is very important - // for example, when upgrading, upgrade packet is sent over, - // and a nonzero prevBufferLen could cause problems on `drain` - this.prevBufferLen = 0; - - if (0 === this.writeBuffer.length) { - this.emit('drain'); - } else { - this.flush(); - } - }; - - /** - * Flush write buffers. - * - * @api private - */ - - Socket.prototype.flush = function () { - if ('closed' !== this.readyState && this.transport.writable && - !this.upgrading && this.writeBuffer.length) { - debug('flushing %d packets in socket', this.writeBuffer.length); - this.transport.send(this.writeBuffer); - // keep track of current length of writeBuffer - // splice writeBuffer and callbackBuffer on `drain` - this.prevBufferLen = this.writeBuffer.length; - this.emit('flush'); - } - }; - - /** - * Sends a message. - * - * @param {String} message. - * @param {Function} callback function. - * @param {Object} options. - * @return {Socket} for chaining. - * @api public - */ - - Socket.prototype.write = - Socket.prototype.send = function (msg, options, fn) { - this.sendPacket('message', msg, options, fn); - return this; - }; - - /** - * Sends a packet. - * - * @param {String} packet type. - * @param {String} data. - * @param {Object} options. - * @param {Function} callback function. - * @api private - */ - - Socket.prototype.sendPacket = function (type, data, options, fn) { - if ('function' === typeof data) { - fn = data; - data = undefined; - } - - if ('function' === typeof options) { - fn = options; - options = null; - } - - if ('closing' === this.readyState || 'closed' === this.readyState) { - return; - } - - options = options || {}; - options.compress = false !== options.compress; - - var packet = { - type: type, - data: data, - options: options - }; - this.emit('packetCreate', packet); - this.writeBuffer.push(packet); - if (fn) this.once('flush', fn); - this.flush(); - }; - - /** - * Closes the connection. - * - * @api private - */ - - Socket.prototype.close = function () { - if ('opening' === this.readyState || 'open' === this.readyState) { - this.readyState = 'closing'; - - var self = this; - - if (this.writeBuffer.length) { - this.once('drain', function () { - if (this.upgrading) { - waitForUpgrade(); - } else { - close(); - } - }); - } else if (this.upgrading) { - waitForUpgrade(); - } else { - close(); - } - } - - function close () { - self.onClose('forced close'); - debug('socket closing - telling transport to close'); - self.transport.close(); - } - - function cleanupAndClose () { - self.removeListener('upgrade', cleanupAndClose); - self.removeListener('upgradeError', cleanupAndClose); - close(); - } - - function waitForUpgrade () { - // wait for upgrade to finish since we can't send packets while pausing a transport - self.once('upgrade', cleanupAndClose); - self.once('upgradeError', cleanupAndClose); - } - - return this; - }; - - /** - * Called upon transport error - * - * @api private - */ - - Socket.prototype.onError = function (err) { - debug('socket error %j', err); - Socket.priorWebsocketSuccess = false; - this.emit('error', err); - this.onClose('transport error', err); - }; - - /** - * Called upon transport close. - * - * @api private - */ - - Socket.prototype.onClose = function (reason, desc) { - if ('opening' === this.readyState || 'open' === this.readyState || 'closing' === this.readyState) { - debug('socket close with reason: "%s"', reason); - var self = this; - - // clear timers - clearTimeout(this.pingIntervalTimer); - clearTimeout(this.pingTimeoutTimer); - - // stop event from firing again for transport - this.transport.removeAllListeners('close'); - - // ensure transport won't stay open - this.transport.close(); - - // ignore further transport communication - this.transport.removeAllListeners(); - - // set ready state - this.readyState = 'closed'; - - // clear session id - this.id = null; - - // emit close event - this.emit('close', reason, desc); - - // clean buffers after, so users can still - // grab the buffers on `close` event - self.writeBuffer = []; - self.prevBufferLen = 0; - } - }; - - /** - * Filters upgrades, returning only those matching client transports. - * - * @param {Array} server upgrades - * @api private - * - */ - - Socket.prototype.filterUpgrades = function (upgrades) { - var filteredUpgrades = []; - for (var i = 0, j = upgrades.length; i < j; i++) { - if (~index(this.transports, upgrades[i])) filteredUpgrades.push(upgrades[i]); - } - return filteredUpgrades; - }; - - -/***/ }), -/* 15 */ -/***/ (function(module, exports, __webpack_require__) { - - /** - * Module dependencies - */ - - var XMLHttpRequest = __webpack_require__(16); - var XHR = __webpack_require__(18); - var JSONP = __webpack_require__(32); - var websocket = __webpack_require__(33); - - /** - * Export transports. - */ - - exports.polling = polling; - exports.websocket = websocket; - - /** - * Polling transport polymorphic constructor. - * Decides on xhr vs jsonp based on feature detection. - * - * @api private - */ - - function polling (opts) { - var xhr; - var xd = false; - var xs = false; - var jsonp = false !== opts.jsonp; - - 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; - } - - xd = opts.hostname !== location.hostname || port !== opts.port; - xs = opts.secure !== isSSL; - } - - opts.xdomain = xd; - opts.xscheme = xs; - xhr = new XMLHttpRequest(opts); - - if ('open' in xhr && !opts.forceJSONP) { - return new XHR(opts); - } else { - if (!jsonp) throw new Error('JSONP disabled'); - return new JSONP(opts); - } - } - - -/***/ }), -/* 16 */ -/***/ (function(module, exports, __webpack_require__) { - - // browser shim for xmlhttprequest module - - var hasCORS = __webpack_require__(17); - - module.exports = function (opts) { - var xdomain = opts.xdomain; - - // scheme must be same when usign XDomainRequest - // http://blogs.msdn.com/b/ieinternals/archive/2010/05/13/xdomainrequest-restrictions-limitations-and-workarounds.aspx - var xscheme = opts.xscheme; - - // XDomainRequest has a flow of not sending cookie, therefore it should be disabled as a default. - // https://github.com/Automattic/engine.io-client/pull/217 - var enablesXDR = opts.enablesXDR; - - // XMLHttpRequest can be disabled on IE - try { - if ('undefined' !== typeof XMLHttpRequest && (!xdomain || hasCORS)) { - return new XMLHttpRequest(); - } - } catch (e) { } - - // Use XDomainRequest for IE8 if enablesXDR is true - // because loading bar keeps flashing when using jsonp-polling - // https://github.com/yujiosaka/socke.io-ie8-loading-example - try { - if ('undefined' !== typeof XDomainRequest && !xscheme && enablesXDR) { - return new XDomainRequest(); - } - } catch (e) { } - - if (!xdomain) { - try { - return new self[['Active'].concat('Object').join('X')]('Microsoft.XMLHTTP'); - } catch (e) { } - } - }; - - -/***/ }), -/* 17 */ -/***/ (function(module, exports) { - - - /** - * Module exports. - * - * Logic borrowed from Modernizr: - * - * - https://github.com/Modernizr/Modernizr/blob/master/feature-detects/cors.js - */ - - try { - module.exports = typeof XMLHttpRequest !== 'undefined' && - 'withCredentials' in new XMLHttpRequest(); - } catch (err) { - // if XMLHttp support is disabled in IE then it will throw - // when trying to create - module.exports = false; - } - - -/***/ }), -/* 18 */ -/***/ (function(module, exports, __webpack_require__) { - - /* global attachEvent */ - - /** - * Module requirements. - */ - - var XMLHttpRequest = __webpack_require__(16); - var Polling = __webpack_require__(19); - var Emitter = __webpack_require__(8); - var inherit = __webpack_require__(30); - var debug = __webpack_require__(3)('engine.io-client:polling-xhr'); - - /** - * Module exports. - */ - - module.exports = XHR; - module.exports.Request = 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. - */ - - inherit(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; - - // 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('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.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`. - */ - - Emitter(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(opts); - var self = this; - - try { - debug('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 = true; - } - - 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') { - 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(xhr.status); - }, 0); - } - }; - } - - debug('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') { - 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 self ? 'pagehide' : 'unload'; - addEventListener(terminationEvent, unloadHandler, false); - } - } - - function unloadHandler () { - for (var i in Request.requests) { - if (Request.requests.hasOwnProperty(i)) { - Request.requests[i].abort(); - } - } - } - - -/***/ }), -/* 19 */ -/***/ (function(module, exports, __webpack_require__) { - - /** - * Module dependencies. - */ - - var Transport = __webpack_require__(20); - var parseqs = __webpack_require__(29); - var parser = __webpack_require__(21); - var inherit = __webpack_require__(30); - var yeast = __webpack_require__(31); - var debug = __webpack_require__(3)('engine.io-client:polling'); - - /** - * Module exports. - */ - - module.exports = Polling; - - /** - * Is XHR2 supported? - */ - - var hasXHR2 = (function () { - var XMLHttpRequest = __webpack_require__(16); - 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. - */ - - inherit(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('paused'); - self.readyState = 'paused'; - onPause(); - } - - if (this.polling || !this.writable) { - var total = 0; - - if (this.polling) { - debug('we are currently polling - waiting to pause'); - total++; - this.once('pollComplete', function () { - debug('pre-pause polling complete'); - --total || pause(); - }); - } - - if (!this.writable) { - debug('we are currently writing - waiting to pause'); - total++; - this.once('drain', function () { - debug('pre-pause writing complete'); - --total || pause(); - }); - } - } else { - pause(); - } - }; - - /** - * Starts polling cycle. - * - * @api public - */ - - Polling.prototype.poll = function () { - debug('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('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 - parser.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('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('writing close packet'); - self.write([{ type: 'close' }]); - } - - if ('open' === this.readyState) { - debug('transport open - closing'); - close(); - } else { - // in case we're trying to close while - // handshaking is in progress (GH-164) - debug('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'); - }; - - parser.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(); - } - - 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; - }; - - -/***/ }), -/* 20 */ -/***/ (function(module, exports, __webpack_require__) { - - /** - * Module dependencies. - */ - - var parser = __webpack_require__(21); - var Emitter = __webpack_require__(8); - - /** - * Module exports. - */ - - module.exports = 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; - - // 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`. - */ - - Emitter(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 = parser.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'); - }; - - -/***/ }), -/* 21 */ -/***/ (function(module, exports, __webpack_require__) { - - /** - * Module dependencies. - */ - - var keys = __webpack_require__(22); - var hasBinary = __webpack_require__(23); - var sliceBuffer = __webpack_require__(24); - var after = __webpack_require__(25); - var utf8 = __webpack_require__(26); - - var base64encoder; - if (typeof ArrayBuffer !== 'undefined') { - base64encoder = __webpack_require__(27); - } - - /** - * Check if we are running an android browser. That requires us to use - * ArrayBuffer with polling transports... - * - * http://ghinda.net/jpeg-blob-ajax-android/ - */ - - var isAndroid = typeof navigator !== 'undefined' && /Android/i.test(navigator.userAgent); - - /** - * Check if we are running in PhantomJS. - * Uploading a Blob with PhantomJS does not work correctly, as reported here: - * https://github.com/ariya/phantomjs/issues/11395 - * @type boolean - */ - var isPhantomJS = typeof navigator !== 'undefined' && /PhantomJS/i.test(navigator.userAgent); - - /** - * When true, avoids using Blobs to encode payloads. - * @type boolean - */ - var dontSendBlobs = isAndroid || isPhantomJS; - - /** - * 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' }; - - /** - * Create a blob api even for blob builder when vendor prefixes exist - */ - - var Blob = __webpack_require__(28); - - /** - * 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 = false; - } - - if (typeof utf8encode === 'function') { - callback = utf8encode; - utf8encode = null; - } - - var data = (packet.data === undefined) - ? undefined - : packet.data.buffer || packet.data; - - if (typeof ArrayBuffer !== 'undefined' && data instanceof ArrayBuffer) { - return encodeArrayBuffer(packet, supportsBinary, callback); - } else if (typeof Blob !== 'undefined' && data instanceof Blob) { - return encodeBlob(packet, supportsBinary, callback); - } - - // might be an object with { base64: true, data: dataAsBase64String } - if (data && data.base64) { - return encodeBase64Object(packet, 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); - - }; - - function encodeBase64Object(packet, callback) { - // packet data is an object { base64: true, data: dataAsBase64String } - var message = 'b' + exports.packets[packet.type] + packet.data.data; - return callback(message); - } - - /** - * Encode packet helpers for binary types - */ - - function encodeArrayBuffer(packet, supportsBinary, callback) { - if (!supportsBinary) { - return exports.encodeBase64Packet(packet, callback); - } - - var data = packet.data; - var contentArray = new Uint8Array(data); - var resultBuffer = new Uint8Array(1 + data.byteLength); - - resultBuffer[0] = packets[packet.type]; - for (var i = 0; i < contentArray.length; i++) { - resultBuffer[i+1] = contentArray[i]; - } - - return callback(resultBuffer.buffer); - } - - function encodeBlobAsArrayBuffer(packet, supportsBinary, callback) { - if (!supportsBinary) { - return exports.encodeBase64Packet(packet, callback); - } - - var fr = new FileReader(); - fr.onload = function() { - exports.encodePacket({ type: packet.type, data: fr.result }, supportsBinary, true, callback); - }; - return fr.readAsArrayBuffer(packet.data); - } - - function encodeBlob(packet, supportsBinary, callback) { - if (!supportsBinary) { - return exports.encodeBase64Packet(packet, callback); - } - - if (dontSendBlobs) { - return encodeBlobAsArrayBuffer(packet, supportsBinary, callback); - } - - var length = new Uint8Array(1); - length[0] = packets[packet.type]; - var blob = new Blob([length.buffer, packet.data]); - - return callback(blob); - } - - /** - * 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 message = 'b' + exports.packets[packet.type]; - if (typeof Blob !== 'undefined' && packet.data instanceof Blob) { - var fr = new FileReader(); - fr.onload = function() { - var b64 = fr.result.split(',')[1]; - callback(message + b64); - }; - return fr.readAsDataURL(packet.data); - } - - var b64data; - try { - b64data = String.fromCharCode.apply(null, new Uint8Array(packet.data)); - } catch (e) { - // iPhone Safari doesn't let you apply with typed arrays - var typed = new Uint8Array(packet.data); - var basic = new Array(typed.length); - for (var i = 0; i < typed.length; i++) { - basic[i] = typed[i]; - } - b64data = String.fromCharCode.apply(null, basic); - } - message += btoa(b64data); - return callback(message); - }; - - /** - * Decodes a packet. Changes format to Blob if requested. - * - * @return {Object} with `type` and `data` (if any) - * @api private - */ - - exports.decodePacket = function (data, binaryType, utf8decode) { - if (data === undefined) { - return err; - } - // String data - if (typeof data === 'string') { - if (data.charAt(0) === 'b') { - return exports.decodeBase64Packet(data.substr(1), binaryType); - } - - if (utf8decode) { - data = tryDecode(data); - if (data === false) { - return err; - } - } - var type = data.charAt(0); - - 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] }; - } - } - - var asArray = new Uint8Array(data); - var type = asArray[0]; - var rest = sliceBuffer(data, 1); - if (Blob && binaryType === 'blob') { - rest = new Blob([rest]); - } - return { type: packetslist[type], data: rest }; - }; - - 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)]; - if (!base64encoder) { - return { type: type, data: { base64: true, data: msg.substr(1) } }; - } - - var data = base64encoder.decode(msg.substr(1)); - - if (binaryType === 'blob' && Blob) { - data = new Blob([data]); - } - - 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; - } - - var isBinary = hasBinary(packets); - - if (supportsBinary && isBinary) { - if (Blob && !dontSendBlobs) { - return exports.encodePayloadAsBlob(packets, callback); - } - - return exports.encodePayloadAsArrayBuffer(packets, callback); - } - - if (!packets.length) { - return callback('0:'); - } - - function setLengthHeader(message) { - return message.length + ':' + message; - } - - function encodeOne(packet, doneCallback) { - exports.encodePacket(packet, !isBinary ? false : supportsBinary, false, function(message) { - doneCallback(null, setLengthHeader(message)); - }); - } - - map(packets, encodeOne, function(err, results) { - return callback(results.join('')); - }); - }; - - /** - * Async array map using after - */ - - function map(ary, each, done) { - var result = new Array(ary.length); - var next = after(ary.length, done); - - var eachWithIndex = function(i, el, cb) { - each(el, function(error, msg) { - result[i] = msg; - cb(error, result); - }); - }; - - for (var i = 0; i < ary.length; i++) { - eachWithIndex(i, ary[i], next); - } - } - - /* - * 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; - } - - var packet; - if (data === '') { - // parser error - ignoring payload - return callback(err, 0, 1); - } - - var length = '', n, msg; - - 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 ret = callback(packet, i + n, l); - if (false === ret) return; - } - - // advance cursor - i += n; - length = ''; - } - - if (length !== '') { - // parser error - ignoring payload - return callback(err, 0, 1); - } - - }; - - /** - * 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 {ArrayBuffer} encoded payload - * @api private - */ - - exports.encodePayloadAsArrayBuffer = function(packets, callback) { - if (!packets.length) { - return callback(new ArrayBuffer(0)); - } - - function encodeOne(packet, doneCallback) { - exports.encodePacket(packet, true, true, function(data) { - return doneCallback(null, data); - }); - } - - map(packets, encodeOne, function(err, encodedPackets) { - var totalLength = encodedPackets.reduce(function(acc, p) { - var len; - if (typeof p === 'string'){ - len = p.length; - } else { - len = p.byteLength; - } - return acc + len.toString().length + len + 2; // string/binary identifier + separator = 2 - }, 0); - - var resultArray = new Uint8Array(totalLength); - - var bufferIndex = 0; - encodedPackets.forEach(function(p) { - var isString = typeof p === 'string'; - var ab = p; - if (isString) { - var view = new Uint8Array(p.length); - for (var i = 0; i < p.length; i++) { - view[i] = p.charCodeAt(i); - } - ab = view.buffer; - } - - if (isString) { // not true binary - resultArray[bufferIndex++] = 0; - } else { // true binary - resultArray[bufferIndex++] = 1; - } - - var lenStr = ab.byteLength.toString(); - for (var i = 0; i < lenStr.length; i++) { - resultArray[bufferIndex++] = parseInt(lenStr[i]); - } - resultArray[bufferIndex++] = 255; - - var view = new Uint8Array(ab); - for (var i = 0; i < view.length; i++) { - resultArray[bufferIndex++] = view[i]; - } - }); - - return callback(resultArray.buffer); - }); - }; - - /** - * Encode as Blob - */ - - exports.encodePayloadAsBlob = function(packets, callback) { - function encodeOne(packet, doneCallback) { - exports.encodePacket(packet, true, true, function(encoded) { - var binaryIdentifier = new Uint8Array(1); - binaryIdentifier[0] = 1; - if (typeof encoded === 'string') { - var view = new Uint8Array(encoded.length); - for (var i = 0; i < encoded.length; i++) { - view[i] = encoded.charCodeAt(i); - } - encoded = view.buffer; - binaryIdentifier[0] = 0; - } - - var len = (encoded instanceof ArrayBuffer) - ? encoded.byteLength - : encoded.size; - - var lenStr = len.toString(); - var lengthAry = new Uint8Array(lenStr.length + 1); - for (var i = 0; i < lenStr.length; i++) { - lengthAry[i] = parseInt(lenStr[i]); - } - lengthAry[lenStr.length] = 255; - - if (Blob) { - var blob = new Blob([binaryIdentifier.buffer, lengthAry.buffer, encoded]); - doneCallback(null, blob); - } - }); - } - - map(packets, encodeOne, function(err, results) { - return callback(new Blob(results)); - }); - }; - - /* - * 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 {ArrayBuffer} data, callback method - * @api public - */ - - exports.decodePayloadAsBinary = function (data, binaryType, callback) { - if (typeof binaryType === 'function') { - callback = binaryType; - binaryType = null; - } - - var bufferTail = data; - var buffers = []; - - while (bufferTail.byteLength > 0) { - var tailArray = new Uint8Array(bufferTail); - var isString = tailArray[0] === 0; - var msgLength = ''; - - for (var i = 1; ; i++) { - if (tailArray[i] === 255) break; - - // 310 = char length of Number.MAX_VALUE - if (msgLength.length > 310) { - return callback(err, 0, 1); - } - - msgLength += tailArray[i]; - } - - bufferTail = sliceBuffer(bufferTail, 2 + msgLength.length); - msgLength = parseInt(msgLength); - - var msg = sliceBuffer(bufferTail, 0, msgLength); - if (isString) { - try { - msg = String.fromCharCode.apply(null, new Uint8Array(msg)); - } catch (e) { - // iPhone Safari doesn't let you apply to typed arrays - var typed = new Uint8Array(msg); - msg = ''; - for (var i = 0; i < typed.length; i++) { - msg += String.fromCharCode(typed[i]); - } - } - } - - buffers.push(msg); - bufferTail = sliceBuffer(bufferTail, msgLength); - } - - var total = buffers.length; - buffers.forEach(function(buffer, i) { - callback(exports.decodePacket(buffer, binaryType, true), i, total); - }); - }; - - -/***/ }), -/* 22 */ -/***/ (function(module, exports) { - - - /** - * Gets the keys for an object. - * - * @return {Array} keys - * @api private - */ - - module.exports = 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; - }; - - -/***/ }), -/* 23 */ -/***/ (function(module, exports, __webpack_require__) { - - /* global Blob File */ - - /* - * Module requirements. - */ - - var isArray = __webpack_require__(10); - - var toString = Object.prototype.toString; - var withNativeBlob = typeof Blob === 'function' || - typeof Blob !== 'undefined' && toString.call(Blob) === '[object BlobConstructor]'; - var withNativeFile = typeof File === 'function' || - typeof File !== 'undefined' && toString.call(File) === '[object FileConstructor]'; - - /** - * Module exports. - */ - - module.exports = 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(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 && obj instanceof Blob) || - (withNativeFile && 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; - } - - -/***/ }), -/* 24 */ -/***/ (function(module, exports) { - - /** - * An abstraction for slicing an arraybuffer even when - * ArrayBuffer.prototype.slice is not supported - * - * @api public - */ - - module.exports = function(arraybuffer, start, end) { - var bytes = arraybuffer.byteLength; - start = start || 0; - end = end || bytes; - - if (arraybuffer.slice) { return arraybuffer.slice(start, end); } - - if (start < 0) { start += bytes; } - if (end < 0) { end += bytes; } - if (end > bytes) { end = bytes; } - - if (start >= bytes || start >= end || bytes === 0) { - return new ArrayBuffer(0); - } - - var abv = new Uint8Array(arraybuffer); - var result = new Uint8Array(end - start); - for (var i = start, ii = 0; i < end; i++, ii++) { - result[ii] = abv[i]; - } - return result.buffer; - }; - - -/***/ }), -/* 25 */ -/***/ (function(module, exports) { - - module.exports = 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() {} - - -/***/ }), -/* 26 */ -/***/ (function(module, exports) { - - /*! 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); - } - - module.exports = { - version: '2.1.2', - encode: utf8encode, - decode: utf8decode - }; - - -/***/ }), -/* 27 */ -/***/ (function(module, exports) { - - /* - * base64-arraybuffer - * https://github.com/niklasvh/base64-arraybuffer - * - * Copyright (c) 2012 Niklas von Hertzen - * Licensed under the MIT license. - */ - (function(){ - "use strict"; - - var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - - // Use a lookup table to find the index. - var lookup = new Uint8Array(256); - for (var i = 0; i < chars.length; i++) { - lookup[chars.charCodeAt(i)] = i; - } - - exports.encode = function(arraybuffer) { - var bytes = new Uint8Array(arraybuffer), - i, len = bytes.length, base64 = ""; - - for (i = 0; i < len; i+=3) { - base64 += chars[bytes[i] >> 2]; - base64 += chars[((bytes[i] & 3) << 4) | (bytes[i + 1] >> 4)]; - base64 += chars[((bytes[i + 1] & 15) << 2) | (bytes[i + 2] >> 6)]; - base64 += chars[bytes[i + 2] & 63]; - } - - if ((len % 3) === 2) { - base64 = base64.substring(0, base64.length - 1) + "="; - } else if (len % 3 === 1) { - base64 = base64.substring(0, base64.length - 2) + "=="; - } - - return base64; - }; - - exports.decode = function(base64) { - var bufferLength = base64.length * 0.75, - len = base64.length, i, p = 0, - encoded1, encoded2, encoded3, encoded4; - - if (base64[base64.length - 1] === "=") { - bufferLength--; - if (base64[base64.length - 2] === "=") { - bufferLength--; - } - } - - var arraybuffer = new ArrayBuffer(bufferLength), - bytes = new Uint8Array(arraybuffer); - - for (i = 0; i < len; i+=4) { - encoded1 = lookup[base64.charCodeAt(i)]; - encoded2 = lookup[base64.charCodeAt(i+1)]; - encoded3 = lookup[base64.charCodeAt(i+2)]; - encoded4 = lookup[base64.charCodeAt(i+3)]; - - bytes[p++] = (encoded1 << 2) | (encoded2 >> 4); - bytes[p++] = ((encoded2 & 15) << 4) | (encoded3 >> 2); - bytes[p++] = ((encoded3 & 3) << 6) | (encoded4 & 63); - } - - return arraybuffer; - }; - })(); - - -/***/ }), -/* 28 */ -/***/ (function(module, exports) { - - /** - * Create a blob builder even when vendor prefixes exist - */ - - var BlobBuilder = typeof BlobBuilder !== 'undefined' ? BlobBuilder : - typeof WebKitBlobBuilder !== 'undefined' ? WebKitBlobBuilder : - typeof MSBlobBuilder !== 'undefined' ? MSBlobBuilder : - typeof MozBlobBuilder !== 'undefined' ? MozBlobBuilder : - false; - - /** - * Check if Blob constructor is supported - */ - - var blobSupported = (function() { - try { - var a = new Blob(['hi']); - return a.size === 2; - } catch(e) { - return false; - } - })(); - - /** - * Check if Blob constructor supports ArrayBufferViews - * Fails in Safari 6, so we need to map to ArrayBuffers there. - */ - - var blobSupportsArrayBufferView = blobSupported && (function() { - try { - var b = new Blob([new Uint8Array([1,2])]); - return b.size === 2; - } catch(e) { - return false; - } - })(); - - /** - * Check if BlobBuilder is supported - */ - - var blobBuilderSupported = BlobBuilder - && BlobBuilder.prototype.append - && BlobBuilder.prototype.getBlob; - - /** - * Helper function that maps ArrayBufferViews to ArrayBuffers - * Used by BlobBuilder constructor and old browsers that didn't - * support it in the Blob constructor. - */ - - function mapArrayBufferViews(ary) { - return ary.map(function(chunk) { - if (chunk.buffer instanceof ArrayBuffer) { - var buf = chunk.buffer; - - // if this is a subarray, make a copy so we only - // include the subarray region from the underlying buffer - if (chunk.byteLength !== buf.byteLength) { - var copy = new Uint8Array(chunk.byteLength); - copy.set(new Uint8Array(buf, chunk.byteOffset, chunk.byteLength)); - buf = copy.buffer; - } - - return buf; - } - - return chunk; - }); - } - - function BlobBuilderConstructor(ary, options) { - options = options || {}; - - var bb = new BlobBuilder(); - mapArrayBufferViews(ary).forEach(function(part) { - bb.append(part); - }); - - return (options.type) ? bb.getBlob(options.type) : bb.getBlob(); - }; - - function BlobConstructor(ary, options) { - return new Blob(mapArrayBufferViews(ary), options || {}); - }; - - if (typeof Blob !== 'undefined') { - BlobBuilderConstructor.prototype = Blob.prototype; - BlobConstructor.prototype = Blob.prototype; - } - - module.exports = (function() { - if (blobSupported) { - return blobSupportsArrayBufferView ? Blob : BlobConstructor; - } else if (blobBuilderSupported) { - return BlobBuilderConstructor; - } else { - return undefined; - } - })(); - - -/***/ }), -/* 29 */ -/***/ (function(module, exports) { - - /** - * Compiles a querystring - * Returns string representation of the object - * - * @param {Object} - * @api private - */ - - exports.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 - */ - - exports.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; - }; - - -/***/ }), -/* 30 */ -/***/ (function(module, exports) { - - - module.exports = function(a, b){ - var fn = function(){}; - fn.prototype = b.prototype; - a.prototype = new fn; - a.prototype.constructor = a; - }; - -/***/ }), -/* 31 */ -/***/ (function(module, exports) { - - 'use strict'; - - 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(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(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(+new Date()); - - if (now !== prev) return seed = 0, prev = now; - return now +'.'+ encode(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; - yeast.decode = decode; - module.exports = yeast; - - -/***/ }), -/* 32 */ -/***/ (function(module, exports, __webpack_require__) { - - /* WEBPACK VAR INJECTION */(function(global) {/** - * Module requirements. - */ - - var Polling = __webpack_require__(19); - var inherit = __webpack_require__(30); - - /** - * Module exports. - */ - - module.exports = JSONPPolling; - - /** - * Cached regular expressions. - */ - - var rNewline = /\n/g; - var rEscapedNewline = /\\n/g; - - /** - * Global JSONP callbacks. - */ - - var callbacks; - - /** - * Noop. - */ - - function empty () { } - - /** - * Until https://github.com/tc39/proposal-global is shipped. - */ - function glob () { - return typeof self !== 'undefined' ? self - : typeof window !== 'undefined' ? window - : typeof global !== 'undefined' ? global : {}; - } - - /** - * 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 - var global = glob(); - callbacks = global.___eio = (global.___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; - }, false); - } - } - - /** - * Inherits from Polling. - */ - - inherit(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 = '