Bug 891944 - Move IDBCursor to WebIDL, r=janv
authorAndrea Marchesini <amarchesini@mozilla.com>
Thu, 01 Aug 2013 00:28:13 +0200
changeset 153114 5737186129bb1a475066132919de7f53f3d0f058
parent 153113 2e7771dcfd89991ddabcad07664d3bcea0c9560b
child 153115 023d2f835ca0006cd86e9b9bd2c31da6eb173732
push id2859
push userakeybl@mozilla.com
push dateMon, 16 Sep 2013 19:14:59 +0000
treeherdermozilla-beta@87d3c51cd2bf [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjanv
bugs891944
milestone25.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 891944 - Move IDBCursor to WebIDL, r=janv
addon-sdk/source/lib/sdk/indexed-db.js
addon-sdk/source/test/test-indexed-db.js
dom/base/nsDOMClassInfo.cpp
dom/base/nsDOMClassInfoClasses.h
dom/bindings/Bindings.conf
dom/bindings/Errors.msg
dom/indexedDB/IDBCursor.cpp
dom/indexedDB/IDBCursor.h
dom/indexedDB/ipc/IndexedDBParent.cpp
dom/indexedDB/moz.build
dom/indexedDB/nsIIDBCursor.idl
dom/indexedDB/nsIIDBCursorWithValue.idl
dom/indexedDB/test/unit/head.js
dom/webidl/IDBCursor.webidl
js/xpconnect/src/dom_quickstubs.qsconf
--- a/addon-sdk/source/lib/sdk/indexed-db.js
+++ b/addon-sdk/source/lib/sdk/indexed-db.js
@@ -48,11 +48,10 @@ let principal = Cc["@mozilla.org/scripts
 exports.indexedDB = Object.freeze({
   open: indexedDB.openForPrincipal.bind(indexedDB, principal),
   deleteDatabase: indexedDB.deleteForPrincipal.bind(indexedDB, principal),
   cmp: indexedDB.cmp
 });
 
 exports.IDBKeyRange = IDBKeyRange;
 exports.DOMException = Ci.nsIDOMDOMException;
-exports.IDBCursor = Ci.nsIIDBCursor;
 exports.IDBOpenDBRequest = Ci.nsIIDBOpenDBRequest;
 exports.IDBRequest = Ci.nsIIDBRequest;
--- a/addon-sdk/source/test/test-indexed-db.js
+++ b/addon-sdk/source/test/test-indexed-db.js
@@ -3,31 +3,31 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
 let xulApp = require("sdk/system/xul-app");
 if (xulApp.versionInRange(xulApp.platformVersion, "16.0a1", "*")) {
 new function tests() {
 
-const { indexedDB, IDBKeyRange, DOMException, IDBCursor,
+const { indexedDB, IDBKeyRange, DOMException
         IDBOpenDBRequest, IDBRequest
       } = require("sdk/indexed-db");
 
 exports["test indexedDB is frozen"] = function(assert){
   let original = indexedDB.open;
   let f = function(){};
   assert.throws(function(){indexedDB.open = f});
   assert.equal(indexedDB.open,original);
   assert.notEqual(indexedDB.open,f);
 
 };
 
 exports["test db variables"] = function(assert) {
-  [ indexedDB, IDBKeyRange, DOMException, IDBCursor,
+  [ indexedDB, IDBKeyRange, DOMException
     IDBOpenDBRequest, IDBOpenDBRequest, IDBRequest
   ].forEach(function(value) {
     assert.notEqual(typeof(value), "undefined", "variable is defined");
   });
 }
 
 exports["test open"] = function(assert, done) {
   let request = indexedDB.open("MyTestDatabase");
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -198,17 +198,16 @@
 #include "nsDOMFile.h"
 
 #include "nsIEventListenerService.h"
 #include "nsIMessageManager.h"
 #include "mozilla/dom/Element.h"
 
 #include "mozilla/dom/indexedDB/IDBWrapperCache.h"
 #include "mozilla/dom/indexedDB/IDBRequest.h"
-#include "mozilla/dom/indexedDB/IDBCursor.h"
 #include "mozilla/dom/indexedDB/IDBKeyRange.h"
 
 using mozilla::dom::indexedDB::IDBWrapperCache;
 using mozilla::dom::workers::ResolveWorkerClasses;
 
 #include "nsIDOMMediaQueryList.h"
 
 #include "mozilla/dom/Activity.h"
@@ -628,20 +627,16 @@ static nsDOMClassInfoData sClassInfoData
                                        nsIXPCScriptable::IS_GLOBAL_OBJECT)
   NS_DEFINE_CHROME_ONLY_CLASSINFO_DATA(ChromeMessageBroadcaster, nsDOMGenericSH,
                                        DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CHROME_ONLY_CLASSINFO_DATA(ChromeMessageSender, nsDOMGenericSH,
                                        DOM_DEFAULT_SCRIPTABLE_FLAGS)
 
   NS_DEFINE_CLASSINFO_DATA(IDBRequest, IDBEventTargetSH,
                            IDBEVENTTARGET_SCRIPTABLE_FLAGS)
-  NS_DEFINE_CLASSINFO_DATA(IDBCursor, nsDOMGenericSH,
-                           DOM_DEFAULT_SCRIPTABLE_FLAGS)
-  NS_DEFINE_CLASSINFO_DATA(IDBCursorWithValue, nsDOMGenericSH,
-                           DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(IDBKeyRange, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(IDBOpenDBRequest, IDBEventTargetSH,
                            IDBEVENTTARGET_SCRIPTABLE_FLAGS)
 
 
   NS_DEFINE_CLASSINFO_DATA(MozCSSKeyframeRule, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
@@ -1527,25 +1522,16 @@ nsDOMClassInfo::Init()
     DOM_CLASSINFO_MAP_ENTRY(nsIMessageSender)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(IDBRequest, nsIIDBRequest)
     DOM_CLASSINFO_MAP_ENTRY(nsIIDBRequest)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
   DOM_CLASSINFO_MAP_END
 
-  DOM_CLASSINFO_MAP_BEGIN(IDBCursor, nsIIDBCursor)
-    DOM_CLASSINFO_MAP_ENTRY(nsIIDBCursor)
-  DOM_CLASSINFO_MAP_END
-
-  DOM_CLASSINFO_MAP_BEGIN(IDBCursorWithValue, nsIIDBCursorWithValue)
-    DOM_CLASSINFO_MAP_ENTRY(nsIIDBCursor)
-    DOM_CLASSINFO_MAP_ENTRY(nsIIDBCursorWithValue)
-  DOM_CLASSINFO_MAP_END
-
   DOM_CLASSINFO_MAP_BEGIN(IDBKeyRange, nsIIDBKeyRange)
     DOM_CLASSINFO_MAP_ENTRY(nsIIDBKeyRange)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(IDBOpenDBRequest, nsIIDBOpenDBRequest)
     DOM_CLASSINFO_MAP_ENTRY(nsIIDBOpenDBRequest)
     DOM_CLASSINFO_MAP_ENTRY(nsIIDBRequest)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
@@ -2804,36 +2790,30 @@ DefineInterfaceConstants(JSContext *cx, 
       return NS_ERROR_UNEXPECTED;
     }
   }
 
   return NS_OK;
 }
 
 // This code is temporary until we remove support for the constants defined
-// on IDBCursor/IDBRequest
+// on IDBRequest
 
 struct IDBConstant
 {
   const char* interface;
   const char* name;
   const char* value;
 
-  static const char* IDBCursor;
   static const char* IDBRequest;
 };
 
-const char* IDBConstant::IDBCursor = "IDBCursor";
 const char* IDBConstant::IDBRequest = "IDBRequest";
 
 static const IDBConstant sIDBConstants[] = {
-  { IDBConstant::IDBCursor,  "NEXT",              "next" },
-  { IDBConstant::IDBCursor,  "NEXT_NO_DUPLICATE", "nextunique" },
-  { IDBConstant::IDBCursor,  "PREV",              "prev" },
-  { IDBConstant::IDBCursor,  "PREV_NO_DUPLICATE", "prevunique" },
   { IDBConstant::IDBRequest, "LOADING",           "pending" },
   { IDBConstant::IDBRequest, "DONE",              "done" },
 };
 
 static JSBool
 IDBConstantGetter(JSContext *cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id,
                   JS::MutableHandle<JS::Value> vp)
 {
@@ -2913,20 +2893,17 @@ IDBConstantGetter(JSContext *cx, JS::Han
   vp.set(value);
   return JS_TRUE;
 }
 
 static nsresult
 DefineIDBInterfaceConstants(JSContext *cx, JS::Handle<JSObject*> obj, const nsIID *aIID)
 {
   const char* interface;
-  if (aIID->Equals(NS_GET_IID(nsIIDBCursor))) {
-    interface = IDBConstant::IDBCursor;
-  }
-  else if (aIID->Equals(NS_GET_IID(nsIIDBRequest))) {
+  if (aIID->Equals(NS_GET_IID(nsIIDBRequest))) {
     interface = IDBConstant::IDBRequest;
   }
   else {
     MOZ_CRASH("unexpected IID");
   }
 
   for (int8_t i = 0; i < (int8_t)mozilla::ArrayLength(sIDBConstants); ++i) {
     const IDBConstant& c = sIDBConstants[i];
@@ -3340,18 +3317,17 @@ nsDOMConstructor::ResolveInterfaceConsta
   // Special case for |IDBKeyRange| which gets funny "static" functions.
   if (class_iid->Equals(NS_GET_IID(nsIIDBKeyRange)) &&
       !indexedDB::IDBKeyRange::DefineConstructors(cx, obj)) {
     return NS_ERROR_FAILURE;
   }
 
   // Special case a few IDB interfaces which for now are getting transitional
   // constants.
-  if (class_iid->Equals(NS_GET_IID(nsIIDBCursor)) ||
-      class_iid->Equals(NS_GET_IID(nsIIDBRequest))) {
+  if (class_iid->Equals(NS_GET_IID(nsIIDBRequest))) {
     rv = DefineIDBInterfaceConstants(cx, obj, class_iid);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
@@ -3478,18 +3454,17 @@ ResolvePrototype(nsIXPConnect *aXPConnec
     // Special case for |IDBKeyRange| which gets funny "static" functions.
     if (primary_iid->Equals(NS_GET_IID(nsIIDBKeyRange)) &&
         !indexedDB::IDBKeyRange::DefineConstructors(cx, class_obj)) {
       return NS_ERROR_FAILURE;
     }
 
     // Special case a few IDB interfaces which for now are getting transitional
     // constants.
-    if (primary_iid->Equals(NS_GET_IID(nsIIDBCursor)) ||
-        primary_iid->Equals(NS_GET_IID(nsIIDBRequest))) {
+    if (primary_iid->Equals(NS_GET_IID(nsIIDBRequest))) {
       rv = DefineIDBInterfaceConstants(cx, class_obj, primary_iid);
       NS_ENSURE_SUCCESS(rv, rv);
     }
 
     nsCOMPtr<nsIInterfaceInfoManager>
       iim(do_GetService(NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID));
     NS_ENSURE_TRUE(iim, NS_ERROR_NOT_AVAILABLE);
 
--- a/dom/base/nsDOMClassInfoClasses.h
+++ b/dom/base/nsDOMClassInfoClasses.h
@@ -115,18 +115,16 @@ DOMCI_CLASS(DataTransfer)
 
 DOMCI_CLASS(EventListenerInfo)
 
 DOMCI_CLASS(ContentFrameMessageManager)
 DOMCI_CLASS(ChromeMessageBroadcaster)
 DOMCI_CLASS(ChromeMessageSender)
 
 DOMCI_CLASS(IDBRequest)
-DOMCI_CLASS(IDBCursor)
-DOMCI_CLASS(IDBCursorWithValue)
 DOMCI_CLASS(IDBKeyRange)
 DOMCI_CLASS(IDBOpenDBRequest)
 
 
 DOMCI_CLASS(MozCSSKeyframeRule)
 DOMCI_CLASS(MozCSSKeyframesRule)
 
 DOMCI_CLASS(CSSPageRule)
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -533,16 +533,28 @@ DOMInterfaces = {
         'sheet'
     ]
 },
 
 'HTMLUListElement': {
     'nativeType' : 'mozilla::dom::HTMLSharedListElement'
 },
 
+'IDBCursor': {
+    'nativeType': 'mozilla::dom::indexedDB::IDBCursor',
+    'implicitJSContext': [ 'delete' ],
+    'binaryNames': {
+        'direction': 'getDirection'
+    }
+},
+
+'IDBCursorWithValue': {
+    'nativeType': 'mozilla::dom::indexedDB::IDBCursor',
+},
+
 'IDBDatabase': {
     'nativeType': 'mozilla::dom::indexedDB::IDBDatabase',
 },
 
 'IDBFactory': {
     'nativeType': 'mozilla::dom::indexedDB::IDBFactory',
 },
 
--- a/dom/bindings/Errors.msg
+++ b/dom/bindings/Errors.msg
@@ -39,8 +39,9 @@ MSG_DEF(MSG_OVERLOAD_RESOLUTION_FAILED, 
 MSG_DEF(MSG_GLOBAL_NOT_NATIVE, 0, "Global is not a native object.")
 MSG_DEF(MSG_ENCODING_NOT_SUPPORTED, 1, "The given encoding '{0}' is not supported.")
 MSG_DEF(MSG_DOM_ENCODING_NOT_UTF, 0, "The encoding must be utf-8, utf-16, or utf-16be.")
 MSG_DEF(MSG_NOT_FINITE, 1, "{0} is not a finite floating-point value.")
 MSG_DEF(MSG_INVALID_VERSION, 0, "0 (Zero) is not a valid database version.")
 MSG_DEF(MSG_INVALID_BYTESTRING, 2, "Cannot convert string to ByteString because the character"
         " at index {0} has value {1} which is greater than 255.")
 MSG_DEF(MSG_NOT_DATE, 1, "{0} is not a date.")
+MSG_DEF(MSG_INVALID_ADVANCE_COUNT, 0, "0 (Zero) is not a valid advance count.")
--- a/dom/indexedDB/IDBCursor.cpp
+++ b/dom/indexedDB/IDBCursor.cpp
@@ -23,19 +23,22 @@
 #include "IDBTransaction.h"
 #include "ProfilerHelpers.h"
 #include "TransactionThreadPool.h"
 
 #include "ipc/IndexedDBChild.h"
 #include "ipc/IndexedDBParent.h"
 
 #include "IndexedDatabaseInlines.h"
+#include "mozilla/dom/BindingDeclarations.h"
 
 USING_INDEXEDDB_NAMESPACE
 using namespace mozilla::dom::indexedDB::ipc;
+using mozilla::dom::Optional;
+using mozilla::ErrorResult;
 
 static_assert(sizeof(size_t) >= sizeof(IDBCursor::Direction),
               "Relying on conversion between size_t and "
               "IDBCursor::Direction");
 
 namespace {
 
 class CursorHelper : public AsyncConnectionHelper
@@ -348,16 +351,18 @@ IDBCursor::IDBCursor()
   mHaveCachedKey(false),
   mHaveCachedPrimaryKey(false),
   mHaveCachedValue(false),
   mRooted(false),
   mContinueCalled(false),
   mHaveValue(true)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
+
+  SetIsDOMBinding();
 }
 
 IDBCursor::~IDBCursor()
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   NS_ASSERTION(!mActorParent, "Actor parent owns us, how can we be dying?!");
   if (mActorChild) {
@@ -383,29 +388,30 @@ IDBCursor::DropJSObjects()
   mHaveCachedKey = false;
   mHaveCachedPrimaryKey = false;
   mHaveCachedValue = false;
   mRooted = false;
   mHaveValue = false;
   NS_DROP_JS_OBJECTS(this, IDBCursor);
 }
 
-nsresult
-IDBCursor::ContinueInternal(const Key& aKey,
-                            int32_t aCount)
+void
+IDBCursor::ContinueInternal(const Key& aKey, int32_t aCount, ErrorResult& aRv)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(aCount > 0, "Must have a count!");
 
   if (!mTransaction->IsOpen()) {
-    return NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR;
+    aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
+    return;
   }
 
   if (!mHaveValue || mContinueCalled) {
-    return NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR;
+    aRv.Throw(NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR);
+    return;
   }
 
   mContinueToKey = aKey;
 
 #ifdef DEBUG
   {
     nsAutoString readyState;
     if (NS_FAILED(mRequest->GetReadyState(readyState))) {
@@ -431,234 +437,240 @@ IDBCursor::ContinueInternal(const Key& a
       helper = new ContinueIndexObjectHelper(this, aCount);
       break;
 
     default:
       NS_NOTREACHED("Unknown cursor type!");
   }
 
   nsresult rv = helper->DispatchToTransactionPool();
-  NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
+  if (NS_FAILED(rv)) {
+    NS_WARNING("Failed to dispatch!");
+    aRv.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
+    return;
+  }
 
   mContinueCalled = true;
-  return NS_OK;
 }
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(IDBCursor)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRequest)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTransaction)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mObjectStore)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIndex)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(IDBCursor)
+  NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
   NS_ASSERTION(tmp->mHaveCachedKey || JSVAL_IS_VOID(tmp->mCachedKey),
                "Should have a cached key");
   NS_ASSERTION(tmp->mHaveCachedPrimaryKey ||
                JSVAL_IS_VOID(tmp->mCachedPrimaryKey),
                "Should have a cached primary key");
   NS_ASSERTION(tmp->mHaveCachedValue || JSVAL_IS_VOID(tmp->mCachedValue),
                "Should have a cached value");
   NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mScriptOwner)
   NS_IMPL_CYCLE_COLLECTION_TRACE_JSVAL_MEMBER_CALLBACK(mCachedKey)
   NS_IMPL_CYCLE_COLLECTION_TRACE_JSVAL_MEMBER_CALLBACK(mCachedPrimaryKey)
   NS_IMPL_CYCLE_COLLECTION_TRACE_JSVAL_MEMBER_CALLBACK(mCachedValue)
 NS_IMPL_CYCLE_COLLECTION_TRACE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(IDBCursor)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
   // Don't unlink mObjectStore, mIndex, or mTransaction!
   tmp->DropJSObjects();
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mRequest)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(IDBCursor)
-  NS_INTERFACE_MAP_ENTRY(nsIIDBCursor)
-  NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIIDBCursorWithValue, mType != INDEXKEY)
-  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO_CONDITIONAL(IDBCursorWithValue,
-                                                   mType != INDEXKEY)
-  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO_CONDITIONAL(IDBCursor,
-                                                   mType == INDEXKEY)
+  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_INTERFACE_MAP_ENTRY(nsISupports)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(IDBCursor)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(IDBCursor)
 
-DOMCI_DATA(IDBCursor, IDBCursor)
-DOMCI_DATA(IDBCursorWithValue, IDBCursor)
+JSObject*
+IDBCursor::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
+{
+  return mType != INDEXKEY
+          ? IDBCursorWithValueBinding::Wrap(aCx, aScope, this)
+          : IDBCursorBinding::Wrap(aCx, aScope, this);
+}
 
-NS_IMETHODIMP
-IDBCursor::GetDirection(nsAString& aDirection)
+mozilla::dom::IDBCursorDirection
+IDBCursor::GetDirection() const
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   switch (mDirection) {
     case NEXT:
-      aDirection.AssignLiteral("next");
-      break;
+      return mozilla::dom::IDBCursorDirection::Next;
+
     case NEXT_UNIQUE:
-      aDirection.AssignLiteral("nextunique");
-      break;
+      return mozilla::dom::IDBCursorDirection::Nextunique;
+
     case PREV:
-      aDirection.AssignLiteral("prev");
-      break;
+      return mozilla::dom::IDBCursorDirection::Prev;
+
     case PREV_UNIQUE:
-      aDirection.AssignLiteral("prevunique");
-      break;
+      return mozilla::dom::IDBCursorDirection::Prevunique;
 
     case DIRECTION_INVALID:
     default:
-      NS_NOTREACHED("Bad direction value!");
-      return NS_ERROR_UNEXPECTED;
+      MOZ_CRASH("Unknown direction!");
+      return mozilla::dom::IDBCursorDirection::Next;
   }
-
-  return NS_OK;
 }
 
-NS_IMETHODIMP
-IDBCursor::GetSource(nsISupports** aSource)
+
+already_AddRefed<nsISupports>
+IDBCursor::Source() const
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
-  return mType == OBJECTSTORE ?
-         CallQueryInterface(mObjectStore, aSource) :
-         CallQueryInterface(mIndex, aSource);
+  nsCOMPtr<nsISupports> source;
+  if (mType == OBJECTSTORE) {
+    source = do_QueryInterface(mObjectStore);
+  }
+  else {
+    source = do_QueryInterface(mIndex);
+  }
+
+  return source.forget();
 }
 
-NS_IMETHODIMP
-IDBCursor::GetKey(JSContext* aCx,
-                  jsval* aKey)
+JS::Value
+IDBCursor::GetKey(JSContext* aCx, ErrorResult& aRv)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   NS_ASSERTION(!mKey.IsUnset() || !mHaveValue, "Bad key!");
 
   if (!mHaveValue) {
-    *aKey = JSVAL_VOID;
-    return NS_OK;
+    return JSVAL_VOID;
   }
 
   if (!mHaveCachedKey) {
     if (!mRooted) {
       NS_HOLD_JS_OBJECTS(this, IDBCursor);
       mRooted = true;
     }
 
-    nsresult rv = mKey.ToJSVal(aCx, mCachedKey);
-    NS_ENSURE_SUCCESS(rv, rv);
+    aRv = mKey.ToJSVal(aCx, mCachedKey);
+    ENSURE_SUCCESS(aRv, JSVAL_VOID);
 
     mHaveCachedKey = true;
   }
 
-  *aKey = mCachedKey;
-  return NS_OK;
+  return mCachedKey;
 }
 
-NS_IMETHODIMP
-IDBCursor::GetPrimaryKey(JSContext* aCx,
-                         jsval* aValue)
+JS::Value
+IDBCursor::GetPrimaryKey(JSContext* aCx, ErrorResult& aRv)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   if (!mHaveValue) {
-    *aValue = JSVAL_VOID;
-    return NS_OK;
+    return JSVAL_VOID;
   }
 
   if (!mHaveCachedPrimaryKey) {
     if (!mRooted) {
       NS_HOLD_JS_OBJECTS(this, IDBCursor);
       mRooted = true;
     }
 
     JSAutoRequest ar(aCx);
 
     NS_ASSERTION(mType == OBJECTSTORE ? !mKey.IsUnset() :
                                         !mObjectKey.IsUnset(), "Bad key!");
 
     const Key& key = mType == OBJECTSTORE ? mKey : mObjectKey;
 
-    nsresult rv = key.ToJSVal(aCx, mCachedPrimaryKey);
-    NS_ENSURE_SUCCESS(rv, rv);
+    aRv = key.ToJSVal(aCx, mCachedPrimaryKey);
+    ENSURE_SUCCESS(aRv, JSVAL_VOID);
 
     mHaveCachedPrimaryKey = true;
   }
 
-  *aValue = mCachedPrimaryKey;
-  return NS_OK;
+  return mCachedPrimaryKey;
 }
 
-NS_IMETHODIMP
-IDBCursor::GetValue(JSContext* aCx,
-                    jsval* aValue)
+JS::Value
+IDBCursor::GetValue(JSContext* aCx, ErrorResult& aRv)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(mType != INDEXKEY, "GetValue shouldn't exist on index keys");
 
   if (!mHaveValue) {
-    *aValue = JSVAL_VOID;
-    return NS_OK;
+    return JSVAL_VOID;
   }
 
   if (!mHaveCachedValue) {
     if (!mRooted) {
       NS_HOLD_JS_OBJECTS(this, IDBCursor);
       mRooted = true;
     }
 
     JS::Rooted<JS::Value> val(aCx);
     if (!IDBObjectStore::DeserializeValue(aCx, mCloneReadInfo, &val)) {
-      return NS_ERROR_DOM_DATA_CLONE_ERR;
+      aRv.Throw(NS_ERROR_DOM_DATA_CLONE_ERR);
+      return JSVAL_VOID;
     }
 
     mCloneReadInfo.mCloneBuffer.clear();
 
     mCachedValue = val;
     mHaveCachedValue = true;
   }
 
-  *aValue = mCachedValue;
-  return NS_OK;
+  return mCachedValue;
 }
 
-NS_IMETHODIMP
-IDBCursor::Continue(const jsval& aKey,
-                    JSContext* aCx)
+void
+IDBCursor::Continue(JSContext* aCx,
+                    const Optional<JS::Handle<JS::Value> >& aKey,
+                    ErrorResult &aRv)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   Key key;
-  nsresult rv = key.SetFromJSVal(aCx, aKey);
-  NS_ENSURE_SUCCESS(rv, rv);
+  if (aKey.WasPassed()) {
+    aRv = key.SetFromJSVal(aCx, aKey.Value());
+    ENSURE_SUCCESS_VOID(aRv);
+  }
 
   if (!key.IsUnset()) {
     switch (mDirection) {
       case IDBCursor::NEXT:
       case IDBCursor::NEXT_UNIQUE:
         if (key <= mKey) {
-          return NS_ERROR_DOM_INDEXEDDB_DATA_ERR;
+          aRv.Throw(NS_ERROR_DOM_INDEXEDDB_DATA_ERR);
+          return;
         }
         break;
 
       case IDBCursor::PREV:
       case IDBCursor::PREV_UNIQUE:
         if (key >= mKey) {
-          return NS_ERROR_DOM_INDEXEDDB_DATA_ERR;
+          aRv.Throw(NS_ERROR_DOM_INDEXEDDB_DATA_ERR);
+          return;
         }
         break;
 
       default:
         NS_NOTREACHED("Unknown direction type!");
     }
   }
 
-  rv = ContinueInternal(key, 1);
-  if (NS_FAILED(rv)) {
-    return rv;
+  ContinueInternal(key, 1, aRv);
+  if (aRv.Failed()) {
+    return;
   }
 
 #ifdef IDB_PROFILER_USE_MARKS
   if (mType == OBJECTSTORE) {
     IDB_PROFILER_MARK("IndexedDB Request %llu: "
                       "database(%s).transaction(%s).objectStore(%s).cursor(%s)."
                       "continue(%s)",
                       "IDBRequest[%llu] MT IDBCursor.continue()",
@@ -678,83 +690,80 @@ IDBCursor::Continue(const jsval& aKey,
                       IDB_PROFILER_STRING(Transaction()->Database()),
                       IDB_PROFILER_STRING(Transaction()),
                       IDB_PROFILER_STRING(mObjectStore),
                       IDB_PROFILER_STRING(mIndex),
                       IDB_PROFILER_STRING(mDirection),
                       key.IsUnset() ? "" : IDB_PROFILER_STRING(key));
   }
 #endif
-
-  return NS_OK;
 }
 
-NS_IMETHODIMP
-IDBCursor::Update(const jsval& aValue,
-                  JSContext* aCx,
-                  nsIIDBRequest** _retval)
+already_AddRefed<IDBRequest>
+IDBCursor::Update(JSContext* aCx, JS::Handle<JS::Value> aValue,
+                  ErrorResult& aRv)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   if (!mTransaction->IsOpen()) {
-    return NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR;
+    aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
+    return nullptr;
   }
 
   if (!mTransaction->IsWriteAllowed()) {
-    return NS_ERROR_DOM_INDEXEDDB_READ_ONLY_ERR;
+    aRv.Throw(NS_ERROR_DOM_INDEXEDDB_READ_ONLY_ERR);
+    return nullptr;
   }
 
   if (!mHaveValue || mType == INDEXKEY) {
-    return NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR;
+    aRv.Throw(NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR);
+    return nullptr;
   }
 
   NS_ASSERTION(mObjectStore, "This cannot be null!");
   NS_ASSERTION(!mKey.IsUnset() , "Bad key!");
   NS_ASSERTION(mType != INDEXOBJECT || !mObjectKey.IsUnset(), "Bad key!");
 
-  nsresult rv;
-
   JSAutoRequest ar(aCx);
 
   Key& objectKey = (mType == OBJECTSTORE) ? mKey : mObjectKey;
 
-  nsCOMPtr<nsIIDBRequest> request;
+  nsRefPtr<IDBRequest> request;
   if (mObjectStore->HasValidKeyPath()) {
     // Make sure the object given has the correct keyPath value set on it.
     const KeyPath& keyPath = mObjectStore->GetKeyPath();
     Key key;
 
-    rv = keyPath.ExtractKey(aCx, aValue, key);
-    if (NS_FAILED(rv)) {
-      return rv;
+    aRv = keyPath.ExtractKey(aCx, aValue, key);
+    if (aRv.Failed()) {
+      return nullptr;
     }
 
     if (key != objectKey) {
-      return NS_ERROR_DOM_INDEXEDDB_DATA_ERR;
+      aRv.Throw(NS_ERROR_DOM_INDEXEDDB_DATA_ERR);
+      return nullptr;
     }
 
-    ErrorResult error;
     JS::Rooted<JS::Value> value(aCx, aValue);
     Optional<JS::Handle<JS::Value> > keyValue(aCx);
-    request = mObjectStore->Put(aCx, value, keyValue, error);
-    if (error.Failed()) {
-      return error.ErrorCode();
+    request = mObjectStore->Put(aCx, value, keyValue, aRv);
+    if (aRv.Failed()) {
+      return nullptr;
     }
   }
   else {
     JS::Rooted<JS::Value> keyVal(aCx);
-    rv = objectKey.ToJSVal(aCx, &keyVal);
-    NS_ENSURE_SUCCESS(rv, rv);
+    aRv = objectKey.ToJSVal(aCx, &keyVal);
+    ENSURE_SUCCESS(aRv, nullptr);
 
-    ErrorResult error;
     JS::Rooted<JS::Value> value(aCx, aValue);
     Optional<JS::Handle<JS::Value> > keyValue(aCx, keyVal);
-    request = mObjectStore->Put(aCx, value, keyValue, error);
-    if (error.Failed()) {
-      return error.ErrorCode();
+    request = mObjectStore->Put(aCx, value, keyValue, aRv);
+    if (aRv.Failed()) {
+      return nullptr;
     }
   }
 
 #ifdef IDB_PROFILER_USE_MARKS
   {
     uint64_t requestSerial =
       static_cast<IDBRequest*>(request.get())->GetSerialNumber();
     if (mType == OBJECTSTORE) {
@@ -782,57 +791,56 @@ IDBCursor::Update(const jsval& aValue,
                         IDB_PROFILER_STRING(mIndex),
                         IDB_PROFILER_STRING(mDirection),
                         mObjectStore->HasValidKeyPath() ? "" :
                           IDB_PROFILER_STRING(objectKey));
     }
   }
 #endif
 
-  request.forget(_retval);
-  return NS_OK;
+  return request.forget();
 }
 
-NS_IMETHODIMP
-IDBCursor::Delete(JSContext* aCx,
-                  nsIIDBRequest** _retval)
+already_AddRefed<IDBRequest>
+IDBCursor::Delete(JSContext* aCx, ErrorResult& aRv)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   if (!mTransaction->IsOpen()) {
-    return NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR;
+    aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
+    return nullptr;
   }
 
   if (!mTransaction->IsWriteAllowed()) {
-    return NS_ERROR_DOM_INDEXEDDB_READ_ONLY_ERR;
+    aRv.Throw(NS_ERROR_DOM_INDEXEDDB_READ_ONLY_ERR);
+    return nullptr;
   }
 
   if (!mHaveValue || mType == INDEXKEY) {
-    return NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR;
+    aRv.Throw(NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR);
+    return nullptr;
   }
 
   NS_ASSERTION(mObjectStore, "This cannot be null!");
   NS_ASSERTION(!mKey.IsUnset() , "Bad key!");
 
   Key& objectKey = (mType == OBJECTSTORE) ? mKey : mObjectKey;
 
   JS::Rooted<JS::Value> key(aCx);
-  nsresult rv = objectKey.ToJSVal(aCx, &key);
-  NS_ENSURE_SUCCESS(rv, rv);
+  aRv = objectKey.ToJSVal(aCx, &key);
+  ENSURE_SUCCESS(aRv, nullptr);
 
-  ErrorResult error;
-  nsCOMPtr<nsIIDBRequest> request = mObjectStore->Delete(aCx, key, error);
-  if (error.Failed()) {
-    return error.ErrorCode();
+  nsRefPtr<IDBRequest> request = mObjectStore->Delete(aCx, key, aRv);
+  if (aRv.Failed()) {
+    return nullptr;
   }
 
 #ifdef IDB_PROFILER_USE_MARKS
   {
-    uint64_t requestSerial =
-      static_cast<IDBRequest*>(request.get())->GetSerialNumber();
+    uint64_t requestSerial = request->GetSerialNumber();
     if (mType == OBJECTSTORE) {
       IDB_PROFILER_MARK("IndexedDB Request %llu: "
                         "database(%s).transaction(%s).objectStore(%s)."
                         "cursor(%s).delete(%s)",
                         "IDBRequest[%llu] MT IDBCursor.delete()",
                         requestSerial,
                         IDB_PROFILER_STRING(mTransaction->Database()),
                         IDB_PROFILER_STRING(mTransaction),
@@ -853,34 +861,32 @@ IDBCursor::Delete(JSContext* aCx,
                         IDB_PROFILER_STRING(mIndex),
                         IDB_PROFILER_STRING(mDirection),
                         mObjectStore->HasValidKeyPath() ? "" :
                           IDB_PROFILER_STRING(objectKey));
     }
   }
 #endif
 
-  request.forget(_retval);
-  return NS_OK;
+  return request.forget();
 }
 
-NS_IMETHODIMP
-IDBCursor::Advance(int64_t aCount)
+void
+IDBCursor::Advance(uint32_t aCount, ErrorResult &aRv)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
-  if (aCount < 1 || aCount > UINT32_MAX) {
-    return NS_ERROR_TYPE_ERR;
+  if (aCount < 1) {
+    aRv.ThrowTypeError(MSG_INVALID_ADVANCE_COUNT);
+    return;
   }
 
   Key key;
-  nsresult rv = ContinueInternal(key, int32_t(aCount));
-  if (NS_FAILED(rv)) {
-    return rv;
-  }
+  ContinueInternal(key, int32_t(aCount), aRv);
+  ENSURE_SUCCESS_VOID(aRv);
 
 #ifdef IDB_PROFILER_USE_MARKS
   {
     if (mType == OBJECTSTORE) {
       IDB_PROFILER_MARK("IndexedDB Request %llu: "
                         "database(%s).transaction(%s).objectStore(%s)."
                         "cursor(%s).advance(%ld)",
                         "IDBRequest[%llu] MT IDBCursor.advance()",
@@ -899,18 +905,16 @@ IDBCursor::Advance(int64_t aCount)
                         IDB_PROFILER_STRING(Transaction()->Database()),
                         IDB_PROFILER_STRING(Transaction()),
                         IDB_PROFILER_STRING(mObjectStore),
                         IDB_PROFILER_STRING(mIndex),
                         IDB_PROFILER_STRING(mDirection), aCount);
     }
   }
 #endif
-
-  return NS_OK;
 }
 
 void
 CursorHelper::ReleaseMainThreadObjects()
 {
   mCursor = nullptr;
   AsyncConnectionHelper::ReleaseMainThreadObjects();
 }
--- a/dom/indexedDB/IDBCursor.h
+++ b/dom/indexedDB/IDBCursor.h
@@ -4,53 +4,51 @@
  * 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_indexeddb_idbcursor_h__
 #define mozilla_dom_indexeddb_idbcursor_h__
 
 #include "mozilla/dom/indexedDB/IndexedDatabase.h"
 
-#include "nsIIDBCursorWithValue.h"
-
+#include "mozilla/Attributes.h"
 #include "mozilla/dom/IDBCursorBinding.h"
+#include "mozilla/ErrorResult.h"
 #include "nsCycleCollectionParticipant.h"
+#include "nsWrapperCache.h"
 
 #include "mozilla/dom/indexedDB/IDBObjectStore.h"
 #include "mozilla/dom/indexedDB/Key.h"
 
-
 class nsIRunnable;
 class nsIScriptContext;
 class nsPIDOMWindow;
 
 BEGIN_INDEXEDDB_NAMESPACE
 
 class ContinueHelper;
 class ContinueObjectStoreHelper;
 class ContinueIndexHelper;
 class ContinueIndexObjectHelper;
 class IDBIndex;
 class IDBRequest;
 class IDBTransaction;
 class IndexedDBCursorChild;
 class IndexedDBCursorParent;
 
-class IDBCursor MOZ_FINAL : public nsIIDBCursorWithValue
+class IDBCursor MOZ_FINAL : public nsISupports,
+                            public nsWrapperCache
 {
   friend class ContinueHelper;
   friend class ContinueObjectStoreHelper;
   friend class ContinueIndexHelper;
   friend class ContinueIndexObjectHelper;
 
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
-  NS_DECL_NSIIDBCURSOR
-  NS_DECL_NSIIDBCURSORWITHVALUE
-
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(IDBCursor)
 
   enum Type
   {
     OBJECTSTORE = 0,
     INDEXKEY,
     INDEXOBJECT
   };
@@ -141,19 +139,58 @@ public:
   }
 
   IndexedDBCursorParent*
   GetActorParent() const
   {
     return mActorParent;
   }
 
-  nsresult
-  ContinueInternal(const Key& aKey,
-                   int32_t aCount);
+  void
+  ContinueInternal(const Key& aKey, int32_t aCount,
+                   ErrorResult& aRv);
+
+  // nsWrapperCache
+  virtual JSObject*
+  WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
+
+  // WebIDL
+  IDBTransaction*
+  GetParentObject() const
+  {
+    return mTransaction;
+  }
+
+  already_AddRefed<nsISupports>
+  Source() const;
+
+  IDBCursorDirection
+  GetDirection() const;
+
+  JS::Value
+  GetKey(JSContext* aCx, ErrorResult& aRv);
+
+  JS::Value
+  GetPrimaryKey(JSContext* aCx, ErrorResult& aRv);
+
+  already_AddRefed<IDBRequest>
+  Update(JSContext* aCx, JS::Handle<JS::Value> aValue, ErrorResult& aRv);
+
+  void
+  Advance(uint32_t aCount, ErrorResult& aRv);
+
+  void
+  Continue(JSContext* aCx, const Optional<JS::Handle<JS::Value> >& aKey,
+           ErrorResult& aRv);
+
+  already_AddRefed<IDBRequest>
+  Delete(JSContext* aCx, ErrorResult& aRv);
+
+  JS::Value
+  GetValue(JSContext* aCx, ErrorResult& aRv);
 
 protected:
   IDBCursor();
   ~IDBCursor();
 
   void DropJSObjects();
 
   static
--- a/dom/indexedDB/ipc/IndexedDBParent.cpp
+++ b/dom/indexedDB/ipc/IndexedDBParent.cpp
@@ -2039,18 +2039,19 @@ bool
 IndexedDBCursorRequestParent::Continue(const ContinueParams& aParams)
 {
   MOZ_ASSERT(mCursor);
   MOZ_ASSERT(mRequestType == ParamsUnionType::TContinueParams);
 
   {
     AutoSetCurrentTransaction asct(mCursor->Transaction());
 
-    nsresult rv = mCursor->ContinueInternal(aParams.key(), aParams.count());
-    NS_ENSURE_SUCCESS(rv, false);
+    ErrorResult rv;
+    mCursor->ContinueInternal(aParams.key(), aParams.count(), rv);
+    ENSURE_SUCCESS(rv, false);
   }
 
   mRequest = mCursor->Request();
   MOZ_ASSERT(mRequest);
 
   mRequest->SetActor(this);
   return true;
 }
--- a/dom/indexedDB/moz.build
+++ b/dom/indexedDB/moz.build
@@ -3,18 +3,16 @@
 # 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/.
 
 DIRS += ['ipc']
 TEST_DIRS += ['test']
 
 XPIDL_SOURCES += [
-    'nsIIDBCursor.idl',
-    'nsIIDBCursorWithValue.idl',
     'nsIIDBKeyRange.idl',
     'nsIIDBOpenDBRequest.idl',
     'nsIIDBRequest.idl',
     'nsIIndexedDatabaseManager.idl',
 ]
 
 XPIDL_MODULE = 'dom_indexeddb'
 
deleted file mode 100644
--- a/dom/indexedDB/nsIIDBCursor.idl
+++ /dev/null
@@ -1,45 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* 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 "nsISupports.idl"
-
-interface nsIIDBRequest;
-
-/**
- * IDBCursor interface.  See
- * http://dev.w3.org/2006/webapi/WebSimpleDB/#idl-def-IDBCursor for more
- * information.
- */
-[scriptable, builtinclass, uuid(148579a3-6b28-4b2a-92c3-ff5719e8e03e)]
-interface nsIIDBCursor : nsISupports
-{
-  // "next", "nextunique", "prev" or "prevunique"
-  readonly attribute DOMString direction;
-
-  readonly attribute nsISupports source;
-
-  [implicit_jscontext]
-  readonly attribute jsval key;
-
-  [implicit_jscontext]
-  readonly attribute jsval primaryKey;
-
-  // Calling continue means that the same onsuccess function will be called
-  // again with the new key/value (or null if no more matches).
-  [implicit_jscontext]
-  void continue([optional /* undefined */] in jsval key);
-
-  // Success fires IDBTransactionEvent, result == key
-  [implicit_jscontext]
-  nsIIDBRequest update(in jsval value);
-
-  // Success fires IDBTransactionEvent, result == null
-  [implicit_jscontext]
-  nsIIDBRequest delete();
-
-  void
-  advance(in long long count);
-};
deleted file mode 100644
--- a/dom/indexedDB/nsIIDBCursorWithValue.idl
+++ /dev/null
@@ -1,19 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* 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 "nsIIDBCursor.idl"
-
-/**
- * IDBCursor interface.  See
- * http://dev.w3.org/2006/webapi/WebSimpleDB/#idl-def-IDBCursor for more
- * information.
- */
-[scriptable, builtinclass, uuid(b6b7e08a-4379-4441-a176-447c5c96df69)]
-interface nsIIDBCursorWithValue : nsIIDBCursor
-{
-  [implicit_jscontext]
-  readonly attribute jsval value;
-};
--- a/dom/indexedDB/test/unit/head.js
+++ b/dom/indexedDB/test/unit/head.js
@@ -1,17 +1,16 @@
 /**
  * Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/
  */
 
 const { 'classes': Cc, 'interfaces': Ci } = Components;
 
 const DOMException = Ci.nsIDOMDOMException;
-const IDBCursor = Ci.nsIIDBCursor;
 const IDBOpenDBRequest = Ci.nsIIDBOpenDBRequest;
 const IDBRequest = Ci.nsIIDBRequest
 
 function is(a, b, msg) {
   dump("is(" + a + ", " + b + ", \"" + msg + "\")");
   do_check_eq(a, b, Components.stack.caller);
 }
 
--- a/dom/webidl/IDBCursor.webidl
+++ b/dom/webidl/IDBCursor.webidl
@@ -8,8 +8,38 @@
  */
 
 enum IDBCursorDirection {
     "next",
     "nextunique",
     "prev",
     "prevunique"
 };
+
+interface IDBCursor {
+    // This should be: readonly    attribute (IDBObjectStore or IDBIndex) source;
+    readonly    attribute nsISupports source;
+
+    readonly    attribute IDBCursorDirection           direction;
+
+    [Throws]
+    readonly    attribute any                          key;
+
+    [Throws]
+    readonly    attribute any                          primaryKey;
+
+    [Throws]
+    IDBRequest update (any value);
+
+    [Throws]
+    void       advance ([EnforceRange] unsigned long count);
+
+    [Throws]
+    void       continue (optional any key);
+
+    [Throws]
+    IDBRequest delete ();
+};
+
+interface IDBCursorWithValue : IDBCursor {
+    [Throws]
+    readonly    attribute any value;
+};
--- a/js/xpconnect/src/dom_quickstubs.qsconf
+++ b/js/xpconnect/src/dom_quickstubs.qsconf
@@ -79,18 +79,16 @@ members = [
     'nsIBoxObject.x',
     'nsIBoxObject.y',
     'nsIBoxObject.screenX',
     'nsIBoxObject.screenY',
     'nsIBoxObject.width',
     'nsIBoxObject.height',
 
     # dom/indexedDB
-    'nsIIDBCursor.*',
-    'nsIIDBCursorWithValue.*',
     'nsIIDBKeyRange.*',
     'nsIIDBRequest.*',
     'nsIIDBOpenDBRequest.*',
     'nsIIndexedDatabaseManager.*',
 
     # dom/file
     'nsIDOMLockedFile.*',