PageRenderTime 237ms CodeModel.GetById 5ms app.highlight 195ms RepoModel.GetById 1ms app.codeStats 1ms

/htdocs/assets/js/socket.io.js

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