source: Dev/trunk/src/node_modules/q/q.js @ 489

Last change on this file since 489 was 489, checked in by hendrikvanantwerpen, 11 years ago

Update node modules

File size: 57.7 KB
Line 
1// vim:ts=4:sts=4:sw=4:
2/*!
3 *
4 * Copyright 2009-2012 Kris Kowal under the terms of the MIT
5 * license found at http://github.com/kriskowal/q/raw/master/LICENSE
6 *
7 * With parts by Tyler Close
8 * Copyright 2007-2009 Tyler Close under the terms of the MIT X license found
9 * at http://www.opensource.org/licenses/mit-license.html
10 * Forked at ref_send.js version: 2009-05-11
11 *
12 * With parts by Mark Miller
13 * Copyright (C) 2011 Google Inc.
14 *
15 * Licensed under the Apache License, Version 2.0 (the "License");
16 * you may not use this file except in compliance with the License.
17 * You may obtain a copy of the License at
18 *
19 * http://www.apache.org/licenses/LICENSE-2.0
20 *
21 * Unless required by applicable law or agreed to in writing, software
22 * distributed under the License is distributed on an "AS IS" BASIS,
23 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
24 * See the License for the specific language governing permissions and
25 * limitations under the License.
26 *
27 */
28
29(function (definition) {
30    // Turn off strict mode for this function so we can assign to global.Q
31    /* jshint strict: false */
32
33    // This file will function properly as a <script> tag, or a module
34    // using CommonJS and NodeJS or RequireJS module formats.  In
35    // Common/Node/RequireJS, the module exports the Q API and when
36    // executed as a simple <script>, it creates a Q global instead.
37
38    // Montage Require
39    if (typeof bootstrap === "function") {
40        bootstrap("promise", definition);
41
42    // CommonJS
43    } else if (typeof exports === "object") {
44        module.exports = definition();
45
46    // RequireJS
47    } else if (typeof define === "function" && define.amd) {
48        define(definition);
49
50    // SES (Secure EcmaScript)
51    } else if (typeof ses !== "undefined") {
52        if (!ses.ok()) {
53            return;
54        } else {
55            ses.makeQ = definition;
56        }
57
58    // <script>
59    } else {
60        Q = definition();
61    }
62
63})(function () {
64"use strict";
65
66var hasStacks = false;
67try {
68    throw new Error();
69} catch (e) {
70    hasStacks = !!e.stack;
71}
72
73// All code after this point will be filtered from stack traces reported
74// by Q.
75var qStartingLine = captureLine();
76var qFileName;
77
78// shims
79
80// used for fallback in "allResolved"
81var noop = function () {};
82
83// Use the fastest possible means to execute a task in a future turn
84// of the event loop.
85var nextTick =(function () {
86    // linked list of tasks (single, with head node)
87    var head = {task: void 0, next: null};
88    var tail = head;
89    var flushing = false;
90    var requestTick = void 0;
91    var isNodeJS = false;
92
93    function flush() {
94        /* jshint loopfunc: true */
95
96        while (head.next) {
97            head = head.next;
98            var task = head.task;
99            head.task = void 0;
100            var domain = head.domain;
101
102            if (domain) {
103                head.domain = void 0;
104                domain.enter();
105            }
106
107            try {
108                task();
109
110            } catch (e) {
111                if (isNodeJS) {
112                    // In node, uncaught exceptions are considered fatal errors.
113                    // Re-throw them synchronously to interrupt flushing!
114
115                    // Ensure continuation if the uncaught exception is suppressed
116                    // listening "uncaughtException" events (as domains does).
117                    // Continue in next event to avoid tick recursion.
118                    if (domain) {
119                        domain.exit();
120                    }
121                    setTimeout(flush, 0);
122                    if (domain) {
123                        domain.enter();
124                    }
125
126                    throw e;
127
128                } else {
129                    // In browsers, uncaught exceptions are not fatal.
130                    // Re-throw them asynchronously to avoid slow-downs.
131                    setTimeout(function() {
132                       throw e;
133                    }, 0);
134                }
135            }
136
137            if (domain) {
138                domain.exit();
139            }
140        }
141
142        flushing = false;
143    }
144
145    nextTick = function (task) {
146        tail = tail.next = {
147            task: task,
148            domain: isNodeJS && process.domain,
149            next: null
150        };
151
152        if (!flushing) {
153            flushing = true;
154            requestTick();
155        }
156    };
157
158    if (typeof process !== "undefined" && process.nextTick) {
159        // Node.js before 0.9. Note that some fake-Node environments, like the
160        // Mocha test runner, introduce a `process` global without a `nextTick`.
161        isNodeJS = true;
162
163        requestTick = function () {
164            process.nextTick(flush);
165        };
166
167    } else if (typeof setImmediate === "function") {
168        // In IE10, Node.js 0.9+, or https://github.com/NobleJS/setImmediate
169        if (typeof window !== "undefined") {
170            requestTick = setImmediate.bind(window, flush);
171        } else {
172            requestTick = function () {
173                setImmediate(flush);
174            };
175        }
176
177    } else if (typeof MessageChannel !== "undefined") {
178        // modern browsers
179        // http://www.nonblocking.io/2011/06/windownexttick.html
180        var channel = new MessageChannel();
181        // At least Safari Version 6.0.5 (8536.30.1) intermittently cannot create
182        // working message ports the first time a page loads.
183        channel.port1.onmessage = function () {
184            requestTick = requestPortTick;
185            channel.port1.onmessage = flush;
186            flush();
187        };
188        var requestPortTick = function () {
189            // Opera requires us to provide a message payload, regardless of
190            // whether we use it.
191            channel.port2.postMessage(0);
192        };
193        requestTick = function () {
194            setTimeout(flush, 0);
195            requestPortTick();
196        };
197
198    } else {
199        // old browsers
200        requestTick = function () {
201            setTimeout(flush, 0);
202        };
203    }
204
205    return nextTick;
206})();
207
208// Attempt to make generics safe in the face of downstream
209// modifications.
210// There is no situation where this is necessary.
211// If you need a security guarantee, these primordials need to be
212// deeply frozen anyway, and if you don’t need a security guarantee,
213// this is just plain paranoid.
214// However, this does have the nice side-effect of reducing the size
215// of the code by reducing x.call() to merely x(), eliminating many
216// hard-to-minify characters.
217// See Mark Miller’s explanation of what this does.
218// http://wiki.ecmascript.org/doku.php?id=conventions:safe_meta_programming
219var call = Function.call;
220function uncurryThis(f) {
221    return function () {
222        return call.apply(f, arguments);
223    };
224}
225// This is equivalent, but slower:
226// uncurryThis = Function_bind.bind(Function_bind.call);
227// http://jsperf.com/uncurrythis
228
229var array_slice = uncurryThis(Array.prototype.slice);
230
231var array_reduce = uncurryThis(
232    Array.prototype.reduce || function (callback, basis) {
233        var index = 0,
234            length = this.length;
235        // concerning the initial value, if one is not provided
236        if (arguments.length === 1) {
237            // seek to the first value in the array, accounting
238            // for the possibility that is is a sparse array
239            do {
240                if (index in this) {
241                    basis = this[index++];
242                    break;
243                }
244                if (++index >= length) {
245                    throw new TypeError();
246                }
247            } while (1);
248        }
249        // reduce
250        for (; index < length; index++) {
251            // account for the possibility that the array is sparse
252            if (index in this) {
253                basis = callback(basis, this[index], index);
254            }
255        }
256        return basis;
257    }
258);
259
260var array_indexOf = uncurryThis(
261    Array.prototype.indexOf || function (value) {
262        // not a very good shim, but good enough for our one use of it
263        for (var i = 0; i < this.length; i++) {
264            if (this[i] === value) {
265                return i;
266            }
267        }
268        return -1;
269    }
270);
271
272var array_map = uncurryThis(
273    Array.prototype.map || function (callback, thisp) {
274        var self = this;
275        var collect = [];
276        array_reduce(self, function (undefined, value, index) {
277            collect.push(callback.call(thisp, value, index, self));
278        }, void 0);
279        return collect;
280    }
281);
282
283var object_create = Object.create || function (prototype) {
284    function Type() { }
285    Type.prototype = prototype;
286    return new Type();
287};
288
289var object_hasOwnProperty = uncurryThis(Object.prototype.hasOwnProperty);
290
291var object_keys = Object.keys || function (object) {
292    var keys = [];
293    for (var key in object) {
294        if (object_hasOwnProperty(object, key)) {
295            keys.push(key);
296        }
297    }
298    return keys;
299};
300
301var object_toString = uncurryThis(Object.prototype.toString);
302
303function isObject(value) {
304    return value === Object(value);
305}
306
307// generator related shims
308
309// FIXME: Remove this function once ES6 generators are in SpiderMonkey.
310function isStopIteration(exception) {
311    return (
312        object_toString(exception) === "[object StopIteration]" ||
313        exception instanceof QReturnValue
314    );
315}
316
317// FIXME: Remove this helper and Q.return once ES6 generators are in
318// SpiderMonkey.
319var QReturnValue;
320if (typeof ReturnValue !== "undefined") {
321    QReturnValue = ReturnValue;
322} else {
323    QReturnValue = function (value) {
324        this.value = value;
325    };
326}
327
328// Until V8 3.19 / Chromium 29 is released, SpiderMonkey is the only
329// engine that has a deployed base of browsers that support generators.
330// However, SM's generators use the Python-inspired semantics of
331// outdated ES6 drafts.  We would like to support ES6, but we'd also
332// like to make it possible to use generators in deployed browsers, so
333// we also support Python-style generators.  At some point we can remove
334// this block.
335var hasES6Generators;
336try {
337    /* jshint evil: true, nonew: false */
338    new Function("(function* (){ yield 1; })");
339    hasES6Generators = true;
340} catch (e) {
341    hasES6Generators = false;
342}
343
344// long stack traces
345
346var STACK_JUMP_SEPARATOR = "From previous event:";
347
348function makeStackTraceLong(error, promise) {
349    // If possible, transform the error stack trace by removing Node and Q
350    // cruft, then concatenating with the stack trace of `promise`. See #57.
351    if (hasStacks &&
352        promise.stack &&
353        typeof error === "object" &&
354        error !== null &&
355        error.stack &&
356        error.stack.indexOf(STACK_JUMP_SEPARATOR) === -1
357    ) {
358        var stacks = [];
359        for (var p = promise; !!p; p = p.source) {
360            if (p.stack) {
361                stacks.unshift(p.stack);
362            }
363        }
364        stacks.unshift(error.stack);
365
366        var concatedStacks = stacks.join("\n" + STACK_JUMP_SEPARATOR + "\n");
367        error.stack = filterStackString(concatedStacks);
368    }
369}
370
371function filterStackString(stackString) {
372    var lines = stackString.split("\n");
373    var desiredLines = [];
374    for (var i = 0; i < lines.length; ++i) {
375        var line = lines[i];
376
377        if (!isInternalFrame(line) && !isNodeFrame(line) && line) {
378            desiredLines.push(line);
379        }
380    }
381    return desiredLines.join("\n");
382}
383
384function isNodeFrame(stackLine) {
385    return stackLine.indexOf("(module.js:") !== -1 ||
386           stackLine.indexOf("(node.js:") !== -1;
387}
388
389function getFileNameAndLineNumber(stackLine) {
390    // Named functions: "at functionName (filename:lineNumber:columnNumber)"
391    // In IE10 function name can have spaces ("Anonymous function") O_o
392    var attempt1 = /at .+ \((.+):(\d+):(?:\d+)\)$/.exec(stackLine);
393    if (attempt1) {
394        return [attempt1[1], Number(attempt1[2])];
395    }
396
397    // Anonymous functions: "at filename:lineNumber:columnNumber"
398    var attempt2 = /at ([^ ]+):(\d+):(?:\d+)$/.exec(stackLine);
399    if (attempt2) {
400        return [attempt2[1], Number(attempt2[2])];
401    }
402
403    // Firefox style: "function@filename:lineNumber or @filename:lineNumber"
404    var attempt3 = /.*@(.+):(\d+)$/.exec(stackLine);
405    if (attempt3) {
406        return [attempt3[1], Number(attempt3[2])];
407    }
408}
409
410function isInternalFrame(stackLine) {
411    var fileNameAndLineNumber = getFileNameAndLineNumber(stackLine);
412
413    if (!fileNameAndLineNumber) {
414        return false;
415    }
416
417    var fileName = fileNameAndLineNumber[0];
418    var lineNumber = fileNameAndLineNumber[1];
419
420    return fileName === qFileName &&
421        lineNumber >= qStartingLine &&
422        lineNumber <= qEndingLine;
423}
424
425// discover own file name and line number range for filtering stack
426// traces
427function captureLine() {
428    if (!hasStacks) {
429        return;
430    }
431
432    try {
433        throw new Error();
434    } catch (e) {
435        var lines = e.stack.split("\n");
436        var firstLine = lines[0].indexOf("@") > 0 ? lines[1] : lines[2];
437        var fileNameAndLineNumber = getFileNameAndLineNumber(firstLine);
438        if (!fileNameAndLineNumber) {
439            return;
440        }
441
442        qFileName = fileNameAndLineNumber[0];
443        return fileNameAndLineNumber[1];
444    }
445}
446
447function deprecate(callback, name, alternative) {
448    return function () {
449        if (typeof console !== "undefined" &&
450            typeof console.warn === "function") {
451            console.warn(name + " is deprecated, use " + alternative +
452                         " instead.", new Error("").stack);
453        }
454        return callback.apply(callback, arguments);
455    };
456}
457
458// end of shims
459// beginning of real work
460
461/**
462 * Constructs a promise for an immediate reference, passes promises through, or
463 * coerces promises from different systems.
464 * @param value immediate reference or promise
465 */
466function Q(value) {
467    // If the object is already a Promise, return it directly.  This enables
468    // the resolve function to both be used to created references from objects,
469    // but to tolerably coerce non-promises to promises.
470    if (isPromise(value)) {
471        return value;
472    }
473
474    // assimilate thenables
475    if (isPromiseAlike(value)) {
476        return coerce(value);
477    } else {
478        return fulfill(value);
479    }
480}
481Q.resolve = Q;
482
483/**
484 * Performs a task in a future turn of the event loop.
485 * @param {Function} task
486 */
487Q.nextTick = nextTick;
488
489/**
490 * Controls whether or not long stack traces will be on
491 */
492Q.longStackSupport = false;
493
494/**
495 * Constructs a {promise, resolve, reject} object.
496 *
497 * `resolve` is a callback to invoke with a more resolved value for the
498 * promise. To fulfill the promise, invoke `resolve` with any value that is
499 * not a thenable. To reject the promise, invoke `resolve` with a rejected
500 * thenable, or invoke `reject` with the reason directly. To resolve the
501 * promise to another thenable, thus putting it in the same state, invoke
502 * `resolve` with that other thenable.
503 */
504Q.defer = defer;
505function defer() {
506    // if "messages" is an "Array", that indicates that the promise has not yet
507    // been resolved.  If it is "undefined", it has been resolved.  Each
508    // element of the messages array is itself an array of complete arguments to
509    // forward to the resolved promise.  We coerce the resolution value to a
510    // promise using the `resolve` function because it handles both fully
511    // non-thenable values and other thenables gracefully.
512    var messages = [], progressListeners = [], resolvedPromise;
513
514    var deferred = object_create(defer.prototype);
515    var promise = object_create(Promise.prototype);
516
517    promise.promiseDispatch = function (resolve, op, operands) {
518        var args = array_slice(arguments);
519        if (messages) {
520            messages.push(args);
521            if (op === "when" && operands[1]) { // progress operand
522                progressListeners.push(operands[1]);
523            }
524        } else {
525            nextTick(function () {
526                resolvedPromise.promiseDispatch.apply(resolvedPromise, args);
527            });
528        }
529    };
530
531    // XXX deprecated
532    promise.valueOf = deprecate(function () {
533        if (messages) {
534            return promise;
535        }
536        var nearerValue = nearer(resolvedPromise);
537        if (isPromise(nearerValue)) {
538            resolvedPromise = nearerValue; // shorten chain
539        }
540        return nearerValue;
541    }, "valueOf", "inspect");
542
543    promise.inspect = function () {
544        if (!resolvedPromise) {
545            return { state: "pending" };
546        }
547        return resolvedPromise.inspect();
548    };
549
550    if (Q.longStackSupport && hasStacks) {
551        try {
552            throw new Error();
553        } catch (e) {
554            // NOTE: don't try to use `Error.captureStackTrace` or transfer the
555            // accessor around; that causes memory leaks as per GH-111. Just
556            // reify the stack trace as a string ASAP.
557            //
558            // At the same time, cut off the first line; it's always just
559            // "[object Promise]\n", as per the `toString`.
560            promise.stack = e.stack.substring(e.stack.indexOf("\n") + 1);
561        }
562    }
563
564    // NOTE: we do the checks for `resolvedPromise` in each method, instead of
565    // consolidating them into `become`, since otherwise we'd create new
566    // promises with the lines `become(whatever(value))`. See e.g. GH-252.
567
568    function become(newPromise) {
569        resolvedPromise = newPromise;
570        promise.source = newPromise;
571
572        array_reduce(messages, function (undefined, message) {
573            nextTick(function () {
574                newPromise.promiseDispatch.apply(newPromise, message);
575            });
576        }, void 0);
577
578        messages = void 0;
579        progressListeners = void 0;
580    }
581
582    deferred.promise = promise;
583    deferred.resolve = function (value) {
584        if (resolvedPromise) {
585            return;
586        }
587
588        become(Q(value));
589    };
590
591    deferred.fulfill = function (value) {
592        if (resolvedPromise) {
593            return;
594        }
595
596        become(fulfill(value));
597    };
598    deferred.reject = function (reason) {
599        if (resolvedPromise) {
600            return;
601        }
602
603        become(reject(reason));
604    };
605    deferred.notify = function (progress) {
606        if (resolvedPromise) {
607            return;
608        }
609
610        array_reduce(progressListeners, function (undefined, progressListener) {
611            nextTick(function () {
612                progressListener(progress);
613            });
614        }, void 0);
615    };
616
617    return deferred;
618}
619
620/**
621 * Creates a Node-style callback that will resolve or reject the deferred
622 * promise.
623 * @returns a nodeback
624 */
625defer.prototype.makeNodeResolver = function () {
626    var self = this;
627    return function (error, value) {
628        if (error) {
629            self.reject(error);
630        } else if (arguments.length > 2) {
631            self.resolve(array_slice(arguments, 1));
632        } else {
633            self.resolve(value);
634        }
635    };
636};
637
638/**
639 * @param resolver {Function} a function that returns nothing and accepts
640 * the resolve, reject, and notify functions for a deferred.
641 * @returns a promise that may be resolved with the given resolve and reject
642 * functions, or rejected by a thrown exception in resolver
643 */
644Q.promise = promise;
645function promise(resolver) {
646    if (typeof resolver !== "function") {
647        throw new TypeError("resolver must be a function.");
648    }
649    var deferred = defer();
650    try {
651        resolver(deferred.resolve, deferred.reject, deferred.notify);
652    } catch (reason) {
653        deferred.reject(reason);
654    }
655    return deferred.promise;
656}
657
658// XXX experimental.  This method is a way to denote that a local value is
659// serializable and should be immediately dispatched to a remote upon request,
660// instead of passing a reference.
661Q.passByCopy = function (object) {
662    //freeze(object);
663    //passByCopies.set(object, true);
664    return object;
665};
666
667Promise.prototype.passByCopy = function () {
668    //freeze(object);
669    //passByCopies.set(object, true);
670    return this;
671};
672
673/**
674 * If two promises eventually fulfill to the same value, promises that value,
675 * but otherwise rejects.
676 * @param x {Any*}
677 * @param y {Any*}
678 * @returns {Any*} a promise for x and y if they are the same, but a rejection
679 * otherwise.
680 *
681 */
682Q.join = function (x, y) {
683    return Q(x).join(y);
684};
685
686Promise.prototype.join = function (that) {
687    return Q([this, that]).spread(function (x, y) {
688        if (x === y) {
689            // TODO: "===" should be Object.is or equiv
690            return x;
691        } else {
692            throw new Error("Can't join: not the same: " + x + " " + y);
693        }
694    });
695};
696
697/**
698 * Returns a promise for the first of an array of promises to become fulfilled.
699 * @param answers {Array[Any*]} promises to race
700 * @returns {Any*} the first promise to be fulfilled
701 */
702Q.race = race;
703function race(answerPs) {
704    return promise(function(resolve, reject) {
705        // Switch to this once we can assume at least ES5
706        // answerPs.forEach(function(answerP) {
707        //     Q(answerP).then(resolve, reject);
708        // });
709        // Use this in the meantime
710        for (var i = 0, len = answerPs.length; i < len; i++) {
711            Q(answerPs[i]).then(resolve, reject);
712        }
713    });
714}
715
716Promise.prototype.race = function () {
717    return this.then(Q.race);
718};
719
720/**
721 * Constructs a Promise with a promise descriptor object and optional fallback
722 * function.  The descriptor contains methods like when(rejected), get(name),
723 * set(name, value), post(name, args), and delete(name), which all
724 * return either a value, a promise for a value, or a rejection.  The fallback
725 * accepts the operation name, a resolver, and any further arguments that would
726 * have been forwarded to the appropriate method above had a method been
727 * provided with the proper name.  The API makes no guarantees about the nature
728 * of the returned object, apart from that it is usable whereever promises are
729 * bought and sold.
730 */
731Q.makePromise = Promise;
732function Promise(descriptor, fallback, inspect) {
733    if (fallback === void 0) {
734        fallback = function (op) {
735            return reject(new Error(
736                "Promise does not support operation: " + op
737            ));
738        };
739    }
740    if (inspect === void 0) {
741        inspect = function () {
742            return {state: "unknown"};
743        };
744    }
745
746    var promise = object_create(Promise.prototype);
747
748    promise.promiseDispatch = function (resolve, op, args) {
749        var result;
750        try {
751            if (descriptor[op]) {
752                result = descriptor[op].apply(promise, args);
753            } else {
754                result = fallback.call(promise, op, args);
755            }
756        } catch (exception) {
757            result = reject(exception);
758        }
759        if (resolve) {
760            resolve(result);
761        }
762    };
763
764    promise.inspect = inspect;
765
766    // XXX deprecated `valueOf` and `exception` support
767    if (inspect) {
768        var inspected = inspect();
769        if (inspected.state === "rejected") {
770            promise.exception = inspected.reason;
771        }
772
773        promise.valueOf = deprecate(function () {
774            var inspected = inspect();
775            if (inspected.state === "pending" ||
776                inspected.state === "rejected") {
777                return promise;
778            }
779            return inspected.value;
780        });
781    }
782
783    return promise;
784}
785
786Promise.prototype.toString = function () {
787    return "[object Promise]";
788};
789
790Promise.prototype.then = function (fulfilled, rejected, progressed) {
791    var self = this;
792    var deferred = defer();
793    var done = false;   // ensure the untrusted promise makes at most a
794                        // single call to one of the callbacks
795
796    function _fulfilled(value) {
797        try {
798            return typeof fulfilled === "function" ? fulfilled(value) : value;
799        } catch (exception) {
800            return reject(exception);
801        }
802    }
803
804    function _rejected(exception) {
805        if (typeof rejected === "function") {
806            makeStackTraceLong(exception, self);
807            try {
808                return rejected(exception);
809            } catch (newException) {
810                return reject(newException);
811            }
812        }
813        return reject(exception);
814    }
815
816    function _progressed(value) {
817        return typeof progressed === "function" ? progressed(value) : value;
818    }
819
820    nextTick(function () {
821        self.promiseDispatch(function (value) {
822            if (done) {
823                return;
824            }
825            done = true;
826
827            deferred.resolve(_fulfilled(value));
828        }, "when", [function (exception) {
829            if (done) {
830                return;
831            }
832            done = true;
833
834            deferred.resolve(_rejected(exception));
835        }]);
836    });
837
838    // Progress propagator need to be attached in the current tick.
839    self.promiseDispatch(void 0, "when", [void 0, function (value) {
840        var newValue;
841        var threw = false;
842        try {
843            newValue = _progressed(value);
844        } catch (e) {
845            threw = true;
846            if (Q.onerror) {
847                Q.onerror(e);
848            } else {
849                throw e;
850            }
851        }
852
853        if (!threw) {
854            deferred.notify(newValue);
855        }
856    }]);
857
858    return deferred.promise;
859};
860
861/**
862 * Registers an observer on a promise.
863 *
864 * Guarantees:
865 *
866 * 1. that fulfilled and rejected will be called only once.
867 * 2. that either the fulfilled callback or the rejected callback will be
868 *    called, but not both.
869 * 3. that fulfilled and rejected will not be called in this turn.
870 *
871 * @param value      promise or immediate reference to observe
872 * @param fulfilled  function to be called with the fulfilled value
873 * @param rejected   function to be called with the rejection exception
874 * @param progressed function to be called on any progress notifications
875 * @return promise for the return value from the invoked callback
876 */
877Q.when = when;
878function when(value, fulfilled, rejected, progressed) {
879    return Q(value).then(fulfilled, rejected, progressed);
880}
881
882Promise.prototype.thenResolve = function (value) {
883    return this.then(function () { return value; });
884};
885
886Q.thenResolve = function (promise, value) {
887    return Q(promise).thenResolve(value);
888};
889
890Promise.prototype.thenReject = function (reason) {
891    return this.then(function () { throw reason; });
892};
893
894Q.thenReject = function (promise, reason) {
895    return Q(promise).thenReject(reason);
896};
897
898/**
899 * If an object is not a promise, it is as "near" as possible.
900 * If a promise is rejected, it is as "near" as possible too.
901 * If it’s a fulfilled promise, the fulfillment value is nearer.
902 * If it’s a deferred promise and the deferred has been resolved, the
903 * resolution is "nearer".
904 * @param object
905 * @returns most resolved (nearest) form of the object
906 */
907
908// XXX should we re-do this?
909Q.nearer = nearer;
910function nearer(value) {
911    if (isPromise(value)) {
912        var inspected = value.inspect();
913        if (inspected.state === "fulfilled") {
914            return inspected.value;
915        }
916    }
917    return value;
918}
919
920/**
921 * @returns whether the given object is a promise.
922 * Otherwise it is a fulfilled value.
923 */
924Q.isPromise = isPromise;
925function isPromise(object) {
926    return isObject(object) &&
927        typeof object.promiseDispatch === "function" &&
928        typeof object.inspect === "function";
929}
930
931Q.isPromiseAlike = isPromiseAlike;
932function isPromiseAlike(object) {
933    return isObject(object) && typeof object.then === "function";
934}
935
936/**
937 * @returns whether the given object is a pending promise, meaning not
938 * fulfilled or rejected.
939 */
940Q.isPending = isPending;
941function isPending(object) {
942    return isPromise(object) && object.inspect().state === "pending";
943}
944
945Promise.prototype.isPending = function () {
946    return this.inspect().state === "pending";
947};
948
949/**
950 * @returns whether the given object is a value or fulfilled
951 * promise.
952 */
953Q.isFulfilled = isFulfilled;
954function isFulfilled(object) {
955    return !isPromise(object) || object.inspect().state === "fulfilled";
956}
957
958Promise.prototype.isFulfilled = function () {
959    return this.inspect().state === "fulfilled";
960};
961
962/**
963 * @returns whether the given object is a rejected promise.
964 */
965Q.isRejected = isRejected;
966function isRejected(object) {
967    return isPromise(object) && object.inspect().state === "rejected";
968}
969
970Promise.prototype.isRejected = function () {
971    return this.inspect().state === "rejected";
972};
973
974//// BEGIN UNHANDLED REJECTION TRACKING
975
976// This promise library consumes exceptions thrown in handlers so they can be
977// handled by a subsequent promise.  The exceptions get added to this array when
978// they are created, and removed when they are handled.  Note that in ES6 or
979// shimmed environments, this would naturally be a `Set`.
980var unhandledReasons = [];
981var unhandledRejections = [];
982var unhandledReasonsDisplayed = false;
983var trackUnhandledRejections = true;
984function displayUnhandledReasons() {
985    if (
986        !unhandledReasonsDisplayed &&
987        typeof window !== "undefined" &&
988        !window.Touch &&
989        window.console
990    ) {
991        console.warn("[Q] Unhandled rejection reasons (should be empty):",
992                     unhandledReasons);
993    }
994
995    unhandledReasonsDisplayed = true;
996}
997
998function logUnhandledReasons() {
999    for (var i = 0; i < unhandledReasons.length; i++) {
1000        var reason = unhandledReasons[i];
1001        console.warn("Unhandled rejection reason:", reason);
1002    }
1003}
1004
1005function resetUnhandledRejections() {
1006    unhandledReasons.length = 0;
1007    unhandledRejections.length = 0;
1008    unhandledReasonsDisplayed = false;
1009
1010    if (!trackUnhandledRejections) {
1011        trackUnhandledRejections = true;
1012
1013        // Show unhandled rejection reasons if Node exits without handling an
1014        // outstanding rejection.  (Note that Browserify presently produces a
1015        // `process` global without the `EventEmitter` `on` method.)
1016        if (typeof process !== "undefined" && process.on) {
1017            process.on("exit", logUnhandledReasons);
1018        }
1019    }
1020}
1021
1022function trackRejection(promise, reason) {
1023    if (!trackUnhandledRejections) {
1024        return;
1025    }
1026
1027    unhandledRejections.push(promise);
1028    if (reason && typeof reason.stack !== "undefined") {
1029        unhandledReasons.push(reason.stack);
1030    } else {
1031        unhandledReasons.push("(no stack) " + reason);
1032    }
1033    displayUnhandledReasons();
1034}
1035
1036function untrackRejection(promise) {
1037    if (!trackUnhandledRejections) {
1038        return;
1039    }
1040
1041    var at = array_indexOf(unhandledRejections, promise);
1042    if (at !== -1) {
1043        unhandledRejections.splice(at, 1);
1044        unhandledReasons.splice(at, 1);
1045    }
1046}
1047
1048Q.resetUnhandledRejections = resetUnhandledRejections;
1049
1050Q.getUnhandledReasons = function () {
1051    // Make a copy so that consumers can't interfere with our internal state.
1052    return unhandledReasons.slice();
1053};
1054
1055Q.stopUnhandledRejectionTracking = function () {
1056    resetUnhandledRejections();
1057    if (typeof process !== "undefined" && process.on) {
1058        process.removeListener("exit", logUnhandledReasons);
1059    }
1060    trackUnhandledRejections = false;
1061};
1062
1063resetUnhandledRejections();
1064
1065//// END UNHANDLED REJECTION TRACKING
1066
1067/**
1068 * Constructs a rejected promise.
1069 * @param reason value describing the failure
1070 */
1071Q.reject = reject;
1072function reject(reason) {
1073    var rejection = Promise({
1074        "when": function (rejected) {
1075            // note that the error has been handled
1076            if (rejected) {
1077                untrackRejection(this);
1078            }
1079            return rejected ? rejected(reason) : this;
1080        }
1081    }, function fallback() {
1082        return this;
1083    }, function inspect() {
1084        return { state: "rejected", reason: reason };
1085    });
1086
1087    // Note that the reason has not been handled.
1088    trackRejection(rejection, reason);
1089
1090    return rejection;
1091}
1092
1093/**
1094 * Constructs a fulfilled promise for an immediate reference.
1095 * @param value immediate reference
1096 */
1097Q.fulfill = fulfill;
1098function fulfill(value) {
1099    return Promise({
1100        "when": function () {
1101            return value;
1102        },
1103        "get": function (name) {
1104            return value[name];
1105        },
1106        "set": function (name, rhs) {
1107            value[name] = rhs;
1108        },
1109        "delete": function (name) {
1110            delete value[name];
1111        },
1112        "post": function (name, args) {
1113            // Mark Miller proposes that post with no name should apply a
1114            // promised function.
1115            if (name === null || name === void 0) {
1116                return value.apply(void 0, args);
1117            } else {
1118                return value[name].apply(value, args);
1119            }
1120        },
1121        "apply": function (thisp, args) {
1122            return value.apply(thisp, args);
1123        },
1124        "keys": function () {
1125            return object_keys(value);
1126        }
1127    }, void 0, function inspect() {
1128        return { state: "fulfilled", value: value };
1129    });
1130}
1131
1132/**
1133 * Converts thenables to Q promises.
1134 * @param promise thenable promise
1135 * @returns a Q promise
1136 */
1137function coerce(promise) {
1138    var deferred = defer();
1139    nextTick(function () {
1140        try {
1141            promise.then(deferred.resolve, deferred.reject, deferred.notify);
1142        } catch (exception) {
1143            deferred.reject(exception);
1144        }
1145    });
1146    return deferred.promise;
1147}
1148
1149/**
1150 * Annotates an object such that it will never be
1151 * transferred away from this process over any promise
1152 * communication channel.
1153 * @param object
1154 * @returns promise a wrapping of that object that
1155 * additionally responds to the "isDef" message
1156 * without a rejection.
1157 */
1158Q.master = master;
1159function master(object) {
1160    return Promise({
1161        "isDef": function () {}
1162    }, function fallback(op, args) {
1163        return dispatch(object, op, args);
1164    }, function () {
1165        return Q(object).inspect();
1166    });
1167}
1168
1169/**
1170 * Spreads the values of a promised array of arguments into the
1171 * fulfillment callback.
1172 * @param fulfilled callback that receives variadic arguments from the
1173 * promised array
1174 * @param rejected callback that receives the exception if the promise
1175 * is rejected.
1176 * @returns a promise for the return value or thrown exception of
1177 * either callback.
1178 */
1179Q.spread = spread;
1180function spread(value, fulfilled, rejected) {
1181    return Q(value).spread(fulfilled, rejected);
1182}
1183
1184Promise.prototype.spread = function (fulfilled, rejected) {
1185    return this.all().then(function (array) {
1186        return fulfilled.apply(void 0, array);
1187    }, rejected);
1188};
1189
1190/**
1191 * The async function is a decorator for generator functions, turning
1192 * them into asynchronous generators.  Although generators are only part
1193 * of the newest ECMAScript 6 drafts, this code does not cause syntax
1194 * errors in older engines.  This code should continue to work and will
1195 * in fact improve over time as the language improves.
1196 *
1197 * ES6 generators are currently part of V8 version 3.19 with the
1198 * --harmony-generators runtime flag enabled.  SpiderMonkey has had them
1199 * for longer, but under an older Python-inspired form.  This function
1200 * works on both kinds of generators.
1201 *
1202 * Decorates a generator function such that:
1203 *  - it may yield promises
1204 *  - execution will continue when that promise is fulfilled
1205 *  - the value of the yield expression will be the fulfilled value
1206 *  - it returns a promise for the return value (when the generator
1207 *    stops iterating)
1208 *  - the decorated function returns a promise for the return value
1209 *    of the generator or the first rejected promise among those
1210 *    yielded.
1211 *  - if an error is thrown in the generator, it propagates through
1212 *    every following yield until it is caught, or until it escapes
1213 *    the generator function altogether, and is translated into a
1214 *    rejection for the promise returned by the decorated generator.
1215 */
1216Q.async = async;
1217function async(makeGenerator) {
1218    return function () {
1219        // when verb is "send", arg is a value
1220        // when verb is "throw", arg is an exception
1221        function continuer(verb, arg) {
1222            var result;
1223            if (hasES6Generators) {
1224                try {
1225                    result = generator[verb](arg);
1226                } catch (exception) {
1227                    return reject(exception);
1228                }
1229                if (result.done) {
1230                    return result.value;
1231                } else {
1232                    return when(result.value, callback, errback);
1233                }
1234            } else {
1235                // FIXME: Remove this case when SM does ES6 generators.
1236                try {
1237                    result = generator[verb](arg);
1238                } catch (exception) {
1239                    if (isStopIteration(exception)) {
1240                        return exception.value;
1241                    } else {
1242                        return reject(exception);
1243                    }
1244                }
1245                return when(result, callback, errback);
1246            }
1247        }
1248        var generator = makeGenerator.apply(this, arguments);
1249        var callback = continuer.bind(continuer, "next");
1250        var errback = continuer.bind(continuer, "throw");
1251        return callback();
1252    };
1253}
1254
1255/**
1256 * The spawn function is a small wrapper around async that immediately
1257 * calls the generator and also ends the promise chain, so that any
1258 * unhandled errors are thrown instead of forwarded to the error
1259 * handler. This is useful because it's extremely common to run
1260 * generators at the top-level to work with libraries.
1261 */
1262Q.spawn = spawn;
1263function spawn(makeGenerator) {
1264    Q.done(Q.async(makeGenerator)());
1265}
1266
1267// FIXME: Remove this interface once ES6 generators are in SpiderMonkey.
1268/**
1269 * Throws a ReturnValue exception to stop an asynchronous generator.
1270 *
1271 * This interface is a stop-gap measure to support generator return
1272 * values in older Firefox/SpiderMonkey.  In browsers that support ES6
1273 * generators like Chromium 29, just use "return" in your generator
1274 * functions.
1275 *
1276 * @param value the return value for the surrounding generator
1277 * @throws ReturnValue exception with the value.
1278 * @example
1279 * // ES6 style
1280 * Q.async(function* () {
1281 *      var foo = yield getFooPromise();
1282 *      var bar = yield getBarPromise();
1283 *      return foo + bar;
1284 * })
1285 * // Older SpiderMonkey style
1286 * Q.async(function () {
1287 *      var foo = yield getFooPromise();
1288 *      var bar = yield getBarPromise();
1289 *      Q.return(foo + bar);
1290 * })
1291 */
1292Q["return"] = _return;
1293function _return(value) {
1294    throw new QReturnValue(value);
1295}
1296
1297/**
1298 * The promised function decorator ensures that any promise arguments
1299 * are settled and passed as values (`this` is also settled and passed
1300 * as a value).  It will also ensure that the result of a function is
1301 * always a promise.
1302 *
1303 * @example
1304 * var add = Q.promised(function (a, b) {
1305 *     return a + b;
1306 * });
1307 * add(Q(a), Q(B));
1308 *
1309 * @param {function} callback The function to decorate
1310 * @returns {function} a function that has been decorated.
1311 */
1312Q.promised = promised;
1313function promised(callback) {
1314    return function () {
1315        return spread([this, all(arguments)], function (self, args) {
1316            return callback.apply(self, args);
1317        });
1318    };
1319}
1320
1321/**
1322 * sends a message to a value in a future turn
1323 * @param object* the recipient
1324 * @param op the name of the message operation, e.g., "when",
1325 * @param args further arguments to be forwarded to the operation
1326 * @returns result {Promise} a promise for the result of the operation
1327 */
1328Q.dispatch = dispatch;
1329function dispatch(object, op, args) {
1330    return Q(object).dispatch(op, args);
1331}
1332
1333Promise.prototype.dispatch = function (op, args) {
1334    var self = this;
1335    var deferred = defer();
1336    nextTick(function () {
1337        self.promiseDispatch(deferred.resolve, op, args);
1338    });
1339    return deferred.promise;
1340};
1341
1342/**
1343 * Gets the value of a property in a future turn.
1344 * @param object    promise or immediate reference for target object
1345 * @param name      name of property to get
1346 * @return promise for the property value
1347 */
1348Q.get = function (object, key) {
1349    return Q(object).dispatch("get", [key]);
1350};
1351
1352Promise.prototype.get = function (key) {
1353    return this.dispatch("get", [key]);
1354};
1355
1356/**
1357 * Sets the value of a property in a future turn.
1358 * @param object    promise or immediate reference for object object
1359 * @param name      name of property to set
1360 * @param value     new value of property
1361 * @return promise for the return value
1362 */
1363Q.set = function (object, key, value) {
1364    return Q(object).dispatch("set", [key, value]);
1365};
1366
1367Promise.prototype.set = function (key, value) {
1368    return this.dispatch("set", [key, value]);
1369};
1370
1371/**
1372 * Deletes a property in a future turn.
1373 * @param object    promise or immediate reference for target object
1374 * @param name      name of property to delete
1375 * @return promise for the return value
1376 */
1377Q.del = // XXX legacy
1378Q["delete"] = function (object, key) {
1379    return Q(object).dispatch("delete", [key]);
1380};
1381
1382Promise.prototype.del = // XXX legacy
1383Promise.prototype["delete"] = function (key) {
1384    return this.dispatch("delete", [key]);
1385};
1386
1387/**
1388 * Invokes a method in a future turn.
1389 * @param object    promise or immediate reference for target object
1390 * @param name      name of method to invoke
1391 * @param value     a value to post, typically an array of
1392 *                  invocation arguments for promises that
1393 *                  are ultimately backed with `resolve` values,
1394 *                  as opposed to those backed with URLs
1395 *                  wherein the posted value can be any
1396 *                  JSON serializable object.
1397 * @return promise for the return value
1398 */
1399// bound locally because it is used by other methods
1400Q.mapply = // XXX As proposed by "Redsandro"
1401Q.post = function (object, name, args) {
1402    return Q(object).dispatch("post", [name, args]);
1403};
1404
1405Promise.prototype.mapply = // XXX As proposed by "Redsandro"
1406Promise.prototype.post = function (name, args) {
1407    return this.dispatch("post", [name, args]);
1408};
1409
1410/**
1411 * Invokes a method in a future turn.
1412 * @param object    promise or immediate reference for target object
1413 * @param name      name of method to invoke
1414 * @param ...args   array of invocation arguments
1415 * @return promise for the return value
1416 */
1417Q.send = // XXX Mark Miller's proposed parlance
1418Q.mcall = // XXX As proposed by "Redsandro"
1419Q.invoke = function (object, name /*...args*/) {
1420    return Q(object).dispatch("post", [name, array_slice(arguments, 2)]);
1421};
1422
1423Promise.prototype.send = // XXX Mark Miller's proposed parlance
1424Promise.prototype.mcall = // XXX As proposed by "Redsandro"
1425Promise.prototype.invoke = function (name /*...args*/) {
1426    return this.dispatch("post", [name, array_slice(arguments, 1)]);
1427};
1428
1429/**
1430 * Applies the promised function in a future turn.
1431 * @param object    promise or immediate reference for target function
1432 * @param args      array of application arguments
1433 */
1434Q.fapply = function (object, args) {
1435    return Q(object).dispatch("apply", [void 0, args]);
1436};
1437
1438Promise.prototype.fapply = function (args) {
1439    return this.dispatch("apply", [void 0, args]);
1440};
1441
1442/**
1443 * Calls the promised function in a future turn.
1444 * @param object    promise or immediate reference for target function
1445 * @param ...args   array of application arguments
1446 */
1447Q["try"] =
1448Q.fcall = function (object /* ...args*/) {
1449    return Q(object).dispatch("apply", [void 0, array_slice(arguments, 1)]);
1450};
1451
1452Promise.prototype.fcall = function (/*...args*/) {
1453    return this.dispatch("apply", [void 0, array_slice(arguments)]);
1454};
1455
1456/**
1457 * Binds the promised function, transforming return values into a fulfilled
1458 * promise and thrown errors into a rejected one.
1459 * @param object    promise or immediate reference for target function
1460 * @param ...args   array of application arguments
1461 */
1462Q.fbind = function (object /*...args*/) {
1463    var promise = Q(object);
1464    var args = array_slice(arguments, 1);
1465    return function fbound() {
1466        return promise.dispatch("apply", [
1467            this,
1468            args.concat(array_slice(arguments))
1469        ]);
1470    };
1471};
1472Promise.prototype.fbind = function (/*...args*/) {
1473    var promise = this;
1474    var args = array_slice(arguments);
1475    return function fbound() {
1476        return promise.dispatch("apply", [
1477            this,
1478            args.concat(array_slice(arguments))
1479        ]);
1480    };
1481};
1482
1483/**
1484 * Requests the names of the owned properties of a promised
1485 * object in a future turn.
1486 * @param object    promise or immediate reference for target object
1487 * @return promise for the keys of the eventually settled object
1488 */
1489Q.keys = function (object) {
1490    return Q(object).dispatch("keys", []);
1491};
1492
1493Promise.prototype.keys = function () {
1494    return this.dispatch("keys", []);
1495};
1496
1497/**
1498 * Turns an array of promises into a promise for an array.  If any of
1499 * the promises gets rejected, the whole array is rejected immediately.
1500 * @param {Array*} an array (or promise for an array) of values (or
1501 * promises for values)
1502 * @returns a promise for an array of the corresponding values
1503 */
1504// By Mark Miller
1505// http://wiki.ecmascript.org/doku.php?id=strawman:concurrency&rev=1308776521#allfulfilled
1506Q.all = all;
1507function all(promises) {
1508    return when(promises, function (promises) {
1509        var countDown = 0;
1510        var deferred = defer();
1511        array_reduce(promises, function (undefined, promise, index) {
1512            var snapshot;
1513            if (
1514                isPromise(promise) &&
1515                (snapshot = promise.inspect()).state === "fulfilled"
1516            ) {
1517                promises[index] = snapshot.value;
1518            } else {
1519                ++countDown;
1520                when(
1521                    promise,
1522                    function (value) {
1523                        promises[index] = value;
1524                        if (--countDown === 0) {
1525                            deferred.resolve(promises);
1526                        }
1527                    },
1528                    deferred.reject,
1529                    function (progress) {
1530                        deferred.notify({ index: index, value: progress });
1531                    }
1532                );
1533            }
1534        }, void 0);
1535        if (countDown === 0) {
1536            deferred.resolve(promises);
1537        }
1538        return deferred.promise;
1539    });
1540}
1541
1542Promise.prototype.all = function () {
1543    return all(this);
1544};
1545
1546/**
1547 * Waits for all promises to be settled, either fulfilled or
1548 * rejected.  This is distinct from `all` since that would stop
1549 * waiting at the first rejection.  The promise returned by
1550 * `allResolved` will never be rejected.
1551 * @param promises a promise for an array (or an array) of promises
1552 * (or values)
1553 * @return a promise for an array of promises
1554 */
1555Q.allResolved = deprecate(allResolved, "allResolved", "allSettled");
1556function allResolved(promises) {
1557    return when(promises, function (promises) {
1558        promises = array_map(promises, Q);
1559        return when(all(array_map(promises, function (promise) {
1560            return when(promise, noop, noop);
1561        })), function () {
1562            return promises;
1563        });
1564    });
1565}
1566
1567Promise.prototype.allResolved = function () {
1568    return allResolved(this);
1569};
1570
1571/**
1572 * @see Promise#allSettled
1573 */
1574Q.allSettled = allSettled;
1575function allSettled(promises) {
1576    return Q(promises).allSettled();
1577}
1578
1579/**
1580 * Turns an array of promises into a promise for an array of their states (as
1581 * returned by `inspect`) when they have all settled.
1582 * @param {Array[Any*]} values an array (or promise for an array) of values (or
1583 * promises for values)
1584 * @returns {Array[State]} an array of states for the respective values.
1585 */
1586Promise.prototype.allSettled = function () {
1587    return this.then(function (promises) {
1588        return all(array_map(promises, function (promise) {
1589            promise = Q(promise);
1590            function regardless() {
1591                return promise.inspect();
1592            }
1593            return promise.then(regardless, regardless);
1594        }));
1595    });
1596};
1597
1598/**
1599 * Captures the failure of a promise, giving an oportunity to recover
1600 * with a callback.  If the given promise is fulfilled, the returned
1601 * promise is fulfilled.
1602 * @param {Any*} promise for something
1603 * @param {Function} callback to fulfill the returned promise if the
1604 * given promise is rejected
1605 * @returns a promise for the return value of the callback
1606 */
1607Q.fail = // XXX legacy
1608Q["catch"] = function (object, rejected) {
1609    return Q(object).then(void 0, rejected);
1610};
1611
1612Promise.prototype.fail = // XXX legacy
1613Promise.prototype["catch"] = function (rejected) {
1614    return this.then(void 0, rejected);
1615};
1616
1617/**
1618 * Attaches a listener that can respond to progress notifications from a
1619 * promise's originating deferred. This listener receives the exact arguments
1620 * passed to ``deferred.notify``.
1621 * @param {Any*} promise for something
1622 * @param {Function} callback to receive any progress notifications
1623 * @returns the given promise, unchanged
1624 */
1625Q.progress = progress;
1626function progress(object, progressed) {
1627    return Q(object).then(void 0, void 0, progressed);
1628}
1629
1630Promise.prototype.progress = function (progressed) {
1631    return this.then(void 0, void 0, progressed);
1632};
1633
1634/**
1635 * Provides an opportunity to observe the settling of a promise,
1636 * regardless of whether the promise is fulfilled or rejected.  Forwards
1637 * the resolution to the returned promise when the callback is done.
1638 * The callback can return a promise to defer completion.
1639 * @param {Any*} promise
1640 * @param {Function} callback to observe the resolution of the given
1641 * promise, takes no arguments.
1642 * @returns a promise for the resolution of the given promise when
1643 * ``fin`` is done.
1644 */
1645Q.fin = // XXX legacy
1646Q["finally"] = function (object, callback) {
1647    return Q(object)["finally"](callback);
1648};
1649
1650Promise.prototype.fin = // XXX legacy
1651Promise.prototype["finally"] = function (callback) {
1652    callback = Q(callback);
1653    return this.then(function (value) {
1654        return callback.fcall().then(function () {
1655            return value;
1656        });
1657    }, function (reason) {
1658        // TODO attempt to recycle the rejection with "this".
1659        return callback.fcall().then(function () {
1660            throw reason;
1661        });
1662    });
1663};
1664
1665/**
1666 * Terminates a chain of promises, forcing rejections to be
1667 * thrown as exceptions.
1668 * @param {Any*} promise at the end of a chain of promises
1669 * @returns nothing
1670 */
1671Q.done = function (object, fulfilled, rejected, progress) {
1672    return Q(object).done(fulfilled, rejected, progress);
1673};
1674
1675Promise.prototype.done = function (fulfilled, rejected, progress) {
1676    var onUnhandledError = function (error) {
1677        // forward to a future turn so that ``when``
1678        // does not catch it and turn it into a rejection.
1679        nextTick(function () {
1680            makeStackTraceLong(error, promise);
1681            if (Q.onerror) {
1682                Q.onerror(error);
1683            } else {
1684                throw error;
1685            }
1686        });
1687    };
1688
1689    // Avoid unnecessary `nextTick`ing via an unnecessary `when`.
1690    var promise = fulfilled || rejected || progress ?
1691        this.then(fulfilled, rejected, progress) :
1692        this;
1693
1694    if (typeof process === "object" && process && process.domain) {
1695        onUnhandledError = process.domain.bind(onUnhandledError);
1696    }
1697
1698    promise.then(void 0, onUnhandledError);
1699};
1700
1701/**
1702 * Causes a promise to be rejected if it does not get fulfilled before
1703 * some milliseconds time out.
1704 * @param {Any*} promise
1705 * @param {Number} milliseconds timeout
1706 * @param {String} custom error message (optional)
1707 * @returns a promise for the resolution of the given promise if it is
1708 * fulfilled before the timeout, otherwise rejected.
1709 */
1710Q.timeout = function (object, ms, message) {
1711    return Q(object).timeout(ms, message);
1712};
1713
1714Promise.prototype.timeout = function (ms, message) {
1715    var deferred = defer();
1716    var timeoutId = setTimeout(function () {
1717        deferred.reject(new Error(message || "Timed out after " + ms + " ms"));
1718    }, ms);
1719
1720    this.then(function (value) {
1721        clearTimeout(timeoutId);
1722        deferred.resolve(value);
1723    }, function (exception) {
1724        clearTimeout(timeoutId);
1725        deferred.reject(exception);
1726    }, deferred.notify);
1727
1728    return deferred.promise;
1729};
1730
1731/**
1732 * Returns a promise for the given value (or promised value), some
1733 * milliseconds after it resolved. Passes rejections immediately.
1734 * @param {Any*} promise
1735 * @param {Number} milliseconds
1736 * @returns a promise for the resolution of the given promise after milliseconds
1737 * time has elapsed since the resolution of the given promise.
1738 * If the given promise rejects, that is passed immediately.
1739 */
1740Q.delay = function (object, timeout) {
1741    if (timeout === void 0) {
1742        timeout = object;
1743        object = void 0;
1744    }
1745    return Q(object).delay(timeout);
1746};
1747
1748Promise.prototype.delay = function (timeout) {
1749    return this.then(function (value) {
1750        var deferred = defer();
1751        setTimeout(function () {
1752            deferred.resolve(value);
1753        }, timeout);
1754        return deferred.promise;
1755    });
1756};
1757
1758/**
1759 * Passes a continuation to a Node function, which is called with the given
1760 * arguments provided as an array, and returns a promise.
1761 *
1762 *      Q.nfapply(FS.readFile, [__filename])
1763 *      .then(function (content) {
1764 *      })
1765 *
1766 */
1767Q.nfapply = function (callback, args) {
1768    return Q(callback).nfapply(args);
1769};
1770
1771Promise.prototype.nfapply = function (args) {
1772    var deferred = defer();
1773    var nodeArgs = array_slice(args);
1774    nodeArgs.push(deferred.makeNodeResolver());
1775    this.fapply(nodeArgs).fail(deferred.reject);
1776    return deferred.promise;
1777};
1778
1779/**
1780 * Passes a continuation to a Node function, which is called with the given
1781 * arguments provided individually, and returns a promise.
1782 * @example
1783 * Q.nfcall(FS.readFile, __filename)
1784 * .then(function (content) {
1785 * })
1786 *
1787 */
1788Q.nfcall = function (callback /*...args*/) {
1789    var args = array_slice(arguments, 1);
1790    return Q(callback).nfapply(args);
1791};
1792
1793Promise.prototype.nfcall = function (/*...args*/) {
1794    var nodeArgs = array_slice(arguments);
1795    var deferred = defer();
1796    nodeArgs.push(deferred.makeNodeResolver());
1797    this.fapply(nodeArgs).fail(deferred.reject);
1798    return deferred.promise;
1799};
1800
1801/**
1802 * Wraps a NodeJS continuation passing function and returns an equivalent
1803 * version that returns a promise.
1804 * @example
1805 * Q.nfbind(FS.readFile, __filename)("utf-8")
1806 * .then(console.log)
1807 * .done()
1808 */
1809Q.nfbind =
1810Q.denodeify = function (callback /*...args*/) {
1811    var baseArgs = array_slice(arguments, 1);
1812    return function () {
1813        var nodeArgs = baseArgs.concat(array_slice(arguments));
1814        var deferred = defer();
1815        nodeArgs.push(deferred.makeNodeResolver());
1816        Q(callback).fapply(nodeArgs).fail(deferred.reject);
1817        return deferred.promise;
1818    };
1819};
1820
1821Promise.prototype.nfbind =
1822Promise.prototype.denodeify = function (/*...args*/) {
1823    var args = array_slice(arguments);
1824    args.unshift(this);
1825    return Q.denodeify.apply(void 0, args);
1826};
1827
1828Q.nbind = function (callback, thisp /*...args*/) {
1829    var baseArgs = array_slice(arguments, 2);
1830    return function () {
1831        var nodeArgs = baseArgs.concat(array_slice(arguments));
1832        var deferred = defer();
1833        nodeArgs.push(deferred.makeNodeResolver());
1834        function bound() {
1835            return callback.apply(thisp, arguments);
1836        }
1837        Q(bound).fapply(nodeArgs).fail(deferred.reject);
1838        return deferred.promise;
1839    };
1840};
1841
1842Promise.prototype.nbind = function (/*thisp, ...args*/) {
1843    var args = array_slice(arguments, 0);
1844    args.unshift(this);
1845    return Q.nbind.apply(void 0, args);
1846};
1847
1848/**
1849 * Calls a method of a Node-style object that accepts a Node-style
1850 * callback with a given array of arguments, plus a provided callback.
1851 * @param object an object that has the named method
1852 * @param {String} name name of the method of object
1853 * @param {Array} args arguments to pass to the method; the callback
1854 * will be provided by Q and appended to these arguments.
1855 * @returns a promise for the value or error
1856 */
1857Q.nmapply = // XXX As proposed by "Redsandro"
1858Q.npost = function (object, name, args) {
1859    return Q(object).npost(name, args);
1860};
1861
1862Promise.prototype.nmapply = // XXX As proposed by "Redsandro"
1863Promise.prototype.npost = function (name, args) {
1864    var nodeArgs = array_slice(args || []);
1865    var deferred = defer();
1866    nodeArgs.push(deferred.makeNodeResolver());
1867    this.dispatch("post", [name, nodeArgs]).fail(deferred.reject);
1868    return deferred.promise;
1869};
1870
1871/**
1872 * Calls a method of a Node-style object that accepts a Node-style
1873 * callback, forwarding the given variadic arguments, plus a provided
1874 * callback argument.
1875 * @param object an object that has the named method
1876 * @param {String} name name of the method of object
1877 * @param ...args arguments to pass to the method; the callback will
1878 * be provided by Q and appended to these arguments.
1879 * @returns a promise for the value or error
1880 */
1881Q.nsend = // XXX Based on Mark Miller's proposed "send"
1882Q.nmcall = // XXX Based on "Redsandro's" proposal
1883Q.ninvoke = function (object, name /*...args*/) {
1884    var nodeArgs = array_slice(arguments, 2);
1885    var deferred = defer();
1886    nodeArgs.push(deferred.makeNodeResolver());
1887    Q(object).dispatch("post", [name, nodeArgs]).fail(deferred.reject);
1888    return deferred.promise;
1889};
1890
1891Promise.prototype.nsend = // XXX Based on Mark Miller's proposed "send"
1892Promise.prototype.nmcall = // XXX Based on "Redsandro's" proposal
1893Promise.prototype.ninvoke = function (name /*...args*/) {
1894    var nodeArgs = array_slice(arguments, 1);
1895    var deferred = defer();
1896    nodeArgs.push(deferred.makeNodeResolver());
1897    this.dispatch("post", [name, nodeArgs]).fail(deferred.reject);
1898    return deferred.promise;
1899};
1900
1901/**
1902 * If a function would like to support both Node continuation-passing-style and
1903 * promise-returning-style, it can end its internal promise chain with
1904 * `nodeify(nodeback)`, forwarding the optional nodeback argument.  If the user
1905 * elects to use a nodeback, the result will be sent there.  If they do not
1906 * pass a nodeback, they will receive the result promise.
1907 * @param object a result (or a promise for a result)
1908 * @param {Function} nodeback a Node.js-style callback
1909 * @returns either the promise or nothing
1910 */
1911Q.nodeify = nodeify;
1912function nodeify(object, nodeback) {
1913    return Q(object).nodeify(nodeback);
1914}
1915
1916Promise.prototype.nodeify = function (nodeback) {
1917    if (nodeback) {
1918        this.then(function (value) {
1919            nextTick(function () {
1920                nodeback(null, value);
1921            });
1922        }, function (error) {
1923            nextTick(function () {
1924                nodeback(error);
1925            });
1926        });
1927    } else {
1928        return this;
1929    }
1930};
1931
1932// All code before this point will be filtered from stack traces.
1933var qEndingLine = captureLine();
1934
1935return Q;
1936
1937});
Note: See TracBrowser for help on using the repository browser.