From 943896b43c97a4688faf017b4bffb64c700678ab Mon Sep 17 00:00:00 2001 From: Karl Tomlinson Date: Mon, 1 Apr 2019 16:54:58 +0000 Subject: [PATCH] Bug 1539039 keep WorkletGlobalScope as long as its Worklet is usable r=baku Depends on D25353 Differential Revision: https://phabricator.services.mozilla.com/D25354 --HG-- extra : moz-landing-system : lando --- dom/worklet/Worklet.cpp | 9 +++------ dom/worklet/WorkletImpl.cpp | 37 +++++++++++++++++++++++++++---------- dom/worklet/WorkletImpl.h | 5 ++++- 3 files changed, 34 insertions(+), 17 deletions(-) diff --git a/dom/worklet/Worklet.cpp b/dom/worklet/Worklet.cpp index c26bfc13bca3..3d95bfe399e1 100644 --- a/dom/worklet/Worklet.cpp +++ b/dom/worklet/Worklet.cpp @@ -326,7 +326,8 @@ NS_IMETHODIMP ExecutionRunnable::Run() { // WorkletThread::IsOnWorkletThread() cannot be used here because it depends // on a WorkletJSContext having been created for this thread. That does not - // happen until the first time RunOnWorkletThread() is called. + // happen until the global scope is created the first time + // RunOnWorkletThread() is called. if (!NS_IsMainThread()) { RunOnWorkletThread(); return NS_DispatchToMainThread(this); @@ -339,11 +340,7 @@ ExecutionRunnable::Run() { void ExecutionRunnable::RunOnWorkletThread() { WorkletThread::EnsureCycleCollectedJSContext(mParentRuntime); - AutoJSAPI jsapi; - jsapi.Init(); - - RefPtr globalScope = - mWorkletImpl->CreateGlobalScope(jsapi.cx()); + WorkletGlobalScope* globalScope = mWorkletImpl->GetGlobalScope(); MOZ_ASSERT(globalScope); AutoEntryScript aes(globalScope, "Worklet"); diff --git a/dom/worklet/WorkletImpl.cpp b/dom/worklet/WorkletImpl.cpp index 9c364b4474d1..fb4e109b9c58 100644 --- a/dom/worklet/WorkletImpl.cpp +++ b/dom/worklet/WorkletImpl.cpp @@ -11,6 +11,7 @@ #include "mozilla/BasePrincipal.h" #include "mozilla/dom/RegisterWorkletBindings.h" +#include "mozilla/dom/ScriptSettings.h" #include "mozilla/dom/WorkletBinding.h" namespace mozilla { @@ -42,7 +43,7 @@ WorkletLoadInfo::~WorkletLoadInfo() { WorkletImpl::WorkletImpl(nsPIDOMWindowInner* aWindow, nsIPrincipal* aPrincipal) : mWorkletLoadInfo(aWindow, aPrincipal), mTerminated(false) {} -WorkletImpl::~WorkletImpl() = default; +WorkletImpl::~WorkletImpl() { MOZ_ASSERT(!mGlobalScope); } JSObject* WorkletImpl::WrapWorklet(JSContext* aCx, dom::Worklet* aWorklet, JS::Handle aGivenProto) { @@ -50,30 +51,46 @@ JSObject* WorkletImpl::WrapWorklet(JSContext* aCx, dom::Worklet* aWorklet, return dom::Worklet_Binding::Wrap(aCx, aWorklet, aGivenProto); } -already_AddRefed WorkletImpl::CreateGlobalScope( - JSContext* aCx) { +dom::WorkletGlobalScope* WorkletImpl::GetGlobalScope() { dom::WorkletThread::AssertIsOnWorkletThread(); - RefPtr scope = ConstructGlobalScope(); + if (mGlobalScope) { + return mGlobalScope; + } - JS::Rooted global(aCx); - NS_ENSURE_TRUE(scope->WrapGlobalObject(aCx, &global), nullptr); + dom::AutoJSAPI jsapi; + jsapi.Init(); + JSContext* cx = jsapi.cx(); - JSAutoRealm ar(aCx, global); + mGlobalScope = ConstructGlobalScope(); + + JS::Rooted global(cx); + NS_ENSURE_TRUE(mGlobalScope->WrapGlobalObject(cx, &global), nullptr); + + JSAutoRealm ar(cx, global); // Init Web IDL bindings - if (!dom::RegisterWorkletBindings(aCx, global)) { + if (!dom::RegisterWorkletBindings(cx, global)) { return nullptr; } - JS_FireOnNewGlobalObject(aCx, global); + JS_FireOnNewGlobalObject(cx, global); - return scope.forget(); + return mGlobalScope; } void WorkletImpl::NotifyWorkletFinished() { MOZ_ASSERT(NS_IsMainThread()); + if (mTerminated) { + return; + } + + // Release global scope on its thread. + SendControlMessage(NS_NewRunnableFunction( + "WorkletImpl::NotifyWorkletFinished", + [self = RefPtr(this)]() { self->mGlobalScope = nullptr; })); + mTerminated = true; if (mWorkletThread) { mWorkletThread->Terminate(); diff --git a/dom/worklet/WorkletImpl.h b/dom/worklet/WorkletImpl.h index 7efc2b066f4c..a9fcc1276d33 100644 --- a/dom/worklet/WorkletImpl.h +++ b/dom/worklet/WorkletImpl.h @@ -74,7 +74,7 @@ class WorkletImpl { void NotifyWorkletFinished(); // Execution thread only. - already_AddRefed CreateGlobalScope(JSContext* aCx); + dom::WorkletGlobalScope* GetGlobalScope(); // Any thread. @@ -93,6 +93,9 @@ class WorkletImpl { // Parent thread only. RefPtr mWorkletThread; bool mTerminated; + + // Execution thread only. + RefPtr mGlobalScope; }; } // namespace mozilla