Bug 856410 - Implement futures - Part 4: Future.accept, Future.reject, Future.resolve. r=mounir
authorAndrea Marchesini <amarchesini@mozilla.com>
Tue, 11 Jun 2013 21:41:22 -0400
changeset 146220 9bcc6c50cd266000bceb38c454450bc57a6292cb
parent 146219 7c3bc1a19c7ab6bdb7d7fe0e81f9dea5612d8a45
child 146221 4fcb23be09100c46acc88fadd25075eb3c90334f
push id2697
push userbbajaj@mozilla.com
push dateMon, 05 Aug 2013 18:49:53 +0000
treeherdermozilla-beta@dfec938c7b63 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmounir
bugs856410
milestone24.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 856410 - Implement futures - Part 4: Future.accept, Future.reject, Future.resolve. r=mounir
dom/future/Future.cpp
dom/future/Future.h
dom/future/tests/test_future.html
dom/webidl/Future.webidl
--- a/dom/future/Future.cpp
+++ b/dom/future/Future.cpp
@@ -121,16 +121,50 @@ Future::Constructor(const GlobalObject& 
     Optional<JS::Handle<JS::Value> > value(aCx);
     aRv.StealJSException(aCx, &value.Value());
     future->mResolver->Reject(aCx, value);
   }
 
   return future.forget();
 }
 
+/* static */ already_AddRefed<Future>
+Future::Resolve(const GlobalObject& aGlobal, JSContext* aCx,
+                JS::Handle<JS::Value> aValue, ErrorResult& aRv)
+{
+  nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aGlobal.Get());
+  if (!window) {
+    aRv.Throw(NS_ERROR_UNEXPECTED);
+    return nullptr;
+  }
+
+  nsRefPtr<Future> future = new Future(window);
+
+  Optional<JS::Handle<JS::Value> > value(aCx, aValue);
+  future->mResolver->Resolve(aCx, value);
+  return future.forget();
+}
+
+/* static */ already_AddRefed<Future>
+Future::Reject(const GlobalObject& aGlobal, JSContext* aCx,
+               JS::Handle<JS::Value> aValue, ErrorResult& aRv)
+{
+  nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aGlobal.Get());
+  if (!window) {
+    aRv.Throw(NS_ERROR_UNEXPECTED);
+    return nullptr;
+  }
+
+  nsRefPtr<Future> future = new Future(window);
+
+  Optional<JS::Handle<JS::Value> > value(aCx, aValue);
+  future->mResolver->Reject(aCx, value);
+  return future.forget();
+}
+
 already_AddRefed<Future>
 Future::Then(AnyCallback* aResolveCallback, AnyCallback* aRejectCallback)
 {
   nsRefPtr<Future> future = new Future(GetParentObject());
 
   nsRefPtr<FutureCallback> resolveCb =
     FutureCallback::Factory(future->mResolver,
                             aResolveCallback,
--- a/dom/future/Future.h
+++ b/dom/future/Future.h
@@ -49,16 +49,24 @@ public:
 
   virtual JSObject*
   WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
 
   static already_AddRefed<Future>
   Constructor(const GlobalObject& aGlobal, JSContext* aCx, FutureInit& aInit,
               ErrorResult& aRv);
 
+  static already_AddRefed<Future>
+  Resolve(const GlobalObject& aGlobal, JSContext* aCx,
+          JS::Handle<JS::Value> aValue, ErrorResult& aRv);
+
+  static already_AddRefed<Future>
+  Reject(const GlobalObject& aGlobal, JSContext* aCx,
+         JS::Handle<JS::Value> aValue, ErrorResult& aRv);
+
   already_AddRefed<Future>
   Then(AnyCallback* aResolveCallback, AnyCallback* aRejectCallback);
 
   already_AddRefed<Future>
   Catch(AnyCallback* aRejectCallback);
 
   void Done(AnyCallback* aResolveCallback, AnyCallback* aRejectCallback);
 
--- a/dom/future/tests/test_future.html
+++ b/dom/future/tests/test_future.html
@@ -338,26 +338,60 @@ function futureLoop() {
   }).then(function(value) {
     is(value, 42, "Nested nested future is executed and then == 42");
     runTest();
   }, function(value) {
      ok(false, "This is wrong");
   });
 }
 
+function futureReject() {
+  var future = Future.reject(42).done(function(what) {
+    ok(false, "This should not be called");
+  }, function(what) {
+    is(what, 42, "Value == 42");
+    runTest();
+  });
+}
+
+function futureResolve() {
+  var future = Future.resolve(42).done(function(what) {
+    is(what, 42, "Value == 42");
+    runTest();
+  }, function() {
+    ok(false, "This should not be called");
+  });
+}
+
+function futureResolveNestedFuture() {
+  var future = Future.resolve(new Future(function(r) {
+    ok(true, "Nested future is executed");
+    r.resolve(42);
+  }, function() {
+    ok(false, "This should not be called");
+  })).done(function(what) {
+    is(what, 42, "Value == 42");
+    runTest();
+  }, function() {
+    ok(false, "This should not be called");
+  });
+}
+
 var tests = [ futureResolve, futureReject,
               futureException, futureGC, futureAsync,
               futureDoubleDone, futureDoneException,
               futureThenCatchDone, futureRejectThenCatchDone,
               futureRejectThenCatchDone2,
               futureRejectThenCatchExceptionDone,
               futureThenCatchOrderingResolve,
               futureThenCatchOrderingReject,
               futureNestedFuture, futureNestedNestedFuture,
-              futureWrongNestedFuture, futureLoop
+              futureWrongNestedFuture, futureLoop,
+              futureReject, futureResolve,
+              futureResolveNestedFuture,
             ];
 
 function runTest() {
   if (!tests.length) {
     SimpleTest.finish();
     return;
   }
 
--- a/dom/webidl/Future.webidl
+++ b/dom/webidl/Future.webidl
@@ -13,16 +13,22 @@ interface FutureResolver {
 };
 
 callback FutureInit = void (FutureResolver resolver);
 callback AnyCallback = any (optional any value);
 
 [Constructor(FutureInit init)]
 interface Future {
   // TODO: update this interface - bug 875289
+
+  [Creator, Throws]
+  static Future resolve(any value); // same as any(value)
+  [Creator, Throws]
+  static Future reject(any value);
+
   [Creator]
   Future then(optional AnyCallback? resolveCallback = null,
               optional AnyCallback? rejectCallback = null);
 
   [Creator]
   Future catch(optional AnyCallback? rejectCallback = null);
 
   void done(optional AnyCallback? resolveCallback = null,