UNPKG

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