Bug 692669 - 'IndexedDB: remove nsIVariant from IDB* interfaces'. r=sicking.

--HG--
extra : transplant_source : %84%E3%96%9F%C5%BA%D56%A4%94%83%9F%C3%F5%2B%01%7B%87%FB9
This commit is contained in:
Ben Turner 2011-11-03 08:57:30 -07:00
parent 86605677d2
commit 3e1f223457
28 changed files with 1047 additions and 1525 deletions

View File

@ -51,6 +51,13 @@
#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;

View File

@ -43,6 +43,7 @@
// Only meant to be included in IndexedDB source files, not exported.
#include "IndexedDatabase.h"
#include "Key.h"
#include "IDBObjectStore.h"
BEGIN_INDEXEDDB_NAMESPACE

View File

@ -39,8 +39,6 @@
#include "IDBCursor.h"
#include "nsIVariant.h"
#include "jscntxt.h"
#include "mozilla/storage.h"
#include "nsComponentManagerUtils.h"
@ -275,8 +273,10 @@ IDBCursor::CreateCommon(IDBRequest* aRequest,
IDBCursor::IDBCursor()
: mType(OBJECTSTORE),
mDirection(nsIIDBCursor::NEXT),
mCachedKey(JSVAL_VOID),
mCachedPrimaryKey(JSVAL_VOID),
mCachedValue(JSVAL_VOID),
mHaveCachedKey(false),
mHaveCachedPrimaryKey(false),
mHaveCachedValue(false),
mRooted(false),
@ -311,27 +311,35 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(IDBCursor)
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;
@ -378,43 +386,33 @@ IDBCursor::GetSource(nsISupports** 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;
}
@ -440,9 +438,9 @@ IDBCursor::GetPrimaryKey(JSContext* 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;
@ -498,7 +496,7 @@ IDBCursor::Continue(const jsval &aKey,
}
Key key;
nsresult rv = IDBObjectStore::GetKeyFromJSVal(aKey, aCx, key);
nsresult rv = key.SetFromJSVal(aCx, aKey);
NS_ENSURE_SUCCESS(rv, rv);
if (!key.IsUnset()) {
@ -588,7 +586,7 @@ IDBCursor::Update(const jsval& aValue,
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.
@ -606,7 +604,7 @@ IDBCursor::Update(const jsval& aValue,
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;
}
@ -619,7 +617,7 @@ IDBCursor::Update(const jsval& aValue,
}
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);
@ -646,10 +644,10 @@ IDBCursor::Delete(JSContext* aCx,
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);
@ -688,7 +686,7 @@ ContinueHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
}
else {
mKey = Key::UNSETKEY;
mKey.Unset();
}
return NS_OK;
@ -699,11 +697,12 @@ 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->mHaveCachedValue = false;
mCursor->mCachedValue = JSVAL_VOID;
mCursor->mHaveCachedKey = false;
mCursor->mHaveCachedPrimaryKey = false;
mCursor->mHaveCachedValue = false;
mCursor->mContinueCalled = false;
if (mKey.IsUnset()) {
@ -717,7 +716,7 @@ ContinueHelper::GetSuccessResult(JSContext* aCx,
// Set new values.
mCursor->mKey = mKey;
mCursor->mObjectKey = mObjectKey;
mCursor->mContinueToKey = Key::UNSETKEY;
mCursor->mContinueToKey.Unset();
mCursor->mCloneBuffer.swap(mCloneBuffer);
mCloneBuffer.clear();
@ -746,31 +745,15 @@ ContinueObjectStoreHelper::BindArgumentsToStatement(
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;
@ -781,20 +764,8 @@ 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);
@ -818,32 +789,14 @@ ContinueIndexHelper::BindArgumentsToStatement(mozIStorageStatement* aStatement)
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
@ -854,18 +807,8 @@ ContinueIndexHelper::BindArgumentsToStatement(mozIStorageStatement* aStatement)
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;
@ -875,42 +818,11 @@ nsresult
ContinueIndexHelper::GatherResultsFromStatement(
mozIStorageStatement* aStatement)
{
PRInt32 keyType;
nsresult rv = aStatement->GetTypeOfIndex(0, &keyType);
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
nsresult rv = mKey.SetFromStatement(aStatement, 0);
NS_ENSURE_SUCCESS(rv, rv);
NS_ASSERTION(keyType == mozIStorageStatement::VALUE_TYPE_INTEGER ||
keyType == mozIStorageStatement::VALUE_TYPE_TEXT,
"Bad key type!");
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;
}
@ -919,42 +831,11 @@ nsresult
ContinueIndexObjectHelper::GatherResultsFromStatement(
mozIStorageStatement* aStatement)
{
PRInt32 keyType;
nsresult rv = aStatement->GetTypeOfIndex(0, &keyType);
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
nsresult rv = mKey.SetFromStatement(aStatement, 0);
NS_ENSURE_SUCCESS(rv, rv);
NS_ASSERTION(keyType == mozIStorageStatement::VALUE_TYPE_INTEGER ||
keyType == mozIStorageStatement::VALUE_TYPE_TEXT,
"Bad key type!");
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);

View File

@ -42,6 +42,7 @@
#include "mozilla/dom/indexedDB/IndexedDatabase.h"
#include "mozilla/dom/indexedDB/IDBObjectStore.h"
#include "mozilla/dom/indexedDB/Key.h"
#include "nsIIDBCursorWithValue.h"
@ -150,15 +151,13 @@ protected:
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;
@ -169,6 +168,7 @@ protected:
JSAutoStructuredCloneBuffer mCloneBuffer;
Key mContinueToKey;
bool mHaveCachedKey;
bool mHaveCachedPrimaryKey;
bool mHaveCachedValue;
bool mRooted;

View File

@ -127,16 +127,6 @@ private:
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
{
@ -162,75 +152,6 @@ private:
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
@ -694,9 +615,8 @@ IDBDatabase::DeleteObjectStore(const nsAString& aName)
}
NS_IMETHODIMP
IDBDatabase::Transaction(nsIVariant* aStoreNames,
IDBDatabase::Transaction(const jsval& aStoreNames,
PRUint16 aMode,
PRUint32 aTimeout,
JSContext* aCx,
PRUint8 aOptionalArgCount,
nsIIDBTransaction** _retval)
@ -711,6 +631,15 @@ IDBDatabase::Transaction(nsIVariant* aStoreNames,
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) {
@ -721,110 +650,102 @@ IDBDatabase::Transaction(nsIVariant* aStoreNames,
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;
}
} break;
storesToOpen.SetCapacity(length);
case nsIDataType::VTYPE_ARRAY: {
nsTArray<nsString> names;
rv = ConvertVariantToStringArray(aStoreNames, names);
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 (!info->ContainsStoreName(name)) {
return NS_ERROR_DOM_INDEXEDDB_NOT_FOUND_ERR;
}
if (!storesToOpen.AppendElement(name)) {
NS_WARNING("Out of memory?");
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;
}
}
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));
storesToOpen.AppendElement(str);
}
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);
NS_Free(iid);
if (wrapper) {
nsISupports* wrappedObject = wrapper->Native();
NS_ENSURE_TRUE(wrappedObject, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
nsCOMPtr<nsIDOMDOMStringList> stringList(do_QueryInterface(supports));
if (!stringList) {
// We don't support anything other than nsIDOMDOMStringList.
return NS_ERROR_DOM_INDEXEDDB_NON_TRANSIENT_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);
PRUint32 stringCount;
rv = stringList->GetLength(&stringCount);
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
if (!length) {
return NS_ERROR_DOM_INVALID_ACCESS_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);
storesToOpen.SetCapacity(length);
if (!info->ContainsStoreName(name)) {
return NS_ERROR_DOM_INDEXEDDB_NOT_FOUND_ERR;
}
for (PRUint32 index = 0; index < length; index++) {
nsString* item = storesToOpen.AppendElement();
NS_ASSERTION(item, "This should never fail!");
if (!storesToOpen.AppendElement(name)) {
NS_WARNING("Out of memory?");
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
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!");
}
}
} break;
}
}
default:
return NS_ERROR_DOM_INDEXEDDB_NON_TRANSIENT_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;
}
storesToOpen.AppendElement(str);
}
// 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 =

View File

@ -52,6 +52,7 @@
#include "AsyncConnectionHelper.h"
#include "IDBCursor.h"
#include "IDBEvents.h"
#include "IDBKeyRange.h"
#include "IDBObjectStore.h"
#include "IDBTransaction.h"
#include "DatabaseInfo.h"
@ -167,14 +168,10 @@ 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);
@ -184,16 +181,14 @@ public:
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.
@ -210,14 +205,10 @@ 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()
@ -232,16 +223,14 @@ public:
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.
@ -271,7 +260,7 @@ 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!");
@ -297,12 +286,12 @@ IDBIndex::IDBIndex()
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)
@ -333,7 +322,7 @@ 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;
@ -342,7 +331,7 @@ IDBIndex::GetName(nsAString& aName)
NS_IMETHODIMP
IDBIndex::GetStoreName(nsAString& aStoreName)
{
NS_PRECONDITION(NS_IsMainThread(), "Wrong thread!");
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
return mObjectStore->GetName(aStoreName);
}
@ -350,7 +339,7 @@ IDBIndex::GetStoreName(nsAString& 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;
@ -359,7 +348,7 @@ IDBIndex::GetKeyPath(nsAString& aKeyPath)
NS_IMETHODIMP
IDBIndex::GetUnique(bool* aUnique)
{
NS_PRECONDITION(NS_IsMainThread(), "Wrong thread!");
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
*aUnique = mUnique;
return NS_OK;
@ -376,10 +365,11 @@ IDBIndex::GetObjectStore(nsIIDBObjectStore** aObjectStore)
}
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()) {
@ -387,19 +377,16 @@ IDBIndex::Get(nsIVariant* aKey,
}
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);
@ -408,10 +395,11 @@ IDBIndex::Get(nsIVariant* aKey,
}
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()) {
@ -419,15 +407,11 @@ IDBIndex::GetKey(nsIVariant* aKey,
}
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);
@ -442,8 +426,9 @@ IDBIndex::GetKey(nsIVariant* aKey,
}
NS_IMETHODIMP
IDBIndex::GetAll(nsIVariant* aKey,
IDBIndex::GetAll(const jsval& aKey,
PRUint32 aLimit,
JSContext* aCx,
PRUint8 aOptionalArgCount,
nsIIDBRequest** _retval)
{
@ -454,18 +439,9 @@ IDBIndex::GetAll(nsIVariant* aKey,
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) {
@ -478,7 +454,7 @@ IDBIndex::GetAll(nsIVariant* aKey,
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);
@ -486,8 +462,9 @@ IDBIndex::GetAll(nsIVariant* aKey,
}
NS_IMETHODIMP
IDBIndex::GetAllKeys(nsIVariant* aKey,
IDBIndex::GetAllKeys(const jsval& aKey,
PRUint32 aLimit,
JSContext* aCx,
PRUint8 aOptionalArgCount,
nsIIDBRequest** _retval)
{
@ -501,15 +478,8 @@ IDBIndex::GetAllKeys(nsIVariant* aKey,
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) {
@ -530,8 +500,9 @@ IDBIndex::GetAllKeys(nsIVariant* aKey,
}
NS_IMETHODIMP
IDBIndex::OpenCursor(nsIIDBKeyRange* aKeyRange,
IDBIndex::OpenCursor(const jsval& aKey,
PRUint16 aDirection,
JSContext* aCx,
PRUint8 aOptionalArgCount,
nsIIDBRequest** _retval)
{
@ -543,52 +514,30 @@ IDBIndex::OpenCursor(nsIIDBKeyRange* aKeyRange,
}
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);
nsRefPtr<IDBKeyRange> keyRange;
if (aOptionalArgCount) {
rv = IDBKeyRange::FromJSVal(aCx, aKey, getter_AddRefs(keyRange));
NS_ENSURE_SUCCESS(rv, rv);
rv = IDBObjectStore::GetKeyFromVariant(variant, lowerKey);
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->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(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);
@ -598,8 +547,9 @@ IDBIndex::OpenCursor(nsIIDBKeyRange* aKeyRange,
}
NS_IMETHODIMP
IDBIndex::OpenKeyCursor(nsIIDBKeyRange* aKeyRange,
IDBIndex::OpenKeyCursor(const jsval& aKey,
PRUint16 aDirection,
JSContext* aCx,
PRUint8 aOptionalArgCount,
nsIIDBRequest** _retval)
{
@ -611,52 +561,30 @@ IDBIndex::OpenKeyCursor(nsIIDBKeyRange* aKeyRange,
}
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);
nsRefPtr<IDBKeyRange> keyRange;
if (aOptionalArgCount) {
rv = IDBKeyRange::FromJSVal(aCx, aKey, getter_AddRefs(keyRange));
NS_ENSURE_SUCCESS(rv, rv);
rv = IDBObjectStore::GetKeyFromVariant(variant, lowerKey);
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->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<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);
@ -665,6 +593,22 @@ IDBIndex::OpenKeyCursor(nsIIDBKeyRange* aKeyRange,
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)
{
@ -683,42 +627,18 @@ GetKeyHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
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;
@ -729,7 +649,7 @@ GetKeyHelper::GetSuccessResult(JSContext* aCx,
jsval* aVal)
{
NS_ASSERTION(!mKey.IsUnset(), "Badness!");
return IDBObjectStore::GetJSValFromKey(mKey, aCx, aVal);
return mKey.ToJSVal(aCx, aVal);
}
nsresult
@ -750,18 +670,10 @@ GetHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
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);
@ -850,48 +762,21 @@ GetAllKeysHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
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);
@ -929,7 +814,7 @@ GetAllKeysHelper::GetSuccessResult(JSContext* aCx,
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;
@ -1014,16 +899,8 @@ GetAllHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
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;
@ -1096,13 +973,15 @@ OpenKeyCursorHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
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;
@ -1138,30 +1017,15 @@ OpenKeyCursorHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
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());
if (mKeyRange) {
if (!mKeyRange->Lower().IsUnset()) {
rv = mKeyRange->Lower().BindToStatement(stmt, lowerKeyName);
NS_ENSURE_SUCCESS(rv, rv);
}
else if (mLowerKey.IsInt()) {
rv = stmt->BindInt64ByName(lowerKeyName, mLowerKey.IntValue());
if (!mKeyRange->Upper().IsUnset()) {
rv = mKeyRange->Upper().BindToStatement(stmt, upperKeyName);
NS_ENSURE_SUCCESS(rv, rv);
}
else {
NS_NOTREACHED("Bad key!");
}
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
}
if (!mUpperKey.IsUnset()) {
if (mUpperKey.IsString()) {
rv = stmt->BindStringByName(upperKeyName, mUpperKey.StringValue());
}
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;
@ -1169,46 +1033,15 @@ OpenKeyCursorHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
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);
rv = mKey.SetFromStatement(stmt, 0);
NS_ENSURE_SUCCESS(rv, rv);
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 = 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 +
@ -1221,9 +1054,10 @@ OpenKeyCursorHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
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 +
@ -1236,9 +1070,10 @@ OpenKeyCursorHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
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 +
@ -1249,9 +1084,10 @@ OpenKeyCursorHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
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 +
@ -1264,9 +1100,10 @@ OpenKeyCursorHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
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 +
@ -1342,13 +1179,15 @@ OpenCursorHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
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;
@ -1391,30 +1230,15 @@ OpenCursorHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
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());
if (mKeyRange) {
if (!mKeyRange->Lower().IsUnset()) {
rv = mKeyRange->Lower().BindToStatement(stmt, lowerKeyName);
NS_ENSURE_SUCCESS(rv, rv);
}
else if (mLowerKey.IsInt()) {
rv = stmt->BindInt64ByName(lowerKeyName, mLowerKey.IntValue());
if (!mKeyRange->Upper().IsUnset()) {
rv = mKeyRange->Upper().BindToStatement(stmt, upperKeyName);
NS_ENSURE_SUCCESS(rv, rv);
}
else {
NS_NOTREACHED("Bad key!");
}
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
}
if (!mUpperKey.IsUnset()) {
if (mUpperKey.IsString()) {
rv = stmt->BindStringByName(upperKeyName, mUpperKey.StringValue());
}
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;
@ -1422,46 +1246,15 @@ OpenCursorHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
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);
rv = mKey.SetFromStatement(stmt, 0);
NS_ENSURE_SUCCESS(rv, rv);
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 = 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);
@ -1485,9 +1278,10 @@ OpenCursorHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
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 +
@ -1504,9 +1298,10 @@ OpenCursorHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
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 +
@ -1517,9 +1312,10 @@ OpenCursorHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
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 +
@ -1536,9 +1332,10 @@ OpenCursorHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
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 +

View File

@ -42,7 +42,7 @@
#include "nsIXPConnect.h"
#include "jscntxt.h"
#include "nsDOMClassInfoID.h"
#include "nsDOMClassInfo.h"
#include "nsJSUtils.h"
#include "nsThreadUtils.h"
#include "nsContentUtils.h"
@ -54,54 +54,7 @@ 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)
@ -115,24 +68,73 @@ ReturnKeyRange(JSContext* aCx,
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
@ -142,21 +144,18 @@ MakeOnlyKeyRange(JSContext* aCx,
{
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
@ -166,27 +165,19 @@ MakeLowerBoundKeyRange(JSContext* aCx,
{
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
@ -196,27 +187,19 @@ MakeUpperBoundKeyRange(JSContext* aCx,
{
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
@ -226,36 +209,29 @@ MakeBoundKeyRange(JSContext* aCx,
{
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[] = {
@ -285,49 +261,129 @@ IDBKeyRange::DefineConstructors(JSContext* aCx,
}
// 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;
return keyRange.forget();
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);
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_INTERFACE_MAP_BEGIN(IDBKeyRange)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIIDBKeyRange)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(IDBKeyRange)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
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;
}
@ -336,7 +392,7 @@ IDBKeyRange::GetLowerOpen(bool* aLowerOpen)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
*aLowerOpen = mLowerOpen ? true : false;
*aLowerOpen = mLowerOpen;
return NS_OK;
}
@ -346,6 +402,6 @@ IDBKeyRange::GetUpperOpen(bool* aUpperOpen)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
*aUpperOpen = mUpperOpen ? true : false;
*aUpperOpen = mUpperOpen;
return NS_OK;
}

View File

@ -41,38 +41,78 @@
#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);
protected:
IDBKeyRange()
: mLowerOpen(false), mUpperOpen(false)
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() { }
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

View File

@ -40,9 +40,7 @@
#include "IDBObjectStore.h"
#include "nsIJSContextStack.h"
#include "nsIVariant.h"
#include "jscntxt.h"
#include "jsclone.h"
#include "mozilla/storage.h"
#include "nsContentUtils.h"
@ -64,9 +62,6 @@ 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:
@ -146,7 +141,7 @@ public:
protected:
// In-params.
nsRefPtr<IDBObjectStore> mObjectStore;
const Key mKey;
Key mKey;
private:
// Out-params.
@ -196,14 +191,10 @@ 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()
@ -218,6 +209,7 @@ public:
void ReleaseMainThreadObjects()
{
mObjectStore = nsnull;
mKeyRange = nsnull;
IDBObjectStore::ClearStructuredCloneBuffer(mCloneBuffer);
AsyncConnectionHelper::ReleaseMainThreadObjects();
}
@ -225,10 +217,7 @@ public:
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.
@ -273,8 +262,7 @@ private:
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
{
@ -316,14 +304,10 @@ 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()
@ -340,6 +324,7 @@ public:
void ReleaseMainThreadObjects()
{
mObjectStore = nsnull;
mKeyRange = nsnull;
for (PRUint32 index = 0; index < mCloneBuffers.Length(); index++) {
IDBObjectStore::ClearStructuredCloneBuffer(mCloneBuffers[index]);
}
@ -349,10 +334,7 @@ public:
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:
@ -414,7 +396,7 @@ GetKeyFromObject(JSContext* aCx,
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;
@ -489,107 +471,6 @@ IDBObjectStore::Create(IDBTransaction* aTransaction,
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,
@ -614,7 +495,7 @@ IDBObjectStore::GetKeyPathValueFromStructuredData(const PRUint8* aData,
if (JSVAL_IS_PRIMITIVE(clone)) {
// This isn't an object, so just leave the key unset.
aValue = Key::UNSETKEY;
aValue.Unset();
return NS_OK;
}
@ -628,11 +509,11 @@ IDBObjectStore::GetKeyPathValueFromStructuredData(const PRUint8* aData,
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;
@ -669,7 +550,7 @@ IDBObjectStore::GetIndexUpdateInfo(ObjectStoreInfo* aObjectStoreInfo,
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;
@ -728,17 +609,7 @@ IDBObjectStore::UpdateIndexes(IDBTransaction* aTransaction,
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;
@ -774,35 +645,15 @@ IDBObjectStore::UpdateIndexes(IDBTransaction* aTransaction,
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();
@ -901,7 +752,7 @@ SwapBytes(PRUint64 u)
((u & 0x00ff000000000000LLU) >> 40) |
((u & 0xff00000000000000LLU) >> 56);
#else
return u;
return jsdouble(u);
#endif
}
@ -910,8 +761,7 @@ 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
@ -920,7 +770,7 @@ IDBObjectStore::ModifyValueForNewKey(JSAutoStructuredCloneBuffer& aBuffer,
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;
@ -959,7 +809,7 @@ IDBObjectStore::GetAddInfo(JSContext* 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 {
@ -1173,7 +1023,8 @@ IDBObjectStore::GetIndexNames(nsIDOMDOMStringList** aIndexNames)
}
NS_IMETHODIMP
IDBObjectStore::Get(nsIVariant* aKey,
IDBObjectStore::Get(const jsval& aKey,
JSContext* aCx,
nsIIDBRequest** _retval)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
@ -1183,32 +1034,10 @@ IDBObjectStore::Get(nsIVariant* aKey,
}
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()) {
@ -1228,8 +1057,9 @@ IDBObjectStore::Get(nsIVariant* aKey,
}
NS_IMETHODIMP
IDBObjectStore::GetAll(nsIIDBKeyRange* aKeyRange,
IDBObjectStore::GetAll(const jsval& aKey,
PRUint32 aLimit,
JSContext* aCx,
PRUint8 aOptionalArgCount,
nsIIDBRequest** _retval)
{
@ -1239,45 +1069,23 @@ IDBObjectStore::GetAll(nsIIDBKeyRange* aKeyRange,
return NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR;
}
if (aOptionalArgCount < 2) {
aLimit = PR_UINT32_MAX;
nsresult rv;
nsRefPtr<IDBKeyRange> keyRange;
if (aOptionalArgCount) {
rv = IDBKeyRange::FromJSVal(aCx, aKey, getter_AddRefs(keyRange));
NS_ENSURE_SUCCESS(rv, rv);
}
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);
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(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);
@ -1326,7 +1134,7 @@ IDBObjectStore::Delete(const jsval& aKey,
}
Key key;
nsresult rv = GetKeyFromJSVal(aKey, aCx, key);
nsresult rv = key.SetFromJSVal(aCx, aKey);
if (NS_FAILED(rv)) {
return rv;
}
@ -1374,8 +1182,9 @@ IDBObjectStore::Clear(nsIIDBRequest** _retval)
}
NS_IMETHODIMP
IDBObjectStore::OpenCursor(nsIIDBKeyRange* aKeyRange,
IDBObjectStore::OpenCursor(const jsval& aKey,
PRUint16 aDirection,
JSContext* aCx,
PRUint8 aOptionalArgCount,
nsIIDBRequest** _retval)
{
@ -1386,52 +1195,30 @@ IDBObjectStore::OpenCursor(nsIIDBKeyRange* aKeyRange,
}
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);
nsRefPtr<IDBKeyRange> keyRange;
if (aOptionalArgCount) {
rv = IDBKeyRange::FromJSVal(aCx, aKey, getter_AddRefs(keyRange));
NS_ENSURE_SUCCESS(rv, rv);
rv = IDBObjectStore::GetKeyFromVariant(variant, lowerKey);
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->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);
@ -1673,6 +1460,21 @@ IDBObjectStore::DeleteIndex(const nsAString& aName)
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)
{
@ -1708,18 +1510,8 @@ AddHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
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);
@ -1744,16 +1536,8 @@ AddHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
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());
@ -1780,16 +1564,8 @@ AddHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
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);
@ -1806,16 +1582,20 @@ AddHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
// 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
@ -1839,8 +1619,8 @@ AddHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
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();
@ -1856,7 +1636,7 @@ AddHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
// 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);
@ -1877,7 +1657,7 @@ AddHelper::GetSuccessResult(JSContext* aCx,
mCloneBuffer.clear();
return IDBObjectStore::GetJSValFromKey(mKey, aCx, aVal);
return mKey.ToJSVal(aCx, aVal);
}
nsresult
@ -1897,18 +1677,8 @@ GetHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
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;
@ -1953,18 +1723,8 @@ DeleteHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
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);
@ -1977,7 +1737,7 @@ DeleteHelper::GetSuccessResult(JSContext* aCx,
jsval* aVal)
{
NS_ASSERTION(!mKey.IsUnset(), "Badness!");
return IDBObjectStore::GetJSValFromKey(mKey, aCx, aVal);
return mKey.ToJSVal(aCx, aVal);
}
nsresult
@ -2031,13 +1791,15 @@ OpenCursorHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
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;
@ -2070,30 +1832,15 @@ OpenCursorHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
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());
if (mKeyRange) {
if (!mKeyRange->Lower().IsUnset()) {
rv = mKeyRange->Lower().BindToStatement(stmt, lowerKeyName);
NS_ENSURE_SUCCESS(rv, rv);
}
else if (mLowerKey.IsInt()) {
rv = stmt->BindInt64ByName(lowerKeyName, mLowerKey.IntValue());
if (!mKeyRange->Upper().IsUnset()) {
rv = mKeyRange->Upper().BindToStatement(stmt, upperKeyName);
NS_ENSURE_SUCCESS(rv, rv);
}
else {
NS_NOTREACHED("Bad key!");
}
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
}
if (!mUpperKey.IsUnset()) {
if (mUpperKey.IsString()) {
rv = stmt->BindStringByName(upperKeyName, mUpperKey.StringValue());
}
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;
@ -2101,24 +1848,12 @@ OpenCursorHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
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);
@ -2138,12 +1873,13 @@ OpenCursorHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
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;
@ -2152,12 +1888,13 @@ OpenCursorHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
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;
@ -2392,24 +2129,13 @@ CreateIndexHelper::InsertDataFromObjectStore(mozIStorageConnection* aConnection)
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);
Key key;
rv = key.SetFromStatement(stmt, 2);
NS_ENSURE_SUCCESS(rv, rv);
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);
rv =
key.BindToStatement(insertStmt, NS_LITERAL_CSTRING("object_data_key"));
NS_ENSURE_SUCCESS(rv, rv);
}
const PRUint8* data;
@ -2432,24 +2158,16 @@ CreateIndexHelper::InsertDataFromObjectStore(mozIStorageConnection* aConnection)
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);
@ -2502,26 +2220,28 @@ GetAllHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
NS_NAMED_LITERAL_CSTRING(upperKeyName, "upper_key");
nsCAutoString keyRangeClause;
if (!mLowerKey.IsUnset()) {
keyRangeClause = NS_LITERAL_CSTRING(" AND ") + keyColumn;
if (mLowerOpen) {
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);
}
else {
keyRangeClause.AppendLiteral(" >= :");
}
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;
@ -2535,10 +2255,7 @@ GetAllHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
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);
@ -2548,30 +2265,15 @@ GetAllHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
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());
if (mKeyRange) {
if (!mKeyRange->Lower().IsUnset()) {
rv = mKeyRange->Lower().BindToStatement(stmt, lowerKeyName);
NS_ENSURE_SUCCESS(rv, rv);
}
else if (mLowerKey.IsInt()) {
rv = stmt->BindInt64ByName(lowerKeyName, mLowerKey.IntValue());
if (!mKeyRange->Upper().IsUnset()) {
rv = mKeyRange->Upper().BindToStatement(stmt, upperKeyName);
NS_ENSURE_SUCCESS(rv, rv);
}
else {
NS_NOTREACHED("Bad key!");
}
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
}
if (!mUpperKey.IsUnset()) {
if (mUpperKey.IsString()) {
rv = stmt->BindStringByName(upperKeyName, mUpperKey.StringValue());
}
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;

View File

@ -42,7 +42,6 @@
#include "mozilla/dom/indexedDB/IndexedDatabase.h"
#include "mozilla/dom/indexedDB/IDBTransaction.h"
#include "mozilla/dom/indexedDB/Key.h"
#include "nsIIDBObjectStore.h"
#include "nsIIDBTransaction.h"
@ -55,6 +54,7 @@ class nsPIDOMWindow;
BEGIN_INDEXEDDB_NAMESPACE
class AsyncConnectionHelper;
class Key;
struct ObjectStoreInfo;
struct IndexInfo;
@ -72,20 +72,6 @@ public:
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,

View File

@ -41,7 +41,6 @@
#include "IDBRequest.h"
#include "nsIScriptContext.h"
#include "nsIVariant.h"
#include "nsComponentManagerUtils.h"
#include "nsDOMClassInfoID.h"

View File

@ -42,70 +42,45 @@
#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!");
@ -121,30 +96,24 @@ public:
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) {
case KEYTYPE_STRING: {
if (aOther.mType == KEYTYPE_INTEGER) {
return false;
}
return true;
NS_ASSERTION(aOther.mType == KEYTYPE_STRING, "Unknown type!");
return ToString() < aOther.ToString();
}
case STRINGKEY:
if (aOther.mType == UNSETKEY ||
aOther.mType == INTKEY) {
return false;
}
NS_ASSERTION(aOther.mType == STRINGKEY, "Unknown type!");
return mString < aOther.mString;
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!");
@ -167,42 +136,188 @@ public:
return (*this == aOther || !(*this < aOther));
}
bool IsUnset() const { return mType == UNSETKEY; }
bool IsString() const { return mType == STRINGKEY; }
bool IsInt() const { return mType == INTKEY; }
const nsString& StringValue() const {
NS_ASSERTION(IsString(), "Wrong type!");
return mString;
void
Unset()
{
mType = KEYTYPE_VOID;
mStringKey.SetIsVoid(true);
mIntKey = 0;
}
PRInt64 IntValue() const {
NS_ASSERTION(IsInt(), "Wrong type!");
return mInt;
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;
}
nsAString& ToString() {
mType = STRINGKEY;
mInt = 0;
return mString;
nsresult SetFromInteger(PRInt64 aInt)
{
mType = KEYTYPE_INTEGER;
mStringKey.SetIsVoid(true);
mIntKey = aInt;
return NS_OK;
}
PRInt64* ToIntPtr() {
mType = INTKEY;
mString.Truncate();
return &mInt;
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;
}
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;
}
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);
}
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

View File

@ -93,6 +93,7 @@ LOCAL_INCLUDES = \
-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

View File

@ -40,14 +40,13 @@
#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;
@ -58,7 +57,8 @@ interface nsIIDBCursor : nsISupports
readonly attribute nsISupports source;
readonly attribute nsIVariant key;
[implicit_jscontext]
readonly attribute jsval key;
[implicit_jscontext]
readonly attribute jsval primaryKey;

View File

@ -39,16 +39,12 @@
#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]

View File

@ -39,7 +39,6 @@
#include "nsISupports.idl"
interface nsIVariant;
interface nsIIDBObjectStore;
interface nsIIDBRequest;
interface nsIIDBTransaction;
@ -51,7 +50,7 @@ interface nsIDOMEventListener;
* 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;
@ -78,9 +77,8 @@ interface nsIIDBDatabase : nsISupports
[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();

View File

@ -39,7 +39,7 @@
#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;

View File

@ -42,14 +42,13 @@
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]

View File

@ -39,17 +39,15 @@
#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;
@ -62,29 +60,38 @@ interface nsIIDBIndex : nsISupports
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);
*/
};

View File

@ -39,18 +39,20 @@
#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;
};

View File

@ -43,7 +43,6 @@ interface nsIIDBIndex;
interface nsIIDBKeyRange;
interface nsIIDBRequest;
interface nsIIDBTransaction;
interface nsIVariant;
interface nsIDOMDOMStringList;
/**
@ -51,7 +50,7 @@ interface nsIDOMDOMStringList;
* 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;
@ -63,13 +62,14 @@ interface nsIIDBObjectStore : nsISupports
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
@ -95,9 +95,9 @@ interface nsIIDBObjectStore : nsISupports
// 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);
/**
@ -118,4 +118,11 @@ interface nsIIDBObjectStore : nsISupports
void
deleteIndex(in AString name);
/*
// Accepts null, a key value, or a nsIIDBKeyRange object.
[implicit_jscontext, optional_argc]
nsIIDBRequest
count([optional] in jsval key);
*/
};

View File

@ -47,7 +47,7 @@ interface nsIDOMEventListener;
* 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;

View File

@ -48,7 +48,7 @@ interface nsIIDBTransaction;
* 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;

View File

@ -50,7 +50,7 @@ interface nsIDOMDOMStringList;
* 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;

View File

@ -39,7 +39,7 @@
#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;

View File

@ -51,7 +51,7 @@ interface nsIIndexedDatabaseUsageCallback : nsISupports
in unsigned long long aUsage);
};
[scriptable, uuid(415f5684-6c84-4a8b-b777-d01f5df778f2)]
[scriptable, builtinclass, uuid(415f5684-6c84-4a8b-b777-d01f5df778f2)]
interface nsIIndexedDatabaseManager : nsISupports
{
/**

View File

@ -31,7 +31,7 @@
request.onsuccess = continueToNextStep;
yield;
transaction = db.transaction("foo");
transaction = db.transaction(db.objectStoreNames);
let objectStore3 = transaction.objectStore("foo");
let objectStore4 = transaction.objectStore("foo");

View File

@ -52,11 +52,7 @@
class nsAutoJSValHolder
{
public:
nsAutoJSValHolder()
: mRt(NULL)
, mVal(JSVAL_NULL)
, mHeld(JS_FALSE)
nsAutoJSValHolder() : mVal(JSVAL_NULL), mRt(nsnull)
{
// nothing to do
}
@ -68,10 +64,28 @@ public:
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));
}
@ -79,16 +93,18 @@ public:
* 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;
}
/**
@ -96,17 +112,14 @@ public:
* 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;
}
@ -114,8 +127,8 @@ public:
/**
* Determine if Hold has been called.
*/
JSBool IsHeld() {
return mHeld;
bool IsHeld() const {
return !!mRt;
}
/**
@ -124,7 +137,7 @@ public:
JSObject* ToJSObject() const {
return JSVAL_IS_OBJECT(mVal)
? JSVAL_TO_OBJECT(mVal)
: NULL;
: nsnull;
}
jsval* ToJSValPtr() {
@ -137,18 +150,13 @@ public:
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;
@ -156,9 +164,8 @@ public:
}
private:
JSRuntime* mRt;
jsval mVal;
JSBool mHeld;
JSRuntime* mRt;
};
#endif /* __NSAUTOJSVALHOLDER_H__ */