faye-rails 1.0.10 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2976de989429620397c37b316df564e99a52cd80
4
- data.tar.gz: 3055dfe04ebf7305c89c2c9a7a8a5b2ec388021d
3
+ metadata.gz: 7bd83a3a2e962e010685339f78b0a1eb76e03566
4
+ data.tar.gz: abf0cbaa64b7c53a407aa550eba83de311a5e35d
5
5
  SHA512:
6
- metadata.gz: ae291a6cabe521c879f2867b828aebae22069f309b6acef2fa332709557e82ba4396a70c9e19f45b42e713c70d49bb2f234950a931fcd81638e6514cc924081c
7
- data.tar.gz: f39fb18c87eeafeb8d68269312dddc6f8a792992a8ff107001accdbb8eaa206c37b33d5486adce01f22ca020a2b11bda3c855fd222b02eb77c7ed9f5f84f41da
6
+ metadata.gz: 3b3a36d23a807a8bab2443cafb911f1d14f0e57cf5d25e5bb3b1248345ef56a97d43f294d2c33c98eb8e8fbe9c110e830fde936c05e0da6143def36920a71b4d
7
+ data.tar.gz: 544853c580199160d8bfcf19530c574ea17585346b2b7cbd942be8a9eb852105b7bdfde4106814fc4a864d42fcb871422ed53652d6574d6ee4255f10ad61314b
data/README.md CHANGED
@@ -149,6 +149,16 @@ App::Application.routes.draw do
149
149
  end
150
150
  ```
151
151
 
152
+ # Running on Phusion Passenger
153
+
154
+ If you want to run faye-rails on passenger, make sure you are using passenger 4.0 standalone or passenger 4.0 on nginx 1.4+ for nginx with websocket support. Passenger on apache is not supported. Because passenger uses a multi-process model, you must use the faye redis backend. Add `gem 'faye-redis'` to your Gemfile and configure your routes like this:
155
+
156
+ ```ruby
157
+ App::Application.routes.draw do
158
+ faye_server '/faye', timeout: 25, server: 'passenger', engine: {type: Faye::Redis, host: 'localhost'}
159
+ end
160
+ ```
161
+
152
162
  # Thanks.
153
163
 
154
164
  Thanks to James Coglan for the excellent Faye Bayeux implementetation and great support for Faye users.
@@ -1,6 +1,6 @@
1
1
  require 'faye'
2
2
  require 'faye-rails/version'
3
- require 'faye-rails/routing_hooks'
3
+ require 'faye-rails/middleware'
4
4
  require 'faye-rails/server_list'
5
5
 
6
6
  module FayeRails
@@ -0,0 +1,54 @@
1
+ module FayeRails
2
+ class Middleware
3
+
4
+ DEFAULTS = {
5
+ :mount => '/faye',
6
+ :timeout => 25,
7
+ :extensions => nil,
8
+ :engine => nil,
9
+ :ping => nil,
10
+ :server => 'thin'
11
+ }
12
+
13
+ def initialize(app, options={}, &block)
14
+ @app = app
15
+
16
+ if Rails.application.config.middleware.include? Rack::Lock
17
+ message = <<-EOF
18
+
19
+ WARNING: You have the Rack::Lock middlware enabled.
20
+
21
+ faye-rails can't work when Rack::Lock is enabled, as it will cause
22
+ a deadlock on every request.
23
+
24
+ Please add:
25
+
26
+ config.middleware.delete Rack::Lock
27
+
28
+ to your application config in application.rb
29
+
30
+ EOF
31
+ Rails.logger.fatal message
32
+ $stdout.puts message
33
+ exit 1
34
+ end
35
+
36
+ unknown_options = options.keys - DEFAULTS.keys
37
+ if unknown_options.one?
38
+ raise ArgumentError, "Unknown option: #{unknown_options.first}."
39
+ elsif unknown_options.any?
40
+ raise ArgumentError, "Unknown options: #{unknown_options * ", "}."
41
+ end
42
+
43
+ options = DEFAULTS.merge(options)
44
+ Faye::WebSocket.load_adapter(options.delete(:server))
45
+
46
+ @adapter = FayeRails::RackAdapter.new(@app, options)
47
+ @adapter.instance_eval(&block) if block.respond_to? :call
48
+ end
49
+
50
+ def call(env)
51
+ @adapter.call(env)
52
+ end
53
+ end
54
+ end
@@ -1,3 +1,3 @@
1
1
  module FayeRails
2
- VERSION = "1.0.10"
2
+ VERSION = "2.0.0"
3
3
  end
@@ -1,4 +1,5 @@
1
1
  (function() {
2
- 'use strict';var Faye={VERSION:'0.8.9',BAYEUX_VERSION:'1.0',ID_LENGTH:160,JSONP_CALLBACK:'jsonpcallback',CONNECTION_TYPES:['long-polling','cross-origin-long-polling','callback-polling','websocket','eventsource','in-process'],MANDATORY_CONNECTION_TYPES:['long-polling','callback-polling','in-process'],ENV:(typeof global==='undefined')?window:global,extend:function(a,b,d){if(!b)return a;for(var f in b){if(!b.hasOwnProperty(f))continue;if(a.hasOwnProperty(f)&&d===false)continue;if(a[f]!==b[f])a[f]=b[f]}return a},random:function(a){a=a||this.ID_LENGTH;if(a>32){var b=Math.ceil(a/32),d='';while(b--)d+=this.random(32);var f=d.split(''),g='';while(f.length>0)g+=f.pop();return g}var h=Math.pow(2,a)-1,i=h.toString(36).length,d=Math.floor(Math.random()*h).toString(36);while(d.length<i)d='0'+d;return d},clientIdFromMessages:function(a){var b=[].concat(a)[0];return b&&b.clientId},copyObject:function(a){var b,d,f;if(a instanceof Array){b=[];d=a.length;while(d--)b[d]=Faye.copyObject(a[d]);return b}else if(typeof a==='object'){b=(a===null)?null:{};for(f in a)b[f]=Faye.copyObject(a[f]);return b}else{return a}},commonElement:function(a,b){for(var d=0,f=a.length;d<f;d++){if(this.indexOf(b,a[d])!==-1)return a[d]}return null},indexOf:function(a,b){if(a.indexOf)return a.indexOf(b);for(var d=0,f=a.length;d<f;d++){if(a[d]===b)return d}return-1},map:function(a,b,d){if(a.map)return a.map(b,d);var f=[];if(a instanceof Array){for(var g=0,h=a.length;g<h;g++){f.push(b.call(d||null,a[g],g))}}else{for(var i in a){if(!a.hasOwnProperty(i))continue;f.push(b.call(d||null,i,a[i]))}}return f},filter:function(a,b,d){var f=[];for(var g=0,h=a.length;g<h;g++){if(b.call(d||null,a[g],g))f.push(a[g])}return f},asyncEach:function(a,b,d,f){var g=a.length,h=-1,i=0,k=false;var j=function(){i-=1;h+=1;if(h===g)return d&&d.call(f);b(a[h],n)};var m=function(){if(k)return;k=true;while(i>0)j();k=false};var n=function(){i+=1;m()};n()},toJSON:function(a){if(this.stringify)return this.stringify(a,function(key,value){return(this[key]instanceof Array)?this[key]:value});return JSON.stringify(a)},logger:function(a){if(typeof console!=='undefined')console.log(a)},timestamp:function(){var b=new Date(),d=b.getFullYear(),f=b.getMonth()+1,g=b.getDate(),h=b.getHours(),i=b.getMinutes(),k=b.getSeconds();var j=function(a){return a<10?'0'+a:String(a)};return j(d)+'-'+j(f)+'-'+j(g)+' '+j(h)+':'+j(i)+':'+j(k)}};if(typeof window!=='undefined')window.Faye=Faye;Faye.Class=function(a,b){if(typeof a!=='function'){b=a;a=Object}var d=function(){if(!this.initialize)return this;return this.initialize.apply(this,arguments)||this};var f=function(){};f.prototype=a.prototype;d.prototype=new f();Faye.extend(d.prototype,b);return d};Faye.Namespace=Faye.Class({initialize:function(){this._e={}},exists:function(a){return this._e.hasOwnProperty(a)},generate:function(){var a=Faye.random();while(this._e.hasOwnProperty(a))a=Faye.random();return this._e[a]=a},release:function(a){delete this._e[a]}});Faye.Error=Faye.Class({initialize:function(a,b,d){this.code=a;this.params=Array.prototype.slice.call(b);this.message=d},toString:function(){return this.code+':'+this.params.join(',')+':'+this.message}});Faye.Error.parse=function(a){a=a||'';if(!Faye.Grammar.ERROR.test(a))return new this(null,[],a);var b=a.split(':'),d=parseInt(b[0]),f=b[1].split(','),a=b[2];return new this(d,f,a)};Faye.Error.versionMismatch=function(){return new this(300,arguments,"Version mismatch").toString()};Faye.Error.conntypeMismatch=function(){return new this(301,arguments,"Connection types not supported").toString()};Faye.Error.extMismatch=function(){return new this(302,arguments,"Extension mismatch").toString()};Faye.Error.badRequest=function(){return new this(400,arguments,"Bad request").toString()};Faye.Error.clientUnknown=function(){return new this(401,arguments,"Unknown client").toString()};Faye.Error.parameterMissing=function(){return new this(402,arguments,"Missing required parameter").toString()};Faye.Error.channelForbidden=function(){return new this(403,arguments,"Forbidden channel").toString()};Faye.Error.channelUnknown=function(){return new this(404,arguments,"Unknown channel").toString()};Faye.Error.channelInvalid=function(){return new this(405,arguments,"Invalid channel").toString()};Faye.Error.extUnknown=function(){return new this(406,arguments,"Unknown extension").toString()};Faye.Error.publishFailed=function(){return new this(407,arguments,"Failed to publish").toString()};Faye.Error.serverError=function(){return new this(500,arguments,"Internal server error").toString()};Faye.Deferrable={callback:function(a,b){if(!a)return;if(this._v==='succeeded')return a.apply(b,this._j);this._k=this._k||[];this._k.push([a,b])},timeout:function(a,b){var d=this;var f=Faye.ENV.setTimeout(function(){d.setDeferredStatus('failed',b)},a*1000);this._w=f},errback:function(a,b){if(!a)return;if(this._v==='failed')return a.apply(b,this._j);this._l=this._l||[];this._l.push([a,b])},setDeferredStatus:function(){if(this._w)Faye.ENV.clearTimeout(this._w);var a=Array.prototype.slice.call(arguments),b=a.shift(),d;this._v=b;this._j=a;if(b==='succeeded')d=this._k;else if(b==='failed')d=this._l;if(!d)return;var f;while(f=d.shift())f[0].apply(f[1],this._j)}};Faye.Publisher={countListeners:function(a){if(!this._4||!this._4[a])return 0;return this._4[a].length},bind:function(a,b,d){this._4=this._4||{};var f=this._4[a]=this._4[a]||[];f.push([b,d])},unbind:function(a,b,d){if(!this._4||!this._4[a])return;if(!b){delete this._4[a];return}var f=this._4[a],g=f.length;while(g--){if(b!==f[g][0])continue;if(d&&f[g][1]!==d)continue;f.splice(g,1)}},trigger:function(){var a=Array.prototype.slice.call(arguments),b=a.shift();if(!this._4||!this._4[b])return;var d=this._4[b].slice(),f;for(var g=0,h=d.length;g<h;g++){f=d[g];f[0].apply(f[1],a)}}};Faye.Timeouts={addTimeout:function(a,b,d,f){this._6=this._6||{};if(this._6.hasOwnProperty(a))return;var g=this;this._6[a]=Faye.ENV.setTimeout(function(){delete g._6[a];d.call(f)},1000*b)},removeTimeout:function(a){this._6=this._6||{};var b=this._6[a];if(!b)return;clearTimeout(b);delete this._6[a]}};Faye.Logging={LOG_LEVELS:{error:3,warn:2,info:1,debug:0},logLevel:'error',log:function(a,b){if(!Faye.logger)return;var d=Faye.Logging.LOG_LEVELS;if(d[Faye.Logging.logLevel]>d[b])return;var a=Array.prototype.slice.apply(a),f=' ['+b.toUpperCase()+'] [Faye',g=this.className,h=a.shift().replace(/\?/g,function(){try{return Faye.toJSON(a.shift())}catch(e){return'[Object]'}});for(var i in Faye){if(g)continue;if(typeof Faye[i]!=='function')continue;if(this instanceof Faye[i])g=i}if(g)f+='.'+g;f+='] ';Faye.logger(Faye.timestamp()+f+h)}};(function(){for(var d in Faye.Logging.LOG_LEVELS)(function(a,b){Faye.Logging[a]=function(){this.log(arguments,a)}})(d,Faye.Logging.LOG_LEVELS[d])})();Faye.Grammar={LOWALPHA:/^[a-z]$/,UPALPHA:/^[A-Z]$/,ALPHA:/^([a-z]|[A-Z])$/,DIGIT:/^[0-9]$/,ALPHANUM:/^(([a-z]|[A-Z])|[0-9])$/,MARK:/^(\-|\_|\!|\~|\(|\)|\$|\@)$/,STRING:/^(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)| |\/|\*|\.))*$/,TOKEN:/^(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)))+$/,INTEGER:/^([0-9])+$/,CHANNEL_SEGMENT:/^(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)))+$/,CHANNEL_SEGMENTS:/^(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)))+(\/(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)))+)*$/,CHANNEL_NAME:/^\/(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)))+(\/(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)))+)*$/,WILD_CARD:/^\*{1,2}$/,CHANNEL_PATTERN:/^(\/(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)))+)*\/\*{1,2}$/,VERSION_ELEMENT:/^(([a-z]|[A-Z])|[0-9])(((([a-z]|[A-Z])|[0-9])|\-|\_))*$/,VERSION:/^([0-9])+(\.(([a-z]|[A-Z])|[0-9])(((([a-z]|[A-Z])|[0-9])|\-|\_))*)*$/,CLIENT_ID:/^((([a-z]|[A-Z])|[0-9]))+$/,ID:/^((([a-z]|[A-Z])|[0-9]))+$/,ERROR_MESSAGE:/^(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)| |\/|\*|\.))*$/,ERROR_ARGS:/^(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)| |\/|\*|\.))*(,(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)| |\/|\*|\.))*)*$/,ERROR_CODE:/^[0-9][0-9][0-9]$/,ERROR:/^([0-9][0-9][0-9]:(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)| |\/|\*|\.))*(,(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)| |\/|\*|\.))*)*:(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)| |\/|\*|\.))*|[0-9][0-9][0-9]::(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)| |\/|\*|\.))*)$/};Faye.Extensible={addExtension:function(a){this._7=this._7||[];this._7.push(a);if(a.added)a.added(this)},removeExtension:function(a){if(!this._7)return;var b=this._7.length;while(b--){if(this._7[b]!==a)continue;this._7.splice(b,1);if(a.removed)a.removed(this)}},pipeThroughExtensions:function(d,f,g,h){this.debug('Passing through ? extensions: ?',d,f);if(!this._7)return g.call(h,f);var i=this._7.slice();var k=function(a){if(!a)return g.call(h,a);var b=i.shift();if(!b)return g.call(h,a);if(b[d])b[d](a,k);else k(a)};k(f)}};Faye.extend(Faye.Extensible,Faye.Logging);Faye.Channel=Faye.Class({initialize:function(a){this.id=this.name=a},push:function(a){this.trigger('message',a)},isUnused:function(){return this.countListeners('message')===0}});Faye.extend(Faye.Channel.prototype,Faye.Publisher);Faye.extend(Faye.Channel,{HANDSHAKE:'/meta/handshake',CONNECT:'/meta/connect',SUBSCRIBE:'/meta/subscribe',UNSUBSCRIBE:'/meta/unsubscribe',DISCONNECT:'/meta/disconnect',META:'meta',SERVICE:'service',expand:function(a){var b=this.parse(a),d=['/**',a];var f=b.slice();f[f.length-1]='*';d.push(this.unparse(f));for(var g=1,h=b.length;g<h;g++){f=b.slice(0,g);f.push('**');d.push(this.unparse(f))}return d},isValid:function(a){return Faye.Grammar.CHANNEL_NAME.test(a)||Faye.Grammar.CHANNEL_PATTERN.test(a)},parse:function(a){if(!this.isValid(a))return null;return a.split('/').slice(1)},unparse:function(a){return'/'+a.join('/')},isMeta:function(a){var b=this.parse(a);return b?(b[0]===this.META):null},isService:function(a){var b=this.parse(a);return b?(b[0]===this.SERVICE):null},isSubscribable:function(a){if(!this.isValid(a))return null;return!this.isMeta(a)&&!this.isService(a)},Set:Faye.Class({initialize:function(){this._2={}},getKeys:function(){var a=[];for(var b in this._2)a.push(b);return a},remove:function(a){delete this._2[a]},hasSubscription:function(a){return this._2.hasOwnProperty(a)},subscribe:function(a,b,d){if(!b)return;var f;for(var g=0,h=a.length;g<h;g++){f=a[g];var i=this._2[f]=this._2[f]||new Faye.Channel(f);i.bind('message',b,d)}},unsubscribe:function(a,b,d){var f=this._2[a];if(!f)return false;f.unbind('message',b,d);if(f.isUnused()){this.remove(a);return true}else{return false}},distributeMessage:function(a){var b=Faye.Channel.expand(a.channel);for(var d=0,f=b.length;d<f;d++){var g=this._2[b[d]];if(g)g.trigger('message',a.data)}}})});Faye.Publication=Faye.Class(Faye.Deferrable);Faye.Subscription=Faye.Class({initialize:function(a,b,d,f){this._8=a;this._2=b;this._m=d;this._n=f;this._x=false},cancel:function(){if(this._x)return;this._8.unsubscribe(this._2,this._m,this._n);this._x=true},unsubscribe:function(){this.cancel()}});Faye.extend(Faye.Subscription.prototype,Faye.Deferrable);Faye.Client=Faye.Class({UNCONNECTED:1,CONNECTING:2,CONNECTED:3,DISCONNECTED:4,HANDSHAKE:'handshake',RETRY:'retry',NONE:'none',CONNECTION_TIMEOUT:60.0,DEFAULT_RETRY:5.0,DEFAULT_ENDPOINT:'/bayeux',INTERVAL:0.0,initialize:function(a,b){this.info('New client created for ?',a);this._f=b||{};this.endpoint=a||this.DEFAULT_ENDPOINT;this.endpoints=this._f.endpoints||{};this.transports={};this._D=Faye.CookieJar&&new Faye.CookieJar();this._y={};this._o=[];this.retry=this._f.retry||this.DEFAULT_RETRY;this._1=this.UNCONNECTED;this._2=new Faye.Channel.Set();this._g=0;this._p={};this._9={reconnect:this.RETRY,interval:1000*(this._f.interval||this.INTERVAL),timeout:1000*(this._f.timeout||this.CONNECTION_TIMEOUT)};if(Faye.Event)Faye.Event.on(Faye.ENV,'beforeunload',function(){if(Faye.indexOf(this._o,'autodisconnect')<0)this.disconnect()},this)},disable:function(a){this._o.push(a)},setHeader:function(a,b){this._y[a]=b},getClientId:function(){return this._0},getState:function(){switch(this._1){case this.UNCONNECTED:return'UNCONNECTED';case this.CONNECTING:return'CONNECTING';case this.CONNECTED:return'CONNECTED';case this.DISCONNECTED:return'DISCONNECTED'}},handshake:function(b,d){if(this._9.reconnect===this.NONE)return;if(this._1!==this.UNCONNECTED)return;this._1=this.CONNECTING;var f=this;this.info('Initiating handshake with ?',this.endpoint);this._z(Faye.MANDATORY_CONNECTION_TYPES);this._a({channel:Faye.Channel.HANDSHAKE,version:Faye.BAYEUX_VERSION,supportedConnectionTypes:[this._5.connectionType]},function(a){if(a.successful){this._1=this.CONNECTED;this._0=a.clientId;this._z(a.supportedConnectionTypes);this.info('Handshake successful: ?',this._0);this.subscribe(this._2.getKeys(),true);if(b)b.call(d)}else{this.info('Handshake unsuccessful');Faye.ENV.setTimeout(function(){f.handshake(b,d)},this._9.interval);this._1=this.UNCONNECTED}},this)},connect:function(a,b){if(this._9.reconnect===this.NONE)return;if(this._1===this.DISCONNECTED)return;if(this._1===this.UNCONNECTED)return this.handshake(function(){this.connect(a,b)},this);this.callback(a,b);if(this._1!==this.CONNECTED)return;this.info('Calling deferred actions for ?',this._0);this.setDeferredStatus('succeeded');this.setDeferredStatus('deferred');if(this._q)return;this._q=true;this.info('Initiating connection for ?',this._0);this._a({channel:Faye.Channel.CONNECT,clientId:this._0,connectionType:this._5.connectionType},this._A,this)},disconnect:function(){if(this._1!==this.CONNECTED)return;this._1=this.DISCONNECTED;this.info('Disconnecting ?',this._0);this._a({channel:Faye.Channel.DISCONNECT,clientId:this._0},function(a){if(a.successful)this._5.close()},this);this.info('Clearing channel listeners for ?',this._0);this._2=new Faye.Channel.Set()},subscribe:function(d,f,g){if(d instanceof Array)return Faye.map(d,function(c){return this.subscribe(c,f,g)},this);var h=new Faye.Subscription(this,d,f,g),i=(f===true),k=this._2.hasSubscription(d);if(k&&!i){this._2.subscribe([d],f,g);h.setDeferredStatus('succeeded');return h}this.connect(function(){this.info('Client ? attempting to subscribe to ?',this._0,d);if(!i)this._2.subscribe([d],f,g);this._a({channel:Faye.Channel.SUBSCRIBE,clientId:this._0,subscription:d},function(a){if(!a.successful){h.setDeferredStatus('failed',Faye.Error.parse(a.error));return this._2.unsubscribe(d,f,g)}var b=[].concat(a.subscription);this.info('Subscription acknowledged for ? to ?',this._0,b);h.setDeferredStatus('succeeded')},this)},this);return h},unsubscribe:function(d,f,g){if(d instanceof Array)return Faye.map(d,function(c){return this.unsubscribe(c,f,g)},this);var h=this._2.unsubscribe(d,f,g);if(!h)return;this.connect(function(){this.info('Client ? attempting to unsubscribe from ?',this._0,d);this._a({channel:Faye.Channel.UNSUBSCRIBE,clientId:this._0,subscription:d},function(a){if(!a.successful)return;var b=[].concat(a.subscription);this.info('Unsubscription acknowledged for ? from ?',this._0,b)},this)},this)},publish:function(b,d){var f=new Faye.Publication();this.connect(function(){this.info('Client ? queueing published message to ?: ?',this._0,b,d);this._a({channel:b,data:d,clientId:this._0},function(a){if(a.successful)f.setDeferredStatus('succeeded');else f.setDeferredStatus('failed',Faye.Error.parse(a.error))},this)},this);return f},receiveMessage:function(d){this.pipeThroughExtensions('incoming',d,function(a){if(!a)return;if(a.advice)this._E(a.advice);this._F(a);if(a.successful===undefined)return;var b=this._p[a.id];if(!b)return;delete this._p[a.id];b[0].call(b[1],a)},this)},_z:function(b){Faye.Transport.get(this,b,this._o,function(a){this.debug('Selected ? transport for ?',a.connectionType,a.endpoint);if(a===this._5)return;if(this._5)this._5.close();this._5=a;this._5.cookies=this._D;this._5.headers=this._y;a.bind('down',function(){if(this._b!==undefined&&!this._b)return;this._b=false;this.trigger('transport:down')},this);a.bind('up',function(){if(this._b!==undefined&&this._b)return;this._b=true;this.trigger('transport:up')},this)},this)},_a:function(b,d,f){b.id=this._G();if(d)this._p[b.id]=[d,f];this.pipeThroughExtensions('outgoing',b,function(a){if(!a)return;this._5.send(a,this._9.timeout/1000)},this)},_G:function(){this._g+=1;if(this._g>=Math.pow(2,32))this._g=0;return this._g.toString(36)},_E:function(a){Faye.extend(this._9,a);if(this._9.reconnect===this.HANDSHAKE&&this._1!==this.DISCONNECTED){this._1=this.UNCONNECTED;this._0=null;this._A()}},_F:function(a){if(!a.channel||a.data===undefined)return;this.info('Client ? calling listeners for ? with ?',this._0,a.channel,a.data);this._2.distributeMessage(a)},_H:function(){if(!this._q)return;this._q=null;this.info('Closed connection for ?',this._0)},_A:function(){this._H();var a=this;Faye.ENV.setTimeout(function(){a.connect()},this._9.interval)}});Faye.extend(Faye.Client.prototype,Faye.Deferrable);Faye.extend(Faye.Client.prototype,Faye.Publisher);Faye.extend(Faye.Client.prototype,Faye.Logging);Faye.extend(Faye.Client.prototype,Faye.Extensible);Faye.Transport=Faye.extend(Faye.Class({MAX_DELAY:0.0,batching:true,initialize:function(a,b){this._8=a;this.endpoint=b;this._c=[]},close:function(){},send:function(a,b){this.debug('Client ? sending message to ?: ?',this._8._0,this.endpoint,a);if(!this.batching)return this.request([a],b);this._c.push(a);this._I=b;if(a.channel===Faye.Channel.HANDSHAKE)return this.addTimeout('publish',0.01,this.flush,this);if(a.channel===Faye.Channel.CONNECT)this._r=a;if(this.shouldFlush&&this.shouldFlush(this._c))return this.flush();this.addTimeout('publish',this.MAX_DELAY,this.flush,this)},flush:function(){this.removeTimeout('publish');if(this._c.length>1&&this._r)this._r.advice={timeout:0};this.request(this._c,this._I);this._r=null;this._c=[]},receive:function(a){this.debug('Client ? received from ?: ?',this._8._0,this.endpoint,a);for(var b=0,d=a.length;b<d;b++){this._8.receiveMessage(a[b])}},retry:function(a,b){var d=false,f=this._8.retry*1000,g=this;return function(){if(d)return;d=true;Faye.ENV.setTimeout(function(){g.request(a,b)},f)}}}),{MAX_URL_LENGTH:2048,get:function(k,j,m,n,o){var l=k.endpoint;Faye.asyncEach(this._B,function(d,f){var g=d[0],h=d[1],i=k.endpoints[g]||l;if(Faye.indexOf(m,g)>=0)return f();if(Faye.indexOf(j,g)<0){h.isUsable(k,i,function(){});return f()}h.isUsable(k,i,function(a){if(!a)return f();var b=h.hasOwnProperty('create')?h.create(k,i):new h(k,i);n.call(o,b)})},function(){throw new Error('Could not find a usable connection type for '+l);})},register:function(a,b){this._B.push([a,b]);b.prototype.connectionType=a},_B:[]});Faye.extend(Faye.Transport.prototype,Faye.Logging);Faye.extend(Faye.Transport.prototype,Faye.Publisher);Faye.extend(Faye.Transport.prototype,Faye.Timeouts);Faye.Event={_h:[],on:function(a,b,d,f){var g=function(){d.call(f)};if(a.addEventListener)a.addEventListener(b,g,false);else a.attachEvent('on'+b,g);this._h.push({_i:a,_s:b,_m:d,_n:f,_C:g})},detach:function(a,b,d,f){var g=this._h.length,h;while(g--){h=this._h[g];if((a&&a!==h._i)||(b&&b!==h._s)||(d&&d!==h._m)||(f&&f!==h._n))continue;if(h._i.removeEventListener)h._i.removeEventListener(h._s,h._C,false);else h._i.detachEvent('on'+h._s,h._C);this._h.splice(g,1);h=null}}};Faye.Event.on(Faye.ENV,'unload',Faye.Event.detach,Faye.Event);Faye.URI=Faye.extend(Faye.Class({queryString:function(){var a=[];for(var b in this.params){if(!this.params.hasOwnProperty(b))continue;a.push(encodeURIComponent(b)+'='+encodeURIComponent(this.params[b]))}return a.join('&')},isSameOrigin:function(){var a=Faye.URI.parse(Faye.ENV.location.href,false);var b=(a.hostname!==this.hostname)||(a.port!==this.port)||(a.protocol!==this.protocol);return!b},toURL:function(){var a=this.queryString();return this.protocol+'//'+this.hostname+(this.port?':'+this.port:'')+this.pathname+(a?'?'+a:'')+this.hash}}),{parse:function(g,h){if(typeof g!=='string')return g;var i=new this(),k;var j=function(b,d,f){g=g.replace(d,function(a){i[b]=a;return''});if(i[b]===undefined)i[b]=f?Faye.ENV.location[b]:''};j('protocol',/^https?\:/,true);j('host',/^\/\/[^\/]+/,true);if(!/^\//.test(g))g=Faye.ENV.location.pathname.replace(/[^\/]*$/,'')+g;j('pathname',/^\/[^\?#]*/);j('search',/^\?[^#]*/);j('hash',/^#.*/);if(/^\/\//.test(i.host)){i.host=i.host.substr(2);k=i.host.split(':');i.hostname=k[0];i.port=k[1]||''}else{i.hostname=Faye.ENV.location.hostname;i.port=Faye.ENV.location.port}if(h===false){i.params={}}else{var m=i.search.replace(/^\?/,''),n=m?m.split('&'):[],o=n.length,l={};while(o--){k=n[o].split('=');l[decodeURIComponent(k[0]||'')]=decodeURIComponent(k[1]||'')}if(typeof h==='object')Faye.extend(l,h);i.params=l}return i}});if(!this.JSON){JSON={}}(function(){function m(a){return a<10?'0'+a:a}if(typeof Date.prototype.toJSON!=='function'){Date.prototype.toJSON=function(a){return this.getUTCFullYear()+'-'+m(this.getUTCMonth()+1)+'-'+m(this.getUTCDate())+'T'+m(this.getUTCHours())+':'+m(this.getUTCMinutes())+':'+m(this.getUTCSeconds())+'Z'};String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(a){return this.valueOf()}}var n=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,o=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,l,q,t={'\b':'\\b','\t':'\\t','\n':'\\n','\f':'\\f','\r':'\\r','"':'\\"','\\':'\\\\'},p;function s(d){o.lastIndex=0;return o.test(d)?'"'+d.replace(o,function(a){var b=t[a];return typeof b==='string'?b:'\\u'+('0000'+a.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+d+'"'}function r(a,b){var d,f,g,h,i=l,k,j=b[a];if(j&&typeof j==='object'&&typeof j.toJSON==='function'){j=j.toJSON(a)}if(typeof p==='function'){j=p.call(b,a,j)}switch(typeof j){case'string':return s(j);case'number':return isFinite(j)?String(j):'null';case'boolean':case'null':return String(j);case'object':if(!j){return'null'}l+=q;k=[];if(Object.prototype.toString.apply(j)==='[object Array]'){h=j.length;for(d=0;d<h;d+=1){k[d]=r(d,j)||'null'}g=k.length===0?'[]':l?'[\n'+l+k.join(',\n'+l)+'\n'+i+']':'['+k.join(',')+']';l=i;return g}if(p&&typeof p==='object'){h=p.length;for(d=0;d<h;d+=1){f=p[d];if(typeof f==='string'){g=r(f,j);if(g){k.push(s(f)+(l?': ':':')+g)}}}}else{for(f in j){if(Object.hasOwnProperty.call(j,f)){g=r(f,j);if(g){k.push(s(f)+(l?': ':':')+g)}}}}g=k.length===0?'{}':l?'{\n'+l+k.join(',\n'+l)+'\n'+i+'}':'{'+k.join(',')+'}';l=i;return g}}Faye.stringify=function(a,b,d){var f;l='';q='';if(typeof d==='number'){for(f=0;f<d;f+=1){q+=' '}}else if(typeof d==='string'){q=d}p=b;if(b&&typeof b!=='function'&&(typeof b!=='object'||typeof b.length!=='number')){throw new Error('JSON.stringify');}return r('',{'':a})};if(typeof JSON.stringify!=='function'){JSON.stringify=Faye.stringify}if(typeof JSON.parse!=='function'){JSON.parse=function(h,i){var k;function j(a,b){var d,f,g=a[b];if(g&&typeof g==='object'){for(d in g){if(Object.hasOwnProperty.call(g,d)){f=j(g,d);if(f!==undefined){g[d]=f}else{delete g[d]}}}}return i.call(a,b,g)}n.lastIndex=0;if(n.test(h)){h=h.replace(n,function(a){return'\\u'+('0000'+a.charCodeAt(0).toString(16)).slice(-4)})}if(/^[\],:{}\s]*$/.test(h.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,'@').replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,']').replace(/(?:^|:|,)(?:\s*\[)+/g,''))){k=eval('('+h+')');return typeof i==='function'?j({'':k},''):k}throw new SyntaxError('JSON.parse');}}}());Faye.Transport.WebSocket=Faye.extend(Faye.Class(Faye.Transport,{UNCONNECTED:1,CONNECTING:2,CONNECTED:3,batching:false,isUsable:function(a,b){this.callback(function(){a.call(b,true)});this.errback(function(){a.call(b,false)});this.connect()},request:function(b,d){if(b.length===0)return;this._d=this._d||{};for(var f=0,g=b.length;f<g;f++){this._d[b[f].id]=b[f]}this.callback(function(a){a.send(Faye.toJSON(b))});this.connect()},close:function(){if(!this._3)return;this._3.onclose=this._3.onerror=null;this._3.close();delete this._3;this.setDeferredStatus('deferred');this._1=this.UNCONNECTED},connect:function(){if(Faye.Transport.WebSocket._J)return;this._1=this._1||this.UNCONNECTED;if(this._1!==this.UNCONNECTED)return;this._1=this.CONNECTING;var g=Faye.Transport.WebSocket.getClass();if(!g)return this.setDeferredStatus('failed');this._3=new g(Faye.Transport.WebSocket.getSocketUrl(this.endpoint));var h=this;this._3.onopen=function(){h._1=h.CONNECTED;h._t=true;h.setDeferredStatus('succeeded',h._3);h.trigger('up')};this._3.onmessage=function(a){var b=JSON.parse(a.data);if(!b)return;b=[].concat(b);for(var d=0,f=b.length;d<f;d++){delete h._d[b[d].id]}h.receive(b)};this._3.onclose=this._3.onerror=function(){var a=(h._1===h.CONNECTED);h.setDeferredStatus('deferred');h._1=h.UNCONNECTED;h.close();if(a)return h.resend();if(!h._t)return h.setDeferredStatus('failed');var b=h._8.retry*1000;Faye.ENV.setTimeout(function(){h.connect()},b);h.trigger('down')}},resend:function(){if(!this._d)return;var d=Faye.map(this._d,function(a,b){return b});this.request(d)}}),{getSocketUrl:function(a){if(Faye.URI)a=Faye.URI.parse(a).toURL();return a.replace(/^http(s?):/ig,'ws$1:')},getClass:function(){return(Faye.WebSocket&&Faye.WebSocket.Client)||Faye.ENV.WebSocket||Faye.ENV.MozWebSocket},isUsable:function(a,b,d,f){this.create(a,b).isUsable(d,f)},create:function(a,b){var d=a.transports.websocket=a.transports.websocket||{};d[b]=d[b]||new this(a,b);return d[b]}});Faye.extend(Faye.Transport.WebSocket.prototype,Faye.Deferrable);Faye.Transport.register('websocket',Faye.Transport.WebSocket);if(Faye.Event)Faye.Event.on(Faye.ENV,'beforeunload',function(){Faye.Transport.WebSocket._J=true});Faye.Transport.EventSource=Faye.extend(Faye.Class(Faye.Transport,{initialize:function(b,d){Faye.Transport.prototype.initialize.call(this,b,d);if(!Faye.ENV.EventSource)return this.setDeferredStatus('failed');this._K=new Faye.Transport.XHR(b,d);var f=new EventSource(d+'/'+b.getClientId()),g=this;f.onopen=function(){g._t=true;g.setDeferredStatus('succeeded');g.trigger('up')};f.onerror=function(){if(g._t){g.trigger('down')}else{g.setDeferredStatus('failed');f.close()}};f.onmessage=function(a){g.receive(JSON.parse(a.data));g.trigger('up')};this._3=f},isUsable:function(a,b){this.callback(function(){a.call(b,true)});this.errback(function(){a.call(b,false)})},request:function(a,b){this._K.request(a,b)},close:function(){if(!this._3)return;this._3.onerror=null;this._3.close();delete this._3}}),{isUsable:function(b,d,f,g){var h=b.getClientId();if(!h)return f.call(g,false);Faye.Transport.XHR.isUsable(b,d,function(a){if(!a)return f.call(g,false);this.create(b,d).isUsable(f,g)},this)},create:function(a,b){var d=a.transports.eventsource=a.transports.eventsource||{},f=a.getClientId(),b=b+'/'+(f||'');d[b]=d[b]||new this(a,b);return d[b]}});Faye.extend(Faye.Transport.EventSource.prototype,Faye.Deferrable);Faye.Transport.register('eventsource',Faye.Transport.EventSource);Faye.Transport.XHR=Faye.extend(Faye.Class(Faye.Transport,{request:function(f,g){var h=this.retry(f,g),i=Faye.URI.parse(this.endpoint).pathname,k=this,j=Faye.ENV.ActiveXObject?new ActiveXObject("Microsoft.XMLHTTP"):new XMLHttpRequest();j.open('POST',i,true);j.setRequestHeader('Content-Type','application/json');j.setRequestHeader('Pragma','no-cache');j.setRequestHeader('X-Requested-With','XMLHttpRequest');var m=this.headers;for(var n in m){if(!m.hasOwnProperty(n))continue;j.setRequestHeader(n,m[n])}var o=function(){j.abort()};Faye.Event.on(Faye.ENV,'beforeunload',o);var l=function(){Faye.Event.detach(Faye.ENV,'beforeunload',o);j.onreadystatechange=function(){};j=null};j.onreadystatechange=function(){if(j.readyState!==4)return;var a=null,b=j.status,d=((b>=200&&b<300)||b===304||b===1223);if(!d){l();h();return k.trigger('down')}try{a=JSON.parse(j.responseText)}catch(e){}l();if(a){k.receive(a);k.trigger('up')}else{h();k.trigger('down')}};j.send(Faye.toJSON(f))}}),{isUsable:function(a,b,d,f){d.call(f,Faye.URI.parse(b).isSameOrigin())}});Faye.Transport.register('long-polling',Faye.Transport.XHR);Faye.Transport.CORS=Faye.extend(Faye.Class(Faye.Transport,{request:function(b,d){var f=Faye.ENV.XDomainRequest?XDomainRequest:XMLHttpRequest,g=new f(),h=this.retry(b,d),i=this;g.open('POST',this.endpoint,true);if(g.setRequestHeader)g.setRequestHeader('Pragma','no-cache');var k=function(){if(!g)return false;g.onload=g.onerror=g.ontimeout=g.onprogress=null;g=null;Faye.ENV.clearTimeout(m);return true};g.onload=function(){var a=null;try{a=JSON.parse(g.responseText)}catch(e){}k();if(a){i.receive(a);i.trigger('up')}else{h();i.trigger('down')}};var j=function(){k();h();i.trigger('down')};var m=Faye.ENV.setTimeout(j,1.5*1000*d);g.onerror=j;g.ontimeout=j;g.onprogress=function(){};g.send('message='+encodeURIComponent(Faye.toJSON(b)))}}),{isUsable:function(a,b,d,f){if(Faye.URI.parse(b).isSameOrigin())return d.call(f,false);if(Faye.ENV.XDomainRequest)return d.call(f,Faye.URI.parse(b).protocol===Faye.URI.parse(Faye.ENV.location).protocol);if(Faye.ENV.XMLHttpRequest){var g=new Faye.ENV.XMLHttpRequest();return d.call(f,g.withCredentials!==undefined)}return d.call(f,false)}});Faye.Transport.register('cross-origin-long-polling',Faye.Transport.CORS);Faye.Transport.JSONP=Faye.extend(Faye.Class(Faye.Transport,{shouldFlush:function(a){var b={message:Faye.toJSON(a),jsonp:'__jsonp'+Faye.Transport.JSONP._u+'__'};var d=Faye.URI.parse(this.endpoint,b).toURL();return d.length>=Faye.Transport.MAX_URL_LENGTH},request:function(b,d){var f={message:Faye.toJSON(b)},g=document.getElementsByTagName('head')[0],h=document.createElement('script'),i=Faye.Transport.JSONP.getCallbackName(),k=Faye.URI.parse(this.endpoint,f),j=this.retry(b,d),m=this;Faye.ENV[i]=function(a){o();m.receive(a);m.trigger('up')};var n=Faye.ENV.setTimeout(function(){o();j();m.trigger('down')},1.5*1000*d);var o=function(){if(!Faye.ENV[i])return false;Faye.ENV[i]=undefined;try{delete Faye.ENV[i]}catch(e){}Faye.ENV.clearTimeout(n);h.parentNode.removeChild(h);return true};k.params.jsonp=i;h.type='text/javascript';h.src=k.toURL();g.appendChild(h)}}),{_u:0,getCallbackName:function(){this._u+=1;return'__jsonp'+this._u+'__'},isUsable:function(a,b,d,f){d.call(f,true)}});Faye.Transport.register('callback-polling',Faye.Transport.JSONP);
2
+ !function(){"use strict";var Faye={VERSION:"1.0.1",BAYEUX_VERSION:"1.0",ID_LENGTH:160,JSONP_CALLBACK:"jsonpcallback",CONNECTION_TYPES:["long-polling","cross-origin-long-polling","callback-polling","websocket","eventsource","in-process"],MANDATORY_CONNECTION_TYPES:["long-polling","callback-polling","in-process"],ENV:"undefined"!=typeof window?window:global,extend:function(e,t,n){if(!t)return e;for(var i in t)t.hasOwnProperty(i)&&(e.hasOwnProperty(i)&&n===!1||e[i]!==t[i]&&(e[i]=t[i]));return e},random:function(e){return e=e||this.ID_LENGTH,csprng(e,36)},clientIdFromMessages:function(e){var t=this.filter([].concat(e),function(e){return"/meta/connect"===e.channel});return t[0]&&t[0].clientId},copyObject:function(e){var t,n,i;if(e instanceof Array){for(t=[],n=e.length;n--;)t[n]=Faye.copyObject(e[n]);return t}if("object"==typeof e){t=null===e?null:{};for(i in e)t[i]=Faye.copyObject(e[i]);return t}return e},commonElement:function(e,t){for(var n=0,i=e.length;i>n;n++)if(-1!==this.indexOf(t,e[n]))return e[n];return null},indexOf:function(e,t){if(e.indexOf)return e.indexOf(t);for(var n=0,i=e.length;i>n;n++)if(e[n]===t)return n;return-1},map:function(e,t,n){if(e.map)return e.map(t,n);var i=[];if(e instanceof Array)for(var s=0,r=e.length;r>s;s++)i.push(t.call(n||null,e[s],s));else for(var o in e)e.hasOwnProperty(o)&&i.push(t.call(n||null,o,e[o]));return i},filter:function(e,t,n){if(e.filter)return e.filter(t,n);for(var i=[],s=0,r=e.length;r>s;s++)t.call(n||null,e[s],s)&&i.push(e[s]);return i},asyncEach:function(e,t,n,i){var s=e.length,r=-1,o=0,a=!1,c=function(){return o-=1,r+=1,r===s?n&&n.call(i):(t(e[r],h),void 0)},u=function(){if(!a){for(a=!0;o>0;)c();a=!1}},h=function(){o+=1,u()};h()},toJSON:function(e){return this.stringify?this.stringify(e,function(e,t){return this[e]instanceof Array?this[e]:t}):JSON.stringify(e)}};"undefined"!=typeof module?module.exports=Faye:"undefined"!=typeof window&&(window.Faye=Faye),Faye.Class=function(e,t){"function"!=typeof e&&(t=e,e=Object);var n=function(){return this.initialize?this.initialize.apply(this,arguments)||this:this},i=function(){};return i.prototype=e.prototype,n.prototype=new i,Faye.extend(n.prototype,t),n},function(){function e(e,t){if(e.indexOf)return e.indexOf(t);for(var n=0;n<e.length;n++)if(t===e[n])return n;return-1}var t=Faye.EventEmitter=function(){},n="function"==typeof Array.isArray?Array.isArray:function(e){return"[object Array]"===Object.prototype.toString.call(e)};t.prototype.emit=function(e){if("error"===e&&(!this._events||!this._events.error||n(this._events.error)&&!this._events.error.length))throw arguments[1]instanceof Error?arguments[1]:Error("Uncaught, unspecified 'error' event.");if(!this._events)return!1;var t=this._events[e];if(!t)return!1;if("function"==typeof t){switch(arguments.length){case 1:t.call(this);break;case 2:t.call(this,arguments[1]);break;case 3:t.call(this,arguments[1],arguments[2]);break;default:var i=Array.prototype.slice.call(arguments,1);t.apply(this,i)}return!0}if(n(t)){for(var i=Array.prototype.slice.call(arguments,1),s=t.slice(),r=0,o=s.length;o>r;r++)s[r].apply(this,i);return!0}return!1},t.prototype.addListener=function(e,t){if("function"!=typeof t)throw Error("addListener only takes instances of Function");return this._events||(this._events={}),this.emit("newListener",e,t),this._events[e]?n(this._events[e])?this._events[e].push(t):this._events[e]=[this._events[e],t]:this._events[e]=t,this},t.prototype.on=t.prototype.addListener,t.prototype.once=function(e,t){var n=this;return n.on(e,function i(){n.removeListener(e,i),t.apply(this,arguments)}),this},t.prototype.removeListener=function(t,i){if("function"!=typeof i)throw Error("removeListener only takes instances of Function");if(!this._events||!this._events[t])return this;var s=this._events[t];if(n(s)){var r=e(s,i);if(0>r)return this;s.splice(r,1),0==s.length&&delete this._events[t]}else this._events[t]===i&&delete this._events[t];return this},t.prototype.removeAllListeners=function(e){return 0===arguments.length?(this._events={},this):(e&&this._events&&this._events[e]&&(this._events[e]=null),this)},t.prototype.listeners=function(e){return this._events||(this._events={}),this._events[e]||(this._events[e]=[]),n(this._events[e])||(this._events[e]=[this._events[e]]),this._events[e]}}(),Faye.Namespace=Faye.Class({initialize:function(){this._used={}},exists:function(e){return this._used.hasOwnProperty(e)},generate:function(){for(var e=Faye.random();this._used.hasOwnProperty(e);)e=Faye.random();return this._used[e]=e},release:function(e){delete this._used[e]}}),function(){var e,t=setTimeout;e="function"==typeof setImmediate?function(e){setImmediate(e)}:"object"==typeof process&&process.nextTick?function(e){process.nextTick(e)}:function(e){t(e,0)};var n=0,i=1,s=2,r=function(e){return e},o=function(e){throw e},a=function(e){if(this._state=n,this._callbacks=[],this._errbacks=[],"function"==typeof e){var t=this;e(function(e){f(t,e)},function(e){p(t,e)})}};a.prototype.then=function(e,t){var n={},i=this;return n.promise=new a(function(s,r){n.fulfill=s,n.reject=r,c(i,e,n),u(i,t,n)}),n.promise};var c=function(e,t,s){"function"!=typeof t&&(t=r);var o=function(e){h(t,e,s)};e._state===n?e._callbacks.push(o):e._state===i&&o(e._value)},u=function(e,t,i){"function"!=typeof t&&(t=o);var r=function(e){h(t,e,i)};e._state===n?e._errbacks.push(r):e._state===s&&r(e._reason)},h=function(t,n,i){e(function(){l(t,n,i)})},l=function(e,t,n){var i,s,o,a=!1;try{if(i=e(t),s=typeof i,o=null!==i&&("function"===s||"object"===s)&&i.then,i===n.promise)return n.reject(new TypeError("Recursive promise chain detected"));if("function"!=typeof o)return n.fulfill(i);o.call(i,function(e){a||(a=!0,l(r,e,n))},function(e){a||(a=!0,n.reject(e))})}catch(c){if(a)return;a=!0,n.reject(c)}},f=a.fulfill=a.resolve=function(e,t){if(e._state===n){e._state=i,e._value=t,e._errbacks=[];for(var s,r=e._callbacks;s=r.shift();)s(t)}},p=a.reject=function(e,t){if(e._state===n){e._state=s,e._reason=t,e._callbacks=[];for(var i,r=e._errbacks;i=r.shift();)i(t)}};a.defer=e,a.deferred=a.pending=function(){var e={};return e.promise=new a(function(t,n){e.fulfill=e.resolve=t,e.reject=n}),e},a.fulfilled=a.resolved=function(e){return new a(function(t){t(e)})},a.rejected=function(e){return new a(function(t,n){n(e)})},void 0===Faye?module.exports=a:Faye.Promise=a}(),Faye.Set=Faye.Class({initialize:function(){this._index={}},add:function(e){var t=void 0!==e.id?e.id:e;return this._index.hasOwnProperty(t)?!1:(this._index[t]=e,!0)},forEach:function(e,t){for(var n in this._index)this._index.hasOwnProperty(n)&&e.call(t,this._index[n])},isEmpty:function(){for(var e in this._index)if(this._index.hasOwnProperty(e))return!1;return!0},member:function(e){for(var t in this._index)if(this._index[t]===e)return!0;return!1},remove:function(e){var t=void 0!==e.id?e.id:e,n=this._index[t];return delete this._index[t],n},toArray:function(){var e=[];return this.forEach(function(t){e.push(t)}),e}}),Faye.URI={isURI:function(e){return e&&e.protocol&&e.host&&e.path},isSameOrigin:function(e){var t=Faye.ENV.location;return e.protocol===t.protocol&&e.hostname===t.hostname&&e.port===t.port},parse:function(e){if("string"!=typeof e)return e;var t,n,i,s,r,o,a={},c=function(t,n){e=e.replace(n,function(e){return a[t]=e,""}),a[t]=a[t]||""};for(c("protocol",/^[a-z]+\:/i),c("host",/^\/\/[^\/\?#]+/),/^\//.test(e)||a.host||(e=Faye.ENV.location.pathname.replace(/[^\/]*$/,"")+e),c("pathname",/^[^\?#]*/),c("search",/^\?[^#]*/),c("hash",/^#.*/),a.protocol=a.protocol||Faye.ENV.location.protocol,a.host?(a.host=a.host.substr(2),t=a.host.split(":"),a.hostname=t[0],a.port=t[1]||""):(a.host=Faye.ENV.location.host,a.hostname=Faye.ENV.location.hostname,a.port=Faye.ENV.location.port),a.pathname=a.pathname||"/",a.path=a.pathname+a.search,n=a.search.replace(/^\?/,""),i=n?n.split("&"):[],o={},s=0,r=i.length;r>s;s++)t=i[s].split("="),o[decodeURIComponent(t[0]||"")]=decodeURIComponent(t[1]||"");return a.query=o,a.href=this.stringify(a),a},stringify:function(e){var t=e.protocol+"//"+e.hostname;return e.port&&(t+=":"+e.port),t+=e.pathname+this.queryString(e.query)+(e.hash||"")},queryString:function(e){var t=[];for(var n in e)e.hasOwnProperty(n)&&t.push(encodeURIComponent(n)+"="+encodeURIComponent(e[n]));return 0===t.length?"":"?"+t.join("&")}},Faye.Error=Faye.Class({initialize:function(e,t,n){this.code=e,this.params=Array.prototype.slice.call(t),this.message=n},toString:function(){return this.code+":"+this.params.join(",")+":"+this.message}}),Faye.Error.parse=function(e){if(e=e||"",!Faye.Grammar.ERROR.test(e))return new this(null,[],e);var t=e.split(":"),n=parseInt(t[0]),i=t[1].split(","),e=t[2];return new this(n,i,e)},Faye.Error.versionMismatch=function(){return""+new this(300,arguments,"Version mismatch")},Faye.Error.conntypeMismatch=function(){return""+new this(301,arguments,"Connection types not supported")},Faye.Error.extMismatch=function(){return""+new this(302,arguments,"Extension mismatch")},Faye.Error.badRequest=function(){return""+new this(400,arguments,"Bad request")},Faye.Error.clientUnknown=function(){return""+new this(401,arguments,"Unknown client")},Faye.Error.parameterMissing=function(){return""+new this(402,arguments,"Missing required parameter")},Faye.Error.channelForbidden=function(){return""+new this(403,arguments,"Forbidden channel")},Faye.Error.channelUnknown=function(){return""+new this(404,arguments,"Unknown channel")},Faye.Error.channelInvalid=function(){return""+new this(405,arguments,"Invalid channel")},Faye.Error.extUnknown=function(){return""+new this(406,arguments,"Unknown extension")},Faye.Error.publishFailed=function(){return""+new this(407,arguments,"Failed to publish")},Faye.Error.serverError=function(){return""+new this(500,arguments,"Internal server error")},Faye.Deferrable={then:function(e,t){var n=this;return this._promise||(this._promise=new Faye.Promise(function(e,t){n._fulfill=e,n._reject=t})),0===arguments.length?this._promise:this._promise.then(e,t)},callback:function(e,t){return this.then(function(n){e.call(t,n)})},errback:function(e,t){return this.then(null,function(n){e.call(t,n)})},timeout:function(e,t){this.then();var n=this;this._timer=Faye.ENV.setTimeout(function(){n._reject(t)},1e3*e)},setDeferredStatus:function(e,t){this._timer&&Faye.ENV.clearTimeout(this._timer);this.then();"succeeded"===e?this._fulfill(t):"failed"===e?this._reject(t):delete this._promise}},Faye.Publisher={countListeners:function(e){return this.listeners(e).length},bind:function(e,t,n){var i=Array.prototype.slice,s=function(){t.apply(n,i.call(arguments))};return this._listeners=this._listeners||[],this._listeners.push([e,t,n,s]),this.on(e,s)},unbind:function(e,t,n){this._listeners=this._listeners||[];for(var i,s=this._listeners.length;s--;)i=this._listeners[s],i[0]===e&&(!t||i[1]===t&&i[2]===n)&&(this._listeners.splice(s,1),this.removeListener(e,i[3]))}},Faye.extend(Faye.Publisher,Faye.EventEmitter.prototype),Faye.Publisher.trigger=Faye.Publisher.emit,Faye.Timeouts={addTimeout:function(e,t,n,i){if(this._timeouts=this._timeouts||{},!this._timeouts.hasOwnProperty(e)){var s=this;this._timeouts[e]=Faye.ENV.setTimeout(function(){delete s._timeouts[e],n.call(i)},1e3*t)}},removeTimeout:function(e){this._timeouts=this._timeouts||{};var t=this._timeouts[e];t&&(clearTimeout(t),delete this._timeouts[e])},removeAllTimeouts:function(){this._timeouts=this._timeouts||{};for(var e in this._timeouts)this.removeTimeout(e)}},Faye.Logging={LOG_LEVELS:{fatal:4,error:3,warn:2,info:1,debug:0},writeLog:function(e,t){if(Faye.logger){var e=Array.prototype.slice.apply(e),n="[Faye",i=this.className,s=e.shift().replace(/\?/g,function(){try{return Faye.toJSON(e.shift())}catch(t){return"[Object]"}});for(var r in Faye)i||"function"==typeof Faye[r]&&this instanceof Faye[r]&&(i=r);i&&(n+="."+i),n+="] ","function"==typeof Faye.logger[t]?Faye.logger[t](n+s):"function"==typeof Faye.logger&&Faye.logger(n+s)}}},function(){for(var e in Faye.Logging.LOG_LEVELS)(function(e){Faye.Logging[e]=function(){this.writeLog(arguments,e)}})(e,Faye.Logging.LOG_LEVELS[e])}(),Faye.Grammar={CHANNEL_NAME:/^\/(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)))+(\/(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)))+)*$/,CHANNEL_PATTERN:/^(\/(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)))+)*\/\*{1,2}$/,ERROR:/^([0-9][0-9][0-9]:(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)| |\/|\*|\.))*(,(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)| |\/|\*|\.))*)*:(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)| |\/|\*|\.))*|[0-9][0-9][0-9]::(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)| |\/|\*|\.))*)$/,VERSION:/^([0-9])+(\.(([a-z]|[A-Z])|[0-9])(((([a-z]|[A-Z])|[0-9])|\-|\_))*)*$/},Faye.Extensible={addExtension:function(e){this._extensions=this._extensions||[],this._extensions.push(e),e.added&&e.added(this)},removeExtension:function(e){if(this._extensions)for(var t=this._extensions.length;t--;)this._extensions[t]===e&&(this._extensions.splice(t,1),e.removed&&e.removed(this))},pipeThroughExtensions:function(e,t,n,i,s){if(this.debug("Passing through ? extensions: ?",e,t),!this._extensions)return i.call(s,t);var r=this._extensions.slice(),o=function(t){if(!t)return i.call(s,t);var a=r.shift();if(!a)return i.call(s,t);var c=a[e];return c?(c.length>=3?a[e](t,n,o):a[e](t,o),void 0):o(t)};o(t)}},Faye.extend(Faye.Extensible,Faye.Logging),Faye.Channel=Faye.Class({initialize:function(e){this.id=this.name=e},push:function(e){this.trigger("message",e)},isUnused:function(){return 0===this.countListeners("message")}}),Faye.extend(Faye.Channel.prototype,Faye.Publisher),Faye.extend(Faye.Channel,{HANDSHAKE:"/meta/handshake",CONNECT:"/meta/connect",SUBSCRIBE:"/meta/subscribe",UNSUBSCRIBE:"/meta/unsubscribe",DISCONNECT:"/meta/disconnect",META:"meta",SERVICE:"service",expand:function(e){var t=this.parse(e),n=["/**",e],i=t.slice();i[i.length-1]="*",n.push(this.unparse(i));for(var s=1,r=t.length;r>s;s++)i=t.slice(0,s),i.push("**"),n.push(this.unparse(i));return n},isValid:function(e){return Faye.Grammar.CHANNEL_NAME.test(e)||Faye.Grammar.CHANNEL_PATTERN.test(e)},parse:function(e){return this.isValid(e)?e.split("/").slice(1):null},unparse:function(e){return"/"+e.join("/")},isMeta:function(e){var t=this.parse(e);return t?t[0]===this.META:null},isService:function(e){var t=this.parse(e);return t?t[0]===this.SERVICE:null},isSubscribable:function(e){return this.isValid(e)?!this.isMeta(e)&&!this.isService(e):null},Set:Faye.Class({initialize:function(){this._channels={}},getKeys:function(){var e=[];for(var t in this._channels)e.push(t);return e},remove:function(e){delete this._channels[e]},hasSubscription:function(e){return this._channels.hasOwnProperty(e)},subscribe:function(e,t,n){if(t)for(var i,s=0,r=e.length;r>s;s++){i=e[s];var o=this._channels[i]=this._channels[i]||new Faye.Channel(i);o.bind("message",t,n)}},unsubscribe:function(e,t,n){var i=this._channels[e];return i?(i.unbind("message",t,n),i.isUnused()?(this.remove(e),!0):!1):!1},distributeMessage:function(e){for(var t=Faye.Channel.expand(e.channel),n=0,i=t.length;i>n;n++){var s=this._channels[t[n]];s&&s.trigger("message",e.data)}}})}),Faye.Envelope=Faye.Class({initialize:function(e,t){this.id=e.id,this.message=e,void 0!==t&&this.timeout(t/1e3,!1)}}),Faye.extend(Faye.Envelope.prototype,Faye.Deferrable),Faye.Publication=Faye.Class(Faye.Deferrable),Faye.Subscription=Faye.Class({initialize:function(e,t,n,i){this._client=e,this._channels=t,this._callback=n,this._context=i,this._cancelled=!1},cancel:function(){this._cancelled||(this._client.unsubscribe(this._channels,this._callback,this._context),this._cancelled=!0)},unsubscribe:function(){this.cancel()}}),Faye.extend(Faye.Subscription.prototype,Faye.Deferrable),Faye.Client=Faye.Class({UNCONNECTED:1,CONNECTING:2,CONNECTED:3,DISCONNECTED:4,HANDSHAKE:"handshake",RETRY:"retry",NONE:"none",CONNECTION_TIMEOUT:60,DEFAULT_RETRY:5,MAX_REQUEST_SIZE:2048,DEFAULT_ENDPOINT:"/bayeux",INTERVAL:0,initialize:function(e,t){this.info("New client created for ?",e),this._options=t||{},this.endpoint=Faye.URI.parse(e||this.DEFAULT_ENDPOINT),this.endpoints=this._options.endpoints||{},this.transports={},this.cookies=Faye.CookieJar&&new Faye.CookieJar,this.headers={},this.ca=this._options.ca,this._disabled=[],this._retry=this._options.retry||this.DEFAULT_RETRY;for(var n in this.endpoints)this.endpoints[n]=Faye.URI.parse(this.endpoints[n]);this.maxRequestSize=this.MAX_REQUEST_SIZE,this._state=this.UNCONNECTED,this._channels=new Faye.Channel.Set,this._messageId=0,this._responseCallbacks={},this._advice={reconnect:this.RETRY,interval:1e3*(this._options.interval||this.INTERVAL),timeout:1e3*(this._options.timeout||this.CONNECTION_TIMEOUT)},Faye.Event&&void 0!==Faye.ENV.onbeforeunload&&Faye.Event.on(Faye.ENV,"beforeunload",function(){Faye.indexOf(this._disabled,"autodisconnect")<0&&this.disconnect()},this)},disable:function(e){this._disabled.push(e)},setHeader:function(e,t){this.headers[e]=t},handshake:function(e,t){if(this._advice.reconnect!==this.NONE&&this._state===this.UNCONNECTED){this._state=this.CONNECTING;var n=this;this.info("Initiating handshake with ?",Faye.URI.stringify(this.endpoint)),this._selectTransport(Faye.MANDATORY_CONNECTION_TYPES),this._send({channel:Faye.Channel.HANDSHAKE,version:Faye.BAYEUX_VERSION,supportedConnectionTypes:[this._transport.connectionType]},function(i){i.successful?(this._state=this.CONNECTED,this._clientId=i.clientId,this._selectTransport(i.supportedConnectionTypes),this.info("Handshake successful: ?",this._clientId),this.subscribe(this._channels.getKeys(),!0),e&&Faye.Promise.defer(function(){e.call(t)})):(this.info("Handshake unsuccessful"),Faye.ENV.setTimeout(function(){n.handshake(e,t)},this._advice.interval),this._state=this.UNCONNECTED)},this)}},connect:function(e,t){if(this._advice.reconnect!==this.NONE&&this._state!==this.DISCONNECTED){if(this._state===this.UNCONNECTED)return this.handshake(function(){this.connect(e,t)},this);this.callback(e,t),this._state===this.CONNECTED&&(this.info("Calling deferred actions for ?",this._clientId),this.setDeferredStatus("succeeded"),this.setDeferredStatus("unknown"),this._connectRequest||(this._connectRequest=!0,this.info("Initiating connection for ?",this._clientId),this._send({channel:Faye.Channel.CONNECT,clientId:this._clientId,connectionType:this._transport.connectionType},this._cycleConnection,this)))}},disconnect:function(){this._state===this.CONNECTED&&(this._state=this.DISCONNECTED,this.info("Disconnecting ?",this._clientId),this._send({channel:Faye.Channel.DISCONNECT,clientId:this._clientId},function(e){e.successful&&(this._transport.close(),delete this._transport)},this),this.info("Clearing channel listeners for ?",this._clientId),this._channels=new Faye.Channel.Set)},subscribe:function(e,t,n){if(e instanceof Array)return Faye.map(e,function(e){return this.subscribe(e,t,n)},this);var i=new Faye.Subscription(this,e,t,n),s=t===!0,r=this._channels.hasSubscription(e);return r&&!s?(this._channels.subscribe([e],t,n),i.setDeferredStatus("succeeded"),i):(this.connect(function(){this.info("Client ? attempting to subscribe to ?",this._clientId,e),s||this._channels.subscribe([e],t,n),this._send({channel:Faye.Channel.SUBSCRIBE,clientId:this._clientId,subscription:e},function(s){if(!s.successful)return i.setDeferredStatus("failed",Faye.Error.parse(s.error)),this._channels.unsubscribe(e,t,n);var r=[].concat(s.subscription);this.info("Subscription acknowledged for ? to ?",this._clientId,r),i.setDeferredStatus("succeeded")},this)},this),i)},unsubscribe:function(e,t,n){if(e instanceof Array)return Faye.map(e,function(e){return this.unsubscribe(e,t,n)},this);var i=this._channels.unsubscribe(e,t,n);i&&this.connect(function(){this.info("Client ? attempting to unsubscribe from ?",this._clientId,e),this._send({channel:Faye.Channel.UNSUBSCRIBE,clientId:this._clientId,subscription:e},function(e){if(e.successful){var t=[].concat(e.subscription);this.info("Unsubscription acknowledged for ? from ?",this._clientId,t)}},this)},this)},publish:function(e,t){var n=new Faye.Publication;return this.connect(function(){this.info("Client ? queueing published message to ?: ?",this._clientId,e,t),this._send({channel:e,data:t,clientId:this._clientId},function(e){e.successful?n.setDeferredStatus("succeeded"):n.setDeferredStatus("failed",Faye.Error.parse(e.error))},this)},this),n},receiveMessage:function(e){var t,n=e.id;void 0!==e.successful&&(t=this._responseCallbacks[n],delete this._responseCallbacks[n]),this.pipeThroughExtensions("incoming",e,null,function(e){e&&(e.advice&&this._handleAdvice(e.advice),this._deliverMessage(e),t&&t[0].call(t[1],e))},this),this._transportUp!==!0&&(this._transportUp=!0,this.trigger("transport:up"))},messageError:function(e,t){for(var n,i,s=this._retry,r=this,o=0,a=e.length;a>o;o++)i=e[o],n=i.id,t?this._transportSend(i):Faye.ENV.setTimeout(function(){r._transportSend(i)},1e3*s);t||this._transportUp===!1||(this._transportUp=!1,this.trigger("transport:down"))},_selectTransport:function(e){Faye.Transport.get(this,e,this._disabled,function(e){this.debug("Selected ? transport for ?",e.connectionType,Faye.URI.stringify(e.endpoint)),e!==this._transport&&(this._transport&&this._transport.close(),this._transport=e)},this)},_send:function(e,t,n){this._transport&&(e.id=e.id||this._generateMessageId(),this.pipeThroughExtensions("outgoing",e,null,function(e){e&&(t&&(this._responseCallbacks[e.id]=[t,n]),this._transportSend(e))},this))},_transportSend:function(e){if(this._transport){var t=1.2*(this._advice.timeout||1e3*this._retry),n=new Faye.Envelope(e,t);n.errback(function(t){this.messageError([e],t)},this),this._transport.send(n)}},_generateMessageId:function(){return this._messageId+=1,this._messageId>=Math.pow(2,32)&&(this._messageId=0),this._messageId.toString(36)},_handleAdvice:function(e){Faye.extend(this._advice,e),this._advice.reconnect===this.HANDSHAKE&&this._state!==this.DISCONNECTED&&(this._state=this.UNCONNECTED,this._clientId=null,this._cycleConnection())},_deliverMessage:function(e){e.channel&&void 0!==e.data&&(this.info("Client ? calling listeners for ? with ?",this._clientId,e.channel,e.data),this._channels.distributeMessage(e))},_cycleConnection:function(){this._connectRequest&&(this._connectRequest=null,this.info("Closed connection for ?",this._clientId));var e=this;Faye.ENV.setTimeout(function(){e.connect()},this._advice.interval)}}),Faye.extend(Faye.Client.prototype,Faye.Deferrable),Faye.extend(Faye.Client.prototype,Faye.Publisher),Faye.extend(Faye.Client.prototype,Faye.Logging),Faye.extend(Faye.Client.prototype,Faye.Extensible),Faye.Transport=Faye.extend(Faye.Class({MAX_DELAY:0,batching:!0,initialize:function(e,t){this._client=e,this.endpoint=t,this._outbox=[]},close:function(){},encode:function(){return""},send:function(e){var t=e.message;return this.debug("Client ? sending message to ?: ?",this._client._clientId,Faye.URI.stringify(this.endpoint),t),this.batching?(this._outbox.push(e),t.channel===Faye.Channel.HANDSHAKE?this.addTimeout("publish",.01,this.flush,this):(t.channel===Faye.Channel.CONNECT&&(this._connectMessage=t),this.flushLargeBatch(),this.addTimeout("publish",this.MAX_DELAY,this.flush,this),void 0)):this.request([e])},flush:function(){this.removeTimeout("publish"),this._outbox.length>1&&this._connectMessage&&(this._connectMessage.advice={timeout:0}),this.request(this._outbox),this._connectMessage=null,this._outbox=[]},flushLargeBatch:function(){var e=this.encode(this._outbox);if(!(e.length<this._client.maxRequestSize)){var t=this._outbox.pop();this.flush(),t&&this._outbox.push(t)}},receive:function(e,t){for(var n=e.length;n--;)e[n].setDeferredStatus("succeeded");t=[].concat(t),this.debug("Client ? received from ?: ?",this._client._clientId,Faye.URI.stringify(this.endpoint),t);for(var i=0,n=t.length;n>i;i++)this._client.receiveMessage(t[i])},handleError:function(e,t){for(var n=e.length;n--;)e[n].setDeferredStatus("failed",t)},_getCookies:function(){var e=this._client.cookies;return e?e.getCookies({domain:this.endpoint.hostname,path:this.endpoint.path,secure:"https:"===this.endpoint.protocol}).toValueString():""},_storeCookies:function(e){if(e&&this._client.cookies){e=[].concat(e);for(var t,n=0,i=e.length;i>n;n++)t=this._client.cookies.setCookie(e[n]),t=t[0]||t,t.domain=t.domain||this.endpoint.hostname}}}),{get:function(e,t,n,i,s){var r=e.endpoint;Faye.asyncEach(this._transports,function(o,a){var c=o[0],u=o[1],h=e.endpoints[c]||r;return Faye.indexOf(n,c)>=0?a():Faye.indexOf(t,c)<0?(u.isUsable(e,h,function(){}),a()):(u.isUsable(e,h,function(t){if(!t)return a();var n=u.hasOwnProperty("create")?u.create(e,h):new u(e,h);i.call(s,n)}),void 0)},function(){throw Error("Could not find a usable connection type for "+Faye.URI.stringify(r))})},register:function(e,t){this._transports.push([e,t]),t.prototype.connectionType=e},_transports:[]}),Faye.extend(Faye.Transport.prototype,Faye.Logging),Faye.extend(Faye.Transport.prototype,Faye.Timeouts),Faye.Event={_registry:[],on:function(e,t,n,i){var s=function(){n.call(i)};e.addEventListener?e.addEventListener(t,s,!1):e.attachEvent("on"+t,s),this._registry.push({_element:e,_type:t,_callback:n,_context:i,_handler:s})},detach:function(e,t,n,i){for(var s,r=this._registry.length;r--;)s=this._registry[r],e&&e!==s._element||t&&t!==s._type||n&&n!==s._callback||i&&i!==s._context||(s._element.removeEventListener?s._element.removeEventListener(s._type,s._handler,!1):s._element.detachEvent("on"+s._type,s._handler),this._registry.splice(r,1),s=null)}},void 0!==Faye.ENV.onunload&&Faye.Event.on(Faye.ENV,"unload",Faye.Event.detach,Faye.Event),"object"!=typeof JSON&&(JSON={}),function(){function f(e){return 10>e?"0"+e:e}function quote(e){return escapable.lastIndex=0,escapable.test(e)?'"'+e.replace(escapable,function(e){var t=meta[e];return"string"==typeof t?t:"\\u"+("0000"+e.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+e+'"'}function str(e,t){var n,i,s,r,o,a=gap,c=t[e];switch(c&&"object"==typeof c&&"function"==typeof c.toJSON&&(c=c.toJSON(e)),"function"==typeof rep&&(c=rep.call(t,e,c)),typeof c){case"string":return quote(c);case"number":return isFinite(c)?c+"":"null";case"boolean":case"null":return c+"";case"object":if(!c)return"null";if(gap+=indent,o=[],"[object Array]"===Object.prototype.toString.apply(c)){for(r=c.length,n=0;r>n;n+=1)o[n]=str(n,c)||"null";return s=0===o.length?"[]":gap?"[\n"+gap+o.join(",\n"+gap)+"\n"+a+"]":"["+o.join(",")+"]",gap=a,s}if(rep&&"object"==typeof rep)for(r=rep.length,n=0;r>n;n+=1)"string"==typeof rep[n]&&(i=rep[n],s=str(i,c),s&&o.push(quote(i)+(gap?": ":":")+s));else for(i in c)Object.prototype.hasOwnProperty.call(c,i)&&(s=str(i,c),s&&o.push(quote(i)+(gap?": ":":")+s));return s=0===o.length?"{}":gap?"{\n"+gap+o.join(",\n"+gap)+"\n"+a+"}":"{"+o.join(",")+"}",gap=a,s}}"function"!=typeof Date.prototype.toJSON&&(Date.prototype.toJSON=function(){return isFinite(this.valueOf())?this.getUTCFullYear()+"-"+f(this.getUTCMonth()+1)+"-"+f(this.getUTCDate())+"T"+f(this.getUTCHours())+":"+f(this.getUTCMinutes())+":"+f(this.getUTCSeconds())+"Z":null},String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(){return this.valueOf()});var cx=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,escapable=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,gap,indent,meta={"\b":"\\b"," ":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"},rep;Faye.stringify=function(e,t,n){var i;if(gap="",indent="","number"==typeof n)for(i=0;n>i;i+=1)indent+=" ";else"string"==typeof n&&(indent=n);if(rep=t,t&&"function"!=typeof t&&("object"!=typeof t||"number"!=typeof t.length))throw Error("JSON.stringify");return str("",{"":e})},"function"!=typeof JSON.stringify&&(JSON.stringify=Faye.stringify),"function"!=typeof JSON.parse&&(JSON.parse=function(text,reviver){function walk(e,t){var n,i,s=e[t];if(s&&"object"==typeof s)for(n in s)Object.prototype.hasOwnProperty.call(s,n)&&(i=walk(s,n),void 0!==i?s[n]=i:delete s[n]);return reviver.call(e,t,s)}var j;if(text+="",cx.lastIndex=0,cx.test(text)&&(text=text.replace(cx,function(e){return"\\u"+("0000"+e.charCodeAt(0).toString(16)).slice(-4)})),/^[\],:{}\s]*$/.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,"")))return j=eval("("+text+")"),"function"==typeof reviver?walk({"":j},""):j;throw new SyntaxError("JSON.parse")})}(),Faye.Transport.WebSocket=Faye.extend(Faye.Class(Faye.Transport,{UNCONNECTED:1,CONNECTING:2,CONNECTED:3,batching:!1,isUsable:function(e,t){this.callback(function(){e.call(t,!0)}),this.errback(function(){e.call(t,!1)}),this.connect()},request:function(e){this._pending=this._pending||new Faye.Set;for(var t=0,n=e.length;n>t;t++)this._pending.add(e[t]);this.callback(function(t){if(t){var n=Faye.map(e,function(e){return e.message});t.send(Faye.toJSON(n))}},this),this.connect()},connect:function(){if(!Faye.Transport.WebSocket._unloaded&&(this._state=this._state||this.UNCONNECTED,this._state===this.UNCONNECTED)){this._state=this.CONNECTING;var e=this._createSocket();if(!e)return this.setDeferredStatus("failed");var t=this;e.onopen=function(){e.headers&&t._storeCookies(e.headers["set-cookie"]),t._socket=e,t._state=t.CONNECTED,t._everConnected=!0,t._ping(),t.setDeferredStatus("succeeded",e)};var n=!1;e.onclose=e.onerror=function(){if(!n){n=!0;var i=t._state===t.CONNECTED;e.onopen=e.onclose=e.onerror=e.onmessage=null,delete t._socket,t._state=t.UNCONNECTED,t.removeTimeout("ping"),t.setDeferredStatus("unknown");var s=t._pending?t._pending.toArray():[];delete t._pending,i?t.handleError(s,!0):t._everConnected?t.handleError(s):t.setDeferredStatus("failed")}},e.onmessage=function(e){var n,i=JSON.parse(e.data),s=[];if(i){i=[].concat(i);for(var r=0,o=i.length;o>r;r++)void 0!==i[r].successful&&(n=t._pending.remove(i[r]),n&&s.push(n));t.receive(s,i)}}}},close:function(){this._socket&&this._socket.close()},_createSocket:function(){var e=Faye.Transport.WebSocket.getSocketUrl(this.endpoint),t={headers:Faye.copyObject(this._client.headers),ca:this._client.ca};return t.headers.Cookie=this._getCookies(),Faye.WebSocket?new Faye.WebSocket.Client(e,[],t):Faye.ENV.MozWebSocket?new MozWebSocket(e):Faye.ENV.WebSocket?new WebSocket(e):void 0},_ping:function(){this._socket&&(this._socket.send("[]"),this.addTimeout("ping",this._client._advice.timeout/2e3,this._ping,this))}}),{PROTOCOLS:{"http:":"ws:","https:":"wss:"},create:function(e,t){var n=e.transports.websocket=e.transports.websocket||{};return n[t.href]=n[t.href]||new this(e,t),n[t.href]},getSocketUrl:function(e){return e=Faye.copyObject(e),e.protocol=this.PROTOCOLS[e.protocol],Faye.URI.stringify(e)},isUsable:function(e,t,n,i){this.create(e,t).isUsable(n,i)}}),Faye.extend(Faye.Transport.WebSocket.prototype,Faye.Deferrable),Faye.Transport.register("websocket",Faye.Transport.WebSocket),Faye.Event&&Faye.Event.on(Faye.ENV,"beforeunload",function(){Faye.Transport.WebSocket._unloaded=!0}),Faye.Transport.EventSource=Faye.extend(Faye.Class(Faye.Transport,{initialize:function(e,t){if(Faye.Transport.prototype.initialize.call(this,e,t),!Faye.ENV.EventSource)return this.setDeferredStatus("failed");this._xhr=new Faye.Transport.XHR(e,t),t=Faye.copyObject(t),t.pathname+="/"+e._clientId;var n=new EventSource(Faye.URI.stringify(t)),i=this;n.onopen=function(){i._everConnected=!0,i.setDeferredStatus("succeeded")},n.onerror=function(){i._everConnected?i._client.messageError([]):(i.setDeferredStatus("failed"),n.close())},n.onmessage=function(e){i.receive([],JSON.parse(e.data))},this._socket=n},close:function(){this._socket&&(this._socket.onopen=this._socket.onerror=this._socket.onmessage=null,this._socket.close(),delete this._socket)},isUsable:function(e,t){this.callback(function(){e.call(t,!0)}),this.errback(function(){e.call(t,!1)})},encode:function(e){return this._xhr.encode(e)},request:function(e){this._xhr.request(e)}}),{isUsable:function(e,t,n,i){var s=e._clientId;
3
+ return s?(Faye.Transport.XHR.isUsable(e,t,function(s){return s?(this.create(e,t).isUsable(n,i),void 0):n.call(i,!1)},this),void 0):n.call(i,!1)},create:function(e,t){var n=e.transports.eventsource=e.transports.eventsource||{},i=e._clientId;t=Faye.copyObject(t),t.pathname+="/"+(i||"");var s=Faye.URI.stringify(t);return n[s]=n[s]||new this(e,t),n[s]}}),Faye.extend(Faye.Transport.EventSource.prototype,Faye.Deferrable),Faye.Transport.register("eventsource",Faye.Transport.EventSource),Faye.Transport.XHR=Faye.extend(Faye.Class(Faye.Transport,{encode:function(e){var t=Faye.map(e,function(e){return e.message});return Faye.toJSON(t)},request:function(e){var t=this.endpoint.path,n=Faye.ENV.ActiveXObject?new ActiveXObject("Microsoft.XMLHTTP"):new XMLHttpRequest,i=this;n.open("POST",t,!0),n.setRequestHeader("Content-Type","application/json"),n.setRequestHeader("Pragma","no-cache"),n.setRequestHeader("X-Requested-With","XMLHttpRequest");var s=this._client.headers;for(var r in s)s.hasOwnProperty(r)&&n.setRequestHeader(r,s[r]);var o=function(){n.abort()};Faye.Event.on(Faye.ENV,"beforeunload",o),n.onreadystatechange=function(){if(n&&4===n.readyState){var t=null,s=n.status,r=n.responseText,a=s>=200&&300>s||304===s||1223===s;if(Faye.Event.detach(Faye.ENV,"beforeunload",o),n.onreadystatechange=function(){},n=null,!a)return i.handleError(e);try{t=JSON.parse(r)}catch(c){}t?i.receive(e,t):i.handleError(e)}},n.send(this.encode(e))}}),{isUsable:function(e,t,n,i){n.call(i,Faye.URI.isSameOrigin(t))}}),Faye.Transport.register("long-polling",Faye.Transport.XHR),Faye.Transport.CORS=Faye.extend(Faye.Class(Faye.Transport,{encode:function(e){var t=Faye.map(e,function(e){return e.message});return"message="+encodeURIComponent(Faye.toJSON(t))},request:function(e){var t,n=Faye.ENV.XDomainRequest?XDomainRequest:XMLHttpRequest,i=new n,s=this._client.headers,r=this;if(i.open("POST",Faye.URI.stringify(this.endpoint),!0),i.setRequestHeader){i.setRequestHeader("Pragma","no-cache");for(t in s)s.hasOwnProperty(t)&&i.setRequestHeader(t,s[t])}var o=function(){return i?(i.onload=i.onerror=i.ontimeout=i.onprogress=null,i=null,void 0):!1};i.onload=function(){var t=null;try{t=JSON.parse(i.responseText)}catch(n){}o(),t?r.receive(e,t):r.handleError(e)},i.onerror=i.ontimeout=function(){o(),r.handleError(e)},i.onprogress=function(){},i.send(this.encode(e))}}),{isUsable:function(e,t,n,i){if(Faye.URI.isSameOrigin(t))return n.call(i,!1);if(Faye.ENV.XDomainRequest)return n.call(i,t.protocol===Faye.ENV.location.protocol);if(Faye.ENV.XMLHttpRequest){var s=new Faye.ENV.XMLHttpRequest;return n.call(i,void 0!==s.withCredentials)}return n.call(i,!1)}}),Faye.Transport.register("cross-origin-long-polling",Faye.Transport.CORS),Faye.Transport.JSONP=Faye.extend(Faye.Class(Faye.Transport,{encode:function(e){var t=Faye.map(e,function(e){return e.message}),n=Faye.copyObject(this.endpoint);return n.query.message=Faye.toJSON(t),n.query.jsonp="__jsonp"+Faye.Transport.JSONP._cbCount+"__",Faye.URI.stringify(n)},request:function(e){var t=Faye.map(e,function(e){return e.message}),n=document.getElementsByTagName("head")[0],i=document.createElement("script"),s=Faye.Transport.JSONP.getCallbackName(),r=Faye.copyObject(this.endpoint),o=this;r.query.message=Faye.toJSON(t),r.query.jsonp=s,Faye.ENV[s]=function(t){if(!Faye.ENV[s])return!1;Faye.ENV[s]=void 0;try{delete Faye.ENV[s]}catch(n){}i.parentNode.removeChild(i),o.receive(e,t)},i.type="text/javascript",i.src=Faye.URI.stringify(r),n.appendChild(i)}}),{_cbCount:0,getCallbackName:function(){return this._cbCount+=1,"__jsonp"+this._cbCount+"__"},isUsable:function(e,t,n,i){n.call(i,!0)}}),Faye.Transport.register("callback-polling",Faye.Transport.JSONP)}();
3
4
  //@ sourceMappingURL=faye-browser-min.js.map
4
- })();
5
+ })(this);
@@ -1,8 +1,9 @@
1
1
  (function() {
2
+ (function() {
2
3
  'use strict';
3
4
 
4
5
  var Faye = {
5
- VERSION: '0.8.9',
6
+ VERSION: '1.0.1',
6
7
 
7
8
  BAYEUX_VERSION: '1.0',
8
9
  ID_LENGTH: 160,
@@ -11,7 +12,7 @@ var Faye = {
11
12
 
12
13
  MANDATORY_CONNECTION_TYPES: ['long-polling', 'callback-polling', 'in-process'],
13
14
 
14
- ENV: (typeof global === 'undefined') ? window : global,
15
+ ENV: (typeof window !== 'undefined') ? window : global,
15
16
 
16
17
  extend: function(dest, source, overwrite) {
17
18
  if (!source) return dest;
@@ -26,25 +27,14 @@ var Faye = {
26
27
 
27
28
  random: function(bitlength) {
28
29
  bitlength = bitlength || this.ID_LENGTH;
29
- if (bitlength > 32) {
30
- var parts = Math.ceil(bitlength / 32),
31
- string = '';
32
- while (parts--) string += this.random(32);
33
- var chars = string.split(''), result = '';
34
- while (chars.length > 0) result += chars.pop();
35
- return result;
36
- }
37
- var limit = Math.pow(2, bitlength) - 1,
38
- maxSize = limit.toString(36).length,
39
- string = Math.floor(Math.random() * limit).toString(36);
40
-
41
- while (string.length < maxSize) string = '0' + string;
42
- return string;
30
+ return csprng(bitlength, 36);
43
31
  },
44
32
 
45
33
  clientIdFromMessages: function(messages) {
46
- var first = [].concat(messages)[0];
47
- return first && first.clientId;
34
+ var connect = this.filter([].concat(messages), function(message) {
35
+ return message.channel === '/meta/connect';
36
+ });
37
+ return connect[0] && connect[0].clientId;
48
38
  },
49
39
 
50
40
  copyObject: function(object) {
@@ -98,6 +88,7 @@ var Faye = {
98
88
  },
99
89
 
100
90
  filter: function(array, callback, context) {
91
+ if (array.filter) return array.filter(callback, context);
101
92
  var result = [];
102
93
  for (var i = 0, n = array.length; i < n; i++) {
103
94
  if (callback.call(context || null, array[i], i))
@@ -135,42 +126,19 @@ var Faye = {
135
126
 
136
127
  // http://assanka.net/content/tech/2009/09/02/json2-js-vs-prototype/
137
128
  toJSON: function(object) {
138
- if (this.stringify)
139
- return this.stringify(object, function(key, value) {
140
- return (this[key] instanceof Array)
141
- ? this[key]
142
- : value;
143
- });
144
-
145
- return JSON.stringify(object);
146
- },
129
+ if (!this.stringify) return JSON.stringify(object);
147
130
 
148
- logger: function(message) {
149
- if (typeof console !== 'undefined') console.log(message);
150
- },
151
-
152
- timestamp: function() {
153
- var date = new Date(),
154
- year = date.getFullYear(),
155
- month = date.getMonth() + 1,
156
- day = date.getDate(),
157
- hour = date.getHours(),
158
- minute = date.getMinutes(),
159
- second = date.getSeconds();
160
-
161
- var pad = function(n) {
162
- return n < 10 ? '0' + n : String(n);
163
- };
164
-
165
- return pad(year) + '-' + pad(month) + '-' + pad(day) + ' ' +
166
- pad(hour) + ':' + pad(minute) + ':' + pad(second);
131
+ return this.stringify(object, function(key, value) {
132
+ return (this[key] instanceof Array) ? this[key] : value;
133
+ });
167
134
  }
168
135
  };
169
136
 
170
- if (typeof window !== 'undefined')
137
+ if (typeof module !== 'undefined')
138
+ module.exports = Faye;
139
+ else if (typeof window !== 'undefined')
171
140
  window.Faye = Faye;
172
141
 
173
-
174
142
  Faye.Class = function(parent, methods) {
175
143
  if (typeof parent !== 'function') {
176
144
  methods = parent;
@@ -191,6 +159,180 @@ Faye.Class = function(parent, methods) {
191
159
  return klass;
192
160
  };
193
161
 
162
+ (function() {
163
+ var EventEmitter = Faye.EventEmitter = function() {};
164
+
165
+ /*
166
+ Copyright Joyent, Inc. and other Node contributors. All rights reserved.
167
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
168
+ this software and associated documentation files (the "Software"), to deal in
169
+ the Software without restriction, including without limitation the rights to
170
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
171
+ of the Software, and to permit persons to whom the Software is furnished to do
172
+ so, subject to the following conditions:
173
+
174
+ The above copyright notice and this permission notice shall be included in all
175
+ copies or substantial portions of the Software.
176
+
177
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
178
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
179
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
180
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
181
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
182
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
183
+ SOFTWARE.
184
+ */
185
+
186
+ var isArray = typeof Array.isArray === 'function'
187
+ ? Array.isArray
188
+ : function (xs) {
189
+ return Object.prototype.toString.call(xs) === '[object Array]'
190
+ }
191
+ ;
192
+ function indexOf (xs, x) {
193
+ if (xs.indexOf) return xs.indexOf(x);
194
+ for (var i = 0; i < xs.length; i++) {
195
+ if (x === xs[i]) return i;
196
+ }
197
+ return -1;
198
+ }
199
+
200
+
201
+ EventEmitter.prototype.emit = function(type) {
202
+ // If there is no 'error' event listener then throw.
203
+ if (type === 'error') {
204
+ if (!this._events || !this._events.error ||
205
+ (isArray(this._events.error) && !this._events.error.length))
206
+ {
207
+ if (arguments[1] instanceof Error) {
208
+ throw arguments[1]; // Unhandled 'error' event
209
+ } else {
210
+ throw new Error("Uncaught, unspecified 'error' event.");
211
+ }
212
+ return false;
213
+ }
214
+ }
215
+
216
+ if (!this._events) return false;
217
+ var handler = this._events[type];
218
+ if (!handler) return false;
219
+
220
+ if (typeof handler == 'function') {
221
+ switch (arguments.length) {
222
+ // fast cases
223
+ case 1:
224
+ handler.call(this);
225
+ break;
226
+ case 2:
227
+ handler.call(this, arguments[1]);
228
+ break;
229
+ case 3:
230
+ handler.call(this, arguments[1], arguments[2]);
231
+ break;
232
+ // slower
233
+ default:
234
+ var args = Array.prototype.slice.call(arguments, 1);
235
+ handler.apply(this, args);
236
+ }
237
+ return true;
238
+
239
+ } else if (isArray(handler)) {
240
+ var args = Array.prototype.slice.call(arguments, 1);
241
+
242
+ var listeners = handler.slice();
243
+ for (var i = 0, l = listeners.length; i < l; i++) {
244
+ listeners[i].apply(this, args);
245
+ }
246
+ return true;
247
+
248
+ } else {
249
+ return false;
250
+ }
251
+ };
252
+
253
+ // EventEmitter is defined in src/node_events.cc
254
+ // EventEmitter.prototype.emit() is also defined there.
255
+ EventEmitter.prototype.addListener = function(type, listener) {
256
+ if ('function' !== typeof listener) {
257
+ throw new Error('addListener only takes instances of Function');
258
+ }
259
+
260
+ if (!this._events) this._events = {};
261
+
262
+ // To avoid recursion in the case that type == "newListeners"! Before
263
+ // adding it to the listeners, first emit "newListeners".
264
+ this.emit('newListener', type, listener);
265
+
266
+ if (!this._events[type]) {
267
+ // Optimize the case of one listener. Don't need the extra array object.
268
+ this._events[type] = listener;
269
+ } else if (isArray(this._events[type])) {
270
+ // If we've already got an array, just append.
271
+ this._events[type].push(listener);
272
+ } else {
273
+ // Adding the second element, need to change to array.
274
+ this._events[type] = [this._events[type], listener];
275
+ }
276
+
277
+ return this;
278
+ };
279
+
280
+ EventEmitter.prototype.on = EventEmitter.prototype.addListener;
281
+
282
+ EventEmitter.prototype.once = function(type, listener) {
283
+ var self = this;
284
+ self.on(type, function g() {
285
+ self.removeListener(type, g);
286
+ listener.apply(this, arguments);
287
+ });
288
+
289
+ return this;
290
+ };
291
+
292
+ EventEmitter.prototype.removeListener = function(type, listener) {
293
+ if ('function' !== typeof listener) {
294
+ throw new Error('removeListener only takes instances of Function');
295
+ }
296
+
297
+ // does not use listeners(), so no side effect of creating _events[type]
298
+ if (!this._events || !this._events[type]) return this;
299
+
300
+ var list = this._events[type];
301
+
302
+ if (isArray(list)) {
303
+ var i = indexOf(list, listener);
304
+ if (i < 0) return this;
305
+ list.splice(i, 1);
306
+ if (list.length == 0)
307
+ delete this._events[type];
308
+ } else if (this._events[type] === listener) {
309
+ delete this._events[type];
310
+ }
311
+
312
+ return this;
313
+ };
314
+
315
+ EventEmitter.prototype.removeAllListeners = function(type) {
316
+ if (arguments.length === 0) {
317
+ this._events = {};
318
+ return this;
319
+ }
320
+
321
+ // does not use listeners(), so no side effect of creating _events[type]
322
+ if (type && this._events && this._events[type]) this._events[type] = null;
323
+ return this;
324
+ };
325
+
326
+ EventEmitter.prototype.listeners = function(type) {
327
+ if (!this._events) this._events = {};
328
+ if (!this._events[type]) this._events[type] = [];
329
+ if (!isArray(this._events[type])) {
330
+ this._events[type] = [this._events[type]];
331
+ }
332
+ return this._events[type];
333
+ };
334
+
335
+ })();
194
336
 
195
337
  Faye.Namespace = Faye.Class({
196
338
  initialize: function() {
@@ -213,6 +355,283 @@ Faye.Namespace = Faye.Class({
213
355
  }
214
356
  });
215
357
 
358
+ (function() {
359
+ 'use strict';
360
+
361
+ var timeout = setTimeout;
362
+
363
+ var defer;
364
+ if (typeof setImmediate === 'function')
365
+ defer = function(fn) { setImmediate(fn) };
366
+ else if (typeof process === 'object' && process.nextTick)
367
+ defer = function(fn) { process.nextTick(fn) };
368
+ else
369
+ defer = function(fn) { timeout(fn, 0) };
370
+
371
+ var PENDING = 0,
372
+ FULFILLED = 1,
373
+ REJECTED = 2;
374
+
375
+ var RETURN = function(x) { return x },
376
+ THROW = function(x) { throw x };
377
+
378
+ var Promise = function(task) {
379
+ this._state = PENDING;
380
+ this._callbacks = [];
381
+ this._errbacks = [];
382
+
383
+ if (typeof task !== 'function') return;
384
+ var self = this;
385
+
386
+ task(function(value) { fulfill(self, value) },
387
+ function(reason) { reject(self, reason) });
388
+ };
389
+
390
+ Promise.prototype.then = function(callback, errback) {
391
+ var next = {}, self = this;
392
+
393
+ next.promise = new Promise(function(fulfill, reject) {
394
+ next.fulfill = fulfill;
395
+ next.reject = reject;
396
+
397
+ registerCallback(self, callback, next);
398
+ registerErrback(self, errback, next);
399
+ });
400
+ return next.promise;
401
+ };
402
+
403
+ var registerCallback = function(promise, callback, next) {
404
+ if (typeof callback !== 'function') callback = RETURN;
405
+ var handler = function(value) { invoke(callback, value, next) };
406
+ if (promise._state === PENDING) {
407
+ promise._callbacks.push(handler);
408
+ } else if (promise._state === FULFILLED) {
409
+ handler(promise._value);
410
+ }
411
+ };
412
+
413
+ var registerErrback = function(promise, errback, next) {
414
+ if (typeof errback !== 'function') errback = THROW;
415
+ var handler = function(reason) { invoke(errback, reason, next) };
416
+ if (promise._state === PENDING) {
417
+ promise._errbacks.push(handler);
418
+ } else if (promise._state === REJECTED) {
419
+ handler(promise._reason);
420
+ }
421
+ };
422
+
423
+ var invoke = function(fn, value, next) {
424
+ defer(function() { _invoke(fn, value, next) });
425
+ };
426
+
427
+ var _invoke = function(fn, value, next) {
428
+ var called = false, outcome, type, then;
429
+
430
+ try {
431
+ outcome = fn(value);
432
+ type = typeof outcome;
433
+ then = outcome !== null && (type === 'function' || type === 'object') && outcome.then;
434
+
435
+ if (outcome === next.promise)
436
+ return next.reject(new TypeError('Recursive promise chain detected'));
437
+
438
+ if (typeof then !== 'function') return next.fulfill(outcome);
439
+
440
+ then.call(outcome, function(v) {
441
+ if (called) return;
442
+ called = true;
443
+ _invoke(RETURN, v, next);
444
+ }, function(r) {
445
+ if (called) return;
446
+ called = true;
447
+ next.reject(r);
448
+ });
449
+
450
+ } catch (error) {
451
+ if (called) return;
452
+ called = true;
453
+ next.reject(error);
454
+ }
455
+ };
456
+
457
+ var fulfill = Promise.fulfill = Promise.resolve = function(promise, value) {
458
+ if (promise._state !== PENDING) return;
459
+
460
+ promise._state = FULFILLED;
461
+ promise._value = value;
462
+ promise._errbacks = [];
463
+
464
+ var callbacks = promise._callbacks, cb;
465
+ while (cb = callbacks.shift()) cb(value);
466
+ };
467
+
468
+ var reject = Promise.reject = function(promise, reason) {
469
+ if (promise._state !== PENDING) return;
470
+
471
+ promise._state = REJECTED;
472
+ promise._reason = reason;
473
+ promise._callbacks = [];
474
+
475
+ var errbacks = promise._errbacks, eb;
476
+ while (eb = errbacks.shift()) eb(reason);
477
+ };
478
+
479
+ Promise.defer = defer;
480
+
481
+ Promise.deferred = Promise.pending = function() {
482
+ var tuple = {};
483
+
484
+ tuple.promise = new Promise(function(fulfill, reject) {
485
+ tuple.fulfill = tuple.resolve = fulfill;
486
+ tuple.reject = reject;
487
+ });
488
+ return tuple;
489
+ };
490
+
491
+ Promise.fulfilled = Promise.resolved = function(value) {
492
+ return new Promise(function(fulfill, reject) { fulfill(value) });
493
+ };
494
+
495
+ Promise.rejected = function(reason) {
496
+ return new Promise(function(fulfill, reject) { reject(reason) });
497
+ };
498
+
499
+ if (typeof Faye === 'undefined')
500
+ module.exports = Promise;
501
+ else
502
+ Faye.Promise = Promise;
503
+
504
+ })();
505
+
506
+ Faye.Set = Faye.Class({
507
+ initialize: function() {
508
+ this._index = {};
509
+ },
510
+
511
+ add: function(item) {
512
+ var key = (item.id !== undefined) ? item.id : item;
513
+ if (this._index.hasOwnProperty(key)) return false;
514
+ this._index[key] = item;
515
+ return true;
516
+ },
517
+
518
+ forEach: function(block, context) {
519
+ for (var key in this._index) {
520
+ if (this._index.hasOwnProperty(key))
521
+ block.call(context, this._index[key]);
522
+ }
523
+ },
524
+
525
+ isEmpty: function() {
526
+ for (var key in this._index) {
527
+ if (this._index.hasOwnProperty(key)) return false;
528
+ }
529
+ return true;
530
+ },
531
+
532
+ member: function(item) {
533
+ for (var key in this._index) {
534
+ if (this._index[key] === item) return true;
535
+ }
536
+ return false;
537
+ },
538
+
539
+ remove: function(item) {
540
+ var key = (item.id !== undefined) ? item.id : item;
541
+ var removed = this._index[key];
542
+ delete this._index[key];
543
+ return removed;
544
+ },
545
+
546
+ toArray: function() {
547
+ var array = [];
548
+ this.forEach(function(item) { array.push(item) });
549
+ return array;
550
+ }
551
+ });
552
+
553
+ Faye.URI = {
554
+ isURI: function(uri) {
555
+ return uri && uri.protocol && uri.host && uri.path;
556
+ },
557
+
558
+ isSameOrigin: function(uri) {
559
+ var location = Faye.ENV.location;
560
+ return uri.protocol === location.protocol &&
561
+ uri.hostname === location.hostname &&
562
+ uri.port === location.port;
563
+ },
564
+
565
+ parse: function(url) {
566
+ if (typeof url !== 'string') return url;
567
+ var uri = {}, parts, query, pairs, i, n, data;
568
+
569
+ var consume = function(name, pattern) {
570
+ url = url.replace(pattern, function(match) {
571
+ uri[name] = match;
572
+ return '';
573
+ });
574
+ uri[name] = uri[name] || '';
575
+ };
576
+
577
+ consume('protocol', /^[a-z]+\:/i);
578
+ consume('host', /^\/\/[^\/\?#]+/);
579
+
580
+ if (!/^\//.test(url) && !uri.host)
581
+ url = Faye.ENV.location.pathname.replace(/[^\/]*$/, '') + url;
582
+
583
+ consume('pathname', /^[^\?#]*/);
584
+ consume('search', /^\?[^#]*/);
585
+ consume('hash', /^#.*/);
586
+
587
+ uri.protocol = uri.protocol || Faye.ENV.location.protocol;
588
+
589
+ if (uri.host) {
590
+ uri.host = uri.host.substr(2);
591
+ parts = uri.host.split(':');
592
+ uri.hostname = parts[0];
593
+ uri.port = parts[1] || '';
594
+ } else {
595
+ uri.host = Faye.ENV.location.host;
596
+ uri.hostname = Faye.ENV.location.hostname;
597
+ uri.port = Faye.ENV.location.port;
598
+ }
599
+
600
+ uri.pathname = uri.pathname || '/';
601
+ uri.path = uri.pathname + uri.search;
602
+
603
+ query = uri.search.replace(/^\?/, '');
604
+ pairs = query ? query.split('&') : [];
605
+ data = {};
606
+
607
+ for (i = 0, n = pairs.length; i < n; i++) {
608
+ parts = pairs[i].split('=');
609
+ data[decodeURIComponent(parts[0] || '')] = decodeURIComponent(parts[1] || '');
610
+ }
611
+
612
+ uri.query = data;
613
+
614
+ uri.href = this.stringify(uri);
615
+ return uri;
616
+ },
617
+
618
+ stringify: function(uri) {
619
+ var string = uri.protocol + '//' + uri.hostname;
620
+ if (uri.port) string += ':' + uri.port;
621
+ string += uri.pathname + this.queryString(uri.query) + (uri.hash || '');
622
+ return string;
623
+ },
624
+
625
+ queryString: function(query) {
626
+ var pairs = [];
627
+ for (var key in query) {
628
+ if (!query.hasOwnProperty(key)) continue;
629
+ pairs.push(encodeURIComponent(key) + '=' + encodeURIComponent(query[key]));
630
+ }
631
+ if (pairs.length === 0) return '';
632
+ return '?' + pairs.join('&');
633
+ }
634
+ };
216
635
 
217
636
  Faye.Error = Faye.Class({
218
637
  initialize: function(code, params, message) {
@@ -240,143 +659,133 @@ Faye.Error.parse = function(message) {
240
659
  return new this(code, params, message);
241
660
  };
242
661
 
662
+
663
+
664
+
243
665
  Faye.Error.versionMismatch = function() {
244
- return new this(300, arguments, "Version mismatch").toString();
666
+ return new this(300, arguments, 'Version mismatch').toString();
245
667
  };
668
+
246
669
  Faye.Error.conntypeMismatch = function() {
247
- return new this(301, arguments, "Connection types not supported").toString();
670
+ return new this(301, arguments, 'Connection types not supported').toString();
248
671
  };
672
+
249
673
  Faye.Error.extMismatch = function() {
250
- return new this(302, arguments, "Extension mismatch").toString();
674
+ return new this(302, arguments, 'Extension mismatch').toString();
251
675
  };
676
+
252
677
  Faye.Error.badRequest = function() {
253
- return new this(400, arguments, "Bad request").toString();
678
+ return new this(400, arguments, 'Bad request').toString();
254
679
  };
680
+
255
681
  Faye.Error.clientUnknown = function() {
256
- return new this(401, arguments, "Unknown client").toString();
682
+ return new this(401, arguments, 'Unknown client').toString();
257
683
  };
684
+
258
685
  Faye.Error.parameterMissing = function() {
259
- return new this(402, arguments, "Missing required parameter").toString();
686
+ return new this(402, arguments, 'Missing required parameter').toString();
260
687
  };
688
+
261
689
  Faye.Error.channelForbidden = function() {
262
- return new this(403, arguments, "Forbidden channel").toString();
690
+ return new this(403, arguments, 'Forbidden channel').toString();
263
691
  };
692
+
264
693
  Faye.Error.channelUnknown = function() {
265
- return new this(404, arguments, "Unknown channel").toString();
694
+ return new this(404, arguments, 'Unknown channel').toString();
266
695
  };
696
+
267
697
  Faye.Error.channelInvalid = function() {
268
- return new this(405, arguments, "Invalid channel").toString();
698
+ return new this(405, arguments, 'Invalid channel').toString();
269
699
  };
700
+
270
701
  Faye.Error.extUnknown = function() {
271
- return new this(406, arguments, "Unknown extension").toString();
702
+ return new this(406, arguments, 'Unknown extension').toString();
272
703
  };
704
+
273
705
  Faye.Error.publishFailed = function() {
274
- return new this(407, arguments, "Failed to publish").toString();
706
+ return new this(407, arguments, 'Failed to publish').toString();
275
707
  };
708
+
276
709
  Faye.Error.serverError = function() {
277
- return new this(500, arguments, "Internal server error").toString();
710
+ return new this(500, arguments, 'Internal server error').toString();
278
711
  };
279
712
 
280
713
 
281
714
  Faye.Deferrable = {
282
- callback: function(callback, context) {
283
- if (!callback) return;
284
-
285
- if (this._deferredStatus === 'succeeded')
286
- return callback.apply(context, this._deferredArgs);
715
+ then: function(callback, errback) {
716
+ var self = this;
717
+ if (!this._promise)
718
+ this._promise = new Faye.Promise(function(fulfill, reject) {
719
+ self._fulfill = fulfill;
720
+ self._reject = reject;
721
+ });
287
722
 
288
- this._callbacks = this._callbacks || [];
289
- this._callbacks.push([callback, context]);
723
+ if (arguments.length === 0)
724
+ return this._promise;
725
+ else
726
+ return this._promise.then(callback, errback);
290
727
  },
291
728
 
292
- timeout: function(seconds, message) {
293
- var _this = this;
294
- var timer = Faye.ENV.setTimeout(function() {
295
- _this.setDeferredStatus('failed', message);
296
- }, seconds * 1000);
297
- this._timer = timer;
729
+ callback: function(callback, context) {
730
+ return this.then(function(value) { callback.call(context, value) });
298
731
  },
299
732
 
300
733
  errback: function(callback, context) {
301
- if (!callback) return;
302
-
303
- if (this._deferredStatus === 'failed')
304
- return callback.apply(context, this._deferredArgs);
305
-
306
- this._errbacks = this._errbacks || [];
307
- this._errbacks.push([callback, context]);
734
+ return this.then(null, function(reason) { callback.call(context, reason) });
308
735
  },
309
736
 
310
- setDeferredStatus: function() {
311
- if (this._timer)
312
- Faye.ENV.clearTimeout(this._timer);
737
+ timeout: function(seconds, message) {
738
+ this.then();
739
+ var self = this;
740
+ this._timer = Faye.ENV.setTimeout(function() {
741
+ self._reject(message);
742
+ }, seconds * 1000);
743
+ },
313
744
 
314
- var args = Array.prototype.slice.call(arguments),
315
- status = args.shift(),
316
- callbacks;
745
+ setDeferredStatus: function(status, value) {
746
+ if (this._timer) Faye.ENV.clearTimeout(this._timer);
317
747
 
318
- this._deferredStatus = status;
319
- this._deferredArgs = args;
748
+ var promise = this.then();
320
749
 
321
750
  if (status === 'succeeded')
322
- callbacks = this._callbacks;
751
+ this._fulfill(value);
323
752
  else if (status === 'failed')
324
- callbacks = this._errbacks;
325
-
326
- if (!callbacks) return;
327
-
328
- var callback;
329
- while (callback = callbacks.shift())
330
- callback[0].apply(callback[1], this._deferredArgs);
753
+ this._reject(value);
754
+ else
755
+ delete this._promise;
331
756
  }
332
757
  };
333
758
 
334
-
335
759
  Faye.Publisher = {
336
760
  countListeners: function(eventType) {
337
- if (!this._subscribers || !this._subscribers[eventType]) return 0;
338
- return this._subscribers[eventType].length;
761
+ return this.listeners(eventType).length;
339
762
  },
340
763
 
341
764
  bind: function(eventType, listener, context) {
342
- this._subscribers = this._subscribers || {};
343
- var list = this._subscribers[eventType] = this._subscribers[eventType] || [];
344
- list.push([listener, context]);
345
- },
346
-
347
- unbind: function(eventType, listener, context) {
348
- if (!this._subscribers || !this._subscribers[eventType]) return;
349
-
350
- if (!listener) {
351
- delete this._subscribers[eventType];
352
- return;
353
- }
354
- var list = this._subscribers[eventType],
355
- i = list.length;
765
+ var slice = Array.prototype.slice,
766
+ handler = function() { listener.apply(context, slice.call(arguments)) };
356
767
 
357
- while (i--) {
358
- if (listener !== list[i][0]) continue;
359
- if (context && list[i][1] !== context) continue;
360
- list.splice(i,1);
361
- }
768
+ this._listeners = this._listeners || [];
769
+ this._listeners.push([eventType, listener, context, handler]);
770
+ return this.on(eventType, handler);
362
771
  },
363
772
 
364
- trigger: function() {
365
- var args = Array.prototype.slice.call(arguments),
366
- eventType = args.shift();
367
-
368
- if (!this._subscribers || !this._subscribers[eventType]) return;
369
-
370
- var listeners = this._subscribers[eventType].slice(),
371
- listener;
372
-
373
- for (var i = 0, n = listeners.length; i < n; i++) {
374
- listener = listeners[i];
375
- listener[0].apply(listener[1], args);
773
+ unbind: function(eventType, listener, context) {
774
+ this._listeners = this._listeners || [];
775
+ var n = this._listeners.length, tuple;
776
+
777
+ while (n--) {
778
+ tuple = this._listeners[n];
779
+ if (tuple[0] !== eventType) continue;
780
+ if (listener && (tuple[1] !== listener || tuple[2] !== context)) continue;
781
+ this._listeners.splice(n, 1);
782
+ this.removeListener(eventType, tuple[3]);
376
783
  }
377
784
  }
378
785
  };
379
786
 
787
+ Faye.extend(Faye.Publisher, Faye.EventEmitter.prototype);
788
+ Faye.Publisher.trigger = Faye.Publisher.emit;
380
789
 
381
790
  Faye.Timeouts = {
382
791
  addTimeout: function(name, delay, callback, context) {
@@ -395,29 +804,29 @@ Faye.Timeouts = {
395
804
  if (!timeout) return;
396
805
  clearTimeout(timeout);
397
806
  delete this._timeouts[name];
807
+ },
808
+
809
+ removeAllTimeouts: function() {
810
+ this._timeouts = this._timeouts || {};
811
+ for (var name in this._timeouts) this.removeTimeout(name);
398
812
  }
399
813
  };
400
814
 
401
-
402
815
  Faye.Logging = {
403
816
  LOG_LEVELS: {
817
+ fatal: 4,
404
818
  error: 3,
405
819
  warn: 2,
406
820
  info: 1,
407
821
  debug: 0
408
822
  },
409
823
 
410
- logLevel: 'error',
411
-
412
- log: function(messageArgs, level) {
824
+ writeLog: function(messageArgs, level) {
413
825
  if (!Faye.logger) return;
414
826
 
415
- var levels = Faye.Logging.LOG_LEVELS;
416
- if (levels[Faye.Logging.logLevel] > levels[level]) return;
417
-
418
827
  var messageArgs = Array.prototype.slice.apply(messageArgs),
419
- banner = ' [' + level.toUpperCase() + '] [Faye',
420
- klass = this.className,
828
+ banner = '[Faye',
829
+ klass = this.className,
421
830
 
422
831
  message = messageArgs.shift().replace(/\?/g, function() {
423
832
  try {
@@ -435,7 +844,10 @@ Faye.Logging = {
435
844
  if (klass) banner += '.' + klass;
436
845
  banner += '] ';
437
846
 
438
- Faye.logger(Faye.timestamp() + banner + message);
847
+ if (typeof Faye.logger[level] === 'function')
848
+ Faye.logger[level](banner + message);
849
+ else if (typeof Faye.logger === 'function')
850
+ Faye.logger(banner + message);
439
851
  }
440
852
  };
441
853
 
@@ -443,38 +855,18 @@ Faye.Logging = {
443
855
  for (var key in Faye.Logging.LOG_LEVELS)
444
856
  (function(level, value) {
445
857
  Faye.Logging[level] = function() {
446
- this.log(arguments, level);
858
+ this.writeLog(arguments, level);
447
859
  };
448
860
  })(key, Faye.Logging.LOG_LEVELS[key]);
449
861
  })();
450
862
 
451
-
452
863
  Faye.Grammar = {
453
- LOWALPHA: /^[a-z]$/,
454
- UPALPHA: /^[A-Z]$/,
455
- ALPHA: /^([a-z]|[A-Z])$/,
456
- DIGIT: /^[0-9]$/,
457
- ALPHANUM: /^(([a-z]|[A-Z])|[0-9])$/,
458
- MARK: /^(\-|\_|\!|\~|\(|\)|\$|\@)$/,
459
- STRING: /^(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)| |\/|\*|\.))*$/,
460
- TOKEN: /^(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)))+$/,
461
- INTEGER: /^([0-9])+$/,
462
- CHANNEL_SEGMENT: /^(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)))+$/,
463
- CHANNEL_SEGMENTS: /^(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)))+(\/(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)))+)*$/,
464
864
  CHANNEL_NAME: /^\/(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)))+(\/(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)))+)*$/,
465
- WILD_CARD: /^\*{1,2}$/,
466
- CHANNEL_PATTERN: /^(\/(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)))+)*\/\*{1,2}$/,
467
- VERSION_ELEMENT: /^(([a-z]|[A-Z])|[0-9])(((([a-z]|[A-Z])|[0-9])|\-|\_))*$/,
468
- VERSION: /^([0-9])+(\.(([a-z]|[A-Z])|[0-9])(((([a-z]|[A-Z])|[0-9])|\-|\_))*)*$/,
469
- CLIENT_ID: /^((([a-z]|[A-Z])|[0-9]))+$/,
470
- ID: /^((([a-z]|[A-Z])|[0-9]))+$/,
471
- ERROR_MESSAGE: /^(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)| |\/|\*|\.))*$/,
472
- ERROR_ARGS: /^(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)| |\/|\*|\.))*(,(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)| |\/|\*|\.))*)*$/,
473
- ERROR_CODE: /^[0-9][0-9][0-9]$/,
474
- ERROR: /^([0-9][0-9][0-9]:(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)| |\/|\*|\.))*(,(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)| |\/|\*|\.))*)*:(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)| |\/|\*|\.))*|[0-9][0-9][0-9]::(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)| |\/|\*|\.))*)$/
865
+ CHANNEL_PATTERN: /^(\/(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)))+)*\/\*{1,2}$/,
866
+ ERROR: /^([0-9][0-9][0-9]:(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)| |\/|\*|\.))*(,(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)| |\/|\*|\.))*)*:(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)| |\/|\*|\.))*|[0-9][0-9][0-9]::(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)| |\/|\*|\.))*)$/,
867
+ VERSION: /^([0-9])+(\.(([a-z]|[A-Z])|[0-9])(((([a-z]|[A-Z])|[0-9])|\-|\_))*)*$/
475
868
  };
476
869
 
477
-
478
870
  Faye.Extensible = {
479
871
  addExtension: function(extension) {
480
872
  this._extensions = this._extensions || [];
@@ -492,7 +884,7 @@ Faye.Extensible = {
492
884
  }
493
885
  },
494
886
 
495
- pipeThroughExtensions: function(stage, message, callback, context) {
887
+ pipeThroughExtensions: function(stage, message, request, callback, context) {
496
888
  this.debug('Passing through ? extensions: ?', stage, message);
497
889
 
498
890
  if (!this._extensions) return callback.call(context, message);
@@ -504,8 +896,11 @@ Faye.Extensible = {
504
896
  var extension = extensions.shift();
505
897
  if (!extension) return callback.call(context, message);
506
898
 
507
- if (extension[stage]) extension[stage](message, pipe);
508
- else pipe(message);
899
+ var fn = extension[stage];
900
+ if (!fn) return pipe(message);
901
+
902
+ if (fn.length >= 3) extension[stage](message, request, pipe);
903
+ else extension[stage](message, pipe);
509
904
  };
510
905
  pipe(message);
511
906
  }
@@ -638,9 +1033,18 @@ Faye.extend(Faye.Channel, {
638
1033
  })
639
1034
  });
640
1035
 
1036
+ Faye.Envelope = Faye.Class({
1037
+ initialize: function(message, timeout) {
1038
+ this.id = message.id;
1039
+ this.message = message;
641
1040
 
642
- Faye.Publication = Faye.Class(Faye.Deferrable);
1041
+ if (timeout !== undefined) this.timeout(timeout / 1000, false);
1042
+ }
1043
+ });
1044
+
1045
+ Faye.extend(Faye.Envelope.prototype, Faye.Deferrable);
643
1046
 
1047
+ Faye.Publication = Faye.Class(Faye.Deferrable);
644
1048
 
645
1049
  Faye.Subscription = Faye.Class({
646
1050
  initialize: function(client, channels, callback, context) {
@@ -664,7 +1068,6 @@ Faye.Subscription = Faye.Class({
664
1068
 
665
1069
  Faye.extend(Faye.Subscription.prototype, Faye.Deferrable);
666
1070
 
667
-
668
1071
  Faye.Client = Faye.Class({
669
1072
  UNCONNECTED: 1,
670
1073
  CONNECTING: 2,
@@ -675,23 +1078,30 @@ Faye.Client = Faye.Class({
675
1078
  RETRY: 'retry',
676
1079
  NONE: 'none',
677
1080
 
678
- CONNECTION_TIMEOUT: 60.0,
679
- DEFAULT_RETRY: 5.0,
1081
+ CONNECTION_TIMEOUT: 60,
1082
+ DEFAULT_RETRY: 5,
1083
+ MAX_REQUEST_SIZE: 2048,
680
1084
 
681
1085
  DEFAULT_ENDPOINT: '/bayeux',
682
- INTERVAL: 0.0,
1086
+ INTERVAL: 0,
683
1087
 
684
1088
  initialize: function(endpoint, options) {
685
1089
  this.info('New client created for ?', endpoint);
686
1090
 
687
1091
  this._options = options || {};
688
- this.endpoint = endpoint || this.DEFAULT_ENDPOINT;
1092
+ this.endpoint = Faye.URI.parse(endpoint || this.DEFAULT_ENDPOINT);
689
1093
  this.endpoints = this._options.endpoints || {};
690
1094
  this.transports = {};
691
- this._cookies = Faye.CookieJar && new Faye.CookieJar();
692
- this._headers = {};
1095
+ this.cookies = Faye.CookieJar && new Faye.CookieJar();
1096
+ this.headers = {};
1097
+ this.ca = this._options.ca;
693
1098
  this._disabled = [];
694
- this.retry = this._options.retry || this.DEFAULT_RETRY;
1099
+ this._retry = this._options.retry || this.DEFAULT_RETRY;
1100
+
1101
+ for (var key in this.endpoints)
1102
+ this.endpoints[key] = Faye.URI.parse(this.endpoints[key]);
1103
+
1104
+ this.maxRequestSize = this.MAX_REQUEST_SIZE;
695
1105
 
696
1106
  this._state = this.UNCONNECTED;
697
1107
  this._channels = new Faye.Channel.Set();
@@ -705,7 +1115,7 @@ Faye.Client = Faye.Class({
705
1115
  timeout: 1000 * (this._options.timeout || this.CONNECTION_TIMEOUT)
706
1116
  };
707
1117
 
708
- if (Faye.Event)
1118
+ if (Faye.Event && Faye.ENV.onbeforeunload !== undefined)
709
1119
  Faye.Event.on(Faye.ENV, 'beforeunload', function() {
710
1120
  if (Faye.indexOf(this._disabled, 'autodisconnect') < 0)
711
1121
  this.disconnect();
@@ -717,20 +1127,7 @@ Faye.Client = Faye.Class({
717
1127
  },
718
1128
 
719
1129
  setHeader: function(name, value) {
720
- this._headers[name] = value;
721
- },
722
-
723
- getClientId: function() {
724
- return this._clientId;
725
- },
726
-
727
- getState: function() {
728
- switch (this._state) {
729
- case this.UNCONNECTED: return 'UNCONNECTED';
730
- case this.CONNECTING: return 'CONNECTING';
731
- case this.CONNECTED: return 'CONNECTED';
732
- case this.DISCONNECTED: return 'DISCONNECTED';
733
- }
1130
+ this.headers[name] = value;
734
1131
  },
735
1132
 
736
1133
  // Request
@@ -759,12 +1156,12 @@ Faye.Client = Faye.Class({
759
1156
  this._state = this.CONNECTING;
760
1157
  var self = this;
761
1158
 
762
- this.info('Initiating handshake with ?', this.endpoint);
1159
+ this.info('Initiating handshake with ?', Faye.URI.stringify(this.endpoint));
763
1160
  this._selectTransport(Faye.MANDATORY_CONNECTION_TYPES);
764
1161
 
765
1162
  this._send({
766
- channel: Faye.Channel.HANDSHAKE,
767
- version: Faye.BAYEUX_VERSION,
1163
+ channel: Faye.Channel.HANDSHAKE,
1164
+ version: Faye.BAYEUX_VERSION,
768
1165
  supportedConnectionTypes: [this._transport.connectionType]
769
1166
 
770
1167
  }, function(response) {
@@ -778,7 +1175,7 @@ Faye.Client = Faye.Class({
778
1175
  this.info('Handshake successful: ?', this._clientId);
779
1176
 
780
1177
  this.subscribe(this._channels.getKeys(), true);
781
- if (callback) callback.call(context);
1178
+ if (callback) Faye.Promise.defer(function() { callback.call(context) });
782
1179
 
783
1180
  } else {
784
1181
  this.info('Handshake unsuccessful');
@@ -809,7 +1206,7 @@ Faye.Client = Faye.Class({
809
1206
 
810
1207
  this.info('Calling deferred actions for ?', this._clientId);
811
1208
  this.setDeferredStatus('succeeded');
812
- this.setDeferredStatus('deferred');
1209
+ this.setDeferredStatus('unknown');
813
1210
 
814
1211
  if (this._connectRequest) return;
815
1212
  this._connectRequest = true;
@@ -838,11 +1235,13 @@ Faye.Client = Faye.Class({
838
1235
  this.info('Disconnecting ?', this._clientId);
839
1236
 
840
1237
  this._send({
841
- channel: Faye.Channel.DISCONNECT,
842
- clientId: this._clientId
1238
+ channel: Faye.Channel.DISCONNECT,
1239
+ clientId: this._clientId
843
1240
 
844
1241
  }, function(response) {
845
- if (response.successful) this._transport.close();
1242
+ if (!response.successful) return;
1243
+ this._transport.close();
1244
+ delete this._transport;
846
1245
  }, this);
847
1246
 
848
1247
  this.info('Clearing channel listeners for ?', this._clientId);
@@ -948,9 +1347,10 @@ Faye.Client = Faye.Class({
948
1347
  this.info('Client ? queueing published message to ?: ?', this._clientId, channel, data);
949
1348
 
950
1349
  this._send({
951
- channel: channel,
952
- data: data,
953
- clientId: this._clientId
1350
+ channel: channel,
1351
+ data: data,
1352
+ clientId: this._clientId
1353
+
954
1354
  }, function(response) {
955
1355
  if (response.successful)
956
1356
  publication.setDeferredStatus('succeeded');
@@ -963,57 +1363,82 @@ Faye.Client = Faye.Class({
963
1363
  },
964
1364
 
965
1365
  receiveMessage: function(message) {
966
- this.pipeThroughExtensions('incoming', message, function(message) {
1366
+ var id = message.id, timeout, callback;
1367
+
1368
+ if (message.successful !== undefined) {
1369
+ callback = this._responseCallbacks[id];
1370
+ delete this._responseCallbacks[id];
1371
+ }
1372
+
1373
+ this.pipeThroughExtensions('incoming', message, null, function(message) {
967
1374
  if (!message) return;
968
1375
 
969
1376
  if (message.advice) this._handleAdvice(message.advice);
970
1377
  this._deliverMessage(message);
971
1378
 
972
- if (message.successful === undefined) return;
1379
+ if (callback) callback[0].call(callback[1], message);
1380
+ }, this);
973
1381
 
974
- var callback = this._responseCallbacks[message.id];
975
- if (!callback) return;
1382
+ if (this._transportUp === true) return;
1383
+ this._transportUp = true;
1384
+ this.trigger('transport:up');
1385
+ },
976
1386
 
977
- delete this._responseCallbacks[message.id];
978
- callback[0].call(callback[1], message);
979
- }, this);
1387
+ messageError: function(messages, immediate) {
1388
+ var retry = this._retry,
1389
+ self = this,
1390
+ id, message, timeout;
1391
+
1392
+ for (var i = 0, n = messages.length; i < n; i++) {
1393
+ message = messages[i];
1394
+ id = message.id;
1395
+
1396
+ if (immediate)
1397
+ this._transportSend(message);
1398
+ else
1399
+ Faye.ENV.setTimeout(function() { self._transportSend(message) }, retry * 1000);
1400
+ }
1401
+
1402
+ if (immediate || this._transportUp === false) return;
1403
+ this._transportUp = false;
1404
+ this.trigger('transport:down');
980
1405
  },
981
1406
 
982
1407
  _selectTransport: function(transportTypes) {
983
1408
  Faye.Transport.get(this, transportTypes, this._disabled, function(transport) {
984
- this.debug('Selected ? transport for ?', transport.connectionType, transport.endpoint);
1409
+ this.debug('Selected ? transport for ?', transport.connectionType, Faye.URI.stringify(transport.endpoint));
985
1410
 
986
1411
  if (transport === this._transport) return;
987
1412
  if (this._transport) this._transport.close();
988
1413
 
989
1414
  this._transport = transport;
990
- this._transport.cookies = this._cookies;
991
- this._transport.headers = this._headers;
992
-
993
- transport.bind('down', function() {
994
- if (this._transportUp !== undefined && !this._transportUp) return;
995
- this._transportUp = false;
996
- this.trigger('transport:down');
997
- }, this);
998
-
999
- transport.bind('up', function() {
1000
- if (this._transportUp !== undefined && this._transportUp) return;
1001
- this._transportUp = true;
1002
- this.trigger('transport:up');
1003
- }, this);
1004
1415
  }, this);
1005
1416
  },
1006
1417
 
1007
1418
  _send: function(message, callback, context) {
1008
- message.id = this._generateMessageId();
1009
- if (callback) this._responseCallbacks[message.id] = [callback, context];
1419
+ if (!this._transport) return;
1420
+ message.id = message.id || this._generateMessageId();
1010
1421
 
1011
- this.pipeThroughExtensions('outgoing', message, function(message) {
1422
+ this.pipeThroughExtensions('outgoing', message, null, function(message) {
1012
1423
  if (!message) return;
1013
- this._transport.send(message, this._advice.timeout / 1000);
1424
+ if (callback) this._responseCallbacks[message.id] = [callback, context];
1425
+ this._transportSend(message);
1014
1426
  }, this);
1015
1427
  },
1016
1428
 
1429
+ _transportSend: function(message) {
1430
+ if (!this._transport) return;
1431
+
1432
+ var timeout = 1.2 * (this._advice.timeout || this._retry * 1000),
1433
+ envelope = new Faye.Envelope(message, timeout);
1434
+
1435
+ envelope.errback(function(immediate) {
1436
+ this.messageError([message], immediate);
1437
+ }, this);
1438
+
1439
+ this._transport.send(envelope);
1440
+ },
1441
+
1017
1442
  _generateMessageId: function() {
1018
1443
  this._messageId += 1;
1019
1444
  if (this._messageId >= Math.pow(2,32)) this._messageId = 0;
@@ -1036,14 +1461,11 @@ Faye.Client = Faye.Class({
1036
1461
  this._channels.distributeMessage(message);
1037
1462
  },
1038
1463
 
1039
- _teardownConnection: function() {
1040
- if (!this._connectRequest) return;
1041
- this._connectRequest = null;
1042
- this.info('Closed connection for ?', this._clientId);
1043
- },
1044
-
1045
1464
  _cycleConnection: function() {
1046
- this._teardownConnection();
1465
+ if (this._connectRequest) {
1466
+ this._connectRequest = null;
1467
+ this.info('Closed connection for ?', this._clientId);
1468
+ }
1047
1469
  var self = this;
1048
1470
  Faye.ENV.setTimeout(function() { self.connect() }, this._advice.interval);
1049
1471
  }
@@ -1054,9 +1476,8 @@ Faye.extend(Faye.Client.prototype, Faye.Publisher);
1054
1476
  Faye.extend(Faye.Client.prototype, Faye.Logging);
1055
1477
  Faye.extend(Faye.Client.prototype, Faye.Extensible);
1056
1478
 
1057
-
1058
1479
  Faye.Transport = Faye.extend(Faye.Class({
1059
- MAX_DELAY: 0.0,
1480
+ MAX_DELAY: 0,
1060
1481
  batching: true,
1061
1482
 
1062
1483
  initialize: function(client, endpoint) {
@@ -1067,14 +1488,19 @@ Faye.Transport = Faye.extend(Faye.Class({
1067
1488
 
1068
1489
  close: function() {},
1069
1490
 
1070
- send: function(message, timeout) {
1491
+ encode: function(envelopes) {
1492
+ return '';
1493
+ },
1494
+
1495
+ send: function(envelope) {
1496
+ var message = envelope.message;
1497
+
1071
1498
  this.debug('Client ? sending message to ?: ?',
1072
- this._client._clientId, this.endpoint, message);
1499
+ this._client._clientId, Faye.URI.stringify(this.endpoint), message);
1073
1500
 
1074
- if (!this.batching) return this.request([message], timeout);
1501
+ if (!this.batching) return this.request([envelope]);
1075
1502
 
1076
- this._outbox.push(message);
1077
- this._timeout = timeout;
1503
+ this._outbox.push(envelope);
1078
1504
 
1079
1505
  if (message.channel === Faye.Channel.HANDSHAKE)
1080
1506
  return this.addTimeout('publish', 0.01, this.flush, this);
@@ -1082,9 +1508,7 @@ Faye.Transport = Faye.extend(Faye.Class({
1082
1508
  if (message.channel === Faye.Channel.CONNECT)
1083
1509
  this._connectMessage = message;
1084
1510
 
1085
- if (this.shouldFlush && this.shouldFlush(this._outbox))
1086
- return this.flush();
1087
-
1511
+ this.flushLargeBatch();
1088
1512
  this.addTimeout('publish', this.MAX_DELAY, this.flush, this);
1089
1513
  },
1090
1514
 
@@ -1094,36 +1518,62 @@ Faye.Transport = Faye.extend(Faye.Class({
1094
1518
  if (this._outbox.length > 1 && this._connectMessage)
1095
1519
  this._connectMessage.advice = {timeout: 0};
1096
1520
 
1097
- this.request(this._outbox, this._timeout);
1521
+ this.request(this._outbox);
1098
1522
 
1099
1523
  this._connectMessage = null;
1100
1524
  this._outbox = [];
1101
1525
  },
1102
1526
 
1103
- receive: function(responses) {
1527
+ flushLargeBatch: function() {
1528
+ var string = this.encode(this._outbox);
1529
+ if (string.length < this._client.maxRequestSize) return;
1530
+ var last = this._outbox.pop();
1531
+ this.flush();
1532
+ if (last) this._outbox.push(last);
1533
+ },
1534
+
1535
+ receive: function(envelopes, responses) {
1536
+ var n = envelopes.length;
1537
+ while (n--) envelopes[n].setDeferredStatus('succeeded');
1538
+
1539
+ responses = [].concat(responses);
1540
+
1104
1541
  this.debug('Client ? received from ?: ?',
1105
- this._client._clientId, this.endpoint, responses);
1542
+ this._client._clientId, Faye.URI.stringify(this.endpoint), responses);
1106
1543
 
1107
- for (var i = 0, n = responses.length; i < n; i++) {
1544
+ for (var i = 0, n = responses.length; i < n; i++)
1108
1545
  this._client.receiveMessage(responses[i]);
1109
- }
1110
1546
  },
1111
1547
 
1112
- retry: function(message, timeout) {
1113
- var called = false,
1114
- retry = this._client.retry * 1000,
1115
- self = this;
1548
+ handleError: function(envelopes, immediate) {
1549
+ var n = envelopes.length;
1550
+ while (n--) envelopes[n].setDeferredStatus('failed', immediate);
1551
+ },
1116
1552
 
1117
- return function() {
1118
- if (called) return;
1119
- called = true;
1120
- Faye.ENV.setTimeout(function() { self.request(message, timeout) }, retry);
1121
- };
1553
+ _getCookies: function() {
1554
+ var cookies = this._client.cookies;
1555
+ if (!cookies) return '';
1556
+
1557
+ return cookies.getCookies({
1558
+ domain: this.endpoint.hostname,
1559
+ path: this.endpoint.path,
1560
+ secure: this.endpoint.protocol === 'https:'
1561
+ }).toValueString();
1562
+ },
1563
+
1564
+ _storeCookies: function(setCookie) {
1565
+ if (!setCookie || !this._client.cookies) return;
1566
+ setCookie = [].concat(setCookie);
1567
+ var cookie;
1568
+
1569
+ for (var i = 0, n = setCookie.length; i < n; i++) {
1570
+ cookie = this._client.cookies.setCookie(setCookie[i]);
1571
+ cookie = cookie[0] || cookie;
1572
+ cookie.domain = cookie.domain || this.endpoint.hostname;
1573
+ }
1122
1574
  }
1123
1575
 
1124
1576
  }), {
1125
- MAX_URL_LENGTH: 2048,
1126
-
1127
1577
  get: function(client, allowed, disabled, callback, context) {
1128
1578
  var endpoint = client.endpoint;
1129
1579
 
@@ -1145,7 +1595,7 @@ Faye.Transport = Faye.extend(Faye.Class({
1145
1595
  callback.call(context, transport);
1146
1596
  });
1147
1597
  }, function() {
1148
- throw new Error('Could not find a usable connection type for ' + endpoint);
1598
+ throw new Error('Could not find a usable connection type for ' + Faye.URI.stringify(endpoint));
1149
1599
  });
1150
1600
  },
1151
1601
 
@@ -1158,10 +1608,8 @@ Faye.Transport = Faye.extend(Faye.Class({
1158
1608
  });
1159
1609
 
1160
1610
  Faye.extend(Faye.Transport.prototype, Faye.Logging);
1161
- Faye.extend(Faye.Transport.prototype, Faye.Publisher);
1162
1611
  Faye.extend(Faye.Transport.prototype, Faye.Timeouts);
1163
1612
 
1164
-
1165
1613
  Faye.Event = {
1166
1614
  _registry: [],
1167
1615
 
@@ -1204,91 +1652,11 @@ Faye.Event = {
1204
1652
  }
1205
1653
  };
1206
1654
 
1207
- Faye.Event.on(Faye.ENV, 'unload', Faye.Event.detach, Faye.Event);
1208
-
1209
-
1210
- Faye.URI = Faye.extend(Faye.Class({
1211
- queryString: function() {
1212
- var pairs = [];
1213
- for (var key in this.params) {
1214
- if (!this.params.hasOwnProperty(key)) continue;
1215
- pairs.push(encodeURIComponent(key) + '=' + encodeURIComponent(this.params[key]));
1216
- }
1217
- return pairs.join('&');
1218
- },
1219
-
1220
- isSameOrigin: function() {
1221
- var host = Faye.URI.parse(Faye.ENV.location.href, false);
1222
-
1223
- var external = (host.hostname !== this.hostname) ||
1224
- (host.port !== this.port) ||
1225
- (host.protocol !== this.protocol);
1226
-
1227
- return !external;
1228
- },
1229
-
1230
- toURL: function() {
1231
- var query = this.queryString();
1232
- return this.protocol + '//' + this.hostname + (this.port ? ':' + this.port : '') +
1233
- this.pathname + (query ? '?' + query : '') + this.hash;
1234
- }
1235
- }), {
1236
- parse: function(url, params) {
1237
- if (typeof url !== 'string') return url;
1238
- var uri = new this(), parts;
1239
-
1240
- var consume = function(name, pattern, infer) {
1241
- url = url.replace(pattern, function(match) {
1242
- uri[name] = match;
1243
- return '';
1244
- });
1245
- if (uri[name] === undefined)
1246
- uri[name] = infer ? Faye.ENV.location[name] : '';
1247
- };
1248
-
1249
- consume('protocol', /^https?\:/, true);
1250
- consume('host', /^\/\/[^\/]+/, true);
1251
-
1252
- if (!/^\//.test(url)) url = Faye.ENV.location.pathname.replace(/[^\/]*$/, '') + url;
1253
- consume('pathname', /^\/[^\?#]*/);
1254
- consume('search', /^\?[^#]*/);
1255
- consume('hash', /^#.*/);
1256
-
1257
- if (/^\/\//.test(uri.host)) {
1258
- uri.host = uri.host.substr(2);
1259
- parts = uri.host.split(':');
1260
- uri.hostname = parts[0];
1261
- uri.port = parts[1] || '';
1262
- } else {
1263
- uri.hostname = Faye.ENV.location.hostname;
1264
- uri.port = Faye.ENV.location.port;
1265
- }
1266
-
1267
- if (params === false) {
1268
- uri.params = {};
1269
- } else {
1270
- var query = uri.search.replace(/^\?/, ''),
1271
- pairs = query ? query.split('&') : [],
1272
- n = pairs.length,
1273
- data = {};
1274
-
1275
- while (n--) {
1276
- parts = pairs[n].split('=');
1277
- data[decodeURIComponent(parts[0] || '')] = decodeURIComponent(parts[1] || '');
1278
- }
1279
- if (typeof params === 'object') Faye.extend(data, params);
1280
-
1281
- uri.params = data;
1282
- }
1283
-
1284
- return uri;
1285
- }
1286
- });
1287
-
1655
+ if (Faye.ENV.onunload !== undefined) Faye.Event.on(Faye.ENV, 'unload', Faye.Event.detach, Faye.Event);
1288
1656
 
1289
1657
  /*
1290
- http://www.JSON.org/json2.js
1291
- 2009-04-16
1658
+ json2.js
1659
+ 2013-05-26
1292
1660
 
1293
1661
  Public Domain.
1294
1662
 
@@ -1296,6 +1664,14 @@ Faye.URI = Faye.extend(Faye.Class({
1296
1664
 
1297
1665
  See http://www.JSON.org/js.html
1298
1666
 
1667
+
1668
+ This code should be minified before deployment.
1669
+ See http://javascript.crockford.com/jsmin.html
1670
+
1671
+ USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
1672
+ NOT CONTROL.
1673
+
1674
+
1299
1675
  This file creates a global JSON object containing two methods: stringify
1300
1676
  and parse.
1301
1677
 
@@ -1321,7 +1697,7 @@ Faye.URI = Faye.extend(Faye.Class({
1321
1697
  value represented by the name/value pair that should be serialized,
1322
1698
  or undefined if nothing should be serialized. The toJSON method
1323
1699
  will be passed the key associated with the value, and this will be
1324
- bound to the object holding the key.
1700
+ bound to the value
1325
1701
 
1326
1702
  For example, this would serialize Dates as ISO strings.
1327
1703
 
@@ -1424,17 +1800,9 @@ Faye.URI = Faye.extend(Faye.Class({
1424
1800
 
1425
1801
  This is a reference implementation. You are free to copy, modify, or
1426
1802
  redistribute.
1427
-
1428
- This code should be minified before deployment.
1429
- See http://javascript.crockford.com/jsmin.html
1430
-
1431
- USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
1432
- NOT CONTROL.
1433
1803
  */
1434
1804
 
1435
- /*jslint evil: true */
1436
-
1437
- /*global JSON */
1805
+ /*jslint evil: true, regexp: true */
1438
1806
 
1439
1807
  /*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply,
1440
1808
  call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
@@ -1443,13 +1811,16 @@ Faye.URI = Faye.extend(Faye.Class({
1443
1811
  test, toJSON, toString, valueOf
1444
1812
  */
1445
1813
 
1814
+
1446
1815
  // Create a JSON object only if one does not already exist. We create the
1447
1816
  // methods in a closure to avoid creating global variables.
1448
1817
 
1449
- if (!this.JSON) {
1818
+ if (typeof JSON !== 'object') {
1450
1819
  JSON = {};
1451
1820
  }
1821
+
1452
1822
  (function () {
1823
+ 'use strict';
1453
1824
 
1454
1825
  function f(n) {
1455
1826
  // Format integers to have at least two digits.
@@ -1458,21 +1829,23 @@ if (!this.JSON) {
1458
1829
 
1459
1830
  if (typeof Date.prototype.toJSON !== 'function') {
1460
1831
 
1461
- Date.prototype.toJSON = function (key) {
1832
+ Date.prototype.toJSON = function () {
1462
1833
 
1463
- return this.getUTCFullYear() + '-' +
1464
- f(this.getUTCMonth() + 1) + '-' +
1465
- f(this.getUTCDate()) + 'T' +
1466
- f(this.getUTCHours()) + ':' +
1467
- f(this.getUTCMinutes()) + ':' +
1468
- f(this.getUTCSeconds()) + 'Z';
1834
+ return isFinite(this.valueOf())
1835
+ ? this.getUTCFullYear() + '-' +
1836
+ f(this.getUTCMonth() + 1) + '-' +
1837
+ f(this.getUTCDate()) + 'T' +
1838
+ f(this.getUTCHours()) + ':' +
1839
+ f(this.getUTCMinutes()) + ':' +
1840
+ f(this.getUTCSeconds()) + 'Z'
1841
+ : null;
1469
1842
  };
1470
1843
 
1471
- String.prototype.toJSON =
1472
- Number.prototype.toJSON =
1473
- Boolean.prototype.toJSON = function (key) {
1474
- return this.valueOf();
1475
- };
1844
+ String.prototype.toJSON =
1845
+ Number.prototype.toJSON =
1846
+ Boolean.prototype.toJSON = function () {
1847
+ return this.valueOf();
1848
+ };
1476
1849
  }
1477
1850
 
1478
1851
  var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
@@ -1499,13 +1872,12 @@ if (!this.JSON) {
1499
1872
  // sequences.
1500
1873
 
1501
1874
  escapable.lastIndex = 0;
1502
- return escapable.test(string) ?
1503
- '"' + string.replace(escapable, function (a) {
1504
- var c = meta[a];
1505
- return typeof c === 'string' ? c :
1506
- '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
1507
- }) + '"' :
1508
- '"' + string + '"';
1875
+ return escapable.test(string) ? '"' + string.replace(escapable, function (a) {
1876
+ var c = meta[a];
1877
+ return typeof c === 'string'
1878
+ ? c
1879
+ : '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
1880
+ }) + '"' : '"' + string + '"';
1509
1881
  }
1510
1882
 
1511
1883
 
@@ -1588,11 +1960,11 @@ if (!this.JSON) {
1588
1960
  // Join all of the elements together, separated with commas, and wrap them in
1589
1961
  // brackets.
1590
1962
 
1591
- v = partial.length === 0 ? '[]' :
1592
- gap ? '[\n' + gap +
1593
- partial.join(',\n' + gap) + '\n' +
1594
- mind + ']' :
1595
- '[' + partial.join(',') + ']';
1963
+ v = partial.length === 0
1964
+ ? '[]'
1965
+ : gap
1966
+ ? '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']'
1967
+ : '[' + partial.join(',') + ']';
1596
1968
  gap = mind;
1597
1969
  return v;
1598
1970
  }
@@ -1602,8 +1974,8 @@ if (!this.JSON) {
1602
1974
  if (rep && typeof rep === 'object') {
1603
1975
  length = rep.length;
1604
1976
  for (i = 0; i < length; i += 1) {
1605
- k = rep[i];
1606
- if (typeof k === 'string') {
1977
+ if (typeof rep[i] === 'string') {
1978
+ k = rep[i];
1607
1979
  v = str(k, value);
1608
1980
  if (v) {
1609
1981
  partial.push(quote(k) + (gap ? ': ' : ':') + v);
@@ -1615,7 +1987,7 @@ if (!this.JSON) {
1615
1987
  // Otherwise, iterate through all of the keys in the object.
1616
1988
 
1617
1989
  for (k in value) {
1618
- if (Object.hasOwnProperty.call(value, k)) {
1990
+ if (Object.prototype.hasOwnProperty.call(value, k)) {
1619
1991
  v = str(k, value);
1620
1992
  if (v) {
1621
1993
  partial.push(quote(k) + (gap ? ': ' : ':') + v);
@@ -1627,9 +1999,11 @@ if (!this.JSON) {
1627
1999
  // Join all of the member texts together, separated with commas,
1628
2000
  // and wrap them in braces.
1629
2001
 
1630
- v = partial.length === 0 ? '{}' :
1631
- gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' +
1632
- mind + '}' : '{' + partial.join(',') + '}';
2002
+ v = partial.length === 0
2003
+ ? '{}'
2004
+ : gap
2005
+ ? '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}'
2006
+ : '{' + partial.join(',') + '}';
1633
2007
  gap = mind;
1634
2008
  return v;
1635
2009
  }
@@ -1637,10 +2011,7 @@ if (!this.JSON) {
1637
2011
 
1638
2012
  // If the JSON object does not yet have a stringify method, give it one.
1639
2013
 
1640
- // NOTE we've hacked this to expose this method to Faye. We need to use this
1641
- // to avoid problems with buggy Firefox version and bad #toJSON implementations
1642
-
1643
- Faye.stringify = function (value, replacer, space) {
2014
+ Faye.stringify = function (value, replacer, space) {
1644
2015
 
1645
2016
  // The stringify method takes a value and an optional replacer, and an optional
1646
2017
  // space parameter, and returns a JSON text. The replacer can be a function
@@ -1648,45 +2019,44 @@ if (!this.JSON) {
1648
2019
  // A default replacer method can be provided. Use of the space parameter can
1649
2020
  // produce text that is more easily readable.
1650
2021
 
1651
- var i;
1652
- gap = '';
1653
- indent = '';
2022
+ var i;
2023
+ gap = '';
2024
+ indent = '';
1654
2025
 
1655
2026
  // If the space parameter is a number, make an indent string containing that
1656
2027
  // many spaces.
1657
2028
 
1658
- if (typeof space === 'number') {
1659
- for (i = 0; i < space; i += 1) {
1660
- indent += ' ';
1661
- }
2029
+ if (typeof space === 'number') {
2030
+ for (i = 0; i < space; i += 1) {
2031
+ indent += ' ';
2032
+ }
1662
2033
 
1663
2034
  // If the space parameter is a string, it will be used as the indent string.
1664
2035
 
1665
- } else if (typeof space === 'string') {
1666
- indent = space;
1667
- }
2036
+ } else if (typeof space === 'string') {
2037
+ indent = space;
2038
+ }
1668
2039
 
1669
2040
  // If there is a replacer, it must be a function or an array.
1670
2041
  // Otherwise, throw an error.
1671
2042
 
1672
- rep = replacer;
1673
- if (replacer && typeof replacer !== 'function' &&
1674
- (typeof replacer !== 'object' ||
1675
- typeof replacer.length !== 'number')) {
1676
- throw new Error('JSON.stringify');
1677
- }
2043
+ rep = replacer;
2044
+ if (replacer && typeof replacer !== 'function' &&
2045
+ (typeof replacer !== 'object' ||
2046
+ typeof replacer.length !== 'number')) {
2047
+ throw new Error('JSON.stringify');
2048
+ }
1678
2049
 
1679
2050
  // Make a fake root object containing our value under the key of ''.
1680
2051
  // Return the result of stringifying the value.
1681
2052
 
1682
- return str('', {'': value});
1683
- };
2053
+ return str('', {'': value});
2054
+ };
1684
2055
 
1685
2056
  if (typeof JSON.stringify !== 'function') {
1686
2057
  JSON.stringify = Faye.stringify;
1687
2058
  }
1688
2059
 
1689
-
1690
2060
  // If the JSON object does not yet have a parse method, give it one.
1691
2061
 
1692
2062
  if (typeof JSON.parse !== 'function') {
@@ -1705,7 +2075,7 @@ if (!this.JSON) {
1705
2075
  var k, v, value = holder[key];
1706
2076
  if (value && typeof value === 'object') {
1707
2077
  for (k in value) {
1708
- if (Object.hasOwnProperty.call(value, k)) {
2078
+ if (Object.prototype.hasOwnProperty.call(value, k)) {
1709
2079
  v = walk(value, k);
1710
2080
  if (v !== undefined) {
1711
2081
  value[k] = v;
@@ -1723,6 +2093,7 @@ if (!this.JSON) {
1723
2093
  // Unicode characters with escape sequences. JavaScript handles many characters
1724
2094
  // incorrectly, either silently deleting them, or treating them as line endings.
1725
2095
 
2096
+ text = String(text);
1726
2097
  cx.lastIndex = 0;
1727
2098
  if (cx.test(text)) {
1728
2099
  text = text.replace(cx, function (a) {
@@ -1744,10 +2115,10 @@ if (!this.JSON) {
1744
2115
  // we look to see that the remaining characters are only whitespace or ']' or
1745
2116
  // ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
1746
2117
 
1747
- if (/^[\],:{}\s]*$/.
1748
- test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@').
1749
- replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').
1750
- replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
2118
+ if (/^[\],:{}\s]*$/
2119
+ .test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@')
2120
+ .replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']')
2121
+ .replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
1751
2122
 
1752
2123
  // In the third stage we use the eval function to compile the text into a
1753
2124
  // JavaScript structure. The '{' operator is subject to a syntactic ambiguity
@@ -1759,8 +2130,9 @@ replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
1759
2130
  // In the optional fourth stage, we recursively walk the new structure, passing
1760
2131
  // each name/value pair to a reviver function for possible transformation.
1761
2132
 
1762
- return typeof reviver === 'function' ?
1763
- walk({'': j}, '') : j;
2133
+ return typeof reviver === 'function'
2134
+ ? walk({'': j}, '')
2135
+ : j;
1764
2136
  }
1765
2137
 
1766
2138
  // If the text is not JSON parseable, then a SyntaxError is thrown.
@@ -1770,7 +2142,6 @@ replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
1770
2142
  }
1771
2143
  }());
1772
2144
 
1773
-
1774
2145
  Faye.Transport.WebSocket = Faye.extend(Faye.Class(Faye.Transport, {
1775
2146
  UNCONNECTED: 1,
1776
2147
  CONNECTING: 2,
@@ -1784,99 +2155,123 @@ Faye.Transport.WebSocket = Faye.extend(Faye.Class(Faye.Transport, {
1784
2155
  this.connect();
1785
2156
  },
1786
2157
 
1787
- request: function(messages, timeout) {
1788
- if (messages.length === 0) return;
1789
- this._messages = this._messages || {};
2158
+ request: function(envelopes) {
2159
+ this._pending = this._pending || new Faye.Set();
2160
+ for (var i = 0, n = envelopes.length; i < n; i++) this._pending.add(envelopes[i]);
1790
2161
 
1791
- for (var i = 0, n = messages.length; i < n; i++) {
1792
- this._messages[messages[i].id] = messages[i];
1793
- }
1794
- this.callback(function(socket) { socket.send(Faye.toJSON(messages)) });
2162
+ this.callback(function(socket) {
2163
+ if (!socket) return;
2164
+ var messages = Faye.map(envelopes, function(e) { return e.message });
2165
+ socket.send(Faye.toJSON(messages));
2166
+ }, this);
1795
2167
  this.connect();
1796
2168
  },
1797
2169
 
1798
- close: function() {
1799
- if (!this._socket) return;
1800
- this._socket.onclose = this._socket.onerror = null;
1801
- this._socket.close();
1802
- delete this._socket;
1803
- this.setDeferredStatus('deferred');
1804
- this._state = this.UNCONNECTED;
1805
- },
1806
-
1807
2170
  connect: function() {
1808
2171
  if (Faye.Transport.WebSocket._unloaded) return;
1809
2172
 
1810
2173
  this._state = this._state || this.UNCONNECTED;
1811
2174
  if (this._state !== this.UNCONNECTED) return;
1812
-
1813
2175
  this._state = this.CONNECTING;
1814
2176
 
1815
- var ws = Faye.Transport.WebSocket.getClass();
1816
- if (!ws) return this.setDeferredStatus('failed');
2177
+ var socket = this._createSocket();
2178
+ if (!socket) return this.setDeferredStatus('failed');
1817
2179
 
1818
- this._socket = new ws(Faye.Transport.WebSocket.getSocketUrl(this.endpoint));
1819
2180
  var self = this;
1820
2181
 
1821
- this._socket.onopen = function() {
2182
+ socket.onopen = function() {
2183
+ if (socket.headers) self._storeCookies(socket.headers['set-cookie']);
2184
+ self._socket = socket;
1822
2185
  self._state = self.CONNECTED;
1823
2186
  self._everConnected = true;
1824
- self.setDeferredStatus('succeeded', self._socket);
1825
- self.trigger('up');
2187
+ self._ping();
2188
+ self.setDeferredStatus('succeeded', socket);
2189
+ };
2190
+
2191
+ var closed = false;
2192
+ socket.onclose = socket.onerror = function() {
2193
+ if (closed) return;
2194
+ closed = true;
2195
+
2196
+ var wasConnected = (self._state === self.CONNECTED);
2197
+ socket.onopen = socket.onclose = socket.onerror = socket.onmessage = null;
2198
+
2199
+ delete self._socket;
2200
+ self._state = self.UNCONNECTED;
2201
+ self.removeTimeout('ping');
2202
+ self.setDeferredStatus('unknown');
2203
+
2204
+ var pending = self._pending ? self._pending.toArray() : [];
2205
+ delete self._pending;
2206
+
2207
+ if (wasConnected) {
2208
+ self.handleError(pending, true);
2209
+ } else if (self._everConnected) {
2210
+ self.handleError(pending);
2211
+ } else {
2212
+ self.setDeferredStatus('failed');
2213
+ }
1826
2214
  };
1827
2215
 
1828
- this._socket.onmessage = function(event) {
1829
- var messages = JSON.parse(event.data);
2216
+ socket.onmessage = function(event) {
2217
+ var messages = JSON.parse(event.data),
2218
+ envelopes = [],
2219
+ envelope;
2220
+
1830
2221
  if (!messages) return;
1831
2222
  messages = [].concat(messages);
1832
2223
 
1833
2224
  for (var i = 0, n = messages.length; i < n; i++) {
1834
- delete self._messages[messages[i].id];
2225
+ if (messages[i].successful === undefined) continue;
2226
+ envelope = self._pending.remove(messages[i]);
2227
+ if (envelope) envelopes.push(envelope);
1835
2228
  }
1836
- self.receive(messages);
2229
+ self.receive(envelopes, messages);
1837
2230
  };
2231
+ },
1838
2232
 
1839
- this._socket.onclose = this._socket.onerror = function() {
1840
- var wasConnected = (self._state === self.CONNECTED);
1841
- self.setDeferredStatus('deferred');
1842
- self._state = self.UNCONNECTED;
2233
+ close: function() {
2234
+ if (!this._socket) return;
2235
+ this._socket.close();
2236
+ },
1843
2237
 
1844
- self.close();
2238
+ _createSocket: function() {
2239
+ var url = Faye.Transport.WebSocket.getSocketUrl(this.endpoint),
2240
+ options = {headers: Faye.copyObject(this._client.headers), ca: this._client.ca};
1845
2241
 
1846
- if (wasConnected) return self.resend();
1847
- if (!self._everConnected) return self.setDeferredStatus('failed');
2242
+ options.headers['Cookie'] = this._getCookies();
1848
2243
 
1849
- var retry = self._client.retry * 1000;
1850
- Faye.ENV.setTimeout(function() { self.connect() }, retry);
1851
- self.trigger('down');
1852
- };
2244
+ if (Faye.WebSocket) return new Faye.WebSocket.Client(url, [], options);
2245
+ if (Faye.ENV.MozWebSocket) return new MozWebSocket(url);
2246
+ if (Faye.ENV.WebSocket) return new WebSocket(url);
1853
2247
  },
1854
2248
 
1855
- resend: function() {
1856
- if (!this._messages) return;
1857
- var messages = Faye.map(this._messages, function(id, msg) { return msg });
1858
- this.request(messages);
2249
+ _ping: function() {
2250
+ if (!this._socket) return;
2251
+ this._socket.send('[]');
2252
+ this.addTimeout('ping', this._client._advice.timeout/2000, this._ping, this);
1859
2253
  }
2254
+
1860
2255
  }), {
1861
- getSocketUrl: function(endpoint) {
1862
- if (Faye.URI) endpoint = Faye.URI.parse(endpoint).toURL();
1863
- return endpoint.replace(/^http(s?):/ig, 'ws$1:');
2256
+ PROTOCOLS: {
2257
+ 'http:': 'ws:',
2258
+ 'https:': 'wss:'
1864
2259
  },
1865
2260
 
1866
- getClass: function() {
1867
- return (Faye.WebSocket && Faye.WebSocket.Client) ||
1868
- Faye.ENV.WebSocket ||
1869
- Faye.ENV.MozWebSocket;
2261
+ create: function(client, endpoint) {
2262
+ var sockets = client.transports.websocket = client.transports.websocket || {};
2263
+ sockets[endpoint.href] = sockets[endpoint.href] || new this(client, endpoint);
2264
+ return sockets[endpoint.href];
1870
2265
  },
1871
2266
 
1872
- isUsable: function(client, endpoint, callback, context) {
1873
- this.create(client, endpoint).isUsable(callback, context);
2267
+ getSocketUrl: function(endpoint) {
2268
+ endpoint = Faye.copyObject(endpoint);
2269
+ endpoint.protocol = this.PROTOCOLS[endpoint.protocol];
2270
+ return Faye.URI.stringify(endpoint);
1874
2271
  },
1875
2272
 
1876
- create: function(client, endpoint) {
1877
- var sockets = client.transports.websocket = client.transports.websocket || {};
1878
- sockets[endpoint] = sockets[endpoint] || new this(client, endpoint);
1879
- return sockets[endpoint];
2273
+ isUsable: function(client, endpoint, callback, context) {
2274
+ this.create(client, endpoint).isUsable(callback, context);
1880
2275
  }
1881
2276
  });
1882
2277
 
@@ -1888,7 +2283,6 @@ if (Faye.Event)
1888
2283
  Faye.Transport.WebSocket._unloaded = true;
1889
2284
  });
1890
2285
 
1891
-
1892
2286
  Faye.Transport.EventSource = Faye.extend(Faye.Class(Faye.Transport, {
1893
2287
  initialize: function(client, endpoint) {
1894
2288
  Faye.Transport.prototype.initialize.call(this, client, endpoint);
@@ -1896,18 +2290,20 @@ Faye.Transport.EventSource = Faye.extend(Faye.Class(Faye.Transport, {
1896
2290
 
1897
2291
  this._xhr = new Faye.Transport.XHR(client, endpoint);
1898
2292
 
1899
- var socket = new EventSource(endpoint + '/' + client.getClientId()),
2293
+ endpoint = Faye.copyObject(endpoint);
2294
+ endpoint.pathname += '/' + client._clientId;
2295
+
2296
+ var socket = new EventSource(Faye.URI.stringify(endpoint)),
1900
2297
  self = this;
1901
2298
 
1902
2299
  socket.onopen = function() {
1903
2300
  self._everConnected = true;
1904
2301
  self.setDeferredStatus('succeeded');
1905
- self.trigger('up');
1906
2302
  };
1907
2303
 
1908
2304
  socket.onerror = function() {
1909
2305
  if (self._everConnected) {
1910
- self.trigger('down');
2306
+ self._client.messageError([]);
1911
2307
  } else {
1912
2308
  self.setDeferredStatus('failed');
1913
2309
  socket.close();
@@ -1915,31 +2311,35 @@ Faye.Transport.EventSource = Faye.extend(Faye.Class(Faye.Transport, {
1915
2311
  };
1916
2312
 
1917
2313
  socket.onmessage = function(event) {
1918
- self.receive(JSON.parse(event.data));
1919
- self.trigger('up');
2314
+ self.receive([], JSON.parse(event.data));
1920
2315
  };
1921
2316
 
1922
2317
  this._socket = socket;
1923
2318
  },
1924
2319
 
2320
+ close: function() {
2321
+ if (!this._socket) return;
2322
+ this._socket.onopen = this._socket.onerror = this._socket.onmessage = null;
2323
+ this._socket.close();
2324
+ delete this._socket;
2325
+ },
2326
+
1925
2327
  isUsable: function(callback, context) {
1926
2328
  this.callback(function() { callback.call(context, true) });
1927
2329
  this.errback(function() { callback.call(context, false) });
1928
2330
  },
1929
2331
 
1930
- request: function(message, timeout) {
1931
- this._xhr.request(message, timeout);
2332
+ encode: function(envelopes) {
2333
+ return this._xhr.encode(envelopes);
1932
2334
  },
1933
2335
 
1934
- close: function() {
1935
- if (!this._socket) return;
1936
- this._socket.onerror = null;
1937
- this._socket.close();
1938
- delete this._socket;
2336
+ request: function(envelopes) {
2337
+ this._xhr.request(envelopes);
1939
2338
  }
2339
+
1940
2340
  }), {
1941
2341
  isUsable: function(client, endpoint, callback, context) {
1942
- var id = client.getClientId();
2342
+ var id = client._clientId;
1943
2343
  if (!id) return callback.call(context, false);
1944
2344
 
1945
2345
  Faye.Transport.XHR.isUsable(client, endpoint, function(usable) {
@@ -1949,34 +2349,38 @@ Faye.Transport.EventSource = Faye.extend(Faye.Class(Faye.Transport, {
1949
2349
  },
1950
2350
 
1951
2351
  create: function(client, endpoint) {
1952
- var sockets = client.transports.eventsource = client.transports.eventsource || {},
1953
- id = client.getClientId(),
1954
- endpoint = endpoint + '/' + (id || '');
2352
+ var sockets = client.transports.eventsource = client.transports.eventsource || {},
2353
+ id = client._clientId;
2354
+
2355
+ endpoint = Faye.copyObject(endpoint);
2356
+ endpoint.pathname += '/' + (id || '');
2357
+ var url = Faye.URI.stringify(endpoint);
1955
2358
 
1956
- sockets[endpoint] = sockets[endpoint] || new this(client, endpoint);
1957
- return sockets[endpoint];
2359
+ sockets[url] = sockets[url] || new this(client, endpoint);
2360
+ return sockets[url];
1958
2361
  }
1959
2362
  });
1960
2363
 
1961
2364
  Faye.extend(Faye.Transport.EventSource.prototype, Faye.Deferrable);
1962
2365
  Faye.Transport.register('eventsource', Faye.Transport.EventSource);
1963
2366
 
1964
-
1965
2367
  Faye.Transport.XHR = Faye.extend(Faye.Class(Faye.Transport, {
1966
- request: function(message, timeout) {
1967
- var retry = this.retry(message, timeout),
1968
- path = Faye.URI.parse(this.endpoint).pathname,
1969
- self = this,
1970
- xhr = Faye.ENV.ActiveXObject
1971
- ? new ActiveXObject("Microsoft.XMLHTTP")
1972
- : new XMLHttpRequest();
2368
+ encode: function(envelopes) {
2369
+ var messages = Faye.map(envelopes, function(e) { return e.message });
2370
+ return Faye.toJSON(messages);
2371
+ },
2372
+
2373
+ request: function(envelopes) {
2374
+ var path = this.endpoint.path,
2375
+ xhr = Faye.ENV.ActiveXObject ? new ActiveXObject('Microsoft.XMLHTTP') : new XMLHttpRequest(),
2376
+ self = this;
1973
2377
 
1974
2378
  xhr.open('POST', path, true);
1975
2379
  xhr.setRequestHeader('Content-Type', 'application/json');
1976
2380
  xhr.setRequestHeader('Pragma', 'no-cache');
1977
2381
  xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
1978
2382
 
1979
- var headers = this.headers;
2383
+ var headers = this._client.headers;
1980
2384
  for (var key in headers) {
1981
2385
  if (!headers.hasOwnProperty(key)) continue;
1982
2386
  xhr.setRequestHeader(key, headers[key]);
@@ -1985,68 +2389,67 @@ Faye.Transport.XHR = Faye.extend(Faye.Class(Faye.Transport, {
1985
2389
  var abort = function() { xhr.abort() };
1986
2390
  Faye.Event.on(Faye.ENV, 'beforeunload', abort);
1987
2391
 
1988
- var cleanUp = function() {
1989
- Faye.Event.detach(Faye.ENV, 'beforeunload', abort);
1990
- xhr.onreadystatechange = function() {};
1991
- xhr = null;
1992
- };
1993
-
1994
2392
  xhr.onreadystatechange = function() {
1995
- if (xhr.readyState !== 4) return;
2393
+ if (!xhr || xhr.readyState !== 4) return;
1996
2394
 
1997
2395
  var parsedMessage = null,
1998
2396
  status = xhr.status,
1999
- successful = ((status >= 200 && status < 300) ||
2000
- status === 304 ||
2001
- status === 1223);
2002
-
2003
- if (!successful) {
2004
- cleanUp();
2005
- retry();
2006
- return self.trigger('down');
2007
- }
2397
+ text = xhr.responseText,
2398
+ successful = (status >= 200 && status < 300) || status === 304 || status === 1223;
2399
+
2400
+ Faye.Event.detach(Faye.ENV, 'beforeunload', abort);
2401
+ xhr.onreadystatechange = function() {};
2402
+ xhr = null;
2403
+
2404
+ if (!successful) return self.handleError(envelopes);
2008
2405
 
2009
2406
  try {
2010
- parsedMessage = JSON.parse(xhr.responseText);
2407
+ parsedMessage = JSON.parse(text);
2011
2408
  } catch (e) {}
2012
2409
 
2013
- cleanUp();
2014
-
2015
- if (parsedMessage) {
2016
- self.receive(parsedMessage);
2017
- self.trigger('up');
2018
- } else {
2019
- retry();
2020
- self.trigger('down');
2021
- }
2410
+ if (parsedMessage)
2411
+ self.receive(envelopes, parsedMessage);
2412
+ else
2413
+ self.handleError(envelopes);
2022
2414
  };
2023
2415
 
2024
- xhr.send(Faye.toJSON(message));
2416
+ xhr.send(this.encode(envelopes));
2025
2417
  }
2026
2418
  }), {
2027
2419
  isUsable: function(client, endpoint, callback, context) {
2028
- callback.call(context, Faye.URI.parse(endpoint).isSameOrigin());
2420
+ callback.call(context, Faye.URI.isSameOrigin(endpoint));
2029
2421
  }
2030
2422
  });
2031
2423
 
2032
2424
  Faye.Transport.register('long-polling', Faye.Transport.XHR);
2033
2425
 
2034
2426
  Faye.Transport.CORS = Faye.extend(Faye.Class(Faye.Transport, {
2035
- request: function(message, timeout) {
2427
+ encode: function(envelopes) {
2428
+ var messages = Faye.map(envelopes, function(e) { return e.message });
2429
+ return 'message=' + encodeURIComponent(Faye.toJSON(messages));
2430
+ },
2431
+
2432
+ request: function(envelopes) {
2036
2433
  var xhrClass = Faye.ENV.XDomainRequest ? XDomainRequest : XMLHttpRequest,
2037
2434
  xhr = new xhrClass(),
2038
- retry = this.retry(message, timeout),
2039
- self = this;
2435
+ headers = this._client.headers,
2436
+ self = this,
2437
+ key;
2438
+
2439
+ xhr.open('POST', Faye.URI.stringify(this.endpoint), true);
2040
2440
 
2041
- xhr.open('POST', this.endpoint, true);
2042
- if (xhr.setRequestHeader) xhr.setRequestHeader('Pragma', 'no-cache');
2441
+ if (xhr.setRequestHeader) {
2442
+ xhr.setRequestHeader('Pragma', 'no-cache');
2443
+ for (key in headers) {
2444
+ if (!headers.hasOwnProperty(key)) continue;
2445
+ xhr.setRequestHeader(key, headers[key]);
2446
+ }
2447
+ }
2043
2448
 
2044
2449
  var cleanUp = function() {
2045
2450
  if (!xhr) return false;
2046
2451
  xhr.onload = xhr.onerror = xhr.ontimeout = xhr.onprogress = null;
2047
2452
  xhr = null;
2048
- Faye.ENV.clearTimeout(timer);
2049
- return true;
2050
2453
  };
2051
2454
 
2052
2455
  xhr.onload = function() {
@@ -2057,35 +2460,27 @@ Faye.Transport.CORS = Faye.extend(Faye.Class(Faye.Transport, {
2057
2460
 
2058
2461
  cleanUp();
2059
2462
 
2060
- if (parsedMessage) {
2061
- self.receive(parsedMessage);
2062
- self.trigger('up');
2063
- } else {
2064
- retry();
2065
- self.trigger('down');
2066
- }
2463
+ if (parsedMessage)
2464
+ self.receive(envelopes, parsedMessage);
2465
+ else
2466
+ self.handleError(envelopes);
2067
2467
  };
2068
2468
 
2069
- var onerror = function() {
2469
+ xhr.onerror = xhr.ontimeout = function() {
2070
2470
  cleanUp();
2071
- retry();
2072
- self.trigger('down');
2471
+ self.handleError(envelopes);
2073
2472
  };
2074
- var timer = Faye.ENV.setTimeout(onerror, 1.5 * 1000 * timeout);
2075
- xhr.onerror = onerror;
2076
- xhr.ontimeout = onerror;
2077
2473
 
2078
2474
  xhr.onprogress = function() {};
2079
- xhr.send('message=' + encodeURIComponent(Faye.toJSON(message)));
2475
+ xhr.send(this.encode(envelopes));
2080
2476
  }
2081
2477
  }), {
2082
2478
  isUsable: function(client, endpoint, callback, context) {
2083
- if (Faye.URI.parse(endpoint).isSameOrigin())
2479
+ if (Faye.URI.isSameOrigin(endpoint))
2084
2480
  return callback.call(context, false);
2085
2481
 
2086
2482
  if (Faye.ENV.XDomainRequest)
2087
- return callback.call(context, Faye.URI.parse(endpoint).protocol ===
2088
- Faye.URI.parse(Faye.ENV.location).protocol);
2483
+ return callback.call(context, endpoint.protocol === Faye.ENV.location.protocol);
2089
2484
 
2090
2485
  if (Faye.ENV.XMLHttpRequest) {
2091
2486
  var xhr = new Faye.ENV.XMLHttpRequest();
@@ -2097,50 +2492,36 @@ Faye.Transport.CORS = Faye.extend(Faye.Class(Faye.Transport, {
2097
2492
 
2098
2493
  Faye.Transport.register('cross-origin-long-polling', Faye.Transport.CORS);
2099
2494
 
2100
-
2101
2495
  Faye.Transport.JSONP = Faye.extend(Faye.Class(Faye.Transport, {
2102
- shouldFlush: function(messages) {
2103
- var params = {
2104
- message: Faye.toJSON(messages),
2105
- jsonp: '__jsonp' + Faye.Transport.JSONP._cbCount + '__'
2106
- };
2107
- var location = Faye.URI.parse(this.endpoint, params).toURL();
2108
- return location.length >= Faye.Transport.MAX_URL_LENGTH;
2496
+ encode: function(envelopes) {
2497
+ var messages = Faye.map(envelopes, function(e) { return e.message });
2498
+ var url = Faye.copyObject(this.endpoint);
2499
+ url.query.message = Faye.toJSON(messages);
2500
+ url.query.jsonp = '__jsonp' + Faye.Transport.JSONP._cbCount + '__';
2501
+ return Faye.URI.stringify(url);
2109
2502
  },
2110
2503
 
2111
- request: function(messages, timeout) {
2112
- var params = {message: Faye.toJSON(messages)},
2504
+ request: function(envelopes) {
2505
+ var messages = Faye.map(envelopes, function(e) { return e.message }),
2113
2506
  head = document.getElementsByTagName('head')[0],
2114
2507
  script = document.createElement('script'),
2115
2508
  callbackName = Faye.Transport.JSONP.getCallbackName(),
2116
- location = Faye.URI.parse(this.endpoint, params),
2117
- retry = this.retry(messages, timeout),
2509
+ endpoint = Faye.copyObject(this.endpoint),
2118
2510
  self = this;
2119
2511
 
2120
- Faye.ENV[callbackName] = function(data) {
2121
- cleanUp();
2122
- self.receive(data);
2123
- self.trigger('up');
2124
- };
2125
-
2126
- var timer = Faye.ENV.setTimeout(function() {
2127
- cleanUp();
2128
- retry();
2129
- self.trigger('down');
2130
- }, 1.5 * 1000 * timeout);
2512
+ endpoint.query.message = Faye.toJSON(messages);
2513
+ endpoint.query.jsonp = callbackName;
2131
2514
 
2132
- var cleanUp = function() {
2515
+ Faye.ENV[callbackName] = function(data) {
2133
2516
  if (!Faye.ENV[callbackName]) return false;
2134
2517
  Faye.ENV[callbackName] = undefined;
2135
2518
  try { delete Faye.ENV[callbackName] } catch (e) {}
2136
- Faye.ENV.clearTimeout(timer);
2137
2519
  script.parentNode.removeChild(script);
2138
- return true;
2520
+ self.receive(envelopes, data);
2139
2521
  };
2140
2522
 
2141
- location.params.jsonp = callbackName;
2142
2523
  script.type = 'text/javascript';
2143
- script.src = location.toURL();
2524
+ script.src = Faye.URI.stringify(endpoint);
2144
2525
  head.appendChild(script);
2145
2526
  }
2146
2527
  }), {
@@ -2158,4 +2539,5 @@ Faye.Transport.JSONP = Faye.extend(Faye.Class(Faye.Transport, {
2158
2539
 
2159
2540
  Faye.Transport.register('callback-polling', Faye.Transport.JSONP);
2160
2541
 
2161
- })();
2542
+ })();
2543
+ })(this);