rsvp.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639
  1. define("rsvp/all",
  2. ["rsvp/promise","exports"],
  3. function(__dependency1__, __exports__) {
  4. "use strict";
  5. var Promise = __dependency1__.Promise;
  6. /* global toString */
  7. function all(promises) {
  8. if (Object.prototype.toString.call(promises) !== "[object Array]") {
  9. throw new TypeError('You must pass an array to all.');
  10. }
  11. return new Promise(function(resolve, reject) {
  12. var results = [], remaining = promises.length,
  13. promise;
  14. if (remaining === 0) {
  15. resolve([]);
  16. }
  17. function resolver(index) {
  18. return function(value) {
  19. resolveAll(index, value);
  20. };
  21. }
  22. function resolveAll(index, value) {
  23. results[index] = value;
  24. if (--remaining === 0) {
  25. resolve(results);
  26. }
  27. }
  28. for (var i = 0; i < promises.length; i++) {
  29. promise = promises[i];
  30. if (promise && typeof promise.then === 'function') {
  31. promise.then(resolver(i), reject);
  32. } else {
  33. resolveAll(i, promise);
  34. }
  35. }
  36. });
  37. }
  38. __exports__.all = all;
  39. });
  40. define("rsvp/async",
  41. ["exports"],
  42. function(__exports__) {
  43. "use strict";
  44. var browserGlobal = (typeof window !== 'undefined') ? window : {};
  45. var BrowserMutationObserver = browserGlobal.MutationObserver || browserGlobal.WebKitMutationObserver;
  46. var async;
  47. var local = (typeof global !== 'undefined') ? global : this;
  48. // old node
  49. function useNextTick() {
  50. return function(callback, arg) {
  51. process.nextTick(function() {
  52. callback(arg);
  53. });
  54. };
  55. }
  56. // node >= 0.10.x
  57. function useSetImmediate() {
  58. return function(callback, arg) {
  59. /* global setImmediate */
  60. setImmediate(function(){
  61. callback(arg);
  62. });
  63. };
  64. }
  65. function useMutationObserver() {
  66. var queue = [];
  67. var observer = new BrowserMutationObserver(function() {
  68. var toProcess = queue.slice();
  69. queue = [];
  70. toProcess.forEach(function(tuple) {
  71. var callback = tuple[0], arg= tuple[1];
  72. callback(arg);
  73. });
  74. });
  75. var element = document.createElement('div');
  76. observer.observe(element, { attributes: true });
  77. // Chrome Memory Leak: https://bugs.webkit.org/show_bug.cgi?id=93661
  78. window.addEventListener('unload', function(){
  79. observer.disconnect();
  80. observer = null;
  81. }, false);
  82. return function(callback, arg) {
  83. queue.push([callback, arg]);
  84. element.setAttribute('drainQueue', 'drainQueue');
  85. };
  86. }
  87. function useSetTimeout() {
  88. return function(callback, arg) {
  89. local.setTimeout(function() {
  90. callback(arg);
  91. }, 1);
  92. };
  93. }
  94. if (typeof setImmediate === 'function') {
  95. async = useSetImmediate();
  96. } else if (typeof process !== 'undefined' && {}.toString.call(process) === '[object process]') {
  97. async = useNextTick();
  98. } else if (BrowserMutationObserver) {
  99. async = useMutationObserver();
  100. } else {
  101. async = useSetTimeout();
  102. }
  103. __exports__.async = async;
  104. });
  105. define("rsvp/config",
  106. ["rsvp/async","exports"],
  107. function(__dependency1__, __exports__) {
  108. "use strict";
  109. var async = __dependency1__.async;
  110. var config = {};
  111. config.async = async;
  112. __exports__.config = config;
  113. });
  114. define("rsvp/defer",
  115. ["rsvp/promise","exports"],
  116. function(__dependency1__, __exports__) {
  117. "use strict";
  118. var Promise = __dependency1__.Promise;
  119. function defer() {
  120. var deferred = {
  121. // pre-allocate shape
  122. resolve: undefined,
  123. reject: undefined,
  124. promise: undefined
  125. };
  126. deferred.promise = new Promise(function(resolve, reject) {
  127. deferred.resolve = resolve;
  128. deferred.reject = reject;
  129. });
  130. return deferred;
  131. }
  132. __exports__.defer = defer;
  133. });
  134. define("rsvp/events",
  135. ["exports"],
  136. function(__exports__) {
  137. "use strict";
  138. var Event = function(type, options) {
  139. this.type = type;
  140. for (var option in options) {
  141. if (!options.hasOwnProperty(option)) { continue; }
  142. this[option] = options[option];
  143. }
  144. };
  145. var indexOf = function(callbacks, callback) {
  146. for (var i=0, l=callbacks.length; i<l; i++) {
  147. if (callbacks[i][0] === callback) { return i; }
  148. }
  149. return -1;
  150. };
  151. var callbacksFor = function(object) {
  152. var callbacks = object._promiseCallbacks;
  153. if (!callbacks) {
  154. callbacks = object._promiseCallbacks = {};
  155. }
  156. return callbacks;
  157. };
  158. var EventTarget = {
  159. mixin: function(object) {
  160. object.on = this.on;
  161. object.off = this.off;
  162. object.trigger = this.trigger;
  163. return object;
  164. },
  165. on: function(eventNames, callback, binding) {
  166. var allCallbacks = callbacksFor(this), callbacks, eventName;
  167. eventNames = eventNames.split(/\s+/);
  168. binding = binding || this;
  169. while (eventName = eventNames.shift()) {
  170. callbacks = allCallbacks[eventName];
  171. if (!callbacks) {
  172. callbacks = allCallbacks[eventName] = [];
  173. }
  174. if (indexOf(callbacks, callback) === -1) {
  175. callbacks.push([callback, binding]);
  176. }
  177. }
  178. },
  179. off: function(eventNames, callback) {
  180. var allCallbacks = callbacksFor(this), callbacks, eventName, index;
  181. eventNames = eventNames.split(/\s+/);
  182. while (eventName = eventNames.shift()) {
  183. if (!callback) {
  184. allCallbacks[eventName] = [];
  185. continue;
  186. }
  187. callbacks = allCallbacks[eventName];
  188. index = indexOf(callbacks, callback);
  189. if (index !== -1) { callbacks.splice(index, 1); }
  190. }
  191. },
  192. trigger: function(eventName, options) {
  193. var allCallbacks = callbacksFor(this),
  194. callbacks, callbackTuple, callback, binding, event;
  195. if (callbacks = allCallbacks[eventName]) {
  196. // Don't cache the callbacks.length since it may grow
  197. for (var i=0; i<callbacks.length; i++) {
  198. callbackTuple = callbacks[i];
  199. callback = callbackTuple[0];
  200. binding = callbackTuple[1];
  201. if (typeof options !== 'object') {
  202. options = { detail: options };
  203. }
  204. event = new Event(eventName, options);
  205. callback.call(binding, event);
  206. }
  207. }
  208. }
  209. };
  210. __exports__.EventTarget = EventTarget;
  211. });
  212. define("rsvp/hash",
  213. ["rsvp/defer","exports"],
  214. function(__dependency1__, __exports__) {
  215. "use strict";
  216. var defer = __dependency1__.defer;
  217. function size(object) {
  218. var s = 0;
  219. for (var prop in object) {
  220. s++;
  221. }
  222. return s;
  223. }
  224. function hash(promises) {
  225. var results = {}, deferred = defer(), remaining = size(promises);
  226. if (remaining === 0) {
  227. deferred.resolve({});
  228. }
  229. var resolver = function(prop) {
  230. return function(value) {
  231. resolveAll(prop, value);
  232. };
  233. };
  234. var resolveAll = function(prop, value) {
  235. results[prop] = value;
  236. if (--remaining === 0) {
  237. deferred.resolve(results);
  238. }
  239. };
  240. var rejectAll = function(error) {
  241. deferred.reject(error);
  242. };
  243. for (var prop in promises) {
  244. if (promises[prop] && typeof promises[prop].then === 'function') {
  245. promises[prop].then(resolver(prop), rejectAll);
  246. } else {
  247. resolveAll(prop, promises[prop]);
  248. }
  249. }
  250. return deferred.promise;
  251. }
  252. __exports__.hash = hash;
  253. });
  254. define("rsvp/node",
  255. ["rsvp/promise","rsvp/all","exports"],
  256. function(__dependency1__, __dependency2__, __exports__) {
  257. "use strict";
  258. var Promise = __dependency1__.Promise;
  259. var all = __dependency2__.all;
  260. function makeNodeCallbackFor(resolve, reject) {
  261. return function (error, value) {
  262. if (error) {
  263. reject(error);
  264. } else if (arguments.length > 2) {
  265. resolve(Array.prototype.slice.call(arguments, 1));
  266. } else {
  267. resolve(value);
  268. }
  269. };
  270. }
  271. function denodeify(nodeFunc) {
  272. return function() {
  273. var nodeArgs = Array.prototype.slice.call(arguments), resolve, reject;
  274. var thisArg = this;
  275. var promise = new Promise(function(nodeResolve, nodeReject) {
  276. resolve = nodeResolve;
  277. reject = nodeReject;
  278. });
  279. all(nodeArgs).then(function(nodeArgs) {
  280. nodeArgs.push(makeNodeCallbackFor(resolve, reject));
  281. try {
  282. nodeFunc.apply(thisArg, nodeArgs);
  283. } catch(e) {
  284. reject(e);
  285. }
  286. });
  287. return promise;
  288. };
  289. }
  290. __exports__.denodeify = denodeify;
  291. });
  292. define("rsvp/promise",
  293. ["rsvp/config","rsvp/events","exports"],
  294. function(__dependency1__, __dependency2__, __exports__) {
  295. "use strict";
  296. var config = __dependency1__.config;
  297. var EventTarget = __dependency2__.EventTarget;
  298. function objectOrFunction(x) {
  299. return isFunction(x) || (typeof x === "object" && x !== null);
  300. }
  301. function isFunction(x){
  302. return typeof x === "function";
  303. }
  304. var Promise = function(resolver) {
  305. var promise = this,
  306. resolved = false;
  307. if (typeof resolver !== 'function') {
  308. throw new TypeError('You must pass a resolver function as the sole argument to the promise constructor');
  309. }
  310. if (!(promise instanceof Promise)) {
  311. return new Promise(resolver);
  312. }
  313. var resolvePromise = function(value) {
  314. if (resolved) { return; }
  315. resolved = true;
  316. resolve(promise, value);
  317. };
  318. var rejectPromise = function(value) {
  319. if (resolved) { return; }
  320. resolved = true;
  321. reject(promise, value);
  322. };
  323. this.on('promise:failed', function(event) {
  324. this.trigger('error', { detail: event.detail });
  325. }, this);
  326. this.on('error', onerror);
  327. try {
  328. resolver(resolvePromise, rejectPromise);
  329. } catch(e) {
  330. rejectPromise(e);
  331. }
  332. };
  333. function onerror(event) {
  334. if (config.onerror) {
  335. config.onerror(event.detail);
  336. }
  337. }
  338. var invokeCallback = function(type, promise, callback, event) {
  339. var hasCallback = isFunction(callback),
  340. value, error, succeeded, failed;
  341. if (hasCallback) {
  342. try {
  343. value = callback(event.detail);
  344. succeeded = true;
  345. } catch(e) {
  346. failed = true;
  347. error = e;
  348. }
  349. } else {
  350. value = event.detail;
  351. succeeded = true;
  352. }
  353. if (handleThenable(promise, value)) {
  354. return;
  355. } else if (hasCallback && succeeded) {
  356. resolve(promise, value);
  357. } else if (failed) {
  358. reject(promise, error);
  359. } else if (type === 'resolve') {
  360. resolve(promise, value);
  361. } else if (type === 'reject') {
  362. reject(promise, value);
  363. }
  364. };
  365. Promise.prototype = {
  366. constructor: Promise,
  367. isRejected: undefined,
  368. isFulfilled: undefined,
  369. rejectedReason: undefined,
  370. fulfillmentValue: undefined,
  371. then: function(done, fail) {
  372. this.off('error', onerror);
  373. var thenPromise = new this.constructor(function() {});
  374. if (this.isFulfilled) {
  375. config.async(function(promise) {
  376. invokeCallback('resolve', thenPromise, done, { detail: promise.fulfillmentValue });
  377. }, this);
  378. }
  379. if (this.isRejected) {
  380. config.async(function(promise) {
  381. invokeCallback('reject', thenPromise, fail, { detail: promise.rejectedReason });
  382. }, this);
  383. }
  384. this.on('promise:resolved', function(event) {
  385. invokeCallback('resolve', thenPromise, done, event);
  386. });
  387. this.on('promise:failed', function(event) {
  388. invokeCallback('reject', thenPromise, fail, event);
  389. });
  390. return thenPromise;
  391. },
  392. fail: function(fail) {
  393. return this.then(null, fail);
  394. }
  395. };
  396. EventTarget.mixin(Promise.prototype);
  397. function resolve(promise, value) {
  398. if (promise === value) {
  399. fulfill(promise, value);
  400. } else if (!handleThenable(promise, value)) {
  401. fulfill(promise, value);
  402. }
  403. }
  404. function handleThenable(promise, value) {
  405. var then = null,
  406. resolved;
  407. try {
  408. if (promise === value) {
  409. throw new TypeError("A promises callback cannot return that same promise.");
  410. }
  411. if (objectOrFunction(value)) {
  412. then = value.then;
  413. if (isFunction(then)) {
  414. then.call(value, function(val) {
  415. if (resolved) { return true; }
  416. resolved = true;
  417. if (value !== val) {
  418. resolve(promise, val);
  419. } else {
  420. fulfill(promise, val);
  421. }
  422. }, function(val) {
  423. if (resolved) { return true; }
  424. resolved = true;
  425. reject(promise, val);
  426. });
  427. return true;
  428. }
  429. }
  430. } catch (error) {
  431. reject(promise, error);
  432. return true;
  433. }
  434. return false;
  435. }
  436. function fulfill(promise, value) {
  437. config.async(function() {
  438. promise.trigger('promise:resolved', { detail: value });
  439. promise.isFulfilled = true;
  440. promise.fulfillmentValue = value;
  441. });
  442. }
  443. function reject(promise, value) {
  444. config.async(function() {
  445. promise.trigger('promise:failed', { detail: value });
  446. promise.isRejected = true;
  447. promise.rejectedReason = value;
  448. });
  449. }
  450. __exports__.Promise = Promise;
  451. });
  452. define("rsvp/reject",
  453. ["rsvp/promise","exports"],
  454. function(__dependency1__, __exports__) {
  455. "use strict";
  456. var Promise = __dependency1__.Promise;
  457. function reject(reason) {
  458. return new Promise(function (resolve, reject) {
  459. reject(reason);
  460. });
  461. }
  462. __exports__.reject = reject;
  463. });
  464. define("rsvp/resolve",
  465. ["rsvp/promise","exports"],
  466. function(__dependency1__, __exports__) {
  467. "use strict";
  468. var Promise = __dependency1__.Promise;
  469. function resolve(thenable) {
  470. return new Promise(function(resolve, reject) {
  471. resolve(thenable);
  472. });
  473. }
  474. __exports__.resolve = resolve;
  475. });
  476. define("rsvp/rethrow",
  477. ["exports"],
  478. function(__exports__) {
  479. "use strict";
  480. var local = (typeof global === "undefined") ? this : global;
  481. function rethrow(reason) {
  482. local.setTimeout(function() {
  483. throw reason;
  484. });
  485. throw reason;
  486. }
  487. __exports__.rethrow = rethrow;
  488. });
  489. define("rsvp",
  490. ["rsvp/events","rsvp/promise","rsvp/node","rsvp/all","rsvp/hash","rsvp/rethrow","rsvp/defer","rsvp/config","rsvp/resolve","rsvp/reject","exports"],
  491. function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __exports__) {
  492. "use strict";
  493. var EventTarget = __dependency1__.EventTarget;
  494. var Promise = __dependency2__.Promise;
  495. var denodeify = __dependency3__.denodeify;
  496. var all = __dependency4__.all;
  497. var hash = __dependency5__.hash;
  498. var rethrow = __dependency6__.rethrow;
  499. var defer = __dependency7__.defer;
  500. var config = __dependency8__.config;
  501. var resolve = __dependency9__.resolve;
  502. var reject = __dependency10__.reject;
  503. function configure(name, value) {
  504. config[name] = value;
  505. }
  506. __exports__.Promise = Promise;
  507. __exports__.EventTarget = EventTarget;
  508. __exports__.all = all;
  509. __exports__.hash = hash;
  510. __exports__.rethrow = rethrow;
  511. __exports__.defer = defer;
  512. __exports__.denodeify = denodeify;
  513. __exports__.configure = configure;
  514. __exports__.resolve = resolve;
  515. __exports__.reject = reject;
  516. });