Skip to content

Commit

Permalink
Bug 718132 - IndexedDB: Intermittent Failing to get JS wrapper in IDB…
Browse files Browse the repository at this point in the history
…Request::NotifyHelperCompleted. r=khuey.
  • Loading branch information
benturner committed Jan 24, 2012
1 parent 6f68931 commit b693b17
Show file tree
Hide file tree
Showing 22 changed files with 468 additions and 391 deletions.
5 changes: 3 additions & 2 deletions content/base/src/nsContentUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5436,8 +5436,9 @@ class DebugWrapperTraversalCallback : public nsCycleCollectionTraversalCallback
}
NS_IMETHOD_(void) NoteScriptChild(PRUint32 langID, void* child)
{
if (langID == nsIProgrammingLanguage::JAVASCRIPT) {
mFound = child == mWrapper;
if (langID == nsIProgrammingLanguage::JAVASCRIPT &&
child == mWrapper) {
mFound = true;
}
}
NS_IMETHOD_(void) NoteXPCOMChild(nsISupports *child)
Expand Down
80 changes: 72 additions & 8 deletions dom/base/nsDOMClassInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -490,6 +490,7 @@
#include "DOMSVGPointList.h"
#include "DOMSVGTransformList.h"

#include "mozilla/dom/indexedDB/IDBWrapperCache.h"
#include "mozilla/dom/indexedDB/IDBFactory.h"
#include "mozilla/dom/indexedDB/IDBRequest.h"
#include "mozilla/dom/indexedDB/IDBDatabase.h"
Expand All @@ -501,6 +502,8 @@
#include "mozilla/dom/indexedDB/IDBIndex.h"
#include "nsIIDBDatabaseException.h"

using mozilla::dom::indexedDB::IDBWrapperCache;

#include "nsIDOMMediaQueryList.h"

#include "nsDOMTouchEvent.h"
Expand Down Expand Up @@ -593,6 +596,9 @@ static const char kDOMStringBundleURL[] =
(DOM_DEFAULT_SCRIPTABLE_FLAGS | \
nsIXPCScriptable::WANT_ADDPROPERTY)

#define IDBEVENTTARGET_SCRIPTABLE_FLAGS \
(EVENTTARGET_SCRIPTABLE_FLAGS)

#define DOMCLASSINFO_STANDARD_FLAGS \
(nsIClassInfo::MAIN_THREAD_ONLY | nsIClassInfo::DOM_OBJECT)

Expand Down Expand Up @@ -654,6 +660,34 @@ DOMCI_DATA(DOMConstructor, void)
NS_DEFINE_CHROME_ONLY_CLASSINFO_DATA_WITH_NAME(_class, _class, _helper, \
_flags)

namespace {

class IDBEventTargetSH : public nsEventTargetSH
{
protected:
IDBEventTargetSH(nsDOMClassInfoData* aData) : nsEventTargetSH(aData)
{ }

virtual ~IDBEventTargetSH()
{ }

public:
NS_IMETHOD PreCreate(nsISupports *aNativeObj, JSContext *aCx,
JSObject *aGlobalObj, JSObject **aParentObj);

NS_IMETHOD AddProperty(nsIXPConnectWrappedNative *aWrapper, JSContext *aCx,
JSObject *aObj, jsid aId, jsval *aVp, bool *aRetval);

virtual void PreserveWrapper(nsISupports *aNative);

static nsIClassInfo *doCreate(nsDOMClassInfoData *aData)
{
return new IDBEventTargetSH(aData);
}
};

} // anonymous namespace

// This list of NS_DEFINE_CLASSINFO_DATA macros is what gives the DOM
// classes their correct behavior when used through XPConnect. The
// arguments that are passed to NS_DEFINE_CLASSINFO_DATA are
Expand Down Expand Up @@ -1537,14 +1571,14 @@ static nsDOMClassInfoData sClassInfoData[] = {

NS_DEFINE_CLASSINFO_DATA(IDBFactory, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(IDBRequest, nsEventTargetSH,
EVENTTARGET_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(IDBDatabase, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(IDBRequest, IDBEventTargetSH,
IDBEVENTTARGET_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(IDBDatabase, IDBEventTargetSH,
IDBEVENTTARGET_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(IDBObjectStore, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(IDBTransaction, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(IDBTransaction, IDBEventTargetSH,
IDBEVENTTARGET_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(IDBCursor, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(IDBCursorWithValue, nsDOMGenericSH,
Expand All @@ -1555,8 +1589,8 @@ static nsDOMClassInfoData sClassInfoData[] = {
DOM_DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(IDBVersionChangeEvent, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(IDBOpenDBRequest, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(IDBOpenDBRequest, IDBEventTargetSH,
IDBEVENTTARGET_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(IDBDatabaseException, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)

Expand Down Expand Up @@ -7612,6 +7646,36 @@ nsEventTargetSH::PreserveWrapper(nsISupports *aNative)
nsContentUtils::PreserveWrapper(aNative, target);
}

// IDBEventTarget helper

NS_IMETHODIMP
IDBEventTargetSH::PreCreate(nsISupports *aNativeObj, JSContext *aCx,
JSObject *aGlobalObj, JSObject **aParentObj)
{
IDBWrapperCache *target = IDBWrapperCache::FromSupports(aNativeObj);
JSObject *parent = target->GetParentObject();
*aParentObj = parent ? parent : aGlobalObj;
return NS_OK;
}

NS_IMETHODIMP
IDBEventTargetSH::AddProperty(nsIXPConnectWrappedNative *aWrapper,
JSContext *aCx, JSObject *aObj, jsid aId,
jsval *aVp, bool *aRetval)
{
if (aId != sAddEventListener_id) {
IDBEventTargetSH::PreserveWrapper(GetNative(aWrapper, aObj));
}

return NS_OK;
}

void
IDBEventTargetSH::PreserveWrapper(nsISupports *aNative)
{
IDBWrapperCache *target = IDBWrapperCache::FromSupports(aNative);
nsContentUtils::PreserveWrapper(aNative, target);
}

// Element helper

Expand Down
15 changes: 4 additions & 11 deletions dom/indexedDB/AsyncConnectionHelper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -146,18 +146,11 @@ HelperBase::WrapNative(JSContext* aCx,
NS_ASSERTION(aResult, "Null pointer!");
NS_ASSERTION(mRequest, "Null request!");

JSObject* obj;
if (mRequest->ScriptContext()) {
obj = mRequest->ScriptContext()->GetNativeGlobal();
}
else {
obj = mRequest->GetWrapper();
}

NS_ENSURE_TRUE(obj, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
JSObject* global = mRequest->GetParentObject();
NS_ASSERTION(global, "This should never be null!");

nsresult rv =
nsContentUtils::WrapNative(aCx, obj, aNative, aResult);
nsContentUtils::WrapNative(aCx, global, aNative, aResult);
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);

return NS_OK;
Expand Down Expand Up @@ -288,7 +281,7 @@ AsyncConnectionHelper::Run()
if (NS_SUCCEEDED(rv)) {
bool hasSavepoint = false;
if (mDatabase) {
IndexedDatabaseManager::SetCurrentWindow(mDatabase->Owner());
IndexedDatabaseManager::SetCurrentWindow(mDatabase->GetOwner());

// Make the first savepoint.
if (mTransaction) {
Expand Down
18 changes: 13 additions & 5 deletions dom/indexedDB/IDBCursor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,7 @@ GenerateRequest(IDBCursor* aCursor)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
IDBDatabase* database = aCursor->Transaction()->Database();
return IDBRequest::Create(aCursor, database->ScriptContext(),
database->Owner(), aCursor->Transaction());
return IDBRequest::Create(aCursor, database, aCursor->Transaction());
}

} // anonymous namespace
Expand Down Expand Up @@ -262,11 +261,14 @@ IDBCursor::CreateCommon(IDBRequest* aRequest,

nsRefPtr<IDBCursor> cursor = new IDBCursor();

IDBDatabase* database = aTransaction->Database();
cursor->mScriptContext = database->GetScriptContext();
cursor->mOwner = database->GetOwner();
cursor->mScriptOwner = database->GetScriptOwner();

cursor->mRequest = aRequest;
cursor->mTransaction = aTransaction;
cursor->mObjectStore = aObjectStore;
cursor->mScriptContext = aTransaction->Database()->ScriptContext();
cursor->mOwner = aTransaction->Database()->Owner();
cursor->mDirection = aDirection;
cursor->mContinueQuery = aContinueQuery;
cursor->mContinueToQuery = aContinueToQuery;
Expand All @@ -276,7 +278,8 @@ IDBCursor::CreateCommon(IDBRequest* aRequest,
}

IDBCursor::IDBCursor()
: mType(OBJECTSTORE),
: mScriptOwner(nsnull),
mType(OBJECTSTORE),
mDirection(nsIIDBCursor::NEXT),
mCachedKey(JSVAL_VOID),
mCachedPrimaryKey(JSVAL_VOID),
Expand Down Expand Up @@ -377,6 +380,10 @@ NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(IDBCursor)
"Should have a cached primary key");
NS_ASSERTION(tmp->mHaveCachedValue || JSVAL_IS_VOID(tmp->mCachedValue),
"Should have a cached value");
if (tmp->mScriptOwner) {
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_CALLBACK(tmp->mScriptOwner,
"mScriptOwner")
}
if (JSVAL_IS_GCTHING(tmp->mCachedKey)) {
void *gcThing = JSVAL_TO_GCTHING(tmp->mCachedKey);
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_CALLBACK(gcThing, "mCachedKey")
Expand All @@ -395,6 +402,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(IDBCursor)
// Don't unlink mObjectStore, mIndex, or mTransaction!
if (tmp->mRooted) {
NS_DROP_JS_OBJECTS(tmp, IDBCursor);
tmp->mScriptOwner = nsnull;
tmp->mCachedKey = JSVAL_VOID;
tmp->mCachedPrimaryKey = JSVAL_VOID;
tmp->mCachedValue = JSVAL_VOID;
Expand Down
1 change: 1 addition & 0 deletions dom/indexedDB/IDBCursor.h
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ class IDBCursor : public nsIIDBCursorWithValue

nsCOMPtr<nsIScriptContext> mScriptContext;
nsCOMPtr<nsPIDOMWindow> mOwner;
JSObject* mScriptOwner;

Type mType;
PRUint16 mDirection;
Expand Down
84 changes: 24 additions & 60 deletions dom/indexedDB/IDBDatabase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -148,8 +148,7 @@ class AutoRemoveObjectStore

// static
already_AddRefed<IDBDatabase>
IDBDatabase::Create(nsIScriptContext* aScriptContext,
nsPIDOMWindow* aOwner,
IDBDatabase::Create(IDBWrapperCache* aOwnerCache,
already_AddRefed<DatabaseInfo> aDatabaseInfo,
const nsACString& aASCIIOrigin,
FileManager* aFileManager)
Expand All @@ -162,8 +161,9 @@ IDBDatabase::Create(nsIScriptContext* aScriptContext,

nsRefPtr<IDBDatabase> db(new IDBDatabase());

db->mScriptContext = aScriptContext;
db->mOwner = aOwner;
db->mScriptContext = aOwnerCache->GetScriptContext();
db->mOwner = aOwnerCache->GetOwner();
db->mScriptOwner = aOwnerCache->GetScriptOwner();

db->mDatabaseId = databaseInfo->id;
db->mName = databaseInfo->name;
Expand Down Expand Up @@ -205,6 +205,8 @@ IDBDatabase::~IDBDatabase()
mgr->UnregisterDatabase(this);
}
}

nsContentUtils::ReleaseWrapper(static_cast<nsIDOMEventTarget*>(this), this);
}

void
Expand All @@ -218,7 +220,7 @@ IDBDatabase::Invalidate()
// When the IndexedDatabaseManager needs to invalidate databases, all it has
// is an origin, so we call back into the manager to cancel any prompts for
// our owner.
IndexedDatabaseManager::CancelPromptsForWindow(Owner());
IndexedDatabaseManager::CancelPromptsForWindow(GetOwner());

mInvalidated = true;
}
Expand Down Expand Up @@ -280,7 +282,8 @@ void
IDBDatabase::OnUnlink()
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
NS_ASSERTION(!mOwner, "Should have been cleared already!");
NS_ASSERTION(!GetOwner() && !GetScriptOwner(),
"Should have been cleared already!");

// We've been unlinked, at the very least we should be able to prevent further
// transactions from starting and unblock any other SetVersion callers.
Expand All @@ -298,18 +301,16 @@ IDBDatabase::OnUnlink()

NS_IMPL_CYCLE_COLLECTION_CLASS(IDBDatabase)

NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(IDBDatabase,
nsDOMEventTargetHelper)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOnAbortListener)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOnErrorListener)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOnVersionChangeListener)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(IDBDatabase, IDBWrapperCache)
NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(abort)
NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(error)
NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(versionchange)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END

NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(IDBDatabase,
nsDOMEventTargetHelper)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOnAbortListener)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOnErrorListener)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOnVersionChangeListener)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(IDBDatabase, IDBWrapperCache)
NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(abort)
NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(error)
NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(versionchange)

// Do some cleanup.
tmp->OnUnlink();
Expand All @@ -318,13 +319,17 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(IDBDatabase)
NS_INTERFACE_MAP_ENTRY(nsIIDBDatabase)
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(IDBDatabase)
NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
NS_INTERFACE_MAP_END_INHERITING(IDBWrapperCache)

NS_IMPL_ADDREF_INHERITED(IDBDatabase, nsDOMEventTargetHelper)
NS_IMPL_RELEASE_INHERITED(IDBDatabase, nsDOMEventTargetHelper)
NS_IMPL_ADDREF_INHERITED(IDBDatabase, IDBWrapperCache)
NS_IMPL_RELEASE_INHERITED(IDBDatabase, IDBWrapperCache)

DOMCI_DATA(IDBDatabase, IDBDatabase)

NS_IMPL_EVENT_HANDLER(IDBDatabase, abort);
NS_IMPL_EVENT_HANDLER(IDBDatabase, error);
NS_IMPL_EVENT_HANDLER(IDBDatabase, versionchange);

NS_IMETHODIMP
IDBDatabase::GetName(nsAString& aName)
{
Expand Down Expand Up @@ -668,47 +673,6 @@ IDBDatabase::Close()
return NS_OK;
}

NS_IMETHODIMP
IDBDatabase::SetOnabort(nsIDOMEventListener* aAbortListener)
{
return RemoveAddEventListener(NS_LITERAL_STRING(ABORT_EVT_STR),
mOnAbortListener, aAbortListener);
}

NS_IMETHODIMP
IDBDatabase::GetOnabort(nsIDOMEventListener** aAbortListener)
{
return GetInnerEventListener(mOnAbortListener, aAbortListener);
}

NS_IMETHODIMP
IDBDatabase::SetOnerror(nsIDOMEventListener* aErrorListener)
{
return RemoveAddEventListener(NS_LITERAL_STRING(ERROR_EVT_STR),
mOnErrorListener, aErrorListener);
}

NS_IMETHODIMP
IDBDatabase::GetOnerror(nsIDOMEventListener** aErrorListener)
{
return GetInnerEventListener(mOnErrorListener, aErrorListener);
}

NS_IMETHODIMP
IDBDatabase::SetOnversionchange(nsIDOMEventListener* aVersionChangeListener)
{
return RemoveAddEventListener(NS_LITERAL_STRING(VERSIONCHANGE_EVT_STR),
mOnVersionChangeListener,
aVersionChangeListener);
}

NS_IMETHODIMP
IDBDatabase::GetOnversionchange(nsIDOMEventListener** aVersionChangeListener)
{
return GetInnerEventListener(mOnVersionChangeListener,
aVersionChangeListener);
}

nsresult
IDBDatabase::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
{
Expand Down
Loading

0 comments on commit b693b17

Please sign in to comment.