Backout changeset 531f544bc9ce for breaking B2G tests.
authorMs2ger <ms2ger@gmail.com>
Fri, 02 Aug 2013 11:38:49 +0200
changeset 140972 c489af94ada55f2f20da71a1a238f4c82016948c
parent 140971 76a944fa6b251610d36d5c3465f1ee39326e9d8c
child 141083 04dd60bdbc04f803c06235d3668bc0c3bd3a5fea
push id25045
push userMs2ger@gmail.com
push dateFri, 02 Aug 2013 09:39:32 +0000
treeherdermozilla-central@c489af94ada5 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone25.0a1
backs out531f544bc9cea36bfa014c2e94c48c40fc5a67c3
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
Backout changeset 531f544bc9ce for breaking B2G tests.
dom/base/nsDOMClassInfo.cpp
dom/base/nsDOMClassInfoClasses.h
dom/bindings/Bindings.conf
dom/indexedDB/IDBIndex.cpp
dom/indexedDB/IDBKeyRange.cpp
dom/indexedDB/IDBKeyRange.h
dom/indexedDB/IndexedDatabaseManager.cpp
dom/indexedDB/moz.build
dom/indexedDB/nsIIDBKeyRange.idl
dom/webidl/IDBKeyRange.webidl
dom/webidl/WebIDL.mk
js/xpconnect/src/dom_quickstubs.qsconf
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -197,16 +197,17 @@
 
 #include "nsDOMFile.h"
 
 #include "nsIEventListenerService.h"
 #include "nsIMessageManager.h"
 #include "mozilla/dom/Element.h"
 
 #include "mozilla/dom/indexedDB/IDBWrapperCache.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"
 
@@ -624,16 +625,20 @@ static nsDOMClassInfoData sClassInfoData
   NS_DEFINE_CHROME_ONLY_CLASSINFO_DATA(ContentFrameMessageManager, nsEventTargetSH,
                                        DOM_DEFAULT_SCRIPTABLE_FLAGS |
                                        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(IDBKeyRange, nsDOMGenericSH,
+                           DOM_DEFAULT_SCRIPTABLE_FLAGS)
+
+
   NS_DEFINE_CLASSINFO_DATA(MozCSSKeyframeRule, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(MozCSSKeyframesRule, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 
   NS_DEFINE_CLASSINFO_DATA(CSSPageRule, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 
@@ -1508,16 +1513,20 @@ nsDOMClassInfo::Init()
 
   DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(ChromeMessageSender, nsISupports)
     DOM_CLASSINFO_MAP_ENTRY(nsIProcessChecker)
     DOM_CLASSINFO_MAP_ENTRY(nsIFrameScriptLoader)
     DOM_CLASSINFO_MAP_ENTRY(nsIMessageListenerManager)
     DOM_CLASSINFO_MAP_ENTRY(nsIMessageSender)
   DOM_CLASSINFO_MAP_END
 
+  DOM_CLASSINFO_MAP_BEGIN(IDBKeyRange, nsIIDBKeyRange)
+    DOM_CLASSINFO_MAP_ENTRY(nsIIDBKeyRange)
+  DOM_CLASSINFO_MAP_END
+
   DOM_CLASSINFO_MAP_BEGIN(MozCSSKeyframeRule, nsIDOMMozCSSKeyframeRule)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozCSSKeyframeRule)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(MozCSSKeyframesRule, nsIDOMMozCSSKeyframesRule)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozCSSKeyframesRule)
   DOM_CLASSINFO_MAP_END
 
@@ -3209,17 +3218,26 @@ nsDOMConstructor::ResolveInterfaceConsta
     class_iid =
       sClassInfoData[class_name_struct->mDOMClassInfoID].mProtoChainInterface;
   } else if (class_name_struct->mType == nsGlobalNameStruct::eTypeExternalClassInfo) {
     class_iid = class_name_struct->mData->mProtoChainInterface;
   } else {
     return NS_OK;
   }
 
-  return DefineInterfaceConstants(cx, obj, class_iid);
+  nsresult rv = DefineInterfaceConstants(cx, obj, class_iid);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  // 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;
+  }
+
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMConstructor::ToString(nsAString &aResult)
 {
   aResult.AssignLiteral("[object ");
   aResult.Append(mClassName);
   aResult.Append(PRUnichar(']'));
@@ -3333,16 +3351,22 @@ ResolvePrototype(nsIXPConnect *aXPConnec
   const char *class_parent_name = nullptr;
 
   if (!primary_iid->Equals(NS_GET_IID(nsISupports))) {
     JSAutoCompartment ac(cx, class_obj);
 
     rv = DefineInterfaceConstants(cx, class_obj, primary_iid);
     NS_ENSURE_SUCCESS(rv, rv);
 
+    // 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;
+    }
+
     nsCOMPtr<nsIInterfaceInfoManager>
       iim(do_GetService(NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID));
     NS_ENSURE_TRUE(iim, NS_ERROR_NOT_AVAILABLE);
 
     iim->GetInfoForIID(primary_iid, getter_AddRefs(if_info));
     NS_ENSURE_TRUE(if_info, NS_ERROR_UNEXPECTED);
 
     const nsIID *iid = nullptr;
--- a/dom/base/nsDOMClassInfoClasses.h
+++ b/dom/base/nsDOMClassInfoClasses.h
@@ -114,16 +114,18 @@ DOMCI_CLASS(CSSFontFaceRule)
 DOMCI_CLASS(DataTransfer)
 
 DOMCI_CLASS(EventListenerInfo)
 
 DOMCI_CLASS(ContentFrameMessageManager)
 DOMCI_CLASS(ChromeMessageBroadcaster)
 DOMCI_CLASS(ChromeMessageSender)
 
+DOMCI_CLASS(IDBKeyRange)
+
 DOMCI_CLASS(MozCSSKeyframeRule)
 DOMCI_CLASS(MozCSSKeyframesRule)
 
 DOMCI_CLASS(CSSPageRule)
 
 DOMCI_CLASS(MediaQueryList)
 
 #ifdef MOZ_B2G_RIL
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -586,21 +586,16 @@ DOMInterfaces = {
 'IDBRequest': {
     'nativeType': 'mozilla::dom::indexedDB::IDBRequest',
 },
 
 'IDBTransaction': {
     'nativeType': 'mozilla::dom::indexedDB::IDBTransaction',
 },
 
-'IDBKeyRange': {
-    'nativeType': 'mozilla::dom::indexedDB::IDBKeyRange',
-    'wrapperCache': False,
-},
-
 'IDBVersionChangeEvent': {
     'nativeType': 'mozilla::dom::indexedDB::IDBVersionChangeEvent',
     'headerFile': 'IDBEvents.h',
 },
 
 'IID': [
 {
     'nativeType': 'nsIJSID',
--- a/dom/indexedDB/IDBIndex.cpp
+++ b/dom/indexedDB/IDBIndex.cpp
@@ -3,16 +3,18 @@
 /* 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 "base/basictypes.h"
 
 #include "IDBIndex.h"
 
+#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 "nsEventDispatcher.h"
 #include "nsThreadUtils.h"
 #include "xpcpublic.h"
--- a/dom/indexedDB/IDBKeyRange.cpp
+++ b/dom/indexedDB/IDBKeyRange.cpp
@@ -13,26 +13,64 @@
 #include "nsJSUtils.h"
 #include "nsThreadUtils.h"
 #include "nsContentUtils.h"
 #include "nsDOMClassInfoID.h"
 #include "Key.h"
 
 #include "mozilla/dom/indexedDB/PIndexedDBIndex.h"
 #include "mozilla/dom/indexedDB/PIndexedDBObjectStore.h"
-#include "mozilla/dom/IDBKeyRangeBinding.h"
 
-using namespace mozilla;
-using namespace mozilla::dom;
 USING_INDEXEDDB_NAMESPACE
 using namespace mozilla::dom::indexedDB::ipc;
 
-static inline nsresult
+namespace {
+
+inline
+bool
+ReturnKeyRange(JSContext* aCx,
+               jsval* aVp,
+               IDBKeyRange* aKeyRange)
+{
+  NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
+  NS_ASSERTION(aCx, "Null pointer!");
+  NS_ASSERTION(aVp, "Null pointer!");
+  NS_ASSERTION(aKeyRange, "Null pointer!");
+
+  nsIXPConnect* xpc = nsContentUtils::XPConnect();
+  NS_ASSERTION(xpc, "This should never be null!");
+
+  JSObject* global = JS::CurrentGlobalOrNull(aCx);
+  if (!global) {
+    NS_WARNING("Couldn't get global object!");
+    return false;
+  }
+
+  nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
+  if (NS_FAILED(xpc->WrapNative(aCx, global, aKeyRange,
+                                NS_GET_IID(nsIIDBKeyRange),
+                                getter_AddRefs(holder)))) {
+    JS_ReportError(aCx, "Couldn't wrap IDBKeyRange object.");
+    return false;
+  }
+
+  JS::Rooted<JSObject*> result(aCx, holder->GetJSObject());
+  if (!result) {
+    JS_ReportError(aCx, "Couldn't get JSObject from wrapper.");
+    return false;
+  }
+
+  JS_SET_RVAL(aCx, aVp, OBJECT_TO_JSVAL(result));
+  return true;
+}
+
+inline
+nsresult
 GetKeyFromJSVal(JSContext* aCx,
-                JS::Handle<JS::Value> aVal,
+                jsval aVal,
                 Key& aKey,
                 bool aAllowUnset = false)
 {
   nsresult rv = aKey.SetFromJSVal(aCx, aVal);
   if (NS_FAILED(rv)) {
     NS_ASSERTION(NS_ERROR_GET_MODULE(rv) == NS_ERROR_MODULE_DOM_INDEXEDDB,
                  "Bad error code!");
     return rv;
@@ -40,144 +78,219 @@ GetKeyFromJSVal(JSContext* aCx,
 
   if (aKey.IsUnset() && !aAllowUnset) {
     return NS_ERROR_DOM_INDEXEDDB_DATA_ERR;
   }
 
   return NS_OK;
 }
 
-JSObject*
-IDBKeyRange::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
+inline
+void
+ThrowException(JSContext* aCx,
+               nsresult aErrorCode)
 {
-  return IDBKeyRangeBinding::Wrap(aCx, aScope, this);
+  NS_ASSERTION(NS_FAILED(aErrorCode), "Not an error code!");
+  xpc::Throw(aCx, aErrorCode);
 }
 
-/* static */ already_AddRefed<IDBKeyRange>
-IDBKeyRange::Only(const GlobalObject& aGlobal, JSContext* aCx,
-                  JS::Handle<JS::Value> aValue, ErrorResult& aRv)
+inline
+bool
+GetKeyFromJSValOrThrow(JSContext* aCx,
+                       jsval aVal,
+                       Key& aKey)
 {
-  MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
+  nsresult rv = GetKeyFromJSVal(aCx, aVal, aKey);
+  if (NS_FAILED(rv)) {
+    ThrowException(aCx, rv);
+    return false;
+  }
+  return true;
+}
 
-  nsRefPtr<IDBKeyRange> keyRange = new IDBKeyRange(aGlobal.Get(), false, false, true);
+JSBool
+MakeOnlyKeyRange(JSContext* aCx,
+                 unsigned aArgc,
+                 jsval* aVp)
+{
+  NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
-  aRv = GetKeyFromJSVal(aCx, aValue, keyRange->Lower());
-  if (aRv.Failed()) {
-    return nullptr;
+  JS::Rooted<JS::Value> val(aCx);
+  if (!JS_ConvertArguments(aCx, aArgc, JS_ARGV(aCx, aVp), "v", val.address())) {
+    return false;
   }
 
-  return keyRange.forget();
-}
+  nsRefPtr<IDBKeyRange> keyRange = new IDBKeyRange(false, false, true);
 
-/* static */ already_AddRefed<IDBKeyRange>
-IDBKeyRange::LowerBound(const GlobalObject& aGlobal, JSContext* aCx,
-                        JS::Handle<JS::Value> aValue, bool aOpen,
-                        ErrorResult& aRv)
-{
-  MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
-
-  nsRefPtr<IDBKeyRange> keyRange = new IDBKeyRange(aGlobal.Get(), aOpen, true, false);
-
-  aRv = GetKeyFromJSVal(aCx, aValue, keyRange->Lower());
-  if (aRv.Failed()) {
-    return nullptr;
+  if (!GetKeyFromJSValOrThrow(aCx, val, keyRange->Lower())) {
+    return false;
   }
 
-  return keyRange.forget();
+  return ReturnKeyRange(aCx, aVp, keyRange);
 }
 
-/* static */ already_AddRefed<IDBKeyRange>
-IDBKeyRange::UpperBound(const GlobalObject& aGlobal, JSContext* aCx,
-                        JS::Handle<JS::Value> aValue, bool aOpen,
-                        ErrorResult& aRv)
+JSBool
+MakeLowerBoundKeyRange(JSContext* aCx,
+                       unsigned aArgc,
+                       jsval* aVp)
 {
-  MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
-
-  nsRefPtr<IDBKeyRange> keyRange = new IDBKeyRange(aGlobal.Get(), true, aOpen, false);
+  NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
-  aRv = GetKeyFromJSVal(aCx, aValue, keyRange->Upper());
-  if (aRv.Failed()) {
-    return nullptr;
+  JS::Rooted<JS::Value> val(aCx);
+  JSBool open = false;
+  if (!JS_ConvertArguments(aCx, aArgc, JS_ARGV(aCx, aVp), "v/b", val.address(),
+                           &open)) {
+    return false;
+  }
+
+  nsRefPtr<IDBKeyRange> keyRange = new IDBKeyRange(open, true, false);
+
+  if (!GetKeyFromJSValOrThrow(aCx, val, keyRange->Lower())) {
+    return false;
   }
 
-  return keyRange.forget();
+  return ReturnKeyRange(aCx, aVp, keyRange);
 }
 
-/* static */ already_AddRefed<IDBKeyRange>
-IDBKeyRange::Bound(const GlobalObject& aGlobal, JSContext* aCx,
-                   JS::Handle<JS::Value> aLower, JS::Handle<JS::Value> aUpper,
-                   bool aLowerOpen, bool aUpperOpen, ErrorResult& aRv)
+JSBool
+MakeUpperBoundKeyRange(JSContext* aCx,
+                       unsigned aArgc,
+                       jsval* aVp)
 {
-  MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
+  NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
-  nsRefPtr<IDBKeyRange> keyRange = new IDBKeyRange(aGlobal.Get(), aLowerOpen,
-                                                   aUpperOpen, false);
+  JS::Rooted<JS::Value> val(aCx);
+  JSBool open = false;
+  if (!JS_ConvertArguments(aCx, aArgc, JS_ARGV(aCx, aVp), "v/b", val.address(),
+                           &open)) {
+    return false;
+  }
 
-  aRv = GetKeyFromJSVal(aCx, aLower, keyRange->Lower());
-  if (aRv.Failed()) {
-    return nullptr;
+  nsRefPtr<IDBKeyRange> keyRange = new IDBKeyRange(true, open, false);
+
+  if (!GetKeyFromJSValOrThrow(aCx, val, keyRange->Upper())) {
+    return false;
   }
 
-  aRv = GetKeyFromJSVal(aCx, aUpper, keyRange->Upper());
-  if (aRv.Failed()) {
-    return nullptr;
+  return ReturnKeyRange(aCx, aVp, keyRange);
+}
+
+JSBool
+MakeBoundKeyRange(JSContext* aCx,
+                  unsigned aArgc,
+                  jsval* aVp)
+{
+  NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
+
+  JS::Rooted<JS::Value> lowerVal(aCx), upperVal(aCx);
+  JSBool lowerOpen = false, upperOpen = false;
+  if (!JS_ConvertArguments(aCx, aArgc, JS_ARGV(aCx, aVp), "vv/bb",
+                           lowerVal.address(), upperVal.address(),
+                           &lowerOpen, &upperOpen)) {
+    return false;
+  }
+
+  nsRefPtr<IDBKeyRange> keyRange = new IDBKeyRange(lowerOpen, upperOpen, false);
+
+  if (!GetKeyFromJSValOrThrow(aCx, lowerVal, keyRange->Lower()) ||
+      !GetKeyFromJSValOrThrow(aCx, upperVal, keyRange->Upper())) {
+    return false;
   }
 
   if (keyRange->Lower() > keyRange->Upper() ||
-      (keyRange->Lower() == keyRange->Upper() && (aLowerOpen || aUpperOpen))) {
-    aRv.Throw(NS_ERROR_DOM_INDEXEDDB_DATA_ERR);
-    return nullptr;
+      (keyRange->Lower() == keyRange->Upper() && (lowerOpen || upperOpen))) {
+    ThrowException(aCx, NS_ERROR_DOM_INDEXEDDB_DATA_ERR);
+    return false;
   }
 
-  return keyRange.forget();
+  return ReturnKeyRange(aCx, aVp, keyRange);
+}
+
+#define KEYRANGE_FUNCTION_FLAGS (JSPROP_ENUMERATE | JSPROP_PERMANENT)
+
+const JSFunctionSpec gKeyRangeConstructors[] = {
+  JS_FN("only", MakeOnlyKeyRange, 1, KEYRANGE_FUNCTION_FLAGS),
+  JS_FN("lowerBound", MakeLowerBoundKeyRange, 1, KEYRANGE_FUNCTION_FLAGS),
+  JS_FN("upperBound", MakeUpperBoundKeyRange, 1, KEYRANGE_FUNCTION_FLAGS),
+  JS_FN("bound", MakeBoundKeyRange, 2, KEYRANGE_FUNCTION_FLAGS),
+  JS_FS_END
+};
+
+#undef KEYRANGE_FUNCTION_FLAGS
+
+} // anonymous namespace
+
+// static
+JSBool
+IDBKeyRange::DefineConstructors(JSContext* aCx,
+                                JSObject* aObject)
+{
+  NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
+  NS_ASSERTION(aCx, "Null pointer!");
+  NS_ASSERTION(aObject, "Null pointer!");
+
+  // Add the constructor methods for key ranges.
+  return JS_DefineFunctions(aCx, aObject, gKeyRangeConstructors);
 }
 
 // static
 nsresult
 IDBKeyRange::FromJSVal(JSContext* aCx,
-                       const jsval& aValue,
+                       const jsval& aVal,
                        IDBKeyRange** aKeyRange)
 {
-  JS::Rooted<JS::Value> value(aCx, aValue);
+  nsresult rv;
   nsRefPtr<IDBKeyRange> keyRange;
 
-  if (value.isNullOrUndefined()) {
+  if (JSVAL_IS_VOID(aVal) || JSVAL_IS_NULL(aVal)) {
     // undefined and null returns no IDBKeyRange.
   }
-  else if (value.isPrimitive() ||
-           JS_IsArrayObject(aCx, &value.toObject()) ||
-           JS_ObjectIsDate(aCx, &value.toObject())) {
+  else if (JSVAL_IS_PRIMITIVE(aVal) ||
+           JS_IsArrayObject(aCx, JSVAL_TO_OBJECT(aVal)) ||
+           JS_ObjectIsDate(aCx, JSVAL_TO_OBJECT(aVal))) {
     // A valid key returns an 'only' IDBKeyRange.
-    keyRange = new IDBKeyRange(nullptr, false, false, true);
+    keyRange = new IDBKeyRange(false, false, true);
 
-    nsresult rv = GetKeyFromJSVal(aCx, value, keyRange->Lower());
+    rv = GetKeyFromJSVal(aCx, aVal, keyRange->Lower());
     if (NS_FAILED(rv)) {
       return rv;
     }
   }
   else {
-    MOZ_ASSERT(value.isObject());
     // An object is not permitted unless it's another IDBKeyRange.
-    if (NS_FAILED(UnwrapObject<IDBKeyRange>(aCx, &value.toObject(),
-                                            keyRange))) {
+    nsIXPConnect* xpc = nsContentUtils::XPConnect();
+    NS_ASSERTION(xpc, "This should never be null!");
+
+    nsCOMPtr<nsIXPConnectWrappedNative> wrapper;
+    rv = xpc->GetWrappedNativeOfJSObject(aCx, JSVAL_TO_OBJECT(aVal),
+                                         getter_AddRefs(wrapper));
+    if (NS_FAILED(rv)) {
       return NS_ERROR_DOM_INDEXEDDB_DATA_ERR;
     }
+
+    nsCOMPtr<nsIIDBKeyRange> iface;
+    if (!wrapper || !(iface = do_QueryInterface(wrapper->Native()))) {
+      // Some random JS object?
+      return NS_ERROR_DOM_INDEXEDDB_DATA_ERR;
+    }
+
+    keyRange = static_cast<IDBKeyRange*>(iface.get());
   }
 
   keyRange.forget(aKeyRange);
   return NS_OK;
 }
 
 // static
 template <class T>
 already_AddRefed<IDBKeyRange>
 IDBKeyRange::FromSerializedKeyRange(const T& aKeyRange)
 {
   nsRefPtr<IDBKeyRange> keyRange =
-    new IDBKeyRange(nullptr, aKeyRange.lowerOpen(), aKeyRange.upperOpen(),
+    new IDBKeyRange(aKeyRange.lowerOpen(), aKeyRange.upperOpen(),
                     aKeyRange.isOnly());
   keyRange->Lower() = aKeyRange.lower();
   if (!keyRange->IsOnly()) {
     keyRange->Upper() = aKeyRange.upper();
   }
   return keyRange.forget();
 }
 
@@ -190,39 +303,40 @@ IDBKeyRange::ToSerializedKeyRange(T& aKe
   aKeyRange.isOnly() = IsOnly();
 
   aKeyRange.lower() = Lower();
   if (!IsOnly()) {
     aKeyRange.upper() = Upper();
   }
 }
 
-
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(IDBKeyRange)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGlobal)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(IDBKeyRange)
   NS_IMPL_CYCLE_COLLECTION_TRACE_JSVAL_MEMBER_CALLBACK(mCachedLowerVal)
   NS_IMPL_CYCLE_COLLECTION_TRACE_JSVAL_MEMBER_CALLBACK(mCachedUpperVal)
 NS_IMPL_CYCLE_COLLECTION_TRACE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(IDBKeyRange)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mGlobal)
   tmp->DropJSObjects();
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(IDBKeyRange)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
+  NS_INTERFACE_MAP_ENTRY(nsIIDBKeyRange)
+  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(IDBKeyRange)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(IDBKeyRange)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(IDBKeyRange)
 
+DOMCI_DATA(IDBKeyRange, IDBKeyRange)
+
 void
 IDBKeyRange::DropJSObjects()
 {
   if (!mRooted) {
     return;
   }
   mCachedLowerVal = JSVAL_VOID;
   mCachedUpperVal = JSVAL_VOID;
@@ -232,58 +346,77 @@ IDBKeyRange::DropJSObjects()
   NS_DROP_JS_OBJECTS(this, IDBKeyRange);
 }
 
 IDBKeyRange::~IDBKeyRange()
 {
   DropJSObjects();
 }
 
-JS::Value
-IDBKeyRange::GetLower(JSContext* aCx, ErrorResult& aRv)
+NS_IMETHODIMP
+IDBKeyRange::GetLower(JSContext* aCx,
+                      jsval* aLower)
 {
-  MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
+  NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   if (!mHaveCachedLowerVal) {
     if (!mRooted) {
       NS_HOLD_JS_OBJECTS(this, IDBKeyRange);
       mRooted = true;
     }
 
-    aRv = Lower().ToJSVal(aCx, mCachedLowerVal);
-    if (aRv.Failed()) {
-      return JS::UndefinedValue();
-    }
+    nsresult rv = Lower().ToJSVal(aCx, mCachedLowerVal);
+    NS_ENSURE_SUCCESS(rv, rv);
 
     mHaveCachedLowerVal = true;
   }
 
-  return mCachedLowerVal;
+  *aLower = mCachedLowerVal;
+  return NS_OK;
 }
 
-JS::Value
-IDBKeyRange::GetUpper(JSContext* aCx, ErrorResult& aRv)
+NS_IMETHODIMP
+IDBKeyRange::GetUpper(JSContext* aCx,
+                      jsval* aUpper)
 {
-  MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
+  NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   if (!mHaveCachedUpperVal) {
     if (!mRooted) {
       NS_HOLD_JS_OBJECTS(this, IDBKeyRange);
       mRooted = true;
     }
 
-    aRv = Upper().ToJSVal(aCx, mCachedUpperVal);
-    if (aRv.Failed()) {
-      return JS::UndefinedValue();
-    }
+    nsresult rv = Upper().ToJSVal(aCx, mCachedUpperVal);
+    NS_ENSURE_SUCCESS(rv, rv);
 
     mHaveCachedUpperVal = true;
   }
 
-  return mCachedUpperVal;
+  *aUpper = mCachedUpperVal;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+IDBKeyRange::GetLowerOpen(bool* aLowerOpen)
+{
+  NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
+
+  *aLowerOpen = mLowerOpen;
+  return NS_OK;
+}
+
+
+NS_IMETHODIMP
+IDBKeyRange::GetUpperOpen(bool* aUpperOpen)
+{
+  NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
+
+  *aUpperOpen = mUpperOpen;
+  return NS_OK;
 }
 
 // Explicitly instantiate for all our key range types... Grumble.
 template already_AddRefed<IDBKeyRange>
 IDBKeyRange::FromSerializedKeyRange<FIXME_Bug_521898_objectstore::KeyRange>
 (const FIXME_Bug_521898_objectstore::KeyRange& aKeyRange);
 
 template already_AddRefed<IDBKeyRange>
--- a/dom/indexedDB/IDBKeyRange.h
+++ b/dom/indexedDB/IDBKeyRange.h
@@ -4,88 +4,53 @@
  * 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_idbkeyrange_h__
 #define mozilla_dom_indexeddb_idbkeyrange_h__
 
 #include "mozilla/dom/indexedDB/IndexedDatabase.h"
 #include "mozilla/dom/indexedDB/Key.h"
-#include "mozilla/ErrorResult.h"
+
+#include "nsIIDBKeyRange.h"
+
 #include "nsCycleCollectionParticipant.h"
-#include "nsISupports.h"
 
 class mozIStorageStatement;
 
-namespace mozilla {
-namespace dom {
-class GlobalObject;
-} // namespace dom
-} // namespace mozilla
-
 BEGIN_INDEXEDDB_NAMESPACE
 
 namespace ipc {
 namespace FIXME_Bug_521898_objectstore {
 class KeyRange;
 } // namespace FIXME_Bug_521898_objectstore
 } // namespace ipc
 
-class IDBKeyRange MOZ_FINAL : public nsISupports
+class IDBKeyRange MOZ_FINAL : public nsIIDBKeyRange
 {
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+  NS_DECL_NSIIDBKEYRANGE
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(IDBKeyRange)
 
-  JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope);
-  nsISupports* GetParentObject() const
-  {
-    return mGlobal;
-  }
-
-  // WebIDL
-  JS::Value GetLower(JSContext* aCx, ErrorResult& aRv);
-  JS::Value GetUpper(JSContext* aCx, ErrorResult& aRv);
-  bool LowerOpen() const
-  {
-    return mLowerOpen;
-  }
-  bool UpperOpen() const
-  {
-    return mUpperOpen;
-  }
-
-  static already_AddRefed<IDBKeyRange>
-  Only(const GlobalObject& aGlobal, JSContext* aCx,
-       JS::Handle<JS::Value> aValue, ErrorResult& aRv);
-  static already_AddRefed<IDBKeyRange>
-  LowerBound(const GlobalObject& aGlobal, JSContext* aCx,
-             JS::Handle<JS::Value> aValue, bool aOpen, ErrorResult& aRv);
-  static already_AddRefed<IDBKeyRange>
-  UpperBound(const GlobalObject& aGlobal, JSContext* aCx,
-             JS::Handle<JS::Value> aValue, bool aOpen, ErrorResult& aRv);
-  static already_AddRefed<IDBKeyRange>
-  Bound(const GlobalObject& aGlobal, JSContext* aCx,
-        JS::Handle<JS::Value> aLower, JS::Handle<JS::Value> aUpper,
-        bool aLowerOpen, bool aUpperOpen, ErrorResult& aRv);
-
+  static JSBool DefineConstructors(JSContext* aCx,
+                                   JSObject* aObject);
 
   static nsresult FromJSVal(JSContext* aCx,
                             const jsval& aVal,
                             IDBKeyRange** aKeyRange);
 
   template <class T>
   static already_AddRefed<IDBKeyRange>
   FromSerializedKeyRange(const T& aKeyRange);
 
-  IDBKeyRange(nsISupports* aGlobal,
-              bool aLowerOpen,
+  IDBKeyRange(bool aLowerOpen,
               bool aUpperOpen,
               bool aIsOnly)
-  : mGlobal(aGlobal), mCachedLowerVal(JSVAL_VOID), mCachedUpperVal(JSVAL_VOID),
+  : mCachedLowerVal(JSVAL_VOID), mCachedUpperVal(JSVAL_VOID),
     mLowerOpen(aLowerOpen), mUpperOpen(aUpperOpen), mIsOnly(aIsOnly),
     mHaveCachedLowerVal(false), mHaveCachedUpperVal(false), mRooted(false)
   { }
 
   const Key& Lower() const
   {
     return mLower;
   }
@@ -100,17 +65,16 @@ public:
     return mIsOnly ? mLower : mUpper;
   }
 
   Key& Upper()
   {
     return mIsOnly ? mLower : mUpper;
   }
 
-  // TODO (bug 900578): Remove these in favour of LowerOpen() / UpperOpen().
   bool IsLowerOpen() const
   {
     return mLowerOpen;
   }
 
   bool IsUpperOpen() const
   {
     return mUpperOpen;
@@ -186,24 +150,23 @@ public:
   template <class T>
   void ToSerializedKeyRange(T& aKeyRange);
 
   void DropJSObjects();
 
 private:
   ~IDBKeyRange();
 
-  nsCOMPtr<nsISupports> mGlobal;
   Key mLower;
   Key mUpper;
   JS::Heap<JS::Value> mCachedLowerVal;
   JS::Heap<JS::Value> mCachedUpperVal;
-  const bool mLowerOpen;
-  const bool mUpperOpen;
-  const bool mIsOnly;
+  bool mLowerOpen;
+  bool mUpperOpen;
+  bool mIsOnly;
   bool mHaveCachedLowerVal;
   bool mHaveCachedUpperVal;
   bool mRooted;
 };
 
 END_INDEXEDDB_NAMESPACE
 
 #endif // mozilla_dom_indexeddb_idbkeyrange_h__
--- a/dom/indexedDB/IndexedDatabaseManager.cpp
+++ b/dom/indexedDB/IndexedDatabaseManager.cpp
@@ -1,28 +1,26 @@
 /* -*- 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 "IndexedDatabaseManager.h"
 
-#include "jsfriendapi.h"
 #include "nsIConsoleService.h"
 #include "nsIDiskSpaceWatcher.h"
 #include "nsIDOMScriptObjectFactory.h"
 #include "nsIFile.h"
 #include "nsIFileStorage.h"
 #include "nsIObserverService.h"
 #include "nsIScriptError.h"
 
 #include "mozilla/ClearOnShutdown.h"
 #include "mozilla/CondVar.h"
-#include "mozilla/dom/IDBKeyRangeBinding.h"
 #include "mozilla/dom/quota/QuotaManager.h"
 #include "mozilla/dom/quota/Utilities.h"
 #include "mozilla/dom/TabContext.h"
 #include "mozilla/Services.h"
 #include "mozilla/storage.h"
 #include "nsContentUtils.h"
 #include "nsEventDispatcher.h"
 #include "nsThreadUtils.h"
@@ -522,20 +520,16 @@ NS_IMPL_QUERY_INTERFACE2(IndexedDatabase
 
 NS_IMETHODIMP
 IndexedDatabaseManager::InitWindowless(const jsval& aObj, JSContext* aCx)
 {
   NS_ENSURE_TRUE(nsContentUtils::IsCallerChrome(), NS_ERROR_NOT_AVAILABLE);
   NS_ENSURE_ARG(!JSVAL_IS_PRIMITIVE(aObj));
 
   JS::Rooted<JSObject*> obj(aCx, JSVAL_TO_OBJECT(aObj));
-  if (!(js::GetObjectClass(obj)->flags & JSCLASS_DOM_GLOBAL)) {
-    NS_WARNING("initWindowless should only be called on a DOM global object.");
-    return NS_ERROR_FAILURE;
-  }
 
   JSBool hasIndexedDB;
   if (!JS_HasProperty(aCx, obj, "indexedDB", &hasIndexedDB)) {
     return NS_ERROR_FAILURE;
   }
 
   if (hasIndexedDB) {
     NS_WARNING("Passed object already has an 'indexedDB' property!");
@@ -561,20 +555,24 @@ IndexedDatabaseManager::InitWindowless(c
   rv = nsContentUtils::WrapNative(aCx, obj, factory, indexedDBVal.address());
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (!JS_DefineProperty(aCx, obj, "indexedDB", indexedDBVal, nullptr,
                          nullptr, JSPROP_ENUMERATE)) {
     return NS_ERROR_FAILURE;
   }
 
-  JS::Handle<JSObject*> keyrangeObj =
-    IDBKeyRangeBinding::GetConstructorObject(aCx, obj);
+  JS::Rooted<JSObject*> keyrangeObj(aCx,
+    JS_NewObject(aCx, nullptr, nullptr, nullptr));
   NS_ENSURE_TRUE(keyrangeObj, NS_ERROR_OUT_OF_MEMORY);
 
+  if (!IDBKeyRange::DefineConstructors(aCx, keyrangeObj)) {
+    return NS_ERROR_FAILURE;
+  }
+
   if (!JS_DefineProperty(aCx, obj, "IDBKeyRange", OBJECT_TO_JSVAL(keyrangeObj),
                          nullptr, nullptr, JSPROP_ENUMERATE)) {
     return NS_ERROR_FAILURE;
   }
 
   return NS_OK;
 }
 
--- a/dom/indexedDB/moz.build
+++ b/dom/indexedDB/moz.build
@@ -3,16 +3,17 @@
 # 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 += [
+    'nsIIDBKeyRange.idl',
     'nsIIndexedDatabaseManager.idl',
 ]
 
 XPIDL_MODULE = 'dom_indexeddb'
 
 XPIDL_FLAGS += [
     '-I$(topsrcdir)/dom/interfaces/base',
     '-I$(topsrcdir)/dom/interfaces/events',
new file mode 100644
--- /dev/null
+++ b/dom/indexedDB/nsIIDBKeyRange.idl
@@ -0,0 +1,25 @@
+/* -*- 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"
+
+/**
+ * IDBKeyRange interface.  See
+ * http://dev.w3.org/2006/webapi/WebSimpleDB/#idl-def-IDBKeyRange for more
+ * information.
+ */
+[scriptable, builtinclass, uuid(8aeb8660-76b3-4651-b8c2-9894ae6dfe68)]
+interface nsIIDBKeyRange : nsISupports
+{
+  [implicit_jscontext]
+  readonly attribute jsval lower;
+
+  [implicit_jscontext]
+  readonly attribute jsval upper;
+
+  readonly attribute boolean lowerOpen;
+  readonly attribute boolean upperOpen;
+};
deleted file mode 100644
--- a/dom/webidl/IDBKeyRange.webidl
+++ /dev/null
@@ -1,29 +0,0 @@
-/* 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/. */
-/*
- * The origin of this IDL file is
- * https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html
- *
- * Copyright © 2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
- * liability, trademark and document use rules apply.
- */
-
-interface IDBKeyRange {
-  [Throws]
-  readonly attribute any     lower;
-  [Throws]
-  readonly attribute any     upper;
-  [Constant]
-  readonly attribute boolean lowerOpen;
-  [Constant]
-  readonly attribute boolean upperOpen;
-  [Creator, Throws]
-  static IDBKeyRange only (any value);
-  [Creator, Throws]
-  static IDBKeyRange lowerBound (any lower, optional boolean open = false);
-  [Creator, Throws]
-  static IDBKeyRange upperBound (any upper, optional boolean open = false);
-  [Creator, Throws]
-  static IDBKeyRange bound (any lower, any upper, optional boolean lowerOpen = false, optional boolean upperOpen = false);
-};
--- a/dom/webidl/WebIDL.mk
+++ b/dom/webidl/WebIDL.mk
@@ -164,17 +164,16 @@ webidl_files = \
   HTMLTrackElement.webidl \
   HTMLUListElement.webidl \
   HTMLVideoElement.webidl \
   IDBCursor.webidl \
   IDBDatabase.webidl \
   IDBFactory.webidl \
   IDBFileHandle.webidl \
   IDBIndex.webidl \
-  IDBKeyRange.webidl \
   IDBObjectStore.webidl \
   IDBOpenDBRequest.webidl \
   IDBRequest.webidl \
   IDBTransaction.webidl \
   IDBVersionChangeEvent.webidl \
   ImageData.webidl \
   ImageDocument.webidl \
   InspectorUtils.webidl \
--- a/js/xpconnect/src/dom_quickstubs.qsconf
+++ b/js/xpconnect/src/dom_quickstubs.qsconf
@@ -79,16 +79,17 @@ members = [
     'nsIBoxObject.x',
     'nsIBoxObject.y',
     'nsIBoxObject.screenX',
     'nsIBoxObject.screenY',
     'nsIBoxObject.width',
     'nsIBoxObject.height',
 
     # dom/indexedDB
+    'nsIIDBKeyRange.*',
     'nsIIndexedDatabaseManager.*',
 
     # dom/file
     'nsIDOMLockedFile.*',
 
     # dom/quota
     'nsIQuotaManager.*',
     'nsIQuotaRequest.*',