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