author | Ben Turner <bent.mozilla@gmail.com> |
Thu, 03 Nov 2011 08:57:30 -0700 | |
changeset 79688 | ad1f423c7755a2da364024f9b4665bf54e43f66c |
parent 79687 | ce1330a5c9cb4a3d590dc81b378e5236279aa76f |
child 79689 | 776dc60cee13872d318d2aaf34b4cb2e78114432 |
push id | 21419 |
push user | bmo@edmorley.co.uk |
push date | Thu, 03 Nov 2011 19:51:58 +0000 |
treeherder | mozilla-central@f8d66a792ddc [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | sicking |
bugs | 692669 |
milestone | 10.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
|
--- a/content/base/public/nsINode.h +++ b/content/base/public/nsINode.h @@ -46,16 +46,23 @@ #include "nsCOMPtr.h" #include "nsWrapperCache.h" #include "nsIProgrammingLanguage.h" // for ::JAVASCRIPT #include "nsDOMError.h" #include "nsDOMString.h" #include "jspubtd.h" #include "nsDOMMemoryReporter.h" +// Including 'windows.h' will #define GetClassInfo to something else. +#ifdef XP_WIN +#ifdef GetClassInfo +#undef GetClassInfo +#endif +#endif + class nsIContent; class nsIDocument; class nsIDOMEvent; class nsIDOMNode; class nsIDOMElement; class nsIDOMNodeList; class nsINodeList; class nsIPresShell;
--- a/dom/indexedDB/DatabaseInfo.h +++ b/dom/indexedDB/DatabaseInfo.h @@ -38,16 +38,17 @@ * ***** END LICENSE BLOCK ***** */ #ifndef mozilla_dom_indexeddb_databaseinfo_h__ #define mozilla_dom_indexeddb_databaseinfo_h__ // Only meant to be included in IndexedDB source files, not exported. #include "IndexedDatabase.h" +#include "Key.h" #include "IDBObjectStore.h" BEGIN_INDEXEDDB_NAMESPACE struct DatabaseInfo { #ifdef NS_BUILD_REFCNT_LOGGING DatabaseInfo();
--- a/dom/indexedDB/IDBCursor.cpp +++ b/dom/indexedDB/IDBCursor.cpp @@ -34,18 +34,16 @@ * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ #include "IDBCursor.h" -#include "nsIVariant.h" - #include "jscntxt.h" #include "mozilla/storage.h" #include "nsComponentManagerUtils.h" #include "nsContentUtils.h" #include "nsDOMClassInfoID.h" #include "nsEventDispatcher.h" #include "nsJSUtils.h" #include "nsThreadUtils.h" @@ -270,18 +268,20 @@ IDBCursor::CreateCommon(IDBRequest* aReq cursor->mRangeKey = aRangeKey; return cursor.forget(); } IDBCursor::IDBCursor() : mType(OBJECTSTORE), mDirection(nsIIDBCursor::NEXT), + mCachedKey(JSVAL_VOID), mCachedPrimaryKey(JSVAL_VOID), mCachedValue(JSVAL_VOID), + mHaveCachedKey(false), mHaveCachedPrimaryKey(false), mHaveCachedValue(false), mRooted(false), mContinueCalled(false), mHaveValue(true) { NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); } @@ -306,37 +306,45 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN( nsIDOMEventTarget) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mObjectStore) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mIndex) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOwner) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mScriptContext) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(IDBCursor) + NS_ASSERTION(tmp->mHaveCachedKey || JSVAL_IS_VOID(tmp->mCachedKey), + "Should have a cached key"); NS_ASSERTION(tmp->mHaveCachedPrimaryKey || JSVAL_IS_VOID(tmp->mCachedPrimaryKey), "Should have a cached primary key"); NS_ASSERTION(tmp->mHaveCachedValue || JSVAL_IS_VOID(tmp->mCachedValue), "Should have a cached value"); - if (JSVAL_IS_GCTHING(tmp->mCachedValue)) { - void *gcThing = JSVAL_TO_GCTHING(tmp->mCachedValue); - NS_IMPL_CYCLE_COLLECTION_TRACE_JS_CALLBACK(gcThing, "mCachedValue") + if (JSVAL_IS_GCTHING(tmp->mCachedKey)) { + void *gcThing = JSVAL_TO_GCTHING(tmp->mCachedKey); + NS_IMPL_CYCLE_COLLECTION_TRACE_JS_CALLBACK(gcThing, "mCachedKey") } if (JSVAL_IS_GCTHING(tmp->mCachedPrimaryKey)) { void *gcThing = JSVAL_TO_GCTHING(tmp->mCachedPrimaryKey); NS_IMPL_CYCLE_COLLECTION_TRACE_JS_CALLBACK(gcThing, "mCachedPrimaryKey") } + if (JSVAL_IS_GCTHING(tmp->mCachedValue)) { + void *gcThing = JSVAL_TO_GCTHING(tmp->mCachedValue); + NS_IMPL_CYCLE_COLLECTION_TRACE_JS_CALLBACK(gcThing, "mCachedValue") + } NS_IMPL_CYCLE_COLLECTION_TRACE_END NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(IDBCursor) // Don't unlink mObjectStore, mIndex, or mTransaction! if (tmp->mRooted) { NS_DROP_JS_OBJECTS(tmp, IDBCursor); + tmp->mCachedKey = JSVAL_VOID; tmp->mCachedPrimaryKey = JSVAL_VOID; tmp->mCachedValue = JSVAL_VOID; + tmp->mHaveCachedKey = false; tmp->mHaveCachedPrimaryKey = false; tmp->mHaveCachedValue = false; tmp->mRooted = false; tmp->mHaveValue = false; } NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mRequest) NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOwner) NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mScriptContext) @@ -373,53 +381,43 @@ IDBCursor::GetSource(nsISupports** aSour NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); return mType == OBJECTSTORE ? CallQueryInterface(mObjectStore, aSource) : CallQueryInterface(mIndex, aSource); } NS_IMETHODIMP -IDBCursor::GetKey(nsIVariant** aKey) +IDBCursor::GetKey(JSContext* aCx, + jsval* aKey) { NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); - if (!mCachedKey) { - nsresult rv; - nsCOMPtr<nsIWritableVariant> variant = - do_CreateInstance(NS_VARIANT_CONTRACTID, &rv); - NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); - - NS_ASSERTION(!mKey.IsUnset() || !mHaveValue, "Bad key!"); + NS_ASSERTION(!mKey.IsUnset() || !mHaveValue, "Bad key!"); - if (!mHaveValue) { - rv = variant->SetAsVoid(); - } - else if (mKey.IsString()) { - rv = variant->SetAsAString(mKey.StringValue()); - } - else if (mKey.IsInt()) { - rv = variant->SetAsInt64(mKey.IntValue()); - } - else { - NS_NOTREACHED("Huh?!"); - } - NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); - - rv = variant->SetWritable(false); - NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); - - nsIWritableVariant* result; - variant.forget(&result); - - mCachedKey = dont_AddRef(static_cast<nsIVariant*>(result)); + if (!mHaveValue) { + *aKey = JSVAL_VOID; + return NS_OK; } - nsCOMPtr<nsIVariant> result(mCachedKey); - result.forget(aKey); + if (!mHaveCachedKey) { + if (!mRooted) { + NS_HOLD_JS_OBJECTS(this, IDBCursor); + mRooted = true; + } + + JSAutoRequest ar(aCx); + + nsresult rv = mKey.ToJSVal(aCx, &mCachedKey); + NS_ENSURE_SUCCESS(rv, rv); + + mHaveCachedKey = true; + } + + *aKey = mCachedKey; return NS_OK; } NS_IMETHODIMP IDBCursor::GetPrimaryKey(JSContext* aCx, jsval* aValue) { NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); @@ -435,19 +433,19 @@ IDBCursor::GetPrimaryKey(JSContext* aCx, mRooted = true; } JSAutoRequest ar(aCx); NS_ASSERTION(mType == OBJECTSTORE ? !mKey.IsUnset() : !mObjectKey.IsUnset(), "Bad key!"); - nsresult rv = - IDBObjectStore::GetJSValFromKey(mType == OBJECTSTORE ? mKey : mObjectKey, - aCx, &mCachedPrimaryKey); + const Key& key = mType == OBJECTSTORE ? mKey : mObjectKey; + + nsresult rv = key.ToJSVal(aCx, &mCachedPrimaryKey); NS_ENSURE_SUCCESS(rv, rv); mHaveCachedPrimaryKey = true; } *aValue = mCachedPrimaryKey; return NS_OK; } @@ -493,17 +491,17 @@ IDBCursor::Continue(const jsval &aKey, return NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR; } if (!mHaveValue || mContinueCalled) { return NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR; } Key key; - nsresult rv = IDBObjectStore::GetKeyFromJSVal(aKey, aCx, key); + nsresult rv = key.SetFromJSVal(aCx, aKey); NS_ENSURE_SUCCESS(rv, rv); if (!key.IsUnset()) { switch (mDirection) { case nsIIDBCursor::NEXT: case nsIIDBCursor::NEXT_NO_DUPLICATE: if (key <= mKey) { return NS_ERROR_DOM_INDEXEDDB_DATA_ERR; @@ -583,17 +581,17 @@ IDBCursor::Update(const jsval& aValue, NS_ASSERTION(mObjectStore, "This cannot be null!"); NS_ASSERTION(!mKey.IsUnset() , "Bad key!"); NS_ASSERTION(mType != INDEXOBJECT || !mObjectKey.IsUnset(), "Bad key!"); nsresult rv; JSAutoRequest ar(aCx); - const Key& objectKey = (mType == OBJECTSTORE) ? mKey : mObjectKey; + Key& objectKey = (mType == OBJECTSTORE) ? mKey : mObjectKey; if (!mObjectStore->KeyPath().IsEmpty()) { // This has to be an object. if (JSVAL_IS_PRIMITIVE(aValue)) { return NS_ERROR_DOM_INDEXEDDB_DATA_ERR; } // Make sure the object given has the correct keyPath value set on it. @@ -601,30 +599,30 @@ IDBCursor::Update(const jsval& aValue, jsval prop; JSBool ok = JS_GetUCProperty(aCx, JSVAL_TO_OBJECT(aValue), reinterpret_cast<const jschar*>(keyPath.get()), keyPath.Length(), &prop); NS_ENSURE_TRUE(ok, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); Key key; - rv = IDBObjectStore::GetKeyFromJSVal(prop, aCx, key); + rv = key.SetFromJSVal(aCx, prop); if (NS_FAILED(rv)) { return rv; } if (key != objectKey) { return NS_ERROR_DOM_INDEXEDDB_DATA_ERR; } return mObjectStore->Put(aValue, JSVAL_VOID, aCx, 0, _retval); } jsval keyVal; - rv = IDBObjectStore::GetJSValFromKey(objectKey, aCx, &keyVal); + rv = objectKey.ToJSVal(aCx, &keyVal); NS_ENSURE_SUCCESS(rv, rv); return mObjectStore->Put(aValue, keyVal, aCx, 1, _retval); } NS_IMETHODIMP IDBCursor::Delete(JSContext* aCx, nsIIDBRequest** _retval) @@ -641,20 +639,20 @@ IDBCursor::Delete(JSContext* aCx, if (!mHaveValue || mType == INDEXKEY) { return NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR; } NS_ASSERTION(mObjectStore, "This cannot be null!"); NS_ASSERTION(!mKey.IsUnset() , "Bad key!"); - const Key& objectKey = (mType == OBJECTSTORE) ? mKey : mObjectKey; + Key& objectKey = (mType == OBJECTSTORE) ? mKey : mObjectKey; jsval key; - nsresult rv = IDBObjectStore::GetJSValFromKey(objectKey, aCx, &key); + nsresult rv = objectKey.ToJSVal(aCx, &key); NS_ENSURE_SUCCESS(rv, rv); return mObjectStore->Delete(key, aCx, _retval); } nsresult ContinueHelper::DoDatabaseWork(mozIStorageConnection* aConnection) { @@ -683,46 +681,47 @@ ContinueHelper::DoDatabaseWork(mozIStora rv = stmt->ExecuteStep(&hasResult); NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); if (hasResult) { rv = GatherResultsFromStatement(stmt); NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); } else { - mKey = Key::UNSETKEY; + mKey.Unset(); } return NS_OK; } nsresult ContinueHelper::GetSuccessResult(JSContext* aCx, jsval* aVal) { // Remove cached stuff from last time. - mCursor->mCachedKey = nsnull; - mCursor->mCachedValue = JSVAL_VOID; + mCursor->mCachedKey = JSVAL_VOID; mCursor->mCachedPrimaryKey = JSVAL_VOID; + mCursor->mCachedValue = JSVAL_VOID; + mCursor->mHaveCachedKey = false; + mCursor->mHaveCachedPrimaryKey = false; mCursor->mHaveCachedValue = false; - mCursor->mHaveCachedPrimaryKey = false; mCursor->mContinueCalled = false; if (mKey.IsUnset()) { mCursor->mHaveValue = false; *aVal = JSVAL_VOID; } else { NS_ASSERTION(mCursor->mType == IDBCursor::OBJECTSTORE || !mObjectKey.IsUnset(), "Bad key!"); // Set new values. mCursor->mKey = mKey; mCursor->mObjectKey = mObjectKey; - mCursor->mContinueToKey = Key::UNSETKEY; + mCursor->mContinueToKey.Unset(); mCursor->mCloneBuffer.swap(mCloneBuffer); mCloneBuffer.clear(); nsresult rv = WrapNative(aCx, mCursor, aVal); NS_ENSURE_SUCCESS(rv, rv); } @@ -741,65 +740,37 @@ ContinueObjectStoreHelper::BindArguments NS_NAMED_LITERAL_CSTRING(currentKeyName, "current_key"); NS_NAMED_LITERAL_CSTRING(rangeKeyName, "range_key"); // Bind current key. const Key& currentKey = mCursor->mContinueToKey.IsUnset() ? mCursor->mKey : mCursor->mContinueToKey; - if (currentKey.IsString()) { - rv = aStatement->BindStringByName(currentKeyName, currentKey.StringValue()); - } - else if (currentKey.IsInt()) { - rv = aStatement->BindInt64ByName(currentKeyName, currentKey.IntValue()); - } - else { - NS_NOTREACHED("Bad key!"); - } - NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); + rv = currentKey.BindToStatement(aStatement, currentKeyName); + NS_ENSURE_SUCCESS(rv, rv); // Bind range key if it is specified. const Key& rangeKey = mCursor->mRangeKey; if (!rangeKey.IsUnset()) { - if (rangeKey.IsString()) { - rv = aStatement->BindStringByName(rangeKeyName, rangeKey.StringValue()); - } - else if (rangeKey.IsInt()) { - rv = aStatement->BindInt64ByName(rangeKeyName, rangeKey.IntValue()); - } - else { - NS_NOTREACHED("Bad key!"); - } - NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); + rv = rangeKey.BindToStatement(aStatement, rangeKeyName); + NS_ENSURE_SUCCESS(rv, rv); } return NS_OK; } nsresult ContinueObjectStoreHelper::GatherResultsFromStatement( mozIStorageStatement* aStatement) { // Figure out what kind of key we have next. - PRInt32 keyType; - nsresult rv = aStatement->GetTypeOfIndex(0, &keyType); - NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); - - if (keyType == mozIStorageStatement::VALUE_TYPE_INTEGER) { - mKey = aStatement->AsInt64(0); - } - else if (keyType == mozIStorageStatement::VALUE_TYPE_TEXT) { - rv = aStatement->GetString(0, mKey.ToString()); - NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); - } - else { - NS_NOTREACHED("Bad SQLite type!"); - } + nsresult rv = mKey.SetFromStatement(aStatement, 0); + NS_ENSURE_SUCCESS(rv, rv); rv = IDBObjectStore::GetStructuredCloneDataFromStatement(aStatement, 1, mCloneBuffer); NS_ENSURE_SUCCESS(rv, rv); return NS_OK; } @@ -813,152 +784,62 @@ ContinueIndexHelper::BindArgumentsToStat NS_NAMED_LITERAL_CSTRING(currentKeyName, "current_key"); // Bind current key. const Key& currentKey = mCursor->mContinueToKey.IsUnset() ? mCursor->mKey : mCursor->mContinueToKey; - if (currentKey.IsString()) { - rv = aStatement->BindStringByName(currentKeyName, currentKey.StringValue()); - } - else if (currentKey.IsInt()) { - rv = aStatement->BindInt64ByName(currentKeyName, currentKey.IntValue()); - } - else { - NS_NOTREACHED("Bad key!"); - } - NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); + rv = currentKey.BindToStatement(aStatement, currentKeyName); + NS_ENSURE_SUCCESS(rv, rv); // Bind range key if it is specified. if (!mCursor->mRangeKey.IsUnset()) { NS_NAMED_LITERAL_CSTRING(rangeKeyName, "range_key"); - if (mCursor->mRangeKey.IsString()) { - rv = aStatement->BindStringByName(rangeKeyName, - mCursor->mRangeKey.StringValue()); - } - else if (mCursor->mRangeKey.IsInt()) { - rv = aStatement->BindInt64ByName(rangeKeyName, - mCursor->mRangeKey.IntValue()); - } - else { - NS_NOTREACHED("Bad key!"); - } - NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); + rv = mCursor->mRangeKey.BindToStatement(aStatement, rangeKeyName); + NS_ENSURE_SUCCESS(rv, rv); } // Bind object key if duplicates are allowed and we're not continuing to a // specific key. if ((mCursor->mDirection == nsIIDBCursor::NEXT || mCursor->mDirection == nsIIDBCursor::PREV) && mCursor->mContinueToKey.IsUnset()) { NS_ASSERTION(!mCursor->mObjectKey.IsUnset(), "Bad key!"); NS_NAMED_LITERAL_CSTRING(objectKeyName, "object_key"); - if (mCursor->mObjectKey.IsString()) { - rv = aStatement->BindStringByName(objectKeyName, - mCursor->mObjectKey.StringValue()); - } - else if (mCursor->mObjectKey.IsInt()) { - rv = aStatement->BindInt64ByName(objectKeyName, - mCursor->mObjectKey.IntValue()); - } - else { - NS_NOTREACHED("Bad key!"); - } - NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); + rv = mCursor->mObjectKey.BindToStatement(aStatement, objectKeyName); + NS_ENSURE_SUCCESS(rv, rv); } return NS_OK; } nsresult ContinueIndexHelper::GatherResultsFromStatement( mozIStorageStatement* aStatement) { - PRInt32 keyType; - nsresult rv = aStatement->GetTypeOfIndex(0, &keyType); - NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); - - NS_ASSERTION(keyType == mozIStorageStatement::VALUE_TYPE_INTEGER || - keyType == mozIStorageStatement::VALUE_TYPE_TEXT, - "Bad key type!"); + nsresult rv = mKey.SetFromStatement(aStatement, 0); + NS_ENSURE_SUCCESS(rv, rv); - if (keyType == mozIStorageStatement::VALUE_TYPE_INTEGER) { - mKey = aStatement->AsInt64(0); - } - else if (keyType == mozIStorageStatement::VALUE_TYPE_TEXT) { - rv = aStatement->GetString(0, mKey.ToString()); - NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); - } - else { - NS_NOTREACHED("Bad SQLite type!"); - } - - rv = aStatement->GetTypeOfIndex(1, &keyType); - NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); - - NS_ASSERTION(keyType == mozIStorageStatement::VALUE_TYPE_INTEGER || - keyType == mozIStorageStatement::VALUE_TYPE_TEXT, - "Bad key type!"); - - if (keyType == mozIStorageStatement::VALUE_TYPE_INTEGER) { - mObjectKey = aStatement->AsInt64(1); - } - else if (keyType == mozIStorageStatement::VALUE_TYPE_TEXT) { - rv = aStatement->GetString(1, mObjectKey.ToString()); - NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); - } - else { - NS_NOTREACHED("Bad SQLite type!"); - } + rv = mObjectKey.SetFromStatement(aStatement, 1); + NS_ENSURE_SUCCESS(rv, rv); return NS_OK; } nsresult ContinueIndexObjectHelper::GatherResultsFromStatement( mozIStorageStatement* aStatement) { - PRInt32 keyType; - nsresult rv = aStatement->GetTypeOfIndex(0, &keyType); - NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); - - NS_ASSERTION(keyType == mozIStorageStatement::VALUE_TYPE_INTEGER || - keyType == mozIStorageStatement::VALUE_TYPE_TEXT, - "Bad key type!"); + nsresult rv = mKey.SetFromStatement(aStatement, 0); + NS_ENSURE_SUCCESS(rv, rv); - if (keyType == mozIStorageStatement::VALUE_TYPE_INTEGER) { - mKey = aStatement->AsInt64(0); - } - else if (keyType == mozIStorageStatement::VALUE_TYPE_TEXT) { - rv = aStatement->GetString(0, mKey.ToString()); - NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); - } - else { - NS_NOTREACHED("Bad SQLite type!"); - } - - rv = aStatement->GetTypeOfIndex(1, &keyType); - NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); - - NS_ASSERTION(keyType == mozIStorageStatement::VALUE_TYPE_INTEGER || - keyType == mozIStorageStatement::VALUE_TYPE_TEXT, - "Bad key type!"); - - if (keyType == mozIStorageStatement::VALUE_TYPE_INTEGER) { - mObjectKey = aStatement->AsInt64(1); - } - else if (keyType == mozIStorageStatement::VALUE_TYPE_TEXT) { - rv = aStatement->GetString(1, mObjectKey.ToString()); - NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); - } - else { - NS_NOTREACHED("Bad SQLite type!"); - } + rv = mObjectKey.SetFromStatement(aStatement, 1); + NS_ENSURE_SUCCESS(rv, rv); rv = IDBObjectStore::GetStructuredCloneDataFromStatement(aStatement, 2, mCloneBuffer); NS_ENSURE_SUCCESS(rv, rv); return NS_OK; }
--- a/dom/indexedDB/IDBCursor.h +++ b/dom/indexedDB/IDBCursor.h @@ -37,16 +37,17 @@ * * ***** END LICENSE BLOCK ***** */ #ifndef mozilla_dom_indexeddb_idbcursor_h__ #define mozilla_dom_indexeddb_idbcursor_h__ #include "mozilla/dom/indexedDB/IndexedDatabase.h" #include "mozilla/dom/indexedDB/IDBObjectStore.h" +#include "mozilla/dom/indexedDB/Key.h" #include "nsIIDBCursorWithValue.h" #include "nsCycleCollectionParticipant.h" class nsIRunnable; class nsIScriptContext; class nsPIDOMWindow; @@ -145,35 +146,34 @@ protected: nsRefPtr<IDBRequest> mRequest; nsRefPtr<IDBTransaction> mTransaction; nsRefPtr<IDBObjectStore> mObjectStore; nsRefPtr<IDBIndex> mIndex; nsCOMPtr<nsIScriptContext> mScriptContext; nsCOMPtr<nsPIDOMWindow> mOwner; - // Not cycle-collected, this is guaranteed to be primitive! - nsCOMPtr<nsIVariant> mCachedKey; - Type mType; PRUint16 mDirection; nsCString mContinueQuery; nsCString mContinueToQuery; // These are cycle-collected! + jsval mCachedKey; jsval mCachedPrimaryKey; jsval mCachedValue; Key mRangeKey; Key mKey; Key mObjectKey; JSAutoStructuredCloneBuffer mCloneBuffer; Key mContinueToKey; + bool mHaveCachedKey; bool mHaveCachedPrimaryKey; bool mHaveCachedValue; bool mRooted; bool mContinueCalled; bool mHaveValue; }; END_INDEXEDDB_NAMESPACE
--- a/dom/indexedDB/IDBDatabase.cpp +++ b/dom/indexedDB/IDBDatabase.cpp @@ -123,26 +123,16 @@ public: } private: // In-params. PRInt64 mObjectStoreId; }; NS_STACK_CLASS -class AutoFree -{ -public: - AutoFree(void* aPtr) : mPtr(aPtr) { } - ~AutoFree() { NS_Free(mPtr); } -private: - void* mPtr; -}; - -NS_STACK_CLASS class AutoRemoveObjectStore { public: AutoRemoveObjectStore(nsIAtom* aId, const nsAString& aName) : mId(aId), mName(aName) { } ~AutoRemoveObjectStore() @@ -157,85 +147,16 @@ public: mId = 0; } private: nsCOMPtr<nsIAtom> mId; nsString mName; }; -inline -nsresult -ConvertVariantToStringArray(nsIVariant* aVariant, - nsTArray<nsString>& aStringArray) -{ -#ifdef DEBUG - PRUint16 type; - NS_ASSERTION(NS_SUCCEEDED(aVariant->GetDataType(&type)) && - type == nsIDataType::VTYPE_ARRAY, "Bad arg!"); -#endif - - PRUint16 valueType; - nsIID iid; - PRUint32 valueCount; - void* rawArray; - - nsresult rv = aVariant->GetAsArray(&valueType, &iid, &valueCount, &rawArray); - NS_ENSURE_SUCCESS(rv, rv); - - AutoFree af(rawArray); - - // Just delete anything that we don't expect and return. - if (valueType != nsIDataType::VTYPE_WCHAR_STR) { - switch (valueType) { - case nsIDataType::VTYPE_ID: - case nsIDataType::VTYPE_CHAR_STR: { - char** charArray = reinterpret_cast<char**>(rawArray); - for (PRUint32 index = 0; index < valueCount; index++) { - if (charArray[index]) { - NS_Free(charArray[index]); - } - } - } break; - - case nsIDataType::VTYPE_INTERFACE: - case nsIDataType::VTYPE_INTERFACE_IS: { - nsISupports** supportsArray = reinterpret_cast<nsISupports**>(rawArray); - for (PRUint32 index = 0; index < valueCount; index++) { - NS_IF_RELEASE(supportsArray[index]); - } - } break; - - default: { - // The other types are primitives that do not need to be freed. - } - } - - return NS_ERROR_ILLEGAL_VALUE; - } - - PRUnichar** strings = reinterpret_cast<PRUnichar**>(rawArray); - - for (PRUint32 index = 0; index < valueCount; index++) { - nsString* newString = aStringArray.AppendElement(); - - if (!newString) { - NS_ERROR("Out of memory?"); - for (; index < valueCount; index++) { - NS_Free(strings[index]); - } - return NS_ERROR_OUT_OF_MEMORY; - } - - newString->Adopt(strings[index], -1); - } - - return NS_OK; -} - } // anonymous namespace // static already_AddRefed<IDBDatabase> IDBDatabase::Create(nsIScriptContext* aScriptContext, nsPIDOMWindow* aOwner, DatabaseInfo* aDatabaseInfo, const nsACString& aASCIIOrigin) @@ -689,147 +610,147 @@ IDBDatabase::DeleteObjectStore(const nsA nsresult rv = helper->DispatchToTransactionPool(); NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); ObjectStoreInfo::Remove(mDatabaseId, aName); return NS_OK; } NS_IMETHODIMP -IDBDatabase::Transaction(nsIVariant* aStoreNames, +IDBDatabase::Transaction(const jsval& aStoreNames, PRUint16 aMode, - PRUint32 aTimeout, JSContext* aCx, PRUint8 aOptionalArgCount, nsIIDBTransaction** _retval) { NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); if (IndexedDatabaseManager::IsShuttingDown()) { return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; } if (mClosed) { return NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR; } + DatabaseInfo* info; + if (!DatabaseInfo::Get(mDatabaseId, &info)) { + NS_ERROR("This should never fail!"); + } + + if (info->runningVersionChange) { + return NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR; + } + if (aOptionalArgCount) { if (aMode != nsIIDBTransaction::READ_WRITE && aMode != nsIIDBTransaction::READ_ONLY) { return NS_ERROR_DOM_INDEXEDDB_NON_TRANSIENT_ERR; } } else { aMode = nsIIDBTransaction::READ_ONLY; } - if (aOptionalArgCount <= 1) { - aTimeout = kDefaultDatabaseTimeoutSeconds; - } - - PRUint16 type; - nsresult rv = aStoreNames->GetDataType(&type); - NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); - - DatabaseInfo* info; - if (!DatabaseInfo::Get(mDatabaseId, &info)) { - NS_ERROR("This should never fail!"); - } - - if (info->runningVersionChange) { - return NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR; - } - + nsresult rv; nsTArray<nsString> storesToOpen; - switch (type) { - case nsIDataType::VTYPE_VOID: - case nsIDataType::VTYPE_EMPTY: - case nsIDataType::VTYPE_EMPTY_ARRAY: { - // Empty, request all object stores - if (!info->GetObjectStoreNames(storesToOpen)) { - NS_WARNING("Out of memory?"); + if (!JSVAL_IS_PRIMITIVE(aStoreNames)) { + JSObject* obj = JSVAL_TO_OBJECT(aStoreNames); + + // See if this is a JS array. + if (JS_IsArrayObject(aCx, obj)) { + jsuint length; + if (!JS_GetArrayLength(aCx, obj, &length)) { return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; } - } break; - case nsIDataType::VTYPE_WSTRING_SIZE_IS: { - // Single name - nsString name; - rv = aStoreNames->GetAsAString(name); - NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); - - if (!info->ContainsStoreName(name)) { - return NS_ERROR_DOM_INDEXEDDB_NOT_FOUND_ERR; + if (!length) { + return NS_ERROR_DOM_INVALID_ACCESS_ERR; } - if (!storesToOpen.AppendElement(name)) { - NS_WARNING("Out of memory?"); - return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; + storesToOpen.SetCapacity(length); + + for (jsuint index = 0; index < length; index++) { + jsval val; + JSString* jsstr; + nsDependentJSString str; + if (!JS_GetElement(aCx, obj, index, &val) || + !(jsstr = JS_ValueToString(aCx, val)) || + !str.init(aCx, jsstr)) { + return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; + } + + storesToOpen.AppendElement(str); } - } break; - case nsIDataType::VTYPE_ARRAY: { - nsTArray<nsString> names; - rv = ConvertVariantToStringArray(aStoreNames, names); + NS_ASSERTION(!storesToOpen.IsEmpty(), + "Must have something here or else code below will " + "misbehave!"); + } + else { + // Perhaps some kind of wrapped object? + nsIXPConnect* xpc = nsContentUtils::XPConnect(); + NS_ASSERTION(xpc, "This should never be null!"); + + nsCOMPtr<nsIXPConnectWrappedNative> wrapper; + rv = xpc->GetWrappedNativeOfJSObject(aCx, obj, getter_AddRefs(wrapper)); NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); - PRUint32 nameCount = names.Length(); - for (PRUint32 nameIndex = 0; nameIndex < nameCount; nameIndex++) { - nsString& name = names[nameIndex]; + if (wrapper) { + nsISupports* wrappedObject = wrapper->Native(); + NS_ENSURE_TRUE(wrappedObject, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); + + // We only accept DOMStringList. + nsCOMPtr<nsIDOMDOMStringList> list = do_QueryInterface(wrappedObject); + if (list) { + PRUint32 length; + rv = list->GetLength(&length); + NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); - if (!info->ContainsStoreName(name)) { - return NS_ERROR_DOM_INDEXEDDB_NOT_FOUND_ERR; - } + if (!length) { + return NS_ERROR_DOM_INVALID_ACCESS_ERR; + } + + storesToOpen.SetCapacity(length); - if (!storesToOpen.AppendElement(name)) { - NS_WARNING("Out of memory?"); - return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; + for (PRUint32 index = 0; index < length; index++) { + nsString* item = storesToOpen.AppendElement(); + NS_ASSERTION(item, "This should never fail!"); + + rv = list->Item(index, *item); + NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); + } + + NS_ASSERTION(!storesToOpen.IsEmpty(), + "Must have something here or else code below will " + "misbehave!"); } } - NS_ASSERTION(nameCount == storesToOpen.Length(), "Should have bailed!"); - } break; - - case nsIDataType::VTYPE_INTERFACE: - case nsIDataType::VTYPE_INTERFACE_IS: { - nsCOMPtr<nsISupports> supports; - nsID *iid; - rv = aStoreNames->GetAsInterface(&iid, getter_AddRefs(supports)); - NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); - - NS_Free(iid); - - nsCOMPtr<nsIDOMDOMStringList> stringList(do_QueryInterface(supports)); - if (!stringList) { - // We don't support anything other than nsIDOMDOMStringList. - return NS_ERROR_DOM_INDEXEDDB_NON_TRANSIENT_ERR; - } + } + } - PRUint32 stringCount; - rv = stringList->GetLength(&stringCount); - NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); - - for (PRUint32 stringIndex = 0; stringIndex < stringCount; stringIndex++) { - nsString name; - rv = stringList->Item(stringIndex, name); - NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); + // If our list is empty here then the argument must have been an object that + // we don't support or a primitive. Either way we convert to a string. + if (storesToOpen.IsEmpty()) { + JSString* jsstr; + nsDependentJSString str; + if (!(jsstr = JS_ValueToString(aCx, aStoreNames)) || + !str.init(aCx, jsstr)) { + return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; + } - if (!info->ContainsStoreName(name)) { - return NS_ERROR_DOM_INDEXEDDB_NOT_FOUND_ERR; - } + storesToOpen.AppendElement(str); + } - if (!storesToOpen.AppendElement(name)) { - NS_WARNING("Out of memory?"); - return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; - } - } - } break; - - default: - return NS_ERROR_DOM_INDEXEDDB_NON_TRANSIENT_ERR; + // Now check to make sure the object store names we collected actually exist. + for (PRUint32 index = 0; index < storesToOpen.Length(); index++) { + if (!info->ContainsStoreName(storesToOpen[index])) { + return NS_ERROR_DOM_INDEXEDDB_NOT_FOUND_ERR; + } } nsRefPtr<IDBTransaction> transaction = IDBTransaction::Create(this, storesToOpen, aMode, kDefaultDatabaseTimeoutSeconds); NS_ENSURE_TRUE(transaction, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); transaction.forget(_retval);
--- a/dom/indexedDB/IDBIndex.cpp +++ b/dom/indexedDB/IDBIndex.cpp @@ -47,16 +47,17 @@ #include "nsDOMClassInfoID.h" #include "nsEventDispatcher.h" #include "nsThreadUtils.h" #include "mozilla/storage.h" #include "AsyncConnectionHelper.h" #include "IDBCursor.h" #include "IDBEvents.h" +#include "IDBKeyRange.h" #include "IDBObjectStore.h" #include "IDBTransaction.h" #include "DatabaseInfo.h" USING_INDEXEDDB_NAMESPACE namespace { @@ -162,91 +163,79 @@ protected: }; class OpenKeyCursorHelper : public AsyncConnectionHelper { public: OpenKeyCursorHelper(IDBTransaction* aTransaction, IDBRequest* aRequest, IDBIndex* aIndex, - const Key& aLowerKey, - const Key& aUpperKey, - bool aLowerOpen, - bool aUpperOpen, + IDBKeyRange* aKeyRange, PRUint16 aDirection) : AsyncConnectionHelper(aTransaction, aRequest), mIndex(aIndex), - mLowerKey(aLowerKey), mUpperKey(aUpperKey), mLowerOpen(aLowerOpen), - mUpperOpen(aUpperOpen), mDirection(aDirection) + mKeyRange(aKeyRange), mDirection(aDirection) { } nsresult DoDatabaseWork(mozIStorageConnection* aConnection); nsresult GetSuccessResult(JSContext* aCx, jsval* aVal); void ReleaseMainThreadObjects() { mIndex = nsnull; + mKeyRange = nsnull; AsyncConnectionHelper::ReleaseMainThreadObjects(); } private: // In-params. nsRefPtr<IDBIndex> mIndex; - const Key mLowerKey; - const Key mUpperKey; - const bool mLowerOpen; - const bool mUpperOpen; + nsRefPtr<IDBKeyRange> mKeyRange; const PRUint16 mDirection; // Out-params. Key mKey; Key mObjectKey; nsCString mContinueQuery; nsCString mContinueToQuery; Key mRangeKey; }; class OpenCursorHelper : public AsyncConnectionHelper { public: OpenCursorHelper(IDBTransaction* aTransaction, IDBRequest* aRequest, IDBIndex* aIndex, - const Key& aLowerKey, - const Key& aUpperKey, - bool aLowerOpen, - bool aUpperOpen, + IDBKeyRange* aKeyRange, PRUint16 aDirection) : AsyncConnectionHelper(aTransaction, aRequest), mIndex(aIndex), - mLowerKey(aLowerKey), mUpperKey(aUpperKey), mLowerOpen(aLowerOpen), - mUpperOpen(aUpperOpen), mDirection(aDirection) + mKeyRange(aKeyRange), mDirection(aDirection) { } ~OpenCursorHelper() { IDBObjectStore::ClearStructuredCloneBuffer(mCloneBuffer); } nsresult DoDatabaseWork(mozIStorageConnection* aConnection); nsresult GetSuccessResult(JSContext* aCx, jsval* aVal); void ReleaseMainThreadObjects() { mIndex = nsnull; + mKeyRange = nsnull; AsyncConnectionHelper::ReleaseMainThreadObjects(); } private: // In-params. nsRefPtr<IDBIndex> mIndex; - const Key mLowerKey; - const Key mUpperKey; - const bool mLowerOpen; - const bool mUpperOpen; + nsRefPtr<IDBKeyRange> mKeyRange; const PRUint16 mDirection; // Out-params. Key mKey; Key mObjectKey; JSAutoStructuredCloneBuffer mCloneBuffer; nsCString mContinueQuery; nsCString mContinueToQuery; @@ -266,17 +255,17 @@ GenerateRequest(IDBIndex* aIndex) } // anonymous namespace // static already_AddRefed<IDBIndex> IDBIndex::Create(IDBObjectStore* aObjectStore, const IndexInfo* aIndexInfo) { - NS_PRECONDITION(NS_IsMainThread(), "Wrong thread!"); + NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); NS_ASSERTION(aObjectStore, "Null pointer!"); NS_ASSERTION(aIndexInfo, "Null pointer!"); IDBDatabase* database = aObjectStore->Transaction()->Database(); nsRefPtr<IDBIndex> index = new IDBIndex(); index->mScriptContext = database->ScriptContext(); @@ -292,22 +281,22 @@ IDBIndex::Create(IDBObjectStore* aObject return index.forget(); } IDBIndex::IDBIndex() : mId(LL_MININT), mUnique(false), mAutoIncrement(false) { - NS_PRECONDITION(NS_IsMainThread(), "Wrong thread!"); + NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); } IDBIndex::~IDBIndex() { - NS_PRECONDITION(NS_IsMainThread(), "Wrong thread!"); + NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); } NS_IMPL_CYCLE_COLLECTION_CLASS(IDBIndex) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(IDBIndex) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mObjectStore) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOwner) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mScriptContext) @@ -328,193 +317,174 @@ 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) { - NS_PRECONDITION(NS_IsMainThread(), "Wrong thread!"); + NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); aName.Assign(mName); return NS_OK; } NS_IMETHODIMP IDBIndex::GetStoreName(nsAString& aStoreName) { - NS_PRECONDITION(NS_IsMainThread(), "Wrong thread!"); + NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); return mObjectStore->GetName(aStoreName); } NS_IMETHODIMP IDBIndex::GetKeyPath(nsAString& aKeyPath) { - NS_PRECONDITION(NS_IsMainThread(), "Wrong thread!"); + NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); aKeyPath.Assign(mKeyPath); return NS_OK; } NS_IMETHODIMP IDBIndex::GetUnique(bool* aUnique) { - NS_PRECONDITION(NS_IsMainThread(), "Wrong thread!"); + NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); *aUnique = mUnique; return NS_OK; } NS_IMETHODIMP IDBIndex::GetObjectStore(nsIIDBObjectStore** aObjectStore) { NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); nsCOMPtr<nsIIDBObjectStore> objectStore(mObjectStore); objectStore.forget(aObjectStore); return NS_OK; } NS_IMETHODIMP -IDBIndex::Get(nsIVariant* aKey, +IDBIndex::Get(const jsval& aKey, + JSContext* aCx, nsIIDBRequest** _retval) { - NS_PRECONDITION(NS_IsMainThread(), "Wrong thread!"); + NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); IDBTransaction* transaction = mObjectStore->Transaction(); if (!transaction->IsOpen()) { return NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR; } Key key; - nsresult rv = IDBObjectStore::GetKeyFromVariant(aKey, key); + nsresult rv = key.SetFromJSVal(aCx, aKey); if (NS_FAILED(rv)) { return rv; } - if (key.IsUnset()) { - return NS_ERROR_DOM_INDEXEDDB_DATA_ERR; - } - nsRefPtr<IDBRequest> request = GenerateRequest(this); NS_ENSURE_TRUE(request, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); - nsRefPtr<GetHelper> helper = new GetHelper(transaction, request, this, key); + nsRefPtr<GetHelper> helper = + new GetHelper(transaction, request, this, key); rv = helper->DispatchToTransactionPool(); NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); request.forget(_retval); return NS_OK; } NS_IMETHODIMP -IDBIndex::GetKey(nsIVariant* aKey, +IDBIndex::GetKey(const jsval& aKey, + JSContext* aCx, nsIIDBRequest** _retval) { - NS_PRECONDITION(NS_IsMainThread(), "Wrong thread!"); + NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); IDBTransaction* transaction = mObjectStore->Transaction(); if (!transaction->IsOpen()) { return NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR; } Key key; - nsresult rv = IDBObjectStore::GetKeyFromVariant(aKey, key); + nsresult rv = key.SetFromJSVal(aCx, aKey); if (NS_FAILED(rv)) { return rv; } - if (key.IsUnset()) { - return NS_ERROR_DOM_INDEXEDDB_DATA_ERR; - } - nsRefPtr<IDBRequest> request = GenerateRequest(this); NS_ENSURE_TRUE(request, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); nsRefPtr<GetKeyHelper> helper = new GetKeyHelper(transaction, request, this, key); rv = helper->DispatchToTransactionPool(); NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); request.forget(_retval); return NS_OK; } NS_IMETHODIMP -IDBIndex::GetAll(nsIVariant* aKey, +IDBIndex::GetAll(const jsval& aKey, PRUint32 aLimit, + JSContext* aCx, PRUint8 aOptionalArgCount, nsIIDBRequest** _retval) { NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); IDBTransaction* transaction = mObjectStore->Transaction(); if (!transaction->IsOpen()) { return NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR; } - nsresult rv; - Key key; - if (aOptionalArgCount && - NS_FAILED(IDBObjectStore::GetKeyFromVariant(aKey, key))) { - PRUint16 type; - rv = aKey->GetDataType(&type); - NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); - - if (type != nsIDataType::VTYPE_EMPTY) { - return NS_ERROR_DOM_INDEXEDDB_DATA_ERR; - } + if (aOptionalArgCount && NS_FAILED(key.SetFromJSVal(aCx, aKey))) { + return NS_ERROR_DOM_INDEXEDDB_DATA_ERR; } if (aOptionalArgCount < 2) { aLimit = PR_UINT32_MAX; } nsRefPtr<IDBRequest> request = GenerateRequest(this); NS_ENSURE_TRUE(request, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); nsRefPtr<GetAllHelper> helper = new GetAllHelper(transaction, request, this, key, aLimit); - rv = helper->DispatchToTransactionPool(); + nsresult rv = helper->DispatchToTransactionPool(); NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); request.forget(_retval); return NS_OK; } NS_IMETHODIMP -IDBIndex::GetAllKeys(nsIVariant* aKey, +IDBIndex::GetAllKeys(const jsval& aKey, PRUint32 aLimit, + JSContext* aCx, PRUint8 aOptionalArgCount, nsIIDBRequest** _retval) { NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); IDBTransaction* transaction = mObjectStore->Transaction(); if (!transaction->IsOpen()) { return NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR; } nsresult rv; Key key; - if (aOptionalArgCount && - NS_FAILED(IDBObjectStore::GetKeyFromVariant(aKey, key))) { - PRUint16 type; - rv = aKey->GetDataType(&type); - NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); - - if (type != nsIDataType::VTYPE_EMPTY) { - return NS_ERROR_DOM_INDEXEDDB_DATA_ERR; - } + if (aOptionalArgCount && NS_FAILED(key.SetFromJSVal(aCx, aKey))) { + return NS_ERROR_DOM_INDEXEDDB_DATA_ERR; } if (aOptionalArgCount < 2) { aLimit = PR_UINT32_MAX; } nsRefPtr<IDBRequest> request = GenerateRequest(this); NS_ENSURE_TRUE(request, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); @@ -525,151 +495,125 @@ IDBIndex::GetAllKeys(nsIVariant* aKey, rv = helper->DispatchToTransactionPool(); NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); request.forget(_retval); return NS_OK; } NS_IMETHODIMP -IDBIndex::OpenCursor(nsIIDBKeyRange* aKeyRange, +IDBIndex::OpenCursor(const jsval& aKey, PRUint16 aDirection, + JSContext* aCx, PRUint8 aOptionalArgCount, nsIIDBRequest** _retval) { NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); IDBTransaction* transaction = mObjectStore->Transaction(); if (!transaction->IsOpen()) { return NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR; } nsresult rv; - Key lowerKey, upperKey; - bool lowerOpen = false, upperOpen = false; - if (aKeyRange) { - nsCOMPtr<nsIVariant> variant; - rv = aKeyRange->GetLower(getter_AddRefs(variant)); - NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); - - rv = IDBObjectStore::GetKeyFromVariant(variant, lowerKey); - if (NS_FAILED(rv)) { - return rv; - } - - rv = aKeyRange->GetUpper(getter_AddRefs(variant)); - NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); + nsRefPtr<IDBKeyRange> keyRange; + if (aOptionalArgCount) { + rv = IDBKeyRange::FromJSVal(aCx, aKey, getter_AddRefs(keyRange)); + NS_ENSURE_SUCCESS(rv, rv); - rv = IDBObjectStore::GetKeyFromVariant(variant, upperKey); - if (NS_FAILED(rv)) { - return rv; + if (aOptionalArgCount >= 2) { + if (aDirection != nsIIDBCursor::NEXT && + aDirection != nsIIDBCursor::NEXT_NO_DUPLICATE && + aDirection != nsIIDBCursor::PREV && + aDirection != nsIIDBCursor::PREV_NO_DUPLICATE) { + return NS_ERROR_DOM_INDEXEDDB_NON_TRANSIENT_ERR; + } } - - rv = aKeyRange->GetLowerOpen(&lowerOpen); - NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); - - rv = aKeyRange->GetUpperOpen(&upperOpen); - NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); - } - - if (aOptionalArgCount >= 2) { - if (aDirection != nsIIDBCursor::NEXT && - aDirection != nsIIDBCursor::NEXT_NO_DUPLICATE && - aDirection != nsIIDBCursor::PREV && - aDirection != nsIIDBCursor::PREV_NO_DUPLICATE) { - return NS_ERROR_DOM_INDEXEDDB_NON_TRANSIENT_ERR; + else { + aDirection = nsIIDBCursor::NEXT; } } - else { - aDirection = nsIIDBCursor::NEXT; - } nsRefPtr<IDBRequest> request = GenerateRequest(this); NS_ENSURE_TRUE(request, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); nsRefPtr<OpenCursorHelper> helper = - new OpenCursorHelper(transaction, request, this, lowerKey, upperKey, - lowerOpen, upperOpen, aDirection); + new OpenCursorHelper(transaction, request, this, keyRange, aDirection); rv = helper->DispatchToTransactionPool(); NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); request.forget(_retval); return NS_OK; } NS_IMETHODIMP -IDBIndex::OpenKeyCursor(nsIIDBKeyRange* aKeyRange, +IDBIndex::OpenKeyCursor(const jsval& aKey, PRUint16 aDirection, + JSContext* aCx, PRUint8 aOptionalArgCount, nsIIDBRequest** _retval) { NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); IDBTransaction* transaction = mObjectStore->Transaction(); if (!transaction->IsOpen()) { return NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR; } nsresult rv; - Key lowerKey, upperKey; - bool lowerOpen = false, upperOpen = false; - if (aKeyRange) { - nsCOMPtr<nsIVariant> variant; - rv = aKeyRange->GetLower(getter_AddRefs(variant)); - NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); - - rv = IDBObjectStore::GetKeyFromVariant(variant, lowerKey); - if (NS_FAILED(rv)) { - return rv; - } - - rv = aKeyRange->GetUpper(getter_AddRefs(variant)); - NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); + nsRefPtr<IDBKeyRange> keyRange; + if (aOptionalArgCount) { + rv = IDBKeyRange::FromJSVal(aCx, aKey, getter_AddRefs(keyRange)); + NS_ENSURE_SUCCESS(rv, rv); - rv = IDBObjectStore::GetKeyFromVariant(variant, upperKey); - if (NS_FAILED(rv)) { - return rv; + if (aOptionalArgCount >= 2) { + if (aDirection != nsIIDBCursor::NEXT && + aDirection != nsIIDBCursor::NEXT_NO_DUPLICATE && + aDirection != nsIIDBCursor::PREV && + aDirection != nsIIDBCursor::PREV_NO_DUPLICATE) { + return NS_ERROR_DOM_INDEXEDDB_NON_TRANSIENT_ERR; + } } - - rv = aKeyRange->GetLowerOpen(&lowerOpen); - NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); - - rv = aKeyRange->GetUpperOpen(&upperOpen); - NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); - } - - if (aOptionalArgCount >= 2) { - if (aDirection != nsIIDBCursor::NEXT && - aDirection != nsIIDBCursor::NEXT_NO_DUPLICATE && - aDirection != nsIIDBCursor::PREV && - aDirection != nsIIDBCursor::PREV_NO_DUPLICATE) { - return NS_ERROR_DOM_INDEXEDDB_NON_TRANSIENT_ERR; + else { + aDirection = nsIIDBCursor::NEXT; } } - else { - aDirection = nsIIDBCursor::NEXT; - } nsRefPtr<IDBRequest> request = GenerateRequest(this); NS_ENSURE_TRUE(request, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); nsRefPtr<OpenKeyCursorHelper> helper = - new OpenKeyCursorHelper(transaction, request, this, lowerKey, upperKey, - lowerOpen, upperOpen, aDirection); + new OpenKeyCursorHelper(transaction, request, this, keyRange, aDirection); rv = helper->DispatchToTransactionPool(); NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); request.forget(_retval); return NS_OK; } +/* +NS_IMETHODIMP +IDBIndex::Count(const jsval& aKey, + JSContext* aCx, + PRUint8 aOptionalArgCount, + nsIIDBRequest** _retval) +{ + IDBTransaction* transaction = mObjectStore->Transaction(); + if (!transaction->IsOpen()) { + return NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR; + } + + return NS_ERROR_NOT_IMPLEMENTED; +} +*/ + nsresult GetKeyHelper::DoDatabaseWork(mozIStorageConnection* aConnection) { NS_ASSERTION(aConnection, "Passed a null connection!"); nsCOMPtr<mozIStorageStatement> stmt = mTransaction->IndexGetStatement(mIndex->IsUnique(), mIndex->IsAutoIncrement()); @@ -678,63 +622,39 @@ GetKeyHelper::DoDatabaseWork(mozIStorage mozStorageStatementScoper scoper(stmt); nsresult rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("index_id"), mIndex->Id()); NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); NS_NAMED_LITERAL_CSTRING(value, "value"); - if (mKey.IsInt()) { - rv = stmt->BindInt64ByName(value, mKey.IntValue()); - } - else if (mKey.IsString()) { - rv = stmt->BindStringByName(value, mKey.StringValue()); - } - else { - NS_NOTREACHED("Bad key type!"); - } - NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); + rv = mKey.BindToStatement(stmt, value); + NS_ENSURE_SUCCESS(rv, rv); - mKey = Key::UNSETKEY; + mKey.Unset(); bool hasResult; rv = stmt->ExecuteStep(&hasResult); NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); if (hasResult) { - PRInt32 keyType; - rv = stmt->GetTypeOfIndex(0, &keyType); - NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); - - NS_ASSERTION(keyType == mozIStorageStatement::VALUE_TYPE_INTEGER || - keyType == mozIStorageStatement::VALUE_TYPE_TEXT, - "Bad key type!"); - - if (keyType == mozIStorageStatement::VALUE_TYPE_INTEGER) { - mKey = stmt->AsInt64(0); - } - else if (keyType == mozIStorageStatement::VALUE_TYPE_TEXT) { - rv = stmt->GetString(0, mKey.ToString()); - NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); - } - else { - NS_NOTREACHED("Bad SQLite type!"); - } + rv = mKey.SetFromStatement(stmt, 0); + NS_ENSURE_SUCCESS(rv, rv); } return NS_OK; } nsresult GetKeyHelper::GetSuccessResult(JSContext* aCx, jsval* aVal) { NS_ASSERTION(!mKey.IsUnset(), "Badness!"); - return IDBObjectStore::GetJSValFromKey(mKey, aCx, aVal); + return mKey.ToJSVal(aCx, aVal); } nsresult GetHelper::DoDatabaseWork(mozIStorageConnection* aConnection) { NS_ASSERTION(aConnection, "Passed a null connection!"); nsCOMPtr<mozIStorageStatement> stmt = @@ -745,28 +665,20 @@ GetHelper::DoDatabaseWork(mozIStorageCon mozStorageStatementScoper scoper(stmt); nsresult rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("index_id"), mIndex->Id()); NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); NS_NAMED_LITERAL_CSTRING(value, "value"); - if (mKey.IsInt()) { - rv = stmt->BindInt64ByName(value, mKey.IntValue()); - } - else if (mKey.IsString()) { - rv = stmt->BindStringByName(value, mKey.StringValue()); - } - else { - NS_NOTREACHED("Bad key type!"); - } - NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); + rv = mKey.BindToStatement(stmt, value); + NS_ENSURE_SUCCESS(rv, rv); - mKey = Key::UNSETKEY; + mKey.Unset(); bool hasResult; rv = stmt->ExecuteStep(&hasResult); NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); if (hasResult) { rv = IDBObjectStore::GetStructuredCloneDataFromStatement(stmt, 0, mCloneBuffer); @@ -845,58 +757,31 @@ GetAllKeysHelper::DoDatabaseWork(mozISto NS_ENSURE_TRUE(stmt, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); mozStorageStatementScoper scoper(stmt); nsresult rv = stmt->BindInt64ByName(indexId, mIndex->Id()); NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); if (!mKey.IsUnset()) { - if (mKey.IsInt()) { - rv = stmt->BindInt64ByName(value, mKey.IntValue()); - } - else if (mKey.IsString()) { - rv = stmt->BindStringByName(value, mKey.StringValue()); - } - else { - NS_NOTREACHED("Bad key type!"); - } - NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); + rv = mKey.BindToStatement(stmt, value); + NS_ENSURE_SUCCESS(rv, rv); } bool hasResult; while(NS_SUCCEEDED((rv = stmt->ExecuteStep(&hasResult))) && hasResult) { if (mKeys.Capacity() == mKeys.Length()) { - if (!mKeys.SetCapacity(mKeys.Capacity() * 2)) { - NS_ERROR("Out of memory!"); - return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; - } + mKeys.SetCapacity(mKeys.Capacity() * 2); } Key* key = mKeys.AppendElement(); NS_ASSERTION(key, "This shouldn't fail!"); - PRInt32 keyType; - rv = stmt->GetTypeOfIndex(0, &keyType); - NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); - - NS_ASSERTION(keyType == mozIStorageStatement::VALUE_TYPE_INTEGER || - keyType == mozIStorageStatement::VALUE_TYPE_TEXT, - "Bad key type!"); - - if (keyType == mozIStorageStatement::VALUE_TYPE_INTEGER) { - *key = stmt->AsInt64(0); - } - else if (keyType == mozIStorageStatement::VALUE_TYPE_TEXT) { - rv = stmt->GetString(0, key->ToString()); - NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); - } - else { - NS_NOTREACHED("Bad SQLite type!"); - } + rv = key->SetFromStatement(stmt, 0); + NS_ENSURE_SUCCESS(rv, rv); } NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); return NS_OK; } nsresult GetAllKeysHelper::GetSuccessResult(JSContext* aCx, @@ -924,17 +809,17 @@ GetAllKeysHelper::GetSuccessResult(JSCon return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; } for (uint32 index = 0, count = keys.Length(); index < count; index++) { const Key& key = keys[index]; NS_ASSERTION(!key.IsUnset(), "Bad key!"); jsval value; - nsresult rv = IDBObjectStore::GetJSValFromKey(key, aCx, &value); + nsresult rv = key.ToJSVal(aCx, &value); if (NS_FAILED(rv)) { NS_WARNING("Failed to get jsval for key!"); return rv; } if (!JS_SetElement(aCx, array, index, &value)) { NS_WARNING("Failed to set array element!"); return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; @@ -1009,26 +894,18 @@ GetAllHelper::DoDatabaseWork(mozIStorage NS_ENSURE_TRUE(stmt, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); mozStorageStatementScoper scoper(stmt); nsresult rv = stmt->BindInt64ByName(indexId, mIndex->Id()); NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); if (!mKey.IsUnset()) { - if (mKey.IsInt()) { - rv = stmt->BindInt64ByName(value, mKey.IntValue()); - } - else if (mKey.IsString()) { - rv = stmt->BindStringByName(value, mKey.StringValue()); - } - else { - NS_NOTREACHED("Bad key type!"); - } - NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); + rv = mKey.BindToStatement(stmt, value); + NS_ENSURE_SUCCESS(rv, rv); } bool hasResult; while(NS_SUCCEEDED((rv = stmt->ExecuteStep(&hasResult))) && hasResult) { if (mCloneBuffers.Capacity() == mCloneBuffers.Length()) { if (!mCloneBuffers.SetCapacity(mCloneBuffers.Capacity() * 2)) { NS_ERROR("Out of memory!"); return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; @@ -1091,23 +968,25 @@ OpenKeyCursorHelper::DoDatabaseWork(mozI NS_NAMED_LITERAL_CSTRING(id, "id"); NS_NAMED_LITERAL_CSTRING(lowerKeyName, "lower_key"); NS_NAMED_LITERAL_CSTRING(upperKeyName, "upper_key"); NS_NAMED_LITERAL_CSTRING(value, "value"); nsCAutoString keyRangeClause; - if (!mLowerKey.IsUnset()) { - AppendConditionClause(value, lowerKeyName, false, !mLowerOpen, - keyRangeClause); - } - if (!mUpperKey.IsUnset()) { - AppendConditionClause(value, upperKeyName, true, !mUpperOpen, - keyRangeClause); + if (mKeyRange) { + if (!mKeyRange->Lower().IsUnset()) { + AppendConditionClause(value, lowerKeyName, false, + !mKeyRange->IsLowerOpen(), keyRangeClause); + } + if (!mKeyRange->Upper().IsUnset()) { + AppendConditionClause(value, upperKeyName, true, + !mKeyRange->IsUpperOpen(), keyRangeClause); + } } nsCAutoString directionClause = NS_LITERAL_CSTRING(" ORDER BY ") + value; switch (mDirection) { case nsIIDBCursor::NEXT: case nsIIDBCursor::NEXT_NO_DUPLICATE: directionClause.AppendLiteral(" ASC"); break; @@ -1133,145 +1012,103 @@ OpenKeyCursorHelper::DoDatabaseWork(mozI mTransaction->GetCachedStatement(firstQuery); NS_ENSURE_TRUE(stmt, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); mozStorageStatementScoper scoper(stmt); nsresult rv = stmt->BindInt64ByName(id, mIndex->Id()); NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); - if (!mLowerKey.IsUnset()) { - if (mLowerKey.IsString()) { - rv = stmt->BindStringByName(lowerKeyName, mLowerKey.StringValue()); - } - else if (mLowerKey.IsInt()) { - rv = stmt->BindInt64ByName(lowerKeyName, mLowerKey.IntValue()); - } - else { - NS_NOTREACHED("Bad key!"); + if (mKeyRange) { + if (!mKeyRange->Lower().IsUnset()) { + rv = mKeyRange->Lower().BindToStatement(stmt, lowerKeyName); + NS_ENSURE_SUCCESS(rv, rv); } - NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); - } - - if (!mUpperKey.IsUnset()) { - if (mUpperKey.IsString()) { - rv = stmt->BindStringByName(upperKeyName, mUpperKey.StringValue()); + if (!mKeyRange->Upper().IsUnset()) { + rv = mKeyRange->Upper().BindToStatement(stmt, upperKeyName); + NS_ENSURE_SUCCESS(rv, rv); } - else if (mUpperKey.IsInt()) { - rv = stmt->BindInt64ByName(upperKeyName, mUpperKey.IntValue()); - } - else { - NS_NOTREACHED("Bad key!"); - } - NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); } bool hasResult; rv = stmt->ExecuteStep(&hasResult); NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); if (!hasResult) { - mKey = Key::UNSETKEY; + mKey.Unset(); return NS_OK; } - PRInt32 keyType; - rv = stmt->GetTypeOfIndex(0, &keyType); - NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); - - NS_ASSERTION(keyType == mozIStorageStatement::VALUE_TYPE_INTEGER || - keyType == mozIStorageStatement::VALUE_TYPE_TEXT, - "Bad key type!"); + rv = mKey.SetFromStatement(stmt, 0); + NS_ENSURE_SUCCESS(rv, rv); - if (keyType == mozIStorageStatement::VALUE_TYPE_INTEGER) { - mKey = stmt->AsInt64(0); - } - else if (keyType == mozIStorageStatement::VALUE_TYPE_TEXT) { - rv = stmt->GetString(0, mKey.ToString()); - NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); - } - else { - NS_NOTREACHED("Bad SQLite type!"); - } - - rv = stmt->GetTypeOfIndex(1, &keyType); - NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); - - NS_ASSERTION(keyType == mozIStorageStatement::VALUE_TYPE_INTEGER || - keyType == mozIStorageStatement::VALUE_TYPE_TEXT, - "Bad key type!"); - - if (keyType == mozIStorageStatement::VALUE_TYPE_INTEGER) { - mObjectKey = stmt->AsInt64(1); - } - else if (keyType == mozIStorageStatement::VALUE_TYPE_TEXT) { - rv = stmt->GetString(1, mObjectKey.ToString()); - NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); - } - else { - NS_NOTREACHED("Bad SQLite type!"); - } + rv = mObjectKey.SetFromStatement(stmt, 1); + NS_ENSURE_SUCCESS(rv, rv); // Now we need to make the query to get the next match. nsCAutoString queryStart = NS_LITERAL_CSTRING("SELECT value, ") + keyColumn + NS_LITERAL_CSTRING(" FROM ") + table + NS_LITERAL_CSTRING(" WHERE index_id = :") + id; NS_NAMED_LITERAL_CSTRING(currentKey, "current_key"); NS_NAMED_LITERAL_CSTRING(rangeKey, "range_key"); NS_NAMED_LITERAL_CSTRING(objectKey, "object_key"); switch (mDirection) { case nsIIDBCursor::NEXT: - if (!mUpperKey.IsUnset()) { - AppendConditionClause(value, rangeKey, true, !mUpperOpen, queryStart); - mRangeKey = mUpperKey; + if (mKeyRange && !mKeyRange->Upper().IsUnset()) { + AppendConditionClause(value, rangeKey, true, !mKeyRange->IsUpperOpen(), + queryStart); + mRangeKey = mKeyRange->Upper(); } mContinueQuery = queryStart + NS_LITERAL_CSTRING(" AND ( ( value = :") + currentKey + NS_LITERAL_CSTRING(" AND ") + keyColumn + NS_LITERAL_CSTRING(" > :") + objectKey + NS_LITERAL_CSTRING(" ) OR ( value > :") + currentKey + NS_LITERAL_CSTRING(" ) )") + directionClause + NS_LITERAL_CSTRING(" LIMIT 1"); mContinueToQuery = queryStart + NS_LITERAL_CSTRING(" AND value >= :") + currentKey + NS_LITERAL_CSTRING(" LIMIT 1"); break; case nsIIDBCursor::NEXT_NO_DUPLICATE: - if (!mUpperKey.IsUnset()) { - AppendConditionClause(value, rangeKey, true, !mUpperOpen, queryStart); - mRangeKey = mUpperKey; + if (mKeyRange && !mKeyRange->Upper().IsUnset()) { + AppendConditionClause(value, rangeKey, true, !mKeyRange->IsUpperOpen(), + queryStart); + mRangeKey = mKeyRange->Upper(); } mContinueQuery = queryStart + NS_LITERAL_CSTRING(" AND value > :") + currentKey + directionClause + NS_LITERAL_CSTRING(" LIMIT 1"); mContinueToQuery = queryStart + NS_LITERAL_CSTRING(" AND value >= :") + currentKey + directionClause + NS_LITERAL_CSTRING(" LIMIT 1"); break; case nsIIDBCursor::PREV: - if (!mLowerKey.IsUnset()) { - AppendConditionClause(value, rangeKey, false, !mLowerOpen, queryStart); - mRangeKey = mLowerKey; + if (mKeyRange && !mKeyRange->Lower().IsUnset()) { + AppendConditionClause(value, rangeKey, false, !mKeyRange->IsLowerOpen(), + queryStart); + mRangeKey = mKeyRange->Lower(); } mContinueQuery = queryStart + NS_LITERAL_CSTRING(" AND ( ( value = :") + currentKey + NS_LITERAL_CSTRING(" AND ") + keyColumn + NS_LITERAL_CSTRING(" < :") + objectKey + NS_LITERAL_CSTRING(" ) OR ( value < :") + currentKey + NS_LITERAL_CSTRING(" ) )") + directionClause + NS_LITERAL_CSTRING(" LIMIT 1"); mContinueToQuery = queryStart + NS_LITERAL_CSTRING(" AND value <= :") + currentKey + NS_LITERAL_CSTRING(" LIMIT 1"); break; case nsIIDBCursor::PREV_NO_DUPLICATE: - if (!mLowerKey.IsUnset()) { - AppendConditionClause(value, rangeKey, false, !mLowerOpen, queryStart); - mRangeKey = mLowerKey; + if (mKeyRange && !mKeyRange->Lower().IsUnset()) { + AppendConditionClause(value, rangeKey, false, !mKeyRange->IsLowerOpen(), + queryStart); + mRangeKey = mKeyRange->Lower(); } mContinueQuery = queryStart + NS_LITERAL_CSTRING(" AND value < :") + currentKey + directionClause + NS_LITERAL_CSTRING(" LIMIT 1"); mContinueToQuery = queryStart + NS_LITERAL_CSTRING(" AND value <= :") + currentKey + directionClause + NS_LITERAL_CSTRING(" LIMIT 1"); break; @@ -1337,23 +1174,25 @@ OpenCursorHelper::DoDatabaseWork(mozISto NS_NAMED_LITERAL_CSTRING(lowerKeyName, "lower_key"); NS_NAMED_LITERAL_CSTRING(upperKeyName, "upper_key"); nsCString value = indexTable + NS_LITERAL_CSTRING(".value"); nsCString data = objectTable + NS_LITERAL_CSTRING(".data"); nsCString keyValue = objectTable + NS_LITERAL_CSTRING(".") + keyValueColumn; nsCAutoString keyRangeClause; - if (!mLowerKey.IsUnset()) { - AppendConditionClause(value, lowerKeyName, false, !mLowerOpen, - keyRangeClause); - } - if (!mUpperKey.IsUnset()) { - AppendConditionClause(value, upperKeyName, true, !mUpperOpen, - keyRangeClause); + if (mKeyRange) { + if (!mKeyRange->Lower().IsUnset()) { + AppendConditionClause(value, lowerKeyName, false, + !mKeyRange->IsLowerOpen(), keyRangeClause); + } + if (!mKeyRange->Upper().IsUnset()) { + AppendConditionClause(value, upperKeyName, true, + !mKeyRange->IsUpperOpen(), keyRangeClause); + } } nsCAutoString directionClause = NS_LITERAL_CSTRING(" ORDER BY ") + value; switch (mDirection) { case nsIIDBCursor::NEXT: case nsIIDBCursor::NEXT_NO_DUPLICATE: directionClause.AppendLiteral(" ASC"); break; @@ -1386,87 +1225,41 @@ OpenCursorHelper::DoDatabaseWork(mozISto mTransaction->GetCachedStatement(firstQuery); NS_ENSURE_TRUE(stmt, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); mozStorageStatementScoper scoper(stmt); nsresult rv = stmt->BindInt64ByName(id, mIndex->Id()); NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); - if (!mLowerKey.IsUnset()) { - if (mLowerKey.IsString()) { - rv = stmt->BindStringByName(lowerKeyName, mLowerKey.StringValue()); - } - else if (mLowerKey.IsInt()) { - rv = stmt->BindInt64ByName(lowerKeyName, mLowerKey.IntValue()); - } - else { - NS_NOTREACHED("Bad key!"); + if (mKeyRange) { + if (!mKeyRange->Lower().IsUnset()) { + rv = mKeyRange->Lower().BindToStatement(stmt, lowerKeyName); + NS_ENSURE_SUCCESS(rv, rv); } - NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); - } - - if (!mUpperKey.IsUnset()) { - if (mUpperKey.IsString()) { - rv = stmt->BindStringByName(upperKeyName, mUpperKey.StringValue()); + if (!mKeyRange->Upper().IsUnset()) { + rv = mKeyRange->Upper().BindToStatement(stmt, upperKeyName); + NS_ENSURE_SUCCESS(rv, rv); } - else if (mUpperKey.IsInt()) { - rv = stmt->BindInt64ByName(upperKeyName, mUpperKey.IntValue()); - } - else { - NS_NOTREACHED("Bad key!"); - } - NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); } bool hasResult; rv = stmt->ExecuteStep(&hasResult); NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); if (!hasResult) { - mKey = Key::UNSETKEY; + mKey.Unset(); return NS_OK; } - PRInt32 keyType; - rv = stmt->GetTypeOfIndex(0, &keyType); - NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); - - NS_ASSERTION(keyType == mozIStorageStatement::VALUE_TYPE_INTEGER || - keyType == mozIStorageStatement::VALUE_TYPE_TEXT, - "Bad key type!"); + rv = mKey.SetFromStatement(stmt, 0); + NS_ENSURE_SUCCESS(rv, rv); - if (keyType == mozIStorageStatement::VALUE_TYPE_INTEGER) { - mKey = stmt->AsInt64(0); - } - else if (keyType == mozIStorageStatement::VALUE_TYPE_TEXT) { - rv = stmt->GetString(0, mKey.ToString()); - NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); - } - else { - NS_NOTREACHED("Bad SQLite type!"); - } - - rv = stmt->GetTypeOfIndex(1, &keyType); - NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); - - NS_ASSERTION(keyType == mozIStorageStatement::VALUE_TYPE_INTEGER || - keyType == mozIStorageStatement::VALUE_TYPE_TEXT, - "Bad key type!"); - - if (keyType == mozIStorageStatement::VALUE_TYPE_INTEGER) { - mObjectKey = stmt->AsInt64(1); - } - else if (keyType == mozIStorageStatement::VALUE_TYPE_TEXT) { - rv = stmt->GetString(1, mObjectKey.ToString()); - NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); - } - else { - NS_NOTREACHED("Bad SQLite type!"); - } + rv = mObjectKey.SetFromStatement(stmt, 1); + NS_ENSURE_SUCCESS(rv, rv); rv = IDBObjectStore::GetStructuredCloneDataFromStatement(stmt, 2, mCloneBuffer); NS_ENSURE_SUCCESS(rv, rv); // Now we need to make the query to get the next match. nsCAutoString queryStart = NS_LITERAL_CSTRING("SELECT ") + value + NS_LITERAL_CSTRING(", ") + keyValue + @@ -1480,70 +1273,74 @@ OpenCursorHelper::DoDatabaseWork(mozISto NS_LITERAL_CSTRING(".index_id = :id"); NS_NAMED_LITERAL_CSTRING(currentKey, "current_key"); NS_NAMED_LITERAL_CSTRING(rangeKey, "range_key"); NS_NAMED_LITERAL_CSTRING(objectKey, "object_key"); switch (mDirection) { case nsIIDBCursor::NEXT: - if (!mUpperKey.IsUnset()) { - AppendConditionClause(value, rangeKey, true, !mUpperOpen, queryStart); - mRangeKey = mUpperKey; + if (mKeyRange && !mKeyRange->Upper().IsUnset()) { + AppendConditionClause(value, rangeKey, true, !mKeyRange->IsUpperOpen(), + queryStart); + mRangeKey = mKeyRange->Upper(); } mContinueQuery = queryStart + NS_LITERAL_CSTRING(" AND ( ( ") + value + NS_LITERAL_CSTRING(" = :") + currentKey + NS_LITERAL_CSTRING(" AND ") + keyValue + NS_LITERAL_CSTRING(" > :") + objectKey + NS_LITERAL_CSTRING(" ) OR ( ") + value + NS_LITERAL_CSTRING(" > :") + currentKey + NS_LITERAL_CSTRING(" ) )") + directionClause + NS_LITERAL_CSTRING(" LIMIT 1"); mContinueToQuery = queryStart + NS_LITERAL_CSTRING(" AND ") + value + NS_LITERAL_CSTRING(" >= :") + currentKey + directionClause + NS_LITERAL_CSTRING(" LIMIT 1"); break; case nsIIDBCursor::NEXT_NO_DUPLICATE: - if (!mUpperKey.IsUnset()) { - AppendConditionClause(value, rangeKey, true, !mUpperOpen, queryStart); - mRangeKey = mUpperKey; + if (mKeyRange && !mKeyRange->Upper().IsUnset()) { + AppendConditionClause(value, rangeKey, true, !mKeyRange->IsUpperOpen(), + queryStart); + mRangeKey = mKeyRange->Upper(); } mContinueQuery = queryStart + NS_LITERAL_CSTRING(" AND ") + value + NS_LITERAL_CSTRING(" > :") + currentKey + directionClause + NS_LITERAL_CSTRING(" LIMIT 1"); mContinueToQuery = queryStart + NS_LITERAL_CSTRING(" AND ") + value + NS_LITERAL_CSTRING(" >= :") + currentKey + directionClause + NS_LITERAL_CSTRING(" LIMIT 1"); break; case nsIIDBCursor::PREV: - if (!mLowerKey.IsUnset()) { - AppendConditionClause(value, rangeKey, false, !mLowerOpen, queryStart); - mRangeKey = mLowerKey; + if (mKeyRange && !mKeyRange->Lower().IsUnset()) { + AppendConditionClause(value, rangeKey, false, !mKeyRange->IsLowerOpen(), + queryStart); + mRangeKey = mKeyRange->Lower(); } mContinueQuery = queryStart + NS_LITERAL_CSTRING(" AND ( ( ") + value + NS_LITERAL_CSTRING(" = :") + currentKey + NS_LITERAL_CSTRING(" AND ") + keyValue + NS_LITERAL_CSTRING(" < :") + objectKey + NS_LITERAL_CSTRING(" ) OR ( ") + value + NS_LITERAL_CSTRING(" < :") + currentKey + NS_LITERAL_CSTRING(" ) )") + directionClause + NS_LITERAL_CSTRING(" LIMIT 1"); mContinueToQuery = queryStart + NS_LITERAL_CSTRING(" AND ") + value + NS_LITERAL_CSTRING(" <= :") + currentKey + directionClause + NS_LITERAL_CSTRING(" LIMIT 1"); break; case nsIIDBCursor::PREV_NO_DUPLICATE: - if (!mLowerKey.IsUnset()) { - AppendConditionClause(value, rangeKey, false, !mLowerOpen, queryStart); - mRangeKey = mLowerKey; + if (mKeyRange && !mKeyRange->Lower().IsUnset()) { + AppendConditionClause(value, rangeKey, false, !mKeyRange->IsLowerOpen(), + queryStart); + mRangeKey = mKeyRange->Lower(); } mContinueQuery = queryStart + NS_LITERAL_CSTRING(" AND ") + value + NS_LITERAL_CSTRING(" < :") + currentKey + directionClause + NS_LITERAL_CSTRING(" LIMIT 1"); mContinueToQuery = queryStart + NS_LITERAL_CSTRING(" AND ") + value + NS_LITERAL_CSTRING(" <= :") + currentKey + directionClause + NS_LITERAL_CSTRING(" LIMIT 1"); break;
--- a/dom/indexedDB/IDBKeyRange.cpp +++ b/dom/indexedDB/IDBKeyRange.cpp @@ -37,230 +37,206 @@ * * ***** END LICENSE BLOCK ***** */ #include "IDBKeyRange.h" #include "nsIXPConnect.h" #include "jscntxt.h" -#include "nsDOMClassInfoID.h" +#include "nsDOMClassInfo.h" #include "nsJSUtils.h" #include "nsThreadUtils.h" #include "nsContentUtils.h" #include "Key.h" USING_INDEXEDDB_NAMESPACE namespace { inline -JSBool -ConvertArguments(JSContext* aCx, - uintN aArgc, - jsval* aVp, - const char* aMethodName, - nsTArray<nsCOMPtr<nsIVariant> >& aKeys) -{ - NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); - NS_ASSERTION(aCx, "Null pointer!"); - NS_ASSERTION(aVp, "Null pointer!"); - NS_ASSERTION(aMethodName, "Null pointer!"); - NS_ASSERTION(aKeys.Capacity(), "Need guaranteed capacity!"); - NS_ASSERTION(aKeys.IsEmpty(), "Not an empty array!"); - - if (aArgc < aKeys.Capacity()) { - nsCString num; - num.AppendInt(aKeys.Length()); - JS_ReportErrorNumberUC(aCx, js_GetErrorMessage, nsnull, - JSMSG_MORE_ARGS_NEEDED, aMethodName, num.get(), - aKeys.Capacity() == 1 ? "" : "s"); - return JS_FALSE; - } - - for (uintN i = 0; i < aKeys.Capacity(); i++) { - jsval& arg = JS_ARGV(aCx, aVp)[i]; - if (JSVAL_IS_VOID(arg) || JSVAL_IS_NULL(arg) || - !Key::CanBeConstructedFromJSVal(arg)) { - JS_ReportError(aCx, "Argument is not a supported key type."); - return JS_FALSE; - } - - nsIXPConnect* xpc = nsContentUtils::XPConnect(); - NS_ASSERTION(xpc, "This should never be null!"); - - nsCOMPtr<nsIVariant>* key = aKeys.AppendElement(); - NS_ASSERTION(key, "This should never fail!"); - - if (NS_FAILED(xpc->JSValToVariant(aCx, &arg, getter_AddRefs(*key)))) { - JS_ReportError(aCx, "Could not convert argument to variant."); - return JS_FALSE; - } - } - - return JS_TRUE; -} - -inline -JSBool +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_GetGlobalForScopeChain(aCx); - NS_ENSURE_TRUE(global, JS_FALSE); + 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 JS_FALSE; + return false; } JSObject* result; if (NS_FAILED(holder->GetJSObject(&result))) { JS_ReportError(aCx, "Couldn't get JSObject from wrapper."); - return JS_FALSE; + return false; } JS_SET_RVAL(aCx, aVp, OBJECT_TO_JSVAL(result)); - return JS_TRUE; + return true; +} + +inline +nsresult +GetKeyFromJSVal(JSContext* aCx, + 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; + } + + if (aKey.IsUnset() && !aAllowUnset) { + return NS_ERROR_DOM_INDEXEDDB_DATA_ERR; + } + + return NS_OK; +} + +inline +void +ThrowException(JSContext* aCx, + nsresult aErrorCode) +{ + NS_ASSERTION(NS_FAILED(aErrorCode), "Not an error code!"); + if (!JS_IsExceptionPending(aCx)) { + nsDOMClassInfo::ThrowJSException(aCx, aErrorCode); + } +} + +inline +bool +GetKeyFromJSValOrThrow(JSContext* aCx, + jsval aVal, + Key& aKey) +{ + nsresult rv = GetKeyFromJSVal(aCx, aVal, aKey); + if (NS_FAILED(rv)) { + ThrowException(aCx, rv); + return false; + } + return true; } JSBool MakeOnlyKeyRange(JSContext* aCx, uintN aArgc, jsval* aVp) { NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); - nsAutoTArray<nsCOMPtr<nsIVariant>, 1> keys; - if (!ConvertArguments(aCx, aArgc, aVp, "IDBKeyRange.only", keys)) { - return JS_FALSE; - } - NS_ASSERTION(keys.Length() == 1, "Didn't set all keys!"); - - nsRefPtr<IDBKeyRange> range = - IDBKeyRange::Create(keys[0], keys[0], false, false); - NS_ASSERTION(range, "Out of memory?"); - - if (!ReturnKeyRange(aCx, aVp, range)) { - return JS_FALSE; + jsval val; + if (!JS_ConvertArguments(aCx, aArgc, JS_ARGV(aCx, aVp), "v", &val)) { + return false; } - return JS_TRUE; + nsRefPtr<IDBKeyRange> keyRange = new IDBKeyRange(false, false, true); + + if (!GetKeyFromJSValOrThrow(aCx, val, keyRange->Lower())) { + return false; + } + + return ReturnKeyRange(aCx, aVp, keyRange); } JSBool MakeLowerBoundKeyRange(JSContext* aCx, uintN aArgc, jsval* aVp) { NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); - nsAutoTArray<nsCOMPtr<nsIVariant>, 1> keys; - if (!ConvertArguments(aCx, aArgc, aVp, "IDBKeyRange.lowerBound", keys)) { - return JS_FALSE; - } - NS_ASSERTION(keys.Length() == 1, "Didn't set all keys!"); - - JSBool open = JS_FALSE; - if (aArgc > 1 && !JS_ValueToBoolean(aCx, JS_ARGV(aCx, aVp)[1], &open)) { - JS_ReportError(aCx, "Couldn't convert argument 2 to boolean."); - return JS_FALSE; + jsval val; + JSBool open = false; + if (!JS_ConvertArguments(aCx, aArgc, JS_ARGV(aCx, aVp), "v/b", &val, &open)) { + return false; } - nsRefPtr<IDBKeyRange> range = - IDBKeyRange::Create(keys[0], nsnull, !!open, true); - NS_ASSERTION(range, "Out of memory?"); + nsRefPtr<IDBKeyRange> keyRange = new IDBKeyRange(open, true, false); - if (!ReturnKeyRange(aCx, aVp, range)) { - return JS_FALSE; + if (!GetKeyFromJSValOrThrow(aCx, val, keyRange->Lower())) { + return false; } - return JS_TRUE; + return ReturnKeyRange(aCx, aVp, keyRange); } JSBool MakeUpperBoundKeyRange(JSContext* aCx, uintN aArgc, jsval* aVp) { NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); - nsAutoTArray<nsCOMPtr<nsIVariant>, 1> keys; - if (!ConvertArguments(aCx, aArgc, aVp, "IDBKeyRange.upperBound", keys)) { - return JS_FALSE; - } - NS_ASSERTION(keys.Length() == 1, "Didn't set all keys!"); - - JSBool open = JS_FALSE; - if (aArgc > 1 && !JS_ValueToBoolean(aCx, JS_ARGV(aCx, aVp)[1], &open)) { - JS_ReportError(aCx, "Couldn't convert argument 2 to boolean."); - return JS_FALSE; + jsval val; + JSBool open = false; + if (!JS_ConvertArguments(aCx, aArgc, JS_ARGV(aCx, aVp), "v/b", &val, &open)) { + return false; } - nsRefPtr<IDBKeyRange> range = - IDBKeyRange::Create(nsnull, keys[0], true, !!open); - NS_ASSERTION(range, "Out of memory?"); + nsRefPtr<IDBKeyRange> keyRange = new IDBKeyRange(true, open, false); - if (!ReturnKeyRange(aCx, aVp, range)) { - return JS_FALSE; + if (!GetKeyFromJSValOrThrow(aCx, val, keyRange->Upper())) { + return false; } - return JS_TRUE; + return ReturnKeyRange(aCx, aVp, keyRange); } JSBool MakeBoundKeyRange(JSContext* aCx, uintN aArgc, jsval* aVp) { NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); - nsAutoTArray<nsCOMPtr<nsIVariant>, 2> keys; - if (!ConvertArguments(aCx, aArgc, aVp, "IDBKeyRange.bound", keys)) { - return JS_FALSE; - } - NS_ASSERTION(keys.Length() == 2, "Didn't set all keys!"); - - JSBool lowerOpen = JS_FALSE; - if (aArgc > 2 && !JS_ValueToBoolean(aCx, JS_ARGV(aCx, aVp)[2], &lowerOpen)) { - JS_ReportError(aCx, "Couldn't convert argument 3 to boolean."); - return JS_FALSE; + jsval lowerVal, upperVal; + JSBool lowerOpen = false, upperOpen = false; + if (!JS_ConvertArguments(aCx, aArgc, JS_ARGV(aCx, aVp), "vv/bb", &lowerVal, + &upperVal, &lowerOpen, &upperOpen)) { + return false; } - JSBool upperOpen = JS_FALSE; - if (aArgc > 3 && !JS_ValueToBoolean(aCx, JS_ARGV(aCx, aVp)[3], &upperOpen)) { - JS_ReportError(aCx, "Couldn't convert argument 3 to boolean."); - return JS_FALSE; + nsRefPtr<IDBKeyRange> keyRange = new IDBKeyRange(lowerOpen, upperOpen, false); + + if (!GetKeyFromJSValOrThrow(aCx, lowerVal, keyRange->Lower()) || + !GetKeyFromJSValOrThrow(aCx, upperVal, keyRange->Upper())) { + return false; } - nsRefPtr<IDBKeyRange> range = - IDBKeyRange::Create(keys[0], keys[1], lowerOpen, upperOpen); - NS_ASSERTION(range, "Out of memory?"); - - if (!ReturnKeyRange(aCx, aVp, range)) { - return JS_FALSE; + if (keyRange->Lower() > keyRange->Upper() || + (keyRange->Lower() == keyRange->Upper() && (lowerOpen || upperOpen))) { + ThrowException(aCx, NS_ERROR_DOM_INDEXEDDB_DATA_ERR); + return false; } - return JS_TRUE; + 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 @@ -280,72 +256,152 @@ IDBKeyRange::DefineConstructors(JSContex NS_ASSERTION(aObject, "Null pointer!"); // Add the constructor methods for key ranges. return JS_DefineFunctions(aCx, aObject, const_cast<JSFunctionSpec*>(gKeyRangeConstructors)); } // static -already_AddRefed<IDBKeyRange> -IDBKeyRange::Create(nsIVariant* aLower, - nsIVariant* aUpper, - bool aLowerOpen, - bool aUpperOpen) +nsresult +IDBKeyRange::FromJSVal(JSContext* aCx, + const jsval& aVal, + IDBKeyRange** aKeyRange) { - nsRefPtr<IDBKeyRange> keyRange(new IDBKeyRange()); - keyRange->mLower = aLower; - keyRange->mUpper = aUpper; - keyRange->mLowerOpen = aLowerOpen; - keyRange->mUpperOpen = aUpperOpen; + nsresult rv; + nsRefPtr<IDBKeyRange> keyRange; + + if (JSVAL_IS_VOID(aVal) || JSVAL_IS_NULL(aVal)) { + // undefined and null returns no IDBKeyRange. + } + else if (JSVAL_IS_PRIMITIVE(aVal)) { + // A valid key returns an 'only' IDBKeyRange. + keyRange = new IDBKeyRange(false, false, true); - return keyRange.forget(); + rv = GetKeyFromJSVal(aCx, aVal, keyRange->Lower()); + if (NS_FAILED(rv)) { + return rv; + } + } + else { + // An object is not permitted unless it's another IDBKeyRange. + 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)); + NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_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; } -NS_IMPL_ADDREF(IDBKeyRange) -NS_IMPL_RELEASE(IDBKeyRange) +NS_IMPL_CYCLE_COLLECTION_CLASS(IDBKeyRange) + +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(IDBKeyRange) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END -NS_INTERFACE_MAP_BEGIN(IDBKeyRange) - NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIIDBKeyRange) +NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(IDBKeyRange) + if (JSVAL_IS_GCTHING(tmp->mCachedLowerVal)) { + void *gcThing = JSVAL_TO_GCTHING(tmp->mCachedLowerVal); + NS_IMPL_CYCLE_COLLECTION_TRACE_JS_CALLBACK(gcThing, "mCachedLowerVal") + } + if (JSVAL_IS_GCTHING(tmp->mCachedUpperVal)) { + void *gcThing = JSVAL_TO_GCTHING(tmp->mCachedUpperVal); + NS_IMPL_CYCLE_COLLECTION_TRACE_JS_CALLBACK(gcThing, "mCachedUpperVal") + } +NS_IMPL_CYCLE_COLLECTION_TRACE_END + +NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(IDBKeyRange) + if (tmp->mRooted) { + NS_DROP_JS_OBJECTS(tmp, IDBKeyRange); + tmp->mCachedLowerVal = JSVAL_VOID; + tmp->mCachedUpperVal = JSVAL_VOID; + tmp->mHaveCachedLowerVal = false; + tmp->mHaveCachedUpperVal = false; + tmp->mRooted = false; + } +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) NS_IMETHODIMP -IDBKeyRange::GetLower(nsIVariant** aLower) +IDBKeyRange::GetLower(JSContext* aCx, + jsval* aLower) { NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); - nsCOMPtr<nsIVariant> result(mLower); - result.forget(aLower); + if (!mHaveCachedLowerVal) { + if (!mRooted) { + NS_HOLD_JS_OBJECTS(this, IDBKeyRange); + mRooted = true; + } + + nsresult rv = Lower().ToJSVal(aCx, &mCachedLowerVal); + NS_ENSURE_SUCCESS(rv, rv); + + mHaveCachedLowerVal = true; + } + + *aLower = mCachedLowerVal; return NS_OK; } NS_IMETHODIMP -IDBKeyRange::GetUpper(nsIVariant** aUpper) +IDBKeyRange::GetUpper(JSContext* aCx, + jsval* aUpper) { NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); - nsCOMPtr<nsIVariant> result(mUpper); - result.forget(aUpper); + if (!mHaveCachedUpperVal) { + if (!mRooted) { + NS_HOLD_JS_OBJECTS(this, IDBKeyRange); + mRooted = true; + } + + nsresult rv = Upper().ToJSVal(aCx, &mCachedUpperVal); + NS_ENSURE_SUCCESS(rv, rv); + + mHaveCachedUpperVal = true; + } + + *aUpper = mCachedUpperVal; return NS_OK; } NS_IMETHODIMP IDBKeyRange::GetLowerOpen(bool* aLowerOpen) { NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); - *aLowerOpen = mLowerOpen ? true : false; + *aLowerOpen = mLowerOpen; return NS_OK; } NS_IMETHODIMP IDBKeyRange::GetUpperOpen(bool* aUpperOpen) { NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); - *aUpperOpen = mUpperOpen ? true : false; + *aUpperOpen = mUpperOpen; return NS_OK; }
--- a/dom/indexedDB/IDBKeyRange.h +++ b/dom/indexedDB/IDBKeyRange.h @@ -36,45 +36,85 @@ * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ #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 "nsIIDBKeyRange.h" -#include "nsIVariant.h" + +#include "nsCycleCollectionParticipant.h" BEGIN_INDEXEDDB_NAMESPACE class IDBKeyRange : public nsIIDBKeyRange { public: - NS_DECL_ISUPPORTS + NS_DECL_CYCLE_COLLECTING_ISUPPORTS NS_DECL_NSIIDBKEYRANGE + NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(IDBKeyRange) static JSBool DefineConstructors(JSContext* aCx, JSObject* aObject); static - already_AddRefed<IDBKeyRange> Create(nsIVariant* aLower, - nsIVariant* aUpper, - bool aLowerOpen, - bool aUpperOpen); + nsresult FromJSVal(JSContext* aCx, + const jsval& aVal, + IDBKeyRange** aKeyRange); + + IDBKeyRange(bool aLowerOpen, bool aUpperOpen, bool aIsOnly) + : mCachedLowerVal(JSVAL_VOID), mCachedUpperVal(JSVAL_VOID), + mLowerOpen(aLowerOpen), mUpperOpen(aUpperOpen), mIsOnly(aIsOnly), + mHaveCachedLowerVal(false), mHaveCachedUpperVal(false), mRooted(false) + { } + + const Key& Lower() const + { + return mLower; + } + + Key& Lower() + { + return mLower; + } + + const Key& Upper() const + { + return mIsOnly ? mLower : mUpper; + } + + Key& Upper() + { + return mIsOnly ? mLower : mUpper; + } + + bool IsLowerOpen() const + { + return mLowerOpen; + } + + bool IsUpperOpen() const + { + return mUpperOpen; + } protected: - IDBKeyRange() - : mLowerOpen(false), mUpperOpen(false) - { } - ~IDBKeyRange() { } - nsCOMPtr<nsIVariant> mLower; - nsCOMPtr<nsIVariant> mUpper; + Key mLower; + Key mUpper; + jsval mCachedLowerVal; + jsval mCachedUpperVal; bool mLowerOpen; bool mUpperOpen; + bool mIsOnly; + bool mHaveCachedLowerVal; + bool mHaveCachedUpperVal; + bool mRooted; }; END_INDEXEDDB_NAMESPACE #endif // mozilla_dom_indexeddb_idbkeyrange_h__
--- a/dom/indexedDB/IDBObjectStore.cpp +++ b/dom/indexedDB/IDBObjectStore.cpp @@ -35,19 +35,17 @@ * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ #include "IDBObjectStore.h" #include "nsIJSContextStack.h" -#include "nsIVariant.h" - -#include "jscntxt.h" + #include "jsclone.h" #include "mozilla/storage.h" #include "nsContentUtils.h" #include "nsDOMClassInfo.h" #include "nsEventDispatcher.h" #include "nsJSUtils.h" #include "nsServiceManagerUtils.h" #include "nsThreadUtils.h" @@ -59,19 +57,16 @@ #include "IDBKeyRange.h" #include "IDBTransaction.h" #include "DatabaseInfo.h" USING_INDEXEDDB_NAMESPACE namespace { -// This is just to give us some random marker in the byte stream -static const PRUint64 kTotallyRandomNumber = LL_INIT(0x286F258B, 0x177D47A9); - class AddHelper : public AsyncConnectionHelper { public: AddHelper(IDBTransaction* aTransaction, IDBRequest* aRequest, IDBObjectStore* aObjectStore, JSAutoStructuredCloneBuffer& aCloneBuffer, const Key& aKey, @@ -141,17 +136,17 @@ public: mObjectStore = nsnull; IDBObjectStore::ClearStructuredCloneBuffer(mCloneBuffer); AsyncConnectionHelper::ReleaseMainThreadObjects(); } protected: // In-params. nsRefPtr<IDBObjectStore> mObjectStore; - const Key mKey; + Key mKey; private: // Out-params. JSAutoStructuredCloneBuffer mCloneBuffer; }; class DeleteHelper : public GetHelper { @@ -191,49 +186,43 @@ protected: }; class OpenCursorHelper : public AsyncConnectionHelper { public: OpenCursorHelper(IDBTransaction* aTransaction, IDBRequest* aRequest, IDBObjectStore* aObjectStore, - const Key& aLowerKey, - const Key& aUpperKey, - bool aLowerOpen, - bool aUpperOpen, + IDBKeyRange* aKeyRange, PRUint16 aDirection) : AsyncConnectionHelper(aTransaction, aRequest), mObjectStore(aObjectStore), - mLowerKey(aLowerKey), mUpperKey(aUpperKey), mLowerOpen(aLowerOpen), - mUpperOpen(aUpperOpen), mDirection(aDirection) + mKeyRange(aKeyRange), mDirection(aDirection) { } ~OpenCursorHelper() { IDBObjectStore::ClearStructuredCloneBuffer(mCloneBuffer); } nsresult DoDatabaseWork(mozIStorageConnection* aConnection); nsresult GetSuccessResult(JSContext* aCx, jsval* aVal); void ReleaseMainThreadObjects() { mObjectStore = nsnull; + mKeyRange = nsnull; IDBObjectStore::ClearStructuredCloneBuffer(mCloneBuffer); AsyncConnectionHelper::ReleaseMainThreadObjects(); } private: // In-params. nsRefPtr<IDBObjectStore> mObjectStore; - const Key mLowerKey; - const Key mUpperKey; - const bool mLowerOpen; - const bool mUpperOpen; + nsRefPtr<IDBKeyRange> mKeyRange; const PRUint16 mDirection; // Out-params. Key mKey; JSAutoStructuredCloneBuffer mCloneBuffer; nsCString mContinueQuery; nsCString mContinueToQuery; Key mRangeKey; @@ -268,18 +257,17 @@ private: static void DestroyTLSEntry(void* aPtr); static PRUintn sTLSIndex; // In-params. nsRefPtr<IDBIndex> mIndex; }; -static const PRUintn BAD_TLS_INDEX = (PRUint32)-1; -PRUintn CreateIndexHelper::sTLSIndex = BAD_TLS_INDEX; +PRUintn CreateIndexHelper::sTLSIndex = PRUintn(BAD_TLS_INDEX); class DeleteIndexHelper : public AsyncConnectionHelper { public: DeleteIndexHelper(IDBTransaction* aTransaction, const nsAString& aName, IDBObjectStore* aObjectStore) : AsyncConnectionHelper(aTransaction, nsnull), mName(aName), @@ -311,53 +299,47 @@ private: }; class GetAllHelper : public AsyncConnectionHelper { public: GetAllHelper(IDBTransaction* aTransaction, IDBRequest* aRequest, IDBObjectStore* aObjectStore, - const Key& aLowerKey, - const Key& aUpperKey, - const bool aLowerOpen, - const bool aUpperOpen, + IDBKeyRange* aKeyRange, const PRUint32 aLimit) : AsyncConnectionHelper(aTransaction, aRequest), mObjectStore(aObjectStore), - mLowerKey(aLowerKey), mUpperKey(aUpperKey), mLowerOpen(aLowerOpen), - mUpperOpen(aUpperOpen), mLimit(aLimit) + mKeyRange(aKeyRange), mLimit(aLimit) { } ~GetAllHelper() { for (PRUint32 index = 0; index < mCloneBuffers.Length(); index++) { IDBObjectStore::ClearStructuredCloneBuffer(mCloneBuffers[index]); } } nsresult DoDatabaseWork(mozIStorageConnection* aConnection); nsresult GetSuccessResult(JSContext* aCx, jsval* aVal); void ReleaseMainThreadObjects() { mObjectStore = nsnull; + mKeyRange = nsnull; for (PRUint32 index = 0; index < mCloneBuffers.Length(); index++) { IDBObjectStore::ClearStructuredCloneBuffer(mCloneBuffers[index]); } AsyncConnectionHelper::ReleaseMainThreadObjects(); } protected: // In-params. nsRefPtr<IDBObjectStore> mObjectStore; - const Key mLowerKey; - const Key mUpperKey; - const bool mLowerOpen; - const bool mUpperOpen; + nsRefPtr<IDBKeyRange> mKeyRange; const PRUint32 mLimit; private: // Out-params. nsTArray<JSAutoStructuredCloneBuffer> mCloneBuffers; }; NS_STACK_CLASS @@ -409,17 +391,17 @@ GetKeyFromObject(JSContext* aCx, const jschar* keyPathChars = reinterpret_cast<const jschar*>(aKeyPath.get()); const size_t keyPathLen = aKeyPath.Length(); jsval key; JSBool ok = JS_GetUCProperty(aCx, aObj, keyPathChars, keyPathLen, &key); NS_ENSURE_TRUE(ok, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); - nsresult rv = IDBObjectStore::GetKeyFromJSVal(key, aCx, aKey); + nsresult rv = aKey.SetFromJSVal(aCx, key); NS_ENSURE_SUCCESS(rv, rv); return NS_OK; } inline already_AddRefed<IDBRequest> GenerateRequest(IDBObjectStore* aObjectStore) @@ -486,117 +468,16 @@ IDBObjectStore::Create(IDBTransaction* a objectStore->mAutoIncrement = aStoreInfo->autoIncrement; objectStore->mDatabaseId = aStoreInfo->databaseId; return objectStore.forget(); } // static nsresult -IDBObjectStore::GetKeyFromVariant(nsIVariant* aKeyVariant, - Key& aKey) -{ - if (!aKeyVariant) { - aKey = Key::UNSETKEY; - return NS_OK; - } - - PRUint16 type; - nsresult rv = aKeyVariant->GetDataType(&type); - NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); - - // See xpcvariant.cpp, these are the only types we should expect. - switch (type) { - case nsIDataType::VTYPE_VOID: - aKey = Key::UNSETKEY; - return NS_OK; - - case nsIDataType::VTYPE_WSTRING_SIZE_IS: - rv = aKeyVariant->GetAsAString(aKey.ToString()); - NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); - return NS_OK; - - case nsIDataType::VTYPE_INT32: - case nsIDataType::VTYPE_DOUBLE: - rv = aKeyVariant->GetAsInt64(aKey.ToIntPtr()); - NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); - return NS_OK; - - default: - return NS_ERROR_DOM_INDEXEDDB_DATA_ERR; - } - - NS_NOTREACHED("Can't get here!"); - return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; -} - -// static -nsresult -IDBObjectStore::GetKeyFromJSVal(jsval aKeyVal, - JSContext* aCx, - Key& aKey) -{ - if (JSVAL_IS_VOID(aKeyVal)) { - aKey = Key::UNSETKEY; - } - else if (JSVAL_IS_STRING(aKeyVal)) { - nsDependentJSString depStr; - if (!depStr.init(aCx, JSVAL_TO_STRING(aKeyVal))) { - return NS_ERROR_OUT_OF_MEMORY; - } - aKey = depStr; - } - else if (JSVAL_IS_INT(aKeyVal)) { - aKey = JSVAL_TO_INT(aKeyVal); - } - else if (JSVAL_IS_DOUBLE(aKeyVal)) { - aKey = JSVAL_TO_DOUBLE(aKeyVal); - } - else { - return NS_ERROR_DOM_INDEXEDDB_DATA_ERR; - } - - return NS_OK; -} - -// static -nsresult -IDBObjectStore::GetJSValFromKey(const Key& aKey, - JSContext* aCx, - jsval* aKeyVal) -{ - if (aKey.IsUnset()) { - *aKeyVal = JSVAL_VOID; - return NS_OK; - } - - if (aKey.IsInt()) { - JSBool ok = JS_NewNumberValue(aCx, aKey.IntValue(), aKeyVal); - NS_ENSURE_TRUE(ok, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); - return NS_OK; - } - - if (aKey.IsString()) { - const nsString& keyString = aKey.StringValue(); - JSString* str = - JS_NewUCStringCopyN(aCx, - reinterpret_cast<const jschar*>(keyString.get()), - keyString.Length()); - NS_ENSURE_TRUE(str, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); - - *aKeyVal = STRING_TO_JSVAL(str); - return NS_OK; - } - - NS_NOTREACHED("Unknown key type!"); - return NS_ERROR_DOM_INDEXEDDB_DATA_ERR; -} - -// static -nsresult IDBObjectStore::GetKeyPathValueFromStructuredData(const PRUint8* aData, PRUint32 aDataLength, const nsAString& aKeyPath, JSContext* aCx, Key& aValue) { NS_ASSERTION(aData, "Null pointer!"); NS_ASSERTION(aDataLength, "Empty data!"); @@ -609,35 +490,35 @@ IDBObjectStore::GetKeyPathValueFromStruc if (!JS_ReadStructuredClone(aCx, reinterpret_cast<const uint64*>(aData), aDataLength, JS_STRUCTURED_CLONE_VERSION, &clone, NULL, NULL)) { return NS_ERROR_DOM_DATA_CLONE_ERR; } if (JSVAL_IS_PRIMITIVE(clone)) { // This isn't an object, so just leave the key unset. - aValue = Key::UNSETKEY; + aValue.Unset(); return NS_OK; } JSObject* obj = JSVAL_TO_OBJECT(clone); const jschar* keyPathChars = reinterpret_cast<const jschar*>(aKeyPath.BeginReading()); const size_t keyPathLen = aKeyPath.Length(); jsval keyVal; JSBool ok = JS_GetUCProperty(aCx, obj, keyPathChars, keyPathLen, &keyVal); NS_ENSURE_TRUE(ok, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); - nsresult rv = GetKeyFromJSVal(keyVal, aCx, aValue); + nsresult rv = aValue.SetFromJSVal(aCx, keyVal); if (NS_FAILED(rv)) { // If the object doesn't have a value that we can use for our index then we // leave it unset. - aValue = Key::UNSETKEY; + aValue.Unset(); } return NS_OK; } /* static */ nsresult IDBObjectStore::GetIndexUpdateInfo(ObjectStoreInfo* aObjectStoreInfo, @@ -664,17 +545,17 @@ IDBObjectStore::GetIndexUpdateInfo(Objec const size_t keyPathLen = indexInfo.keyPath.Length(); jsval keyPathValue; JSBool ok = JS_GetUCProperty(aCx, cloneObj, keyPathChars, keyPathLen, &keyPathValue); NS_ENSURE_TRUE(ok, NS_ERROR_FAILURE); Key value; - nsresult rv = GetKeyFromJSVal(keyPathValue, aCx, value); + nsresult rv = value.SetFromJSVal(aCx, keyPathValue); if (NS_FAILED(rv) || value.IsUnset()) { // Not a value we can do anything with, ignore it. continue; } IndexUpdateInfo* updateInfo = aUpdateInfoArray.AppendElement(); updateInfo->info = indexInfo; updateInfo->value = value; @@ -723,27 +604,17 @@ IDBObjectStore::UpdateIndexes(IDBTransac mozStorageStatementScoper scoper(stmt); rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("osid"), aObjectStoreId); NS_ENSURE_SUCCESS(rv, rv); NS_ASSERTION(!aObjectStoreKey.IsUnset(), "This shouldn't happen!"); - NS_NAMED_LITERAL_CSTRING(keyValue, "key_value"); - - if (aObjectStoreKey.IsInt()) { - rv = stmt->BindInt64ByName(keyValue, aObjectStoreKey.IntValue()); - } - else if (aObjectStoreKey.IsString()) { - rv = stmt->BindStringByName(keyValue, aObjectStoreKey.StringValue()); - } - else { - NS_NOTREACHED("Unknown key type!"); - } + rv = aObjectStoreKey.BindToStatement(stmt, NS_LITERAL_CSTRING("key_value")); NS_ENSURE_SUCCESS(rv, rv); bool hasResult; rv = stmt->ExecuteStep(&hasResult); NS_ENSURE_SUCCESS(rv, rv); if (!hasResult) { NS_ERROR("This is bad, we just added this value! Where'd it go?!"); @@ -769,45 +640,25 @@ IDBObjectStore::UpdateIndexes(IDBTransac updateInfo.info.id); NS_ENSURE_SUCCESS(rv, rv); rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("object_data_id"), aObjectDataId); NS_ENSURE_SUCCESS(rv, rv); if (!updateInfo.info.autoIncrement) { - NS_NAMED_LITERAL_CSTRING(objectDataKey, "object_data_key"); - - if (aObjectStoreKey.IsInt()) { - rv = stmt->BindInt64ByName(objectDataKey, aObjectStoreKey.IntValue()); - } - else if (aObjectStoreKey.IsString()) { - rv = stmt->BindStringByName(objectDataKey, - aObjectStoreKey.StringValue()); - } - else { - NS_NOTREACHED("Unknown key type!"); - } + rv = + aObjectStoreKey.BindToStatement(stmt, + NS_LITERAL_CSTRING("object_data_key")); NS_ENSURE_SUCCESS(rv, rv); } - NS_NAMED_LITERAL_CSTRING(value, "value"); - - if (updateInfo.value.IsInt()) { - rv = stmt->BindInt64ByName(value, updateInfo.value.IntValue()); - } - else if (updateInfo.value.IsString()) { - rv = stmt->BindStringByName(value, updateInfo.value.StringValue()); - } - else if (updateInfo.value.IsUnset()) { - rv = stmt->BindStringByName(value, updateInfo.value.StringValue()); - } - else { - NS_NOTREACHED("Unknown key type!"); - } + rv = + updateInfo.value.BindToStatementAllowUnset(stmt, + NS_LITERAL_CSTRING("value")); NS_ENSURE_SUCCESS(rv, rv); rv = stmt->Execute(); if (NS_FAILED(rv)) { return rv; } } @@ -896,36 +747,35 @@ SwapBytes(PRUint64 u) ((u & 0x000000000000ff00LLU) << 40) | ((u & 0x0000000000ff0000LLU) << 24) | ((u & 0x00000000ff000000LLU) << 8) | ((u & 0x000000ff00000000LLU) >> 8) | ((u & 0x0000ff0000000000LLU) >> 24) | ((u & 0x00ff000000000000LLU) >> 40) | ((u & 0xff00000000000000LLU) >> 56); #else - return u; + return jsdouble(u); #endif } nsresult IDBObjectStore::ModifyValueForNewKey(JSAutoStructuredCloneBuffer& aBuffer, Key& aKey, PRUint64 aOffsetToKeyProp) { - NS_ASSERTION(IsAutoIncrement() && KeyPath().IsEmpty() && aKey.IsInt(), - "Don't call me!"); + NS_ASSERTION(IsAutoIncrement() && aKey.IsInteger(), "Don't call me!"); NS_ASSERTION(!NS_IsMainThread(), "Wrong thread"); // This is a duplicate of the js engine's byte munging here union { jsdouble d; PRUint64 u; } pun; - pun.d = SwapBytes(aKey.IntValue()); + pun.d = SwapBytes(aKey.ToInteger()); memcpy((char*)aBuffer.data() + aOffsetToKeyProp, &pun.u, sizeof(PRUint64)); return NS_OK; } IDBObjectStore::IDBObjectStore() : mId(LL_MININT), mAutoIncrement(false) @@ -954,17 +804,17 @@ IDBObjectStore::GetAddInfo(JSContext* aC if (!JSVAL_IS_VOID(aKeyVal) && !mKeyPath.IsEmpty()) { return NS_ERROR_DOM_INDEXEDDB_DATA_ERR; } JSAutoRequest ar(aCx); if (mKeyPath.IsEmpty()) { // Out-of-line keys must be passed in. - rv = GetKeyFromJSVal(aKeyVal, aCx, aKey); + rv = aKey.SetFromJSVal(aCx, aKeyVal); NS_ENSURE_SUCCESS(rv, rv); } else { // Inline keys live on the object. Make sure that the value passed in is an // object. if (JSVAL_IS_PRIMITIVE(aValue)) { return NS_ERROR_DOM_INDEXEDDB_DATA_ERR; } @@ -1168,52 +1018,31 @@ IDBObjectStore::GetIndexNames(nsIDOMDOMS NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); } list.forget(aIndexNames); return NS_OK; } NS_IMETHODIMP -IDBObjectStore::Get(nsIVariant* aKey, +IDBObjectStore::Get(const jsval& aKey, + JSContext* aCx, nsIIDBRequest** _retval) { NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); if (!mTransaction->IsOpen()) { return NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR; } Key key; - nsresult rv = GetKeyFromVariant(aKey, key); + nsresult rv = key.SetFromJSVal(aCx, aKey); if (NS_FAILED(rv)) { - // Check to see if this is a key range. - PRUint16 type; - rv = aKey->GetDataType(&type); - NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); - - if (type != nsIDataType::VTYPE_INTERFACE && - type != nsIDataType::VTYPE_INTERFACE_IS) { - return NS_ERROR_DOM_INDEXEDDB_DATA_ERR; - } - - // XXX I hate this API. Move to jsvals, stat. - nsID* iid; - nsCOMPtr<nsISupports> supports; - rv = aKey->GetAsInterface(&iid, getter_AddRefs(supports)); - NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); - - NS_Free(iid); - - nsCOMPtr<nsIIDBKeyRange> keyRange = do_QueryInterface(supports); - if (!keyRange) { - return NS_ERROR_DOM_INDEXEDDB_DATA_ERR; - } - - return GetAll(keyRange, 0, 0, _retval); + // Maybe this is a key range. + return GetAll(aKey, 0, aCx, 1, _retval); } if (key.IsUnset()) { return NS_ERROR_DOM_INDEXEDDB_DATA_ERR; } nsRefPtr<IDBRequest> request = GenerateRequest(this); NS_ENSURE_TRUE(request, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); @@ -1223,66 +1052,45 @@ IDBObjectStore::Get(nsIVariant* aKey, rv = helper->DispatchToTransactionPool(); NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); request.forget(_retval); return NS_OK; } NS_IMETHODIMP -IDBObjectStore::GetAll(nsIIDBKeyRange* aKeyRange, +IDBObjectStore::GetAll(const jsval& aKey, PRUint32 aLimit, + JSContext* aCx, PRUint8 aOptionalArgCount, nsIIDBRequest** _retval) { NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); if (!mTransaction->IsOpen()) { return NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR; } + nsresult rv; + + nsRefPtr<IDBKeyRange> keyRange; + if (aOptionalArgCount) { + rv = IDBKeyRange::FromJSVal(aCx, aKey, getter_AddRefs(keyRange)); + NS_ENSURE_SUCCESS(rv, rv); + } + if (aOptionalArgCount < 2) { aLimit = PR_UINT32_MAX; } - nsresult rv; - Key lowerKey, upperKey; - bool lowerOpen = false, upperOpen = false; - - if (aKeyRange) { - nsCOMPtr<nsIVariant> variant; - rv = aKeyRange->GetLower(getter_AddRefs(variant)); - NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); - - rv = IDBObjectStore::GetKeyFromVariant(variant, lowerKey); - if (NS_FAILED(rv)) { - return rv; - } - - rv = aKeyRange->GetUpper(getter_AddRefs(variant)); - NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); - - rv = IDBObjectStore::GetKeyFromVariant(variant, upperKey); - if (NS_FAILED(rv)) { - return rv; - } - - rv = aKeyRange->GetLowerOpen(&lowerOpen); - NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); - - rv = aKeyRange->GetUpperOpen(&upperOpen); - NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); - } - nsRefPtr<IDBRequest> request = GenerateRequest(this); NS_ENSURE_TRUE(request, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); nsRefPtr<GetAllHelper> helper = - new GetAllHelper(mTransaction, request, this, lowerKey, upperKey, lowerOpen, - upperOpen, aLimit); + new GetAllHelper(mTransaction, request, this, keyRange, aLimit); rv = helper->DispatchToTransactionPool(); NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); request.forget(_retval); return NS_OK; } @@ -1321,17 +1129,17 @@ IDBObjectStore::Delete(const jsval& aKey return NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR; } if (!IsWriteAllowed()) { return NS_ERROR_DOM_INDEXEDDB_READ_ONLY_ERR; } Key key; - nsresult rv = GetKeyFromJSVal(aKey, aCx, key); + nsresult rv = key.SetFromJSVal(aCx, aKey); if (NS_FAILED(rv)) { return rv; } if (key.IsUnset()) { return NS_ERROR_DOM_INDEXEDDB_DATA_ERR; } @@ -1369,74 +1177,53 @@ IDBObjectStore::Clear(nsIIDBRequest** _r nsresult rv = helper->DispatchToTransactionPool(); NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); request.forget(_retval); return NS_OK; } NS_IMETHODIMP -IDBObjectStore::OpenCursor(nsIIDBKeyRange* aKeyRange, +IDBObjectStore::OpenCursor(const jsval& aKey, PRUint16 aDirection, + JSContext* aCx, PRUint8 aOptionalArgCount, nsIIDBRequest** _retval) { NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); if (!mTransaction->IsOpen()) { return NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR; } nsresult rv; - Key lowerKey, upperKey; - bool lowerOpen = false, upperOpen = false; - - if (aKeyRange) { - nsCOMPtr<nsIVariant> variant; - rv = aKeyRange->GetLower(getter_AddRefs(variant)); - NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); - - rv = IDBObjectStore::GetKeyFromVariant(variant, lowerKey); - if (NS_FAILED(rv)) { - return rv; + + nsRefPtr<IDBKeyRange> keyRange; + if (aOptionalArgCount) { + rv = IDBKeyRange::FromJSVal(aCx, aKey, getter_AddRefs(keyRange)); + NS_ENSURE_SUCCESS(rv, rv); + + if (aOptionalArgCount >= 2) { + if (aDirection != nsIIDBCursor::NEXT && + aDirection != nsIIDBCursor::NEXT_NO_DUPLICATE && + aDirection != nsIIDBCursor::PREV && + aDirection != nsIIDBCursor::PREV_NO_DUPLICATE) { + return NS_ERROR_DOM_INDEXEDDB_NON_TRANSIENT_ERR; + } } - - rv = aKeyRange->GetUpper(getter_AddRefs(variant)); - NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); - - rv = IDBObjectStore::GetKeyFromVariant(variant, upperKey); - if (NS_FAILED(rv)) { - return rv; + else { + aDirection = nsIIDBCursor::NEXT; } - - rv = aKeyRange->GetLowerOpen(&lowerOpen); - NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); - - rv = aKeyRange->GetUpperOpen(&upperOpen); - NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); - } - - if (aOptionalArgCount >= 2) { - if (aDirection != nsIIDBCursor::NEXT && - aDirection != nsIIDBCursor::NEXT_NO_DUPLICATE && - aDirection != nsIIDBCursor::PREV && - aDirection != nsIIDBCursor::PREV_NO_DUPLICATE) { - return NS_ERROR_DOM_INDEXEDDB_NON_TRANSIENT_ERR; - } - } - else { - aDirection = nsIIDBCursor::NEXT; } nsRefPtr<IDBRequest> request = GenerateRequest(this); NS_ENSURE_TRUE(request, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); nsRefPtr<OpenCursorHelper> helper = - new OpenCursorHelper(mTransaction, request, this, lowerKey, upperKey, - lowerOpen, upperOpen, aDirection); + new OpenCursorHelper(mTransaction, request, this, keyRange, aDirection); rv = helper->DispatchToTransactionPool(); NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); request.forget(_retval); return NS_OK; } @@ -1668,16 +1455,31 @@ IDBObjectStore::DeleteIndex(const nsAStr nsresult rv = helper->DispatchToTransactionPool(); NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); info->indexes.RemoveElementAt(index); return NS_OK; } +/* +NS_IMETHODIMP +IDBObjectStore::Count(jsval aKey, + JSContext* aCx, + PRUint8 aOptionalArgCount, + nsIIDBRequest** _retval) +{ + if (!mTransaction->IsOpen()) { + return NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR; + } + + return NS_ERROR_NOT_IMPLEMENTED; +} +*/ + nsresult AddHelper::DoDatabaseWork(mozIStorageConnection* aConnection) { NS_PRECONDITION(aConnection, "Passed a null connection!"); nsresult rv; bool mayOverwrite = mOverwrite; bool unsetKey = mKey.IsUnset(); @@ -1703,28 +1505,18 @@ AddHelper::DoDatabaseWork(mozIStorageCon stmt = mTransaction->GetStatement(autoIncrement); NS_ENSURE_TRUE(stmt, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); mozStorageStatementScoper scoper(stmt); rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("osid"), osid); NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); - NS_NAMED_LITERAL_CSTRING(id, "id"); - - if (mKey.IsInt()) { - rv = stmt->BindInt64ByName(id, mKey.IntValue()); - } - else if (mKey.IsString()) { - rv = stmt->BindStringByName(id, mKey.StringValue()); - } - else { - NS_NOTREACHED("Unknown key type!"); - } - NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); + rv = mKey.BindToStatement(stmt, NS_LITERAL_CSTRING("id")); + NS_ENSURE_SUCCESS(rv, rv); bool hasResult; rv = stmt->ExecuteStep(&hasResult); NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); if (hasResult) { return NS_ERROR_DOM_INDEXEDDB_CONSTRAINT_ERR; } @@ -1739,26 +1531,18 @@ AddHelper::DoDatabaseWork(mozIStorageCon NS_NAMED_LITERAL_CSTRING(keyValue, "key_value"); rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("osid"), osid); NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); if (!autoIncrement || mayOverwrite) { NS_ASSERTION(!mKey.IsUnset(), "This shouldn't happen!"); - if (mKey.IsInt()) { - rv = stmt->BindInt64ByName(keyValue, mKey.IntValue()); - } - else if (mKey.IsString()) { - rv = stmt->BindStringByName(keyValue, mKey.StringValue()); - } - else { - NS_NOTREACHED("Unknown key type!"); - } - NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); + rv = mKey.BindToStatement(stmt, keyValue); + NS_ENSURE_SUCCESS(rv, rv); } const PRUint8* buffer = reinterpret_cast<const PRUint8*>(mCloneBuffer.data()); size_t bufferLength = mCloneBuffer.nbytes(); rv = stmt->BindBlobByName(NS_LITERAL_CSTRING("data"), buffer, bufferLength); NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); @@ -1775,52 +1559,48 @@ AddHelper::DoDatabaseWork(mozIStorageCon mozStorageStatementScoper scoper2(stmt); rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("osid"), osid); NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); NS_ASSERTION(!mKey.IsUnset(), "This shouldn't happen!"); - if (mKey.IsInt()) { - rv = stmt->BindInt64ByName(keyValue, mKey.IntValue()); - } - else if (mKey.IsString()) { - rv = stmt->BindStringByName(keyValue, mKey.StringValue()); - } - else { - NS_NOTREACHED("Unknown key type!"); - } - NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); + rv = mKey.BindToStatement(stmt, keyValue); + NS_ENSURE_SUCCESS(rv, rv); rv = stmt->BindBlobByName(NS_LITERAL_CSTRING("data"), buffer, bufferLength); NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); rv = stmt->Execute(); } if (NS_FAILED(rv)) { return NS_ERROR_DOM_INDEXEDDB_CONSTRAINT_ERR; } } // If we are supposed to generate a key, get the new id. if (autoIncrement && !mOverwrite) { #ifdef DEBUG - PRInt64 oldKey = unsetKey ? 0 : mKey.IntValue(); + PRInt64 oldKey = unsetKey ? 0 : mKey.ToInteger(); #endif - rv = aConnection->GetLastInsertRowID(mKey.ToIntPtr()); + PRInt64 newIntKey; + rv = aConnection->GetLastInsertRowID(&newIntKey); NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); + rv = mKey.SetFromInteger(newIntKey); + NS_ENSURE_SUCCESS(rv, rv); + #ifdef DEBUG - NS_ASSERTION(mKey.IsInt(), "Bad key value!"); + NS_ASSERTION(mKey.IsInteger(), "Bad key value!"); if (!unsetKey) { - NS_ASSERTION(mKey.IntValue() == oldKey, "Something went haywire!"); + NS_ASSERTION(mKey.ToInteger() == oldKey, "Something went haywire!"); } #endif if (!keyPath.IsEmpty() && unsetKey) { // Special case where someone put an object into an autoIncrement'ing // objectStore with no key in its keyPath set. We needed to figure out // which row id we would get above before we could set that properly. rv = mObjectStore->ModifyValueForNewKey(mCloneBuffer, mKey, @@ -1834,34 +1614,34 @@ AddHelper::DoDatabaseWork(mozIStorageCon stmt = mTransaction->AddStatement(false, true, true); NS_ENSURE_TRUE(stmt, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); mozStorageStatementScoper scoper2(stmt); rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("osid"), osid); NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); - rv = stmt->BindInt64ByName(keyValue, mKey.IntValue()); - NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); + rv = mKey.BindToStatement(stmt, keyValue); + NS_ENSURE_SUCCESS(rv, rv); buffer = reinterpret_cast<const PRUint8*>(mCloneBuffer.data()); bufferLength = mCloneBuffer.nbytes(); rv = stmt->BindBlobByName(NS_LITERAL_CSTRING("data"), buffer, bufferLength); NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); rv = stmt->Execute(); NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); } } // Update our indexes if needed. if (!mIndexUpdateInfo.IsEmpty()) { - PRInt64 objectDataId = autoIncrement ? mKey.IntValue() : LL_MININT; + PRInt64 objectDataId = autoIncrement ? mKey.ToInteger() : LL_MININT; rv = IDBObjectStore::UpdateIndexes(mTransaction, osid, mKey, autoIncrement, mOverwrite, objectDataId, mIndexUpdateInfo); if (rv == NS_ERROR_STORAGE_CONSTRAINT) { return NS_ERROR_DOM_INDEXEDDB_CONSTRAINT_ERR; } NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); } @@ -1872,17 +1652,17 @@ AddHelper::DoDatabaseWork(mozIStorageCon nsresult AddHelper::GetSuccessResult(JSContext* aCx, jsval* aVal) { NS_ASSERTION(!mKey.IsUnset(), "Badness!"); mCloneBuffer.clear(); - return IDBObjectStore::GetJSValFromKey(mKey, aCx, aVal); + return mKey.ToJSVal(aCx, aVal); } nsresult GetHelper::DoDatabaseWork(mozIStorageConnection* aConnection) { NS_PRECONDITION(aConnection, "Passed a null connection!"); nsCOMPtr<mozIStorageStatement> stmt = @@ -1892,28 +1672,18 @@ GetHelper::DoDatabaseWork(mozIStorageCon mozStorageStatementScoper scoper(stmt); nsresult rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("osid"), mObjectStore->Id()); NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); NS_ASSERTION(!mKey.IsUnset(), "Must have a key here!"); - NS_NAMED_LITERAL_CSTRING(id, "id"); - - if (mKey.IsInt()) { - rv = stmt->BindInt64ByName(id, mKey.IntValue()); - } - else if (mKey.IsString()) { - rv = stmt->BindStringByName(id, mKey.StringValue()); - } - else { - NS_NOTREACHED("Unknown key type!"); - } - NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); + rv = mKey.BindToStatement(stmt, NS_LITERAL_CSTRING("id")); + NS_ENSURE_SUCCESS(rv, rv); // Search for it! bool hasResult; rv = stmt->ExecuteStep(&hasResult); NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); if (hasResult) { rv = IDBObjectStore::GetStructuredCloneDataFromStatement(stmt, 0, @@ -1948,41 +1718,31 @@ DeleteHelper::DoDatabaseWork(mozIStorage mozStorageStatementScoper scoper(stmt); nsresult rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("osid"), mObjectStore->Id()); NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); NS_ASSERTION(!mKey.IsUnset(), "Must have a key here!"); - NS_NAMED_LITERAL_CSTRING(key_value, "key_value"); - - if (mKey.IsInt()) { - rv = stmt->BindInt64ByName(key_value, mKey.IntValue()); - } - else if (mKey.IsString()) { - rv = stmt->BindStringByName(key_value, mKey.StringValue()); - } - else { - NS_NOTREACHED("Unknown key type!"); - } - NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); + rv = mKey.BindToStatement(stmt, NS_LITERAL_CSTRING("key_value")); + NS_ENSURE_SUCCESS(rv, rv); rv = stmt->Execute(); NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); return NS_OK; } nsresult DeleteHelper::GetSuccessResult(JSContext* aCx, jsval* aVal) { NS_ASSERTION(!mKey.IsUnset(), "Badness!"); - return IDBObjectStore::GetJSValFromKey(mKey, aCx, aVal); + return mKey.ToJSVal(aCx, aVal); } nsresult ClearHelper::DoDatabaseWork(mozIStorageConnection* aConnection) { NS_PRECONDITION(aConnection, "Passed a null connection!"); nsCString table; @@ -2026,23 +1786,25 @@ OpenCursorHelper::DoDatabaseWork(mozISto keyColumn.AssignLiteral("key_value"); } NS_NAMED_LITERAL_CSTRING(id, "id"); NS_NAMED_LITERAL_CSTRING(lowerKeyName, "lower_key"); NS_NAMED_LITERAL_CSTRING(upperKeyName, "upper_key"); nsCAutoString keyRangeClause; - if (!mLowerKey.IsUnset()) { - AppendConditionClause(keyColumn, lowerKeyName, false, !mLowerOpen, - keyRangeClause); - } - if (!mUpperKey.IsUnset()) { - AppendConditionClause(keyColumn, upperKeyName, true, !mUpperOpen, - keyRangeClause); + if (mKeyRange) { + if (!mKeyRange->Lower().IsUnset()) { + AppendConditionClause(keyColumn, lowerKeyName, false, + !mKeyRange->IsLowerOpen(), keyRangeClause); + } + if (!mKeyRange->Upper().IsUnset()) { + AppendConditionClause(keyColumn, upperKeyName, true, + !mKeyRange->IsUpperOpen(), keyRangeClause); + } } nsCAutoString directionClause = NS_LITERAL_CSTRING(" ORDER BY ") + keyColumn; switch (mDirection) { case nsIIDBCursor::NEXT: case nsIIDBCursor::NEXT_NO_DUPLICATE: directionClause += NS_LITERAL_CSTRING(" ASC"); break; @@ -2065,65 +1827,38 @@ OpenCursorHelper::DoDatabaseWork(mozISto mTransaction->GetCachedStatement(firstQuery); NS_ENSURE_TRUE(stmt, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); mozStorageStatementScoper scoper(stmt); nsresult rv = stmt->BindInt64ByName(id, mObjectStore->Id()); NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); - if (!mLowerKey.IsUnset()) { - if (mLowerKey.IsString()) { - rv = stmt->BindStringByName(lowerKeyName, mLowerKey.StringValue()); - } - else if (mLowerKey.IsInt()) { - rv = stmt->BindInt64ByName(lowerKeyName, mLowerKey.IntValue()); - } - else { - NS_NOTREACHED("Bad key!"); + if (mKeyRange) { + if (!mKeyRange->Lower().IsUnset()) { + rv = mKeyRange->Lower().BindToStatement(stmt, lowerKeyName); + NS_ENSURE_SUCCESS(rv, rv); } - NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); - } - - if (!mUpperKey.IsUnset()) { - if (mUpperKey.IsString()) { - rv = stmt->BindStringByName(upperKeyName, mUpperKey.StringValue()); + if (!mKeyRange->Upper().IsUnset()) { + rv = mKeyRange->Upper().BindToStatement(stmt, upperKeyName); + NS_ENSURE_SUCCESS(rv, rv); } - else if (mUpperKey.IsInt()) { - rv = stmt->BindInt64ByName(upperKeyName, mUpperKey.IntValue()); - } - else { - NS_NOTREACHED("Bad key!"); - } - NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); } bool hasResult; rv = stmt->ExecuteStep(&hasResult); NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); if (!hasResult) { - mKey = Key::UNSETKEY; + mKey.Unset(); return NS_OK; } - PRInt32 keyType; - rv = stmt->GetTypeOfIndex(0, &keyType); - NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); - - if (keyType == mozIStorageStatement::VALUE_TYPE_INTEGER) { - mKey = stmt->AsInt64(0); - } - else if (keyType == mozIStorageStatement::VALUE_TYPE_TEXT) { - rv = stmt->GetString(0, mKey.ToString()); - NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); - } - else { - NS_NOTREACHED("Bad SQLite type!"); - } + rv = mKey.SetFromStatement(stmt, 0); + NS_ENSURE_SUCCESS(rv, rv); rv = IDBObjectStore::GetStructuredCloneDataFromStatement(stmt, 1, mCloneBuffer); NS_ENSURE_SUCCESS(rv, rv); // Now we need to make the query to get the next match. keyRangeClause.Truncate(); nsCAutoString continueToKeyRangeClause; @@ -2133,36 +1868,38 @@ OpenCursorHelper::DoDatabaseWork(mozISto switch (mDirection) { case nsIIDBCursor::NEXT: case nsIIDBCursor::NEXT_NO_DUPLICATE: AppendConditionClause(keyColumn, currentKey, false, false, keyRangeClause); AppendConditionClause(keyColumn, currentKey, false, true, continueToKeyRangeClause); - if (!mUpperKey.IsUnset()) { - AppendConditionClause(keyColumn, rangeKey, true, !mUpperOpen, - keyRangeClause); - AppendConditionClause(keyColumn, rangeKey, true, !mUpperOpen, + if (mKeyRange && !mKeyRange->Upper().IsUnset()) { + AppendConditionClause(keyColumn, rangeKey, true, + !mKeyRange->IsUpperOpen(), keyRangeClause); + AppendConditionClause(keyColumn, rangeKey, true, + !mKeyRange->IsUpperOpen(), continueToKeyRangeClause); - mRangeKey = mUpperKey; + mRangeKey = mKeyRange->Upper(); } break; case nsIIDBCursor::PREV: case nsIIDBCursor::PREV_NO_DUPLICATE: AppendConditionClause(keyColumn, currentKey, true, false, keyRangeClause); AppendConditionClause(keyColumn, currentKey, true, true, continueToKeyRangeClause); - if (!mLowerKey.IsUnset()) { - AppendConditionClause(keyColumn, rangeKey, false, !mLowerOpen, - keyRangeClause); - AppendConditionClause(keyColumn, rangeKey, false, !mLowerOpen, + if (mKeyRange && !mKeyRange->Lower().IsUnset()) { + AppendConditionClause(keyColumn, rangeKey, false, + !mKeyRange->IsLowerOpen(), keyRangeClause); + AppendConditionClause(keyColumn, rangeKey, false, + !mKeyRange->IsLowerOpen(), continueToKeyRangeClause); - mRangeKey = mLowerKey; + mRangeKey = mKeyRange->Lower(); } break; default: NS_NOTREACHED("Unknown direction type!"); } mContinueQuery = NS_LITERAL_CSTRING("SELECT ") + keyColumn + @@ -2387,34 +2124,23 @@ CreateIndexHelper::InsertDataFromObjectS rv = insertStmt->BindInt64ByName(NS_LITERAL_CSTRING("object_data_id"), stmt->AsInt64(0)); NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); if (!mIndex->IsAutoIncrement()) { NS_NAMED_LITERAL_CSTRING(objectDataKey, "object_data_key"); - PRInt32 keyType; - rv = stmt->GetTypeOfIndex(2, &keyType); - NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); - - if (keyType == mozIStorageStatement::VALUE_TYPE_INTEGER) { - rv = insertStmt->BindInt64ByName(objectDataKey, stmt->AsInt64(2)); - } - else if (keyType == mozIStorageStatement::VALUE_TYPE_TEXT) { - nsString stringKey; - rv = stmt->GetString(2, stringKey); - NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); - - rv = insertStmt->BindStringByName(objectDataKey, stringKey); - } - else { - NS_NOTREACHED("Bad SQLite type!"); - } - NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); + Key key; + rv = key.SetFromStatement(stmt, 2); + NS_ENSURE_SUCCESS(rv, rv); + + rv = + key.BindToStatement(insertStmt, NS_LITERAL_CSTRING("object_data_key")); + NS_ENSURE_SUCCESS(rv, rv); } const PRUint8* data; PRUint32 dataLength; rv = stmt->GetSharedBlob(1, &dataLength, &data); NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); NS_ENSURE_TRUE(sTLSIndex != BAD_TLS_INDEX, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); @@ -2427,34 +2153,26 @@ CreateIndexHelper::InsertDataFromObjectS NS_ENSURE_TRUE(tlsEntry, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); PR_SetThreadPrivate(sTLSIndex, tlsEntry); } Key key; rv = IDBObjectStore::GetKeyPathValueFromStructuredData(data, dataLength, mIndex->KeyPath(), - tlsEntry->Context(), key); + tlsEntry->Context(), + key); NS_ENSURE_SUCCESS(rv, rv); if (key.IsUnset()) { continue; } - NS_NAMED_LITERAL_CSTRING(value, "value"); - if (key.IsInt()) { - rv = insertStmt->BindInt64ByName(value, key.IntValue()); - } - else if (key.IsString()) { - rv = insertStmt->BindStringByName(value, key.StringValue()); - } - else { - return NS_ERROR_DOM_INDEXEDDB_CONSTRAINT_ERR; - } - NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); + rv = key.BindToStatement(insertStmt, NS_LITERAL_CSTRING("value")); + NS_ENSURE_SUCCESS(rv, rv); rv = insertStmt->Execute(); NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); } return NS_OK; } @@ -2497,86 +2215,70 @@ GetAllHelper::DoDatabaseWork(mozIStorage keyColumn.AssignLiteral("key_value"); } NS_NAMED_LITERAL_CSTRING(osid, "osid"); NS_NAMED_LITERAL_CSTRING(lowerKeyName, "lower_key"); NS_NAMED_LITERAL_CSTRING(upperKeyName, "upper_key"); nsCAutoString keyRangeClause; - if (!mLowerKey.IsUnset()) { - keyRangeClause = NS_LITERAL_CSTRING(" AND ") + keyColumn; - if (mLowerOpen) { - keyRangeClause.AppendLiteral(" > :"); - } - else { - keyRangeClause.AppendLiteral(" >= :"); + if (mKeyRange) { + if (!mKeyRange->Lower().IsUnset()) { + keyRangeClause = NS_LITERAL_CSTRING(" AND ") + keyColumn; + if (mKeyRange->IsLowerOpen()) { + keyRangeClause.AppendLiteral(" > :"); + } + else { + keyRangeClause.AppendLiteral(" >= :"); + } + keyRangeClause.Append(lowerKeyName); } - keyRangeClause.Append(lowerKeyName); - } - - if (!mUpperKey.IsUnset()) { - keyRangeClause += NS_LITERAL_CSTRING(" AND ") + keyColumn; - if (mUpperOpen) { - keyRangeClause.AppendLiteral(" < :"); + + if (!mKeyRange->Upper().IsUnset()) { + keyRangeClause += NS_LITERAL_CSTRING(" AND ") + keyColumn; + if (mKeyRange->IsUpperOpen()) { + keyRangeClause.AppendLiteral(" < :"); + } + else { + keyRangeClause.AppendLiteral(" <= :"); + } + keyRangeClause.Append(upperKeyName); } - else { - keyRangeClause.AppendLiteral(" <= :"); - } - keyRangeClause.Append(upperKeyName); } nsCAutoString limitClause; if (mLimit != PR_UINT32_MAX) { limitClause.AssignLiteral(" LIMIT "); limitClause.AppendInt(mLimit); } nsCString query = NS_LITERAL_CSTRING("SELECT data FROM ") + table + NS_LITERAL_CSTRING(" WHERE object_store_id = :") + osid + keyRangeClause + NS_LITERAL_CSTRING(" ORDER BY ") + keyColumn + NS_LITERAL_CSTRING(" ASC") + limitClause; - if (!mCloneBuffers.SetCapacity(50)) { - NS_ERROR("Out of memory!"); - return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; - } + mCloneBuffers.SetCapacity(50); nsCOMPtr<mozIStorageStatement> stmt = mTransaction->GetCachedStatement(query); NS_ENSURE_TRUE(stmt, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); mozStorageStatementScoper scoper(stmt); nsresult rv = stmt->BindInt64ByName(osid, mObjectStore->Id()); NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); - if (!mLowerKey.IsUnset()) { - if (mLowerKey.IsString()) { - rv = stmt->BindStringByName(lowerKeyName, mLowerKey.StringValue()); - } - else if (mLowerKey.IsInt()) { - rv = stmt->BindInt64ByName(lowerKeyName, mLowerKey.IntValue()); - } - else { - NS_NOTREACHED("Bad key!"); + if (mKeyRange) { + if (!mKeyRange->Lower().IsUnset()) { + rv = mKeyRange->Lower().BindToStatement(stmt, lowerKeyName); + NS_ENSURE_SUCCESS(rv, rv); } - NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); - } - - if (!mUpperKey.IsUnset()) { - if (mUpperKey.IsString()) { - rv = stmt->BindStringByName(upperKeyName, mUpperKey.StringValue()); + if (!mKeyRange->Upper().IsUnset()) { + rv = mKeyRange->Upper().BindToStatement(stmt, upperKeyName); + NS_ENSURE_SUCCESS(rv, rv); } - else if (mUpperKey.IsInt()) { - rv = stmt->BindInt64ByName(upperKeyName, mUpperKey.IntValue()); - } - else { - NS_NOTREACHED("Bad key!"); - } - NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); } bool hasResult; while (NS_SUCCEEDED((rv = stmt->ExecuteStep(&hasResult))) && hasResult) { if (mCloneBuffers.Capacity() == mCloneBuffers.Length()) { if (!mCloneBuffers.SetCapacity(mCloneBuffers.Capacity() * 2)) { NS_ERROR("Out of memory!"); return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
--- a/dom/indexedDB/IDBObjectStore.h +++ b/dom/indexedDB/IDBObjectStore.h @@ -37,29 +37,29 @@ * * ***** END LICENSE BLOCK ***** */ #ifndef mozilla_dom_indexeddb_idbobjectstore_h__ #define mozilla_dom_indexeddb_idbobjectstore_h__ #include "mozilla/dom/indexedDB/IndexedDatabase.h" #include "mozilla/dom/indexedDB/IDBTransaction.h" -#include "mozilla/dom/indexedDB/Key.h" #include "nsIIDBObjectStore.h" #include "nsIIDBTransaction.h" #include "nsCycleCollectionParticipant.h" class nsIScriptContext; class nsPIDOMWindow; BEGIN_INDEXEDDB_NAMESPACE class AsyncConnectionHelper; +class Key; struct ObjectStoreInfo; struct IndexInfo; struct IndexUpdateInfo; class IDBObjectStore : public nsIIDBObjectStore { public: @@ -68,30 +68,16 @@ public: NS_DECL_CYCLE_COLLECTION_CLASS(IDBObjectStore) static already_AddRefed<IDBObjectStore> Create(IDBTransaction* aTransaction, const ObjectStoreInfo* aInfo); static nsresult - GetKeyFromVariant(nsIVariant* aKeyVariant, - Key& aKey); - - static nsresult - GetKeyFromJSVal(jsval aKeyVal, - JSContext* aCx, - Key& aKey); - - static nsresult - GetJSValFromKey(const Key& aKey, - JSContext* aCx, - jsval* aKeyVal); - - static nsresult GetKeyPathValueFromStructuredData(const PRUint8* aData, PRUint32 aDataLength, const nsAString& aKeyPath, JSContext* aCx, Key& aValue); static nsresult GetIndexUpdateInfo(ObjectStoreInfo* aObjectStoreInfo,
--- a/dom/indexedDB/IDBRequest.cpp +++ b/dom/indexedDB/IDBRequest.cpp @@ -36,17 +36,16 @@ * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ #include "IDBRequest.h" #include "nsIScriptContext.h" -#include "nsIVariant.h" #include "nsComponentManagerUtils.h" #include "nsDOMClassInfoID.h" #include "nsDOMJSUtils.h" #include "nsContentUtils.h" #include "nsEventDispatcher.h" #include "nsPIDOMWindow.h" #include "nsStringGlue.h"
--- a/dom/indexedDB/Key.h +++ b/dom/indexedDB/Key.h @@ -37,119 +37,88 @@ * * ***** END LICENSE BLOCK ***** */ #ifndef mozilla_dom_indexeddb_key_h__ #define mozilla_dom_indexeddb_key_h__ #include "mozilla/dom/indexedDB/IndexedDatabase.h" +#include "mozIStorageStatement.h" + +#include "xpcprivate.h" +#include "XPCQuickStubs.h" + BEGIN_INDEXEDDB_NAMESPACE class Key { public: - enum Type { UNSETKEY, STRINGKEY, INTKEY }; - Key() - : mType(UNSETKEY), mInt(0) - { } - - Key(const Key& aOther) - { - *this = aOther; - } - - Key& operator=(const Key& aOther) { - if (this != &aOther) { - mType = aOther.mType; - mString = aOther.mString; - mInt = aOther.mInt; - } - return *this; - } - - Key& operator=(Type aType) - { - NS_ASSERTION(aType == UNSETKEY , - "Use one of the other operators to assign your value!"); - mType = aType; - mString.Truncate(); - mInt = 0; - return *this; + Unset(); } Key& operator=(const nsAString& aString) { - mType = STRINGKEY; - mString = aString; - mInt = 0; + SetFromString(aString); return *this; } Key& operator=(PRInt64 aInt) { - mType = INTKEY; - mString.Truncate(); - mInt = aInt; + SetFromInteger(aInt); return *this; } bool operator==(const Key& aOther) const { + NS_ASSERTION(mType != KEYTYPE_VOID && aOther.mType != KEYTYPE_VOID, + "Don't compare unset keys!"); + if (mType == aOther.mType) { switch (mType) { - case UNSETKEY: - return true; + case KEYTYPE_STRING: + return ToString() == aOther.ToString(); - case STRINGKEY: - return mString == aOther.mString; - - case INTKEY: - return mInt == aOther.mInt; + case KEYTYPE_INTEGER: + return ToInteger() == aOther.ToInteger(); default: NS_NOTREACHED("Unknown type!"); } } return false; } bool operator!=(const Key& aOther) const { return !(*this == aOther); } bool operator<(const Key& aOther) const { + NS_ASSERTION(mType != KEYTYPE_VOID && aOther.mType != KEYTYPE_VOID, + "Don't compare unset keys!"); + switch (mType) { - case UNSETKEY: - if (aOther.mType == UNSETKEY) { - return false; - } - return true; - - case STRINGKEY: - if (aOther.mType == UNSETKEY || - aOther.mType == INTKEY) { + case KEYTYPE_STRING: { + if (aOther.mType == KEYTYPE_INTEGER) { return false; } - NS_ASSERTION(aOther.mType == STRINGKEY, "Unknown type!"); - return mString < aOther.mString; + NS_ASSERTION(aOther.mType == KEYTYPE_STRING, "Unknown type!"); + return ToString() < aOther.ToString(); + } - case INTKEY: - if (aOther.mType == UNSETKEY) { - return false; - } - if (aOther.mType == STRINGKEY) { + case KEYTYPE_INTEGER: + if (aOther.mType == KEYTYPE_STRING) { return true; } - NS_ASSERTION(aOther.mType == INTKEY, "Unknown type!"); - return mInt < aOther.mInt; + NS_ASSERTION(aOther.mType == KEYTYPE_INTEGER, "Unknown type!"); + return ToInteger() < aOther.ToInteger(); default: NS_NOTREACHED("Unknown type!"); } return false; } bool operator>(const Key& aOther) const @@ -162,49 +131,195 @@ public: return (*this == aOther || *this < aOther); } bool operator>=(const Key& aOther) const { return (*this == aOther || !(*this < aOther)); } - bool IsUnset() const { return mType == UNSETKEY; } - bool IsString() const { return mType == STRINGKEY; } - bool IsInt() const { return mType == INTKEY; } + void + Unset() + { + mType = KEYTYPE_VOID; + mStringKey.SetIsVoid(true); + mIntKey = 0; + } + + bool IsUnset() const { return mType == KEYTYPE_VOID; } + bool IsString() const { return mType == KEYTYPE_STRING; } + bool IsInteger() const { return mType == KEYTYPE_INTEGER; } + + nsresult SetFromString(const nsAString& aString) + { + mType = KEYTYPE_STRING; + mStringKey = aString; + mIntKey = 0; + return NS_OK; + } + + nsresult SetFromInteger(PRInt64 aInt) + { + mType = KEYTYPE_INTEGER; + mStringKey.SetIsVoid(true); + mIntKey = aInt; + return NS_OK; + } - const nsString& StringValue() const { - NS_ASSERTION(IsString(), "Wrong type!"); - return mString; + nsresult SetFromJSVal(JSContext* aCx, + jsval aVal) + { + if (JSVAL_IS_STRING(aVal)) { + jsval tempRoot = JSVAL_VOID; + SetFromString(xpc_qsAString(aCx, aVal, &tempRoot)); + return NS_OK; + } + + if (JSVAL_IS_INT(aVal)) { + SetFromInteger(JSVAL_TO_INT(aVal)); + return NS_OK; + } + + if (JSVAL_IS_DOUBLE(aVal)) { + jsdouble doubleActual = JSVAL_TO_DOUBLE(aVal); + int64 doubleAsInt = static_cast<int64>(doubleActual); + if (doubleActual == doubleAsInt) { + SetFromInteger(doubleAsInt); + return NS_OK; + } + } + + if (JSVAL_IS_NULL(aVal) || JSVAL_IS_VOID(aVal)) { + Unset(); + return NS_OK; + } + + return NS_ERROR_DOM_INDEXEDDB_DATA_ERR; } - PRInt64 IntValue() const { - NS_ASSERTION(IsInt(), "Wrong type!"); - return mInt; + nsresult ToJSVal(JSContext* aCx, + jsval* aVal) const + { + if (IsString()) { + nsString key = ToString(); + if (!xpc_qsStringToJsval(aCx, key, aVal)) { + return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; + } + } + else if (IsInteger()) { + if (!JS_NewNumberValue(aCx, static_cast<jsdouble>(ToInteger()), aVal)) { + return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; + } + } + else if (IsUnset()) { + *aVal = JSVAL_VOID; + } + else { + NS_NOTREACHED("Unknown key type!"); + } + return NS_OK; + } + + PRInt64 ToInteger() const + { + NS_ASSERTION(IsInteger(), "Don't call me!"); + return mIntKey; + } + + const nsString& ToString() const + { + NS_ASSERTION(IsString(), "Don't call me!"); + return mStringKey; } - nsAString& ToString() { - mType = STRINGKEY; - mInt = 0; - return mString; + nsresult BindToStatement(mozIStorageStatement* aStatement, + const nsACString& aParamName) const + { + nsresult rv; + + if (IsString()) { + rv = aStatement->BindStringByName(aParamName, ToString()); + } + else if (IsInteger()) { + rv = aStatement->BindInt64ByName(aParamName, ToInteger()); + } + else { + NS_NOTREACHED("Bad key!"); + } + + return NS_SUCCEEDED(rv) ? NS_OK : NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; + } + + nsresult BindToStatementAllowUnset(mozIStorageStatement* aStatement, + const nsACString& aParamName) const + { + nsresult rv; + + if (IsUnset()) { + rv = aStatement->BindStringByName(aParamName, EmptyString()); + return NS_SUCCEEDED(rv) ? NS_OK : NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; + } + + return BindToStatement(aStatement, aParamName); } - PRInt64* ToIntPtr() { - mType = INTKEY; - mString.Truncate(); - return &mInt; + nsresult SetFromStatement(mozIStorageStatement* aStatement, + PRUint32 aIndex) + { + PRInt32 columnType; + nsresult rv = aStatement->GetTypeOfIndex(aIndex, &columnType); + NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); + + NS_ASSERTION(columnType == mozIStorageStatement::VALUE_TYPE_INTEGER || + columnType == mozIStorageStatement::VALUE_TYPE_TEXT, + "Unsupported column type!"); + + return SetFromStatement(aStatement, aIndex, columnType); + } + + nsresult SetFromStatement(mozIStorageStatement* aStatement, + PRUint32 aIndex, + PRInt32 aColumnType) + { + if (aColumnType == mozIStorageStatement::VALUE_TYPE_INTEGER) { + return SetFromInteger(aStatement->AsInt64(aIndex)); + } + + if (aColumnType == mozIStorageStatement::VALUE_TYPE_TEXT) { + nsString keyString; + nsresult rv = aStatement->GetString(aIndex, keyString); + NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); + + return SetFromString(keyString); + } + + NS_NOTREACHED("Unsupported column type!"); + return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; } static - JSBool CanBeConstructedFromJSVal(jsval aVal) { - return JSVAL_IS_VOID(aVal) || JSVAL_IS_NULL(aVal) || JSVAL_IS_INT(aVal) || - JSVAL_IS_DOUBLE(aVal) || JSVAL_IS_STRING(aVal); + bool CanBeConstructedFromJSVal(jsval aVal) + { + return JSVAL_IS_INT(aVal) || JSVAL_IS_DOUBLE(aVal) || JSVAL_IS_STRING(aVal); } private: + // Wish we could use JSType here but we will end up supporting types like Date + // which JSType can't really identify. Rolling our own for now. + enum Type { + KEYTYPE_VOID, + KEYTYPE_STRING, + KEYTYPE_INTEGER + }; + + // Type of value in mJSVal. Type mType; - nsString mString; - PRInt64 mInt; + + // The string if mType is KEYTYPE_STRING, otherwise a void string. + nsString mStringKey; + + // The integer value if mType is KEYTYPE_INTEGER, otherwise 0. + int64 mIntKey; }; END_INDEXEDDB_NAMESPACE #endif /* mozilla_dom_indexeddb_key_h__ */
--- a/dom/indexedDB/Makefile.in +++ b/dom/indexedDB/Makefile.in @@ -88,16 +88,17 @@ EXPORTS_mozilla/dom/indexedDB = \ $(NULL) LOCAL_INCLUDES = \ -I$(topsrcdir)/xpcom/build \ -I$(topsrcdir)/dom/base \ -I$(topsrcdir)/dom/src/storage \ -I$(topsrcdir)/content/base/src \ -I$(topsrcdir)/content/events/src \ + -I$(topsrcdir)/js/xpconnect/src \ $(NULL) DEFINES += -D_IMPL_NS_LAYOUT # Make sure to quickstub as much as possible here! See # js/xpconnect/src/dom_quickstubs.qsconf. XPIDLSRCS = \ nsIIDBCursor.idl \
--- a/dom/indexedDB/nsIIDBCursor.idl +++ b/dom/indexedDB/nsIIDBCursor.idl @@ -35,35 +35,35 @@ * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ #include "nsISupports.idl" interface nsIIDBRequest; -interface nsIVariant; /** * IDBCursor interface. See * http://dev.w3.org/2006/webapi/WebSimpleDB/#idl-def-IDBCursor for more * information. */ -[scriptable, uuid(adee4085-68cd-4568-9d74-e3d32b6dc5c5)] +[scriptable, builtinclass, uuid(462a3607-b2d6-4f4b-9dd7-8ca0b26d3414)] interface nsIIDBCursor : nsISupports { const unsigned short NEXT = 0; const unsigned short NEXT_NO_DUPLICATE = 1; const unsigned short PREV = 2; const unsigned short PREV_NO_DUPLICATE = 3; readonly attribute unsigned short direction; readonly attribute nsISupports source; - readonly attribute nsIVariant key; + [implicit_jscontext] + readonly attribute jsval key; [implicit_jscontext] readonly attribute jsval primaryKey; // Calling continue means that the same onsuccess function will be called // again with the new key/value (or null if no more matches). [implicit_jscontext] void continue([optional /* undefined */] in jsval key);
--- a/dom/indexedDB/nsIIDBCursorWithValue.idl +++ b/dom/indexedDB/nsIIDBCursorWithValue.idl @@ -34,23 +34,19 @@ * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ #include "nsIIDBCursor.idl" -%{C++ -#include "jsapi.h" -%} - /** * IDBCursor interface. See * http://dev.w3.org/2006/webapi/WebSimpleDB/#idl-def-IDBCursor for more * information. */ -[scriptable, uuid(b6b7e08a-4379-4441-a176-447c5c96df69)] +[scriptable, builtinclass, uuid(b6b7e08a-4379-4441-a176-447c5c96df69)] interface nsIIDBCursorWithValue : nsIIDBCursor { [implicit_jscontext] readonly attribute jsval value; };
--- a/dom/indexedDB/nsIIDBDatabase.idl +++ b/dom/indexedDB/nsIIDBDatabase.idl @@ -34,29 +34,28 @@ * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ #include "nsISupports.idl" -interface nsIVariant; interface nsIIDBObjectStore; interface nsIIDBRequest; interface nsIIDBTransaction; interface nsIDOMDOMStringList; interface nsIDOMEventListener; /** * IDBDatabase interface. See * http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#idl-def-IDBDatabase * for more information. */ -[scriptable, uuid(ac14faa5-261c-4a84-9616-a700fd606f83)] +[scriptable, builtinclass, uuid(ddc9dd43-704f-45da-bb91-20f4b3103117)] interface nsIIDBDatabase : nsISupports { readonly attribute DOMString name; readonly attribute unsigned long long version; readonly attribute nsIDOMDOMStringList objectStoreNames; @@ -73,19 +72,18 @@ interface nsIIDBDatabase : nsISupports createObjectStore(in AString name, [optional /* none */] in jsval options); void deleteObjectStore(in AString name); [optional_argc, implicit_jscontext] nsIIDBTransaction - transaction(in nsIVariant storeNames, // js array of strings - [optional /* READ_ONLY */] in unsigned short mode, - [optional /* 5000ms */] in unsigned long timeout); + transaction(in jsval storeNames, // js array of strings + [optional /* READ_ONLY */] in unsigned short mode); void close(); attribute nsIDOMEventListener onerror; attribute nsIDOMEventListener onversionchange; };
--- a/dom/indexedDB/nsIIDBDatabaseException.idl +++ b/dom/indexedDB/nsIIDBDatabaseException.idl @@ -34,17 +34,17 @@ * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ #include "nsISupports.idl" -[scriptable, uuid(7aad2542-a5cb-4a57-b20c-c7d16b8582ab)] +[scriptable, builtinclass, uuid(7aad2542-a5cb-4a57-b20c-c7d16b8582ab)] interface nsIIDBDatabaseException : nsISupports { // const unsigned short NO_ERR = 0; const unsigned short UNKNOWN_ERR = 1; const unsigned short NON_TRANSIENT_ERR = 2; const unsigned short NOT_FOUND_ERR = 3; const unsigned short CONSTRAINT_ERR = 4; const unsigned short DATA_ERR = 5;
--- a/dom/indexedDB/nsIIDBFactory.idl +++ b/dom/indexedDB/nsIIDBFactory.idl @@ -37,23 +37,22 @@ * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ #include "nsISupports.idl" interface nsIIDBKeyRange; interface nsIIDBOpenDBRequest; -interface nsIVariant; /** * Interface that defines the indexedDB property on a window. See * http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#idl-def-IDBFactory * for more information. */ -[scriptable, uuid(d2889b8f-662a-42d3-8a8f-ac5179b9d5b0)] +[scriptable, builtinclass, uuid(d2889b8f-662a-42d3-8a8f-ac5179b9d5b0)] interface nsIIDBFactory : nsISupports { [implicit_jscontext, optional_argc] nsIIDBOpenDBRequest open(in AString name, [optional] in long long version); };
--- a/dom/indexedDB/nsIIDBIndex.idl +++ b/dom/indexedDB/nsIIDBIndex.idl @@ -34,57 +34,64 @@ * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ #include "nsISupports.idl" -interface nsIIDBKeyRange; interface nsIIDBObjectStore; interface nsIIDBRequest; -interface nsIVariant; /** * IDBIndex interface. See * http://dev.w3.org/2006/webapi/WebSimpleDB/#idl-def-IDBIndex for more * information. */ -[scriptable, uuid(9df1ac24-06cf-47d1-9159-3b3d65975b80)] +[scriptable, builtinclass, uuid(1da60889-3db4-4f66-9fd7-b78c1e7969b7)] interface nsIIDBIndex : nsISupports { readonly attribute DOMString name; readonly attribute DOMString storeName; readonly attribute DOMString keyPath; readonly attribute boolean unique; readonly attribute nsIIDBObjectStore objectStore; + [implicit_jscontext] nsIIDBRequest - get(in nsIVariant key); + get(in jsval key); + [implicit_jscontext] nsIIDBRequest - getKey(in nsIVariant key); + getKey(in jsval key); - [optional_argc] + [implicit_jscontext, optional_argc] nsIIDBRequest - getAll([optional /* null */] in nsIVariant key, + getAll([optional /* null */] in jsval key, [optional /* unlimited */] in unsigned long limit); - [optional_argc] + [implicit_jscontext, optional_argc] nsIIDBRequest - getAllKeys([optional /* null */] in nsIVariant key, + getAllKeys([optional /* null */] in jsval key, [optional /* unlimited */] in unsigned long limit); - [optional_argc] + [implicit_jscontext, optional_argc] nsIIDBRequest - openCursor([optional /* null */] in nsIIDBKeyRange range, + openCursor([optional /* null */] in jsval key, [optional /* nsIIDBCursor::NEXT */] in unsigned short direction); - [optional_argc] + [implicit_jscontext, optional_argc] nsIIDBRequest - openKeyCursor([optional /* null */] in nsIIDBKeyRange range, + openKeyCursor([optional /* null */] in jsval key, [optional /* nsIIDBCursor::NEXT */] in unsigned short direction); + + /* + // Accepts null, a key value, or a nsIIDBKeyRange object. + [implicit_jscontext, optional_argc] + nsIIDBRequest + count([optional] in jsval key); + */ };
--- a/dom/indexedDB/nsIIDBKeyRange.idl +++ b/dom/indexedDB/nsIIDBKeyRange.idl @@ -34,23 +34,25 @@ * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ #include "nsISupports.idl" -interface nsIVariant; - /** * IDBKeyRange interface. See * http://dev.w3.org/2006/webapi/WebSimpleDB/#idl-def-IDBKeyRange for more * information. */ -[scriptable, uuid(a1505e41-7e48-4542-9fa5-3f2c98233567)] +[scriptable, builtinclass, uuid(8aeb8660-76b3-4651-b8c2-9894ae6dfe68)] interface nsIIDBKeyRange : nsISupports { - readonly attribute nsIVariant lower; - readonly attribute nsIVariant upper; + [implicit_jscontext] + readonly attribute jsval lower; + + [implicit_jscontext] + readonly attribute jsval upper; + readonly attribute boolean lowerOpen; readonly attribute boolean upperOpen; };
--- a/dom/indexedDB/nsIIDBObjectStore.idl +++ b/dom/indexedDB/nsIIDBObjectStore.idl @@ -38,43 +38,43 @@ * ***** END LICENSE BLOCK ***** */ #include "nsISupports.idl" interface nsIIDBIndex; interface nsIIDBKeyRange; interface nsIIDBRequest; interface nsIIDBTransaction; -interface nsIVariant; interface nsIDOMDOMStringList; /** * nsIIDBObjectStore interface. See * http://dev.w3.org/2006/webapi/WebSimpleDB/#idl-def-nsIIDBObjectStore * for more information. */ -[scriptable, uuid(6a65dc92-66e3-407a-a370-590a6c54664a)] +[scriptable, builtinclass, uuid(d25dff2f-81ad-4531-bcbe-e85c8a19f11a)] interface nsIIDBObjectStore : nsISupports { readonly attribute DOMString name; readonly attribute DOMString keyPath; readonly attribute nsIDOMDOMStringList indexNames; readonly attribute nsIIDBTransaction transaction; // Success fires IDBTransactionEvent, result == value for key + [implicit_jscontext] nsIIDBRequest - get(in nsIVariant key); + get(in jsval key); // Success fires IDBTransactionEvent, result == array of values for given keys - [optional_argc] + [implicit_jscontext, optional_argc] nsIIDBRequest - getAll([optional /* null */] in nsIIDBKeyRange key, + getAll([optional /* null */] in jsval key, [optional /* unlimited */] in unsigned long limit); // Success fires IDBTransactionEvent, result == key [implicit_jscontext, optional_argc] nsIIDBRequest add(in jsval value, [optional /* undefined */] in jsval key); @@ -90,19 +90,19 @@ interface nsIIDBObjectStore : nsISupport delete(in jsval key); // Success fires IDBTransactionEvent, result == null nsIIDBRequest clear(); // Success fires IDBTransactionEvent, result == IDBCursor or result == null if // no match. - [optional_argc] + [implicit_jscontext, optional_argc] nsIIDBRequest - openCursor([optional /* null */] in nsIIDBKeyRange range, + openCursor([optional /* null */] in jsval range, [optional /* NEXT */] in unsigned short direction); /** * Optional arguments: * - unique (boolean): * Specifies whether values in the index must be unique. Defaults to * false. */ @@ -113,9 +113,16 @@ interface nsIIDBObjectStore : nsISupport [optional /* none */] in jsval options); // Returns object immediately nsIIDBIndex index(in AString name); void deleteIndex(in AString name); + + /* + // Accepts null, a key value, or a nsIIDBKeyRange object. + [implicit_jscontext, optional_argc] + nsIIDBRequest + count([optional] in jsval key); + */ };
--- a/dom/indexedDB/nsIIDBOpenDBRequest.idl +++ b/dom/indexedDB/nsIIDBOpenDBRequest.idl @@ -42,14 +42,14 @@ interface nsIDOMEventListener; /** * IDBOpenDBRequest interface. See * http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#idl-def-IDBOpenDBRequest * for more information. */ -[scriptable, uuid(91010fbe-1dfb-435d-852e-288d2804c0a7)] +[scriptable, builtinclass, uuid(91010fbe-1dfb-435d-852e-288d2804c0a7)] interface nsIIDBOpenDBRequest : nsISupports { attribute nsIDOMEventListener onblocked; attribute nsIDOMEventListener onupgradeneeded; };
--- a/dom/indexedDB/nsIIDBRequest.idl +++ b/dom/indexedDB/nsIIDBRequest.idl @@ -43,17 +43,17 @@ interface nsIDOMEventListener; interface nsIIDBTransaction; /** * IDBReqeust interface. See * http://dev.w3.org/2006/webapi/WebSimpleDB/#idl-def-IDBRequest for more * information. */ -[scriptable, uuid(a1e4a0ff-e0b2-431c-89cf-43b078189e27)] +[scriptable, builtinclass, uuid(a1e4a0ff-e0b2-431c-89cf-43b078189e27)] interface nsIIDBRequest : nsISupports { const unsigned short LOADING = 1; const unsigned short DONE = 2; readonly attribute unsigned short readyState; readonly attribute nsISupports source;
--- a/dom/indexedDB/nsIIDBTransaction.idl +++ b/dom/indexedDB/nsIIDBTransaction.idl @@ -45,17 +45,17 @@ interface nsIIDBRequest; interface nsIIDBDatabase; interface nsIDOMDOMStringList; /** * IDBDTransaction interface. See * http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#idl-def-IDBTransaction * for more information. */ -[scriptable, uuid(13e551a1-1a58-42ec-b0bd-7102ec0f64d6)] +[scriptable, builtinclass, uuid(13e551a1-1a58-42ec-b0bd-7102ec0f64d6)] interface nsIIDBTransaction : nsISupports { readonly attribute nsIIDBDatabase db; const unsigned short INITIAL = 0; const unsigned short LOADING = 1; const unsigned short COMMITTING = 2; const unsigned short DONE = 3;
--- a/dom/indexedDB/nsIIDBVersionChangeEvent.idl +++ b/dom/indexedDB/nsIIDBVersionChangeEvent.idl @@ -34,14 +34,14 @@ * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ #include "nsIDOMEvent.idl" -[scriptable, uuid(2c5159dc-7d71-4fc6-a3b3-884ed7586456)] +[scriptable, builtinclass, uuid(2c5159dc-7d71-4fc6-a3b3-884ed7586456)] interface nsIIDBVersionChangeEvent : nsIDOMEvent { readonly attribute unsigned long long oldVersion; readonly attribute unsigned long long newVersion; };
--- a/dom/indexedDB/nsIIndexedDatabaseManager.idl +++ b/dom/indexedDB/nsIIndexedDatabaseManager.idl @@ -46,17 +46,17 @@ interface nsIIndexedDatabaseUsageCallbac { /** * */ void onUsageResult(in nsIURI aURI, in unsigned long long aUsage); }; -[scriptable, uuid(415f5684-6c84-4a8b-b777-d01f5df778f2)] +[scriptable, builtinclass, uuid(415f5684-6c84-4a8b-b777-d01f5df778f2)] interface nsIIndexedDatabaseManager : nsISupports { /** * Schedules an asynchronous callback that will return the total amount of * disk space being used by databases for the given origin. * * @param aURI * The URI whose usage is being queried.
--- a/dom/indexedDB/test/test_object_identity.html +++ b/dom/indexedDB/test/test_object_identity.html @@ -26,17 +26,17 @@ let index1 = objectStore1.createIndex("bar", "key"); let index2 = objectStore2.index("bar"); ok(index1 === index2, "Got same indexes"); request.onsuccess = continueToNextStep; yield; - transaction = db.transaction("foo"); + transaction = db.transaction(db.objectStoreNames); let objectStore3 = transaction.objectStore("foo"); let objectStore4 = transaction.objectStore("foo"); ok(objectStore3 === objectStore4, "Got same objectStores"); ok(objectStore3 !== objectStore1, "Different objectStores"); ok(objectStore4 !== objectStore2, "Different objectStores");
--- a/js/xpconnect/public/nsAutoJSValHolder.h +++ b/js/xpconnect/public/nsAutoJSValHolder.h @@ -47,118 +47,125 @@ /** * Simple class that looks and acts like a jsval except that it unroots * itself automatically if Root() is ever called. Designed to be rooted on the * context or runtime (but not both!). */ class nsAutoJSValHolder { public: - - nsAutoJSValHolder() - : mRt(NULL) - , mVal(JSVAL_NULL) - , mHeld(JS_FALSE) + nsAutoJSValHolder() : mVal(JSVAL_NULL), mRt(nsnull) { // nothing to do } /** * Always release on destruction. */ virtual ~nsAutoJSValHolder() { Release(); } + nsAutoJSValHolder(const nsAutoJSValHolder& aOther) { + *this = aOther; + } + + nsAutoJSValHolder& operator=(const nsAutoJSValHolder& aOther) { + if (this != &aOther) { + if (aOther.IsHeld()) { + // XXX No error handling here... + this->Hold(aOther.mRt); + } + else { + this->Release(); + } + *this = static_cast<jsval>(aOther); + } + return *this; + } + /** * Hold by rooting on the context's runtime. */ - JSBool Hold(JSContext* aCx) { + bool Hold(JSContext* aCx) { return Hold(JS_GetRuntime(aCx)); } /** * Hold by rooting on the runtime. * Note that mVal may be JSVAL_NULL, which is not a problem. */ - JSBool Hold(JSRuntime* aRt) { - if (!mHeld) { - if (js_AddRootRT(aRt, &mVal, "nsAutoJSValHolder")) { - mRt = aRt; - mHeld = JS_TRUE; - } else { - Release(); // out of memory - } + bool Hold(JSRuntime* aRt) { + // Do we really care about different runtimes? + if (mRt && aRt != mRt) { + js_RemoveRoot(mRt, &mVal); + mRt = nsnull; } - return mHeld; + + if (!mRt && js_AddRootRT(aRt, &mVal, "nsAutoJSValHolder")) { + mRt = aRt; + } + + return !!mRt; } /** * Manually release, nullifying mVal, and mRt, but returning * the original jsval. */ jsval Release() { - NS_ASSERTION(!mHeld || mRt, "Bad!"); - jsval oldval = mVal; - if (mHeld) { + if (mRt) { js_RemoveRoot(mRt, &mVal); // infallible - mHeld = JS_FALSE; + mRt = nsnull; } mVal = JSVAL_NULL; - mRt = NULL; return oldval; } /** * Determine if Hold has been called. */ - JSBool IsHeld() { - return mHeld; + bool IsHeld() const { + return !!mRt; } /** * Explicit JSObject* conversion. */ JSObject* ToJSObject() const { return JSVAL_IS_OBJECT(mVal) ? JSVAL_TO_OBJECT(mVal) - : NULL; + : nsnull; } jsval* ToJSValPtr() { return &mVal; } /** * Pretend to be a jsval. */ operator jsval() const { return mVal; } nsAutoJSValHolder &operator=(JSObject* aOther) { -#ifdef DEBUG - if (aOther) { - NS_ASSERTION(mHeld, "Not rooted!"); - } -#endif return *this = OBJECT_TO_JSVAL(aOther); } nsAutoJSValHolder &operator=(jsval aOther) { #ifdef DEBUG - if (JSVAL_IS_OBJECT(aOther) && JSVAL_TO_OBJECT(aOther)) { - NS_ASSERTION(mHeld, "Not rooted!"); + if (JSVAL_IS_GCTHING(aOther) && !JSVAL_IS_NULL(aOther)) { + NS_ASSERTION(IsHeld(), "Not rooted!"); } #endif mVal = aOther; return *this; } private: + jsval mVal; JSRuntime* mRt; - jsval mVal; - JSBool mHeld; }; #endif /* __NSAUTOJSVALHOLDER_H__ */