diff --git a/dom/workers/RuntimeService.cpp b/dom/workers/RuntimeService.cpp index 789bfa59f5bc..ba9d18bc448c 100644 --- a/dom/workers/RuntimeService.cpp +++ b/dom/workers/RuntimeService.cpp @@ -576,6 +576,13 @@ InterruptCallback(JSContext* aCx) WorkerPrivate* worker = GetWorkerPrivateFromContext(aCx); MOZ_ASSERT(worker); + // As with the main thread, the interrupt callback is triggered + // non-deterministically when recording/replaying, so return early to avoid + // performing any recorded events. + if (recordreplay::IsRecordingOrReplaying()) { + return true; + } + // Now is a good time to turn on profiling if it's pending. PROFILER_JS_INTERRUPT_CALLBACK(); @@ -965,6 +972,11 @@ public: NS_WARNING("failed to set workerCx's default locale"); } } + + // Cycle collections must occur at consistent points when recording/replaying. + if (recordreplay::IsRecordingOrReplaying()) { + recordreplay::RegisterTrigger(this, [=]() { nsCycleCollector_collect(nullptr); }); + } } void Shutdown(JSContext* cx) override @@ -979,6 +991,10 @@ public: ~WorkerJSRuntime() { MOZ_COUNT_DTOR_INHERITED(WorkerJSRuntime, CycleCollectedJSRuntime); + + if (recordreplay::IsRecordingOrReplaying()) { + recordreplay::UnregisterTrigger(this); + } } virtual void @@ -1015,7 +1031,11 @@ public: mWorkerPrivate->AssertIsOnWorkerThread(); if (aStatus == JSGC_END) { - nsCycleCollector_collect(nullptr); + if (recordreplay::IsRecordingOrReplaying()) { + recordreplay::ActivateTrigger(this); + } else { + nsCycleCollector_collect(nullptr); + } } }