| 486 | */ |
| 487 | Q.defer = defer; |
| 488 | function defer() { |
| 489 | // if "messages" is an "Array", that indicates that the promise has not yet |
| 490 | // been resolved. If it is "undefined", it has been resolved. Each |
| 491 | // element of the messages array is itself an array of complete arguments to |
| 492 | // forward to the resolved promise. We coerce the resolution value to a |
| 493 | // promise using the `resolve` function because it handles both fully |
| 494 | // non-thenable values and other thenables gracefully. |
| 495 | var messages = [], progressListeners = [], resolvedPromise; |
| 496 | |
| 497 | var deferred = object_create(defer.prototype); |
| 498 | var promise = object_create(Promise.prototype); |
| 499 | |
| 500 | promise.promiseDispatch = function (resolve, op, operands) { |
| 501 | var args = array_slice(arguments); |
| 502 | if (messages) { |
| 503 | messages.push(args); |
| 504 | if (op === "when" && operands[1]) { // progress operand |
| 505 | progressListeners.push(operands[1]); |
| 506 | } |
| 507 | } else { |
| 508 | nextTick(function () { |
| 509 | resolvedPromise.promiseDispatch.apply(resolvedPromise, args); |
| 510 | }); |
| 511 | } |
| 512 | }; |
| 513 | |
| 514 | // XXX deprecated |
| 515 | promise.valueOf = function () { |
| 516 | if (messages) { |
| 517 | return promise; |
| 518 | } |
| 519 | var nearerValue = nearer(resolvedPromise); |
| 520 | if (isPromise(nearerValue)) { |
| 521 | resolvedPromise = nearerValue; // shorten chain |
| 522 | } |
| 523 | return nearerValue; |
| 524 | }; |
| 525 | |
| 526 | promise.inspect = function () { |
| 527 | if (!resolvedPromise) { |
| 528 | return { state: "pending" }; |
| 529 | } |
| 530 | return resolvedPromise.inspect(); |
| 531 | }; |
| 532 | |
| 533 | if (Q.longStackSupport && hasStacks) { |
| 534 | try { |
| 535 | throw new Error(); |
| 536 | } catch (e) { |
| 537 | // NOTE: don't try to use `Error.captureStackTrace` or transfer the |
| 538 | // accessor around; that causes memory leaks as per GH-111. Just |
| 539 | // reify the stack trace as a string ASAP. |
| 540 | // |
| 541 | // At the same time, cut off the first line; it's always just |
| 542 | // "[object Promise]\n", as per the `toString`. |
| 543 | promise.stack = e.stack.substring(e.stack.indexOf("\n") + 1); |
| 544 | } |
| 545 | } |