dom/indexedDB/IDBKeyRange.cpp

Wed, 31 Dec 2014 06:55:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:55:50 +0100
changeset 2
7e26c7da4463
permissions
-rw-r--r--

Added tag UPSTREAM_283F7C6 for changeset ca08bd8f51b2

michael@0 1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* vim: set ts=2 et sw=2 tw=80: */
michael@0 3 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 4 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 6
michael@0 7 #include "base/basictypes.h"
michael@0 8
michael@0 9 #include "IDBKeyRange.h"
michael@0 10
michael@0 11 #include "nsIXPConnect.h"
michael@0 12
michael@0 13 #include "nsJSUtils.h"
michael@0 14 #include "nsThreadUtils.h"
michael@0 15 #include "nsContentUtils.h"
michael@0 16 #include "nsDOMClassInfoID.h"
michael@0 17 #include "Key.h"
michael@0 18
michael@0 19 #include "mozilla/dom/IDBKeyRangeBinding.h"
michael@0 20 #include "mozilla/dom/indexedDB/PIndexedDBIndex.h"
michael@0 21 #include "mozilla/dom/indexedDB/PIndexedDBObjectStore.h"
michael@0 22
michael@0 23 using namespace mozilla;
michael@0 24 using namespace mozilla::dom;
michael@0 25 USING_INDEXEDDB_NAMESPACE
michael@0 26 using namespace mozilla::dom::indexedDB::ipc;
michael@0 27
michael@0 28 namespace {
michael@0 29
michael@0 30 inline nsresult
michael@0 31 GetKeyFromJSVal(JSContext* aCx,
michael@0 32 JS::Handle<JS::Value> aVal,
michael@0 33 Key& aKey,
michael@0 34 bool aAllowUnset = false)
michael@0 35 {
michael@0 36 nsresult rv = aKey.SetFromJSVal(aCx, aVal);
michael@0 37 if (NS_FAILED(rv)) {
michael@0 38 NS_ASSERTION(NS_ERROR_GET_MODULE(rv) == NS_ERROR_MODULE_DOM_INDEXEDDB,
michael@0 39 "Bad error code!");
michael@0 40 return rv;
michael@0 41 }
michael@0 42
michael@0 43 if (aKey.IsUnset() && !aAllowUnset) {
michael@0 44 return NS_ERROR_DOM_INDEXEDDB_DATA_ERR;
michael@0 45 }
michael@0 46
michael@0 47 return NS_OK;
michael@0 48 }
michael@0 49
michael@0 50 } // anonymous namespace
michael@0 51
michael@0 52 // static
michael@0 53 nsresult
michael@0 54 IDBKeyRange::FromJSVal(JSContext* aCx,
michael@0 55 JS::Handle<JS::Value> aVal,
michael@0 56 IDBKeyRange** aKeyRange)
michael@0 57 {
michael@0 58 nsRefPtr<IDBKeyRange> keyRange;
michael@0 59
michael@0 60 if (aVal.isNullOrUndefined()) {
michael@0 61 // undefined and null returns no IDBKeyRange.
michael@0 62 keyRange.forget(aKeyRange);
michael@0 63 return NS_OK;
michael@0 64 }
michael@0 65
michael@0 66 JS::Rooted<JSObject*> obj(aCx, aVal.isObject() ? &aVal.toObject() : nullptr);
michael@0 67 if (aVal.isPrimitive() || JS_IsArrayObject(aCx, obj) ||
michael@0 68 JS_ObjectIsDate(aCx, obj)) {
michael@0 69 // A valid key returns an 'only' IDBKeyRange.
michael@0 70 keyRange = new IDBKeyRange(nullptr, false, false, true);
michael@0 71
michael@0 72 nsresult rv = GetKeyFromJSVal(aCx, aVal, keyRange->Lower());
michael@0 73 if (NS_FAILED(rv)) {
michael@0 74 return rv;
michael@0 75 }
michael@0 76 }
michael@0 77 else {
michael@0 78 MOZ_ASSERT(aVal.isObject());
michael@0 79 // An object is not permitted unless it's another IDBKeyRange.
michael@0 80 if (NS_FAILED(UNWRAP_OBJECT(IDBKeyRange, obj, keyRange))) {
michael@0 81 return NS_ERROR_DOM_INDEXEDDB_DATA_ERR;
michael@0 82 }
michael@0 83 }
michael@0 84
michael@0 85 keyRange.forget(aKeyRange);
michael@0 86 return NS_OK;
michael@0 87 }
michael@0 88
michael@0 89 // static
michael@0 90 template <class T>
michael@0 91 already_AddRefed<IDBKeyRange>
michael@0 92 IDBKeyRange::FromSerializedKeyRange(const T& aKeyRange)
michael@0 93 {
michael@0 94 nsRefPtr<IDBKeyRange> keyRange =
michael@0 95 new IDBKeyRange(nullptr, aKeyRange.lowerOpen(), aKeyRange.upperOpen(),
michael@0 96 aKeyRange.isOnly());
michael@0 97 keyRange->Lower() = aKeyRange.lower();
michael@0 98 if (!keyRange->IsOnly()) {
michael@0 99 keyRange->Upper() = aKeyRange.upper();
michael@0 100 }
michael@0 101 return keyRange.forget();
michael@0 102 }
michael@0 103
michael@0 104 template <class T>
michael@0 105 void
michael@0 106 IDBKeyRange::ToSerializedKeyRange(T& aKeyRange)
michael@0 107 {
michael@0 108 aKeyRange.lowerOpen() = IsLowerOpen();
michael@0 109 aKeyRange.upperOpen() = IsUpperOpen();
michael@0 110 aKeyRange.isOnly() = IsOnly();
michael@0 111
michael@0 112 aKeyRange.lower() = Lower();
michael@0 113 if (!IsOnly()) {
michael@0 114 aKeyRange.upper() = Upper();
michael@0 115 }
michael@0 116 }
michael@0 117
michael@0 118 NS_IMPL_CYCLE_COLLECTION_CLASS(IDBKeyRange)
michael@0 119
michael@0 120 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(IDBKeyRange)
michael@0 121 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGlobal)
michael@0 122 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
michael@0 123 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
michael@0 124
michael@0 125 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(IDBKeyRange)
michael@0 126 NS_IMPL_CYCLE_COLLECTION_TRACE_JSVAL_MEMBER_CALLBACK(mCachedLowerVal)
michael@0 127 NS_IMPL_CYCLE_COLLECTION_TRACE_JSVAL_MEMBER_CALLBACK(mCachedUpperVal)
michael@0 128 NS_IMPL_CYCLE_COLLECTION_TRACE_END
michael@0 129
michael@0 130 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(IDBKeyRange)
michael@0 131 NS_IMPL_CYCLE_COLLECTION_UNLINK(mGlobal)
michael@0 132 tmp->DropJSObjects();
michael@0 133 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
michael@0 134
michael@0 135 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(IDBKeyRange)
michael@0 136 NS_INTERFACE_MAP_ENTRY(nsISupports)
michael@0 137 NS_INTERFACE_MAP_END
michael@0 138
michael@0 139 NS_IMPL_CYCLE_COLLECTING_ADDREF(IDBKeyRange)
michael@0 140 NS_IMPL_CYCLE_COLLECTING_RELEASE(IDBKeyRange)
michael@0 141
michael@0 142 void
michael@0 143 IDBKeyRange::DropJSObjects()
michael@0 144 {
michael@0 145 if (!mRooted) {
michael@0 146 return;
michael@0 147 }
michael@0 148 mCachedLowerVal = JS::UndefinedValue();
michael@0 149 mCachedUpperVal = JS::UndefinedValue();
michael@0 150 mHaveCachedLowerVal = false;
michael@0 151 mHaveCachedUpperVal = false;
michael@0 152 mRooted = false;
michael@0 153 mozilla::DropJSObjects(this);
michael@0 154 }
michael@0 155
michael@0 156 IDBKeyRange::~IDBKeyRange()
michael@0 157 {
michael@0 158 DropJSObjects();
michael@0 159 }
michael@0 160
michael@0 161 JSObject*
michael@0 162 IDBKeyRange::WrapObject(JSContext* aCx)
michael@0 163 {
michael@0 164 return IDBKeyRangeBinding::Wrap(aCx, this);
michael@0 165 }
michael@0 166
michael@0 167 void
michael@0 168 IDBKeyRange::GetLower(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
michael@0 169 ErrorResult& aRv)
michael@0 170 {
michael@0 171 MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
michael@0 172
michael@0 173 if (!mHaveCachedLowerVal) {
michael@0 174 if (!mRooted) {
michael@0 175 mozilla::HoldJSObjects(this);
michael@0 176 mRooted = true;
michael@0 177 }
michael@0 178
michael@0 179 aRv = Lower().ToJSVal(aCx, mCachedLowerVal);
michael@0 180 if (aRv.Failed()) {
michael@0 181 return;
michael@0 182 }
michael@0 183
michael@0 184 mHaveCachedLowerVal = true;
michael@0 185 }
michael@0 186
michael@0 187 JS::ExposeValueToActiveJS(mCachedLowerVal);
michael@0 188 aResult.set(mCachedLowerVal);
michael@0 189 }
michael@0 190
michael@0 191 void
michael@0 192 IDBKeyRange::GetUpper(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
michael@0 193 ErrorResult& aRv)
michael@0 194 {
michael@0 195 MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
michael@0 196
michael@0 197 if (!mHaveCachedUpperVal) {
michael@0 198 if (!mRooted) {
michael@0 199 mozilla::HoldJSObjects(this);
michael@0 200 mRooted = true;
michael@0 201 }
michael@0 202
michael@0 203 aRv = Upper().ToJSVal(aCx, mCachedUpperVal);
michael@0 204 if (aRv.Failed()) {
michael@0 205 return;
michael@0 206 }
michael@0 207
michael@0 208 mHaveCachedUpperVal = true;
michael@0 209 }
michael@0 210
michael@0 211 JS::ExposeValueToActiveJS(mCachedUpperVal);
michael@0 212 aResult.set(mCachedUpperVal);
michael@0 213 }
michael@0 214
michael@0 215 // static
michael@0 216 already_AddRefed<IDBKeyRange>
michael@0 217 IDBKeyRange::Only(const GlobalObject& aGlobal, JSContext* aCx,
michael@0 218 JS::Handle<JS::Value> aValue, ErrorResult& aRv)
michael@0 219 {
michael@0 220 MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
michael@0 221
michael@0 222 nsRefPtr<IDBKeyRange> keyRange =
michael@0 223 new IDBKeyRange(aGlobal.GetAsSupports(), false, false, true);
michael@0 224
michael@0 225 aRv = GetKeyFromJSVal(aCx, aValue, keyRange->Lower());
michael@0 226 if (aRv.Failed()) {
michael@0 227 return nullptr;
michael@0 228 }
michael@0 229
michael@0 230 return keyRange.forget();
michael@0 231 }
michael@0 232
michael@0 233 // static
michael@0 234 already_AddRefed<IDBKeyRange>
michael@0 235 IDBKeyRange::LowerBound(const GlobalObject& aGlobal, JSContext* aCx,
michael@0 236 JS::Handle<JS::Value> aValue, bool aOpen,
michael@0 237 ErrorResult& aRv)
michael@0 238 {
michael@0 239 MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
michael@0 240
michael@0 241 nsRefPtr<IDBKeyRange> keyRange =
michael@0 242 new IDBKeyRange(aGlobal.GetAsSupports(), aOpen, true, false);
michael@0 243
michael@0 244 aRv = GetKeyFromJSVal(aCx, aValue, keyRange->Lower());
michael@0 245 if (aRv.Failed()) {
michael@0 246 return nullptr;
michael@0 247 }
michael@0 248
michael@0 249 return keyRange.forget();
michael@0 250 }
michael@0 251
michael@0 252 // static
michael@0 253 already_AddRefed<IDBKeyRange>
michael@0 254 IDBKeyRange::UpperBound(const GlobalObject& aGlobal, JSContext* aCx,
michael@0 255 JS::Handle<JS::Value> aValue, bool aOpen,
michael@0 256 ErrorResult& aRv)
michael@0 257 {
michael@0 258 MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
michael@0 259
michael@0 260 nsRefPtr<IDBKeyRange> keyRange =
michael@0 261 new IDBKeyRange(aGlobal.GetAsSupports(), true, aOpen, false);
michael@0 262
michael@0 263 aRv = GetKeyFromJSVal(aCx, aValue, keyRange->Upper());
michael@0 264 if (aRv.Failed()) {
michael@0 265 return nullptr;
michael@0 266 }
michael@0 267
michael@0 268 return keyRange.forget();
michael@0 269 }
michael@0 270
michael@0 271 // static
michael@0 272 already_AddRefed<IDBKeyRange>
michael@0 273 IDBKeyRange::Bound(const GlobalObject& aGlobal, JSContext* aCx,
michael@0 274 JS::Handle<JS::Value> aLower, JS::Handle<JS::Value> aUpper,
michael@0 275 bool aLowerOpen, bool aUpperOpen, ErrorResult& aRv)
michael@0 276 {
michael@0 277 MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
michael@0 278
michael@0 279 nsRefPtr<IDBKeyRange> keyRange =
michael@0 280 new IDBKeyRange(aGlobal.GetAsSupports(), aLowerOpen, aUpperOpen, false);
michael@0 281
michael@0 282 aRv = GetKeyFromJSVal(aCx, aLower, keyRange->Lower());
michael@0 283 if (aRv.Failed()) {
michael@0 284 return nullptr;
michael@0 285 }
michael@0 286
michael@0 287 aRv = GetKeyFromJSVal(aCx, aUpper, keyRange->Upper());
michael@0 288 if (aRv.Failed()) {
michael@0 289 return nullptr;
michael@0 290 }
michael@0 291
michael@0 292 if (keyRange->Lower() > keyRange->Upper() ||
michael@0 293 (keyRange->Lower() == keyRange->Upper() && (aLowerOpen || aUpperOpen))) {
michael@0 294 aRv.Throw(NS_ERROR_DOM_INDEXEDDB_DATA_ERR);
michael@0 295 return nullptr;
michael@0 296 }
michael@0 297
michael@0 298 return keyRange.forget();
michael@0 299 }
michael@0 300
michael@0 301 // Explicitly instantiate for all our key range types... Grumble.
michael@0 302 template already_AddRefed<IDBKeyRange>
michael@0 303 IDBKeyRange::FromSerializedKeyRange<KeyRange> (const KeyRange& aKeyRange);
michael@0 304
michael@0 305 template void
michael@0 306 IDBKeyRange::ToSerializedKeyRange<KeyRange> (KeyRange& aKeyRange);

mercurial