summaryrefslogtreecommitdiffstats
path: root/xpcom
diff options
context:
space:
mode:
Diffstat (limited to 'xpcom')
-rw-r--r--xpcom/base/CycleCollectedJSContext.cpp12
-rw-r--r--xpcom/base/CycleCollectedJSContext.h51
-rw-r--r--xpcom/base/moz.build1
3 files changed, 63 insertions, 1 deletions
diff --git a/xpcom/base/CycleCollectedJSContext.cpp b/xpcom/base/CycleCollectedJSContext.cpp
index e16c15455..0a85ae6ac 100644
--- a/xpcom/base/CycleCollectedJSContext.cpp
+++ b/xpcom/base/CycleCollectedJSContext.cpp
@@ -79,6 +79,7 @@
#include "nsCycleCollectionParticipant.h"
#include "nsCycleCollector.h"
#include "nsDOMJSUtils.h"
+#include "nsDOMMutationObserver.h"
#include "nsJSUtils.h"
#include "nsWrapperCache.h"
@@ -438,6 +439,7 @@ CycleCollectedJSContext::CycleCollectedJSContext()
, mJSHolders(256)
, mDoingStableStates(false)
, mDisableMicroTaskCheckpoint(false)
+ , mMicroTaskLevel(0)
, mOutOfMemoryState(OOMState::OK)
, mLargeAllocationFailureState(OOMState::OK)
{
@@ -1379,7 +1381,7 @@ CycleCollectedJSContext::AfterProcessTask(uint32_t aRecursionDepth)
// Step 4.1: Execute microtasks.
if (!mDisableMicroTaskCheckpoint) {
if (NS_IsMainThread()) {
- nsContentUtils::PerformMainThreadMicroTaskCheckpoint();
+ PerformMainThreadMicroTaskCheckpoint();
Promise::PerformMicroTaskCheckpoint();
} else {
Promise::PerformWorkerMicroTaskCheckpoint();
@@ -1660,6 +1662,14 @@ CycleCollectedJSContext::DispatchToMicroTask(already_AddRefed<nsIRunnable> aRunn
}
void
+CycleCollectedJSContext::PerformMainThreadMicroTaskCheckpoint()
+{
+ MOZ_ASSERT(NS_IsMainThread());
+
+ nsDOMMutationObserver::HandleMutations();
+}
+
+void
CycleCollectedJSContext::EnvironmentPreparer::invoke(JS::HandleObject scope,
js::ScriptEnvironmentPreparer::Closure& closure)
{
diff --git a/xpcom/base/CycleCollectedJSContext.h b/xpcom/base/CycleCollectedJSContext.h
index ac4cf4361..2197eae92 100644
--- a/xpcom/base/CycleCollectedJSContext.h
+++ b/xpcom/base/CycleCollectedJSContext.h
@@ -402,6 +402,37 @@ public:
// Queue an async microtask to the current main or worker thread.
virtual void DispatchToMicroTask(already_AddRefed<nsIRunnable> aRunnable);
+ // Call EnterMicroTask when you're entering JS execution.
+ // Usually the best way to do this is to use nsAutoMicroTask.
+ void EnterMicroTask()
+ {
+ ++mMicroTaskLevel;
+ }
+
+ void LeaveMicroTask()
+ {
+ if (--mMicroTaskLevel == 0) {
+ PerformMainThreadMicroTaskCheckpoint();
+ }
+ }
+
+ bool IsInMicroTask()
+ {
+ return mMicroTaskLevel != 0;
+ }
+
+ uint32_t MicroTaskLevel()
+ {
+ return mMicroTaskLevel;
+ }
+
+ void SetMicroTaskLevel(uint32_t aLevel)
+ {
+ mMicroTaskLevel = aLevel;
+ }
+
+ void PerformMainThreadMicroTaskCheckpoint();
+
// Storage for watching rejected promises waiting for some client to
// consume their rejection.
@@ -452,6 +483,7 @@ private:
bool mDisableMicroTaskCheckpoint;
+ uint32_t mMicroTaskLevel;
OOMState mOutOfMemoryState;
OOMState mLargeAllocationFailureState;
@@ -470,6 +502,25 @@ private:
EnvironmentPreparer mEnvironmentPreparer;
};
+class MOZ_STACK_CLASS nsAutoMicroTask
+{
+public:
+ nsAutoMicroTask()
+ {
+ CycleCollectedJSContext* ccjs = CycleCollectedJSContext::Get();
+ if (ccjs) {
+ ccjs->EnterMicroTask();
+ }
+ }
+ ~nsAutoMicroTask()
+ {
+ CycleCollectedJSContext* ccjs = CycleCollectedJSContext::Get();
+ if (ccjs) {
+ ccjs->LeaveMicroTask();
+ }
+ }
+};
+
void TraceScriptHolder(nsISupports* aHolder, JSTracer* aTracer);
// Returns true if the JS::TraceKind is one the cycle collector cares about.
diff --git a/xpcom/base/moz.build b/xpcom/base/moz.build
index d6a336b40..0fdf47d7d 100644
--- a/xpcom/base/moz.build
+++ b/xpcom/base/moz.build
@@ -152,6 +152,7 @@ FINAL_LIBRARY = 'xul'
LOCAL_INCLUDES += [
'../build',
+ '/dom/base',
'/xpcom/ds',
]