1 !function(e
){if("object"==typeof exports
)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
.eio
=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
){
3 module
.exports
= _dereq_('./lib/');
5 },{"./lib/":2}],2:[function(_dereq_
,module
,exports
){
7 module
.exports
= _dereq_('./socket');
15 module
.exports
.parser
= _dereq_('engine.io-parser');
17 },{"./socket":3,"engine.io-parser":15}],3:[function(_dereq_
,module
,exports
){
20 * Module dependencies.
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');
36 module
.exports
= Socket
;
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.forceBase64 = !!opts.forceBase64;
93 this.timestampParam = opts.timestampParam || 't
';
94 this.timestampRequests = opts.timestampRequests;
95 this.transports = opts.transports || ['polling
', 'websocket
'];
97 this.writeBuffer = [];
98 this.callbackBuffer = [];
99 this.policyPort = opts.policyPort || 843;
100 this.rememberUpgrade = opts.rememberUpgrade || false;
102 this.binaryType = null;
103 this.onlyBinaryUpgrades = opts.onlyBinaryUpgrades;
106 Socket.priorWebsocketSuccess = false;
112 Emitter(Socket.prototype);
120 Socket.protocol = parser.protocol; // this is an int
123 * Expose deps for legacy compatibility
124 * and standalone browser access.
127 Socket.Socket = Socket;
128 Socket.Transport = _dereq_('./transport
');
129 Socket.transports = _dereq_('./transports
');
130 Socket.parser = _dereq_('engine
.io
-parser
');
133 * Creates transport of the given type.
135 * @param {String} transport name
136 * @return {Transport}
140 Socket.prototype.createTransport = function (name) {
141 debug('creating transport
"%s"', name);
142 var query = clone(this.query);
144 // append engine.io protocol identifier
145 query.EIO = parser.protocol;
148 query.transport = name;
150 // session id if we already have one
151 if (this.id) query.sid = this.id;
153 var transport = new transports[name]({
155 hostname: this.hostname,
160 forceJSONP: this.forceJSONP,
161 forceBase64: this.forceBase64,
162 timestampRequests: this.timestampRequests,
163 timestampParam: this.timestampParam,
164 policyPort: this.policyPort,
171 function clone (obj) {
174 if (obj.hasOwnProperty(i)) {
182 * Initializes transport to use and starts probe.
186 Socket.prototype.open = function () {
188 if (this.rememberUpgrade && Socket.priorWebsocketSuccess && this.transports.indexOf('websocket
') != -1) {
189 transport = 'websocket
';
191 transport = this.transports[0];
193 this.readyState = 'opening
';
194 var transport = this.createTransport(transport);
196 this.setTransport(transport);
200 * Sets the current transport. Disables the existing one (if any).
205 Socket.prototype.setTransport = function(transport){
206 debug('setting transport
%s
', transport.name);
209 if (this.transport) {
210 debug('clearing existing transport
%s
', this.transport.name);
211 this.transport.removeAllListeners();
215 this.transport = transport;
217 // set up transport listeners
219 .on('drain
', function(){
222 .on('packet
', function(packet){
223 self.onPacket(packet);
225 .on('error
', function(e){
228 .on('close
', function(){
229 self.onClose('transport close
');
234 * Probes a transport.
236 * @param {String} transport name
240 Socket.prototype.probe = function (name) {
241 debug('probing transport
"%s"', name);
242 var transport = this.createTransport(name, { probe: 1 })
246 Socket.priorWebsocketSuccess = false;
248 function onTransportOpen(){
249 if (self.onlyBinaryUpgrades) {
250 var upgradeLosesBinary = !this.supportsBinary && self.transport.supportsBinary;
251 failed = failed || upgradeLosesBinary;
255 debug('probe transport
"%s" opened
', name);
256 transport.send([{ type: 'ping
', data: 'probe
' }]);
257 transport.once('packet
', function (msg) {
259 if ('pong
' == msg.type && 'probe
' == msg.data) {
260 debug('probe transport
"%s" pong
', name);
261 self.upgrading = true;
262 self.emit('upgrading
', transport);
263 Socket.priorWebsocketSuccess = 'websocket
' == transport.name;
265 debug('pausing current transport
"%s"', self.transport.name);
266 self.transport.pause(function () {
268 if ('closed
' == self.readyState || 'closing
' == self.readyState) {
271 debug('changing transport and sending upgrade packet
');
275 self.setTransport(transport);
276 transport.send([{ type: 'upgrade
' }]);
277 self.emit('upgrade
', transport);
279 self.upgrading = false;
283 debug('probe transport
"%s" failed
', name);
284 var err = new Error('probe error
');
285 err.transport = transport.name;
286 self.emit('upgradeError
', err);
291 function freezeTransport() {
294 // Any callback called by transport should be ignored since now
303 //Handle any error that happens while probing
304 function onerror(err) {
305 var error = new Error('probe error
: ' + err);
306 error.transport = transport.name;
310 debug('probe transport
"%s" failed because
of error
: %s
', name, err);
312 self.emit('upgradeError
', error);
315 function onTransportClose(){
316 onerror("transport closed");
319 //When the socket is closed while we're probing
321 onerror("socket closed");
324 //When the socket is upgraded while we're probing
325 function onupgrade(to
){
326 if (transport
&& to
.name
!= transport
.name
) {
327 debug('"%s" works - aborting "%s"', to
.name
, transport
.name
);
332 //Remove all listeners on the transport and on self
334 transport
.removeListener('open', onTransportOpen
);
335 transport
.removeListener('error', onerror
);
336 transport
.removeListener('close', onTransportClose
);
337 self
.removeListener('close', onclose
);
338 self
.removeListener('upgrading', onupgrade
);
341 transport
.once('open', onTransportOpen
);
342 transport
.once('error', onerror
);
343 transport
.once('close', onTransportClose
);
345 this.once('close', onclose
);
346 this.once('upgrading', onupgrade
);
353 * Called when connection is deemed open.
358 Socket
.prototype.onOpen = function () {
359 debug('socket open');
360 this.readyState
= 'open';
361 Socket
.priorWebsocketSuccess
= 'websocket' == this.transport
.name
;
365 // we check for `readyState` in case an `open`
366 // listener already closed the socket
367 if ('open' == this.readyState
&& this.upgrade
&& this.transport
.pause
) {
368 debug('starting upgrade probes');
369 for (var i
= 0, l
= this.upgrades
.length
; i
< l
; i
++) {
370 this.probe(this.upgrades
[i
]);
381 Socket
.prototype.onPacket = function (packet
) {
382 if ('opening' == this.readyState
|| 'open' == this.readyState
) {
383 debug('socket receive: type "%s", data "%s"', packet
.type
, packet
.data
);
385 this.emit('packet', packet
);
387 // Socket is live - any packet counts
388 this.emit('heartbeat');
390 switch (packet
.type
) {
392 this.onHandshake(parsejson(packet
.data
));
400 var err
= new Error('server error');
401 err
.code
= packet
.data
;
402 this.emit('error', err
);
406 this.emit('data', packet
.data
);
407 this.emit('message', packet
.data
);
411 debug('packet received with socket readyState "%s"', this.readyState
);
416 * Called upon handshake completion.
418 * @param {Object} handshake obj
422 Socket
.prototype.onHandshake = function (data
) {
423 this.emit('handshake', data
);
425 this.transport
.query
.sid
= data
.sid
;
426 this.upgrades
= this.filterUpgrades(data
.upgrades
);
427 this.pingInterval
= data
.pingInterval
;
428 this.pingTimeout
= data
.pingTimeout
;
430 // In case open handler closes socket
431 if ('closed' == this.readyState
) return;
434 // Prolong liveness of socket on heartbeat
435 this.removeListener('heartbeat', this.onHeartbeat
);
436 this.on('heartbeat', this.onHeartbeat
);
440 * Resets ping timeout.
445 Socket
.prototype.onHeartbeat = function (timeout
) {
446 clearTimeout(this.pingTimeoutTimer
);
448 self
.pingTimeoutTimer
= setTimeout(function () {
449 if ('closed' == self
.readyState
) return;
450 self
.onClose('ping timeout');
451 }, timeout
|| (self
.pingInterval
+ self
.pingTimeout
));
455 * Pings server every `this.pingInterval` and expects response
456 * within `this.pingTimeout` or closes connection.
461 Socket
.prototype.setPing = function () {
463 clearTimeout(self
.pingIntervalTimer
);
464 self
.pingIntervalTimer
= setTimeout(function () {
465 debug('writing ping packet - expecting pong within %sms', self
.pingTimeout
);
467 self
.onHeartbeat(self
.pingTimeout
);
468 }, self
.pingInterval
);
472 * Sends a ping packet.
477 Socket
.prototype.ping = function () {
478 this.sendPacket('ping');
482 * Called on `drain` event
487 Socket
.prototype.onDrain = function() {
488 for (var i
= 0; i
< this.prevBufferLen
; i
++) {
489 if (this.callbackBuffer
[i
]) {
490 this.callbackBuffer
[i
]();
494 this.writeBuffer
.splice(0, this.prevBufferLen
);
495 this.callbackBuffer
.splice(0, this.prevBufferLen
);
497 // setting prevBufferLen = 0 is very important
498 // for example, when upgrading, upgrade packet is sent over,
499 // and a nonzero prevBufferLen could cause problems on `drain`
500 this.prevBufferLen
= 0;
502 if (this.writeBuffer
.length
== 0) {
510 * Flush write buffers.
515 Socket
.prototype.flush = function () {
516 if ('closed' != this.readyState
&& this.transport
.writable
&&
517 !this.upgrading
&& this.writeBuffer
.length
) {
518 debug('flushing %d packets in socket', this.writeBuffer
.length
);
519 this.transport
.send(this.writeBuffer
);
520 // keep track of current length of writeBuffer
521 // splice writeBuffer and callbackBuffer on `drain`
522 this.prevBufferLen
= this.writeBuffer
.length
;
530 * @param {String} message.
531 * @param {Function} callback function.
532 * @return {Socket} for chaining.
536 Socket
.prototype.write
=
537 Socket
.prototype.send = function (msg
, fn
) {
538 this.sendPacket('message', msg
, fn
);
545 * @param {String} packet type.
546 * @param {String} data.
547 * @param {Function} callback function.
551 Socket
.prototype.sendPacket = function (type
, data
, fn
) {
552 var packet
= { type
: type
, data
: data
};
553 this.emit('packetCreate', packet
);
554 this.writeBuffer
.push(packet
);
555 this.callbackBuffer
.push(fn
);
560 * Closes the connection.
565 Socket
.prototype.close = function () {
566 if ('opening' == this.readyState
|| 'open' == this.readyState
) {
567 this.onClose('forced close');
568 debug('socket closing - telling transport to close');
569 this.transport
.close();
576 * Called upon transport error
581 Socket
.prototype.onError = function (err
) {
582 debug('socket error %j', err
);
583 Socket
.priorWebsocketSuccess
= false;
584 this.emit('error', err
);
585 this.onClose('transport error', err
);
589 * Called upon transport close.
594 Socket
.prototype.onClose = function (reason
, desc
) {
595 if ('opening' == this.readyState
|| 'open' == this.readyState
) {
596 debug('socket close with reason: "%s"', reason
);
600 clearTimeout(this.pingIntervalTimer
);
601 clearTimeout(this.pingTimeoutTimer
);
603 // clean buffers in next tick, so developers can still
604 // grab the buffers on `close` event
605 setTimeout(function() {
606 self
.writeBuffer
= [];
607 self
.callbackBuffer
= [];
608 self
.prevBufferLen
= 0;
611 // stop event from firing again for transport
612 this.transport
.removeAllListeners('close');
614 // ensure transport won't stay open
615 this.transport
.close();
617 // ignore further transport communication
618 this.transport
.removeAllListeners();
621 this.readyState
= 'closed';
627 this.emit('close', reason
, desc
);
632 * Filters upgrades, returning only those matching client transports.
634 * @param {Array} server upgrades
639 Socket
.prototype.filterUpgrades = function (upgrades
) {
640 var filteredUpgrades
= [];
641 for (var i
= 0, j
= upgrades
.length
; i
<j
; i
++) {
642 if (~index(this.transports
, upgrades
[i
])) filteredUpgrades
.push(upgrades
[i
]);
644 return filteredUpgrades
;
647 }).call(this,typeof self
!== "undefined" ? self
: typeof window
!== "undefined" ? window
: {})
648 },{"./transport":4,"./transports":5,"component-emitter":12,"debug":14,"engine.io-parser":15,"indexof":23,"parsejson":24,"parseqs":25,"parseuri":26}],4:[function(_dereq_
,module
,exports
){
650 * Module dependencies.
653 var parser
= _dereq_('engine.io-parser');
654 var Emitter
= _dereq_('component-emitter');
660 module
.exports
= Transport
;
663 * Transport abstract constructor.
665 * @param {Object} options.
669 function Transport (opts
) {
670 this.path
= opts
.path
;
671 this.hostname
= opts
.hostname
;
672 this.port
= opts
.port
;
673 this.secure
= opts
.secure
;
674 this.query
= opts
.query
;
675 this.timestampParam
= opts
.timestampParam
;
676 this.timestampRequests
= opts
.timestampRequests
;
677 this.readyState
= '';
678 this.agent
= opts
.agent
|| false;
679 this.socket
= opts
.socket
;
686 Emitter(Transport
.prototype);
689 * A counter used to prevent collisions in the timestamps used
693 Transport
.timestamps
= 0;
698 * @param {String} str
699 * @return {Transport} for chaining
703 Transport
.prototype.onError = function (msg
, desc
) {
704 var err
= new Error(msg
);
705 err
.type
= 'TransportError';
706 err
.description
= desc
;
707 this.emit('error', err
);
712 * Opens the transport.
717 Transport
.prototype.open = function () {
718 if ('closed' == this.readyState
|| '' == this.readyState
) {
719 this.readyState
= 'opening';
727 * Closes the transport.
732 Transport
.prototype.close = function () {
733 if ('opening' == this.readyState
|| 'open' == this.readyState
) {
742 * Sends multiple packets.
744 * @param {Array} packets
748 Transport
.prototype.send = function(packets
){
749 if ('open' == this.readyState
) {
752 throw new Error('Transport not open');
762 Transport
.prototype.onOpen = function () {
763 this.readyState
= 'open';
764 this.writable
= true;
771 * @param {String} data
775 Transport
.prototype.onData = function(data
){
777 var packet
= parser
.decodePacket(data
, this.socket
.binaryType
);
778 this.onPacket(packet
);
781 this.onError('parser decode error', e
);
786 * Called with a decoded packet.
789 Transport
.prototype.onPacket = function (packet
) {
790 this.emit('packet', packet
);
799 Transport
.prototype.onClose = function () {
800 this.readyState
= 'closed';
804 },{"component-emitter":12,"engine.io-parser":15}],5:[function(_dereq_
,module
,exports
){
807 * Module dependencies
810 var XMLHttpRequest
= _dereq_('xmlhttprequest');
811 var XHR
= _dereq_('./polling-xhr');
812 var JSONP
= _dereq_('./polling-jsonp');
813 var websocket
= _dereq_('./websocket');
819 exports
.polling
= polling
;
820 exports
.websocket
= websocket
;
823 * Polling transport polymorphic constructor.
824 * Decides on xhr vs jsonp based on feature detection.
829 function polling(opts
){
833 if (global
.location
) {
834 var isSSL
= 'https:' == location
.protocol
;
835 var port
= location
.port
;
837 // some user agents have empty `location.port`
839 port
= isSSL
? 443 : 80;
842 xd
= opts
.hostname
!= location
.hostname
|| port
!= opts
.port
;
846 xhr
= new XMLHttpRequest(opts
);
848 if ('open' in xhr
&& !opts
.forceJSONP
) {
849 return new XHR(opts
);
851 return new JSONP(opts
);
855 }).call(this,typeof self
!== "undefined" ? self
: typeof window
!== "undefined" ? window
: {})
856 },{"./polling-jsonp":6,"./polling-xhr":7,"./websocket":9,"xmlhttprequest":10}],6:[function(_dereq_
,module
,exports
){
860 * Module requirements.
863 var Polling
= _dereq_('./polling');
864 var inherit
= _dereq_('component-inherit');
870 module
.exports
= JSONPPolling
;
873 * Cached regular expressions.
876 var rNewline
= /\n/g;
877 var rEscapedNewline
= /\\n/g;
880 * Global JSONP callbacks.
895 function empty () { }
898 * JSONP Polling constructor.
900 * @param {Object} opts.
904 function JSONPPolling (opts
) {
905 Polling
.call(this, opts
);
907 this.query
= this.query
|| {};
909 // define global callbacks array if not present
910 // we do this here (lazily) to avoid unneeded global pollution
912 // we need to consider multiple engines in the same page
913 if (!global
.___eio
) global
.___eio
= [];
914 callbacks
= global
.___eio
;
917 // callback identifier
918 this.index
= callbacks
.length
;
920 // add callback to jsonp global
922 callbacks
.push(function (msg
) {
926 // append to query string
927 this.query
.j
= this.index
;
929 // prevent spurious errors from being emitted when the window is unloaded
930 if (global
.document
&& global
.addEventListener
) {
931 global
.addEventListener('beforeunload', function () {
932 if (self
.script
) self
.script
.onerror
= empty
;
938 * Inherits from Polling.
941 inherit(JSONPPolling
, Polling
);
944 * JSONP only supports binary as base64 encoded strings
947 JSONPPolling
.prototype.supportsBinary
= false;
955 JSONPPolling
.prototype.doClose = function () {
957 this.script
.parentNode
.removeChild(this.script
);
962 this.form
.parentNode
.removeChild(this.form
);
966 Polling
.prototype.doClose
.call(this);
970 * Starts a poll cycle.
975 JSONPPolling
.prototype.doPoll = function () {
977 var script
= document
.createElement('script');
980 this.script
.parentNode
.removeChild(this.script
);
985 script
.src
= this.uri();
986 script
.onerror = function(e
){
987 self
.onError('jsonp poll error',e
);
990 var insertAt
= document
.getElementsByTagName('script')[0];
991 insertAt
.parentNode
.insertBefore(script
, insertAt
);
992 this.script
= script
;
994 var isUAgecko
= 'undefined' != typeof navigator
&& /gecko/i.test(navigator
.userAgent
);
997 setTimeout(function () {
998 var iframe
= document
.createElement('iframe');
999 document
.body
.appendChild(iframe
);
1000 document
.body
.removeChild(iframe
);
1006 * Writes with a hidden iframe.
1008 * @param {String} data to send
1009 * @param {Function} called upon flush.
1013 JSONPPolling
.prototype.doWrite = function (data
, fn
) {
1017 var form
= document
.createElement('form');
1018 var area
= document
.createElement('textarea');
1019 var id
= this.iframeId
= 'eio_iframe_' + this.index
;
1022 form
.className
= 'socketio';
1023 form
.style
.position
= 'absolute';
1024 form
.style
.top
= '-1000px';
1025 form
.style
.left
= '-1000px';
1027 form
.method
= 'POST';
1028 form
.setAttribute('accept-charset', 'utf-8');
1030 form
.appendChild(area
);
1031 document
.body
.appendChild(form
);
1037 this.form
.action
= this.uri();
1039 function complete () {
1044 function initIframe () {
1047 self
.form
.removeChild(self
.iframe
);
1049 self
.onError('jsonp polling iframe removal error', e
);
1054 // ie6 dynamic iframes with target="" support (thanks Chris Lambacher)
1055 var html
= '<iframe src="javascript:0" name="'+ self
.iframeId
+'">';
1056 iframe
= document
.createElement(html
);
1058 iframe
= document
.createElement('iframe');
1059 iframe
.name
= self
.iframeId
;
1060 iframe
.src
= 'javascript:0';
1063 iframe
.id
= self
.iframeId
;
1065 self
.form
.appendChild(iframe
);
1066 self
.iframe
= iframe
;
1071 // escape \n to prevent it from being converted into \r\n by some UAs
1072 // double escaping is required for escaped new lines because unescaping of new lines can be done safely on server-side
1073 data
= data
.replace(rEscapedNewline
, '\\\n');
1074 this.area
.value
= data
.replace(rNewline
, '\\n');
1080 if (this.iframe
.attachEvent
) {
1081 this.iframe
.onreadystatechange = function(){
1082 if (self
.iframe
.readyState
== 'complete') {
1087 this.iframe
.onload
= complete
;
1091 }).call(this,typeof self
!== "undefined" ? self
: typeof window
!== "undefined" ? window
: {})
1092 },{"./polling":8,"component-inherit":13}],7:[function(_dereq_
,module
,exports
){
1095 * Module requirements.
1098 var XMLHttpRequest
= _dereq_('xmlhttprequest');
1099 var Polling
= _dereq_('./polling');
1100 var Emitter
= _dereq_('component-emitter');
1101 var inherit
= _dereq_('component-inherit');
1102 var debug
= _dereq_('debug')('engine.io-client:polling-xhr');
1108 module
.exports
= XHR
;
1109 module
.exports
.Request
= Request
;
1118 * XHR Polling constructor.
1120 * @param {Object} opts
1125 Polling
.call(this, opts
);
1127 if (global
.location
) {
1128 var isSSL
= 'https:' == location
.protocol
;
1129 var port
= location
.port
;
1131 // some user agents have empty `location.port`
1133 port
= isSSL
? 443 : 80;
1136 this.xd
= opts
.hostname
!= global
.location
.hostname
||
1142 * Inherits from Polling.
1145 inherit(XHR
, Polling
);
1148 * XHR supports binary
1151 XHR
.prototype.supportsBinary
= true;
1154 * Creates a request.
1156 * @param {String} method
1160 XHR
.prototype.request = function(opts
){
1162 opts
.uri
= this.uri();
1164 opts
.agent
= this.agent
|| false;
1165 opts
.supportsBinary
= this.supportsBinary
;
1166 return new Request(opts
);
1172 * @param {String} data to send.
1173 * @param {Function} called upon flush.
1177 XHR
.prototype.doWrite = function(data
, fn
){
1178 var isBinary
= typeof data
!== 'string' && data
!== undefined;
1179 var req
= this.request({ method
: 'POST', data
: data
, isBinary
: isBinary
});
1181 req
.on('success', fn
);
1182 req
.on('error', function(err
){
1183 self
.onError('xhr post error', err
);
1189 * Starts a poll cycle.
1194 XHR
.prototype.doPoll = function(){
1196 var req
= this.request();
1198 req
.on('data', function(data
){
1201 req
.on('error', function(err
){
1202 self
.onError('xhr poll error', err
);
1208 * Request constructor
1210 * @param {Object} options
1214 function Request(opts
){
1215 this.method
= opts
.method
|| 'GET';
1216 this.uri
= opts
.uri
;
1217 this.xd
= !!opts
.xd
;
1218 this.async
= false !== opts
.async
;
1219 this.data
= undefined != opts
.data
? opts
.data
: null;
1220 this.agent
= opts
.agent
;
1221 this.create(opts
.isBinary
, opts
.supportsBinary
);
1228 Emitter(Request
.prototype);
1231 * Creates the XHR object and sends the request.
1236 Request
.prototype.create = function(isBinary
, supportsBinary
){
1237 var xhr
= this.xhr
= new XMLHttpRequest({ agent
: this.agent
, xdomain
: this.xd
});
1241 debug('xhr open %s: %s', this.method
, this.uri
);
1242 xhr
.open(this.method
, this.uri
, this.async
);
1243 if (supportsBinary
) {
1244 // This has to be done after open because Firefox is stupid
1245 // http://stackoverflow.com/questions/13216903/get-binary-data-with-xmlhttprequest-in-a-firefox-extension
1246 xhr
.responseType
= 'arraybuffer';
1249 if ('POST' == this.method
) {
1252 xhr
.setRequestHeader('Content-type', 'application/octet-stream');
1254 xhr
.setRequestHeader('Content-type', 'text/plain;charset=UTF-8');
1260 if ('withCredentials' in xhr
) {
1261 xhr
.withCredentials
= true;
1264 xhr
.onreadystatechange = function(){
1268 if (4 != xhr
.readyState
) return;
1269 if (200 == xhr
.status
|| 1223 == xhr
.status
) {
1270 var contentType
= xhr
.getResponseHeader('Content-Type');
1271 if (contentType
=== 'application/octet-stream') {
1272 data
= xhr
.response
;
1274 if (!supportsBinary
) {
1275 data
= xhr
.responseText
;
1281 // make sure the `error` event handler that's user-set
1282 // does not throw in the same tick and gets caught here
1283 setTimeout(function(){
1284 self
.onError(xhr
.status
);
1296 debug('xhr data %s', this.data
);
1297 xhr
.send(this.data
);
1299 // Need to defer since .create() is called directly fhrom the constructor
1300 // and thus the 'error' event can only be only bound *after* this exception
1301 // occurs. Therefore, also, we cannot throw here at all.
1302 setTimeout(function() {
1308 if (global
.document
) {
1309 this.index
= Request
.requestsCount
++;
1310 Request
.requests
[this.index
] = this;
1315 * Called upon successful response.
1320 Request
.prototype.onSuccess = function(){
1321 this.emit('success');
1326 * Called if we have data.
1331 Request
.prototype.onData = function(data
){
1332 this.emit('data', data
);
1337 * Called upon error.
1342 Request
.prototype.onError = function(err
){
1343 this.emit('error', err
);
1353 Request
.prototype.cleanup = function(){
1354 if ('undefined' == typeof this.xhr
|| null === this.xhr
) {
1358 this.xhr
.onreadystatechange
= empty
;
1364 if (global
.document
) {
1365 delete Request
.requests
[this.index
];
1372 * Aborts the request.
1377 Request
.prototype.abort = function(){
1382 * Aborts pending requests when unloading the window. This is needed to prevent
1383 * memory leaks (e.g. when using IE) and to ensure that no spurious error is
1387 if (global
.document
) {
1388 Request
.requestsCount
= 0;
1389 Request
.requests
= {};
1390 if (global
.attachEvent
) {
1391 global
.attachEvent('onunload', unloadHandler
);
1392 } else if (global
.addEventListener
) {
1393 global
.addEventListener('beforeunload', unloadHandler
);
1397 function unloadHandler() {
1398 for (var i
in Request
.requests
) {
1399 if (Request
.requests
.hasOwnProperty(i
)) {
1400 Request
.requests
[i
].abort();
1405 }).call(this,typeof self
!== "undefined" ? self
: typeof window
!== "undefined" ? window
: {})
1406 },{"./polling":8,"component-emitter":12,"component-inherit":13,"debug":14,"xmlhttprequest":10}],8:[function(_dereq_
,module
,exports
){
1408 * Module dependencies.
1411 var Transport
= _dereq_('../transport');
1412 var parseqs
= _dereq_('parseqs');
1413 var parser
= _dereq_('engine.io-parser');
1414 var inherit
= _dereq_('component-inherit');
1415 var debug
= _dereq_('debug')('engine.io-client:polling');
1421 module
.exports
= Polling
;
1424 * Is XHR2 supported?
1427 var hasXHR2
= (function() {
1428 var XMLHttpRequest
= _dereq_('xmlhttprequest');
1429 var xhr
= new XMLHttpRequest({ agent
: this.agent
, xdomain
: false });
1430 return null != xhr
.responseType
;
1434 * Polling interface.
1436 * @param {Object} opts
1440 function Polling(opts
){
1441 var forceBase64
= (opts
&& opts
.forceBase64
);
1442 if (!hasXHR2
|| forceBase64
) {
1443 this.supportsBinary
= false;
1445 Transport
.call(this, opts
);
1449 * Inherits from Transport.
1452 inherit(Polling
, Transport
);
1458 Polling
.prototype.name
= 'polling';
1461 * Opens the socket (triggers polling). We write a PING message to determine
1462 * when the transport is open.
1467 Polling
.prototype.doOpen = function(){
1474 * @param {Function} callback upon buffers are flushed and transport is paused
1478 Polling
.prototype.pause = function(onPause
){
1482 this.readyState
= 'pausing';
1486 self
.readyState
= 'paused';
1490 if (this.polling
|| !this.writable
) {
1494 debug('we are currently polling - waiting to pause');
1496 this.once('pollComplete', function(){
1497 debug('pre-pause polling complete');
1502 if (!this.writable
) {
1503 debug('we are currently writing - waiting to pause');
1505 this.once('drain', function(){
1506 debug('pre-pause writing complete');
1516 * Starts polling cycle.
1521 Polling
.prototype.poll = function(){
1523 this.polling
= true;
1529 * Overloads onData to detect payloads.
1534 Polling
.prototype.onData = function(data
){
1536 debug('polling got data %s', data
);
1537 var callback = function(packet
, index
, total
) {
1538 // if its the first message we consider the transport open
1539 if ('opening' == self
.readyState
) {
1543 // if its a close packet, we close the ongoing requests
1544 if ('close' == packet
.type
) {
1549 // otherwise bypass onData and handle the message
1550 self
.onPacket(packet
);
1554 parser
.decodePayload(data
, this.socket
.binaryType
, callback
);
1556 // if an event did not trigger closing
1557 if ('closed' != this.readyState
) {
1558 // if we got data we're not polling
1559 this.polling
= false;
1560 this.emit('pollComplete');
1562 if ('open' == this.readyState
) {
1565 debug('ignoring poll - transport state "%s"', this.readyState
);
1571 * For polling, send a close packet.
1576 Polling
.prototype.doClose = function(){
1580 debug('writing close packet');
1581 self
.write([{ type
: 'close' }]);
1584 if ('open' == this.readyState
) {
1585 debug('transport open - closing');
1588 // in case we're trying to close while
1589 // handshaking is in progress (GH-164)
1590 debug('transport not open - deferring close');
1591 this.once('open', close
);
1596 * Writes a packets payload.
1598 * @param {Array} data packets
1599 * @param {Function} drain callback
1603 Polling
.prototype.write = function(packets
){
1605 this.writable
= false;
1606 var callbackfn = function() {
1607 self
.writable
= true;
1612 parser
.encodePayload(packets
, this.supportsBinary
, function(data
) {
1613 self
.doWrite(data
, callbackfn
);
1618 * Generates uri for connection.
1623 Polling
.prototype.uri = function(){
1624 var query
= this.query
|| {};
1625 var schema
= this.secure
? 'https' : 'http';
1628 // cache busting is forced
1629 if (false !== this.timestampRequests
) {
1630 query
[this.timestampParam
] = +new Date
+ '-' + Transport
.timestamps
++;
1633 if (!this.supportsBinary
&& !query
.sid
) {
1637 query
= parseqs
.encode(query
);
1639 // avoid port if default for schema
1640 if (this.port
&& (('https' == schema
&& this.port
!= 443) ||
1641 ('http' == schema
&& this.port
!= 80))) {
1642 port
= ':' + this.port
;
1645 // prepend ? to query
1647 query
= '?' + query
;
1650 return schema
+ '://' + this.hostname
+ port
+ this.path
+ query
;
1653 },{"../transport":4,"component-inherit":13,"debug":14,"engine.io-parser":15,"parseqs":25,"xmlhttprequest":10}],9:[function(_dereq_
,module
,exports
){
1655 * Module dependencies.
1658 var Transport
= _dereq_('../transport');
1659 var parser
= _dereq_('engine.io-parser');
1660 var parseqs
= _dereq_('parseqs');
1661 var inherit
= _dereq_('component-inherit');
1662 var debug
= _dereq_('debug')('engine.io-client:websocket');
1665 * `ws` exposes a WebSocket-compatible interface in
1666 * Node, or the `WebSocket` or `MozWebSocket` globals
1670 var WebSocket
= _dereq_('ws');
1676 module
.exports
= WS
;
1679 * WebSocket transport constructor.
1681 * @api {Object} connection options
1686 var forceBase64
= (opts
&& opts
.forceBase64
);
1688 this.supportsBinary
= false;
1690 Transport
.call(this, opts
);
1694 * Inherits from Transport.
1697 inherit(WS
, Transport
);
1705 WS
.prototype.name
= 'websocket';
1708 * WebSockets support binary
1711 WS
.prototype.supportsBinary
= true;
1719 WS
.prototype.doOpen = function(){
1720 if (!this.check()) {
1721 // let probe timeout
1726 var uri
= this.uri();
1727 var protocols
= void(0);
1728 var opts
= { agent
: this.agent
};
1730 this.ws
= new WebSocket(uri
, protocols
, opts
);
1732 if (this.ws
.binaryType
=== undefined) {
1733 this.supportsBinary
= false;
1736 this.ws
.binaryType
= 'arraybuffer';
1737 this.addEventListeners();
1741 * Adds event listeners to the socket
1746 WS
.prototype.addEventListeners = function(){
1749 this.ws
.onopen = function(){
1752 this.ws
.onclose = function(){
1755 this.ws
.onmessage = function(ev
){
1756 self
.onData(ev
.data
);
1758 this.ws
.onerror = function(e
){
1759 self
.onError('websocket error', e
);
1764 * Override `onData` to use a timer on iOS.
1765 * See: https://gist.github.com/mloughran/2052006
1770 if ('undefined' != typeof navigator
1771 && /iPad|iPhone|iPod/i.test(navigator
.userAgent
)) {
1772 WS
.prototype.onData = function(data
){
1774 setTimeout(function(){
1775 Transport
.prototype.onData
.call(self
, data
);
1781 * Writes data to socket.
1783 * @param {Array} array of packets.
1787 WS
.prototype.write = function(packets
){
1789 this.writable
= false;
1790 // encodePacket efficient as it uses WS framing
1791 // no need for encodePayload
1792 for (var i
= 0, l
= packets
.length
; i
< l
; i
++) {
1793 parser
.encodePacket(packets
[i
], this.supportsBinary
, function(data
) {
1794 //Sometimes the websocket has already been closed but the browser didn't
1795 //have a chance of informing us about it yet, in that case send will
1800 debug('websocket closed before onclose event');
1805 function ondrain() {
1806 self
.writable
= true;
1810 // defer to next tick to allow Socket to clear writeBuffer
1811 setTimeout(ondrain
, 0);
1820 WS
.prototype.onClose = function(){
1821 Transport
.prototype.onClose
.call(this);
1830 WS
.prototype.doClose = function(){
1831 if (typeof this.ws
!== 'undefined') {
1837 * Generates uri for connection.
1842 WS
.prototype.uri = function(){
1843 var query
= this.query
|| {};
1844 var schema
= this.secure
? 'wss' : 'ws';
1847 // avoid port if default for schema
1848 if (this.port
&& (('wss' == schema
&& this.port
!= 443)
1849 || ('ws' == schema
&& this.port
!= 80))) {
1850 port
= ':' + this.port
;
1853 // append timestamp to URI
1854 if (this.timestampRequests
) {
1855 query
[this.timestampParam
] = +new Date
;
1858 // communicate binary support capabilities
1859 if (!this.supportsBinary
) {
1863 query
= parseqs
.encode(query
);
1865 // prepend ? to query
1867 query
= '?' + query
;
1870 return schema
+ '://' + this.hostname
+ port
+ this.path
+ query
;
1874 * Feature detection for WebSocket.
1876 * @return {Boolean} whether this transport is available.
1880 WS
.prototype.check = function(){
1881 return !!WebSocket
&& !('__initialize' in WebSocket
&& this.name
=== WS
.prototype.name
);
1884 },{"../transport":4,"component-inherit":13,"debug":14,"engine.io-parser":15,"parseqs":25,"ws":27}],10:[function(_dereq_
,module
,exports
){
1885 // browser shim for xmlhttprequest module
1886 var hasCORS
= _dereq_('has-cors');
1888 module
.exports = function(opts
) {
1889 var xdomain
= opts
.xdomain
;
1891 // XMLHttpRequest can be disabled on IE
1893 if ('undefined' != typeof XMLHttpRequest
&& (!xdomain
|| hasCORS
)) {
1894 return new XMLHttpRequest();
1900 return new ActiveXObject('Microsoft.XMLHTTP');
1905 },{"has-cors":21}],11:[function(_dereq_
,module
,exports
){
1908 * Create a blob builder even when vendor prefixes exist
1911 var BlobBuilder
= global
.BlobBuilder
1912 || global
.WebKitBlobBuilder
1913 || global
.MSBlobBuilder
1914 || global
.MozBlobBuilder
;
1917 * Check if Blob constructor is supported
1920 var blobSupported
= (function() {
1922 var b
= new Blob(['hi']);
1930 * Check if BlobBuilder is supported
1933 var blobBuilderSupported
= BlobBuilder
1934 && BlobBuilder
.prototype.append
1935 && BlobBuilder
.prototype.getBlob
;
1937 function BlobBuilderConstructor(ary
, options
) {
1938 options
= options
|| {};
1940 var bb
= new BlobBuilder();
1941 for (var i
= 0; i
< ary
.length
; i
++) {
1944 return (options
.type
) ? bb
.getBlob(options
.type
) : bb
.getBlob();
1947 module
.exports
= (function() {
1948 if (blobSupported
) {
1950 } else if (blobBuilderSupported
) {
1951 return BlobBuilderConstructor
;
1957 }).call(this,typeof self
!== "undefined" ? self
: typeof window
!== "undefined" ? window
: {})
1958 },{}],12:[function(_dereq_
,module
,exports
){
1964 module
.exports
= Emitter
;
1967 * Initialize a new `Emitter`.
1972 function Emitter(obj
) {
1973 if (obj
) return mixin(obj
);
1977 * Mixin the emitter properties.
1979 * @param {Object} obj
1984 function mixin(obj
) {
1985 for (var key
in Emitter
.prototype) {
1986 obj
[key
] = Emitter
.prototype[key
];
1992 * Listen on the given `event` with `fn`.
1994 * @param {String} event
1995 * @param {Function} fn
2000 Emitter
.prototype.on
=
2001 Emitter
.prototype.addEventListener = function(event
, fn
){
2002 this._callbacks
= this._callbacks
|| {};
2003 (this._callbacks
[event
] = this._callbacks
[event
] || [])
2009 * Adds an `event` listener that will be invoked a single
2010 * time then automatically removed.
2012 * @param {String} event
2013 * @param {Function} fn
2018 Emitter
.prototype.once = function(event
, fn
){
2020 this._callbacks
= this._callbacks
|| {};
2023 self
.off(event
, on
);
2024 fn
.apply(this, arguments
);
2033 * Remove the given callback for `event` or all
2034 * registered callbacks.
2036 * @param {String} event
2037 * @param {Function} fn
2042 Emitter
.prototype.off
=
2043 Emitter
.prototype.removeListener
=
2044 Emitter
.prototype.removeAllListeners
=
2045 Emitter
.prototype.removeEventListener = function(event
, fn
){
2046 this._callbacks
= this._callbacks
|| {};
2049 if (0 == arguments
.length
) {
2050 this._callbacks
= {};
2055 var callbacks
= this._callbacks
[event
];
2056 if (!callbacks
) return this;
2058 // remove all handlers
2059 if (1 == arguments
.length
) {
2060 delete this._callbacks
[event
];
2064 // remove specific handler
2066 for (var i
= 0; i
< callbacks
.length
; i
++) {
2068 if (cb
=== fn
|| cb
.fn
=== fn
) {
2069 callbacks
.splice(i
, 1);
2077 * Emit `event` with the given args.
2079 * @param {String} event
2080 * @param {Mixed} ...
2084 Emitter
.prototype.emit = function(event
){
2085 this._callbacks
= this._callbacks
|| {};
2086 var args
= [].slice
.call(arguments
, 1)
2087 , callbacks
= this._callbacks
[event
];
2090 callbacks
= callbacks
.slice(0);
2091 for (var i
= 0, len
= callbacks
.length
; i
< len
; ++i
) {
2092 callbacks
[i
].apply(this, args
);
2100 * Return array of callbacks for `event`.
2102 * @param {String} event
2107 Emitter
.prototype.listeners = function(event
){
2108 this._callbacks
= this._callbacks
|| {};
2109 return this._callbacks
[event
] || [];
2113 * Check if this emitter has `event` handlers.
2115 * @param {String} event
2120 Emitter
.prototype.hasListeners = function(event
){
2121 return !! this.listeners(event
).length
;
2124 },{}],13:[function(_dereq_
,module
,exports
){
2126 module
.exports = function(a
, b
){
2127 var fn = function(){};
2128 fn
.prototype = b
.prototype;
2129 a
.prototype = new fn
;
2130 a
.prototype.constructor = a
;
2132 },{}],14:[function(_dereq_
,module
,exports
){
2135 * Expose `debug()` as the module.
2138 module
.exports
= debug
;
2141 * Create a debugger with the given `name`.
2143 * @param {String} name
2148 function debug(name
) {
2149 if (!debug
.enabled(name
)) return function(){};
2151 return function(fmt
){
2154 var curr
= new Date
;
2155 var ms
= curr
- (debug
[name
] || curr
);
2161 + ' +' + debug
.humanize(ms
);
2163 // This hackery is required for IE8
2164 // where `console.log` doesn't have 'apply'
2167 && Function
.prototype.apply
.call(console
.log
, console
, arguments
);
2172 * The currently active debug mode names.
2179 * Enables a debug mode by name. This can include modes
2180 * separated by a colon and wildcards.
2182 * @param {String} name
2186 debug
.enable = function(name
) {
2188 localStorage
.debug
= name
;
2191 var split
= (name
|| '').split(/[\s,]+/)
2192 , len
= split
.length
;
2194 for (var i
= 0; i
< len
; i
++) {
2195 name
= split
[i
].replace('*', '.*?');
2196 if (name
[0] === '-') {
2197 debug
.skips
.push(new RegExp('^' + name
.substr(1) + '$'));
2200 debug
.names
.push(new RegExp('^' + name
+ '$'));
2206 * Disable debug output.
2211 debug
.disable = function(){
2216 * Humanize the given `ms`.
2223 debug
.humanize = function(ms
) {
2228 if (ms
>= hour
) return (ms
/ hour
).toFixed(1) + 'h';
2229 if (ms
>= min
) return (ms
/ min
).toFixed(1) + 'm';
2230 if (ms
>= sec
) return (ms
/ sec
| 0) + 's';
2235 * Returns true if the given mode name is enabled, false otherwise.
2237 * @param {String} name
2242 debug
.enabled = function(name
) {
2243 for (var i
= 0, len
= debug
.skips
.length
; i
< len
; i
++) {
2244 if (debug
.skips
[i
].test(name
)) {
2248 for (var i
= 0, len
= debug
.names
.length
; i
< len
; i
++) {
2249 if (debug
.names
[i
].test(name
)) {
2260 function coerce(val
) {
2261 if (val
instanceof Error
) return val
.stack
|| val
.message
;
2268 if (window
.localStorage
) debug
.enable(localStorage
.debug
);
2271 },{}],15:[function(_dereq_
,module
,exports
){
2274 * Module dependencies.
2277 var keys
= _dereq_('./keys');
2278 var sliceBuffer
= _dereq_('arraybuffer.slice');
2279 var base64encoder
= _dereq_('base64-arraybuffer');
2280 var after
= _dereq_('after');
2281 var utf8
= _dereq_('utf8');
2284 * Check if we are running an android browser. That requires us to use
2285 * ArrayBuffer with polling transports...
2287 * http://ghinda.net/jpeg-blob-ajax-android/
2290 var isAndroid
= navigator
.userAgent
.match(/Android/i);
2293 * Current protocol version.
2296 exports
.protocol
= 2;
2302 var packets
= exports
.packets
= {
2304 , close
: 1 // non-ws
2312 var packetslist
= keys(packets
);
2315 * Premade error packet.
2318 var err
= { type
: 'error', data
: 'parser error' };
2321 * Create a blob api even for blob builder when vendor prefixes exist
2324 var Blob
= _dereq_('blob');
2329 * <packet type id> [ <data> ]
2337 * Binary is encoded in an identical principle
2342 exports
.encodePacket = function (packet
, supportsBinary
, callback
) {
2343 if (typeof supportsBinary
== 'function') {
2344 callback
= supportsBinary
;
2345 supportsBinary
= false;
2348 var data
= (packet
.data
=== undefined)
2350 : packet
.data
.buffer
|| packet
.data
;
2352 if (global
.ArrayBuffer
&& data
instanceof ArrayBuffer
) {
2353 return encodeArrayBuffer(packet
, supportsBinary
, callback
);
2354 } else if (Blob
&& data
instanceof global
.Blob
) {
2355 return encodeBlob(packet
, supportsBinary
, callback
);
2358 // Sending data as a utf-8 string
2359 var encoded
= packets
[packet
.type
];
2361 // data fragment is optional
2362 if (undefined !== packet
.data
) {
2363 encoded
+= utf8
.encode(String(packet
.data
));
2366 return callback('' + encoded
);
2371 * Encode packet helpers for binary types
2374 function encodeArrayBuffer(packet
, supportsBinary
, callback
) {
2375 if (!supportsBinary
) {
2376 return exports
.encodeBase64Packet(packet
, callback
);
2379 var data
= packet
.data
;
2380 var contentArray
= new Uint8Array(data
);
2381 var resultBuffer
= new Uint8Array(1 + data
.byteLength
);
2383 resultBuffer
[0] = packets
[packet
.type
];
2384 for (var i
= 0; i
< contentArray
.length
; i
++) {
2385 resultBuffer
[i
+1] = contentArray
[i
];
2388 return callback(resultBuffer
.buffer
);
2391 function encodeBlobAsArrayBuffer(packet
, supportsBinary
, callback
) {
2392 if (!supportsBinary
) {
2393 return exports
.encodeBase64Packet(packet
, callback
);
2396 var fr
= new FileReader();
2397 fr
.onload = function() {
2398 packet
.data
= fr
.result
;
2399 exports
.encodePacket(packet
, supportsBinary
, callback
);
2401 return fr
.readAsArrayBuffer(packet
.data
);
2404 function encodeBlob(packet
, supportsBinary
, callback
) {
2405 if (!supportsBinary
) {
2406 return exports
.encodeBase64Packet(packet
, callback
);
2410 return encodeBlobAsArrayBuffer(packet
, supportsBinary
, callback
);
2413 var length
= new Uint8Array(1);
2414 length
[0] = packets
[packet
.type
];
2415 var blob
= new Blob([length
.buffer
, packet
.data
]);
2417 return callback(blob
);
2421 * Encodes a packet with binary data in a base64 string
2423 * @param {Object} packet, has `type` and `data`
2424 * @return {String} base64 encoded message
2427 exports
.encodeBase64Packet = function(packet
, callback
) {
2428 var message
= 'b' + exports
.packets
[packet
.type
];
2429 if (Blob
&& packet
.data
instanceof Blob
) {
2430 var fr
= new FileReader();
2431 fr
.onload = function() {
2432 var b64
= fr
.result
.split(',')[1];
2433 callback(message
+ b64
);
2435 return fr
.readAsDataURL(packet
.data
);
2440 b64data
= String
.fromCharCode
.apply(null, new Uint8Array(packet
.data
));
2442 // iPhone Safari doesn't let you apply with typed arrays
2443 var typed
= new Uint8Array(packet
.data
);
2444 var basic
= new Array(typed
.length
);
2445 for (var i
= 0; i
< typed
.length
; i
++) {
2446 basic
[i
] = typed
[i
];
2448 b64data
= String
.fromCharCode
.apply(null, basic
);
2450 message
+= global
.btoa(b64data
);
2451 return callback(message
);
2455 * Decodes a packet. Changes format to Blob if requested.
2457 * @return {Object} with `type` and `data` (if any)
2461 exports
.decodePacket = function (data
, binaryType
) {
2463 if (typeof data
== 'string' || data
=== undefined) {
2464 if (data
.charAt(0) == 'b') {
2465 return exports
.decodeBase64Packet(data
.substr(1), binaryType
);
2468 data
= utf8
.decode(data
);
2469 var type
= data
.charAt(0);
2471 if (Number(type
) != type
|| !packetslist
[type
]) {
2475 if (data
.length
> 1) {
2476 return { type
: packetslist
[type
], data
: data
.substring(1) };
2478 return { type
: packetslist
[type
] };
2482 var asArray
= new Uint8Array(data
);
2483 var type
= asArray
[0];
2484 var rest
= sliceBuffer(data
, 1);
2485 if (Blob
&& binaryType
=== 'blob') {
2486 rest
= new Blob([rest
]);
2488 return { type
: packetslist
[type
], data
: rest
};
2492 * Decodes a packet encoded in a base64 string
2494 * @param {String} base64 encoded message
2495 * @return {Object} with `type` and `data` (if any)
2498 exports
.decodeBase64Packet = function(msg
, binaryType
) {
2499 var type
= packetslist
[msg
.charAt(0)];
2500 if (!global
.ArrayBuffer
) {
2501 return { type
: type
, data
: { base64
: true, data
: msg
.substr(1) } };
2504 var data
= base64encoder
.decode(msg
.substr(1));
2506 if (binaryType
=== 'blob' && Blob
) {
2507 data
= new Blob([data
]);
2510 return { type
: type
, data
: data
};
2514 * Encodes multiple messages (payload).
2520 * 11:hello world2:hi
2522 * If any contents are binary, they will be encoded as base64 strings. Base64
2523 * encoded strings are marked with a b before the length specifier
2525 * @param {Array} packets
2529 exports
.encodePayload = function (packets
, supportsBinary
, callback
) {
2530 if (typeof supportsBinary
== 'function') {
2531 callback
= supportsBinary
;
2532 supportsBinary
= null;
2535 if (supportsBinary
) {
2536 if (Blob
&& !isAndroid
) {
2537 return exports
.encodePayloadAsBlob(packets
, callback
);
2540 return exports
.encodePayloadAsArrayBuffer(packets
, callback
);
2543 if (!packets
.length
) {
2544 return callback('0:');
2547 function setLengthHeader(message
) {
2548 return message
.length
+ ':' + message
;
2551 function encodeOne(packet
, doneCallback
) {
2552 exports
.encodePacket(packet
, supportsBinary
, function(message
) {
2553 doneCallback(null, setLengthHeader(message
));
2557 map(packets
, encodeOne
, function(err
, results
) {
2558 return callback(results
.join(''));
2563 * Async array map using after
2566 function map(ary
, each
, done
) {
2567 var result
= new Array(ary
.length
);
2568 var next
= after(ary
.length
, done
);
2570 var eachWithIndex = function(i
, el
, cb
) {
2571 each(el
, function(error
, msg
) {
2577 for (var i
= 0; i
< ary
.length
; i
++) {
2578 eachWithIndex(i
, ary
[i
], next
);
2583 * Decodes data when a payload is maybe expected. Possible binary contents are
2584 * decoded from their base64 representation
2586 * @param {String} data, callback method
2590 exports
.decodePayload = function (data
, binaryType
, callback
) {
2591 if (typeof data
!= 'string') {
2592 return exports
.decodePayloadAsBinary(data
, binaryType
, callback
);
2595 if (typeof binaryType
=== 'function') {
2596 callback
= binaryType
;
2602 // parser error - ignoring payload
2603 return callback(err
, 0, 1);
2609 for (var i
= 0, l
= data
.length
; i
< l
; i
++) {
2610 var chr
= data
.charAt(i
);
2615 if ('' == length
|| (length
!= (n
= Number(length
)))) {
2616 // parser error - ignoring payload
2617 return callback(err
, 0, 1);
2620 msg
= data
.substr(i
+ 1, n
);
2622 if (length
!= msg
.length
) {
2623 // parser error - ignoring payload
2624 return callback(err
, 0, 1);
2628 packet
= exports
.decodePacket(msg
, binaryType
);
2630 if (err
.type
== packet
.type
&& err
.data
== packet
.data
) {
2631 // parser error in individual packet - ignoring payload
2632 return callback(err
, 0, 1);
2635 var ret
= callback(packet
, i
+ n
, l
);
2636 if (false === ret
) return;
2646 // parser error - ignoring payload
2647 return callback(err
, 0, 1);
2653 * Encodes multiple messages (payload) as binary.
2655 * <1 = binary, 0 = string><number from 0-9><number from 0-9>[...]<number
2659 * 1 3 255 1 2 3, if the binary contents are interpreted as 8 bit integers
2661 * @param {Array} packets
2662 * @return {ArrayBuffer} encoded payload
2666 exports
.encodePayloadAsArrayBuffer = function(packets
, callback
) {
2667 if (!packets
.length
) {
2668 return callback(new ArrayBuffer(0));
2671 function encodeOne(packet
, doneCallback
) {
2672 exports
.encodePacket(packet
, true, function(data
) {
2673 return doneCallback(null, data
);
2677 map(packets
, encodeOne
, function(err
, encodedPackets
) {
2678 var totalLength
= encodedPackets
.reduce(function(acc
, p
) {
2680 if (typeof p
=== 'string'){
2685 return acc
+ len
.toString().length
+ len
+ 2; // string/binary identifier + separator = 2
2688 var resultArray
= new Uint8Array(totalLength
);
2690 var bufferIndex
= 0;
2691 encodedPackets
.forEach(function(p
) {
2692 var isString
= typeof p
=== 'string';
2695 var view
= new Uint8Array(p
.length
);
2696 for (var i
= 0; i
< p
.length
; i
++) {
2697 view
[i
] = p
.charCodeAt(i
);
2702 if (isString
) { // not true binary
2703 resultArray
[bufferIndex
++] = 0;
2704 } else { // true binary
2705 resultArray
[bufferIndex
++] = 1;
2708 var lenStr
= ab
.byteLength
.toString();
2709 for (var i
= 0; i
< lenStr
.length
; i
++) {
2710 resultArray
[bufferIndex
++] = parseInt(lenStr
[i
]);
2712 resultArray
[bufferIndex
++] = 255;
2714 var view
= new Uint8Array(ab
);
2715 for (var i
= 0; i
< view
.length
; i
++) {
2716 resultArray
[bufferIndex
++] = view
[i
];
2720 return callback(resultArray
.buffer
);
2728 exports
.encodePayloadAsBlob = function(packets
, callback
) {
2729 function encodeOne(packet
, doneCallback
) {
2730 exports
.encodePacket(packet
, true, function(encoded
) {
2731 var binaryIdentifier
= new Uint8Array(1);
2732 binaryIdentifier
[0] = 1;
2733 if (typeof encoded
=== 'string') {
2734 var view
= new Uint8Array(encoded
.length
);
2735 for (var i
= 0; i
< encoded
.length
; i
++) {
2736 view
[i
] = encoded
.charCodeAt(i
);
2738 encoded
= view
.buffer
;
2739 binaryIdentifier
[0] = 0;
2742 var len
= (encoded
instanceof ArrayBuffer
)
2743 ? encoded
.byteLength
2746 var lenStr
= len
.toString();
2747 var lengthAry
= new Uint8Array(lenStr
.length
+ 1);
2748 for (var i
= 0; i
< lenStr
.length
; i
++) {
2749 lengthAry
[i
] = parseInt(lenStr
[i
]);
2751 lengthAry
[lenStr
.length
] = 255;
2754 var blob
= new Blob([binaryIdentifier
.buffer
, lengthAry
.buffer
, encoded
]);
2755 doneCallback(null, blob
);
2760 map(packets
, encodeOne
, function(err
, results
) {
2761 return callback(new Blob(results
));
2766 * Decodes data when a payload is maybe expected. Strings are decoded by
2767 * interpreting each byte as a key code for entries marked to start with 0. See
2768 * description of encodePayloadAsBinary
2770 * @param {ArrayBuffer} data, callback method
2774 exports
.decodePayloadAsBinary = function (data
, binaryType
, callback
) {
2775 if (typeof binaryType
=== 'function') {
2776 callback
= binaryType
;
2780 var bufferTail
= data
;
2783 while (bufferTail
.byteLength
> 0) {
2784 var tailArray
= new Uint8Array(bufferTail
);
2785 var isString
= tailArray
[0] === 0;
2787 for (var i
= 1; ; i
++) {
2788 if (tailArray
[i
] == 255) break;
2789 msgLength
+= tailArray
[i
];
2791 bufferTail
= sliceBuffer(bufferTail
, 2 + msgLength
.length
);
2792 msgLength
= parseInt(msgLength
);
2794 var msg
= sliceBuffer(bufferTail
, 0, msgLength
);
2797 msg
= String
.fromCharCode
.apply(null, new Uint8Array(msg
));
2799 // iPhone Safari doesn't let you apply to typed arrays
2800 var typed
= new Uint8Array(msg
);
2802 for (var i
= 0; i
< typed
.length
; i
++) {
2803 msg
+= String
.fromCharCode(typed
[i
]);
2808 bufferTail
= sliceBuffer(bufferTail
, msgLength
);
2811 var total
= buffers
.length
;
2812 buffers
.forEach(function(buffer
, i
) {
2813 callback(exports
.decodePacket(buffer
, binaryType
), i
, total
);
2817 }).call(this,typeof self
!== "undefined" ? self
: typeof window
!== "undefined" ? window
: {})
2818 },{"./keys":16,"after":17,"arraybuffer.slice":18,"base64-arraybuffer":19,"blob":11,"utf8":20}],16:[function(_dereq_
,module
,exports
){
2821 * Gets the keys for an object.
2823 * @return {Array} keys
2827 module
.exports
= Object
.keys
|| function keys (obj
){
2829 var has
= Object
.prototype.hasOwnProperty
;
2831 for (var i
in obj
) {
2832 if (has
.call(obj
, i
)) {
2839 },{}],17:[function(_dereq_
,module
,exports
){
2840 module
.exports
= after
2842 function after(count
, callback
, err_cb
) {
2844 err_cb
= err_cb
|| noop
2847 return (count
=== 0) ? callback() : proxy
2849 function proxy(err
, result
) {
2850 if (proxy
.count
<= 0) {
2851 throw new Error('after called too many times')
2855 // after first error, rest are passed to err_cb
2859 // future error callbacks will go to error handler
2861 } else if (proxy
.count
=== 0 && !bail
) {
2862 callback(null, result
)
2869 },{}],18:[function(_dereq_
,module
,exports
){
2871 * An abstraction for slicing an arraybuffer even when
2872 * ArrayBuffer.prototype.slice is not supported
2877 module
.exports = function(arraybuffer
, start
, end
) {
2878 var bytes
= arraybuffer
.byteLength
;
2882 if (arraybuffer
.slice
) { return arraybuffer
.slice(start
, end
); }
2884 if (start
< 0) { start
+= bytes
; }
2885 if (end
< 0) { end
+= bytes
; }
2886 if (end
> bytes
) { end
= bytes
; }
2888 if (start
>= bytes
|| start
>= end
|| bytes
=== 0) {
2889 return new ArrayBuffer(0);
2892 var abv
= new Uint8Array(arraybuffer
);
2893 var result
= new Uint8Array(end
- start
);
2894 for (var i
= start
, ii
= 0; i
< end
; i
++, ii
++) {
2895 result
[ii
] = abv
[i
];
2897 return result
.buffer
;
2900 },{}],19:[function(_dereq_
,module
,exports
){
2902 * base64-arraybuffer
2903 * https://github.com/niklasvh/base64-arraybuffer
2905 * Copyright (c) 2012 Niklas von Hertzen
2906 * Licensed under the MIT license.
2911 exports
.encode = function(arraybuffer
) {
2912 var bytes
= new Uint8Array(arraybuffer
),
2913 i
, len
= bytes
.length
, base64
= "";
2915 for (i
= 0; i
< len
; i
+=3) {
2916 base64
+= chars
[bytes
[i
] >> 2];
2917 base64
+= chars
[((bytes
[i
] & 3) << 4) | (bytes
[i
+ 1] >> 4)];
2918 base64
+= chars
[((bytes
[i
+ 1] & 15) << 2) | (bytes
[i
+ 2] >> 6)];
2919 base64
+= chars
[bytes
[i
+ 2] & 63];
2922 if ((len
% 3) === 2) {
2923 base64
= base64
.substring(0, base64
.length
- 1) + "=";
2924 } else if (len
% 3 === 1) {
2925 base64
= base64
.substring(0, base64
.length
- 2) + "==";
2931 exports
.decode = function(base64
) {
2932 var bufferLength
= base64
.length
* 0.75,
2933 len
= base64
.length
, i
, p
= 0,
2934 encoded1
, encoded2
, encoded3
, encoded4
;
2936 if (base64
[base64
.length
- 1] === "=") {
2938 if (base64
[base64
.length
- 2] === "=") {
2943 var arraybuffer
= new ArrayBuffer(bufferLength
),
2944 bytes
= new Uint8Array(arraybuffer
);
2946 for (i
= 0; i
< len
; i
+=4) {
2947 encoded1
= chars
.indexOf(base64
[i
]);
2948 encoded2
= chars
.indexOf(base64
[i
+1]);
2949 encoded3
= chars
.indexOf(base64
[i
+2]);
2950 encoded4
= chars
.indexOf(base64
[i
+3]);
2952 bytes
[p
++] = (encoded1
<< 2) | (encoded2
>> 4);
2953 bytes
[p
++] = ((encoded2
& 15) << 4) | (encoded3
>> 2);
2954 bytes
[p
++] = ((encoded3
& 3) << 6) | (encoded4
& 63);
2959 })("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/");
2961 },{}],20:[function(_dereq_
,module
,exports
){
2963 /*! http://mths.be/utf8js v2.0.0 by @mathias */
2966 // Detect free variables `exports`
2967 var freeExports
= typeof exports
== 'object' && exports
;
2969 // Detect free variable `module`
2970 var freeModule
= typeof module
== 'object' && module
&&
2971 module
.exports
== freeExports
&& module
;
2973 // Detect free variable `global`, from Node.js or Browserified code,
2974 // and use it as `root`
2975 var freeGlobal
= typeof global
== 'object' && global
;
2976 if (freeGlobal
.global
=== freeGlobal
|| freeGlobal
.window
=== freeGlobal
) {
2980 /*--------------------------------------------------------------------------*/
2982 var stringFromCharCode
= String
.fromCharCode
;
2984 // Taken from http://mths.be/punycode
2985 function ucs2decode(string
) {
2988 var length
= string
.length
;
2991 while (counter
< length
) {
2992 value
= string
.charCodeAt(counter
++);
2993 if (value
>= 0xD800 && value
<= 0xDBFF && counter
< length
) {
2994 // high surrogate, and there is a next character
2995 extra
= string
.charCodeAt(counter
++);
2996 if ((extra
& 0xFC00) == 0xDC00) { // low surrogate
2997 output
.push(((value
& 0x3FF) << 10) + (extra
& 0x3FF) + 0x10000);
2999 // unmatched surrogate; only append this code unit, in case the next
3000 // code unit is the high surrogate of a surrogate pair
3011 // Taken from http://mths.be/punycode
3012 function ucs2encode(array
) {
3013 var length
= array
.length
;
3017 while (++index
< length
) {
3018 value
= array
[index
];
3019 if (value
> 0xFFFF) {
3021 output
+= stringFromCharCode(value
>>> 10 & 0x3FF | 0xD800);
3022 value
= 0xDC00 | value
& 0x3FF;
3024 output
+= stringFromCharCode(value
);
3029 /*--------------------------------------------------------------------------*/
3031 function createByte(codePoint
, shift
) {
3032 return stringFromCharCode(((codePoint
>> shift
) & 0x3F) | 0x80);
3035 function encodeCodePoint(codePoint
) {
3036 if ((codePoint
& 0xFFFFFF80) == 0) { // 1-byte sequence
3037 return stringFromCharCode(codePoint
);
3040 if ((codePoint
& 0xFFFFF800) == 0) { // 2-byte sequence
3041 symbol
= stringFromCharCode(((codePoint
>> 6) & 0x1F) | 0xC0);
3043 else if ((codePoint
& 0xFFFF0000) == 0) { // 3-byte sequence
3044 symbol
= stringFromCharCode(((codePoint
>> 12) & 0x0F) | 0xE0);
3045 symbol
+= createByte(codePoint
, 6);
3047 else if ((codePoint
& 0xFFE00000) == 0) { // 4-byte sequence
3048 symbol
= stringFromCharCode(((codePoint
>> 18) & 0x07) | 0xF0);
3049 symbol
+= createByte(codePoint
, 12);
3050 symbol
+= createByte(codePoint
, 6);
3052 symbol
+= stringFromCharCode((codePoint
& 0x3F) | 0x80);
3056 function utf8encode(string
) {
3057 var codePoints
= ucs2decode(string
);
3059 // console.log(JSON.stringify(codePoints.map(function(x) {
3060 // return 'U+' + x.toString(16).toUpperCase();
3063 var length
= codePoints
.length
;
3066 var byteString
= '';
3067 while (++index
< length
) {
3068 codePoint
= codePoints
[index
];
3069 byteString
+= encodeCodePoint(codePoint
);
3074 /*--------------------------------------------------------------------------*/
3076 function readContinuationByte() {
3077 if (byteIndex
>= byteCount
) {
3078 throw Error('Invalid byte index');
3081 var continuationByte
= byteArray
[byteIndex
] & 0xFF;
3084 if ((continuationByte
& 0xC0) == 0x80) {
3085 return continuationByte
& 0x3F;
3088 // If we end up here, it’s not a continuation byte
3089 throw Error('Invalid continuation byte');
3092 function decodeSymbol() {
3099 if (byteIndex
> byteCount
) {
3100 throw Error('Invalid byte index');
3103 if (byteIndex
== byteCount
) {
3108 byte1
= byteArray
[byteIndex
] & 0xFF;
3111 // 1-byte sequence (no continuation bytes)
3112 if ((byte1
& 0x80) == 0) {
3117 if ((byte1
& 0xE0) == 0xC0) {
3118 var byte2
= readContinuationByte();
3119 codePoint
= ((byte1
& 0x1F) << 6) | byte2
;
3120 if (codePoint
>= 0x80) {
3123 throw Error('Invalid continuation byte');
3127 // 3-byte sequence (may include unpaired surrogates)
3128 if ((byte1
& 0xF0) == 0xE0) {
3129 byte2
= readContinuationByte();
3130 byte3
= readContinuationByte();
3131 codePoint
= ((byte1
& 0x0F) << 12) | (byte2
<< 6) | byte3
;
3132 if (codePoint
>= 0x0800) {
3135 throw Error('Invalid continuation byte');
3140 if ((byte1
& 0xF8) == 0xF0) {
3141 byte2
= readContinuationByte();
3142 byte3
= readContinuationByte();
3143 byte4
= readContinuationByte();
3144 codePoint
= ((byte1
& 0x0F) << 0x12) | (byte2
<< 0x0C) |
3145 (byte3
<< 0x06) | byte4
;
3146 if (codePoint
>= 0x010000 && codePoint
<= 0x10FFFF) {
3151 throw Error('Invalid UTF-8 detected');
3157 function utf8decode(byteString
) {
3158 byteArray
= ucs2decode(byteString
);
3159 byteCount
= byteArray
.length
;
3161 var codePoints
= [];
3163 while ((tmp
= decodeSymbol()) !== false) {
3164 codePoints
.push(tmp
);
3166 return ucs2encode(codePoints
);
3169 /*--------------------------------------------------------------------------*/
3173 'encode': utf8encode
,
3174 'decode': utf8decode
3177 // Some AMD build optimizers, like r.js, check for specific condition patterns
3178 // like the following:
3180 typeof define
== 'function' &&
3181 typeof define
.amd
== 'object' &&
3187 } else if (freeExports
&& !freeExports
.nodeType
) {
3188 if (freeModule
) { // in Node.js or RingoJS v0.8.0+
3189 freeModule
.exports
= utf8
;
3190 } else { // in Narwhal or RingoJS v0.7.0-
3192 var hasOwnProperty
= object
.hasOwnProperty
;
3193 for (var key
in utf8
) {
3194 hasOwnProperty
.call(utf8
, key
) && (freeExports
[key
] = utf8
[key
]);
3197 } else { // in Rhino or a web browser
3203 }).call(this,typeof self
!== "undefined" ? self
: typeof window
!== "undefined" ? window
: {})
3204 },{}],21:[function(_dereq_
,module
,exports
){
3207 * Module dependencies.
3210 var global
= _dereq_('global');
3215 * Logic borrowed from Modernizr:
3217 * - https://github.com/Modernizr/Modernizr/blob/master/feature-detects/cors.js
3221 module
.exports
= 'XMLHttpRequest' in global
&&
3222 'withCredentials' in new global
.XMLHttpRequest();
3224 // if XMLHttp support is disabled in IE then it will throw
3225 // when trying to create
3226 module
.exports
= false;
3229 },{"global":22}],22:[function(_dereq_
,module
,exports
){
3232 * Returns `this`. Execute this without a "context" (i.e. without it being
3233 * attached to an object of the left-hand side), and `this` points to the
3234 * "global" scope of the current JS execution.
3237 module
.exports
= (function () { return this; })();
3239 },{}],23:[function(_dereq_
,module
,exports
){
3241 var indexOf
= [].indexOf
;
3243 module
.exports = function(arr
, obj
){
3244 if (indexOf
) return arr
.indexOf(obj
);
3245 for (var i
= 0; i
< arr
.length
; ++i
) {
3246 if (arr
[i
] === obj
) return i
;
3250 },{}],24:[function(_dereq_
,module
,exports
){
3255 * @see Based on jQuery#parseJSON (MIT) and JSON2
3259 var rvalidchars
= /^[\],:{}\s]*$/;
3260 var rvalidescape
= /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g;
3261 var rvalidtokens
= /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g;
3262 var rvalidbraces
= /(?:^|:|,)(?:\s*\[)+/g;
3263 var rtrimLeft
= /^\s+/;
3264 var rtrimRight
= /\s+$/;
3266 module
.exports
= function parsejson(data
) {
3267 if ('string' != typeof data
|| !data
) {
3271 data
= data
.replace(rtrimLeft
, '').replace(rtrimRight
, '');
3273 // Attempt to parse using the native JSON parser first
3274 if (global
.JSON
&& JSON
.parse
) {
3275 return JSON
.parse(data
);
3278 if (rvalidchars
.test(data
.replace(rvalidescape
, '@')
3279 .replace(rvalidtokens
, ']')
3280 .replace(rvalidbraces
, ''))) {
3281 return (new Function('return ' + data
))();
3284 }).call(this,typeof self
!== "undefined" ? self
: typeof window
!== "undefined" ? window
: {})
3285 },{}],25:[function(_dereq_
,module
,exports
){
3287 * Compiles a querystring
3288 * Returns string representation of the object
3294 exports
.encode = function (obj
) {
3297 for (var i
in obj
) {
3298 if (obj
.hasOwnProperty(i
)) {
3299 if (str
.length
) str
+= '&';
3300 str
+= encodeURIComponent(i
) + '=' + encodeURIComponent(obj
[i
]);
3308 * Parses a simple querystring into an object
3310 * @param {String} qs
3314 exports
.decode = function(qs
){
3316 var pairs
= qs
.split('&');
3317 for (var i
= 0, l
= pairs
.length
; i
< l
; i
++) {
3318 var pair
= pairs
[i
].split('=');
3319 qry
[decodeURIComponent(pair
[0])] = decodeURIComponent(pair
[1]);
3324 },{}],26:[function(_dereq_
,module
,exports
){
3328 * @author Steven Levithan <stevenlevithan.com> (MIT license)
3332 var re
= /^(?:(?![^:@]+:[^:@\/]*@)(http|https|ws|wss):\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?((?:[a-f0-9]{0,4}:){2,7}[a-f0-9]{0,4}|[^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/;
3335 'source', 'protocol', 'authority', 'userInfo', 'user', 'password', 'host'
3336 , 'port', 'relative', 'path', 'directory', 'file', 'query', 'anchor'
3339 module
.exports
= function parseuri(str
) {
3340 var m
= re
.exec(str
|| '')
3345 uri
[parts
[i
]] = m
[i
] || '';
3351 },{}],27:[function(_dereq_
,module
,exports
){
3354 * Module dependencies.
3357 var global
= (function() { return this; })();
3360 * WebSocket constructor.
3363 var WebSocket
= global
.WebSocket
|| global
.MozWebSocket
;
3369 module
.exports
= WebSocket
? ws
: null;
3372 * WebSocket constructor.
3374 * The third `opts` options object gets ignored in web browsers, since it's
3375 * non-standard, and throws a TypeError if passed to the constructor.
3376 * See: https://github.com/einaros/ws/issues/227
3378 * @param {String} uri
3379 * @param {Array} protocols (optional)
3380 * @param {Object) opts (optional)
3384 function ws(uri
, protocols
, opts
) {
3387 instance
= new WebSocket(uri
, protocols
);
3389 instance
= new WebSocket(uri
);
3394 if (WebSocket
) ws
.prototype = WebSocket
.prototype;