Bug 892065 - Move IDBIndex to WebIDL, r=janv
authorAndrea Marchesini <amarchesini@mozilla.com>
Wed, 31 Jul 2013 17:48:40 +0200
changeset 153073 afac636489dee5201f001d2c7153e24120856540
parent 153072 947b4570fae6827474da90120767c7ef3218dc68
child 153074 9f455064253542311a0f971eb7e9c2698cccc733
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
bugs892065
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 892065 - Move IDBIndex 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/indexedDB/IDBCursor.cpp
dom/indexedDB/IDBCursor.h
dom/indexedDB/IDBIndex.cpp
dom/indexedDB/IDBIndex.h
dom/indexedDB/IDBObjectStore.cpp
dom/indexedDB/IDBObjectStore.h
dom/indexedDB/ipc/IndexedDBParent.cpp
dom/indexedDB/moz.build
dom/indexedDB/nsIIDBIndex.idl
dom/indexedDB/test/unit/head.js
dom/webidl/IDBIndex.webidl
dom/webidl/IDBObjectStore.webidl
js/xpconnect/src/dom_quickstubs.qsconf
js/xpconnect/src/nsXPConnect.cpp
--- a/addon-sdk/source/lib/sdk/indexed-db.js
+++ b/addon-sdk/source/lib/sdk/indexed-db.js
@@ -51,10 +51,9 @@ exports.indexedDB = Object.freeze({
   cmp: indexedDB.cmp
 });
 
 exports.IDBKeyRange = IDBKeyRange;
 exports.DOMException = Ci.nsIDOMDOMException;
 exports.IDBCursor = Ci.nsIIDBCursor;
 exports.IDBOpenDBRequest = Ci.nsIIDBOpenDBRequest;
 exports.IDBDatabase = Ci.nsIIDBDatabase;
-exports.IDBIndex = Ci.nsIIDBIndex;
 exports.IDBRequest = Ci.nsIIDBRequest;
--- a/addon-sdk/source/test/test-indexed-db.js
+++ b/addon-sdk/source/test/test-indexed-db.js
@@ -4,31 +4,31 @@
 
 "use strict";
 
 let xulApp = require("sdk/system/xul-app");
 if (xulApp.versionInRange(xulApp.platformVersion, "16.0a1", "*")) {
 new function tests() {
 
 const { indexedDB, IDBKeyRange, DOMException, IDBCursor,
-        IDBOpenDBRequest, IDBDatabase, IDBIndex, IDBRequest
+        IDBOpenDBRequest, IDBDatabase, 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,
-    IDBOpenDBRequest, IDBOpenDBRequest, IDBDatabase, IDBIndex,
+    IDBOpenDBRequest, IDBOpenDBRequest, IDBDatabase,
     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
@@ -201,17 +201,16 @@
 #include "nsIMessageManager.h"
 #include "mozilla/dom/Element.h"
 
 #include "mozilla/dom/indexedDB/IDBWrapperCache.h"
 #include "mozilla/dom/indexedDB/IDBRequest.h"
 #include "mozilla/dom/indexedDB/IDBDatabase.h"
 #include "mozilla/dom/indexedDB/IDBCursor.h"
 #include "mozilla/dom/indexedDB/IDBKeyRange.h"
-#include "mozilla/dom/indexedDB/IDBIndex.h"
 
 using mozilla::dom::indexedDB::IDBWrapperCache;
 using mozilla::dom::workers::ResolveWorkerClasses;
 
 #include "nsIDOMMediaQueryList.h"
 
 #include "mozilla/dom/Activity.h"
 
@@ -638,18 +637,16 @@ static nsDOMClassInfoData sClassInfoData
   NS_DEFINE_CLASSINFO_DATA(IDBDatabase, 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(IDBIndex, nsDOMGenericSH,
-                           DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(IDBOpenDBRequest, IDBEventTargetSH,
                            IDBEVENTTARGET_SCRIPTABLE_FLAGS)
 
 
   NS_DEFINE_CLASSINFO_DATA(MozCSSKeyframeRule, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(MozCSSKeyframesRule, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
@@ -1551,20 +1548,16 @@ nsDOMClassInfo::Init()
     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(IDBIndex, nsIIDBIndex)
-    DOM_CLASSINFO_MAP_ENTRY(nsIIDBIndex)
-  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)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(MozCSSKeyframeRule, nsIDOMMozCSSKeyframeRule)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozCSSKeyframeRule)
--- a/dom/base/nsDOMClassInfoClasses.h
+++ b/dom/base/nsDOMClassInfoClasses.h
@@ -119,17 +119,16 @@ DOMCI_CLASS(ContentFrameMessageManager)
 DOMCI_CLASS(ChromeMessageBroadcaster)
 DOMCI_CLASS(ChromeMessageSender)
 
 DOMCI_CLASS(IDBRequest)
 DOMCI_CLASS(IDBDatabase)
 DOMCI_CLASS(IDBCursor)
 DOMCI_CLASS(IDBCursorWithValue)
 DOMCI_CLASS(IDBKeyRange)
-DOMCI_CLASS(IDBIndex)
 DOMCI_CLASS(IDBOpenDBRequest)
 
 
 DOMCI_CLASS(MozCSSKeyframeRule)
 DOMCI_CLASS(MozCSSKeyframesRule)
 
 DOMCI_CLASS(CSSPageRule)
 
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -541,16 +541,24 @@ DOMInterfaces = {
 'IDBFactory': {
     'nativeType': 'mozilla::dom::indexedDB::IDBFactory',
 },
 
 'IDBFileHandle': {
     'nativeType': 'mozilla::dom::indexedDB::IDBFileHandle',
 },
 
+'IDBIndex': {
+    'nativeType': 'mozilla::dom::indexedDB::IDBIndex',
+    'binaryNames': {
+        'mozGetAll': 'getAll',
+        'mozGetAllKeys': 'getAllKeys',
+    }
+},
+
 'IDBObjectStore': {
     'nativeType': 'mozilla::dom::indexedDB::IDBObjectStore',
     'implicitJSContext': [ 'createIndex' ],
     'binaryNames': {
         'mozGetAll': 'getAll'
     }
 },
 
@@ -1663,17 +1671,16 @@ addExternalIface('mozIDOMApplication', n
 addExternalIface('CSSRuleList')
 addExternalIface('DOMStringList')
 addExternalIface('RTCDataChannel', nativeType='nsIDOMDataChannel')
 addExternalIface('File')
 addExternalIface('FileCallback', nativeType='nsIFileCallback',
                  headerFile='nsIDOMHTMLCanvasElement.h')
 addExternalIface('HitRegionOptions', nativeType='nsISupports')
 addExternalIface('IDBDatabase', nativeType='nsIIDBDatabase')
-addExternalIface('IDBIndex', nativeType='nsIIDBIndex')
 addExternalIface('IDBOpenDBRequest', nativeType='nsIIDBOpenDBRequest')
 addExternalIface('IDBRequest', nativeType='nsIIDBRequest')
 addExternalIface('imgINotificationObserver', nativeType='imgINotificationObserver')
 addExternalIface('imgIRequest', nativeType='imgIRequest', notflattened=True)
 addExternalIface('LockedFile')
 addExternalIface('MediaList')
 addExternalIface('MenuBuilder', nativeType='nsIMenuBuilder', notflattened=True)
 addExternalIface('MozBluetoothManager', nativeType='nsIDOMBluetoothManager')
--- a/dom/indexedDB/IDBCursor.cpp
+++ b/dom/indexedDB/IDBCursor.cpp
@@ -268,39 +268,16 @@ IDBCursor::Create(IDBRequest* aRequest,
   cursor->mKey = aKey;
   cursor->mObjectKey = aObjectKey;
   cursor->mCloneReadInfo.Swap(aCloneReadInfo);
 
   return cursor.forget();
 }
 
 // static
-nsresult
-IDBCursor::ParseDirection(const nsAString& aDirection, Direction* aResult)
-{
-  if (aDirection.EqualsLiteral("next")) {
-    *aResult = NEXT;
-  }
-  else if (aDirection.EqualsLiteral("nextunique")) {
-    *aResult = NEXT_UNIQUE;
-  }
-  else if (aDirection.EqualsLiteral("prev")) {
-    *aResult = PREV;
-  }
-  else if (aDirection.EqualsLiteral("prevunique")) {
-    *aResult = PREV_UNIQUE;
-  }
-  else {
-    return NS_ERROR_TYPE_ERR;
-  }
-  
-  return NS_OK;
-}
-
-// static
 IDBCursor::Direction
 IDBCursor::ConvertDirection(mozilla::dom::IDBCursorDirection aDirection)
 {
   switch (aDirection) {
     case mozilla::dom::IDBCursorDirection::Next:
       return NEXT;
 
     case mozilla::dom::IDBCursorDirection::Nextunique:
--- a/dom/indexedDB/IDBCursor.h
+++ b/dom/indexedDB/IDBCursor.h
@@ -111,19 +111,16 @@ public:
     return mTransaction;
   }
 
   IDBRequest* Request() const
   {
     return mRequest;
   }
 
-  static nsresult
-  ParseDirection(const nsAString& aDirection, Direction* aResult);
-
   static Direction
   ConvertDirection(IDBCursorDirection aDirection);
 
   void
   SetActor(IndexedDBCursorChild* aActorChild)
   {
     NS_ASSERTION(!aActorChild || !mActorChild, "Shouldn't have more than one!");
     mActorChild = aActorChild;
--- a/dom/indexedDB/IDBIndex.cpp
+++ b/dom/indexedDB/IDBIndex.cpp
@@ -10,17 +10,16 @@
 
 #include "nsIIDBKeyRange.h"
 
 #include "mozilla/dom/ContentChild.h"
 #include "mozilla/dom/ContentParent.h"
 #include "mozilla/dom/ipc/Blob.h"
 #include "mozilla/storage.h"
 #include "nsContentUtils.h"
-#include "nsDOMClassInfoID.h"
 #include "nsEventDispatcher.h"
 #include "nsThreadUtils.h"
 #include "xpcpublic.h"
 
 #include "AsyncConnectionHelper.h"
 #include "DatabaseInfo.h"
 #include "IDBCursor.h"
 #include "IDBEvents.h"
@@ -32,16 +31,17 @@
 #include "ipc/IndexedDBChild.h"
 #include "ipc/IndexedDBParent.h"
 
 #include "IndexedDatabaseInlines.h"
 
 USING_INDEXEDDB_NAMESPACE
 using namespace mozilla::dom;
 using namespace mozilla::dom::indexedDB::ipc;
+using mozilla::ErrorResult;
 
 namespace {
 
 class IndexHelper : public AsyncConnectionHelper
 {
 public:
   IndexHelper(IDBTransaction* aTransaction,
               IDBRequest* aRequest,
@@ -401,16 +401,18 @@ IDBIndex::IDBIndex()
   mCachedKeyPath(JSVAL_VOID),
   mActorChild(nullptr),
   mActorParent(nullptr),
   mUnique(false),
   mMultiEntry(false),
   mRooted(false)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
+
+  SetIsDOMBinding();
 }
 
 IDBIndex::~IDBIndex()
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(!mActorParent, "Actor parent owns us, how can we be dying?!");
 
   if (mRooted) {
@@ -420,239 +422,274 @@ IDBIndex::~IDBIndex()
 
   if (mActorChild) {
     NS_ASSERTION(!IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
     mActorChild->Send__delete__(mActorChild);
     NS_ASSERTION(!mActorChild, "Should have cleared in Send__delete__!");
   }
 }
 
-nsresult
-IDBIndex::GetInternal(IDBKeyRange* aKeyRange,
-                      JSContext* aCx,
-                      IDBRequest** _retval)
+already_AddRefed<IDBRequest>
+IDBIndex::GetInternal(IDBKeyRange* aKeyRange, ErrorResult& aRv)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   IDBTransaction* transaction = mObjectStore->Transaction();
   if (!transaction->IsOpen()) {
-    return NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR;
+    aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
+    return nullptr;
   }
 
   nsRefPtr<IDBRequest> request = GenerateRequest(this);
-  NS_ENSURE_TRUE(request, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
+  if (!request) {
+    NS_WARNING("Failed to generate request!");
+    aRv.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
+    return nullptr;
+  }
 
   nsRefPtr<GetHelper> helper =
     new GetHelper(transaction, request, this, aKeyRange);
 
   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 nullptr;
+  }
 
   IDB_PROFILER_MARK("IndexedDB Request %llu: "
                     "database(%s).transaction(%s).objectStore(%s).index(%s)."
                     "get(%s)",
                     "IDBRequest[%llu] MT IDBIndex.get()",
                     request->GetSerialNumber(),
                     IDB_PROFILER_STRING(ObjectStore()->Transaction()->
                                         Database()),
                     IDB_PROFILER_STRING(ObjectStore()->Transaction()),
                     IDB_PROFILER_STRING(ObjectStore()),
                     IDB_PROFILER_STRING(this), IDB_PROFILER_STRING(aKeyRange));
 
-  request.forget(_retval);
-  return NS_OK;
+  return request.forget();
 }
 
-nsresult
-IDBIndex::GetKeyInternal(IDBKeyRange* aKeyRange,
-                         JSContext* aCx,
-                         IDBRequest** _retval)
+already_AddRefed<IDBRequest>
+IDBIndex::GetKeyInternal(IDBKeyRange* aKeyRange, ErrorResult& aRv)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   IDBTransaction* transaction = mObjectStore->Transaction();
   if (!transaction->IsOpen()) {
-    return NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR;
+    aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
+    return nullptr;
   }
 
   nsRefPtr<IDBRequest> request = GenerateRequest(this);
-  NS_ENSURE_TRUE(request, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
+  if (!request) {
+    NS_WARNING("Failed to generate request!");
+    aRv.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
+    return nullptr;
+  }
 
   nsRefPtr<GetKeyHelper> helper =
     new GetKeyHelper(transaction, request, this, aKeyRange);
 
   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 nullptr;
+  }
 
   IDB_PROFILER_MARK("IndexedDB Request %llu: "
                     "database(%s).transaction(%s).objectStore(%s).index(%s)."
                     "getKey(%s)",
                     "IDBRequest[%llu] MT IDBIndex.getKey()",
                     request->GetSerialNumber(),
                     IDB_PROFILER_STRING(ObjectStore()->Transaction()->
                                         Database()),
                     IDB_PROFILER_STRING(ObjectStore()->Transaction()),
                     IDB_PROFILER_STRING(ObjectStore()),
                     IDB_PROFILER_STRING(this), IDB_PROFILER_STRING(aKeyRange));
 
-  request.forget(_retval);
-  return NS_OK;
+  return request.forget();
 }
 
-nsresult
-IDBIndex::GetAllInternal(IDBKeyRange* aKeyRange,
-                         uint32_t aLimit,
-                         JSContext* aCx,
-                         IDBRequest** _retval)
+already_AddRefed<IDBRequest>
+IDBIndex::GetAllInternal(IDBKeyRange* aKeyRange, uint32_t aLimit,
+                         ErrorResult& aRv)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   IDBTransaction* transaction = mObjectStore->Transaction();
   if (!transaction->IsOpen()) {
-    return NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR;
+    aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
+    return nullptr;
   }
 
   nsRefPtr<IDBRequest> request = GenerateRequest(this);
-  NS_ENSURE_TRUE(request, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
+  if (!request) {
+    NS_WARNING("Failed to generate request!");
+    aRv.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
+    return nullptr;
+  }
 
   nsRefPtr<GetAllHelper> helper =
     new GetAllHelper(transaction, request, this, aKeyRange, aLimit);
 
   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 nullptr;
+  }
 
   IDB_PROFILER_MARK("IndexedDB Request %llu: "
                     "database(%s).transaction(%s).objectStore(%s).index(%s)."
                     "getAll(%s, %lu)",
                     "IDBRequest[%llu] MT IDBIndex.getAll()",
                     request->GetSerialNumber(),
                     IDB_PROFILER_STRING(ObjectStore()->Transaction()->
                                         Database()),
                     IDB_PROFILER_STRING(ObjectStore()->Transaction()),
                     IDB_PROFILER_STRING(ObjectStore()),
                     IDB_PROFILER_STRING(this),
                     IDB_PROFILER_STRING(aKeyRange), aLimit);
 
-  request.forget(_retval);
-  return NS_OK;
+  return request.forget();
 }
 
-nsresult
-IDBIndex::GetAllKeysInternal(IDBKeyRange* aKeyRange,
-                             uint32_t aLimit,
-                             JSContext* aCx,
-                             IDBRequest** _retval)
+already_AddRefed<IDBRequest>
+IDBIndex::GetAllKeysInternal(IDBKeyRange* aKeyRange, uint32_t aLimit,
+                             ErrorResult& aRv)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   IDBTransaction* transaction = mObjectStore->Transaction();
   if (!transaction->IsOpen()) {
-    return NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR;
+    aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
   }
 
   nsRefPtr<IDBRequest> request = GenerateRequest(this);
-  NS_ENSURE_TRUE(request, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
+  if (!request) {
+    NS_WARNING("Failed to generate request!");
+    aRv.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
+    return nullptr;
+  }
 
   nsRefPtr<GetAllKeysHelper> helper =
     new GetAllKeysHelper(transaction, request, this, aKeyRange, aLimit);
 
   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 nullptr;
+  }
 
   IDB_PROFILER_MARK("IndexedDB Request %llu: "
                     "database(%s).transaction(%s).objectStore(%s).index(%s)."
                     "getAllKeys(%s, %lu)",
                     "IDBRequest[%llu] MT IDBIndex.getAllKeys()",
                     request->GetSerialNumber(),
                     IDB_PROFILER_STRING(ObjectStore()->Transaction()->
                                         Database()),
                     IDB_PROFILER_STRING(ObjectStore()->Transaction()),
                     IDB_PROFILER_STRING(ObjectStore()),
                     IDB_PROFILER_STRING(this), IDB_PROFILER_STRING(aKeyRange),
                     aLimit);
 
-  request.forget(_retval);
-  return NS_OK;
+  return request.forget();
 }
 
-nsresult
-IDBIndex::CountInternal(IDBKeyRange* aKeyRange,
-                        JSContext* aCx,
-                        IDBRequest** _retval)
+already_AddRefed<IDBRequest>
+IDBIndex::CountInternal(IDBKeyRange* aKeyRange, ErrorResult& aRv)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   IDBTransaction* transaction = mObjectStore->Transaction();
   if (!transaction->IsOpen()) {
-    return NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR;
+    aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
+    return nullptr;
   }
 
   nsRefPtr<IDBRequest> request = GenerateRequest(this);
-  NS_ENSURE_TRUE(request, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
+  if (!request) {
+    NS_WARNING("Failed to generate request!");
+    aRv.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
+    return nullptr;
+  }
 
   nsRefPtr<CountHelper> helper =
     new CountHelper(transaction, request, this, aKeyRange);
 
   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 nullptr;
+  }
 
   IDB_PROFILER_MARK("IndexedDB Request %llu: "
                     "database(%s).transaction(%s).objectStore(%s).index(%s)."
                     "count(%s)",
                     "IDBRequest[%llu] MT IDBIndex.count()",
                     request->GetSerialNumber(),
                     IDB_PROFILER_STRING(ObjectStore()->Transaction()->
                                         Database()),
                     IDB_PROFILER_STRING(ObjectStore()->Transaction()),
                     IDB_PROFILER_STRING(ObjectStore()),
                     IDB_PROFILER_STRING(this), IDB_PROFILER_STRING(aKeyRange));
 
-  request.forget(_retval);
-  return NS_OK;
+  return request.forget();
 }
 
-nsresult
-IDBIndex::OpenKeyCursorInternal(IDBKeyRange* aKeyRange,
-                                size_t aDirection,
-                                JSContext* aCx,
-                                IDBRequest** _retval)
+already_AddRefed<IDBRequest>
+IDBIndex::OpenKeyCursorInternal(IDBKeyRange* aKeyRange, size_t aDirection,
+                                ErrorResult& aRv)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   IDBTransaction* transaction = mObjectStore->Transaction();
   if (!transaction->IsOpen()) {
-    return NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR;
+    aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
+    return nullptr;
   }
 
   IDBCursor::Direction direction =
     static_cast<IDBCursor::Direction>(aDirection);
 
   nsRefPtr<IDBRequest> request = GenerateRequest(this);
-  NS_ENSURE_TRUE(request, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
+  if (!request) {
+    NS_WARNING("Failed to generate request!");
+    aRv.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
+    return nullptr;
+  }
 
   nsRefPtr<OpenKeyCursorHelper> helper =
     new OpenKeyCursorHelper(transaction, request, this, aKeyRange, direction);
 
   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 nullptr;
+  }
 
   IDB_PROFILER_MARK("IndexedDB Request %llu: "
                     "database(%s).transaction(%s).objectStore(%s).index(%s)."
                     "openKeyCursor(%s)",
                     "IDBRequest[%llu] MT IDBIndex.openKeyCursor()",
                     request->GetSerialNumber(),
                     IDB_PROFILER_STRING(ObjectStore()->Transaction()->
                                         Database()),
                     IDB_PROFILER_STRING(ObjectStore()->Transaction()),
                     IDB_PROFILER_STRING(ObjectStore()),
                     IDB_PROFILER_STRING(this), IDB_PROFILER_STRING(aKeyRange),
                     IDB_PROFILER_STRING(direction));
 
-  request.forget(_retval);
-  return NS_OK;
+  return request.forget();
 }
 
 nsresult
 IDBIndex::OpenCursorInternal(IDBKeyRange* aKeyRange,
                              size_t aDirection,
                              IDBRequest** _retval)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
@@ -746,346 +783,255 @@ IDBIndex::OpenCursorFromChildProcess(
 
   NS_ASSERTION(!cloneInfo.mCloneBuffer.data(), "Should have swapped!");
 
   cursor.forget(_retval);
   return NS_OK;
 }
 
 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(IDBIndex)
+  NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
   NS_IMPL_CYCLE_COLLECTION_TRACE_JSVAL_MEMBER_CALLBACK(mCachedKeyPath)
 NS_IMPL_CYCLE_COLLECTION_TRACE_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(IDBIndex)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mObjectStore)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(IDBIndex)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
+
   // Don't unlink mObjectStore!
 
   tmp->mCachedKeyPath = JSVAL_VOID;
 
   if (tmp->mRooted) {
     NS_DROP_JS_OBJECTS(tmp, IDBIndex);
     tmp->mRooted = false;
   }
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(IDBIndex)
-  NS_INTERFACE_MAP_ENTRY(nsIIDBIndex)
-  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(IDBIndex)
+  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_INTERFACE_MAP_ENTRY(nsISupports)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(IDBIndex)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(IDBIndex)
 
-DOMCI_DATA(IDBIndex, IDBIndex)
-
-NS_IMETHODIMP
-IDBIndex::GetName(nsAString& aName)
+JSObject*
+IDBIndex::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
 {
-  NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
-
-  aName.Assign(mName);
-  return NS_OK;
+  return IDBIndexBinding::Wrap(aCx, aScope, this);
 }
 
-NS_IMETHODIMP
-IDBIndex::GetStoreName(nsAString& aStoreName)
-{
-  NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
-
-  aStoreName.Assign(mObjectStore->Name());
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-IDBIndex::GetKeyPath(JSContext* aCx,
-                     jsval* aVal)
+JS::Value
+IDBIndex::GetKeyPath(JSContext* aCx, ErrorResult& aRv)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   if (!JSVAL_IS_VOID(mCachedKeyPath)) {
-    *aVal = mCachedKeyPath;
-    return NS_OK;
+    return mCachedKeyPath;
   }
 
-  nsresult rv = GetKeyPath().ToJSVal(aCx, mCachedKeyPath);
-  NS_ENSURE_SUCCESS(rv, rv);
+  aRv = GetKeyPath().ToJSVal(aCx, mCachedKeyPath);
+  ENSURE_SUCCESS(aRv, JSVAL_VOID);
 
   if (JSVAL_IS_GCTHING(mCachedKeyPath)) {
     NS_HOLD_JS_OBJECTS(this, IDBIndex);
     mRooted = true;
   }
 
-  *aVal = mCachedKeyPath;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-IDBIndex::GetUnique(bool* aUnique)
-{
-  NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
-
-  *aUnique = mUnique;
-  return NS_OK;
+  return mCachedKeyPath;
 }
 
-NS_IMETHODIMP
-IDBIndex::GetMultiEntry(bool* aMultiEntry)
-{
-  NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
-
-  *aMultiEntry = mMultiEntry;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-IDBIndex::GetObjectStore(nsISupports** aObjectStore)
-{
-  NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
-
-  nsCOMPtr<nsISupports> objectStore(mObjectStore);
-  objectStore.forget(aObjectStore);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-IDBIndex::Get(const jsval& aKey,
-              JSContext* aCx,
-              nsIIDBRequest** _retval)
+already_AddRefed<IDBRequest>
+IDBIndex::Get(JSContext* aCx, JS::Handle<JS::Value> aKey, ErrorResult& aRv)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   IDBTransaction* transaction = mObjectStore->Transaction();
   if (!transaction->IsOpen()) {
-    return NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR;
+    aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
+    return nullptr;
   }
 
   nsRefPtr<IDBKeyRange> keyRange;
-  nsresult rv = IDBKeyRange::FromJSVal(aCx, aKey, getter_AddRefs(keyRange));
-  NS_ENSURE_SUCCESS(rv, rv);
+  aRv = IDBKeyRange::FromJSVal(aCx, aKey, getter_AddRefs(keyRange));
+  ENSURE_SUCCESS(aRv, nullptr);
 
   if (!keyRange) {
-    // Must specify a key or keyRange for get().
-    return NS_ERROR_DOM_INDEXEDDB_DATA_ERR;
+    // Must specify a key or keyRange for getKey().
+    aRv.Throw(NS_ERROR_DOM_INDEXEDDB_DATA_ERR);
+    return nullptr;
   }
 
-  nsRefPtr<IDBRequest> request;
-  rv = GetInternal(keyRange, aCx, getter_AddRefs(request));
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  request.forget(_retval);
-  return NS_OK;
+  return GetInternal(keyRange, aRv);
 }
 
-NS_IMETHODIMP
-IDBIndex::GetKey(const jsval& aKey,
-                 JSContext* aCx,
-                 nsIIDBRequest** _retval)
+already_AddRefed<IDBRequest>
+IDBIndex::GetKey(JSContext* aCx, JS::Handle<JS::Value> aKey, ErrorResult& aRv)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   IDBTransaction* transaction = mObjectStore->Transaction();
   if (!transaction->IsOpen()) {
-    return NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR;
+    aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
+    return nullptr;
   }
 
   nsRefPtr<IDBKeyRange> keyRange;
-  nsresult rv = IDBKeyRange::FromJSVal(aCx, aKey, getter_AddRefs(keyRange));
-  NS_ENSURE_SUCCESS(rv, rv);
+  aRv = IDBKeyRange::FromJSVal(aCx, aKey, getter_AddRefs(keyRange));
+  ENSURE_SUCCESS(aRv, nullptr);
 
   if (!keyRange) {
     // Must specify a key or keyRange for get().
-    return NS_ERROR_DOM_INDEXEDDB_DATA_ERR;
+    aRv.Throw(NS_ERROR_DOM_INDEXEDDB_DATA_ERR);
+    return nullptr;
   }
 
-  nsRefPtr<IDBRequest> request;
-  rv = GetKeyInternal(keyRange, aCx, getter_AddRefs(request));
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  request.forget(_retval);
-  return NS_OK;
+  return GetKeyInternal(keyRange, aRv);
 }
 
-NS_IMETHODIMP
-IDBIndex::GetAll(const jsval& aKey,
-                 uint32_t aLimit,
-                 JSContext* aCx,
-                 uint8_t aOptionalArgCount,
-                 nsIIDBRequest** _retval)
+already_AddRefed<IDBRequest>
+IDBIndex::GetAll(JSContext* aCx, const Optional<JS::Handle<JS::Value> >& aKey,
+                 const Optional<uint32_t>& aLimit, ErrorResult& aRv)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   IDBTransaction* transaction = mObjectStore->Transaction();
   if (!transaction->IsOpen()) {
-    return NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR;
+    aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
+    return nullptr;
   }
 
-  nsresult rv;
-
   nsRefPtr<IDBKeyRange> keyRange;
-  if (aOptionalArgCount) {
-    rv = IDBKeyRange::FromJSVal(aCx, aKey, getter_AddRefs(keyRange));
-    NS_ENSURE_SUCCESS(rv, rv);
+  if (aKey.WasPassed()) {
+    aRv = IDBKeyRange::FromJSVal(aCx, aKey.Value(), getter_AddRefs(keyRange));
+    ENSURE_SUCCESS(aRv, nullptr);
   }
 
-  if (aOptionalArgCount < 2 || aLimit == 0) {
-    aLimit = UINT32_MAX;
+  uint32_t limit = UINT32_MAX;
+  if (aLimit.WasPassed() && aLimit.Value() > 0) {
+    limit = aLimit.Value();
   }
 
-  nsRefPtr<IDBRequest> request;
-  rv = GetAllInternal(keyRange, aLimit, aCx, getter_AddRefs(request));
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  request.forget(_retval);
-  return NS_OK;
+  return GetAllInternal(keyRange, limit, aRv);
 }
 
-NS_IMETHODIMP
-IDBIndex::GetAllKeys(const jsval& aKey,
-                     uint32_t aLimit,
-                     JSContext* aCx,
-                     uint8_t aOptionalArgCount,
-                     nsIIDBRequest** _retval)
+already_AddRefed<IDBRequest>
+IDBIndex::GetAllKeys(JSContext* aCx,
+                     const Optional<JS::Handle<JS::Value> >& aKey,
+                     const Optional<uint32_t>& aLimit, ErrorResult& aRv)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   IDBTransaction* transaction = mObjectStore->Transaction();
   if (!transaction->IsOpen()) {
-    return NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR;
+    aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
+    return nullptr;
   }
 
-  nsresult rv;
-
   nsRefPtr<IDBKeyRange> keyRange;
-  if (aOptionalArgCount) {
-    rv = IDBKeyRange::FromJSVal(aCx, aKey, getter_AddRefs(keyRange));
-    NS_ENSURE_SUCCESS(rv, rv);
+  if (aKey.WasPassed()) {
+    aRv = IDBKeyRange::FromJSVal(aCx, aKey.Value(), getter_AddRefs(keyRange));
+    ENSURE_SUCCESS(aRv, nullptr);
   }
 
-  if (aOptionalArgCount < 2 || aLimit == 0) {
-    aLimit = UINT32_MAX;
+  uint32_t limit = UINT32_MAX;
+  if (aLimit.WasPassed() && aLimit.Value() > 0) {
+    limit = aLimit.Value();
   }
 
-  nsRefPtr<IDBRequest> request;
-  rv = GetAllKeysInternal(keyRange, aLimit, aCx, getter_AddRefs(request));
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  request.forget(_retval);
-  return NS_OK;
+  return GetAllKeysInternal(keyRange, limit, aRv);
 }
 
-NS_IMETHODIMP
-IDBIndex::OpenCursor(const jsval& aKey,
-                     const nsAString& aDirection,
-                     JSContext* aCx,
-                     uint8_t aOptionalArgCount,
-                     nsIIDBRequest** _retval)
+already_AddRefed<IDBRequest>
+IDBIndex::OpenCursor(JSContext* aCx,
+                     const Optional<JS::Handle<JS::Value> >& aRange,
+                     IDBCursorDirection aDirection, ErrorResult& aRv)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   IDBTransaction* transaction = mObjectStore->Transaction();
   if (!transaction->IsOpen()) {
-    return NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR;
+    aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
+    return nullptr;
   }
 
-  nsresult rv;
-
-  IDBCursor::Direction direction = IDBCursor::NEXT;
-
   nsRefPtr<IDBKeyRange> keyRange;
-  if (aOptionalArgCount) {
-    rv = IDBKeyRange::FromJSVal(aCx, aKey, getter_AddRefs(keyRange));
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    if (aOptionalArgCount >= 2) {
-      rv = IDBCursor::ParseDirection(aDirection, &direction);
-      NS_ENSURE_SUCCESS(rv, rv);
-    }
+  if (aRange.WasPassed()) {
+    aRv = IDBKeyRange::FromJSVal(aCx, aRange.Value(), getter_AddRefs(keyRange));
+    ENSURE_SUCCESS(aRv, nullptr);
   }
 
+  IDBCursor::Direction direction = IDBCursor::ConvertDirection(aDirection);
+
   nsRefPtr<IDBRequest> request = GenerateRequest(this);
-  NS_ENSURE_TRUE(request, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
+  if (!request) {
+    NS_WARNING("Failed to generate request!");
+    aRv.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
+    return nullptr;
+  }
 
   nsRefPtr<OpenCursorHelper> helper =
     new OpenCursorHelper(transaction, request, this, keyRange, direction);
 
-  rv = helper->DispatchToTransactionPool();
-  NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
-
-  request.forget(_retval);
-  return NS_OK;
+  nsresult rv = helper->DispatchToTransactionPool();
+  if (NS_FAILED(rv)) {
+    NS_WARNING("Failed to dispatch!");
+    aRv.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
+    return nullptr;
+  }
+
+  return request.forget();
 }
 
-NS_IMETHODIMP
-IDBIndex::OpenKeyCursor(const jsval& aKey,
-                        const nsAString& aDirection,
-                        JSContext* aCx,
-                        uint8_t aOptionalArgCount,
-                        nsIIDBRequest** _retval)
+already_AddRefed<IDBRequest>
+IDBIndex::OpenKeyCursor(JSContext* aCx,
+                        const Optional<JS::Handle<JS::Value> >& aRange,
+                        IDBCursorDirection aDirection, ErrorResult& aRv)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   IDBTransaction* transaction = mObjectStore->Transaction();
   if (!transaction->IsOpen()) {
-    return NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR;
+    aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
+    return nullptr;
   }
 
-  nsresult rv;
-
-  IDBCursor::Direction direction = IDBCursor::NEXT;
-
   nsRefPtr<IDBKeyRange> keyRange;
-  if (aOptionalArgCount) {
-    rv = IDBKeyRange::FromJSVal(aCx, aKey, getter_AddRefs(keyRange));
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    if (aOptionalArgCount >= 2) {
-      rv = IDBCursor::ParseDirection(aDirection, &direction);
-      NS_ENSURE_SUCCESS(rv, rv);
-    }
+  if (aRange.WasPassed()) {
+    aRv = IDBKeyRange::FromJSVal(aCx, aRange.Value(), getter_AddRefs(keyRange));
+    ENSURE_SUCCESS(aRv, nullptr);
   }
 
-  nsRefPtr<IDBRequest> request;
-  rv = OpenKeyCursorInternal(keyRange, direction, aCx,
-                             getter_AddRefs(request));
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  request.forget(_retval);
-  return NS_OK;
+  IDBCursor::Direction direction = IDBCursor::ConvertDirection(aDirection);
+
+  return OpenKeyCursorInternal(keyRange, direction, aRv);
 }
 
-NS_IMETHODIMP
-IDBIndex::Count(const jsval& aKey,
-                JSContext* aCx,
-                uint8_t aOptionalArgCount,
-                nsIIDBRequest** _retval)
+already_AddRefed<IDBRequest>
+IDBIndex::Count(JSContext* aCx, const Optional<JS::Handle<JS::Value> >& aKey,
+                ErrorResult& aRv)
 {
   IDBTransaction* transaction = mObjectStore->Transaction();
   if (!transaction->IsOpen()) {
-    return NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR;
+    aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
+    return nullptr;
   }
 
-  nsresult rv;
-
   nsRefPtr<IDBKeyRange> keyRange;
-  if (aOptionalArgCount) {
-    rv = IDBKeyRange::FromJSVal(aCx, aKey, getter_AddRefs(keyRange));
-    NS_ENSURE_SUCCESS(rv, rv);
+  if (aKey.WasPassed()) {
+    aRv = IDBKeyRange::FromJSVal(aCx, aKey.Value(), getter_AddRefs(keyRange));
+    ENSURE_SUCCESS(aRv, nullptr);
   }
 
-  nsRefPtr<IDBRequest> request;
-  rv = CountInternal(keyRange, aCx, getter_AddRefs(request));
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  request.forget(_retval);
-  return NS_OK;
+  return CountInternal(keyRange, aRv);
 }
 
 void
 IndexHelper::ReleaseMainThreadObjects()
 {
   mIndex = nullptr;
   AsyncConnectionHelper::ReleaseMainThreadObjects();
 }
--- a/dom/indexedDB/IDBIndex.h
+++ b/dom/indexedDB/IDBIndex.h
@@ -3,21 +3,26 @@
 /* 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_indexeddb_idbindex_h__
 #define mozilla_dom_indexeddb_idbindex_h__
 
 #include "mozilla/dom/indexedDB/IndexedDatabase.h"
-#include "mozilla/dom/indexedDB/KeyPath.h"
 
-#include "nsIIDBIndex.h"
+#include "mozilla/Attributes.h"
+#include "mozilla/dom/IDBCursorBinding.h"
+#include "mozilla/ErrorResult.h"
+#include "nsCycleCollectionParticipant.h"
+#include "nsWrapperCache.h"
 
-#include "nsCycleCollectionParticipant.h"
+#include "mozilla/dom/indexedDB/IDBObjectStore.h"
+#include "mozilla/dom/indexedDB/IDBRequest.h"
+#include "mozilla/dom/indexedDB/KeyPath.h"
 
 class nsIScriptContext;
 class nsPIDOMWindow;
 
 BEGIN_INDEXEDDB_NAMESPACE
 
 class AsyncConnectionHelper;
 class IDBCursor;
@@ -25,22 +30,21 @@ class IDBKeyRange;
 class IDBObjectStore;
 class IDBRequest;
 class IndexedDBIndexChild;
 class IndexedDBIndexParent;
 class Key;
 
 struct IndexInfo;
 
-class IDBIndex MOZ_FINAL : public nsIIDBIndex
+class IDBIndex MOZ_FINAL : public nsISupports,
+                           public nsWrapperCache
 {
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
-  NS_DECL_NSIIDBINDEX
-
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(IDBIndex)
 
   static already_AddRefed<IDBIndex>
   Create(IDBObjectStore* aObjectStore,
          const IndexInfo* aIndexInfo,
          bool aCreating);
 
   IDBObjectStore* ObjectStore()
@@ -95,63 +99,138 @@ public:
   }
 
   IndexedDBIndexParent*
   GetActorParent() const
   {
     return mActorParent;
   }
 
-  nsresult GetInternal(IDBKeyRange* aKeyRange,
-                       JSContext* aCx,
-                       IDBRequest** _retval);
+  already_AddRefed<IDBRequest>
+  GetInternal(IDBKeyRange* aKeyRange,
+              ErrorResult& aRv);
 
-  nsresult GetKeyInternal(IDBKeyRange* aKeyRange,
-                          JSContext* aCx,
-                          IDBRequest** _retval);
+  already_AddRefed<IDBRequest>
+  GetKeyInternal(IDBKeyRange* aKeyRange,
+                 ErrorResult& aRv);
 
-  nsresult GetAllInternal(IDBKeyRange* aKeyRange,
-                          uint32_t aLimit,
-                          JSContext* aCx,
-                          IDBRequest** _retval);
+  already_AddRefed<IDBRequest>
+  GetAllInternal(IDBKeyRange* aKeyRange,
+                 uint32_t aLimit,
+                 ErrorResult& aRv);
 
-  nsresult GetAllKeysInternal(IDBKeyRange* aKeyRange,
-                              uint32_t aLimit,
-                              JSContext* aCx,
-                              IDBRequest** _retval);
+  already_AddRefed<IDBRequest>
+  GetAllKeysInternal(IDBKeyRange* aKeyRange,
+                     uint32_t aLimit,
+                     ErrorResult& aRv);
 
-  nsresult CountInternal(IDBKeyRange* aKeyRange,
-                         JSContext* aCx,
-                         IDBRequest** _retval);
+  already_AddRefed<IDBRequest>
+  CountInternal(IDBKeyRange* aKeyRange,
+                ErrorResult& aRv);
 
   nsresult OpenCursorFromChildProcess(
                             IDBRequest* aRequest,
                             size_t aDirection,
                             const Key& aKey,
                             const Key& aObjectKey,
                             IDBCursor** _retval);
 
-  nsresult OpenKeyCursorInternal(IDBKeyRange* aKeyRange,
-                                 size_t aDirection,
-                                 JSContext* aCx,
-                                 IDBRequest** _retval);
+  already_AddRefed<IDBRequest>
+  OpenKeyCursorInternal(IDBKeyRange* aKeyRange,
+                        size_t aDirection,
+                        ErrorResult& aRv);
 
   nsresult OpenCursorInternal(IDBKeyRange* aKeyRange,
                               size_t aDirection,
                               IDBRequest** _retval);
 
   nsresult OpenCursorFromChildProcess(
                             IDBRequest* aRequest,
                             size_t aDirection,
                             const Key& aKey,
                             const Key& aObjectKey,
                             const SerializedStructuredCloneReadInfo& aCloneInfo,
                             nsTArray<StructuredCloneFile>& aBlobs,
                             IDBCursor** _retval);
 
+  // nsWrapperCache
+  virtual JSObject*
+  WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
+
+  // WebIDL
+  IDBObjectStore*
+  GetParentObject() const
+  {
+    return mObjectStore;
+  }
+
+  void
+  GetName(nsString& aName) const
+  {
+    NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
+    aName.Assign(mName);
+  }
+
+  IDBObjectStore*
+  ObjectStore() const
+  {
+    NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
+    return mObjectStore;
+  }
+
+  JS::Value
+  GetKeyPath(JSContext* aCx, ErrorResult& aRv);
+
+  bool
+  MultiEntry() const
+  {
+    NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
+    return mMultiEntry;
+  }
+
+  bool
+  Unique() const
+  {
+    NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
+    return mUnique;
+  }
+
+  already_AddRefed<IDBRequest>
+  OpenCursor(JSContext* aCx, const Optional<JS::Handle<JS::Value> >& aRange,
+             IDBCursorDirection aDirection, ErrorResult& aRv);
+
+  already_AddRefed<IDBRequest>
+  OpenKeyCursor(JSContext* aCx, const Optional<JS::Handle<JS::Value> >& aRange,
+                IDBCursorDirection aDirection, ErrorResult& aRv);
+
+  already_AddRefed<IDBRequest>
+  Get(JSContext* aCx, JS::Handle<JS::Value> aKey, ErrorResult& aRv);
+
+  already_AddRefed<IDBRequest>
+  GetKey(JSContext* aCx, JS::Handle<JS::Value> aKey, ErrorResult& aRv);
+
+  already_AddRefed<IDBRequest>
+  Count(JSContext* aCx, const Optional<JS::Handle<JS::Value> >& aKey,
+         ErrorResult& aRv);
+
+  void
+  GetStoreName(nsString& aStoreName) const
+  {
+    NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
+    mObjectStore->GetName(aStoreName);
+  }
+
+  already_AddRefed<IDBRequest>
+  GetAll(JSContext* aCx, const Optional<JS::Handle<JS::Value> >& aKey,
+         const Optional<uint32_t>& aLimit, ErrorResult& aRv);
+
+  already_AddRefed<IDBRequest>
+  GetAllKeys(JSContext* aCx, const Optional<JS::Handle<JS::Value> >& aKey,
+             const Optional<uint32_t>& aLimit, ErrorResult& aRv);
+
 private:
   IDBIndex();
   ~IDBIndex();
 
   nsRefPtr<IDBObjectStore> mObjectStore;
 
   int64_t mId;
   nsString mName;
--- a/dom/indexedDB/IDBObjectStore.cpp
+++ b/dom/indexedDB/IDBObjectStore.cpp
@@ -2288,17 +2288,17 @@ void
 IDBObjectStore::SetInfo(ObjectStoreInfo* aInfo)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread");
   NS_ASSERTION(aInfo != mInfo, "This is nonsense");
 
   mInfo = aInfo;
 }
 
-already_AddRefed<nsIIDBIndex>
+already_AddRefed<IDBIndex>
 IDBObjectStore::CreateIndexInternal(const IndexInfo& aInfo, ErrorResult& aRv)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   IndexInfo* indexInfo = mInfo->indexes.AppendElement();
 
   indexInfo->name = aInfo.name;
   indexInfo->id = aInfo.id;
@@ -2333,17 +2333,17 @@ IDBObjectStore::CreateIndexInternal(cons
                     "MT IDBObjectStore.createIndex()",
                     IDB_PROFILER_STRING(Transaction()->Database()),
                     IDB_PROFILER_STRING(Transaction()),
                     IDB_PROFILER_STRING(this), IDB_PROFILER_STRING(index));
 
   return index.forget();
 }
 
-already_AddRefed<nsIIDBIndex>
+already_AddRefed<IDBIndex>
 IDBObjectStore::Index(const nsAString& aName, ErrorResult &aRv)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   if (mTransaction->IsFinished()) {
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
     return nullptr;
   }
@@ -2395,17 +2395,17 @@ NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(IDB
 NS_IMPL_CYCLE_COLLECTION_TRACE_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(IDBObjectStore)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTransaction)
 
   for (uint32_t i = 0; i < tmp->mCreatedIndexes.Length(); i++) {
     NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mCreatedIndexes[i]");
-    cb.NoteXPCOMChild(static_cast<nsIIDBIndex*>(tmp->mCreatedIndexes[i].get()));
+    cb.NoteXPCOMChild(static_cast<nsISupports*>(tmp->mCreatedIndexes[i].get()));
   }
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(IDBObjectStore)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
 
   // Don't unlink mTransaction!
 
@@ -2577,17 +2577,17 @@ IDBObjectStore::OpenCursor(JSContext* aC
   }
 
   IDBCursor::Direction direction = IDBCursor::ConvertDirection(aDirection);
   size_t argDirection = static_cast<size_t>(direction);
 
   return OpenCursorInternal(keyRange, argDirection, aRv);
 }
 
-already_AddRefed<nsIIDBIndex>
+already_AddRefed<IDBIndex>
 IDBObjectStore::CreateIndex(JSContext* aCx, const nsAString& aName,
                             const nsAString& aKeyPath,
                             const IDBIndexParameters& aOptionalParameters,
                             ErrorResult& aRv)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   KeyPath keyPath(0);
@@ -2595,17 +2595,17 @@ IDBObjectStore::CreateIndex(JSContext* a
       !keyPath.IsValid()) {
     aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
     return nullptr;
   }
 
   return CreateIndex(aCx, aName, keyPath, aOptionalParameters, aRv);
 }
 
-already_AddRefed<nsIIDBIndex>
+already_AddRefed<IDBIndex>
 IDBObjectStore::CreateIndex(JSContext* aCx, const nsAString& aName,
                             const Sequence<nsString >& aKeyPath,
                             const IDBIndexParameters& aOptionalParameters,
                             ErrorResult& aRv)
 {
   NS_PRECONDITION(NS_IsMainThread(), "Wrong thread!");
 
   if (!aKeyPath.Length()) {
@@ -2617,17 +2617,17 @@ IDBObjectStore::CreateIndex(JSContext* a
   if (NS_FAILED(KeyPath::Parse(aCx, aKeyPath, &keyPath))) {
     aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
     return nullptr;
   }
 
   return CreateIndex(aCx, aName, keyPath, aOptionalParameters, aRv);
 }
 
-already_AddRefed<nsIIDBIndex>
+already_AddRefed<IDBIndex>
 IDBObjectStore::CreateIndex(JSContext* aCx, const nsAString& aName,
                             KeyPath& aKeyPath,
                             const IDBIndexParameters& aOptionalParameters,
                             ErrorResult& aRv)
 {
   // Check name and current mode
   IDBTransaction* transaction = AsyncConnectionHelper::GetCurrentTransaction();
 
--- a/dom/indexedDB/IDBObjectStore.h
+++ b/dom/indexedDB/IDBObjectStore.h
@@ -16,17 +16,16 @@
 
 #include "mozilla/dom/indexedDB/IDBRequest.h"
 #include "mozilla/dom/indexedDB/IDBTransaction.h"
 #include "mozilla/dom/indexedDB/KeyPath.h"
 
 class nsIDOMBlob;
 class nsIScriptContext;
 class nsPIDOMWindow;
-class nsIIDBIndex;
 
 namespace mozilla {
 namespace dom {
 class ContentParent;
 class PBlobChild;
 class PBlobParent;
 }
 }
@@ -194,17 +193,17 @@ public:
   }
 
   IndexedDBObjectStoreParent*
   GetActorParent() const
   {
     return mActorParent;
   }
 
-  already_AddRefed<nsIIDBIndex>
+  already_AddRefed<IDBIndex>
   CreateIndexInternal(const IndexInfo& aInfo,
                       ErrorResult& aRv);
 
   nsresult AddOrPutInternal(
                       const SerializedStructuredCloneWriteInfo& aCloneWriteInfo,
                       const Key& aKey,
                       const InfallibleTArray<IndexUpdateInfo>& aUpdateInfoArray,
                       const nsTArray<nsCOMPtr<nsIDOMBlob> >& aBlobs,
@@ -308,26 +307,26 @@ public:
 
   already_AddRefed<IDBRequest>
   Clear(ErrorResult& aRv);
 
   already_AddRefed<IDBRequest>
   OpenCursor(JSContext* aCx, const Optional<JS::Handle<JS::Value> >& aRange,
              IDBCursorDirection aDirection, ErrorResult& aRv);
 
-  already_AddRefed<nsIIDBIndex>
+  already_AddRefed<IDBIndex>
   CreateIndex(JSContext* aCx, const nsAString& aName, const nsAString& aKeyPath,
               const IDBIndexParameters& aOptionalParameters, ErrorResult& aRv);
 
-  already_AddRefed<nsIIDBIndex>
+  already_AddRefed<IDBIndex>
   CreateIndex(JSContext* aCx, const nsAString& aName,
               const Sequence<nsString >& aKeyPath,
               const IDBIndexParameters& aOptionalParameters, ErrorResult& aRv);
 
-  already_AddRefed<nsIIDBIndex>
+  already_AddRefed<IDBIndex>
   Index(const nsAString& aName, ErrorResult &aRv);
 
   void
   DeleteIndex(const nsAString& aIndexName, ErrorResult& aRv);
 
   already_AddRefed<IDBRequest>
   Count(JSContext* aCx, const Optional<JS::Handle<JS::Value> >& aKey,
         ErrorResult& aRv);
@@ -347,17 +346,17 @@ protected:
                       Key& aKey,
                       nsTArray<IndexUpdateInfo>& aUpdateInfoArray);
 
   already_AddRefed<IDBRequest>
   AddOrPut(JSContext* aCx, JS::Handle<JS::Value> aValue,
            const Optional<JS::Handle<JS::Value> >& aKey, bool aOverwrite,
            ErrorResult& aRv);
 
-  already_AddRefed<nsIIDBIndex>
+  already_AddRefed<IDBIndex>
   CreateIndex(JSContext* aCx, const nsAString& aName, KeyPath& aKeyPath,
               const IDBIndexParameters& aOptionalParameters, ErrorResult& aRv);
 
   static void
   ClearStructuredCloneBuffer(JSAutoStructuredCloneBuffer& aBuffer);
 
   static bool
   ReadFileHandle(JSStructuredCloneReader* aReader,
--- a/dom/indexedDB/ipc/IndexedDBParent.cpp
+++ b/dom/indexedDB/ipc/IndexedDBParent.cpp
@@ -1145,20 +1145,19 @@ IndexedDBObjectStoreParent::RecvPIndexed
     const nsString& name = params.name();
 
     nsRefPtr<IDBIndex> index;
 
     {
       AutoSetCurrentTransaction asct(mObjectStore->Transaction());
 
       ErrorResult rv;
-      nsCOMPtr<nsIIDBIndex> obj = mObjectStore->Index(name, rv);
+      index = mObjectStore->Index(name, rv);
       ENSURE_SUCCESS(rv, false);
 
-      index = static_cast<IDBIndex*>(obj.get());
       actor->SetIndex(index);
     }
 
     index->SetActor(actor);
     return true;
   }
 
   if (aParams.type() == IndexConstructorParams::TCreateIndexParams) {
@@ -1293,20 +1292,18 @@ IndexedDBVersionChangeObjectStoreParent:
     const IndexInfo& info = params.info();
 
     nsRefPtr<IDBIndex> index;
 
     {
       AutoSetCurrentTransaction asct(mObjectStore->Transaction());
 
       ErrorResult rv;
-      nsCOMPtr<nsIIDBIndex> obj = mObjectStore->CreateIndexInternal(info, rv);
+      index = mObjectStore->CreateIndexInternal(info, rv);
       ENSURE_SUCCESS(rv, false);
-
-      index = static_cast<IDBIndex*>(obj.get());
     }
 
     actor->SetIndex(index);
     index->SetActor(actor);
     return true;
   }
 
   return IndexedDBObjectStoreParent::RecvPIndexedDBIndexConstructor(aActor,
@@ -1780,19 +1777,19 @@ IndexedDBIndexRequestParent::Get(const G
 
   nsRefPtr<IDBKeyRange> keyRange =
     IDBKeyRange::FromSerializedKeyRange(aParams.keyRange());
   MOZ_ASSERT(keyRange);
 
   {
     AutoSetCurrentTransaction asct(mIndex->ObjectStore()->Transaction());
 
-    nsresult rv = mIndex->GetInternal(keyRange, nullptr,
-                                      getter_AddRefs(request));
-    NS_ENSURE_SUCCESS(rv, false);
+    ErrorResult rv;
+    request = mIndex->GetInternal(keyRange, rv);
+    ENSURE_SUCCESS(rv, false);
   }
 
   request->SetActor(this);
   mRequest.swap(request);
   return true;
 }
 
 bool
@@ -1805,19 +1802,19 @@ IndexedDBIndexRequestParent::GetKey(cons
 
   nsRefPtr<IDBKeyRange> keyRange =
     IDBKeyRange::FromSerializedKeyRange(aParams.keyRange());
   MOZ_ASSERT(keyRange);
 
   {
     AutoSetCurrentTransaction asct(mIndex->ObjectStore()->Transaction());
 
-    nsresult rv = mIndex->GetKeyInternal(keyRange, nullptr,
-                                         getter_AddRefs(request));
-    NS_ENSURE_SUCCESS(rv, false);
+    ErrorResult rv;
+    request = mIndex->GetKeyInternal(keyRange, rv);
+    ENSURE_SUCCESS(rv, false);
   }
 
   request->SetActor(this);
   mRequest.swap(request);
   return true;
 }
 
 bool
@@ -1844,19 +1841,19 @@ IndexedDBIndexRequestParent::GetAll(cons
 
     default:
       MOZ_CRASH("Unknown param type!");
   }
 
   {
     AutoSetCurrentTransaction asct(mIndex->ObjectStore()->Transaction());
 
-    nsresult rv = mIndex->GetAllInternal(keyRange, aParams.limit(), nullptr,
-                                         getter_AddRefs(request));
-    NS_ENSURE_SUCCESS(rv, false);
+    ErrorResult rv;
+    request = mIndex->GetAllInternal(keyRange, aParams.limit(), rv);
+    ENSURE_SUCCESS(rv, false);
   }
 
   request->SetActor(this);
   mRequest.swap(request);
   return true;
 }
 
 bool
@@ -1883,19 +1880,19 @@ IndexedDBIndexRequestParent::GetAllKeys(
 
     default:
       MOZ_CRASH("Unknown param type!");
   }
 
   {
     AutoSetCurrentTransaction asct(mIndex->ObjectStore()->Transaction());
 
-    nsresult rv = mIndex->GetAllKeysInternal(keyRange, aParams.limit(), nullptr,
-                                             getter_AddRefs(request));
-    NS_ENSURE_SUCCESS(rv, false);
+    ErrorResult rv;
+    request = mIndex->GetAllKeysInternal(keyRange, aParams.limit(), rv);
+    ENSURE_SUCCESS(rv, false);
   }
 
   request->SetActor(this);
   mRequest.swap(request);
   return true;
 }
 
 bool
@@ -1922,19 +1919,19 @@ IndexedDBIndexRequestParent::Count(const
       MOZ_CRASH("Unknown param type!");
   }
 
   nsRefPtr<IDBRequest> request;
 
   {
     AutoSetCurrentTransaction asct(mIndex->ObjectStore()->Transaction());
 
-    nsresult rv = mIndex->CountInternal(keyRange, nullptr,
-                                        getter_AddRefs(request));
-    NS_ENSURE_SUCCESS(rv, false);
+    ErrorResult rv;
+    request = mIndex->CountInternal(keyRange, rv);
+    ENSURE_SUCCESS(rv, false);
   }
 
   request->SetActor(this);
   mRequest.swap(request);
   return true;
 }
 
 bool
@@ -2004,20 +2001,19 @@ IndexedDBIndexRequestParent::OpenKeyCurs
 
   size_t direction = static_cast<size_t>(aParams.direction());
 
   nsRefPtr<IDBRequest> request;
 
   {
     AutoSetCurrentTransaction asct(mIndex->ObjectStore()->Transaction());
 
-    nsresult rv =
-      mIndex->OpenKeyCursorInternal(keyRange, direction, nullptr,
-                                    getter_AddRefs(request));
-    NS_ENSURE_SUCCESS(rv, false);
+    ErrorResult rv;
+    request = mIndex->OpenKeyCursorInternal(keyRange, direction, rv);
+    ENSURE_SUCCESS(rv, false);
   }
 
   request->SetActor(this);
   mRequest.swap(request);
   return true;
 }
 
 /*******************************************************************************
--- a/dom/indexedDB/moz.build
+++ b/dom/indexedDB/moz.build
@@ -6,17 +6,16 @@
 
 DIRS += ['ipc']
 TEST_DIRS += ['test']
 
 XPIDL_SOURCES += [
     'nsIIDBCursor.idl',
     'nsIIDBCursorWithValue.idl',
     'nsIIDBDatabase.idl',
-    'nsIIDBIndex.idl',
     'nsIIDBKeyRange.idl',
     'nsIIDBOpenDBRequest.idl',
     'nsIIDBRequest.idl',
     'nsIIndexedDatabaseManager.idl',
 ]
 
 XPIDL_MODULE = 'dom_indexeddb'
 
deleted file mode 100644
--- a/dom/indexedDB/nsIIDBIndex.idl
+++ /dev/null
@@ -1,67 +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;
-
-/**
- * IDBIndex interface.  See
- * http://dev.w3.org/2006/webapi/WebSimpleDB/#idl-def-IDBIndex for more
- * information.
- */
-[scriptable, builtinclass, uuid(a859747a-0f05-4dfb-8f42-05c61415d4e4)]
-interface nsIIDBIndex : nsISupports
-{
-  readonly attribute DOMString name;
-
-  readonly attribute DOMString storeName;
-
-  [implicit_jscontext]
-  readonly attribute jsval keyPath;
-
-  readonly attribute boolean unique;
-
-  readonly attribute boolean multiEntry;
-
-  // This is a IDBObjectStore
-  readonly attribute nsISupports objectStore;
-
-  [implicit_jscontext]
-  nsIIDBRequest
-  get(in jsval key);
-
-  [implicit_jscontext]
-  nsIIDBRequest
-  getKey(in jsval key);
-
-  [implicit_jscontext, optional_argc, binaryname(GetAll)]
-  nsIIDBRequest
-  mozGetAll([optional /* null */] in jsval key,
-            [optional /* unlimited */] in unsigned long limit);
-
-  [implicit_jscontext, optional_argc, binaryname(GetAllKeys)]
-  nsIIDBRequest
-  mozGetAllKeys([optional /* null */] in jsval key,
-                [optional /* unlimited */] in unsigned long limit);
-
-  // direction can be "next", "nextunique", "prev" or "prevunique"
-  [implicit_jscontext, optional_argc]
-  nsIIDBRequest
-  openCursor([optional /* null */] in jsval key,
-             [optional /* "next" */] in DOMString direction);
-
-  // direction can be "next", "nextunique", "prev" or "prevunique"
-  [implicit_jscontext, optional_argc]
-  nsIIDBRequest
-  openKeyCursor([optional /* null */] in jsval key,
-                [optional /* "next" */] in DOMString direction);
-
-  // Accepts null, a key value, or a nsIIDBKeyRange object.
-  [implicit_jscontext, optional_argc]
-  nsIIDBRequest
-  count([optional] in jsval key);
-};
--- a/dom/indexedDB/test/unit/head.js
+++ b/dom/indexedDB/test/unit/head.js
@@ -4,17 +4,16 @@
  */
 
 const { 'classes': Cc, 'interfaces': Ci } = Components;
 
 const DOMException = Ci.nsIDOMDOMException;
 const IDBCursor = Ci.nsIIDBCursor;
 const IDBOpenDBRequest = Ci.nsIIDBOpenDBRequest;
 const IDBDatabase = Ci.nsIIDBDatabase
-const IDBIndex = Ci.nsIIDBIndex
 const IDBRequest = Ci.nsIIDBRequest
 
 function is(a, b, msg) {
   dump("is(" + a + ", " + b + ", \"" + msg + "\")");
   do_check_eq(a, b, Components.stack.caller);
 }
 
 function ok(cond, msg) {
--- a/dom/webidl/IDBIndex.webidl
+++ b/dom/webidl/IDBIndex.webidl
@@ -7,8 +7,43 @@
  * https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#idl-def-IDBIndexParameters
  */
 
 dictionary IDBIndexParameters {
     boolean unique = false;
     boolean multiEntry = false;
 };
 
+interface IDBIndex {
+    readonly    attribute DOMString      name;
+    readonly    attribute IDBObjectStore objectStore;
+
+    [Throws]
+    readonly    attribute any            keyPath;
+
+    readonly    attribute boolean        multiEntry;
+    readonly    attribute boolean        unique;
+
+    [Throws]
+    IDBRequest openCursor (optional any range, optional IDBCursorDirection direction = "next");
+
+    [Throws]
+    IDBRequest openKeyCursor (optional any range, optional IDBCursorDirection direction = "next");
+
+    [Throws]
+    IDBRequest get (any key);
+
+    [Throws]
+    IDBRequest getKey (any key);
+
+    [Throws]
+    IDBRequest count (optional any key);
+};
+
+partial interface IDBIndex {
+    readonly attribute DOMString storeName;
+
+    [Throws]
+    IDBRequest mozGetAll (optional any key, optional unsigned long limit);
+
+    [Throws]
+    IDBRequest mozGetAllKeys (optional any key, optional unsigned long limit);
+};
--- a/dom/webidl/IDBObjectStore.webidl
+++ b/dom/webidl/IDBObjectStore.webidl
@@ -3,17 +3,16 @@
  * 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/.
  *
  * The origin of this IDL file is
  * https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#idl-def-IDBObjectStore
  */
 
 interface IDBRequest;
-interface IDBIndex;
 
 interface IDBObjectStore {
     readonly    attribute DOMString      name;
 
     [Throws]
     readonly    attribute any            keyPath;
 
     [Throws]
--- a/js/xpconnect/src/dom_quickstubs.qsconf
+++ b/js/xpconnect/src/dom_quickstubs.qsconf
@@ -82,17 +82,16 @@ members = [
     'nsIBoxObject.screenY',
     'nsIBoxObject.width',
     'nsIBoxObject.height',
 
     # dom/indexedDB
     'nsIIDBCursor.*',
     'nsIIDBCursorWithValue.*',
     'nsIIDBDatabase.*',
-    'nsIIDBIndex.*',
     'nsIIDBKeyRange.*',
     'nsIIDBRequest.*',
     'nsIIDBOpenDBRequest.*',
     'nsIIndexedDatabaseManager.*',
 
     # dom/file
     'nsIDOMLockedFile.*',
 
--- a/js/xpconnect/src/nsXPConnect.cpp
+++ b/js/xpconnect/src/nsXPConnect.cpp
@@ -30,16 +30,17 @@
 
 #ifdef MOZ_JSDEBUGGER
 #include "jsdIDebuggerService.h"
 #endif
 
 #include "XPCQuickStubs.h"
 
 #include "mozilla/dom/BindingUtils.h"
+#include "mozilla/dom/IDBIndexBinding.h"
 #include "mozilla/dom/IDBObjectStoreBinding.h"
 #include "mozilla/dom/IDBTransactionBinding.h"
 #include "mozilla/dom/IDBVersionChangeEventBinding.h"
 #include "mozilla/dom/TextDecoderBinding.h"
 #include "mozilla/dom/TextEncoderBinding.h"
 #include "mozilla/dom/DOMErrorBinding.h"
 
 #include "nsWrapperCacheInlines.h"
@@ -540,17 +541,18 @@ nsXPConnect::InitClassesWithNewWrappedGl
     }
 
     // Stuff coming through this path always ends up as a DOM global.
     // XXX Someone who knows why we can assert this should re-check
     //     (after bug 720580).
     MOZ_ASSERT(js::GetObjectClass(global)->flags & JSCLASS_DOM_GLOBAL);
 
     // Init WebIDL binding constructors wanted on all XPConnect globals.
-    if (!IDBObjectStoreBinding::GetConstructorObject(aJSContext, global) ||
+    if (!IDBIndexBinding::GetConstructorObject(aJSContext, global) ||
+        !IDBObjectStoreBinding::GetConstructorObject(aJSContext, global) ||
         !IDBTransactionBinding::GetConstructorObject(aJSContext, global) ||
         !IDBVersionChangeEventBinding::GetConstructorObject(aJSContext, global) ||
         !TextDecoderBinding::GetConstructorObject(aJSContext, global) ||
         !TextEncoderBinding::GetConstructorObject(aJSContext, global) ||
         !DOMErrorBinding::GetConstructorObject(aJSContext, global)) {
         return UnexpectedFailure(NS_ERROR_FAILURE);
     }