Issue #2452 - Handle re-entrant Microtask checkpoints from Events dispatched by StableState callbacks

This commit is contained in:
Martok
2024-01-16 11:04:58 +01:00
committed by roytam1
parent fbd829908e
commit a2c28b4268
2 changed files with 27 additions and 4 deletions
+4 -3
View File
@@ -695,9 +695,10 @@ EventDispatcher::Dispatch(nsISupports* aTarget,
// Events shall not be fired while we are in stable state to prevent anything
// visible from the scripts.
MOZ_ASSERT(!nsContentUtils::IsInStableOrMetaStableState());
NS_ENSURE_TRUE(!nsContentUtils::IsInStableOrMetaStableState(),
NS_ERROR_DOM_INVALID_STATE_ERR);
// See comment in CycleCollectedJSContext::AfterProcessMicrotasks for why we allow it anyway.
// MOZ_ASSERT(!nsContentUtils::IsInStableOrMetaStableState());
// NS_ENSURE_TRUE(!nsContentUtils::IsInStableOrMetaStableState(),
// NS_ERROR_DOM_INVALID_STATE_ERR);
#ifdef MOZ_TASK_TRACER
{
+23 -1
View File
@@ -1479,7 +1479,29 @@ CycleCollectedJSContext::AfterProcessMicrotasks()
}
// Cleanup Indexed Database transactions:
// https://html.spec.whatwg.org/multipage/webappapis.html#perform-a-microtask-checkpoint
CleanupIDBTransactions(RecursionDepth());
// We should only ever get here from PerformMicroTaskCheckPoint after a task or other
// checkpoint-able state, never from within ProcessStableStateQueue (mDoingStableStates==false).
// However, some buggy XUL addons may dispatch JS Events from runnables in the StableState queue,
// which then perform a checkpoint at their end, ending up here while ProcessStableStateQueue is
// on the stack.
// Specifically catch that here and add the call to CleanupIDBTransactions to the outer queue, to
// be performed when we know we're in a "regular" stable state again.
if (!mDoingStableStates) {
CleanupIDBTransactions(RecursionDepth());
} else {
// Don't need a RefPtr to this here as we know this->ProcessStableStateQueue is on the stack
nsCOMPtr<nsIRunnable> cleanupRunnable = NS_NewRunnableFunction(
[this, rec = RecursionDepth()] {
MOZ_ASSERT(mDoingStableStates);
// As this is called from ProcessStableStateQueue, mDoingStableStates == true.
// Switch the flag while CleanupIDBTransactions executes.
mDoingStableStates = false;
CleanupIDBTransactions(rec);
mDoingStableStates = true;
});
RunInStableState(cleanupRunnable.forget());
};
}
uint32_t