Index: chrome/browser/resources/google_now/common_test_util.js |
diff --git a/chrome/browser/resources/google_now/common_test_util.js b/chrome/browser/resources/google_now/common_test_util.js |
index 66d65f49d9efa9d3f0f77aa6db76165f119cf9c1..c090c9545bb0e6fdf4c1ee68e712ca7faf98745f 100644 |
--- a/chrome/browser/resources/google_now/common_test_util.js |
+++ b/chrome/browser/resources/google_now/common_test_util.js |
@@ -78,36 +78,70 @@ function getMockHandlerContainer(eventIdentifier) { |
* As a result, we can't use built-in JS promises since they run asynchronously. |
* Instead of mocking all possible calls to promises, a skeleton |
* implementation is provided to get the tests to pass. |
+ * |
+ * This functionality and logic originates from ECMAScript 6's spec of promises. |
*/ |
var Promise = function() { |
function PromisePrototypeObject(asyncTask) { |
- var result; |
- var resolved = false; |
- asyncTask( |
- function(asyncResult) { |
- result = asyncResult; |
- resolved = true; |
- }, |
- function(asyncFailureResult) { |
- result = asyncFailureResult; |
- resolved = false; |
- }); |
+ function isThenable(value) { |
+ return (typeof value === 'object') && isCallable(value.then); |
+ } |
- function then(callback) { |
- if (resolved) { |
- callback.call(null, result); |
+ function isCallable(value) { |
+ return typeof value === 'function'; |
+ } |
+ |
+ function callResolveRejectFunc(func) { |
+ var funcResult; |
+ var funcResolved = false; |
+ func( |
+ function(resolveResult) { |
+ funcResult = resolveResult; |
+ funcResolved = true; |
+ }, |
+ function(rejectResult) { |
+ funcResult = rejectResult; |
+ funcResolved = false; |
+ }); |
+ return { result: funcResult, resolved: funcResolved }; |
+ } |
+ |
+ function then(onResolve, onReject) { |
+ var resolutionHandler = |
+ isCallable(onResolve) ? onResolve : function() { return result; }; |
+ var rejectionHandler = |
+ isCallable(onReject) ? onReject : function() { return result; }; |
+ var handlerResult = |
+ resolved ? resolutionHandler(result) : rejectionHandler(result); |
+ var promiseResolved = resolved; |
+ if (isThenable(handlerResult)) { |
+ var resolveReject = callResolveRejectFunc(handlerResult.then); |
+ handlerResult = resolveReject.result; |
+ promiseResolved = resolveReject.resolved; |
+ } |
+ |
+ if (promiseResolved) { |
+ return Promise.resolve(handlerResult); |
+ } else { |
+ return Promise.reject(handlerResult); |
} |
- return this; |
} |
// Promises use the function name "catch" to call back error handlers. |
// We can't use "catch" since function or variable names cannot use the word |
// "catch". |
- function catchFunc(callback) { |
- if (!resolved) { |
- callback.call(null, result); |
- } |
- return this; |
+ function catchFunc(onRejected) { |
+ return this.then(undefined, onRejected); |
+ } |
+ |
+ var resolveReject = callResolveRejectFunc(asyncTask); |
+ var result = resolveReject.result; |
+ var resolved = resolveReject.resolved; |
+ |
+ if (isThenable(result)) { |
+ var thenResolveReject = callResolveRejectFunc(result.then); |
+ result = thenResolveReject.result; |
+ resolved = thenResolveReject.resolved; |
} |
return {then: then, catch: catchFunc, isPromise: true}; |
@@ -137,12 +171,19 @@ var Promise = function() { |
return promise; |
} |
+ function reject(value) { |
+ var promise = new PromisePrototypeObject(function(resolve, reject) { |
+ reject(value); |
+ }); |
+ return promise; |
+ } |
+ |
PromisePrototypeObject.all = all; |
PromisePrototypeObject.resolve = resolve; |
+ PromisePrototypeObject.reject = reject; |
return PromisePrototypeObject; |
}(); |
- |
/** |
* Sets up the test to expect a Chrome Local Storage call. |
* @param {Object} fixture Mock JS Test Object. |