зеркало из https://github.com/mozilla/pjs.git
Backout eb32aca6d54d, b5c0bfd03fcf and 5675bf2c7930 (bug 692669 and bug 692669) for failing to build on all platforms
This commit is contained in:
Родитель
f8c31947fd
Коммит
f643cfb775
|
@ -51,13 +51,6 @@
|
|||
#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;
|
||||
|
|
|
@ -43,7 +43,6 @@
|
|||
// Only meant to be included in IndexedDB source files, not exported.
|
||||
#include "IndexedDatabase.h"
|
||||
|
||||
#include "Key.h"
|
||||
#include "IDBObjectStore.h"
|
||||
|
||||
BEGIN_INDEXEDDB_NAMESPACE
|
||||
|
|
|
@ -39,6 +39,8 @@
|
|||
|
||||
#include "IDBCursor.h"
|
||||
|
||||
#include "nsIVariant.h"
|
||||
|
||||
#include "jscntxt.h"
|
||||
#include "mozilla/storage.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
|
@ -273,10 +275,8 @@ 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,35 +311,27 @@ 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->mCachedKey)) {
|
||||
void *gcThing = JSVAL_TO_GCTHING(tmp->mCachedKey);
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_CALLBACK(gcThing, "mCachedKey")
|
||||
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->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;
|
||||
|
@ -386,33 +378,43 @@ IDBCursor::GetSource(nsISupports** aSource)
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
IDBCursor::GetKey(JSContext* aCx,
|
||||
jsval* aKey)
|
||||
IDBCursor::GetKey(nsIVariant** aKey)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
NS_ASSERTION(!mKey.IsUnset() || !mHaveValue, "Bad key!");
|
||||
if (!mCachedKey) {
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIWritableVariant> variant =
|
||||
do_CreateInstance(NS_VARIANT_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||
|
||||
if (!mHaveValue) {
|
||||
*aKey = JSVAL_VOID;
|
||||
return NS_OK;
|
||||
}
|
||||
NS_ASSERTION(!mKey.IsUnset() || !mHaveValue, "Bad key!");
|
||||
|
||||
if (!mHaveCachedKey) {
|
||||
if (!mRooted) {
|
||||
NS_HOLD_JS_OBJECTS(this, IDBCursor);
|
||||
mRooted = true;
|
||||
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);
|
||||
|
||||
JSAutoRequest ar(aCx);
|
||||
rv = variant->SetWritable(false);
|
||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||
|
||||
nsresult rv = mKey.ToJSVal(aCx, &mCachedKey);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsIWritableVariant* result;
|
||||
variant.forget(&result);
|
||||
|
||||
mHaveCachedKey = true;
|
||||
mCachedKey = dont_AddRef(static_cast<nsIVariant*>(result));
|
||||
}
|
||||
|
||||
*aKey = mCachedKey;
|
||||
nsCOMPtr<nsIVariant> result(mCachedKey);
|
||||
result.forget(aKey);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -438,9 +440,9 @@ IDBCursor::GetPrimaryKey(JSContext* aCx,
|
|||
NS_ASSERTION(mType == OBJECTSTORE ? !mKey.IsUnset() :
|
||||
!mObjectKey.IsUnset(), "Bad key!");
|
||||
|
||||
const Key& key = mType == OBJECTSTORE ? mKey : mObjectKey;
|
||||
|
||||
nsresult rv = key.ToJSVal(aCx, &mCachedPrimaryKey);
|
||||
nsresult rv =
|
||||
IDBObjectStore::GetJSValFromKey(mType == OBJECTSTORE ? mKey : mObjectKey,
|
||||
aCx, &mCachedPrimaryKey);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mHaveCachedPrimaryKey = true;
|
||||
|
@ -496,7 +498,7 @@ IDBCursor::Continue(const jsval &aKey,
|
|||
}
|
||||
|
||||
Key key;
|
||||
nsresult rv = key.SetFromJSVal(aCx, aKey);
|
||||
nsresult rv = IDBObjectStore::GetKeyFromJSVal(aKey, aCx, key);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!key.IsUnset()) {
|
||||
|
@ -586,7 +588,7 @@ IDBCursor::Update(const jsval& aValue,
|
|||
|
||||
JSAutoRequest ar(aCx);
|
||||
|
||||
Key& objectKey = (mType == OBJECTSTORE) ? mKey : mObjectKey;
|
||||
const Key& objectKey = (mType == OBJECTSTORE) ? mKey : mObjectKey;
|
||||
|
||||
if (!mObjectStore->KeyPath().IsEmpty()) {
|
||||
// This has to be an object.
|
||||
|
@ -604,7 +606,7 @@ IDBCursor::Update(const jsval& aValue,
|
|||
NS_ENSURE_TRUE(ok, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||
|
||||
Key key;
|
||||
rv = key.SetFromJSVal(aCx, prop);
|
||||
rv = IDBObjectStore::GetKeyFromJSVal(prop, aCx, key);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
@ -617,7 +619,7 @@ IDBCursor::Update(const jsval& aValue,
|
|||
}
|
||||
|
||||
jsval keyVal;
|
||||
rv = objectKey.ToJSVal(aCx, &keyVal);
|
||||
rv = IDBObjectStore::GetJSValFromKey(objectKey, aCx, &keyVal);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return mObjectStore->Put(aValue, keyVal, aCx, 1, _retval);
|
||||
|
@ -644,10 +646,10 @@ IDBCursor::Delete(JSContext* aCx,
|
|||
NS_ASSERTION(mObjectStore, "This cannot be null!");
|
||||
NS_ASSERTION(!mKey.IsUnset() , "Bad key!");
|
||||
|
||||
Key& objectKey = (mType == OBJECTSTORE) ? mKey : mObjectKey;
|
||||
const Key& objectKey = (mType == OBJECTSTORE) ? mKey : mObjectKey;
|
||||
|
||||
jsval key;
|
||||
nsresult rv = objectKey.ToJSVal(aCx, &key);
|
||||
nsresult rv = IDBObjectStore::GetJSValFromKey(objectKey, aCx, &key);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return mObjectStore->Delete(key, aCx, _retval);
|
||||
|
@ -686,7 +688,7 @@ ContinueHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
|
|||
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||
}
|
||||
else {
|
||||
mKey.Unset();
|
||||
mKey = Key::UNSETKEY;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
@ -697,12 +699,11 @@ ContinueHelper::GetSuccessResult(JSContext* aCx,
|
|||
jsval* aVal)
|
||||
{
|
||||
// Remove cached stuff from last time.
|
||||
mCursor->mCachedKey = JSVAL_VOID;
|
||||
mCursor->mCachedPrimaryKey = JSVAL_VOID;
|
||||
mCursor->mCachedKey = nsnull;
|
||||
mCursor->mCachedValue = JSVAL_VOID;
|
||||
mCursor->mHaveCachedKey = false;
|
||||
mCursor->mHaveCachedPrimaryKey = false;
|
||||
mCursor->mCachedPrimaryKey = JSVAL_VOID;
|
||||
mCursor->mHaveCachedValue = false;
|
||||
mCursor->mHaveCachedPrimaryKey = false;
|
||||
mCursor->mContinueCalled = false;
|
||||
|
||||
if (mKey.IsUnset()) {
|
||||
|
@ -716,7 +717,7 @@ ContinueHelper::GetSuccessResult(JSContext* aCx,
|
|||
// Set new values.
|
||||
mCursor->mKey = mKey;
|
||||
mCursor->mObjectKey = mObjectKey;
|
||||
mCursor->mContinueToKey.Unset();
|
||||
mCursor->mContinueToKey = Key::UNSETKEY;
|
||||
|
||||
mCursor->mCloneBuffer.swap(mCloneBuffer);
|
||||
mCloneBuffer.clear();
|
||||
|
@ -745,15 +746,31 @@ ContinueObjectStoreHelper::BindArgumentsToStatement(
|
|||
mCursor->mKey :
|
||||
mCursor->mContinueToKey;
|
||||
|
||||
rv = currentKey.BindToStatement(aStatement, currentKeyName);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
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);
|
||||
|
||||
// Bind range key if it is specified.
|
||||
const Key& rangeKey = mCursor->mRangeKey;
|
||||
|
||||
if (!rangeKey.IsUnset()) {
|
||||
rv = rangeKey.BindToStatement(aStatement, rangeKeyName);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
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);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
@ -764,8 +781,20 @@ ContinueObjectStoreHelper::GatherResultsFromStatement(
|
|||
mozIStorageStatement* aStatement)
|
||||
{
|
||||
// Figure out what kind of key we have next.
|
||||
nsresult rv = mKey.SetFromStatement(aStatement, 0);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
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!");
|
||||
}
|
||||
|
||||
rv = IDBObjectStore::GetStructuredCloneDataFromStatement(aStatement, 1,
|
||||
mCloneBuffer);
|
||||
|
@ -789,14 +818,32 @@ ContinueIndexHelper::BindArgumentsToStatement(mozIStorageStatement* aStatement)
|
|||
mCursor->mKey :
|
||||
mCursor->mContinueToKey;
|
||||
|
||||
rv = currentKey.BindToStatement(aStatement, currentKeyName);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
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);
|
||||
|
||||
// Bind range key if it is specified.
|
||||
if (!mCursor->mRangeKey.IsUnset()) {
|
||||
NS_NAMED_LITERAL_CSTRING(rangeKeyName, "range_key");
|
||||
rv = mCursor->mRangeKey.BindToStatement(aStatement, rangeKeyName);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
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);
|
||||
}
|
||||
|
||||
// Bind object key if duplicates are allowed and we're not continuing to a
|
||||
|
@ -807,8 +854,18 @@ ContinueIndexHelper::BindArgumentsToStatement(mozIStorageStatement* aStatement)
|
|||
NS_ASSERTION(!mCursor->mObjectKey.IsUnset(), "Bad key!");
|
||||
|
||||
NS_NAMED_LITERAL_CSTRING(objectKeyName, "object_key");
|
||||
rv = mCursor->mObjectKey.BindToStatement(aStatement, objectKeyName);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
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);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
@ -818,11 +875,42 @@ nsresult
|
|||
ContinueIndexHelper::GatherResultsFromStatement(
|
||||
mozIStorageStatement* aStatement)
|
||||
{
|
||||
nsresult rv = mKey.SetFromStatement(aStatement, 0);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
PRInt32 keyType;
|
||||
nsresult rv = aStatement->GetTypeOfIndex(0, &keyType);
|
||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||
|
||||
rv = mObjectKey.SetFromStatement(aStatement, 1);
|
||||
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!");
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -831,11 +919,42 @@ nsresult
|
|||
ContinueIndexObjectHelper::GatherResultsFromStatement(
|
||||
mozIStorageStatement* aStatement)
|
||||
{
|
||||
nsresult rv = mKey.SetFromStatement(aStatement, 0);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
PRInt32 keyType;
|
||||
nsresult rv = aStatement->GetTypeOfIndex(0, &keyType);
|
||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||
|
||||
rv = mObjectKey.SetFromStatement(aStatement, 1);
|
||||
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 = IDBObjectStore::GetStructuredCloneDataFromStatement(aStatement, 2,
|
||||
mCloneBuffer);
|
||||
|
|
|
@ -42,7 +42,6 @@
|
|||
|
||||
#include "mozilla/dom/indexedDB/IndexedDatabase.h"
|
||||
#include "mozilla/dom/indexedDB/IDBObjectStore.h"
|
||||
#include "mozilla/dom/indexedDB/Key.h"
|
||||
|
||||
#include "nsIIDBCursorWithValue.h"
|
||||
|
||||
|
@ -151,13 +150,15 @@ 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;
|
||||
|
||||
|
@ -168,7 +169,6 @@ protected:
|
|||
JSAutoStructuredCloneBuffer mCloneBuffer;
|
||||
Key mContinueToKey;
|
||||
|
||||
bool mHaveCachedKey;
|
||||
bool mHaveCachedPrimaryKey;
|
||||
bool mHaveCachedValue;
|
||||
bool mRooted;
|
||||
|
|
|
@ -127,6 +127,16 @@ 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
|
||||
{
|
||||
|
@ -152,6 +162,75 @@ 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
|
||||
|
@ -615,8 +694,9 @@ IDBDatabase::DeleteObjectStore(const nsAString& aName)
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
IDBDatabase::Transaction(const jsval& aStoreNames,
|
||||
IDBDatabase::Transaction(nsIVariant* aStoreNames,
|
||||
PRUint16 aMode,
|
||||
PRUint32 aTimeout,
|
||||
JSContext* aCx,
|
||||
PRUint8 aOptionalArgCount,
|
||||
nsIIDBTransaction** _retval)
|
||||
|
@ -631,15 +711,6 @@ IDBDatabase::Transaction(const jsval& 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) {
|
||||
|
@ -650,102 +721,110 @@ IDBDatabase::Transaction(const jsval& aStoreNames,
|
|||
aMode = nsIIDBTransaction::READ_ONLY;
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
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;
|
||||
}
|
||||
|
||||
nsTArray<nsString> storesToOpen;
|
||||
|
||||
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)) {
|
||||
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?");
|
||||
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
||||
}
|
||||
} break;
|
||||
|
||||
if (!length) {
|
||||
return NS_ERROR_DOM_INVALID_ACCESS_ERR;
|
||||
}
|
||||
|
||||
storesToOpen.SetCapacity(length);
|
||||
|
||||
for (jsuint index = 0; index < length; index++) {
|
||||
jsval val;
|
||||
JSString* jsstr;
|
||||
nsDependentJSString str;
|
||||
if (!JS_GetElement(aCx, obj, index, &val) ||
|
||||
!(jsstr = JS_ValueToString(aCx, val)) ||
|
||||
!str.init(aCx, jsstr)) {
|
||||
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
||||
}
|
||||
|
||||
storesToOpen.AppendElement(str);
|
||||
}
|
||||
|
||||
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));
|
||||
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 (wrapper) {
|
||||
nsISupports* wrappedObject = wrapper->Native();
|
||||
NS_ENSURE_TRUE(wrappedObject, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||
if (!info->ContainsStoreName(name)) {
|
||||
return NS_ERROR_DOM_INDEXEDDB_NOT_FOUND_ERR;
|
||||
}
|
||||
|
||||
// We only accept DOMStringList.
|
||||
nsCOMPtr<nsIDOMDOMStringList> list = do_QueryInterface(wrappedObject);
|
||||
if (list) {
|
||||
PRUint32 length;
|
||||
rv = list->GetLength(&length);
|
||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||
if (!storesToOpen.AppendElement(name)) {
|
||||
NS_WARNING("Out of memory?");
|
||||
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
||||
}
|
||||
} break;
|
||||
|
||||
if (!length) {
|
||||
return NS_ERROR_DOM_INVALID_ACCESS_ERR;
|
||||
}
|
||||
case nsIDataType::VTYPE_ARRAY: {
|
||||
nsTArray<nsString> names;
|
||||
rv = ConvertVariantToStringArray(aStoreNames, names);
|
||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||
|
||||
storesToOpen.SetCapacity(length);
|
||||
PRUint32 nameCount = names.Length();
|
||||
for (PRUint32 nameIndex = 0; nameIndex < nameCount; nameIndex++) {
|
||||
nsString& name = names[nameIndex];
|
||||
|
||||
for (PRUint32 index = 0; index < length; index++) {
|
||||
nsString* item = storesToOpen.AppendElement();
|
||||
NS_ASSERTION(item, "This should never fail!");
|
||||
if (!info->ContainsStoreName(name)) {
|
||||
return NS_ERROR_DOM_INDEXEDDB_NOT_FOUND_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!");
|
||||
if (!storesToOpen.AppendElement(name)) {
|
||||
NS_WARNING("Out of memory?");
|
||||
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
NS_ASSERTION(nameCount == storesToOpen.Length(), "Should have bailed!");
|
||||
} break;
|
||||
|
||||
// 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;
|
||||
}
|
||||
case nsIDataType::VTYPE_INTERFACE:
|
||||
case nsIDataType::VTYPE_INTERFACE_IS: {
|
||||
nsCOMPtr<nsISupports> supports;
|
||||
nsID *iid;
|
||||
rv = aStoreNames->GetAsInterface(&iid, getter_AddRefs(supports));
|
||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||
|
||||
storesToOpen.AppendElement(str);
|
||||
}
|
||||
NS_Free(iid);
|
||||
|
||||
// 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;
|
||||
}
|
||||
nsCOMPtr<nsIDOMDOMStringList> stringList(do_QueryInterface(supports));
|
||||
if (!stringList) {
|
||||
// We don't support anything other than nsIDOMDOMStringList.
|
||||
return NS_ERROR_DOM_INDEXEDDB_NON_TRANSIENT_ERR;
|
||||
}
|
||||
|
||||
PRUint32 stringCount;
|
||||
rv = stringList->GetLength(&stringCount);
|
||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||
|
||||
for (PRUint32 stringIndex = 0; stringIndex < stringCount; stringIndex++) {
|
||||
nsString name;
|
||||
rv = stringList->Item(stringIndex, name);
|
||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||
|
||||
if (!info->ContainsStoreName(name)) {
|
||||
return NS_ERROR_DOM_INDEXEDDB_NOT_FOUND_ERR;
|
||||
}
|
||||
|
||||
if (!storesToOpen.AppendElement(name)) {
|
||||
NS_WARNING("Out of memory?");
|
||||
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
default:
|
||||
return NS_ERROR_DOM_INDEXEDDB_NON_TRANSIENT_ERR;
|
||||
}
|
||||
|
||||
nsRefPtr<IDBTransaction> transaction =
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -42,7 +42,7 @@
|
|||
#include "nsIXPConnect.h"
|
||||
|
||||
#include "jscntxt.h"
|
||||
#include "nsDOMClassInfo.h"
|
||||
#include "nsDOMClassInfoID.h"
|
||||
#include "nsJSUtils.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsContentUtils.h"
|
||||
|
@ -54,7 +54,54 @@ USING_INDEXEDDB_NAMESPACE
|
|||
namespace {
|
||||
|
||||
inline
|
||||
bool
|
||||
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
|
||||
ReturnKeyRange(JSContext* aCx,
|
||||
jsval* aVp,
|
||||
IDBKeyRange* aKeyRange)
|
||||
|
@ -68,73 +115,24 @@ ReturnKeyRange(JSContext* aCx,
|
|||
NS_ASSERTION(xpc, "This should never be null!");
|
||||
|
||||
JSObject* global = JS_GetGlobalForScopeChain(aCx);
|
||||
if (!global) {
|
||||
NS_WARNING("Couldn't get global object!");
|
||||
return false;
|
||||
}
|
||||
NS_ENSURE_TRUE(global, JS_FALSE);
|
||||
|
||||
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
|
||||
if (NS_FAILED(xpc->WrapNative(aCx, global, aKeyRange,
|
||||
NS_GET_IID(nsIIDBKeyRange),
|
||||
getter_AddRefs(holder)))) {
|
||||
JS_ReportError(aCx, "Couldn't wrap IDBKeyRange object.");
|
||||
return false;
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
JSObject* result;
|
||||
if (NS_FAILED(holder->GetJSObject(&result))) {
|
||||
JS_ReportError(aCx, "Couldn't get JSObject from wrapper.");
|
||||
return false;
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
JS_SET_RVAL(aCx, aVp, OBJECT_TO_JSVAL(result));
|
||||
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;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSBool
|
||||
|
@ -144,18 +142,21 @@ MakeOnlyKeyRange(JSContext* aCx,
|
|||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
jsval val;
|
||||
if (!JS_ConvertArguments(aCx, aArgc, JS_ARGV(aCx, aVp), "v", &val)) {
|
||||
return false;
|
||||
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;
|
||||
}
|
||||
|
||||
nsRefPtr<IDBKeyRange> keyRange = new IDBKeyRange(false, false, true);
|
||||
|
||||
if (!GetKeyFromJSValOrThrow(aCx, val, keyRange->Lower())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return ReturnKeyRange(aCx, aVp, keyRange);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSBool
|
||||
|
@ -165,19 +166,27 @@ MakeLowerBoundKeyRange(JSContext* aCx,
|
|||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
jsval val;
|
||||
JSBool open = false;
|
||||
if (!JS_ConvertArguments(aCx, aArgc, JS_ARGV(aCx, aVp), "v/b", &val, &open)) {
|
||||
return false;
|
||||
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;
|
||||
}
|
||||
|
||||
nsRefPtr<IDBKeyRange> keyRange = new IDBKeyRange(open, true, false);
|
||||
nsRefPtr<IDBKeyRange> range =
|
||||
IDBKeyRange::Create(keys[0], nsnull, !!open, true);
|
||||
NS_ASSERTION(range, "Out of memory?");
|
||||
|
||||
if (!GetKeyFromJSValOrThrow(aCx, val, keyRange->Lower())) {
|
||||
return false;
|
||||
if (!ReturnKeyRange(aCx, aVp, range)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
return ReturnKeyRange(aCx, aVp, keyRange);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSBool
|
||||
|
@ -187,19 +196,27 @@ MakeUpperBoundKeyRange(JSContext* aCx,
|
|||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
jsval val;
|
||||
JSBool open = false;
|
||||
if (!JS_ConvertArguments(aCx, aArgc, JS_ARGV(aCx, aVp), "v/b", &val, &open)) {
|
||||
return false;
|
||||
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;
|
||||
}
|
||||
|
||||
nsRefPtr<IDBKeyRange> keyRange = new IDBKeyRange(true, open, false);
|
||||
nsRefPtr<IDBKeyRange> range =
|
||||
IDBKeyRange::Create(nsnull, keys[0], true, !!open);
|
||||
NS_ASSERTION(range, "Out of memory?");
|
||||
|
||||
if (!GetKeyFromJSValOrThrow(aCx, val, keyRange->Upper())) {
|
||||
return false;
|
||||
if (!ReturnKeyRange(aCx, aVp, range)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
return ReturnKeyRange(aCx, aVp, keyRange);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSBool
|
||||
|
@ -209,29 +226,36 @@ MakeBoundKeyRange(JSContext* aCx,
|
|||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
nsRefPtr<IDBKeyRange> keyRange = new IDBKeyRange(lowerOpen, upperOpen, false);
|
||||
|
||||
if (!GetKeyFromJSValOrThrow(aCx, lowerVal, keyRange->Lower()) ||
|
||||
!GetKeyFromJSValOrThrow(aCx, upperVal, keyRange->Upper())) {
|
||||
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;
|
||||
}
|
||||
|
||||
if (keyRange->Lower() > keyRange->Upper() ||
|
||||
(keyRange->Lower() == keyRange->Upper() && (lowerOpen || upperOpen))) {
|
||||
ThrowException(aCx, NS_ERROR_DOM_INDEXEDDB_DATA_ERR);
|
||||
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;
|
||||
}
|
||||
|
||||
return ReturnKeyRange(aCx, aVp, keyRange);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
|
||||
#define KEYRANGE_FUNCTION_FLAGS (JSPROP_ENUMERATE | JSPROP_PERMANENT)
|
||||
|
||||
const JSFunctionSpec gKeyRangeConstructors[] = {
|
||||
|
@ -261,129 +285,49 @@ IDBKeyRange::DefineConstructors(JSContext* aCx,
|
|||
}
|
||||
|
||||
// static
|
||||
nsresult
|
||||
IDBKeyRange::FromJSVal(JSContext* aCx,
|
||||
const jsval& aVal,
|
||||
IDBKeyRange** aKeyRange)
|
||||
already_AddRefed<IDBKeyRange>
|
||||
IDBKeyRange::Create(nsIVariant* aLower,
|
||||
nsIVariant* aUpper,
|
||||
bool aLowerOpen,
|
||||
bool aUpperOpen)
|
||||
{
|
||||
nsresult rv;
|
||||
nsRefPtr<IDBKeyRange> keyRange;
|
||||
nsRefPtr<IDBKeyRange> keyRange(new IDBKeyRange());
|
||||
keyRange->mLower = aLower;
|
||||
keyRange->mUpper = aUpper;
|
||||
keyRange->mLowerOpen = aLowerOpen;
|
||||
keyRange->mUpperOpen = aUpperOpen;
|
||||
|
||||
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;
|
||||
return keyRange.forget();
|
||||
}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(IDBKeyRange)
|
||||
NS_IMPL_ADDREF(IDBKeyRange)
|
||||
NS_IMPL_RELEASE(IDBKeyRange)
|
||||
|
||||
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_BEGIN(IDBKeyRange)
|
||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIIDBKeyRange)
|
||||
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(JSContext* aCx,
|
||||
jsval* aLower)
|
||||
IDBKeyRange::GetLower(nsIVariant** aLower)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
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;
|
||||
nsCOMPtr<nsIVariant> result(mLower);
|
||||
result.forget(aLower);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
IDBKeyRange::GetUpper(JSContext* aCx,
|
||||
jsval* aUpper)
|
||||
IDBKeyRange::GetUpper(nsIVariant** aUpper)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
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;
|
||||
nsCOMPtr<nsIVariant> result(mUpper);
|
||||
result.forget(aUpper);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -392,7 +336,7 @@ IDBKeyRange::GetLowerOpen(bool* aLowerOpen)
|
|||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
*aLowerOpen = mLowerOpen;
|
||||
*aLowerOpen = mLowerOpen ? true : false;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -402,6 +346,6 @@ IDBKeyRange::GetUpperOpen(bool* aUpperOpen)
|
|||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
*aUpperOpen = mUpperOpen;
|
||||
*aUpperOpen = mUpperOpen ? true : false;
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -41,78 +41,38 @@
|
|||
#define mozilla_dom_indexeddb_idbkeyrange_h__
|
||||
|
||||
#include "mozilla/dom/indexedDB/IndexedDatabase.h"
|
||||
#include "mozilla/dom/indexedDB/Key.h"
|
||||
|
||||
#include "nsIIDBKeyRange.h"
|
||||
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsIVariant.h"
|
||||
|
||||
BEGIN_INDEXEDDB_NAMESPACE
|
||||
|
||||
class IDBKeyRange : public nsIIDBKeyRange
|
||||
{
|
||||
public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIIDBKEYRANGE
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(IDBKeyRange)
|
||||
|
||||
static JSBool DefineConstructors(JSContext* aCx,
|
||||
JSObject* aObject);
|
||||
|
||||
static
|
||||
nsresult FromJSVal(JSContext* aCx,
|
||||
const jsval& aVal,
|
||||
IDBKeyRange** aKeyRange);
|
||||
|
||||
IDBKeyRange(bool aLowerOpen, bool aUpperOpen, bool aIsOnly)
|
||||
: mCachedLowerVal(JSVAL_VOID), mCachedUpperVal(JSVAL_VOID),
|
||||
mLowerOpen(aLowerOpen), mUpperOpen(aUpperOpen), mIsOnly(aIsOnly),
|
||||
mHaveCachedLowerVal(false), mHaveCachedUpperVal(false), mRooted(false)
|
||||
{ }
|
||||
|
||||
const Key& Lower() const
|
||||
{
|
||||
return mLower;
|
||||
}
|
||||
|
||||
Key& Lower()
|
||||
{
|
||||
return mLower;
|
||||
}
|
||||
|
||||
const Key& Upper() const
|
||||
{
|
||||
return mIsOnly ? mLower : mUpper;
|
||||
}
|
||||
|
||||
Key& Upper()
|
||||
{
|
||||
return mIsOnly ? mLower : mUpper;
|
||||
}
|
||||
|
||||
bool IsLowerOpen() const
|
||||
{
|
||||
return mLowerOpen;
|
||||
}
|
||||
|
||||
bool IsUpperOpen() const
|
||||
{
|
||||
return mUpperOpen;
|
||||
}
|
||||
already_AddRefed<IDBKeyRange> Create(nsIVariant* aLower,
|
||||
nsIVariant* aUpper,
|
||||
bool aLowerOpen,
|
||||
bool aUpperOpen);
|
||||
|
||||
protected:
|
||||
IDBKeyRange()
|
||||
: mLowerOpen(false), mUpperOpen(false)
|
||||
{ }
|
||||
|
||||
~IDBKeyRange() { }
|
||||
|
||||
Key mLower;
|
||||
Key mUpper;
|
||||
jsval mCachedLowerVal;
|
||||
jsval mCachedUpperVal;
|
||||
nsCOMPtr<nsIVariant> mLower;
|
||||
nsCOMPtr<nsIVariant> mUpper;
|
||||
bool mLowerOpen;
|
||||
bool mUpperOpen;
|
||||
bool mIsOnly;
|
||||
bool mHaveCachedLowerVal;
|
||||
bool mHaveCachedUpperVal;
|
||||
bool mRooted;
|
||||
};
|
||||
|
||||
END_INDEXEDDB_NAMESPACE
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -42,6 +42,7 @@
|
|||
|
||||
#include "mozilla/dom/indexedDB/IndexedDatabase.h"
|
||||
#include "mozilla/dom/indexedDB/IDBTransaction.h"
|
||||
#include "mozilla/dom/indexedDB/Key.h"
|
||||
|
||||
#include "nsIIDBObjectStore.h"
|
||||
#include "nsIIDBTransaction.h"
|
||||
|
@ -54,7 +55,6 @@ class nsPIDOMWindow;
|
|||
BEGIN_INDEXEDDB_NAMESPACE
|
||||
|
||||
class AsyncConnectionHelper;
|
||||
class Key;
|
||||
|
||||
struct ObjectStoreInfo;
|
||||
struct IndexInfo;
|
||||
|
@ -72,6 +72,20 @@ 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,
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include "IDBRequest.h"
|
||||
|
||||
#include "nsIScriptContext.h"
|
||||
#include "nsIVariant.h"
|
||||
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsDOMClassInfoID.h"
|
||||
|
|
|
@ -42,45 +42,70 @@
|
|||
|
||||
#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)
|
||||
{
|
||||
Unset();
|
||||
*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;
|
||||
}
|
||||
|
||||
Key& operator=(const nsAString& aString)
|
||||
{
|
||||
SetFromString(aString);
|
||||
mType = STRINGKEY;
|
||||
mString = aString;
|
||||
mInt = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Key& operator=(PRInt64 aInt)
|
||||
{
|
||||
SetFromInteger(aInt);
|
||||
mType = INTKEY;
|
||||
mString.Truncate();
|
||||
mInt = 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 KEYTYPE_STRING:
|
||||
return ToString() == aOther.ToString();
|
||||
case UNSETKEY:
|
||||
return true;
|
||||
|
||||
case KEYTYPE_INTEGER:
|
||||
return ToInteger() == aOther.ToInteger();
|
||||
case STRINGKEY:
|
||||
return mString == aOther.mString;
|
||||
|
||||
case INTKEY:
|
||||
return mInt == aOther.mInt;
|
||||
|
||||
default:
|
||||
NS_NOTREACHED("Unknown type!");
|
||||
|
@ -96,24 +121,30 @@ public:
|
|||
|
||||
bool operator<(const Key& aOther) const
|
||||
{
|
||||
NS_ASSERTION(mType != KEYTYPE_VOID && aOther.mType != KEYTYPE_VOID,
|
||||
"Don't compare unset keys!");
|
||||
|
||||
switch (mType) {
|
||||
case KEYTYPE_STRING: {
|
||||
if (aOther.mType == KEYTYPE_INTEGER) {
|
||||
case UNSETKEY:
|
||||
if (aOther.mType == UNSETKEY) {
|
||||
return false;
|
||||
}
|
||||
NS_ASSERTION(aOther.mType == KEYTYPE_STRING, "Unknown type!");
|
||||
return ToString() < aOther.ToString();
|
||||
}
|
||||
return true;
|
||||
|
||||
case KEYTYPE_INTEGER:
|
||||
if (aOther.mType == KEYTYPE_STRING) {
|
||||
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) {
|
||||
return true;
|
||||
}
|
||||
NS_ASSERTION(aOther.mType == KEYTYPE_INTEGER, "Unknown type!");
|
||||
return ToInteger() < aOther.ToInteger();
|
||||
NS_ASSERTION(aOther.mType == INTKEY, "Unknown type!");
|
||||
return mInt < aOther.mInt;
|
||||
|
||||
default:
|
||||
NS_NOTREACHED("Unknown type!");
|
||||
|
@ -136,188 +167,42 @@ public:
|
|||
return (*this == aOther || !(*this < aOther));
|
||||
}
|
||||
|
||||
void
|
||||
Unset()
|
||||
{
|
||||
mType = KEYTYPE_VOID;
|
||||
mStringKey.SetIsVoid(true);
|
||||
mIntKey = 0;
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
PRInt64 IntValue() const {
|
||||
NS_ASSERTION(IsInt(), "Wrong type!");
|
||||
return mInt;
|
||||
}
|
||||
|
||||
nsresult SetFromInteger(PRInt64 aInt)
|
||||
{
|
||||
mType = KEYTYPE_INTEGER;
|
||||
mStringKey.SetIsVoid(true);
|
||||
mIntKey = aInt;
|
||||
return NS_OK;
|
||||
nsAString& ToString() {
|
||||
mType = STRINGKEY;
|
||||
mInt = 0;
|
||||
return mString;
|
||||
}
|
||||
|
||||
nsresult SetFromJSVal(JSContext* aCx,
|
||||
jsval aVal)
|
||||
{
|
||||
if (JSVAL_IS_STRING(aVal)) {
|
||||
jsval tempRoot = JSVAL_VOID;
|
||||
SetFromString(xpc_qsAString(aCx, aVal, &tempRoot));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (JSVAL_IS_INT(aVal)) {
|
||||
SetFromInteger(JSVAL_TO_INT(aVal));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (JSVAL_IS_DOUBLE(aVal)) {
|
||||
jsdouble doubleActual = JSVAL_TO_DOUBLE(aVal);
|
||||
int64 doubleAsInt = static_cast<int64>(doubleActual);
|
||||
if (doubleActual == doubleAsInt) {
|
||||
SetFromInteger(doubleAsInt);
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
if (JSVAL_IS_NULL(aVal) || JSVAL_IS_VOID(aVal)) {
|
||||
Unset();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return NS_ERROR_DOM_INDEXEDDB_DATA_ERR;
|
||||
}
|
||||
|
||||
nsresult ToJSVal(JSContext* aCx,
|
||||
jsval* aVal) const
|
||||
{
|
||||
if (IsString()) {
|
||||
nsString stringKey = ToString();
|
||||
if (!xpc_qsStringToJsval(aCx, stringKey, 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 nsAString& 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;
|
||||
PRInt64* ToIntPtr() {
|
||||
mType = INTKEY;
|
||||
mString.Truncate();
|
||||
return &mInt;
|
||||
}
|
||||
|
||||
static
|
||||
bool CanBeConstructedFromJSVal(jsval aVal)
|
||||
{
|
||||
return JSVAL_IS_INT(aVal) || JSVAL_IS_DOUBLE(aVal) || JSVAL_IS_STRING(aVal);
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
// 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;
|
||||
nsString mString;
|
||||
PRInt64 mInt;
|
||||
};
|
||||
|
||||
END_INDEXEDDB_NAMESPACE
|
||||
|
|
|
@ -93,7 +93,6 @@ 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
|
||||
|
|
|
@ -40,13 +40,14 @@
|
|||
#include "nsISupports.idl"
|
||||
|
||||
interface nsIIDBRequest;
|
||||
interface nsIVariant;
|
||||
|
||||
/**
|
||||
* IDBCursor interface. See
|
||||
* http://dev.w3.org/2006/webapi/WebSimpleDB/#idl-def-IDBCursor for more
|
||||
* information.
|
||||
*/
|
||||
[scriptable, builtinclass, uuid(462a3607-b2d6-4f4b-9dd7-8ca0b26d3414)]
|
||||
[scriptable, uuid(adee4085-68cd-4568-9d74-e3d32b6dc5c5)]
|
||||
interface nsIIDBCursor : nsISupports
|
||||
{
|
||||
const unsigned short NEXT = 0;
|
||||
|
@ -57,8 +58,7 @@ interface nsIIDBCursor : nsISupports
|
|||
|
||||
readonly attribute nsISupports source;
|
||||
|
||||
[implicit_jscontext]
|
||||
readonly attribute jsval key;
|
||||
readonly attribute nsIVariant key;
|
||||
|
||||
[implicit_jscontext]
|
||||
readonly attribute jsval primaryKey;
|
||||
|
|
|
@ -39,12 +39,16 @@
|
|||
|
||||
#include "nsIIDBCursor.idl"
|
||||
|
||||
%{C++
|
||||
#include "jsapi.h"
|
||||
%}
|
||||
|
||||
/**
|
||||
* IDBCursor interface. See
|
||||
* http://dev.w3.org/2006/webapi/WebSimpleDB/#idl-def-IDBCursor for more
|
||||
* information.
|
||||
*/
|
||||
[scriptable, builtinclass, uuid(b6b7e08a-4379-4441-a176-447c5c96df69)]
|
||||
[scriptable, uuid(b6b7e08a-4379-4441-a176-447c5c96df69)]
|
||||
interface nsIIDBCursorWithValue : nsIIDBCursor
|
||||
{
|
||||
[implicit_jscontext]
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
interface nsIVariant;
|
||||
interface nsIIDBObjectStore;
|
||||
interface nsIIDBRequest;
|
||||
interface nsIIDBTransaction;
|
||||
|
@ -50,7 +51,7 @@ interface nsIDOMEventListener;
|
|||
* http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#idl-def-IDBDatabase
|
||||
* for more information.
|
||||
*/
|
||||
[scriptable, builtinclass, uuid(ddc9dd43-704f-45da-bb91-20f4b3103117)]
|
||||
[scriptable, uuid(ac14faa5-261c-4a84-9616-a700fd606f83)]
|
||||
interface nsIIDBDatabase : nsISupports
|
||||
{
|
||||
readonly attribute DOMString name;
|
||||
|
@ -77,8 +78,9 @@ interface nsIIDBDatabase : nsISupports
|
|||
|
||||
[optional_argc, implicit_jscontext]
|
||||
nsIIDBTransaction
|
||||
transaction(in jsval storeNames, // js array of strings
|
||||
[optional /* READ_ONLY */] in unsigned short mode);
|
||||
transaction(in nsIVariant storeNames, // js array of strings
|
||||
[optional /* READ_ONLY */] in unsigned short mode,
|
||||
[optional /* 5000ms */] in unsigned long timeout);
|
||||
|
||||
void
|
||||
close();
|
||||
|
|
|
@ -39,7 +39,7 @@
|
|||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
[scriptable, builtinclass, uuid(7aad2542-a5cb-4a57-b20c-c7d16b8582ab)]
|
||||
[scriptable, uuid(7aad2542-a5cb-4a57-b20c-c7d16b8582ab)]
|
||||
interface nsIIDBDatabaseException : nsISupports
|
||||
{
|
||||
// const unsigned short NO_ERR = 0;
|
||||
|
|
|
@ -42,13 +42,14 @@
|
|||
|
||||
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, builtinclass, uuid(d2889b8f-662a-42d3-8a8f-ac5179b9d5b0)]
|
||||
[scriptable, uuid(d2889b8f-662a-42d3-8a8f-ac5179b9d5b0)]
|
||||
interface nsIIDBFactory : nsISupports
|
||||
{
|
||||
[implicit_jscontext, optional_argc]
|
||||
|
|
|
@ -39,15 +39,17 @@
|
|||
|
||||
#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, builtinclass, uuid(1da60889-3db4-4f66-9fd7-b78c1e7969b7)]
|
||||
[scriptable, uuid(9df1ac24-06cf-47d1-9159-3b3d65975b80)]
|
||||
interface nsIIDBIndex : nsISupports
|
||||
{
|
||||
readonly attribute DOMString name;
|
||||
|
@ -60,36 +62,29 @@ interface nsIIDBIndex : nsISupports
|
|||
|
||||
readonly attribute nsIIDBObjectStore objectStore;
|
||||
|
||||
[implicit_jscontext]
|
||||
nsIIDBRequest
|
||||
get(in jsval key);
|
||||
get(in nsIVariant key);
|
||||
|
||||
[implicit_jscontext]
|
||||
nsIIDBRequest
|
||||
getKey(in jsval key);
|
||||
getKey(in nsIVariant key);
|
||||
|
||||
[implicit_jscontext, optional_argc]
|
||||
[optional_argc]
|
||||
nsIIDBRequest
|
||||
getAll([optional /* null */] in jsval key,
|
||||
getAll([optional /* null */] in nsIVariant key,
|
||||
[optional /* unlimited */] in unsigned long limit);
|
||||
|
||||
[implicit_jscontext, optional_argc]
|
||||
[optional_argc]
|
||||
nsIIDBRequest
|
||||
getAllKeys([optional /* null */] in jsval key,
|
||||
getAllKeys([optional /* null */] in nsIVariant key,
|
||||
[optional /* unlimited */] in unsigned long limit);
|
||||
|
||||
[implicit_jscontext, optional_argc]
|
||||
[optional_argc]
|
||||
nsIIDBRequest
|
||||
openCursor([optional /* null */] in jsval key,
|
||||
openCursor([optional /* null */] in nsIIDBKeyRange range,
|
||||
[optional /* nsIIDBCursor::NEXT */] in unsigned short direction);
|
||||
|
||||
[implicit_jscontext, optional_argc]
|
||||
[optional_argc]
|
||||
nsIIDBRequest
|
||||
openKeyCursor([optional /* null */] in jsval key,
|
||||
openKeyCursor([optional /* null */] in nsIIDBKeyRange range,
|
||||
[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);
|
||||
};
|
||||
|
|
|
@ -39,20 +39,18 @@
|
|||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
interface nsIVariant;
|
||||
|
||||
/**
|
||||
* IDBKeyRange interface. See
|
||||
* http://dev.w3.org/2006/webapi/WebSimpleDB/#idl-def-IDBKeyRange for more
|
||||
* information.
|
||||
*/
|
||||
[scriptable, builtinclass, uuid(8aeb8660-76b3-4651-b8c2-9894ae6dfe68)]
|
||||
[scriptable, uuid(a1505e41-7e48-4542-9fa5-3f2c98233567)]
|
||||
interface nsIIDBKeyRange : nsISupports
|
||||
{
|
||||
[implicit_jscontext]
|
||||
readonly attribute jsval lower;
|
||||
|
||||
[implicit_jscontext]
|
||||
readonly attribute jsval upper;
|
||||
|
||||
readonly attribute nsIVariant lower;
|
||||
readonly attribute nsIVariant upper;
|
||||
readonly attribute boolean lowerOpen;
|
||||
readonly attribute boolean upperOpen;
|
||||
};
|
||||
|
|
|
@ -43,6 +43,7 @@ interface nsIIDBIndex;
|
|||
interface nsIIDBKeyRange;
|
||||
interface nsIIDBRequest;
|
||||
interface nsIIDBTransaction;
|
||||
interface nsIVariant;
|
||||
interface nsIDOMDOMStringList;
|
||||
|
||||
/**
|
||||
|
@ -50,7 +51,7 @@ interface nsIDOMDOMStringList;
|
|||
* http://dev.w3.org/2006/webapi/WebSimpleDB/#idl-def-nsIIDBObjectStore
|
||||
* for more information.
|
||||
*/
|
||||
[scriptable, builtinclass, uuid(d25dff2f-81ad-4531-bcbe-e85c8a19f11a)]
|
||||
[scriptable, uuid(6a65dc92-66e3-407a-a370-590a6c54664a)]
|
||||
interface nsIIDBObjectStore : nsISupports
|
||||
{
|
||||
readonly attribute DOMString name;
|
||||
|
@ -62,14 +63,13 @@ interface nsIIDBObjectStore : nsISupports
|
|||
readonly attribute nsIIDBTransaction transaction;
|
||||
|
||||
// Success fires IDBTransactionEvent, result == value for key
|
||||
[implicit_jscontext]
|
||||
nsIIDBRequest
|
||||
get(in jsval key);
|
||||
get(in nsIVariant key);
|
||||
|
||||
// Success fires IDBTransactionEvent, result == array of values for given keys
|
||||
[implicit_jscontext, optional_argc]
|
||||
[optional_argc]
|
||||
nsIIDBRequest
|
||||
getAll([optional /* null */] in jsval key,
|
||||
getAll([optional /* null */] in nsIIDBKeyRange 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.
|
||||
[implicit_jscontext, optional_argc]
|
||||
[optional_argc]
|
||||
nsIIDBRequest
|
||||
openCursor([optional /* null */] in jsval range,
|
||||
openCursor([optional /* null */] in nsIIDBKeyRange range,
|
||||
[optional /* NEXT */] in unsigned short direction);
|
||||
|
||||
/**
|
||||
|
@ -118,9 +118,4 @@ 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);
|
||||
};
|
||||
|
|
|
@ -47,7 +47,7 @@ interface nsIDOMEventListener;
|
|||
* http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#idl-def-IDBOpenDBRequest
|
||||
* for more information.
|
||||
*/
|
||||
[scriptable, builtinclass, uuid(91010fbe-1dfb-435d-852e-288d2804c0a7)]
|
||||
[scriptable, uuid(91010fbe-1dfb-435d-852e-288d2804c0a7)]
|
||||
interface nsIIDBOpenDBRequest : nsISupports
|
||||
{
|
||||
attribute nsIDOMEventListener onblocked;
|
||||
|
|
|
@ -48,7 +48,7 @@ interface nsIIDBTransaction;
|
|||
* http://dev.w3.org/2006/webapi/WebSimpleDB/#idl-def-IDBRequest for more
|
||||
* information.
|
||||
*/
|
||||
[scriptable, builtinclass, uuid(a1e4a0ff-e0b2-431c-89cf-43b078189e27)]
|
||||
[scriptable, uuid(a1e4a0ff-e0b2-431c-89cf-43b078189e27)]
|
||||
interface nsIIDBRequest : nsISupports
|
||||
{
|
||||
const unsigned short LOADING = 1;
|
||||
|
|
|
@ -50,7 +50,7 @@ interface nsIDOMDOMStringList;
|
|||
* http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#idl-def-IDBTransaction
|
||||
* for more information.
|
||||
*/
|
||||
[scriptable, builtinclass, uuid(13e551a1-1a58-42ec-b0bd-7102ec0f64d6)]
|
||||
[scriptable, uuid(13e551a1-1a58-42ec-b0bd-7102ec0f64d6)]
|
||||
interface nsIIDBTransaction : nsISupports
|
||||
{
|
||||
readonly attribute nsIIDBDatabase db;
|
||||
|
|
|
@ -39,7 +39,7 @@
|
|||
|
||||
#include "nsIDOMEvent.idl"
|
||||
|
||||
[scriptable, builtinclass, uuid(2c5159dc-7d71-4fc6-a3b3-884ed7586456)]
|
||||
[scriptable, uuid(2c5159dc-7d71-4fc6-a3b3-884ed7586456)]
|
||||
interface nsIIDBVersionChangeEvent : nsIDOMEvent
|
||||
{
|
||||
readonly attribute unsigned long long oldVersion;
|
||||
|
|
|
@ -51,7 +51,7 @@ interface nsIIndexedDatabaseUsageCallback : nsISupports
|
|||
in unsigned long long aUsage);
|
||||
};
|
||||
|
||||
[scriptable, builtinclass, uuid(415f5684-6c84-4a8b-b777-d01f5df778f2)]
|
||||
[scriptable, uuid(415f5684-6c84-4a8b-b777-d01f5df778f2)]
|
||||
interface nsIIndexedDatabaseManager : nsISupports
|
||||
{
|
||||
/**
|
||||
|
|
|
@ -57,7 +57,6 @@ TEST_FILES = \
|
|||
test_bad_keypath.html \
|
||||
test_bfcache.html \
|
||||
test_clear.html \
|
||||
test_count.html \
|
||||
test_create_index.html \
|
||||
test_create_index_with_integer_keys.html \
|
||||
test_create_objectStore.html \
|
||||
|
|
|
@ -1,366 +0,0 @@
|
|||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
<title>Indexed Database Property Test</title>
|
||||
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
|
||||
<script type="text/javascript;version=1.7">
|
||||
function testSteps()
|
||||
{
|
||||
const name = window.location.pathname;
|
||||
const objectStoreName = "People";
|
||||
|
||||
const objectStoreData = [
|
||||
{ key: "237-23-7732", value: { name: "Bob", height: 60, weight: 120 } },
|
||||
{ key: "237-23-7733", value: { name: "Ann", height: 52, weight: 110 } },
|
||||
{ key: "237-23-7734", value: { name: "Ron", height: 73, weight: 180 } },
|
||||
{ key: "237-23-7735", value: { name: "Sue", height: 58, weight: 130 } },
|
||||
{ key: "237-23-7736", value: { name: "Joe", height: 65, weight: 150 } },
|
||||
{ key: "237-23-7737", value: { name: "Pat", height: 65 } },
|
||||
{ key: "237-23-7738", value: { name: "Mel", height: 66, weight: {} } },
|
||||
{ key: "237-23-7739", value: { name: "Tom", height: 62, weight: 130 } }
|
||||
];
|
||||
|
||||
const indexData = {
|
||||
name: "weight",
|
||||
keyPath: "weight",
|
||||
options: { unique: false }
|
||||
};
|
||||
|
||||
const weightSort = [1, 0, 3, 7, 4, 2];
|
||||
|
||||
let request = mozIndexedDB.open(name, 1);
|
||||
request.onerror = errorHandler;
|
||||
request.onupgradeneeded = grabEventAndContinueHandler;
|
||||
request.onsuccess = grabEventAndContinueHandler;
|
||||
let event = yield;
|
||||
|
||||
is(event.type, "upgradeneeded", "Got correct event type");
|
||||
|
||||
let db = event.target.result;
|
||||
db.onerror = errorHandler;
|
||||
|
||||
let objectStore = db.createObjectStore(objectStoreName, { });
|
||||
objectStore.createIndex(indexData.name, indexData.keyPath,
|
||||
indexData.options);
|
||||
|
||||
for each (let data in objectStoreData) {
|
||||
objectStore.add(data.value, data.key);
|
||||
}
|
||||
|
||||
event = yield;
|
||||
|
||||
is(event.type, "success", "Got correct event type");
|
||||
|
||||
objectStore = db.transaction(db.objectStoreNames)
|
||||
.objectStore(objectStoreName);
|
||||
|
||||
objectStore.count().onsuccess = grabEventAndContinueHandler;
|
||||
event = yield;
|
||||
|
||||
is(event.target.result, objectStoreData.length,
|
||||
"Correct number of object store entries for all keys");
|
||||
|
||||
objectStore.count(null).onsuccess = grabEventAndContinueHandler;
|
||||
event = yield;
|
||||
|
||||
is(event.target.result, objectStoreData.length,
|
||||
"Correct number of object store entries for null key");
|
||||
|
||||
objectStore.count(objectStoreData[2].key).onsuccess =
|
||||
grabEventAndContinueHandler;
|
||||
event = yield;
|
||||
|
||||
is(event.target.result, 1,
|
||||
"Correct number of object store entries for single existing key");
|
||||
|
||||
objectStore.count("foo").onsuccess = grabEventAndContinueHandler;
|
||||
event = yield;
|
||||
|
||||
is(event.target.result, 0,
|
||||
"Correct number of object store entries for single non-existing key");
|
||||
|
||||
let keyRange = IDBKeyRange.only(objectStoreData[2].key);
|
||||
objectStore.count(keyRange).onsuccess = grabEventAndContinueHandler;
|
||||
event = yield;
|
||||
|
||||
is(event.target.result, 1,
|
||||
"Correct number of object store entries for existing only keyRange");
|
||||
|
||||
keyRange = IDBKeyRange.only("foo");
|
||||
objectStore.count(keyRange).onsuccess = grabEventAndContinueHandler;
|
||||
event = yield;
|
||||
|
||||
is(event.target.result, 0,
|
||||
"Correct number of object store entries for non-existing only keyRange");
|
||||
|
||||
keyRange = IDBKeyRange.lowerBound(objectStoreData[2].key);
|
||||
objectStore.count(keyRange).onsuccess = grabEventAndContinueHandler;
|
||||
event = yield;
|
||||
|
||||
is(event.target.result, objectStoreData.length - 2,
|
||||
"Correct number of object store entries for lowerBound keyRange");
|
||||
|
||||
keyRange = IDBKeyRange.lowerBound(objectStoreData[2].key, true);
|
||||
objectStore.count(keyRange).onsuccess = grabEventAndContinueHandler;
|
||||
event = yield;
|
||||
|
||||
is(event.target.result, objectStoreData.length - 3,
|
||||
"Correct number of object store entries for lowerBound keyRange");
|
||||
|
||||
keyRange = IDBKeyRange.lowerBound("foo");
|
||||
objectStore.count(keyRange).onsuccess = grabEventAndContinueHandler;
|
||||
event = yield;
|
||||
|
||||
is(event.target.result, 0,
|
||||
"Correct number of object store entries for lowerBound keyRange");
|
||||
|
||||
keyRange = IDBKeyRange.upperBound(objectStoreData[2].key, false);
|
||||
objectStore.count(keyRange).onsuccess = grabEventAndContinueHandler;
|
||||
event = yield;
|
||||
|
||||
is(event.target.result, 3,
|
||||
"Correct number of object store entries for upperBound keyRange");
|
||||
|
||||
keyRange = IDBKeyRange.upperBound(objectStoreData[2].key, true);
|
||||
objectStore.count(keyRange).onsuccess = grabEventAndContinueHandler;
|
||||
event = yield;
|
||||
|
||||
is(event.target.result, 2,
|
||||
"Correct number of object store entries for upperBound keyRange");
|
||||
|
||||
keyRange = IDBKeyRange.upperBound("foo", true);
|
||||
objectStore.count(keyRange).onsuccess = grabEventAndContinueHandler;
|
||||
event = yield;
|
||||
|
||||
is(event.target.result, objectStoreData.length,
|
||||
"Correct number of object store entries for upperBound keyRange");
|
||||
|
||||
keyRange = IDBKeyRange.bound(objectStoreData[0].key,
|
||||
objectStoreData[objectStoreData.length - 1].key);
|
||||
objectStore.count(keyRange).onsuccess = grabEventAndContinueHandler;
|
||||
event = yield;
|
||||
|
||||
is(event.target.result, objectStoreData.length,
|
||||
"Correct number of object store entries for bound keyRange");
|
||||
|
||||
keyRange = IDBKeyRange.bound(objectStoreData[0].key,
|
||||
objectStoreData[objectStoreData.length - 1].key,
|
||||
true);
|
||||
objectStore.count(keyRange).onsuccess = grabEventAndContinueHandler;
|
||||
event = yield;
|
||||
|
||||
is(event.target.result, objectStoreData.length - 1,
|
||||
"Correct number of object store entries for bound keyRange");
|
||||
|
||||
keyRange = IDBKeyRange.bound(objectStoreData[0].key,
|
||||
objectStoreData[objectStoreData.length - 1].key,
|
||||
true, true);
|
||||
objectStore.count(keyRange).onsuccess = grabEventAndContinueHandler;
|
||||
event = yield;
|
||||
|
||||
is(event.target.result, objectStoreData.length - 2,
|
||||
"Correct number of object store entries for bound keyRange");
|
||||
|
||||
keyRange = IDBKeyRange.bound("foo", "foopy", true, true);
|
||||
objectStore.count(keyRange).onsuccess = grabEventAndContinueHandler;
|
||||
event = yield;
|
||||
|
||||
is(event.target.result, 0,
|
||||
"Correct number of object store entries for bound keyRange");
|
||||
|
||||
keyRange = IDBKeyRange.bound(objectStoreData[0].key, "foo", true, true);
|
||||
objectStore.count(keyRange).onsuccess = grabEventAndContinueHandler;
|
||||
event = yield;
|
||||
|
||||
is(event.target.result, objectStoreData.length - 1,
|
||||
"Correct number of object store entries for bound keyRange");
|
||||
|
||||
let index = objectStore.index(indexData.name);
|
||||
|
||||
index.count().onsuccess = grabEventAndContinueHandler;
|
||||
event = yield;
|
||||
|
||||
is(event.target.result, weightSort.length,
|
||||
"Correct number of index entries for no key");
|
||||
|
||||
index.count(objectStoreData[7].value.weight).onsuccess =
|
||||
grabEventAndContinueHandler;
|
||||
event = yield;
|
||||
|
||||
is(event.target.result, 2,
|
||||
"Correct number of index entries for duplicate key");
|
||||
|
||||
index.count(objectStoreData[0].value.weight).onsuccess =
|
||||
grabEventAndContinueHandler;
|
||||
event = yield;
|
||||
|
||||
is(event.target.result, 1,
|
||||
"Correct number of index entries for single key");
|
||||
|
||||
keyRange = IDBKeyRange.only(objectStoreData[0].value.weight);
|
||||
index.count(keyRange).onsuccess = grabEventAndContinueHandler;
|
||||
event = yield;
|
||||
|
||||
is(event.target.result, 1,
|
||||
"Correct number of index entries for only existing keyRange");
|
||||
|
||||
keyRange = IDBKeyRange.only("foo");
|
||||
index.count(keyRange).onsuccess = grabEventAndContinueHandler;
|
||||
event = yield;
|
||||
|
||||
is(event.target.result, 0,
|
||||
"Correct number of index entries for only non-existing keyRange");
|
||||
|
||||
keyRange = IDBKeyRange.only(objectStoreData[7].value.weight);
|
||||
index.count(keyRange).onsuccess = grabEventAndContinueHandler;
|
||||
event = yield;
|
||||
|
||||
is(event.target.result, 2,
|
||||
"Correct number of index entries for only duplicate keyRange");
|
||||
|
||||
keyRange = IDBKeyRange.lowerBound(objectStoreData[weightSort[0]].value.weight);
|
||||
index.count(keyRange).onsuccess = grabEventAndContinueHandler;
|
||||
event = yield;
|
||||
|
||||
is(event.target.result, weightSort.length,
|
||||
"Correct number of index entries for lowerBound keyRange");
|
||||
|
||||
keyRange = IDBKeyRange.lowerBound(objectStoreData[weightSort[1]].value.weight);
|
||||
index.count(keyRange).onsuccess = grabEventAndContinueHandler;
|
||||
event = yield;
|
||||
|
||||
is(event.target.result, weightSort.length - 1,
|
||||
"Correct number of index entries for lowerBound keyRange");
|
||||
|
||||
keyRange = IDBKeyRange.lowerBound(objectStoreData[weightSort[0]].value.weight - 1);
|
||||
index.count(keyRange).onsuccess = grabEventAndContinueHandler;
|
||||
event = yield;
|
||||
|
||||
is(event.target.result, weightSort.length,
|
||||
"Correct number of index entries for lowerBound keyRange");
|
||||
|
||||
keyRange = IDBKeyRange.lowerBound(objectStoreData[weightSort[0]].value.weight,
|
||||
true);
|
||||
index.count(keyRange).onsuccess = grabEventAndContinueHandler;
|
||||
event = yield;
|
||||
|
||||
is(event.target.result, weightSort.length - 1,
|
||||
"Correct number of index entries for lowerBound keyRange");
|
||||
|
||||
keyRange = IDBKeyRange.lowerBound(objectStoreData[weightSort[weightSort.length - 1]].value.weight);
|
||||
index.count(keyRange).onsuccess = grabEventAndContinueHandler;
|
||||
event = yield;
|
||||
|
||||
is(event.target.result, 1,
|
||||
"Correct number of index entries for lowerBound keyRange");
|
||||
|
||||
keyRange = IDBKeyRange.lowerBound(objectStoreData[weightSort[weightSort.length - 1]].value.weight,
|
||||
true);
|
||||
index.count(keyRange).onsuccess = grabEventAndContinueHandler;
|
||||
event = yield;
|
||||
|
||||
is(event.target.result, 0,
|
||||
"Correct number of index entries for lowerBound keyRange");
|
||||
|
||||
keyRange = IDBKeyRange.lowerBound(objectStoreData[weightSort[weightSort.length - 1]].value.weight + 1,
|
||||
true);
|
||||
index.count(keyRange).onsuccess = grabEventAndContinueHandler;
|
||||
event = yield;
|
||||
|
||||
is(event.target.result, 0,
|
||||
"Correct number of index entries for lowerBound keyRange");
|
||||
|
||||
keyRange = IDBKeyRange.upperBound(objectStoreData[weightSort[0]].value.weight);
|
||||
index.count(keyRange).onsuccess = grabEventAndContinueHandler;
|
||||
event = yield;
|
||||
|
||||
is(event.target.result, 1,
|
||||
"Correct number of index entries for upperBound keyRange");
|
||||
|
||||
keyRange = IDBKeyRange.upperBound(objectStoreData[weightSort[0]].value.weight,
|
||||
true);
|
||||
index.count(keyRange).onsuccess = grabEventAndContinueHandler;
|
||||
event = yield;
|
||||
|
||||
is(event.target.result, 0,
|
||||
"Correct number of index entries for upperBound keyRange");
|
||||
|
||||
keyRange = IDBKeyRange.upperBound(objectStoreData[weightSort[weightSort.length - 1]].value.weight);
|
||||
index.count(keyRange).onsuccess = grabEventAndContinueHandler;
|
||||
event = yield;
|
||||
|
||||
is(event.target.result, weightSort.length,
|
||||
"Correct number of index entries for upperBound keyRange");
|
||||
|
||||
keyRange = IDBKeyRange.upperBound(objectStoreData[weightSort[weightSort.length - 1]].value.weight,
|
||||
true);
|
||||
index.count(keyRange).onsuccess = grabEventAndContinueHandler;
|
||||
event = yield;
|
||||
|
||||
is(event.target.result, weightSort.length - 1,
|
||||
"Correct number of index entries for upperBound keyRange");
|
||||
|
||||
keyRange = IDBKeyRange.upperBound(objectStoreData[weightSort[weightSort.length - 1]].value.weight,
|
||||
true);
|
||||
index.count(keyRange).onsuccess = grabEventAndContinueHandler;
|
||||
event = yield;
|
||||
|
||||
is(event.target.result, weightSort.length - 1,
|
||||
"Correct number of index entries for upperBound keyRange");
|
||||
|
||||
keyRange = IDBKeyRange.upperBound("foo");
|
||||
index.count(keyRange).onsuccess = grabEventAndContinueHandler;
|
||||
event = yield;
|
||||
|
||||
is(event.target.result, weightSort.length,
|
||||
"Correct number of index entries for upperBound keyRange");
|
||||
|
||||
keyRange = IDBKeyRange.bound("foo", "foopy");
|
||||
index.count(keyRange).onsuccess = grabEventAndContinueHandler;
|
||||
event = yield;
|
||||
|
||||
is(event.target.result, 0,
|
||||
"Correct number of index entries for bound keyRange");
|
||||
|
||||
keyRange = IDBKeyRange.bound(objectStoreData[weightSort[0]].value.weight,
|
||||
objectStoreData[weightSort[weightSort.length - 1]].value.weight);
|
||||
index.count(keyRange).onsuccess = grabEventAndContinueHandler;
|
||||
event = yield;
|
||||
|
||||
is(event.target.result, weightSort.length,
|
||||
"Correct number of index entries for bound keyRange");
|
||||
|
||||
keyRange = IDBKeyRange.bound(objectStoreData[weightSort[0]].value.weight,
|
||||
objectStoreData[weightSort[weightSort.length - 1]].value.weight,
|
||||
true);
|
||||
index.count(keyRange).onsuccess = grabEventAndContinueHandler;
|
||||
event = yield;
|
||||
|
||||
is(event.target.result, weightSort.length - 1,
|
||||
"Correct number of index entries for bound keyRange");
|
||||
|
||||
keyRange = IDBKeyRange.bound(objectStoreData[weightSort[0]].value.weight,
|
||||
objectStoreData[weightSort[weightSort.length - 1]].value.weight,
|
||||
true, true);
|
||||
index.count(keyRange).onsuccess = grabEventAndContinueHandler;
|
||||
event = yield;
|
||||
|
||||
is(event.target.result, weightSort.length - 2,
|
||||
"Correct number of index entries for bound keyRange");
|
||||
|
||||
finishTest();
|
||||
yield;
|
||||
}
|
||||
</script>
|
||||
<script type="text/javascript;version=1.7" src="helpers.js"></script>
|
||||
</head>
|
||||
|
||||
<body onload="runTest();"></body>
|
||||
|
||||
</html>
|
|
@ -31,7 +31,7 @@
|
|||
request.onsuccess = continueToNextStep;
|
||||
yield;
|
||||
|
||||
transaction = db.transaction(db.objectStoreNames);
|
||||
transaction = db.transaction("foo");
|
||||
|
||||
let objectStore3 = transaction.objectStore("foo");
|
||||
let objectStore4 = transaction.objectStore("foo");
|
||||
|
|
|
@ -52,7 +52,11 @@
|
|||
class nsAutoJSValHolder
|
||||
{
|
||||
public:
|
||||
nsAutoJSValHolder() : mVal(JSVAL_NULL), mRt(nsnull)
|
||||
|
||||
nsAutoJSValHolder()
|
||||
: mRt(NULL)
|
||||
, mVal(JSVAL_NULL)
|
||||
, mHeld(JS_FALSE)
|
||||
{
|
||||
// nothing to do
|
||||
}
|
||||
|
@ -64,28 +68,10 @@ 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.
|
||||
*/
|
||||
bool Hold(JSContext* aCx) {
|
||||
JSBool Hold(JSContext* aCx) {
|
||||
return Hold(JS_GetRuntime(aCx));
|
||||
}
|
||||
|
||||
|
@ -93,18 +79,16 @@ public:
|
|||
* Hold by rooting on the runtime.
|
||||
* Note that mVal may be JSVAL_NULL, which is not a problem.
|
||||
*/
|
||||
bool Hold(JSRuntime* aRt) {
|
||||
// Do we really care about different runtimes?
|
||||
if (mRt && aRt != mRt) {
|
||||
js_RemoveRoot(mRt, &mVal);
|
||||
mRt = nsnull;
|
||||
JSBool Hold(JSRuntime* aRt) {
|
||||
if (!mHeld) {
|
||||
if (js_AddRootRT(aRt, &mVal, "nsAutoJSValHolder")) {
|
||||
mRt = aRt;
|
||||
mHeld = JS_TRUE;
|
||||
} else {
|
||||
Release(); // out of memory
|
||||
}
|
||||
}
|
||||
|
||||
if (!mRt && js_AddRootRT(aRt, &mVal, "nsAutoJSValHolder")) {
|
||||
mRt = aRt;
|
||||
}
|
||||
|
||||
return !!mRt;
|
||||
return mHeld;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -112,14 +96,17 @@ public:
|
|||
* the original jsval.
|
||||
*/
|
||||
jsval Release() {
|
||||
NS_ASSERTION(!mHeld || mRt, "Bad!");
|
||||
|
||||
jsval oldval = mVal;
|
||||
|
||||
if (mRt) {
|
||||
if (mHeld) {
|
||||
js_RemoveRoot(mRt, &mVal); // infallible
|
||||
mRt = nsnull;
|
||||
mHeld = JS_FALSE;
|
||||
}
|
||||
|
||||
mVal = JSVAL_NULL;
|
||||
mRt = NULL;
|
||||
|
||||
return oldval;
|
||||
}
|
||||
|
@ -127,8 +114,8 @@ public:
|
|||
/**
|
||||
* Determine if Hold has been called.
|
||||
*/
|
||||
bool IsHeld() const {
|
||||
return !!mRt;
|
||||
JSBool IsHeld() {
|
||||
return mHeld;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -137,7 +124,7 @@ public:
|
|||
JSObject* ToJSObject() const {
|
||||
return JSVAL_IS_OBJECT(mVal)
|
||||
? JSVAL_TO_OBJECT(mVal)
|
||||
: nsnull;
|
||||
: NULL;
|
||||
}
|
||||
|
||||
jsval* ToJSValPtr() {
|
||||
|
@ -150,13 +137,18 @@ 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_GCTHING(aOther) && !JSVAL_IS_NULL(aOther)) {
|
||||
NS_ASSERTION(IsHeld(), "Not rooted!");
|
||||
if (JSVAL_IS_OBJECT(aOther) && JSVAL_TO_OBJECT(aOther)) {
|
||||
NS_ASSERTION(mHeld, "Not rooted!");
|
||||
}
|
||||
#endif
|
||||
mVal = aOther;
|
||||
|
@ -164,8 +156,9 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
jsval mVal;
|
||||
JSRuntime* mRt;
|
||||
jsval mVal;
|
||||
JSBool mHeld;
|
||||
};
|
||||
|
||||
#endif /* __NSAUTOJSVALHOLDER_H__ */
|
||||
|
|
Загрузка…
Ссылка в новой задаче