Bug 882076 - C++ callbacks to DOM Promises. r=baku,mccr8
authorNikhil Marathe <nsm.nikhil@gmail.com>
Tue, 19 Nov 2013 10:43:51 -0800
changeset 171001 a6bb8146e7bcb174224fab5eccf34b819250e4ef
parent 171000 66ab5cb18c25043aa7fd299e072daf682d6b2463
child 171002 4f75c9e6e793460054c6213e75bb9a9a77f55137
push id3224
push userlsblakk@mozilla.com
push dateTue, 04 Feb 2014 01:06:49 +0000
treeherdermozilla-beta@60c04d0987f1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbaku, mccr8
bugs882076
milestone28.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 882076 - C++ callbacks to DOM Promises. r=baku,mccr8
dom/promise/Promise.cpp
dom/promise/Promise.h
dom/promise/PromiseCallback.cpp
dom/promise/PromiseCallback.h
dom/promise/PromiseNativeHandler.h
dom/promise/moz.build
--- a/dom/promise/Promise.cpp
+++ b/dom/promise/Promise.cpp
@@ -6,27 +6,30 @@
 
 #include "mozilla/dom/Promise.h"
 
 #include "jsfriendapi.h"
 #include "mozilla/dom/OwningNonNull.h"
 #include "mozilla/dom/PromiseBinding.h"
 #include "mozilla/Preferences.h"
 #include "PromiseCallback.h"
+#include "PromiseNativeHandler.h"
 #include "nsContentUtils.h"
 #include "nsPIDOMWindow.h"
 #include "WorkerPrivate.h"
 #include "nsJSPrincipals.h"
 #include "nsJSUtils.h"
 #include "nsPIDOMWindow.h"
 #include "nsJSEnvironment.h"
 
 namespace mozilla {
 namespace dom {
 
+NS_IMPL_ISUPPORTS0(PromiseNativeHandler)
+
 // PromiseTask
 
 // This class processes the promise's callbacks with promise's result.
 class PromiseTask MOZ_FINAL : public nsRunnable
 {
 public:
   PromiseTask(Promise* aPromise)
     : mPromise(aPromise)
@@ -375,16 +378,28 @@ Promise::Then(const Optional<OwningNonNu
 already_AddRefed<Promise>
 Promise::Catch(const Optional<OwningNonNull<AnyCallback> >& aRejectCallback)
 {
   Optional<OwningNonNull<AnyCallback> > resolveCb;
   return Then(resolveCb, aRejectCallback);
 }
 
 void
+Promise::AppendNativeHandler(PromiseNativeHandler* aRunnable)
+{
+  nsRefPtr<PromiseCallback> resolveCb =
+  new NativePromiseCallback(aRunnable, Resolved);
+
+  nsRefPtr<PromiseCallback> rejectCb =
+  new NativePromiseCallback(aRunnable, Rejected);
+
+  AppendCallbacks(resolveCb, rejectCb);
+}
+
+void
 Promise::AppendCallbacks(PromiseCallback* aResolveCallback,
                          PromiseCallback* aRejectCallback)
 {
   if (aResolveCallback) {
     mResolveCallbacks.AppendElement(aResolveCallback);
   }
 
   if (aRejectCallback) {
--- a/dom/promise/Promise.h
+++ b/dom/promise/Promise.h
@@ -15,23 +15,25 @@
 #include "nsWrapperCache.h"
 #include "nsAutoPtr.h"
 #include "nsPIDOMWindow.h"
 #include "js/TypeDecls.h"
 
 namespace mozilla {
 namespace dom {
 
-class PromiseInit;
+class AnyCallback;
 class PromiseCallback;
-class AnyCallback;
+class PromiseInit;
+class PromiseNativeHandler;
 
 class Promise MOZ_FINAL : public nsISupports,
                           public nsWrapperCache
 {
+  friend class NativePromiseCallback;
   friend class PromiseTask;
   friend class PromiseResolverTask;
   friend class ResolvePromiseCallback;
   friend class RejectPromiseCallback;
   friend class WrapperPromiseCallback;
 
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
@@ -73,16 +75,18 @@ public:
   already_AddRefed<Promise>
   Then(const Optional<OwningNonNull<AnyCallback> >& aResolveCallback,
        const Optional<OwningNonNull<AnyCallback> >& aRejectCallback);
 
 
   already_AddRefed<Promise>
   Catch(const Optional<OwningNonNull<AnyCallback> >& aRejectCallback);
 
+  void AppendNativeHandler(PromiseNativeHandler* aRunnable);
+
 private:
   enum PromiseState {
     Pending,
     Resolved,
     Rejected
   };
 
   enum PromiseTaskSync {
--- a/dom/promise/PromiseCallback.cpp
+++ b/dom/promise/PromiseCallback.cpp
@@ -1,16 +1,17 @@
 /* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
 /* vim: set ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "PromiseCallback.h"
 #include "mozilla/dom/Promise.h"
+#include "mozilla/dom/PromiseNativeHandler.h"
 
 namespace mozilla {
 namespace dom {
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(PromiseCallback)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(PromiseCallback)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(PromiseCallback)
@@ -204,16 +205,57 @@ SimpleWrapperPromiseCallback::~SimpleWra
 
 void
 SimpleWrapperPromiseCallback::Call(JS::Handle<JS::Value> aValue)
 {
   ErrorResult rv;
   mCallback->Call(mPromise, aValue, rv);
 }
 
+// NativePromiseCallback
+
+NS_IMPL_CYCLE_COLLECTION_INHERITED_1(NativePromiseCallback,
+                                     PromiseCallback, mHandler)
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(NativePromiseCallback)
+NS_INTERFACE_MAP_END_INHERITING(PromiseCallback)
+
+NS_IMPL_ADDREF_INHERITED(NativePromiseCallback, PromiseCallback)
+NS_IMPL_RELEASE_INHERITED(NativePromiseCallback, PromiseCallback)
+
+NativePromiseCallback::NativePromiseCallback(PromiseNativeHandler* aHandler,
+                                             Promise::PromiseState aState)
+  : mHandler(aHandler)
+  , mState(aState)
+{
+  MOZ_ASSERT(aHandler);
+  MOZ_COUNT_CTOR(NativePromiseCallback);
+}
+
+NativePromiseCallback::~NativePromiseCallback()
+{
+  MOZ_COUNT_DTOR(NativePromiseCallback);
+}
+
+void
+NativePromiseCallback::Call(JS::Handle<JS::Value> aValue)
+{
+  if (mState == Promise::Resolved) {
+    mHandler->ResolvedCallback(aValue);
+    return;
+  }
+
+  if (mState == Promise::Rejected) {
+    mHandler->RejectedCallback(aValue);
+    return;
+  }
+
+  NS_NOTREACHED("huh?");
+}
+
 /* static */ PromiseCallback*
 PromiseCallback::Factory(Promise* aNextPromise, AnyCallback* aCallback,
                          Task aTask)
 {
   MOZ_ASSERT(aNextPromise);
 
   // If we have a callback and a next resolver, we have to exec the callback and
   // then propagate the return value to the next resolver->resolve().
--- a/dom/promise/PromiseCallback.h
+++ b/dom/promise/PromiseCallback.h
@@ -106,12 +106,31 @@ public:
 
   RejectPromiseCallback(Promise* aPromise);
   ~RejectPromiseCallback();
 
 private:
   nsRefPtr<Promise> mPromise;
 };
 
+// NativePromiseCallback wraps a NativePromiseHandler.
+class NativePromiseCallback MOZ_FINAL : public PromiseCallback
+{
+public:
+  NS_DECL_ISUPPORTS_INHERITED
+  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(NativePromiseCallback,
+                                           PromiseCallback)
+
+  void Call(JS::Handle<JS::Value> aValue) MOZ_OVERRIDE;
+
+  NativePromiseCallback(PromiseNativeHandler* aHandler,
+                        Promise::PromiseState aState);
+  ~NativePromiseCallback();
+
+private:
+  nsRefPtr<PromiseNativeHandler> mHandler;
+  Promise::PromiseState mState;
+};
+
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_PromiseCallback_h
new file mode 100644
--- /dev/null
+++ b/dom/promise/PromiseNativeHandler.h
@@ -0,0 +1,39 @@
+/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+* License, v. 2.0. If a copy of the MPL was not distributed with this file,
+* You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_dom_PromiseNativeHandler_h
+#define mozilla_dom_PromiseNativeHandler_h
+
+#include "nsISupports.h"
+
+namespace mozilla {
+namespace dom {
+
+/*
+ * PromiseNativeHandler allows C++ to react to a Promise being rejected/resolved.
+ * A PromiseNativeHandler can be appended to a Promise using
+ * Promise::AppendNativeHandler().
+ */
+class PromiseNativeHandler : public nsISupports
+{
+public:
+  // NS_IMPL_ISUPPORTS0 in Promise.cpp.
+  NS_DECL_ISUPPORTS
+
+  virtual ~PromiseNativeHandler()
+  { }
+
+  virtual void
+  ResolvedCallback(JS::Handle<JS::Value> aValue) = 0;
+
+  virtual void
+  RejectedCallback(JS::Handle<JS::Value> aValue) = 0;
+};
+
+} // namespace dom
+} // namespace mozilla
+
+#endif // mozilla_dom_PromiseNativeHandler_h
--- a/dom/promise/moz.build
+++ b/dom/promise/moz.build
@@ -5,16 +5,17 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 TEST_DIRS += ['tests']
 
 XPIDL_MODULE = 'dom_promise'
 
 EXPORTS.mozilla.dom += [
     'Promise.h',
+    'PromiseNativeHandler.h'
 ]
 
 SOURCES += [
     'Promise.cpp',
     'PromiseCallback.cpp',
 ]
 
 FAIL_ON_WARNINGS = True