Bug 1800496 - Re-introduce Cycle Collected LoadContextBase for Workers; r=jonco

The non-cycle collected LoadContextBase caused failures for Module Workers. This reverts that change

Differential Revision: https://phabricator.services.mozilla.com/D162214
This commit is contained in:
Yulia Startsev 2022-11-18 10:02:26 +00:00
parent 2310f5b5b6
commit 32c96913a6
10 changed files with 38 additions and 104 deletions

View File

@ -31,12 +31,12 @@ namespace mozilla::dom {
//////////////////////////////////////////////////////////////
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ScriptLoadContext)
NS_INTERFACE_MAP_END_INHERITING(JS::loader::LoadContextCCBase)
NS_INTERFACE_MAP_END_INHERITING(JS::loader::LoadContextBase)
NS_IMPL_CYCLE_COLLECTION_CLASS(ScriptLoadContext)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(ScriptLoadContext,
JS::loader::LoadContextCCBase)
JS::loader::LoadContextBase)
if (Runnable* runnable = tmp->mRunnable.exchange(nullptr)) {
runnable->Release();
}
@ -44,15 +44,15 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(ScriptLoadContext,
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(ScriptLoadContext,
JS::loader::LoadContextCCBase)
JS::loader::LoadContextBase)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLoadBlockedDocument)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_ADDREF_INHERITED(ScriptLoadContext, JS::loader::LoadContextCCBase)
NS_IMPL_RELEASE_INHERITED(ScriptLoadContext, JS::loader::LoadContextCCBase)
NS_IMPL_ADDREF_INHERITED(ScriptLoadContext, JS::loader::LoadContextBase)
NS_IMPL_RELEASE_INHERITED(ScriptLoadContext, JS::loader::LoadContextBase)
ScriptLoadContext::ScriptLoadContext()
: JS::loader::LoadContextCCBase(JS::loader::ContextKind::Window),
: JS::loader::LoadContextBase(JS::loader::ContextKind::Window),
mScriptMode(ScriptMode::eBlocking),
mScriptFromHead(false),
mIsInline(true),

View File

@ -74,7 +74,7 @@ class Element;
*
*/
class ScriptLoadContext : public JS::loader::LoadContextCCBase,
class ScriptLoadContext : public JS::loader::LoadContextBase,
public PreloaderBase {
protected:
virtual ~ScriptLoadContext();
@ -84,7 +84,7 @@ class ScriptLoadContext : public JS::loader::LoadContextCCBase,
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(ScriptLoadContext,
JS::loader::LoadContextCCBase)
JS::loader::LoadContextBase)
// PreloaderBase
static void PrioritizeAsPreload(nsIChannel* aChannel);

View File

@ -677,8 +677,8 @@ bool WorkerScriptLoader::ProcessPendingRequests(JSContext* aCx) {
// once modules are introduced as we will have some extra work to do.
if (!EvaluateScript(aCx, req)) {
mExecutionAborted = true;
RefPtr<WorkerLoadContext> loadInfo = req->StealWorkerLoadContext();
mMutedErrorFlag = loadInfo->mMutedErrorFlag.valueOr(true);
WorkerLoadContext* loadContext = req->GetWorkerLoadContext();
mMutedErrorFlag = loadContext->mMutedErrorFlag.valueOr(true);
mLoadedRequests.CancelRequestsAndClear();
break;
}
@ -1038,7 +1038,7 @@ void WorkerScriptLoader::AbruptShutdown() {
while (!mLoadedRequests.isEmpty()) {
RefPtr<ScriptLoadRequest> request = mLoadedRequests.StealFirst();
RefPtr<WorkerLoadContext> loadContext = request->StealWorkerLoadContext();
WorkerLoadContext* loadContext = request->GetWorkerLoadContext();
mRv.MightThrowJSException();
if (NS_FAILED(loadContext->mLoadResult)) {
ReportErrorToConsole(request, loadContext->mLoadResult);
@ -1111,7 +1111,6 @@ bool WorkerScriptLoader::EvaluateScript(JSContext* aCx,
}
// steal the loadContext so that the cycle is broken and cycle collector can
// collect the scriptLoadRequest.
RefPtr<WorkerLoadContext> droppedContext = aRequest->StealWorkerLoadContext();
return true;
}

View File

@ -12,7 +12,7 @@ namespace dom {
WorkerLoadContext::WorkerLoadContext(Kind aKind,
const Maybe<ClientInfo>& aClientInfo)
: JS::loader::LoadContextNoCCBase(JS::loader::ContextKind::Worker),
: JS::loader::LoadContextBase(JS::loader::ContextKind::Worker),
mKind(aKind),
mClientInfo(aClientInfo){};

View File

@ -51,7 +51,7 @@ class CacheCreator;
*
*/
class WorkerLoadContext : public JS::loader::LoadContextNoCCBase {
class WorkerLoadContext : public JS::loader::LoadContextBase {
public:
/* Worker Load Context Kinds
*
@ -80,13 +80,10 @@ class WorkerLoadContext : public JS::loader::LoadContextNoCCBase {
explicit WorkerLoadContext(Kind aKind, const Maybe<ClientInfo>& aClientInfo);
void SetRequest(JS::loader::ScriptLoadRequest* aRequest) override {
LoadContextBase::SetRequest(aRequest);
mIsTopLevel = aRequest->IsTopLevel() && (mKind == Kind::MainScript);
}
// Used to detect if the `is top-level` bit is set on a given module.
bool IsTopLevel() { return mIsTopLevel; };
bool IsTopLevel() {
return mRequest->IsTopLevel() && (mKind == Kind::MainScript);
};
static Kind GetKind(bool isMainScript, bool isDebuggerScript) {
if (isDebuggerScript) {

View File

@ -16,6 +16,22 @@ namespace JS::loader {
// LoadContextBase
////////////////////////////////////////////////////////////////
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(LoadContextBase)
NS_INTERFACE_MAP_END
NS_IMPL_CYCLE_COLLECTING_ADDREF(LoadContextBase)
NS_IMPL_CYCLE_COLLECTING_RELEASE(LoadContextBase)
NS_IMPL_CYCLE_COLLECTION_CLASS(LoadContextBase)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(LoadContextBase)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mRequest)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(LoadContextBase)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRequest)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
LoadContextBase::LoadContextBase(ContextKind kind)
: mKind(kind), mRequest(nullptr) {}
@ -43,36 +59,4 @@ mozilla::dom::WorkerLoadContext* LoadContextBase::AsWorkerContext() {
return static_cast<mozilla::dom::WorkerLoadContext*>(this);
}
////////////////////////////////////////////////////////////////
// LoadContextCCBase
////////////////////////////////////////////////////////////////
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(LoadContextCCBase)
NS_INTERFACE_MAP_END
NS_IMPL_CYCLE_COLLECTING_ADDREF(LoadContextCCBase)
NS_IMPL_CYCLE_COLLECTING_RELEASE(LoadContextCCBase)
NS_IMPL_CYCLE_COLLECTION_CLASS(LoadContextCCBase)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(LoadContextCCBase)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mRequest)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(LoadContextCCBase)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRequest)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
LoadContextCCBase::LoadContextCCBase(ContextKind kind)
: LoadContextBase(kind) {}
////////////////////////////////////////////////////////////////
// LoadContextNoCCBase
////////////////////////////////////////////////////////////////
NS_IMPL_ISUPPORTS0(LoadContextNoCCBase);
LoadContextNoCCBase::LoadContextNoCCBase(ContextKind kind)
: LoadContextBase(kind) {}
} // namespace JS::loader

View File

@ -28,18 +28,7 @@ class ScriptLoadRequest;
*
* LoadContexts augment the loading of a ScriptLoadRequest. This class
* is used as a base for all LoadContexts, and provides shared functionality.
* This class should not be inherited from directly, unless you plan on
* implementing a unique nsISupports behavior not handled by LoadContextNoCCBase
* or LoadContextCCBase.
*
* Different loading environments have different rules applied to how a script
* is loaded. In DOM scripts, there are flags controlling load order (Async,
* Deferred, normal) as well as other elements that impact the loading of a
* script (<preload>). In the case of workers, service workers are potentially
* loaded from the Cache. For more detailed information per context see
* * The ScriptLoadContext: dom/script/ScriptLoadContext.h
* * The ComponentLoadContext: js/xpconnect/loader/ComponentModuleLoader.h
* * The WorkerLoadContext: dom/workers/loader/WorkerLoadContext.h
*/
enum class ContextKind { Window, Component, Worker };
@ -52,9 +41,12 @@ class LoadContextBase : public nsISupports {
virtual ~LoadContextBase() = default;
public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_CLASS(LoadContextBase)
explicit LoadContextBase(ContextKind kind);
virtual void SetRequest(JS::loader::ScriptLoadRequest* aRequest);
void SetRequest(JS::loader::ScriptLoadRequest* aRequest);
// Used to output a string for the Gecko Profiler.
virtual void GetProfilerLabel(nsACString& aOutString);
@ -72,32 +64,6 @@ class LoadContextBase : public nsISupports {
RefPtr<JS::loader::ScriptLoadRequest> mRequest;
};
// A variant of the LoadContextbase with CC. Used by most LoadContexts. This
// works with the cycle collector and is the default class to inherit from.
class LoadContextCCBase : public LoadContextBase {
public:
explicit LoadContextCCBase(ContextKind kind);
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_CLASS(LoadContextCCBase)
protected:
virtual ~LoadContextCCBase() = default;
};
// A variant of the LoadContextbase without CC. Used by the WorkerLoadContext,
// so that it can refcounted safely across threads. Note: You must manually
// break the cycle pointing to ScriptLoadRequest if you use this!
class LoadContextNoCCBase : public LoadContextBase {
public:
explicit LoadContextNoCCBase(ContextKind kind);
NS_DECL_THREADSAFE_ISUPPORTS
protected:
virtual ~LoadContextNoCCBase() = default;
};
} // namespace JS::loader
#endif // js_loader_BaseLoadContext_h

View File

@ -152,17 +152,6 @@ mozilla::dom::WorkerLoadContext* ScriptLoadRequest::GetWorkerLoadContext() {
return mLoadContext->AsWorkerContext();
}
already_AddRefed<mozilla::dom::WorkerLoadContext>
ScriptLoadRequest::StealWorkerLoadContext() {
MOZ_ASSERT(mLoadContext);
RefPtr<mozilla::dom::WorkerLoadContext> workerContext =
mLoadContext->AsWorkerContext();
// Break cycle.
mLoadContext->mRequest = nullptr;
mLoadContext = nullptr;
return workerContext.forget();
}
ModuleLoadRequest* ScriptLoadRequest::AsModuleRequest() {
MOZ_ASSERT(IsModuleRequest());
return static_cast<ModuleLoadRequest*>(this);

View File

@ -313,7 +313,6 @@ class ScriptLoadRequest
mozilla::loader::ComponentLoadContext* GetComponentLoadContext();
mozilla::dom::WorkerLoadContext* GetWorkerLoadContext();
already_AddRefed<mozilla::dom::WorkerLoadContext> StealWorkerLoadContext();
const ScriptKind mKind; // Whether this is a classic script or a module
// script.

View File

@ -95,10 +95,10 @@ class ComponentModuleLoader : public JS::loader::ModuleLoaderBase {
// Data specific to ComponentModuleLoader that is associated with each load
// request.
class ComponentLoadContext : public JS::loader::LoadContextCCBase {
class ComponentLoadContext : public JS::loader::LoadContextBase {
public:
ComponentLoadContext()
: LoadContextCCBase(JS::loader::ContextKind::Component) {}
: LoadContextBase(JS::loader::ContextKind::Component) {}
public:
// The result of compiling a module script. These fields are used temporarily