1 !function(e
){if("object"==typeof exports
&&"undefined"!=typeof mod
)mod
.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
.eio
=e()}}(function(){var define
,mod
,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 mod '"+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_
,mod
,exports
){
3 mod
.exports
= _dereq_('./lib/');
5 },{"./lib/":2}],2:[function(_dereq_
,mod
,exports
){
7 mod
.exports
= _dereq_('./socket');
15 mod
.exports
.parser
= _dereq_('engine.io-parser');
17 },{"./socket":3,"engine.io-parser":15}],3:[function(_dereq_
,mod
,exports
){
23 var transports
= _dereq_('./transports');
24 var Emitter
= _dereq_('component-emitter');
25 var debug
= _dereq_('debug')('engine.io-client:socket');
26 var index
= _dereq_('indexof');
27 var parser
= _dereq_('engine.io-parser');
28 var parseuri
= _dereq_('parseuri');
29 var parsejson
= _dereq_('parsejson');
30 var parseqs
= _dereq_('parseqs');
49 * @param {String|Object} uri or options
50 * @param {Object} options
54 function Socket(uri
, opts
){
55 if (!(this instanceof Socket
)) return new Socket(uri
, opts
);
59 if (uri
&& 'object' == typeof uri
) {
67 opts
.secure
= uri
.protocol
== 'https' || uri
.protocol
== 'wss';
69 if (uri
.query
) opts
.query
= uri
.query
;
72 this.secure
= null != opts
.secure
? opts
.secure
:
73 (global
.location
&& 'https:' == location
.protocol
);
76 var pieces
= opts
.host
.split(':');
77 opts
.hostname
= pieces
.shift();
78 if (pieces
.length
) opts
.port
= pieces
.pop();
81 this.agent
= opts
.agent
|| false;
82 this.hostname
= opts
.hostname
||
83 (global
.location
? location
.hostname
: 'localhost');
84 this.port
= opts
.port
|| (global
.location
&& location
.port
?
86 (this.secure
? 443 : 80));
87 this.query
= opts
.query
|| {};
88 if ('string' == typeof this.query
) this.query
= parseqs
.decode(this.query
);
89 this.upgrade
= false !== opts
.upgrade
;
90 this.path
= (opts
.path
|| '/engine.io').replace(/\/$/, '') + '/';
91 this.forceJSONP = !!opts.forceJSONP;
92 this.jsonp = false !== opts.jsonp;
93 this.forceBase64 = !!opts.forceBase64;
94 this.enablesXDR = !!opts.enablesXDR;
95 this.timestampParam = opts.timestampParam || 't
';
96 this.timestampRequests = opts.timestampRequests;
97 this.transports = opts.transports || ['polling
', 'websocket
'];
99 this.writeBuffer = [];
100 this.callbackBuffer = [];
101 this.policyPort = opts.policyPort || 843;
102 this.rememberUpgrade = opts.rememberUpgrade || false;
104 this.binaryType = null;
105 this.onlyBinaryUpgrades = opts.onlyBinaryUpgrades;
108 Socket.priorWebsocketSuccess = false;
114 Emitter(Socket.prototype);
122 Socket.protocol = parser.protocol; // this is an int
125 * Expose deps for legacy compatibility
126 * and standalone browser access.
129 Socket.Socket = Socket;
130 Socket.Transport = _dereq_('./transport
');
131 Socket.transports = _dereq_('./transports
');
132 Socket.parser = _dereq_('engine
.io
-parser
');
135 * Creates transport of the given type.
137 * @param {String} transport name
138 * @return {Transport}
142 Socket.prototype.createTransport = function (name) {
143 debug('creating transport
"%s"', name);
144 var query = clone(this.query);
146 // append engine.io protocol identifier
147 query.EIO = parser.protocol;
150 query.transport = name;
152 // session id if we already have one
153 if (this.id) query.sid = this.id;
155 var transport = new transports[name]({
157 hostname: this.hostname,
162 forceJSONP: this.forceJSONP,
164 forceBase64: this.forceBase64,
165 enablesXDR: this.enablesXDR,
166 timestampRequests: this.timestampRequests,
167 timestampParam: this.timestampParam,
168 policyPort: this.policyPort,
175 function clone (obj) {
178 if (obj.hasOwnProperty(i)) {
186 * Initializes transport to use and starts probe.
190 Socket.prototype.open = function () {
192 if (this.rememberUpgrade && Socket.priorWebsocketSuccess && this.transports.indexOf('websocket
') != -1) {
193 transport = 'websocket
';
194 } else if (0 == this.transports.length) {
195 // Emit error on next tick so it can be listened to
197 setTimeout(function() {
198 self.emit('error
', 'No transports available
');
202 transport = this.transports[0];
204 this.readyState = 'opening
';
206 // Retry with the next transport if the transport is disabled (jsonp: false)
209 transport = this.createTransport(transport);
211 this.transports.shift();
217 this.setTransport(transport);
221 * Sets the current transport. Disables the existing one (if any).
226 Socket.prototype.setTransport = function(transport){
227 debug('setting transport
%s
', transport.name);
230 if (this.transport) {
231 debug('clearing existing transport
%s
', this.transport.name);
232 this.transport.removeAllListeners();
236 this.transport = transport;
238 // set up transport listeners
240 .on('drain
', function(){
243 .on('packet
', function(packet){
244 self.onPacket(packet);
246 .on('error
', function(e){
249 .on('close
', function(){
250 self.onClose('transport close
');
255 * Probes a transport.
257 * @param {String} transport name
261 Socket.prototype.probe = function (name) {
262 debug('probing transport
"%s"', name);
263 var transport = this.createTransport(name, { probe: 1 })
267 Socket.priorWebsocketSuccess = false;
269 function onTransportOpen(){
270 if (self.onlyBinaryUpgrades) {
271 var upgradeLosesBinary = !this.supportsBinary && self.transport.supportsBinary;
272 failed = failed || upgradeLosesBinary;
276 debug('probe transport
"%s" opened
', name);
277 transport.send([{ type: 'ping
', data: 'probe
' }]);
278 transport.once('packet
', function (msg) {
280 if ('pong
' == msg.type && 'probe
' == msg.data) {
281 debug('probe transport
"%s" pong
', name);
282 self.upgrading = true;
283 self.emit('upgrading
', transport);
284 Socket.priorWebsocketSuccess = 'websocket
' == transport.name;
286 debug('pausing current transport
"%s"', self.transport.name);
287 self.transport.pause(function () {
289 if ('closed
' == self.readyState || 'closing
' == self.readyState) {
292 debug('changing transport and sending upgrade packet
');
296 self.setTransport(transport);
297 transport.send([{ type: 'upgrade
' }]);
298 self.emit('upgrade
', transport);
300 self.upgrading = false;
304 debug('probe transport
"%s" failed
', name);
305 var err = new Error('probe error
');
306 err.transport = transport.name;
307 self.emit('upgradeError
', err);
312 function freezeTransport() {
315 // Any callback called by transport should be ignored since now
324 //Handle any error that happens while probing
325 function onerror(err) {
326 var error = new Error('probe error
: ' + err);
327 error.transport = transport.name;
331 debug('probe transport
"%s" failed because
of error
: %s
', name, err);
333 self.emit('upgradeError
', error);
336 function onTransportClose(){
337 onerror("transport closed");
340 //When the socket is closed while we're probing
342 onerror("socket closed");
345 //When the socket is upgraded while we're probing
346 function onupgrade(to
){
347 if (transport
&& to
.name
!= transport
.name
) {
348 debug('"%s" works - aborting "%s"', to
.name
, transport
.name
);
353 //Remove all listeners on the transport and on self
355 transport
.removeListener('open', onTransportOpen
);
356 transport
.removeListener('error', onerror
);
357 transport
.removeListener('close', onTransportClose
);
358 self
.removeListener('close', onclose
);
359 self
.removeListener('upgrading', onupgrade
);
362 transport
.once('open', onTransportOpen
);
363 transport
.once('error', onerror
);
364 transport
.once('close', onTransportClose
);
366 this.once('close', onclose
);
367 this.once('upgrading', onupgrade
);
374 * Called when connection is deemed open.
379 Socket
.prototype.onOpen = function () {
380 debug('socket open');
381 this.readyState
= 'open';
382 Socket
.priorWebsocketSuccess
= 'websocket' == this.transport
.name
;
386 // we check for `readyState` in case an `open`
387 // listener already closed the socket
388 if ('open' == this.readyState
&& this.upgrade
&& this.transport
.pause
) {
389 debug('starting upgrade probes');
390 for (var i
= 0, l
= this.upgrades
.length
; i
< l
; i
++) {
391 this.probe(this.upgrades
[i
]);
402 Socket
.prototype.onPacket = function (packet
) {
403 if ('opening' == this.readyState
|| 'open' == this.readyState
) {
404 debug('socket receive: type "%s", data "%s"', packet
.type
, packet
.data
);
406 this.emit('packet', packet
);
408 // Socket is live - any packet counts
409 this.emit('heartbeat');
411 switch (packet
.type
) {
413 this.onHandshake(parsejson(packet
.data
));
421 var err
= new Error('server error');
422 err
.code
= packet
.data
;
423 this.emit('error', err
);
427 this.emit('data', packet
.data
);
428 this.emit('message', packet
.data
);
432 debug('packet received with socket readyState "%s"', this.readyState
);
437 * Called upon handshake completion.
439 * @param {Object} handshake obj
443 Socket
.prototype.onHandshake = function (data
) {
444 this.emit('handshake', data
);
446 this.transport
.query
.sid
= data
.sid
;
447 this.upgrades
= this.filterUpgrades(data
.upgrades
);
448 this.pingInterval
= data
.pingInterval
;
449 this.pingTimeout
= data
.pingTimeout
;
451 // In case open handler closes socket
452 if ('closed' == this.readyState
) return;
455 // Prolong liveness of socket on heartbeat
456 this.removeListener('heartbeat', this.onHeartbeat
);
457 this.on('heartbeat', this.onHeartbeat
);
461 * Resets ping timeout.
466 Socket
.prototype.onHeartbeat = function (timeout
) {
467 clearTimeout(this.pingTimeoutTimer
);
469 self
.pingTimeoutTimer
= setTimeout(function () {
470 if ('closed' == self
.readyState
) return;
471 self
.onClose('ping timeout');
472 }, timeout
|| (self
.pingInterval
+ self
.pingTimeout
));
476 * Pings server every `this.pingInterval` and expects response
477 * within `this.pingTimeout` or closes connection.
482 Socket
.prototype.setPing = function () {
484 clearTimeout(self
.pingIntervalTimer
);
485 self
.pingIntervalTimer
= setTimeout(function () {
486 debug('writing ping packet - expecting pong within %sms', self
.pingTimeout
);
488 self
.onHeartbeat(self
.pingTimeout
);
489 }, self
.pingInterval
);
493 * Sends a ping packet.
498 Socket
.prototype.ping = function () {
499 this.sendPacket('ping');
503 * Called on `drain` event
508 Socket
.prototype.onDrain = function() {
509 for (var i
= 0; i
< this.prevBufferLen
; i
++) {
510 if (this.callbackBuffer
[i
]) {
511 this.callbackBuffer
[i
]();
515 this.writeBuffer
.splice(0, this.prevBufferLen
);
516 this.callbackBuffer
.splice(0, this.prevBufferLen
);
518 // setting prevBufferLen = 0 is very important
519 // for example, when upgrading, upgrade packet is sent over,
520 // and a nonzero prevBufferLen could cause problems on `drain`
521 this.prevBufferLen
= 0;
523 if (this.writeBuffer
.length
== 0) {
531 * Flush write buffers.
536 Socket
.prototype.flush = function () {
537 if ('closed' != this.readyState
&& this.transport
.writable
&&
538 !this.upgrading
&& this.writeBuffer
.length
) {
539 debug('flushing %d packets in socket', this.writeBuffer
.length
);
540 this.transport
.send(this.writeBuffer
);
541 // keep track of current length of writeBuffer
542 // splice writeBuffer and callbackBuffer on `drain`
543 this.prevBufferLen
= this.writeBuffer
.length
;
551 * @param {String} message.
552 * @param {Function} callback function.
553 * @return {Socket} for chaining.
557 Socket
.prototype.write
=
558 Socket
.prototype.send = function (msg
, fn
) {
559 this.sendPacket('message', msg
, fn
);
566 * @param {String} packet type.
567 * @param {String} data.
568 * @param {Function} callback function.
572 Socket
.prototype.sendPacket = function (type
, data
, fn
) {
573 var packet
= { type
: type
, data
: data
};
574 this.emit('packetCreate', packet
);
575 this.writeBuffer
.push(packet
);
576 this.callbackBuffer
.push(fn
);
581 * Closes the connection.
586 Socket
.prototype.close = function () {
587 if ('opening' == this.readyState
|| 'open' == this.readyState
) {
588 this.onClose('forced close');
589 debug('socket closing - telling transport to close');
590 this.transport
.close();
597 * Called upon transport error
602 Socket
.prototype.onError = function (err
) {
603 debug('socket error %j', err
);
604 Socket
.priorWebsocketSuccess
= false;
605 this.emit('error', err
);
606 this.onClose('transport error', err
);
610 * Called upon transport close.
615 Socket
.prototype.onClose = function (reason
, desc
) {
616 if ('opening' == this.readyState
|| 'open' == this.readyState
) {
617 debug('socket close with reason: "%s"', reason
);
621 clearTimeout(this.pingIntervalTimer
);
622 clearTimeout(this.pingTimeoutTimer
);
624 // clean buffers in next tick, so developers can still
625 // grab the buffers on `close` event
626 setTimeout(function() {
627 self
.writeBuffer
= [];
628 self
.callbackBuffer
= [];
629 self
.prevBufferLen
= 0;
632 // stop event from firing again for transport
633 this.transport
.removeAllListeners('close');
635 // ensure transport won't stay open
636 this.transport
.close();
638 // ignore further transport communication
639 this.transport
.removeAllListeners();
642 this.readyState
= 'closed';
648 this.emit('close', reason
, desc
);
653 * Filters upgrades, returning only those matching client transports.
655 * @param {Array} server upgrades
660 Socket
.prototype.filterUpgrades = function (upgrades
) {
661 var filteredUpgrades
= [];
662 for (var i
= 0, j
= upgrades
.length
; i
<j
; i
++) {
663 if (~index(this.transports
, upgrades
[i
])) filteredUpgrades
.push(upgrades
[i
]);
665 return filteredUpgrades
;
668 }).call(this,typeof self
!== "undefined" ? self
: typeof window
!== "undefined" ? window
: {})
669 },{"./transport":4,"./transports":5,"component-emitter":12,"debug":14,"engine.io-parser":15,"indexof":23,"parsejson":24,"parseqs":25,"parseuri":26}],4:[function(_dereq_
,mod
,exports
){
674 var parser
= _dereq_('engine.io-parser');
675 var Emitter
= _dereq_('component-emitter');
681 mod
.exports
= Transport
;
684 * Transport abstract constructor.
686 * @param {Object} options.
690 function Transport (opts
) {
691 this.path
= opts
.path
;
692 this.hostname
= opts
.hostname
;
693 this.port
= opts
.port
;
694 this.secure
= opts
.secure
;
695 this.query
= opts
.query
;
696 this.timestampParam
= opts
.timestampParam
;
697 this.timestampRequests
= opts
.timestampRequests
;
698 this.readyState
= '';
699 this.agent
= opts
.agent
|| false;
700 this.socket
= opts
.socket
;
701 this.enablesXDR
= opts
.enablesXDR
;
708 Emitter(Transport
.prototype);
711 * A counter used to prevent collisions in the timestamps used
715 Transport
.timestamps
= 0;
720 * @param {String} str
721 * @return {Transport} for chaining
725 Transport
.prototype.onError = function (msg
, desc
) {
726 var err
= new Error(msg
);
727 err
.type
= 'TransportError';
728 err
.description
= desc
;
729 this.emit('error', err
);
734 * Opens the transport.
739 Transport
.prototype.open = function () {
740 if ('closed' == this.readyState
|| '' == this.readyState
) {
741 this.readyState
= 'opening';
749 * Closes the transport.
754 Transport
.prototype.close = function () {
755 if ('opening' == this.readyState
|| 'open' == this.readyState
) {
764 * Sends multiple packets.
766 * @param {Array} packets
770 Transport
.prototype.send = function(packets
){
771 if ('open' == this.readyState
) {
774 throw new Error('Transport not open');
784 Transport
.prototype.onOpen = function () {
785 this.readyState
= 'open';
786 this.writable
= true;
793 * @param {String} data
797 Transport
.prototype.onData = function(data
){
798 var packet
= parser
.decodePacket(data
, this.socket
.binaryType
);
799 this.onPacket(packet
);
803 * Called with a decoded packet.
806 Transport
.prototype.onPacket = function (packet
) {
807 this.emit('packet', packet
);
816 Transport
.prototype.onClose = function () {
817 this.readyState
= 'closed';
821 },{"component-emitter":12,"engine.io-parser":15}],5:[function(_dereq_
,mod
,exports
){
827 var XMLHttpRequest
= _dereq_('xmlhttprequest');
828 var XHR
= _dereq_('./polling-xhr');
829 var JSONP
= _dereq_('./polling-jsonp');
830 var websocket
= _dereq_('./websocket');
836 exports
.polling
= polling
;
837 exports
.websocket
= websocket
;
840 * Polling transport polymorphic constructor.
841 * Decides on xhr vs jsonp based on feature detection.
846 function polling(opts
){
850 var jsonp
= false !== opts
.jsonp
;
852 if (global
.location
) {
853 var isSSL
= 'https:' == location
.protocol
;
854 var port
= location
.port
;
856 // some user agents have empty `location.port`
858 port
= isSSL
? 443 : 80;
861 xd
= opts
.hostname
!= location
.hostname
|| port
!= opts
.port
;
862 xs
= opts
.secure
!= isSSL
;
867 xhr
= new XMLHttpRequest(opts
);
869 if ('open' in xhr
&& !opts
.forceJSONP
) {
870 return new XHR(opts
);
872 if (!jsonp
) throw new Error('JSONP disabled');
873 return new JSONP(opts
);
877 }).call(this,typeof self
!== "undefined" ? self
: typeof window
!== "undefined" ? window
: {})
878 },{"./polling-jsonp":6,"./polling-xhr":7,"./websocket":9,"xmlhttprequest":10}],6:[function(_dereq_
,mod
,exports
){
885 var Polling
= _dereq_('./polling');
886 var inherit
= _dereq_('component-inherit');
892 mod
.exports
= JSONPPolling
;
895 * Cached regular expressions.
898 var rNewline
= /\n/g;
899 var rEscapedNewline
= /\\n/g;
902 * Global JSONP callbacks.
917 function empty () { }
920 * JSONP Polling constructor.
922 * @param {Object} opts.
926 function JSONPPolling (opts
) {
927 Polling
.call(this, opts
);
929 this.query
= this.query
|| {};
931 // define global callbacks array if not present
932 // we do this here (lazily) to avoid unneeded global pollution
934 // we need to consider multiple engines in the same page
935 if (!global
.___eio
) global
.___eio
= [];
936 callbacks
= global
.___eio
;
939 // callback identifier
940 this.index
= callbacks
.length
;
942 // add callback to jsonp global
944 callbacks
.push(function (msg
) {
948 // append to query string
949 this.query
.j
= this.index
;
951 // prevent spurious errors from being emitted when the window is unloaded
952 if (global
.document
&& global
.addEventListener
) {
953 global
.addEventListener('beforeunload', function () {
954 if (self
.script
) self
.script
.onerror
= empty
;
960 * Inherits from Polling.
963 inherit(JSONPPolling
, Polling
);
966 * JSONP only supports binary as base64 encoded strings
969 JSONPPolling
.prototype.supportsBinary
= false;
977 JSONPPolling
.prototype.doClose = function () {
979 this.script
.parentNode
.removeChild(this.script
);
984 this.form
.parentNode
.removeChild(this.form
);
988 Polling
.prototype.doClose
.call(this);
992 * Starts a poll cycle.
997 JSONPPolling
.prototype.doPoll = function () {
999 var script
= document
.createElement('script');
1002 this.script
.parentNode
.removeChild(this.script
);
1006 script
.async
= true;
1007 script
.src
= this.uri();
1008 script
.onerror = function(e
){
1009 self
.onError('jsonp poll error',e
);
1012 var insertAt
= document
.getElementsByTagName('script')[0];
1013 insertAt
.parentNode
.insertBefore(script
, insertAt
);
1014 this.script
= script
;
1016 var isUAgecko
= 'undefined' != typeof navigator
&& /gecko/i.test(navigator
.userAgent
);
1019 setTimeout(function () {
1020 var iframe
= document
.createElement('iframe');
1021 document
.body
.appendChild(iframe
);
1022 document
.body
.removeChild(iframe
);
1028 * Writes with a hidden iframe.
1030 * @param {String} data to send
1031 * @param {Function} called upon flush.
1035 JSONPPolling
.prototype.doWrite = function (data
, fn
) {
1039 var form
= document
.createElement('form');
1040 var area
= document
.createElement('textarea');
1041 var id
= this.iframeId
= 'eio_iframe_' + this.index
;
1044 form
.className
= 'socketio';
1045 form
.style
.position
= 'absolute';
1046 form
.style
.top
= '-1000px';
1047 form
.style
.left
= '-1000px';
1049 form
.method
= 'POST';
1050 form
.setAttribute('accept-charset', 'utf-8');
1052 form
.appendChild(area
);
1053 document
.body
.appendChild(form
);
1059 this.form
.action
= this.uri();
1061 function complete () {
1066 function initIframe () {
1069 self
.form
.removeChild(self
.iframe
);
1071 self
.onError('jsonp polling iframe removal error', e
);
1076 // ie6 dynamic iframes with target="" support (thanks Chris Lambacher)
1077 var html
= '<iframe src="javascript:0" name="'+ self
.iframeId
+'">';
1078 iframe
= document
.createElement(html
);
1080 iframe
= document
.createElement('iframe');
1081 iframe
.name
= self
.iframeId
;
1082 iframe
.src
= 'javascript:0';
1085 iframe
.id
= self
.iframeId
;
1087 self
.form
.appendChild(iframe
);
1088 self
.iframe
= iframe
;
1093 // escape \n to prevent it from being converted into \r\n by some UAs
1094 // double escaping is required for escaped new lines because unescaping of new lines can be done safely on server-side
1095 data
= data
.replace(rEscapedNewline
, '\\\n');
1096 this.area
.value
= data
.replace(rNewline
, '\\n');
1102 if (this.iframe
.attachEvent
) {
1103 this.iframe
.onreadystatechange = function(){
1104 if (self
.iframe
.readyState
== 'complete') {
1109 this.iframe
.onload
= complete
;
1113 }).call(this,typeof self
!== "undefined" ? self
: typeof window
!== "undefined" ? window
: {})
1114 },{"./polling":8,"component-inherit":13}],7:[function(_dereq_
,mod
,exports
){
1120 var XMLHttpRequest
= _dereq_('xmlhttprequest');
1121 var Polling
= _dereq_('./polling');
1122 var Emitter
= _dereq_('component-emitter');
1123 var inherit
= _dereq_('component-inherit');
1124 var debug
= _dereq_('debug')('engine.io-client:polling-xhr');
1131 mod
.exports
.Request
= Request
;
1140 * XHR Polling constructor.
1142 * @param {Object} opts
1147 Polling
.call(this, opts
);
1149 if (global
.location
) {
1150 var isSSL
= 'https:' == location
.protocol
;
1151 var port
= location
.port
;
1153 // some user agents have empty `location.port`
1155 port
= isSSL
? 443 : 80;
1158 this.xd
= opts
.hostname
!= global
.location
.hostname
||
1160 this.xs
= opts
.secure
!= isSSL
;
1165 * Inherits from Polling.
1168 inherit(XHR
, Polling
);
1171 * XHR supports binary
1174 XHR
.prototype.supportsBinary
= true;
1177 * Creates a request.
1179 * @param {String} method
1183 XHR
.prototype.request = function(opts
){
1185 opts
.uri
= this.uri();
1188 opts
.agent
= this.agent
|| false;
1189 opts
.supportsBinary
= this.supportsBinary
;
1190 opts
.enablesXDR
= this.enablesXDR
;
1191 return new Request(opts
);
1197 * @param {String} data to send.
1198 * @param {Function} called upon flush.
1202 XHR
.prototype.doWrite = function(data
, fn
){
1203 var isBinary
= typeof data
!== 'string' && data
!== undefined;
1204 var req
= this.request({ method
: 'POST', data
: data
, isBinary
: isBinary
});
1206 req
.on('success', fn
);
1207 req
.on('error', function(err
){
1208 self
.onError('xhr post error', err
);
1214 * Starts a poll cycle.
1219 XHR
.prototype.doPoll = function(){
1221 var req
= this.request();
1223 req
.on('data', function(data
){
1226 req
.on('error', function(err
){
1227 self
.onError('xhr poll error', err
);
1233 * Request constructor
1235 * @param {Object} options
1239 function Request(opts
){
1240 this.method
= opts
.method
|| 'GET';
1241 this.uri
= opts
.uri
;
1242 this.xd
= !!opts
.xd
;
1243 this.xs
= !!opts
.xs
;
1244 this.async
= false !== opts
.async
;
1245 this.data
= undefined != opts
.data
? opts
.data
: null;
1246 this.agent
= opts
.agent
;
1247 this.isBinary
= opts
.isBinary
;
1248 this.supportsBinary
= opts
.supportsBinary
;
1249 this.enablesXDR
= opts
.enablesXDR
;
1257 Emitter(Request
.prototype);
1260 * Creates the XHR object and sends the request.
1265 Request
.prototype.create = function(){
1266 var xhr
= this.xhr
= new XMLHttpRequest({ agent
: this.agent
, xdomain
: this.xd
, xscheme
: this.xs
, enablesXDR
: this.enablesXDR
});
1270 debug('xhr open %s: %s', this.method
, this.uri
);
1271 xhr
.open(this.method
, this.uri
, this.async
);
1272 if (this.supportsBinary
) {
1273 // This has to be done after open because Firefox is stupid
1274 // http://stackoverflow.com/questions/13216903/get-binary-data-with-xmlhttprequest-in-a-firefox-extension
1275 xhr
.responseType
= 'arraybuffer';
1278 if ('POST' == this.method
) {
1280 if (this.isBinary
) {
1281 xhr
.setRequestHeader('Content-type', 'application/octet-stream');
1283 xhr
.setRequestHeader('Content-type', 'text/plain;charset=UTF-8');
1289 if ('withCredentials' in xhr
) {
1290 xhr
.withCredentials
= true;
1293 if (this.hasXDR()) {
1294 xhr
.onload = function(){
1297 xhr
.onerror = function(){
1298 self
.onError(xhr
.responseText
);
1301 xhr
.onreadystatechange = function(){
1302 if (4 != xhr
.readyState
) return;
1303 if (200 == xhr
.status
|| 1223 == xhr
.status
) {
1306 // make sure the `error` event handler that's user-set
1307 // does not throw in the same tick and gets caught here
1308 setTimeout(function(){
1309 self
.onError(xhr
.status
);
1315 debug('xhr data %s', this.data
);
1316 xhr
.send(this.data
);
1318 // Need to defer since .create() is called directly fhrom the constructor
1319 // and thus the 'error' event can only be only bound *after* this exception
1320 // occurs. Therefore, also, we cannot throw here at all.
1321 setTimeout(function() {
1327 if (global
.document
) {
1328 this.index
= Request
.requestsCount
++;
1329 Request
.requests
[this.index
] = this;
1334 * Called upon successful response.
1339 Request
.prototype.onSuccess = function(){
1340 this.emit('success');
1345 * Called if we have data.
1350 Request
.prototype.onData = function(data
){
1351 this.emit('data', data
);
1356 * Called upon error.
1361 Request
.prototype.onError = function(err
){
1362 this.emit('error', err
);
1372 Request
.prototype.cleanup = function(){
1373 if ('undefined' == typeof this.xhr
|| null === this.xhr
) {
1377 if (this.hasXDR()) {
1378 this.xhr
.onload
= this.xhr
.onerror
= empty
;
1380 this.xhr
.onreadystatechange
= empty
;
1387 if (global
.document
) {
1388 delete Request
.requests
[this.index
];
1400 Request
.prototype.onLoad = function(){
1405 contentType
= this.xhr
.getResponseHeader('Content-Type');
1407 if (contentType
=== 'application/octet-stream') {
1408 data
= this.xhr
.response
;
1410 if (!this.supportsBinary
) {
1411 data
= this.xhr
.responseText
;
1425 * Check if it has XDomainRequest.
1430 Request
.prototype.hasXDR = function(){
1431 return 'undefined' !== typeof global
.XDomainRequest
&& !this.xs
&& this.enablesXDR
;
1435 * Aborts the request.
1440 Request
.prototype.abort = function(){
1445 * Aborts pending requests when unloading the window. This is needed to prevent
1446 * memory leaks (e.g. when using IE) and to ensure that no spurious error is
1450 if (global
.document
) {
1451 Request
.requestsCount
= 0;
1452 Request
.requests
= {};
1453 if (global
.attachEvent
) {
1454 global
.attachEvent('onunload', unloadHandler
);
1455 } else if (global
.addEventListener
) {
1456 global
.addEventListener('beforeunload', unloadHandler
);
1460 function unloadHandler() {
1461 for (var i
in Request
.requests
) {
1462 if (Request
.requests
.hasOwnProperty(i
)) {
1463 Request
.requests
[i
].abort();
1468 }).call(this,typeof self
!== "undefined" ? self
: typeof window
!== "undefined" ? window
: {})
1469 },{"./polling":8,"component-emitter":12,"component-inherit":13,"debug":14,"xmlhttprequest":10}],8:[function(_dereq_
,mod
,exports
){
1474 var Transport
= _dereq_('../transport');
1475 var parseqs
= _dereq_('parseqs');
1476 var parser
= _dereq_('engine.io-parser');
1477 var inherit
= _dereq_('component-inherit');
1478 var debug
= _dereq_('debug')('engine.io-client:polling');
1484 mod
.exports
= Polling
;
1487 * Is XHR2 supported?
1490 var hasXHR2
= (function() {
1491 var XMLHttpRequest
= _dereq_('xmlhttprequest');
1492 var xhr
= new XMLHttpRequest({ agent
: this.agent
, xdomain
: false });
1493 return null != xhr
.responseType
;
1497 * Polling interface.
1499 * @param {Object} opts
1503 function Polling(opts
){
1504 var forceBase64
= (opts
&& opts
.forceBase64
);
1505 if (!hasXHR2
|| forceBase64
) {
1506 this.supportsBinary
= false;
1508 Transport
.call(this, opts
);
1512 * Inherits from Transport.
1515 inherit(Polling
, Transport
);
1521 Polling
.prototype.name
= 'polling';
1524 * Opens the socket (triggers polling). We write a PING message to determine
1525 * when the transport is open.
1530 Polling
.prototype.doOpen = function(){
1537 * @param {Function} callback upon buffers are flushed and transport is paused
1541 Polling
.prototype.pause = function(onPause
){
1545 this.readyState
= 'pausing';
1549 self
.readyState
= 'paused';
1553 if (this.polling
|| !this.writable
) {
1557 debug('we are currently polling - waiting to pause');
1559 this.once('pollComplete', function(){
1560 debug('pre-pause polling complete');
1565 if (!this.writable
) {
1566 debug('we are currently writing - waiting to pause');
1568 this.once('drain', function(){
1569 debug('pre-pause writing complete');
1579 * Starts polling cycle.
1584 Polling
.prototype.poll = function(){
1586 this.polling
= true;
1592 * Overloads onData to detect payloads.
1597 Polling
.prototype.onData = function(data
){
1599 debug('polling got data %s', data
);
1600 var callback = function(packet
, index
, total
) {
1601 // if its the first message we consider the transport open
1602 if ('opening' == self
.readyState
) {
1606 // if its a close packet, we close the ongoing requests
1607 if ('close' == packet
.type
) {
1612 // otherwise bypass onData and handle the message
1613 self
.onPacket(packet
);
1617 parser
.decodePayload(data
, this.socket
.binaryType
, callback
);
1619 // if an event did not trigger closing
1620 if ('closed' != this.readyState
) {
1621 // if we got data we're not polling
1622 this.polling
= false;
1623 this.emit('pollComplete');
1625 if ('open' == this.readyState
) {
1628 debug('ignoring poll - transport state "%s"', this.readyState
);
1634 * For polling, send a close packet.
1639 Polling
.prototype.doClose = function(){
1643 debug('writing close packet');
1644 self
.write([{ type
: 'close' }]);
1647 if ('open' == this.readyState
) {
1648 debug('transport open - closing');
1651 // in case we're trying to close while
1652 // handshaking is in progress (GH-164)
1653 debug('transport not open - deferring close');
1654 this.once('open', close
);
1659 * Writes a packets payload.
1661 * @param {Array} data packets
1662 * @param {Function} drain callback
1666 Polling
.prototype.write = function(packets
){
1668 this.writable
= false;
1669 var callbackfn = function() {
1670 self
.writable
= true;
1675 parser
.encodePayload(packets
, this.supportsBinary
, function(data
) {
1676 self
.doWrite(data
, callbackfn
);
1681 * Generates uri for connection.
1686 Polling
.prototype.uri = function(){
1687 var query
= this.query
|| {};
1688 var schema
= this.secure
? 'https' : 'http';
1691 // cache busting is forced
1692 if (false !== this.timestampRequests
) {
1693 query
[this.timestampParam
] = +new Date
+ '-' + Transport
.timestamps
++;
1696 if (!this.supportsBinary
&& !query
.sid
) {
1700 query
= parseqs
.encode(query
);
1702 // avoid port if default for schema
1703 if (this.port
&& (('https' == schema
&& this.port
!= 443) ||
1704 ('http' == schema
&& this.port
!= 80))) {
1705 port
= ':' + this.port
;
1708 // prepend ? to query
1710 query
= '?' + query
;
1713 return schema
+ '://' + this.hostname
+ port
+ this.path
+ query
;
1716 },{"../transport":4,"component-inherit":13,"debug":14,"engine.io-parser":15,"parseqs":25,"xmlhttprequest":10}],9:[function(_dereq_
,mod
,exports
){
1721 var Transport
= _dereq_('../transport');
1722 var parser
= _dereq_('engine.io-parser');
1723 var parseqs
= _dereq_('parseqs');
1724 var inherit
= _dereq_('component-inherit');
1725 var debug
= _dereq_('debug')('engine.io-client:websocket');
1728 * `ws` exposes a WebSocket-compatible interface in
1729 * Node, or the `WebSocket` or `MozWebSocket` globals
1733 var WebSocket
= _dereq_('ws');
1742 * WebSocket transport constructor.
1744 * @api {Object} connection options
1749 var forceBase64
= (opts
&& opts
.forceBase64
);
1751 this.supportsBinary
= false;
1753 Transport
.call(this, opts
);
1757 * Inherits from Transport.
1760 inherit(WS
, Transport
);
1768 WS
.prototype.name
= 'websocket';
1771 * WebSockets support binary
1774 WS
.prototype.supportsBinary
= true;
1782 WS
.prototype.doOpen = function(){
1783 if (!this.check()) {
1784 // let probe timeout
1789 var uri
= this.uri();
1790 var protocols
= void(0);
1791 var opts
= { agent
: this.agent
};
1793 this.ws
= new WebSocket(uri
, protocols
, opts
);
1795 if (this.ws
.binaryType
=== undefined) {
1796 this.supportsBinary
= false;
1799 this.ws
.binaryType
= 'arraybuffer';
1800 this.addEventListeners();
1804 * Adds event listeners to the socket
1809 WS
.prototype.addEventListeners = function(){
1812 this.ws
.onopen = function(){
1815 this.ws
.onclose = function(){
1818 this.ws
.onmessage = function(ev
){
1819 self
.onData(ev
.data
);
1821 this.ws
.onerror = function(e
){
1822 self
.onError('websocket error', e
);
1827 * Override `onData` to use a timer on iOS.
1828 * See: https://gist.github.com/mloughran/2052006
1833 if ('undefined' != typeof navigator
1834 && /iPad|iPhone|iPod/i.test(navigator
.userAgent
)) {
1835 WS
.prototype.onData = function(data
){
1837 setTimeout(function(){
1838 Transport
.prototype.onData
.call(self
, data
);
1844 * Writes data to socket.
1846 * @param {Array} array of packets.
1850 WS
.prototype.write = function(packets
){
1852 this.writable
= false;
1853 // encodePacket efficient as it uses WS framing
1854 // no need for encodePayload
1855 for (var i
= 0, l
= packets
.length
; i
< l
; i
++) {
1856 parser
.encodePacket(packets
[i
], this.supportsBinary
, function(data
) {
1857 //Sometimes the websocket has already been closed but the browser didn't
1858 //have a chance of informing us about it yet, in that case send will
1863 debug('websocket closed before onclose event');
1868 function ondrain() {
1869 self
.writable
= true;
1873 // defer to next tick to allow Socket to clear writeBuffer
1874 setTimeout(ondrain
, 0);
1883 WS
.prototype.onClose = function(){
1884 Transport
.prototype.onClose
.call(this);
1893 WS
.prototype.doClose = function(){
1894 if (typeof this.ws
!== 'undefined') {
1900 * Generates uri for connection.
1905 WS
.prototype.uri = function(){
1906 var query
= this.query
|| {};
1907 var schema
= this.secure
? 'wss' : 'ws';
1910 // avoid port if default for schema
1911 if (this.port
&& (('wss' == schema
&& this.port
!= 443)
1912 || ('ws' == schema
&& this.port
!= 80))) {
1913 port
= ':' + this.port
;
1916 // append timestamp to URI
1917 if (this.timestampRequests
) {
1918 query
[this.timestampParam
] = +new Date
;
1921 // communicate binary support capabilities
1922 if (!this.supportsBinary
) {
1926 query
= parseqs
.encode(query
);
1928 // prepend ? to query
1930 query
= '?' + query
;
1933 return schema
+ '://' + this.hostname
+ port
+ this.path
+ query
;
1937 * Feature detection for WebSocket.
1939 * @return {Boolean} whether this transport is available.
1943 WS
.prototype.check = function(){
1944 return !!WebSocket
&& !('__initialize' in WebSocket
&& this.name
=== WS
.prototype.name
);
1947 },{"../transport":4,"component-inherit":13,"debug":14,"engine.io-parser":15,"parseqs":25,"ws":27}],10:[function(_dereq_
,mod
,exports
){
1948 // browser shim for xmlhttprequest mod
1949 var hasCORS
= _dereq_('has-cors');
1951 mod
.exports = function(opts
) {
1952 var xdomain
= opts
.xdomain
;
1954 // scheme must be same when usign XDomainRequest
1955 // http://blogs.msdn.com/b/ieinternals/archive/2010/05/13/xdomainrequest-restrictions-limitations-and-workarounds.aspx
1956 var xscheme
= opts
.xscheme
;
1958 // XDomainRequest has a flow of not sending cookie, therefore it should be disabled as a default.
1959 // https://github.com/Automattic/engine.io-client/pull/217
1960 var enablesXDR
= opts
.enablesXDR
;
1962 // Use XDomainRequest for IE8 if enablesXDR is true
1963 // because loading bar keeps flashing when using jsonp-polling
1964 // https://github.com/yujiosaka/socke.io-ie8-loading-example
1966 if ('undefined' != typeof XDomainRequest
&& !xscheme
&& enablesXDR
) {
1967 return new XDomainRequest();
1971 // XMLHttpRequest can be disabled on IE
1973 if ('undefined' != typeof XMLHttpRequest
&& (!xdomain
|| hasCORS
)) {
1974 return new XMLHttpRequest();
1980 return new ActiveXObject('Microsoft.XMLHTTP');
1985 },{"has-cors":21}],11:[function(_dereq_
,mod
,exports
){
1988 * Create a blob builder even when vendor prefixes exist
1991 var BlobBuilder
= global
.BlobBuilder
1992 || global
.WebKitBlobBuilder
1993 || global
.MSBlobBuilder
1994 || global
.MozBlobBuilder
;
1997 * Check if Blob constructor is supported
2000 var blobSupported
= (function() {
2002 var b
= new Blob(['hi']);
2010 * Check if BlobBuilder is supported
2013 var blobBuilderSupported
= BlobBuilder
2014 && BlobBuilder
.prototype.append
2015 && BlobBuilder
.prototype.getBlob
;
2017 function BlobBuilderConstructor(ary
, options
) {
2018 options
= options
|| {};
2020 var bb
= new BlobBuilder();
2021 for (var i
= 0; i
< ary
.length
; i
++) {
2024 return (options
.type
) ? bb
.getBlob(options
.type
) : bb
.getBlob();
2027 mod
.exports
= (function() {
2028 if (blobSupported
) {
2030 } else if (blobBuilderSupported
) {
2031 return BlobBuilderConstructor
;
2037 }).call(this,typeof self
!== "undefined" ? self
: typeof window
!== "undefined" ? window
: {})
2038 },{}],12:[function(_dereq_
,mod
,exports
){
2044 mod
.exports
= Emitter
;
2047 * Initialize a new `Emitter`.
2052 function Emitter(obj
) {
2053 if (obj
) return mixin(obj
);
2057 * Mixin the emitter properties.
2059 * @param {Object} obj
2064 function mixin(obj
) {
2065 for (var key
in Emitter
.prototype) {
2066 obj
[key
] = Emitter
.prototype[key
];
2072 * Listen on the given `event` with `fn`.
2074 * @param {String} event
2075 * @param {Function} fn
2080 Emitter
.prototype.on
=
2081 Emitter
.prototype.addEventListener = function(event
, fn
){
2082 this._callbacks
= this._callbacks
|| {};
2083 (this._callbacks
[event
] = this._callbacks
[event
] || [])
2089 * Adds an `event` listener that will be invoked a single
2090 * time then automatically removed.
2092 * @param {String} event
2093 * @param {Function} fn
2098 Emitter
.prototype.once = function(event
, fn
){
2100 this._callbacks
= this._callbacks
|| {};
2103 self
.off(event
, on
);
2104 fn
.apply(this, arguments
);
2113 * Remove the given callback for `event` or all
2114 * registered callbacks.
2116 * @param {String} event
2117 * @param {Function} fn
2122 Emitter
.prototype.off
=
2123 Emitter
.prototype.removeListener
=
2124 Emitter
.prototype.removeAllListeners
=
2125 Emitter
.prototype.removeEventListener = function(event
, fn
){
2126 this._callbacks
= this._callbacks
|| {};
2129 if (0 == arguments
.length
) {
2130 this._callbacks
= {};
2135 var callbacks
= this._callbacks
[event
];
2136 if (!callbacks
) return this;
2138 // remove all handlers
2139 if (1 == arguments
.length
) {
2140 delete this._callbacks
[event
];
2144 // remove specific handler
2146 for (var i
= 0; i
< callbacks
.length
; i
++) {
2148 if (cb
=== fn
|| cb
.fn
=== fn
) {
2149 callbacks
.splice(i
, 1);
2157 * Emit `event` with the given args.
2159 * @param {String} event
2160 * @param {Mixed} ...
2164 Emitter
.prototype.emit = function(event
){
2165 this._callbacks
= this._callbacks
|| {};
2166 var args
= [].slice
.call(arguments
, 1)
2167 , callbacks
= this._callbacks
[event
];
2170 callbacks
= callbacks
.slice(0);
2171 for (var i
= 0, len
= callbacks
.length
; i
< len
; ++i
) {
2172 callbacks
[i
].apply(this, args
);
2180 * Return array of callbacks for `event`.
2182 * @param {String} event
2187 Emitter
.prototype.listeners = function(event
){
2188 this._callbacks
= this._callbacks
|| {};
2189 return this._callbacks
[event
] || [];
2193 * Check if this emitter has `event` handlers.
2195 * @param {String} event
2200 Emitter
.prototype.hasListeners = function(event
){
2201 return !! this.listeners(event
).length
;
2204 },{}],13:[function(_dereq_
,mod
,exports
){
2206 mod
.exports = function(a
, b
){
2207 var fn = function(){};
2208 fn
.prototype = b
.prototype;
2209 a
.prototype = new fn
;
2210 a
.prototype.constructor = a
;
2212 },{}],14:[function(_dereq_
,mod
,exports
){
2215 * Expose `debug()` as the mod.
2218 mod
.exports
= debug
;
2221 * Create a debugger with the given `name`.
2223 * @param {String} name
2228 function debug(name
) {
2229 if (!debug
.enabled(name
)) return function(){};
2231 return function(fmt
){
2234 var curr
= new Date
;
2235 var ms
= curr
- (debug
[name
] || curr
);
2241 + ' +' + debug
.humanize(ms
);
2243 // This hackery is required for IE8
2244 // where `console.log` doesn't have 'apply'
2247 && Function
.prototype.apply
.call(console
.log
, console
, arguments
);
2252 * The currently active debug mode names.
2259 * Enables a debug mode by name. This can include modes
2260 * separated by a colon and wildcards.
2262 * @param {String} name
2266 debug
.enable = function(name
) {
2268 localStorage
.debug
= name
;
2271 var split
= (name
|| '').split(/[\s,]+/)
2272 , len
= split
.length
;
2274 for (var i
= 0; i
< len
; i
++) {
2275 name
= split
[i
].replace('*', '.*?');
2276 if (name
[0] === '-') {
2277 debug
.skips
.push(new RegExp('^' + name
.substr(1) + '$'));
2280 debug
.names
.push(new RegExp('^' + name
+ '$'));
2286 * Disable debug output.
2291 debug
.disable = function(){
2296 * Humanize the given `ms`.
2303 debug
.humanize = function(ms
) {
2308 if (ms
>= hour
) return (ms
/ hour
).toFixed(1) + 'h';
2309 if (ms
>= min
) return (ms
/ min
).toFixed(1) + 'm';
2310 if (ms
>= sec
) return (ms
/ sec
| 0) + 's';
2315 * Returns true if the given mode name is enabled, false otherwise.
2317 * @param {String} name
2322 debug
.enabled = function(name
) {
2323 for (var i
= 0, len
= debug
.skips
.length
; i
< len
; i
++) {
2324 if (debug
.skips
[i
].test(name
)) {
2328 for (var i
= 0, len
= debug
.names
.length
; i
< len
; i
++) {
2329 if (debug
.names
[i
].test(name
)) {
2340 function coerce(val
) {
2341 if (val
instanceof Error
) return val
.stack
|| val
.message
;
2348 if (window
.localStorage
) debug
.enable(localStorage
.debug
);
2351 },{}],15:[function(_dereq_
,mod
,exports
){
2357 var keys
= _dereq_('./keys');
2358 var sliceBuffer
= _dereq_('arraybuffer.slice');
2359 var base64encoder
= _dereq_('base64-arraybuffer');
2360 var after
= _dereq_('after');
2361 var utf8
= _dereq_('utf8');
2364 * Check if we are running an android browser. That requires us to use
2365 * ArrayBuffer with polling transports...
2367 * http://ghinda.net/jpeg-blob-ajax-android/
2370 var isAndroid
= navigator
.userAgent
.match(/Android/i);
2373 * Current protocol version.
2376 exports
.protocol
= 3;
2382 var packets
= exports
.packets
= {
2384 , close
: 1 // non-ws
2392 var packetslist
= keys(packets
);
2395 * Premade error packet.
2398 var err
= { type
: 'error', data
: 'parser error' };
2401 * Create a blob api even for blob builder when vendor prefixes exist
2404 var Blob
= _dereq_('blob');
2409 * <packet type id> [ <data> ]
2417 * Binary is encoded in an identical principle
2422 exports
.encodePacket = function (packet
, supportsBinary
, utf8encode
, callback
) {
2423 if ('function' == typeof supportsBinary
) {
2424 callback
= supportsBinary
;
2425 supportsBinary
= false;
2428 if ('function' == typeof utf8encode
) {
2429 callback
= utf8encode
;
2433 var data
= (packet
.data
=== undefined)
2435 : packet
.data
.buffer
|| packet
.data
;
2437 if (global
.ArrayBuffer
&& data
instanceof ArrayBuffer
) {
2438 return encodeArrayBuffer(packet
, supportsBinary
, callback
);
2439 } else if (Blob
&& data
instanceof global
.Blob
) {
2440 return encodeBlob(packet
, supportsBinary
, callback
);
2443 // Sending data as a utf-8 string
2444 var encoded
= packets
[packet
.type
];
2446 // data fragment is optional
2447 if (undefined !== packet
.data
) {
2448 encoded
+= utf8encode
? utf8
.encode(String(packet
.data
)) : String(packet
.data
);
2451 return callback('' + encoded
);
2456 * Encode packet helpers for binary types
2459 function encodeArrayBuffer(packet
, supportsBinary
, callback
) {
2460 if (!supportsBinary
) {
2461 return exports
.encodeBase64Packet(packet
, callback
);
2464 var data
= packet
.data
;
2465 var contentArray
= new Uint8Array(data
);
2466 var resultBuffer
= new Uint8Array(1 + data
.byteLength
);
2468 resultBuffer
[0] = packets
[packet
.type
];
2469 for (var i
= 0; i
< contentArray
.length
; i
++) {
2470 resultBuffer
[i
+1] = contentArray
[i
];
2473 return callback(resultBuffer
.buffer
);
2476 function encodeBlobAsArrayBuffer(packet
, supportsBinary
, callback
) {
2477 if (!supportsBinary
) {
2478 return exports
.encodeBase64Packet(packet
, callback
);
2481 var fr
= new FileReader();
2482 fr
.onload = function() {
2483 packet
.data
= fr
.result
;
2484 exports
.encodePacket(packet
, supportsBinary
, true, callback
);
2486 return fr
.readAsArrayBuffer(packet
.data
);
2489 function encodeBlob(packet
, supportsBinary
, callback
) {
2490 if (!supportsBinary
) {
2491 return exports
.encodeBase64Packet(packet
, callback
);
2495 return encodeBlobAsArrayBuffer(packet
, supportsBinary
, callback
);
2498 var length
= new Uint8Array(1);
2499 length
[0] = packets
[packet
.type
];
2500 var blob
= new Blob([length
.buffer
, packet
.data
]);
2502 return callback(blob
);
2506 * Encodes a packet with binary data in a base64 string
2508 * @param {Object} packet, has `type` and `data`
2509 * @return {String} base64 encoded message
2512 exports
.encodeBase64Packet = function(packet
, callback
) {
2513 var message
= 'b' + exports
.packets
[packet
.type
];
2514 if (Blob
&& packet
.data
instanceof Blob
) {
2515 var fr
= new FileReader();
2516 fr
.onload = function() {
2517 var b64
= fr
.result
.split(',')[1];
2518 callback(message
+ b64
);
2520 return fr
.readAsDataURL(packet
.data
);
2525 b64data
= String
.fromCharCode
.apply(null, new Uint8Array(packet
.data
));
2527 // iPhone Safari doesn't let you apply with typed arrays
2528 var typed
= new Uint8Array(packet
.data
);
2529 var basic
= new Array(typed
.length
);
2530 for (var i
= 0; i
< typed
.length
; i
++) {
2531 basic
[i
] = typed
[i
];
2533 b64data
= String
.fromCharCode
.apply(null, basic
);
2535 message
+= global
.btoa(b64data
);
2536 return callback(message
);
2540 * Decodes a packet. Changes format to Blob if requested.
2542 * @return {Object} with `type` and `data` (if any)
2546 exports
.decodePacket = function (data
, binaryType
, utf8decode
) {
2548 if (typeof data
== 'string' || data
=== undefined) {
2549 if (data
.charAt(0) == 'b') {
2550 return exports
.decodeBase64Packet(data
.substr(1), binaryType
);
2555 data
= utf8
.decode(data
);
2560 var type
= data
.charAt(0);
2562 if (Number(type
) != type
|| !packetslist
[type
]) {
2566 if (data
.length
> 1) {
2567 return { type
: packetslist
[type
], data
: data
.substring(1) };
2569 return { type
: packetslist
[type
] };
2573 var asArray
= new Uint8Array(data
);
2574 var type
= asArray
[0];
2575 var rest
= sliceBuffer(data
, 1);
2576 if (Blob
&& binaryType
=== 'blob') {
2577 rest
= new Blob([rest
]);
2579 return { type
: packetslist
[type
], data
: rest
};
2583 * Decodes a packet encoded in a base64 string
2585 * @param {String} base64 encoded message
2586 * @return {Object} with `type` and `data` (if any)
2589 exports
.decodeBase64Packet = function(msg
, binaryType
) {
2590 var type
= packetslist
[msg
.charAt(0)];
2591 if (!global
.ArrayBuffer
) {
2592 return { type
: type
, data
: { base64
: true, data
: msg
.substr(1) } };
2595 var data
= base64encoder
.decode(msg
.substr(1));
2597 if (binaryType
=== 'blob' && Blob
) {
2598 data
= new Blob([data
]);
2601 return { type
: type
, data
: data
};
2605 * Encodes multiple messages (payload).
2611 * 11:hello world2:hi
2613 * If any contents are binary, they will be encoded as base64 strings. Base64
2614 * encoded strings are marked with a b before the length specifier
2616 * @param {Array} packets
2620 exports
.encodePayload = function (packets
, supportsBinary
, callback
) {
2621 if (typeof supportsBinary
== 'function') {
2622 callback
= supportsBinary
;
2623 supportsBinary
= null;
2626 if (supportsBinary
) {
2627 if (Blob
&& !isAndroid
) {
2628 return exports
.encodePayloadAsBlob(packets
, callback
);
2631 return exports
.encodePayloadAsArrayBuffer(packets
, callback
);
2634 if (!packets
.length
) {
2635 return callback('0:');
2638 function setLengthHeader(message
) {
2639 return message
.length
+ ':' + message
;
2642 function encodeOne(packet
, doneCallback
) {
2643 exports
.encodePacket(packet
, supportsBinary
, true, function(message
) {
2644 doneCallback(null, setLengthHeader(message
));
2648 map(packets
, encodeOne
, function(err
, results
) {
2649 return callback(results
.join(''));
2654 * Async array map using after
2657 function map(ary
, each
, done
) {
2658 var result
= new Array(ary
.length
);
2659 var next
= after(ary
.length
, done
);
2661 var eachWithIndex = function(i
, el
, cb
) {
2662 each(el
, function(error
, msg
) {
2668 for (var i
= 0; i
< ary
.length
; i
++) {
2669 eachWithIndex(i
, ary
[i
], next
);
2674 * Decodes data when a payload is maybe expected. Possible binary contents are
2675 * decoded from their base64 representation
2677 * @param {String} data, callback method
2681 exports
.decodePayload = function (data
, binaryType
, callback
) {
2682 if (typeof data
!= 'string') {
2683 return exports
.decodePayloadAsBinary(data
, binaryType
, callback
);
2686 if (typeof binaryType
=== 'function') {
2687 callback
= binaryType
;
2693 // parser error - ignoring payload
2694 return callback(err
, 0, 1);
2700 for (var i
= 0, l
= data
.length
; i
< l
; i
++) {
2701 var chr
= data
.charAt(i
);
2706 if ('' == length
|| (length
!= (n
= Number(length
)))) {
2707 // parser error - ignoring payload
2708 return callback(err
, 0, 1);
2711 msg
= data
.substr(i
+ 1, n
);
2713 if (length
!= msg
.length
) {
2714 // parser error - ignoring payload
2715 return callback(err
, 0, 1);
2719 packet
= exports
.decodePacket(msg
, binaryType
, true);
2721 if (err
.type
== packet
.type
&& err
.data
== packet
.data
) {
2722 // parser error in individual packet - ignoring payload
2723 return callback(err
, 0, 1);
2726 var ret
= callback(packet
, i
+ n
, l
);
2727 if (false === ret
) return;
2737 // parser error - ignoring payload
2738 return callback(err
, 0, 1);
2744 * Encodes multiple messages (payload) as binary.
2746 * <1 = binary, 0 = string><number from 0-9><number from 0-9>[...]<number
2750 * 1 3 255 1 2 3, if the binary contents are interpreted as 8 bit integers
2752 * @param {Array} packets
2753 * @return {ArrayBuffer} encoded payload
2757 exports
.encodePayloadAsArrayBuffer = function(packets
, callback
) {
2758 if (!packets
.length
) {
2759 return callback(new ArrayBuffer(0));
2762 function encodeOne(packet
, doneCallback
) {
2763 exports
.encodePacket(packet
, true, true, function(data
) {
2764 return doneCallback(null, data
);
2768 map(packets
, encodeOne
, function(err
, encodedPackets
) {
2769 var totalLength
= encodedPackets
.reduce(function(acc
, p
) {
2771 if (typeof p
=== 'string'){
2776 return acc
+ len
.toString().length
+ len
+ 2; // string/binary identifier + separator = 2
2779 var resultArray
= new Uint8Array(totalLength
);
2781 var bufferIndex
= 0;
2782 encodedPackets
.forEach(function(p
) {
2783 var isString
= typeof p
=== 'string';
2786 var view
= new Uint8Array(p
.length
);
2787 for (var i
= 0; i
< p
.length
; i
++) {
2788 view
[i
] = p
.charCodeAt(i
);
2793 if (isString
) { // not true binary
2794 resultArray
[bufferIndex
++] = 0;
2795 } else { // true binary
2796 resultArray
[bufferIndex
++] = 1;
2799 var lenStr
= ab
.byteLength
.toString();
2800 for (var i
= 0; i
< lenStr
.length
; i
++) {
2801 resultArray
[bufferIndex
++] = parseInt(lenStr
[i
]);
2803 resultArray
[bufferIndex
++] = 255;
2805 var view
= new Uint8Array(ab
);
2806 for (var i
= 0; i
< view
.length
; i
++) {
2807 resultArray
[bufferIndex
++] = view
[i
];
2811 return callback(resultArray
.buffer
);
2819 exports
.encodePayloadAsBlob = function(packets
, callback
) {
2820 function encodeOne(packet
, doneCallback
) {
2821 exports
.encodePacket(packet
, true, true, function(encoded
) {
2822 var binaryIdentifier
= new Uint8Array(1);
2823 binaryIdentifier
[0] = 1;
2824 if (typeof encoded
=== 'string') {
2825 var view
= new Uint8Array(encoded
.length
);
2826 for (var i
= 0; i
< encoded
.length
; i
++) {
2827 view
[i
] = encoded
.charCodeAt(i
);
2829 encoded
= view
.buffer
;
2830 binaryIdentifier
[0] = 0;
2833 var len
= (encoded
instanceof ArrayBuffer
)
2834 ? encoded
.byteLength
2837 var lenStr
= len
.toString();
2838 var lengthAry
= new Uint8Array(lenStr
.length
+ 1);
2839 for (var i
= 0; i
< lenStr
.length
; i
++) {
2840 lengthAry
[i
] = parseInt(lenStr
[i
]);
2842 lengthAry
[lenStr
.length
] = 255;
2845 var blob
= new Blob([binaryIdentifier
.buffer
, lengthAry
.buffer
, encoded
]);
2846 doneCallback(null, blob
);
2851 map(packets
, encodeOne
, function(err
, results
) {
2852 return callback(new Blob(results
));
2857 * Decodes data when a payload is maybe expected. Strings are decoded by
2858 * interpreting each byte as a key code for entries marked to start with 0. See
2859 * description of encodePayloadAsBinary
2861 * @param {ArrayBuffer} data, callback method
2865 exports
.decodePayloadAsBinary = function (data
, binaryType
, callback
) {
2866 if (typeof binaryType
=== 'function') {
2867 callback
= binaryType
;
2871 var bufferTail
= data
;
2874 var numberTooLong
= false;
2875 while (bufferTail
.byteLength
> 0) {
2876 var tailArray
= new Uint8Array(bufferTail
);
2877 var isString
= tailArray
[0] === 0;
2880 for (var i
= 1; ; i
++) {
2881 if (tailArray
[i
] == 255) break;
2883 if (msgLength
.length
> 310) {
2884 numberTooLong
= true;
2888 msgLength
+= tailArray
[i
];
2891 if(numberTooLong
) return callback(err
, 0, 1);
2893 bufferTail
= sliceBuffer(bufferTail
, 2 + msgLength
.length
);
2894 msgLength
= parseInt(msgLength
);
2896 var msg
= sliceBuffer(bufferTail
, 0, msgLength
);
2899 msg
= String
.fromCharCode
.apply(null, new Uint8Array(msg
));
2901 // iPhone Safari doesn't let you apply to typed arrays
2902 var typed
= new Uint8Array(msg
);
2904 for (var i
= 0; i
< typed
.length
; i
++) {
2905 msg
+= String
.fromCharCode(typed
[i
]);
2911 bufferTail
= sliceBuffer(bufferTail
, msgLength
);
2914 var total
= buffers
.length
;
2915 buffers
.forEach(function(buffer
, i
) {
2916 callback(exports
.decodePacket(buffer
, binaryType
, true), i
, total
);
2920 }).call(this,typeof self
!== "undefined" ? self
: typeof window
!== "undefined" ? window
: {})
2921 },{"./keys":16,"after":17,"arraybuffer.slice":18,"base64-arraybuffer":19,"blob":11,"utf8":20}],16:[function(_dereq_
,mod
,exports
){
2924 * Gets the keys for an object.
2926 * @return {Array} keys
2930 mod
.exports
= Object
.keys
|| function keys (obj
){
2932 var has
= Object
.prototype.hasOwnProperty
;
2934 for (var i
in obj
) {
2935 if (has
.call(obj
, i
)) {
2942 },{}],17:[function(_dereq_
,mod
,exports
){
2945 function after(count
, callback
, err_cb
) {
2947 err_cb
= err_cb
|| noop
2950 return (count
=== 0) ? callback() : proxy
2952 function proxy(err
, result
) {
2953 if (proxy
.count
<= 0) {
2954 throw new Error('after called too many times')
2958 // after first error, rest are passed to err_cb
2962 // future error callbacks will go to error handler
2964 } else if (proxy
.count
=== 0 && !bail
) {
2965 callback(null, result
)
2972 },{}],18:[function(_dereq_
,mod
,exports
){
2974 * An abstraction for slicing an arraybuffer even when
2975 * ArrayBuffer.prototype.slice is not supported
2980 mod
.exports = function(arraybuffer
, start
, end
) {
2981 var bytes
= arraybuffer
.byteLength
;
2985 if (arraybuffer
.slice
) { return arraybuffer
.slice(start
, end
); }
2987 if (start
< 0) { start
+= bytes
; }
2988 if (end
< 0) { end
+= bytes
; }
2989 if (end
> bytes
) { end
= bytes
; }
2991 if (start
>= bytes
|| start
>= end
|| bytes
=== 0) {
2992 return new ArrayBuffer(0);
2995 var abv
= new Uint8Array(arraybuffer
);
2996 var result
= new Uint8Array(end
- start
);
2997 for (var i
= start
, ii
= 0; i
< end
; i
++, ii
++) {
2998 result
[ii
] = abv
[i
];
3000 return result
.buffer
;
3003 },{}],19:[function(_dereq_
,mod
,exports
){
3005 * base64-arraybuffer
3006 * https://github.com/niklasvh/base64-arraybuffer
3008 * Copyright (c) 2012 Niklas von Hertzen
3009 * Licensed under the MIT license.
3014 exports
.encode = function(arraybuffer
) {
3015 var bytes
= new Uint8Array(arraybuffer
),
3016 i
, len
= bytes
.length
, base64
= "";
3018 for (i
= 0; i
< len
; i
+=3) {
3019 base64
+= chars
[bytes
[i
] >> 2];
3020 base64
+= chars
[((bytes
[i
] & 3) << 4) | (bytes
[i
+ 1] >> 4)];
3021 base64
+= chars
[((bytes
[i
+ 1] & 15) << 2) | (bytes
[i
+ 2] >> 6)];
3022 base64
+= chars
[bytes
[i
+ 2] & 63];
3025 if ((len
% 3) === 2) {
3026 base64
= base64
.substring(0, base64
.length
- 1) + "=";
3027 } else if (len
% 3 === 1) {
3028 base64
= base64
.substring(0, base64
.length
- 2) + "==";
3034 exports
.decode = function(base64
) {
3035 var bufferLength
= base64
.length
* 0.75,
3036 len
= base64
.length
, i
, p
= 0,
3037 encoded1
, encoded2
, encoded3
, encoded4
;
3039 if (base64
[base64
.length
- 1] === "=") {
3041 if (base64
[base64
.length
- 2] === "=") {
3046 var arraybuffer
= new ArrayBuffer(bufferLength
),
3047 bytes
= new Uint8Array(arraybuffer
);
3049 for (i
= 0; i
< len
; i
+=4) {
3050 encoded1
= chars
.indexOf(base64
[i
]);
3051 encoded2
= chars
.indexOf(base64
[i
+1]);
3052 encoded3
= chars
.indexOf(base64
[i
+2]);
3053 encoded4
= chars
.indexOf(base64
[i
+3]);
3055 bytes
[p
++] = (encoded1
<< 2) | (encoded2
>> 4);
3056 bytes
[p
++] = ((encoded2
& 15) << 4) | (encoded3
>> 2);
3057 bytes
[p
++] = ((encoded3
& 3) << 6) | (encoded4
& 63);
3062 })("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/");
3064 },{}],20:[function(_dereq_
,mod
,exports
){
3066 /*! http://mths.be/utf8js v2.0.0 by @mathias */
3069 // Detect free variables `exports`
3070 var freeExports
= typeof exports
== 'object' && exports
;
3072 // Detect free variable `mod`
3073 var freeMod
= typeof mod
== 'object' && mod
&&
3074 mod
.exports
== freeExports
&& mod
;
3076 // Detect free variable `global`, from Node.js or Browserified code,
3077 // and use it as `root`
3078 var freeGlobal
= typeof global
== 'object' && global
;
3079 if (freeGlobal
.global
=== freeGlobal
|| freeGlobal
.window
=== freeGlobal
) {
3083 /*--------------------------------------------------------------------------*/
3085 var stringFromCharCode
= String
.fromCharCode
;
3087 // Taken from http://mths.be/punycode
3088 function ucs2decode(string
) {
3091 var length
= string
.length
;
3094 while (counter
< length
) {
3095 value
= string
.charCodeAt(counter
++);
3096 if (value
>= 0xD800 && value
<= 0xDBFF && counter
< length
) {
3097 // high surrogate, and there is a next character
3098 extra
= string
.charCodeAt(counter
++);
3099 if ((extra
& 0xFC00) == 0xDC00) { // low surrogate
3100 output
.push(((value
& 0x3FF) << 10) + (extra
& 0x3FF) + 0x10000);
3102 // unmatched surrogate; only append this code unit, in case the next
3103 // code unit is the high surrogate of a surrogate pair
3114 // Taken from http://mths.be/punycode
3115 function ucs2encode(array
) {
3116 var length
= array
.length
;
3120 while (++index
< length
) {
3121 value
= array
[index
];
3122 if (value
> 0xFFFF) {
3124 output
+= stringFromCharCode(value
>>> 10 & 0x3FF | 0xD800);
3125 value
= 0xDC00 | value
& 0x3FF;
3127 output
+= stringFromCharCode(value
);
3132 /*--------------------------------------------------------------------------*/
3134 function createByte(codePoint
, shift
) {
3135 return stringFromCharCode(((codePoint
>> shift
) & 0x3F) | 0x80);
3138 function encodeCodePoint(codePoint
) {
3139 if ((codePoint
& 0xFFFFFF80) == 0) { // 1-byte sequence
3140 return stringFromCharCode(codePoint
);
3143 if ((codePoint
& 0xFFFFF800) == 0) { // 2-byte sequence
3144 symbol
= stringFromCharCode(((codePoint
>> 6) & 0x1F) | 0xC0);
3146 else if ((codePoint
& 0xFFFF0000) == 0) { // 3-byte sequence
3147 symbol
= stringFromCharCode(((codePoint
>> 12) & 0x0F) | 0xE0);
3148 symbol
+= createByte(codePoint
, 6);
3150 else if ((codePoint
& 0xFFE00000) == 0) { // 4-byte sequence
3151 symbol
= stringFromCharCode(((codePoint
>> 18) & 0x07) | 0xF0);
3152 symbol
+= createByte(codePoint
, 12);
3153 symbol
+= createByte(codePoint
, 6);
3155 symbol
+= stringFromCharCode((codePoint
& 0x3F) | 0x80);
3159 function utf8encode(string
) {
3160 var codePoints
= ucs2decode(string
);
3162 // console.log(JSON.stringify(codePoints.map(function(x) {
3163 // return 'U+' + x.toString(16).toUpperCase();
3166 var length
= codePoints
.length
;
3169 var byteString
= '';
3170 while (++index
< length
) {
3171 codePoint
= codePoints
[index
];
3172 byteString
+= encodeCodePoint(codePoint
);
3177 /*--------------------------------------------------------------------------*/
3179 function readContinuationByte() {
3180 if (byteIndex
>= byteCount
) {
3181 throw Error('Invalid byte index');
3184 var continuationByte
= byteArray
[byteIndex
] & 0xFF;
3187 if ((continuationByte
& 0xC0) == 0x80) {
3188 return continuationByte
& 0x3F;
3191 // If we end up here, it’s not a continuation byte
3192 throw Error('Invalid continuation byte');
3195 function decodeSymbol() {
3202 if (byteIndex
> byteCount
) {
3203 throw Error('Invalid byte index');
3206 if (byteIndex
== byteCount
) {
3211 byte1
= byteArray
[byteIndex
] & 0xFF;
3214 // 1-byte sequence (no continuation bytes)
3215 if ((byte1
& 0x80) == 0) {
3220 if ((byte1
& 0xE0) == 0xC0) {
3221 var byte2
= readContinuationByte();
3222 codePoint
= ((byte1
& 0x1F) << 6) | byte2
;
3223 if (codePoint
>= 0x80) {
3226 throw Error('Invalid continuation byte');
3230 // 3-byte sequence (may include unpaired surrogates)
3231 if ((byte1
& 0xF0) == 0xE0) {
3232 byte2
= readContinuationByte();
3233 byte3
= readContinuationByte();
3234 codePoint
= ((byte1
& 0x0F) << 12) | (byte2
<< 6) | byte3
;
3235 if (codePoint
>= 0x0800) {
3238 throw Error('Invalid continuation byte');
3243 if ((byte1
& 0xF8) == 0xF0) {
3244 byte2
= readContinuationByte();
3245 byte3
= readContinuationByte();
3246 byte4
= readContinuationByte();
3247 codePoint
= ((byte1
& 0x0F) << 0x12) | (byte2
<< 0x0C) |
3248 (byte3
<< 0x06) | byte4
;
3249 if (codePoint
>= 0x010000 && codePoint
<= 0x10FFFF) {
3254 throw Error('Invalid UTF-8 detected');
3260 function utf8decode(byteString
) {
3261 byteArray
= ucs2decode(byteString
);
3262 byteCount
= byteArray
.length
;
3264 var codePoints
= [];
3266 while ((tmp
= decodeSymbol()) !== false) {
3267 codePoints
.push(tmp
);
3269 return ucs2encode(codePoints
);
3272 /*--------------------------------------------------------------------------*/
3276 'encode': utf8encode
,
3277 'decode': utf8decode
3280 // Some AMD build optimizers, like r.js, check for specific condition patterns
3281 // like the following:
3283 typeof define
== 'function' &&
3284 typeof define
.amd
== 'object' &&
3290 } else if (freeExports
&& !freeExports
.nodeType
) {
3291 if (freeMod
) { // in Node.js or RingoJS v0.8.0+
3292 freeMod
.exports
= utf8
;
3293 } else { // in Narwhal or RingoJS v0.7.0-
3295 var hasOwnProperty
= object
.hasOwnProperty
;
3296 for (var key
in utf8
) {
3297 hasOwnProperty
.call(utf8
, key
) && (freeExports
[key
] = utf8
[key
]);
3300 } else { // in Rhino or a web browser
3306 }).call(this,typeof self
!== "undefined" ? self
: typeof window
!== "undefined" ? window
: {})
3307 },{}],21:[function(_dereq_
,mod
,exports
){
3313 var global
= _dereq_('global');
3318 * Logic borrowed from Modernizr:
3320 * - https://github.com/Modernizr/Modernizr/blob/master/feature-detects/cors.js
3324 mod
.exports
= 'XMLHttpRequest' in global
&&
3325 'withCredentials' in new global
.XMLHttpRequest();
3327 // if XMLHttp support is disabled in IE then it will throw
3328 // when trying to create
3329 mod
.exports
= false;
3332 },{"global":22}],22:[function(_dereq_
,mod
,exports
){
3335 * Returns `this`. Execute this without a "context" (i.e. without it being
3336 * attached to an object of the left-hand side), and `this` points to the
3337 * "global" scope of the current JS execution.
3340 mod
.exports
= (function () { return this; })();
3342 },{}],23:[function(_dereq_
,mod
,exports
){
3344 var indexOf
= [].indexOf
;
3346 mod
.exports = function(arr
, obj
){
3347 if (indexOf
) return arr
.indexOf(obj
);
3348 for (var i
= 0; i
< arr
.length
; ++i
) {
3349 if (arr
[i
] === obj
) return i
;
3353 },{}],24:[function(_dereq_
,mod
,exports
){
3358 * @see Based on jQuery#parseJSON (MIT) and JSON2
3362 var rvalidchars
= /^[\],:{}\s]*$/;
3363 var rvalidescape
= /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g;
3364 var rvalidtokens
= /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g;
3365 var rvalidbraces
= /(?:^|:|,)(?:\s*\[)+/g;
3366 var rtrimLeft
= /^\s+/;
3367 var rtrimRight
= /\s+$/;
3369 mod
.exports
= function parsejson(data
) {
3370 if ('string' != typeof data
|| !data
) {
3374 data
= data
.replace(rtrimLeft
, '').replace(rtrimRight
, '');
3376 // Attempt to parse using the native JSON parser first
3377 if (global
.JSON
&& JSON
.parse
) {
3378 return JSON
.parse(data
);
3381 if (rvalidchars
.test(data
.replace(rvalidescape
, '@')
3382 .replace(rvalidtokens
, ']')
3383 .replace(rvalidbraces
, ''))) {
3384 return (new Function('return ' + data
))();
3387 }).call(this,typeof self
!== "undefined" ? self
: typeof window
!== "undefined" ? window
: {})
3388 },{}],25:[function(_dereq_
,mod
,exports
){
3390 * Compiles a querystring
3391 * Returns string representation of the object
3397 exports
.encode = function (obj
) {
3400 for (var i
in obj
) {
3401 if (obj
.hasOwnProperty(i
)) {
3402 if (str
.length
) str
+= '&';
3403 str
+= encodeURIComponent(i
) + '=' + encodeURIComponent(obj
[i
]);
3411 * Parses a simple querystring into an object
3413 * @param {String} qs
3417 exports
.decode = function(qs
){
3419 var pairs
= qs
.split('&');
3420 for (var i
= 0, l
= pairs
.length
; i
< l
; i
++) {
3421 var pair
= pairs
[i
].split('=');
3422 qry
[decodeURIComponent(pair
[0])] = decodeURIComponent(pair
[1]);
3427 },{}],26:[function(_dereq_
,mod
,exports
){
3431 * @author Steven Levithan <stevenlevithan.com> (MIT license)
3435 var re
= /^(?:(?![^:@]+:[^:@\/]*@)(http|https|ws|wss):\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?((?:[a-f0-9]{0,4}:){2,7}[a-f0-9]{0,4}|[^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/;
3438 'source', 'protocol', 'authority', 'userInfo', 'user', 'password', 'host', 'port', 'relative', 'path', 'directory', 'file', 'query', 'anchor'
3441 mod
.exports
= function parseuri(str
) {
3443 b
= str
.indexOf('['),
3444 e
= str
.indexOf(']');
3446 if (b
!= -1 && e
!= -1) {
3447 str
= str
.substring(0, b
) + str
.substring(b
, e
).replace(/:/g
, ';') + str
.substring(e
, str
.length
);
3450 var m
= re
.exec(str
|| ''),
3455 uri
[parts
[i
]] = m
[i
] || '';
3458 if (b
!= -1 && e
!= -1) {
3460 uri
.host
= uri
.host
.substring(1, uri
.host
.length
- 1).replace(/;/g
, ':');
3461 uri
.authority
= uri
.authority
.replace('[', '').replace(']', '').replace(/;/g
, ':');
3468 },{}],27:[function(_dereq_
,mod
,exports
){
3474 var global
= (function() { return this; })();
3477 * WebSocket constructor.
3480 var WebSocket
= global
.WebSocket
|| global
.MozWebSocket
;
3486 mod
.exports
= WebSocket
? ws
: null;
3489 * WebSocket constructor.
3491 * The third `opts` options object gets ignored in web browsers, since it's
3492 * non-standard, and throws a TypeError if passed to the constructor.
3493 * See: https://github.com/einaros/ws/issues/227
3495 * @param {String} uri
3496 * @param {Array} protocols (optional)
3497 * @param {Object) opts (optional)
3501 function ws(uri
, protocols
, opts
) {
3504 instance
= new WebSocket(uri
, protocols
);
3506 instance
= new WebSocket(uri
);
3511 if (WebSocket
) ws
.prototype = WebSocket
.prototype;