Commit | Line | Data |
---|---|---|
d99e7823 D |
1 | ;(function(){ |
2 | ||
3 | /** | |
4 | * Require the given path. | |
5 | * | |
6 | * @param {String} path | |
7 | * @return {Object} exports | |
8 | * @api public | |
9 | */ | |
10 | ||
11 | function require(path, parent, orig) { | |
12 | var resolved = require.resolve(path); | |
13 | ||
14 | // lookup failed | |
15 | if (null == resolved) { | |
16 | orig = orig || path; | |
17 | parent = parent || 'root'; | |
18 | var err = new Error('Failed to require "' + orig + '" from "' + parent + '"'); | |
19 | err.path = orig; | |
20 | err.parent = parent; | |
21 | err.require = true; | |
22 | throw err; | |
23 | } | |
24 | ||
25 | var module = require.modules[resolved]; | |
26 | ||
27 | // perform real require() | |
28 | // by invoking the module's | |
29 | // registered function | |
30 | if (!module.exports) { | |
31 | module.exports = {}; | |
32 | module.client = module.component = true; | |
33 | module.call(this, module.exports, require.relative(resolved), module); | |
34 | } | |
35 | ||
36 | return module.exports; | |
37 | } | |
38 | ||
39 | /** | |
40 | * Registered modules. | |
41 | */ | |
42 | ||
43 | require.modules = {}; | |
44 | ||
45 | /** | |
46 | * Registered aliases. | |
47 | */ | |
48 | ||
49 | require.aliases = {}; | |
50 | ||
51 | /** | |
52 | * Resolve `path`. | |
53 | * | |
54 | * Lookup: | |
55 | * | |
56 | * - PATH/index.js | |
57 | * - PATH.js | |
58 | * - PATH | |
59 | * | |
60 | * @param {String} path | |
61 | * @return {String} path or null | |
62 | * @api private | |
63 | */ | |
64 | ||
65 | require.resolve = function(path) { | |
66 | if (path.charAt(0) === '/') path = path.slice(1); | |
67 | var index = path + '/index.js'; | |
68 | ||
69 | var paths = [ | |
70 | path, | |
71 | path + '.js', | |
72 | path + '.json', | |
73 | path + '/index.js', | |
74 | path + '/index.json' | |
75 | ]; | |
76 | ||
77 | for (var i = 0; i < paths.length; i++) { | |
78 | var path = paths[i]; | |
79 | if (require.modules.hasOwnProperty(path)) return path; | |
80 | } | |
81 | ||
82 | if (require.aliases.hasOwnProperty(index)) { | |
83 | return require.aliases[index]; | |
84 | } | |
85 | }; | |
86 | ||
87 | /** | |
88 | * Normalize `path` relative to the current path. | |
89 | * | |
90 | * @param {String} curr | |
91 | * @param {String} path | |
92 | * @return {String} | |
93 | * @api private | |
94 | */ | |
95 | ||
96 | require.normalize = function(curr, path) { | |
97 | var segs = []; | |
98 | ||
99 | if ('.' != path.charAt(0)) return path; | |
100 | ||
101 | curr = curr.split('/'); | |
102 | path = path.split('/'); | |
103 | ||
104 | for (var i = 0; i < path.length; ++i) { | |
105 | if ('..' == path[i]) { | |
106 | curr.pop(); | |
107 | } else if ('.' != path[i] && '' != path[i]) { | |
108 | segs.push(path[i]); | |
109 | } | |
110 | } | |
111 | ||
112 | return curr.concat(segs).join('/'); | |
113 | }; | |
114 | ||
115 | /** | |
116 | * Register module at `path` with callback `definition`. | |
117 | * | |
118 | * @param {String} path | |
119 | * @param {Function} definition | |
120 | * @api private | |
121 | */ | |
122 | ||
123 | require.register = function(path, definition) { | |
124 | require.modules[path] = definition; | |
125 | }; | |
126 | ||
127 | /** | |
128 | * Alias a module definition. | |
129 | * | |
130 | * @param {String} from | |
131 | * @param {String} to | |
132 | * @api private | |
133 | */ | |
134 | ||
135 | require.alias = function(from, to) { | |
136 | if (!require.modules.hasOwnProperty(from)) { | |
137 | throw new Error('Failed to alias "' + from + '", it does not exist'); | |
138 | } | |
139 | require.aliases[to] = from; | |
140 | }; | |
141 | ||
142 | /** | |
143 | * Return a require function relative to the `parent` path. | |
144 | * | |
145 | * @param {String} parent | |
146 | * @return {Function} | |
147 | * @api private | |
148 | */ | |
149 | ||
150 | require.relative = function(parent) { | |
151 | var p = require.normalize(parent, '..'); | |
152 | ||
153 | /** | |
154 | * lastIndexOf helper. | |
155 | */ | |
156 | ||
157 | function lastIndexOf(arr, obj) { | |
158 | var i = arr.length; | |
159 | while (i--) { | |
160 | if (arr[i] === obj) return i; | |
161 | } | |
162 | return -1; | |
163 | } | |
164 | ||
165 | /** | |
166 | * The relative require() itself. | |
167 | */ | |
168 | ||
169 | function localRequire(path) { | |
170 | var resolved = localRequire.resolve(path); | |
171 | return require(resolved, parent, path); | |
172 | } | |
173 | ||
174 | /** | |
175 | * Resolve relative to the parent. | |
176 | */ | |
177 | ||
178 | localRequire.resolve = function(path) { | |
179 | var c = path.charAt(0); | |
180 | if ('/' == c) return path.slice(1); | |
181 | if ('.' == c) return require.normalize(p, path); | |
182 | ||
183 | // resolve deps by returning | |
184 | // the dep in the nearest "deps" | |
185 | // directory | |
186 | var segs = parent.split('/'); | |
187 | var i = lastIndexOf(segs, 'deps') + 1; | |
188 | if (!i) i = 0; | |
189 | path = segs.slice(0, i + 1).join('/') + '/deps/' + path; | |
190 | return path; | |
191 | }; | |
192 | ||
193 | /** | |
194 | * Check if module is defined at `path`. | |
195 | */ | |
196 | ||
197 | localRequire.exists = function(path) { | |
198 | return require.modules.hasOwnProperty(localRequire.resolve(path)); | |
199 | }; | |
200 | ||
201 | return localRequire; | |
202 | }; | |
203 | require.register("component-emitter/index.js", function(exports, require, module){ | |
204 | ||
205 | /** | |
206 | * Expose `Emitter`. | |
207 | */ | |
208 | ||
209 | module.exports = Emitter; | |
210 | ||
211 | /** | |
212 | * Initialize a new `Emitter`. | |
213 | * | |
214 | * @api public | |
215 | */ | |
216 | ||
217 | function Emitter(obj) { | |
218 | if (obj) return mixin(obj); | |
219 | }; | |
220 | ||
221 | /** | |
222 | * Mixin the emitter properties. | |
223 | * | |
224 | * @param {Object} obj | |
225 | * @return {Object} | |
226 | * @api private | |
227 | */ | |
228 | ||
229 | function mixin(obj) { | |
230 | for (var key in Emitter.prototype) { | |
231 | obj[key] = Emitter.prototype[key]; | |
232 | } | |
233 | return obj; | |
234 | } | |
235 | ||
236 | /** | |
237 | * Listen on the given `event` with `fn`. | |
238 | * | |
239 | * @param {String} event | |
240 | * @param {Function} fn | |
241 | * @return {Emitter} | |
242 | * @api public | |
243 | */ | |
244 | ||
245 | Emitter.prototype.on = function(event, fn){ | |
246 | this._callbacks = this._callbacks || {}; | |
247 | (this._callbacks[event] = this._callbacks[event] || []) | |
248 | .push(fn); | |
249 | return this; | |
250 | }; | |
251 | ||
252 | /** | |
253 | * Adds an `event` listener that will be invoked a single | |
254 | * time then automatically removed. | |
255 | * | |
256 | * @param {String} event | |
257 | * @param {Function} fn | |
258 | * @return {Emitter} | |
259 | * @api public | |
260 | */ | |
261 | ||
262 | Emitter.prototype.once = function(event, fn){ | |
263 | var self = this; | |
264 | this._callbacks = this._callbacks || {}; | |
265 | ||
266 | function on() { | |
267 | self.off(event, on); | |
268 | fn.apply(this, arguments); | |
269 | } | |
270 | ||
271 | fn._off = on; | |
272 | this.on(event, on); | |
273 | return this; | |
274 | }; | |
275 | ||
276 | /** | |
277 | * Remove the given callback for `event` or all | |
278 | * registered callbacks. | |
279 | * | |
280 | * @param {String} event | |
281 | * @param {Function} fn | |
282 | * @return {Emitter} | |
283 | * @api public | |
284 | */ | |
285 | ||
286 | Emitter.prototype.off = | |
287 | Emitter.prototype.removeListener = | |
288 | Emitter.prototype.removeAllListeners = function(event, fn){ | |
289 | this._callbacks = this._callbacks || {}; | |
290 | ||
291 | // all | |
292 | if (0 == arguments.length) { | |
293 | this._callbacks = {}; | |
294 | return this; | |
295 | } | |
296 | ||
297 | // specific event | |
298 | var callbacks = this._callbacks[event]; | |
299 | if (!callbacks) return this; | |
300 | ||
301 | // remove all handlers | |
302 | if (1 == arguments.length) { | |
303 | delete this._callbacks[event]; | |
304 | return this; | |
305 | } | |
306 | ||
307 | // remove specific handler | |
308 | var i = callbacks.indexOf(fn._off || fn); | |
309 | if (~i) callbacks.splice(i, 1); | |
310 | return this; | |
311 | }; | |
312 | ||
313 | /** | |
314 | * Emit `event` with the given args. | |
315 | * | |
316 | * @param {String} event | |
317 | * @param {Mixed} ... | |
318 | * @return {Emitter} | |
319 | */ | |
320 | ||
321 | Emitter.prototype.emit = function(event){ | |
322 | this._callbacks = this._callbacks || {}; | |
323 | var args = [].slice.call(arguments, 1) | |
324 | , callbacks = this._callbacks[event]; | |
325 | ||
326 | if (callbacks) { | |
327 | callbacks = callbacks.slice(0); | |
328 | for (var i = 0, len = callbacks.length; i < len; ++i) { | |
329 | callbacks[i].apply(this, args); | |
330 | } | |
331 | } | |
332 | ||
333 | return this; | |
334 | }; | |
335 | ||
336 | /** | |
337 | * Return array of callbacks for `event`. | |
338 | * | |
339 | * @param {String} event | |
340 | * @return {Array} | |
341 | * @api public | |
342 | */ | |
343 | ||
344 | Emitter.prototype.listeners = function(event){ | |
345 | this._callbacks = this._callbacks || {}; | |
346 | return this._callbacks[event] || []; | |
347 | }; | |
348 | ||
349 | /** | |
350 | * Check if this emitter has `event` handlers. | |
351 | * | |
352 | * @param {String} event | |
353 | * @return {Boolean} | |
354 | * @api public | |
355 | */ | |
356 | ||
357 | Emitter.prototype.hasListeners = function(event){ | |
358 | return !! this.listeners(event).length; | |
359 | }; | |
360 | ||
361 | }); | |
362 | require.register("component-indexof/index.js", function(exports, require, module){ | |
363 | ||
364 | var indexOf = [].indexOf; | |
365 | ||
366 | module.exports = function(arr, obj){ | |
367 | if (indexOf) return arr.indexOf(obj); | |
368 | for (var i = 0; i < arr.length; ++i) { | |
369 | if (arr[i] === obj) return i; | |
370 | } | |
371 | return -1; | |
372 | }; | |
373 | }); | |
374 | require.register("LearnBoost-engine.io-protocol/lib/index.js", function(exports, require, module){ | |
375 | /** | |
376 | * Module dependencies. | |
377 | */ | |
378 | ||
379 | var keys = require('./keys'); | |
380 | ||
381 | /** | |
382 | * Current protocol version. | |
383 | */ | |
384 | exports.protocol = 2; | |
385 | ||
386 | /** | |
387 | * Packet types. | |
388 | */ | |
389 | ||
390 | var packets = exports.packets = { | |
391 | open: 0 // non-ws | |
392 | , close: 1 // non-ws | |
393 | , ping: 2 | |
394 | , pong: 3 | |
395 | , message: 4 | |
396 | , upgrade: 5 | |
397 | , noop: 6 | |
398 | }; | |
399 | ||
400 | var packetslist = keys(packets); | |
401 | ||
402 | /** | |
403 | * Premade error packet. | |
404 | */ | |
405 | ||
406 | var err = { type: 'error', data: 'parser error' }; | |
407 | ||
408 | /** | |
409 | * Encodes a packet. | |
410 | * | |
411 | * <packet type id> [ `:` <data> ] | |
412 | * | |
413 | * Example: | |
414 | * | |
415 | * 5:hello world | |
416 | * 3 | |
417 | * 4 | |
418 | * | |
419 | * @api private | |
420 | */ | |
421 | ||
422 | exports.encodePacket = function (packet) { | |
423 | var encoded = packets[packet.type]; | |
424 | ||
425 | // data fragment is optional | |
426 | if (undefined !== packet.data) { | |
427 | encoded += String(packet.data); | |
428 | } | |
429 | ||
430 | return '' + encoded; | |
431 | }; | |
432 | ||
433 | /** | |
434 | * Decodes a packet. | |
435 | * | |
436 | * @return {Object} with `type` and `data` (if any) | |
437 | * @api private | |
438 | */ | |
439 | ||
440 | exports.decodePacket = function (data) { | |
441 | var type = data.charAt(0); | |
442 | ||
443 | if (Number(type) != type || !packetslist[type]) { | |
444 | return err; | |
445 | } | |
446 | ||
447 | if (data.length > 1) { | |
448 | return { type: packetslist[type], data: data.substring(1) }; | |
449 | } else { | |
450 | return { type: packetslist[type] }; | |
451 | } | |
452 | }; | |
453 | ||
454 | /** | |
455 | * Encodes multiple messages (payload). | |
456 | * | |
457 | * <length>:data | |
458 | * | |
459 | * Example: | |
460 | * | |
461 | * 11:hello world2:hi | |
462 | * | |
463 | * @param {Array} packets | |
464 | * @api private | |
465 | */ | |
466 | ||
467 | exports.encodePayload = function (packets) { | |
468 | if (!packets.length) { | |
469 | return '0:'; | |
470 | } | |
471 | ||
472 | var encoded = ''; | |
473 | var message; | |
474 | ||
475 | for (var i = 0, l = packets.length; i < l; i++) { | |
476 | message = exports.encodePacket(packets[i]); | |
477 | encoded += message.length + ':' + message; | |
478 | } | |
479 | ||
480 | return encoded; | |
481 | }; | |
482 | ||
483 | /* | |
484 | * Decodes data when a payload is maybe expected. | |
485 | * | |
486 | * @param {String} data, callback method | |
487 | * @api public | |
488 | */ | |
489 | ||
490 | exports.decodePayload = function (data, callback) { | |
491 | var packet; | |
492 | if (data == '') { | |
493 | // parser error - ignoring payload | |
494 | return callback(err, 0, 1); | |
495 | } | |
496 | ||
497 | var length = '' | |
498 | , n, msg; | |
499 | ||
500 | for (var i = 0, l = data.length; i < l; i++) { | |
501 | var chr = data.charAt(i); | |
502 | ||
503 | if (':' != chr) { | |
504 | length += chr; | |
505 | } else { | |
506 | if ('' == length || (length != (n = Number(length)))) { | |
507 | // parser error - ignoring payload | |
508 | return callback(err, 0, 1); | |
509 | } | |
510 | ||
511 | msg = data.substr(i + 1, n); | |
512 | ||
513 | if (length != msg.length) { | |
514 | // parser error - ignoring payload | |
515 | return callback(err, 0, 1); | |
516 | } | |
517 | ||
518 | if (msg.length) { | |
519 | packet = exports.decodePacket(msg); | |
520 | ||
521 | if (err.type == packet.type && err.data == packet.data) { | |
522 | // parser error in individual packet - ignoring payload | |
523 | return callback(err, 0, 1); | |
524 | } | |
525 | ||
526 | var ret = callback(packet, i + n, l); | |
527 | if (false === ret) return; | |
528 | } | |
529 | ||
530 | // advance cursor | |
531 | i += n; | |
532 | length = ''; | |
533 | } | |
534 | } | |
535 | ||
536 | if (length != '') { | |
537 | // parser error - ignoring payload | |
538 | return callback(err, 0, 1); | |
539 | } | |
540 | ||
541 | }; | |
542 | ||
543 | }); | |
544 | require.register("LearnBoost-engine.io-protocol/lib/keys.js", function(exports, require, module){ | |
545 | ||
546 | /** | |
547 | * Gets the keys for an object. | |
548 | * | |
549 | * @return {Array} keys | |
550 | * @api private | |
551 | */ | |
552 | ||
553 | module.exports = Object.keys || function keys (obj){ | |
554 | var arr = []; | |
555 | var has = Object.prototype.hasOwnProperty; | |
556 | ||
557 | for (var i in obj) { | |
558 | if (has.call(obj, i)) { | |
559 | arr.push(i); | |
560 | } | |
561 | } | |
562 | return arr; | |
563 | }; | |
564 | ||
565 | }); | |
566 | require.register("visionmedia-debug/index.js", function(exports, require, module){ | |
567 | if ('undefined' == typeof window) { | |
568 | module.exports = require('./lib/debug'); | |
569 | } else { | |
570 | module.exports = require('./debug'); | |
571 | } | |
572 | ||
573 | }); | |
574 | require.register("visionmedia-debug/debug.js", function(exports, require, module){ | |
575 | ||
576 | /** | |
577 | * Expose `debug()` as the module. | |
578 | */ | |
579 | ||
580 | module.exports = debug; | |
581 | ||
582 | /** | |
583 | * Create a debugger with the given `name`. | |
584 | * | |
585 | * @param {String} name | |
586 | * @return {Type} | |
587 | * @api public | |
588 | */ | |
589 | ||
590 | function debug(name) { | |
591 | if (!debug.enabled(name)) return function(){}; | |
592 | ||
593 | return function(fmt){ | |
594 | fmt = coerce(fmt); | |
595 | ||
596 | var curr = new Date; | |
597 | var ms = curr - (debug[name] || curr); | |
598 | debug[name] = curr; | |
599 | ||
600 | fmt = name | |
601 | + ' ' | |
602 | + fmt | |
603 | + ' +' + debug.humanize(ms); | |
604 | ||
605 | // This hackery is required for IE8 | |
606 | // where `console.log` doesn't have 'apply' | |
607 | window.console | |
608 | && console.log | |
609 | && Function.prototype.apply.call(console.log, console, arguments); | |
610 | } | |
611 | } | |
612 | ||
613 | /** | |
614 | * The currently active debug mode names. | |
615 | */ | |
616 | ||
617 | debug.names = []; | |
618 | debug.skips = []; | |
619 | ||
620 | /** | |
621 | * Enables a debug mode by name. This can include modes | |
622 | * separated by a colon and wildcards. | |
623 | * | |
624 | * @param {String} name | |
625 | * @api public | |
626 | */ | |
627 | ||
628 | debug.enable = function(name) { | |
629 | try { | |
630 | localStorage.debug = name; | |
631 | } catch(e){} | |
632 | ||
633 | var split = (name || '').split(/[\s,]+/) | |
634 | , len = split.length; | |
635 | ||
636 | for (var i = 0; i < len; i++) { | |
637 | name = split[i].replace('*', '.*?'); | |
638 | if (name[0] === '-') { | |
639 | debug.skips.push(new RegExp('^' + name.substr(1) + '$')); | |
640 | } | |
641 | else { | |
642 | debug.names.push(new RegExp('^' + name + '$')); | |
643 | } | |
644 | } | |
645 | }; | |
646 | ||
647 | /** | |
648 | * Disable debug output. | |
649 | * | |
650 | * @api public | |
651 | */ | |
652 | ||
653 | debug.disable = function(){ | |
654 | debug.enable(''); | |
655 | }; | |
656 | ||
657 | /** | |
658 | * Humanize the given `ms`. | |
659 | * | |
660 | * @param {Number} m | |
661 | * @return {String} | |
662 | * @api private | |
663 | */ | |
664 | ||
665 | debug.humanize = function(ms) { | |
666 | var sec = 1000 | |
667 | , min = 60 * 1000 | |
668 | , hour = 60 * min; | |
669 | ||
670 | if (ms >= hour) return (ms / hour).toFixed(1) + 'h'; | |
671 | if (ms >= min) return (ms / min).toFixed(1) + 'm'; | |
672 | if (ms >= sec) return (ms / sec | 0) + 's'; | |
673 | return ms + 'ms'; | |
674 | }; | |
675 | ||
676 | /** | |
677 | * Returns true if the given mode name is enabled, false otherwise. | |
678 | * | |
679 | * @param {String} name | |
680 | * @return {Boolean} | |
681 | * @api public | |
682 | */ | |
683 | ||
684 | debug.enabled = function(name) { | |
685 | for (var i = 0, len = debug.skips.length; i < len; i++) { | |
686 | if (debug.skips[i].test(name)) { | |
687 | return false; | |
688 | } | |
689 | } | |
690 | for (var i = 0, len = debug.names.length; i < len; i++) { | |
691 | if (debug.names[i].test(name)) { | |
692 | return true; | |
693 | } | |
694 | } | |
695 | return false; | |
696 | }; | |
697 | ||
698 | /** | |
699 | * Coerce `val`. | |
700 | */ | |
701 | ||
702 | function coerce(val) { | |
703 | if (val instanceof Error) return val.stack || val.message; | |
704 | return val; | |
705 | } | |
706 | ||
707 | // persist | |
708 | ||
709 | if (window.localStorage) debug.enable(localStorage.debug); | |
710 | ||
711 | }); | |
712 | require.register("engine.io/lib/index.js", function(exports, require, module){ | |
713 | ||
714 | module.exports = require('./socket'); | |
715 | ||
716 | /** | |
717 | * Exports parser | |
718 | * | |
719 | * @api public | |
720 | * | |
721 | */ | |
722 | module.exports.parser = require('engine.io-parser'); | |
723 | ||
724 | }); | |
725 | require.register("engine.io/lib/socket.js", function(exports, require, module){ | |
726 | /** | |
727 | * Module dependencies. | |
728 | */ | |
729 | ||
730 | var util = require('./util') | |
731 | , transports = require('./transports') | |
732 | , Emitter = require('./emitter') | |
733 | , debug = require('debug')('engine-client:socket') | |
734 | , index = require('indexof') | |
735 | , parser = require('engine.io-parser'); | |
736 | ||
737 | /** | |
738 | * Module exports. | |
739 | */ | |
740 | ||
741 | module.exports = Socket; | |
742 | ||
743 | /** | |
744 | * Global reference. | |
745 | */ | |
746 | ||
747 | var global = util.global(); | |
748 | ||
749 | /** | |
750 | * Noop function. | |
751 | * | |
752 | * @api private | |
753 | */ | |
754 | ||
755 | function noop () {}; | |
756 | ||
757 | /** | |
758 | * Socket constructor. | |
759 | * | |
760 | * @param {String|Object} uri or options | |
761 | * @param {Object} options | |
762 | * @api public | |
763 | */ | |
764 | ||
765 | function Socket(uri, opts){ | |
766 | if (!(this instanceof Socket)) return new Socket(uri, opts); | |
767 | ||
768 | opts = opts || {}; | |
769 | ||
770 | if ('object' == typeof uri) { | |
771 | opts = uri; | |
772 | uri = null; | |
773 | } | |
774 | ||
775 | if (uri) { | |
776 | uri = util.parseUri(uri); | |
777 | opts.host = uri.host; | |
778 | opts.secure = uri.protocol == 'https' || uri.protocol == 'wss'; | |
779 | opts.port = uri.port; | |
780 | if (uri.query) opts.query = uri.query; | |
781 | } | |
782 | ||
783 | this.secure = null != opts.secure ? opts.secure : | |
784 | (global.location && 'https:' == location.protocol); | |
785 | ||
786 | if (opts.host) { | |
787 | var pieces = opts.host.split(':'); | |
788 | opts.hostname = pieces.shift(); | |
789 | if (pieces.length) opts.port = pieces.pop(); | |
790 | } | |
791 | ||
792 | this.hostname = opts.hostname || | |
793 | (global.location ? location.hostname : 'localhost'); | |
794 | this.port = opts.port || (global.location && location.port ? | |
795 | location.port : | |
796 | (this.secure ? 443 : 80)); | |
797 | this.query = opts.query || {}; | |
798 | if ('string' == typeof this.query) this.query = util.qsParse(this.query); | |
799 | this.upgrade = false !== opts.upgrade; | |
800 | this.path = (opts.path || '/engine.io').replace(/\/$/, '') + '/'; | |
801 | this.forceJSONP = !!opts.forceJSONP; | |
802 | this.timestampParam = opts.timestampParam || 't'; | |
803 | this.timestampRequests = !!opts.timestampRequests; | |
804 | this.flashPath = opts.flashPath || ''; | |
805 | this.transports = opts.transports || ['polling', 'websocket', 'flashsocket']; | |
806 | this.readyState = ''; | |
807 | this.writeBuffer = []; | |
808 | this.callbackBuffer = []; | |
809 | this.policyPort = opts.policyPort || 843; | |
810 | this.open(); | |
811 | ||
812 | Socket.sockets.push(this); | |
813 | Socket.sockets.evs.emit('add', this); | |
814 | }; | |
815 | ||
816 | /** | |
817 | * Mix in `Emitter`. | |
818 | */ | |
819 | ||
820 | Emitter(Socket.prototype); | |
821 | ||
822 | /** | |
823 | * Protocol version. | |
824 | * | |
825 | * @api public | |
826 | */ | |
827 | ||
828 | Socket.protocol = parser.protocol; // this is an int | |
829 | ||
830 | /** | |
831 | * Static EventEmitter. | |
832 | */ | |
833 | ||
834 | Socket.sockets = []; | |
835 | Socket.sockets.evs = new Emitter; | |
836 | ||
837 | /** | |
838 | * Expose deps for legacy compatibility | |
839 | * and standalone browser access. | |
840 | */ | |
841 | ||
842 | Socket.Socket = Socket; | |
843 | Socket.Transport = require('./transport'); | |
844 | Socket.Emitter = require('./emitter'); | |
845 | Socket.transports = require('./transports'); | |
846 | Socket.util = require('./util'); | |
847 | Socket.parser = require('engine.io-parser'); | |
848 | ||
849 | /** | |
850 | * Creates transport of the given type. | |
851 | * | |
852 | * @param {String} transport name | |
853 | * @return {Transport} | |
854 | * @api private | |
855 | */ | |
856 | ||
857 | Socket.prototype.createTransport = function (name) { | |
858 | debug('creating transport "%s"', name); | |
859 | var query = clone(this.query); | |
860 | ||
861 | // append engine.io protocol identifier | |
862 | query.EIO = parser.protocol; | |
863 | ||
864 | // transport name | |
865 | query.transport = name; | |
866 | ||
867 | // session id if we already have one | |
868 | if (this.id) query.sid = this.id; | |
869 | ||
870 | var transport = new transports[name]({ | |
871 | hostname: this.hostname, | |
872 | port: this.port, | |
873 | secure: this.secure, | |
874 | path: this.path, | |
875 | query: query, | |
876 | forceJSONP: this.forceJSONP, | |
877 | timestampRequests: this.timestampRequests, | |
878 | timestampParam: this.timestampParam, | |
879 | flashPath: this.flashPath, | |
880 | policyPort: this.policyPort | |
881 | }); | |
882 | ||
883 | return transport; | |
884 | }; | |
885 | ||
886 | function clone (obj) { | |
887 | var o = {}; | |
888 | for (var i in obj) { | |
889 | if (obj.hasOwnProperty(i)) { | |
890 | o[i] = obj[i]; | |
891 | } | |
892 | } | |
893 | return o; | |
894 | } | |
895 | ||
896 | /** | |
897 | * Initializes transport to use and starts probe. | |
898 | * | |
899 | * @api private | |
900 | */ | |
901 | ||
902 | Socket.prototype.open = function () { | |
903 | this.readyState = 'opening'; | |
904 | var transport = this.createTransport(this.transports[0]); | |
905 | transport.open(); | |
906 | this.setTransport(transport); | |
907 | }; | |
908 | ||
909 | /** | |
910 | * Sets the current transport. Disables the existing one (if any). | |
911 | * | |
912 | * @api private | |
913 | */ | |
914 | ||
915 | Socket.prototype.setTransport = function (transport) { | |
916 | var self = this; | |
917 | ||
918 | if (this.transport) { | |
919 | debug('clearing existing transport'); | |
920 | this.transport.removeAllListeners(); | |
921 | } | |
922 | ||
923 | // set up transport | |
924 | this.transport = transport; | |
925 | ||
926 | // set up transport listeners | |
927 | transport | |
928 | .on('drain', function () { | |
929 | self.onDrain(); | |
930 | }) | |
931 | .on('packet', function (packet) { | |
932 | self.onPacket(packet); | |
933 | }) | |
934 | .on('error', function (e) { | |
935 | self.onError(e); | |
936 | }) | |
937 | .on('close', function () { | |
938 | self.onClose('transport close'); | |
939 | }); | |
940 | }; | |
941 | ||
942 | /** | |
943 | * Probes a transport. | |
944 | * | |
945 | * @param {String} transport name | |
946 | * @api private | |
947 | */ | |
948 | ||
949 | Socket.prototype.probe = function (name) { | |
950 | debug('probing transport "%s"', name); | |
951 | var transport = this.createTransport(name, { probe: 1 }) | |
952 | , failed = false | |
953 | , self = this; | |
954 | ||
955 | transport.once('open', function () { | |
956 | if (failed) return; | |
957 | ||
958 | debug('probe transport "%s" opened', name); | |
959 | transport.send([{ type: 'ping', data: 'probe' }]); | |
960 | transport.once('packet', function (msg) { | |
961 | if (failed) return; | |
962 | if ('pong' == msg.type && 'probe' == msg.data) { | |
963 | debug('probe transport "%s" pong', name); | |
964 | self.upgrading = true; | |
965 | self.emit('upgrading', transport); | |
966 | ||
967 | debug('pausing current transport "%s"', self.transport.name); | |
968 | self.transport.pause(function () { | |
969 | if (failed) return; | |
970 | if ('closed' == self.readyState || 'closing' == self.readyState) { | |
971 | return; | |
972 | } | |
973 | debug('changing transport and sending upgrade packet'); | |
974 | transport.removeListener('error', onerror); | |
975 | self.emit('upgrade', transport); | |
976 | self.setTransport(transport); | |
977 | transport.send([{ type: 'upgrade' }]); | |
978 | transport = null; | |
979 | self.upgrading = false; | |
980 | self.flush(); | |
981 | }); | |
982 | } else { | |
983 | debug('probe transport "%s" failed', name); | |
984 | var err = new Error('probe error'); | |
985 | err.transport = transport.name; | |
986 | self.emit('error', err); | |
987 | } | |
988 | }); | |
989 | }); | |
990 | ||
991 | transport.once('error', onerror); | |
992 | function onerror(err) { | |
993 | if (failed) return; | |
994 | ||
995 | // Any callback called by transport should be ignored since now | |
996 | failed = true; | |
997 | ||
998 | var error = new Error('probe error: ' + err); | |
999 | error.transport = transport.name; | |
1000 | ||
1001 | transport.close(); | |
1002 | transport = null; | |
1003 | ||
1004 | debug('probe transport "%s" failed because of error: %s', name, err); | |
1005 | ||
1006 | self.emit('error', error); | |
1007 | }; | |
1008 | ||
1009 | transport.open(); | |
1010 | ||
1011 | this.once('close', function () { | |
1012 | if (transport) { | |
1013 | debug('socket closed prematurely - aborting probe'); | |
1014 | failed = true; | |
1015 | transport.close(); | |
1016 | transport = null; | |
1017 | } | |
1018 | }); | |
1019 | ||
1020 | this.once('upgrading', function (to) { | |
1021 | if (transport && to.name != transport.name) { | |
1022 | debug('"%s" works - aborting "%s"', to.name, transport.name); | |
1023 | transport.close(); | |
1024 | transport = null; | |
1025 | } | |
1026 | }); | |
1027 | }; | |
1028 | ||
1029 | /** | |
1030 | * Called when connection is deemed open. | |
1031 | * | |
1032 | * @api public | |
1033 | */ | |
1034 | ||
1035 | Socket.prototype.onOpen = function () { | |
1036 | debug('socket open'); | |
1037 | this.readyState = 'open'; | |
1038 | this.emit('open'); | |
1039 | this.onopen && this.onopen.call(this); | |
1040 | this.flush(); | |
1041 | ||
1042 | // we check for `readyState` in case an `open` | |
1043 | // listener alreay closed the socket | |
1044 | if ('open' == this.readyState && this.upgrade && this.transport.pause) { | |
1045 | debug('starting upgrade probes'); | |
1046 | for (var i = 0, l = this.upgrades.length; i < l; i++) { | |
1047 | this.probe(this.upgrades[i]); | |
1048 | } | |
1049 | } | |
1050 | }; | |
1051 | ||
1052 | /** | |
1053 | * Handles a packet. | |
1054 | * | |
1055 | * @api private | |
1056 | */ | |
1057 | ||
1058 | Socket.prototype.onPacket = function (packet) { | |
1059 | if ('opening' == this.readyState || 'open' == this.readyState) { | |
1060 | debug('socket receive: type "%s", data "%s"', packet.type, packet.data); | |
1061 | ||
1062 | this.emit('packet', packet); | |
1063 | ||
1064 | // Socket is live - any packet counts | |
1065 | this.emit('heartbeat'); | |
1066 | ||
1067 | switch (packet.type) { | |
1068 | case 'open': | |
1069 | this.onHandshake(util.parseJSON(packet.data)); | |
1070 | break; | |
1071 | ||
1072 | case 'pong': | |
1073 | this.setPing(); | |
1074 | break; | |
1075 | ||
1076 | case 'error': | |
1077 | var err = new Error('server error'); | |
1078 | err.code = packet.data; | |
1079 | this.emit('error', err); | |
1080 | break; | |
1081 | ||
1082 | case 'message': | |
1083 | this.emit('data', packet.data); | |
1084 | this.emit('message', packet.data); | |
1085 | var event = { data: packet.data }; | |
1086 | event.toString = function () { | |
1087 | return packet.data; | |
1088 | }; | |
1089 | this.onmessage && this.onmessage.call(this, event); | |
1090 | break; | |
1091 | } | |
1092 | } else { | |
1093 | debug('packet received with socket readyState "%s"', this.readyState); | |
1094 | } | |
1095 | }; | |
1096 | ||
1097 | /** | |
1098 | * Called upon handshake completion. | |
1099 | * | |
1100 | * @param {Object} handshake obj | |
1101 | * @api private | |
1102 | */ | |
1103 | ||
1104 | Socket.prototype.onHandshake = function (data) { | |
1105 | this.emit('handshake', data); | |
1106 | this.id = data.sid; | |
1107 | this.transport.query.sid = data.sid; | |
1108 | this.upgrades = this.filterUpgrades(data.upgrades); | |
1109 | this.pingInterval = data.pingInterval; | |
1110 | this.pingTimeout = data.pingTimeout; | |
1111 | this.onOpen(); | |
1112 | this.setPing(); | |
1113 | ||
1114 | // Prolong liveness of socket on heartbeat | |
1115 | this.removeListener('heartbeat', this.onHeartbeat); | |
1116 | this.on('heartbeat', this.onHeartbeat); | |
1117 | }; | |
1118 | ||
1119 | /** | |
1120 | * Resets ping timeout. | |
1121 | * | |
1122 | * @api private | |
1123 | */ | |
1124 | ||
1125 | Socket.prototype.onHeartbeat = function (timeout) { | |
1126 | clearTimeout(this.pingTimeoutTimer); | |
1127 | var self = this; | |
1128 | self.pingTimeoutTimer = setTimeout(function () { | |
1129 | if ('closed' == self.readyState) return; | |
1130 | self.onClose('ping timeout'); | |
1131 | }, timeout || (self.pingInterval + self.pingTimeout)); | |
1132 | }; | |
1133 | ||
1134 | /** | |
1135 | * Pings server every `this.pingInterval` and expects response | |
1136 | * within `this.pingTimeout` or closes connection. | |
1137 | * | |
1138 | * @api private | |
1139 | */ | |
1140 | ||
1141 | Socket.prototype.setPing = function () { | |
1142 | var self = this; | |
1143 | clearTimeout(self.pingIntervalTimer); | |
1144 | self.pingIntervalTimer = setTimeout(function () { | |
1145 | debug('writing ping packet - expecting pong within %sms', self.pingTimeout); | |
1146 | self.ping(); | |
1147 | self.onHeartbeat(self.pingTimeout); | |
1148 | }, self.pingInterval); | |
1149 | }; | |
1150 | ||
1151 | /** | |
1152 | * Sends a ping packet. | |
1153 | * | |
1154 | * @api public | |
1155 | */ | |
1156 | ||
1157 | Socket.prototype.ping = function () { | |
1158 | this.sendPacket('ping'); | |
1159 | }; | |
1160 | ||
1161 | /** | |
1162 | * Called on `drain` event | |
1163 | * | |
1164 | * @api private | |
1165 | */ | |
1166 | ||
1167 | Socket.prototype.onDrain = function() { | |
1168 | for (var i = 0; i < this.prevBufferLen; i++) { | |
1169 | if (this.callbackBuffer[i]) { | |
1170 | this.callbackBuffer[i](); | |
1171 | } | |
1172 | } | |
1173 | ||
1174 | this.writeBuffer.splice(0, this.prevBufferLen); | |
1175 | this.callbackBuffer.splice(0, this.prevBufferLen); | |
1176 | ||
1177 | // setting prevBufferLen = 0 is very important | |
1178 | // for example, when upgrading, upgrade packet is sent over, | |
1179 | // and a nonzero prevBufferLen could cause problems on `drain` | |
1180 | this.prevBufferLen = 0; | |
1181 | ||
1182 | if (this.writeBuffer.length == 0) { | |
1183 | this.emit('drain'); | |
1184 | } else { | |
1185 | this.flush(); | |
1186 | } | |
1187 | }; | |
1188 | ||
1189 | /** | |
1190 | * Flush write buffers. | |
1191 | * | |
1192 | * @api private | |
1193 | */ | |
1194 | ||
1195 | Socket.prototype.flush = function () { | |
1196 | if ('closed' != this.readyState && this.transport.writable && | |
1197 | !this.upgrading && this.writeBuffer.length) { | |
1198 | debug('flushing %d packets in socket', this.writeBuffer.length); | |
1199 | this.transport.send(this.writeBuffer); | |
1200 | // keep track of current length of writeBuffer | |
1201 | // splice writeBuffer and callbackBuffer on `drain` | |
1202 | this.prevBufferLen = this.writeBuffer.length; | |
1203 | this.emit('flush'); | |
1204 | } | |
1205 | }; | |
1206 | ||
1207 | /** | |
1208 | * Sends a message. | |
1209 | * | |
1210 | * @param {String} message. | |
1211 | * @param {Function} callback function. | |
1212 | * @return {Socket} for chaining. | |
1213 | * @api public | |
1214 | */ | |
1215 | ||
1216 | Socket.prototype.write = | |
1217 | Socket.prototype.send = function (msg, fn) { | |
1218 | this.sendPacket('message', msg, fn); | |
1219 | return this; | |
1220 | }; | |
1221 | ||
1222 | /** | |
1223 | * Sends a packet. | |
1224 | * | |
1225 | * @param {String} packet type. | |
1226 | * @param {String} data. | |
1227 | * @param {Function} callback function. | |
1228 | * @api private | |
1229 | */ | |
1230 | ||
1231 | Socket.prototype.sendPacket = function (type, data, fn) { | |
1232 | var packet = { type: type, data: data }; | |
1233 | this.emit('packetCreate', packet); | |
1234 | this.writeBuffer.push(packet); | |
1235 | this.callbackBuffer.push(fn); | |
1236 | this.flush(); | |
1237 | }; | |
1238 | ||
1239 | /** | |
1240 | * Closes the connection. | |
1241 | * | |
1242 | * @api private | |
1243 | */ | |
1244 | ||
1245 | Socket.prototype.close = function () { | |
1246 | if ('opening' == this.readyState || 'open' == this.readyState) { | |
1247 | this.onClose('forced close'); | |
1248 | debug('socket closing - telling transport to close'); | |
1249 | this.transport.close(); | |
1250 | } | |
1251 | ||
1252 | return this; | |
1253 | }; | |
1254 | ||
1255 | /** | |
1256 | * Called upon transport error | |
1257 | * | |
1258 | * @api private | |
1259 | */ | |
1260 | ||
1261 | Socket.prototype.onError = function (err) { | |
1262 | debug('socket error %j', err); | |
1263 | this.emit('error', err); | |
1264 | this.onerror && this.onerror.call(this, err); | |
1265 | this.onClose('transport error', err); | |
1266 | }; | |
1267 | ||
1268 | /** | |
1269 | * Called upon transport close. | |
1270 | * | |
1271 | * @api private | |
1272 | */ | |
1273 | ||
1274 | Socket.prototype.onClose = function (reason, desc) { | |
1275 | if ('opening' == this.readyState || 'open' == this.readyState) { | |
1276 | debug('socket close with reason: "%s"', reason); | |
1277 | var self = this; | |
1278 | ||
1279 | // clear timers | |
1280 | clearTimeout(this.pingIntervalTimer); | |
1281 | clearTimeout(this.pingTimeoutTimer); | |
1282 | ||
1283 | // clean buffers in next tick, so developers can still | |
1284 | // grab the buffers on `close` event | |
1285 | setTimeout(function() { | |
1286 | self.writeBuffer = []; | |
1287 | self.callbackBuffer = []; | |
1288 | }, 0); | |
1289 | ||
1290 | // ignore further transport communication | |
1291 | this.transport.removeAllListeners(); | |
1292 | ||
1293 | // set ready state | |
1294 | var prev = this.readyState; | |
1295 | this.readyState = 'closed'; | |
1296 | ||
1297 | // clear session id | |
1298 | this.id = null; | |
1299 | ||
1300 | // emit events | |
1301 | if (prev == 'open') { | |
1302 | this.emit('close', reason, desc); | |
1303 | this.onclose && this.onclose.call(this); | |
1304 | } | |
1305 | } | |
1306 | }; | |
1307 | ||
1308 | /** | |
1309 | * Filters upgrades, returning only those matching client transports. | |
1310 | * | |
1311 | * @param {Array} server upgrades | |
1312 | * @api private | |
1313 | * | |
1314 | */ | |
1315 | ||
1316 | Socket.prototype.filterUpgrades = function (upgrades) { | |
1317 | var filteredUpgrades = []; | |
1318 | for (var i = 0, j = upgrades.length; i<j; i++) { | |
1319 | if (~index(this.transports, upgrades[i])) filteredUpgrades.push(upgrades[i]); | |
1320 | } | |
1321 | return filteredUpgrades; | |
1322 | }; | |
1323 | ||
1324 | }); | |
1325 | require.register("engine.io/lib/transport.js", function(exports, require, module){ | |
1326 | ||
1327 | /** | |
1328 | * Module dependencies. | |
1329 | */ | |
1330 | ||
1331 | var util = require('./util') | |
1332 | , parser = require('engine.io-parser') | |
1333 | , Emitter = require('./emitter'); | |
1334 | ||
1335 | /** | |
1336 | * Module exports. | |
1337 | */ | |
1338 | ||
1339 | module.exports = Transport; | |
1340 | ||
1341 | /** | |
1342 | * Transport abstract constructor. | |
1343 | * | |
1344 | * @param {Object} options. | |
1345 | * @api private | |
1346 | */ | |
1347 | ||
1348 | function Transport (opts) { | |
1349 | this.path = opts.path; | |
1350 | this.hostname = opts.hostname; | |
1351 | this.port = opts.port; | |
1352 | this.secure = opts.secure; | |
1353 | this.query = opts.query; | |
1354 | this.timestampParam = opts.timestampParam; | |
1355 | this.timestampRequests = opts.timestampRequests; | |
1356 | this.readyState = ''; | |
1357 | }; | |
1358 | ||
1359 | /** | |
1360 | * Mix in `Emitter`. | |
1361 | */ | |
1362 | ||
1363 | Emitter(Transport.prototype); | |
1364 | ||
1365 | /** | |
1366 | * Emits an error. | |
1367 | * | |
1368 | * @param {String} str | |
1369 | * @return {Transport} for chaining | |
1370 | * @api public | |
1371 | */ | |
1372 | ||
1373 | Transport.prototype.onError = function (msg, desc) { | |
1374 | var err = new Error(msg); | |
1375 | err.type = 'TransportError'; | |
1376 | err.description = desc; | |
1377 | this.emit('error', err); | |
1378 | return this; | |
1379 | }; | |
1380 | ||
1381 | /** | |
1382 | * Opens the transport. | |
1383 | * | |
1384 | * @api public | |
1385 | */ | |
1386 | ||
1387 | Transport.prototype.open = function () { | |
1388 | if ('closed' == this.readyState || '' == this.readyState) { | |
1389 | this.readyState = 'opening'; | |
1390 | this.doOpen(); | |
1391 | } | |
1392 | ||
1393 | return this; | |
1394 | }; | |
1395 | ||
1396 | /** | |
1397 | * Closes the transport. | |
1398 | * | |
1399 | * @api private | |
1400 | */ | |
1401 | ||
1402 | Transport.prototype.close = function () { | |
1403 | if ('opening' == this.readyState || 'open' == this.readyState) { | |
1404 | this.doClose(); | |
1405 | this.onClose(); | |
1406 | } | |
1407 | ||
1408 | return this; | |
1409 | }; | |
1410 | ||
1411 | /** | |
1412 | * Sends multiple packets. | |
1413 | * | |
1414 | * @param {Array} packets | |
1415 | * @api private | |
1416 | */ | |
1417 | ||
1418 | Transport.prototype.send = function(packets){ | |
1419 | if ('open' == this.readyState) { | |
1420 | this.write(packets); | |
1421 | } else { | |
1422 | throw new Error('Transport not open'); | |
1423 | } | |
1424 | }; | |
1425 | ||
1426 | /** | |
1427 | * Called upon open | |
1428 | * | |
1429 | * @api private | |
1430 | */ | |
1431 | ||
1432 | Transport.prototype.onOpen = function () { | |
1433 | this.readyState = 'open'; | |
1434 | this.writable = true; | |
1435 | this.emit('open'); | |
1436 | }; | |
1437 | ||
1438 | /** | |
1439 | * Called with data. | |
1440 | * | |
1441 | * @param {String} data | |
1442 | * @api private | |
1443 | */ | |
1444 | ||
1445 | Transport.prototype.onData = function (data) { | |
1446 | this.onPacket(parser.decodePacket(data)); | |
1447 | }; | |
1448 | ||
1449 | /** | |
1450 | * Called with a decoded packet. | |
1451 | */ | |
1452 | ||
1453 | Transport.prototype.onPacket = function (packet) { | |
1454 | this.emit('packet', packet); | |
1455 | }; | |
1456 | ||
1457 | /** | |
1458 | * Called upon close. | |
1459 | * | |
1460 | * @api private | |
1461 | */ | |
1462 | ||
1463 | Transport.prototype.onClose = function () { | |
1464 | this.readyState = 'closed'; | |
1465 | this.emit('close'); | |
1466 | }; | |
1467 | ||
1468 | }); | |
1469 | require.register("engine.io/lib/emitter.js", function(exports, require, module){ | |
1470 | ||
1471 | /** | |
1472 | * Module dependencies. | |
1473 | */ | |
1474 | ||
1475 | var Emitter = require('emitter'); | |
1476 | ||
1477 | /** | |
1478 | * Module exports. | |
1479 | */ | |
1480 | ||
1481 | module.exports = Emitter; | |
1482 | ||
1483 | /** | |
1484 | * Compatibility with `WebSocket#addEventListener`. | |
1485 | * | |
1486 | * @api public | |
1487 | */ | |
1488 | ||
1489 | Emitter.prototype.addEventListener = Emitter.prototype.on; | |
1490 | ||
1491 | /** | |
1492 | * Compatibility with `WebSocket#removeEventListener`. | |
1493 | * | |
1494 | * @api public | |
1495 | */ | |
1496 | ||
1497 | Emitter.prototype.removeEventListener = Emitter.prototype.off; | |
1498 | ||
1499 | /** | |
1500 | * Node-compatible `EventEmitter#removeListener` | |
1501 | * | |
1502 | * @api public | |
1503 | */ | |
1504 | ||
1505 | Emitter.prototype.removeListener = Emitter.prototype.off; | |
1506 | ||
1507 | }); | |
1508 | require.register("engine.io/lib/util.js", function(exports, require, module){ | |
1509 | /** | |
1510 | * Status of page load. | |
1511 | */ | |
1512 | ||
1513 | var pageLoaded = false; | |
1514 | ||
1515 | /** | |
1516 | * Returns the global object | |
1517 | * | |
1518 | * @api private | |
1519 | */ | |
1520 | ||
1521 | exports.global = function () { | |
1522 | return 'undefined' != typeof window ? window : global; | |
1523 | }; | |
1524 | ||
1525 | /** | |
1526 | * Inheritance. | |
1527 | * | |
1528 | * @param {Function} ctor a | |
1529 | * @param {Function} ctor b | |
1530 | * @api private | |
1531 | */ | |
1532 | ||
1533 | exports.inherits = function inherits (a, b) { | |
1534 | function c () { } | |
1535 | c.prototype = b.prototype; | |
1536 | a.prototype = new c; | |
1537 | }; | |
1538 | ||
1539 | /** | |
1540 | * Object.keys | |
1541 | */ | |
1542 | ||
1543 | exports.keys = Object.keys || function (obj) { | |
1544 | var ret = []; | |
1545 | var has = Object.prototype.hasOwnProperty; | |
1546 | ||
1547 | for (var i in obj) { | |
1548 | if (has.call(obj, i)) { | |
1549 | ret.push(i); | |
1550 | } | |
1551 | } | |
1552 | ||
1553 | return ret; | |
1554 | }; | |
1555 | ||
1556 | /** | |
1557 | * Adds an event. | |
1558 | * | |
1559 | * @api private | |
1560 | */ | |
1561 | ||
1562 | exports.on = function (element, event, fn, capture) { | |
1563 | if (element.attachEvent) { | |
1564 | element.attachEvent('on' + event, fn); | |
1565 | } else if (element.addEventListener) { | |
1566 | element.addEventListener(event, fn, capture); | |
1567 | } | |
1568 | }; | |
1569 | ||
1570 | /** | |
1571 | * Load utility. | |
1572 | * | |
1573 | * @api private | |
1574 | */ | |
1575 | ||
1576 | exports.load = function (fn) { | |
1577 | var global = exports.global(); | |
1578 | if (global.document && document.readyState === 'complete' || pageLoaded) { | |
1579 | return fn(); | |
1580 | } | |
1581 | ||
1582 | exports.on(global, 'load', fn, false); | |
1583 | }; | |
1584 | ||
1585 | /** | |
1586 | * Change the internal pageLoaded value. | |
1587 | */ | |
1588 | ||
1589 | if ('undefined' != typeof window) { | |
1590 | exports.load(function () { | |
1591 | pageLoaded = true; | |
1592 | }); | |
1593 | } | |
1594 | ||
1595 | /** | |
1596 | * Defers a function to ensure a spinner is not displayed by the browser. | |
1597 | * | |
1598 | * @param {Function} fn | |
1599 | * @api private | |
1600 | */ | |
1601 | ||
1602 | exports.defer = function (fn) { | |
1603 | if (!exports.ua.webkit || 'undefined' != typeof importScripts) { | |
1604 | return fn(); | |
1605 | } | |
1606 | ||
1607 | exports.load(function () { | |
1608 | setTimeout(fn, 100); | |
1609 | }); | |
1610 | }; | |
1611 | ||
1612 | /** | |
1613 | * JSON parse. | |
1614 | * | |
1615 | * @see Based on jQuery#parseJSON (MIT) and JSON2 | |
1616 | * @api private | |
1617 | */ | |
1618 | ||
1619 | var rvalidchars = /^[\],:{}\s]*$/; | |
1620 | var rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g; | |
1621 | var rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g; | |
1622 | var rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g; | |
1623 | var rtrimLeft = /^\s+/; | |
1624 | var rtrimRight = /\s+$/; | |
1625 | ||
1626 | exports.parseJSON = function (data) { | |
1627 | var global = exports.global(); | |
1628 | ||
1629 | if ('string' != typeof data || !data) { | |
1630 | return null; | |
1631 | } | |
1632 | ||
1633 | data = data.replace(rtrimLeft, '').replace(rtrimRight, ''); | |
1634 | ||
1635 | // Attempt to parse using the native JSON parser first | |
1636 | if (global.JSON && JSON.parse) { | |
1637 | return JSON.parse(data); | |
1638 | } | |
1639 | ||
1640 | if (rvalidchars.test(data.replace(rvalidescape, '@') | |
1641 | .replace(rvalidtokens, ']') | |
1642 | .replace(rvalidbraces, ''))) { | |
1643 | return (new Function('return ' + data))(); | |
1644 | } | |
1645 | }; | |
1646 | ||
1647 | /** | |
1648 | * UA / engines detection namespace. | |
1649 | * | |
1650 | * @namespace | |
1651 | */ | |
1652 | ||
1653 | exports.ua = {}; | |
1654 | ||
1655 | /** | |
1656 | * Whether the UA supports CORS for XHR. | |
1657 | * | |
1658 | * @api private | |
1659 | */ | |
1660 | ||
1661 | exports.ua.hasCORS = 'undefined' != typeof XMLHttpRequest && (function () { | |
1662 | var a; | |
1663 | try { | |
1664 | a = new XMLHttpRequest(); | |
1665 | } catch (e) { | |
1666 | return false; | |
1667 | } | |
1668 | ||
1669 | return a.withCredentials != undefined; | |
1670 | })(); | |
1671 | ||
1672 | /** | |
1673 | * Detect webkit. | |
1674 | * | |
1675 | * @api private | |
1676 | */ | |
1677 | ||
1678 | exports.ua.webkit = 'undefined' != typeof navigator && | |
1679 | /webkit/i.test(navigator.userAgent); | |
1680 | ||
1681 | /** | |
1682 | * Detect gecko. | |
1683 | * | |
1684 | * @api private | |
1685 | */ | |
1686 | ||
1687 | exports.ua.gecko = 'undefined' != typeof navigator && | |
1688 | /gecko/i.test(navigator.userAgent); | |
1689 | ||
1690 | /** | |
1691 | * Detect android; | |
1692 | */ | |
1693 | ||
1694 | exports.ua.android = 'undefined' != typeof navigator && | |
1695 | /android/i.test(navigator.userAgent); | |
1696 | ||
1697 | /** | |
1698 | * Detect iOS. | |
1699 | */ | |
1700 | ||
1701 | exports.ua.ios = 'undefined' != typeof navigator && | |
1702 | /^(iPad|iPhone|iPod)$/.test(navigator.platform); | |
1703 | exports.ua.ios6 = exports.ua.ios && /OS 6_/.test(navigator.userAgent); | |
1704 | ||
1705 | /** | |
1706 | * XHR request helper. | |
1707 | * | |
1708 | * @param {Boolean} whether we need xdomain | |
1709 | * @api private | |
1710 | */ | |
1711 | ||
1712 | exports.request = function request (xdomain) { | |
1713 | try { | |
1714 | var _XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest; | |
1715 | return new _XMLHttpRequest(); | |
1716 | } catch (e) {} | |
1717 | ||
1718 | if (xdomain && 'undefined' != typeof XDomainRequest && !exports.ua.hasCORS) { | |
1719 | return new XDomainRequest(); | |
1720 | } | |
1721 | ||
1722 | // XMLHttpRequest can be disabled on IE | |
1723 | try { | |
1724 | if ('undefined' != typeof XMLHttpRequest && (!xdomain || exports.ua.hasCORS)) { | |
1725 | return new XMLHttpRequest(); | |
1726 | } | |
1727 | } catch (e) { } | |
1728 | ||
1729 | if (!xdomain) { | |
1730 | try { | |
1731 | return new ActiveXObject('Microsoft.XMLHTTP'); | |
1732 | } catch(e) { } | |
1733 | } | |
1734 | }; | |
1735 | ||
1736 | /** | |
1737 | * Parses an URI | |
1738 | * | |
1739 | * @author Steven Levithan <stevenlevithan.com> (MIT license) | |
1740 | * @api private | |
1741 | */ | |
1742 | ||
1743 | var re = /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/; | |
1744 | ||
1745 | var parts = [ | |
1746 | 'source', 'protocol', 'authority', 'userInfo', 'user', 'password', 'host' | |
1747 | , 'port', 'relative', 'path', 'directory', 'file', 'query', 'anchor' | |
1748 | ]; | |
1749 | ||
1750 | exports.parseUri = function (str) { | |
1751 | var m = re.exec(str || '') | |
1752 | , uri = {} | |
1753 | , i = 14; | |
1754 | ||
1755 | while (i--) { | |
1756 | uri[parts[i]] = m[i] || ''; | |
1757 | } | |
1758 | ||
1759 | return uri; | |
1760 | }; | |
1761 | ||
1762 | /** | |
1763 | * Compiles a querystring | |
1764 | * | |
1765 | * @param {Object} | |
1766 | * @api private | |
1767 | */ | |
1768 | ||
1769 | exports.qs = function (obj) { | |
1770 | var str = ''; | |
1771 | ||
1772 | for (var i in obj) { | |
1773 | if (obj.hasOwnProperty(i)) { | |
1774 | if (str.length) str += '&'; | |
1775 | str += encodeURIComponent(i) + '=' + encodeURIComponent(obj[i]); | |
1776 | } | |
1777 | } | |
1778 | ||
1779 | return str; | |
1780 | }; | |
1781 | ||
1782 | /** | |
1783 | * Parses a simple querystring. | |
1784 | * | |
1785 | * @param {String} qs | |
1786 | * @api private | |
1787 | */ | |
1788 | ||
1789 | exports.qsParse = function(qs){ | |
1790 | var qry = {}; | |
1791 | var pairs = qs.split('&'); | |
1792 | for (var i = 0, l = pairs.length; i < l; i++) { | |
1793 | var pair = pairs[i].split('='); | |
1794 | qry[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1]); | |
1795 | } | |
1796 | return qry; | |
1797 | }; | |
1798 | ||
1799 | }); | |
1800 | require.register("engine.io/lib/transports/index.js", function(exports, require, module){ | |
1801 | ||
1802 | /** | |
1803 | * Module dependencies | |
1804 | */ | |
1805 | ||
1806 | var XHR = require('./polling-xhr') | |
1807 | , JSONP = require('./polling-jsonp') | |
1808 | , websocket = require('./websocket') | |
1809 | , flashsocket = require('./flashsocket') | |
1810 | , util = require('../util'); | |
1811 | ||
1812 | /** | |
1813 | * Export transports. | |
1814 | */ | |
1815 | ||
1816 | exports.polling = polling; | |
1817 | exports.websocket = websocket; | |
1818 | exports.flashsocket = flashsocket; | |
1819 | ||
1820 | /** | |
1821 | * Global reference. | |
1822 | */ | |
1823 | ||
1824 | var global = util.global() | |
1825 | ||
1826 | /** | |
1827 | * Polling transport polymorphic constructor. | |
1828 | * Decides on xhr vs jsonp based on feature detection. | |
1829 | * | |
1830 | * @api private | |
1831 | */ | |
1832 | ||
1833 | function polling (opts) { | |
1834 | var xhr | |
1835 | , xd = false | |
1836 | , isXProtocol = false; | |
1837 | ||
1838 | if (global.location) { | |
1839 | var isSSL = 'https:' == location.protocol; | |
1840 | var port = location.port; | |
1841 | ||
1842 | // some user agents have empty `location.port` | |
1843 | if (Number(port) !== port) { | |
1844 | port = isSSL ? 443 : 80; | |
1845 | } | |
1846 | ||
1847 | xd = opts.hostname != location.hostname || port != opts.port; | |
1848 | isXProtocol = opts.secure != isSSL; | |
1849 | } | |
1850 | ||
1851 | xhr = util.request(xd); | |
1852 | /* See #7 at http://blogs.msdn.com/b/ieinternals/archive/2010/05/13/xdomainrequest-restrictions-limitations-and-workarounds.aspx */ | |
1853 | if (isXProtocol && global.XDomainRequest && xhr instanceof global.XDomainRequest) { | |
1854 | return new JSONP(opts); | |
1855 | } | |
1856 | ||
1857 | if (xhr && !opts.forceJSONP) { | |
1858 | return new XHR(opts); | |
1859 | } else { | |
1860 | return new JSONP(opts); | |
1861 | } | |
1862 | }; | |
1863 | ||
1864 | }); | |
1865 | require.register("engine.io/lib/transports/polling.js", function(exports, require, module){ | |
1866 | /** | |
1867 | * Module dependencies. | |
1868 | */ | |
1869 | ||
1870 | var Transport = require('../transport') | |
1871 | , util = require('../util') | |
1872 | , parser = require('engine.io-parser') | |
1873 | , debug = require('debug')('engine.io-client:polling'); | |
1874 | ||
1875 | /** | |
1876 | * Module exports. | |
1877 | */ | |
1878 | ||
1879 | module.exports = Polling; | |
1880 | ||
1881 | /** | |
1882 | * Global reference. | |
1883 | */ | |
1884 | ||
1885 | var global = util.global(); | |
1886 | ||
1887 | /** | |
1888 | * Polling interface. | |
1889 | * | |
1890 | * @param {Object} opts | |
1891 | * @api private | |
1892 | */ | |
1893 | ||
1894 | function Polling(opts){ | |
1895 | Transport.call(this, opts); | |
1896 | } | |
1897 | ||
1898 | /** | |
1899 | * Inherits from Transport. | |
1900 | */ | |
1901 | ||
1902 | util.inherits(Polling, Transport); | |
1903 | ||
1904 | /** | |
1905 | * Transport name. | |
1906 | */ | |
1907 | ||
1908 | Polling.prototype.name = 'polling'; | |
1909 | ||
1910 | /** | |
1911 | * Opens the socket (triggers polling). We write a PING message to determine | |
1912 | * when the transport is open. | |
1913 | * | |
1914 | * @api private | |
1915 | */ | |
1916 | ||
1917 | Polling.prototype.doOpen = function(){ | |
1918 | this.poll(); | |
1919 | }; | |
1920 | ||
1921 | /** | |
1922 | * Pauses polling. | |
1923 | * | |
1924 | * @param {Function} callback upon buffers are flushed and transport is paused | |
1925 | * @api private | |
1926 | */ | |
1927 | ||
1928 | Polling.prototype.pause = function(onPause){ | |
1929 | var pending = 0; | |
1930 | var self = this; | |
1931 | ||
1932 | this.readyState = 'pausing'; | |
1933 | ||
1934 | function pause(){ | |
1935 | debug('paused'); | |
1936 | self.readyState = 'paused'; | |
1937 | onPause(); | |
1938 | } | |
1939 | ||
1940 | if (this.polling || !this.writable) { | |
1941 | var total = 0; | |
1942 | ||
1943 | if (this.polling) { | |
1944 | debug('we are currently polling - waiting to pause'); | |
1945 | total++; | |
1946 | this.once('pollComplete', function(){ | |
1947 | debug('pre-pause polling complete'); | |
1948 | --total || pause(); | |
1949 | }); | |
1950 | } | |
1951 | ||
1952 | if (!this.writable) { | |
1953 | debug('we are currently writing - waiting to pause'); | |
1954 | total++; | |
1955 | this.once('drain', function(){ | |
1956 | debug('pre-pause writing complete'); | |
1957 | --total || pause(); | |
1958 | }); | |
1959 | } | |
1960 | } else { | |
1961 | pause(); | |
1962 | } | |
1963 | }; | |
1964 | ||
1965 | /** | |
1966 | * Starts polling cycle. | |
1967 | * | |
1968 | * @api public | |
1969 | */ | |
1970 | ||
1971 | Polling.prototype.poll = function(){ | |
1972 | debug('polling'); | |
1973 | this.polling = true; | |
1974 | this.doPoll(); | |
1975 | this.emit('poll'); | |
1976 | }; | |
1977 | ||
1978 | /** | |
1979 | * Overloads onData to detect payloads. | |
1980 | * | |
1981 | * @api private | |
1982 | */ | |
1983 | ||
1984 | Polling.prototype.onData = function(data){ | |
1985 | var self = this; | |
1986 | debug('polling got data %s', data); | |
1987 | ||
1988 | // decode payload | |
1989 | parser.decodePayload(data, function(packet, index, total) { | |
1990 | // if its the first message we consider the transport open | |
1991 | if ('opening' == self.readyState) { | |
1992 | self.onOpen(); | |
1993 | } | |
1994 | ||
1995 | // if its a close packet, we close the ongoing requests | |
1996 | if ('close' == packet.type) { | |
1997 | self.onClose(); | |
1998 | return false; | |
1999 | } | |
2000 | ||
2001 | // otherwise bypass onData and handle the message | |
2002 | self.onPacket(packet); | |
2003 | }); | |
2004 | ||
2005 | // if an event did not trigger closing | |
2006 | if ('closed' != this.readyState) { | |
2007 | // if we got data we're not polling | |
2008 | this.polling = false; | |
2009 | this.emit('pollComplete'); | |
2010 | ||
2011 | if ('open' == this.readyState) { | |
2012 | this.poll(); | |
2013 | } else { | |
2014 | debug('ignoring poll - transport state "%s"', this.readyState); | |
2015 | } | |
2016 | } | |
2017 | }; | |
2018 | ||
2019 | /** | |
2020 | * For polling, send a close packet. | |
2021 | * | |
2022 | * @api private | |
2023 | */ | |
2024 | ||
2025 | Polling.prototype.doClose = function(){ | |
2026 | var self = this; | |
2027 | ||
2028 | function close(){ | |
2029 | debug('writing close packet'); | |
2030 | self.write([{ type: 'close' }]); | |
2031 | } | |
2032 | ||
2033 | if (this.open) { | |
2034 | debug('transport open - closing'); | |
2035 | close(); | |
2036 | } else { | |
2037 | // in case we're trying to close while | |
2038 | // handshaking is in progress (GH-164) | |
2039 | debug('transport not open - defering close'); | |
2040 | this.once('open', close); | |
2041 | } | |
2042 | }; | |
2043 | ||
2044 | /** | |
2045 | * Writes a packets payload. | |
2046 | * | |
2047 | * @param {Array} data packets | |
2048 | * @param {Function} drain callback | |
2049 | * @api private | |
2050 | */ | |
2051 | ||
2052 | Polling.prototype.write = function(packets){ | |
2053 | var self = this; | |
2054 | this.writable = false; | |
2055 | this.doWrite(parser.encodePayload(packets), function(){ | |
2056 | self.writable = true; | |
2057 | self.emit('drain'); | |
2058 | }); | |
2059 | }; | |
2060 | ||
2061 | /** | |
2062 | * Generates uri for connection. | |
2063 | * | |
2064 | * @api private | |
2065 | */ | |
2066 | ||
2067 | Polling.prototype.uri = function(){ | |
2068 | var query = this.query || {}; | |
2069 | var schema = this.secure ? 'https' : 'http'; | |
2070 | var port = ''; | |
2071 | ||
2072 | // cache busting is forced for IE / android / iOS6 ಠ_ಠ| |
2073 | if (global.ActiveXObject || util.ua.android || util.ua.ios6 || | |
2074 | this.timestampRequests) { | |
2075 | query[this.timestampParam] = +new Date; | |
2076 | } | |
2077 | ||
2078 | query = util.qs(query); | |
2079 | ||
2080 | // avoid port if default for schema | |
2081 | if (this.port && (('https' == schema && this.port != 443) || | |
2082 | ('http' == schema && this.port != 80))) { | |
2083 | port = ':' + this.port; | |
2084 | } | |
2085 | ||
2086 | // prepend ? to query | |
2087 | if (query.length) { | |
2088 | query = '?' + query; | |
2089 | } | |
2090 | ||
2091 | return schema + '://' + this.hostname + port + this.path + query; | |
2092 | }; | |
2093 | ||
2094 | }); | |
2095 | require.register("engine.io/lib/transports/polling-xhr.js", function(exports, require, module){ | |
2096 | /** | |
2097 | * Module requirements. | |
2098 | */ | |
2099 | ||
2100 | var Polling = require('./polling') | |
2101 | , util = require('../util') | |
2102 | , Emitter = require('../emitter') | |
2103 | , debug = require('debug')('engine.io-client:polling-xhr'); | |
2104 | ||
2105 | /** | |
2106 | * Module exports. | |
2107 | */ | |
2108 | ||
2109 | module.exports = XHR; | |
2110 | module.exports.Request = Request; | |
2111 | ||
2112 | /** | |
2113 | * Global reference. | |
2114 | */ | |
2115 | ||
2116 | var global = util.global(); | |
2117 | ||
2118 | ||
2119 | /** | |
2120 | * Obfuscated key for Blue Coat. | |
2121 | */ | |
2122 | ||
2123 | var xobject = global[['Active'].concat('Object').join('X')]; | |
2124 | ||
2125 | /** | |
2126 | * Empty function | |
2127 | */ | |
2128 | ||
2129 | function empty(){} | |
2130 | ||
2131 | /** | |
2132 | * XHR Polling constructor. | |
2133 | * | |
2134 | * @param {Object} opts | |
2135 | * @api public | |
2136 | */ | |
2137 | ||
2138 | function XHR(opts){ | |
2139 | Polling.call(this, opts); | |
2140 | ||
2141 | if (global.location) { | |
2142 | var isSSL = 'https:' == location.protocol; | |
2143 | var port = location.port; | |
2144 | ||
2145 | // some user agents have empty `location.port` | |
2146 | if (Number(port) !== port) { | |
2147 | port = isSSL ? 443 : 80; | |
2148 | } | |
2149 | ||
2150 | this.xd = opts.hostname != global.location.hostname || | |
2151 | port != opts.port; | |
2152 | } | |
2153 | }; | |
2154 | ||
2155 | /** | |
2156 | * Inherits from Polling. | |
2157 | */ | |
2158 | ||
2159 | util.inherits(XHR, Polling); | |
2160 | ||
2161 | /** | |
2162 | * Opens the socket | |
2163 | * | |
2164 | * @api private | |
2165 | */ | |
2166 | ||
2167 | XHR.prototype.doOpen = function(){ | |
2168 | var self = this; | |
2169 | util.defer(function(){ | |
2170 | Polling.prototype.doOpen.call(self); | |
2171 | }); | |
2172 | }; | |
2173 | ||
2174 | /** | |
2175 | * Creates a request. | |
2176 | * | |
2177 | * @param {String} method | |
2178 | * @api private | |
2179 | */ | |
2180 | ||
2181 | XHR.prototype.request = function(opts){ | |
2182 | opts = opts || {}; | |
2183 | opts.uri = this.uri(); | |
2184 | opts.xd = this.xd; | |
2185 | return new Request(opts); | |
2186 | }; | |
2187 | ||
2188 | /** | |
2189 | * Sends data. | |
2190 | * | |
2191 | * @param {String} data to send. | |
2192 | * @param {Function} called upon flush. | |
2193 | * @api private | |
2194 | */ | |
2195 | ||
2196 | XHR.prototype.doWrite = function(data, fn){ | |
2197 | var req = this.request({ method: 'POST', data: data }); | |
2198 | var self = this; | |
2199 | req.on('success', fn); | |
2200 | req.on('error', function(err){ | |
2201 | self.onError('xhr post error', err); | |
2202 | }); | |
2203 | this.sendXhr = req; | |
2204 | }; | |
2205 | ||
2206 | /** | |
2207 | * Starts a poll cycle. | |
2208 | * | |
2209 | * @api private | |
2210 | */ | |
2211 | ||
2212 | XHR.prototype.doPoll = function(){ | |
2213 | debug('xhr poll'); | |
2214 | var req = this.request(); | |
2215 | var self = this; | |
2216 | req.on('data', function(data){ | |
2217 | self.onData(data); | |
2218 | }); | |
2219 | req.on('error', function(err){ | |
2220 | self.onError('xhr poll error', err); | |
2221 | }); | |
2222 | this.pollXhr = req; | |
2223 | }; | |
2224 | ||
2225 | /** | |
2226 | * Request constructor | |
2227 | * | |
2228 | * @param {Object} options | |
2229 | * @api public | |
2230 | */ | |
2231 | ||
2232 | function Request(opts){ | |
2233 | this.method = opts.method || 'GET'; | |
2234 | this.uri = opts.uri; | |
2235 | this.xd = !!opts.xd; | |
2236 | this.async = false !== opts.async; | |
2237 | this.data = undefined != opts.data ? opts.data : null; | |
2238 | this.create(); | |
2239 | } | |
2240 | ||
2241 | /** | |
2242 | * Mix in `Emitter`. | |
2243 | */ | |
2244 | ||
2245 | Emitter(Request.prototype); | |
2246 | ||
2247 | /** | |
2248 | * Creates the XHR object and sends the request. | |
2249 | * | |
2250 | * @api private | |
2251 | */ | |
2252 | ||
2253 | Request.prototype.create = function(){ | |
2254 | var xhr = this.xhr = util.request(this.xd); | |
2255 | var self = this; | |
2256 | ||
2257 | xhr.open(this.method, this.uri, this.async); | |
2258 | ||
2259 | if ('POST' == this.method) { | |
2260 | try { | |
2261 | if (xhr.setRequestHeader) { | |
2262 | // xmlhttprequest | |
2263 | xhr.setRequestHeader('Content-type', 'text/plain;charset=UTF-8'); | |
2264 | } else { | |
2265 | // xdomainrequest | |
2266 | xhr.contentType = 'text/plain'; | |
2267 | } | |
2268 | } catch (e) {} | |
2269 | } | |
2270 | ||
2271 | if (this.xd && global.XDomainRequest && xhr instanceof XDomainRequest) { | |
2272 | xhr.onerror = function(e){ | |
2273 | self.onError(e); | |
2274 | }; | |
2275 | xhr.onload = function(){ | |
2276 | self.onData(xhr.responseText); | |
2277 | }; | |
2278 | xhr.onprogress = empty; | |
2279 | } else { | |
2280 | // ie6 check | |
2281 | if ('withCredentials' in xhr) { | |
2282 | xhr.withCredentials = true; | |
2283 | } | |
2284 | ||
2285 | xhr.onreadystatechange = function(){ | |
2286 | var data; | |
2287 | ||
2288 | try { | |
2289 | if (4 != xhr.readyState) return; | |
2290 | if (200 == xhr.status || 1223 == xhr.status) { | |
2291 | data = xhr.responseText; | |
2292 | } else { | |
2293 | self.onError(xhr.status); | |
2294 | } | |
2295 | } catch (e) { | |
2296 | self.onError(e); | |
2297 | } | |
2298 | ||
2299 | if (undefined !== data) { | |
2300 | self.onData(data); | |
2301 | } | |
2302 | }; | |
2303 | } | |
2304 | ||
2305 | debug('sending xhr with url %s | data %s', this.uri, this.data); | |
2306 | xhr.send(this.data); | |
2307 | ||
2308 | if (xobject) { | |
2309 | this.index = Request.requestsCount++; | |
2310 | Request.requests[this.index] = this; | |
2311 | } | |
2312 | }; | |
2313 | ||
2314 | /** | |
2315 | * Called upon successful response. | |
2316 | * | |
2317 | * @api private | |
2318 | */ | |
2319 | ||
2320 | Request.prototype.onSuccess = function(){ | |
2321 | this.emit('success'); | |
2322 | this.cleanup(); | |
2323 | }; | |
2324 | ||
2325 | /** | |
2326 | * Called if we have data. | |
2327 | * | |
2328 | * @api private | |
2329 | */ | |
2330 | ||
2331 | Request.prototype.onData = function(data){ | |
2332 | this.emit('data', data); | |
2333 | this.onSuccess(); | |
2334 | }; | |
2335 | ||
2336 | /** | |
2337 | * Called upon error. | |
2338 | * | |
2339 | * @api private | |
2340 | */ | |
2341 | ||
2342 | Request.prototype.onError = function(err){ | |
2343 | this.emit('error', err); | |
2344 | this.cleanup(); | |
2345 | }; | |
2346 | ||
2347 | /** | |
2348 | * Cleans up house. | |
2349 | * | |
2350 | * @api private | |
2351 | */ | |
2352 | ||
2353 | Request.prototype.cleanup = function(){ | |
2354 | if ('undefined' == typeof this.xhr ) { | |
2355 | return; | |
2356 | } | |
2357 | // xmlhttprequest | |
2358 | this.xhr.onreadystatechange = empty; | |
2359 | ||
2360 | // xdomainrequest | |
2361 | this.xhr.onload = this.xhr.onerror = empty; | |
2362 | ||
2363 | try { | |
2364 | this.xhr.abort(); | |
2365 | } catch(e) {} | |
2366 | ||
2367 | if (xobject) { | |
2368 | delete Request.requests[this.index]; | |
2369 | } | |
2370 | ||
2371 | this.xhr = null; | |
2372 | }; | |
2373 | ||
2374 | /** | |
2375 | * Aborts the request. | |
2376 | * | |
2377 | * @api public | |
2378 | */ | |
2379 | ||
2380 | Request.prototype.abort = function(){ | |
2381 | this.cleanup(); | |
2382 | }; | |
2383 | ||
2384 | if (xobject) { | |
2385 | Request.requestsCount = 0; | |
2386 | Request.requests = {}; | |
2387 | ||
2388 | global.attachEvent('onunload', function(){ | |
2389 | for (var i in Request.requests) { | |
2390 | if (Request.requests.hasOwnProperty(i)) { | |
2391 | Request.requests[i].abort(); | |
2392 | } | |
2393 | } | |
2394 | }); | |
2395 | } | |
2396 | ||
2397 | }); | |
2398 | require.register("engine.io/lib/transports/polling-jsonp.js", function(exports, require, module){ | |
2399 | ||
2400 | /** | |
2401 | * Module requirements. | |
2402 | */ | |
2403 | ||
2404 | var Polling = require('./polling') | |
2405 | , util = require('../util'); | |
2406 | ||
2407 | /** | |
2408 | * Module exports. | |
2409 | */ | |
2410 | ||
2411 | module.exports = JSONPPolling; | |
2412 | ||
2413 | /** | |
2414 | * Global reference. | |
2415 | */ | |
2416 | ||
2417 | var global = util.global(); | |
2418 | ||
2419 | /** | |
2420 | * Cached regular expressions. | |
2421 | */ | |
2422 | ||
2423 | var rNewline = /\n/g; | |
2424 | ||
2425 | /** | |
2426 | * Global JSONP callbacks. | |
2427 | */ | |
2428 | ||
2429 | var callbacks; | |
2430 | ||
2431 | /** | |
2432 | * Callbacks count. | |
2433 | */ | |
2434 | ||
2435 | var index = 0; | |
2436 | ||
2437 | /** | |
2438 | * Noop. | |
2439 | */ | |
2440 | ||
2441 | function empty () { } | |
2442 | ||
2443 | /** | |
2444 | * JSONP Polling constructor. | |
2445 | * | |
2446 | * @param {Object} opts. | |
2447 | * @api public | |
2448 | */ | |
2449 | ||
2450 | function JSONPPolling (opts) { | |
2451 | Polling.call(this, opts); | |
2452 | ||
2453 | // define global callbacks array if not present | |
2454 | // we do this here (lazily) to avoid unneeded global pollution | |
2455 | if (!callbacks) { | |
2456 | // we need to consider multiple engines in the same page | |
2457 | if (!global.___eio) global.___eio = []; | |
2458 | callbacks = global.___eio; | |
2459 | } | |
2460 | ||
2461 | // callback identifier | |
2462 | this.index = callbacks.length; | |
2463 | ||
2464 | // add callback to jsonp global | |
2465 | var self = this; | |
2466 | callbacks.push(function (msg) { | |
2467 | self.onData(msg); | |
2468 | }); | |
2469 | ||
2470 | // append to query string | |
2471 | this.query.j = this.index; | |
2472 | }; | |
2473 | ||
2474 | /** | |
2475 | * Inherits from Polling. | |
2476 | */ | |
2477 | ||
2478 | util.inherits(JSONPPolling, Polling); | |
2479 | ||
2480 | /** | |
2481 | * Opens the socket. | |
2482 | * | |
2483 | * @api private | |
2484 | */ | |
2485 | ||
2486 | JSONPPolling.prototype.doOpen = function () { | |
2487 | var self = this; | |
2488 | util.defer(function () { | |
2489 | Polling.prototype.doOpen.call(self); | |
2490 | }); | |
2491 | }; | |
2492 | ||
2493 | /** | |
2494 | * Closes the socket | |
2495 | * | |
2496 | * @api private | |
2497 | */ | |
2498 | ||
2499 | JSONPPolling.prototype.doClose = function () { | |
2500 | if (this.script) { | |
2501 | this.script.parentNode.removeChild(this.script); | |
2502 | this.script = null; | |
2503 | } | |
2504 | ||
2505 | if (this.form) { | |
2506 | this.form.parentNode.removeChild(this.form); | |
2507 | this.form = null; | |
2508 | } | |
2509 | ||
2510 | Polling.prototype.doClose.call(this); | |
2511 | }; | |
2512 | ||
2513 | /** | |
2514 | * Starts a poll cycle. | |
2515 | * | |
2516 | * @api private | |
2517 | */ | |
2518 | ||
2519 | JSONPPolling.prototype.doPoll = function () { | |
2520 | var self = this; | |
2521 | var script = document.createElement('script'); | |
2522 | ||
2523 | if (this.script) { | |
2524 | this.script.parentNode.removeChild(this.script); | |
2525 | this.script = null; | |
2526 | } | |
2527 | ||
2528 | script.async = true; | |
2529 | script.src = this.uri(); | |
2530 | script.onerror = function(e){ | |
2531 | self.onError('jsonp poll error',e); | |
2532 | } | |
2533 | ||
2534 | var insertAt = document.getElementsByTagName('script')[0]; | |
2535 | insertAt.parentNode.insertBefore(script, insertAt); | |
2536 | this.script = script; | |
2537 | ||
2538 | ||
2539 | if (util.ua.gecko) { | |
2540 | setTimeout(function () { | |
2541 | var iframe = document.createElement('iframe'); | |
2542 | document.body.appendChild(iframe); | |
2543 | document.body.removeChild(iframe); | |
2544 | }, 100); | |
2545 | } | |
2546 | }; | |
2547 | ||
2548 | /** | |
2549 | * Writes with a hidden iframe. | |
2550 | * | |
2551 | * @param {String} data to send | |
2552 | * @param {Function} called upon flush. | |
2553 | * @api private | |
2554 | */ | |
2555 | ||
2556 | JSONPPolling.prototype.doWrite = function (data, fn) { | |
2557 | var self = this; | |
2558 | ||
2559 | if (!this.form) { | |
2560 | var form = document.createElement('form'); | |
2561 | var area = document.createElement('textarea'); | |
2562 | var id = this.iframeId = 'eio_iframe_' + this.index; | |
2563 | var iframe; | |
2564 | ||
2565 | form.className = 'socketio'; | |
2566 | form.style.position = 'absolute'; | |
2567 | form.style.top = '-1000px'; | |
2568 | form.style.left = '-1000px'; | |
2569 | form.target = id; | |
2570 | form.method = 'POST'; | |
2571 | form.setAttribute('accept-charset', 'utf-8'); | |
2572 | area.name = 'd'; | |
2573 | form.appendChild(area); | |
2574 | document.body.appendChild(form); | |
2575 | ||
2576 | this.form = form; | |
2577 | this.area = area; | |
2578 | } | |
2579 | ||
2580 | this.form.action = this.uri(); | |
2581 | ||
2582 | function complete () { | |
2583 | initIframe(); | |
2584 | fn(); | |
2585 | }; | |
2586 | ||
2587 | function initIframe () { | |
2588 | if (self.iframe) { | |
2589 | try { | |
2590 | self.form.removeChild(self.iframe); | |
2591 | } catch (e) { | |
2592 | self.onError('jsonp polling iframe removal error', e); | |
2593 | } | |
2594 | } | |
2595 | ||
2596 | try { | |
2597 | // ie6 dynamic iframes with target="" support (thanks Chris Lambacher) | |
2598 | var html = '<iframe src="javascript:0" name="'+ self.iframeId +'">'; | |
2599 | iframe = document.createElement(html); | |
2600 | } catch (e) { | |
2601 | iframe = document.createElement('iframe'); | |
2602 | iframe.name = self.iframeId; | |
2603 | iframe.src = 'javascript:0'; | |
2604 | } | |
2605 | ||
2606 | iframe.id = self.iframeId; | |
2607 | ||
2608 | self.form.appendChild(iframe); | |
2609 | self.iframe = iframe; | |
2610 | }; | |
2611 | ||
2612 | initIframe(); | |
2613 | ||
2614 | // escape \n to prevent it from being converted into \r\n by some UAs | |
2615 | this.area.value = data.replace(rNewline, '\\n'); | |
2616 | ||
2617 | try { | |
2618 | this.form.submit(); | |
2619 | } catch(e) {} | |
2620 | ||
2621 | if (this.iframe.attachEvent) { | |
2622 | this.iframe.onreadystatechange = function(){ | |
2623 | if (self.iframe.readyState == 'complete') { | |
2624 | complete(); | |
2625 | } | |
2626 | }; | |
2627 | } else { | |
2628 | this.iframe.onload = complete; | |
2629 | } | |
2630 | }; | |
2631 | ||
2632 | }); | |
2633 | require.register("engine.io/lib/transports/websocket.js", function(exports, require, module){ | |
2634 | /** | |
2635 | * Module dependencies. | |
2636 | */ | |
2637 | ||
2638 | var Transport = require('../transport') | |
2639 | , parser = require('engine.io-parser') | |
2640 | , util = require('../util') | |
2641 | , debug = require('debug')('engine.io-client:websocket'); | |
2642 | ||
2643 | /** | |
2644 | * Module exports. | |
2645 | */ | |
2646 | ||
2647 | module.exports = WS; | |
2648 | ||
2649 | /** | |
2650 | * Global reference. | |
2651 | */ | |
2652 | ||
2653 | var global = util.global(); | |
2654 | ||
2655 | /** | |
2656 | * WebSocket transport constructor. | |
2657 | * | |
2658 | * @api {Object} connection options | |
2659 | * @api public | |
2660 | */ | |
2661 | ||
2662 | function WS(opts){ | |
2663 | Transport.call(this, opts); | |
2664 | }; | |
2665 | ||
2666 | /** | |
2667 | * Inherits from Transport. | |
2668 | */ | |
2669 | ||
2670 | util.inherits(WS, Transport); | |
2671 | ||
2672 | /** | |
2673 | * Transport name. | |
2674 | * | |
2675 | * @api public | |
2676 | */ | |
2677 | ||
2678 | WS.prototype.name = 'websocket'; | |
2679 | ||
2680 | /** | |
2681 | * Opens socket. | |
2682 | * | |
2683 | * @api private | |
2684 | */ | |
2685 | ||
2686 | WS.prototype.doOpen = function(){ | |
2687 | if (!this.check()) { | |
2688 | // let probe timeout | |
2689 | return; | |
2690 | } | |
2691 | ||
2692 | var self = this; | |
2693 | ||
2694 | this.socket = new (ws())(this.uri()); | |
2695 | this.socket.onopen = function(){ | |
2696 | self.onOpen(); | |
2697 | }; | |
2698 | this.socket.onclose = function(){ | |
2699 | self.onClose(); | |
2700 | }; | |
2701 | this.socket.onmessage = function(ev){ | |
2702 | self.onData(ev.data); | |
2703 | }; | |
2704 | this.socket.onerror = function(e){ | |
2705 | self.onError('websocket error', e); | |
2706 | }; | |
2707 | }; | |
2708 | ||
2709 | /** | |
2710 | * Override `onData` to use a timer on iOS. | |
2711 | * See: https://gist.github.com/mloughran/2052006 | |
2712 | * | |
2713 | * @api private | |
2714 | */ | |
2715 | ||
2716 | if ('undefined' != typeof navigator | |
2717 | && /iPad|iPhone|iPod/i.test(navigator.userAgent)) { | |
2718 | WS.prototype.onData = function(data){ | |
2719 | var self = this; | |
2720 | setTimeout(function(){ | |
2721 | Transport.prototype.onData.call(self, data); | |
2722 | }, 0); | |
2723 | }; | |
2724 | } | |
2725 | ||
2726 | /** | |
2727 | * Writes data to socket. | |
2728 | * | |
2729 | * @param {Array} array of packets. | |
2730 | * @api private | |
2731 | */ | |
2732 | ||
2733 | WS.prototype.write = function(packets){ | |
2734 | var self = this; | |
2735 | this.writable = false; | |
2736 | // encodePacket efficient as it uses WS framing | |
2737 | // no need for encodePayload | |
2738 | for (var i = 0, l = packets.length; i < l; i++) { | |
2739 | this.socket.send(parser.encodePacket(packets[i])); | |
2740 | } | |
2741 | function ondrain() { | |
2742 | self.writable = true; | |
2743 | self.emit('drain'); | |
2744 | } | |
2745 | // check periodically if we're done sending | |
2746 | if ('bufferedAmount' in this.socket) { | |
2747 | this.bufferedAmountId = setInterval(function() { | |
2748 | if (self.socket.bufferedAmount == 0) { | |
2749 | clearInterval(self.bufferedAmountId); | |
2750 | ondrain(); | |
2751 | } | |
2752 | }, 50); | |
2753 | } else { | |
2754 | // fake drain | |
2755 | // defer to next tick to allow Socket to clear writeBuffer | |
2756 | setTimeout(ondrain, 0); | |
2757 | } | |
2758 | }; | |
2759 | ||
2760 | /** | |
2761 | * Called upon close | |
2762 | * | |
2763 | * @api private | |
2764 | */ | |
2765 | ||
2766 | WS.prototype.onClose = function(){ | |
2767 | // stop checking to see if websocket is done sending buffer | |
2768 | clearInterval(this.bufferedAmountId); | |
2769 | Transport.prototype.onClose.call(this); | |
2770 | }; | |
2771 | ||
2772 | /** | |
2773 | * Closes socket. | |
2774 | * | |
2775 | * @api private | |
2776 | */ | |
2777 | ||
2778 | WS.prototype.doClose = function(){ | |
2779 | if (typeof this.socket !== 'undefined') { | |
2780 | this.socket.close(); | |
2781 | } | |
2782 | }; | |
2783 | ||
2784 | /** | |
2785 | * Generates uri for connection. | |
2786 | * | |
2787 | * @api private | |
2788 | */ | |
2789 | ||
2790 | WS.prototype.uri = function(){ | |
2791 | var query = this.query || {}; | |
2792 | var schema = this.secure ? 'wss' : 'ws'; | |
2793 | var port = ''; | |
2794 | ||
2795 | // avoid port if default for schema | |
2796 | if (this.port && (('wss' == schema && this.port != 443) | |
2797 | || ('ws' == schema && this.port != 80))) { | |
2798 | port = ':' + this.port; | |
2799 | } | |
2800 | ||
2801 | // append timestamp to URI | |
2802 | if (this.timestampRequests) { | |
2803 | query[this.timestampParam] = +new Date; | |
2804 | } | |
2805 | ||
2806 | query = util.qs(query); | |
2807 | ||
2808 | // prepend ? to query | |
2809 | if (query.length) { | |
2810 | query = '?' + query; | |
2811 | } | |
2812 | ||
2813 | return schema + '://' + this.hostname + port + this.path + query; | |
2814 | }; | |
2815 | ||
2816 | /** | |
2817 | * Feature detection for WebSocket. | |
2818 | * | |
2819 | * @return {Boolean} whether this transport is available. | |
2820 | * @api public | |
2821 | */ | |
2822 | ||
2823 | WS.prototype.check = function(){ | |
2824 | var websocket = ws(); | |
2825 | return !!websocket && !('__initialize' in websocket && this.name === WS.prototype.name); | |
2826 | }; | |
2827 | ||
2828 | /** | |
2829 | * Getter for WS constructor. | |
2830 | * | |
2831 | * @api private | |
2832 | */ | |
2833 | ||
2834 | function ws(){ | |
2835 | if ('undefined' == typeof window) { | |
2836 | return require('ws'); | |
2837 | } | |
2838 | ||
2839 | return global.WebSocket || global.MozWebSocket; | |
2840 | } | |
2841 | ||
2842 | }); | |
2843 | require.register("engine.io/lib/transports/flashsocket.js", function(exports, require, module){ | |
2844 | /** | |
2845 | * Module dependencies. | |
2846 | */ | |
2847 | ||
2848 | var WS = require('./websocket') | |
2849 | , util = require('../util') | |
2850 | , debug = require('debug')('engine.io-client:flashsocket'); | |
2851 | ||
2852 | /** | |
2853 | * Module exports. | |
2854 | */ | |
2855 | ||
2856 | module.exports = FlashWS; | |
2857 | ||
2858 | /** | |
2859 | * Global reference. | |
2860 | */ | |
2861 | ||
2862 | var global = util.global() | |
2863 | ||
2864 | /** | |
2865 | * Obfuscated key for Blue Coat. | |
2866 | */ | |
2867 | ||
2868 | var xobject = global[['Active'].concat('Object').join('X')]; | |
2869 | ||
2870 | /** | |
2871 | * FlashWS constructor. | |
2872 | * | |
2873 | * @api public | |
2874 | */ | |
2875 | ||
2876 | function FlashWS (options) { | |
2877 | WS.call(this, options); | |
2878 | this.flashPath = options.flashPath; | |
2879 | this.policyPort = options.policyPort; | |
2880 | }; | |
2881 | ||
2882 | /** | |
2883 | * Inherits from WebSocket. | |
2884 | */ | |
2885 | ||
2886 | util.inherits(FlashWS, WS); | |
2887 | ||
2888 | /** | |
2889 | * Transport name. | |
2890 | * | |
2891 | * @api public | |
2892 | */ | |
2893 | ||
2894 | FlashWS.prototype.name = 'flashsocket'; | |
2895 | ||
2896 | /** | |
2897 | * Opens the transport. | |
2898 | * | |
2899 | * @api public | |
2900 | */ | |
2901 | ||
2902 | FlashWS.prototype.doOpen = function () { | |
2903 | if (!this.check()) { | |
2904 | // let the probe timeout | |
2905 | return; | |
2906 | } | |
2907 | ||
2908 | // instrument websocketjs logging | |
2909 | function log (type) { | |
2910 | return function(){ | |
2911 | var str = Array.prototype.join.call(arguments, ' '); | |
2912 | debug('[websocketjs %s] %s', type, str); | |
2913 | }; | |
2914 | }; | |
2915 | ||
2916 | WEB_SOCKET_LOGGER = { log: log('debug'), error: log('error') }; | |
2917 | WEB_SOCKET_SUPPRESS_CROSS_DOMAIN_SWF_ERROR = true; | |
2918 | WEB_SOCKET_DISABLE_AUTO_INITIALIZATION = true; | |
2919 | ||
2920 | if ('undefined' == typeof WEB_SOCKET_SWF_LOCATION) { | |
2921 | WEB_SOCKET_SWF_LOCATION = this.flashPath + 'WebSocketMainInsecure.swf'; | |
2922 | } | |
2923 | ||
2924 | // dependencies | |
2925 | var deps = [this.flashPath + 'web_socket.js']; | |
2926 | ||
2927 | if ('undefined' == typeof swfobject) { | |
2928 | deps.unshift(this.flashPath + 'swfobject.js'); | |
2929 | } | |
2930 | ||
2931 | var self = this; | |
2932 | ||
2933 | load(deps, function () { | |
2934 | self.ready(function () { | |
2935 | WebSocket.__addTask(function () { | |
2936 | WS.prototype.doOpen.call(self); | |
2937 | }); | |
2938 | }); | |
2939 | }); | |
2940 | }; | |
2941 | ||
2942 | /** | |
2943 | * Override to prevent closing uninitialized flashsocket. | |
2944 | * | |
2945 | * @api private | |
2946 | */ | |
2947 | ||
2948 | FlashWS.prototype.doClose = function () { | |
2949 | if (!this.socket) return; | |
2950 | var self = this; | |
2951 | WebSocket.__addTask(function() { | |
2952 | WS.prototype.doClose.call(self); | |
2953 | }); | |
2954 | }; | |
2955 | ||
2956 | /** | |
2957 | * Writes to the Flash socket. | |
2958 | * | |
2959 | * @api private | |
2960 | */ | |
2961 | ||
2962 | FlashWS.prototype.write = function() { | |
2963 | var self = this, args = arguments; | |
2964 | WebSocket.__addTask(function () { | |
2965 | WS.prototype.write.apply(self, args); | |
2966 | }); | |
2967 | }; | |
2968 | ||
2969 | /** | |
2970 | * Called upon dependencies are loaded. | |
2971 | * | |
2972 | * @api private | |
2973 | */ | |
2974 | ||
2975 | FlashWS.prototype.ready = function (fn) { | |
2976 | if (typeof WebSocket == 'undefined' || | |
2977 | !('__initialize' in WebSocket) || !swfobject) { | |
2978 | return; | |
2979 | } | |
2980 | ||
2981 | if (swfobject.getFlashPlayerVersion().major < 10) { | |
2982 | return; | |
2983 | } | |
2984 | ||
2985 | function init () { | |
2986 | // Only start downloading the swf file when the checked that this browser | |
2987 | // actually supports it | |
2988 | if (!FlashWS.loaded) { | |
2989 | if (843 != self.policyPort) { | |
2990 | WebSocket.loadFlashPolicyFile('xmlsocket://' + self.host + ':' + self.policyPort); | |
2991 | } | |
2992 | ||
2993 | WebSocket.__initialize(); | |
2994 | FlashWS.loaded = true; | |
2995 | } | |
2996 | ||
2997 | fn.call(self); | |
2998 | } | |
2999 | ||
3000 | var self = this; | |
3001 | if (document.body) { | |
3002 | return init(); | |
3003 | } | |
3004 | ||
3005 | util.load(init); | |
3006 | }; | |
3007 | ||
3008 | /** | |
3009 | * Feature detection for flashsocket. | |
3010 | * | |
3011 | * @return {Boolean} whether this transport is available. | |
3012 | * @api public | |
3013 | */ | |
3014 | ||
3015 | FlashWS.prototype.check = function () { | |
3016 | if ('undefined' == typeof window) { | |
3017 | return false; | |
3018 | } | |
3019 | ||
3020 | if (typeof WebSocket != 'undefined' && !('__initialize' in WebSocket)) { | |
3021 | return false; | |
3022 | } | |
3023 | ||
3024 | if (xobject) { | |
3025 | var control = null; | |
3026 | try { | |
3027 | control = new xobject('ShockwaveFlash.ShockwaveFlash'); | |
3028 | } catch (e) { } | |
3029 | if (control) { | |
3030 | return true; | |
3031 | } | |
3032 | } else { | |
3033 | for (var i = 0, l = navigator.plugins.length; i < l; i++) { | |
3034 | for (var j = 0, m = navigator.plugins[i].length; j < m; j++) { | |
3035 | if (navigator.plugins[i][j].description == 'Shockwave Flash') { | |
3036 | return true; | |
3037 | } | |
3038 | } | |
3039 | } | |
3040 | } | |
3041 | ||
3042 | return false; | |
3043 | }; | |
3044 | ||
3045 | /** | |
3046 | * Lazy loading of scripts. | |
3047 | * Based on $script by Dustin Diaz - MIT | |
3048 | */ | |
3049 | ||
3050 | var scripts = {}; | |
3051 | ||
3052 | /** | |
3053 | * Injects a script. Keeps tracked of injected ones. | |
3054 | * | |
3055 | * @param {String} path | |
3056 | * @param {Function} callback | |
3057 | * @api private | |
3058 | */ | |
3059 | ||
3060 | function create (path, fn) { | |
3061 | if (scripts[path]) return fn(); | |
3062 | ||
3063 | var el = document.createElement('script'); | |
3064 | var loaded = false; | |
3065 | ||
3066 | debug('loading "%s"', path); | |
3067 | el.onload = el.onreadystatechange = function () { | |
3068 | if (loaded || scripts[path]) return; | |
3069 | var rs = el.readyState; | |
3070 | if (!rs || 'loaded' == rs || 'complete' == rs) { | |
3071 | debug('loaded "%s"', path); | |
3072 | el.onload = el.onreadystatechange = null; | |
3073 | loaded = true; | |
3074 | scripts[path] = true; | |
3075 | fn(); | |
3076 | } | |
3077 | }; | |
3078 | ||
3079 | el.async = 1; | |
3080 | el.src = path; | |
3081 | ||
3082 | var head = document.getElementsByTagName('head')[0]; | |
3083 | head.insertBefore(el, head.firstChild); | |
3084 | }; | |
3085 | ||
3086 | /** | |
3087 | * Loads scripts and fires a callback. | |
3088 | * | |
3089 | * @param {Array} paths | |
3090 | * @param {Function} callback | |
3091 | */ | |
3092 | ||
3093 | function load (arr, fn) { | |
3094 | function process (i) { | |
3095 | if (!arr[i]) return fn(); | |
3096 | create(arr[i], function () { | |
3097 | process(++i); | |
3098 | }); | |
3099 | }; | |
3100 | ||
3101 | process(0); | |
3102 | }; | |
3103 | ||
3104 | }); | |
3105 | require.alias("component-emitter/index.js", "engine.io/deps/emitter/index.js"); | |
3106 | require.alias("component-emitter/index.js", "emitter/index.js"); | |
3107 | ||
3108 | require.alias("component-indexof/index.js", "engine.io/deps/indexof/index.js"); | |
3109 | require.alias("component-indexof/index.js", "indexof/index.js"); | |
3110 | ||
3111 | require.alias("LearnBoost-engine.io-protocol/lib/index.js", "engine.io/deps/engine.io-parser/lib/index.js"); | |
3112 | require.alias("LearnBoost-engine.io-protocol/lib/keys.js", "engine.io/deps/engine.io-parser/lib/keys.js"); | |
3113 | require.alias("LearnBoost-engine.io-protocol/lib/index.js", "engine.io/deps/engine.io-parser/index.js"); | |
3114 | require.alias("LearnBoost-engine.io-protocol/lib/index.js", "engine.io-parser/index.js"); | |
3115 | require.alias("LearnBoost-engine.io-protocol/lib/index.js", "LearnBoost-engine.io-protocol/index.js"); | |
3116 | ||
3117 | require.alias("visionmedia-debug/index.js", "engine.io/deps/debug/index.js"); | |
3118 | require.alias("visionmedia-debug/debug.js", "engine.io/deps/debug/debug.js"); | |
3119 | require.alias("visionmedia-debug/index.js", "debug/index.js"); | |
3120 | ||
3121 | require.alias("engine.io/lib/index.js", "engine.io/index.js"); | |
3122 | ||
3123 | if (typeof exports == "object") { | |
3124 | module.exports = require("engine.io"); | |
3125 | } else if (typeof define == "function" && define.amd) { | |
3126 | define(function(){ return require("engine.io"); }); | |
3127 | } else { | |
3128 | this["eio"] = require("engine.io"); | |
3129 | }})(); |