diff --git a/History.md b/History.md index c6a14a378..6d4d61a3e 100644 --- a/History.md +++ b/History.md @@ -1,4 +1,36 @@ +2.0.0 / 2017-05-09 +=================== + +`dist/socket.io.js`: 61.1 kB ; `dist/socket.io.slim.js`: 52.8 kB + + * [feat] Move binary detection to the parser (#1103) + * [feat] Allow the use of a custom parser (#1075) + + * [fix] Run tests on the minified files (#1042) + * [fix] Add nsp prefix to socket.id (#1058) + + * [test] Update browsers matrix (#1059) + + * [chore] Bump engine.io to version 3.1.0 (#1109) + * [chore] Bump dev dependencies (#1108) + * [chore] Bump debug to version 2.6.4 (#1101) + * [chore] Fix dependencies (#1096) + * [chore] Bump engine.io-client to version 2.0.2 (#1074) + * [chore] Bump socket.io-parser to version 2.3.2 (#1071) + * [chore] Bump engine.io-client to version 2.0.0 (#1062) + * [chore] Update issue template with fiddle (#1057) + + * [docs] Fix messed events documentation (#1089) + * [docs] Fix Manager constructor documentation (#1093) + * [docs] Fix format in API.md (#1090) + * [docs] Add note regarding the Emitter class (#1079) + * [docs] Add missing path option in the documentation (#1078) + * [docs] Fix typo (#1076) + * [docs] Fix typo (#1066) + * [docs] Add `connect_error` and `connect_timeout` events (#1051) + * [docs] API documentation (#1049) + 1.7.2 / 2016-12-11 =================== diff --git a/dist/socket.io.js b/dist/socket.io.js index d5175e14e..1160659b5 100644 --- a/dist/socket.io.js +++ b/dist/socket.io.js @@ -1,8201 +1,3 @@ -(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__(17); - 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; - } else if (opts && 'object' === _typeof(opts.query)) { - opts.query = encodeQueryString(opts.query); - } - return io.socket(parsed.path, opts); - } - /** - * Helper method to parse query objects to string. - * @param {object} query - * @returns {string} - */ - function encodeQueryString(obj) { - var str = []; - for (var p in obj) { - if (obj.hasOwnProperty(p)) { - str.push(encodeURIComponent(p) + '=' + encodeURIComponent(obj[p])); - } - } - return str.join('&'); - } - /** - * 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__(17); - exports.Socket = __webpack_require__(44); - -/***/ }, -/* 1 */ -/***/ function(module, exports, __webpack_require__) { - - /* WEBPACK VAR INJECTION */(function(global) {'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 || global.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; - } - /* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }()))) - -/***/ }, -/* 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 = [ - 'lightseagreen', - 'forestgreen', - 'goldenrod', - 'dodgerblue', - 'darkorchid', - 'crimson' - ]; - - /** - * 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() { - // 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' && 'WebkitAppearance' in document.documentElement.style) || - // is firebug? http://stackoverflow.com/a/398120/376773 - (window.console && (console.firebug || (console.exception && console.table))) || - // is firefox >= v31? - // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages - (navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31); - } - - /** - * 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() { - var args = arguments; - var useColors = this.useColors; - - args[0] = (useColors ? '%c' : '') - + this.namespace - + (useColors ? ' %c' : ' ') - + args[0] - + (useColors ? '%c ' : ' ') - + '+' + exports.humanize(this.diff); - - if (!useColors) return args; - - var c = 'color: ' + this.color; - args = [args[0], c, 'color: inherit'].concat(Array.prototype.slice.call(args, 1)); - - // 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-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); - return args; - } - - /** - * 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 { - return exports.storage.debug; - } catch(e) {} - - // If debug isn't set in LS, and we're in Electron, try to load $DEBUG - if (typeof process !== 'undefined' && 'env' in process) { - return process.env.DEBUG; - } - } - - /** - * 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.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 = debug.debug = debug; - exports.coerce = coerce; - exports.disable = disable; - exports.enable = enable; - exports.enabled = enabled; - exports.humanize = __webpack_require__(6); - - /** - * 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, lowercased letter, i.e. "n". - */ - - exports.formatters = {}; - - /** - * Previously assigned color. - */ - - var prevColor = 0; - - /** - * Previous log timestamp. - */ - - var prevTime; - - /** - * Select a color. - * - * @return {Number} - * @api private - */ - - function selectColor() { - return exports.colors[prevColor++ % exports.colors.length]; - } - - /** - * Create a debugger with the given `namespace`. - * - * @param {String} namespace - * @return {Function} - * @api public - */ - - function debug(namespace) { - - // define the `disabled` version - function disabled() { - } - disabled.enabled = false; - - // define the `enabled` version - function enabled() { - - var self = enabled; - - // set `diff` timestamp - var curr = +new Date(); - var ms = curr - (prevTime || curr); - self.diff = ms; - self.prev = prevTime; - self.curr = curr; - prevTime = curr; - - // add the `color` if not set - if (null == self.useColors) self.useColors = exports.useColors(); - if (null == self.color && self.useColors) self.color = selectColor(); - - 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 = ['%o'].concat(args); - } - - // apply any `formatters` transformations - var index = 0; - args[0] = args[0].replace(/%([a-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 - args = exports.formatArgs.apply(self, args); - - var logFn = enabled.log || exports.log || console.log.bind(console); - logFn.apply(self, args); - } - enabled.enabled = true; - - var fn = exports.enabled(namespace) ? enabled : disabled; - - fn.namespace = namespace; - - return fn; - } - - /** - * 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); - - var split = (namespaces || '').split(/[\s,]+/); - var len = split.length; - - for (var i = 0; i < len; i++) { - if (!split[i]) continue; // ignore empty strings - namespaces = split[i].replace(/[\\^$+?.()|[\]{}]/g, '\\$&').replace(/\*/g, '.*?'); - if (namespaces[0] === '-') { - exports.skips.push(new RegExp('^' + namespaces.substr(1) + '$')); - } else { - exports.names.push(new RegExp('^' + namespaces + '$')); - } - } - } - - /** - * 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) { - 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 > 10000) { - 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__(8)('socket.io-parser'); - var json = __webpack_require__(11); - var Emitter = __webpack_require__(13); - var binary = __webpack_require__(14); - var isBuf = __webpack_require__(16); - - /** - * 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() {} - - /** - * 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) { - var str = ''; - var nsp = false; - - // first is type - str += obj.type; - - // attachments if we have them - if (exports.BINARY_EVENT == obj.type || exports.BINARY_ACK == obj.type) { - str += obj.attachments; - str += '-'; - } - - // if we have a namespace other than `/` - // we append it followed by a comma `,` - if (obj.nsp && '/' != obj.nsp) { - nsp = true; - str += obj.nsp; - } - - // immediately followed by the id - if (null != obj.id) { - if (nsp) { - str += ','; - nsp = false; - } - str += obj.id; - } - - // json data - if (null != obj.data) { - if (nsp) str += ','; - str += json.stringify(obj.data); - } - - debug('encoded %j as %s', obj, str); - return str; - } - - /** - * 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 ecoded packet string into packet JSON. - * - * @param {String} obj - encoded packet - * @return {Object} packet - * @api public - */ - - Decoder.prototype.add = function(obj) { - var packet; - if ('string' == typeof obj) { - 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 p = {}; - var i = 0; - - // look up type - p.type = Number(str.charAt(0)); - if (null == exports.types[p.type]) return error(); - - // 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)) { - p = tryParse(p, str.substr(i)); - } - - debug('decoded %s as %j', str, p); - return p; - } - - function tryParse(p, str) { - try { - p.data = json.parse(str); - } catch(e){ - return error(); - } - return p; - }; - - /** - * 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(data){ - return { - type: exports.ERROR, - data: 'parser error' - }; - } - - -/***/ }, -/* 8 */ -/***/ function(module, exports, __webpack_require__) { - - - /** - * This is the web browser implementation of `debug()`. - * - * Expose `debug()` as the module. - */ - - exports = module.exports = __webpack_require__(9); - 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 = [ - 'lightseagreen', - 'forestgreen', - 'goldenrod', - 'dodgerblue', - 'darkorchid', - 'crimson' - ]; - - /** - * 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() { - // is webkit? http://stackoverflow.com/a/16459606/376773 - return ('WebkitAppearance' in document.documentElement.style) || - // is firebug? http://stackoverflow.com/a/398120/376773 - (window.console && (console.firebug || (console.exception && console.table))) || - // is firefox >= v31? - // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages - (navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31); - } - - /** - * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default. - */ - - exports.formatters.j = function(v) { - return JSON.stringify(v); - }; - - - /** - * Colorize log arguments if enabled. - * - * @api public - */ - - function formatArgs() { - var args = arguments; - var useColors = this.useColors; - - args[0] = (useColors ? '%c' : '') - + this.namespace - + (useColors ? ' %c' : ' ') - + args[0] - + (useColors ? '%c ' : ' ') - + '+' + exports.humanize(this.diff); - - if (!useColors) return args; - - var c = 'color: ' + this.color; - args = [args[0], c, 'color: inherit'].concat(Array.prototype.slice.call(args, 1)); - - // 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-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); - return args; - } - - /** - * 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) {} - 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) {} - } - - -/***/ }, -/* 9 */ -/***/ 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 = debug; - exports.coerce = coerce; - exports.disable = disable; - exports.enable = enable; - exports.enabled = enabled; - exports.humanize = __webpack_require__(10); - - /** - * 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, lowercased letter, i.e. "n". - */ - - exports.formatters = {}; - - /** - * Previously assigned color. - */ - - var prevColor = 0; - - /** - * Previous log timestamp. - */ - - var prevTime; - - /** - * Select a color. - * - * @return {Number} - * @api private - */ - - function selectColor() { - return exports.colors[prevColor++ % exports.colors.length]; - } - - /** - * Create a debugger with the given `namespace`. - * - * @param {String} namespace - * @return {Function} - * @api public - */ - - function debug(namespace) { - - // define the `disabled` version - function disabled() { - } - disabled.enabled = false; - - // define the `enabled` version - function enabled() { - - var self = enabled; - - // set `diff` timestamp - var curr = +new Date(); - var ms = curr - (prevTime || curr); - self.diff = ms; - self.prev = prevTime; - self.curr = curr; - prevTime = curr; - - // add the `color` if not set - if (null == self.useColors) self.useColors = exports.useColors(); - if (null == self.color && self.useColors) self.color = selectColor(); - - var args = Array.prototype.slice.call(arguments); - - args[0] = exports.coerce(args[0]); - - if ('string' !== typeof args[0]) { - // anything else let's inspect with %o - args = ['%o'].concat(args); - } - - // apply any `formatters` transformations - var index = 0; - args[0] = args[0].replace(/%([a-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; - }); - - if ('function' === typeof exports.formatArgs) { - args = exports.formatArgs.apply(self, args); - } - var logFn = enabled.log || exports.log || console.log.bind(console); - logFn.apply(self, args); - } - enabled.enabled = true; - - var fn = exports.enabled(namespace) ? enabled : disabled; - - fn.namespace = namespace; - - return fn; - } - - /** - * 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); - - var split = (namespaces || '').split(/[\s,]+/); - var len = split.length; - - for (var 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 + '$')); - } - } - } - - /** - * 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) { - 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; - } - - -/***/ }, -/* 10 */ -/***/ 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 - * @return {String|Number} - * @api public - */ - - module.exports = function(val, options){ - options = options || {}; - if ('string' == typeof val) return parse(val); - return options.long - ? long(val) - : short(val); - }; - - /** - * Parse the given `str` and return milliseconds. - * - * @param {String} str - * @return {Number} - * @api private - */ - - function parse(str) { - str = '' + str; - if (str.length > 10000) 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; - } - } - - /** - * Short format for `ms`. - * - * @param {Number} ms - * @return {String} - * @api private - */ - - function short(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 long(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'; - } - - -/***/ }, -/* 11 */ -/***/ function(module, exports, __webpack_require__) { - - /* WEBPACK VAR INJECTION */(function(module, global) {/*** IMPORTS FROM imports-loader ***/ - var define = false; - - /*! JSON v3.3.2 | http://bestiejs.github.io/json3 | Copyright 2012-2014, Kit Cambridge | http://kit.mit-license.org */ - ;(function () { - // Detect the `define` function exposed by asynchronous module loaders. The - // strict `define` check is necessary for compatibility with `r.js`. - var isLoader = typeof define === "function" && define.amd; - - // A set of types used to distinguish objects from primitives. - var objectTypes = { - "function": true, - "object": true - }; - - // Detect the `exports` object exposed by CommonJS implementations. - var freeExports = objectTypes[typeof exports] && exports && !exports.nodeType && exports; - - // Use the `global` object exposed by Node (including Browserify via - // `insert-module-globals`), Narwhal, and Ringo as the default context, - // and the `window` object in browsers. Rhino exports a `global` function - // instead. - var root = objectTypes[typeof window] && window || this, - freeGlobal = freeExports && objectTypes[typeof module] && module && !module.nodeType && typeof global == "object" && global; - - if (freeGlobal && (freeGlobal["global"] === freeGlobal || freeGlobal["window"] === freeGlobal || freeGlobal["self"] === freeGlobal)) { - root = freeGlobal; - } - - // Public: Initializes JSON 3 using the given `context` object, attaching the - // `stringify` and `parse` functions to the specified `exports` object. - function runInContext(context, exports) { - context || (context = root["Object"]()); - exports || (exports = root["Object"]()); - - // Native constructor aliases. - var Number = context["Number"] || root["Number"], - String = context["String"] || root["String"], - Object = context["Object"] || root["Object"], - Date = context["Date"] || root["Date"], - SyntaxError = context["SyntaxError"] || root["SyntaxError"], - TypeError = context["TypeError"] || root["TypeError"], - Math = context["Math"] || root["Math"], - nativeJSON = context["JSON"] || root["JSON"]; - - // Delegate to the native `stringify` and `parse` implementations. - if (typeof nativeJSON == "object" && nativeJSON) { - exports.stringify = nativeJSON.stringify; - exports.parse = nativeJSON.parse; - } - - // Convenience aliases. - var objectProto = Object.prototype, - getClass = objectProto.toString, - isProperty, forEach, undef; - - // Test the `Date#getUTC*` methods. Based on work by @Yaffle. - var isExtended = new Date(-3509827334573292); - try { - // The `getUTCFullYear`, `Month`, and `Date` methods return nonsensical - // results for certain dates in Opera >= 10.53. - isExtended = isExtended.getUTCFullYear() == -109252 && isExtended.getUTCMonth() === 0 && isExtended.getUTCDate() === 1 && - // Safari < 2.0.2 stores the internal millisecond time value correctly, - // but clips the values returned by the date methods to the range of - // signed 32-bit integers ([-2 ** 31, 2 ** 31 - 1]). - isExtended.getUTCHours() == 10 && isExtended.getUTCMinutes() == 37 && isExtended.getUTCSeconds() == 6 && isExtended.getUTCMilliseconds() == 708; - } catch (exception) {} - - // Internal: Determines whether the native `JSON.stringify` and `parse` - // implementations are spec-compliant. Based on work by Ken Snyder. - function has(name) { - if (has[name] !== undef) { - // Return cached feature test result. - return has[name]; - } - var isSupported; - if (name == "bug-string-char-index") { - // IE <= 7 doesn't support accessing string characters using square - // bracket notation. IE 8 only supports this for primitives. - isSupported = "a"[0] != "a"; - } else if (name == "json") { - // Indicates whether both `JSON.stringify` and `JSON.parse` are - // supported. - isSupported = has("json-stringify") && has("json-parse"); - } else { - var value, serialized = '{"a":[1,true,false,null,"\\u0000\\b\\n\\f\\r\\t"]}'; - // Test `JSON.stringify`. - if (name == "json-stringify") { - var stringify = exports.stringify, stringifySupported = typeof stringify == "function" && isExtended; - if (stringifySupported) { - // A test function object with a custom `toJSON` method. - (value = function () { - return 1; - }).toJSON = value; - try { - stringifySupported = - // Firefox 3.1b1 and b2 serialize string, number, and boolean - // primitives as object literals. - stringify(0) === "0" && - // FF 3.1b1, b2, and JSON 2 serialize wrapped primitives as object - // literals. - stringify(new Number()) === "0" && - stringify(new String()) == '""' && - // FF 3.1b1, 2 throw an error if the value is `null`, `undefined`, or - // does not define a canonical JSON representation (this applies to - // objects with `toJSON` properties as well, *unless* they are nested - // within an object or array). - stringify(getClass) === undef && - // IE 8 serializes `undefined` as `"undefined"`. Safari <= 5.1.7 and - // FF 3.1b3 pass this test. - stringify(undef) === undef && - // Safari <= 5.1.7 and FF 3.1b3 throw `Error`s and `TypeError`s, - // respectively, if the value is omitted entirely. - stringify() === undef && - // FF 3.1b1, 2 throw an error if the given value is not a number, - // string, array, object, Boolean, or `null` literal. This applies to - // objects with custom `toJSON` methods as well, unless they are nested - // inside object or array literals. YUI 3.0.0b1 ignores custom `toJSON` - // methods entirely. - stringify(value) === "1" && - stringify([value]) == "[1]" && - // Prototype <= 1.6.1 serializes `[undefined]` as `"[]"` instead of - // `"[null]"`. - stringify([undef]) == "[null]" && - // YUI 3.0.0b1 fails to serialize `null` literals. - stringify(null) == "null" && - // FF 3.1b1, 2 halts serialization if an array contains a function: - // `[1, true, getClass, 1]` serializes as "[1,true,],". FF 3.1b3 - // elides non-JSON values from objects and arrays, unless they - // define custom `toJSON` methods. - stringify([undef, getClass, null]) == "[null,null,null]" && - // Simple serialization test. FF 3.1b1 uses Unicode escape sequences - // where character escape codes are expected (e.g., `\b` => `\u0008`). - stringify({ "a": [value, true, false, null, "\x00\b\n\f\r\t"] }) == serialized && - // FF 3.1b1 and b2 ignore the `filter` and `width` arguments. - stringify(null, value) === "1" && - stringify([1, 2], null, 1) == "[\n 1,\n 2\n]" && - // JSON 2, Prototype <= 1.7, and older WebKit builds incorrectly - // serialize extended years. - stringify(new Date(-8.64e15)) == '"-271821-04-20T00:00:00.000Z"' && - // The milliseconds are optional in ES 5, but required in 5.1. - stringify(new Date(8.64e15)) == '"+275760-09-13T00:00:00.000Z"' && - // Firefox <= 11.0 incorrectly serializes years prior to 0 as negative - // four-digit years instead of six-digit years. Credits: @Yaffle. - stringify(new Date(-621987552e5)) == '"-000001-01-01T00:00:00.000Z"' && - // Safari <= 5.1.5 and Opera >= 10.53 incorrectly serialize millisecond - // values less than 1000. Credits: @Yaffle. - stringify(new Date(-1)) == '"1969-12-31T23:59:59.999Z"'; - } catch (exception) { - stringifySupported = false; - } - } - isSupported = stringifySupported; - } - // Test `JSON.parse`. - if (name == "json-parse") { - var parse = exports.parse; - if (typeof parse == "function") { - try { - // FF 3.1b1, b2 will throw an exception if a bare literal is provided. - // Conforming implementations should also coerce the initial argument to - // a string prior to parsing. - if (parse("0") === 0 && !parse(false)) { - // Simple parsing test. - value = parse(serialized); - var parseSupported = value["a"].length == 5 && value["a"][0] === 1; - if (parseSupported) { - try { - // Safari <= 5.1.2 and FF 3.1b1 allow unescaped tabs in strings. - parseSupported = !parse('"\t"'); - } catch (exception) {} - if (parseSupported) { - try { - // FF 4.0 and 4.0.1 allow leading `+` signs and leading - // decimal points. FF 4.0, 4.0.1, and IE 9-10 also allow - // certain octal literals. - parseSupported = parse("01") !== 1; - } catch (exception) {} - } - if (parseSupported) { - try { - // FF 4.0, 4.0.1, and Rhino 1.7R3-R4 allow trailing decimal - // points. These environments, along with FF 3.1b1 and 2, - // also allow trailing commas in JSON objects and arrays. - parseSupported = parse("1.") !== 1; - } catch (exception) {} - } - } - } - } catch (exception) { - parseSupported = false; - } - } - isSupported = parseSupported; - } - } - return has[name] = !!isSupported; - } - - if (!has("json")) { - // Common `[[Class]]` name aliases. - var functionClass = "[object Function]", - dateClass = "[object Date]", - numberClass = "[object Number]", - stringClass = "[object String]", - arrayClass = "[object Array]", - booleanClass = "[object Boolean]"; - - // Detect incomplete support for accessing string characters by index. - var charIndexBuggy = has("bug-string-char-index"); - - // Define additional utility methods if the `Date` methods are buggy. - if (!isExtended) { - var floor = Math.floor; - // A mapping between the months of the year and the number of days between - // January 1st and the first of the respective month. - var Months = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334]; - // Internal: Calculates the number of days between the Unix epoch and the - // first day of the given month. - var getDay = function (year, month) { - return Months[month] + 365 * (year - 1970) + floor((year - 1969 + (month = +(month > 1))) / 4) - floor((year - 1901 + month) / 100) + floor((year - 1601 + month) / 400); - }; - } - - // Internal: Determines if a property is a direct property of the given - // object. Delegates to the native `Object#hasOwnProperty` method. - if (!(isProperty = objectProto.hasOwnProperty)) { - isProperty = function (property) { - var members = {}, constructor; - if ((members.__proto__ = null, members.__proto__ = { - // The *proto* property cannot be set multiple times in recent - // versions of Firefox and SeaMonkey. - "toString": 1 - }, members).toString != getClass) { - // Safari <= 2.0.3 doesn't implement `Object#hasOwnProperty`, but - // supports the mutable *proto* property. - isProperty = function (property) { - // Capture and break the object's prototype chain (see section 8.6.2 - // of the ES 5.1 spec). The parenthesized expression prevents an - // unsafe transformation by the Closure Compiler. - var original = this.__proto__, result = property in (this.__proto__ = null, this); - // Restore the original prototype chain. - this.__proto__ = original; - return result; - }; - } else { - // Capture a reference to the top-level `Object` constructor. - constructor = members.constructor; - // Use the `constructor` property to simulate `Object#hasOwnProperty` in - // other environments. - isProperty = function (property) { - var parent = (this.constructor || constructor).prototype; - return property in this && !(property in parent && this[property] === parent[property]); - }; - } - members = null; - return isProperty.call(this, property); - }; - } - - // Internal: Normalizes the `for...in` iteration algorithm across - // environments. Each enumerated key is yielded to a `callback` function. - forEach = function (object, callback) { - var size = 0, Properties, members, property; - - // Tests for bugs in the current environment's `for...in` algorithm. The - // `valueOf` property inherits the non-enumerable flag from - // `Object.prototype` in older versions of IE, Netscape, and Mozilla. - (Properties = function () { - this.valueOf = 0; - }).prototype.valueOf = 0; - - // Iterate over a new instance of the `Properties` class. - members = new Properties(); - for (property in members) { - // Ignore all properties inherited from `Object.prototype`. - if (isProperty.call(members, property)) { - size++; - } - } - Properties = members = null; - - // Normalize the iteration algorithm. - if (!size) { - // A list of non-enumerable properties inherited from `Object.prototype`. - members = ["valueOf", "toString", "toLocaleString", "propertyIsEnumerable", "isPrototypeOf", "hasOwnProperty", "constructor"]; - // IE <= 8, Mozilla 1.0, and Netscape 6.2 ignore shadowed non-enumerable - // properties. - forEach = function (object, callback) { - var isFunction = getClass.call(object) == functionClass, property, length; - var hasProperty = !isFunction && typeof object.constructor != "function" && objectTypes[typeof object.hasOwnProperty] && object.hasOwnProperty || isProperty; - for (property in object) { - // Gecko <= 1.0 enumerates the `prototype` property of functions under - // certain conditions; IE does not. - if (!(isFunction && property == "prototype") && hasProperty.call(object, property)) { - callback(property); - } - } - // Manually invoke the callback for each non-enumerable property. - for (length = members.length; property = members[--length]; hasProperty.call(object, property) && callback(property)); - }; - } else if (size == 2) { - // Safari <= 2.0.4 enumerates shadowed properties twice. - forEach = function (object, callback) { - // Create a set of iterated properties. - var members = {}, isFunction = getClass.call(object) == functionClass, property; - for (property in object) { - // Store each property name to prevent double enumeration. The - // `prototype` property of functions is not enumerated due to cross- - // environment inconsistencies. - if (!(isFunction && property == "prototype") && !isProperty.call(members, property) && (members[property] = 1) && isProperty.call(object, property)) { - callback(property); - } - } - }; - } else { - // No bugs detected; use the standard `for...in` algorithm. - forEach = function (object, callback) { - var isFunction = getClass.call(object) == functionClass, property, isConstructor; - for (property in object) { - if (!(isFunction && property == "prototype") && isProperty.call(object, property) && !(isConstructor = property === "constructor")) { - callback(property); - } - } - // Manually invoke the callback for the `constructor` property due to - // cross-environment inconsistencies. - if (isConstructor || isProperty.call(object, (property = "constructor"))) { - callback(property); - } - }; - } - return forEach(object, callback); - }; - - // Public: Serializes a JavaScript `value` as a JSON string. The optional - // `filter` argument may specify either a function that alters how object and - // array members are serialized, or an array of strings and numbers that - // indicates which properties should be serialized. The optional `width` - // argument may be either a string or number that specifies the indentation - // level of the output. - if (!has("json-stringify")) { - // Internal: A map of control characters and their escaped equivalents. - var Escapes = { - 92: "\\\\", - 34: '\\"', - 8: "\\b", - 12: "\\f", - 10: "\\n", - 13: "\\r", - 9: "\\t" - }; - - // Internal: Converts `value` into a zero-padded string such that its - // length is at least equal to `width`. The `width` must be <= 6. - var leadingZeroes = "000000"; - var toPaddedString = function (width, value) { - // The `|| 0` expression is necessary to work around a bug in - // Opera <= 7.54u2 where `0 == -0`, but `String(-0) !== "0"`. - return (leadingZeroes + (value || 0)).slice(-width); - }; - - // Internal: Double-quotes a string `value`, replacing all ASCII control - // characters (characters with code unit values between 0 and 31) with - // their escaped equivalents. This is an implementation of the - // `Quote(value)` operation defined in ES 5.1 section 15.12.3. - var unicodePrefix = "\\u00"; - var quote = function (value) { - var result = '"', index = 0, length = value.length, useCharIndex = !charIndexBuggy || length > 10; - var symbols = useCharIndex && (charIndexBuggy ? value.split("") : value); - for (; index < length; index++) { - var charCode = value.charCodeAt(index); - // If the character is a control character, append its Unicode or - // shorthand escape sequence; otherwise, append the character as-is. - switch (charCode) { - case 8: case 9: case 10: case 12: case 13: case 34: case 92: - result += Escapes[charCode]; - break; - default: - if (charCode < 32) { - result += unicodePrefix + toPaddedString(2, charCode.toString(16)); - break; - } - result += useCharIndex ? symbols[index] : value.charAt(index); - } - } - return result + '"'; - }; - - // Internal: Recursively serializes an object. Implements the - // `Str(key, holder)`, `JO(value)`, and `JA(value)` operations. - var serialize = function (property, object, callback, properties, whitespace, indentation, stack) { - var value, className, year, month, date, time, hours, minutes, seconds, milliseconds, results, element, index, length, prefix, result; - try { - // Necessary for host object support. - value = object[property]; - } catch (exception) {} - if (typeof value == "object" && value) { - className = getClass.call(value); - if (className == dateClass && !isProperty.call(value, "toJSON")) { - if (value > -1 / 0 && value < 1 / 0) { - // Dates are serialized according to the `Date#toJSON` method - // specified in ES 5.1 section 15.9.5.44. See section 15.9.1.15 - // for the ISO 8601 date time string format. - if (getDay) { - // Manually compute the year, month, date, hours, minutes, - // seconds, and milliseconds if the `getUTC*` methods are - // buggy. Adapted from @Yaffle's `date-shim` project. - date = floor(value / 864e5); - for (year = floor(date / 365.2425) + 1970 - 1; getDay(year + 1, 0) <= date; year++); - for (month = floor((date - getDay(year, 0)) / 30.42); getDay(year, month + 1) <= date; month++); - date = 1 + date - getDay(year, month); - // The `time` value specifies the time within the day (see ES - // 5.1 section 15.9.1.2). The formula `(A % B + B) % B` is used - // to compute `A modulo B`, as the `%` operator does not - // correspond to the `modulo` operation for negative numbers. - time = (value % 864e5 + 864e5) % 864e5; - // The hours, minutes, seconds, and milliseconds are obtained by - // decomposing the time within the day. See section 15.9.1.10. - hours = floor(time / 36e5) % 24; - minutes = floor(time / 6e4) % 60; - seconds = floor(time / 1e3) % 60; - milliseconds = time % 1e3; - } else { - year = value.getUTCFullYear(); - month = value.getUTCMonth(); - date = value.getUTCDate(); - hours = value.getUTCHours(); - minutes = value.getUTCMinutes(); - seconds = value.getUTCSeconds(); - milliseconds = value.getUTCMilliseconds(); - } - // Serialize extended years correctly. - value = (year <= 0 || year >= 1e4 ? (year < 0 ? "-" : "+") + toPaddedString(6, year < 0 ? -year : year) : toPaddedString(4, year)) + - "-" + toPaddedString(2, month + 1) + "-" + toPaddedString(2, date) + - // Months, dates, hours, minutes, and seconds should have two - // digits; milliseconds should have three. - "T" + toPaddedString(2, hours) + ":" + toPaddedString(2, minutes) + ":" + toPaddedString(2, seconds) + - // Milliseconds are optional in ES 5.0, but required in 5.1. - "." + toPaddedString(3, milliseconds) + "Z"; - } else { - value = null; - } - } else if (typeof value.toJSON == "function" && ((className != numberClass && className != stringClass && className != arrayClass) || isProperty.call(value, "toJSON"))) { - // Prototype <= 1.6.1 adds non-standard `toJSON` methods to the - // `Number`, `String`, `Date`, and `Array` prototypes. JSON 3 - // ignores all `toJSON` methods on these objects unless they are - // defined directly on an instance. - value = value.toJSON(property); - } - } - if (callback) { - // If a replacement function was provided, call it to obtain the value - // for serialization. - value = callback.call(object, property, value); - } - if (value === null) { - return "null"; - } - className = getClass.call(value); - if (className == booleanClass) { - // Booleans are represented literally. - return "" + value; - } else if (className == numberClass) { - // JSON numbers must be finite. `Infinity` and `NaN` are serialized as - // `"null"`. - return value > -1 / 0 && value < 1 / 0 ? "" + value : "null"; - } else if (className == stringClass) { - // Strings are double-quoted and escaped. - return quote("" + value); - } - // Recursively serialize objects and arrays. - if (typeof value == "object") { - // Check for cyclic structures. This is a linear search; performance - // is inversely proportional to the number of unique nested objects. - for (length = stack.length; length--;) { - if (stack[length] === value) { - // Cyclic structures cannot be serialized by `JSON.stringify`. - throw TypeError(); - } - } - // Add the object to the stack of traversed objects. - stack.push(value); - results = []; - // Save the current indentation level and indent one additional level. - prefix = indentation; - indentation += whitespace; - if (className == arrayClass) { - // Recursively serialize array elements. - for (index = 0, length = value.length; index < length; index++) { - element = serialize(index, value, callback, properties, whitespace, indentation, stack); - results.push(element === undef ? "null" : element); - } - result = results.length ? (whitespace ? "[\n" + indentation + results.join(",\n" + indentation) + "\n" + prefix + "]" : ("[" + results.join(",") + "]")) : "[]"; - } else { - // Recursively serialize object members. Members are selected from - // either a user-specified list of property names, or the object - // itself. - forEach(properties || value, function (property) { - var element = serialize(property, value, callback, properties, whitespace, indentation, stack); - if (element !== undef) { - // According to ES 5.1 section 15.12.3: "If `gap` {whitespace} - // is not the empty string, let `member` {quote(property) + ":"} - // be the concatenation of `member` and the `space` character." - // The "`space` character" refers to the literal space - // character, not the `space` {width} argument provided to - // `JSON.stringify`. - results.push(quote(property) + ":" + (whitespace ? " " : "") + element); - } - }); - result = results.length ? (whitespace ? "{\n" + indentation + results.join(",\n" + indentation) + "\n" + prefix + "}" : ("{" + results.join(",") + "}")) : "{}"; - } - // Remove the object from the traversed object stack. - stack.pop(); - return result; - } - }; - - // Public: `JSON.stringify`. See ES 5.1 section 15.12.3. - exports.stringify = function (source, filter, width) { - var whitespace, callback, properties, className; - if (objectTypes[typeof filter] && filter) { - if ((className = getClass.call(filter)) == functionClass) { - callback = filter; - } else if (className == arrayClass) { - // Convert the property names array into a makeshift set. - properties = {}; - for (var index = 0, length = filter.length, value; index < length; value = filter[index++], ((className = getClass.call(value)), className == stringClass || className == numberClass) && (properties[value] = 1)); - } - } - if (width) { - if ((className = getClass.call(width)) == numberClass) { - // Convert the `width` to an integer and create a string containing - // `width` number of space characters. - if ((width -= width % 1) > 0) { - for (whitespace = "", width > 10 && (width = 10); whitespace.length < width; whitespace += " "); - } - } else if (className == stringClass) { - whitespace = width.length <= 10 ? width : width.slice(0, 10); - } - } - // Opera <= 7.54u2 discards the values associated with empty string keys - // (`""`) only if they are used directly within an object member list - // (e.g., `!("" in { "": 1})`). - return serialize("", (value = {}, value[""] = source, value), callback, properties, whitespace, "", []); - }; - } - - // Public: Parses a JSON source string. - if (!has("json-parse")) { - var fromCharCode = String.fromCharCode; - - // Internal: A map of escaped control characters and their unescaped - // equivalents. - var Unescapes = { - 92: "\\", - 34: '"', - 47: "/", - 98: "\b", - 116: "\t", - 110: "\n", - 102: "\f", - 114: "\r" - }; - - // Internal: Stores the parser state. - var Index, Source; - - // Internal: Resets the parser state and throws a `SyntaxError`. - var abort = function () { - Index = Source = null; - throw SyntaxError(); - }; - - // Internal: Returns the next token, or `"$"` if the parser has reached - // the end of the source string. A token may be a string, number, `null` - // literal, or Boolean literal. - var lex = function () { - var source = Source, length = source.length, value, begin, position, isSigned, charCode; - while (Index < length) { - charCode = source.charCodeAt(Index); - switch (charCode) { - case 9: case 10: case 13: case 32: - // Skip whitespace tokens, including tabs, carriage returns, line - // feeds, and space characters. - Index++; - break; - case 123: case 125: case 91: case 93: case 58: case 44: - // Parse a punctuator token (`{`, `}`, `[`, `]`, `:`, or `,`) at - // the current position. - value = charIndexBuggy ? source.charAt(Index) : source[Index]; - Index++; - return value; - case 34: - // `"` delimits a JSON string; advance to the next character and - // begin parsing the string. String tokens are prefixed with the - // sentinel `@` character to distinguish them from punctuators and - // end-of-string tokens. - for (value = "@", Index++; Index < length;) { - charCode = source.charCodeAt(Index); - if (charCode < 32) { - // Unescaped ASCII control characters (those with a code unit - // less than the space character) are not permitted. - abort(); - } else if (charCode == 92) { - // A reverse solidus (`\`) marks the beginning of an escaped - // control character (including `"`, `\`, and `/`) or Unicode - // escape sequence. - charCode = source.charCodeAt(++Index); - switch (charCode) { - case 92: case 34: case 47: case 98: case 116: case 110: case 102: case 114: - // Revive escaped control characters. - value += Unescapes[charCode]; - Index++; - break; - case 117: - // `\u` marks the beginning of a Unicode escape sequence. - // Advance to the first character and validate the - // four-digit code point. - begin = ++Index; - for (position = Index + 4; Index < position; Index++) { - charCode = source.charCodeAt(Index); - // A valid sequence comprises four hexdigits (case- - // insensitive) that form a single hexadecimal value. - if (!(charCode >= 48 && charCode <= 57 || charCode >= 97 && charCode <= 102 || charCode >= 65 && charCode <= 70)) { - // Invalid Unicode escape sequence. - abort(); - } - } - // Revive the escaped character. - value += fromCharCode("0x" + source.slice(begin, Index)); - break; - default: - // Invalid escape sequence. - abort(); - } - } else { - if (charCode == 34) { - // An unescaped double-quote character marks the end of the - // string. - break; - } - charCode = source.charCodeAt(Index); - begin = Index; - // Optimize for the common case where a string is valid. - while (charCode >= 32 && charCode != 92 && charCode != 34) { - charCode = source.charCodeAt(++Index); - } - // Append the string as-is. - value += source.slice(begin, Index); - } - } - if (source.charCodeAt(Index) == 34) { - // Advance to the next character and return the revived string. - Index++; - return value; - } - // Unterminated string. - abort(); - default: - // Parse numbers and literals. - begin = Index; - // Advance past the negative sign, if one is specified. - if (charCode == 45) { - isSigned = true; - charCode = source.charCodeAt(++Index); - } - // Parse an integer or floating-point value. - if (charCode >= 48 && charCode <= 57) { - // Leading zeroes are interpreted as octal literals. - if (charCode == 48 && ((charCode = source.charCodeAt(Index + 1)), charCode >= 48 && charCode <= 57)) { - // Illegal octal literal. - abort(); - } - isSigned = false; - // Parse the integer component. - for (; Index < length && ((charCode = source.charCodeAt(Index)), charCode >= 48 && charCode <= 57); Index++); - // Floats cannot contain a leading decimal point; however, this - // case is already accounted for by the parser. - if (source.charCodeAt(Index) == 46) { - position = ++Index; - // Parse the decimal component. - for (; position < length && ((charCode = source.charCodeAt(position)), charCode >= 48 && charCode <= 57); position++); - if (position == Index) { - // Illegal trailing decimal. - abort(); - } - Index = position; - } - // Parse exponents. The `e` denoting the exponent is - // case-insensitive. - charCode = source.charCodeAt(Index); - if (charCode == 101 || charCode == 69) { - charCode = source.charCodeAt(++Index); - // Skip past the sign following the exponent, if one is - // specified. - if (charCode == 43 || charCode == 45) { - Index++; - } - // Parse the exponential component. - for (position = Index; position < length && ((charCode = source.charCodeAt(position)), charCode >= 48 && charCode <= 57); position++); - if (position == Index) { - // Illegal empty exponent. - abort(); - } - Index = position; - } - // Coerce the parsed value to a JavaScript number. - return +source.slice(begin, Index); - } - // A negative sign may only precede numbers. - if (isSigned) { - abort(); - } - // `true`, `false`, and `null` literals. - if (source.slice(Index, Index + 4) == "true") { - Index += 4; - return true; - } else if (source.slice(Index, Index + 5) == "false") { - Index += 5; - return false; - } else if (source.slice(Index, Index + 4) == "null") { - Index += 4; - return null; - } - // Unrecognized token. - abort(); - } - } - // Return the sentinel `$` character if the parser has reached the end - // of the source string. - return "$"; - }; - - // Internal: Parses a JSON `value` token. - var get = function (value) { - var results, hasMembers; - if (value == "$") { - // Unexpected end of input. - abort(); - } - if (typeof value == "string") { - if ((charIndexBuggy ? value.charAt(0) : value[0]) == "@") { - // Remove the sentinel `@` character. - return value.slice(1); - } - // Parse object and array literals. - if (value == "[") { - // Parses a JSON array, returning a new JavaScript array. - results = []; - for (;; hasMembers || (hasMembers = true)) { - value = lex(); - // A closing square bracket marks the end of the array literal. - if (value == "]") { - break; - } - // If the array literal contains elements, the current token - // should be a comma separating the previous element from the - // next. - if (hasMembers) { - if (value == ",") { - value = lex(); - if (value == "]") { - // Unexpected trailing `,` in array literal. - abort(); - } - } else { - // A `,` must separate each array element. - abort(); - } - } - // Elisions and leading commas are not permitted. - if (value == ",") { - abort(); - } - results.push(get(value)); - } - return results; - } else if (value == "{") { - // Parses a JSON object, returning a new JavaScript object. - results = {}; - for (;; hasMembers || (hasMembers = true)) { - value = lex(); - // A closing curly brace marks the end of the object literal. - if (value == "}") { - break; - } - // If the object literal contains members, the current token - // should be a comma separator. - if (hasMembers) { - if (value == ",") { - value = lex(); - if (value == "}") { - // Unexpected trailing `,` in object literal. - abort(); - } - } else { - // A `,` must separate each object member. - abort(); - } - } - // Leading commas are not permitted, object property names must be - // double-quoted strings, and a `:` must separate each property - // name and value. - if (value == "," || typeof value != "string" || (charIndexBuggy ? value.charAt(0) : value[0]) != "@" || lex() != ":") { - abort(); - } - results[value.slice(1)] = get(lex()); - } - return results; - } - // Unexpected token encountered. - abort(); - } - return value; - }; - - // Internal: Updates a traversed object member. - var update = function (source, property, callback) { - var element = walk(source, property, callback); - if (element === undef) { - delete source[property]; - } else { - source[property] = element; - } - }; - - // Internal: Recursively traverses a parsed JSON object, invoking the - // `callback` function for each value. This is an implementation of the - // `Walk(holder, name)` operation defined in ES 5.1 section 15.12.2. - var walk = function (source, property, callback) { - var value = source[property], length; - if (typeof value == "object" && value) { - // `forEach` can't be used to traverse an array in Opera <= 8.54 - // because its `Object#hasOwnProperty` implementation returns `false` - // for array indices (e.g., `![1, 2, 3].hasOwnProperty("0")`). - if (getClass.call(value) == arrayClass) { - for (length = value.length; length--;) { - update(value, length, callback); - } - } else { - forEach(value, function (property) { - update(value, property, callback); - }); - } - } - return callback.call(source, property, value); - }; - - // Public: `JSON.parse`. See ES 5.1 section 15.12.2. - exports.parse = function (source, callback) { - var result, value; - Index = 0; - Source = "" + source; - result = get(lex()); - // If a JSON string contains multiple tokens, it is invalid. - if (lex() != "$") { - abort(); - } - // Reset the parser state. - Index = Source = null; - return callback && getClass.call(callback) == functionClass ? walk((value = {}, value[""] = result, value), "", callback) : result; - }; - } - } - - exports["runInContext"] = runInContext; - return exports; - } - - if (freeExports && !isLoader) { - // Export for CommonJS environments. - runInContext(root, freeExports); - } else { - // Export for web browsers and JavaScript engines. - var nativeJSON = root.JSON, - previousJSON = root["JSON3"], - isRestored = false; - - var JSON3 = runInContext(root, (root["JSON3"] = { - // Public: Restores the original value of the global `JSON` object and - // returns a reference to the `JSON3` object. - "noConflict": function () { - if (!isRestored) { - isRestored = true; - root.JSON = nativeJSON; - root["JSON3"] = previousJSON; - nativeJSON = previousJSON = null; - } - return JSON3; - } - })); - - root.JSON = { - "parse": JSON3.parse, - "stringify": JSON3.stringify - }; - } - - // Export for asynchronous module loaders. - if (isLoader) { - define(function () { - return JSON3; - }); - } - }).call(this); - - - /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(12)(module), (function() { return this; }()))) - -/***/ }, -/* 12 */ -/***/ function(module, exports) { - - module.exports = function(module) { - if(!module.webpackPolyfill) { - module.deprecate = function() {}; - module.paths = []; - // module.parent = undefined by default - module.children = []; - module.webpackPolyfill = 1; - } - return module; - } - - -/***/ }, -/* 13 */ -/***/ function(module, exports) { - - - /** - * Expose `Emitter`. - */ - - module.exports = Emitter; - - /** - * Initialize a new `Emitter`. - * - * @api public - */ - - function Emitter(obj) { - if (obj) return mixin(obj); - }; - - /** - * Mixin the emitter properties. - * - * @param {Object} obj - * @return {Object} - * @api private - */ - - function mixin(obj) { - for (var key in Emitter.prototype) { - obj[key] = Emitter.prototype[key]; - } - return obj; - } - - /** - * Listen on the given `event` with `fn`. - * - * @param {String} event - * @param {Function} fn - * @return {Emitter} - * @api public - */ - - Emitter.prototype.on = - Emitter.prototype.addEventListener = function(event, fn){ - this._callbacks = this._callbacks || {}; - (this._callbacks[event] = this._callbacks[event] || []) - .push(fn); - return this; - }; - - /** - * Adds an `event` listener that will be invoked a single - * time then automatically removed. - * - * @param {String} event - * @param {Function} fn - * @return {Emitter} - * @api public - */ - - Emitter.prototype.once = function(event, fn){ - var self = this; - this._callbacks = this._callbacks || {}; - - function on() { - self.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; - }; - - -/***/ }, -/* 14 */ -/***/ function(module, exports, __webpack_require__) { - - /* WEBPACK VAR INJECTION */(function(global) {/*global Blob,File*/ - - /** - * Module requirements - */ - - var isArray = __webpack_require__(15); - var isBuf = __webpack_require__(16); - - /** - * 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; - - function _deconstructPacket(data) { - 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]); - } - return newData; - } else if ('object' == typeof data && !(data instanceof Date)) { - var newData = {}; - for (var key in data) { - newData[key] = _deconstructPacket(data[key]); - } - return newData; - } - return data; - } - - var pack = packet; - pack.data = _deconstructPacket(packetData); - pack.attachments = buffers.length; // number of binary 'attachments' - return {packet: pack, buffers: buffers}; - }; - - /** - * 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) { - var curPlaceHolder = 0; - - function _reconstructPacket(data) { - if (data && data._placeholder) { - var buf = buffers[data.num]; // appropriate buffer (should be natural order anyway) - return buf; - } else if (isArray(data)) { - for (var i = 0; i < data.length; i++) { - data[i] = _reconstructPacket(data[i]); - } - return data; - } else if (data && 'object' == typeof data) { - for (var key in data) { - data[key] = _reconstructPacket(data[key]); - } - return data; - } - return data; - } - - packet.data = _reconstructPacket(packet.data); - packet.attachments = undefined; // no longer useful - return packet; - }; - - /** - * 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 ((global.Blob && obj instanceof Blob) || - (global.File && 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 (obj && 'object' == typeof obj && !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); - } - }; - - /* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }()))) - -/***/ }, -/* 15 */ -/***/ function(module, exports) { - - module.exports = Array.isArray || function (arr) { - return Object.prototype.toString.call(arr) == '[object Array]'; - }; - - -/***/ }, -/* 16 */ -/***/ function(module, exports) { - - /* WEBPACK VAR INJECTION */(function(global) { - module.exports = isBuf; - - /** - * Returns true if obj is a buffer or an arraybuffer. - * - * @api private - */ - - function isBuf(obj) { - return (global.Buffer && global.Buffer.isBuffer(obj)) || - (global.ArrayBuffer && obj instanceof ArrayBuffer); - } - - /* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }()))) - -/***/ }, -/* 17 */ -/***/ 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__(18); - var Socket = __webpack_require__(44); - var Emitter = __webpack_require__(35); - var parser = __webpack_require__(7); - var on = __webpack_require__(46); - var bind = __webpack_require__(47); - var debug = __webpack_require__(3)('socket.io-client:manager'); - var indexOf = __webpack_require__(42); - var Backoff = __webpack_require__(48); - - /** - * 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 = []; - 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.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.engine.id; - }); - - if (this.autoConnect) { - // manually call here since connecting evnet 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); - }; - -/***/ }, -/* 18 */ -/***/ function(module, exports, __webpack_require__) { - - - module.exports = __webpack_require__(19); - - -/***/ }, -/* 19 */ -/***/ function(module, exports, __webpack_require__) { - - - module.exports = __webpack_require__(20); - - /** - * Exports parser - * - * @api public - * - */ - module.exports.parser = __webpack_require__(27); - - -/***/ }, -/* 20 */ -/***/ function(module, exports, __webpack_require__) { - - /* WEBPACK VAR INJECTION */(function(global) {/** - * Module dependencies. - */ - - var transports = __webpack_require__(21); - var Emitter = __webpack_require__(35); - var debug = __webpack_require__(3)('engine.io-client:socket'); - var index = __webpack_require__(42); - var parser = __webpack_require__(27); - var parseuri = __webpack_require__(2); - var parsejson = __webpack_require__(43); - var parseqs = __webpack_require__(36); - - /** - * 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 - : (global.location && '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 || - (global.location ? location.hostname : 'localhost'); - this.port = opts.port || (global.location && 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.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 ? null : opts.rejectUnauthorized; - this.forceNode = !!opts.forceNode; - - // other options for Node.js client - var freeGlobal = typeof global === 'object' && global; - if (freeGlobal.global === freeGlobal) { - 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__(26); - Socket.transports = __webpack_require__(21); - Socket.parser = __webpack_require__(27); - - /** - * 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; - - // session id if we already have one - if (this.id) query.sid = this.id; - - var transport = new transports[name]({ - agent: this.agent, - hostname: this.hostname, - port: this.port, - secure: this.secure, - path: this.path, - query: query, - forceJSONP: this.forceJSONP, - jsonp: this.jsonp, - forceBase64: this.forceBase64, - enablesXDR: this.enablesXDR, - timestampRequests: this.timestampRequests, - timestampParam: this.timestampParam, - policyPort: this.policyPort, - socket: this, - pfx: this.pfx, - key: this.key, - passphrase: this.passphrase, - cert: this.cert, - ca: this.ca, - ciphers: this.ciphers, - rejectUnauthorized: this.rejectUnauthorized, - perMessageDeflate: this.perMessageDeflate, - extraHeaders: this.extraHeaders, - forceNode: this.forceNode, - localAddress: this.localAddress - }); - - 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(parsejson(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; - }; - - /* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }()))) - -/***/ }, -/* 21 */ -/***/ function(module, exports, __webpack_require__) { - - /* WEBPACK VAR INJECTION */(function(global) {/** - * Module dependencies - */ - - var XMLHttpRequest = __webpack_require__(22); - var XHR = __webpack_require__(24); - var JSONP = __webpack_require__(39); - var websocket = __webpack_require__(40); - - /** - * 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 (global.location) { - 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); - } - } - - /* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }()))) - -/***/ }, -/* 22 */ -/***/ function(module, exports, __webpack_require__) { - - /* WEBPACK VAR INJECTION */(function(global) {// browser shim for xmlhttprequest module - - var hasCORS = __webpack_require__(23); - - 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 global[['Active'].concat('Object').join('X')]('Microsoft.XMLHTTP'); - } catch (e) { } - } - }; - - /* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }()))) - -/***/ }, -/* 23 */ -/***/ 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; - } - - -/***/ }, -/* 24 */ -/***/ function(module, exports, __webpack_require__) { - - /* WEBPACK VAR INJECTION */(function(global) {/** - * Module requirements. - */ - - var XMLHttpRequest = __webpack_require__(22); - var Polling = __webpack_require__(25); - var Emitter = __webpack_require__(35); - var inherit = __webpack_require__(37); - 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; - - if (global.location) { - var isSSL = 'https:' === location.protocol; - var port = location.port; - - // some user agents have empty `location.port` - if (!port) { - port = isSSL ? 443 : 80; - } - - this.xd = opts.hostname !== global.location.hostname || - port !== opts.port; - this.xs = opts.secure !== isSSL; - } else { - this.extraHeaders = opts.extraHeaders; - } - } - - /** - * 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(true); - for (var i in this.extraHeaders) { - if (this.extraHeaders.hasOwnProperty(i)) { - xhr.setRequestHeader(i, this.extraHeaders[i]); - } - } - } - } catch (e) {} - if (this.supportsBinary) { - // This has to be done after open because Firefox is stupid - // http://stackoverflow.com/questions/13216903/get-binary-data-with-xmlhttprequest-in-a-firefox-extension - xhr.responseType = 'arraybuffer'; - } - - 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 (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 (global.document) { - 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 (global.document) { - 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').split(';')[0]; - } catch (e) {} - if (contentType === 'application/octet-stream') { - data = this.xhr.response || this.xhr.responseText; - } else { - if (!this.supportsBinary) { - data = this.xhr.responseText; - } else { - try { - data = String.fromCharCode.apply(null, new Uint8Array(this.xhr.response)); - } catch (e) { - var ui8Arr = new Uint8Array(this.xhr.response); - var dataArray = []; - for (var idx = 0, length = ui8Arr.length; idx < length; idx++) { - dataArray.push(ui8Arr[idx]); - } - - data = String.fromCharCode.apply(null, dataArray); - } - } - } - } catch (e) { - this.onError(e); - } - if (null != data) { - this.onData(data); - } - }; - - /** - * Check if it has XDomainRequest. - * - * @api private - */ - - Request.prototype.hasXDR = function () { - return 'undefined' !== typeof global.XDomainRequest && !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 (global.document) { - if (global.attachEvent) { - global.attachEvent('onunload', unloadHandler); - } else if (global.addEventListener) { - global.addEventListener('beforeunload', unloadHandler, false); - } - } - - function unloadHandler () { - for (var i in Request.requests) { - if (Request.requests.hasOwnProperty(i)) { - Request.requests[i].abort(); - } - } - } - - /* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }()))) - -/***/ }, -/* 25 */ -/***/ function(module, exports, __webpack_require__) { - - /** - * Module dependencies. - */ - - var Transport = __webpack_require__(26); - var parseqs = __webpack_require__(36); - var parser = __webpack_require__(27); - var inherit = __webpack_require__(37); - var yeast = __webpack_require__(38); - var debug = __webpack_require__(3)('engine.io-client:polling'); - - /** - * Module exports. - */ - - module.exports = Polling; - - /** - * Is XHR2 supported? - */ - - var hasXHR2 = (function () { - var XMLHttpRequest = __webpack_require__(22); - 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; - }; - - -/***/ }, -/* 26 */ -/***/ function(module, exports, __webpack_require__) { - - /** - * Module dependencies. - */ - - var parser = __webpack_require__(27); - var Emitter = __webpack_require__(35); - - /** - * 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; - - // 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'); - }; - - -/***/ }, -/* 27 */ -/***/ function(module, exports, __webpack_require__) { - - /* WEBPACK VAR INJECTION */(function(global) {/** - * Module dependencies. - */ - - var keys = __webpack_require__(28); - var hasBinary = __webpack_require__(29); - var sliceBuffer = __webpack_require__(30); - var after = __webpack_require__(31); - var utf8 = __webpack_require__(32); - - var base64encoder; - if (global && global.ArrayBuffer) { - base64encoder = __webpack_require__(33); - } - - /** - * 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__(34); - - /** - * 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 ('function' == typeof supportsBinary) { - callback = supportsBinary; - supportsBinary = false; - } - - if ('function' == typeof utf8encode) { - callback = utf8encode; - utf8encode = null; - } - - var data = (packet.data === undefined) - ? undefined - : packet.data.buffer || packet.data; - - if (global.ArrayBuffer && data instanceof ArrayBuffer) { - return encodeArrayBuffer(packet, supportsBinary, callback); - } else if (Blob && data instanceof global.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)) : 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() { - packet.data = fr.result; - exports.encodePacket(packet, 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 (Blob && packet.data instanceof global.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 += global.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); - } 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, true, 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; - } else { - 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, true); - - 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 = []; - - var numberTooLong = false; - 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; - - if (msgLength.length > 310) { - numberTooLong = true; - break; - } - - msgLength += tailArray[i]; - } - - if(numberTooLong) return callback(err, 0, 1); - - 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); - }); - }; - - /* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }()))) - -/***/ }, -/* 28 */ -/***/ 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; - }; - - -/***/ }, -/* 29 */ -/***/ function(module, exports, __webpack_require__) { - - /* WEBPACK VAR INJECTION */(function(global) { - /* - * Module requirements. - */ - - var isArray = __webpack_require__(15); - - /** - * Module exports. - */ - - module.exports = hasBinary; - - /** - * Checks for binary data. - * - * Right now only Buffer and ArrayBuffer are supported.. - * - * @param {Object} anything - * @api public - */ - - function hasBinary(data) { - - function _hasBinary(obj) { - if (!obj) return false; - - if ( (global.Buffer && global.Buffer.isBuffer && global.Buffer.isBuffer(obj)) || - (global.ArrayBuffer && obj instanceof ArrayBuffer) || - (global.Blob && obj instanceof Blob) || - (global.File && obj instanceof File) - ) { - return true; - } - - if (isArray(obj)) { - for (var i = 0; i < obj.length; i++) { - if (_hasBinary(obj[i])) { - return true; - } - } - } else if (obj && 'object' == typeof obj) { - // see: https://github.com/Automattic/has-binary/pull/4 - if (obj.toJSON && 'function' == typeof obj.toJSON) { - obj = obj.toJSON(); - } - - for (var key in obj) { - if (Object.prototype.hasOwnProperty.call(obj, key) && _hasBinary(obj[key])) { - return true; - } - } - } - - return false; - } - - return _hasBinary(data); - } - - /* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }()))) - -/***/ }, -/* 30 */ -/***/ 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; - }; - - -/***/ }, -/* 31 */ -/***/ 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() {} - - -/***/ }, -/* 32 */ -/***/ function(module, exports, __webpack_require__) { - - var __WEBPACK_AMD_DEFINE_RESULT__;/* WEBPACK VAR INJECTION */(function(module, global) {/*! https://mths.be/wtf8 v1.0.0 by @mathias */ - ;(function(root) { - - // Detect free variables `exports` - var freeExports = typeof exports == 'object' && exports; - - // Detect free variable `module` - var freeModule = typeof module == 'object' && module && - module.exports == freeExports && module; - - // Detect free variable `global`, from Node.js or Browserified code, - // and use it as `root` - var freeGlobal = typeof global == 'object' && global; - if (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal) { - root = freeGlobal; - } - - /*--------------------------------------------------------------------------*/ - - 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 createByte(codePoint, shift) { - return stringFromCharCode(((codePoint >> shift) & 0x3F) | 0x80); - } - - function encodeCodePoint(codePoint) { - 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 - 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 wtf8encode(string) { - var codePoints = ucs2decode(string); - var length = codePoints.length; - var index = -1; - var codePoint; - var byteString = ''; - while (++index < length) { - codePoint = codePoints[index]; - byteString += encodeCodePoint(codePoint); - } - 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() { - var byte1; - var byte2; - var byte3; - var byte4; - var codePoint; - - if (byteIndex > byteCount) { - throw Error('Invalid byte index'); - } - - if (byteIndex == byteCount) { - return false; - } - - // Read the 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) { - var 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 codePoint; - } else { - throw Error('Invalid continuation byte'); - } - } - - // 4-byte sequence - if ((byte1 & 0xF8) == 0xF0) { - byte2 = readContinuationByte(); - byte3 = readContinuationByte(); - byte4 = readContinuationByte(); - codePoint = ((byte1 & 0x0F) << 0x12) | (byte2 << 0x0C) | - (byte3 << 0x06) | byte4; - if (codePoint >= 0x010000 && codePoint <= 0x10FFFF) { - return codePoint; - } - } - - throw Error('Invalid WTF-8 detected'); - } - - var byteArray; - var byteCount; - var byteIndex; - function wtf8decode(byteString) { - byteArray = ucs2decode(byteString); - byteCount = byteArray.length; - byteIndex = 0; - var codePoints = []; - var tmp; - while ((tmp = decodeSymbol()) !== false) { - codePoints.push(tmp); - } - return ucs2encode(codePoints); - } - - /*--------------------------------------------------------------------------*/ - - var wtf8 = { - 'version': '1.0.0', - 'encode': wtf8encode, - 'decode': wtf8decode - }; - - // Some AMD build optimizers, like r.js, check for specific condition patterns - // like the following: - if ( - true - ) { - !(__WEBPACK_AMD_DEFINE_RESULT__ = function() { - return wtf8; - }.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); - } else if (freeExports && !freeExports.nodeType) { - if (freeModule) { // in Node.js or RingoJS v0.8.0+ - freeModule.exports = wtf8; - } else { // in Narwhal or RingoJS v0.7.0- - var object = {}; - var hasOwnProperty = object.hasOwnProperty; - for (var key in wtf8) { - hasOwnProperty.call(wtf8, key) && (freeExports[key] = wtf8[key]); - } - } - } else { // in Rhino or a web browser - root.wtf8 = wtf8; - } - - }(this)); - - /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(12)(module), (function() { return this; }()))) - -/***/ }, -/* 33 */ -/***/ 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; - }; - })(); - - -/***/ }, -/* 34 */ -/***/ function(module, exports) { - - /* WEBPACK VAR INJECTION */(function(global) {/** - * Create a blob builder even when vendor prefixes exist - */ - - var BlobBuilder = global.BlobBuilder - || global.WebKitBlobBuilder - || global.MSBlobBuilder - || global.MozBlobBuilder; - - /** - * 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) { - for (var i = 0; i < ary.length; i++) { - var chunk = ary[i]; - 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; - } - - ary[i] = buf; - } - } - } - - function BlobBuilderConstructor(ary, options) { - options = options || {}; - - var bb = new BlobBuilder(); - mapArrayBufferViews(ary); - - for (var i = 0; i < ary.length; i++) { - bb.append(ary[i]); - } - - return (options.type) ? bb.getBlob(options.type) : bb.getBlob(); - }; - - function BlobConstructor(ary, options) { - mapArrayBufferViews(ary); - return new Blob(ary, options || {}); - }; - - module.exports = (function() { - if (blobSupported) { - return blobSupportsArrayBufferView ? global.Blob : BlobConstructor; - } else if (blobBuilderSupported) { - return BlobBuilderConstructor; - } else { - return undefined; - } - })(); - - /* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }()))) - -/***/ }, -/* 35 */ -/***/ 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; - }; - - -/***/ }, -/* 36 */ -/***/ 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; - }; - - -/***/ }, -/* 37 */ -/***/ function(module, exports) { - - - module.exports = function(a, b){ - var fn = function(){}; - fn.prototype = b.prototype; - a.prototype = new fn; - a.prototype.constructor = a; - }; - -/***/ }, -/* 38 */ -/***/ 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; - - -/***/ }, -/* 39 */ -/***/ function(module, exports, __webpack_require__) { - - /* WEBPACK VAR INJECTION */(function(global) { - /** - * Module requirements. - */ - - var Polling = __webpack_require__(25); - var inherit = __webpack_require__(37); - - /** - * Module exports. - */ - - module.exports = JSONPPolling; - - /** - * Cached regular expressions. - */ - - var rNewline = /\n/g; - var rEscapedNewline = /\\n/g; - - /** - * Global JSONP callbacks. - */ - - var callbacks; - - /** - * Noop. - */ - - function empty () { } - - /** - * 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 - if (!global.___eio) global.___eio = []; - callbacks = 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 (global.document && global.addEventListener) { - global.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 = '