zoukankan      html  css  js  c++  java
  • vue使用远程在线更新代码

    一、main.js

     1 import Vue from 'vue'
     2 import App from './App'
     3 import router from './router'
     4 import Vuex from 'vuex'
     5 import store from './store'
     6 import axios from 'axios'
     7 import VueAwesomeSwiper from 'vue-awesome-swiper'
     8 import 'swiper/dist/css/swiper.css'
     9 // import VueSocketio from 'vue-socket.io'
    10 
    11 Vue.config.productionTip = false
    12 Vue.use(Vuex)
    13 // Vue.use(VueSocketio)
    14 
    15 
    16 var ls_mac = "_ioBox_mac_code_key_";
    17 var ls_proid = "_io_ioBox_pro_id_key_";
    18 var ls_protitle = "_io_ioBox_title_key_";
    19 
    20 //检查mac地址缓存
    21 var macCode = localStorage.getItem(ls_mac);
    22 console.log("macCode",macCode)
    23 if(!macCode){
    24   console.log("macCode222",macCode)
    25   //没有则生成mac,提交设备号
    26   NWBridge && NWBridge.getMac((mac) => {
    27       //alert(str);
    28       macCode = mac;
    29       localStorage.setItem(ls_mac,macCode);
    30       ini && ini.setString('',macCode,()=>{},ini.fileName.macCode);
    31     var zipFormData = new FormData();
    32     console.log("macCode333",macCode)
    33     zipFormData.append('mac',macCode);
    34     zipFormData.append('title',"北京65box(抽奖)");
    35 
    36     return axios.post('http://iboxmanager.ioart.cn/Api/add/module/device/key/dac509bd90a82719a3569291e12c24a6f1af4bac/',zipFormData).then((res) => {
    37       console.log("macCode444",res.data.error_code)
    38       console.log("macCode555",res.data.error_code == 0)
    39       if (res.data.error_code == 0) {
    40 
    41         NWBridge.checkUpdate();
    42         //增加监听
    43         autoUpdateSocket(macCode);
    44       }
    45     }).catch(function (error) {
    46       console.log(error);
    47     })
    48 
    49     }
    50   );
    51 }else{
    52   //检查更新
    53   NWBridge.checkUpdate();
    54   //增加监听
    55   autoUpdateSocket(macCode);
    56 }
    57 
    58 
    59 function autoUpdateSocket(mac) {
    60   //监听 用于自动升级处理
    61   var socket = io('http://msgsender.ioart.cn:2120');
    62   //建立连接后
    63   socket.on('connect', function() {
    64     socket.emit('login',mac);
    65   });
    66   //接收通信
    67   socket.on('coffeeorder', function(msg){
    68     NWBridge.checkUpdate();
    69   });
    70 }
    71 
    72 
    73 /* eslint-disable no-new */
    74 new Vue({
    75   el: '#app',
    76   router,
    77   store,
    78   components: { App },
    79   template: '<App/>'
    80 })
    View Code



    二、index.html

     1 <!DOCTYPE html>
     2 <html>
     3   <head>
     4     <meta charset="utf-8">
     5     <meta name="viewport" content="width=device-width,initial-scale=1.0">
     6     <meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" name="viewport" />
     7     <title>my-project</title>
     8   </head>
     9   <body style="overflow:hidden;">
    10 
    11   <script src="../static/js/md5.min.js?v=1547962386444"></script>
    12   <script src="../static/js/ini.js?v=1547962386444"></script>
    13   <script src="../static/js/NWBridge.js?v=1547962386444"></script>
    14   <script src="../static/js/socket.io.js?v=<%= htmlWebpackPlugin.options.version %>"></script>
    15     <div id="app"></div>
    16     <!-- built files will be auto injected -->
    17   </body>
    18 </html>
    View Code



    三、ini.js (直接引入)

     1 var ini = (function () {
     2  var that;
     3  /*将ini文件更新到res目录统计,防止更新时覆盖此文件*/
     4  var  fs = require && require("fs") || null;
     5  var obj = function () {
     6   that = this;
     7   that.fileName = {
     8    config: '../config.ini',
     9    macCode: '../macCode.txt'
    10   };
    11  };
    12  obj.prototype = {
    13   set: function (key, value, callback, file) {
    14    var cf = this._readFile(file || that.fileName.config);
    15    cf[key] = value;
    16 
    17    fs.writeFile(file || that.fileName.config, JSON.stringify(cf), function (err) {
    18     if (err) throw err;
    19 
    20     if (typeof callback == "function") callback();
    21    });
    22   },
    23 
    24   setString: function (key, value, callback, file) {
    25    var cf = this._readFile(file, true);
    26    cf[key] = value;
    27             fs && fs.writeFile(file || that.fileName.config, value, function (err) {
    28     if (err) throw err;
    29     if (typeof callback == "function") callback();
    30    });
    31   },
    32 
    33   setSync: function (key, value, callback, file) {
    34    var cf = this._readFile(file || that.fileName.config);
    35    cf[key] = value;
    36             fs && fs.writeFileSync(file || that.fileName.config, JSON.stringify(cf));
    37   },
    38 
    39   get: function (key, file) {
    40    var cf = this._readFile(file || that.fileName.config);
    41    return cf[key] || '';
    42   },
    43         getString: function (key, file) {
    44             var cf = this._readFile(file || that.fileName.config, true);
    45             return cf[key] || '';
    46         },
    47   getAll: function (file) {
    48    var cf = this._readFile(file || that.fileName.config);
    49    return cf;
    50   },
    51 
    52   _readFile: function (file, defaultValue) {
    53    //file = file || fileName;
    54 
    55    if (file) {
    56     return this._writeFile(file, defaultValue);
    57    } else {
    58     for (var i = 0; i < that.fileName.length; i++) {
    59      this._writeFile(that.fileName.config, defaultValue);
    60     }
    61    }
    62   },
    63   _writeFile: function (file, defaultValue) {
    64    if (!fs) return '';
    65    if (!fs.existsSync(file)) {
    66     fs.writeFile(file, (!defaultValue ? '{}' : ''), function (err) {
    67      if (err) throw err;
    68     });
    69     return {};
    70    }
    71 
    72    var str = fs.readFileSync(file);
    73    try {
    74     return JSON.parse(str);
    75    } catch (e) {
    76     return {};
    77    }
    78   }
    79  };
    80 
    81  return new obj();
    82 })();
    View Code



    四、md5.min.js(直接引入)

    1 !function(a){"use strict";function b(a,b){var c=(65535&a)+(65535&b),d=(a>>16)+(b>>16)+(c>>16);return d<<16|65535&c}function c(a,b){return a<<b|a>>>32-b}function d(a,d,e,f,g,h){return b(c(b(b(d,a),b(f,h)),g),e)}function e(a,b,c,e,f,g,h){return d(b&c|~b&e,a,b,f,g,h)}function f(a,b,c,e,f,g,h){return d(b&e|c&~e,a,b,f,g,h)}function g(a,b,c,e,f,g,h){return d(b^c^e,a,b,f,g,h)}function h(a,b,c,e,f,g,h){return d(c^(b|~e),a,b,f,g,h)}function i(a,c){a[c>>5]|=128<<c%32,a[(c+64>>>9<<4)+14]=c;var d,i,j,k,l,m=1732584193,n=-271733879,o=-1732584194,p=271733878;for(d=0;d<a.length;d+=16)i=m,j=n,k=o,l=p,m=e(m,n,o,p,a[d],7,-680876936),p=e(p,m,n,o,a[d+1],12,-389564586),o=e(o,p,m,n,a[d+2],17,606105819),n=e(n,o,p,m,a[d+3],22,-1044525330),m=e(m,n,o,p,a[d+4],7,-176418897),p=e(p,m,n,o,a[d+5],12,1200080426),o=e(o,p,m,n,a[d+6],17,-1473231341),n=e(n,o,p,m,a[d+7],22,-45705983),m=e(m,n,o,p,a[d+8],7,1770035416),p=e(p,m,n,o,a[d+9],12,-1958414417),o=e(o,p,m,n,a[d+10],17,-42063),n=e(n,o,p,m,a[d+11],22,-1990404162),m=e(m,n,o,p,a[d+12],7,1804603682),p=e(p,m,n,o,a[d+13],12,-40341101),o=e(o,p,m,n,a[d+14],17,-1502002290),n=e(n,o,p,m,a[d+15],22,1236535329),m=f(m,n,o,p,a[d+1],5,-165796510),p=f(p,m,n,o,a[d+6],9,-1069501632),o=f(o,p,m,n,a[d+11],14,643717713),n=f(n,o,p,m,a[d],20,-373897302),m=f(m,n,o,p,a[d+5],5,-701558691),p=f(p,m,n,o,a[d+10],9,38016083),o=f(o,p,m,n,a[d+15],14,-660478335),n=f(n,o,p,m,a[d+4],20,-405537848),m=f(m,n,o,p,a[d+9],5,568446438),p=f(p,m,n,o,a[d+14],9,-1019803690),o=f(o,p,m,n,a[d+3],14,-187363961),n=f(n,o,p,m,a[d+8],20,1163531501),m=f(m,n,o,p,a[d+13],5,-1444681467),p=f(p,m,n,o,a[d+2],9,-51403784),o=f(o,p,m,n,a[d+7],14,1735328473),n=f(n,o,p,m,a[d+12],20,-1926607734),m=g(m,n,o,p,a[d+5],4,-378558),p=g(p,m,n,o,a[d+8],11,-2022574463),o=g(o,p,m,n,a[d+11],16,1839030562),n=g(n,o,p,m,a[d+14],23,-35309556),m=g(m,n,o,p,a[d+1],4,-1530992060),p=g(p,m,n,o,a[d+4],11,1272893353),o=g(o,p,m,n,a[d+7],16,-155497632),n=g(n,o,p,m,a[d+10],23,-1094730640),m=g(m,n,o,p,a[d+13],4,681279174),p=g(p,m,n,o,a[d],11,-358537222),o=g(o,p,m,n,a[d+3],16,-722521979),n=g(n,o,p,m,a[d+6],23,76029189),m=g(m,n,o,p,a[d+9],4,-640364487),p=g(p,m,n,o,a[d+12],11,-421815835),o=g(o,p,m,n,a[d+15],16,530742520),n=g(n,o,p,m,a[d+2],23,-995338651),m=h(m,n,o,p,a[d],6,-198630844),p=h(p,m,n,o,a[d+7],10,1126891415),o=h(o,p,m,n,a[d+14],15,-1416354905),n=h(n,o,p,m,a[d+5],21,-57434055),m=h(m,n,o,p,a[d+12],6,1700485571),p=h(p,m,n,o,a[d+3],10,-1894986606),o=h(o,p,m,n,a[d+10],15,-1051523),n=h(n,o,p,m,a[d+1],21,-2054922799),m=h(m,n,o,p,a[d+8],6,1873313359),p=h(p,m,n,o,a[d+15],10,-30611744),o=h(o,p,m,n,a[d+6],15,-1560198380),n=h(n,o,p,m,a[d+13],21,1309151649),m=h(m,n,o,p,a[d+4],6,-145523070),p=h(p,m,n,o,a[d+11],10,-1120210379),o=h(o,p,m,n,a[d+2],15,718787259),n=h(n,o,p,m,a[d+9],21,-343485551),m=b(m,i),n=b(n,j),o=b(o,k),p=b(p,l);return[m,n,o,p]}function j(a){var b,c="";for(b=0;b<32*a.length;b+=8)c+=String.fromCharCode(a[b>>5]>>>b%32&255);return c}function k(a){var b,c=[];for(c[(a.length>>2)-1]=void 0,b=0;b<c.length;b+=1)c[b]=0;for(b=0;b<8*a.length;b+=8)c[b>>5]|=(255&a.charCodeAt(b/8))<<b%32;return c}function l(a){return j(i(k(a),8*a.length))}function m(a,b){var c,d,e=k(a),f=[],g=[];for(f[15]=g[15]=void 0,e.length>16&&(e=i(e,8*a.length)),c=0;16>c;c+=1)f[c]=909522486^e[c],g[c]=1549556828^e[c];return d=i(f.concat(k(b)),512+8*b.length),j(i(g.concat(d),640))}function n(a){var b,c,d="0123456789abcdef",e="";for(c=0;c<a.length;c+=1)b=a.charCodeAt(c),e+=d.charAt(b>>>4&15)+d.charAt(15&b);return e}function o(a){return unescape(encodeURIComponent(a))}function p(a){return l(o(a))}function q(a){return n(p(a))}function r(a,b){return m(o(a),o(b))}function s(a,b){return n(r(a,b))}function t(a,b,c){return b?c?r(b,a):s(b,a):c?p(a):q(a)}"function"==typeof define&&define.amd?define(function(){return t}):a.md5=t}(this);
    View Code
    五、NWBridge.js(直接引入)

     1 /**
     2  * Created by Administrator on 2017/10/17 0017.
     3  */
     4 var NWBridge = (function (){
     5     var that;
     6     var obj = function () {
     7         that = this;
     8         if (top.require) {
     9             that.http = top.require('http');
    10             that.https = top.require('https');
    11             that.mac = top.require("getmac");
    12             that.nodePath = top.require('path');
    13             that.exec = top.require('child_process').exec;
    14             that.spawn = top.require('child_process').spawn;
    15         }
    16     };
    17     obj.prototype = {
    18         getMac: (callback) => {
    19             that.mac && that.mac.getMac(function (err, macAddress) {
    20                 if (err) throw err;
    21                 var macCode = md5(macAddress);
    22                 callback(macCode);
    23             });
    24         },
    25         checkAutoUpdaterTwo: (callback) => {
    26             if ( !top.require) return;
    27             var fs = top.require('fs');
    28             var pathParent = that.nodePath.dirname(process.cwd());
    29             fs.exists(pathParent + '\autoUpdate2.exe', (exists) => {
    30                 if (exists) {
    31                     var unlinkName = '\autoUpdate.exe';
    32                     fs.exists(pathParent + unlinkName, (flag) => {
    33                         if (flag) {
    34                             fs.unlink(pathParent + unlinkName,  (err) =>{
    35                                 if ( err ) console.log('ERROR: ' + err);
    36                                 fs.rename(pathParent + '\autoUpdate2.exe', pathParent + '\autoUpdate.exe', (err) =>{
    37                                     if ( err ) console.log('ERROR: ' + err);
    38                                     callback && callback();
    39                                 });
    40                             });
    41                         } else {
    42                             callback && callback();
    43                         }
    44                     });
    45                 } else {
    46                     callback && callback();
    47                 }
    48             });
    49         },
    50         checkUpdate: (callback) => {
    51             // 加 "" 是因为 直接执行路径有空格时会抛异常 所以需要加双引号当成一个字符串
    52             that.lsUpdate = that.exec('"' + that.nodePath.dirname(process.cwd())  + '\autoUpdate.exe' + '"',
    53                  (error, stdout, stderr) => {
    54                     console.log('stdout: ' + stdout);
    55                     console.log('stderr: ' + stderr);
    56                     if (error !== null) {
    57                         console.log('exec error: ' + error);
    58                     }
    59                 });
    60             that.lsUpdate.stdout.on('data',  (data)  => {
    61                 if (data) {
    62                     if (eval(data)) {
    63                         setTimeout( ()  =>{
    64                             var gui = top.require('nw.gui');
    65                             gui.Window.get().close();
    66                         }, 2000);
    67                     } else {
    68                         callback && callback();
    69                     }
    70                 } else {
    71                     callback && callback();
    72                 }
    73             });
    74 
    75             that.lsUpdate.stderr.on('data', (data)  => {
    76                 that.lsUpdate.kill();
    77                 console.error('stderr: ' + data);
    78             });
    79 
    80             that.lsUpdate.on('close',(code)  =>{
    81                 that.lsUpdate.kill();
    82                 callback && callback();
    83             });
    84             return that.lsUpdate;
    85         }
    86     };
    87     return new obj();
    88 })();
    View Code



    六、socket.io.js(直接引入)

       1 !function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.io=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){
       2 
       3 module.exports = _dereq_('./lib/');
       4 
       5 },{"./lib/":2}],2:[function(_dereq_,module,exports){
       6 
       7 /**
       8  * Module dependencies.
       9  */
      10 
      11 var url = _dereq_('./url');
      12 var parser = _dereq_('socket.io-parser');
      13 var Manager = _dereq_('./manager');
      14 var debug = _dereq_('debug')('socket.io-client');
      15 
      16 /**
      17  * Module exports.
      18  */
      19 
      20 module.exports = exports = lookup;
      21 
      22 /**
      23  * Managers cache.
      24  */
      25 
      26 var cache = exports.managers = {};
      27 
      28 /**
      29  * Looks up an existing `Manager` for multiplexing.
      30  * If the user summons:
      31  *
      32  *   `io('http://localhost/a');`
      33  *   `io('http://localhost/b');`
      34  *
      35  * We reuse the existing instance based on same scheme/port/host,
      36  * and we initialize sockets for each namespace.
      37  *
      38  * @api public
      39  */
      40 
      41 function lookup(uri, opts) {
      42   if (typeof uri == 'object') {
      43     opts = uri;
      44     uri = undefined;
      45   }
      46 
      47   opts = opts || {};
      48 
      49   var parsed = url(uri);
      50   var source = parsed.source;
      51   var id = parsed.id;
      52   var io;
      53 
      54   if (opts.forceNew || opts['force new connection'] || false === opts.multiplex) {
      55     debug('ignoring socket cache for %s', source);
      56     io = Manager(source, opts);
      57   } else {
      58     if (!cache[id]) {
      59       debug('new io instance for %s', source);
      60       cache[id] = Manager(source, opts);
      61     }
      62     io = cache[id];
      63   }
      64 
      65   return io.socket(parsed.path);
      66 }
      67 
      68 /**
      69  * Protocol version.
      70  *
      71  * @api public
      72  */
      73 
      74 exports.protocol = parser.protocol;
      75 
      76 /**
      77  * `connect`.
      78  *
      79  * @param {String} uri
      80  * @api public
      81  */
      82 
      83 exports.connect = lookup;
      84 
      85 /**
      86  * Expose constructors for standalone build.
      87  *
      88  * @api public
      89  */
      90 
      91 exports.Manager = _dereq_('./manager');
      92 exports.Socket = _dereq_('./socket');
      93 
      94 },{"./manager":3,"./socket":5,"./url":6,"debug":10,"socket.io-parser":44}],3:[function(_dereq_,module,exports){
      95 
      96 /**
      97  * Module dependencies.
      98  */
      99 
     100 var url = _dereq_('./url');
     101 var eio = _dereq_('engine.io-client');
     102 var Socket = _dereq_('./socket');
     103 var Emitter = _dereq_('component-emitter');
     104 var parser = _dereq_('socket.io-parser');
     105 var on = _dereq_('./on');
     106 var bind = _dereq_('component-bind');
     107 var object = _dereq_('object-component');
     108 var debug = _dereq_('debug')('socket.io-client:manager');
     109 var indexOf = _dereq_('indexof');
     110 var Backoff = _dereq_('backo2');
     111 
     112 /**
     113  * Module exports
     114  */
     115 
     116 module.exports = Manager;
     117 
     118 /**
     119  * `Manager` constructor.
     120  *
     121  * @param {String} engine instance or engine uri/opts
     122  * @param {Object} options
     123  * @api public
     124  */
     125 
     126 function Manager(uri, opts){
     127   if (!(this instanceof Manager)) return new Manager(uri, opts);
     128   if (uri && ('object' == typeof uri)) {
     129     opts = uri;
     130     uri = undefined;
     131   }
     132   opts = opts || {};
     133 
     134   opts.path = opts.path || '/socket.io';
     135   this.nsps = {};
     136   this.subs = [];
     137   this.opts = opts;
     138   this.reconnection(opts.reconnection !== false);
     139   this.reconnectionAttempts(opts.reconnectionAttempts || Infinity);
     140   this.reconnectionDelay(opts.reconnectionDelay || 1000);
     141   this.reconnectionDelayMax(opts.reconnectionDelayMax || 5000);
     142   this.randomizationFactor(opts.randomizationFactor || 0.5);
     143   this.backoff = new Backoff({
     144     min: this.reconnectionDelay(),
     145     max: this.reconnectionDelayMax(),
     146     jitter: this.randomizationFactor()
     147   });
     148   this.timeout(null == opts.timeout ? 20000 : opts.timeout);
     149   this.readyState = 'closed';
     150   this.uri = uri;
     151   this.connected = [];
     152   this.encoding = false;
     153   this.packetBuffer = [];
     154   this.encoder = new parser.Encoder();
     155   this.decoder = new parser.Decoder();
     156   this.autoConnect = opts.autoConnect !== false;
     157   if (this.autoConnect) this.open();
     158 }
     159 
     160 /**
     161  * Propagate given event to sockets and emit on `this`
     162  *
     163  * @api private
     164  */
     165 
     166 Manager.prototype.emitAll = function() {
     167   this.emit.apply(this, arguments);
     168   for (var nsp in this.nsps) {
     169     this.nsps[nsp].emit.apply(this.nsps[nsp], arguments);
     170   }
     171 };
     172 
     173 /**
     174  * Update `socket.id` of all sockets
     175  *
     176  * @api private
     177  */
     178 
     179 Manager.prototype.updateSocketIds = function(){
     180   for (var nsp in this.nsps) {
     181     this.nsps[nsp].id = this.engine.id;
     182   }
     183 };
     184 
     185 /**
     186  * Mix in `Emitter`.
     187  */
     188 
     189 Emitter(Manager.prototype);
     190 
     191 /**
     192  * Sets the `reconnection` config.
     193  *
     194  * @param {Boolean} true/false if it should automatically reconnect
     195  * @return {Manager} self or value
     196  * @api public
     197  */
     198 
     199 Manager.prototype.reconnection = function(v){
     200   if (!arguments.length) return this._reconnection;
     201   this._reconnection = !!v;
     202   return this;
     203 };
     204 
     205 /**
     206  * Sets the reconnection attempts config.
     207  *
     208  * @param {Number} max reconnection attempts before giving up
     209  * @return {Manager} self or value
     210  * @api public
     211  */
     212 
     213 Manager.prototype.reconnectionAttempts = function(v){
     214   if (!arguments.length) return this._reconnectionAttempts;
     215   this._reconnectionAttempts = v;
     216   return this;
     217 };
     218 
     219 /**
     220  * Sets the delay between reconnections.
     221  *
     222  * @param {Number} delay
     223  * @return {Manager} self or value
     224  * @api public
     225  */
     226 
     227 Manager.prototype.reconnectionDelay = function(v){
     228   if (!arguments.length) return this._reconnectionDelay;
     229   this._reconnectionDelay = v;
     230   this.backoff && this.backoff.setMin(v);
     231   return this;
     232 };
     233 
     234 Manager.prototype.randomizationFactor = function(v){
     235   if (!arguments.length) return this._randomizationFactor;
     236   this._randomizationFactor = v;
     237   this.backoff && this.backoff.setJitter(v);
     238   return this;
     239 };
     240 
     241 /**
     242  * Sets the maximum delay between reconnections.
     243  *
     244  * @param {Number} delay
     245  * @return {Manager} self or value
     246  * @api public
     247  */
     248 
     249 Manager.prototype.reconnectionDelayMax = function(v){
     250   if (!arguments.length) return this._reconnectionDelayMax;
     251   this._reconnectionDelayMax = v;
     252   this.backoff && this.backoff.setMax(v);
     253   return this;
     254 };
     255 
     256 /**
     257  * Sets the connection timeout. `false` to disable
     258  *
     259  * @return {Manager} self or value
     260  * @api public
     261  */
     262 
     263 Manager.prototype.timeout = function(v){
     264   if (!arguments.length) return this._timeout;
     265   this._timeout = v;
     266   return this;
     267 };
     268 
     269 /**
     270  * Starts trying to reconnect if reconnection is enabled and we have not
     271  * started reconnecting yet
     272  *
     273  * @api private
     274  */
     275 
     276 Manager.prototype.maybeReconnectOnOpen = function() {
     277   // Only try to reconnect if it's the first time we're connecting
     278   if (!this.reconnecting && this._reconnection && this.backoff.attempts === 0) {
     279     // keeps reconnection from firing twice for the same reconnection loop
     280     this.reconnect();
     281   }
     282 };
     283 
     284 
     285 /**
     286  * Sets the current transport `socket`.
     287  *
     288  * @param {Function} optional, callback
     289  * @return {Manager} self
     290  * @api public
     291  */
     292 
     293 Manager.prototype.open =
     294 Manager.prototype.connect = function(fn){
     295   debug('readyState %s', this.readyState);
     296   if (~this.readyState.indexOf('open')) return this;
     297 
     298   debug('opening %s', this.uri);
     299   this.engine = eio(this.uri, this.opts);
     300   var socket = this.engine;
     301   var self = this;
     302   this.readyState = 'opening';
     303   this.skipReconnect = false;
     304 
     305   // emit `open`
     306   var openSub = on(socket, 'open', function() {
     307     self.onopen();
     308     fn && fn();
     309   });
     310 
     311   // emit `connect_error`
     312   var errorSub = on(socket, 'error', function(data){
     313     debug('connect_error');
     314     self.cleanup();
     315     self.readyState = 'closed';
     316     self.emitAll('connect_error', data);
     317     if (fn) {
     318       var err = new Error('Connection error');
     319       err.data = data;
     320       fn(err);
     321     } else {
     322       // Only do this if there is no fn to handle the error
     323       self.maybeReconnectOnOpen();
     324     }
     325   });
     326 
     327   // emit `connect_timeout`
     328   if (false !== this._timeout) {
     329     var timeout = this._timeout;
     330     debug('connect attempt will timeout after %d', timeout);
     331 
     332     // set timer
     333     var timer = setTimeout(function(){
     334       debug('connect attempt timed out after %d', timeout);
     335       openSub.destroy();
     336       socket.close();
     337       socket.emit('error', 'timeout');
     338       self.emitAll('connect_timeout', timeout);
     339     }, timeout);
     340 
     341     this.subs.push({
     342       destroy: function(){
     343         clearTimeout(timer);
     344       }
     345     });
     346   }
     347 
     348   this.subs.push(openSub);
     349   this.subs.push(errorSub);
     350 
     351   return this;
     352 };
     353 
     354 /**
     355  * Called upon transport open.
     356  *
     357  * @api private
     358  */
     359 
     360 Manager.prototype.onopen = function(){
     361   debug('open');
     362 
     363   // clear old subs
     364   this.cleanup();
     365 
     366   // mark as open
     367   this.readyState = 'open';
     368   this.emit('open');
     369 
     370   // add new subs
     371   var socket = this.engine;
     372   this.subs.push(on(socket, 'data', bind(this, 'ondata')));
     373   this.subs.push(on(this.decoder, 'decoded', bind(this, 'ondecoded')));
     374   this.subs.push(on(socket, 'error', bind(this, 'onerror')));
     375   this.subs.push(on(socket, 'close', bind(this, 'onclose')));
     376 };
     377 
     378 /**
     379  * Called with data.
     380  *
     381  * @api private
     382  */
     383 
     384 Manager.prototype.ondata = function(data){
     385   this.decoder.add(data);
     386 };
     387 
     388 /**
     389  * Called when parser fully decodes a packet.
     390  *
     391  * @api private
     392  */
     393 
     394 Manager.prototype.ondecoded = function(packet) {
     395   this.emit('packet', packet);
     396 };
     397 
     398 /**
     399  * Called upon socket error.
     400  *
     401  * @api private
     402  */
     403 
     404 Manager.prototype.onerror = function(err){
     405   debug('error', err);
     406   this.emitAll('error', err);
     407 };
     408 
     409 /**
     410  * Creates a new socket for the given `nsp`.
     411  *
     412  * @return {Socket}
     413  * @api public
     414  */
     415 
     416 Manager.prototype.socket = function(nsp){
     417   var socket = this.nsps[nsp];
     418   if (!socket) {
     419     socket = new Socket(this, nsp);
     420     this.nsps[nsp] = socket;
     421     var self = this;
     422     socket.on('connect', function(){
     423       socket.id = self.engine.id;
     424       if (!~indexOf(self.connected, socket)) {
     425         self.connected.push(socket);
     426       }
     427     });
     428   }
     429   return socket;
     430 };
     431 
     432 /**
     433  * Called upon a socket close.
     434  *
     435  * @param {Socket} socket
     436  */
     437 
     438 Manager.prototype.destroy = function(socket){
     439   var index = indexOf(this.connected, socket);
     440   if (~index) this.connected.splice(index, 1);
     441   if (this.connected.length) return;
     442 
     443   this.close();
     444 };
     445 
     446 /**
     447  * Writes a packet.
     448  *
     449  * @param {Object} packet
     450  * @api private
     451  */
     452 
     453 Manager.prototype.packet = function(packet){
     454   debug('writing packet %j', packet);
     455   var self = this;
     456 
     457   if (!self.encoding) {
     458     // encode, then write to engine with result
     459     self.encoding = true;
     460     this.encoder.encode(packet, function(encodedPackets) {
     461       for (var i = 0; i < encodedPackets.length; i++) {
     462         self.engine.write(encodedPackets[i]);
     463       }
     464       self.encoding = false;
     465       self.processPacketQueue();
     466     });
     467   } else { // add packet to the queue
     468     self.packetBuffer.push(packet);
     469   }
     470 };
     471 
     472 /**
     473  * If packet buffer is non-empty, begins encoding the
     474  * next packet in line.
     475  *
     476  * @api private
     477  */
     478 
     479 Manager.prototype.processPacketQueue = function() {
     480   if (this.packetBuffer.length > 0 && !this.encoding) {
     481     var pack = this.packetBuffer.shift();
     482     this.packet(pack);
     483   }
     484 };
     485 
     486 /**
     487  * Clean up transport subscriptions and packet buffer.
     488  *
     489  * @api private
     490  */
     491 
     492 Manager.prototype.cleanup = function(){
     493   var sub;
     494   while (sub = this.subs.shift()) sub.destroy();
     495 
     496   this.packetBuffer = [];
     497   this.encoding = false;
     498 
     499   this.decoder.destroy();
     500 };
     501 
     502 /**
     503  * Close the current socket.
     504  *
     505  * @api private
     506  */
     507 
     508 Manager.prototype.close =
     509 Manager.prototype.disconnect = function(){
     510   this.skipReconnect = true;
     511   this.backoff.reset();
     512   this.readyState = 'closed';
     513   this.engine && this.engine.close();
     514 };
     515 
     516 /**
     517  * Called upon engine close.
     518  *
     519  * @api private
     520  */
     521 
     522 Manager.prototype.onclose = function(reason){
     523   debug('close');
     524   this.cleanup();
     525   this.backoff.reset();
     526   this.readyState = 'closed';
     527   this.emit('close', reason);
     528   if (this._reconnection && !this.skipReconnect) {
     529     this.reconnect();
     530   }
     531 };
     532 
     533 /**
     534  * Attempt a reconnection.
     535  *
     536  * @api private
     537  */
     538 
     539 Manager.prototype.reconnect = function(){
     540   if (this.reconnecting || this.skipReconnect) return this;
     541 
     542   var self = this;
     543 
     544   if (this.backoff.attempts >= this._reconnectionAttempts) {
     545     debug('reconnect failed');
     546     this.backoff.reset();
     547     this.emitAll('reconnect_failed');
     548     this.reconnecting = false;
     549   } else {
     550     var delay = this.backoff.duration();
     551     debug('will wait %dms before reconnect attempt', delay);
     552 
     553     this.reconnecting = true;
     554     var timer = setTimeout(function(){
     555       if (self.skipReconnect) return;
     556 
     557       debug('attempting reconnect');
     558       self.emitAll('reconnect_attempt', self.backoff.attempts);
     559       self.emitAll('reconnecting', self.backoff.attempts);
     560 
     561       // check again for the case socket closed in above events
     562       if (self.skipReconnect) return;
     563 
     564       self.open(function(err){
     565         if (err) {
     566           debug('reconnect attempt error');
     567           self.reconnecting = false;
     568           self.reconnect();
     569           self.emitAll('reconnect_error', err.data);
     570         } else {
     571           debug('reconnect success');
     572           self.onreconnect();
     573         }
     574       });
     575     }, delay);
     576 
     577     this.subs.push({
     578       destroy: function(){
     579         clearTimeout(timer);
     580       }
     581     });
     582   }
     583 };
     584 
     585 /**
     586  * Called upon successful reconnect.
     587  *
     588  * @api private
     589  */
     590 
     591 Manager.prototype.onreconnect = function(){
     592   var attempt = this.backoff.attempts;
     593   this.reconnecting = false;
     594   this.backoff.reset();
     595   this.updateSocketIds();
     596   this.emitAll('reconnect', attempt);
     597 };
     598 
     599 },{"./on":4,"./socket":5,"./url":6,"backo2":7,"component-bind":8,"component-emitter":9,"debug":10,"engine.io-client":11,"indexof":40,"object-component":41,"socket.io-parser":44}],4:[function(_dereq_,module,exports){
     600 
     601 /**
     602  * Module exports.
     603  */
     604 
     605 module.exports = on;
     606 
     607 /**
     608  * Helper for subscriptions.
     609  *
     610  * @param {Object|EventEmitter} obj with `Emitter` mixin or `EventEmitter`
     611  * @param {String} event name
     612  * @param {Function} callback
     613  * @api public
     614  */
     615 
     616 function on(obj, ev, fn) {
     617   obj.on(ev, fn);
     618   return {
     619     destroy: function(){
     620       obj.removeListener(ev, fn);
     621     }
     622   };
     623 }
     624 
     625 },{}],5:[function(_dereq_,module,exports){
     626 
     627 /**
     628  * Module dependencies.
     629  */
     630 
     631 var parser = _dereq_('socket.io-parser');
     632 var Emitter = _dereq_('component-emitter');
     633 var toArray = _dereq_('to-array');
     634 var on = _dereq_('./on');
     635 var bind = _dereq_('component-bind');
     636 var debug = _dereq_('debug')('socket.io-client:socket');
     637 var hasBin = _dereq_('has-binary');
     638 
     639 /**
     640  * Module exports.
     641  */
     642 
     643 module.exports = exports = Socket;
     644 
     645 /**
     646  * Internal events (blacklisted).
     647  * These events can't be emitted by the user.
     648  *
     649  * @api private
     650  */
     651 
     652 var events = {
     653   connect: 1,
     654   connect_error: 1,
     655   connect_timeout: 1,
     656   disconnect: 1,
     657   error: 1,
     658   reconnect: 1,
     659   reconnect_attempt: 1,
     660   reconnect_failed: 1,
     661   reconnect_error: 1,
     662   reconnecting: 1
     663 };
     664 
     665 /**
     666  * Shortcut to `Emitter#emit`.
     667  */
     668 
     669 var emit = Emitter.prototype.emit;
     670 
     671 /**
     672  * `Socket` constructor.
     673  *
     674  * @api public
     675  */
     676 
     677 function Socket(io, nsp){
     678   this.io = io;
     679   this.nsp = nsp;
     680   this.json = this; // compat
     681   this.ids = 0;
     682   this.acks = {};
     683   if (this.io.autoConnect) this.open();
     684   this.receiveBuffer = [];
     685   this.sendBuffer = [];
     686   this.connected = false;
     687   this.disconnected = true;
     688 }
     689 
     690 /**
     691  * Mix in `Emitter`.
     692  */
     693 
     694 Emitter(Socket.prototype);
     695 
     696 /**
     697  * Subscribe to open, close and packet events
     698  *
     699  * @api private
     700  */
     701 
     702 Socket.prototype.subEvents = function() {
     703   if (this.subs) return;
     704 
     705   var io = this.io;
     706   this.subs = [
     707     on(io, 'open', bind(this, 'onopen')),
     708     on(io, 'packet', bind(this, 'onpacket')),
     709     on(io, 'close', bind(this, 'onclose'))
     710   ];
     711 };
     712 
     713 /**
     714  * "Opens" the socket.
     715  *
     716  * @api public
     717  */
     718 
     719 Socket.prototype.open =
     720 Socket.prototype.connect = function(){
     721   if (this.connected) return this;
     722 
     723   this.subEvents();
     724   this.io.open(); // ensure open
     725   if ('open' == this.io.readyState) this.onopen();
     726   return this;
     727 };
     728 
     729 /**
     730  * Sends a `message` event.
     731  *
     732  * @return {Socket} self
     733  * @api public
     734  */
     735 
     736 Socket.prototype.send = function(){
     737   var args = toArray(arguments);
     738   args.unshift('message');
     739   this.emit.apply(this, args);
     740   return this;
     741 };
     742 
     743 /**
     744  * Override `emit`.
     745  * If the event is in `events`, it's emitted normally.
     746  *
     747  * @param {String} event name
     748  * @return {Socket} self
     749  * @api public
     750  */
     751 
     752 Socket.prototype.emit = function(ev){
     753   if (events.hasOwnProperty(ev)) {
     754     emit.apply(this, arguments);
     755     return this;
     756   }
     757 
     758   var args = toArray(arguments);
     759   var parserType = parser.EVENT; // default
     760   if (hasBin(args)) { parserType = parser.BINARY_EVENT; } // binary
     761   var packet = { type: parserType, data: args };
     762 
     763   // event ack callback
     764   if ('function' == typeof args[args.length - 1]) {
     765     debug('emitting packet with ack id %d', this.ids);
     766     this.acks[this.ids] = args.pop();
     767     packet.id = this.ids++;
     768   }
     769 
     770   if (this.connected) {
     771     this.packet(packet);
     772   } else {
     773     this.sendBuffer.push(packet);
     774   }
     775 
     776   return this;
     777 };
     778 
     779 /**
     780  * Sends a packet.
     781  *
     782  * @param {Object} packet
     783  * @api private
     784  */
     785 
     786 Socket.prototype.packet = function(packet){
     787   packet.nsp = this.nsp;
     788   this.io.packet(packet);
     789 };
     790 
     791 /**
     792  * Called upon engine `open`.
     793  *
     794  * @api private
     795  */
     796 
     797 Socket.prototype.onopen = function(){
     798   debug('transport is open - connecting');
     799 
     800   // write connect packet if necessary
     801   if ('/' != this.nsp) {
     802     this.packet({ type: parser.CONNECT });
     803   }
     804 };
     805 
     806 /**
     807  * Called upon engine `close`.
     808  *
     809  * @param {String} reason
     810  * @api private
     811  */
     812 
     813 Socket.prototype.onclose = function(reason){
     814   debug('close (%s)', reason);
     815   this.connected = false;
     816   this.disconnected = true;
     817   delete this.id;
     818   this.emit('disconnect', reason);
     819 };
     820 
     821 /**
     822  * Called with socket packet.
     823  *
     824  * @param {Object} packet
     825  * @api private
     826  */
     827 
     828 Socket.prototype.onpacket = function(packet){
     829   if (packet.nsp != this.nsp) return;
     830 
     831   switch (packet.type) {
     832     case parser.CONNECT:
     833       this.onconnect();
     834       break;
     835 
     836     case parser.EVENT:
     837       this.onevent(packet);
     838       break;
     839 
     840     case parser.BINARY_EVENT:
     841       this.onevent(packet);
     842       break;
     843 
     844     case parser.ACK:
     845       this.onack(packet);
     846       break;
     847 
     848     case parser.BINARY_ACK:
     849       this.onack(packet);
     850       break;
     851 
     852     case parser.DISCONNECT:
     853       this.ondisconnect();
     854       break;
     855 
     856     case parser.ERROR:
     857       this.emit('error', packet.data);
     858       break;
     859   }
     860 };
     861 
     862 /**
     863  * Called upon a server event.
     864  *
     865  * @param {Object} packet
     866  * @api private
     867  */
     868 
     869 Socket.prototype.onevent = function(packet){
     870   var args = packet.data || [];
     871   debug('emitting event %j', args);
     872 
     873   if (null != packet.id) {
     874     debug('attaching ack callback to event');
     875     args.push(this.ack(packet.id));
     876   }
     877 
     878   if (this.connected) {
     879     emit.apply(this, args);
     880   } else {
     881     this.receiveBuffer.push(args);
     882   }
     883 };
     884 
     885 /**
     886  * Produces an ack callback to emit with an event.
     887  *
     888  * @api private
     889  */
     890 
     891 Socket.prototype.ack = function(id){
     892   var self = this;
     893   var sent = false;
     894   return function(){
     895     // prevent double callbacks
     896     if (sent) return;
     897     sent = true;
     898     var args = toArray(arguments);
     899     debug('sending ack %j', args);
     900 
     901     var type = hasBin(args) ? parser.BINARY_ACK : parser.ACK;
     902     self.packet({
     903       type: type,
     904       id: id,
     905       data: args
     906     });
     907   };
     908 };
     909 
     910 /**
     911  * Called upon a server acknowlegement.
     912  *
     913  * @param {Object} packet
     914  * @api private
     915  */
     916 
     917 Socket.prototype.onack = function(packet){
     918   debug('calling ack %s with %j', packet.id, packet.data);
     919   var fn = this.acks[packet.id];
     920   fn.apply(this, packet.data);
     921   delete this.acks[packet.id];
     922 };
     923 
     924 /**
     925  * Called upon server connect.
     926  *
     927  * @api private
     928  */
     929 
     930 Socket.prototype.onconnect = function(){
     931   this.connected = true;
     932   this.disconnected = false;
     933   this.emit('connect');
     934   this.emitBuffered();
     935 };
     936 
     937 /**
     938  * Emit buffered events (received and emitted).
     939  *
     940  * @api private
     941  */
     942 
     943 Socket.prototype.emitBuffered = function(){
     944   var i;
     945   for (i = 0; i < this.receiveBuffer.length; i++) {
     946     emit.apply(this, this.receiveBuffer[i]);
     947   }
     948   this.receiveBuffer = [];
     949 
     950   for (i = 0; i < this.sendBuffer.length; i++) {
     951     this.packet(this.sendBuffer[i]);
     952   }
     953   this.sendBuffer = [];
     954 };
     955 
     956 /**
     957  * Called upon server disconnect.
     958  *
     959  * @api private
     960  */
     961 
     962 Socket.prototype.ondisconnect = function(){
     963   debug('server disconnect (%s)', this.nsp);
     964   this.destroy();
     965   this.onclose('io server disconnect');
     966 };
     967 
     968 /**
     969  * Called upon forced client/server side disconnections,
     970  * this method ensures the manager stops tracking us and
     971  * that reconnections don't get triggered for this.
     972  *
     973  * @api private.
     974  */
     975 
     976 Socket.prototype.destroy = function(){
     977   if (this.subs) {
     978     // clean subscriptions to avoid reconnections
     979     for (var i = 0; i < this.subs.length; i++) {
     980       this.subs[i].destroy();
     981     }
     982     this.subs = null;
     983   }
     984 
     985   this.io.destroy(this);
     986 };
     987 
     988 /**
     989  * Disconnects the socket manually.
     990  *
     991  * @return {Socket} self
     992  * @api public
     993  */
     994 
     995 Socket.prototype.close =
     996 Socket.prototype.disconnect = function(){
     997   if (this.connected) {
     998     debug('performing disconnect (%s)', this.nsp);
     999     this.packet({ type: parser.DISCONNECT });
    1000   }
    1001 
    1002   // remove socket from pool
    1003   this.destroy();
    1004 
    1005   if (this.connected) {
    1006     // fire events
    1007     this.onclose('io client disconnect');
    1008   }
    1009   return this;
    1010 };
    1011 
    1012 },{"./on":4,"component-bind":8,"component-emitter":9,"debug":10,"has-binary":36,"socket.io-parser":44,"to-array":48}],6:[function(_dereq_,module,exports){
    1013 (function (global){
    1014 
    1015 /**
    1016  * Module dependencies.
    1017  */
    1018 
    1019 var parseuri = _dereq_('parseuri');
    1020 var debug = _dereq_('debug')('socket.io-client:url');
    1021 
    1022 /**
    1023  * Module exports.
    1024  */
    1025 
    1026 module.exports = url;
    1027 
    1028 /**
    1029  * URL parser.
    1030  *
    1031  * @param {String} url
    1032  * @param {Object} An object meant to mimic window.location.
    1033  *                 Defaults to window.location.
    1034  * @api public
    1035  */
    1036 
    1037 function url(uri, loc){
    1038   var obj = uri;
    1039 
    1040   // default to window.location
    1041   var loc = loc || global.location;
    1042   if (null == uri) uri = loc.protocol + '//' + loc.host;
    1043 
    1044   // relative path support
    1045   if ('string' == typeof uri) {
    1046     if ('/' == uri.charAt(0)) {
    1047       if ('/' == uri.charAt(1)) {
    1048         uri = loc.protocol + uri;
    1049       } else {
    1050         uri = loc.hostname + uri;
    1051       }
    1052     }
    1053 
    1054     if (!/^(https?|wss?):///.test(uri)) {
    1055       debug('protocol-less url %s', uri);
    1056       if ('undefined' != typeof loc) {
    1057         uri = loc.protocol + '//' + uri;
    1058       } else {
    1059         uri = 'https://' + uri;
    1060       }
    1061     }
    1062 
    1063     // parse
    1064     debug('parse %s', uri);
    1065     obj = parseuri(uri);
    1066   }
    1067 
    1068   // make sure we treat `localhost:80` and `localhost` equally
    1069   if (!obj.port) {
    1070     if (/^(http|ws)$/.test(obj.protocol)) {
    1071       obj.port = '80';
    1072     }
    1073     else if (/^(http|ws)s$/.test(obj.protocol)) {
    1074       obj.port = '443';
    1075     }
    1076   }
    1077 
    1078   obj.path = obj.path || '/';
    1079 
    1080   // define unique id
    1081   obj.id = obj.protocol + '://' + obj.host + ':' + obj.port;
    1082   // define href
    1083   obj.href = obj.protocol + '://' + obj.host + (loc && loc.port == obj.port ? '' : (':' + obj.port));
    1084 
    1085   return obj;
    1086 }
    1087 
    1088 }).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
    1089 },{"debug":10,"parseuri":42}],7:[function(_dereq_,module,exports){
    1090 
    1091 /**
    1092  * Expose `Backoff`.
    1093  */
    1094 
    1095 module.exports = Backoff;
    1096 
    1097 /**
    1098  * Initialize backoff timer with `opts`.
    1099  *
    1100  * - `min` initial timeout in milliseconds [100]
    1101  * - `max` max timeout [10000]
    1102  * - `jitter` [0]
    1103  * - `factor` [2]
    1104  *
    1105  * @param {Object} opts
    1106  * @api public
    1107  */
    1108 
    1109 function Backoff(opts) {
    1110   opts = opts || {};
    1111   this.ms = opts.min || 100;
    1112   this.max = opts.max || 10000;
    1113   this.factor = opts.factor || 2;
    1114   this.jitter = opts.jitter > 0 && opts.jitter <= 1 ? opts.jitter : 0;
    1115   this.attempts = 0;
    1116 }
    1117 
    1118 /**
    1119  * Return the backoff duration.
    1120  *
    1121  * @return {Number}
    1122  * @api public
    1123  */
    1124 
    1125 Backoff.prototype.duration = function(){
    1126   var ms = this.ms * Math.pow(this.factor, this.attempts++);
    1127   if (this.jitter) {
    1128     var rand =  Math.random();
    1129     var deviation = Math.floor(rand * this.jitter * ms);
    1130     ms = (Math.floor(rand * 10) & 1) == 0  ? ms - deviation : ms + deviation;
    1131   }
    1132   return Math.min(ms, this.max) | 0;
    1133 };
    1134 
    1135 /**
    1136  * Reset the number of attempts.
    1137  *
    1138  * @api public
    1139  */
    1140 
    1141 Backoff.prototype.reset = function(){
    1142   this.attempts = 0;
    1143 };
    1144 
    1145 /**
    1146  * Set the minimum duration
    1147  *
    1148  * @api public
    1149  */
    1150 
    1151 Backoff.prototype.setMin = function(min){
    1152   this.ms = min;
    1153 };
    1154 
    1155 /**
    1156  * Set the maximum duration
    1157  *
    1158  * @api public
    1159  */
    1160 
    1161 Backoff.prototype.setMax = function(max){
    1162   this.max = max;
    1163 };
    1164 
    1165 /**
    1166  * Set the jitter
    1167  *
    1168  * @api public
    1169  */
    1170 
    1171 Backoff.prototype.setJitter = function(jitter){
    1172   this.jitter = jitter;
    1173 };
    1174 
    1175 
    1176 },{}],8:[function(_dereq_,module,exports){
    1177 /**
    1178  * Slice reference.
    1179  */
    1180 
    1181 var slice = [].slice;
    1182 
    1183 /**
    1184  * Bind `obj` to `fn`.
    1185  *
    1186  * @param {Object} obj
    1187  * @param {Function|String} fn or string
    1188  * @return {Function}
    1189  * @api public
    1190  */
    1191 
    1192 module.exports = function(obj, fn){
    1193   if ('string' == typeof fn) fn = obj[fn];
    1194   if ('function' != typeof fn) throw new Error('bind() requires a function');
    1195   var args = slice.call(arguments, 2);
    1196   return function(){
    1197     return fn.apply(obj, args.concat(slice.call(arguments)));
    1198   }
    1199 };
    1200 
    1201 },{}],9:[function(_dereq_,module,exports){
    1202 
    1203 /**
    1204  * Expose `Emitter`.
    1205  */
    1206 
    1207 module.exports = Emitter;
    1208 
    1209 /**
    1210  * Initialize a new `Emitter`.
    1211  *
    1212  * @api public
    1213  */
    1214 
    1215 function Emitter(obj) {
    1216   if (obj) return mixin(obj);
    1217 };
    1218 
    1219 /**
    1220  * Mixin the emitter properties.
    1221  *
    1222  * @param {Object} obj
    1223  * @return {Object}
    1224  * @api private
    1225  */
    1226 
    1227 function mixin(obj) {
    1228   for (var key in Emitter.prototype) {
    1229     obj[key] = Emitter.prototype[key];
    1230   }
    1231   return obj;
    1232 }
    1233 
    1234 /**
    1235  * Listen on the given `event` with `fn`.
    1236  *
    1237  * @param {String} event
    1238  * @param {Function} fn
    1239  * @return {Emitter}
    1240  * @api public
    1241  */
    1242 
    1243 Emitter.prototype.on =
    1244 Emitter.prototype.addEventListener = function(event, fn){
    1245   this._callbacks = this._callbacks || {};
    1246   (this._callbacks[event] = this._callbacks[event] || [])
    1247     .push(fn);
    1248   return this;
    1249 };
    1250 
    1251 /**
    1252  * Adds an `event` listener that will be invoked a single
    1253  * time then automatically removed.
    1254  *
    1255  * @param {String} event
    1256  * @param {Function} fn
    1257  * @return {Emitter}
    1258  * @api public
    1259  */
    1260 
    1261 Emitter.prototype.once = function(event, fn){
    1262   var self = this;
    1263   this._callbacks = this._callbacks || {};
    1264 
    1265   function on() {
    1266     self.off(event, on);
    1267     fn.apply(this, arguments);
    1268   }
    1269 
    1270   on.fn = fn;
    1271   this.on(event, on);
    1272   return this;
    1273 };
    1274 
    1275 /**
    1276  * Remove the given callback for `event` or all
    1277  * registered callbacks.
    1278  *
    1279  * @param {String} event
    1280  * @param {Function} fn
    1281  * @return {Emitter}
    1282  * @api public
    1283  */
    1284 
    1285 Emitter.prototype.off =
    1286 Emitter.prototype.removeListener =
    1287 Emitter.prototype.removeAllListeners =
    1288 Emitter.prototype.removeEventListener = function(event, fn){
    1289   this._callbacks = this._callbacks || {};
    1290 
    1291   // all
    1292   if (0 == arguments.length) {
    1293     this._callbacks = {};
    1294     return this;
    1295   }
    1296 
    1297   // specific event
    1298   var callbacks = this._callbacks[event];
    1299   if (!callbacks) return this;
    1300 
    1301   // remove all handlers
    1302   if (1 == arguments.length) {
    1303     delete this._callbacks[event];
    1304     return this;
    1305   }
    1306 
    1307   // remove specific handler
    1308   var cb;
    1309   for (var i = 0; i < callbacks.length; i++) {
    1310     cb = callbacks[i];
    1311     if (cb === fn || cb.fn === fn) {
    1312       callbacks.splice(i, 1);
    1313       break;
    1314     }
    1315   }
    1316   return this;
    1317 };
    1318 
    1319 /**
    1320  * Emit `event` with the given args.
    1321  *
    1322  * @param {String} event
    1323  * @param {Mixed} ...
    1324  * @return {Emitter}
    1325  */
    1326 
    1327 Emitter.prototype.emit = function(event){
    1328   this._callbacks = this._callbacks || {};
    1329   var args = [].slice.call(arguments, 1)
    1330     , callbacks = this._callbacks[event];
    1331 
    1332   if (callbacks) {
    1333     callbacks = callbacks.slice(0);
    1334     for (var i = 0, len = callbacks.length; i < len; ++i) {
    1335       callbacks[i].apply(this, args);
    1336     }
    1337   }
    1338 
    1339   return this;
    1340 };
    1341 
    1342 /**
    1343  * Return array of callbacks for `event`.
    1344  *
    1345  * @param {String} event
    1346  * @return {Array}
    1347  * @api public
    1348  */
    1349 
    1350 Emitter.prototype.listeners = function(event){
    1351   this._callbacks = this._callbacks || {};
    1352   return this._callbacks[event] || [];
    1353 };
    1354 
    1355 /**
    1356  * Check if this emitter has `event` handlers.
    1357  *
    1358  * @param {String} event
    1359  * @return {Boolean}
    1360  * @api public
    1361  */
    1362 
    1363 Emitter.prototype.hasListeners = function(event){
    1364   return !! this.listeners(event).length;
    1365 };
    1366 
    1367 },{}],10:[function(_dereq_,module,exports){
    1368 
    1369 /**
    1370  * Expose `debug()` as the module.
    1371  */
    1372 
    1373 module.exports = debug;
    1374 
    1375 /**
    1376  * Create a debugger with the given `name`.
    1377  *
    1378  * @param {String} name
    1379  * @return {Type}
    1380  * @api public
    1381  */
    1382 
    1383 function debug(name) {
    1384   if (!debug.enabled(name)) return function(){};
    1385 
    1386   return function(fmt){
    1387     fmt = coerce(fmt);
    1388 
    1389     var curr = new Date;
    1390     var ms = curr - (debug[name] || curr);
    1391     debug[name] = curr;
    1392 
    1393     fmt = name
    1394       + ' '
    1395       + fmt
    1396       + ' +' + debug.humanize(ms);
    1397 
    1398     // This hackery is required for IE8
    1399     // where `console.log` doesn't have 'apply'
    1400     window.console
    1401       && console.log
    1402       && Function.prototype.apply.call(console.log, console, arguments);
    1403   }
    1404 }
    1405 
    1406 /**
    1407  * The currently active debug mode names.
    1408  */
    1409 
    1410 debug.names = [];
    1411 debug.skips = [];
    1412 
    1413 /**
    1414  * Enables a debug mode by name. This can include modes
    1415  * separated by a colon and wildcards.
    1416  *
    1417  * @param {String} name
    1418  * @api public
    1419  */
    1420 
    1421 debug.enable = function(name) {
    1422   try {
    1423     localStorage.debug = name;
    1424   } catch(e){}
    1425 
    1426   var split = (name || '').split(/[s,]+/)
    1427     , len = split.length;
    1428 
    1429   for (var i = 0; i < len; i++) {
    1430     name = split[i].replace('*', '.*?');
    1431     if (name[0] === '-') {
    1432       debug.skips.push(new RegExp('^' + name.substr(1) + '$'));
    1433     }
    1434     else {
    1435       debug.names.push(new RegExp('^' + name + '$'));
    1436     }
    1437   }
    1438 };
    1439 
    1440 /**
    1441  * Disable debug output.
    1442  *
    1443  * @api public
    1444  */
    1445 
    1446 debug.disable = function(){
    1447   debug.enable('');
    1448 };
    1449 
    1450 /**
    1451  * Humanize the given `ms`.
    1452  *
    1453  * @param {Number} m
    1454  * @return {String}
    1455  * @api private
    1456  */
    1457 
    1458 debug.humanize = function(ms) {
    1459   var sec = 1000
    1460     , min = 60 * 1000
    1461     , hour = 60 * min;
    1462 
    1463   if (ms >= hour) return (ms / hour).toFixed(1) + 'h';
    1464   if (ms >= min) return (ms / min).toFixed(1) + 'm';
    1465   if (ms >= sec) return (ms / sec | 0) + 's';
    1466   return ms + 'ms';
    1467 };
    1468 
    1469 /**
    1470  * Returns true if the given mode name is enabled, false otherwise.
    1471  *
    1472  * @param {String} name
    1473  * @return {Boolean}
    1474  * @api public
    1475  */
    1476 
    1477 debug.enabled = function(name) {
    1478   for (var i = 0, len = debug.skips.length; i < len; i++) {
    1479     if (debug.skips[i].test(name)) {
    1480       return false;
    1481     }
    1482   }
    1483   for (var i = 0, len = debug.names.length; i < len; i++) {
    1484     if (debug.names[i].test(name)) {
    1485       return true;
    1486     }
    1487   }
    1488   return false;
    1489 };
    1490 
    1491 /**
    1492  * Coerce `val`.
    1493  */
    1494 
    1495 function coerce(val) {
    1496   if (val instanceof Error) return val.stack || val.message;
    1497   return val;
    1498 }
    1499 
    1500 // persist
    1501 
    1502 try {
    1503   if (window.localStorage) debug.enable(localStorage.debug);
    1504 } catch(e){}
    1505 
    1506 },{}],11:[function(_dereq_,module,exports){
    1507 
    1508 module.exports =  _dereq_('./lib/');
    1509 
    1510 },{"./lib/":12}],12:[function(_dereq_,module,exports){
    1511 
    1512 module.exports = _dereq_('./socket');
    1513 
    1514 /**
    1515  * Exports parser
    1516  *
    1517  * @api public
    1518  *
    1519  */
    1520 module.exports.parser = _dereq_('engine.io-parser');
    1521 
    1522 },{"./socket":13,"engine.io-parser":25}],13:[function(_dereq_,module,exports){
    1523 (function (global){
    1524 /**
    1525  * Module dependencies.
    1526  */
    1527 
    1528 var transports = _dereq_('./transports');
    1529 var Emitter = _dereq_('component-emitter');
    1530 var debug = _dereq_('debug')('engine.io-client:socket');
    1531 var index = _dereq_('indexof');
    1532 var parser = _dereq_('engine.io-parser');
    1533 var parseuri = _dereq_('parseuri');
    1534 var parsejson = _dereq_('parsejson');
    1535 var parseqs = _dereq_('parseqs');
    1536 
    1537 /**
    1538  * Module exports.
    1539  */
    1540 
    1541 module.exports = Socket;
    1542 
    1543 /**
    1544  * Noop function.
    1545  *
    1546  * @api private
    1547  */
    1548 
    1549 function noop(){}
    1550 
    1551 /**
    1552  * Socket constructor.
    1553  *
    1554  * @param {String|Object} uri or options
    1555  * @param {Object} options
    1556  * @api public
    1557  */
    1558 
    1559 function Socket(uri, opts){
    1560   if (!(this instanceof Socket)) return new Socket(uri, opts);
    1561 
    1562   opts = opts || {};
    1563 
    1564   if (uri && 'object' == typeof uri) {
    1565     opts = uri;
    1566     uri = null;
    1567   }
    1568 
    1569   if (uri) {
    1570     uri = parseuri(uri);
    1571     opts.host = uri.host;
    1572     opts.secure = uri.protocol == 'https' || uri.protocol == 'wss';
    1573     opts.port = uri.port;
    1574     if (uri.query) opts.query = uri.query;
    1575   }
    1576 
    1577   this.secure = null != opts.secure ? opts.secure :
    1578     (global.location && 'https:' == location.protocol);
    1579 
    1580   if (opts.host) {
    1581     var pieces = opts.host.split(':');
    1582     opts.hostname = pieces.shift();
    1583     if (pieces.length) {
    1584       opts.port = pieces.pop();
    1585     } else if (!opts.port) {
    1586       // if no port is specified manually, use the protocol default
    1587       opts.port = this.secure ? '443' : '80';
    1588     }
    1589   }
    1590 
    1591   this.agent = opts.agent || false;
    1592   this.hostname = opts.hostname ||
    1593     (global.location ? location.hostname : 'localhost');
    1594   this.port = opts.port || (global.location && location.port ?
    1595        location.port :
    1596        (this.secure ? 443 : 80));
    1597   this.query = opts.query || {};
    1598   if ('string' == typeof this.query) this.query = parseqs.decode(this.query);
    1599   this.upgrade = false !== opts.upgrade;
    1600   this.path = (opts.path || '/engine.io').replace(//$/, '') + '/';
    1601   this.forceJSONP = !!opts.forceJSONP;
    1602   this.jsonp = false !== opts.jsonp;
    1603   this.forceBase64 = !!opts.forceBase64;
    1604   this.enablesXDR = !!opts.enablesXDR;
    1605   this.timestampParam = opts.timestampParam || 't';
    1606   this.timestampRequests = opts.timestampRequests;
    1607   this.transports = opts.transports || ['polling', 'websocket'];
    1608   this.readyState = '';
    1609   this.writeBuffer = [];
    1610   this.callbackBuffer = [];
    1611   this.policyPort = opts.policyPort || 843;
    1612   this.rememberUpgrade = opts.rememberUpgrade || false;
    1613   this.binaryType = null;
    1614   this.onlyBinaryUpgrades = opts.onlyBinaryUpgrades;
    1615 
    1616   // SSL options for Node.js client
    1617   this.pfx = opts.pfx || null;
    1618   this.key = opts.key || null;
    1619   this.passphrase = opts.passphrase || null;
    1620   this.cert = opts.cert || null;
    1621   this.ca = opts.ca || null;
    1622   this.ciphers = opts.ciphers || null;
    1623   this.rejectUnauthorized = opts.rejectUnauthorized || null;
    1624 
    1625   this.open();
    1626 }
    1627 
    1628 Socket.priorWebsocketSuccess = false;
    1629 
    1630 /**
    1631  * Mix in `Emitter`.
    1632  */
    1633 
    1634 Emitter(Socket.prototype);
    1635 
    1636 /**
    1637  * Protocol version.
    1638  *
    1639  * @api public
    1640  */
    1641 
    1642 Socket.protocol = parser.protocol; // this is an int
    1643 
    1644 /**
    1645  * Expose deps for legacy compatibility
    1646  * and standalone browser access.
    1647  */
    1648 
    1649 Socket.Socket = Socket;
    1650 Socket.Transport = _dereq_('./transport');
    1651 Socket.transports = _dereq_('./transports');
    1652 Socket.parser = _dereq_('engine.io-parser');
    1653 
    1654 /**
    1655  * Creates transport of the given type.
    1656  *
    1657  * @param {String} transport name
    1658  * @return {Transport}
    1659  * @api private
    1660  */
    1661 
    1662 Socket.prototype.createTransport = function (name) {
    1663   debug('creating transport "%s"', name);
    1664   var query = clone(this.query);
    1665 
    1666   // append engine.io protocol identifier
    1667   query.EIO = parser.protocol;
    1668 
    1669   // transport name
    1670   query.transport = name;
    1671 
    1672   // session id if we already have one
    1673   if (this.id) query.sid = this.id;
    1674 
    1675   var transport = new transports[name]({
    1676     agent: this.agent,
    1677     hostname: this.hostname,
    1678     port: this.port,
    1679     secure: this.secure,
    1680     path: this.path,
    1681     query: query,
    1682     forceJSONP: this.forceJSONP,
    1683     jsonp: this.jsonp,
    1684     forceBase64: this.forceBase64,
    1685     enablesXDR: this.enablesXDR,
    1686     timestampRequests: this.timestampRequests,
    1687     timestampParam: this.timestampParam,
    1688     policyPort: this.policyPort,
    1689     socket: this,
    1690     pfx: this.pfx,
    1691     key: this.key,
    1692     passphrase: this.passphrase,
    1693     cert: this.cert,
    1694     ca: this.ca,
    1695     ciphers: this.ciphers,
    1696     rejectUnauthorized: this.rejectUnauthorized
    1697   });
    1698 
    1699   return transport;
    1700 };
    1701 
    1702 function clone (obj) {
    1703   var o = {};
    1704   for (var i in obj) {
    1705     if (obj.hasOwnProperty(i)) {
    1706       o[i] = obj[i];
    1707     }
    1708   }
    1709   return o;
    1710 }
    1711 
    1712 /**
    1713  * Initializes transport to use and starts probe.
    1714  *
    1715  * @api private
    1716  */
    1717 Socket.prototype.open = function () {
    1718   var transport;
    1719   if (this.rememberUpgrade && Socket.priorWebsocketSuccess && this.transports.indexOf('websocket') != -1) {
    1720     transport = 'websocket';
    1721   } else if (0 == this.transports.length) {
    1722     // Emit error on next tick so it can be listened to
    1723     var self = this;
    1724     setTimeout(function() {
    1725       self.emit('error', 'No transports available');
    1726     }, 0);
    1727     return;
    1728   } else {
    1729     transport = this.transports[0];
    1730   }
    1731   this.readyState = 'opening';
    1732 
    1733   // Retry with the next transport if the transport is disabled (jsonp: false)
    1734   var transport;
    1735   try {
    1736     transport = this.createTransport(transport);
    1737   } catch (e) {
    1738     this.transports.shift();
    1739     this.open();
    1740     return;
    1741   }
    1742 
    1743   transport.open();
    1744   this.setTransport(transport);
    1745 };
    1746 
    1747 /**
    1748  * Sets the current transport. Disables the existing one (if any).
    1749  *
    1750  * @api private
    1751  */
    1752 
    1753 Socket.prototype.setTransport = function(transport){
    1754   debug('setting transport %s', transport.name);
    1755   var self = this;
    1756 
    1757   if (this.transport) {
    1758     debug('clearing existing transport %s', this.transport.name);
    1759     this.transport.removeAllListeners();
    1760   }
    1761 
    1762   // set up transport
    1763   this.transport = transport;
    1764 
    1765   // set up transport listeners
    1766   transport
    1767   .on('drain', function(){
    1768     self.onDrain();
    1769   })
    1770   .on('packet', function(packet){
    1771     self.onPacket(packet);
    1772   })
    1773   .on('error', function(e){
    1774     self.onError(e);
    1775   })
    1776   .on('close', function(){
    1777     self.onClose('transport close');
    1778   });
    1779 };
    1780 
    1781 /**
    1782  * Probes a transport.
    1783  *
    1784  * @param {String} transport name
    1785  * @api private
    1786  */
    1787 
    1788 Socket.prototype.probe = function (name) {
    1789   debug('probing transport "%s"', name);
    1790   var transport = this.createTransport(name, { probe: 1 })
    1791     , failed = false
    1792     , self = this;
    1793 
    1794   Socket.priorWebsocketSuccess = false;
    1795 
    1796   function onTransportOpen(){
    1797     if (self.onlyBinaryUpgrades) {
    1798       var upgradeLosesBinary = !this.supportsBinary && self.transport.supportsBinary;
    1799       failed = failed || upgradeLosesBinary;
    1800     }
    1801     if (failed) return;
    1802 
    1803     debug('probe transport "%s" opened', name);
    1804     transport.send([{ type: 'ping', data: 'probe' }]);
    1805     transport.once('packet', function (msg) {
    1806       if (failed) return;
    1807       if ('pong' == msg.type && 'probe' == msg.data) {
    1808         debug('probe transport "%s" pong', name);
    1809         self.upgrading = true;
    1810         self.emit('upgrading', transport);
    1811         if (!transport) return;
    1812         Socket.priorWebsocketSuccess = 'websocket' == transport.name;
    1813 
    1814         debug('pausing current transport "%s"', self.transport.name);
    1815         self.transport.pause(function () {
    1816           if (failed) return;
    1817           if ('closed' == self.readyState) return;
    1818           debug('changing transport and sending upgrade packet');
    1819 
    1820           cleanup();
    1821 
    1822           self.setTransport(transport);
    1823           transport.send([{ type: 'upgrade' }]);
    1824           self.emit('upgrade', transport);
    1825           transport = null;
    1826           self.upgrading = false;
    1827           self.flush();
    1828         });
    1829       } else {
    1830         debug('probe transport "%s" failed', name);
    1831         var err = new Error('probe error');
    1832         err.transport = transport.name;
    1833         self.emit('upgradeError', err);
    1834       }
    1835     });
    1836   }
    1837 
    1838   function freezeTransport() {
    1839     if (failed) return;
    1840 
    1841     // Any callback called by transport should be ignored since now
    1842     failed = true;
    1843 
    1844     cleanup();
    1845 
    1846     transport.close();
    1847     transport = null;
    1848   }
    1849 
    1850   //Handle any error that happens while probing
    1851   function onerror(err) {
    1852     var error = new Error('probe error: ' + err);
    1853     error.transport = transport.name;
    1854 
    1855     freezeTransport();
    1856 
    1857     debug('probe transport "%s" failed because of error: %s', name, err);
    1858 
    1859     self.emit('upgradeError', error);
    1860   }
    1861 
    1862   function onTransportClose(){
    1863     onerror("transport closed");
    1864   }
    1865 
    1866   //When the socket is closed while we're probing
    1867   function onclose(){
    1868     onerror("socket closed");
    1869   }
    1870 
    1871   //When the socket is upgraded while we're probing
    1872   function onupgrade(to){
    1873     if (transport && to.name != transport.name) {
    1874       debug('"%s" works - aborting "%s"', to.name, transport.name);
    1875       freezeTransport();
    1876     }
    1877   }
    1878 
    1879   //Remove all listeners on the transport and on self
    1880   function cleanup(){
    1881     transport.removeListener('open', onTransportOpen);
    1882     transport.removeListener('error', onerror);
    1883     transport.removeListener('close', onTransportClose);
    1884     self.removeListener('close', onclose);
    1885     self.removeListener('upgrading', onupgrade);
    1886   }
    1887 
    1888   transport.once('open', onTransportOpen);
    1889   transport.once('error', onerror);
    1890   transport.once('close', onTransportClose);
    1891 
    1892   this.once('close', onclose);
    1893   this.once('upgrading', onupgrade);
    1894 
    1895   transport.open();
    1896 
    1897 };
    1898 
    1899 /**
    1900  * Called when connection is deemed open.
    1901  *
    1902  * @api public
    1903  */
    1904 
    1905 Socket.prototype.onOpen = function () {
    1906   debug('socket open');
    1907   this.readyState = 'open';
    1908   Socket.priorWebsocketSuccess = 'websocket' == this.transport.name;
    1909   this.emit('open');
    1910   this.flush();
    1911 
    1912   // we check for `readyState` in case an `open`
    1913   // listener already closed the socket
    1914   if ('open' == this.readyState && this.upgrade && this.transport.pause) {
    1915     debug('starting upgrade probes');
    1916     for (var i = 0, l = this.upgrades.length; i < l; i++) {
    1917       this.probe(this.upgrades[i]);
    1918     }
    1919   }
    1920 };
    1921 
    1922 /**
    1923  * Handles a packet.
    1924  *
    1925  * @api private
    1926  */
    1927 
    1928 Socket.prototype.onPacket = function (packet) {
    1929   if ('opening' == this.readyState || 'open' == this.readyState) {
    1930     debug('socket receive: type "%s", data "%s"', packet.type, packet.data);
    1931 
    1932     this.emit('packet', packet);
    1933 
    1934     // Socket is live - any packet counts
    1935     this.emit('heartbeat');
    1936 
    1937     switch (packet.type) {
    1938       case 'open':
    1939         this.onHandshake(parsejson(packet.data));
    1940         break;
    1941 
    1942       case 'pong':
    1943         this.setPing();
    1944         break;
    1945 
    1946       case 'error':
    1947         var err = new Error('server error');
    1948         err.code = packet.data;
    1949         this.emit('error', err);
    1950         break;
    1951 
    1952       case 'message':
    1953         this.emit('data', packet.data);
    1954         this.emit('message', packet.data);
    1955         break;
    1956     }
    1957   } else {
    1958     debug('packet received with socket readyState "%s"', this.readyState);
    1959   }
    1960 };
    1961 
    1962 /**
    1963  * Called upon handshake completion.
    1964  *
    1965  * @param {Object} handshake obj
    1966  * @api private
    1967  */
    1968 
    1969 Socket.prototype.onHandshake = function (data) {
    1970   this.emit('handshake', data);
    1971   this.id = data.sid;
    1972   this.transport.query.sid = data.sid;
    1973   this.upgrades = this.filterUpgrades(data.upgrades);
    1974   this.pingInterval = data.pingInterval;
    1975   this.pingTimeout = data.pingTimeout;
    1976   this.onOpen();
    1977   // In case open handler closes socket
    1978   if  ('closed' == this.readyState) return;
    1979   this.setPing();
    1980 
    1981   // Prolong liveness of socket on heartbeat
    1982   this.removeListener('heartbeat', this.onHeartbeat);
    1983   this.on('heartbeat', this.onHeartbeat);
    1984 };
    1985 
    1986 /**
    1987  * Resets ping timeout.
    1988  *
    1989  * @api private
    1990  */
    1991 
    1992 Socket.prototype.onHeartbeat = function (timeout) {
    1993   clearTimeout(this.pingTimeoutTimer);
    1994   var self = this;
    1995   self.pingTimeoutTimer = setTimeout(function () {
    1996     if ('closed' == self.readyState) return;
    1997     self.onClose('ping timeout');
    1998   }, timeout || (self.pingInterval + self.pingTimeout));
    1999 };
    2000 
    2001 /**
    2002  * Pings server every `this.pingInterval` and expects response
    2003  * within `this.pingTimeout` or closes connection.
    2004  *
    2005  * @api private
    2006  */
    2007 
    2008 Socket.prototype.setPing = function () {
    2009   var self = this;
    2010   clearTimeout(self.pingIntervalTimer);
    2011   self.pingIntervalTimer = setTimeout(function () {
    2012     debug('writing ping packet - expecting pong within %sms', self.pingTimeout);
    2013     self.ping();
    2014     self.onHeartbeat(self.pingTimeout);
    2015   }, self.pingInterval);
    2016 };
    2017 
    2018 /**
    2019 * Sends a ping packet.
    2020 *
    2021 * @api public
    2022 */
    2023 
    2024 Socket.prototype.ping = function () {
    2025   this.sendPacket('ping');
    2026 };
    2027 
    2028 /**
    2029  * Called on `drain` event
    2030  *
    2031  * @api private
    2032  */
    2033 
    2034 Socket.prototype.onDrain = function() {
    2035   for (var i = 0; i < this.prevBufferLen; i++) {
    2036     if (this.callbackBuffer[i]) {
    2037       this.callbackBuffer[i]();
    2038     }
    2039   }
    2040 
    2041   this.writeBuffer.splice(0, this.prevBufferLen);
    2042   this.callbackBuffer.splice(0, this.prevBufferLen);
    2043 
    2044   // setting prevBufferLen = 0 is very important
    2045   // for example, when upgrading, upgrade packet is sent over,
    2046   // and a nonzero prevBufferLen could cause problems on `drain`
    2047   this.prevBufferLen = 0;
    2048 
    2049   if (this.writeBuffer.length == 0) {
    2050     this.emit('drain');
    2051   } else {
    2052     this.flush();
    2053   }
    2054 };
    2055 
    2056 /**
    2057  * Flush write buffers.
    2058  *
    2059  * @api private
    2060  */
    2061 
    2062 Socket.prototype.flush = function () {
    2063   if ('closed' != this.readyState && this.transport.writable &&
    2064     !this.upgrading && this.writeBuffer.length) {
    2065     debug('flushing %d packets in socket', this.writeBuffer.length);
    2066     this.transport.send(this.writeBuffer);
    2067     // keep track of current length of writeBuffer
    2068     // splice writeBuffer and callbackBuffer on `drain`
    2069     this.prevBufferLen = this.writeBuffer.length;
    2070     this.emit('flush');
    2071   }
    2072 };
    2073 
    2074 /**
    2075  * Sends a message.
    2076  *
    2077  * @param {String} message.
    2078  * @param {Function} callback function.
    2079  * @return {Socket} for chaining.
    2080  * @api public
    2081  */
    2082 
    2083 Socket.prototype.write =
    2084 Socket.prototype.send = function (msg, fn) {
    2085   this.sendPacket('message', msg, fn);
    2086   return this;
    2087 };
    2088 
    2089 /**
    2090  * Sends a packet.
    2091  *
    2092  * @param {String} packet type.
    2093  * @param {String} data.
    2094  * @param {Function} callback function.
    2095  * @api private
    2096  */
    2097 
    2098 Socket.prototype.sendPacket = function (type, data, fn) {
    2099   if ('closing' == this.readyState || 'closed' == this.readyState) {
    2100     return;
    2101   }
    2102 
    2103   var packet = { type: type, data: data };
    2104   this.emit('packetCreate', packet);
    2105   this.writeBuffer.push(packet);
    2106   this.callbackBuffer.push(fn);
    2107   this.flush();
    2108 };
    2109 
    2110 /**
    2111  * Closes the connection.
    2112  *
    2113  * @api private
    2114  */
    2115 
    2116 Socket.prototype.close = function () {
    2117   if ('opening' == this.readyState || 'open' == this.readyState) {
    2118     this.readyState = 'closing';
    2119 
    2120     var self = this;
    2121 
    2122     function close() {
    2123       self.onClose('forced close');
    2124       debug('socket closing - telling transport to close');
    2125       self.transport.close();
    2126     }
    2127 
    2128     function cleanupAndClose() {
    2129       self.removeListener('upgrade', cleanupAndClose);
    2130       self.removeListener('upgradeError', cleanupAndClose);
    2131       close();
    2132     }
    2133 
    2134     function waitForUpgrade() {
    2135       // wait for upgrade to finish since we can't send packets while pausing a transport
    2136       self.once('upgrade', cleanupAndClose);
    2137       self.once('upgradeError', cleanupAndClose);
    2138     }
    2139 
    2140     if (this.writeBuffer.length) {
    2141       this.once('drain', function() {
    2142         if (this.upgrading) {
    2143           waitForUpgrade();
    2144         } else {
    2145           close();
    2146         }
    2147       });
    2148     } else if (this.upgrading) {
    2149       waitForUpgrade();
    2150     } else {
    2151       close();
    2152     }
    2153   }
    2154 
    2155   return this;
    2156 };
    2157 
    2158 /**
    2159  * Called upon transport error
    2160  *
    2161  * @api private
    2162  */
    2163 
    2164 Socket.prototype.onError = function (err) {
    2165   debug('socket error %j', err);
    2166   Socket.priorWebsocketSuccess = false;
    2167   this.emit('error', err);
    2168   this.onClose('transport error', err);
    2169 };
    2170 
    2171 /**
    2172  * Called upon transport close.
    2173  *
    2174  * @api private
    2175  */
    2176 
    2177 Socket.prototype.onClose = function (reason, desc) {
    2178   if ('opening' == this.readyState || 'open' == this.readyState || 'closing' == this.readyState) {
    2179     debug('socket close with reason: "%s"', reason);
    2180     var self = this;
    2181 
    2182     // clear timers
    2183     clearTimeout(this.pingIntervalTimer);
    2184     clearTimeout(this.pingTimeoutTimer);
    2185 
    2186     // clean buffers in next tick, so developers can still
    2187     // grab the buffers on `close` event
    2188     setTimeout(function() {
    2189       self.writeBuffer = [];
    2190       self.callbackBuffer = [];
    2191       self.prevBufferLen = 0;
    2192     }, 0);
    2193 
    2194     // stop event from firing again for transport
    2195     this.transport.removeAllListeners('close');
    2196 
    2197     // ensure transport won't stay open
    2198     this.transport.close();
    2199 
    2200     // ignore further transport communication
    2201     this.transport.removeAllListeners();
    2202 
    2203     // set ready state
    2204     this.readyState = 'closed';
    2205 
    2206     // clear session id
    2207     this.id = null;
    2208 
    2209     // emit close event
    2210     this.emit('close', reason, desc);
    2211   }
    2212 };
    2213 
    2214 /**
    2215  * Filters upgrades, returning only those matching client transports.
    2216  *
    2217  * @param {Array} server upgrades
    2218  * @api private
    2219  *
    2220  */
    2221 
    2222 Socket.prototype.filterUpgrades = function (upgrades) {
    2223   var filteredUpgrades = [];
    2224   for (var i = 0, j = upgrades.length; i<j; i++) {
    2225     if (~index(this.transports, upgrades[i])) filteredUpgrades.push(upgrades[i]);
    2226   }
    2227   return filteredUpgrades;
    2228 };
    2229 
    2230 }).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
    2231 },{"./transport":14,"./transports":15,"component-emitter":9,"debug":22,"engine.io-parser":25,"indexof":40,"parsejson":32,"parseqs":33,"parseuri":34}],14:[function(_dereq_,module,exports){
    2232 /**
    2233  * Module dependencies.
    2234  */
    2235 
    2236 var parser = _dereq_('engine.io-parser');
    2237 var Emitter = _dereq_('component-emitter');
    2238 
    2239 /**
    2240  * Module exports.
    2241  */
    2242 
    2243 module.exports = Transport;
    2244 
    2245 /**
    2246  * Transport abstract constructor.
    2247  *
    2248  * @param {Object} options.
    2249  * @api private
    2250  */
    2251 
    2252 function Transport (opts) {
    2253   this.path = opts.path;
    2254   this.hostname = opts.hostname;
    2255   this.port = opts.port;
    2256   this.secure = opts.secure;
    2257   this.query = opts.query;
    2258   this.timestampParam = opts.timestampParam;
    2259   this.timestampRequests = opts.timestampRequests;
    2260   this.readyState = '';
    2261   this.agent = opts.agent || false;
    2262   this.socket = opts.socket;
    2263   this.enablesXDR = opts.enablesXDR;
    2264 
    2265   // SSL options for Node.js client
    2266   this.pfx = opts.pfx;
    2267   this.key = opts.key;
    2268   this.passphrase = opts.passphrase;
    2269   this.cert = opts.cert;
    2270   this.ca = opts.ca;
    2271   this.ciphers = opts.ciphers;
    2272   this.rejectUnauthorized = opts.rejectUnauthorized;
    2273 }
    2274 
    2275 /**
    2276  * Mix in `Emitter`.
    2277  */
    2278 
    2279 Emitter(Transport.prototype);
    2280 
    2281 /**
    2282  * A counter used to prevent collisions in the timestamps used
    2283  * for cache busting.
    2284  */
    2285 
    2286 Transport.timestamps = 0;
    2287 
    2288 /**
    2289  * Emits an error.
    2290  *
    2291  * @param {String} str
    2292  * @return {Transport} for chaining
    2293  * @api public
    2294  */
    2295 
    2296 Transport.prototype.onError = function (msg, desc) {
    2297   var err = new Error(msg);
    2298   err.type = 'TransportError';
    2299   err.description = desc;
    2300   this.emit('error', err);
    2301   return this;
    2302 };
    2303 
    2304 /**
    2305  * Opens the transport.
    2306  *
    2307  * @api public
    2308  */
    2309 
    2310 Transport.prototype.open = function () {
    2311   if ('closed' == this.readyState || '' == this.readyState) {
    2312     this.readyState = 'opening';
    2313     this.doOpen();
    2314   }
    2315 
    2316   return this;
    2317 };
    2318 
    2319 /**
    2320  * Closes the transport.
    2321  *
    2322  * @api private
    2323  */
    2324 
    2325 Transport.prototype.close = function () {
    2326   if ('opening' == this.readyState || 'open' == this.readyState) {
    2327     this.doClose();
    2328     this.onClose();
    2329   }
    2330 
    2331   return this;
    2332 };
    2333 
    2334 /**
    2335  * Sends multiple packets.
    2336  *
    2337  * @param {Array} packets
    2338  * @api private
    2339  */
    2340 
    2341 Transport.prototype.send = function(packets){
    2342   if ('open' == this.readyState) {
    2343     this.write(packets);
    2344   } else {
    2345     throw new Error('Transport not open');
    2346   }
    2347 };
    2348 
    2349 /**
    2350  * Called upon open
    2351  *
    2352  * @api private
    2353  */
    2354 
    2355 Transport.prototype.onOpen = function () {
    2356   this.readyState = 'open';
    2357   this.writable = true;
    2358   this.emit('open');
    2359 };
    2360 
    2361 /**
    2362  * Called with data.
    2363  *
    2364  * @param {String} data
    2365  * @api private
    2366  */
    2367 
    2368 Transport.prototype.onData = function(data){
    2369   var packet = parser.decodePacket(data, this.socket.binaryType);
    2370   this.onPacket(packet);
    2371 };
    2372 
    2373 /**
    2374  * Called with a decoded packet.
    2375  */
    2376 
    2377 Transport.prototype.onPacket = function (packet) {
    2378   this.emit('packet', packet);
    2379 };
    2380 
    2381 /**
    2382  * Called upon close.
    2383  *
    2384  * @api private
    2385  */
    2386 
    2387 Transport.prototype.onClose = function () {
    2388   this.readyState = 'closed';
    2389   this.emit('close');
    2390 };
    2391 
    2392 },{"component-emitter":9,"engine.io-parser":25}],15:[function(_dereq_,module,exports){
    2393 (function (global){
    2394 /**
    2395  * Module dependencies
    2396  */
    2397 
    2398 var XMLHttpRequest = _dereq_('xmlhttprequest');
    2399 var XHR = _dereq_('./polling-xhr');
    2400 var JSONP = _dereq_('./polling-jsonp');
    2401 var websocket = _dereq_('./websocket');
    2402 
    2403 /**
    2404  * Export transports.
    2405  */
    2406 
    2407 exports.polling = polling;
    2408 exports.websocket = websocket;
    2409 
    2410 /**
    2411  * Polling transport polymorphic constructor.
    2412  * Decides on xhr vs jsonp based on feature detection.
    2413  *
    2414  * @api private
    2415  */
    2416 
    2417 function polling(opts){
    2418   var xhr;
    2419   var xd = false;
    2420   var xs = false;
    2421   var jsonp = false !== opts.jsonp;
    2422 
    2423   if (global.location) {
    2424     var isSSL = 'https:' == location.protocol;
    2425     var port = location.port;
    2426 
    2427     // some user agents have empty `location.port`
    2428     if (!port) {
    2429       port = isSSL ? 443 : 80;
    2430     }
    2431 
    2432     xd = opts.hostname != location.hostname || port != opts.port;
    2433     xs = opts.secure != isSSL;
    2434   }
    2435 
    2436   opts.xdomain = xd;
    2437   opts.xscheme = xs;
    2438   xhr = new XMLHttpRequest(opts);
    2439 
    2440   if ('open' in xhr && !opts.forceJSONP) {
    2441     return new XHR(opts);
    2442   } else {
    2443     if (!jsonp) throw new Error('JSONP disabled');
    2444     return new JSONP(opts);
    2445   }
    2446 }
    2447 
    2448 }).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
    2449 },{"./polling-jsonp":16,"./polling-xhr":17,"./websocket":19,"xmlhttprequest":20}],16:[function(_dereq_,module,exports){
    2450 (function (global){
    2451 
    2452 /**
    2453  * Module requirements.
    2454  */
    2455 
    2456 var Polling = _dereq_('./polling');
    2457 var inherit = _dereq_('component-inherit');
    2458 
    2459 /**
    2460  * Module exports.
    2461  */
    2462 
    2463 module.exports = JSONPPolling;
    2464 
    2465 /**
    2466  * Cached regular expressions.
    2467  */
    2468 
    2469 var rNewline = /
    /g;
    2470 var rEscapedNewline = /\n/g;
    2471 
    2472 /**
    2473  * Global JSONP callbacks.
    2474  */
    2475 
    2476 var callbacks;
    2477 
    2478 /**
    2479  * Callbacks count.
    2480  */
    2481 
    2482 var index = 0;
    2483 
    2484 /**
    2485  * Noop.
    2486  */
    2487 
    2488 function empty () { }
    2489 
    2490 /**
    2491  * JSONP Polling constructor.
    2492  *
    2493  * @param {Object} opts.
    2494  * @api public
    2495  */
    2496 
    2497 function JSONPPolling (opts) {
    2498   Polling.call(this, opts);
    2499 
    2500   this.query = this.query || {};
    2501 
    2502   // define global callbacks array if not present
    2503   // we do this here (lazily) to avoid unneeded global pollution
    2504   if (!callbacks) {
    2505     // we need to consider multiple engines in the same page
    2506     if (!global.___eio) global.___eio = [];
    2507     callbacks = global.___eio;
    2508   }
    2509 
    2510   // callback identifier
    2511   this.index = callbacks.length;
    2512 
    2513   // add callback to jsonp global
    2514   var self = this;
    2515   callbacks.push(function (msg) {
    2516     self.onData(msg);
    2517   });
    2518 
    2519   // append to query string
    2520   this.query.j = this.index;
    2521 
    2522   // prevent spurious errors from being emitted when the window is unloaded
    2523   if (global.document && global.addEventListener) {
    2524     global.addEventListener('beforeunload', function () {
    2525       if (self.script) self.script.onerror = empty;
    2526     }, false);
    2527   }
    2528 }
    2529 
    2530 /**
    2531  * Inherits from Polling.
    2532  */
    2533 
    2534 inherit(JSONPPolling, Polling);
    2535 
    2536 /*
    2537  * JSONP only supports binary as base64 encoded strings
    2538  */
    2539 
    2540 JSONPPolling.prototype.supportsBinary = false;
    2541 
    2542 /**
    2543  * Closes the socket.
    2544  *
    2545  * @api private
    2546  */
    2547 
    2548 JSONPPolling.prototype.doClose = function () {
    2549   if (this.script) {
    2550     this.script.parentNode.removeChild(this.script);
    2551     this.script = null;
    2552   }
    2553 
    2554   if (this.form) {
    2555     this.form.parentNode.removeChild(this.form);
    2556     this.form = null;
    2557     this.iframe = null;
    2558   }
    2559 
    2560   Polling.prototype.doClose.call(this);
    2561 };
    2562 
    2563 /**
    2564  * Starts a poll cycle.
    2565  *
    2566  * @api private
    2567  */
    2568 
    2569 JSONPPolling.prototype.doPoll = function () {
    2570   var self = this;
    2571   var script = document.createElement('script');
    2572 
    2573   if (this.script) {
    2574     this.script.parentNode.removeChild(this.script);
    2575     this.script = null;
    2576   }
    2577 
    2578   script.async = true;
    2579   script.src = this.uri();
    2580   script.onerror = function(e){
    2581     self.onError('jsonp poll error',e);
    2582   };
    2583 
    2584   var insertAt = document.getElementsByTagName('script')[0];
    2585   insertAt.parentNode.insertBefore(script, insertAt);
    2586   this.script = script;
    2587 
    2588   var isUAgecko = 'undefined' != typeof navigator && /gecko/i.test(navigator.userAgent);
    2589   
    2590   if (isUAgecko) {
    2591     setTimeout(function () {
    2592       var iframe = document.createElement('iframe');
    2593       document.body.appendChild(iframe);
    2594       document.body.removeChild(iframe);
    2595     }, 100);
    2596   }
    2597 };
    2598 
    2599 /**
    2600  * Writes with a hidden iframe.
    2601  *
    2602  * @param {String} data to send
    2603  * @param {Function} called upon flush.
    2604  * @api private
    2605  */
    2606 
    2607 JSONPPolling.prototype.doWrite = function (data, fn) {
    2608   var self = this;
    2609 
    2610   if (!this.form) {
    2611     var form = document.createElement('form');
    2612     var area = document.createElement('textarea');
    2613     var id = this.iframeId = 'eio_iframe_' + this.index;
    2614     var iframe;
    2615 
    2616     form.className = 'socketio';
    2617     form.style.position = 'absolute';
    2618     form.style.top = '-1000px';
    2619     form.style.left = '-1000px';
    2620     form.target = id;
    2621     form.method = 'POST';
    2622     form.setAttribute('accept-charset', 'utf-8');
    2623     area.name = 'd';
    2624     form.appendChild(area);
    2625     document.body.appendChild(form);
    2626 
    2627     this.form = form;
    2628     this.area = area;
    2629   }
    2630 
    2631   this.form.action = this.uri();
    2632 
    2633   function complete () {
    2634     initIframe();
    2635     fn();
    2636   }
    2637 
    2638   function initIframe () {
    2639     if (self.iframe) {
    2640       try {
    2641         self.form.removeChild(self.iframe);
    2642       } catch (e) {
    2643         self.onError('jsonp polling iframe removal error', e);
    2644       }
    2645     }
    2646 
    2647     try {
    2648       // ie6 dynamic iframes with target="" support (thanks Chris Lambacher)
    2649       var html = '<iframe src="javascript:0" name="'+ self.iframeId +'">';
    2650       iframe = document.createElement(html);
    2651     } catch (e) {
    2652       iframe = document.createElement('iframe');
    2653       iframe.name = self.iframeId;
    2654       iframe.src = 'javascript:0';
    2655     }
    2656 
    2657     iframe.id = self.iframeId;
    2658 
    2659     self.form.appendChild(iframe);
    2660     self.iframe = iframe;
    2661   }
    2662 
    2663   initIframe();
    2664 
    2665   // escape 
     to prevent it from being converted into 
     by some UAs
    2666   // double escaping is required for escaped new lines because unescaping of new lines can be done safely on server-side
    2667   data = data.replace(rEscapedNewline, '\
    ');
    2668   this.area.value = data.replace(rNewline, '\n');
    2669 
    2670   try {
    2671     this.form.submit();
    2672   } catch(e) {}
    2673 
    2674   if (this.iframe.attachEvent) {
    2675     this.iframe.onreadystatechange = function(){
    2676       if (self.iframe.readyState == 'complete') {
    2677         complete();
    2678       }
    2679     };
    2680   } else {
    2681     this.iframe.onload = complete;
    2682   }
    2683 };
    2684 
    2685 }).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
    2686 },{"./polling":18,"component-inherit":21}],17:[function(_dereq_,module,exports){
    2687 (function (global){
    2688 /**
    2689  * Module requirements.
    2690  */
    2691 
    2692 var XMLHttpRequest = _dereq_('xmlhttprequest');
    2693 var Polling = _dereq_('./polling');
    2694 var Emitter = _dereq_('component-emitter');
    2695 var inherit = _dereq_('component-inherit');
    2696 var debug = _dereq_('debug')('engine.io-client:polling-xhr');
    2697 
    2698 /**
    2699  * Module exports.
    2700  */
    2701 
    2702 module.exports = XHR;
    2703 module.exports.Request = Request;
    2704 
    2705 /**
    2706  * Empty function
    2707  */
    2708 
    2709 function empty(){}
    2710 
    2711 /**
    2712  * XHR Polling constructor.
    2713  *
    2714  * @param {Object} opts
    2715  * @api public
    2716  */
    2717 
    2718 function XHR(opts){
    2719   Polling.call(this, opts);
    2720 
    2721   if (global.location) {
    2722     var isSSL = 'https:' == location.protocol;
    2723     var port = location.port;
    2724 
    2725     // some user agents have empty `location.port`
    2726     if (!port) {
    2727       port = isSSL ? 443 : 80;
    2728     }
    2729 
    2730     this.xd = opts.hostname != global.location.hostname ||
    2731       port != opts.port;
    2732     this.xs = opts.secure != isSSL;
    2733   }
    2734 }
    2735 
    2736 /**
    2737  * Inherits from Polling.
    2738  */
    2739 
    2740 inherit(XHR, Polling);
    2741 
    2742 /**
    2743  * XHR supports binary
    2744  */
    2745 
    2746 XHR.prototype.supportsBinary = true;
    2747 
    2748 /**
    2749  * Creates a request.
    2750  *
    2751  * @param {String} method
    2752  * @api private
    2753  */
    2754 
    2755 XHR.prototype.request = function(opts){
    2756   opts = opts || {};
    2757   opts.uri = this.uri();
    2758   opts.xd = this.xd;
    2759   opts.xs = this.xs;
    2760   opts.agent = this.agent || false;
    2761   opts.supportsBinary = this.supportsBinary;
    2762   opts.enablesXDR = this.enablesXDR;
    2763 
    2764   // SSL options for Node.js client
    2765   opts.pfx = this.pfx;
    2766   opts.key = this.key;
    2767   opts.passphrase = this.passphrase;
    2768   opts.cert = this.cert;
    2769   opts.ca = this.ca;
    2770   opts.ciphers = this.ciphers;
    2771   opts.rejectUnauthorized = this.rejectUnauthorized;
    2772 
    2773   return new Request(opts);
    2774 };
    2775 
    2776 /**
    2777  * Sends data.
    2778  *
    2779  * @param {String} data to send.
    2780  * @param {Function} called upon flush.
    2781  * @api private
    2782  */
    2783 
    2784 XHR.prototype.doWrite = function(data, fn){
    2785   var isBinary = typeof data !== 'string' && data !== undefined;
    2786   var req = this.request({ method: 'POST', data: data, isBinary: isBinary });
    2787   var self = this;
    2788   req.on('success', fn);
    2789   req.on('error', function(err){
    2790     self.onError('xhr post error', err);
    2791   });
    2792   this.sendXhr = req;
    2793 };
    2794 
    2795 /**
    2796  * Starts a poll cycle.
    2797  *
    2798  * @api private
    2799  */
    2800 
    2801 XHR.prototype.doPoll = function(){
    2802   debug('xhr poll');
    2803   var req = this.request();
    2804   var self = this;
    2805   req.on('data', function(data){
    2806     self.onData(data);
    2807   });
    2808   req.on('error', function(err){
    2809     self.onError('xhr poll error', err);
    2810   });
    2811   this.pollXhr = req;
    2812 };
    2813 
    2814 /**
    2815  * Request constructor
    2816  *
    2817  * @param {Object} options
    2818  * @api public
    2819  */
    2820 
    2821 function Request(opts){
    2822   this.method = opts.method || 'GET';
    2823   this.uri = opts.uri;
    2824   this.xd = !!opts.xd;
    2825   this.xs = !!opts.xs;
    2826   this.async = false !== opts.async;
    2827   this.data = undefined != opts.data ? opts.data : null;
    2828   this.agent = opts.agent;
    2829   this.isBinary = opts.isBinary;
    2830   this.supportsBinary = opts.supportsBinary;
    2831   this.enablesXDR = opts.enablesXDR;
    2832 
    2833   // SSL options for Node.js client
    2834   this.pfx = opts.pfx;
    2835   this.key = opts.key;
    2836   this.passphrase = opts.passphrase;
    2837   this.cert = opts.cert;
    2838   this.ca = opts.ca;
    2839   this.ciphers = opts.ciphers;
    2840   this.rejectUnauthorized = opts.rejectUnauthorized;
    2841 
    2842   this.create();
    2843 }
    2844 
    2845 /**
    2846  * Mix in `Emitter`.
    2847  */
    2848 
    2849 Emitter(Request.prototype);
    2850 
    2851 /**
    2852  * Creates the XHR object and sends the request.
    2853  *
    2854  * @api private
    2855  */
    2856 
    2857 Request.prototype.create = function(){
    2858   var opts = { agent: this.agent, xdomain: this.xd, xscheme: this.xs, enablesXDR: this.enablesXDR };
    2859 
    2860   // SSL options for Node.js client
    2861   opts.pfx = this.pfx;
    2862   opts.key = this.key;
    2863   opts.passphrase = this.passphrase;
    2864   opts.cert = this.cert;
    2865   opts.ca = this.ca;
    2866   opts.ciphers = this.ciphers;
    2867   opts.rejectUnauthorized = this.rejectUnauthorized;
    2868 
    2869   var xhr = this.xhr = new XMLHttpRequest(opts);
    2870   var self = this;
    2871 
    2872   try {
    2873     debug('xhr open %s: %s', this.method, this.uri);
    2874     xhr.open(this.method, this.uri, this.async);
    2875     if (this.supportsBinary) {
    2876       // This has to be done after open because Firefox is stupid
    2877       // http://stackoverflow.com/questions/13216903/get-binary-data-with-xmlhttprequest-in-a-firefox-extension
    2878       xhr.responseType = 'arraybuffer';
    2879     }
    2880 
    2881     if ('POST' == this.method) {
    2882       try {
    2883         if (this.isBinary) {
    2884           xhr.setRequestHeader('Content-type', 'application/octet-stream');
    2885         } else {
    2886           xhr.setRequestHeader('Content-type', 'text/plain;charset=UTF-8');
    2887         }
    2888       } catch (e) {}
    2889     }
    2890 
    2891     // ie6 check
    2892     if ('withCredentials' in xhr) {
    2893       xhr.withCredentials = true;
    2894     }
    2895 
    2896     if (this.hasXDR()) {
    2897       xhr.onload = function(){
    2898         self.onLoad();
    2899       };
    2900       xhr.onerror = function(){
    2901         self.onError(xhr.responseText);
    2902       };
    2903     } else {
    2904       xhr.onreadystatechange = function(){
    2905         if (4 != xhr.readyState) return;
    2906         if (200 == xhr.status || 1223 == xhr.status) {
    2907           self.onLoad();
    2908         } else {
    2909           // make sure the `error` event handler that's user-set
    2910           // does not throw in the same tick and gets caught here
    2911           setTimeout(function(){
    2912             self.onError(xhr.status);
    2913           }, 0);
    2914         }
    2915       };
    2916     }
    2917 
    2918     debug('xhr data %s', this.data);
    2919     xhr.send(this.data);
    2920   } catch (e) {
    2921     // Need to defer since .create() is called directly fhrom the constructor
    2922     // and thus the 'error' event can only be only bound *after* this exception
    2923     // occurs.  Therefore, also, we cannot throw here at all.
    2924     setTimeout(function() {
    2925       self.onError(e);
    2926     }, 0);
    2927     return;
    2928   }
    2929 
    2930   if (global.document) {
    2931     this.index = Request.requestsCount++;
    2932     Request.requests[this.index] = this;
    2933   }
    2934 };
    2935 
    2936 /**
    2937  * Called upon successful response.
    2938  *
    2939  * @api private
    2940  */
    2941 
    2942 Request.prototype.onSuccess = function(){
    2943   this.emit('success');
    2944   this.cleanup();
    2945 };
    2946 
    2947 /**
    2948  * Called if we have data.
    2949  *
    2950  * @api private
    2951  */
    2952 
    2953 Request.prototype.onData = function(data){
    2954   this.emit('data', data);
    2955   this.onSuccess();
    2956 };
    2957 
    2958 /**
    2959  * Called upon error.
    2960  *
    2961  * @api private
    2962  */
    2963 
    2964 Request.prototype.onError = function(err){
    2965   this.emit('error', err);
    2966   this.cleanup(true);
    2967 };
    2968 
    2969 /**
    2970  * Cleans up house.
    2971  *
    2972  * @api private
    2973  */
    2974 
    2975 Request.prototype.cleanup = function(fromError){
    2976   if ('undefined' == typeof this.xhr || null === this.xhr) {
    2977     return;
    2978   }
    2979   // xmlhttprequest
    2980   if (this.hasXDR()) {
    2981     this.xhr.onload = this.xhr.onerror = empty;
    2982   } else {
    2983     this.xhr.onreadystatechange = empty;
    2984   }
    2985 
    2986   if (fromError) {
    2987     try {
    2988       this.xhr.abort();
    2989     } catch(e) {}
    2990   }
    2991 
    2992   if (global.document) {
    2993     delete Request.requests[this.index];
    2994   }
    2995 
    2996   this.xhr = null;
    2997 };
    2998 
    2999 /**
    3000  * Called upon load.
    3001  *
    3002  * @api private
    3003  */
    3004 
    3005 Request.prototype.onLoad = function(){
    3006   var data;
    3007   try {
    3008     var contentType;
    3009     try {
    3010       contentType = this.xhr.getResponseHeader('Content-Type').split(';')[0];
    3011     } catch (e) {}
    3012     if (contentType === 'application/octet-stream') {
    3013       data = this.xhr.response;
    3014     } else {
    3015       if (!this.supportsBinary) {
    3016         data = this.xhr.responseText;
    3017       } else {
    3018         data = 'ok';
    3019       }
    3020     }
    3021   } catch (e) {
    3022     this.onError(e);
    3023   }
    3024   if (null != data) {
    3025     this.onData(data);
    3026   }
    3027 };
    3028 
    3029 /**
    3030  * Check if it has XDomainRequest.
    3031  *
    3032  * @api private
    3033  */
    3034 
    3035 Request.prototype.hasXDR = function(){
    3036   return 'undefined' !== typeof global.XDomainRequest && !this.xs && this.enablesXDR;
    3037 };
    3038 
    3039 /**
    3040  * Aborts the request.
    3041  *
    3042  * @api public
    3043  */
    3044 
    3045 Request.prototype.abort = function(){
    3046   this.cleanup();
    3047 };
    3048 
    3049 /**
    3050  * Aborts pending requests when unloading the window. This is needed to prevent
    3051  * memory leaks (e.g. when using IE) and to ensure that no spurious error is
    3052  * emitted.
    3053  */
    3054 
    3055 if (global.document) {
    3056   Request.requestsCount = 0;
    3057   Request.requests = {};
    3058   if (global.attachEvent) {
    3059     global.attachEvent('onunload', unloadHandler);
    3060   } else if (global.addEventListener) {
    3061     global.addEventListener('beforeunload', unloadHandler, false);
    3062   }
    3063 }
    3064 
    3065 function unloadHandler() {
    3066   for (var i in Request.requests) {
    3067     if (Request.requests.hasOwnProperty(i)) {
    3068       Request.requests[i].abort();
    3069     }
    3070   }
    3071 }
    3072 
    3073 }).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
    3074 },{"./polling":18,"component-emitter":9,"component-inherit":21,"debug":22,"xmlhttprequest":20}],18:[function(_dereq_,module,exports){
    3075 /**
    3076  * Module dependencies.
    3077  */
    3078 
    3079 var Transport = _dereq_('../transport');
    3080 var parseqs = _dereq_('parseqs');
    3081 var parser = _dereq_('engine.io-parser');
    3082 var inherit = _dereq_('component-inherit');
    3083 var debug = _dereq_('debug')('engine.io-client:polling');
    3084 
    3085 /**
    3086  * Module exports.
    3087  */
    3088 
    3089 module.exports = Polling;
    3090 
    3091 /**
    3092  * Is XHR2 supported?
    3093  */
    3094 
    3095 var hasXHR2 = (function() {
    3096   var XMLHttpRequest = _dereq_('xmlhttprequest');
    3097   var xhr = new XMLHttpRequest({ xdomain: false });
    3098   return null != xhr.responseType;
    3099 })();
    3100 
    3101 /**
    3102  * Polling interface.
    3103  *
    3104  * @param {Object} opts
    3105  * @api private
    3106  */
    3107 
    3108 function Polling(opts){
    3109   var forceBase64 = (opts && opts.forceBase64);
    3110   if (!hasXHR2 || forceBase64) {
    3111     this.supportsBinary = false;
    3112   }
    3113   Transport.call(this, opts);
    3114 }
    3115 
    3116 /**
    3117  * Inherits from Transport.
    3118  */
    3119 
    3120 inherit(Polling, Transport);
    3121 
    3122 /**
    3123  * Transport name.
    3124  */
    3125 
    3126 Polling.prototype.name = 'polling';
    3127 
    3128 /**
    3129  * Opens the socket (triggers polling). We write a PING message to determine
    3130  * when the transport is open.
    3131  *
    3132  * @api private
    3133  */
    3134 
    3135 Polling.prototype.doOpen = function(){
    3136   this.poll();
    3137 };
    3138 
    3139 /**
    3140  * Pauses polling.
    3141  *
    3142  * @param {Function} callback upon buffers are flushed and transport is paused
    3143  * @api private
    3144  */
    3145 
    3146 Polling.prototype.pause = function(onPause){
    3147   var pending = 0;
    3148   var self = this;
    3149 
    3150   this.readyState = 'pausing';
    3151 
    3152   function pause(){
    3153     debug('paused');
    3154     self.readyState = 'paused';
    3155     onPause();
    3156   }
    3157 
    3158   if (this.polling || !this.writable) {
    3159     var total = 0;
    3160 
    3161     if (this.polling) {
    3162       debug('we are currently polling - waiting to pause');
    3163       total++;
    3164       this.once('pollComplete', function(){
    3165         debug('pre-pause polling complete');
    3166         --total || pause();
    3167       });
    3168     }
    3169 
    3170     if (!this.writable) {
    3171       debug('we are currently writing - waiting to pause');
    3172       total++;
    3173       this.once('drain', function(){
    3174         debug('pre-pause writing complete');
    3175         --total || pause();
    3176       });
    3177     }
    3178   } else {
    3179     pause();
    3180   }
    3181 };
    3182 
    3183 /**
    3184  * Starts polling cycle.
    3185  *
    3186  * @api public
    3187  */
    3188 
    3189 Polling.prototype.poll = function(){
    3190   debug('polling');
    3191   this.polling = true;
    3192   this.doPoll();
    3193   this.emit('poll');
    3194 };
    3195 
    3196 /**
    3197  * Overloads onData to detect payloads.
    3198  *
    3199  * @api private
    3200  */
    3201 
    3202 Polling.prototype.onData = function(data){
    3203   var self = this;
    3204   debug('polling got data %s', data);
    3205   var callback = function(packet, index, total) {
    3206     // if its the first message we consider the transport open
    3207     if ('opening' == self.readyState) {
    3208       self.onOpen();
    3209     }
    3210 
    3211     // if its a close packet, we close the ongoing requests
    3212     if ('close' == packet.type) {
    3213       self.onClose();
    3214       return false;
    3215     }
    3216 
    3217     // otherwise bypass onData and handle the message
    3218     self.onPacket(packet);
    3219   };
    3220 
    3221   // decode payload
    3222   parser.decodePayload(data, this.socket.binaryType, callback);
    3223 
    3224   // if an event did not trigger closing
    3225   if ('closed' != this.readyState) {
    3226     // if we got data we're not polling
    3227     this.polling = false;
    3228     this.emit('pollComplete');
    3229 
    3230     if ('open' == this.readyState) {
    3231       this.poll();
    3232     } else {
    3233       debug('ignoring poll - transport state "%s"', this.readyState);
    3234     }
    3235   }
    3236 };
    3237 
    3238 /**
    3239  * For polling, send a close packet.
    3240  *
    3241  * @api private
    3242  */
    3243 
    3244 Polling.prototype.doClose = function(){
    3245   var self = this;
    3246 
    3247   function close(){
    3248     debug('writing close packet');
    3249     self.write([{ type: 'close' }]);
    3250   }
    3251 
    3252   if ('open' == this.readyState) {
    3253     debug('transport open - closing');
    3254     close();
    3255   } else {
    3256     // in case we're trying to close while
    3257     // handshaking is in progress (GH-164)
    3258     debug('transport not open - deferring close');
    3259     this.once('open', close);
    3260   }
    3261 };
    3262 
    3263 /**
    3264  * Writes a packets payload.
    3265  *
    3266  * @param {Array} data packets
    3267  * @param {Function} drain callback
    3268  * @api private
    3269  */
    3270 
    3271 Polling.prototype.write = function(packets){
    3272   var self = this;
    3273   this.writable = false;
    3274   var callbackfn = function() {
    3275     self.writable = true;
    3276     self.emit('drain');
    3277   };
    3278 
    3279   var self = this;
    3280   parser.encodePayload(packets, this.supportsBinary, function(data) {
    3281     self.doWrite(data, callbackfn);
    3282   });
    3283 };
    3284 
    3285 /**
    3286  * Generates uri for connection.
    3287  *
    3288  * @api private
    3289  */
    3290 
    3291 Polling.prototype.uri = function(){
    3292   var query = this.query || {};
    3293   var schema = this.secure ? 'https' : 'http';
    3294   var port = '';
    3295 
    3296   // cache busting is forced
    3297   if (false !== this.timestampRequests) {
    3298     query[this.timestampParam] = +new Date + '-' + Transport.timestamps++;
    3299   }
    3300 
    3301   if (!this.supportsBinary && !query.sid) {
    3302     query.b64 = 1;
    3303   }
    3304 
    3305   query = parseqs.encode(query);
    3306 
    3307   // avoid port if default for schema
    3308   if (this.port && (('https' == schema && this.port != 443) ||
    3309      ('http' == schema && this.port != 80))) {
    3310     port = ':' + this.port;
    3311   }
    3312 
    3313   // prepend ? to query
    3314   if (query.length) {
    3315     query = '?' + query;
    3316   }
    3317 
    3318   return schema + '://' + this.hostname + port + this.path + query;
    3319 };
    3320 
    3321 },{"../transport":14,"component-inherit":21,"debug":22,"engine.io-parser":25,"parseqs":33,"xmlhttprequest":20}],19:[function(_dereq_,module,exports){
    3322 /**
    3323  * Module dependencies.
    3324  */
    3325 
    3326 var Transport = _dereq_('../transport');
    3327 var parser = _dereq_('engine.io-parser');
    3328 var parseqs = _dereq_('parseqs');
    3329 var inherit = _dereq_('component-inherit');
    3330 var debug = _dereq_('debug')('engine.io-client:websocket');
    3331 
    3332 /**
    3333  * `ws` exposes a WebSocket-compatible interface in
    3334  * Node, or the `WebSocket` or `MozWebSocket` globals
    3335  * in the browser.
    3336  */
    3337 
    3338 var WebSocket = _dereq_('ws');
    3339 
    3340 /**
    3341  * Module exports.
    3342  */
    3343 
    3344 module.exports = WS;
    3345 
    3346 /**
    3347  * WebSocket transport constructor.
    3348  *
    3349  * @api {Object} connection options
    3350  * @api public
    3351  */
    3352 
    3353 function WS(opts){
    3354   var forceBase64 = (opts && opts.forceBase64);
    3355   if (forceBase64) {
    3356     this.supportsBinary = false;
    3357   }
    3358   Transport.call(this, opts);
    3359 }
    3360 
    3361 /**
    3362  * Inherits from Transport.
    3363  */
    3364 
    3365 inherit(WS, Transport);
    3366 
    3367 /**
    3368  * Transport name.
    3369  *
    3370  * @api public
    3371  */
    3372 
    3373 WS.prototype.name = 'websocket';
    3374 
    3375 /*
    3376  * WebSockets support binary
    3377  */
    3378 
    3379 WS.prototype.supportsBinary = true;
    3380 
    3381 /**
    3382  * Opens socket.
    3383  *
    3384  * @api private
    3385  */
    3386 
    3387 WS.prototype.doOpen = function(){
    3388   if (!this.check()) {
    3389     // let probe timeout
    3390     return;
    3391   }
    3392 
    3393   var self = this;
    3394   var uri = this.uri();
    3395   var protocols = void(0);
    3396   var opts = { agent: this.agent };
    3397 
    3398   // SSL options for Node.js client
    3399   opts.pfx = this.pfx;
    3400   opts.key = this.key;
    3401   opts.passphrase = this.passphrase;
    3402   opts.cert = this.cert;
    3403   opts.ca = this.ca;
    3404   opts.ciphers = this.ciphers;
    3405   opts.rejectUnauthorized = this.rejectUnauthorized;
    3406 
    3407   this.ws = new WebSocket(uri, protocols, opts);
    3408 
    3409   if (this.ws.binaryType === undefined) {
    3410     this.supportsBinary = false;
    3411   }
    3412 
    3413   this.ws.binaryType = 'arraybuffer';
    3414   this.addEventListeners();
    3415 };
    3416 
    3417 /**
    3418  * Adds event listeners to the socket
    3419  *
    3420  * @api private
    3421  */
    3422 
    3423 WS.prototype.addEventListeners = function(){
    3424   var self = this;
    3425 
    3426   this.ws.onopen = function(){
    3427     self.onOpen();
    3428   };
    3429   this.ws.onclose = function(){
    3430     self.onClose();
    3431   };
    3432   this.ws.onmessage = function(ev){
    3433     self.onData(ev.data);
    3434   };
    3435   this.ws.onerror = function(e){
    3436     self.onError('websocket error', e);
    3437   };
    3438 };
    3439 
    3440 /**
    3441  * Override `onData` to use a timer on iOS.
    3442  * See: https://gist.github.com/mloughran/2052006
    3443  *
    3444  * @api private
    3445  */
    3446 
    3447 if ('undefined' != typeof navigator
    3448   && /iPad|iPhone|iPod/i.test(navigator.userAgent)) {
    3449   WS.prototype.onData = function(data){
    3450     var self = this;
    3451     setTimeout(function(){
    3452       Transport.prototype.onData.call(self, data);
    3453     }, 0);
    3454   };
    3455 }
    3456 
    3457 /**
    3458  * Writes data to socket.
    3459  *
    3460  * @param {Array} array of packets.
    3461  * @api private
    3462  */
    3463 
    3464 WS.prototype.write = function(packets){
    3465   var self = this;
    3466   this.writable = false;
    3467   // encodePacket efficient as it uses WS framing
    3468   // no need for encodePayload
    3469   for (var i = 0, l = packets.length; i < l; i++) {
    3470     parser.encodePacket(packets[i], this.supportsBinary, function(data) {
    3471       //Sometimes the websocket has already been closed but the browser didn't
    3472       //have a chance of informing us about it yet, in that case send will
    3473       //throw an error
    3474       try {
    3475         self.ws.send(data);
    3476       } catch (e){
    3477         debug('websocket closed before onclose event');
    3478       }
    3479     });
    3480   }
    3481 
    3482   function ondrain() {
    3483     self.writable = true;
    3484     self.emit('drain');
    3485   }
    3486   // fake drain
    3487   // defer to next tick to allow Socket to clear writeBuffer
    3488   setTimeout(ondrain, 0);
    3489 };
    3490 
    3491 /**
    3492  * Called upon close
    3493  *
    3494  * @api private
    3495  */
    3496 
    3497 WS.prototype.onClose = function(){
    3498   Transport.prototype.onClose.call(this);
    3499 };
    3500 
    3501 /**
    3502  * Closes socket.
    3503  *
    3504  * @api private
    3505  */
    3506 
    3507 WS.prototype.doClose = function(){
    3508   if (typeof this.ws !== 'undefined') {
    3509     this.ws.close();
    3510   }
    3511 };
    3512 
    3513 /**
    3514  * Generates uri for connection.
    3515  *
    3516  * @api private
    3517  */
    3518 
    3519 WS.prototype.uri = function(){
    3520   var query = this.query || {};
    3521   var schema = this.secure ? 'wss' : 'ws';
    3522   var port = '';
    3523 
    3524   // avoid port if default for schema
    3525   if (this.port && (('wss' == schema && this.port != 443)
    3526     || ('ws' == schema && this.port != 80))) {
    3527     port = ':' + this.port;
    3528   }
    3529 
    3530   // append timestamp to URI
    3531   if (this.timestampRequests) {
    3532     query[this.timestampParam] = +new Date;
    3533   }
    3534 
    3535   // communicate binary support capabilities
    3536   if (!this.supportsBinary) {
    3537     query.b64 = 1;
    3538   }
    3539 
    3540   query = parseqs.encode(query);
    3541 
    3542   // prepend ? to query
    3543   if (query.length) {
    3544     query = '?' + query;
    3545   }
    3546 
    3547   return schema + '://' + this.hostname + port + this.path + query;
    3548 };
    3549 
    3550 /**
    3551  * Feature detection for WebSocket.
    3552  *
    3553  * @return {Boolean} whether this transport is available.
    3554  * @api public
    3555  */
    3556 
    3557 WS.prototype.check = function(){
    3558   return !!WebSocket && !('__initialize' in WebSocket && this.name === WS.prototype.name);
    3559 };
    3560 
    3561 },{"../transport":14,"component-inherit":21,"debug":22,"engine.io-parser":25,"parseqs":33,"ws":35}],20:[function(_dereq_,module,exports){
    3562 // browser shim for xmlhttprequest module
    3563 var hasCORS = _dereq_('has-cors');
    3564 
    3565 module.exports = function(opts) {
    3566   var xdomain = opts.xdomain;
    3567 
    3568   // scheme must be same when usign XDomainRequest
    3569   // http://blogs.msdn.com/b/ieinternals/archive/2010/05/13/xdomainrequest-restrictions-limitations-and-workarounds.aspx
    3570   var xscheme = opts.xscheme;
    3571 
    3572   // XDomainRequest has a flow of not sending cookie, therefore it should be disabled as a default.
    3573   // https://github.com/Automattic/engine.io-client/pull/217
    3574   var enablesXDR = opts.enablesXDR;
    3575 
    3576   // XMLHttpRequest can be disabled on IE
    3577   try {
    3578     if ('undefined' != typeof XMLHttpRequest && (!xdomain || hasCORS)) {
    3579       return new XMLHttpRequest();
    3580     }
    3581   } catch (e) { }
    3582 
    3583   // Use XDomainRequest for IE8 if enablesXDR is true
    3584   // because loading bar keeps flashing when using jsonp-polling
    3585   // https://github.com/yujiosaka/socke.io-ie8-loading-example
    3586   try {
    3587     if ('undefined' != typeof XDomainRequest && !xscheme && enablesXDR) {
    3588       return new XDomainRequest();
    3589     }
    3590   } catch (e) { }
    3591 
    3592   if (!xdomain) {
    3593     try {
    3594       return new ActiveXObject('Microsoft.XMLHTTP');
    3595     } catch(e) { }
    3596   }
    3597 }
    3598 
    3599 },{"has-cors":38}],21:[function(_dereq_,module,exports){
    3600 
    3601 module.exports = function(a, b){
    3602   var fn = function(){};
    3603   fn.prototype = b.prototype;
    3604   a.prototype = new fn;
    3605   a.prototype.constructor = a;
    3606 };
    3607 },{}],22:[function(_dereq_,module,exports){
    3608 
    3609 /**
    3610  * This is the web browser implementation of `debug()`.
    3611  *
    3612  * Expose `debug()` as the module.
    3613  */
    3614 
    3615 exports = module.exports = _dereq_('./debug');
    3616 exports.log = log;
    3617 exports.formatArgs = formatArgs;
    3618 exports.save = save;
    3619 exports.load = load;
    3620 exports.useColors = useColors;
    3621 
    3622 /**
    3623  * Colors.
    3624  */
    3625 
    3626 exports.colors = [
    3627   'lightseagreen',
    3628   'forestgreen',
    3629   'goldenrod',
    3630   'dodgerblue',
    3631   'darkorchid',
    3632   'crimson'
    3633 ];
    3634 
    3635 /**
    3636  * Currently only WebKit-based Web Inspectors, Firefox >= v31,
    3637  * and the Firebug extension (any Firefox version) are known
    3638  * to support "%c" CSS customizations.
    3639  *
    3640  * TODO: add a `localStorage` variable to explicitly enable/disable colors
    3641  */
    3642 
    3643 function useColors() {
    3644   // is webkit? http://stackoverflow.com/a/16459606/376773
    3645   return ('WebkitAppearance' in document.documentElement.style) ||
    3646     // is firebug? http://stackoverflow.com/a/398120/376773
    3647     (window.console && (console.firebug || (console.exception && console.table))) ||
    3648     // is firefox >= v31?
    3649     // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages
    3650     (navigator.userAgent.toLowerCase().match(/firefox/(d+)/) && parseInt(RegExp.$1, 10) >= 31);
    3651 }
    3652 
    3653 /**
    3654  * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default.
    3655  */
    3656 
    3657 exports.formatters.j = function(v) {
    3658   return JSON.stringify(v);
    3659 };
    3660 
    3661 
    3662 /**
    3663  * Colorize log arguments if enabled.
    3664  *
    3665  * @api public
    3666  */
    3667 
    3668 function formatArgs() {
    3669   var args = arguments;
    3670   var useColors = this.useColors;
    3671 
    3672   args[0] = (useColors ? '%c' : '')
    3673     + this.namespace
    3674     + (useColors ? ' %c' : ' ')
    3675     + args[0]
    3676     + (useColors ? '%c ' : ' ')
    3677     + '+' + exports.humanize(this.diff);
    3678 
    3679   if (!useColors) return args;
    3680 
    3681   var c = 'color: ' + this.color;
    3682   args = [args[0], c, 'color: inherit'].concat(Array.prototype.slice.call(args, 1));
    3683 
    3684   // the final "%c" is somewhat tricky, because there could be other
    3685   // arguments passed either before or after the %c, so we need to
    3686   // figure out the correct index to insert the CSS into
    3687   var index = 0;
    3688   var lastC = 0;
    3689   args[0].replace(/%[a-z%]/g, function(match) {
    3690     if ('%%' === match) return;
    3691     index++;
    3692     if ('%c' === match) {
    3693       // we only are interested in the *last* %c
    3694       // (the user may have provided their own)
    3695       lastC = index;
    3696     }
    3697   });
    3698 
    3699   args.splice(lastC, 0, c);
    3700   return args;
    3701 }
    3702 
    3703 /**
    3704  * Invokes `console.log()` when available.
    3705  * No-op when `console.log` is not a "function".
    3706  *
    3707  * @api public
    3708  */
    3709 
    3710 function log() {
    3711   // This hackery is required for IE8,
    3712   // where the `console.log` function doesn't have 'apply'
    3713   return 'object' == typeof console
    3714     && 'function' == typeof console.log
    3715     && Function.prototype.apply.call(console.log, console, arguments);
    3716 }
    3717 
    3718 /**
    3719  * Save `namespaces`.
    3720  *
    3721  * @param {String} namespaces
    3722  * @api private
    3723  */
    3724 
    3725 function save(namespaces) {
    3726   try {
    3727     if (null == namespaces) {
    3728       localStorage.removeItem('debug');
    3729     } else {
    3730       localStorage.debug = namespaces;
    3731     }
    3732   } catch(e) {}
    3733 }
    3734 
    3735 /**
    3736  * Load `namespaces`.
    3737  *
    3738  * @return {String} returns the previously persisted debug modes
    3739  * @api private
    3740  */
    3741 
    3742 function load() {
    3743   var r;
    3744   try {
    3745     r = localStorage.debug;
    3746   } catch(e) {}
    3747   return r;
    3748 }
    3749 
    3750 /**
    3751  * Enable namespaces listed in `localStorage.debug` initially.
    3752  */
    3753 
    3754 exports.enable(load());
    3755 
    3756 },{"./debug":23}],23:[function(_dereq_,module,exports){
    3757 
    3758 /**
    3759  * This is the common logic for both the Node.js and web browser
    3760  * implementations of `debug()`.
    3761  *
    3762  * Expose `debug()` as the module.
    3763  */
    3764 
    3765 exports = module.exports = debug;
    3766 exports.coerce = coerce;
    3767 exports.disable = disable;
    3768 exports.enable = enable;
    3769 exports.enabled = enabled;
    3770 exports.humanize = _dereq_('ms');
    3771 
    3772 /**
    3773  * The currently active debug mode names, and names to skip.
    3774  */
    3775 
    3776 exports.names = [];
    3777 exports.skips = [];
    3778 
    3779 /**
    3780  * Map of special "%n" handling functions, for the debug "format" argument.
    3781  *
    3782  * Valid key names are a single, lowercased letter, i.e. "n".
    3783  */
    3784 
    3785 exports.formatters = {};
    3786 
    3787 /**
    3788  * Previously assigned color.
    3789  */
    3790 
    3791 var prevColor = 0;
    3792 
    3793 /**
    3794  * Previous log timestamp.
    3795  */
    3796 
    3797 var prevTime;
    3798 
    3799 /**
    3800  * Select a color.
    3801  *
    3802  * @return {Number}
    3803  * @api private
    3804  */
    3805 
    3806 function selectColor() {
    3807   return exports.colors[prevColor++ % exports.colors.length];
    3808 }
    3809 
    3810 /**
    3811  * Create a debugger with the given `namespace`.
    3812  *
    3813  * @param {String} namespace
    3814  * @return {Function}
    3815  * @api public
    3816  */
    3817 
    3818 function debug(namespace) {
    3819 
    3820   // define the `disabled` version
    3821   function disabled() {
    3822   }
    3823   disabled.enabled = false;
    3824 
    3825   // define the `enabled` version
    3826   function enabled() {
    3827 
    3828     var self = enabled;
    3829 
    3830     // set `diff` timestamp
    3831     var curr = +new Date();
    3832     var ms = curr - (prevTime || curr);
    3833     self.diff = ms;
    3834     self.prev = prevTime;
    3835     self.curr = curr;
    3836     prevTime = curr;
    3837 
    3838     // add the `color` if not set
    3839     if (null == self.useColors) self.useColors = exports.useColors();
    3840     if (null == self.color && self.useColors) self.color = selectColor();
    3841 
    3842     var args = Array.prototype.slice.call(arguments);
    3843 
    3844     args[0] = exports.coerce(args[0]);
    3845 
    3846     if ('string' !== typeof args[0]) {
    3847       // anything else let's inspect with %o
    3848       args = ['%o'].concat(args);
    3849     }
    3850 
    3851     // apply any `formatters` transformations
    3852     var index = 0;
    3853     args[0] = args[0].replace(/%([a-z%])/g, function(match, format) {
    3854       // if we encounter an escaped % then don't increase the array index
    3855       if (match === '%%') return match;
    3856       index++;
    3857       var formatter = exports.formatters[format];
    3858       if ('function' === typeof formatter) {
    3859         var val = args[index];
    3860         match = formatter.call(self, val);
    3861 
    3862         // now we need to remove `args[index]` since it's inlined in the `format`
    3863         args.splice(index, 1);
    3864         index--;
    3865       }
    3866       return match;
    3867     });
    3868 
    3869     if ('function' === typeof exports.formatArgs) {
    3870       args = exports.formatArgs.apply(self, args);
    3871     }
    3872     var logFn = enabled.log || exports.log || console.log.bind(console);
    3873     logFn.apply(self, args);
    3874   }
    3875   enabled.enabled = true;
    3876 
    3877   var fn = exports.enabled(namespace) ? enabled : disabled;
    3878 
    3879   fn.namespace = namespace;
    3880 
    3881   return fn;
    3882 }
    3883 
    3884 /**
    3885  * Enables a debug mode by namespaces. This can include modes
    3886  * separated by a colon and wildcards.
    3887  *
    3888  * @param {String} namespaces
    3889  * @api public
    3890  */
    3891 
    3892 function enable(namespaces) {
    3893   exports.save(namespaces);
    3894 
    3895   var split = (namespaces || '').split(/[s,]+/);
    3896   var len = split.length;
    3897 
    3898   for (var i = 0; i < len; i++) {
    3899     if (!split[i]) continue; // ignore empty strings
    3900     namespaces = split[i].replace(/*/g, '.*?');
    3901     if (namespaces[0] === '-') {
    3902       exports.skips.push(new RegExp('^' + namespaces.substr(1) + '$'));
    3903     } else {
    3904       exports.names.push(new RegExp('^' + namespaces + '$'));
    3905     }
    3906   }
    3907 }
    3908 
    3909 /**
    3910  * Disable debug output.
    3911  *
    3912  * @api public
    3913  */
    3914 
    3915 function disable() {
    3916   exports.enable('');
    3917 }
    3918 
    3919 /**
    3920  * Returns true if the given mode name is enabled, false otherwise.
    3921  *
    3922  * @param {String} name
    3923  * @return {Boolean}
    3924  * @api public
    3925  */
    3926 
    3927 function enabled(name) {
    3928   var i, len;
    3929   for (i = 0, len = exports.skips.length; i < len; i++) {
    3930     if (exports.skips[i].test(name)) {
    3931       return false;
    3932     }
    3933   }
    3934   for (i = 0, len = exports.names.length; i < len; i++) {
    3935     if (exports.names[i].test(name)) {
    3936       return true;
    3937     }
    3938   }
    3939   return false;
    3940 }
    3941 
    3942 /**
    3943  * Coerce `val`.
    3944  *
    3945  * @param {Mixed} val
    3946  * @return {Mixed}
    3947  * @api private
    3948  */
    3949 
    3950 function coerce(val) {
    3951   if (val instanceof Error) return val.stack || val.message;
    3952   return val;
    3953 }
    3954 
    3955 },{"ms":24}],24:[function(_dereq_,module,exports){
    3956 /**
    3957  * Helpers.
    3958  */
    3959 
    3960 var s = 1000;
    3961 var m = s * 60;
    3962 var h = m * 60;
    3963 var d = h * 24;
    3964 var y = d * 365.25;
    3965 
    3966 /**
    3967  * Parse or format the given `val`.
    3968  *
    3969  * Options:
    3970  *
    3971  *  - `long` verbose formatting [false]
    3972  *
    3973  * @param {String|Number} val
    3974  * @param {Object} options
    3975  * @return {String|Number}
    3976  * @api public
    3977  */
    3978 
    3979 module.exports = function(val, options){
    3980   options = options || {};
    3981   if ('string' == typeof val) return parse(val);
    3982   return options.long
    3983     ? long(val)
    3984     : short(val);
    3985 };
    3986 
    3987 /**
    3988  * Parse the given `str` and return milliseconds.
    3989  *
    3990  * @param {String} str
    3991  * @return {Number}
    3992  * @api private
    3993  */
    3994 
    3995 function parse(str) {
    3996   var match = /^((?:d+)?.?d+) *(ms|seconds?|s|minutes?|m|hours?|h|days?|d|years?|y)?$/i.exec(str);
    3997   if (!match) return;
    3998   var n = parseFloat(match[1]);
    3999   var type = (match[2] || 'ms').toLowerCase();
    4000   switch (type) {
    4001     case 'years':
    4002     case 'year':
    4003     case 'y':
    4004       return n * y;
    4005     case 'days':
    4006     case 'day':
    4007     case 'd':
    4008       return n * d;
    4009     case 'hours':
    4010     case 'hour':
    4011     case 'h':
    4012       return n * h;
    4013     case 'minutes':
    4014     case 'minute':
    4015     case 'm':
    4016       return n * m;
    4017     case 'seconds':
    4018     case 'second':
    4019     case 's':
    4020       return n * s;
    4021     case 'ms':
    4022       return n;
    4023   }
    4024 }
    4025 
    4026 /**
    4027  * Short format for `ms`.
    4028  *
    4029  * @param {Number} ms
    4030  * @return {String}
    4031  * @api private
    4032  */
    4033 
    4034 function short(ms) {
    4035   if (ms >= d) return Math.round(ms / d) + 'd';
    4036   if (ms >= h) return Math.round(ms / h) + 'h';
    4037   if (ms >= m) return Math.round(ms / m) + 'm';
    4038   if (ms >= s) return Math.round(ms / s) + 's';
    4039   return ms + 'ms';
    4040 }
    4041 
    4042 /**
    4043  * Long format for `ms`.
    4044  *
    4045  * @param {Number} ms
    4046  * @return {String}
    4047  * @api private
    4048  */
    4049 
    4050 function long(ms) {
    4051   return plural(ms, d, 'day')
    4052     || plural(ms, h, 'hour')
    4053     || plural(ms, m, 'minute')
    4054     || plural(ms, s, 'second')
    4055     || ms + ' ms';
    4056 }
    4057 
    4058 /**
    4059  * Pluralization helper.
    4060  */
    4061 
    4062 function plural(ms, n, name) {
    4063   if (ms < n) return;
    4064   if (ms < n * 1.5) return Math.floor(ms / n) + ' ' + name;
    4065   return Math.ceil(ms / n) + ' ' + name + 's';
    4066 }
    4067 
    4068 },{}],25:[function(_dereq_,module,exports){
    4069 (function (global){
    4070 /**
    4071  * Module dependencies.
    4072  */
    4073 
    4074 var keys = _dereq_('./keys');
    4075 var hasBinary = _dereq_('has-binary');
    4076 var sliceBuffer = _dereq_('arraybuffer.slice');
    4077 var base64encoder = _dereq_('base64-arraybuffer');
    4078 var after = _dereq_('after');
    4079 var utf8 = _dereq_('utf8');
    4080 
    4081 /**
    4082  * Check if we are running an android browser. That requires us to use
    4083  * ArrayBuffer with polling transports...
    4084  *
    4085  * http://ghinda.net/jpeg-blob-ajax-android/
    4086  */
    4087 
    4088 var isAndroid = navigator.userAgent.match(/Android/i);
    4089 
    4090 /**
    4091  * Check if we are running in PhantomJS.
    4092  * Uploading a Blob with PhantomJS does not work correctly, as reported here:
    4093  * https://github.com/ariya/phantomjs/issues/11395
    4094  * @type boolean
    4095  */
    4096 var isPhantomJS = /PhantomJS/i.test(navigator.userAgent);
    4097 
    4098 /**
    4099  * When true, avoids using Blobs to encode payloads.
    4100  * @type boolean
    4101  */
    4102 var dontSendBlobs = isAndroid || isPhantomJS;
    4103 
    4104 /**
    4105  * Current protocol version.
    4106  */
    4107 
    4108 exports.protocol = 3;
    4109 
    4110 /**
    4111  * Packet types.
    4112  */
    4113 
    4114 var packets = exports.packets = {
    4115     open:     0    // non-ws
    4116   , close:    1    // non-ws
    4117   , ping:     2
    4118   , pong:     3
    4119   , message:  4
    4120   , upgrade:  5
    4121   , noop:     6
    4122 };
    4123 
    4124 var packetslist = keys(packets);
    4125 
    4126 /**
    4127  * Premade error packet.
    4128  */
    4129 
    4130 var err = { type: 'error', data: 'parser error' };
    4131 
    4132 /**
    4133  * Create a blob api even for blob builder when vendor prefixes exist
    4134  */
    4135 
    4136 var Blob = _dereq_('blob');
    4137 
    4138 /**
    4139  * Encodes a packet.
    4140  *
    4141  *     <packet type id> [ <data> ]
    4142  *
    4143  * Example:
    4144  *
    4145  *     5hello world
    4146  *     3
    4147  *     4
    4148  *
    4149  * Binary is encoded in an identical principle
    4150  *
    4151  * @api private
    4152  */
    4153 
    4154 exports.encodePacket = function (packet, supportsBinary, utf8encode, callback) {
    4155   if ('function' == typeof supportsBinary) {
    4156     callback = supportsBinary;
    4157     supportsBinary = false;
    4158   }
    4159 
    4160   if ('function' == typeof utf8encode) {
    4161     callback = utf8encode;
    4162     utf8encode = null;
    4163   }
    4164 
    4165   var data = (packet.data === undefined)
    4166     ? undefined
    4167     : packet.data.buffer || packet.data;
    4168 
    4169   if (global.ArrayBuffer && data instanceof ArrayBuffer) {
    4170     return encodeArrayBuffer(packet, supportsBinary, callback);
    4171   } else if (Blob && data instanceof global.Blob) {
    4172     return encodeBlob(packet, supportsBinary, callback);
    4173   }
    4174 
    4175   // might be an object with { base64: true, data: dataAsBase64String }
    4176   if (data && data.base64) {
    4177     return encodeBase64Object(packet, callback);
    4178   }
    4179 
    4180   // Sending data as a utf-8 string
    4181   var encoded = packets[packet.type];
    4182 
    4183   // data fragment is optional
    4184   if (undefined !== packet.data) {
    4185     encoded += utf8encode ? utf8.encode(String(packet.data)) : String(packet.data);
    4186   }
    4187 
    4188   return callback('' + encoded);
    4189 
    4190 };
    4191 
    4192 function encodeBase64Object(packet, callback) {
    4193   // packet data is an object { base64: true, data: dataAsBase64String }
    4194   var message = 'b' + exports.packets[packet.type] + packet.data.data;
    4195   return callback(message);
    4196 }
    4197 
    4198 /**
    4199  * Encode packet helpers for binary types
    4200  */
    4201 
    4202 function encodeArrayBuffer(packet, supportsBinary, callback) {
    4203   if (!supportsBinary) {
    4204     return exports.encodeBase64Packet(packet, callback);
    4205   }
    4206 
    4207   var data = packet.data;
    4208   var contentArray = new Uint8Array(data);
    4209   var resultBuffer = new Uint8Array(1 + data.byteLength);
    4210 
    4211   resultBuffer[0] = packets[packet.type];
    4212   for (var i = 0; i < contentArray.length; i++) {
    4213     resultBuffer[i+1] = contentArray[i];
    4214   }
    4215 
    4216   return callback(resultBuffer.buffer);
    4217 }
    4218 
    4219 function encodeBlobAsArrayBuffer(packet, supportsBinary, callback) {
    4220   if (!supportsBinary) {
    4221     return exports.encodeBase64Packet(packet, callback);
    4222   }
    4223 
    4224   var fr = new FileReader();
    4225   fr.onload = function() {
    4226     packet.data = fr.result;
    4227     exports.encodePacket(packet, supportsBinary, true, callback);
    4228   };
    4229   return fr.readAsArrayBuffer(packet.data);
    4230 }
    4231 
    4232 function encodeBlob(packet, supportsBinary, callback) {
    4233   if (!supportsBinary) {
    4234     return exports.encodeBase64Packet(packet, callback);
    4235   }
    4236 
    4237   if (dontSendBlobs) {
    4238     return encodeBlobAsArrayBuffer(packet, supportsBinary, callback);
    4239   }
    4240 
    4241   var length = new Uint8Array(1);
    4242   length[0] = packets[packet.type];
    4243   var blob = new Blob([length.buffer, packet.data]);
    4244 
    4245   return callback(blob);
    4246 }
    4247 
    4248 /**
    4249  * Encodes a packet with binary data in a base64 string
    4250  *
    4251  * @param {Object} packet, has `type` and `data`
    4252  * @return {String} base64 encoded message
    4253  */
    4254 
    4255 exports.encodeBase64Packet = function(packet, callback) {
    4256   var message = 'b' + exports.packets[packet.type];
    4257   if (Blob && packet.data instanceof Blob) {
    4258     var fr = new FileReader();
    4259     fr.onload = function() {
    4260       var b64 = fr.result.split(',')[1];
    4261       callback(message + b64);
    4262     };
    4263     return fr.readAsDataURL(packet.data);
    4264   }
    4265 
    4266   var b64data;
    4267   try {
    4268     b64data = String.fromCharCode.apply(null, new Uint8Array(packet.data));
    4269   } catch (e) {
    4270     // iPhone Safari doesn't let you apply with typed arrays
    4271     var typed = new Uint8Array(packet.data);
    4272     var basic = new Array(typed.length);
    4273     for (var i = 0; i < typed.length; i++) {
    4274       basic[i] = typed[i];
    4275     }
    4276     b64data = String.fromCharCode.apply(null, basic);
    4277   }
    4278   message += global.btoa(b64data);
    4279   return callback(message);
    4280 };
    4281 
    4282 /**
    4283  * Decodes a packet. Changes format to Blob if requested.
    4284  *
    4285  * @return {Object} with `type` and `data` (if any)
    4286  * @api private
    4287  */
    4288 
    4289 exports.decodePacket = function (data, binaryType, utf8decode) {
    4290   // String data
    4291   if (typeof data == 'string' || data === undefined) {
    4292     if (data.charAt(0) == 'b') {
    4293       return exports.decodeBase64Packet(data.substr(1), binaryType);
    4294     }
    4295 
    4296     if (utf8decode) {
    4297       try {
    4298         data = utf8.decode(data);
    4299       } catch (e) {
    4300         return err;
    4301       }
    4302     }
    4303     var type = data.charAt(0);
    4304 
    4305     if (Number(type) != type || !packetslist[type]) {
    4306       return err;
    4307     }
    4308 
    4309     if (data.length > 1) {
    4310       return { type: packetslist[type], data: data.substring(1) };
    4311     } else {
    4312       return { type: packetslist[type] };
    4313     }
    4314   }
    4315 
    4316   var asArray = new Uint8Array(data);
    4317   var type = asArray[0];
    4318   var rest = sliceBuffer(data, 1);
    4319   if (Blob && binaryType === 'blob') {
    4320     rest = new Blob([rest]);
    4321   }
    4322   return { type: packetslist[type], data: rest };
    4323 };
    4324 
    4325 /**
    4326  * Decodes a packet encoded in a base64 string
    4327  *
    4328  * @param {String} base64 encoded message
    4329  * @return {Object} with `type` and `data` (if any)
    4330  */
    4331 
    4332 exports.decodeBase64Packet = function(msg, binaryType) {
    4333   var type = packetslist[msg.charAt(0)];
    4334   if (!global.ArrayBuffer) {
    4335     return { type: type, data: { base64: true, data: msg.substr(1) } };
    4336   }
    4337 
    4338   var data = base64encoder.decode(msg.substr(1));
    4339 
    4340   if (binaryType === 'blob' && Blob) {
    4341     data = new Blob([data]);
    4342   }
    4343 
    4344   return { type: type, data: data };
    4345 };
    4346 
    4347 /**
    4348  * Encodes multiple messages (payload).
    4349  *
    4350  *     <length>:data
    4351  *
    4352  * Example:
    4353  *
    4354  *     11:hello world2:hi
    4355  *
    4356  * If any contents are binary, they will be encoded as base64 strings. Base64
    4357  * encoded strings are marked with a b before the length specifier
    4358  *
    4359  * @param {Array} packets
    4360  * @api private
    4361  */
    4362 
    4363 exports.encodePayload = function (packets, supportsBinary, callback) {
    4364   if (typeof supportsBinary == 'function') {
    4365     callback = supportsBinary;
    4366     supportsBinary = null;
    4367   }
    4368 
    4369   var isBinary = hasBinary(packets);
    4370 
    4371   if (supportsBinary && isBinary) {
    4372     if (Blob && !dontSendBlobs) {
    4373       return exports.encodePayloadAsBlob(packets, callback);
    4374     }
    4375 
    4376     return exports.encodePayloadAsArrayBuffer(packets, callback);
    4377   }
    4378 
    4379   if (!packets.length) {
    4380     return callback('0:');
    4381   }
    4382 
    4383   function setLengthHeader(message) {
    4384     return message.length + ':' + message;
    4385   }
    4386 
    4387   function encodeOne(packet, doneCallback) {
    4388     exports.encodePacket(packet, !isBinary ? false : supportsBinary, true, function(message) {
    4389       doneCallback(null, setLengthHeader(message));
    4390     });
    4391   }
    4392 
    4393   map(packets, encodeOne, function(err, results) {
    4394     return callback(results.join(''));
    4395   });
    4396 };
    4397 
    4398 /**
    4399  * Async array map using after
    4400  */
    4401 
    4402 function map(ary, each, done) {
    4403   var result = new Array(ary.length);
    4404   var next = after(ary.length, done);
    4405 
    4406   var eachWithIndex = function(i, el, cb) {
    4407     each(el, function(error, msg) {
    4408       result[i] = msg;
    4409       cb(error, result);
    4410     });
    4411   };
    4412 
    4413   for (var i = 0; i < ary.length; i++) {
    4414     eachWithIndex(i, ary[i], next);
    4415   }
    4416 }
    4417 
    4418 /*
    4419  * Decodes data when a payload is maybe expected. Possible binary contents are
    4420  * decoded from their base64 representation
    4421  *
    4422  * @param {String} data, callback method
    4423  * @api public
    4424  */
    4425 
    4426 exports.decodePayload = function (data, binaryType, callback) {
    4427   if (typeof data != 'string') {
    4428     return exports.decodePayloadAsBinary(data, binaryType, callback);
    4429   }
    4430 
    4431   if (typeof binaryType === 'function') {
    4432     callback = binaryType;
    4433     binaryType = null;
    4434   }
    4435 
    4436   var packet;
    4437   if (data == '') {
    4438     // parser error - ignoring payload
    4439     return callback(err, 0, 1);
    4440   }
    4441 
    4442   var length = ''
    4443     , n, msg;
    4444 
    4445   for (var i = 0, l = data.length; i < l; i++) {
    4446     var chr = data.charAt(i);
    4447 
    4448     if (':' != chr) {
    4449       length += chr;
    4450     } else {
    4451       if ('' == length || (length != (n = Number(length)))) {
    4452         // parser error - ignoring payload
    4453         return callback(err, 0, 1);
    4454       }
    4455 
    4456       msg = data.substr(i + 1, n);
    4457 
    4458       if (length != msg.length) {
    4459         // parser error - ignoring payload
    4460         return callback(err, 0, 1);
    4461       }
    4462 
    4463       if (msg.length) {
    4464         packet = exports.decodePacket(msg, binaryType, true);
    4465 
    4466         if (err.type == packet.type && err.data == packet.data) {
    4467           // parser error in individual packet - ignoring payload
    4468           return callback(err, 0, 1);
    4469         }
    4470 
    4471         var ret = callback(packet, i + n, l);
    4472         if (false === ret) return;
    4473       }
    4474 
    4475       // advance cursor
    4476       i += n;
    4477       length = '';
    4478     }
    4479   }
    4480 
    4481   if (length != '') {
    4482     // parser error - ignoring payload
    4483     return callback(err, 0, 1);
    4484   }
    4485 
    4486 };
    4487 
    4488 /**
    4489  * Encodes multiple messages (payload) as binary.
    4490  *
    4491  * <1 = binary, 0 = string><number from 0-9><number from 0-9>[...]<number
    4492  * 255><data>
    4493  *
    4494  * Example:
    4495  * 1 3 255 1 2 3, if the binary contents are interpreted as 8 bit integers
    4496  *
    4497  * @param {Array} packets
    4498  * @return {ArrayBuffer} encoded payload
    4499  * @api private
    4500  */
    4501 
    4502 exports.encodePayloadAsArrayBuffer = function(packets, callback) {
    4503   if (!packets.length) {
    4504     return callback(new ArrayBuffer(0));
    4505   }
    4506 
    4507   function encodeOne(packet, doneCallback) {
    4508     exports.encodePacket(packet, true, true, function(data) {
    4509       return doneCallback(null, data);
    4510     });
    4511   }
    4512 
    4513   map(packets, encodeOne, function(err, encodedPackets) {
    4514     var totalLength = encodedPackets.reduce(function(acc, p) {
    4515       var len;
    4516       if (typeof p === 'string'){
    4517         len = p.length;
    4518       } else {
    4519         len = p.byteLength;
    4520       }
    4521       return acc + len.toString().length + len + 2; // string/binary identifier + separator = 2
    4522     }, 0);
    4523 
    4524     var resultArray = new Uint8Array(totalLength);
    4525 
    4526     var bufferIndex = 0;
    4527     encodedPackets.forEach(function(p) {
    4528       var isString = typeof p === 'string';
    4529       var ab = p;
    4530       if (isString) {
    4531         var view = new Uint8Array(p.length);
    4532         for (var i = 0; i < p.length; i++) {
    4533           view[i] = p.charCodeAt(i);
    4534         }
    4535         ab = view.buffer;
    4536       }
    4537 
    4538       if (isString) { // not true binary
    4539         resultArray[bufferIndex++] = 0;
    4540       } else { // true binary
    4541         resultArray[bufferIndex++] = 1;
    4542       }
    4543 
    4544       var lenStr = ab.byteLength.toString();
    4545       for (var i = 0; i < lenStr.length; i++) {
    4546         resultArray[bufferIndex++] = parseInt(lenStr[i]);
    4547       }
    4548       resultArray[bufferIndex++] = 255;
    4549 
    4550       var view = new Uint8Array(ab);
    4551       for (var i = 0; i < view.length; i++) {
    4552         resultArray[bufferIndex++] = view[i];
    4553       }
    4554     });
    4555 
    4556     return callback(resultArray.buffer);
    4557   });
    4558 };
    4559 
    4560 /**
    4561  * Encode as Blob
    4562  */
    4563 
    4564 exports.encodePayloadAsBlob = function(packets, callback) {
    4565   function encodeOne(packet, doneCallback) {
    4566     exports.encodePacket(packet, true, true, function(encoded) {
    4567       var binaryIdentifier = new Uint8Array(1);
    4568       binaryIdentifier[0] = 1;
    4569       if (typeof encoded === 'string') {
    4570         var view = new Uint8Array(encoded.length);
    4571         for (var i = 0; i < encoded.length; i++) {
    4572           view[i] = encoded.charCodeAt(i);
    4573         }
    4574         encoded = view.buffer;
    4575         binaryIdentifier[0] = 0;
    4576       }
    4577 
    4578       var len = (encoded instanceof ArrayBuffer)
    4579         ? encoded.byteLength
    4580         : encoded.size;
    4581 
    4582       var lenStr = len.toString();
    4583       var lengthAry = new Uint8Array(lenStr.length + 1);
    4584       for (var i = 0; i < lenStr.length; i++) {
    4585         lengthAry[i] = parseInt(lenStr[i]);
    4586       }
    4587       lengthAry[lenStr.length] = 255;
    4588 
    4589       if (Blob) {
    4590         var blob = new Blob([binaryIdentifier.buffer, lengthAry.buffer, encoded]);
    4591         doneCallback(null, blob);
    4592       }
    4593     });
    4594   }
    4595 
    4596   map(packets, encodeOne, function(err, results) {
    4597     return callback(new Blob(results));
    4598   });
    4599 };
    4600 
    4601 /*
    4602  * Decodes data when a payload is maybe expected. Strings are decoded by
    4603  * interpreting each byte as a key code for entries marked to start with 0. See
    4604  * description of encodePayloadAsBinary
    4605  *
    4606  * @param {ArrayBuffer} data, callback method
    4607  * @api public
    4608  */
    4609 
    4610 exports.decodePayloadAsBinary = function (data, binaryType, callback) {
    4611   if (typeof binaryType === 'function') {
    4612     callback = binaryType;
    4613     binaryType = null;
    4614   }
    4615 
    4616   var bufferTail = data;
    4617   var buffers = [];
    4618 
    4619   var numberTooLong = false;
    4620   while (bufferTail.byteLength > 0) {
    4621     var tailArray = new Uint8Array(bufferTail);
    4622     var isString = tailArray[0] === 0;
    4623     var msgLength = '';
    4624 
    4625     for (var i = 1; ; i++) {
    4626       if (tailArray[i] == 255) break;
    4627 
    4628       if (msgLength.length > 310) {
    4629         numberTooLong = true;
    4630         break;
    4631       }
    4632 
    4633       msgLength += tailArray[i];
    4634     }
    4635 
    4636     if(numberTooLong) return callback(err, 0, 1);
    4637 
    4638     bufferTail = sliceBuffer(bufferTail, 2 + msgLength.length);
    4639     msgLength = parseInt(msgLength);
    4640 
    4641     var msg = sliceBuffer(bufferTail, 0, msgLength);
    4642     if (isString) {
    4643       try {
    4644         msg = String.fromCharCode.apply(null, new Uint8Array(msg));
    4645       } catch (e) {
    4646         // iPhone Safari doesn't let you apply to typed arrays
    4647         var typed = new Uint8Array(msg);
    4648         msg = '';
    4649         for (var i = 0; i < typed.length; i++) {
    4650           msg += String.fromCharCode(typed[i]);
    4651         }
    4652       }
    4653     }
    4654 
    4655     buffers.push(msg);
    4656     bufferTail = sliceBuffer(bufferTail, msgLength);
    4657   }
    4658 
    4659   var total = buffers.length;
    4660   buffers.forEach(function(buffer, i) {
    4661     callback(exports.decodePacket(buffer, binaryType, true), i, total);
    4662   });
    4663 };
    4664 
    4665 }).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
    4666 },{"./keys":26,"after":27,"arraybuffer.slice":28,"base64-arraybuffer":29,"blob":30,"has-binary":36,"utf8":31}],26:[function(_dereq_,module,exports){
    4667 
    4668 /**
    4669  * Gets the keys for an object.
    4670  *
    4671  * @return {Array} keys
    4672  * @api private
    4673  */
    4674 
    4675 module.exports = Object.keys || function keys (obj){
    4676   var arr = [];
    4677   var has = Object.prototype.hasOwnProperty;
    4678 
    4679   for (var i in obj) {
    4680     if (has.call(obj, i)) {
    4681       arr.push(i);
    4682     }
    4683   }
    4684   return arr;
    4685 };
    4686 
    4687 },{}],27:[function(_dereq_,module,exports){
    4688 module.exports = after
    4689 
    4690 function after(count, callback, err_cb) {
    4691     var bail = false
    4692     err_cb = err_cb || noop
    4693     proxy.count = count
    4694 
    4695     return (count === 0) ? callback() : proxy
    4696 
    4697     function proxy(err, result) {
    4698         if (proxy.count <= 0) {
    4699             throw new Error('after called too many times')
    4700         }
    4701         --proxy.count
    4702 
    4703         // after first error, rest are passed to err_cb
    4704         if (err) {
    4705             bail = true
    4706             callback(err)
    4707             // future error callbacks will go to error handler
    4708             callback = err_cb
    4709         } else if (proxy.count === 0 && !bail) {
    4710             callback(null, result)
    4711         }
    4712     }
    4713 }
    4714 
    4715 function noop() {}
    4716 
    4717 },{}],28:[function(_dereq_,module,exports){
    4718 /**
    4719  * An abstraction for slicing an arraybuffer even when
    4720  * ArrayBuffer.prototype.slice is not supported
    4721  *
    4722  * @api public
    4723  */
    4724 
    4725 module.exports = function(arraybuffer, start, end) {
    4726   var bytes = arraybuffer.byteLength;
    4727   start = start || 0;
    4728   end = end || bytes;
    4729 
    4730   if (arraybuffer.slice) { return arraybuffer.slice(start, end); }
    4731 
    4732   if (start < 0) { start += bytes; }
    4733   if (end < 0) { end += bytes; }
    4734   if (end > bytes) { end = bytes; }
    4735 
    4736   if (start >= bytes || start >= end || bytes === 0) {
    4737     return new ArrayBuffer(0);
    4738   }
    4739 
    4740   var abv = new Uint8Array(arraybuffer);
    4741   var result = new Uint8Array(end - start);
    4742   for (var i = start, ii = 0; i < end; i++, ii++) {
    4743     result[ii] = abv[i];
    4744   }
    4745   return result.buffer;
    4746 };
    4747 
    4748 },{}],29:[function(_dereq_,module,exports){
    4749 /*
    4750  * base64-arraybuffer
    4751  * https://github.com/niklasvh/base64-arraybuffer
    4752  *
    4753  * Copyright (c) 2012 Niklas von Hertzen
    4754  * Licensed under the MIT license.
    4755  */
    4756 (function(chars){
    4757   "use strict";
    4758 
    4759   exports.encode = function(arraybuffer) {
    4760     var bytes = new Uint8Array(arraybuffer),
    4761     i, len = bytes.length, base64 = "";
    4762 
    4763     for (i = 0; i < len; i+=3) {
    4764       base64 += chars[bytes[i] >> 2];
    4765       base64 += chars[((bytes[i] & 3) << 4) | (bytes[i + 1] >> 4)];
    4766       base64 += chars[((bytes[i + 1] & 15) << 2) | (bytes[i + 2] >> 6)];
    4767       base64 += chars[bytes[i + 2] & 63];
    4768     }
    4769 
    4770     if ((len % 3) === 2) {
    4771       base64 = base64.substring(0, base64.length - 1) + "=";
    4772     } else if (len % 3 === 1) {
    4773       base64 = base64.substring(0, base64.length - 2) + "==";
    4774     }
    4775 
    4776     return base64;
    4777   };
    4778 
    4779   exports.decode =  function(base64) {
    4780     var bufferLength = base64.length * 0.75,
    4781     len = base64.length, i, p = 0,
    4782     encoded1, encoded2, encoded3, encoded4;
    4783 
    4784     if (base64[base64.length - 1] === "=") {
    4785       bufferLength--;
    4786       if (base64[base64.length - 2] === "=") {
    4787         bufferLength--;
    4788       }
    4789     }
    4790 
    4791     var arraybuffer = new ArrayBuffer(bufferLength),
    4792     bytes = new Uint8Array(arraybuffer);
    4793 
    4794     for (i = 0; i < len; i+=4) {
    4795       encoded1 = chars.indexOf(base64[i]);
    4796       encoded2 = chars.indexOf(base64[i+1]);
    4797       encoded3 = chars.indexOf(base64[i+2]);
    4798       encoded4 = chars.indexOf(base64[i+3]);
    4799 
    4800       bytes[p++] = (encoded1 << 2) | (encoded2 >> 4);
    4801       bytes[p++] = ((encoded2 & 15) << 4) | (encoded3 >> 2);
    4802       bytes[p++] = ((encoded3 & 3) << 6) | (encoded4 & 63);
    4803     }
    4804 
    4805     return arraybuffer;
    4806   };
    4807 })("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/");
    4808 
    4809 },{}],30:[function(_dereq_,module,exports){
    4810 (function (global){
    4811 /**
    4812  * Create a blob builder even when vendor prefixes exist
    4813  */
    4814 
    4815 var BlobBuilder = global.BlobBuilder
    4816   || global.WebKitBlobBuilder
    4817   || global.MSBlobBuilder
    4818   || global.MozBlobBuilder;
    4819 
    4820 /**
    4821  * Check if Blob constructor is supported
    4822  */
    4823 
    4824 var blobSupported = (function() {
    4825   try {
    4826     var a = new Blob(['hi']);
    4827     return a.size === 2;
    4828   } catch(e) {
    4829     return false;
    4830   }
    4831 })();
    4832 
    4833 /**
    4834  * Check if Blob constructor supports ArrayBufferViews
    4835  * Fails in Safari 6, so we need to map to ArrayBuffers there.
    4836  */
    4837 
    4838 var blobSupportsArrayBufferView = blobSupported && (function() {
    4839   try {
    4840     var b = new Blob([new Uint8Array([1,2])]);
    4841     return b.size === 2;
    4842   } catch(e) {
    4843     return false;
    4844   }
    4845 })();
    4846 
    4847 /**
    4848  * Check if BlobBuilder is supported
    4849  */
    4850 
    4851 var blobBuilderSupported = BlobBuilder
    4852   && BlobBuilder.prototype.append
    4853   && BlobBuilder.prototype.getBlob;
    4854 
    4855 /**
    4856  * Helper function that maps ArrayBufferViews to ArrayBuffers
    4857  * Used by BlobBuilder constructor and old browsers that didn't
    4858  * support it in the Blob constructor.
    4859  */
    4860 
    4861 function mapArrayBufferViews(ary) {
    4862   for (var i = 0; i < ary.length; i++) {
    4863     var chunk = ary[i];
    4864     if (chunk.buffer instanceof ArrayBuffer) {
    4865       var buf = chunk.buffer;
    4866 
    4867       // if this is a subarray, make a copy so we only
    4868       // include the subarray region from the underlying buffer
    4869       if (chunk.byteLength !== buf.byteLength) {
    4870         var copy = new Uint8Array(chunk.byteLength);
    4871         copy.set(new Uint8Array(buf, chunk.byteOffset, chunk.byteLength));
    4872         buf = copy.buffer;
    4873       }
    4874 
    4875       ary[i] = buf;
    4876     }
    4877   }
    4878 }
    4879 
    4880 function BlobBuilderConstructor(ary, options) {
    4881   options = options || {};
    4882 
    4883   var bb = new BlobBuilder();
    4884   mapArrayBufferViews(ary);
    4885 
    4886   for (var i = 0; i < ary.length; i++) {
    4887     bb.append(ary[i]);
    4888   }
    4889 
    4890   return (options.type) ? bb.getBlob(options.type) : bb.getBlob();
    4891 };
    4892 
    4893 function BlobConstructor(ary, options) {
    4894   mapArrayBufferViews(ary);
    4895   return new Blob(ary, options || {});
    4896 };
    4897 
    4898 module.exports = (function() {
    4899   if (blobSupported) {
    4900     return blobSupportsArrayBufferView ? global.Blob : BlobConstructor;
    4901   } else if (blobBuilderSupported) {
    4902     return BlobBuilderConstructor;
    4903   } else {
    4904     return undefined;
    4905   }
    4906 })();
    4907 
    4908 }).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
    4909 },{}],31:[function(_dereq_,module,exports){
    4910 (function (global){
    4911 /*! https://mths.be/utf8js v2.0.0 by @mathias */
    4912 ;(function(root) {
    4913 
    4914  // Detect free variables `exports`
    4915  var freeExports = typeof exports == 'object' && exports;
    4916 
    4917  // Detect free variable `module`
    4918  var freeModule = typeof module == 'object' && module &&
    4919   module.exports == freeExports && module;
    4920 
    4921  // Detect free variable `global`, from Node.js or Browserified code,
    4922  // and use it as `root`
    4923  var freeGlobal = typeof global == 'object' && global;
    4924  if (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal) {
    4925   root = freeGlobal;
    4926  }
    4927 
    4928  /*--------------------------------------------------------------------------*/
    4929 
    4930  var stringFromCharCode = String.fromCharCode;
    4931 
    4932  // Taken from https://mths.be/punycode
    4933  function ucs2decode(string) {
    4934   var output = [];
    4935   var counter = 0;
    4936   var length = string.length;
    4937   var value;
    4938   var extra;
    4939   while (counter < length) {
    4940    value = string.charCodeAt(counter++);
    4941    if (value >= 0xD800 && value <= 0xDBFF && counter < length) {
    4942     // high surrogate, and there is a next character
    4943     extra = string.charCodeAt(counter++);
    4944     if ((extra & 0xFC00) == 0xDC00) { // low surrogate
    4945      output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000);
    4946     } else {
    4947      // unmatched surrogate; only append this code unit, in case the next
    4948      // code unit is the high surrogate of a surrogate pair
    4949      output.push(value);
    4950      counter--;
    4951     }
    4952    } else {
    4953     output.push(value);
    4954    }
    4955   }
    4956   return output;
    4957  }
    4958 
    4959  // Taken from https://mths.be/punycode
    4960  function ucs2encode(array) {
    4961   var length = array.length;
    4962   var index = -1;
    4963   var value;
    4964   var output = '';
    4965   while (++index < length) {
    4966    value = array[index];
    4967    if (value > 0xFFFF) {
    4968     value -= 0x10000;
    4969     output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800);
    4970     value = 0xDC00 | value & 0x3FF;
    4971    }
    4972    output += stringFromCharCode(value);
    4973   }
    4974   return output;
    4975  }
    4976 
    4977  function checkScalarValue(codePoint) {
    4978   if (codePoint >= 0xD800 && codePoint <= 0xDFFF) {
    4979    throw Error(
    4980     'Lone surrogate U+' + codePoint.toString(16).toUpperCase() +
    4981     ' is not a scalar value'
    4982    );
    4983   }
    4984  }
    4985  /*--------------------------------------------------------------------------*/
    4986 
    4987  function createByte(codePoint, shift) {
    4988   return stringFromCharCode(((codePoint >> shift) & 0x3F) | 0x80);
    4989  }
    4990 
    4991  function encodeCodePoint(codePoint) {
    4992   if ((codePoint & 0xFFFFFF80) == 0) { // 1-byte sequence
    4993    return stringFromCharCode(codePoint);
    4994   }
    4995   var symbol = '';
    4996   if ((codePoint & 0xFFFFF800) == 0) { // 2-byte sequence
    4997    symbol = stringFromCharCode(((codePoint >> 6) & 0x1F) | 0xC0);
    4998   }
    4999   else if ((codePoint & 0xFFFF0000) == 0) { // 3-byte sequence
    5000    checkScalarValue(codePoint);
    5001    symbol = stringFromCharCode(((codePoint >> 12) & 0x0F) | 0xE0);
    5002    symbol += createByte(codePoint, 6);
    5003   }
    5004   else if ((codePoint & 0xFFE00000) == 0) { // 4-byte sequence
    5005    symbol = stringFromCharCode(((codePoint >> 18) & 0x07) | 0xF0);
    5006    symbol += createByte(codePoint, 12);
    5007    symbol += createByte(codePoint, 6);
    5008   }
    5009   symbol += stringFromCharCode((codePoint & 0x3F) | 0x80);
    5010   return symbol;
    5011  }
    5012 
    5013  function utf8encode(string) {
    5014   var codePoints = ucs2decode(string);
    5015   var length = codePoints.length;
    5016   var index = -1;
    5017   var codePoint;
    5018   var byteString = '';
    5019   while (++index < length) {
    5020    codePoint = codePoints[index];
    5021    byteString += encodeCodePoint(codePoint);
    5022   }
    5023   return byteString;
    5024  }
    5025 
    5026  /*--------------------------------------------------------------------------*/
    5027 
    5028  function readContinuationByte() {
    5029   if (byteIndex >= byteCount) {
    5030    throw Error('Invalid byte index');
    5031   }
    5032 
    5033   var continuationByte = byteArray[byteIndex] & 0xFF;
    5034   byteIndex++;
    5035 
    5036   if ((continuationByte & 0xC0) == 0x80) {
    5037    return continuationByte & 0x3F;
    5038   }
    5039 
    5040   // If we end up here, it’s not a continuation byte
    5041   throw Error('Invalid continuation byte');
    5042  }
    5043 
    5044  function decodeSymbol() {
    5045   var byte1;
    5046   var byte2;
    5047   var byte3;
    5048   var byte4;
    5049   var codePoint;
    5050 
    5051   if (byteIndex > byteCount) {
    5052    throw Error('Invalid byte index');
    5053   }
    5054 
    5055   if (byteIndex == byteCount) {
    5056    return false;
    5057   }
    5058 
    5059   // Read first byte
    5060   byte1 = byteArray[byteIndex] & 0xFF;
    5061   byteIndex++;
    5062 
    5063   // 1-byte sequence (no continuation bytes)
    5064   if ((byte1 & 0x80) == 0) {
    5065    return byte1;
    5066   }
    5067 
    5068   // 2-byte sequence
    5069   if ((byte1 & 0xE0) == 0xC0) {
    5070    var byte2 = readContinuationByte();
    5071    codePoint = ((byte1 & 0x1F) << 6) | byte2;
    5072    if (codePoint >= 0x80) {
    5073     return codePoint;
    5074    } else {
    5075     throw Error('Invalid continuation byte');
    5076    }
    5077   }
    5078 
    5079   // 3-byte sequence (may include unpaired surrogates)
    5080   if ((byte1 & 0xF0) == 0xE0) {
    5081    byte2 = readContinuationByte();
    5082    byte3 = readContinuationByte();
    5083    codePoint = ((byte1 & 0x0F) << 12) | (byte2 << 6) | byte3;
    5084    if (codePoint >= 0x0800) {
    5085     checkScalarValue(codePoint);
    5086     return codePoint;
    5087    } else {
    5088     throw Error('Invalid continuation byte');
    5089    }
    5090   }
    5091 
    5092   // 4-byte sequence
    5093   if ((byte1 & 0xF8) == 0xF0) {
    5094    byte2 = readContinuationByte();
    5095    byte3 = readContinuationByte();
    5096    byte4 = readContinuationByte();
    5097    codePoint = ((byte1 & 0x0F) << 0x12) | (byte2 << 0x0C) |
    5098     (byte3 << 0x06) | byte4;
    5099    if (codePoint >= 0x010000 && codePoint <= 0x10FFFF) {
    5100     return codePoint;
    5101    }
    5102   }
    5103 
    5104   throw Error('Invalid UTF-8 detected');
    5105  }
    5106 
    5107  var byteArray;
    5108  var byteCount;
    5109  var byteIndex;
    5110  function utf8decode(byteString) {
    5111   byteArray = ucs2decode(byteString);
    5112   byteCount = byteArray.length;
    5113   byteIndex = 0;
    5114   var codePoints = [];
    5115   var tmp;
    5116   while ((tmp = decodeSymbol()) !== false) {
    5117    codePoints.push(tmp);
    5118   }
    5119   return ucs2encode(codePoints);
    5120  }
    5121 
    5122  /*--------------------------------------------------------------------------*/
    5123 
    5124  var utf8 = {
    5125   'version': '2.0.0',
    5126   'encode': utf8encode,
    5127   'decode': utf8decode
    5128  };
    5129 
    5130  // Some AMD build optimizers, like r.js, check for specific condition patterns
    5131  // like the following:
    5132  if (
    5133   typeof define == 'function' &&
    5134   typeof define.amd == 'object' &&
    5135   define.amd
    5136  ) {
    5137   define(function() {
    5138    return utf8;
    5139   });
    5140  }  else if (freeExports && !freeExports.nodeType) {
    5141   if (freeModule) { // in Node.js or RingoJS v0.8.0+
    5142    freeModule.exports = utf8;
    5143   } else { // in Narwhal or RingoJS v0.7.0-
    5144    var object = {};
    5145    var hasOwnProperty = object.hasOwnProperty;
    5146    for (var key in utf8) {
    5147     hasOwnProperty.call(utf8, key) && (freeExports[key] = utf8[key]);
    5148    }
    5149   }
    5150  } else { // in Rhino or a web browser
    5151   root.utf8 = utf8;
    5152  }
    5153 
    5154 }(this));
    5155 
    5156 }).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
    5157 },{}],32:[function(_dereq_,module,exports){
    5158 (function (global){
    5159 /**
    5160  * JSON parse.
    5161  *
    5162  * @see Based on jQuery#parseJSON (MIT) and JSON2
    5163  * @api private
    5164  */
    5165 
    5166 var rvalidchars = /^[],:{}s]*$/;
    5167 var rvalidescape = /\(?:["\/bfnrt]|u[0-9a-fA-F]{4})/g;
    5168 var rvalidtokens = /"[^"\
    
    ]*"|true|false|null|-?d+(?:.d*)?(?:[eE][+-]?d+)?/g;
    5169 var rvalidbraces = /(?:^|:|,)(?:s*[)+/g;
    5170 var rtrimLeft = /^s+/;
    5171 var rtrimRight = /s+$/;
    5172 
    5173 module.exports = function parsejson(data) {
    5174   if ('string' != typeof data || !data) {
    5175     return null;
    5176   }
    5177 
    5178   data = data.replace(rtrimLeft, '').replace(rtrimRight, '');
    5179 
    5180   // Attempt to parse using the native JSON parser first
    5181   if (global.JSON && JSON.parse) {
    5182     return JSON.parse(data);
    5183   }
    5184 
    5185   if (rvalidchars.test(data.replace(rvalidescape, '@')
    5186       .replace(rvalidtokens, ']')
    5187       .replace(rvalidbraces, ''))) {
    5188     return (new Function('return ' + data))();
    5189   }
    5190 };
    5191 }).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
    5192 },{}],33:[function(_dereq_,module,exports){
    5193 /**
    5194  * Compiles a querystring
    5195  * Returns string representation of the object
    5196  *
    5197  * @param {Object}
    5198  * @api private
    5199  */
    5200 
    5201 exports.encode = function (obj) {
    5202   var str = '';
    5203 
    5204   for (var i in obj) {
    5205     if (obj.hasOwnProperty(i)) {
    5206       if (str.length) str += '&';
    5207       str += encodeURIComponent(i) + '=' + encodeURIComponent(obj[i]);
    5208     }
    5209   }
    5210 
    5211   return str;
    5212 };
    5213 
    5214 /**
    5215  * Parses a simple querystring into an object
    5216  *
    5217  * @param {String} qs
    5218  * @api private
    5219  */
    5220 
    5221 exports.decode = function(qs){
    5222   var qry = {};
    5223   var pairs = qs.split('&');
    5224   for (var i = 0, l = pairs.length; i < l; i++) {
    5225     var pair = pairs[i].split('=');
    5226     qry[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1]);
    5227   }
    5228   return qry;
    5229 };
    5230 
    5231 },{}],34:[function(_dereq_,module,exports){
    5232 /**
    5233  * Parses an URI
    5234  *
    5235  * @author Steven Levithan <stevenlevithan.com> (MIT license)
    5236  * @api private
    5237  */
    5238 
    5239 var re = /^(?:(?![^:@]+:[^:@/]*@)(http|https|ws|wss)://)?((?:(([^:@]*)(?::([^:@]*))?)?@)?((?:[a-f0-9]{0,4}:){2,7}[a-f0-9]{0,4}|[^:/?#]*)(?::(d*))?)(((/(?:[^?#](?![^?#/]*.[^?#/.]+(?:[?#]|$)))*/?)?([^?#/]*))(?:?([^#]*))?(?:#(.*))?)/;
    5240 
    5241 var parts = [
    5242     'source', 'protocol', 'authority', 'userInfo', 'user', 'password', 'host', 'port', 'relative', 'path', 'directory', 'file', 'query', 'anchor'
    5243 ];
    5244 
    5245 module.exports = function parseuri(str) {
    5246     var src = str,
    5247         b = str.indexOf('['),
    5248         e = str.indexOf(']');
    5249 
    5250     if (b != -1 && e != -1) {
    5251         str = str.substring(0, b) + str.substring(b, e).replace(/:/g, ';') + str.substring(e, str.length);
    5252     }
    5253 
    5254     var m = re.exec(str || ''),
    5255         uri = {},
    5256         i = 14;
    5257 
    5258     while (i--) {
    5259         uri[parts[i]] = m[i] || '';
    5260     }
    5261 
    5262     if (b != -1 && e != -1) {
    5263         uri.source = src;
    5264         uri.host = uri.host.substring(1, uri.host.length - 1).replace(/;/g, ':');
    5265         uri.authority = uri.authority.replace('[', '').replace(']', '').replace(/;/g, ':');
    5266         uri.ipv6uri = true;
    5267     }
    5268 
    5269     return uri;
    5270 };
    5271 
    5272 },{}],35:[function(_dereq_,module,exports){
    5273 
    5274 /**
    5275  * Module dependencies.
    5276  */
    5277 
    5278 var global = (function() { return this; })();
    5279 
    5280 /**
    5281  * WebSocket constructor.
    5282  */
    5283 
    5284 var WebSocket = global.WebSocket || global.MozWebSocket;
    5285 
    5286 /**
    5287  * Module exports.
    5288  */
    5289 
    5290 module.exports = WebSocket ? ws : null;
    5291 
    5292 /**
    5293  * WebSocket constructor.
    5294  *
    5295  * The third `opts` options object gets ignored in web browsers, since it's
    5296  * non-standard, and throws a TypeError if passed to the constructor.
    5297  * See: https://github.com/einaros/ws/issues/227
    5298  *
    5299  * @param {String} uri
    5300  * @param {Array} protocols (optional)
    5301  * @param {Object) opts (optional)
    5302  * @api public
    5303  */
    5304 
    5305 function ws(uri, protocols, opts) {
    5306   var instance;
    5307   if (protocols) {
    5308     instance = new WebSocket(uri, protocols);
    5309   } else {
    5310     instance = new WebSocket(uri);
    5311   }
    5312   return instance;
    5313 }
    5314 
    5315 if (WebSocket) ws.prototype = WebSocket.prototype;
    5316 
    5317 },{}],36:[function(_dereq_,module,exports){
    5318 (function (global){
    5319 
    5320 /*
    5321  * Module requirements.
    5322  */
    5323 
    5324 var isArray = _dereq_('isarray');
    5325 
    5326 /**
    5327  * Module exports.
    5328  */
    5329 
    5330 module.exports = hasBinary;
    5331 
    5332 /**
    5333  * Checks for binary data.
    5334  *
    5335  * Right now only Buffer and ArrayBuffer are supported..
    5336  *
    5337  * @param {Object} anything
    5338  * @api public
    5339  */
    5340 
    5341 function hasBinary(data) {
    5342 
    5343   function _hasBinary(obj) {
    5344     if (!obj) return false;
    5345 
    5346     if ( (global.Buffer && global.Buffer.isBuffer(obj)) ||
    5347          (global.ArrayBuffer && obj instanceof ArrayBuffer) ||
    5348          (global.Blob && obj instanceof Blob) ||
    5349          (global.File && obj instanceof File)
    5350         ) {
    5351       return true;
    5352     }
    5353 
    5354     if (isArray(obj)) {
    5355       for (var i = 0; i < obj.length; i++) {
    5356           if (_hasBinary(obj[i])) {
    5357               return true;
    5358           }
    5359       }
    5360     } else if (obj && 'object' == typeof obj) {
    5361       if (obj.toJSON) {
    5362         obj = obj.toJSON();
    5363       }
    5364 
    5365       for (var key in obj) {
    5366         if (Object.prototype.hasOwnProperty.call(obj, key) && _hasBinary(obj[key])) {
    5367           return true;
    5368         }
    5369       }
    5370     }
    5371 
    5372     return false;
    5373   }
    5374 
    5375   return _hasBinary(data);
    5376 }
    5377 
    5378 }).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
    5379 },{"isarray":37}],37:[function(_dereq_,module,exports){
    5380 module.exports = Array.isArray || function (arr) {
    5381   return Object.prototype.toString.call(arr) == '[object Array]';
    5382 };
    5383 
    5384 },{}],38:[function(_dereq_,module,exports){
    5385 
    5386 /**
    5387  * Module dependencies.
    5388  */
    5389 
    5390 var global = _dereq_('global');
    5391 
    5392 /**
    5393  * Module exports.
    5394  *
    5395  * Logic borrowed from Modernizr:
    5396  *
    5397  *   - https://github.com/Modernizr/Modernizr/blob/master/feature-detects/cors.js
    5398  */
    5399 
    5400 try {
    5401   module.exports = 'XMLHttpRequest' in global &&
    5402     'withCredentials' in new global.XMLHttpRequest();
    5403 } catch (err) {
    5404   // if XMLHttp support is disabled in IE then it will throw
    5405   // when trying to create
    5406   module.exports = false;
    5407 }
    5408 
    5409 },{"global":39}],39:[function(_dereq_,module,exports){
    5410 
    5411 /**
    5412  * Returns `this`. Execute this without a "context" (i.e. without it being
    5413  * attached to an object of the left-hand side), and `this` points to the
    5414  * "global" scope of the current JS execution.
    5415  */
    5416 
    5417 module.exports = (function () { return this; })();
    5418 
    5419 },{}],40:[function(_dereq_,module,exports){
    5420 
    5421 var indexOf = [].indexOf;
    5422 
    5423 module.exports = function(arr, obj){
    5424   if (indexOf) return arr.indexOf(obj);
    5425   for (var i = 0; i < arr.length; ++i) {
    5426     if (arr[i] === obj) return i;
    5427   }
    5428   return -1;
    5429 };
    5430 },{}],41:[function(_dereq_,module,exports){
    5431 
    5432 /**
    5433  * HOP ref.
    5434  */
    5435 
    5436 var has = Object.prototype.hasOwnProperty;
    5437 
    5438 /**
    5439  * Return own keys in `obj`.
    5440  *
    5441  * @param {Object} obj
    5442  * @return {Array}
    5443  * @api public
    5444  */
    5445 
    5446 exports.keys = Object.keys || function(obj){
    5447   var keys = [];
    5448   for (var key in obj) {
    5449     if (has.call(obj, key)) {
    5450       keys.push(key);
    5451     }
    5452   }
    5453   return keys;
    5454 };
    5455 
    5456 /**
    5457  * Return own values in `obj`.
    5458  *
    5459  * @param {Object} obj
    5460  * @return {Array}
    5461  * @api public
    5462  */
    5463 
    5464 exports.values = function(obj){
    5465   var vals = [];
    5466   for (var key in obj) {
    5467     if (has.call(obj, key)) {
    5468       vals.push(obj[key]);
    5469     }
    5470   }
    5471   return vals;
    5472 };
    5473 
    5474 /**
    5475  * Merge `b` into `a`.
    5476  *
    5477  * @param {Object} a
    5478  * @param {Object} b
    5479  * @return {Object} a
    5480  * @api public
    5481  */
    5482 
    5483 exports.merge = function(a, b){
    5484   for (var key in b) {
    5485     if (has.call(b, key)) {
    5486       a[key] = b[key];
    5487     }
    5488   }
    5489   return a;
    5490 };
    5491 
    5492 /**
    5493  * Return length of `obj`.
    5494  *
    5495  * @param {Object} obj
    5496  * @return {Number}
    5497  * @api public
    5498  */
    5499 
    5500 exports.length = function(obj){
    5501   return exports.keys(obj).length;
    5502 };
    5503 
    5504 /**
    5505  * Check if `obj` is empty.
    5506  *
    5507  * @param {Object} obj
    5508  * @return {Boolean}
    5509  * @api public
    5510  */
    5511 
    5512 exports.isEmpty = function(obj){
    5513   return 0 == exports.length(obj);
    5514 };
    5515 },{}],42:[function(_dereq_,module,exports){
    5516 /**
    5517  * Parses an URI
    5518  *
    5519  * @author Steven Levithan <stevenlevithan.com> (MIT license)
    5520  * @api private
    5521  */
    5522 
    5523 var re = /^(?:(?![^:@]+:[^:@/]*@)(http|https|ws|wss)://)?((?:(([^:@]*)(?::([^:@]*))?)?@)?((?:[a-f0-9]{0,4}:){2,7}[a-f0-9]{0,4}|[^:/?#]*)(?::(d*))?)(((/(?:[^?#](?![^?#/]*.[^?#/.]+(?:[?#]|$)))*/?)?([^?#/]*))(?:?([^#]*))?(?:#(.*))?)/;
    5524 
    5525 var parts = [
    5526     'source', 'protocol', 'authority', 'userInfo', 'user', 'password', 'host'
    5527   , 'port', 'relative', 'path', 'directory', 'file', 'query', 'anchor'
    5528 ];
    5529 
    5530 module.exports = function parseuri(str) {
    5531   var m = re.exec(str || '')
    5532     , uri = {}
    5533     , i = 14;
    5534 
    5535   while (i--) {
    5536     uri[parts[i]] = m[i] || '';
    5537   }
    5538 
    5539   return uri;
    5540 };
    5541 
    5542 },{}],43:[function(_dereq_,module,exports){
    5543 (function (global){
    5544 /*global Blob,File*/
    5545 
    5546 /**
    5547  * Module requirements
    5548  */
    5549 
    5550 var isArray = _dereq_('isarray');
    5551 var isBuf = _dereq_('./is-buffer');
    5552 
    5553 /**
    5554  * Replaces every Buffer | ArrayBuffer in packet with a numbered placeholder.
    5555  * Anything with blobs or files should be fed through removeBlobs before coming
    5556  * here.
    5557  *
    5558  * @param {Object} packet - socket.io event packet
    5559  * @return {Object} with deconstructed packet and list of buffers
    5560  * @api public
    5561  */
    5562 
    5563 exports.deconstructPacket = function(packet){
    5564   var buffers = [];
    5565   var packetData = packet.data;
    5566 
    5567   function _deconstructPacket(data) {
    5568     if (!data) return data;
    5569 
    5570     if (isBuf(data)) {
    5571       var placeholder = { _placeholder: true, num: buffers.length };
    5572       buffers.push(data);
    5573       return placeholder;
    5574     } else if (isArray(data)) {
    5575       var newData = new Array(data.length);
    5576       for (var i = 0; i < data.length; i++) {
    5577         newData[i] = _deconstructPacket(data[i]);
    5578       }
    5579       return newData;
    5580     } else if ('object' == typeof data && !(data instanceof Date)) {
    5581       var newData = {};
    5582       for (var key in data) {
    5583         newData[key] = _deconstructPacket(data[key]);
    5584       }
    5585       return newData;
    5586     }
    5587     return data;
    5588   }
    5589 
    5590   var pack = packet;
    5591   pack.data = _deconstructPacket(packetData);
    5592   pack.attachments = buffers.length; // number of binary 'attachments'
    5593   return {packet: pack, buffers: buffers};
    5594 };
    5595 
    5596 /**
    5597  * Reconstructs a binary packet from its placeholder packet and buffers
    5598  *
    5599  * @param {Object} packet - event packet with placeholders
    5600  * @param {Array} buffers - binary buffers to put in placeholder positions
    5601  * @return {Object} reconstructed packet
    5602  * @api public
    5603  */
    5604 
    5605 exports.reconstructPacket = function(packet, buffers) {
    5606   var curPlaceHolder = 0;
    5607 
    5608   function _reconstructPacket(data) {
    5609     if (data && data._placeholder) {
    5610       var buf = buffers[data.num]; // appropriate buffer (should be natural order anyway)
    5611       return buf;
    5612     } else if (isArray(data)) {
    5613       for (var i = 0; i < data.length; i++) {
    5614         data[i] = _reconstructPacket(data[i]);
    5615       }
    5616       return data;
    5617     } else if (data && 'object' == typeof data) {
    5618       for (var key in data) {
    5619         data[key] = _reconstructPacket(data[key]);
    5620       }
    5621       return data;
    5622     }
    5623     return data;
    5624   }
    5625 
    5626   packet.data = _reconstructPacket(packet.data);
    5627   packet.attachments = undefined; // no longer useful
    5628   return packet;
    5629 };
    5630 
    5631 /**
    5632  * Asynchronously removes Blobs or Files from data via
    5633  * FileReader's readAsArrayBuffer method. Used before encoding
    5634  * data as msgpack. Calls callback with the blobless data.
    5635  *
    5636  * @param {Object} data
    5637  * @param {Function} callback
    5638  * @api private
    5639  */
    5640 
    5641 exports.removeBlobs = function(data, callback) {
    5642   function _removeBlobs(obj, curKey, containingObject) {
    5643     if (!obj) return obj;
    5644 
    5645     // convert any blob
    5646     if ((global.Blob && obj instanceof Blob) ||
    5647         (global.File && obj instanceof File)) {
    5648       pendingBlobs++;
    5649 
    5650       // async filereader
    5651       var fileReader = new FileReader();
    5652       fileReader.onload = function() { // this.result == arraybuffer
    5653         if (containingObject) {
    5654           containingObject[curKey] = this.result;
    5655         }
    5656         else {
    5657           bloblessData = this.result;
    5658         }
    5659 
    5660         // if nothing pending its callback time
    5661         if(! --pendingBlobs) {
    5662           callback(bloblessData);
    5663         }
    5664       };
    5665 
    5666       fileReader.readAsArrayBuffer(obj); // blob -> arraybuffer
    5667     } else if (isArray(obj)) { // handle array
    5668       for (var i = 0; i < obj.length; i++) {
    5669         _removeBlobs(obj[i], i, obj);
    5670       }
    5671     } else if (obj && 'object' == typeof obj && !isBuf(obj)) { // and object
    5672       for (var key in obj) {
    5673         _removeBlobs(obj[key], key, obj);
    5674       }
    5675     }
    5676   }
    5677 
    5678   var pendingBlobs = 0;
    5679   var bloblessData = data;
    5680   _removeBlobs(bloblessData);
    5681   if (!pendingBlobs) {
    5682     callback(bloblessData);
    5683   }
    5684 };
    5685 
    5686 }).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
    5687 },{"./is-buffer":45,"isarray":46}],44:[function(_dereq_,module,exports){
    5688 
    5689 /**
    5690  * Module dependencies.
    5691  */
    5692 
    5693 var debug = _dereq_('debug')('socket.io-parser');
    5694 var json = _dereq_('json3');
    5695 var isArray = _dereq_('isarray');
    5696 var Emitter = _dereq_('component-emitter');
    5697 var binary = _dereq_('./binary');
    5698 var isBuf = _dereq_('./is-buffer');
    5699 
    5700 /**
    5701  * Protocol version.
    5702  *
    5703  * @api public
    5704  */
    5705 
    5706 exports.protocol = 4;
    5707 
    5708 /**
    5709  * Packet types.
    5710  *
    5711  * @api public
    5712  */
    5713 
    5714 exports.types = [
    5715   'CONNECT',
    5716   'DISCONNECT',
    5717   'EVENT',
    5718   'BINARY_EVENT',
    5719   'ACK',
    5720   'BINARY_ACK',
    5721   'ERROR'
    5722 ];
    5723 
    5724 /**
    5725  * Packet type `connect`.
    5726  *
    5727  * @api public
    5728  */
    5729 
    5730 exports.CONNECT = 0;
    5731 
    5732 /**
    5733  * Packet type `disconnect`.
    5734  *
    5735  * @api public
    5736  */
    5737 
    5738 exports.DISCONNECT = 1;
    5739 
    5740 /**
    5741  * Packet type `event`.
    5742  *
    5743  * @api public
    5744  */
    5745 
    5746 exports.EVENT = 2;
    5747 
    5748 /**
    5749  * Packet type `ack`.
    5750  *
    5751  * @api public
    5752  */
    5753 
    5754 exports.ACK = 3;
    5755 
    5756 /**
    5757  * Packet type `error`.
    5758  *
    5759  * @api public
    5760  */
    5761 
    5762 exports.ERROR = 4;
    5763 
    5764 /**
    5765  * Packet type 'binary event'
    5766  *
    5767  * @api public
    5768  */
    5769 
    5770 exports.BINARY_EVENT = 5;
    5771 
    5772 /**
    5773  * Packet type `binary ack`. For acks with binary arguments.
    5774  *
    5775  * @api public
    5776  */
    5777 
    5778 exports.BINARY_ACK = 6;
    5779 
    5780 /**
    5781  * Encoder constructor.
    5782  *
    5783  * @api public
    5784  */
    5785 
    5786 exports.Encoder = Encoder;
    5787 
    5788 /**
    5789  * Decoder constructor.
    5790  *
    5791  * @api public
    5792  */
    5793 
    5794 exports.Decoder = Decoder;
    5795 
    5796 /**
    5797  * A socket.io Encoder instance
    5798  *
    5799  * @api public
    5800  */
    5801 
    5802 function Encoder() {}
    5803 
    5804 /**
    5805  * Encode a packet as a single string if non-binary, or as a
    5806  * buffer sequence, depending on packet type.
    5807  *
    5808  * @param {Object} obj - packet object
    5809  * @param {Function} callback - function to handle encodings (likely engine.write)
    5810  * @return Calls callback with Array of encodings
    5811  * @api public
    5812  */
    5813 
    5814 Encoder.prototype.encode = function(obj, callback){
    5815   debug('encoding packet %j', obj);
    5816 
    5817   if (exports.BINARY_EVENT == obj.type || exports.BINARY_ACK == obj.type) {
    5818     encodeAsBinary(obj, callback);
    5819   }
    5820   else {
    5821     var encoding = encodeAsString(obj);
    5822     callback([encoding]);
    5823   }
    5824 };
    5825 
    5826 /**
    5827  * Encode packet as string.
    5828  *
    5829  * @param {Object} packet
    5830  * @return {String} encoded
    5831  * @api private
    5832  */
    5833 
    5834 function encodeAsString(obj) {
    5835   var str = '';
    5836   var nsp = false;
    5837 
    5838   // first is type
    5839   str += obj.type;
    5840 
    5841   // attachments if we have them
    5842   if (exports.BINARY_EVENT == obj.type || exports.BINARY_ACK == obj.type) {
    5843     str += obj.attachments;
    5844     str += '-';
    5845   }
    5846 
    5847   // if we have a namespace other than `/`
    5848   // we append it followed by a comma `,`
    5849   if (obj.nsp && '/' != obj.nsp) {
    5850     nsp = true;
    5851     str += obj.nsp;
    5852   }
    5853 
    5854   // immediately followed by the id
    5855   if (null != obj.id) {
    5856     if (nsp) {
    5857       str += ',';
    5858       nsp = false;
    5859     }
    5860     str += obj.id;
    5861   }
    5862 
    5863   // json data
    5864   if (null != obj.data) {
    5865     if (nsp) str += ',';
    5866     str += json.stringify(obj.data);
    5867   }
    5868 
    5869   debug('encoded %j as %s', obj, str);
    5870   return str;
    5871 }
    5872 
    5873 /**
    5874  * Encode packet as 'buffer sequence' by removing blobs, and
    5875  * deconstructing packet into object with placeholders and
    5876  * a list of buffers.
    5877  *
    5878  * @param {Object} packet
    5879  * @return {Buffer} encoded
    5880  * @api private
    5881  */
    5882 
    5883 function encodeAsBinary(obj, callback) {
    5884 
    5885   function writeEncoding(bloblessData) {
    5886     var deconstruction = binary.deconstructPacket(bloblessData);
    5887     var pack = encodeAsString(deconstruction.packet);
    5888     var buffers = deconstruction.buffers;
    5889 
    5890     buffers.unshift(pack); // add packet info to beginning of data list
    5891     callback(buffers); // write all the buffers
    5892   }
    5893 
    5894   binary.removeBlobs(obj, writeEncoding);
    5895 }
    5896 
    5897 /**
    5898  * A socket.io Decoder instance
    5899  *
    5900  * @return {Object} decoder
    5901  * @api public
    5902  */
    5903 
    5904 function Decoder() {
    5905   this.reconstructor = null;
    5906 }
    5907 
    5908 /**
    5909  * Mix in `Emitter` with Decoder.
    5910  */
    5911 
    5912 Emitter(Decoder.prototype);
    5913 
    5914 /**
    5915  * Decodes an ecoded packet string into packet JSON.
    5916  *
    5917  * @param {String} obj - encoded packet
    5918  * @return {Object} packet
    5919  * @api public
    5920  */
    5921 
    5922 Decoder.prototype.add = function(obj) {
    5923   var packet;
    5924   if ('string' == typeof obj) {
    5925     packet = decodeString(obj);
    5926     if (exports.BINARY_EVENT == packet.type || exports.BINARY_ACK == packet.type) { // binary packet's json
    5927       this.reconstructor = new BinaryReconstructor(packet);
    5928 
    5929       // no attachments, labeled binary but no binary data to follow
    5930       if (this.reconstructor.reconPack.attachments === 0) {
    5931         this.emit('decoded', packet);
    5932       }
    5933     } else { // non-binary full packet
    5934       this.emit('decoded', packet);
    5935     }
    5936   }
    5937   else if (isBuf(obj) || obj.base64) { // raw binary data
    5938     if (!this.reconstructor) {
    5939       throw new Error('got binary data when not reconstructing a packet');
    5940     } else {
    5941       packet = this.reconstructor.takeBinaryData(obj);
    5942       if (packet) { // received final buffer
    5943         this.reconstructor = null;
    5944         this.emit('decoded', packet);
    5945       }
    5946     }
    5947   }
    5948   else {
    5949     throw new Error('Unknown type: ' + obj);
    5950   }
    5951 };
    5952 
    5953 /**
    5954  * Decode a packet String (JSON data)
    5955  *
    5956  * @param {String} str
    5957  * @return {Object} packet
    5958  * @api private
    5959  */
    5960 
    5961 function decodeString(str) {
    5962   var p = {};
    5963   var i = 0;
    5964 
    5965   // look up type
    5966   p.type = Number(str.charAt(0));
    5967   if (null == exports.types[p.type]) return error();
    5968 
    5969   // look up attachments if type binary
    5970   if (exports.BINARY_EVENT == p.type || exports.BINARY_ACK == p.type) {
    5971     var buf = '';
    5972     while (str.charAt(++i) != '-') {
    5973       buf += str.charAt(i);
    5974       if (i == str.length) break;
    5975     }
    5976     if (buf != Number(buf) || str.charAt(i) != '-') {
    5977       throw new Error('Illegal attachments');
    5978     }
    5979     p.attachments = Number(buf);
    5980   }
    5981 
    5982   // look up namespace (if any)
    5983   if ('/' == str.charAt(i + 1)) {
    5984     p.nsp = '';
    5985     while (++i) {
    5986       var c = str.charAt(i);
    5987       if (',' == c) break;
    5988       p.nsp += c;
    5989       if (i == str.length) break;
    5990     }
    5991   } else {
    5992     p.nsp = '/';
    5993   }
    5994 
    5995   // look up id
    5996   var next = str.charAt(i + 1);
    5997   if ('' !== next && Number(next) == next) {
    5998     p.id = '';
    5999     while (++i) {
    6000       var c = str.charAt(i);
    6001       if (null == c || Number(c) != c) {
    6002         --i;
    6003         break;
    6004       }
    6005       p.id += str.charAt(i);
    6006       if (i == str.length) break;
    6007     }
    6008     p.id = Number(p.id);
    6009   }
    6010 
    6011   // look up json data
    6012   if (str.charAt(++i)) {
    6013     try {
    6014       p.data = json.parse(str.substr(i));
    6015     } catch(e){
    6016       return error();
    6017     }
    6018   }
    6019 
    6020   debug('decoded %s as %j', str, p);
    6021   return p;
    6022 }
    6023 
    6024 /**
    6025  * Deallocates a parser's resources
    6026  *
    6027  * @api public
    6028  */
    6029 
    6030 Decoder.prototype.destroy = function() {
    6031   if (this.reconstructor) {
    6032     this.reconstructor.finishedReconstruction();
    6033   }
    6034 };
    6035 
    6036 /**
    6037  * A manager of a binary event's 'buffer sequence'. Should
    6038  * be constructed whenever a packet of type BINARY_EVENT is
    6039  * decoded.
    6040  *
    6041  * @param {Object} packet
    6042  * @return {BinaryReconstructor} initialized reconstructor
    6043  * @api private
    6044  */
    6045 
    6046 function BinaryReconstructor(packet) {
    6047   this.reconPack = packet;
    6048   this.buffers = [];
    6049 }
    6050 
    6051 /**
    6052  * Method to be called when binary data received from connection
    6053  * after a BINARY_EVENT packet.
    6054  *
    6055  * @param {Buffer | ArrayBuffer} binData - the raw binary data received
    6056  * @return {null | Object} returns null if more binary data is expected or
    6057  *   a reconstructed packet object if all buffers have been received.
    6058  * @api private
    6059  */
    6060 
    6061 BinaryReconstructor.prototype.takeBinaryData = function(binData) {
    6062   this.buffers.push(binData);
    6063   if (this.buffers.length == this.reconPack.attachments) { // done with buffer list
    6064     var packet = binary.reconstructPacket(this.reconPack, this.buffers);
    6065     this.finishedReconstruction();
    6066     return packet;
    6067   }
    6068   return null;
    6069 };
    6070 
    6071 /**
    6072  * Cleans up binary packet reconstruction variables.
    6073  *
    6074  * @api private
    6075  */
    6076 
    6077 BinaryReconstructor.prototype.finishedReconstruction = function() {
    6078   this.reconPack = null;
    6079   this.buffers = [];
    6080 };
    6081 
    6082 function error(data){
    6083   return {
    6084     type: exports.ERROR,
    6085     data: 'parser error'
    6086   };
    6087 }
    6088 
    6089 },{"./binary":43,"./is-buffer":45,"component-emitter":9,"debug":10,"isarray":46,"json3":47}],45:[function(_dereq_,module,exports){
    6090 (function (global){
    6091 
    6092 module.exports = isBuf;
    6093 
    6094 /**
    6095  * Returns true if obj is a buffer or an arraybuffer.
    6096  *
    6097  * @api private
    6098  */
    6099 
    6100 function isBuf(obj) {
    6101   return (global.Buffer && global.Buffer.isBuffer(obj)) ||
    6102          (global.ArrayBuffer && obj instanceof ArrayBuffer);
    6103 }
    6104 
    6105 }).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
    6106 },{}],46:[function(_dereq_,module,exports){
    6107 module.exports=_dereq_(37)
    6108 },{}],47:[function(_dereq_,module,exports){
    6109 /*! JSON v3.2.6 | http://bestiejs.github.io/json3 | Copyright 2012-2013, Kit Cambridge | http://kit.mit-license.org */
    6110 ;(function (window) {
    6111   // Convenience aliases.
    6112   var getClass = {}.toString, isProperty, forEach, undef;
    6113 
    6114   // Detect the `define` function exposed by asynchronous module loaders. The
    6115   // strict `define` check is necessary for compatibility with `r.js`.
    6116   var isLoader = typeof define === "function" && define.amd;
    6117 
    6118   // Detect native implementations.
    6119   var nativeJSON = typeof JSON == "object" && JSON;
    6120 
    6121   // Set up the JSON 3 namespace, preferring the CommonJS `exports` object if
    6122   // available.
    6123   var JSON3 = typeof exports == "object" && exports && !exports.nodeType && exports;
    6124 
    6125   if (JSON3 && nativeJSON) {
    6126     // Explicitly delegate to the native `stringify` and `parse`
    6127     // implementations in CommonJS environments.
    6128     JSON3.stringify = nativeJSON.stringify;
    6129     JSON3.parse = nativeJSON.parse;
    6130   } else {
    6131     // Export for web browsers, JavaScript engines, and asynchronous module
    6132     // loaders, using the global `JSON` object if available.
    6133     JSON3 = window.JSON = nativeJSON || {};
    6134   }
    6135 
    6136   // Test the `Date#getUTC*` methods. Based on work by @Yaffle.
    6137   var isExtended = new Date(-3509827334573292);
    6138   try {
    6139     // The `getUTCFullYear`, `Month`, and `Date` methods return nonsensical
    6140     // results for certain dates in Opera >= 10.53.
    6141     isExtended = isExtended.getUTCFullYear() == -109252 && isExtended.getUTCMonth() === 0 && isExtended.getUTCDate() === 1 &&
    6142       // Safari < 2.0.2 stores the internal millisecond time value correctly,
    6143       // but clips the values returned by the date methods to the range of
    6144       // signed 32-bit integers ([-2 ** 31, 2 ** 31 - 1]).
    6145       isExtended.getUTCHours() == 10 && isExtended.getUTCMinutes() == 37 && isExtended.getUTCSeconds() == 6 && isExtended.getUTCMilliseconds() == 708;
    6146   } catch (exception) {}
    6147 
    6148   // Internal: Determines whether the native `JSON.stringify` and `parse`
    6149   // implementations are spec-compliant. Based on work by Ken Snyder.
    6150   function has(name) {
    6151     if (has[name] !== undef) {
    6152       // Return cached feature test result.
    6153       return has[name];
    6154     }
    6155 
    6156     var isSupported;
    6157     if (name == "bug-string-char-index") {
    6158       // IE <= 7 doesn't support accessing string characters using square
    6159       // bracket notation. IE 8 only supports this for primitives.
    6160       isSupported = "a"[0] != "a";
    6161     } else if (name == "json") {
    6162       // Indicates whether both `JSON.stringify` and `JSON.parse` are
    6163       // supported.
    6164       isSupported = has("json-stringify") && has("json-parse");
    6165     } else {
    6166       var value, serialized = '{"a":[1,true,false,null,"\u0000\b\n\f\r\t"]}';
    6167       // Test `JSON.stringify`.
    6168       if (name == "json-stringify") {
    6169         var stringify = JSON3.stringify, stringifySupported = typeof stringify == "function" && isExtended;
    6170         if (stringifySupported) {
    6171           // A test function object with a custom `toJSON` method.
    6172           (value = function () {
    6173             return 1;
    6174           }).toJSON = value;
    6175           try {
    6176             stringifySupported =
    6177               // Firefox 3.1b1 and b2 serialize string, number, and boolean
    6178               // primitives as object literals.
    6179               stringify(0) === "0" &&
    6180               // FF 3.1b1, b2, and JSON 2 serialize wrapped primitives as object
    6181               // literals.
    6182               stringify(new Number()) === "0" &&
    6183               stringify(new String()) == '""' &&
    6184               // FF 3.1b1, 2 throw an error if the value is `null`, `undefined`, or
    6185               // does not define a canonical JSON representation (this applies to
    6186               // objects with `toJSON` properties as well, *unless* they are nested
    6187               // within an object or array).
    6188               stringify(getClass) === undef &&
    6189               // IE 8 serializes `undefined` as `"undefined"`. Safari <= 5.1.7 and
    6190               // FF 3.1b3 pass this test.
    6191               stringify(undef) === undef &&
    6192               // Safari <= 5.1.7 and FF 3.1b3 throw `Error`s and `TypeError`s,
    6193               // respectively, if the value is omitted entirely.
    6194               stringify() === undef &&
    6195               // FF 3.1b1, 2 throw an error if the given value is not a number,
    6196               // string, array, object, Boolean, or `null` literal. This applies to
    6197               // objects with custom `toJSON` methods as well, unless they are nested
    6198               // inside object or array literals. YUI 3.0.0b1 ignores custom `toJSON`
    6199               // methods entirely.
    6200               stringify(value) === "1" &&
    6201               stringify([value]) == "[1]" &&
    6202               // Prototype <= 1.6.1 serializes `[undefined]` as `"[]"` instead of
    6203               // `"[null]"`.
    6204               stringify([undef]) == "[null]" &&
    6205               // YUI 3.0.0b1 fails to serialize `null` literals.
    6206               stringify(null) == "null" &&
    6207               // FF 3.1b1, 2 halts serialization if an array contains a function:
    6208               // `[1, true, getClass, 1]` serializes as "[1,true,],". FF 3.1b3
    6209               // elides non-JSON values from objects and arrays, unless they
    6210               // define custom `toJSON` methods.
    6211               stringify([undef, getClass, null]) == "[null,null,null]" &&
    6212               // Simple serialization test. FF 3.1b1 uses Unicode escape sequences
    6213               // where character escape codes are expected (e.g., `` => `u0008`).
    6214               stringify({ "a": [value, true, false, null, "x00
    f
    	"] }) == serialized &&
    6215               // FF 3.1b1 and b2 ignore the `filter` and `width` arguments.
    6216               stringify(null, value) === "1" &&
    6217               stringify([1, 2], null, 1) == "[
     1,
     2
    ]" &&
    6218               // JSON 2, Prototype <= 1.7, and older WebKit builds incorrectly
    6219               // serialize extended years.
    6220               stringify(new Date(-8.64e15)) == '"-271821-04-20T00:00:00.000Z"' &&
    6221               // The milliseconds are optional in ES 5, but required in 5.1.
    6222               stringify(new Date(8.64e15)) == '"+275760-09-13T00:00:00.000Z"' &&
    6223               // Firefox <= 11.0 incorrectly serializes years prior to 0 as negative
    6224               // four-digit years instead of six-digit years. Credits: @Yaffle.
    6225               stringify(new Date(-621987552e5)) == '"-000001-01-01T00:00:00.000Z"' &&
    6226               // Safari <= 5.1.5 and Opera >= 10.53 incorrectly serialize millisecond
    6227               // values less than 1000. Credits: @Yaffle.
    6228               stringify(new Date(-1)) == '"1969-12-31T23:59:59.999Z"';
    6229           } catch (exception) {
    6230             stringifySupported = false;
    6231           }
    6232         }
    6233         isSupported = stringifySupported;
    6234       }
    6235       // Test `JSON.parse`.
    6236       if (name == "json-parse") {
    6237         var parse = JSON3.parse;
    6238         if (typeof parse == "function") {
    6239           try {
    6240             // FF 3.1b1, b2 will throw an exception if a bare literal is provided.
    6241             // Conforming implementations should also coerce the initial argument to
    6242             // a string prior to parsing.
    6243             if (parse("0") === 0 && !parse(false)) {
    6244               // Simple parsing test.
    6245               value = parse(serialized);
    6246               var parseSupported = value["a"].length == 5 && value["a"][0] === 1;
    6247               if (parseSupported) {
    6248                 try {
    6249                   // Safari <= 5.1.2 and FF 3.1b1 allow unescaped tabs in strings.
    6250                   parseSupported = !parse('"	"');
    6251                 } catch (exception) {}
    6252                 if (parseSupported) {
    6253                   try {
    6254                     // FF 4.0 and 4.0.1 allow leading `+` signs and leading
    6255                     // decimal points. FF 4.0, 4.0.1, and IE 9-10 also allow
    6256                     // certain octal literals.
    6257                     parseSupported = parse("01") !== 1;
    6258                   } catch (exception) {}
    6259                 }
    6260                 if (parseSupported) {
    6261                   try {
    6262                     // FF 4.0, 4.0.1, and Rhino 1.7R3-R4 allow trailing decimal
    6263                     // points. These environments, along with FF 3.1b1 and 2,
    6264                     // also allow trailing commas in JSON objects and arrays.
    6265                     parseSupported = parse("1.") !== 1;
    6266                   } catch (exception) {}
    6267                 }
    6268               }
    6269             }
    6270           } catch (exception) {
    6271             parseSupported = false;
    6272           }
    6273         }
    6274         isSupported = parseSupported;
    6275       }
    6276     }
    6277     return has[name] = !!isSupported;
    6278   }
    6279 
    6280   if (!has("json")) {
    6281     // Common `[[Class]]` name aliases.
    6282     var functionClass = "[object Function]";
    6283     var dateClass = "[object Date]";
    6284     var numberClass = "[object Number]";
    6285     var stringClass = "[object String]";
    6286     var arrayClass = "[object Array]";
    6287     var booleanClass = "[object Boolean]";
    6288 
    6289     // Detect incomplete support for accessing string characters by index.
    6290     var charIndexBuggy = has("bug-string-char-index");
    6291 
    6292     // Define additional utility methods if the `Date` methods are buggy.
    6293     if (!isExtended) {
    6294       var floor = Math.floor;
    6295       // A mapping between the months of the year and the number of days between
    6296       // January 1st and the first of the respective month.
    6297       var Months = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334];
    6298       // Internal: Calculates the number of days between the Unix epoch and the
    6299       // first day of the given month.
    6300       var getDay = function (year, month) {
    6301         return Months[month] + 365 * (year - 1970) + floor((year - 1969 + (month = +(month > 1))) / 4) - floor((year - 1901 + month) / 100) + floor((year - 1601 + month) / 400);
    6302       };
    6303     }
    6304 
    6305     // Internal: Determines if a property is a direct property of the given
    6306     // object. Delegates to the native `Object#hasOwnProperty` method.
    6307     if (!(isProperty = {}.hasOwnProperty)) {
    6308       isProperty = function (property) {
    6309         var members = {}, constructor;
    6310         if ((members.__proto__ = null, members.__proto__ = {
    6311           // The *proto* property cannot be set multiple times in recent
    6312           // versions of Firefox and SeaMonkey.
    6313           "toString": 1
    6314         }, members).toString != getClass) {
    6315           // Safari <= 2.0.3 doesn't implement `Object#hasOwnProperty`, but
    6316           // supports the mutable *proto* property.
    6317           isProperty = function (property) {
    6318             // Capture and break the object's prototype chain (see section 8.6.2
    6319             // of the ES 5.1 spec). The parenthesized expression prevents an
    6320             // unsafe transformation by the Closure Compiler.
    6321             var original = this.__proto__, result = property in (this.__proto__ = null, this);
    6322             // Restore the original prototype chain.
    6323             this.__proto__ = original;
    6324             return result;
    6325           };
    6326         } else {
    6327           // Capture a reference to the top-level `Object` constructor.
    6328           constructor = members.constructor;
    6329           // Use the `constructor` property to simulate `Object#hasOwnProperty` in
    6330           // other environments.
    6331           isProperty = function (property) {
    6332             var parent = (this.constructor || constructor).prototype;
    6333             return property in this && !(property in parent && this[property] === parent[property]);
    6334           };
    6335         }
    6336         members = null;
    6337         return isProperty.call(this, property);
    6338       };
    6339     }
    6340 
    6341     // Internal: A set of primitive types used by `isHostType`.
    6342     var PrimitiveTypes = {
    6343       'boolean': 1,
    6344       'number': 1,
    6345       'string': 1,
    6346       'undefined': 1
    6347     };
    6348 
    6349     // Internal: Determines if the given object `property` value is a
    6350     // non-primitive.
    6351     var isHostType = function (object, property) {
    6352       var type = typeof object[property];
    6353       return type == 'object' ? !!object[property] : !PrimitiveTypes[type];
    6354     };
    6355 
    6356     // Internal: Normalizes the `for...in` iteration algorithm across
    6357     // environments. Each enumerated key is yielded to a `callback` function.
    6358     forEach = function (object, callback) {
    6359       var size = 0, Properties, members, property;
    6360 
    6361       // Tests for bugs in the current environment's `for...in` algorithm. The
    6362       // `valueOf` property inherits the non-enumerable flag from
    6363       // `Object.prototype` in older versions of IE, Netscape, and Mozilla.
    6364       (Properties = function () {
    6365         this.valueOf = 0;
    6366       }).prototype.valueOf = 0;
    6367 
    6368       // Iterate over a new instance of the `Properties` class.
    6369       members = new Properties();
    6370       for (property in members) {
    6371         // Ignore all properties inherited from `Object.prototype`.
    6372         if (isProperty.call(members, property)) {
    6373           size++;
    6374         }
    6375       }
    6376       Properties = members = null;
    6377 
    6378       // Normalize the iteration algorithm.
    6379       if (!size) {
    6380         // A list of non-enumerable properties inherited from `Object.prototype`.
    6381         members = ["valueOf", "toString", "toLocaleString", "propertyIsEnumerable", "isPrototypeOf", "hasOwnProperty", "constructor"];
    6382         // IE <= 8, Mozilla 1.0, and Netscape 6.2 ignore shadowed non-enumerable
    6383         // properties.
    6384         forEach = function (object, callback) {
    6385           var isFunction = getClass.call(object) == functionClass, property, length;
    6386           var hasProperty = !isFunction && typeof object.constructor != 'function' && isHostType(object, 'hasOwnProperty') ? object.hasOwnProperty : isProperty;
    6387           for (property in object) {
    6388             // Gecko <= 1.0 enumerates the `prototype` property of functions under
    6389             // certain conditions; IE does not.
    6390             if (!(isFunction && property == "prototype") && hasProperty.call(object, property)) {
    6391               callback(property);
    6392             }
    6393           }
    6394           // Manually invoke the callback for each non-enumerable property.
    6395           for (length = members.length; property = members[--length]; hasProperty.call(object, property) && callback(property));
    6396         };
    6397       } else if (size == 2) {
    6398         // Safari <= 2.0.4 enumerates shadowed properties twice.
    6399         forEach = function (object, callback) {
    6400           // Create a set of iterated properties.
    6401           var members = {}, isFunction = getClass.call(object) == functionClass, property;
    6402           for (property in object) {
    6403             // Store each property name to prevent double enumeration. The
    6404             // `prototype` property of functions is not enumerated due to cross-
    6405             // environment inconsistencies.
    6406             if (!(isFunction && property == "prototype") && !isProperty.call(members, property) && (members[property] = 1) && isProperty.call(object, property)) {
    6407               callback(property);
    6408             }
    6409           }
    6410         };
    6411       } else {
    6412         // No bugs detected; use the standard `for...in` algorithm.
    6413         forEach = function (object, callback) {
    6414           var isFunction = getClass.call(object) == functionClass, property, isConstructor;
    6415           for (property in object) {
    6416             if (!(isFunction && property == "prototype") && isProperty.call(object, property) && !(isConstructor = property === "constructor")) {
    6417               callback(property);
    6418             }
    6419           }
    6420           // Manually invoke the callback for the `constructor` property due to
    6421           // cross-environment inconsistencies.
    6422           if (isConstructor || isProperty.call(object, (property = "constructor"))) {
    6423             callback(property);
    6424           }
    6425         };
    6426       }
    6427       return forEach(object, callback);
    6428     };
    6429 
    6430     // Public: Serializes a JavaScript `value` as a JSON string. The optional
    6431     // `filter` argument may specify either a function that alters how object and
    6432     // array members are serialized, or an array of strings and numbers that
    6433     // indicates which properties should be serialized. The optional `width`
    6434     // argument may be either a string or number that specifies the indentation
    6435     // level of the output.
    6436     if (!has("json-stringify")) {
    6437       // Internal: A map of control characters and their escaped equivalents.
    6438       var Escapes = {
    6439         92: "\\",
    6440         34: '\"',
    6441         8: "\b",
    6442         12: "\f",
    6443         10: "\n",
    6444         13: "\r",
    6445         9: "\t"
    6446       };
    6447 
    6448       // Internal: Converts `value` into a zero-padded string such that its
    6449       // length is at least equal to `width`. The `width` must be <= 6.
    6450       var leadingZeroes = "000000";
    6451       var toPaddedString = function (width, value) {
    6452         // The `|| 0` expression is necessary to work around a bug in
    6453         // Opera <= 7.54u2 where `0 == -0`, but `String(-0) !== "0"`.
    6454         return (leadingZeroes + (value || 0)).slice(-width);
    6455       };
    6456 
    6457       // Internal: Double-quotes a string `value`, replacing all ASCII control
    6458       // characters (characters with code unit values between 0 and 31) with
    6459       // their escaped equivalents. This is an implementation of the
    6460       // `Quote(value)` operation defined in ES 5.1 section 15.12.3.
    6461       var unicodePrefix = "\u00";
    6462       var quote = function (value) {
    6463         var result = '"', index = 0, length = value.length, isLarge = length > 10 && charIndexBuggy, symbols;
    6464         if (isLarge) {
    6465           symbols = value.split("");
    6466         }
    6467         for (; index < length; index++) {
    6468           var charCode = value.charCodeAt(index);
    6469           // If the character is a control character, append its Unicode or
    6470           // shorthand escape sequence; otherwise, append the character as-is.
    6471           switch (charCode) {
    6472             case 8: case 9: case 10: case 12: case 13: case 34: case 92:
    6473               result += Escapes[charCode];
    6474               break;
    6475             default:
    6476               if (charCode < 32) {
    6477                 result += unicodePrefix + toPaddedString(2, charCode.toString(16));
    6478                 break;
    6479               }
    6480               result += isLarge ? symbols[index] : charIndexBuggy ? value.charAt(index) : value[index];
    6481           }
    6482         }
    6483         return result + '"';
    6484       };
    6485 
    6486       // Internal: Recursively serializes an object. Implements the
    6487       // `Str(key, holder)`, `JO(value)`, and `JA(value)` operations.
    6488       var serialize = function (property, object, callback, properties, whitespace, indentation, stack) {
    6489         var value, className, year, month, date, time, hours, minutes, seconds, milliseconds, results, element, index, length, prefix, result;
    6490         try {
    6491           // Necessary for host object support.
    6492           value = object[property];
    6493         } catch (exception) {}
    6494         if (typeof value == "object" && value) {
    6495           className = getClass.call(value);
    6496           if (className == dateClass && !isProperty.call(value, "toJSON")) {
    6497             if (value > -1 / 0 && value < 1 / 0) {
    6498               // Dates are serialized according to the `Date#toJSON` method
    6499               // specified in ES 5.1 section 15.9.5.44. See section 15.9.1.15
    6500               // for the ISO 8601 date time string format.
    6501               if (getDay) {
    6502                 // Manually compute the year, month, date, hours, minutes,
    6503                 // seconds, and milliseconds if the `getUTC*` methods are
    6504                 // buggy. Adapted from @Yaffle's `date-shim` project.
    6505                 date = floor(value / 864e5);
    6506                 for (year = floor(date / 365.2425) + 1970 - 1; getDay(year + 1, 0) <= date; year++);
    6507                 for (month = floor((date - getDay(year, 0)) / 30.42); getDay(year, month + 1) <= date; month++);
    6508                 date = 1 + date - getDay(year, month);
    6509                 // The `time` value specifies the time within the day (see ES
    6510                 // 5.1 section 15.9.1.2). The formula `(A % B + B) % B` is used
    6511                 // to compute `A modulo B`, as the `%` operator does not
    6512                 // correspond to the `modulo` operation for negative numbers.
    6513                 time = (value % 864e5 + 864e5) % 864e5;
    6514                 // The hours, minutes, seconds, and milliseconds are obtained by
    6515                 // decomposing the time within the day. See section 15.9.1.10.
    6516                 hours = floor(time / 36e5) % 24;
    6517                 minutes = floor(time / 6e4) % 60;
    6518                 seconds = floor(time / 1e3) % 60;
    6519                 milliseconds = time % 1e3;
    6520               } else {
    6521                 year = value.getUTCFullYear();
    6522                 month = value.getUTCMonth();
    6523                 date = value.getUTCDate();
    6524                 hours = value.getUTCHours();
    6525                 minutes = value.getUTCMinutes();
    6526                 seconds = value.getUTCSeconds();
    6527                 milliseconds = value.getUTCMilliseconds();
    6528               }
    6529               // Serialize extended years correctly.
    6530               value = (year <= 0 || year >= 1e4 ? (year < 0 ? "-" : "+") + toPaddedString(6, year < 0 ? -year : year) : toPaddedString(4, year)) +
    6531                 "-" + toPaddedString(2, month + 1) + "-" + toPaddedString(2, date) +
    6532                 // Months, dates, hours, minutes, and seconds should have two
    6533                 // digits; milliseconds should have three.
    6534                 "T" + toPaddedString(2, hours) + ":" + toPaddedString(2, minutes) + ":" + toPaddedString(2, seconds) +
    6535                 // Milliseconds are optional in ES 5.0, but required in 5.1.
    6536                 "." + toPaddedString(3, milliseconds) + "Z";
    6537             } else {
    6538               value = null;
    6539             }
    6540           } else if (typeof value.toJSON == "function" && ((className != numberClass && className != stringClass && className != arrayClass) || isProperty.call(value, "toJSON"))) {
    6541             // Prototype <= 1.6.1 adds non-standard `toJSON` methods to the
    6542             // `Number`, `String`, `Date`, and `Array` prototypes. JSON 3
    6543             // ignores all `toJSON` methods on these objects unless they are
    6544             // defined directly on an instance.
    6545             value = value.toJSON(property);
    6546           }
    6547         }
    6548         if (callback) {
    6549           // If a replacement function was provided, call it to obtain the value
    6550           // for serialization.
    6551           value = callback.call(object, property, value);
    6552         }
    6553         if (value === null) {
    6554           return "null";
    6555         }
    6556         className = getClass.call(value);
    6557         if (className == booleanClass) {
    6558           // Booleans are represented literally.
    6559           return "" + value;
    6560         } else if (className == numberClass) {
    6561           // JSON numbers must be finite. `Infinity` and `NaN` are serialized as
    6562           // `"null"`.
    6563           return value > -1 / 0 && value < 1 / 0 ? "" + value : "null";
    6564         } else if (className == stringClass) {
    6565           // Strings are double-quoted and escaped.
    6566           return quote("" + value);
    6567         }
    6568         // Recursively serialize objects and arrays.
    6569         if (typeof value == "object") {
    6570           // Check for cyclic structures. This is a linear search; performance
    6571           // is inversely proportional to the number of unique nested objects.
    6572           for (length = stack.length; length--;) {
    6573             if (stack[length] === value) {
    6574               // Cyclic structures cannot be serialized by `JSON.stringify`.
    6575               throw TypeError();
    6576             }
    6577           }
    6578           // Add the object to the stack of traversed objects.
    6579           stack.push(value);
    6580           results = [];
    6581           // Save the current indentation level and indent one additional level.
    6582           prefix = indentation;
    6583           indentation += whitespace;
    6584           if (className == arrayClass) {
    6585             // Recursively serialize array elements.
    6586             for (index = 0, length = value.length; index < length; index++) {
    6587               element = serialize(index, value, callback, properties, whitespace, indentation, stack);
    6588               results.push(element === undef ? "null" : element);
    6589             }
    6590             result = results.length ? (whitespace ? "[
    " + indentation + results.join(",
    " + indentation) + "
    " + prefix + "]" : ("[" + results.join(",") + "]")) : "[]";
    6591           } else {
    6592             // Recursively serialize object members. Members are selected from
    6593             // either a user-specified list of property names, or the object
    6594             // itself.
    6595             forEach(properties || value, function (property) {
    6596               var element = serialize(property, value, callback, properties, whitespace, indentation, stack);
    6597               if (element !== undef) {
    6598                 // According to ES 5.1 section 15.12.3: "If `gap` {whitespace}
    6599                 // is not the empty string, let `member` {quote(property) + ":"}
    6600                 // be the concatenation of `member` and the `space` character."
    6601                 // The "`space` character" refers to the literal space
    6602                 // character, not the `space` {width} argument provided to
    6603                 // `JSON.stringify`.
    6604                 results.push(quote(property) + ":" + (whitespace ? " " : "") + element);
    6605               }
    6606             });
    6607             result = results.length ? (whitespace ? "{
    " + indentation + results.join(",
    " + indentation) + "
    " + prefix + "}" : ("{" + results.join(",") + "}")) : "{}";
    6608           }
    6609           // Remove the object from the traversed object stack.
    6610           stack.pop();
    6611           return result;
    6612         }
    6613       };
    6614 
    6615       // Public: `JSON.stringify`. See ES 5.1 section 15.12.3.
    6616       JSON3.stringify = function (source, filter, width) {
    6617         var whitespace, callback, properties, className;
    6618         if (typeof filter == "function" || typeof filter == "object" && filter) {
    6619           if ((className = getClass.call(filter)) == functionClass) {
    6620             callback = filter;
    6621           } else if (className == arrayClass) {
    6622             // Convert the property names array into a makeshift set.
    6623             properties = {};
    6624             for (var index = 0, length = filter.length, value; index < length; value = filter[index++], ((className = getClass.call(value)), className == stringClass || className == numberClass) && (properties[value] = 1));
    6625           }
    6626         }
    6627         if (width) {
    6628           if ((className = getClass.call(width)) == numberClass) {
    6629             // Convert the `width` to an integer and create a string containing
    6630             // `width` number of space characters.
    6631             if ((width -= width % 1) > 0) {
    6632               for (whitespace = "", width > 10 && (width = 10); whitespace.length < width; whitespace += " ");
    6633             }
    6634           } else if (className == stringClass) {
    6635             whitespace = width.length <= 10 ? width : width.slice(0, 10);
    6636           }
    6637         }
    6638         // Opera <= 7.54u2 discards the values associated with empty string keys
    6639         // (`""`) only if they are used directly within an object member list
    6640         // (e.g., `!("" in { "": 1})`).
    6641         return serialize("", (value = {}, value[""] = source, value), callback, properties, whitespace, "", []);
    6642       };
    6643     }
    6644 
    6645     // Public: Parses a JSON source string.
    6646     if (!has("json-parse")) {
    6647       var fromCharCode = String.fromCharCode;
    6648 
    6649       // Internal: A map of escaped control characters and their unescaped
    6650       // equivalents.
    6651       var Unescapes = {
    6652         92: "\",
    6653         34: '"',
    6654         47: "/",
    6655         98: "",
    6656         116: "	",
    6657         110: "
    ",
    6658         102: "f",
    6659         114: "
    "
    6660       };
    6661 
    6662       // Internal: Stores the parser state.
    6663       var Index, Source;
    6664 
    6665       // Internal: Resets the parser state and throws a `SyntaxError`.
    6666       var abort = function() {
    6667         Index = Source = null;
    6668         throw SyntaxError();
    6669       };
    6670 
    6671       // Internal: Returns the next token, or `"$"` if the parser has reached
    6672       // the end of the source string. A token may be a string, number, `null`
    6673       // literal, or Boolean literal.
    6674       var lex = function () {
    6675         var source = Source, length = source.length, value, begin, position, isSigned, charCode;
    6676         while (Index < length) {
    6677           charCode = source.charCodeAt(Index);
    6678           switch (charCode) {
    6679             case 9: case 10: case 13: case 32:
    6680               // Skip whitespace tokens, including tabs, carriage returns, line
    6681               // feeds, and space characters.
    6682               Index++;
    6683               break;
    6684             case 123: case 125: case 91: case 93: case 58: case 44:
    6685               // Parse a punctuator token (`{`, `}`, `[`, `]`, `:`, or `,`) at
    6686               // the current position.
    6687               value = charIndexBuggy ? source.charAt(Index) : source[Index];
    6688               Index++;
    6689               return value;
    6690             case 34:
    6691               // `"` delimits a JSON string; advance to the next character and
    6692               // begin parsing the string. String tokens are prefixed with the
    6693               // sentinel `@` character to distinguish them from punctuators and
    6694               // end-of-string tokens.
    6695               for (value = "@", Index++; Index < length;) {
    6696                 charCode = source.charCodeAt(Index);
    6697                 if (charCode < 32) {
    6698                   // Unescaped ASCII control characters (those with a code unit
    6699                   // less than the space character) are not permitted.
    6700                   abort();
    6701                 } else if (charCode == 92) {
    6702                   // A reverse solidus (`\`) marks the beginning of an escaped
    6703                   // control character (including `"`, `\`, and `/`) or Unicode
    6704                   // escape sequence.
    6705                   charCode = source.charCodeAt(++Index);
    6706                   switch (charCode) {
    6707                     case 92: case 34: case 47: case 98: case 116: case 110: case 102: case 114:
    6708                       // Revive escaped control characters.
    6709                       value += Unescapes[charCode];
    6710                       Index++;
    6711                       break;
    6712                     case 117:
    6713                       // `u` marks the beginning of a Unicode escape sequence.
    6714                       // Advance to the first character and validate the
    6715                       // four-digit code point.
    6716                       begin = ++Index;
    6717                       for (position = Index + 4; Index < position; Index++) {
    6718                         charCode = source.charCodeAt(Index);
    6719                         // A valid sequence comprises four hexdigits (case-
    6720                         // insensitive) that form a single hexadecimal value.
    6721                         if (!(charCode >= 48 && charCode <= 57 || charCode >= 97 && charCode <= 102 || charCode >= 65 && charCode <= 70)) {
    6722                           // Invalid Unicode escape sequence.
    6723                           abort();
    6724                         }
    6725                       }
    6726                       // Revive the escaped character.
    6727                       value += fromCharCode("0x" + source.slice(begin, Index));
    6728                       break;
    6729                     default:
    6730                       // Invalid escape sequence.
    6731                       abort();
    6732                   }
    6733                 } else {
    6734                   if (charCode == 34) {
    6735                     // An unescaped double-quote character marks the end of the
    6736                     // string.
    6737                     break;
    6738                   }
    6739                   charCode = source.charCodeAt(Index);
    6740                   begin = Index;
    6741                   // Optimize for the common case where a string is valid.
    6742                   while (charCode >= 32 && charCode != 92 && charCode != 34) {
    6743                     charCode = source.charCodeAt(++Index);
    6744                   }
    6745                   // Append the string as-is.
    6746                   value += source.slice(begin, Index);
    6747                 }
    6748               }
    6749               if (source.charCodeAt(Index) == 34) {
    6750                 // Advance to the next character and return the revived string.
    6751                 Index++;
    6752                 return value;
    6753               }
    6754               // Unterminated string.
    6755               abort();
    6756             default:
    6757               // Parse numbers and literals.
    6758               begin = Index;
    6759               // Advance past the negative sign, if one is specified.
    6760               if (charCode == 45) {
    6761                 isSigned = true;
    6762                 charCode = source.charCodeAt(++Index);
    6763               }
    6764               // Parse an integer or floating-point value.
    6765               if (charCode >= 48 && charCode <= 57) {
    6766                 // Leading zeroes are interpreted as octal literals.
    6767                 if (charCode == 48 && ((charCode = source.charCodeAt(Index + 1)), charCode >= 48 && charCode <= 57)) {
    6768                   // Illegal octal literal.
    6769                   abort();
    6770                 }
    6771                 isSigned = false;
    6772                 // Parse the integer component.
    6773                 for (; Index < length && ((charCode = source.charCodeAt(Index)), charCode >= 48 && charCode <= 57); Index++);
    6774                 // Floats cannot contain a leading decimal point; however, this
    6775                 // case is already accounted for by the parser.
    6776                 if (source.charCodeAt(Index) == 46) {
    6777                   position = ++Index;
    6778                   // Parse the decimal component.
    6779                   for (; position < length && ((charCode = source.charCodeAt(position)), charCode >= 48 && charCode <= 57); position++);
    6780                   if (position == Index) {
    6781                     // Illegal trailing decimal.
    6782                     abort();
    6783                   }
    6784                   Index = position;
    6785                 }
    6786                 // Parse exponents. The `e` denoting the exponent is
    6787                 // case-insensitive.
    6788                 charCode = source.charCodeAt(Index);
    6789                 if (charCode == 101 || charCode == 69) {
    6790                   charCode = source.charCodeAt(++Index);
    6791                   // Skip past the sign following the exponent, if one is
    6792                   // specified.
    6793                   if (charCode == 43 || charCode == 45) {
    6794                     Index++;
    6795                   }
    6796                   // Parse the exponential component.
    6797                   for (position = Index; position < length && ((charCode = source.charCodeAt(position)), charCode >= 48 && charCode <= 57); position++);
    6798                   if (position == Index) {
    6799                     // Illegal empty exponent.
    6800                     abort();
    6801                   }
    6802                   Index = position;
    6803                 }
    6804                 // Coerce the parsed value to a JavaScript number.
    6805                 return +source.slice(begin, Index);
    6806               }
    6807               // A negative sign may only precede numbers.
    6808               if (isSigned) {
    6809                 abort();
    6810               }
    6811               // `true`, `false`, and `null` literals.
    6812               if (source.slice(Index, Index + 4) == "true") {
    6813                 Index += 4;
    6814                 return true;
    6815               } else if (source.slice(Index, Index + 5) == "false") {
    6816                 Index += 5;
    6817                 return false;
    6818               } else if (source.slice(Index, Index + 4) == "null") {
    6819                 Index += 4;
    6820                 return null;
    6821               }
    6822               // Unrecognized token.
    6823               abort();
    6824           }
    6825         }
    6826         // Return the sentinel `$` character if the parser has reached the end
    6827         // of the source string.
    6828         return "$";
    6829       };
    6830 
    6831       // Internal: Parses a JSON `value` token.
    6832       var get = function (value) {
    6833         var results, hasMembers;
    6834         if (value == "$") {
    6835           // Unexpected end of input.
    6836           abort();
    6837         }
    6838         if (typeof value == "string") {
    6839           if ((charIndexBuggy ? value.charAt(0) : value[0]) == "@") {
    6840             // Remove the sentinel `@` character.
    6841             return value.slice(1);
    6842           }
    6843           // Parse object and array literals.
    6844           if (value == "[") {
    6845             // Parses a JSON array, returning a new JavaScript array.
    6846             results = [];
    6847             for (;; hasMembers || (hasMembers = true)) {
    6848               value = lex();
    6849               // A closing square bracket marks the end of the array literal.
    6850               if (value == "]") {
    6851                 break;
    6852               }
    6853               // If the array literal contains elements, the current token
    6854               // should be a comma separating the previous element from the
    6855               // next.
    6856               if (hasMembers) {
    6857                 if (value == ",") {
    6858                   value = lex();
    6859                   if (value == "]") {
    6860                     // Unexpected trailing `,` in array literal.
    6861                     abort();
    6862                   }
    6863                 } else {
    6864                   // A `,` must separate each array element.
    6865                   abort();
    6866                 }
    6867               }
    6868               // Elisions and leading commas are not permitted.
    6869               if (value == ",") {
    6870                 abort();
    6871               }
    6872               results.push(get(value));
    6873             }
    6874             return results;
    6875           } else if (value == "{") {
    6876             // Parses a JSON object, returning a new JavaScript object.
    6877             results = {};
    6878             for (;; hasMembers || (hasMembers = true)) {
    6879               value = lex();
    6880               // A closing curly brace marks the end of the object literal.
    6881               if (value == "}") {
    6882                 break;
    6883               }
    6884               // If the object literal contains members, the current token
    6885               // should be a comma separator.
    6886               if (hasMembers) {
    6887                 if (value == ",") {
    6888                   value = lex();
    6889                   if (value == "}") {
    6890                     // Unexpected trailing `,` in object literal.
    6891                     abort();
    6892                   }
    6893                 } else {
    6894                   // A `,` must separate each object member.
    6895                   abort();
    6896                 }
    6897               }
    6898               // Leading commas are not permitted, object property names must be
    6899               // double-quoted strings, and a `:` must separate each property
    6900               // name and value.
    6901               if (value == "," || typeof value != "string" || (charIndexBuggy ? value.charAt(0) : value[0]) != "@" || lex() != ":") {
    6902                 abort();
    6903               }
    6904               results[value.slice(1)] = get(lex());
    6905             }
    6906             return results;
    6907           }
    6908           // Unexpected token encountered.
    6909           abort();
    6910         }
    6911         return value;
    6912       };
    6913 
    6914       // Internal: Updates a traversed object member.
    6915       var update = function(source, property, callback) {
    6916         var element = walk(source, property, callback);
    6917         if (element === undef) {
    6918           delete source[property];
    6919         } else {
    6920           source[property] = element;
    6921         }
    6922       };
    6923 
    6924       // Internal: Recursively traverses a parsed JSON object, invoking the
    6925       // `callback` function for each value. This is an implementation of the
    6926       // `Walk(holder, name)` operation defined in ES 5.1 section 15.12.2.
    6927       var walk = function (source, property, callback) {
    6928         var value = source[property], length;
    6929         if (typeof value == "object" && value) {
    6930           // `forEach` can't be used to traverse an array in Opera <= 8.54
    6931           // because its `Object#hasOwnProperty` implementation returns `false`
    6932           // for array indices (e.g., `![1, 2, 3].hasOwnProperty("0")`).
    6933           if (getClass.call(value) == arrayClass) {
    6934             for (length = value.length; length--;) {
    6935               update(value, length, callback);
    6936             }
    6937           } else {
    6938             forEach(value, function (property) {
    6939               update(value, property, callback);
    6940             });
    6941           }
    6942         }
    6943         return callback.call(source, property, value);
    6944       };
    6945 
    6946       // Public: `JSON.parse`. See ES 5.1 section 15.12.2.
    6947       JSON3.parse = function (source, callback) {
    6948         var result, value;
    6949         Index = 0;
    6950         Source = "" + source;
    6951         result = get(lex());
    6952         // If a JSON string contains multiple tokens, it is invalid.
    6953         if (lex() != "$") {
    6954           abort();
    6955         }
    6956         // Reset the parser state.
    6957         Index = Source = null;
    6958         return callback && getClass.call(callback) == functionClass ? walk((value = {}, value[""] = result, value), "", callback) : result;
    6959       };
    6960     }
    6961   }
    6962 
    6963   // Export for asynchronous module loaders.
    6964   if (isLoader) {
    6965     define(function () {
    6966       return JSON3;
    6967     });
    6968   }
    6969 }(this));
    6970 
    6971 },{}],48:[function(_dereq_,module,exports){
    6972 module.exports = toArray
    6973 
    6974 function toArray(list, index) {
    6975     var array = []
    6976 
    6977     index = index || 0
    6978 
    6979     for (var i = index || 0; i < list.length; i++) {
    6980         array[i - index] = list[i]
    6981     }
    6982 
    6983     return array
    6984 }
    6985 
    6986 },{}]},{},[1])
    6987 (1)
    6988 });
    View Code

    项目结构如下图:

    
    
  • 相关阅读:
    极化码的matlab仿真(4)——SC译码(2)
    极化码的matlab仿真(3)——SC译码(1)
    极化码的matlab仿真(2)——编码
    极化码的matlab仿真(1)——参数设置
    开启极化码之路
    matlab-常用函数(2)
    从零开始搭建django前后端分离项目 系列一(技术选型)
    java8 新特性parallelStream 修改默认多线程数量
    从零开始搭建django前后端分离项目 系列六(实战之聚类分析)
    从零开始搭建django前后端分离项目 系列五(实战之excel流式导出)
  • 原文地址:https://www.cnblogs.com/yinhao-jack/p/10298012.html
Copyright © 2011-2022 走看看