1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "base/basictypes.h"
9 #include "IDBKeyRange.h"
11 #include "nsIXPConnect.h"
13 #include "nsJSUtils.h"
14 #include "nsThreadUtils.h"
15 #include "nsContentUtils.h"
16 #include "nsDOMClassInfoID.h"
19 #include "mozilla/dom/IDBKeyRangeBinding.h"
20 #include "mozilla/dom/indexedDB/PIndexedDBIndex.h"
21 #include "mozilla/dom/indexedDB/PIndexedDBObjectStore.h"
23 using namespace mozilla
;
24 using namespace mozilla::dom
;
25 USING_INDEXEDDB_NAMESPACE
26 using namespace mozilla::dom::indexedDB::ipc
;
31 GetKeyFromJSVal(JSContext
* aCx
,
32 JS::Handle
<JS::Value
> aVal
,
34 bool aAllowUnset
= false)
36 nsresult rv
= aKey
.SetFromJSVal(aCx
, aVal
);
38 NS_ASSERTION(NS_ERROR_GET_MODULE(rv
) == NS_ERROR_MODULE_DOM_INDEXEDDB
,
43 if (aKey
.IsUnset() && !aAllowUnset
) {
44 return NS_ERROR_DOM_INDEXEDDB_DATA_ERR
;
50 } // anonymous namespace
54 IDBKeyRange::FromJSVal(JSContext
* aCx
,
55 JS::Handle
<JS::Value
> aVal
,
56 IDBKeyRange
** aKeyRange
)
58 nsRefPtr
<IDBKeyRange
> keyRange
;
60 if (aVal
.isNullOrUndefined()) {
61 // undefined and null returns no IDBKeyRange.
62 keyRange
.forget(aKeyRange
);
66 JS::Rooted
<JSObject
*> obj(aCx
, aVal
.isObject() ? &aVal
.toObject() : nullptr);
67 if (aVal
.isPrimitive() || JS_IsArrayObject(aCx
, obj
) ||
68 JS_ObjectIsDate(aCx
, obj
)) {
69 // A valid key returns an 'only' IDBKeyRange.
70 keyRange
= new IDBKeyRange(nullptr, false, false, true);
72 nsresult rv
= GetKeyFromJSVal(aCx
, aVal
, keyRange
->Lower());
78 MOZ_ASSERT(aVal
.isObject());
79 // An object is not permitted unless it's another IDBKeyRange.
80 if (NS_FAILED(UNWRAP_OBJECT(IDBKeyRange
, obj
, keyRange
))) {
81 return NS_ERROR_DOM_INDEXEDDB_DATA_ERR
;
85 keyRange
.forget(aKeyRange
);
91 already_AddRefed
<IDBKeyRange
>
92 IDBKeyRange::FromSerializedKeyRange(const T
& aKeyRange
)
94 nsRefPtr
<IDBKeyRange
> keyRange
=
95 new IDBKeyRange(nullptr, aKeyRange
.lowerOpen(), aKeyRange
.upperOpen(),
97 keyRange
->Lower() = aKeyRange
.lower();
98 if (!keyRange
->IsOnly()) {
99 keyRange
->Upper() = aKeyRange
.upper();
101 return keyRange
.forget();
106 IDBKeyRange::ToSerializedKeyRange(T
& aKeyRange
)
108 aKeyRange
.lowerOpen() = IsLowerOpen();
109 aKeyRange
.upperOpen() = IsUpperOpen();
110 aKeyRange
.isOnly() = IsOnly();
112 aKeyRange
.lower() = Lower();
114 aKeyRange
.upper() = Upper();
118 NS_IMPL_CYCLE_COLLECTION_CLASS(IDBKeyRange
)
120 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(IDBKeyRange
)
121 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGlobal
)
122 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
123 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
125 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(IDBKeyRange
)
126 NS_IMPL_CYCLE_COLLECTION_TRACE_JSVAL_MEMBER_CALLBACK(mCachedLowerVal
)
127 NS_IMPL_CYCLE_COLLECTION_TRACE_JSVAL_MEMBER_CALLBACK(mCachedUpperVal
)
128 NS_IMPL_CYCLE_COLLECTION_TRACE_END
130 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(IDBKeyRange
)
131 NS_IMPL_CYCLE_COLLECTION_UNLINK(mGlobal
)
132 tmp
->DropJSObjects();
133 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
135 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(IDBKeyRange
)
136 NS_INTERFACE_MAP_ENTRY(nsISupports
)
139 NS_IMPL_CYCLE_COLLECTING_ADDREF(IDBKeyRange
)
140 NS_IMPL_CYCLE_COLLECTING_RELEASE(IDBKeyRange
)
143 IDBKeyRange::DropJSObjects()
148 mCachedLowerVal
= JS::UndefinedValue();
149 mCachedUpperVal
= JS::UndefinedValue();
150 mHaveCachedLowerVal
= false;
151 mHaveCachedUpperVal
= false;
153 mozilla::DropJSObjects(this);
156 IDBKeyRange::~IDBKeyRange()
162 IDBKeyRange::WrapObject(JSContext
* aCx
)
164 return IDBKeyRangeBinding::Wrap(aCx
, this);
168 IDBKeyRange::GetLower(JSContext
* aCx
, JS::MutableHandle
<JS::Value
> aResult
,
171 MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
173 if (!mHaveCachedLowerVal
) {
175 mozilla::HoldJSObjects(this);
179 aRv
= Lower().ToJSVal(aCx
, mCachedLowerVal
);
184 mHaveCachedLowerVal
= true;
187 JS::ExposeValueToActiveJS(mCachedLowerVal
);
188 aResult
.set(mCachedLowerVal
);
192 IDBKeyRange::GetUpper(JSContext
* aCx
, JS::MutableHandle
<JS::Value
> aResult
,
195 MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
197 if (!mHaveCachedUpperVal
) {
199 mozilla::HoldJSObjects(this);
203 aRv
= Upper().ToJSVal(aCx
, mCachedUpperVal
);
208 mHaveCachedUpperVal
= true;
211 JS::ExposeValueToActiveJS(mCachedUpperVal
);
212 aResult
.set(mCachedUpperVal
);
216 already_AddRefed
<IDBKeyRange
>
217 IDBKeyRange::Only(const GlobalObject
& aGlobal
,
218 JS::Handle
<JS::Value
> aValue
, ErrorResult
& aRv
)
220 MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
222 nsRefPtr
<IDBKeyRange
> keyRange
=
223 new IDBKeyRange(aGlobal
.GetAsSupports(), false, false, true);
225 aRv
= GetKeyFromJSVal(aGlobal
.Context(), aValue
, keyRange
->Lower());
230 return keyRange
.forget();
234 already_AddRefed
<IDBKeyRange
>
235 IDBKeyRange::LowerBound(const GlobalObject
& aGlobal
,
236 JS::Handle
<JS::Value
> aValue
, bool aOpen
,
239 MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
241 nsRefPtr
<IDBKeyRange
> keyRange
=
242 new IDBKeyRange(aGlobal
.GetAsSupports(), aOpen
, true, false);
244 aRv
= GetKeyFromJSVal(aGlobal
.Context(), aValue
, keyRange
->Lower());
249 return keyRange
.forget();
253 already_AddRefed
<IDBKeyRange
>
254 IDBKeyRange::UpperBound(const GlobalObject
& aGlobal
,
255 JS::Handle
<JS::Value
> aValue
, bool aOpen
,
258 MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
260 nsRefPtr
<IDBKeyRange
> keyRange
=
261 new IDBKeyRange(aGlobal
.GetAsSupports(), true, aOpen
, false);
263 aRv
= GetKeyFromJSVal(aGlobal
.Context(), aValue
, keyRange
->Upper());
268 return keyRange
.forget();
272 already_AddRefed
<IDBKeyRange
>
273 IDBKeyRange::Bound(const GlobalObject
& aGlobal
,
274 JS::Handle
<JS::Value
> aLower
, JS::Handle
<JS::Value
> aUpper
,
275 bool aLowerOpen
, bool aUpperOpen
, ErrorResult
& aRv
)
277 MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
279 nsRefPtr
<IDBKeyRange
> keyRange
=
280 new IDBKeyRange(aGlobal
.GetAsSupports(), aLowerOpen
, aUpperOpen
, false);
282 aRv
= GetKeyFromJSVal(aGlobal
.Context(), aLower
, keyRange
->Lower());
287 aRv
= GetKeyFromJSVal(aGlobal
.Context(), aUpper
, keyRange
->Upper());
292 if (keyRange
->Lower() > keyRange
->Upper() ||
293 (keyRange
->Lower() == keyRange
->Upper() && (aLowerOpen
|| aUpperOpen
))) {
294 aRv
.Throw(NS_ERROR_DOM_INDEXEDDB_DATA_ERR
);
298 return keyRange
.forget();
301 // Explicitly instantiate for all our key range types... Grumble.
302 template already_AddRefed
<IDBKeyRange
>
303 IDBKeyRange::FromSerializedKeyRange
<KeyRange
> (const KeyRange
& aKeyRange
);
306 IDBKeyRange::ToSerializedKeyRange
<KeyRange
> (KeyRange
& aKeyRange
);