lib/faye-browser.js in faye-1.0.0 vs lib/faye-browser.js in faye-1.0.1

- old
+ new

@@ -1,10 +1,10 @@ (function() { 'use strict'; var Faye = { - VERSION: '1.0.0', + 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'], @@ -369,12 +369,12 @@ var PENDING = 0, FULFILLED = 1, REJECTED = 2; -var FORWARD = function(x) { return x }, - BREAK = function(x) { throw x }; +var RETURN = function(x) { return x }, + THROW = function(x) { throw x }; var Promise = function(task) { this._state = PENDING; this._callbacks = []; this._errbacks = []; @@ -385,52 +385,77 @@ task(function(value) { fulfill(self, value) }, function(reason) { reject(self, reason) }); }; Promise.prototype.then = function(callback, errback) { - var self = this; - return new Promise(function(fulfill, reject) { - var next = {fulfill: fulfill, reject: reject}; + var next = {}, self = this; + + next.promise = new Promise(function(fulfill, reject) { + next.fulfill = fulfill; + next.reject = reject; + registerCallback(self, callback, next); registerErrback(self, errback, next); }); + return next.promise; }; var registerCallback = function(promise, callback, next) { - if (typeof callback !== 'function') callback = FORWARD; + if (typeof callback !== 'function') callback = RETURN; var handler = function(value) { invoke(callback, value, next) }; if (promise._state === PENDING) { promise._callbacks.push(handler); } else if (promise._state === FULFILLED) { - defer(function() { handler(promise._value) }); + handler(promise._value); } }; var registerErrback = function(promise, errback, next) { - if (typeof errback !== 'function') errback = BREAK; + if (typeof errback !== 'function') errback = THROW; var handler = function(reason) { invoke(errback, reason, next) }; if (promise._state === PENDING) { promise._errbacks.push(handler); } else if (promise._state === REJECTED) { - defer(function() { handler(promise._reason) }); + handler(promise._reason); } }; var invoke = function(fn, value, next) { + defer(function() { _invoke(fn, value, next) }); +}; + +var _invoke = function(fn, value, next) { + var called = false, outcome, type, then; + try { - var outcome = fn(value); - if (outcome && typeof outcome.then === 'function') { - outcome.then(next.fulfill, next.reject); - } else { - next.fulfill(outcome); - } + outcome = fn(value); + type = typeof outcome; + then = outcome !== null && (type === 'function' || type === 'object') && outcome.then; + + if (outcome === next.promise) + return next.reject(new TypeError('Recursive promise chain detected')); + + if (typeof then !== 'function') return next.fulfill(outcome); + + then.call(outcome, function(v) { + if (called) return; + called = true; + _invoke(RETURN, v, next); + }, function(r) { + if (called) return; + called = true; + next.reject(r); + }); + } catch (error) { + if (called) return; + called = true; next.reject(error); } }; -var fulfill = Promise.fulfill = function(promise, value) { +var fulfill = Promise.fulfill = Promise.resolve = function(promise, value) { if (promise._state !== PENDING) return; promise._state = FULFILLED; promise._value = value; promise._errbacks = []; @@ -450,21 +475,21 @@ while (eb = errbacks.shift()) eb(reason); }; Promise.defer = defer; -Promise.pending = function() { +Promise.deferred = Promise.pending = function() { var tuple = {}; tuple.promise = new Promise(function(fulfill, reject) { - tuple.fulfill = fulfill; + tuple.fulfill = tuple.resolve = fulfill; tuple.reject = reject; }); return tuple; }; -Promise.fulfilled = function(value) { +Promise.fulfilled = Promise.resolved = function(value) { return new Promise(function(fulfill, reject) { fulfill(value) }); }; Promise.rejected = function(reason) { return new Promise(function(fulfill, reject) { reject(reason) }); @@ -776,10 +801,15 @@ this._timeouts = this._timeouts || {}; var timeout = this._timeouts[name]; if (!timeout) return; clearTimeout(timeout); delete this._timeouts[name]; + }, + + removeAllTimeouts: function() { + this._timeouts = this._timeouts || {}; + for (var name in this._timeouts) this.removeTimeout(name); } }; Faye.Logging = { LOG_LEVELS: { @@ -2123,13 +2153,15 @@ this.errback(function() { callback.call(context, false) }); this.connect(); }, request: function(envelopes) { + this._pending = this._pending || new Faye.Set(); + for (var i = 0, n = envelopes.length; i < n; i++) this._pending.add(envelopes[i]); + this.callback(function(socket) { if (!socket) return; - for (var i = 0, n = envelopes.length; i < n; i++) this._pending.add(envelopes[i]); var messages = Faye.map(envelopes, function(e) { return e.message }); socket.send(Faye.toJSON(messages)); }, this); this.connect(); }, @@ -2147,10 +2179,9 @@ var self = this; socket.onopen = function() { if (socket.headers) self._storeCookies(socket.headers['set-cookie']); self._socket = socket; - self._pending = new Faye.Set(); self._state = self.CONNECTED; self._everConnected = true; self._ping(); self.setDeferredStatus('succeeded', socket); }; \ No newline at end of file