From 2e8a4708cd7fa884c04727b66bea2d6166ca3e0f Mon Sep 17 00:00:00 2001 From: Michael Layzell Date: Tue, 20 Jun 2017 15:59:46 -0400 Subject: [PATCH] Bug 1343728 - Part 3: Add StableStateEventTarget, an event target which runs dispatched runnables at the next stable state, r=smaug MozReview-Commit-ID: 8dlo5Z60qsG --- dom/base/nsContentUtils.cpp | 59 +++++++++++++++++++++++++++++++++++++ dom/base/nsContentUtils.h | 12 ++++++++ 2 files changed, 71 insertions(+) diff --git a/dom/base/nsContentUtils.cpp b/dom/base/nsContentUtils.cpp index 931ca8fae063..b2dd845f69e1 100644 --- a/dom/base/nsContentUtils.cpp +++ b/dom/base/nsContentUtils.cpp @@ -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 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(aEvent).forget(), aFlags); +} + +NS_IMETHODIMP +StableStateEventTarget::DelayedDispatch(already_AddRefed aEvent, uint32_t aDelay) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + } // namespace /** @@ -730,6 +777,9 @@ nsContentUtils::Init() Unused << nsRFPService::GetOrCreate(); + RefPtr stableStateEventTarget = new StableStateEventTarget(); + stableStateEventTarget.forget(&sStableStateEventTarget); + nsCOMPtr 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 aRunnable) CycleCollectedJSContext::Get()->RunInMetastableState(Move(aRunnable)); } +/* static */ +nsISerialEventTarget* +nsContentUtils::GetStableStateEventTarget() +{ + return sStableStateEventTarget; +} + void nsContentUtils::EnterMicroTask() { diff --git a/dom/base/nsContentUtils.h b/dom/base/nsContentUtils.h index ae3c5fd2ad18..da3b8c3ecb4d 100644 --- a/dom/base/nsContentUtils.h +++ b/dom/base/nsContentUtils.h @@ -1879,6 +1879,16 @@ public: */ static void RunInMetastableState(already_AddRefed 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;