From 2077cdb41e3ef814cbbef482774d8bbec464fb1c Mon Sep 17 00:00:00 2001 From: Gaming4JC Date: Wed, 22 Jan 2020 21:07:19 -0500 Subject: Bug 1406922 - Make CycleCollectedJSContext to handle microtasks and make MutationObserver to use them Tag UXP Issue #1344 --- dom/base/nsDOMMutationObserver.cpp | 67 +++++++++++++++++--------------------- 1 file changed, 30 insertions(+), 37 deletions(-) (limited to 'dom/base/nsDOMMutationObserver.cpp') diff --git a/dom/base/nsDOMMutationObserver.cpp b/dom/base/nsDOMMutationObserver.cpp index 858a30ce5..4c4731c11 100644 --- a/dom/base/nsDOMMutationObserver.cpp +++ b/dom/base/nsDOMMutationObserver.cpp @@ -32,8 +32,6 @@ using mozilla::dom::Element; AutoTArray, 4>* nsDOMMutationObserver::sScheduledMutationObservers = nullptr; -nsDOMMutationObserver* nsDOMMutationObserver::sCurrentObserver = nullptr; - uint32_t nsDOMMutationObserver::sMutationLevel = 0; uint64_t nsDOMMutationObserver::sCount = 0; @@ -597,10 +595,32 @@ nsDOMMutationObserver::ScheduleForRun() RescheduleForRun(); } +class MutationObserverMicroTask final : public MicroTaskRunnable +{ +public: + virtual void Run(AutoSlowOperation& aAso) override + { + nsDOMMutationObserver::HandleMutations(aAso); + } + + virtual bool Suppressed() override + { + return nsDOMMutationObserver::AllScheduledMutationObserversAreSuppressed(); + } +}; + void nsDOMMutationObserver::RescheduleForRun() { if (!sScheduledMutationObservers) { + CycleCollectedJSContext* ccjs = CycleCollectedJSContext::Get(); + if (!ccjs) { + return; + } + + RefPtr momt = + new MutationObserverMicroTask(); + ccjs->DispatchMicroTaskRunnable(momt.forget()); sScheduledMutationObservers = new AutoTArray, 4>; } @@ -862,36 +882,9 @@ nsDOMMutationObserver::HandleMutation() mCallback->Call(this, mutations, *this); } -class AsyncMutationHandler : public mozilla::Runnable -{ -public: - NS_IMETHOD Run() override - { - nsDOMMutationObserver::HandleMutations(); - return NS_OK; - } -}; - void -nsDOMMutationObserver::HandleMutationsInternal() +nsDOMMutationObserver::HandleMutationsInternal(AutoSlowOperation& aAso) { - if (!nsContentUtils::IsSafeToRunScript()) { - nsContentUtils::AddScriptRunner(new AsyncMutationHandler()); - return; - } - static RefPtr sCurrentObserver; - if (sCurrentObserver && !sCurrentObserver->Suppressed()) { - // In normal cases sScheduledMutationObservers will be handled - // after previous mutations are handled. But in case some - // callback calls a sync API, which spins the eventloop, we need to still - // process other mutations happening during that sync call. - // This does *not* catch all cases, but should work for stuff running - // in separate tabs. - return; - } - - mozilla::AutoSlowOperation aso; - nsTArray >* suppressedObservers = nullptr; while (sScheduledMutationObservers) { @@ -899,20 +892,21 @@ nsDOMMutationObserver::HandleMutationsInternal() sScheduledMutationObservers; sScheduledMutationObservers = nullptr; for (uint32_t i = 0; i < observers->Length(); ++i) { - sCurrentObserver = static_cast((*observers)[i]); - if (!sCurrentObserver->Suppressed()) { - sCurrentObserver->HandleMutation(); + RefPtr currentObserver = + static_cast((*observers)[i]); + if (!currentObserver->Suppressed()) { + currentObserver->HandleMutation(); } else { if (!suppressedObservers) { suppressedObservers = new nsTArray >; } - if (!suppressedObservers->Contains(sCurrentObserver)) { - suppressedObservers->AppendElement(sCurrentObserver); + if (!suppressedObservers->Contains(currentObserver)) { + suppressedObservers->AppendElement(currentObserver); } } } delete observers; - aso.CheckForInterrupt(); + aAso.CheckForInterrupt(); } if (suppressedObservers) { @@ -923,7 +917,6 @@ nsDOMMutationObserver::HandleMutationsInternal() delete suppressedObservers; suppressedObservers = nullptr; } - sCurrentObserver = nullptr; } nsDOMMutationRecord* -- cgit v1.2.3