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