From facbb77e6aa62ab30fe72f7536dfd456f51b01ff Mon Sep 17 00:00:00 2001 From: Kris Kowal Date: Thu, 23 Aug 2012 16:51:00 -0700 Subject: [PATCH] Break coercion cycles with cooperating promises Cooperating promise libraries must implement `valueOf` to extract the fulfillment value from a fulfilled promise (or return the selfsame promise for an unresolved or rejected promise). This breaks cycles in coercion, where one library uses `resolve` to coerce a foreign promise to a local promise, which would in turn call `then` on the foreign promise, which would in turn attempt to coerce the promise with its own `resolve`, which would then in turn call `then` on our coerced promise, ad nauseum. Fixes #106. --- q.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/q.js b/q.js index d509990d..8268a703 100644 --- a/q.js +++ b/q.js @@ -775,6 +775,15 @@ function resolve(object) { if (isPromise(object)) { return object; } + // In order to break infinite recursion or loops between `then` and + // `resolve`, it is necessary to attempt to extract fulfilled values + // out of foreign promise implementations before attempting to wrap + // them as unresolved promises. It is my hope that other + // implementations will implement `valueOf` to synchronously extract + // the fulfillment value from their fulfilled promises. If the + // other promise library does not implement `valueOf`, the + // implementations on primordial prototypes are harmless. + object = valueOf(object); // assimilate thenables, CommonJS/Promises/A if (object && typeof object.then === "function") { var deferred = defer();