Bug 1343728 - Part 3: Add StableStateEventTarget, an event target which runs dispatched runnables at the next stable state, r=smaug

MozReview-Commit-ID: 8dlo5Z60qsG
This commit is contained in:
Michael Layzell 2017-06-20 15:59:46 -04:00
Родитель a6f9d86063
Коммит 2e8a4708cd
2 изменённых файлов: 71 добавлений и 0 удалений

Просмотреть файл

@ -326,6 +326,7 @@ nsHtml5StringParser* nsContentUtils::sHTMLFragmentParser = nullptr;
nsIParser* nsContentUtils::sXMLFragmentParser = nullptr;
nsIFragmentContentSink* nsContentUtils::sXMLFragmentSink = nullptr;
bool nsContentUtils::sFragmentParsingActive = false;
nsISerialEventTarget* nsContentUtils::sStableStateEventTarget = nullptr;
#if !(defined(DEBUG) || defined(MOZ_ENABLE_JS_DUMP))
bool nsContentUtils::sDOMWindowDumpEnabled;
@ -519,6 +520,52 @@ class SameOriginCheckerImpl final : public nsIChannelEventSink,
NS_DECL_NSIINTERFACEREQUESTOR
};
class StableStateEventTarget final : public nsISerialEventTarget
{
public:
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIEVENTTARGET_FULL
private:
~StableStateEventTarget() {}
};
NS_IMPL_ISUPPORTS(StableStateEventTarget, nsISerialEventTarget);
bool
StableStateEventTarget::IsOnCurrentThreadInfallible()
{
return true;
}
NS_IMETHODIMP
StableStateEventTarget::IsOnCurrentThread(bool* aResult)
{
*aResult = true;
return NS_OK;
}
NS_IMETHODIMP
StableStateEventTarget::Dispatch(already_AddRefed<nsIRunnable> aEvent, uint32_t aFlags)
{
if (NS_WARN_IF(!CycleCollectedJSContext::Get())) {
return NS_ERROR_UNEXPECTED;
}
nsContentUtils::RunInStableState(Move(aEvent));
return NS_OK;
}
NS_IMETHODIMP
StableStateEventTarget::DispatchFromScript(nsIRunnable* aEvent, uint32_t aFlags)
{
return Dispatch(nsCOMPtr<nsIRunnable>(aEvent).forget(), aFlags);
}
NS_IMETHODIMP
StableStateEventTarget::DelayedDispatch(already_AddRefed<nsIRunnable> aEvent, uint32_t aDelay)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
} // namespace
/**
@ -730,6 +777,9 @@ nsContentUtils::Init()
Unused << nsRFPService::GetOrCreate();
RefPtr<StableStateEventTarget> stableStateEventTarget = new StableStateEventTarget();
stableStateEventTarget.forget(&sStableStateEventTarget);
nsCOMPtr<nsIUUIDGenerator> uuidGenerator =
do_GetService("@mozilla.org/uuid-generator;1", &rv);
if (NS_WARN_IF(NS_FAILED(rv))) {
@ -2156,6 +2206,8 @@ nsContentUtils::Shutdown()
NS_IF_RELEASE(sSameOriginChecker);
NS_IF_RELEASE(sStableStateEventTarget);
if (sUserInteractionObserver) {
sUserInteractionObserver->Shutdown();
NS_RELEASE(sUserInteractionObserver);
@ -5661,6 +5713,13 @@ nsContentUtils::RunInMetastableState(already_AddRefed<nsIRunnable> aRunnable)
CycleCollectedJSContext::Get()->RunInMetastableState(Move(aRunnable));
}
/* static */
nsISerialEventTarget*
nsContentUtils::GetStableStateEventTarget()
{
return sStableStateEventTarget;
}
void
nsContentUtils::EnterMicroTask()
{

Просмотреть файл

@ -1879,6 +1879,16 @@ public:
*/
static void RunInMetastableState(already_AddRefed<nsIRunnable> aRunnable);
/**
* Returns a nsISerialEventTarget which will run any event dispatched to it
* once the event loop has reached a "stable state". Runnables dispatched to
* this event target must not cause any queued events to be processed (i.e.
* must not spin the event loop).
*
* See RunInStableState for more information about stable states
*/
static nsISerialEventTarget* GetStableStateEventTarget();
// Call EnterMicroTask when you're entering JS execution.
// Usually the best way to do this is to use nsAutoMicroTask.
static void EnterMicroTask();
@ -3227,6 +3237,8 @@ private:
*/
static bool sFragmentParsingActive;
static nsISerialEventTarget* sStableStateEventTarget;
static nsString* sShiftText;
static nsString* sControlText;
static nsString* sMetaText;