mirror of
https://github.com/roytam1/basilisk55.git
synced 2026-05-26 15:02:46 +00:00
import from UXP: Bug 1406922 - Make CycleCollectedJSContext to handle microtasks and make MutationObserver to use them (24966709)
This commit is contained in:
@@ -443,6 +443,7 @@ CycleCollectedJSContext::CycleCollectedJSContext()
|
||||
, mDoingStableStates(false)
|
||||
, mDisableMicroTaskCheckpoint(false)
|
||||
, mMicroTaskLevel(0)
|
||||
, mMicroTaskRecursionDepth(0)
|
||||
, mOutOfMemoryState(OOMState::OK)
|
||||
, mLargeAllocationFailureState(OOMState::OK)
|
||||
{
|
||||
@@ -1405,8 +1406,8 @@ CycleCollectedJSContext::AfterProcessTask(uint32_t aRecursionDepth)
|
||||
|
||||
// Step 4.1: Execute microtasks.
|
||||
if (!mDisableMicroTaskCheckpoint) {
|
||||
PerformMicroTaskCheckPoint();
|
||||
if (NS_IsMainThread()) {
|
||||
PerformMainThreadMicroTaskCheckpoint();
|
||||
Promise::PerformMicroTaskCheckpoint();
|
||||
} else {
|
||||
Promise::PerformWorkerMicroTaskCheckpoint();
|
||||
@@ -1689,12 +1690,70 @@ CycleCollectedJSContext::DispatchToMicroTask(already_AddRefed<nsIRunnable> aRunn
|
||||
mPromiseMicroTaskQueue.push(runnable.forget());
|
||||
}
|
||||
|
||||
void
|
||||
CycleCollectedJSContext::PerformMainThreadMicroTaskCheckpoint()
|
||||
class AsyncMutationHandler final : public mozilla::Runnable
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
public:
|
||||
NS_IMETHOD Run() override
|
||||
{
|
||||
CycleCollectedJSContext* ccjs = CycleCollectedJSContext::Get();
|
||||
if (ccjs) {
|
||||
ccjs->PerformMicroTaskCheckPoint();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
};
|
||||
|
||||
nsDOMMutationObserver::HandleMutations();
|
||||
void
|
||||
CycleCollectedJSContext::PerformMicroTaskCheckPoint()
|
||||
{
|
||||
if (mPendingMicroTaskRunnables.empty()) {
|
||||
// Nothing to do, return early.
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t currentDepth = RecursionDepth();
|
||||
if (mMicroTaskRecursionDepth >= currentDepth) {
|
||||
// We are already executing microtasks for the current recursion depth.
|
||||
return;
|
||||
}
|
||||
|
||||
if (NS_IsMainThread() && !nsContentUtils::IsSafeToRunScript()) {
|
||||
// Special case for main thread where DOM mutations may happen when
|
||||
// it is not safe to run scripts.
|
||||
nsContentUtils::AddScriptRunner(new AsyncMutationHandler());
|
||||
return;
|
||||
}
|
||||
|
||||
mozilla::AutoRestore<uint32_t> restore(mMicroTaskRecursionDepth);
|
||||
MOZ_ASSERT(currentDepth > 0);
|
||||
mMicroTaskRecursionDepth = currentDepth;
|
||||
|
||||
AutoSlowOperation aso;
|
||||
|
||||
std::queue<RefPtr<MicroTaskRunnable>> suppressed;
|
||||
while (!mPendingMicroTaskRunnables.empty()) {
|
||||
RefPtr<MicroTaskRunnable> runnable =
|
||||
mPendingMicroTaskRunnables.front().forget();
|
||||
mPendingMicroTaskRunnables.pop();
|
||||
if (runnable->Suppressed()) {
|
||||
suppressed.push(runnable);
|
||||
} else {
|
||||
runnable->Run(aso);
|
||||
}
|
||||
}
|
||||
|
||||
// Put back the suppressed microtasks so that they will be run later.
|
||||
// Note, it is possible that we end up keeping these suppressed tasks around
|
||||
// for some time, but no longer than spinning the event loop nestedly
|
||||
// (sync XHR, alert, etc.)
|
||||
mPendingMicroTaskRunnables.swap(suppressed);
|
||||
}
|
||||
|
||||
void
|
||||
CycleCollectedJSContext::DispatchMicroTaskRunnable(
|
||||
already_AddRefed<MicroTaskRunnable> aRunnable)
|
||||
{
|
||||
mPendingMicroTaskRunnables.push(aRunnable);
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
Reference in New Issue
Block a user