Merge branch 'development'
[KiwiIRC.git] / client / assets / libs / engine.io.js
CommitLineData
0de9e7ec 1!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.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){
6ab4b1ba
D
2
3module.exports = _dereq_('./lib/');
4
5},{"./lib/":2}],2:[function(_dereq_,module,exports){
6
7module.exports = _dereq_('./socket');
d99e7823 8
f8e5fb60 9/**
6ab4b1ba 10 * Exports parser
a74c0f0c 11 *
a74c0f0c 12 * @api public
6ab4b1ba 13 *
f8e5fb60 14 */
6ab4b1ba 15module.exports.parser = _dereq_('engine.io-parser');
d99e7823 16
e65c2242 17},{"./socket":3,"engine.io-parser":15}],3:[function(_dereq_,module,exports){
6ab4b1ba
D
18(function (global){
19/**
20 * Module dependencies.
21 */
a74c0f0c 22
6ab4b1ba 23var transports = _dereq_('./transports');
e65c2242 24var Emitter = _dereq_('component-emitter');
6ab4b1ba
D
25var debug = _dereq_('debug')('engine.io-client:socket');
26var index = _dereq_('indexof');
27var parser = _dereq_('engine.io-parser');
28var parseuri = _dereq_('parseuri');
29var parsejson = _dereq_('parsejson');
30var parseqs = _dereq_('parseqs');
d99e7823
D
31
32/**
6ab4b1ba 33 * Module exports.
d99e7823
D
34 */
35
6ab4b1ba 36module.exports = Socket;
d99e7823
D
37
38/**
6ab4b1ba
D
39 * Noop function.
40 *
41 * @api private
d99e7823
D
42 */
43
6ab4b1ba 44function noop(){}
d99e7823
D
45
46/**
6ab4b1ba 47 * Socket constructor.
a74c0f0c 48 *
6ab4b1ba
D
49 * @param {String|Object} uri or options
50 * @param {Object} options
51 * @api public
d99e7823
D
52 */
53
6ab4b1ba
D
54function Socket(uri, opts){
55 if (!(this instanceof Socket)) return new Socket(uri, opts);
56
57 opts = opts || {};
d99e7823 58
6ab4b1ba
D
59 if (uri && 'object' == typeof uri) {
60 opts = uri;
61 uri = null;
62 }
d99e7823 63
6ab4b1ba
D
64 if (uri) {
65 uri = parseuri(uri);
66 opts.host = uri.host;
67 opts.secure = uri.protocol == 'https' || uri.protocol == 'wss';
68 opts.port = uri.port;
69 if (uri.query) opts.query = uri.query;
a74c0f0c
D
70 }
71
6ab4b1ba
D
72 this.secure = null != opts.secure ? opts.secure :
73 (global.location && 'https:' == location.protocol);
74
75 if (opts.host) {
76 var pieces = opts.host.split(':');
77 opts.hostname = pieces.shift();
78 if (pieces.length) opts.port = pieces.pop();
a74c0f0c 79 }
6ab4b1ba
D
80
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 ?
85 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;
0de9e7ec 92 this.jsonp = false !== opts.jsonp;
6ab4b1ba 93 this.forceBase64 = !!opts.forceBase64;
0de9e7ec 94 this.enablesXDR = !!opts.enablesXDR;
6ab4b1ba
D
95 this.timestampParam = opts.timestampParam || 't';
96 this.timestampRequests = opts.timestampRequests;
97 this.transports = opts.transports || ['polling', 'websocket'];
98 this.readyState = '';
99 this.writeBuffer = [];
100 this.callbackBuffer = [];
101 this.policyPort = opts.policyPort || 843;
102 this.rememberUpgrade = opts.rememberUpgrade || false;
103 this.open();
104 this.binaryType = null;
105 this.onlyBinaryUpgrades = opts.onlyBinaryUpgrades;
106}
107
108Socket.priorWebsocketSuccess = false;
109
110/**
111 * Mix in `Emitter`.
112 */
113
114Emitter(Socket.prototype);
d99e7823
D
115
116/**
6ab4b1ba 117 * Protocol version.
d99e7823 118 *
6ab4b1ba
D
119 * @api public
120 */
121
122Socket.protocol = parser.protocol; // this is an int
123
124/**
125 * Expose deps for legacy compatibility
126 * and standalone browser access.
127 */
128
129Socket.Socket = Socket;
130Socket.Transport = _dereq_('./transport');
131Socket.transports = _dereq_('./transports');
132Socket.parser = _dereq_('engine.io-parser');
133
134/**
135 * Creates transport of the given type.
136 *
137 * @param {String} transport name
138 * @return {Transport}
a74c0f0c 139 * @api private
d99e7823
D
140 */
141
6ab4b1ba
D
142Socket.prototype.createTransport = function (name) {
143 debug('creating transport "%s"', name);
144 var query = clone(this.query);
145
146 // append engine.io protocol identifier
147 query.EIO = parser.protocol;
148
149 // transport name
150 query.transport = name;
151
152 // session id if we already have one
153 if (this.id) query.sid = this.id;
d99e7823 154
6ab4b1ba
D
155 var transport = new transports[name]({
156 agent: this.agent,
157 hostname: this.hostname,
158 port: this.port,
159 secure: this.secure,
160 path: this.path,
161 query: query,
162 forceJSONP: this.forceJSONP,
0de9e7ec 163 jsonp: this.jsonp,
6ab4b1ba 164 forceBase64: this.forceBase64,
0de9e7ec 165 enablesXDR: this.enablesXDR,
6ab4b1ba
D
166 timestampRequests: this.timestampRequests,
167 timestampParam: this.timestampParam,
168 policyPort: this.policyPort,
169 socket: this
170 });
d99e7823 171
6ab4b1ba
D
172 return transport;
173};
d99e7823 174
6ab4b1ba
D
175function clone (obj) {
176 var o = {};
177 for (var i in obj) {
178 if (obj.hasOwnProperty(i)) {
179 o[i] = obj[i];
a74c0f0c
D
180 }
181 }
6ab4b1ba
D
182 return o;
183}
d99e7823
D
184
185/**
6ab4b1ba 186 * Initializes transport to use and starts probe.
a74c0f0c 187 *
a74c0f0c 188 * @api private
d99e7823 189 */
6ab4b1ba
D
190Socket.prototype.open = function () {
191 var transport;
192 if (this.rememberUpgrade && Socket.priorWebsocketSuccess && this.transports.indexOf('websocket') != -1) {
193 transport = 'websocket';
0de9e7ec
JA
194 } else if (0 == this.transports.length) {
195 // Emit error on next tick so it can be listened to
196 var self = this;
197 setTimeout(function() {
198 self.emit('error', 'No transports available');
199 }, 0);
200 return;
6ab4b1ba
D
201 } else {
202 transport = this.transports[0];
203 }
204 this.readyState = 'opening';
0de9e7ec
JA
205
206 // Retry with the next transport if the transport is disabled (jsonp: false)
207 var transport;
208 try {
209 transport = this.createTransport(transport);
210 } catch (e) {
211 this.transports.shift();
212 this.open();
213 return;
214 }
215
6ab4b1ba
D
216 transport.open();
217 this.setTransport(transport);
a74c0f0c 218};
d99e7823
D
219
220/**
6ab4b1ba 221 * Sets the current transport. Disables the existing one (if any).
d99e7823 222 *
d99e7823
D
223 * @api private
224 */
225
6ab4b1ba
D
226Socket.prototype.setTransport = function(transport){
227 debug('setting transport %s', transport.name);
228 var self = this;
229
230 if (this.transport) {
231 debug('clearing existing transport %s', this.transport.name);
232 this.transport.removeAllListeners();
a74c0f0c 233 }
6ab4b1ba
D
234
235 // set up transport
236 this.transport = transport;
237
238 // set up transport listeners
239 transport
240 .on('drain', function(){
241 self.onDrain();
242 })
243 .on('packet', function(packet){
244 self.onPacket(packet);
245 })
246 .on('error', function(e){
247 self.onError(e);
248 })
249 .on('close', function(){
250 self.onClose('transport close');
251 });
a74c0f0c 252};
d99e7823
D
253
254/**
6ab4b1ba 255 * Probes a transport.
d99e7823 256 *
6ab4b1ba 257 * @param {String} transport name
a74c0f0c 258 * @api private
d99e7823
D
259 */
260
6ab4b1ba
D
261Socket.prototype.probe = function (name) {
262 debug('probing transport "%s"', name);
263 var transport = this.createTransport(name, { probe: 1 })
264 , failed = false
265 , self = this;
d99e7823 266
6ab4b1ba 267 Socket.priorWebsocketSuccess = false;
d99e7823 268
6ab4b1ba
D
269 function onTransportOpen(){
270 if (self.onlyBinaryUpgrades) {
271 var upgradeLosesBinary = !this.supportsBinary && self.transport.supportsBinary;
272 failed = failed || upgradeLosesBinary;
a74c0f0c 273 }
6ab4b1ba
D
274 if (failed) return;
275
276 debug('probe transport "%s" opened', name);
277 transport.send([{ type: 'ping', data: 'probe' }]);
278 transport.once('packet', function (msg) {
279 if (failed) return;
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;
285
286 debug('pausing current transport "%s"', self.transport.name);
287 self.transport.pause(function () {
288 if (failed) return;
289 if ('closed' == self.readyState || 'closing' == self.readyState) {
290 return;
291 }
292 debug('changing transport and sending upgrade packet');
293
294 cleanup();
295
296 self.setTransport(transport);
297 transport.send([{ type: 'upgrade' }]);
298 self.emit('upgrade', transport);
299 transport = null;
300 self.upgrading = false;
301 self.flush();
302 });
303 } else {
304 debug('probe transport "%s" failed', name);
305 var err = new Error('probe error');
306 err.transport = transport.name;
307 self.emit('upgradeError', err);
308 }
309 });
310 }
311
312 function freezeTransport() {
313 if (failed) return;
314
315 // Any callback called by transport should be ignored since now
316 failed = true;
317
318 cleanup();
319
320 transport.close();
321 transport = null;
d99e7823
D
322 }
323
6ab4b1ba
D
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;
328
329 freezeTransport();
330
331 debug('probe transport "%s" failed because of error: %s', name, err);
a74c0f0c 332
6ab4b1ba 333 self.emit('upgradeError', error);
d99e7823
D
334 }
335
6ab4b1ba
D
336 function onTransportClose(){
337 onerror("transport closed");
338 }
d99e7823 339
6ab4b1ba
D
340 //When the socket is closed while we're probing
341 function onclose(){
342 onerror("socket closed");
343 }
d99e7823 344
6ab4b1ba
D
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);
349 freezeTransport();
350 }
351 }
d99e7823 352
6ab4b1ba
D
353 //Remove all listeners on the transport and on self
354 function cleanup(){
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);
360 }
d99e7823 361
6ab4b1ba
D
362 transport.once('open', onTransportOpen);
363 transport.once('error', onerror);
364 transport.once('close', onTransportClose);
a74c0f0c 365
6ab4b1ba
D
366 this.once('close', onclose);
367 this.once('upgrading', onupgrade);
d99e7823 368
6ab4b1ba 369 transport.open();
d99e7823 370
6ab4b1ba 371};
d99e7823
D
372
373/**
6ab4b1ba 374 * Called when connection is deemed open.
a74c0f0c
D
375 *
376 * @api public
f8e5fb60
JA
377 */
378
6ab4b1ba
D
379Socket.prototype.onOpen = function () {
380 debug('socket open');
381 this.readyState = 'open';
382 Socket.priorWebsocketSuccess = 'websocket' == this.transport.name;
383 this.emit('open');
384 this.flush();
385
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]);
392 }
393 }
a74c0f0c 394};
f8e5fb60
JA
395
396/**
6ab4b1ba 397 * Handles a packet.
d99e7823 398 *
d99e7823
D
399 * @api private
400 */
401
6ab4b1ba
D
402Socket.prototype.onPacket = function (packet) {
403 if ('opening' == this.readyState || 'open' == this.readyState) {
404 debug('socket receive: type "%s", data "%s"', packet.type, packet.data);
d99e7823 405
6ab4b1ba 406 this.emit('packet', packet);
d99e7823 407
6ab4b1ba
D
408 // Socket is live - any packet counts
409 this.emit('heartbeat');
d99e7823 410
6ab4b1ba
D
411 switch (packet.type) {
412 case 'open':
413 this.onHandshake(parsejson(packet.data));
414 break;
d99e7823 415
6ab4b1ba
D
416 case 'pong':
417 this.setPing();
418 break;
d99e7823 419
6ab4b1ba
D
420 case 'error':
421 var err = new Error('server error');
422 err.code = packet.data;
423 this.emit('error', err);
424 break;
d99e7823 425
6ab4b1ba
D
426 case 'message':
427 this.emit('data', packet.data);
428 this.emit('message', packet.data);
429 break;
430 }
431 } else {
432 debug('packet received with socket readyState "%s"', this.readyState);
433 }
d99e7823
D
434};
435
436/**
6ab4b1ba 437 * Called upon handshake completion.
d99e7823 438 *
6ab4b1ba
D
439 * @param {Object} handshake obj
440 * @api private
d99e7823
D
441 */
442
6ab4b1ba
D
443Socket.prototype.onHandshake = function (data) {
444 this.emit('handshake', data);
445 this.id = data.sid;
446 this.transport.query.sid = data.sid;
447 this.upgrades = this.filterUpgrades(data.upgrades);
448 this.pingInterval = data.pingInterval;
449 this.pingTimeout = data.pingTimeout;
450 this.onOpen();
451 // In case open handler closes socket
452 if ('closed' == this.readyState) return;
453 this.setPing();
d99e7823 454
6ab4b1ba
D
455 // Prolong liveness of socket on heartbeat
456 this.removeListener('heartbeat', this.onHeartbeat);
457 this.on('heartbeat', this.onHeartbeat);
a74c0f0c 458};
d99e7823 459
a74c0f0c 460/**
6ab4b1ba 461 * Resets ping timeout.
a74c0f0c 462 *
6ab4b1ba 463 * @api private
a74c0f0c 464 */
d99e7823 465
6ab4b1ba
D
466Socket.prototype.onHeartbeat = function (timeout) {
467 clearTimeout(this.pingTimeoutTimer);
468 var self = this;
469 self.pingTimeoutTimer = setTimeout(function () {
470 if ('closed' == self.readyState) return;
471 self.onClose('ping timeout');
472 }, timeout || (self.pingInterval + self.pingTimeout));
a74c0f0c 473};
d99e7823 474
a74c0f0c 475/**
6ab4b1ba
D
476 * Pings server every `this.pingInterval` and expects response
477 * within `this.pingTimeout` or closes connection.
a74c0f0c 478 *
6ab4b1ba 479 * @api private
a74c0f0c 480 */
f8e5fb60 481
6ab4b1ba
D
482Socket.prototype.setPing = function () {
483 var self = this;
484 clearTimeout(self.pingIntervalTimer);
485 self.pingIntervalTimer = setTimeout(function () {
486 debug('writing ping packet - expecting pong within %sms', self.pingTimeout);
487 self.ping();
488 self.onHeartbeat(self.pingTimeout);
489 }, self.pingInterval);
d99e7823
D
490};
491
492/**
6ab4b1ba
D
493* Sends a ping packet.
494*
495* @api public
496*/
497
498Socket.prototype.ping = function () {
499 this.sendPacket('ping');
500};
501
502/**
503 * Called on `drain` event
d99e7823 504 *
6ab4b1ba 505 * @api private
d99e7823
D
506 */
507
6ab4b1ba
D
508Socket.prototype.onDrain = function() {
509 for (var i = 0; i < this.prevBufferLen; i++) {
510 if (this.callbackBuffer[i]) {
511 this.callbackBuffer[i]();
512 }
513 }
d99e7823 514
6ab4b1ba
D
515 this.writeBuffer.splice(0, this.prevBufferLen);
516 this.callbackBuffer.splice(0, this.prevBufferLen);
a74c0f0c 517
6ab4b1ba
D
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;
a74c0f0c 522
6ab4b1ba
D
523 if (this.writeBuffer.length == 0) {
524 this.emit('drain');
525 } else {
526 this.flush();
d99e7823 527 }
d99e7823 528};
d99e7823 529
a74c0f0c 530/**
6ab4b1ba
D
531 * Flush write buffers.
532 *
533 * @api private
a74c0f0c 534 */
d99e7823 535
6ab4b1ba
D
536Socket.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;
544 this.emit('flush');
545 }
a74c0f0c 546};
d99e7823 547
a74c0f0c 548/**
6ab4b1ba
D
549 * Sends a message.
550 *
551 * @param {String} message.
552 * @param {Function} callback function.
553 * @return {Socket} for chaining.
554 * @api public
a74c0f0c 555 */
d99e7823 556
6ab4b1ba
D
557Socket.prototype.write =
558Socket.prototype.send = function (msg, fn) {
559 this.sendPacket('message', msg, fn);
560 return this;
561};
d99e7823
D
562
563/**
6ab4b1ba 564 * Sends a packet.
f8e5fb60 565 *
6ab4b1ba
D
566 * @param {String} packet type.
567 * @param {String} data.
568 * @param {Function} callback function.
f8e5fb60 569 * @api private
d99e7823
D
570 */
571
6ab4b1ba
D
572Socket.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);
577 this.flush();
f8e5fb60 578};
d99e7823
D
579
580/**
6ab4b1ba 581 * Closes the connection.
d99e7823 582 *
f8e5fb60 583 * @api private
d99e7823
D
584 */
585
6ab4b1ba
D
586Socket.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();
a74c0f0c
D
591 }
592
6ab4b1ba 593 return this;
f8e5fb60 594};
d99e7823
D
595
596/**
6ab4b1ba 597 * Called upon transport error
a74c0f0c 598 *
f8e5fb60 599 * @api private
d99e7823
D
600 */
601
6ab4b1ba
D
602Socket.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);
f8e5fb60 607};
d99e7823 608
6ab4b1ba
D
609/**
610 * Called upon transport close.
a74c0f0c 611 *
6ab4b1ba 612 * @api private
a74c0f0c
D
613 */
614
6ab4b1ba
D
615Socket.prototype.onClose = function (reason, desc) {
616 if ('opening' == this.readyState || 'open' == this.readyState) {
617 debug('socket close with reason: "%s"', reason);
618 var self = this;
a74c0f0c 619
6ab4b1ba
D
620 // clear timers
621 clearTimeout(this.pingIntervalTimer);
622 clearTimeout(this.pingTimeoutTimer);
a74c0f0c 623
6ab4b1ba
D
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;
630 }, 0);
a74c0f0c 631
6ab4b1ba
D
632 // stop event from firing again for transport
633 this.transport.removeAllListeners('close');
a74c0f0c 634
6ab4b1ba
D
635 // ensure transport won't stay open
636 this.transport.close();
a74c0f0c 637
6ab4b1ba
D
638 // ignore further transport communication
639 this.transport.removeAllListeners();
a74c0f0c 640
6ab4b1ba
D
641 // set ready state
642 this.readyState = 'closed';
a74c0f0c 643
6ab4b1ba
D
644 // clear session id
645 this.id = null;
a74c0f0c 646
6ab4b1ba
D
647 // emit close event
648 this.emit('close', reason, desc);
a74c0f0c 649 }
f8e5fb60 650};
d99e7823
D
651
652/**
6ab4b1ba 653 * Filters upgrades, returning only those matching client transports.
d99e7823 654 *
6ab4b1ba 655 * @param {Array} server upgrades
d99e7823 656 * @api private
6ab4b1ba 657 *
d99e7823
D
658 */
659
6ab4b1ba
D
660Socket.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]);
f8e5fb60 664 }
6ab4b1ba 665 return filteredUpgrades;
a74c0f0c 666};
d99e7823 667
6ab4b1ba 668}).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
e65c2242 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_,module,exports){
6ab4b1ba
D
670/**
671 * Module dependencies.
672 */
d99e7823 673
6ab4b1ba 674var parser = _dereq_('engine.io-parser');
e65c2242 675var Emitter = _dereq_('component-emitter');
d99e7823 676
a74c0f0c 677/**
6ab4b1ba 678 * Module exports.
a74c0f0c
D
679 */
680
6ab4b1ba 681module.exports = Transport;
d99e7823 682
f8e5fb60 683/**
6ab4b1ba 684 * Transport abstract constructor.
f8e5fb60 685 *
6ab4b1ba
D
686 * @param {Object} options.
687 * @api private
f8e5fb60 688 */
d99e7823 689
6ab4b1ba
D
690function 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;
0de9e7ec 701 this.enablesXDR = opts.enablesXDR;
6ab4b1ba 702}
a74c0f0c 703
6ab4b1ba
D
704/**
705 * Mix in `Emitter`.
706 */
a74c0f0c 707
6ab4b1ba 708Emitter(Transport.prototype);
d99e7823 709
f8e5fb60 710/**
6ab4b1ba
D
711 * A counter used to prevent collisions in the timestamps used
712 * for cache busting.
a74c0f0c
D
713 */
714
6ab4b1ba 715Transport.timestamps = 0;
a74c0f0c
D
716
717/**
6ab4b1ba 718 * Emits an error.
f8e5fb60 719 *
6ab4b1ba
D
720 * @param {String} str
721 * @return {Transport} for chaining
f8e5fb60
JA
722 * @api public
723 */
724
6ab4b1ba
D
725Transport.prototype.onError = function (msg, desc) {
726 var err = new Error(msg);
727 err.type = 'TransportError';
728 err.description = desc;
729 this.emit('error', err);
730 return this;
f8e5fb60 731};
d99e7823
D
732
733/**
6ab4b1ba 734 * Opens the transport.
d99e7823 735 *
a74c0f0c 736 * @api public
d99e7823
D
737 */
738
6ab4b1ba
D
739Transport.prototype.open = function () {
740 if ('closed' == this.readyState || '' == this.readyState) {
741 this.readyState = 'opening';
742 this.doOpen();
743 }
744
745 return this;
d99e7823
D
746};
747
748/**
6ab4b1ba 749 * Closes the transport.
d99e7823
D
750 *
751 * @api private
752 */
753
6ab4b1ba
D
754Transport.prototype.close = function () {
755 if ('opening' == this.readyState || 'open' == this.readyState) {
756 this.doClose();
757 this.onClose();
758 }
d99e7823 759
6ab4b1ba 760 return this;
f8e5fb60 761};
d99e7823 762
f8e5fb60 763/**
6ab4b1ba 764 * Sends multiple packets.
f8e5fb60 765 *
6ab4b1ba
D
766 * @param {Array} packets
767 * @api private
f8e5fb60
JA
768 */
769
6ab4b1ba
D
770Transport.prototype.send = function(packets){
771 if ('open' == this.readyState) {
772 this.write(packets);
773 } else {
774 throw new Error('Transport not open');
a74c0f0c 775 }
d99e7823
D
776};
777
778/**
6ab4b1ba
D
779 * Called upon open
780 *
781 * @api private
d99e7823
D
782 */
783
6ab4b1ba
D
784Transport.prototype.onOpen = function () {
785 this.readyState = 'open';
786 this.writable = true;
787 this.emit('open');
788};
f8e5fb60
JA
789
790/**
6ab4b1ba 791 * Called with data.
f8e5fb60 792 *
6ab4b1ba
D
793 * @param {String} data
794 * @api private
f8e5fb60 795 */
d99e7823 796
e65c2242 797Transport.prototype.onData = function(data){
0de9e7ec
JA
798 var packet = parser.decodePacket(data, this.socket.binaryType);
799 this.onPacket(packet);
6ab4b1ba
D
800};
801
f8e5fb60 802/**
6ab4b1ba 803 * Called with a decoded packet.
f8e5fb60 804 */
d99e7823 805
6ab4b1ba
D
806Transport.prototype.onPacket = function (packet) {
807 this.emit('packet', packet);
808};
d99e7823 809
f8e5fb60 810/**
6ab4b1ba
D
811 * Called upon close.
812 *
813 * @api private
f8e5fb60 814 */
d99e7823 815
6ab4b1ba
D
816Transport.prototype.onClose = function () {
817 this.readyState = 'closed';
818 this.emit('close');
819};
d99e7823 820
e65c2242 821},{"component-emitter":12,"engine.io-parser":15}],5:[function(_dereq_,module,exports){
6ab4b1ba 822(function (global){
f8e5fb60 823/**
6ab4b1ba 824 * Module dependencies
f8e5fb60 825 */
d99e7823 826
6ab4b1ba
D
827var XMLHttpRequest = _dereq_('xmlhttprequest');
828var XHR = _dereq_('./polling-xhr');
829var JSONP = _dereq_('./polling-jsonp');
830var websocket = _dereq_('./websocket');
d99e7823 831
f8e5fb60 832/**
6ab4b1ba 833 * Export transports.
f8e5fb60
JA
834 */
835
6ab4b1ba
D
836exports.polling = polling;
837exports.websocket = websocket;
d99e7823
D
838
839/**
6ab4b1ba
D
840 * Polling transport polymorphic constructor.
841 * Decides on xhr vs jsonp based on feature detection.
d99e7823 842 *
6ab4b1ba 843 * @api private
d99e7823
D
844 */
845
6ab4b1ba
D
846function polling(opts){
847 var xhr;
848 var xd = false;
0de9e7ec
JA
849 var xs = false;
850 var jsonp = false !== opts.jsonp;
a74c0f0c 851
6ab4b1ba
D
852 if (global.location) {
853 var isSSL = 'https:' == location.protocol;
854 var port = location.port;
a74c0f0c 855
6ab4b1ba
D
856 // some user agents have empty `location.port`
857 if (!port) {
858 port = isSSL ? 443 : 80;
859 }
a74c0f0c 860
6ab4b1ba 861 xd = opts.hostname != location.hostname || port != opts.port;
0de9e7ec 862 xs = opts.secure != isSSL;
a74c0f0c
D
863 }
864
6ab4b1ba 865 opts.xdomain = xd;
0de9e7ec 866 opts.xscheme = xs;
6ab4b1ba 867 xhr = new XMLHttpRequest(opts);
a74c0f0c 868
6ab4b1ba
D
869 if ('open' in xhr && !opts.forceJSONP) {
870 return new XHR(opts);
871 } else {
0de9e7ec 872 if (!jsonp) throw new Error('JSONP disabled');
6ab4b1ba 873 return new JSONP(opts);
a74c0f0c 874 }
6ab4b1ba 875}
a74c0f0c 876
6ab4b1ba
D
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_,module,exports){
879(function (global){
a74c0f0c 880
6ab4b1ba
D
881/**
882 * Module requirements.
883 */
884
885var Polling = _dereq_('./polling');
e65c2242 886var inherit = _dereq_('component-inherit');
d99e7823 887
f8e5fb60 888/**
6ab4b1ba 889 * Module exports.
a74c0f0c
D
890 */
891
6ab4b1ba 892module.exports = JSONPPolling;
a74c0f0c
D
893
894/**
6ab4b1ba 895 * Cached regular expressions.
f8e5fb60
JA
896 */
897
6ab4b1ba
D
898var rNewline = /\n/g;
899var rEscapedNewline = /\\n/g;
900
901/**
902 * Global JSONP callbacks.
903 */
904
905var callbacks;
d99e7823
D
906
907/**
6ab4b1ba 908 * Callbacks count.
d99e7823
D
909 */
910
6ab4b1ba 911var index = 0;
d99e7823 912
a74c0f0c 913/**
6ab4b1ba 914 * Noop.
a74c0f0c
D
915 */
916
6ab4b1ba 917function empty () { }
d99e7823 918
f8e5fb60 919/**
6ab4b1ba 920 * JSONP Polling constructor.
f8e5fb60 921 *
6ab4b1ba
D
922 * @param {Object} opts.
923 * @api public
f8e5fb60 924 */
d99e7823 925
6ab4b1ba
D
926function JSONPPolling (opts) {
927 Polling.call(this, opts);
a74c0f0c 928
6ab4b1ba 929 this.query = this.query || {};
a74c0f0c 930
6ab4b1ba
D
931 // define global callbacks array if not present
932 // we do this here (lazily) to avoid unneeded global pollution
933 if (!callbacks) {
934 // we need to consider multiple engines in the same page
935 if (!global.___eio) global.___eio = [];
936 callbacks = global.___eio;
937 }
a74c0f0c 938
6ab4b1ba
D
939 // callback identifier
940 this.index = callbacks.length;
a74c0f0c 941
6ab4b1ba
D
942 // add callback to jsonp global
943 var self = this;
944 callbacks.push(function (msg) {
945 self.onData(msg);
a74c0f0c
D
946 });
947
6ab4b1ba
D
948 // append to query string
949 this.query.j = this.index;
d99e7823 950
6ab4b1ba
D
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;
955 });
a74c0f0c 956 }
a74c0f0c
D
957}
958
d99e7823 959/**
6ab4b1ba
D
960 * Inherits from Polling.
961 */
962
963inherit(JSONPPolling, Polling);
964
965/*
966 * JSONP only supports binary as base64 encoded strings
967 */
968
969JSONPPolling.prototype.supportsBinary = false;
970
971/**
972 * Closes the socket.
d99e7823 973 *
d99e7823
D
974 * @api private
975 */
976
6ab4b1ba
D
977JSONPPolling.prototype.doClose = function () {
978 if (this.script) {
979 this.script.parentNode.removeChild(this.script);
980 this.script = null;
981 }
982
983 if (this.form) {
984 this.form.parentNode.removeChild(this.form);
985 this.form = null;
986 }
987
988 Polling.prototype.doClose.call(this);
d99e7823
D
989};
990
991/**
6ab4b1ba 992 * Starts a poll cycle.
d99e7823
D
993 *
994 * @api private
995 */
996
6ab4b1ba 997JSONPPolling.prototype.doPoll = function () {
a74c0f0c 998 var self = this;
6ab4b1ba 999 var script = document.createElement('script');
d99e7823 1000
6ab4b1ba
D
1001 if (this.script) {
1002 this.script.parentNode.removeChild(this.script);
1003 this.script = null;
a74c0f0c 1004 }
f8e5fb60 1005
6ab4b1ba
D
1006 script.async = true;
1007 script.src = this.uri();
1008 script.onerror = function(e){
1009 self.onError('jsonp poll error',e);
1010 };
a74c0f0c 1011
6ab4b1ba
D
1012 var insertAt = document.getElementsByTagName('script')[0];
1013 insertAt.parentNode.insertBefore(script, insertAt);
1014 this.script = script;
1015
1016 var isUAgecko = 'undefined' != typeof navigator && /gecko/i.test(navigator.userAgent);
e65c2242 1017
6ab4b1ba
D
1018 if (isUAgecko) {
1019 setTimeout(function () {
1020 var iframe = document.createElement('iframe');
1021 document.body.appendChild(iframe);
1022 document.body.removeChild(iframe);
1023 }, 100);
1024 }
f8e5fb60
JA
1025};
1026
1027/**
6ab4b1ba 1028 * Writes with a hidden iframe.
d99e7823 1029 *
6ab4b1ba
D
1030 * @param {String} data to send
1031 * @param {Function} called upon flush.
d99e7823
D
1032 * @api private
1033 */
1034
6ab4b1ba
D
1035JSONPPolling.prototype.doWrite = function (data, fn) {
1036 var self = this;
f8e5fb60 1037
6ab4b1ba
D
1038 if (!this.form) {
1039 var form = document.createElement('form');
1040 var area = document.createElement('textarea');
1041 var id = this.iframeId = 'eio_iframe_' + this.index;
1042 var iframe;
d99e7823 1043
6ab4b1ba
D
1044 form.className = 'socketio';
1045 form.style.position = 'absolute';
1046 form.style.top = '-1000px';
1047 form.style.left = '-1000px';
1048 form.target = id;
1049 form.method = 'POST';
1050 form.setAttribute('accept-charset', 'utf-8');
1051 area.name = 'd';
1052 form.appendChild(area);
1053 document.body.appendChild(form);
d99e7823 1054
6ab4b1ba
D
1055 this.form = form;
1056 this.area = area;
a74c0f0c 1057 }
f8e5fb60 1058
6ab4b1ba 1059 this.form.action = this.uri();
f8e5fb60 1060
6ab4b1ba
D
1061 function complete () {
1062 initIframe();
1063 fn();
a74c0f0c 1064 }
d99e7823 1065
6ab4b1ba
D
1066 function initIframe () {
1067 if (self.iframe) {
1068 try {
1069 self.form.removeChild(self.iframe);
1070 } catch (e) {
1071 self.onError('jsonp polling iframe removal error', e);
1072 }
a74c0f0c 1073 }
a74c0f0c 1074
6ab4b1ba
D
1075 try {
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);
1079 } catch (e) {
1080 iframe = document.createElement('iframe');
1081 iframe.name = self.iframeId;
1082 iframe.src = 'javascript:0';
1083 }
d99e7823 1084
6ab4b1ba 1085 iframe.id = self.iframeId;
d99e7823 1086
6ab4b1ba
D
1087 self.form.appendChild(iframe);
1088 self.iframe = iframe;
a74c0f0c 1089 }
d99e7823 1090
6ab4b1ba 1091 initIframe();
f8e5fb60 1092
6ab4b1ba
D
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');
f8e5fb60 1097
6ab4b1ba
D
1098 try {
1099 this.form.submit();
1100 } catch(e) {}
d99e7823 1101
6ab4b1ba
D
1102 if (this.iframe.attachEvent) {
1103 this.iframe.onreadystatechange = function(){
1104 if (self.iframe.readyState == 'complete') {
1105 complete();
1106 }
1107 };
1108 } else {
1109 this.iframe.onload = complete;
a74c0f0c
D
1110 }
1111};
d99e7823 1112
6ab4b1ba 1113}).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
e65c2242 1114},{"./polling":8,"component-inherit":13}],7:[function(_dereq_,module,exports){
6ab4b1ba 1115(function (global){
d99e7823 1116/**
6ab4b1ba 1117 * Module requirements.
d99e7823
D
1118 */
1119
6ab4b1ba
D
1120var XMLHttpRequest = _dereq_('xmlhttprequest');
1121var Polling = _dereq_('./polling');
e65c2242
JA
1122var Emitter = _dereq_('component-emitter');
1123var inherit = _dereq_('component-inherit');
6ab4b1ba 1124var debug = _dereq_('debug')('engine.io-client:polling-xhr');
d99e7823
D
1125
1126/**
6ab4b1ba 1127 * Module exports.
a74c0f0c
D
1128 */
1129
6ab4b1ba
D
1130module.exports = XHR;
1131module.exports.Request = Request;
a74c0f0c
D
1132
1133/**
6ab4b1ba 1134 * Empty function
d99e7823
D
1135 */
1136
6ab4b1ba 1137function empty(){}
d99e7823
D
1138
1139/**
6ab4b1ba 1140 * XHR Polling constructor.
d99e7823 1141 *
6ab4b1ba
D
1142 * @param {Object} opts
1143 * @api public
d99e7823
D
1144 */
1145
6ab4b1ba
D
1146function XHR(opts){
1147 Polling.call(this, opts);
a74c0f0c 1148
6ab4b1ba
D
1149 if (global.location) {
1150 var isSSL = 'https:' == location.protocol;
1151 var port = location.port;
a74c0f0c 1152
6ab4b1ba
D
1153 // some user agents have empty `location.port`
1154 if (!port) {
1155 port = isSSL ? 443 : 80;
1156 }
a74c0f0c 1157
6ab4b1ba
D
1158 this.xd = opts.hostname != global.location.hostname ||
1159 port != opts.port;
0de9e7ec 1160 this.xs = opts.secure != isSSL;
a74c0f0c 1161 }
6ab4b1ba 1162}
a74c0f0c 1163
6ab4b1ba
D
1164/**
1165 * Inherits from Polling.
1166 */
1167
1168inherit(XHR, Polling);
d99e7823
D
1169
1170/**
6ab4b1ba 1171 * XHR supports binary
d99e7823
D
1172 */
1173
6ab4b1ba 1174XHR.prototype.supportsBinary = true;
d99e7823
D
1175
1176/**
6ab4b1ba 1177 * Creates a request.
a74c0f0c 1178 *
6ab4b1ba 1179 * @param {String} method
a74c0f0c 1180 * @api private
d99e7823
D
1181 */
1182
6ab4b1ba
D
1183XHR.prototype.request = function(opts){
1184 opts = opts || {};
1185 opts.uri = this.uri();
1186 opts.xd = this.xd;
0de9e7ec 1187 opts.xs = this.xs;
6ab4b1ba
D
1188 opts.agent = this.agent || false;
1189 opts.supportsBinary = this.supportsBinary;
0de9e7ec 1190 opts.enablesXDR = this.enablesXDR;
6ab4b1ba
D
1191 return new Request(opts);
1192};
d99e7823
D
1193
1194/**
6ab4b1ba 1195 * Sends data.
d99e7823 1196 *
6ab4b1ba
D
1197 * @param {String} data to send.
1198 * @param {Function} called upon flush.
d99e7823
D
1199 * @api private
1200 */
1201
6ab4b1ba
D
1202XHR.prototype.doWrite = function(data, fn){
1203 var isBinary = typeof data !== 'string' && data !== undefined;
1204 var req = this.request({ method: 'POST', data: data, isBinary: isBinary });
1205 var self = this;
1206 req.on('success', fn);
1207 req.on('error', function(err){
1208 self.onError('xhr post error', err);
1209 });
1210 this.sendXhr = req;
1211};
d99e7823 1212
a74c0f0c 1213/**
6ab4b1ba 1214 * Starts a poll cycle.
a74c0f0c
D
1215 *
1216 * @api private
1217 */
d99e7823 1218
6ab4b1ba
D
1219XHR.prototype.doPoll = function(){
1220 debug('xhr poll');
1221 var req = this.request();
1222 var self = this;
1223 req.on('data', function(data){
1224 self.onData(data);
1225 });
1226 req.on('error', function(err){
1227 self.onError('xhr poll error', err);
1228 });
1229 this.pollXhr = req;
1230};
d99e7823 1231
a74c0f0c 1232/**
6ab4b1ba
D
1233 * Request constructor
1234 *
1235 * @param {Object} options
1236 * @api public
a74c0f0c 1237 */
d99e7823 1238
6ab4b1ba
D
1239function Request(opts){
1240 this.method = opts.method || 'GET';
1241 this.uri = opts.uri;
1242 this.xd = !!opts.xd;
0de9e7ec 1243 this.xs = !!opts.xs;
6ab4b1ba
D
1244 this.async = false !== opts.async;
1245 this.data = undefined != opts.data ? opts.data : null;
1246 this.agent = opts.agent;
0de9e7ec
JA
1247 this.isBinary = opts.isBinary;
1248 this.supportsBinary = opts.supportsBinary;
1249 this.enablesXDR = opts.enablesXDR;
1250 this.create();
6ab4b1ba 1251}
d99e7823 1252
a74c0f0c 1253/**
6ab4b1ba 1254 * Mix in `Emitter`.
a74c0f0c 1255 */
d99e7823 1256
6ab4b1ba 1257Emitter(Request.prototype);
d99e7823 1258
a74c0f0c 1259/**
6ab4b1ba 1260 * Creates the XHR object and sends the request.
a74c0f0c 1261 *
a74c0f0c
D
1262 * @api private
1263 */
1264
0de9e7ec
JA
1265Request.prototype.create = function(){
1266 var xhr = this.xhr = new XMLHttpRequest({ agent: this.agent, xdomain: this.xd, xscheme: this.xs, enablesXDR: this.enablesXDR });
6ab4b1ba 1267 var self = this;
f8e5fb60 1268
a74c0f0c 1269 try {
6ab4b1ba
D
1270 debug('xhr open %s: %s', this.method, this.uri);
1271 xhr.open(this.method, this.uri, this.async);
0de9e7ec 1272 if (this.supportsBinary) {
6ab4b1ba
D
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';
a74c0f0c 1276 }
a74c0f0c 1277
6ab4b1ba
D
1278 if ('POST' == this.method) {
1279 try {
0de9e7ec 1280 if (this.isBinary) {
6ab4b1ba
D
1281 xhr.setRequestHeader('Content-type', 'application/octet-stream');
1282 } else {
1283 xhr.setRequestHeader('Content-type', 'text/plain;charset=UTF-8');
1284 }
1285 } catch (e) {}
1286 }
d99e7823 1287
6ab4b1ba
D
1288 // ie6 check
1289 if ('withCredentials' in xhr) {
1290 xhr.withCredentials = true;
1291 }
d99e7823 1292
0de9e7ec
JA
1293 if (this.hasXDR()) {
1294 xhr.onload = function(){
1295 self.onLoad();
1296 };
1297 xhr.onerror = function(){
1298 self.onError(xhr.responseText);
1299 };
1300 } else {
1301 xhr.onreadystatechange = function(){
6ab4b1ba
D
1302 if (4 != xhr.readyState) return;
1303 if (200 == xhr.status || 1223 == xhr.status) {
0de9e7ec 1304 self.onLoad();
6ab4b1ba
D
1305 } else {
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);
1310 }, 0);
1311 }
0de9e7ec
JA
1312 };
1313 }
a74c0f0c 1314
6ab4b1ba
D
1315 debug('xhr data %s', this.data);
1316 xhr.send(this.data);
1317 } catch (e) {
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() {
1322 self.onError(e);
1323 }, 0);
1324 return;
a74c0f0c
D
1325 }
1326
6ab4b1ba
D
1327 if (global.document) {
1328 this.index = Request.requestsCount++;
1329 Request.requests[this.index] = this;
1330 }
f8e5fb60 1331};
d99e7823
D
1332
1333/**
6ab4b1ba 1334 * Called upon successful response.
f8e5fb60
JA
1335 *
1336 * @api private
d99e7823
D
1337 */
1338
6ab4b1ba
D
1339Request.prototype.onSuccess = function(){
1340 this.emit('success');
1341 this.cleanup();
f8e5fb60 1342};
d99e7823
D
1343
1344/**
6ab4b1ba 1345 * Called if we have data.
f8e5fb60
JA
1346 *
1347 * @api private
d99e7823
D
1348 */
1349
6ab4b1ba
D
1350Request.prototype.onData = function(data){
1351 this.emit('data', data);
1352 this.onSuccess();
f8e5fb60 1353};
d99e7823
D
1354
1355/**
6ab4b1ba
D
1356 * Called upon error.
1357 *
1358 * @api private
d99e7823
D
1359 */
1360
6ab4b1ba
D
1361Request.prototype.onError = function(err){
1362 this.emit('error', err);
1363 this.cleanup();
1364};
d99e7823 1365
a74c0f0c 1366/**
6ab4b1ba
D
1367 * Cleans up house.
1368 *
1369 * @api private
a74c0f0c 1370 */
d99e7823 1371
6ab4b1ba
D
1372Request.prototype.cleanup = function(){
1373 if ('undefined' == typeof this.xhr || null === this.xhr) {
1374 return;
1375 }
1376 // xmlhttprequest
0de9e7ec
JA
1377 if (this.hasXDR()) {
1378 this.xhr.onload = this.xhr.onerror = empty;
1379 } else {
1380 this.xhr.onreadystatechange = empty;
1381 }
d99e7823 1382
6ab4b1ba
D
1383 try {
1384 this.xhr.abort();
1385 } catch(e) {}
1386
1387 if (global.document) {
1388 delete Request.requests[this.index];
1389 }
f8e5fb60 1390
6ab4b1ba
D
1391 this.xhr = null;
1392};
d99e7823 1393
0de9e7ec
JA
1394/**
1395 * Called upon load.
1396 *
1397 * @api private
1398 */
1399
1400Request.prototype.onLoad = function(){
1401 var data;
1402 try {
1403 var contentType;
1404 try {
1405 contentType = this.xhr.getResponseHeader('Content-Type');
1406 } catch (e) {}
1407 if (contentType === 'application/octet-stream') {
1408 data = this.xhr.response;
1409 } else {
1410 if (!this.supportsBinary) {
1411 data = this.xhr.responseText;
1412 } else {
1413 data = 'ok';
1414 }
1415 }
1416 } catch (e) {
1417 this.onError(e);
1418 }
1419 if (null != data) {
1420 this.onData(data);
1421 }
1422};
1423
1424/**
1425 * Check if it has XDomainRequest.
1426 *
1427 * @api private
1428 */
1429
1430Request.prototype.hasXDR = function(){
1431 return 'undefined' !== typeof global.XDomainRequest && !this.xs && this.enablesXDR;
1432};
1433
f8e5fb60 1434/**
6ab4b1ba 1435 * Aborts the request.
a74c0f0c 1436 *
6ab4b1ba 1437 * @api public
f8e5fb60
JA
1438 */
1439
6ab4b1ba
D
1440Request.prototype.abort = function(){
1441 this.cleanup();
1442};
a74c0f0c 1443
6ab4b1ba
D
1444/**
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
1447 * emitted.
1448 */
1449
1450if (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);
a74c0f0c 1457 }
6ab4b1ba 1458}
a74c0f0c 1459
6ab4b1ba
D
1460function unloadHandler() {
1461 for (var i in Request.requests) {
1462 if (Request.requests.hasOwnProperty(i)) {
1463 Request.requests[i].abort();
1464 }
a74c0f0c 1465 }
6ab4b1ba 1466}
a74c0f0c 1467
6ab4b1ba 1468}).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
e65c2242 1469},{"./polling":8,"component-emitter":12,"component-inherit":13,"debug":14,"xmlhttprequest":10}],8:[function(_dereq_,module,exports){
d99e7823
D
1470/**
1471 * Module dependencies.
1472 */
1473
6ab4b1ba
D
1474var Transport = _dereq_('../transport');
1475var parseqs = _dereq_('parseqs');
1476var parser = _dereq_('engine.io-parser');
e65c2242 1477var inherit = _dereq_('component-inherit');
6ab4b1ba 1478var debug = _dereq_('debug')('engine.io-client:polling');
d99e7823
D
1479
1480/**
1481 * Module exports.
1482 */
1483
1484module.exports = Polling;
1485
1486/**
6ab4b1ba 1487 * Is XHR2 supported?
d99e7823
D
1488 */
1489
6ab4b1ba
D
1490var hasXHR2 = (function() {
1491 var XMLHttpRequest = _dereq_('xmlhttprequest');
1492 var xhr = new XMLHttpRequest({ agent: this.agent, xdomain: false });
1493 return null != xhr.responseType;
1494})();
d99e7823
D
1495
1496/**
1497 * Polling interface.
1498 *
1499 * @param {Object} opts
1500 * @api private
1501 */
1502
1503function Polling(opts){
6ab4b1ba
D
1504 var forceBase64 = (opts && opts.forceBase64);
1505 if (!hasXHR2 || forceBase64) {
1506 this.supportsBinary = false;
1507 }
d99e7823
D
1508 Transport.call(this, opts);
1509}
1510
1511/**
1512 * Inherits from Transport.
1513 */
1514
6ab4b1ba 1515inherit(Polling, Transport);
d99e7823
D
1516
1517/**
1518 * Transport name.
1519 */
1520
1521Polling.prototype.name = 'polling';
1522
1523/**
1524 * Opens the socket (triggers polling). We write a PING message to determine
1525 * when the transport is open.
1526 *
1527 * @api private
1528 */
1529
1530Polling.prototype.doOpen = function(){
1531 this.poll();
1532};
1533
1534/**
1535 * Pauses polling.
1536 *
1537 * @param {Function} callback upon buffers are flushed and transport is paused
1538 * @api private
1539 */
1540
1541Polling.prototype.pause = function(onPause){
1542 var pending = 0;
1543 var self = this;
1544
1545 this.readyState = 'pausing';
1546
1547 function pause(){
1548 debug('paused');
1549 self.readyState = 'paused';
1550 onPause();
1551 }
1552
1553 if (this.polling || !this.writable) {
1554 var total = 0;
1555
1556 if (this.polling) {
1557 debug('we are currently polling - waiting to pause');
1558 total++;
1559 this.once('pollComplete', function(){
1560 debug('pre-pause polling complete');
1561 --total || pause();
1562 });
1563 }
1564
1565 if (!this.writable) {
1566 debug('we are currently writing - waiting to pause');
1567 total++;
1568 this.once('drain', function(){
1569 debug('pre-pause writing complete');
1570 --total || pause();
1571 });
1572 }
1573 } else {
1574 pause();
1575 }
1576};
1577
1578/**
1579 * Starts polling cycle.
1580 *
1581 * @api public
1582 */
1583
1584Polling.prototype.poll = function(){
1585 debug('polling');
1586 this.polling = true;
1587 this.doPoll();
1588 this.emit('poll');
1589};
1590
1591/**
1592 * Overloads onData to detect payloads.
1593 *
1594 * @api private
1595 */
1596
1597Polling.prototype.onData = function(data){
1598 var self = this;
1599 debug('polling got data %s', data);
6ab4b1ba 1600 var callback = function(packet, index, total) {
d99e7823
D
1601 // if its the first message we consider the transport open
1602 if ('opening' == self.readyState) {
1603 self.onOpen();
1604 }
1605
1606 // if its a close packet, we close the ongoing requests
1607 if ('close' == packet.type) {
1608 self.onClose();
1609 return false;
1610 }
1611
1612 // otherwise bypass onData and handle the message
1613 self.onPacket(packet);
6ab4b1ba
D
1614 };
1615
1616 // decode payload
1617 parser.decodePayload(data, this.socket.binaryType, callback);
d99e7823
D
1618
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');
1624
1625 if ('open' == this.readyState) {
1626 this.poll();
1627 } else {
1628 debug('ignoring poll - transport state "%s"', this.readyState);
1629 }
1630 }
1631};
1632
1633/**
1634 * For polling, send a close packet.
1635 *
1636 * @api private
1637 */
1638
1639Polling.prototype.doClose = function(){
1640 var self = this;
1641
1642 function close(){
1643 debug('writing close packet');
1644 self.write([{ type: 'close' }]);
1645 }
1646
6ab4b1ba 1647 if ('open' == this.readyState) {
d99e7823
D
1648 debug('transport open - closing');
1649 close();
1650 } else {
1651 // in case we're trying to close while
1652 // handshaking is in progress (GH-164)
6ab4b1ba 1653 debug('transport not open - deferring close');
d99e7823
D
1654 this.once('open', close);
1655 }
1656};
1657
1658/**
1659 * Writes a packets payload.
1660 *
1661 * @param {Array} data packets
1662 * @param {Function} drain callback
1663 * @api private
1664 */
1665
1666Polling.prototype.write = function(packets){
1667 var self = this;
1668 this.writable = false;
6ab4b1ba 1669 var callbackfn = function() {
d99e7823
D
1670 self.writable = true;
1671 self.emit('drain');
6ab4b1ba
D
1672 };
1673
1674 var self = this;
1675 parser.encodePayload(packets, this.supportsBinary, function(data) {
1676 self.doWrite(data, callbackfn);
d99e7823
D
1677 });
1678};
1679
1680/**
1681 * Generates uri for connection.
1682 *
1683 * @api private
1684 */
1685
1686Polling.prototype.uri = function(){
1687 var query = this.query || {};
1688 var schema = this.secure ? 'https' : 'http';
1689 var port = '';
1690
6ab4b1ba
D
1691 // cache busting is forced
1692 if (false !== this.timestampRequests) {
1693 query[this.timestampParam] = +new Date + '-' + Transport.timestamps++;
1694 }
1695
1696 if (!this.supportsBinary && !query.sid) {
1697 query.b64 = 1;
1698 }
1699
1700 query = parseqs.encode(query);
1701
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;
1706 }
1707
1708 // prepend ? to query
1709 if (query.length) {
1710 query = '?' + query;
1711 }
1712
1713 return schema + '://' + this.hostname + port + this.path + query;
1714};
1715
e65c2242 1716},{"../transport":4,"component-inherit":13,"debug":14,"engine.io-parser":15,"parseqs":25,"xmlhttprequest":10}],9:[function(_dereq_,module,exports){
6ab4b1ba
D
1717/**
1718 * Module dependencies.
1719 */
1720
1721var Transport = _dereq_('../transport');
1722var parser = _dereq_('engine.io-parser');
1723var parseqs = _dereq_('parseqs');
e65c2242 1724var inherit = _dereq_('component-inherit');
6ab4b1ba 1725var debug = _dereq_('debug')('engine.io-client:websocket');
6ab4b1ba
D
1726
1727/**
1728 * `ws` exposes a WebSocket-compatible interface in
1729 * Node, or the `WebSocket` or `MozWebSocket` globals
1730 * in the browser.
1731 */
1732
1733var WebSocket = _dereq_('ws');
1734
1735/**
1736 * Module exports.
1737 */
1738
1739module.exports = WS;
1740
1741/**
1742 * WebSocket transport constructor.
1743 *
1744 * @api {Object} connection options
1745 * @api public
1746 */
1747
1748function WS(opts){
1749 var forceBase64 = (opts && opts.forceBase64);
1750 if (forceBase64) {
1751 this.supportsBinary = false;
1752 }
1753 Transport.call(this, opts);
1754}
1755
1756/**
1757 * Inherits from Transport.
1758 */
1759
1760inherit(WS, Transport);
1761
1762/**
1763 * Transport name.
1764 *
1765 * @api public
1766 */
1767
1768WS.prototype.name = 'websocket';
1769
1770/*
1771 * WebSockets support binary
1772 */
1773
1774WS.prototype.supportsBinary = true;
1775
1776/**
1777 * Opens socket.
1778 *
1779 * @api private
1780 */
1781
1782WS.prototype.doOpen = function(){
1783 if (!this.check()) {
1784 // let probe timeout
1785 return;
1786 }
1787
1788 var self = this;
1789 var uri = this.uri();
1790 var protocols = void(0);
1791 var opts = { agent: this.agent };
1792
1793 this.ws = new WebSocket(uri, protocols, opts);
1794
1795 if (this.ws.binaryType === undefined) {
1796 this.supportsBinary = false;
1797 }
1798
1799 this.ws.binaryType = 'arraybuffer';
1800 this.addEventListeners();
1801};
1802
1803/**
1804 * Adds event listeners to the socket
1805 *
1806 * @api private
1807 */
1808
1809WS.prototype.addEventListeners = function(){
1810 var self = this;
1811
1812 this.ws.onopen = function(){
1813 self.onOpen();
1814 };
1815 this.ws.onclose = function(){
1816 self.onClose();
1817 };
1818 this.ws.onmessage = function(ev){
1819 self.onData(ev.data);
1820 };
1821 this.ws.onerror = function(e){
1822 self.onError('websocket error', e);
1823 };
1824};
1825
1826/**
1827 * Override `onData` to use a timer on iOS.
1828 * See: https://gist.github.com/mloughran/2052006
1829 *
1830 * @api private
1831 */
1832
1833if ('undefined' != typeof navigator
1834 && /iPad|iPhone|iPod/i.test(navigator.userAgent)) {
1835 WS.prototype.onData = function(data){
1836 var self = this;
1837 setTimeout(function(){
1838 Transport.prototype.onData.call(self, data);
1839 }, 0);
1840 };
1841}
1842
1843/**
1844 * Writes data to socket.
1845 *
1846 * @param {Array} array of packets.
1847 * @api private
1848 */
1849
1850WS.prototype.write = function(packets){
1851 var self = this;
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
1859 //throw an error
1860 try {
1861 self.ws.send(data);
1862 } catch (e){
1863 debug('websocket closed before onclose event');
1864 }
1865 });
1866 }
1867
1868 function ondrain() {
1869 self.writable = true;
1870 self.emit('drain');
1871 }
1872 // fake drain
1873 // defer to next tick to allow Socket to clear writeBuffer
1874 setTimeout(ondrain, 0);
1875};
1876
1877/**
1878 * Called upon close
1879 *
1880 * @api private
1881 */
1882
1883WS.prototype.onClose = function(){
1884 Transport.prototype.onClose.call(this);
1885};
1886
1887/**
1888 * Closes socket.
1889 *
1890 * @api private
1891 */
1892
1893WS.prototype.doClose = function(){
1894 if (typeof this.ws !== 'undefined') {
1895 this.ws.close();
1896 }
1897};
1898
1899/**
1900 * Generates uri for connection.
1901 *
1902 * @api private
1903 */
1904
1905WS.prototype.uri = function(){
1906 var query = this.query || {};
1907 var schema = this.secure ? 'wss' : 'ws';
1908 var port = '';
1909
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;
1914 }
1915
1916 // append timestamp to URI
1917 if (this.timestampRequests) {
a74c0f0c 1918 query[this.timestampParam] = +new Date;
d99e7823
D
1919 }
1920
6ab4b1ba
D
1921 // communicate binary support capabilities
1922 if (!this.supportsBinary) {
1923 query.b64 = 1;
1924 }
1925
1926 query = parseqs.encode(query);
1927
1928 // prepend ? to query
1929 if (query.length) {
1930 query = '?' + query;
1931 }
1932
1933 return schema + '://' + this.hostname + port + this.path + query;
1934};
1935
1936/**
1937 * Feature detection for WebSocket.
1938 *
1939 * @return {Boolean} whether this transport is available.
1940 * @api public
1941 */
1942
1943WS.prototype.check = function(){
1944 return !!WebSocket && !('__initialize' in WebSocket && this.name === WS.prototype.name);
1945};
1946
e65c2242 1947},{"../transport":4,"component-inherit":13,"debug":14,"engine.io-parser":15,"parseqs":25,"ws":27}],10:[function(_dereq_,module,exports){
6ab4b1ba
D
1948// browser shim for xmlhttprequest module
1949var hasCORS = _dereq_('has-cors');
1950
1951module.exports = function(opts) {
1952 var xdomain = opts.xdomain;
1953
0de9e7ec
JA
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;
1957
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;
1961
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
1965 try {
1966 if ('undefined' != typeof XDomainRequest && !xscheme && enablesXDR) {
1967 return new XDomainRequest();
1968 }
1969 } catch (e) { }
1970
6ab4b1ba
D
1971 // XMLHttpRequest can be disabled on IE
1972 try {
1973 if ('undefined' != typeof XMLHttpRequest && (!xdomain || hasCORS)) {
1974 return new XMLHttpRequest();
1975 }
1976 } catch (e) { }
1977
1978 if (!xdomain) {
1979 try {
1980 return new ActiveXObject('Microsoft.XMLHTTP');
1981 } catch(e) { }
1982 }
1983}
1984
1985},{"has-cors":21}],11:[function(_dereq_,module,exports){
1986(function (global){
1987/**
1988 * Create a blob builder even when vendor prefixes exist
1989 */
1990
1991var BlobBuilder = global.BlobBuilder
1992 || global.WebKitBlobBuilder
1993 || global.MSBlobBuilder
1994 || global.MozBlobBuilder;
1995
1996/**
1997 * Check if Blob constructor is supported
1998 */
1999
2000var blobSupported = (function() {
2001 try {
2002 var b = new Blob(['hi']);
2003 return b.size == 2;
2004 } catch(e) {
2005 return false;
2006 }
2007})();
2008
2009/**
2010 * Check if BlobBuilder is supported
2011 */
d99e7823 2012
6ab4b1ba
D
2013var blobBuilderSupported = BlobBuilder
2014 && BlobBuilder.prototype.append
2015 && BlobBuilder.prototype.getBlob;
d99e7823 2016
6ab4b1ba
D
2017function BlobBuilderConstructor(ary, options) {
2018 options = options || {};
d99e7823 2019
6ab4b1ba
D
2020 var bb = new BlobBuilder();
2021 for (var i = 0; i < ary.length; i++) {
2022 bb.append(ary[i]);
2023 }
2024 return (options.type) ? bb.getBlob(options.type) : bb.getBlob();
d99e7823
D
2025};
2026
6ab4b1ba
D
2027module.exports = (function() {
2028 if (blobSupported) {
2029 return global.Blob;
2030 } else if (blobBuilderSupported) {
2031 return BlobBuilderConstructor;
2032 } else {
2033 return undefined;
2034 }
2035})();
d99e7823 2036
6ab4b1ba
D
2037}).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
2038},{}],12:[function(_dereq_,module,exports){
d99e7823 2039
6ab4b1ba
D
2040/**
2041 * Expose `Emitter`.
2042 */
2043
2044module.exports = Emitter;
2045
2046/**
2047 * Initialize a new `Emitter`.
f8e5fb60 2048 *
6ab4b1ba 2049 * @api public
f8e5fb60
JA
2050 */
2051
6ab4b1ba
D
2052function Emitter(obj) {
2053 if (obj) return mixin(obj);
d99e7823
D
2054};
2055
2056/**
6ab4b1ba 2057 * Mixin the emitter properties.
d99e7823 2058 *
6ab4b1ba
D
2059 * @param {Object} obj
2060 * @return {Object}
2061 * @api private
d99e7823
D
2062 */
2063
6ab4b1ba
D
2064function mixin(obj) {
2065 for (var key in Emitter.prototype) {
2066 obj[key] = Emitter.prototype[key];
2067 }
2068 return obj;
a74c0f0c 2069}
d99e7823
D
2070
2071/**
6ab4b1ba
D
2072 * Listen on the given `event` with `fn`.
2073 *
2074 * @param {String} event
2075 * @param {Function} fn
2076 * @return {Emitter}
2077 * @api public
d99e7823
D
2078 */
2079
e65c2242
JA
2080Emitter.prototype.on =
2081Emitter.prototype.addEventListener = function(event, fn){
6ab4b1ba
D
2082 this._callbacks = this._callbacks || {};
2083 (this._callbacks[event] = this._callbacks[event] || [])
2084 .push(fn);
2085 return this;
2086};
d99e7823
D
2087
2088/**
6ab4b1ba
D
2089 * Adds an `event` listener that will be invoked a single
2090 * time then automatically removed.
d99e7823 2091 *
6ab4b1ba
D
2092 * @param {String} event
2093 * @param {Function} fn
2094 * @return {Emitter}
2095 * @api public
d99e7823
D
2096 */
2097
6ab4b1ba 2098Emitter.prototype.once = function(event, fn){
a74c0f0c 2099 var self = this;
6ab4b1ba 2100 this._callbacks = this._callbacks || {};
f8e5fb60 2101
6ab4b1ba
D
2102 function on() {
2103 self.off(event, on);
2104 fn.apply(this, arguments);
f8e5fb60 2105 }
d99e7823 2106
e65c2242 2107 on.fn = fn;
6ab4b1ba
D
2108 this.on(event, on);
2109 return this;
2110};
a74c0f0c 2111
6ab4b1ba
D
2112/**
2113 * Remove the given callback for `event` or all
2114 * registered callbacks.
2115 *
2116 * @param {String} event
2117 * @param {Function} fn
2118 * @return {Emitter}
2119 * @api public
2120 */
a74c0f0c 2121
6ab4b1ba
D
2122Emitter.prototype.off =
2123Emitter.prototype.removeListener =
e65c2242
JA
2124Emitter.prototype.removeAllListeners =
2125Emitter.prototype.removeEventListener = function(event, fn){
6ab4b1ba
D
2126 this._callbacks = this._callbacks || {};
2127
2128 // all
2129 if (0 == arguments.length) {
2130 this._callbacks = {};
2131 return this;
d99e7823
D
2132 }
2133
6ab4b1ba
D
2134 // specific event
2135 var callbacks = this._callbacks[event];
2136 if (!callbacks) return this;
a74c0f0c 2137
6ab4b1ba
D
2138 // remove all handlers
2139 if (1 == arguments.length) {
2140 delete this._callbacks[event];
2141 return this;
a74c0f0c 2142 }
6ab4b1ba
D
2143
2144 // remove specific handler
e65c2242
JA
2145 var cb;
2146 for (var i = 0; i < callbacks.length; i++) {
2147 cb = callbacks[i];
2148 if (cb === fn || cb.fn === fn) {
2149 callbacks.splice(i, 1);
2150 break;
2151 }
2152 }
6ab4b1ba 2153 return this;
d99e7823
D
2154};
2155
2156/**
6ab4b1ba 2157 * Emit `event` with the given args.
d99e7823 2158 *
6ab4b1ba
D
2159 * @param {String} event
2160 * @param {Mixed} ...
2161 * @return {Emitter}
d99e7823
D
2162 */
2163
6ab4b1ba
D
2164Emitter.prototype.emit = function(event){
2165 this._callbacks = this._callbacks || {};
2166 var args = [].slice.call(arguments, 1)
2167 , callbacks = this._callbacks[event];
2168
2169 if (callbacks) {
2170 callbacks = callbacks.slice(0);
2171 for (var i = 0, len = callbacks.length; i < len; ++i) {
2172 callbacks[i].apply(this, args);
2173 }
2174 }
2175
2176 return this;
d99e7823
D
2177};
2178
f8e5fb60 2179/**
6ab4b1ba 2180 * Return array of callbacks for `event`.
a74c0f0c 2181 *
6ab4b1ba
D
2182 * @param {String} event
2183 * @return {Array}
2184 * @api public
f8e5fb60
JA
2185 */
2186
6ab4b1ba
D
2187Emitter.prototype.listeners = function(event){
2188 this._callbacks = this._callbacks || {};
2189 return this._callbacks[event] || [];
a74c0f0c 2190};
d99e7823
D
2191
2192/**
6ab4b1ba 2193 * Check if this emitter has `event` handlers.
f8e5fb60 2194 *
6ab4b1ba
D
2195 * @param {String} event
2196 * @return {Boolean}
2197 * @api public
d99e7823
D
2198 */
2199
6ab4b1ba
D
2200Emitter.prototype.hasListeners = function(event){
2201 return !! this.listeners(event).length;
f8e5fb60 2202};
d99e7823 2203
e65c2242
JA
2204},{}],13:[function(_dereq_,module,exports){
2205
2206module.exports = function(a, b){
2207 var fn = function(){};
2208 fn.prototype = b.prototype;
2209 a.prototype = new fn;
2210 a.prototype.constructor = a;
2211};
2212},{}],14:[function(_dereq_,module,exports){
2213
2214/**
2215 * Expose `debug()` as the module.
2216 */
2217
2218module.exports = debug;
2219
2220/**
2221 * Create a debugger with the given `name`.
2222 *
2223 * @param {String} name
2224 * @return {Type}
2225 * @api public
2226 */
2227
2228function debug(name) {
2229 if (!debug.enabled(name)) return function(){};
2230
2231 return function(fmt){
2232 fmt = coerce(fmt);
2233
2234 var curr = new Date;
2235 var ms = curr - (debug[name] || curr);
2236 debug[name] = curr;
2237
2238 fmt = name
2239 + ' '
2240 + fmt
2241 + ' +' + debug.humanize(ms);
2242
2243 // This hackery is required for IE8
2244 // where `console.log` doesn't have 'apply'
2245 window.console
2246 && console.log
2247 && Function.prototype.apply.call(console.log, console, arguments);
2248 }
2249}
2250
2251/**
2252 * The currently active debug mode names.
2253 */
2254
2255debug.names = [];
2256debug.skips = [];
2257
2258/**
2259 * Enables a debug mode by name. This can include modes
2260 * separated by a colon and wildcards.
2261 *
2262 * @param {String} name
2263 * @api public
2264 */
2265
2266debug.enable = function(name) {
2267 try {
2268 localStorage.debug = name;
2269 } catch(e){}
2270
2271 var split = (name || '').split(/[\s,]+/)
2272 , len = split.length;
2273
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) + '$'));
2278 }
2279 else {
2280 debug.names.push(new RegExp('^' + name + '$'));
2281 }
2282 }
2283};
2284
2285/**
2286 * Disable debug output.
2287 *
2288 * @api public
2289 */
2290
2291debug.disable = function(){
2292 debug.enable('');
2293};
2294
2295/**
2296 * Humanize the given `ms`.
2297 *
2298 * @param {Number} m
2299 * @return {String}
2300 * @api private
2301 */
2302
2303debug.humanize = function(ms) {
2304 var sec = 1000
2305 , min = 60 * 1000
2306 , hour = 60 * min;
2307
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';
2311 return ms + 'ms';
2312};
2313
2314/**
2315 * Returns true if the given mode name is enabled, false otherwise.
2316 *
2317 * @param {String} name
2318 * @return {Boolean}
2319 * @api public
2320 */
2321
2322debug.enabled = function(name) {
2323 for (var i = 0, len = debug.skips.length; i < len; i++) {
2324 if (debug.skips[i].test(name)) {
2325 return false;
2326 }
2327 }
2328 for (var i = 0, len = debug.names.length; i < len; i++) {
2329 if (debug.names[i].test(name)) {
2330 return true;
2331 }
2332 }
2333 return false;
2334};
2335
2336/**
2337 * Coerce `val`.
2338 */
2339
2340function coerce(val) {
2341 if (val instanceof Error) return val.stack || val.message;
2342 return val;
2343}
2344
2345// persist
2346
2347try {
2348 if (window.localStorage) debug.enable(localStorage.debug);
2349} catch(e){}
2350
2351},{}],15:[function(_dereq_,module,exports){
6ab4b1ba 2352(function (global){
d99e7823 2353/**
6ab4b1ba 2354 * Module dependencies.
d99e7823
D
2355 */
2356
6ab4b1ba
D
2357var keys = _dereq_('./keys');
2358var sliceBuffer = _dereq_('arraybuffer.slice');
2359var base64encoder = _dereq_('base64-arraybuffer');
2360var after = _dereq_('after');
2361var utf8 = _dereq_('utf8');
f8e5fb60 2362
6ab4b1ba
D
2363/**
2364 * Check if we are running an android browser. That requires us to use
2365 * ArrayBuffer with polling transports...
2366 *
2367 * http://ghinda.net/jpeg-blob-ajax-android/
2368 */
d99e7823 2369
6ab4b1ba 2370var isAndroid = navigator.userAgent.match(/Android/i);
d99e7823 2371
6ab4b1ba
D
2372/**
2373 * Current protocol version.
2374 */
a74c0f0c 2375
0de9e7ec 2376exports.protocol = 3;
d99e7823
D
2377
2378/**
6ab4b1ba 2379 * Packet types.
d99e7823
D
2380 */
2381
6ab4b1ba
D
2382var packets = exports.packets = {
2383 open: 0 // non-ws
2384 , close: 1 // non-ws
2385 , ping: 2
2386 , pong: 3
2387 , message: 4
2388 , upgrade: 5
2389 , noop: 6
f8e5fb60 2390};
d99e7823 2391
6ab4b1ba 2392var packetslist = keys(packets);
a74c0f0c 2393
d99e7823 2394/**
6ab4b1ba 2395 * Premade error packet.
d99e7823
D
2396 */
2397
6ab4b1ba 2398var err = { type: 'error', data: 'parser error' };
f8e5fb60 2399
a74c0f0c 2400/**
6ab4b1ba 2401 * Create a blob api even for blob builder when vendor prefixes exist
a74c0f0c 2402 */
f8e5fb60 2403
6ab4b1ba 2404var Blob = _dereq_('blob');
f8e5fb60 2405
a74c0f0c 2406/**
6ab4b1ba
D
2407 * Encodes a packet.
2408 *
2409 * <packet type id> [ <data> ]
2410 *
2411 * Example:
2412 *
2413 * 5hello world
2414 * 3
2415 * 4
2416 *
2417 * Binary is encoded in an identical principle
2418 *
2419 * @api private
a74c0f0c 2420 */
f8e5fb60 2421
0de9e7ec
JA
2422exports.encodePacket = function (packet, supportsBinary, utf8encode, callback) {
2423 if ('function' == typeof supportsBinary) {
6ab4b1ba
D
2424 callback = supportsBinary;
2425 supportsBinary = false;
2426 }
d99e7823 2427
0de9e7ec
JA
2428 if ('function' == typeof utf8encode) {
2429 callback = utf8encode;
2430 utf8encode = null;
2431 }
2432
6ab4b1ba
D
2433 var data = (packet.data === undefined)
2434 ? undefined
2435 : packet.data.buffer || packet.data;
d99e7823 2436
6ab4b1ba
D
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);
2441 }
d99e7823 2442
6ab4b1ba
D
2443 // Sending data as a utf-8 string
2444 var encoded = packets[packet.type];
d99e7823 2445
6ab4b1ba
D
2446 // data fragment is optional
2447 if (undefined !== packet.data) {
0de9e7ec 2448 encoded += utf8encode ? utf8.encode(String(packet.data)) : String(packet.data);
6ab4b1ba 2449 }
d99e7823 2450
6ab4b1ba 2451 return callback('' + encoded);
d99e7823 2452
6ab4b1ba 2453};
d99e7823 2454
f8e5fb60 2455/**
6ab4b1ba 2456 * Encode packet helpers for binary types
f8e5fb60
JA
2457 */
2458
6ab4b1ba
D
2459function encodeArrayBuffer(packet, supportsBinary, callback) {
2460 if (!supportsBinary) {
2461 return exports.encodeBase64Packet(packet, callback);
2462 }
f8e5fb60 2463
6ab4b1ba
D
2464 var data = packet.data;
2465 var contentArray = new Uint8Array(data);
2466 var resultBuffer = new Uint8Array(1 + data.byteLength);
d99e7823 2467
6ab4b1ba
D
2468 resultBuffer[0] = packets[packet.type];
2469 for (var i = 0; i < contentArray.length; i++) {
2470 resultBuffer[i+1] = contentArray[i];
2471 }
a74c0f0c 2472
6ab4b1ba
D
2473 return callback(resultBuffer.buffer);
2474}
2475
2476function encodeBlobAsArrayBuffer(packet, supportsBinary, callback) {
2477 if (!supportsBinary) {
2478 return exports.encodeBase64Packet(packet, callback);
a74c0f0c
D
2479 }
2480
6ab4b1ba
D
2481 var fr = new FileReader();
2482 fr.onload = function() {
2483 packet.data = fr.result;
0de9e7ec 2484 exports.encodePacket(packet, supportsBinary, true, callback);
6ab4b1ba
D
2485 };
2486 return fr.readAsArrayBuffer(packet.data);
2487}
a74c0f0c 2488
6ab4b1ba
D
2489function encodeBlob(packet, supportsBinary, callback) {
2490 if (!supportsBinary) {
2491 return exports.encodeBase64Packet(packet, callback);
2492 }
a74c0f0c 2493
6ab4b1ba
D
2494 if (isAndroid) {
2495 return encodeBlobAsArrayBuffer(packet, supportsBinary, callback);
2496 }
2497
2498 var length = new Uint8Array(1);
2499 length[0] = packets[packet.type];
2500 var blob = new Blob([length.buffer, packet.data]);
2501
2502 return callback(blob);
2503}
d99e7823
D
2504
2505/**
6ab4b1ba
D
2506 * Encodes a packet with binary data in a base64 string
2507 *
2508 * @param {Object} packet, has `type` and `data`
2509 * @return {String} base64 encoded message
d99e7823
D
2510 */
2511
6ab4b1ba
D
2512exports.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);
2519 };
2520 return fr.readAsDataURL(packet.data);
2521 }
2522
2523 var b64data;
2524 try {
2525 b64data = String.fromCharCode.apply(null, new Uint8Array(packet.data));
2526 } catch (e) {
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];
2532 }
2533 b64data = String.fromCharCode.apply(null, basic);
2534 }
2535 message += global.btoa(b64data);
2536 return callback(message);
2537};
d99e7823
D
2538
2539/**
6ab4b1ba 2540 * Decodes a packet. Changes format to Blob if requested.
d99e7823 2541 *
6ab4b1ba 2542 * @return {Object} with `type` and `data` (if any)
d99e7823
D
2543 * @api private
2544 */
2545
0de9e7ec 2546exports.decodePacket = function (data, binaryType, utf8decode) {
6ab4b1ba
D
2547 // String data
2548 if (typeof data == 'string' || data === undefined) {
2549 if (data.charAt(0) == 'b') {
2550 return exports.decodeBase64Packet(data.substr(1), binaryType);
2551 }
2552
0de9e7ec
JA
2553 if (utf8decode) {
2554 try {
2555 data = utf8.decode(data);
2556 } catch (e) {
2557 return err;
2558 }
2559 }
6ab4b1ba
D
2560 var type = data.charAt(0);
2561
2562 if (Number(type) != type || !packetslist[type]) {
2563 return err;
2564 }
2565
2566 if (data.length > 1) {
2567 return { type: packetslist[type], data: data.substring(1) };
2568 } else {
2569 return { type: packetslist[type] };
2570 }
2571 }
2572
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]);
2578 }
2579 return { type: packetslist[type], data: rest };
d99e7823
D
2580};
2581
2582/**
6ab4b1ba 2583 * Decodes a packet encoded in a base64 string
d99e7823 2584 *
6ab4b1ba
D
2585 * @param {String} base64 encoded message
2586 * @return {Object} with `type` and `data` (if any)
d99e7823
D
2587 */
2588
6ab4b1ba
D
2589exports.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) } };
a74c0f0c 2593 }
d99e7823 2594
6ab4b1ba
D
2595 var data = base64encoder.decode(msg.substr(1));
2596
2597 if (binaryType === 'blob' && Blob) {
2598 data = new Blob([data]);
d99e7823
D
2599 }
2600
6ab4b1ba 2601 return { type: type, data: data };
d99e7823
D
2602};
2603
2604/**
6ab4b1ba
D
2605 * Encodes multiple messages (payload).
2606 *
2607 * <length>:data
2608 *
2609 * Example:
2610 *
2611 * 11:hello world2:hi
2612 *
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
d99e7823 2615 *
6ab4b1ba 2616 * @param {Array} packets
d99e7823
D
2617 * @api private
2618 */
2619
6ab4b1ba
D
2620exports.encodePayload = function (packets, supportsBinary, callback) {
2621 if (typeof supportsBinary == 'function') {
2622 callback = supportsBinary;
2623 supportsBinary = null;
2624 }
a74c0f0c 2625
6ab4b1ba
D
2626 if (supportsBinary) {
2627 if (Blob && !isAndroid) {
2628 return exports.encodePayloadAsBlob(packets, callback);
2629 }
2630
2631 return exports.encodePayloadAsArrayBuffer(packets, callback);
d99e7823
D
2632 }
2633
6ab4b1ba
D
2634 if (!packets.length) {
2635 return callback('0:');
2636 }
2637
2638 function setLengthHeader(message) {
2639 return message.length + ':' + message;
2640 }
2641
2642 function encodeOne(packet, doneCallback) {
0de9e7ec 2643 exports.encodePacket(packet, supportsBinary, true, function(message) {
6ab4b1ba
D
2644 doneCallback(null, setLengthHeader(message));
2645 });
2646 }
2647
2648 map(packets, encodeOne, function(err, results) {
2649 return callback(results.join(''));
2650 });
2651};
2652
2653/**
2654 * Async array map using after
2655 */
d99e7823 2656
6ab4b1ba
D
2657function map(ary, each, done) {
2658 var result = new Array(ary.length);
2659 var next = after(ary.length, done);
d99e7823 2660
6ab4b1ba
D
2661 var eachWithIndex = function(i, el, cb) {
2662 each(el, function(error, msg) {
2663 result[i] = msg;
2664 cb(error, result);
2665 });
2666 };
d99e7823 2667
6ab4b1ba
D
2668 for (var i = 0; i < ary.length; i++) {
2669 eachWithIndex(i, ary[i], next);
d99e7823 2670 }
6ab4b1ba 2671}
f8e5fb60 2672
6ab4b1ba
D
2673/*
2674 * Decodes data when a payload is maybe expected. Possible binary contents are
2675 * decoded from their base64 representation
d99e7823 2676 *
6ab4b1ba
D
2677 * @param {String} data, callback method
2678 * @api public
d99e7823
D
2679 */
2680
6ab4b1ba
D
2681exports.decodePayload = function (data, binaryType, callback) {
2682 if (typeof data != 'string') {
2683 return exports.decodePayloadAsBinary(data, binaryType, callback);
2684 }
d99e7823 2685
6ab4b1ba
D
2686 if (typeof binaryType === 'function') {
2687 callback = binaryType;
2688 binaryType = null;
2689 }
f8e5fb60 2690
6ab4b1ba
D
2691 var packet;
2692 if (data == '') {
2693 // parser error - ignoring payload
2694 return callback(err, 0, 1);
d99e7823 2695 }
d99e7823 2696
6ab4b1ba
D
2697 var length = ''
2698 , n, msg;
d99e7823 2699
6ab4b1ba
D
2700 for (var i = 0, l = data.length; i < l; i++) {
2701 var chr = data.charAt(i);
d99e7823 2702
6ab4b1ba
D
2703 if (':' != chr) {
2704 length += chr;
2705 } else {
2706 if ('' == length || (length != (n = Number(length)))) {
2707 // parser error - ignoring payload
2708 return callback(err, 0, 1);
a74c0f0c 2709 }
d99e7823 2710
6ab4b1ba 2711 msg = data.substr(i + 1, n);
d99e7823 2712
6ab4b1ba
D
2713 if (length != msg.length) {
2714 // parser error - ignoring payload
2715 return callback(err, 0, 1);
2716 }
d99e7823 2717
6ab4b1ba 2718 if (msg.length) {
0de9e7ec 2719 packet = exports.decodePacket(msg, binaryType, true);
d99e7823 2720
6ab4b1ba
D
2721 if (err.type == packet.type && err.data == packet.data) {
2722 // parser error in individual packet - ignoring payload
2723 return callback(err, 0, 1);
2724 }
f8e5fb60 2725
6ab4b1ba
D
2726 var ret = callback(packet, i + n, l);
2727 if (false === ret) return;
2728 }
d99e7823 2729
6ab4b1ba
D
2730 // advance cursor
2731 i += n;
2732 length = '';
2733 }
2734 }
d99e7823 2735
6ab4b1ba
D
2736 if (length != '') {
2737 // parser error - ignoring payload
2738 return callback(err, 0, 1);
f8e5fb60 2739 }
6ab4b1ba 2740
f8e5fb60 2741};
d99e7823
D
2742
2743/**
6ab4b1ba
D
2744 * Encodes multiple messages (payload) as binary.
2745 *
2746 * <1 = binary, 0 = string><number from 0-9><number from 0-9>[...]<number
2747 * 255><data>
2748 *
2749 * Example:
2750 * 1 3 255 1 2 3, if the binary contents are interpreted as 8 bit integers
2751 *
2752 * @param {Array} packets
2753 * @return {ArrayBuffer} encoded payload
2754 * @api private
d99e7823
D
2755 */
2756
6ab4b1ba
D
2757exports.encodePayloadAsArrayBuffer = function(packets, callback) {
2758 if (!packets.length) {
2759 return callback(new ArrayBuffer(0));
2760 }
2761
2762 function encodeOne(packet, doneCallback) {
0de9e7ec 2763 exports.encodePacket(packet, true, true, function(data) {
6ab4b1ba
D
2764 return doneCallback(null, data);
2765 });
2766 }
f8e5fb60 2767
6ab4b1ba
D
2768 map(packets, encodeOne, function(err, encodedPackets) {
2769 var totalLength = encodedPackets.reduce(function(acc, p) {
2770 var len;
2771 if (typeof p === 'string'){
2772 len = p.length;
2773 } else {
2774 len = p.byteLength;
2775 }
2776 return acc + len.toString().length + len + 2; // string/binary identifier + separator = 2
2777 }, 0);
d99e7823 2778
6ab4b1ba 2779 var resultArray = new Uint8Array(totalLength);
a74c0f0c 2780
6ab4b1ba
D
2781 var bufferIndex = 0;
2782 encodedPackets.forEach(function(p) {
2783 var isString = typeof p === 'string';
2784 var ab = p;
2785 if (isString) {
2786 var view = new Uint8Array(p.length);
2787 for (var i = 0; i < p.length; i++) {
2788 view[i] = p.charCodeAt(i);
2789 }
2790 ab = view.buffer;
2791 }
d99e7823 2792
6ab4b1ba
D
2793 if (isString) { // not true binary
2794 resultArray[bufferIndex++] = 0;
2795 } else { // true binary
2796 resultArray[bufferIndex++] = 1;
2797 }
d99e7823 2798
6ab4b1ba
D
2799 var lenStr = ab.byteLength.toString();
2800 for (var i = 0; i < lenStr.length; i++) {
2801 resultArray[bufferIndex++] = parseInt(lenStr[i]);
2802 }
2803 resultArray[bufferIndex++] = 255;
d99e7823 2804
6ab4b1ba
D
2805 var view = new Uint8Array(ab);
2806 for (var i = 0; i < view.length; i++) {
2807 resultArray[bufferIndex++] = view[i];
2808 }
2809 });
2810
2811 return callback(resultArray.buffer);
2812 });
a74c0f0c 2813};
d99e7823
D
2814
2815/**
6ab4b1ba 2816 * Encode as Blob
d99e7823
D
2817 */
2818
6ab4b1ba
D
2819exports.encodePayloadAsBlob = function(packets, callback) {
2820 function encodeOne(packet, doneCallback) {
0de9e7ec 2821 exports.encodePacket(packet, true, true, function(encoded) {
6ab4b1ba
D
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);
2828 }
2829 encoded = view.buffer;
2830 binaryIdentifier[0] = 0;
2831 }
d99e7823 2832
6ab4b1ba
D
2833 var len = (encoded instanceof ArrayBuffer)
2834 ? encoded.byteLength
2835 : encoded.size;
d99e7823 2836
6ab4b1ba
D
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]);
2841 }
2842 lengthAry[lenStr.length] = 255;
d99e7823 2843
6ab4b1ba
D
2844 if (Blob) {
2845 var blob = new Blob([binaryIdentifier.buffer, lengthAry.buffer, encoded]);
2846 doneCallback(null, blob);
2847 }
2848 });
d99e7823 2849 }
a74c0f0c 2850
6ab4b1ba
D
2851 map(packets, encodeOne, function(err, results) {
2852 return callback(new Blob(results));
2853 });
a74c0f0c 2854};
d99e7823 2855
6ab4b1ba
D
2856/*
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
d99e7823 2860 *
6ab4b1ba
D
2861 * @param {ArrayBuffer} data, callback method
2862 * @api public
d99e7823
D
2863 */
2864
6ab4b1ba
D
2865exports.decodePayloadAsBinary = function (data, binaryType, callback) {
2866 if (typeof binaryType === 'function') {
2867 callback = binaryType;
2868 binaryType = null;
2869 }
d99e7823 2870
6ab4b1ba
D
2871 var bufferTail = data;
2872 var buffers = [];
d99e7823 2873
0de9e7ec 2874 var numberTooLong = false;
6ab4b1ba
D
2875 while (bufferTail.byteLength > 0) {
2876 var tailArray = new Uint8Array(bufferTail);
2877 var isString = tailArray[0] === 0;
2878 var msgLength = '';
0de9e7ec 2879
6ab4b1ba
D
2880 for (var i = 1; ; i++) {
2881 if (tailArray[i] == 255) break;
0de9e7ec
JA
2882
2883 if (msgLength.length > 310) {
2884 numberTooLong = true;
2885 break;
2886 }
2887
6ab4b1ba
D
2888 msgLength += tailArray[i];
2889 }
0de9e7ec
JA
2890
2891 if(numberTooLong) return callback(err, 0, 1);
2892
6ab4b1ba
D
2893 bufferTail = sliceBuffer(bufferTail, 2 + msgLength.length);
2894 msgLength = parseInt(msgLength);
2895
2896 var msg = sliceBuffer(bufferTail, 0, msgLength);
2897 if (isString) {
2898 try {
2899 msg = String.fromCharCode.apply(null, new Uint8Array(msg));
2900 } catch (e) {
2901 // iPhone Safari doesn't let you apply to typed arrays
2902 var typed = new Uint8Array(msg);
2903 msg = '';
2904 for (var i = 0; i < typed.length; i++) {
2905 msg += String.fromCharCode(typed[i]);
2906 }
a74c0f0c 2907 }
6ab4b1ba 2908 }
0de9e7ec 2909
6ab4b1ba
D
2910 buffers.push(msg);
2911 bufferTail = sliceBuffer(bufferTail, msgLength);
d99e7823 2912 }
6ab4b1ba
D
2913
2914 var total = buffers.length;
2915 buffers.forEach(function(buffer, i) {
0de9e7ec 2916 callback(exports.decodePacket(buffer, binaryType, true), i, total);
6ab4b1ba 2917 });
d99e7823
D
2918};
2919
6ab4b1ba 2920}).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
e65c2242 2921},{"./keys":16,"after":17,"arraybuffer.slice":18,"base64-arraybuffer":19,"blob":11,"utf8":20}],16:[function(_dereq_,module,exports){
6ab4b1ba 2922
d99e7823 2923/**
6ab4b1ba 2924 * Gets the keys for an object.
d99e7823 2925 *
6ab4b1ba 2926 * @return {Array} keys
a74c0f0c 2927 * @api private
d99e7823
D
2928 */
2929
6ab4b1ba
D
2930module.exports = Object.keys || function keys (obj){
2931 var arr = [];
2932 var has = Object.prototype.hasOwnProperty;
2933
2934 for (var i in obj) {
2935 if (has.call(obj, i)) {
2936 arr.push(i);
2937 }
2938 }
2939 return arr;
a74c0f0c 2940};
d99e7823 2941
e65c2242 2942},{}],17:[function(_dereq_,module,exports){
6ab4b1ba
D
2943module.exports = after
2944
2945function after(count, callback, err_cb) {
2946 var bail = false
2947 err_cb = err_cb || noop
2948 proxy.count = count
2949
2950 return (count === 0) ? callback() : proxy
2951
2952 function proxy(err, result) {
2953 if (proxy.count <= 0) {
2954 throw new Error('after called too many times')
2955 }
2956 --proxy.count
2957
2958 // after first error, rest are passed to err_cb
2959 if (err) {
2960 bail = true
2961 callback(err)
2962 // future error callbacks will go to error handler
2963 callback = err_cb
2964 } else if (proxy.count === 0 && !bail) {
2965 callback(null, result)
2966 }
2967 }
2968}
2969
2970function noop() {}
2971
e65c2242 2972},{}],18:[function(_dereq_,module,exports){
a74c0f0c 2973/**
6ab4b1ba
D
2974 * An abstraction for slicing an arraybuffer even when
2975 * ArrayBuffer.prototype.slice is not supported
a74c0f0c 2976 *
6ab4b1ba 2977 * @api public
a74c0f0c 2978 */
f8e5fb60 2979
6ab4b1ba
D
2980module.exports = function(arraybuffer, start, end) {
2981 var bytes = arraybuffer.byteLength;
2982 start = start || 0;
2983 end = end || bytes;
2984
2985 if (arraybuffer.slice) { return arraybuffer.slice(start, end); }
2986
2987 if (start < 0) { start += bytes; }
2988 if (end < 0) { end += bytes; }
2989 if (end > bytes) { end = bytes; }
2990
2991 if (start >= bytes || start >= end || bytes === 0) {
2992 return new ArrayBuffer(0);
2993 }
2994
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];
d99e7823 2999 }
6ab4b1ba 3000 return result.buffer;
d99e7823
D
3001};
3002
e65c2242 3003},{}],19:[function(_dereq_,module,exports){
6ab4b1ba
D
3004/*
3005 * base64-arraybuffer
3006 * https://github.com/niklasvh/base64-arraybuffer
d99e7823 3007 *
6ab4b1ba
D
3008 * Copyright (c) 2012 Niklas von Hertzen
3009 * Licensed under the MIT license.
d99e7823 3010 */
6ab4b1ba
D
3011(function(chars){
3012 "use strict";
d99e7823 3013
6ab4b1ba
D
3014 exports.encode = function(arraybuffer) {
3015 var bytes = new Uint8Array(arraybuffer),
3016 i, len = bytes.length, base64 = "";
d99e7823 3017
6ab4b1ba
D
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];
3023 }
d99e7823 3024
6ab4b1ba
D
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) + "==";
3029 }
a74c0f0c 3030
6ab4b1ba
D
3031 return base64;
3032 };
a74c0f0c 3033
6ab4b1ba
D
3034 exports.decode = function(base64) {
3035 var bufferLength = base64.length * 0.75,
3036 len = base64.length, i, p = 0,
3037 encoded1, encoded2, encoded3, encoded4;
a74c0f0c 3038
6ab4b1ba
D
3039 if (base64[base64.length - 1] === "=") {
3040 bufferLength--;
3041 if (base64[base64.length - 2] === "=") {
3042 bufferLength--;
3043 }
3044 }
d99e7823 3045
6ab4b1ba
D
3046 var arraybuffer = new ArrayBuffer(bufferLength),
3047 bytes = new Uint8Array(arraybuffer);
d99e7823 3048
6ab4b1ba
D
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]);
d99e7823 3054
6ab4b1ba
D
3055 bytes[p++] = (encoded1 << 2) | (encoded2 >> 4);
3056 bytes[p++] = ((encoded2 & 15) << 4) | (encoded3 >> 2);
3057 bytes[p++] = ((encoded3 & 3) << 6) | (encoded4 & 63);
3058 }
d99e7823 3059
6ab4b1ba
D
3060 return arraybuffer;
3061 };
3062})("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/");
3063
e65c2242 3064},{}],20:[function(_dereq_,module,exports){
6ab4b1ba
D
3065(function (global){
3066/*! http://mths.be/utf8js v2.0.0 by @mathias */
3067;(function(root) {
3068
3069 // Detect free variables `exports`
3070 var freeExports = typeof exports == 'object' && exports;
3071
3072 // Detect free variable `module`
3073 var freeModule = typeof module == 'object' && module &&
3074 module.exports == freeExports && module;
3075
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) {
3080 root = freeGlobal;
3081 }
3082
3083 /*--------------------------------------------------------------------------*/
3084
3085 var stringFromCharCode = String.fromCharCode;
3086
3087 // Taken from http://mths.be/punycode
3088 function ucs2decode(string) {
3089 var output = [];
3090 var counter = 0;
3091 var length = string.length;
3092 var value;
3093 var extra;
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);
3101 } else {
3102 // unmatched surrogate; only append this code unit, in case the next
3103 // code unit is the high surrogate of a surrogate pair
3104 output.push(value);
3105 counter--;
3106 }
3107 } else {
3108 output.push(value);
3109 }
3110 }
3111 return output;
3112 }
3113
3114 // Taken from http://mths.be/punycode
3115 function ucs2encode(array) {
3116 var length = array.length;
3117 var index = -1;
3118 var value;
3119 var output = '';
3120 while (++index < length) {
3121 value = array[index];
3122 if (value > 0xFFFF) {
3123 value -= 0x10000;
3124 output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800);
3125 value = 0xDC00 | value & 0x3FF;
3126 }
3127 output += stringFromCharCode(value);
3128 }
3129 return output;
a74c0f0c 3130 }
d99e7823 3131
6ab4b1ba 3132 /*--------------------------------------------------------------------------*/
f8e5fb60 3133
6ab4b1ba
D
3134 function createByte(codePoint, shift) {
3135 return stringFromCharCode(((codePoint >> shift) & 0x3F) | 0x80);
3136 }
3137
3138 function encodeCodePoint(codePoint) {
3139 if ((codePoint & 0xFFFFFF80) == 0) { // 1-byte sequence
3140 return stringFromCharCode(codePoint);
3141 }
3142 var symbol = '';
3143 if ((codePoint & 0xFFFFF800) == 0) { // 2-byte sequence
3144 symbol = stringFromCharCode(((codePoint >> 6) & 0x1F) | 0xC0);
3145 }
3146 else if ((codePoint & 0xFFFF0000) == 0) { // 3-byte sequence
3147 symbol = stringFromCharCode(((codePoint >> 12) & 0x0F) | 0xE0);
3148 symbol += createByte(codePoint, 6);
3149 }
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);
3154 }
3155 symbol += stringFromCharCode((codePoint & 0x3F) | 0x80);
3156 return symbol;
3157 }
d99e7823 3158
6ab4b1ba
D
3159 function utf8encode(string) {
3160 var codePoints = ucs2decode(string);
d99e7823 3161
6ab4b1ba
D
3162 // console.log(JSON.stringify(codePoints.map(function(x) {
3163 // return 'U+' + x.toString(16).toUpperCase();
3164 // })));
f8e5fb60 3165
6ab4b1ba
D
3166 var length = codePoints.length;
3167 var index = -1;
3168 var codePoint;
3169 var byteString = '';
3170 while (++index < length) {
3171 codePoint = codePoints[index];
3172 byteString += encodeCodePoint(codePoint);
3173 }
3174 return byteString;
3175 }
d99e7823 3176
6ab4b1ba 3177 /*--------------------------------------------------------------------------*/
d99e7823 3178
6ab4b1ba
D
3179 function readContinuationByte() {
3180 if (byteIndex >= byteCount) {
3181 throw Error('Invalid byte index');
3182 }
d99e7823 3183
6ab4b1ba
D
3184 var continuationByte = byteArray[byteIndex] & 0xFF;
3185 byteIndex++;
d99e7823 3186
6ab4b1ba
D
3187 if ((continuationByte & 0xC0) == 0x80) {
3188 return continuationByte & 0x3F;
3189 }
d99e7823 3190
6ab4b1ba
D
3191 // If we end up here, it’s not a continuation byte
3192 throw Error('Invalid continuation byte');
3193 }
d99e7823 3194
6ab4b1ba
D
3195 function decodeSymbol() {
3196 var byte1;
3197 var byte2;
3198 var byte3;
3199 var byte4;
3200 var codePoint;
d99e7823 3201
6ab4b1ba
D
3202 if (byteIndex > byteCount) {
3203 throw Error('Invalid byte index');
3204 }
d99e7823 3205
6ab4b1ba
D
3206 if (byteIndex == byteCount) {
3207 return false;
3208 }
f8e5fb60 3209
6ab4b1ba
D
3210 // Read first byte
3211 byte1 = byteArray[byteIndex] & 0xFF;
3212 byteIndex++;
f8e5fb60 3213
6ab4b1ba
D
3214 // 1-byte sequence (no continuation bytes)
3215 if ((byte1 & 0x80) == 0) {
3216 return byte1;
3217 }
f8e5fb60 3218
6ab4b1ba
D
3219 // 2-byte sequence
3220 if ((byte1 & 0xE0) == 0xC0) {
3221 var byte2 = readContinuationByte();
3222 codePoint = ((byte1 & 0x1F) << 6) | byte2;
3223 if (codePoint >= 0x80) {
3224 return codePoint;
3225 } else {
3226 throw Error('Invalid continuation byte');
3227 }
3228 }
d99e7823 3229
6ab4b1ba
D
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) {
3236 return codePoint;
3237 } else {
3238 throw Error('Invalid continuation byte');
3239 }
3240 }
d99e7823 3241
6ab4b1ba
D
3242 // 4-byte sequence
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) {
3250 return codePoint;
3251 }
3252 }
d99e7823 3253
6ab4b1ba
D
3254 throw Error('Invalid UTF-8 detected');
3255 }
d99e7823 3256
6ab4b1ba
D
3257 var byteArray;
3258 var byteCount;
3259 var byteIndex;
3260 function utf8decode(byteString) {
3261 byteArray = ucs2decode(byteString);
3262 byteCount = byteArray.length;
3263 byteIndex = 0;
3264 var codePoints = [];
3265 var tmp;
3266 while ((tmp = decodeSymbol()) !== false) {
3267 codePoints.push(tmp);
3268 }
3269 return ucs2encode(codePoints);
a74c0f0c 3270 }
d99e7823 3271
6ab4b1ba
D
3272 /*--------------------------------------------------------------------------*/
3273
3274 var utf8 = {
3275 'version': '2.0.0',
3276 'encode': utf8encode,
3277 'decode': utf8decode
3278 };
d99e7823 3279
6ab4b1ba
D
3280 // Some AMD build optimizers, like r.js, check for specific condition patterns
3281 // like the following:
3282 if (
3283 typeof define == 'function' &&
3284 typeof define.amd == 'object' &&
3285 define.amd
3286 ) {
3287 define(function() {
3288 return utf8;
3289 });
3290 } else if (freeExports && !freeExports.nodeType) {
3291 if (freeModule) { // in Node.js or RingoJS v0.8.0+
3292 freeModule.exports = utf8;
3293 } else { // in Narwhal or RingoJS v0.7.0-
3294 var object = {};
3295 var hasOwnProperty = object.hasOwnProperty;
3296 for (var key in utf8) {
3297 hasOwnProperty.call(utf8, key) && (freeExports[key] = utf8[key]);
3298 }
3299 }
3300 } else { // in Rhino or a web browser
3301 root.utf8 = utf8;
a74c0f0c 3302 }
d99e7823 3303
6ab4b1ba 3304}(this));
d99e7823 3305
6ab4b1ba 3306}).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
6ab4b1ba
D
3307},{}],21:[function(_dereq_,module,exports){
3308
3309/**
3310 * Module dependencies.
3311 */
3312
3313var global = _dereq_('global');
d99e7823 3314
a74c0f0c 3315/**
6ab4b1ba 3316 * Module exports.
a74c0f0c 3317 *
6ab4b1ba
D
3318 * Logic borrowed from Modernizr:
3319 *
3320 * - https://github.com/Modernizr/Modernizr/blob/master/feature-detects/cors.js
a74c0f0c 3321 */
d99e7823 3322
6ab4b1ba
D
3323try {
3324 module.exports = 'XMLHttpRequest' in global &&
3325 'withCredentials' in new global.XMLHttpRequest();
3326} catch (err) {
3327 // if XMLHttp support is disabled in IE then it will throw
3328 // when trying to create
3329 module.exports = false;
3330}
3331
e65c2242
JA
3332},{"global":22}],22:[function(_dereq_,module,exports){
3333
3334/**
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.
3338 */
3339
3340module.exports = (function () { return this; })();
3341
3342},{}],23:[function(_dereq_,module,exports){
6ab4b1ba
D
3343
3344var indexOf = [].indexOf;
3345
3346module.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;
3350 }
3351 return -1;
d99e7823 3352};
6ab4b1ba
D
3353},{}],24:[function(_dereq_,module,exports){
3354(function (global){
d99e7823 3355/**
6ab4b1ba 3356 * JSON parse.
d99e7823 3357 *
6ab4b1ba 3358 * @see Based on jQuery#parseJSON (MIT) and JSON2
d99e7823
D
3359 * @api private
3360 */
3361
6ab4b1ba
D
3362var rvalidchars = /^[\],:{}\s]*$/;
3363var rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g;
3364var rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g;
3365var rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g;
3366var rtrimLeft = /^\s+/;
3367var rtrimRight = /\s+$/;
d99e7823 3368
6ab4b1ba
D
3369module.exports = function parsejson(data) {
3370 if ('string' != typeof data || !data) {
3371 return null;
a74c0f0c 3372 }
d99e7823 3373
6ab4b1ba 3374 data = data.replace(rtrimLeft, '').replace(rtrimRight, '');
d99e7823 3375
6ab4b1ba
D
3376 // Attempt to parse using the native JSON parser first
3377 if (global.JSON && JSON.parse) {
3378 return JSON.parse(data);
a74c0f0c 3379 }
d99e7823 3380
6ab4b1ba
D
3381 if (rvalidchars.test(data.replace(rvalidescape, '@')
3382 .replace(rvalidtokens, ']')
3383 .replace(rvalidbraces, ''))) {
3384 return (new Function('return ' + data))();
a74c0f0c 3385 }
a74c0f0c 3386};
6ab4b1ba
D
3387}).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
3388},{}],25:[function(_dereq_,module,exports){
d99e7823 3389/**
6ab4b1ba
D
3390 * Compiles a querystring
3391 * Returns string representation of the object
f8e5fb60 3392 *
6ab4b1ba
D
3393 * @param {Object}
3394 * @api private
d99e7823
D
3395 */
3396
6ab4b1ba
D
3397exports.encode = function (obj) {
3398 var str = '';
d99e7823 3399
6ab4b1ba
D
3400 for (var i in obj) {
3401 if (obj.hasOwnProperty(i)) {
3402 if (str.length) str += '&';
3403 str += encodeURIComponent(i) + '=' + encodeURIComponent(obj[i]);
a74c0f0c 3404 }
f8e5fb60 3405 }
a74c0f0c 3406
6ab4b1ba 3407 return str;
d99e7823
D
3408};
3409
3410/**
6ab4b1ba
D
3411 * Parses a simple querystring into an object
3412 *
3413 * @param {String} qs
3414 * @api private
d99e7823
D
3415 */
3416
6ab4b1ba
D
3417exports.decode = function(qs){
3418 var qry = {};
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]);
3423 }
3424 return qry;
3425};
d99e7823 3426
6ab4b1ba 3427},{}],26:[function(_dereq_,module,exports){
d99e7823 3428/**
6ab4b1ba 3429 * Parses an URI
a74c0f0c 3430 *
6ab4b1ba 3431 * @author Steven Levithan <stevenlevithan.com> (MIT license)
a74c0f0c 3432 * @api private
d99e7823
D
3433 */
3434
6ab4b1ba 3435var re = /^(?:(?![^:@]+:[^:@\/]*@)(http|https|ws|wss):\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?((?:[a-f0-9]{0,4}:){2,7}[a-f0-9]{0,4}|[^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/;
d99e7823 3436
6ab4b1ba 3437var parts = [
0de9e7ec 3438 'source', 'protocol', 'authority', 'userInfo', 'user', 'password', 'host', 'port', 'relative', 'path', 'directory', 'file', 'query', 'anchor'
6ab4b1ba 3439];
a74c0f0c 3440
6ab4b1ba 3441module.exports = function parseuri(str) {
0de9e7ec
JA
3442 var src = str,
3443 b = str.indexOf('['),
3444 e = str.indexOf(']');
a74c0f0c 3445
0de9e7ec
JA
3446 if (b != -1 && e != -1) {
3447 str = str.substring(0, b) + str.substring(b, e).replace(/:/g, ';') + str.substring(e, str.length);
3448 }
3449
3450 var m = re.exec(str || ''),
3451 uri = {},
3452 i = 14;
3453
3454 while (i--) {
3455 uri[parts[i]] = m[i] || '';
3456 }
3457
3458 if (b != -1 && e != -1) {
3459 uri.source = src;
3460 uri.host = uri.host.substring(1, uri.host.length - 1).replace(/;/g, ':');
3461 uri.authority = uri.authority.replace('[', '').replace(']', '').replace(/;/g, ':');
3462 uri.ipv6uri = true;
3463 }
d99e7823 3464
0de9e7ec 3465 return uri;
a74c0f0c 3466};
d99e7823 3467
6ab4b1ba
D
3468},{}],27:[function(_dereq_,module,exports){
3469
d99e7823 3470/**
6ab4b1ba 3471 * Module dependencies.
d99e7823
D
3472 */
3473
6ab4b1ba 3474var global = (function() { return this; })();
d99e7823 3475
6ab4b1ba
D
3476/**
3477 * WebSocket constructor.
3478 */
3479
3480var WebSocket = global.WebSocket || global.MozWebSocket;
d99e7823 3481
6ab4b1ba
D
3482/**
3483 * Module exports.
3484 */
a74c0f0c 3485
6ab4b1ba 3486module.exports = WebSocket ? ws : null;
a74c0f0c 3487
6ab4b1ba
D
3488/**
3489 * WebSocket constructor.
3490 *
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
3494 *
3495 * @param {String} uri
3496 * @param {Array} protocols (optional)
3497 * @param {Object) opts (optional)
3498 * @api public
3499 */
a74c0f0c 3500
6ab4b1ba
D
3501function ws(uri, protocols, opts) {
3502 var instance;
3503 if (protocols) {
3504 instance = new WebSocket(uri, protocols);
3505 } else {
3506 instance = new WebSocket(uri);
3507 }
3508 return instance;
3509}
a74c0f0c 3510
6ab4b1ba 3511if (WebSocket) ws.prototype = WebSocket.prototype;
a74c0f0c 3512
6ab4b1ba
D
3513},{}]},{},[1])
3514(1)
e65c2242 3515});