UNPKG

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