Not logged in.  Login/Logout/Register | List snippets | | Create snippet | Upload image | Upload data

1937
LINES

< > BotCompany Repo | #1018989 // q.js

Document

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  
66  
var hasStacks = false;
67  
try {
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.
75  
var qStartingLine = captureLine();
76  
var qFileName;
77  
78  
// shims
79  
80  
// used for fallback in "allResolved"
81  
var noop = function () {};
82  
83  
// Use the fastest possible means to execute a task in a future turn
84  
// of the event loop.
85  
var 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
219  
var call = Function.call;
220  
function 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  
229  
var array_slice = uncurryThis(Array.prototype.slice);
230  
231  
var 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  
260  
var 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  
272  
var 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  
283  
var object_create = Object.create || function (prototype) {
284  
    function Type() { }
285  
    Type.prototype = prototype;
286  
    return new Type();
287  
};
288  
289  
var object_hasOwnProperty = uncurryThis(Object.prototype.hasOwnProperty);
290  
291  
var 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  
301  
var object_toString = uncurryThis(Object.prototype.toString);
302  
303  
function 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.
310  
function 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.
319  
var QReturnValue;
320  
if (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.
335  
var hasES6Generators;
336  
try {
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  
346  
var STACK_JUMP_SEPARATOR = "From previous event:";
347  
348  
function 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  
371  
function 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  
384  
function isNodeFrame(stackLine) {
385  
    return stackLine.indexOf("(module.js:") !== -1 ||
386  
           stackLine.indexOf("(node.js:") !== -1;
387  
}
388  
389  
function 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  
410  
function 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
427  
function 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  
447  
function 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  
 */
466  
function 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  
}
481  
Q.resolve = Q;
482  
483  
/**
484  
 * Performs a task in a future turn of the event loop.
485  
 * @param {Function} task
486  
 */
487  
Q.nextTick = nextTick;
488  
489  
/**
490  
 * Controls whether or not long stack traces will be on
491  
 */
492  
Q.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  
 */
504  
Q.defer = defer;
505  
function 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  
 */
625  
defer.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  
 */
644  
Q.promise = promise;
645  
function 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.
661  
Q.passByCopy = function (object) {
662  
    //freeze(object);
663  
    //passByCopies.set(object, true);
664  
    return object;
665  
};
666  
667  
Promise.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  
 */
682  
Q.join = function (x, y) {
683  
    return Q(x).join(y);
684  
};
685  
686  
Promise.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  
 */
702  
Q.race = race;
703  
function 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  
716  
Promise.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  
 */
731  
Q.makePromise = Promise;
732  
function 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  
786  
Promise.prototype.toString = function () {
787  
    return "[object Promise]";
788  
};
789  
790  
Promise.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  
 */
877  
Q.when = when;
878  
function when(value, fulfilled, rejected, progressed) {
879  
    return Q(value).then(fulfilled, rejected, progressed);
880  
}
881  
882  
Promise.prototype.thenResolve = function (value) {
883  
    return this.then(function () { return value; });
884  
};
885  
886  
Q.thenResolve = function (promise, value) {
887  
    return Q(promise).thenResolve(value);
888  
};
889  
890  
Promise.prototype.thenReject = function (reason) {
891  
    return this.then(function () { throw reason; });
892  
};
893  
894  
Q.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?
909  
Q.nearer = nearer;
910  
function 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  
 */
924  
Q.isPromise = isPromise;
925  
function isPromise(object) {
926  
    return isObject(object) &&
927  
        typeof object.promiseDispatch === "function" &&
928  
        typeof object.inspect === "function";
929  
}
930  
931  
Q.isPromiseAlike = isPromiseAlike;
932  
function 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  
 */
940  
Q.isPending = isPending;
941  
function isPending(object) {
942  
    return isPromise(object) && object.inspect().state === "pending";
943  
}
944  
945  
Promise.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  
 */
953  
Q.isFulfilled = isFulfilled;
954  
function isFulfilled(object) {
955  
    return !isPromise(object) || object.inspect().state === "fulfilled";
956  
}
957  
958  
Promise.prototype.isFulfilled = function () {
959  
    return this.inspect().state === "fulfilled";
960  
};
961  
962  
/**
963  
 * @returns whether the given object is a rejected promise.
964  
 */
965  
Q.isRejected = isRejected;
966  
function isRejected(object) {
967  
    return isPromise(object) && object.inspect().state === "rejected";
968  
}
969  
970  
Promise.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`.
980  
var unhandledReasons = [];
981  
var unhandledRejections = [];
982  
var unhandledReasonsDisplayed = false;
983  
var trackUnhandledRejections = true;
984  
function 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  
998  
function 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  
1005  
function 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  
1022  
function 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  
1036  
function 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  
1048  
Q.resetUnhandledRejections = resetUnhandledRejections;
1049  
1050  
Q.getUnhandledReasons = function () {
1051  
    // Make a copy so that consumers can't interfere with our internal state.
1052  
    return unhandledReasons.slice();
1053  
};
1054  
1055  
Q.stopUnhandledRejectionTracking = function () {
1056  
    resetUnhandledRejections();
1057  
    if (typeof process !== "undefined" && process.on) {
1058  
        process.removeListener("exit", logUnhandledReasons);
1059  
    }
1060  
    trackUnhandledRejections = false;
1061  
};
1062  
1063  
resetUnhandledRejections();
1064  
1065  
//// END UNHANDLED REJECTION TRACKING
1066  
1067  
/**
1068  
 * Constructs a rejected promise.
1069  
 * @param reason value describing the failure
1070  
 */
1071  
Q.reject = reject;
1072  
function 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  
 */
1097  
Q.fulfill = fulfill;
1098  
function 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  
 */
1137  
function 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  
 */
1158  
Q.master = master;
1159  
function 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  
 */
1179  
Q.spread = spread;
1180  
function spread(value, fulfilled, rejected) {
1181  
    return Q(value).spread(fulfilled, rejected);
1182  
}
1183  
1184  
Promise.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  
 */
1216  
Q.async = async;
1217  
function 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  
 */
1262  
Q.spawn = spawn;
1263  
function 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  
 */
1292  
Q["return"] = _return;
1293  
function _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  
 */
1312  
Q.promised = promised;
1313  
function 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  
 */
1328  
Q.dispatch = dispatch;
1329  
function dispatch(object, op, args) {
1330  
    return Q(object).dispatch(op, args);
1331  
}
1332  
1333  
Promise.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  
 */
1348  
Q.get = function (object, key) {
1349  
    return Q(object).dispatch("get", [key]);
1350  
};
1351  
1352  
Promise.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  
 */
1363  
Q.set = function (object, key, value) {
1364  
    return Q(object).dispatch("set", [key, value]);
1365  
};
1366  
1367  
Promise.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  
 */
1377  
Q.del = // XXX legacy
1378  
Q["delete"] = function (object, key) {
1379  
    return Q(object).dispatch("delete", [key]);
1380  
};
1381  
1382  
Promise.prototype.del = // XXX legacy
1383  
Promise.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
1400  
Q.mapply = // XXX As proposed by "Redsandro"
1401  
Q.post = function (object, name, args) {
1402  
    return Q(object).dispatch("post", [name, args]);
1403  
};
1404  
1405  
Promise.prototype.mapply = // XXX As proposed by "Redsandro"
1406  
Promise.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  
 */
1417  
Q.send = // XXX Mark Miller's proposed parlance
1418  
Q.mcall = // XXX As proposed by "Redsandro"
1419  
Q.invoke = function (object, name /*...args*/) {
1420  
    return Q(object).dispatch("post", [name, array_slice(arguments, 2)]);
1421  
};
1422  
1423  
Promise.prototype.send = // XXX Mark Miller's proposed parlance
1424  
Promise.prototype.mcall = // XXX As proposed by "Redsandro"
1425  
Promise.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  
 */
1434  
Q.fapply = function (object, args) {
1435  
    return Q(object).dispatch("apply", [void 0, args]);
1436  
};
1437  
1438  
Promise.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  
 */
1447  
Q["try"] =
1448  
Q.fcall = function (object /* ...args*/) {
1449  
    return Q(object).dispatch("apply", [void 0, array_slice(arguments, 1)]);
1450  
};
1451  
1452  
Promise.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  
 */
1462  
Q.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  
};
1472  
Promise.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  
 */
1489  
Q.keys = function (object) {
1490  
    return Q(object).dispatch("keys", []);
1491  
};
1492  
1493  
Promise.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
1506  
Q.all = all;
1507  
function 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  
1542  
Promise.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  
 */
1555  
Q.allResolved = deprecate(allResolved, "allResolved", "allSettled");
1556  
function 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  
1567  
Promise.prototype.allResolved = function () {
1568  
    return allResolved(this);
1569  
};
1570  
1571  
/**
1572  
 * @see Promise#allSettled
1573  
 */
1574  
Q.allSettled = allSettled;
1575  
function 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  
 */
1586  
Promise.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  
 */
1607  
Q.fail = // XXX legacy
1608  
Q["catch"] = function (object, rejected) {
1609  
    return Q(object).then(void 0, rejected);
1610  
};
1611  
1612  
Promise.prototype.fail = // XXX legacy
1613  
Promise.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  
 */
1625  
Q.progress = progress;
1626  
function progress(object, progressed) {
1627  
    return Q(object).then(void 0, void 0, progressed);
1628  
}
1629  
1630  
Promise.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  
 */
1645  
Q.fin = // XXX legacy
1646  
Q["finally"] = function (object, callback) {
1647  
    return Q(object)["finally"](callback);
1648  
};
1649  
1650  
Promise.prototype.fin = // XXX legacy
1651  
Promise.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  
 */
1671  
Q.done = function (object, fulfilled, rejected, progress) {
1672  
    return Q(object).done(fulfilled, rejected, progress);
1673  
};
1674  
1675  
Promise.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  
 */
1710  
Q.timeout = function (object, ms, message) {
1711  
    return Q(object).timeout(ms, message);
1712  
};
1713  
1714  
Promise.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  
 */
1740  
Q.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  
1748  
Promise.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  
 */
1767  
Q.nfapply = function (callback, args) {
1768  
    return Q(callback).nfapply(args);
1769  
};
1770  
1771  
Promise.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  
 */
1788  
Q.nfcall = function (callback /*...args*/) {
1789  
    var args = array_slice(arguments, 1);
1790  
    return Q(callback).nfapply(args);
1791  
};
1792  
1793  
Promise.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  
 */
1809  
Q.nfbind =
1810  
Q.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  
1821  
Promise.prototype.nfbind =
1822  
Promise.prototype.denodeify = function (/*...args*/) {
1823  
    var args = array_slice(arguments);
1824  
    args.unshift(this);
1825  
    return Q.denodeify.apply(void 0, args);
1826  
};
1827  
1828  
Q.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  
1842  
Promise.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  
 */
1857  
Q.nmapply = // XXX As proposed by "Redsandro"
1858  
Q.npost = function (object, name, args) {
1859  
    return Q(object).npost(name, args);
1860  
};
1861  
1862  
Promise.prototype.nmapply = // XXX As proposed by "Redsandro"
1863  
Promise.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  
 */
1881  
Q.nsend = // XXX Based on Mark Miller's proposed "send"
1882  
Q.nmcall = // XXX Based on "Redsandro's" proposal
1883  
Q.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  
1891  
Promise.prototype.nsend = // XXX Based on Mark Miller's proposed "send"
1892  
Promise.prototype.nmcall = // XXX Based on "Redsandro's" proposal
1893  
Promise.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  
 */
1911  
Q.nodeify = nodeify;
1912  
function nodeify(object, nodeback) {
1913  
    return Q(object).nodeify(nodeback);
1914  
}
1915  
1916  
Promise.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.
1933  
var qEndingLine = captureLine();
1934  
1935  
return Q;
1936  
1937  
});

Author comment

From http://tantaman.github.io/LargeLocalStorage/bower_components/q/q.js

download  show line numbers   

Travelled to 12 computer(s): aoiabmzegqzx, bhatertpkbcr, cbybwowwnfue, gwrvuhgaqvyk, irmadwmeruwu, ishqpsrjomds, lpdgvwnxivlt, mqqgnosmbjvj, pyentgdyhuwx, pzhvpgtvlbxg, tvejysmllsmz, vouqrxazstgt

No comments. add comment

Snippet ID: #1018989
Snippet name: q.js
Eternal ID of this version: #1018989/1
Text MD5: de7d0e89ff04793eb1575a968be7e0a2
Author: stefan
Category: javax / web
Type: Document
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2018-10-19 16:39:57
Source code size: 60990 bytes / 1937 lines
Pitched / IR pitched: No / No
Views / Downloads: 311 / 100
Referenced in: [show references]