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