(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; } module.exports = _arrayLikeToArray, module.exports.__esModule = true, module.exports["default"] = module.exports; },{}],3:[function(require,module,exports){ function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } module.exports = _arrayWithHoles, module.exports.__esModule = true, module.exports["default"] = module.exports; },{}],4:[function(require,module,exports){ function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } module.exports = _assertThisInitialized, module.exports.__esModule = true, module.exports["default"] = module.exports; },{}],5:[function(require,module,exports){ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } module.exports = _classCallCheck, module.exports.__esModule = true, module.exports["default"] = module.exports; },{}],6:[function(require,module,exports){ function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; } module.exports = _createClass, module.exports.__esModule = true, module.exports["default"] = module.exports; },{}],7:[function(require,module,exports){ function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } module.exports = _defineProperty, module.exports.__esModule = true, module.exports["default"] = module.exports; },{}],8:[function(require,module,exports){ function _getPrototypeOf(o) { module.exports = _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }, module.exports.__esModule = true, module.exports["default"] = module.exports; return _getPrototypeOf(o); } module.exports = _getPrototypeOf, module.exports.__esModule = true, module.exports["default"] = module.exports; },{}],9:[function(require,module,exports){ var setPrototypeOf = require("./setPrototypeOf.js"); function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); Object.defineProperty(subClass, "prototype", { writable: false }); if (superClass) setPrototypeOf(subClass, superClass); } module.exports = _inherits, module.exports.__esModule = true, module.exports["default"] = module.exports; },{"./setPrototypeOf.js":13}],10:[function(require,module,exports){ function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); } module.exports = _iterableToArray, module.exports.__esModule = true, module.exports["default"] = module.exports; },{}],11:[function(require,module,exports){ function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } module.exports = _nonIterableRest, module.exports.__esModule = true, module.exports["default"] = module.exports; },{}],12:[function(require,module,exports){ var _typeof = require("./typeof.js")["default"]; var assertThisInitialized = require("./assertThisInitialized.js"); function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } else if (call !== void 0) { throw new TypeError("Derived constructors may only return object or undefined"); } return assertThisInitialized(self); } module.exports = _possibleConstructorReturn, module.exports.__esModule = true, module.exports["default"] = module.exports; },{"./assertThisInitialized.js":4,"./typeof.js":15}],13:[function(require,module,exports){ function _setPrototypeOf(o, p) { module.exports = _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }, module.exports.__esModule = true, module.exports["default"] = module.exports; return _setPrototypeOf(o, p); } module.exports = _setPrototypeOf, module.exports.__esModule = true, module.exports["default"] = module.exports; },{}],14:[function(require,module,exports){ var arrayWithHoles = require("./arrayWithHoles.js"); var iterableToArray = require("./iterableToArray.js"); var unsupportedIterableToArray = require("./unsupportedIterableToArray.js"); var nonIterableRest = require("./nonIterableRest.js"); function _toArray(arr) { return arrayWithHoles(arr) || iterableToArray(arr) || unsupportedIterableToArray(arr) || nonIterableRest(); } module.exports = _toArray, module.exports.__esModule = true, module.exports["default"] = module.exports; },{"./arrayWithHoles.js":3,"./iterableToArray.js":10,"./nonIterableRest.js":11,"./unsupportedIterableToArray.js":16}],15:[function(require,module,exports){ function _typeof(obj) { "@babel/helpers - typeof"; return (module.exports = _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, module.exports.__esModule = true, module.exports["default"] = module.exports), _typeof(obj); } module.exports = _typeof, module.exports.__esModule = true, module.exports["default"] = module.exports; },{}],16:[function(require,module,exports){ var arrayLikeToArray = require("./arrayLikeToArray.js"); function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return arrayLikeToArray(o, minLen); } module.exports = _unsupportedIterableToArray, module.exports.__esModule = true, module.exports["default"] = module.exports; },{"./arrayLikeToArray.js":2}],17:[function(require,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() {} },{}],18:[function(require,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; }; },{}],19:[function(require,module,exports){ /** * Expose `Backoff`. */ module.exports = Backoff; /** * Initialize backoff timer with `opts`. * * - `min` initial timeout in milliseconds [100] * - `max` max timeout [10000] * - `jitter` [0] * - `factor` [2] * * @param {Object} opts * @api public */ function Backoff(opts) { opts = opts || {}; this.ms = opts.min || 100; this.max = opts.max || 10000; this.factor = opts.factor || 2; this.jitter = opts.jitter > 0 && opts.jitter <= 1 ? opts.jitter : 0; this.attempts = 0; } /** * Return the backoff duration. * * @return {Number} * @api public */ Backoff.prototype.duration = function(){ var ms = this.ms * Math.pow(this.factor, this.attempts++); if (this.jitter) { var rand = Math.random(); var deviation = Math.floor(rand * this.jitter * ms); ms = (Math.floor(rand * 10) & 1) == 0 ? ms - deviation : ms + deviation; } return Math.min(ms, this.max) | 0; }; /** * Reset the number of attempts. * * @api public */ Backoff.prototype.reset = function(){ this.attempts = 0; }; /** * Set the minimum duration * * @api public */ Backoff.prototype.setMin = function(min){ this.ms = min; }; /** * Set the maximum duration * * @api public */ Backoff.prototype.setMax = function(max){ this.max = max; }; /** * Set the jitter * * @api public */ Backoff.prototype.setJitter = function(jitter){ this.jitter = jitter; }; },{}],20:[function(require,module,exports){ /** * Create a blob builder even when vendor prefixes exist */ var BlobBuilder = typeof BlobBuilder !== 'undefined' ? BlobBuilder : typeof WebKitBlobBuilder !== 'undefined' ? WebKitBlobBuilder : typeof MSBlobBuilder !== 'undefined' ? MSBlobBuilder : typeof MozBlobBuilder !== 'undefined' ? MozBlobBuilder : false; /** * Check if Blob constructor is supported */ var blobSupported = (function() { try { var a = new Blob(['hi']); return a.size === 2; } catch(e) { return false; } })(); /** * Check if Blob constructor supports ArrayBufferViews * Fails in Safari 6, so we need to map to ArrayBuffers there. */ var blobSupportsArrayBufferView = blobSupported && (function() { try { var b = new Blob([new Uint8Array([1,2])]); return b.size === 2; } catch(e) { return false; } })(); /** * Check if BlobBuilder is supported */ var blobBuilderSupported = BlobBuilder && BlobBuilder.prototype.append && BlobBuilder.prototype.getBlob; /** * Helper function that maps ArrayBufferViews to ArrayBuffers * Used by BlobBuilder constructor and old browsers that didn't * support it in the Blob constructor. */ function mapArrayBufferViews(ary) { return ary.map(function(chunk) { if (chunk.buffer instanceof ArrayBuffer) { var buf = chunk.buffer; // if this is a subarray, make a copy so we only // include the subarray region from the underlying buffer if (chunk.byteLength !== buf.byteLength) { var copy = new Uint8Array(chunk.byteLength); copy.set(new Uint8Array(buf, chunk.byteOffset, chunk.byteLength)); buf = copy.buffer; } return buf; } return chunk; }); } function BlobBuilderConstructor(ary, options) { options = options || {}; var bb = new BlobBuilder(); mapArrayBufferViews(ary).forEach(function(part) { bb.append(part); }); return (options.type) ? bb.getBlob(options.type) : bb.getBlob(); }; function BlobConstructor(ary, options) { return new Blob(mapArrayBufferViews(ary), options || {}); }; if (typeof Blob !== 'undefined') { BlobBuilderConstructor.prototype = Blob.prototype; BlobConstructor.prototype = Blob.prototype; } module.exports = (function() { if (blobSupported) { return blobSupportsArrayBufferView ? Blob : BlobConstructor; } else if (blobBuilderSupported) { return BlobBuilderConstructor; } else { return undefined; } })(); },{}],21:[function(require,module,exports){ 'use strict'; var GetIntrinsic = require('get-intrinsic'); var callBind = require('./'); var $indexOf = callBind(GetIntrinsic('String.prototype.indexOf')); module.exports = function callBoundIntrinsic(name, allowMissing) { var intrinsic = GetIntrinsic(name, !!allowMissing); if (typeof intrinsic === 'function' && $indexOf(name, '.prototype.') > -1) { return callBind(intrinsic); } return intrinsic; }; },{"./":22,"get-intrinsic":67}],22:[function(require,module,exports){ 'use strict'; var bind = require('function-bind'); var GetIntrinsic = require('get-intrinsic'); var $apply = GetIntrinsic('%Function.prototype.apply%'); var $call = GetIntrinsic('%Function.prototype.call%'); var $reflectApply = GetIntrinsic('%Reflect.apply%', true) || bind.call($call, $apply); var $gOPD = GetIntrinsic('%Object.getOwnPropertyDescriptor%', true); var $defineProperty = GetIntrinsic('%Object.defineProperty%', true); var $max = GetIntrinsic('%Math.max%'); if ($defineProperty) { try { $defineProperty({}, 'a', { value: 1 }); } catch (e) { // IE 8 has a broken defineProperty $defineProperty = null; } } module.exports = function callBind(originalFunction) { var func = $reflectApply(bind, $call, arguments); if ($gOPD && $defineProperty) { var desc = $gOPD(func, 'length'); if (desc.configurable) { // original length, plus the receiver, minus any additional arguments (after the receiver) $defineProperty( func, 'length', { value: 1 + $max(0, originalFunction.length - (arguments.length - 1)) } ); } } return func; }; var applyBind = function applyBind() { return $reflectApply(bind, $apply, arguments); }; if ($defineProperty) { $defineProperty(module.exports, 'apply', { value: applyBind }); } else { module.exports.apply = applyBind; } },{"function-bind":65,"get-intrinsic":67}],23:[function(require,module,exports){ var EventEmitter = require('events').EventEmitter var storage = require('./lib/storage') var logger = require('./lib/logger') var debug = require('./lib/debug') var copy = require('./lib/copy') var help = require('./lib/help') var perf = require('./lib/perf') var log = require('./lib/log') var getAllRoutes = require('wayfarer/get-all-routes') module.exports = expose function expose (opts) { opts = opts || {} store.storeName = 'choo-devtools' return store function store (state, emitter, app) { var localEmitter = new EventEmitter() if (typeof window !== 'undefined') { logger(state, emitter, opts) } emitter.on('DOMContentLoaded', function () { if (typeof window === 'undefined') return window.choo = {} window.choo.state = state window.choo.emit = function () { emitter.emit.apply(emitter, arguments) } window.choo.on = function (eventName, listener) { emitter.on(eventName, listener) } debug(state, emitter, app, localEmitter) log(state, emitter, app, localEmitter) perf(state, emitter, app, localEmitter) window.choo.copy = copy if (app.router && app.router.router) { window.choo.routes = Object.keys(getAllRoutes(app.router.router)) } storage() help() }) } } },{"./lib/copy":24,"./lib/debug":25,"./lib/help":26,"./lib/log":27,"./lib/logger":28,"./lib/perf":29,"./lib/storage":30,"events":294,"wayfarer/get-all-routes":198}],24:[function(require,module,exports){ var stateCopy = require('state-copy') var pluck = require('plucker') module.exports = copy function copy (state) { var isStateString = state && typeof state === 'string' var isChooPath = isStateString && arguments.length === 1 && state.indexOf('state.') === 0 if (!state || typeof state === 'function') state = window.choo.state if (isChooPath) [].push.call(arguments, { state: window.choo.state }) stateCopy(isStateString ? pluck.apply(this, arguments) : state) } },{"plucker":132,"state-copy":189}],25:[function(require,module,exports){ /* eslint-disable node/no-deprecated-api */ var onChange = require('object-change-callsite') var nanologger = require('nanologger') var assert = require('assert') var enabledMessage = 'Debugging enabled. To disable run: `choo.debug = false`' var disabledMessage = 'Debugging disabled. We hope it was helpful! 🙌' module.exports = debug function debug (state, emitter, app, localEmitter) { var log = nanologger('choo-devtools') var enabled = window.localStorage.logLevel === 'debug' if (enabled) log.info(enabledMessage) state = onChange(state, function (attr, value, callsite) { if (!enabled) return callsite = callsite.split('\n')[1].replace(/^ +/, '') log.info('state.' + attr, value, '\n' + callsite) }) app.state = state Object.defineProperty(window.choo, 'debug', { get: function () { window.localStorage.logLevel = 'debug' localEmitter.emit('debug', true) enabled = true return enabledMessage }, set: function (bool) { assert.equal(typeof bool, 'boolean', 'choo-devtools.debug: bool should be type boolean') window.localStorage.logLevel = bool ? 'debug' : 'info' enabled = bool localEmitter.emit('debug', enabled) if (enabled) log.info(enabledMessage) else log.info(disabledMessage) } }) } },{"assert":287,"nanologger":116,"object-change-callsite":126}],26:[function(require,module,exports){ module.exports = help function help () { Object.defineProperty(window.choo, 'help', { get: get, set: noop }) function get () { setTimeout(function () { print('copy', 'Serialize the current state to the clipboard.') print('debug', 'Enable Choo debug mode.') print('emit', 'Emit an event in the Choo emitter.') print('help', 'Print usage information.') print('log', 'Print the last 150 events emitted.') print('on', 'Listen for an event in the Choo emitter.') print('once', 'Listen for an event once in the Choo emitter.') print('perf', 'Print out performance metrics') print('state', 'Print the Choo state object.') print('storage', 'Print browser storage information.') }, 0) return 'Choo command overview' } } function print (cmd, desc) { var color = '#cc99cc' console.log(' %cchoo.' + cmd, 'color: ' + color, '— ' + desc) } function noop () {} },{}],27:[function(require,module,exports){ var removeItems = require('remove-array-items') var scheduler = require('nanoscheduler')() var nanologger = require('nanologger') var _log = nanologger('choo') var clone = require('clone') var MAX_HISTORY_LENGTH = 150 // How many items we should keep around module.exports = log function log (state, emitter, app, localEmitter) { var shouldDebug = window.localStorage.logLevel === 'debug' var history = [] var i = 0 var shouldWarn = true localEmitter.on('debug', function (bool) { shouldDebug = bool }) window.choo._history = history window.choo.history = showHistory Object.defineProperty(window.choo, 'log', { get: showHistory, set: noop }) Object.defineProperty(window.choo, 'history', { get: showHistory, set: noop }) emitter.on('*', function (name, data) { i += 1 var entry = new Event(name, data, state) history.push(entry) scheduler.push(function () { var length = history.length if (length > MAX_HISTORY_LENGTH) { removeItems(history, 0, length - MAX_HISTORY_LENGTH) } }) }) function showHistory () { setTimeout(function () { console.table(history) }, 0) var events = i === 1 ? 'event' : 'events' var msg = i + ' ' + events + ' recorded, showing the last ' + MAX_HISTORY_LENGTH + '.' if (shouldDebug === false) { msg += ' Enable state capture by calling `choo.debug`.' } else { msg += ' Disable state capture by calling `choo.debug = false`.' } return msg } function Event (name, data, state) { this.name = name this.data = data === undefined ? '' : data this.state = shouldDebug ? tryClone(state) : '' } function tryClone (state) { try { var _state = clone(state) if (!shouldWarn) shouldWarn = true return _state } catch (ex) { if (shouldWarn) { _log.warn('Could not clone your app state. Make sure to have a serializable state so it can be cloned') shouldWarn = false } return '' } } } function noop () {} },{"clone":39,"nanologger":116,"nanoscheduler":124,"remove-array-items":31}],28:[function(require,module,exports){ var scheduler = require('nanoscheduler')() var nanologger = require('nanologger') var Hooks = require('choo-hooks') module.exports = logger function logger (state, emitter, opts) { var initialRender = true var hooks = Hooks(emitter) var log = nanologger('choo') hooks.on('log:debug', logger('debug')) hooks.on('log:info', logger('info')) hooks.on('log:warn', logger('warn')) hooks.on('log:error', logger('error')) hooks.on('log:fatal', logger('fatal')) hooks.on('event', function (eventName, data, timing) { if (opts.filter && !opts.filter(eventName, data, timing)) return if (timing) { var duration = timing.duration.toFixed() var level = duration < 50 ? 'info' : 'warn' if (data !== undefined) logger(level)(eventName, data, duration + 'ms') else logger(level)(eventName, duration + 'ms') } else { if (data !== undefined) logger('info')(eventName, data) else logger('info')(eventName) } }) hooks.on('unhandled', function (eventName, data) { logger('error')('No listeners for ' + eventName) }) hooks.on('DOMContentLoaded', function (timing) { if (!timing) return logger('info')('DOMContentLoaded') var level = timing.interactive < 1000 ? 'info' : 'warn' logger(level)('DOMContentLoaded', timing.interactive + 'ms to interactive') }) hooks.on('render', function (timings) { if (!timings || !timings.render) return logger('info')('render') var duration = timings.render.duration.toFixed() var msg = 'render' if (initialRender) { initialRender = false msg = 'initial ' + msg } // each frame has 10ms available for userland stuff var fps = Math.min((600 / duration).toFixed(), 60) if (fps === 60) { logger('info')(msg, fps + 'fps', duration + 'ms') } else { var times = { render: timings.render.duration.toFixed() + 'ms' } if (timings.morph) times.morph = timings.morph.duration.toFixed() + 'ms' logger('warn')(msg, fps + 'fps', duration + 'ms', times) } }) hooks.on('resource-timing-buffer-full', function () { logger('error')("The browser's Resource Resource timing buffer is full. Cannot store any more timing information") }) hooks.start() function logger (level) { return function () { var args = [] for (var i = 0, len = arguments.length; i < len; i++) { args.push(arguments[i]) } scheduler.push(function () { log[level].apply(log, args) }) } } } },{"choo-hooks":32,"nanologger":116,"nanoscheduler":124}],29:[function(require,module,exports){ var onPerformance = require('on-performance') var BAR = '█' module.exports = perf function perf (state, emitter, app, localEmitter) { var stats = {} window.choo.perf = {} // Print all events var all = new Perf(stats, 'all') Object.defineProperty(window.choo.perf, 'all', { get: all.get.bind(all), set: noop }) // Print only Choo core events var core = new Perf(stats, 'core', function (name) { return /^choo/.test(name) }) Object.defineProperty(window.choo.perf, 'core', { get: core.get.bind(core), set: noop }) // Print component data var components = new Perf(stats, 'components', function (name) { return !/^choo/.test(name) && !/^bankai/.test(name) }) Object.defineProperty(window.choo.perf, 'components', { get: components.get.bind(components), set: noop }) // Print choo userland events (event emitter) var events = new Perf(stats, 'events', function (name) { return /^choo\.emit/.test(name) }, function (name) { return name.replace(/^choo\.emit\('/, '').replace(/'\)$/, '') }) Object.defineProperty(window.choo.perf, 'events', { get: events.get.bind(events), set: noop }) onPerformance(function (entry) { if (entry.entryType !== 'measure') return var name = entry.name.replace(/ .*$/, '') if (!stats[name]) { stats[name] = { name: name, count: 0, entries: [] } } var stat = stats[name] stat.count += 1 stat.entries.push(entry.duration) }) } // Create a new Perf instance by passing it a filter function Perf (stats, name, filter, rename) { this.stats = stats this.name = name this.filter = filter || function () { return true } this.rename = rename || function (name) { return name } } // Compute a table of performance entries based on a filter Perf.prototype.get = function () { var filtered = Object.keys(this.stats).filter(this.filter) var self = this var maxTime = 0 var maxMedian = 0 var fmt = filtered.map(function (key) { var stat = self.stats[key] var totalTime = Number(stat.entries.reduce(function (time, entry) { return time + entry }, 0).toFixed(2)) if (totalTime > maxTime) maxTime = totalTime var median = getMedian(stat.entries) if (median > maxMedian) maxMedian = median var name = self.rename(stat.name) return new PerfEntry(name, totalTime, median, stat.count) }) var barLength = 10 fmt.forEach(function (entry) { var totalTime = entry['Total Time (ms)'] var median = entry['Median (ms)'] entry[' '] = createBar(totalTime / maxTime * 100 / barLength) entry[' '] = createBar(median / maxMedian * 100 / barLength) }) function createBar (len) { var str = '' for (var i = 0, max = Math.round(len); i < max; i++) { str += BAR } return str } var res = fmt.sort(function (a, b) { return b['Total Time (ms)'] - a['Total Time (ms)'] }) console.table(res) return "Showing performance events for '" + this.name + "'" } // An entry for the performance timeline. function PerfEntry (name, totalTime, median, count) { this.Name = name this['Total Time (ms)'] = totalTime this[' '] = 0 this['Median (ms)'] = median this[' '] = 0 this['Total Count'] = count } // Get the median from an array of numbers. function getMedian (args) { if (!args.length) return 0 var numbers = args.slice(0).sort(function (a, b) { return a - b }) var middle = Math.floor(numbers.length / 2) var isEven = numbers.length % 2 === 0 var res = isEven ? (numbers[middle] + numbers[middle - 1]) / 2 : numbers[middle] return Number(res.toFixed(2)) } // Do nothing. function noop () {} },{"on-performance":129}],30:[function(require,module,exports){ var pretty = require('prettier-bytes') module.exports = storage function storage () { Object.defineProperty(window.choo, 'storage', { get: get, set: noop }) function get () { if (navigator.storage) { navigator.storage.estimate().then(function (estimate) { var value = (estimate.usage / estimate.quota).toFixed() clr('Max storage:', fmt(estimate.quota)) clr('Storage used:', fmt(estimate.usage) + ' (' + value + '%)') navigator.storage.persisted().then(function (bool) { var val = bool ? 'enabled' : 'disabled' clr('Persistent storage:', val) }) }) return 'Calculating storage quota…' } else { var protocol = window.location.protocol return (/https/.test(protocol)) ? "The Storage API is unavailable in this browser. We're sorry!" : 'The Storage API is unavailable. Serving this site over HTTPS might help enable it!' } } } function clr (msg, arg) { var color = '#cc99cc' console.log('%c' + msg, 'color: ' + color, arg) } function fmt (num) { return pretty(num).replace(' ', '') } function noop () {} },{"prettier-bytes":133}],31:[function(require,module,exports){ 'use strict'; /** * Remove a range of items from an array * * @function removeItems * @param {Array<*>} arr The target array * @param {number} startIdx The index to begin removing from (inclusive) * @param {number} removeCount How many items to remove */ function removeItems (arr, startIdx, removeCount) { var i, length = arr.length; if (startIdx >= length || removeCount <= 0 || startIdx < 0) { return } removeCount = (startIdx + removeCount > length ? length - startIdx : removeCount); var len = length - removeCount; for (i = startIdx; i < len; ++i) { arr[i] = arr[i + removeCount]; } arr.length = len; } module.exports = removeItems; },{}],32:[function(require,module,exports){ var onPerformance = require('on-performance') var scheduler = require('nanoscheduler')() var assert = require('assert') module.exports = ChooHooks function ChooHooks (emitter) { if (!(this instanceof ChooHooks)) return new ChooHooks(emitter) assert.equal(typeof emitter, 'object') this.hasWindow = typeof window !== 'undefined' this.hasIdleCallback = this.hasWindow && window.requestIdleCallback this.hasPerformance = this.hasWindow && window.performance && window.performance.getEntriesByName this.emitter = emitter this.listeners = {} this.buffer = { render: {}, events: {} } } ChooHooks.prototype.on = function (name, handler) { this.listeners[name] = handler } ChooHooks.prototype.start = function () { var self = this if (this.hasPerformance) { window.performance.onresourcetimingbufferfull = function () { var listener = self.listeners['resource-timing-buffer-full'] if (listener) listener() } } // TODO also handle log events onPerformance(function (timing) { if (!timing) return if (timing.entryType !== 'measure') return var eventName = timing.name if (/choo\.morph/.test(eventName)) { self.buffer.render.morph = timing } else if (/choo\.route/.test(eventName)) { self.buffer.render.route = timing } else if (/choo\.render/.test(eventName)) { self.buffer.render.render = timing } else if (/choo\.emit/.test(eventName) && !/log:/.test(eventName)) { var eventListener = self.listeners['event'] if (eventListener) { var timingName = eventName.match(/choo\.emit\('(.*)'\)/)[1] if (timingName === 'render' || timingName === 'DOMContentLoaded') return var traceId = eventName.match(/\[(\d+)\]/)[1] var data = self.buffer.events[traceId] self.buffer.events[traceId] = null eventListener(timingName, data, timing) } } var rBuf = self.buffer.render if (rBuf.render && rBuf.route && rBuf.morph) { var renderListener = self.listeners['render'] if (!renderListener) return var timings = {} while (self.buffer.render.length) { var _timing = self.buffer.render.pop() var name = _timing.name if (/choo\.render/.test(name)) timings.render = _timing else if (/choo\.morph/.test(name)) timings.morph = _timing else timings.route = _timing } rBuf.render = rBuf.route = rBuf.morph = void 0 renderListener(timings) } }) // Check if there's timings without any listeners // and trigger the DOMContentLoaded event. // If the timing API is not available, we handle all events here this.emitter.on('*', function (eventName, data, uuid) { var logLevel = /^log:(\w{4,5})/.exec(eventName) if (!self.hasPerformance && eventName === 'render') { // Render var renderListener = self.listeners['render'] if (renderListener) renderListener() } else if (eventName === 'DOMContentLoaded') { // DOMContentLoaded self._emitLoaded() } else if (logLevel) { logLevel = logLevel[1] // Log:* var logListener = self.listeners['log:' + logLevel] if (logListener) { logListener.apply(null, Array.prototype.slice.call(arguments, 0, arguments.length - 1)) } } else if (!self.emitter.listeners(eventName).length) { // Unhandled var unhandledListener = self.listeners['unhandled'] if (unhandledListener) unhandledListener(eventName, data) } else if (eventName !== 'render') { // * if (self.hasPerformance) self.buffer.events[uuid] = data } }) } // compute and log time till interactive when DOMContentLoaded event fires ChooHooks.prototype._emitLoaded = function () { var self = this scheduler.push(function clear () { var listener = self.listeners['DOMContentLoaded'] var timing = self.hasWindow && window.performance && window.performance.timing if (listener && timing) { listener({ interactive: timing.domInteractive - timing.navigationStart, loaded: timing.domContentLoadedEventEnd - timing.navigationStart }) } }) } },{"assert":287,"nanoscheduler":124,"on-performance":129}],33:[function(require,module,exports){ var assert = require('assert') var LRU = require('nanolru') module.exports = ChooComponentCache function ChooComponentCache (state, emit, lru) { assert.ok(this instanceof ChooComponentCache, 'ChooComponentCache should be created with `new`') assert.equal(typeof state, 'object', 'ChooComponentCache: state should be type object') assert.equal(typeof emit, 'function', 'ChooComponentCache: emit should be type function') if (typeof lru === 'number') this.cache = new LRU(lru) else this.cache = lru || new LRU(100) this.state = state this.emit = emit } // Get & create component instances. ChooComponentCache.prototype.render = function (Component, id) { assert.equal(typeof Component, 'function', 'ChooComponentCache.render: Component should be type function') assert.ok(typeof id === 'string' || typeof id === 'number', 'ChooComponentCache.render: id should be type string or type number') var el = this.cache.get(id) if (!el) { var args = [] for (var i = 2, len = arguments.length; i < len; i++) { args.push(arguments[i]) } args.unshift(Component, id, this.state, this.emit) el = newCall.apply(newCall, args) this.cache.set(id, el) } return el } // Because you can't call `new` and `.apply()` at the same time. This is a mad // hack, but hey it works so we gonna go for it. Whoop. function newCall (Cls) { return new (Cls.bind.apply(Cls, arguments)) // eslint-disable-line } },{"assert":103,"nanolru":117}],34:[function(require,module,exports){ module.exports = require('nanocomponent') },{"nanocomponent":105}],35:[function(require,module,exports){ module.exports = require('nanohtml') },{"nanohtml":110}],36:[function(require,module,exports){ module.exports = require('nanohtml/raw') },{"nanohtml/raw":113}],37:[function(require,module,exports){ var scrollToAnchor = require('scroll-to-anchor') var documentReady = require('document-ready') var nanotiming = require('nanotiming') var nanorouter = require('nanorouter') var nanomorph = require('nanomorph') var nanoquery = require('nanoquery') var nanohref = require('nanohref') var nanoraf = require('nanoraf') var nanobus = require('nanobus') var assert = require('assert') var Cache = require('./component/cache') module.exports = Choo var HISTORY_OBJECT = {} function Choo (opts) { var timing = nanotiming('choo.constructor') if (!(this instanceof Choo)) return new Choo(opts) opts = opts || {} assert.equal(typeof opts, 'object', 'choo: opts should be type object') var self = this // define events used by choo this._events = { DOMCONTENTLOADED: 'DOMContentLoaded', DOMTITLECHANGE: 'DOMTitleChange', REPLACESTATE: 'replaceState', PUSHSTATE: 'pushState', NAVIGATE: 'navigate', POPSTATE: 'popState', RENDER: 'render' } // properties for internal use only this._historyEnabled = opts.history === undefined ? true : opts.history this._hrefEnabled = opts.href === undefined ? true : opts.href this._hashEnabled = opts.hash === undefined ? false : opts.hash this._hasWindow = typeof window !== 'undefined' this._cache = opts.cache this._loaded = false this._stores = [ondomtitlechange] this._tree = null // state var _state = { events: this._events, components: {} } if (this._hasWindow) { this.state = window.initialState ? Object.assign({}, window.initialState, _state) : _state delete window.initialState } else { this.state = _state } // properties that are part of the API this.router = nanorouter({ curry: true }) this.emitter = nanobus('choo.emit') this.emit = this.emitter.emit.bind(this.emitter) // listen for title changes; available even when calling .toString() if (this._hasWindow) this.state.title = document.title function ondomtitlechange (state) { self.emitter.prependListener(self._events.DOMTITLECHANGE, function (title) { assert.equal(typeof title, 'string', 'events.DOMTitleChange: title should be type string') state.title = title if (self._hasWindow) document.title = title }) } timing() } Choo.prototype.route = function (route, handler) { var routeTiming = nanotiming("choo.route('" + route + "')") assert.equal(typeof route, 'string', 'choo.route: route should be type string') assert.equal(typeof handler, 'function', 'choo.handler: route should be type function') this.router.on(route, handler) routeTiming() } Choo.prototype.use = function (cb) { assert.equal(typeof cb, 'function', 'choo.use: cb should be type function') var self = this this._stores.push(function (state) { var msg = 'choo.use' msg = cb.storeName ? msg + '(' + cb.storeName + ')' : msg var endTiming = nanotiming(msg) cb(state, self.emitter, self) endTiming() }) } Choo.prototype.start = function () { assert.equal(typeof window, 'object', 'choo.start: window was not found. .start() must be called in a browser, use .toString() if running in Node') var startTiming = nanotiming('choo.start') var self = this if (this._historyEnabled) { this.emitter.prependListener(this._events.NAVIGATE, function () { self._matchRoute(self.state) if (self._loaded) { self.emitter.emit(self._events.RENDER) setTimeout(scrollToAnchor.bind(null, window.location.hash), 0) } }) this.emitter.prependListener(this._events.POPSTATE, function () { self.emitter.emit(self._events.NAVIGATE) }) this.emitter.prependListener(this._events.PUSHSTATE, function (href) { assert.equal(typeof href, 'string', 'events.pushState: href should be type string') window.history.pushState(HISTORY_OBJECT, null, href) self.emitter.emit(self._events.NAVIGATE) }) this.emitter.prependListener(this._events.REPLACESTATE, function (href) { assert.equal(typeof href, 'string', 'events.replaceState: href should be type string') window.history.replaceState(HISTORY_OBJECT, null, href) self.emitter.emit(self._events.NAVIGATE) }) window.onpopstate = function () { self.emitter.emit(self._events.POPSTATE) } if (self._hrefEnabled) { nanohref(function (location) { var href = location.href var hash = location.hash if (href === window.location.href) { if (!self._hashEnabled && hash) scrollToAnchor(hash) return } self.emitter.emit(self._events.PUSHSTATE, href) }) } } this._setCache(this.state) this._matchRoute(this.state) this._stores.forEach(function (initStore) { initStore(self.state) }) this._tree = this._prerender(this.state) assert.ok(this._tree, 'choo.start: no valid DOM node returned for location ' + this.state.href) this.emitter.prependListener(self._events.RENDER, nanoraf(function () { var renderTiming = nanotiming('choo.render') var newTree = self._prerender(self.state) assert.ok(newTree, 'choo.render: no valid DOM node returned for location ' + self.state.href) assert.equal(self._tree.nodeName, newTree.nodeName, 'choo.render: The target node <' + self._tree.nodeName.toLowerCase() + '> is not the same type as the new node <' + newTree.nodeName.toLowerCase() + '>.') var morphTiming = nanotiming('choo.morph') nanomorph(self._tree, newTree) morphTiming() renderTiming() })) documentReady(function () { self.emitter.emit(self._events.DOMCONTENTLOADED) self._loaded = true }) startTiming() return this._tree } Choo.prototype.mount = function mount (selector) { var mountTiming = nanotiming("choo.mount('" + selector + "')") if (typeof window !== 'object') { assert.ok(typeof selector === 'string', 'choo.mount: selector should be type String') this.selector = selector mountTiming() return this } assert.ok(typeof selector === 'string' || typeof selector === 'object', 'choo.mount: selector should be type String or HTMLElement') var self = this documentReady(function () { var renderTiming = nanotiming('choo.render') var newTree = self.start() if (typeof selector === 'string') { self._tree = document.querySelector(selector) } else { self._tree = selector } assert.ok(self._tree, 'choo.mount: could not query selector: ' + selector) assert.equal(self._tree.nodeName, newTree.nodeName, 'choo.mount: The target node <' + self._tree.nodeName.toLowerCase() + '> is not the same type as the new node <' + newTree.nodeName.toLowerCase() + '>.') var morphTiming = nanotiming('choo.morph') nanomorph(self._tree, newTree) morphTiming() renderTiming() }) mountTiming() } Choo.prototype.toString = function (location, state) { state = state || {} state.components = state.components || {} state.events = Object.assign({}, state.events, this._events) assert.notEqual(typeof window, 'object', 'choo.mount: window was found. .toString() must be called in Node, use .start() or .mount() if running in the browser') assert.equal(typeof location, 'string', 'choo.toString: location should be type string') assert.equal(typeof state, 'object', 'choo.toString: state should be type object') this._setCache(state) this._matchRoute(state, location) this.emitter.removeAllListeners() this._stores.forEach(function (initStore) { initStore(state) }) var html = this._prerender(state) assert.ok(html, 'choo.toString: no valid value returned for the route ' + location) assert(!Array.isArray(html), 'choo.toString: return value was an array for the route ' + location) return typeof html.outerHTML === 'string' ? html.outerHTML : html.toString() } Choo.prototype._matchRoute = function (state, locationOverride) { var location, queryString if (locationOverride) { location = locationOverride.replace(/\?.+$/, '').replace(/\/$/, '') if (!this._hashEnabled) location = location.replace(/#.+$/, '') queryString = locationOverride } else { location = window.location.pathname.replace(/\/$/, '') if (this._hashEnabled) location += window.location.hash.replace(/^#/, '/') queryString = window.location.search } var matched = this.router.match(location) this._handler = matched.cb state.href = location state.query = nanoquery(queryString) state.route = matched.route state.params = matched.params } Choo.prototype._prerender = function (state) { var routeTiming = nanotiming("choo.prerender('" + state.route + "')") var res = this._handler(state, this.emit) routeTiming() return res } Choo.prototype._setCache = function (state) { var cache = new Cache(state, this.emitter.emit.bind(this.emitter), this._cache) state.cache = renderComponent function renderComponent (Component, id) { assert.equal(typeof Component, 'function', 'choo.state.cache: Component should be type function') var args = [] for (var i = 0, len = arguments.length; i < len; i++) { args.push(arguments[i]) } return cache.render.apply(cache, args) } // When the state gets stringified, make sure `state.cache` isn't // stringified too. renderComponent.toJSON = function () { return null } } },{"./component/cache":33,"assert":103,"document-ready":43,"nanobus":104,"nanohref":107,"nanomorph":118,"nanoquery":121,"nanoraf":122,"nanorouter":123,"nanotiming":125,"scroll-to-anchor":143}],38:[function(require,module,exports){ /*! clipboard-copy. MIT License. Feross Aboukhadijeh */ /* global DOMException */ module.exports = clipboardCopy function clipboardCopy (text) { // Use the Async Clipboard API when available. Requires a secure browsing // context (i.e. HTTPS) if (navigator.clipboard) { return navigator.clipboard.writeText(text).catch(function (err) { throw (err !== undefined ? err : new DOMException('The request is not allowed', 'NotAllowedError')) }) } // ...Otherwise, use document.execCommand() fallback // Put the text to copy into a var span = document.createElement('span') span.textContent = text // Preserve consecutive spaces and newlines span.style.whiteSpace = 'pre' span.style.webkitUserSelect = 'auto' span.style.userSelect = 'all' // Add the to the page document.body.appendChild(span) // Make a selection object representing the range of text selected by the user var selection = window.getSelection() var range = window.document.createRange() selection.removeAllRanges() range.selectNode(span) selection.addRange(range) // Copy text to the clipboard var success = false try { success = window.document.execCommand('copy') } catch (err) { console.log('error', err) } // Cleanup selection.removeAllRanges() window.document.body.removeChild(span) return success ? Promise.resolve() : Promise.reject(new DOMException('The request is not allowed', 'NotAllowedError')) } },{}],39:[function(require,module,exports){ (function (Buffer){(function (){ var clone = (function() { 'use strict'; function _instanceof(obj, type) { return type != null && obj instanceof type; } var nativeMap; try { nativeMap = Map; } catch(_) { // maybe a reference error because no `Map`. Give it a dummy value that no // value will ever be an instanceof. nativeMap = function() {}; } var nativeSet; try { nativeSet = Set; } catch(_) { nativeSet = function() {}; } var nativePromise; try { nativePromise = Promise; } catch(_) { nativePromise = function() {}; } /** * Clones (copies) an Object using deep copying. * * This function supports circular references by default, but if you are certain * there are no circular references in your object, you can save some CPU time * by calling clone(obj, false). * * Caution: if `circular` is false and `parent` contains circular references, * your program may enter an infinite loop and crash. * * @param `parent` - the object to be cloned * @param `circular` - set to true if the object to be cloned may contain * circular references. (optional - true by default) * @param `depth` - set to a number if the object is only to be cloned to * a particular depth. (optional - defaults to Infinity) * @param `prototype` - sets the prototype to be used when cloning an object. * (optional - defaults to parent prototype). * @param `includeNonEnumerable` - set to true if the non-enumerable properties * should be cloned as well. Non-enumerable properties on the prototype * chain will be ignored. (optional - false by default) */ function clone(parent, circular, depth, prototype, includeNonEnumerable) { if (typeof circular === 'object') { depth = circular.depth; prototype = circular.prototype; includeNonEnumerable = circular.includeNonEnumerable; circular = circular.circular; } // maintain two arrays for circular references, where corresponding parents // and children have the same index var allParents = []; var allChildren = []; var useBuffer = typeof Buffer != 'undefined'; if (typeof circular == 'undefined') circular = true; if (typeof depth == 'undefined') depth = Infinity; // recurse this function so we don't reset allParents and allChildren function _clone(parent, depth) { // cloning null always returns null if (parent === null) return null; if (depth === 0) return parent; var child; var proto; if (typeof parent != 'object') { return parent; } if (_instanceof(parent, nativeMap)) { child = new nativeMap(); } else if (_instanceof(parent, nativeSet)) { child = new nativeSet(); } else if (_instanceof(parent, nativePromise)) { child = new nativePromise(function (resolve, reject) { parent.then(function(value) { resolve(_clone(value, depth - 1)); }, function(err) { reject(_clone(err, depth - 1)); }); }); } else if (clone.__isArray(parent)) { child = []; } else if (clone.__isRegExp(parent)) { child = new RegExp(parent.source, __getRegExpFlags(parent)); if (parent.lastIndex) child.lastIndex = parent.lastIndex; } else if (clone.__isDate(parent)) { child = new Date(parent.getTime()); } else if (useBuffer && Buffer.isBuffer(parent)) { if (Buffer.allocUnsafe) { // Node.js >= 4.5.0 child = Buffer.allocUnsafe(parent.length); } else { // Older Node.js versions child = new Buffer(parent.length); } parent.copy(child); return child; } else if (_instanceof(parent, Error)) { child = Object.create(parent); } else { if (typeof prototype == 'undefined') { proto = Object.getPrototypeOf(parent); child = Object.create(proto); } else { child = Object.create(prototype); proto = prototype; } } if (circular) { var index = allParents.indexOf(parent); if (index != -1) { return allChildren[index]; } allParents.push(parent); allChildren.push(child); } if (_instanceof(parent, nativeMap)) { parent.forEach(function(value, key) { var keyChild = _clone(key, depth - 1); var valueChild = _clone(value, depth - 1); child.set(keyChild, valueChild); }); } if (_instanceof(parent, nativeSet)) { parent.forEach(function(value) { var entryChild = _clone(value, depth - 1); child.add(entryChild); }); } for (var i in parent) { var attrs; if (proto) { attrs = Object.getOwnPropertyDescriptor(proto, i); } if (attrs && attrs.set == null) { continue; } child[i] = _clone(parent[i], depth - 1); } if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(parent); for (var i = 0; i < symbols.length; i++) { // Don't need to worry about cloning a symbol because it is a primitive, // like a number or string. var symbol = symbols[i]; var descriptor = Object.getOwnPropertyDescriptor(parent, symbol); if (descriptor && !descriptor.enumerable && !includeNonEnumerable) { continue; } child[symbol] = _clone(parent[symbol], depth - 1); if (!descriptor.enumerable) { Object.defineProperty(child, symbol, { enumerable: false }); } } } if (includeNonEnumerable) { var allPropertyNames = Object.getOwnPropertyNames(parent); for (var i = 0; i < allPropertyNames.length; i++) { var propertyName = allPropertyNames[i]; var descriptor = Object.getOwnPropertyDescriptor(parent, propertyName); if (descriptor && descriptor.enumerable) { continue; } child[propertyName] = _clone(parent[propertyName], depth - 1); Object.defineProperty(child, propertyName, { enumerable: false }); } } return child; } return _clone(parent, depth); } /** * Simple flat clone using prototype, accepts only objects, usefull for property * override on FLAT configuration object (no nested props). * * USE WITH CAUTION! This may not behave as you wish if you do not know how this * works. */ clone.clonePrototype = function clonePrototype(parent) { if (parent === null) return null; var c = function () {}; c.prototype = parent; return new c(); }; // private utility functions function __objToStr(o) { return Object.prototype.toString.call(o); } clone.__objToStr = __objToStr; function __isDate(o) { return typeof o === 'object' && __objToStr(o) === '[object Date]'; } clone.__isDate = __isDate; function __isArray(o) { return typeof o === 'object' && __objToStr(o) === '[object Array]'; } clone.__isArray = __isArray; function __isRegExp(o) { return typeof o === 'object' && __objToStr(o) === '[object RegExp]'; } clone.__isRegExp = __isRegExp; function __getRegExpFlags(re) { var flags = ''; if (re.global) flags += 'g'; if (re.ignoreCase) flags += 'i'; if (re.multiline) flags += 'm'; return flags; } clone.__getRegExpFlags = __getRegExpFlags; return clone; })(); if (typeof module === 'object' && module.exports) { module.exports = clone; } }).call(this)}).call(this,require("buffer").Buffer) },{"buffer":293}],40:[function(require,module,exports){ /** * Slice reference. */ var slice = [].slice; /** * Bind `obj` to `fn`. * * @param {Object} obj * @param {Function|String} fn or string * @return {Function} * @api public */ module.exports = function(obj, fn){ if ('string' == typeof fn) fn = obj[fn]; if ('function' != typeof fn) throw new Error('bind() requires a function'); var args = slice.call(arguments, 2); return function(){ return fn.apply(obj, args.concat(slice.call(arguments))); } }; },{}],41:[function(require,module,exports){ /** * Expose `Emitter`. */ if (typeof module !== 'undefined') { module.exports = Emitter; } /** * Initialize a new `Emitter`. * * @api public */ function Emitter(obj) { if (obj) return mixin(obj); }; /** * Mixin the emitter properties. * * @param {Object} obj * @return {Object} * @api private */ function mixin(obj) { for (var key in Emitter.prototype) { obj[key] = Emitter.prototype[key]; } return obj; } /** * Listen on the given `event` with `fn`. * * @param {String} event * @param {Function} fn * @return {Emitter} * @api public */ Emitter.prototype.on = Emitter.prototype.addEventListener = function(event, fn){ this._callbacks = this._callbacks || {}; (this._callbacks['$' + event] = this._callbacks['$' + event] || []) .push(fn); return this; }; /** * Adds an `event` listener that will be invoked a single * time then automatically removed. * * @param {String} event * @param {Function} fn * @return {Emitter} * @api public */ Emitter.prototype.once = function(event, fn){ function on() { this.off(event, on); fn.apply(this, arguments); } on.fn = fn; this.on(event, on); return this; }; /** * Remove the given callback for `event` or all * registered callbacks. * * @param {String} event * @param {Function} fn * @return {Emitter} * @api public */ Emitter.prototype.off = Emitter.prototype.removeListener = Emitter.prototype.removeAllListeners = Emitter.prototype.removeEventListener = function(event, fn){ this._callbacks = this._callbacks || {}; // all if (0 == arguments.length) { this._callbacks = {}; return this; } // specific event var callbacks = this._callbacks['$' + event]; if (!callbacks) return this; // remove all handlers if (1 == arguments.length) { delete this._callbacks['$' + event]; return this; } // remove specific handler var cb; for (var i = 0; i < callbacks.length; i++) { cb = callbacks[i]; if (cb === fn || cb.fn === fn) { callbacks.splice(i, 1); break; } } // Remove event specific arrays for event types that no // one is subscribed for to avoid memory leak. if (callbacks.length === 0) { delete this._callbacks['$' + event]; } return this; }; /** * Emit `event` with the given args. * * @param {String} event * @param {Mixed} ... * @return {Emitter} */ Emitter.prototype.emit = function(event){ this._callbacks = this._callbacks || {}; var args = new Array(arguments.length - 1) , callbacks = this._callbacks['$' + event]; for (var i = 1; i < arguments.length; i++) { args[i - 1] = arguments[i]; } if (callbacks) { callbacks = callbacks.slice(0); for (var i = 0, len = callbacks.length; i < len; ++i) { callbacks[i].apply(this, args); } } return this; }; /** * Return array of callbacks for `event`. * * @param {String} event * @return {Array} * @api public */ Emitter.prototype.listeners = function(event){ this._callbacks = this._callbacks || {}; return this._callbacks['$' + event] || []; }; /** * Check if this emitter has `event` handlers. * * @param {String} event * @return {Boolean} * @api public */ Emitter.prototype.hasListeners = function(event){ return !! this.listeners(event).length; }; },{}],42:[function(require,module,exports){ module.exports = function(a, b){ var fn = function(){}; fn.prototype = b.prototype; a.prototype = new fn; a.prototype.constructor = a; }; },{}],43:[function(require,module,exports){ 'use strict' module.exports = ready function ready (callback) { if (typeof document === 'undefined') { throw new Error('document-ready only runs in the browser') } var state = document.readyState if (state === 'complete' || state === 'interactive') { return setTimeout(callback, 0) } document.addEventListener('DOMContentLoaded', function onLoad () { callback() }) } },{}],44:[function(require,module,exports){ module.exports = (function () { if (typeof self !== 'undefined') { return self; } else if (typeof window !== 'undefined') { return window; } else { return Function('return this')(); // eslint-disable-line no-new-func } })(); },{}],45:[function(require,module,exports){ module.exports = require('./socket'); /** * Exports parser * * @api public * */ module.exports.parser = require('engine.io-parser'); },{"./socket":46,"engine.io-parser":58}],46:[function(require,module,exports){ /** * Module dependencies. */ var transports = require('./transports/index'); var Emitter = require('component-emitter'); var debug = require('debug')('engine.io-client:socket'); var index = require('indexof'); var parser = require('engine.io-parser'); var parseuri = require('parseuri'); var parseqs = require('parseqs'); /** * Module exports. */ module.exports = Socket; /** * Socket constructor. * * @param {String|Object} uri or options * @param {Object} options * @api public */ function Socket (uri, opts) { if (!(this instanceof Socket)) return new Socket(uri, opts); opts = opts || {}; if (uri && 'object' === typeof uri) { opts = uri; uri = null; } if (uri) { uri = parseuri(uri); opts.hostname = uri.host; opts.secure = uri.protocol === 'https' || uri.protocol === 'wss'; opts.port = uri.port; if (uri.query) opts.query = uri.query; } else if (opts.host) { opts.hostname = parseuri(opts.host).host; } this.secure = null != opts.secure ? opts.secure : (typeof location !== 'undefined' && 'https:' === location.protocol); if (opts.hostname && !opts.port) { // if no port is specified manually, use the protocol default opts.port = this.secure ? '443' : '80'; } this.agent = opts.agent || false; this.hostname = opts.hostname || (typeof location !== 'undefined' ? location.hostname : 'localhost'); this.port = opts.port || (typeof location !== 'undefined' && location.port ? location.port : (this.secure ? 443 : 80)); this.query = opts.query || {}; if ('string' === typeof this.query) this.query = parseqs.decode(this.query); this.upgrade = false !== opts.upgrade; this.path = (opts.path || '/engine.io').replace(/\/$/, '') + '/'; this.forceJSONP = !!opts.forceJSONP; this.jsonp = false !== opts.jsonp; this.forceBase64 = !!opts.forceBase64; this.enablesXDR = !!opts.enablesXDR; this.withCredentials = false !== opts.withCredentials; this.timestampParam = opts.timestampParam || 't'; this.timestampRequests = opts.timestampRequests; this.transports = opts.transports || ['polling', 'websocket']; this.transportOptions = opts.transportOptions || {}; this.readyState = ''; this.writeBuffer = []; this.prevBufferLen = 0; this.policyPort = opts.policyPort || 843; this.rememberUpgrade = opts.rememberUpgrade || false; this.binaryType = null; this.onlyBinaryUpgrades = opts.onlyBinaryUpgrades; this.perMessageDeflate = false !== opts.perMessageDeflate ? (opts.perMessageDeflate || {}) : false; if (true === this.perMessageDeflate) this.perMessageDeflate = {}; if (this.perMessageDeflate && null == this.perMessageDeflate.threshold) { this.perMessageDeflate.threshold = 1024; } // SSL options for Node.js client this.pfx = opts.pfx || null; this.key = opts.key || null; this.passphrase = opts.passphrase || null; this.cert = opts.cert || null; this.ca = opts.ca || null; this.ciphers = opts.ciphers || null; this.rejectUnauthorized = opts.rejectUnauthorized === undefined ? true : opts.rejectUnauthorized; this.forceNode = !!opts.forceNode; // detect ReactNative environment this.isReactNative = (typeof navigator !== 'undefined' && typeof navigator.product === 'string' && navigator.product.toLowerCase() === 'reactnative'); // other options for Node.js or ReactNative client if (typeof self === 'undefined' || this.isReactNative) { if (opts.extraHeaders && Object.keys(opts.extraHeaders).length > 0) { this.extraHeaders = opts.extraHeaders; } if (opts.localAddress) { this.localAddress = opts.localAddress; } } // set on handshake this.id = null; this.upgrades = null; this.pingInterval = null; this.pingTimeout = null; // set on heartbeat this.pingIntervalTimer = null; this.pingTimeoutTimer = null; this.open(); } Socket.priorWebsocketSuccess = false; /** * Mix in `Emitter`. */ Emitter(Socket.prototype); /** * Protocol version. * * @api public */ Socket.protocol = parser.protocol; // this is an int /** * Expose deps for legacy compatibility * and standalone browser access. */ Socket.Socket = Socket; Socket.Transport = require('./transport'); Socket.transports = require('./transports/index'); Socket.parser = require('engine.io-parser'); /** * Creates transport of the given type. * * @param {String} transport name * @return {Transport} * @api private */ Socket.prototype.createTransport = function (name) { debug('creating transport "%s"', name); var query = clone(this.query); // append engine.io protocol identifier query.EIO = parser.protocol; // transport name query.transport = name; // per-transport options var options = this.transportOptions[name] || {}; // session id if we already have one if (this.id) query.sid = this.id; var transport = new transports[name]({ query: query, socket: this, agent: options.agent || this.agent, hostname: options.hostname || this.hostname, port: options.port || this.port, secure: options.secure || this.secure, path: options.path || this.path, forceJSONP: options.forceJSONP || this.forceJSONP, jsonp: options.jsonp || this.jsonp, forceBase64: options.forceBase64 || this.forceBase64, enablesXDR: options.enablesXDR || this.enablesXDR, withCredentials: options.withCredentials || this.withCredentials, timestampRequests: options.timestampRequests || this.timestampRequests, timestampParam: options.timestampParam || this.timestampParam, policyPort: options.policyPort || this.policyPort, pfx: options.pfx || this.pfx, key: options.key || this.key, passphrase: options.passphrase || this.passphrase, cert: options.cert || this.cert, ca: options.ca || this.ca, ciphers: options.ciphers || this.ciphers, rejectUnauthorized: options.rejectUnauthorized || this.rejectUnauthorized, perMessageDeflate: options.perMessageDeflate || this.perMessageDeflate, extraHeaders: options.extraHeaders || this.extraHeaders, forceNode: options.forceNode || this.forceNode, localAddress: options.localAddress || this.localAddress, requestTimeout: options.requestTimeout || this.requestTimeout, protocols: options.protocols || void (0), isReactNative: this.isReactNative }); return transport; }; function clone (obj) { var o = {}; for (var i in obj) { if (obj.hasOwnProperty(i)) { o[i] = obj[i]; } } return o; } /** * Initializes transport to use and starts probe. * * @api private */ Socket.prototype.open = function () { var transport; if (this.rememberUpgrade && Socket.priorWebsocketSuccess && this.transports.indexOf('websocket') !== -1) { transport = 'websocket'; } else if (0 === this.transports.length) { // Emit error on next tick so it can be listened to var self = this; setTimeout(function () { self.emit('error', 'No transports available'); }, 0); return; } else { transport = this.transports[0]; } this.readyState = 'opening'; // Retry with the next transport if the transport is disabled (jsonp: false) try { transport = this.createTransport(transport); } catch (e) { this.transports.shift(); this.open(); return; } transport.open(); this.setTransport(transport); }; /** * Sets the current transport. Disables the existing one (if any). * * @api private */ Socket.prototype.setTransport = function (transport) { debug('setting transport %s', transport.name); var self = this; if (this.transport) { debug('clearing existing transport %s', this.transport.name); this.transport.removeAllListeners(); } // set up transport this.transport = transport; // set up transport listeners transport .on('drain', function () { self.onDrain(); }) .on('packet', function (packet) { self.onPacket(packet); }) .on('error', function (e) { self.onError(e); }) .on('close', function () { self.onClose('transport close'); }); }; /** * Probes a transport. * * @param {String} transport name * @api private */ Socket.prototype.probe = function (name) { debug('probing transport "%s"', name); var transport = this.createTransport(name, { probe: 1 }); var failed = false; var self = this; Socket.priorWebsocketSuccess = false; function onTransportOpen () { if (self.onlyBinaryUpgrades) { var upgradeLosesBinary = !this.supportsBinary && self.transport.supportsBinary; failed = failed || upgradeLosesBinary; } if (failed) return; debug('probe transport "%s" opened', name); transport.send([{ type: 'ping', data: 'probe' }]); transport.once('packet', function (msg) { if (failed) return; if ('pong' === msg.type && 'probe' === msg.data) { debug('probe transport "%s" pong', name); self.upgrading = true; self.emit('upgrading', transport); if (!transport) return; Socket.priorWebsocketSuccess = 'websocket' === transport.name; debug('pausing current transport "%s"', self.transport.name); self.transport.pause(function () { if (failed) return; if ('closed' === self.readyState) return; debug('changing transport and sending upgrade packet'); cleanup(); self.setTransport(transport); transport.send([{ type: 'upgrade' }]); self.emit('upgrade', transport); transport = null; self.upgrading = false; self.flush(); }); } else { debug('probe transport "%s" failed', name); var err = new Error('probe error'); err.transport = transport.name; self.emit('upgradeError', err); } }); } function freezeTransport () { if (failed) return; // Any callback called by transport should be ignored since now failed = true; cleanup(); transport.close(); transport = null; } // Handle any error that happens while probing function onerror (err) { var error = new Error('probe error: ' + err); error.transport = transport.name; freezeTransport(); debug('probe transport "%s" failed because of error: %s', name, err); self.emit('upgradeError', error); } function onTransportClose () { onerror('transport closed'); } // When the socket is closed while we're probing function onclose () { onerror('socket closed'); } // When the socket is upgraded while we're probing function onupgrade (to) { if (transport && to.name !== transport.name) { debug('"%s" works - aborting "%s"', to.name, transport.name); freezeTransport(); } } // Remove all listeners on the transport and on self function cleanup () { transport.removeListener('open', onTransportOpen); transport.removeListener('error', onerror); transport.removeListener('close', onTransportClose); self.removeListener('close', onclose); self.removeListener('upgrading', onupgrade); } transport.once('open', onTransportOpen); transport.once('error', onerror); transport.once('close', onTransportClose); this.once('close', onclose); this.once('upgrading', onupgrade); transport.open(); }; /** * Called when connection is deemed open. * * @api public */ Socket.prototype.onOpen = function () { debug('socket open'); this.readyState = 'open'; Socket.priorWebsocketSuccess = 'websocket' === this.transport.name; this.emit('open'); this.flush(); // we check for `readyState` in case an `open` // listener already closed the socket if ('open' === this.readyState && this.upgrade && this.transport.pause) { debug('starting upgrade probes'); for (var i = 0, l = this.upgrades.length; i < l; i++) { this.probe(this.upgrades[i]); } } }; /** * Handles a packet. * * @api private */ Socket.prototype.onPacket = function (packet) { if ('opening' === this.readyState || 'open' === this.readyState || 'closing' === this.readyState) { debug('socket receive: type "%s", data "%s"', packet.type, packet.data); this.emit('packet', packet); // Socket is live - any packet counts this.emit('heartbeat'); switch (packet.type) { case 'open': this.onHandshake(JSON.parse(packet.data)); break; case 'pong': this.setPing(); this.emit('pong'); break; case 'error': var err = new Error('server error'); err.code = packet.data; this.onError(err); break; case 'message': this.emit('data', packet.data); this.emit('message', packet.data); break; } } else { debug('packet received with socket readyState "%s"', this.readyState); } }; /** * Called upon handshake completion. * * @param {Object} handshake obj * @api private */ Socket.prototype.onHandshake = function (data) { this.emit('handshake', data); this.id = data.sid; this.transport.query.sid = data.sid; this.upgrades = this.filterUpgrades(data.upgrades); this.pingInterval = data.pingInterval; this.pingTimeout = data.pingTimeout; this.onOpen(); // In case open handler closes socket if ('closed' === this.readyState) return; this.setPing(); // Prolong liveness of socket on heartbeat this.removeListener('heartbeat', this.onHeartbeat); this.on('heartbeat', this.onHeartbeat); }; /** * Resets ping timeout. * * @api private */ Socket.prototype.onHeartbeat = function (timeout) { clearTimeout(this.pingTimeoutTimer); var self = this; self.pingTimeoutTimer = setTimeout(function () { if ('closed' === self.readyState) return; self.onClose('ping timeout'); }, timeout || (self.pingInterval + self.pingTimeout)); }; /** * Pings server every `this.pingInterval` and expects response * within `this.pingTimeout` or closes connection. * * @api private */ Socket.prototype.setPing = function () { var self = this; clearTimeout(self.pingIntervalTimer); self.pingIntervalTimer = setTimeout(function () { debug('writing ping packet - expecting pong within %sms', self.pingTimeout); self.ping(); self.onHeartbeat(self.pingTimeout); }, self.pingInterval); }; /** * Sends a ping packet. * * @api private */ Socket.prototype.ping = function () { var self = this; this.sendPacket('ping', function () { self.emit('ping'); }); }; /** * Called on `drain` event * * @api private */ Socket.prototype.onDrain = function () { this.writeBuffer.splice(0, this.prevBufferLen); // setting prevBufferLen = 0 is very important // for example, when upgrading, upgrade packet is sent over, // and a nonzero prevBufferLen could cause problems on `drain` this.prevBufferLen = 0; if (0 === this.writeBuffer.length) { this.emit('drain'); } else { this.flush(); } }; /** * Flush write buffers. * * @api private */ Socket.prototype.flush = function () { if ('closed' !== this.readyState && this.transport.writable && !this.upgrading && this.writeBuffer.length) { debug('flushing %d packets in socket', this.writeBuffer.length); this.transport.send(this.writeBuffer); // keep track of current length of writeBuffer // splice writeBuffer and callbackBuffer on `drain` this.prevBufferLen = this.writeBuffer.length; this.emit('flush'); } }; /** * Sends a message. * * @param {String} message. * @param {Function} callback function. * @param {Object} options. * @return {Socket} for chaining. * @api public */ Socket.prototype.write = Socket.prototype.send = function (msg, options, fn) { this.sendPacket('message', msg, options, fn); return this; }; /** * Sends a packet. * * @param {String} packet type. * @param {String} data. * @param {Object} options. * @param {Function} callback function. * @api private */ Socket.prototype.sendPacket = function (type, data, options, fn) { if ('function' === typeof data) { fn = data; data = undefined; } if ('function' === typeof options) { fn = options; options = null; } if ('closing' === this.readyState || 'closed' === this.readyState) { return; } options = options || {}; options.compress = false !== options.compress; var packet = { type: type, data: data, options: options }; this.emit('packetCreate', packet); this.writeBuffer.push(packet); if (fn) this.once('flush', fn); this.flush(); }; /** * Closes the connection. * * @api private */ Socket.prototype.close = function () { if ('opening' === this.readyState || 'open' === this.readyState) { this.readyState = 'closing'; var self = this; if (this.writeBuffer.length) { this.once('drain', function () { if (this.upgrading) { waitForUpgrade(); } else { close(); } }); } else if (this.upgrading) { waitForUpgrade(); } else { close(); } } function close () { self.onClose('forced close'); debug('socket closing - telling transport to close'); self.transport.close(); } function cleanupAndClose () { self.removeListener('upgrade', cleanupAndClose); self.removeListener('upgradeError', cleanupAndClose); close(); } function waitForUpgrade () { // wait for upgrade to finish since we can't send packets while pausing a transport self.once('upgrade', cleanupAndClose); self.once('upgradeError', cleanupAndClose); } return this; }; /** * Called upon transport error * * @api private */ Socket.prototype.onError = function (err) { debug('socket error %j', err); Socket.priorWebsocketSuccess = false; this.emit('error', err); this.onClose('transport error', err); }; /** * Called upon transport close. * * @api private */ Socket.prototype.onClose = function (reason, desc) { if ('opening' === this.readyState || 'open' === this.readyState || 'closing' === this.readyState) { debug('socket close with reason: "%s"', reason); var self = this; // clear timers clearTimeout(this.pingIntervalTimer); clearTimeout(this.pingTimeoutTimer); // stop event from firing again for transport this.transport.removeAllListeners('close'); // ensure transport won't stay open this.transport.close(); // ignore further transport communication this.transport.removeAllListeners(); // set ready state this.readyState = 'closed'; // clear session id this.id = null; // emit close event this.emit('close', reason, desc); // clean buffers after, so users can still // grab the buffers on `close` event self.writeBuffer = []; self.prevBufferLen = 0; } }; /** * Filters upgrades, returning only those matching client transports. * * @param {Array} server upgrades * @api private * */ Socket.prototype.filterUpgrades = function (upgrades) { var filteredUpgrades = []; for (var i = 0, j = upgrades.length; i < j; i++) { if (~index(this.transports, upgrades[i])) filteredUpgrades.push(upgrades[i]); } return filteredUpgrades; }; },{"./transport":47,"./transports/index":48,"component-emitter":41,"debug":54,"engine.io-parser":58,"indexof":100,"parseqs":56,"parseuri":57}],47:[function(require,module,exports){ /** * Module dependencies. */ var parser = require('engine.io-parser'); var Emitter = require('component-emitter'); /** * 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; this.withCredentials = opts.withCredentials; // SSL options for Node.js client this.pfx = opts.pfx; this.key = opts.key; this.passphrase = opts.passphrase; this.cert = opts.cert; this.ca = opts.ca; this.ciphers = opts.ciphers; this.rejectUnauthorized = opts.rejectUnauthorized; this.forceNode = opts.forceNode; // results of ReactNative environment detection this.isReactNative = opts.isReactNative; // other options for Node.js client this.extraHeaders = opts.extraHeaders; this.localAddress = opts.localAddress; } /** * Mix in `Emitter`. */ 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'); }; },{"component-emitter":41,"engine.io-parser":58}],48:[function(require,module,exports){ /** * Module dependencies */ var XMLHttpRequest = require('xmlhttprequest-ssl'); var XHR = require('./polling-xhr'); var JSONP = require('./polling-jsonp'); var websocket = require('./websocket'); /** * Export transports. */ exports.polling = polling; exports.websocket = websocket; /** * Polling transport polymorphic constructor. * Decides on xhr vs jsonp based on feature detection. * * @api private */ function polling (opts) { var xhr; var xd = false; var xs = false; var jsonp = false !== opts.jsonp; if (typeof location !== 'undefined') { var isSSL = 'https:' === location.protocol; var port = location.port; // some user agents have empty `location.port` if (!port) { port = isSSL ? 443 : 80; } xd = opts.hostname !== location.hostname || port !== opts.port; xs = opts.secure !== isSSL; } opts.xdomain = xd; opts.xscheme = xs; xhr = new XMLHttpRequest(opts); if ('open' in xhr && !opts.forceJSONP) { return new XHR(opts); } else { if (!jsonp) throw new Error('JSONP disabled'); return new JSONP(opts); } } },{"./polling-jsonp":49,"./polling-xhr":50,"./websocket":52,"xmlhttprequest-ssl":53}],49:[function(require,module,exports){ /** * Module requirements. */ var Polling = require('./polling'); var inherit = require('component-inherit'); var globalThis = require('../globalThis'); /** * 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 callbacks = globalThis.___eio = (globalThis.___eio || []); } // callback identifier this.index = callbacks.length; // add callback to jsonp global var self = this; callbacks.push(function (msg) { self.onData(msg); }); // append to query string this.query.j = this.index; // prevent spurious errors from being emitted when the window is unloaded if (typeof addEventListener === 'function') { addEventListener('beforeunload', function () { if (self.script) self.script.onerror = empty; }, false); } } /** * Inherits from Polling. */ inherit(JSONPPolling, Polling); /* * JSONP only supports binary as base64 encoded strings */ JSONPPolling.prototype.supportsBinary = false; /** * Closes the socket. * * @api private */ JSONPPolling.prototype.doClose = function () { if (this.script) { this.script.parentNode.removeChild(this.script); this.script = null; } if (this.form) { this.form.parentNode.removeChild(this.form); this.form = null; this.iframe = null; } Polling.prototype.doClose.call(this); }; /** * Starts a poll cycle. * * @api private */ JSONPPolling.prototype.doPoll = function () { var self = this; var script = document.createElement('script'); if (this.script) { this.script.parentNode.removeChild(this.script); this.script = null; } script.async = true; script.src = this.uri(); script.onerror = function (e) { self.onError('jsonp poll error', e); }; var insertAt = document.getElementsByTagName('script')[0]; if (insertAt) { insertAt.parentNode.insertBefore(script, insertAt); } else { (document.head || document.body).appendChild(script); } this.script = script; var isUAgecko = 'undefined' !== typeof navigator && /gecko/i.test(navigator.userAgent); if (isUAgecko) { setTimeout(function () { var iframe = document.createElement('iframe'); document.body.appendChild(iframe); document.body.removeChild(iframe); }, 100); } }; /** * Writes with a hidden iframe. * * @param {String} data to send * @param {Function} called upon flush. * @api private */ JSONPPolling.prototype.doWrite = function (data, fn) { var self = this; if (!this.form) { var form = document.createElement('form'); var area = document.createElement('textarea'); var id = this.iframeId = 'eio_iframe_' + this.index; var iframe; form.className = 'socketio'; form.style.position = 'absolute'; form.style.top = '-1000px'; form.style.left = '-1000px'; form.target = id; form.method = 'POST'; form.setAttribute('accept-charset', 'utf-8'); area.name = 'd'; form.appendChild(area); document.body.appendChild(form); this.form = form; this.area = area; } this.form.action = this.uri(); function complete () { initIframe(); fn(); } function initIframe () { if (self.iframe) { try { self.form.removeChild(self.iframe); } catch (e) { self.onError('jsonp polling iframe removal error', e); } } try { // ie6 dynamic iframes with target="" support (thanks Chris Lambacher) var html = '