From 862ec9b9d1f5a98afdfd5fb8a93239d3ff362a5f Mon Sep 17 00:00:00 2001 From: Brian Cavalier Date: Wed, 22 May 2013 09:33:03 -0400 Subject: [PATCH] Use bower for deps. Add initial markdown support --- .gitignore | 4 + .gitmodules | 0 LICENSE.txt | 2 +- README.mdown => README.md | 0 app/hc/markdown.js | 15 + app/hc/slides/PresentationController.js | 4 +- app/hc/slides/SingleFilePresentationModel.js | 2 +- app/main.js | 2 +- app/run.js | 19 +- bower.json | 9 + index.html | 4 +- lib/curl.js | 29 - lib/when/.editorconfig | 6 - lib/when/.gitignore | 4 - lib/when/.gitmodules | 0 lib/when/.jshintrc | 74 -- lib/when/.travis.yml | 7 - lib/when/LICENSE.txt | 24 - lib/when/README.md | 90 --- lib/when/apply.js | 70 -- lib/when/cancelable.js | 66 -- lib/when/debug.js | 302 -------- lib/when/delay.js | 61 -- lib/when/package.json | 39 - lib/when/parallel.js | 40 - lib/when/pipeline.js | 57 -- lib/when/sequence.js | 43 -- lib/when/timed.js | 31 - lib/when/timeout.js | 75 -- lib/when/when.js | 724 ------------------- 30 files changed, 45 insertions(+), 1758 deletions(-) create mode 100644 .gitignore delete mode 100644 .gitmodules rename README.mdown => README.md (100%) create mode 100644 app/hc/markdown.js create mode 100644 bower.json delete mode 100644 lib/curl.js delete mode 100644 lib/when/.editorconfig delete mode 100644 lib/when/.gitignore delete mode 100644 lib/when/.gitmodules delete mode 100644 lib/when/.jshintrc delete mode 100644 lib/when/.travis.yml delete mode 100644 lib/when/LICENSE.txt delete mode 100644 lib/when/README.md delete mode 100644 lib/when/apply.js delete mode 100644 lib/when/cancelable.js delete mode 100644 lib/when/debug.js delete mode 100644 lib/when/delay.js delete mode 100644 lib/when/package.json delete mode 100644 lib/when/parallel.js delete mode 100644 lib/when/pipeline.js delete mode 100644 lib/when/sequence.js delete mode 100644 lib/when/timed.js delete mode 100644 lib/when/timeout.js delete mode 100644 lib/when/when.js diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ff2f688 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +/node_modules +/.idea +/components +.DS_Store \ No newline at end of file diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index e69de29..0000000 diff --git a/LICENSE.txt b/LICENSE.txt index 09a1063..194ac91 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -2,7 +2,7 @@ Open Source Initiative OSI - The MIT License http://www.opensource.org/licenses/mit-license.php -Copyright (c) 2011 Brian Cavalier +Copyright (c) 2011-2013 Brian Cavalier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/README.mdown b/README.md similarity index 100% rename from README.mdown rename to README.md diff --git a/app/hc/markdown.js b/app/hc/markdown.js new file mode 100644 index 0000000..9859c4c --- /dev/null +++ b/app/hc/markdown.js @@ -0,0 +1,15 @@ +/* + @license Copyright (c) 2011 Brian Cavalier + LICENSE: see the LICENSE.txt file. If file is missing, this file is subject + to the MIT License at: http://www.opensource.org/licenses/mit-license.php. + */ +define(['marked'], function(marked) { + return { + load: function (absId, require, loaded, config) { + require(['text!' + absId], function(text) { + marked.setOptions(config); + loaded(marked(text)); + }); + } + } +}); \ No newline at end of file diff --git a/app/hc/slides/PresentationController.js b/app/hc/slides/PresentationController.js index 1ba8c65..7d17972 100644 --- a/app/hc/slides/PresentationController.js +++ b/app/hc/slides/PresentationController.js @@ -1,12 +1,12 @@ /* - @license Copyright (c) 2011 Brian Cavalier + @license Copyright (c) 2011-2013 Brian Cavalier LICENSE: see the LICENSE.txt file. If file is missing, this file is subject to the MIT License at: http://www.opensource.org/licenses/mit-license.php. */ /* Class: PresentationController */ -define([], function() { +define(function() { var doc = window.document, html = doc.getElementsByTagName('html')[0], diff --git a/app/hc/slides/SingleFilePresentationModel.js b/app/hc/slides/SingleFilePresentationModel.js index ddf98d7..c4a3133 100644 --- a/app/hc/slides/SingleFilePresentationModel.js +++ b/app/hc/slides/SingleFilePresentationModel.js @@ -29,7 +29,7 @@ define(['require', 'when'], function(require, when) { loaded = false, resolveOnLoad = []; - require(['text!' + slidePath], function(slideContent) { + require([slidePath], function(slideContent) { cachedSlides = slideContent.split(/\s*\\s*|\s*----\s*/i); loaded = true; diff --git a/app/main.js b/app/main.js index 747fe9c..2a79b11 100644 --- a/app/main.js +++ b/app/main.js @@ -9,7 +9,7 @@ define([ function(Model, View, Controller) { var model, view, controller; - model = new Model('slides/slides.html'); + model = new Model('text!slides/slides.html'); view = new View(document.getElementById('slide-container'), model); controller = new Controller(view); diff --git a/app/run.js b/app/run.js index 0f9a761..39f1d4e 100644 --- a/app/run.js +++ b/app/run.js @@ -3,16 +3,17 @@ // Configure curl and load components, theme css, // and wait for DOM Ready. Then create model, view, // and controller, and start the presentation. - var config = { - baseUrl: '', + curl({ + main: 'app/main', paths: { - 'themes': 'css/themes' + 'themes': 'css/themes', + 'markdown': 'app/hc/markdown' }, - packages: [ - { name: 'when', location: 'lib/when', main: 'when' } - ] - }; - - curl(config, ['app/main']); + packages: { + curl: { location: 'components/curl/src/curl' }, + when: { location: 'components/when', main: 'when' }, + marked: { location: 'components/marked', main: 'lib/marked' } + } + }); })(window.curl); \ No newline at end of file diff --git a/bower.json b/bower.json new file mode 100644 index 0000000..a1721d3 --- /dev/null +++ b/bower.json @@ -0,0 +1,9 @@ +{ + "name": "slides", + "version": "2.0.0", + "dependencies": { + "when": "~2", + "marked": "~0.2", + "curl": "~0.7" + } +} \ No newline at end of file diff --git a/index.html b/index.html index c5bb99d..d6f0af4 100644 --- a/index.html +++ b/index.html @@ -1,7 +1,7 @@ - + diff --git a/lib/curl.js b/lib/curl.js deleted file mode 100644 index 7e3fc72..0000000 --- a/lib/curl.js +++ /dev/null @@ -1,29 +0,0 @@ -(function(){/* - MIT License (c) copyright B Cavalier & J Hann */ -var h=!0,k=!1,l=this.window||global;function n(){}function p(a,b){return 0==aa.call(a).indexOf("[object "+b)}function q(a){return a&&"/"==a.charAt(a.length-1)?a.substr(0,a.length-1):a}function s(a,b){var c,e,d,f;c=1;e=a;b&&(e=e.replace(ba,function(a,b,e,d){e&&c++;f=h;return d||""}));if(f){d=b.split("/");if(c>d)throw Error("attempt to access module beyond root of package: "+a);d.splice(d.length-c,c);return d.concat(e||[]).join("/")}return e} -function ca(a){var b=a.indexOf("!");return{I:a.substr(b+1),i:0<=b&&a.substr(0,b)}}function t(){}function u(a,b){t.prototype=a||v;var c=new t;t.prototype=v;for(var e in b)c[e]=b[e];return c} -function w(){function a(a,b,d){e.push([a,b,d])}function b(a,b){for(var d,c=0;d=e[c++];)(d=d[a])&&d(b)}var c,e,d;c=this;e=[];d=function(f,c){a=f?function(a){a&&a(c)}:function(a,b){b&&b(c)};d=n;b(f?0:1,c);b=n;e=x};this.aa=function(b,e,d){a(b,e,d)};this.g=function(a){c.fa=a;d(h,a)};this.d=function(a){c.ea=a;d(k,a)};this.p=function(a){b(2,a)}}function z(a,b,c,e){a instanceof w?a.aa(b,c,e):b(a)}function A(a,b,c){var e;return function(){0<=--a&&b&&(e=b.apply(x,arguments));0==a&&c&&c(e);return e}} -function B(){function a(b,d,c,g){var i;i=C.f(D,x,[].concat(b));this.then=b=function(a,b){z(i,function(b){a&&a.apply(x,b)},function(a){if(b)b(a);else throw a;});return this};this.next=function(b,d,e){return new a(b,d,e,i)};d&&b(d,c);z(g,function(){C.h(i)})}var b=[].slice.call(arguments),c;p(b[0],"Object")&&(c=b.shift(),D=C.a(c,D),C.t(c));return new a(b[0],b[1],b[2])} -function da(a){var b=a.id;if(b==x)if(E!==x)E={A:"Multiple anonymous defines in url"};else if(!(b=C.W()))E=a;if(b!=x){var c=F[b];b in F||(c=C.j(b,D).a,c=F[b]=C.v(c,b));if(!(c instanceof w))throw Error("duplicate define: "+b);c.ba=k;C.w(c,a)}} -var D,I,J,K=l.document,L=K&&(K.head||K.getElementsByTagName("head")[0]),ea=L&&L.getElementsByTagName("base")[0]||null,fa={},ga={},M={},ha="addEventListener"in l?{}:{loaded:1,complete:1},v={},aa=v.toString,x,F={},N=k,E,ia=/\?/,ja=/^\/|^[^:]+:\/\//,ba=/(\.)(\.?)(?:$|\/([^\.\/]+.*)?)/g,ka=/\/\*[\s\S]*?\*\/|(?:[^\\])\/\/.*?[\n\r]/g,la=/require\s*\(\s*["']([^"']+)["']\s*\)|(?:[^\\]?)(["'])/g,O,C; -C={K:function(a,b){return C.m(s(a,b))},m:function(a,b){return b.c&&a in b.c&&b.c[a].Z||a},n:function(a,b){a&&(b.G&&0>a.indexOf("/"))&&(a=q(b.G)+"/"+a);return a},f:function(a,b,c,e){function d(b){return C.m(s(b,g.id),a)}function f(b,c,f){var j,y;j=c&&function(a){c.apply(x,a)};if(p(b,"String")){b=d(b);f=F[b];y=f instanceof w&&f.b;if(!(b in F))throw Error("Module not resolved: "+b);if(j)throw Error("require(id, callback) not allowed");return y||f}z(C.h(C.f(a,g.id,b,e)),j,f)}var g;g=new w;g.id=b||""; -g.X=e;g.z=c;g.a=a;g.q=f;f.toUrl=function(b){return C.j(d(b),a).url};g.K=d;return g},v:function(a,b,c){var e,d,f;e=C.f(a,b,x,c);d=e.g;f=A(1,function(a){e.l=a;try{return C.P(e)}catch(b){e.d(b)}});e.g=function(a){z(c||N,function(){d(F[e.id]=f(a))})};e.B=function(a){z(c||N,function(){e.b&&(f(a),e.p(ga))})};return e},M:function(a,b,c,e){return C.f(a,c,x,e)},V:function(a){return a.q},C:function(a){return a.b||(a.b={})},U:function(a){var b=a.o;b||(b=a.o={id:a.id,uri:C.D(a),exports:C.C(a),config:function(){return a.a}}, -b.b=b.exports);return b},D:function(a){return a.url||(a.url=C.u(a.q.toUrl(a.id)),a.a)},a:function(a){var b,c,e,d,f,g;b=!a;a&&(C.a=C.F);a||(a={});e=a.apiName||"curl";d=a.apiContext||l;f=a.defineName||"define";g=a.defineContext||l;c=a.overwriteApi;!b&&I&&(l.curl=I,I=k);if(!b&&!c&&d[e]&&d[e]!=B)throw Error(e+" already exists");d[e]=B;if(!b||!l.define){if(!b&&!c&&f in g&&g[f]!=J)throw Error(f+" already exists");g[f]=J=function(){var a=C.T(arguments);da(a)};J.amd={plugins:h,jQuery:h,curl:"0.7.0"}}return C.F(a)}, -F:function(a,b){function c(a,b){var e,c,g,i,G;for(G in a){g=a[G];g.name=g.id||g.name||G;i=d;c=ca(q(g.name||G));e=c.I;if(c=C.n(c.i,d))i=f[c],i||(i=f[c]=u(d),i.c=u(d.c),i.e=[]),delete a[G];if(b){c=g;var H=void 0;c.path=q(c.path||c.location||"");H=q(c.main)||"main";"."!=H.charAt(0)&&(H="./"+H);c.Z=s(H,c.name+"/");c.a=c.config;c.a&&(c.a=u(d,c.a))}else c={path:q(g)};c.J=e.split("/").length;e?(i.c[e]=c,i.e.push(e)):i.s=C.H(g,d)}}function e(a){var b=a.c;a.$=RegExp("^("+a.e.sort(function(a,c){return b[c].J- -b[a].J}).join("|").replace(/\/|\./g,"\\$&")+")(?=\\/|$)");delete a.e}var d,f,g;b||(b={});d=u(b,a);d.s=d.baseUrl||"";d.G=d.pluginPath||"curl/plugin";d.N=RegExp(d.dontAddFileExt||ia);d.c=u(b.c);f=a.plugins||{};d.plugins=u(b.plugins);for(g in f)d.plugins[C.n(g,d)]=f[g];f=d.plugins;d.e=[];c(a.paths,k);c(a.packages,h);for(g in f){f[g]=u(d,f[g]);var i=f[g].e;i&&(f[g].e=i.concat(d.e),e(f[g]))}e(d);return d},t:function(a){var b;(b=a&&a.preloads)&&0i.status?f(i.responseText):g(Error("fetchText() failed. status: "+i.statusText)))};i.send(null)},"plugin-builder":"./builder/text"}});function va(){var a;a=W[wa]("link");a.rel="stylesheet";a.type="text/css";return a}function xa(a,b,c){ya.push({url:a,L:b,O:function(){c(Error(za))}});a=Aa.shift();!a&&Ba.length` -1. `when` will be available as `window.when` - -### Node - -1. `npm install when` -1. `var when = require('when');` - -### RingoJS - -1. `ringo-admin install cujojs/when` -1. `var when = require('when');` - -Running the Unit Tests -====================== - -Install [buster.js](http://busterjs.org/) - -`npm install -g buster` - -Run unit tests in Node: - -1. `buster test -e node` - -Run unit tests in Browsers (and Node): - -1. `buster server` - this will print a url -2. Point browsers at /capture, e.g. `localhost:1111/capture` -3. `buster test` or `buster test -e browser` - -References ----------- - -Much of this code was inspired by @[unscriptable](https://github.com/unscriptable)'s [tiny promises](https://github.com/unscriptable/promises), the async innards of [wire.js](https://github.com/cujojs/wire), and some gists [here](https://gist.github.com/870729), [here](https://gist.github.com/892345), [here](https://gist.github.com/894356), and [here](https://gist.github.com/894360) - -Some of the code has been influenced by the great work in [Q](https://github.com/kriskowal/q), [Dojo's Deferred](https://github.com/dojo/dojo), and [uber.js](https://github.com/phiggins42/uber.js). diff --git a/lib/when/apply.js b/lib/when/apply.js deleted file mode 100644 index b4dbd33..0000000 --- a/lib/when/apply.js +++ /dev/null @@ -1,70 +0,0 @@ -/** @license MIT License (c) copyright B Cavalier & J Hann */ - -/** - * apply.js - * Helper for using arguments-based and variadic callbacks with any - * {@link Promise} that resolves to an array. - * - * @author brian@hovercraftstudios.com - */ - -(function(define) { -define(function() { - - var toString = Object.prototype.toString; - - /** - * Creates a function that accepts a function that takes individual - * arguments (it can be variadic, too), and returns a new function that - * takes a single array as its only param: - * - * function argBased(a, b, c) { - * return a + b + c; - * } - * - * argBased(1, 2, 3); // 6 - * - * // Create an array-based version of argBased - * var arrayBased = apply(argBased); - * var inputs = [1, 2, 3]; - * - * arrayBased(inputs); // 6 - * - * With promises: - * - * var d = when.defer(); - * d.promise.then(arrayBased); - * - * d.resolve([1, 2, 3]); // arrayBased called with args 1, 2, 3 -> 6 - * - * @param f {Function} arguments-based function - * - * @returns {Function} a new function that accepts an array - */ - return function(f) { - /** - * @param array {Array} must be an array of arguments to use to apply the original function - * - * @returns the result of applying f with the arguments in array. - */ - return function(array) { - // It better be an array - if(toString.call(array) != '[object Array]') { - throw new Error('apply called with non-array arg'); - } - - return f.apply(null, array); - }; - }; - -}); -})(typeof define == 'function' - ? define - : function (factory) { typeof module != 'undefined' - ? (module.exports = factory()) - : (this.when_apply = factory()); - } - // Boilerplate for AMD, Node, and browser global -); - - diff --git a/lib/when/cancelable.js b/lib/when/cancelable.js deleted file mode 100644 index 8521548..0000000 --- a/lib/when/cancelable.js +++ /dev/null @@ -1,66 +0,0 @@ -/** @license MIT License (c) copyright B Cavalier & J Hann */ - -/** - * cancelable.js - * - * Decorator that makes a deferred "cancelable". It adds a cancel() method that - * will call a special cancel handler function and then reject the deferred. The - * cancel handler can be used to do resource cleanup, or anything else that should - * be done before any other rejection handlers are executed. - * - * Usage: - * - * var cancelableDeferred = cancelable(when.defer(), myCancelHandler); - * - * @author brian@hovercraftstudios.com - */ - -(function(define) { -define(['./when'], function(when) { - - /** - * Makes deferred cancelable, adding a cancel() method. - * - * @param deferred {Deferred} the {@link Deferred} to make cancelable - * @param canceler {Function} cancel handler function to execute when this deferred is canceled. This - * is guaranteed to run before all other rejection handlers. The canceler will NOT be executed if the - * deferred is rejected in the standard way, i.e. deferred.reject(). It ONLY executes if the deferred - * is canceled, i.e. deferred.cancel() - * - * @returns deferred, with an added cancel() method. - */ - return function(deferred, canceler) { - - var delegate = when.defer(); - - // Add a cancel method to the deferred to reject the delegate - // with the special canceled indicator. - deferred.cancel = function() { - return delegate.reject(canceler(deferred)); - }; - - // Ensure that the original resolve, reject, and progress all forward - // to the delegate - deferred.then(delegate.resolve, delegate.reject, delegate.progress); - - // Replace deferred's promise with the delegate promise - deferred.promise = delegate.promise; - - // Also replace deferred.then to allow it to be called safely and - // observe the cancellation - deferred.then = delegate.promise.then; - - return deferred; - }; - -}); -})(typeof define == 'function' - ? define - : function (deps, factory) { typeof module != 'undefined' - ? (module.exports = factory(require('./when'))) - : (this.when_cancelable = factory(this.when)); - } - // Boilerplate for AMD, Node, and browser global -); - - diff --git a/lib/when/debug.js b/lib/when/debug.js deleted file mode 100644 index 79390c5..0000000 --- a/lib/when/debug.js +++ /dev/null @@ -1,302 +0,0 @@ -/** @license MIT License (c) copyright B Cavalier & J Hann */ - -/*jshint devel: true*/ -/*global console:true, setTimeout:true*/ - -/** - * This is a drop-in replacement for the when module that sets up automatic - * debug output for promises created or consumed by when.js. Use this - * instead of when to help with debugging. - * - * WARNING: This module **should never** be use this in a production environment. - * It exposes details of the promise - * - * In an AMD environment, you can simply change your path or package mappings: - * - * paths: { - * // 'when': 'path/to/when/when' - * 'when': 'path/to/when/debug' - * } - * - * or - * - * packages: [ - * // { name: 'when', location: 'path/to/when', main: 'when' } - * { name: 'when', location: 'path/to/when', main: 'debug' } - * ] - * - * In a CommonJS environment, you can directly require this module where - * you would normally require 'when': - * - * // var when = require('when'); - * var when = require('when/debug'); - * - * Or you can temporarily modify the package.js to point main at debug. - * For example, when/package.json: - * - * ... - * "main": "./debug" - * ... - * - * @author brian@hovercraftstudios.com - */ -(function(define) { -define(['./when'], function(when) { - - var promiseId, freeze, pending, exceptionsToRethrow, undef; - - promiseId = 0; - freeze = Object.freeze || function(o) { return o; }; - pending = {}; - - exceptionsToRethrow = { - RangeError: 1, - ReferenceError: 1, - SyntaxError: 1, - TypeError: 1 - }; - - /** - * Setup debug output handlers for the supplied promise. - * @param p {Promise} A trusted (when.js) promise - * @return p - */ - function debugPromise(p) { - // TODO: Need to find a way for promises returned by .then() - // to also be debug promises. - p.then( - undef, - function(err) { - if(p.id) { - console.error(p.toString()); - } else { - console.error('[object Promise] REJECTED:', err); - } - - return when.reject(err); - } - ); - - return p; - } - - function wrapCallback(cb) { - if(typeof cb != 'function') { - return cb; - } - - return function(v) { - try { - return cb(v); - } catch(err) { - if(err) { - if (err.name in exceptionsToRethrow) { - setTimeout(function() { - throw err; - }, 0); - } else if (err.stack) { - console.error(err.stack); - } - } - - throw err; - } - }; - } - - function wrapCallbacks(callbacks) { - var cb, args, len, i; - - args = []; - - for(i = 0, len = callbacks.length; i < len; i++) { - args[i] = typeof (cb = callbacks[i]) == 'function' - ? wrapCallback(cb) - : cb; - } - - return args; - } - - /** - * Helper to form debug string for promises depending on their - * current state - * @param name - * @param id - * @param status - * @param value - */ - function toString(name, id, status, value) { - var s = '[object ' + name + ' ' + id + '] ' + status; - - if(value !== pending) { - s += ': ' + value; - } - - return s; - } - - function F() {} - function beget(o) { - F.prototype = o; - o = new F(); - F.prototype = undef; - - return o; - } - - /** - * Replacement for when() that sets up debug logging on the - * returned promise. - */ - function whenDebug() { - return debugPromise(when.apply(null, wrapCallbacks(arguments))); - } - - /** - * Replacement for when.defer() that sets up debug logging - * on the created Deferred, its resolver, and its promise. - * @param [id] anything optional identifier for this Deferred that will show - * up in debug output - * @return {Deferred} a Deferred with debug logging - */ - function deferDebug() { - var d, status, value, origResolve, origReject, origProgress, origThen, id; - - // Delegate to create a Deferred; - d = when.defer(); - - status = 'pending'; - value = pending; - - // if no id provided, generate one. Not sure if this is - // useful or not. - id = arguments[arguments.length - 1]; - if(id === undef) { - id = ++promiseId; - } - - // Promise and resolver are frozen, so have to delegate - // in order to setup toString() on promise, resolver, - // and deferred - d.promise = beget(d.promise); - d.promise.toString = function() { - return toString('Promise', id, status, value); - }; - - d.resolver = beget(d.resolver); - d.resolver.toString = function() { - return toString('Resolver', id, status, value); - }; - - origProgress = d.resolver.progress; - d.progress = d.resolver.progress = function(update) { - if(value !== pending) { - alreadyResolved(); - } - - return origProgress.apply(undef, arguments); - }; - - origResolve = d.resolver.resolve; - d.resolve = d.resolver.resolve = function(val) { - if(value !== pending) { - alreadyResolved(); - } - - value = val; - status = 'resolving'; - return origResolve.apply(undef, arguments); - }; - - origReject = d.resolver.reject; - d.reject = d.resolver.reject = function(err) { - if(value !== pending) { - alreadyResolved(); - } - - value = err; - status = 'REJECTING'; - return origReject.apply(undef, arguments); - }; - - d.toString = function() { - return toString('Deferred', id, status, value); - }; - - // Setup final state change handlers - d.then( - function(v) { status = 'resolved'; return v; }, - function(e) { status = 'REJECTED'; return when.reject(e); } - ); - - // Experimenting with setting up ways to also debug promises returned - // by .then(). Also need to find a way to extend the id in a way that - // makes it obvious the returned promise is NOT the original, but is - // related to it--it's downstream in the promise chain. - origThen = d.promise.then; - d.then = d.promise.then = function(cb, eb, pb) { - - var id = d.id + '>' + (++promiseId); - - var p = origThen.apply(null, wrapCallbacks(arguments)); - - p.id = id; - p = beget(p); - p.toString = function() { - return toString('Promise', p.id, status, value); - }; - - // See below. Not sure if debug promises should be frozen - return freeze(p); - }; - - // Add an id to all directly created promises. It'd be great - // to find a way to propagate this id to promise created by .then() - d.id = d.promise.id = d.resolver.id = id; - - // Attach debug handlers after the substitute promise - // has been setup, so the id can be logged. - //debugPromise(d.promise); - - // TODO: Should we still freeze these? - // Seems safer for now to err on the side of caution and freeze them, - // but it could be useful to all them to be modified during debugging. - freeze(d.promise); - freeze(d.resolver); - - return d; - } - - function alreadyResolved() { - throw new Error('already completed'); - } - - whenDebug.defer = deferDebug; - whenDebug.isPromise = when.isPromise; - - function makeDebug(name, func) { - whenDebug[name] = function() { - return debugPromise(func.apply(when, arguments)); - }; - } - - // For each method we haven't already replaced, replace it with - // one that sets up debug logging on the returned promise - for(var p in when) { - if(when.hasOwnProperty(p) && !(p in whenDebug)) { - makeDebug(p, when[p]); - } - } - - return whenDebug; - -}); -})(typeof define == 'function' - ? define - : function (deps, factory) { typeof module != 'undefined' - ? (module.exports = factory(require('./when'))) - : (this.when = factory(this.when)); - } - // Boilerplate for AMD, Node, and browser global -); diff --git a/lib/when/delay.js b/lib/when/delay.js deleted file mode 100644 index 201dd77..0000000 --- a/lib/when/delay.js +++ /dev/null @@ -1,61 +0,0 @@ -/** @license MIT License (c) copyright B Cavalier & J Hann */ - -/*global setTimeout:true*/ - -/** - * delay.js - * - * Helper that returns a promise that resolves after a delay. - * - * @author brian@hovercraftstudios.com - */ - -(function(define) { -define(['./when'], function(when) { - - var undef; - - /** - * Creates a new promise that will resolve after a msec delay. If promise - * is supplied, the delay will start *after* the supplied promise is resolved. - * - * Usage: - * // Do something after 1 second, similar to using setTimeout - * delay(1000).then(doSomething); - * // or - * when(delay(1000), doSomething); - * - * // Do something 1 second after triggeringPromise resolves - * delay(triggeringPromise, 1000).then(doSomething, handleRejection); - * // or - * when(delay(triggeringPromise, 1000), doSomething, handleRejection); - * - * @param [promise] anything - any promise or value after which the delay will start - * @param msec {Number} delay in milliseconds - */ - return function delay(promise, msec) { - if(arguments.length < 2) { - msec = promise >>> 0; - promise = undef; - } - - var deferred = when.defer(); - - setTimeout(function() { - deferred.resolve(promise); - }, msec); - - return deferred.promise; - }; - -}); -})(typeof define == 'function' - ? define - : function (deps, factory) { typeof module != 'undefined' - ? (module.exports = factory(require('./when'))) - : (this.when_delay = factory(this.when)); - } - // Boilerplate for AMD, Node, and browser global -); - - diff --git a/lib/when/package.json b/lib/when/package.json deleted file mode 100644 index 88c3491..0000000 --- a/lib/when/package.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "name": "when", - "version": "1.5.0", - "description": "A lightweight Promise and when() implementation, plus other async goodies.", - "keywords": ["promises", "when", "async", "cujo"], - "licenses": [ - { - "type": "MIT", - "url": "http://www.opensource.org/licenses/mit-license.php" - } - ], - "repositories": [ - { - "type": "git", - "url": "https://github.com/cujojs/when" - } - ], - "bugs": "https://github.com/cujojs/when/issues", - "maintainers": [ - { - "name": "Brian Cavalier", - "web": "http://hovercraftstudios.com" - }, - { - "name": "John Hann", - "web": "http://unscriptable.com" - } - ], - "devDependencies": { - "buster": "~0.6" - }, - "main": "when", - "directories": { - "test": "test" - }, - "scripts": { - "test": "./node_modules/buster/bin/buster-test -e node" - } -} \ No newline at end of file diff --git a/lib/when/parallel.js b/lib/when/parallel.js deleted file mode 100644 index 6fe43f3..0000000 --- a/lib/when/parallel.js +++ /dev/null @@ -1,40 +0,0 @@ -/** @license MIT License (c) copyright B Cavalier & J Hann */ - -/** - * parallel.js - * - * Run a set of task functions in parallel. All tasks will - * receive the same args - * - * @author brian@hovercraftstudios.com - */ - -(function(define) { -define(['./when'], function(when) { - - /** - * Run array of tasks in parallel - * @param tasks {Array|Promise} array or promiseForArray of task functions - * @param [args] {*} arguments to be passed to all tasks - * @return {Promise} promise for array containing the - * result of each task in the array position corresponding - * to position of the task in the tasks array - */ - return function parallel(tasks /*, args... */) { - var args = Array.prototype.slice.call(arguments, 1); - return when.map(tasks, function(task) { - return task.apply(null, args); - }); - }; - -}); -})(typeof define == 'function' && define.amd - ? define - : function (deps, factory) { typeof exports == 'object' - ? (module.exports = factory(require('./when'))) - : (this.when_parallel = factory(this.when)); - } - // Boilerplate for AMD, Node, and browser global -); - - diff --git a/lib/when/pipeline.js b/lib/when/pipeline.js deleted file mode 100644 index dad1c4a..0000000 --- a/lib/when/pipeline.js +++ /dev/null @@ -1,57 +0,0 @@ -/** @license MIT License (c) copyright B Cavalier & J Hann */ - -/** - * pipeline.js - * - * Run a set of task functions in sequence, passing the result - * of the previous as an argument to the next. Like a shell - * pipeline, e.g. `cat file.txt | grep 'foo' | sed -e 's/foo/bar/g' - * - * @author brian@hovercraftstudios.com - */ - -(function(define) { -define(['./when'], function(when) { - - /** - * Run array of tasks in a pipeline where the next - * tasks receives the result of the previous. The first task - * will receive the initialArgs as its argument list. - * @param tasks {Array|Promise} array or promise for array of task functions - * @param [initialArgs...] {*} arguments to be passed to the first task - * @return {Promise} promise for return value of the final task - */ - return function pipeline(tasks /* initialArgs... */) { - var initialArgs, runTask; - - initialArgs = Array.prototype.slice.call(arguments, 1); - - // Self-optimizing function to run first task with multiple - // args using apply, but subsequence tasks via direct invocation - runTask = function(task, args) { - runTask = function(task, arg) { - return task(arg); - }; - - return task.apply(null, args); - }; - - return when.reduce(tasks, - function(args, task) { - return runTask(task, args); - }, - initialArgs - ); - }; - -}); -})(typeof define == 'function' && define.amd - ? define - : function (deps, factory) { typeof exports == 'object' - ? (module.exports = factory(require('./when'))) - : (this.when_pipeline = factory(this.when)); - } - // Boilerplate for AMD, Node, and browser global -); - - diff --git a/lib/when/sequence.js b/lib/when/sequence.js deleted file mode 100644 index 21939b3..0000000 --- a/lib/when/sequence.js +++ /dev/null @@ -1,43 +0,0 @@ -/** @license MIT License (c) copyright B Cavalier & J Hann */ - -/** - * sequence.js - * - * Run a set of task functions in sequence. All tasks will - * receive the same args. - * - * @author brian@hovercraftstudios.com - */ - -(function(define) { -define(['./when'], function(when) { - - /** - * Run array of tasks in sequence with no overlap - * @param tasks {Array|Promise} array or promiseForArray of task functions - * @param [args] {*} arguments to be passed to all tasks - * @return {Promise} promise for an array containing - * the result of each task in the array position corresponding - * to position of the task in the tasks array - */ - return function sequence(tasks /*, args... */) { - var args = Array.prototype.slice.call(arguments, 1); - return when.reduce(tasks, function(results, task) { - return when(task.apply(null, args), function(result) { - results.push(result); - return results; - }); - }, []); - }; - -}); -})(typeof define == 'function' && define.amd - ? define - : function (deps, factory) { typeof exports == 'object' - ? (module.exports = factory(require('./when'))) - : (this.when_sequence = factory(this.when)); - } - // Boilerplate for AMD, Node, and browser global -); - - diff --git a/lib/when/timed.js b/lib/when/timed.js deleted file mode 100644 index 973cbb5..0000000 --- a/lib/when/timed.js +++ /dev/null @@ -1,31 +0,0 @@ -/** @license MIT License (c) copyright B Cavalier & J Hann */ - -/** - * timed.js - * - * Helper group that aggregates all time & delay related helpers. If you - * use several of these helpers it can be more convenient to use this module - * instead of the individual helpers - * - * @author brian@hovercraftstudios.com - */ - -(function(define) { -define(['./timeout', './delay'], function(timeout, delay) { - - return { - timeout: timeout, - delay: delay - }; - -}); -})(typeof define == 'function' - ? define - : function (deps, factory) { typeof module != 'undefined' - ? (module.exports = factory.apply(this, deps.map(require))) - : (this.when_timed = factory(this.when_timeout, this.when_delay)); - } - // Boilerplate for AMD, Node, and browser global -); - - diff --git a/lib/when/timeout.js b/lib/when/timeout.js deleted file mode 100644 index aa11b3e..0000000 --- a/lib/when/timeout.js +++ /dev/null @@ -1,75 +0,0 @@ -/** @license MIT License (c) copyright B Cavalier & J Hann */ - -/*global setTimeout:true, clearTimeout:true*/ - -/** - * timeout.js - * - * Helper that returns a promise that rejects after a specified timeout, - * if not explicitly resolved or rejected before that. - * - * @author brian@hovercraftstudios.com - */ - -(function(define) { -define(['./when'], function(when) { - - var undef; - - /** - * Returns a new promise that will automatically reject after msec if - * the supplied promise doesn't resolve or reject before that. - * - * Usage: - * - * var d = when.defer(); - * // Setup d however you need - * - * // return a new promise that will timeout if d doesn't resolve/reject first - * return timeout(d.promise, 1000); - * - * @param promise anything - any promise or value that should trigger - * the returned promise to resolve or reject before the msec timeout - * @param msec {Number} timeout in milliseconds - * - * @returns {Promise} - */ - return function timeout(promise, msec) { - var deferred, timeoutRef; - - deferred = when.defer(); - - timeoutRef = setTimeout(function onTimeout() { - timeoutRef && deferred.reject(new Error('timed out')); - }, msec); - - function cancelTimeout() { - clearTimeout(timeoutRef); - timeoutRef = undef; - } - - when(promise, - function(value) { - cancelTimeout(); - deferred.resolve(value); - }, - function(reason) { - cancelTimeout(); - deferred.reject(reason); - } - ); - - return deferred.promise; - }; - -}); -})(typeof define == 'function' - ? define - : function (deps, factory) { typeof module != 'undefined' - ? (module.exports = factory(require('./when'))) - : (this.when_timeout = factory(this.when)); - } - // Boilerplate for AMD, Node, and browser global -); - - diff --git a/lib/when/when.js b/lib/when/when.js deleted file mode 100644 index b123a17..0000000 --- a/lib/when/when.js +++ /dev/null @@ -1,724 +0,0 @@ -/** @license MIT License (c) copyright B Cavalier & J Hann */ - -/** - * A lightweight CommonJS Promises/A and when() implementation - * when is part of the cujo.js family of libraries (http://cujojs.com/) - * - * Licensed under the MIT License at: - * http://www.opensource.org/licenses/mit-license.php - * - * @version 1.5.0 - */ - -(function(define, global) { -define(['module'], function(module) { "use strict"; - var freeze, reduceArray, slice, envFreeze, falseRx, undef; - - falseRx = /^false$/i; - envFreeze = 'WHEN_PARANOID'; - - // Do we need to be extra-secure? i.e. freeze promise, etc. - if(module && typeof module.config === 'function') { - freeze = module.config().paranoid !== false; - } else if(typeof process == 'object') { - freeze = !falseRx.test(process.env[envFreeze]); - } else if(typeof system == 'object') { - freeze = !falseRx.test(system.env[envFreeze]); - } else { - freeze = !(global && global.when_config && global.when_config.paranoid === false); - } - - // If secure and Object.freeze is available, use it. - freeze = (freeze && Object.freeze) || identity; - - // - // Public API - // - - when.defer = defer; // Create a deferred - when.resolve = resolve; // Create a resolved promise - when.reject = reject; // Create a rejected promise - - when.all = all; // Resolve a list of promises - when.some = some; // Resolve a sub-set of promises - when.any = any; // Resolve one promise in a list - - when.map = map; // Array.map() for promises - when.reduce = reduce; // Array.reduce() for promises - - when.chain = chain; // Make a promise trigger another resolver - - when.isPromise = isPromise; // Determine if a thing is a promise - - /** - * Register an observer for a promise or immediate value. - * @function - * @name when - * @namespace - * - * @param promiseOrValue {*} - * @param {Function} [callback] callback to be called when promiseOrValue is - * successfully resolved. If promiseOrValue is an immediate value, callback - * will be invoked immediately. - * @param {Function} [errback] callback to be called when promiseOrValue is - * rejected. - * @param {Function} [progressHandler] callback to be called when progress updates - * are issued for promiseOrValue. - * @returns {Promise} a new {@link Promise} that will complete with the return - * value of callback or errback or the completion value of promiseOrValue if - * callback and/or errback is not supplied. - */ - function when(promiseOrValue, callback, errback, progressHandler) { - // Get a trusted promise for the input promiseOrValue, and then - // register promise handlers - return resolve(promiseOrValue).then(callback, errback, progressHandler); - } - - /** - * Returns promiseOrValue if promiseOrValue is a {@link Promise}, a new Promise if - * promiseOrValue is a foreign promise, or a new, already-resolved {@link Promise} - * whose resolution value is promiseOrValue if promiseOrValue is an immediate value. - * @memberOf when - * - * @param promiseOrValue {*} - * @returns Guaranteed to return a trusted Promise. If promiseOrValue is a when.js {@link Promise} - * returns promiseOrValue, otherwise, returns a new, already-resolved, when.js {@link Promise} - * whose resolution value is: - * * the resolution value of promiseOrValue if it's a foreign promise, or - * * promiseOrValue if it's a value - */ - function resolve(promiseOrValue) { - var promise, deferred; - - if(promiseOrValue instanceof Promise) { - // It's a when.js promise, so we trust it - promise = promiseOrValue; - - } else { - // It's not a when.js promise. - // Check to see if it's a foreign promise or a value. - - // Some promises, particularly Q promises, provide a valueOf method that - // attempts to synchronously return the fulfilled value of the promise, or - // returns the unresolved promise itself. Attempting to break a fulfillment - // value out of a promise appears to be necessary to break cycles between - // Q and When attempting to coerce each-other's promises in an infinite loop. - // For promises that do not implement "valueOf", the Object#valueOf is harmless. - // See: https://github.com/kriskowal/q/issues/106 - if (promiseOrValue != null && typeof promiseOrValue.valueOf === "function") { - promiseOrValue = promiseOrValue.valueOf(); - } - - if(isPromise(promiseOrValue)) { - // It looks like a thenable, but we don't know where it came from, - // so we don't trust its implementation entirely. Introduce a trusted - // middleman when.js promise - deferred = defer(); - - // IMPORTANT: This is the only place when.js should ever call .then() on - // an untrusted promise. - promiseOrValue.then(deferred.resolve, deferred.reject, deferred.progress); - promise = deferred.promise; - - } else { - // It's a value, not a promise. Create a resolved promise for it. - promise = resolved(promiseOrValue); - } - } - - return promise; - } - - /** - * Returns a rejected promise for the supplied promiseOrValue. If - * promiseOrValue is a value, it will be the rejection value of the - * returned promise. If promiseOrValue is a promise, its - * completion value will be the rejected value of the returned promise - * @memberOf when - * - * @param promiseOrValue {*} the rejected value of the returned {@link Promise} - * @return {Promise} rejected {@link Promise} - */ - function reject(promiseOrValue) { - return when(promiseOrValue, function(value) { - return rejected(value); - }); - } - - /** - * Trusted Promise constructor. A Promise created from this constructor is - * a trusted when.js promise. Any other duck-typed promise is considered - * untrusted. - * @constructor - * @name Promise - */ - function Promise() {} - - Promise.prototype = freeze({ - /** - * Register a callback that will be called when a promise is - * resolved or rejected. Optionally also register a progress handler. - * Shortcut for .then(alwaysback, alwaysback, progback) - * @memberOf Promise - * @param alwaysback {Function} - * @param progback {Function} - * @return {Promise} - */ - always: function(alwaysback, progback) { - return this.then(alwaysback, alwaysback, progback); - }, - - /** - * Register a rejection handler. Shortcut for .then(null, errback) - * @memberOf Promise - * @param errback {Function} - * @return {Promise} - */ - otherwise: function(errback) { - return this.then(undef, errback); - } - }); - - /** - * Create an already-resolved promise for the supplied value - * @private - * - * @param value anything - * @return {Promise} - */ - function resolved(value) { - - var p = new Promise(); - - p.then = function(callback) { - try { - return resolve(callback ? callback(value) : value); - } catch(e) { - return rejected(e); - } - }; - - return freeze(p); - } - - /** - * Create an already-rejected {@link Promise} with the supplied - * rejection reason. - * @private - * - * @param reason rejection reason - * @return {Promise} - */ - function rejected(reason) { - - var p = new Promise(); - - p.then = function(callback, errback) { - try { - return errback ? resolve(errback(reason)) : rejected(reason); - } catch(e) { - return rejected(e); - } - }; - - return freeze(p); - } - - /** - * Creates a new, Deferred with fully isolated resolver and promise parts, - * either or both of which may be given out safely to consumers. - * The Deferred itself has the full API: resolve, reject, progress, and - * then. The resolver has resolve, reject, and progress. The promise - * only has then. - * @memberOf when - * @function - * - * @return {Deferred} - */ - function defer() { - var deferred, promise, resolver, listeners, progressHandlers, - _then, _progress, _resolve; - - listeners = []; - progressHandlers = []; - - /** - * The full Deferred object, with {@link Promise} and {@link Resolver} parts - * @class Deferred - * @name Deferred - */ - deferred = {}; - - /** - * The {@link Resolver} for this {@link Deferred} - * @memberOf Deferred - * @name resolver - * @class Resolver - */ - resolver = {}; - - /** - * The {@link Promise} for this {@link Deferred} - * @memberOf Deferred - * @name promise - * @type {Promise} - */ - promise = new Promise(); - - /** - * Registers a handler for this {@link Deferred}'s {@link Promise}. Even though all arguments - * are optional, each argument that *is* supplied must be null, undefined, or a Function. - * Any other value will cause an Error to be thrown. - * @memberOf Promise - * @name then - * @param [callback] {Function} resolution handler - * @param [errback] {Function} rejection handler - * @param [progback] {Function} progress handler - * @throw {Error} if any argument is not null, undefined, or a Function - */ - promise.then = deferred.then = function then(callback, errback, progback) { - return _then(callback, errback, progback); - }; - - deferred.promise = freeze(promise); - - /** - * Resolves this {@link Deferred}'s {@link Promise} with val as the - * resolution value. - * @memberOf Resolver - * @param val {*|Promise} If val is anything but a Promise, resolves this - * Deferred's Promise with val. If val is a Promise, puts this Deferred's - * Promise into the same state as val. For example, if val is a rejected - * promise, this Deferred will become rejected. - * @return {Promise} a promise for the resolution value - */ - resolver.resolve = deferred.resolve = function promiseResolve(val) { - return _resolve(val); - }; - - /** - * Rejects this {@link Deferred}'s {@link Promise} with err as the - * reason. - * @memberOf Resolver - * @param err anything - * @return {Promise} a promise for the rejection value - */ - resolver.reject = deferred.reject = function promiseReject(err) { - return _resolve(rejected(err)); - }; - - /** - * Emits a progress update to all progress observers registered with - * this {@link Deferred}'s {@link Promise} - * @memberOf Resolver - * @param update anything - */ - resolver.progress = deferred.progress = function promiseProgress(update) { - _progress(update); - }; - - deferred.resolver = freeze(resolver); - - /** - * Pre-resolution then() that adds the supplied callback, errback, and progback - * functions to the registered listeners - * @private - * - * @param [callback] {Function} resolution handler - * @param [errback] {Function} rejection handler - * @param [progback] {Function} progress handler - * @throws {Error} if any argument is not null, undefined, or a Function - */ - _then = function(callback, errback, progback) { - var deferred = defer(); - - listeners.push(function(promise) { - promise.then(callback, errback) - .then(deferred.resolve, deferred.reject, deferred.progress); - }); - - progback && progressHandlers.push(progback); - - return deferred.promise; - }; - - /** - * Issue a progress event, notifying all progress listeners - * @private - * @param update {*} progress event payload to pass to all listeners - */ - _progress = function(update) { - var progress, i = 0; - - while (progress = progressHandlers[i++]) { - progress(update); - } - }; - - /** - * Transition from pre-resolution state to post-resolution state, notifying - * all listeners of the resolution or rejection - * @private - * @param completed {Promise} the completed value of this deferred - */ - _resolve = function(completed) { - var listener, i = 0; - - completed = resolve(completed); - - // Replace _then with one that directly notifies with the result. - _then = completed.then; - - // Replace _resolve so that this Deferred can only be completed - // once. Also make _progress a noop, since progress can no longer - // be issued for the resolved promise. - _resolve = resolve; - _progress = noop; - - // Notify listeners - while (listener = listeners[i++]) { - listener(completed); - } - - // Free progressHandlers array since we'll never issue progress events - progressHandlers = listeners = undef; - - return completed; - }; - - return deferred; - } - - /** - * Determines if promiseOrValue is a promise or not. Uses the feature - * test from http://wiki.commonjs.org/wiki/Promises/A to determine if - * promiseOrValue is a promise. - * - * @param promiseOrValue anything - * @returns {Boolean} true if promiseOrValue is a {@link Promise} - */ - function isPromise(promiseOrValue) { - return promiseOrValue && typeof promiseOrValue.then === 'function'; - } - - /** - * Return a promise that will resolve when howMany of the supplied promisesOrValues - * have resolved. The resolution value of the returned promise will be an array of - * length howMany containing the resolutions values of the triggering promisesOrValues. - * @memberOf when - * - * @param promisesOrValues {Array} array of anything, may contain a mix - * of {@link Promise}s and values - * @param howMany - * @param [callback] - * @param [errback] - * @param [progressHandler] - * @returns {Promise} - */ - function some(promisesOrValues, howMany, callback, errback, progressHandler) { - - checkCallbacks(2, arguments); - - return when(promisesOrValues, function(promisesOrValues) { - - var toResolve, results, deferred, resolve, reject, progress, len, i; - - len = promisesOrValues.length >>> 0; - - toResolve = Math.max(0, Math.min(howMany, len)); - results = []; - deferred = defer(); - - // No items in the input, resolve immediately - if (!toResolve) { - deferred.resolve(results); - - } else { - // TODO: Consider rejecting only when N (or promises.length - N?) - // promises have been rejected instead of only one? - reject = deferred.reject; - progress = deferred.progress; - - // Resolver for promises. Captures the value and resolves - // the returned promise when toResolve reaches zero. - // Overwrites resolver var with a noop once promise has - // be resolved to cover case where n < promises.length - resolve = function(val) { - // This orders the values based on promise resolution order - // Another strategy would be to use the original position of - // the corresponding promise. - results.push(val); - - if (!--toResolve) { - resolve = noop; - deferred.resolve(results); - } - }; - - for(i = 0; i < len; ++i) { - if(i in promisesOrValues) { - when(promisesOrValues[i], resolve, reject, progress); - } - } - } - - return deferred.then(callback, errback, progressHandler); - }); - } - - /** - * Return a promise that will resolve only once all the supplied promisesOrValues - * have resolved. The resolution value of the returned promise will be an array - * containing the resolution values of each of the promisesOrValues. - * @memberOf when - * - * @param promisesOrValues {Array|Promise} array of anything, may contain a mix - * of {@link Promise}s and values - * @param [callback] {Function} - * @param [errback] {Function} - * @param [progressHandler] {Function} - * @returns {Promise} - */ - function all(promisesOrValues, callback, errback, progressHandler) { - checkCallbacks(1, arguments); - return map(promisesOrValues, identity).then(callback, errback, progressHandler); - } - - /** - * Return a promise that will resolve when any one of the supplied promisesOrValues - * has resolved. The resolution value of the returned promise will be the resolution - * value of the triggering promiseOrValue. - * @memberOf when - * - * @param promisesOrValues {Array|Promise} array of anything, may contain a mix - * of {@link Promise}s and values - * @param [callback] {Function} - * @param [errback] {Function} - * @param [progressHandler] {Function} - * @returns {Promise} - */ - function any(promisesOrValues, callback, errback, progressHandler) { - - function unwrapSingleResult(val) { - return callback ? callback(val[0]) : val[0]; - } - - return some(promisesOrValues, 1, unwrapSingleResult, errback, progressHandler); - } - - /** - * Traditional map function, similar to `Array.prototype.map()`, but allows - * input to contain {@link Promise}s and/or values, and mapFunc may return - * either a value or a {@link Promise} - * - * @memberOf when - * - * @param promise {Array|Promise} array of anything, may contain a mix - * of {@link Promise}s and values - * @param mapFunc {Function} mapping function mapFunc(value) which may return - * either a {@link Promise} or value - * @returns {Promise} a {@link Promise} that will resolve to an array containing - * the mapped output values. - */ - function map(promise, mapFunc) { - return when(promise, function(array) { - var results, len, toResolve, resolve, reject, i, d; - - // Since we know the resulting length, we can preallocate the results - // array to avoid array expansions. - toResolve = len = array.length >>> 0; - results = []; - d = defer(); - - if(!toResolve) { - d.resolve(results); - } else { - - reject = d.reject; - resolve = function resolveOne(item, i) { - when(item, mapFunc).then(function(mapped) { - results[i] = mapped; - - if(!--toResolve) { - d.resolve(results); - } - }, reject); - }; - - // Since mapFunc may be async, get all invocations of it into flight - for(i = 0; i < len; i++) { - if(i in array) { - resolve(array[i], i); - } else { - --toResolve; - } - } - - } - - return d.promise; - - }); - } - - /** - * Traditional reduce function, similar to `Array.prototype.reduce()`, but - * input may contain {@link Promise}s and/or values, and reduceFunc - * may return either a value or a {@link Promise}, *and* initialValue may - * be a {@link Promise} for the starting value. - * @memberOf when - * - * @param promise {Array|Promise} array of anything, may contain a mix - * of {@link Promise}s and values. May also be a {@link Promise} for - * an array. - * @param reduceFunc {Function} reduce function reduce(currentValue, nextValue, index, total), - * where total is the total number of items being reduced, and will be the same - * in each call to reduceFunc. - * @param [initialValue] {*} starting value, or a {@link Promise} for the starting value - * @returns {Promise} that will resolve to the final reduced value - */ - function reduce(promise, reduceFunc /*, initialValue */) { - var args = slice.call(arguments, 1); - - return when(promise, function(array) { - var total; - - total = array.length; - - // Wrap the supplied reduceFunc with one that handles promises and then - // delegates to the supplied. - args[0] = function (current, val, i) { - return when(current, function (c) { - return when(val, function (value) { - return reduceFunc(c, value, i, total); - }); - }); - }; - - return reduceArray.apply(array, args); - }); - } - - /** - * Ensure that resolution of promiseOrValue will complete resolver with the completion - * value of promiseOrValue, or instead with resolveValue if it is provided. - * @memberOf when - * - * @param promiseOrValue - * @param resolver {Resolver} - * @param [resolveValue] anything - * @returns {Promise} - */ - function chain(promiseOrValue, resolver, resolveValue) { - var useResolveValue = arguments.length > 2; - - return when(promiseOrValue, - function(val) { - return resolver.resolve(useResolveValue ? resolveValue : val); - }, - resolver.reject, - resolver.progress - ); - } - - // - // Utility functions - // - - /** - * Helper that checks arrayOfCallbacks to ensure that each element is either - * a function, or null or undefined. - * @private - * - * @param arrayOfCallbacks {Array} array to check - * @throws {Error} if any element of arrayOfCallbacks is something other than - * a Functions, null, or undefined. - */ - function checkCallbacks(start, arrayOfCallbacks) { - var arg, i = arrayOfCallbacks.length; - - while(i > start) { - arg = arrayOfCallbacks[--i]; - - if (arg != null && typeof arg != 'function') { - throw new Error('arg '+i+' must be a function'); - } - } - } - - /** - * No-Op function used in method replacement - * @private - */ - function noop() {} - - slice = [].slice; - - // ES5 reduce implementation if native not available - // See: http://es5.github.com/#x15.4.4.21 as there are many - // specifics and edge cases. - reduceArray = [].reduce || - function(reduceFunc /*, initialValue */) { - // ES5 dictates that reduce.length === 1 - - // This implementation deviates from ES5 spec in the following ways: - // 1. It does not check if reduceFunc is a Callable - - var arr, args, reduced, len, i; - - i = 0; - // This generates a jshint warning, despite being valid - // "Missing 'new' prefix when invoking a constructor." - // See https://github.com/jshint/jshint/issues/392 - /*jshint newcap: false */ - arr = Object(this); - len = arr.length >>> 0; - args = arguments; - - // If no initialValue, use first item of array (we know length !== 0 here) - // and adjust i to start at second item - if(args.length <= 1) { - // Skip to the first real element in the array - for(;;) { - if(i in arr) { - reduced = arr[i++]; - break; - } - - // If we reached the end of the array without finding any real - // elements, it's a TypeError - if(++i >= len) { - throw new TypeError(); - } - } - } else { - // If initialValue provided, use it - reduced = args[1]; - } - - // Do the actual reduce - for(;i < len; ++i) { - // Skip holes - if(i in arr) { - reduced = reduceFunc(reduced, arr[i], i, arr); - } - } - - return reduced; - }; - - function identity(x) { - return x; - } - - return when; -}); -})(typeof define == 'function' && define.amd - ? define - : function (deps, factory) { typeof exports === 'object' - ? (module.exports = factory()) - : (this.when = factory()); - }, - // Boilerplate for AMD, Node, and browser global - this -);