Bug 1742438 - Part 1: Use ScriptLoadRequestList and have ScriptLoadInfo inherit from ScriptLoadRequest; r=asuth

This section of the patch queue starts the migration from ScriptLoadInfo to
ScriptLoadRequest/LoadContext pairs.

We will be making use of the ModuleLoader, and in the future we will have a unified ScriptLoader
implementation (currently, the skeleton for this is in ScriptLoaderInterface). ScriptLoadRequest has
been rewritten to be generic to all contexts, with a companion object "LoadContext" that will handle
specialized behavior required to load the request. That is exactly the case we have with workers,
most of the fields are generic with a couple of specialized fields associated with service workers.

Quick itemization of what will happen
* Patches 1-5: Focuses on getting things into place without using them, we rely on
ScriptLoadInfo (later renamed to WorkerLoadContext).
* Patches 6-7: This is a refactoring of what will be a shared data structure for decoding scripts.
 As we will be using requests, we can use this pretty much in the form it exists in on the DOM, and
 this cleanup makes it a bit nicer for the DOM as well (in my opinion anyway).
* Patches 8-12: We migrate all shared data to the standard utilization used by other loaders (DOM
 and component loader). The biggest pieces is `.mScriptData` transitioning from a stream of bits
 that haven't been decoded, to a decoded source text that can be used directly. This was enabled by
 patches 6-7.
* The final patches are small cleanups and documentation.

Differential Revision: https://phabricator.services.mozilla.com/D146173
This commit is contained in:
Yulia Startsev
2022-07-14 17:07:24 +00:00
parent cca38a8cd6
commit cb5cba08e1
4 changed files with 71 additions and 53 deletions

View File

@@ -82,6 +82,14 @@ using mozilla::ipc::PrincipalInfo;
namespace mozilla::dom::workerinternals {
namespace {
ScriptLoadInfo* AsWorkerRequest(JS::loader::ScriptLoadRequest* req) {
return static_cast<ScriptLoadInfo*>(req);
}
JS::loader::ScriptLoadRequest* AsScriptRequest(ScriptLoadInfo* aLoadInfo) {
return static_cast<JS::loader::ScriptLoadRequest*>(aLoadInfo);
}
nsresult ConstructURI(const nsAString& aScriptURL, nsIURI* baseURI,
const mozilla::Encoding* aDocumentEncoding,
nsIURI** aResult) {
@@ -258,19 +266,10 @@ void LoadAllScripts(WorkerPrivate* aWorkerPrivate,
clientInfo = global->GetClientInfo();
controller = global->GetController();
nsTArray<ScriptLoadInfo> aLoadInfos =
TransformIntoNewArray(aScriptURLs, [](const auto& scriptURL) {
ScriptLoadInfo res;
res.mURL = scriptURL;
return res;
});
RefPtr<loader::WorkerScriptLoader> loader = new loader::WorkerScriptLoader(
aWorkerPrivate, std::move(aOriginStack), syncLoopTarget,
std::move(aLoadInfos), aDocumentEncoding, clientInfo, controller,
aIsMainScript, aWorkerScriptType, aRv);
NS_ASSERTION(aLoadInfos.IsEmpty(), "Should have swapped!");
aWorkerPrivate, std::move(aOriginStack), syncLoopTarget, aScriptURLs,
aDocumentEncoding, clientInfo, controller, aIsMainScript,
aWorkerScriptType, aRv);
RefPtr<StrongWorkerRef> workerRef =
StrongWorkerRef::Create(aWorkerPrivate, "ScriptLoader", [loader]() {
@@ -459,7 +458,7 @@ static bool EvaluateSourceBuffer(JSContext* aCx,
WorkerScriptLoader::WorkerScriptLoader(
WorkerPrivate* aWorkerPrivate,
UniquePtr<SerializedStackHolder> aOriginStack,
nsIEventTarget* aSyncLoopTarget, nsTArray<ScriptLoadInfo> aLoadInfos,
nsIEventTarget* aSyncLoopTarget, const nsTArray<nsString>& aScriptURLs,
const mozilla::Encoding* aDocumentEncoding,
const Maybe<ClientInfo>& aClientInfo,
const Maybe<ServiceWorkerDescriptor>& aController, bool aIsMainScript,
@@ -467,7 +466,6 @@ WorkerScriptLoader::WorkerScriptLoader(
: mWorkerPrivate(aWorkerPrivate),
mOriginStack(std::move(aOriginStack)),
mSyncLoopTarget(aSyncLoopTarget),
mLoadInfos(std::move(aLoadInfos)),
mClientInfo(aClientInfo),
mController(aController),
mIsMainScript(aIsMainScript),
@@ -476,22 +474,30 @@ WorkerScriptLoader::WorkerScriptLoader(
mRv(aRv) {
aWorkerPrivate->AssertIsOnWorkerThread();
MOZ_ASSERT(aSyncLoopTarget);
MOZ_ASSERT_IF(aIsMainScript, mLoadInfos.Length() == 1);
MOZ_ASSERT_IF(aIsMainScript, aScriptURLs.Length() == 1);
for (const nsString& aScriptURL : aScriptURLs) {
// Create ScriptLoadRequests for this WorkerScriptLoader
ReferrerPolicy aReferrerPolicy = mWorkerPrivate->GetReferrerPolicy();
for (ScriptLoadInfo& loadInfo : mLoadInfos) {
// Only top level workers' main script use the document charset for the
// script uri encoding. Otherwise, default encoding (UTF-8) is applied.
MOZ_ASSERT_IF(bool(aDocumentEncoding),
aIsMainScript && !aWorkerPrivate->GetParent());
nsresult rv = ConstructURI(loadInfo.mURL, GetBaseURI(), aDocumentEncoding,
getter_AddRefs(loadInfo.mURI));
nsCOMPtr<nsIURI> baseURI = GetBaseURI();
nsCOMPtr<nsIURI> aURI;
nsresult rv = ConstructURI(aScriptURL, baseURI, aDocumentEncoding,
getter_AddRefs(aURI));
RefPtr<ScriptFetchOptions> fetchOptions =
new ScriptFetchOptions(CORSMode::CORS_NONE, aReferrerPolicy, nullptr);
RefPtr<ScriptLoadInfo> request = new ScriptLoadInfo(aURI, fetchOptions);
request->mURL = aScriptURL;
if (NS_WARN_IF(NS_FAILED(rv))) {
loadInfo.mLoadResult = rv;
request->mLoadResult = rv;
}
// Build up our list of references here. This will be removed once
// we move to ScriptLoadRequestList.
mLoadingRequests.AppendElement(&loadInfo);
mLoadingRequests.AppendElement(request);
}
}
@@ -555,21 +561,20 @@ void WorkerScriptLoader::MaybeExecuteFinishedScripts(
}
}
bool WorkerScriptLoader::MaybeMoveToLoadedList(ScriptLoadInfo* aLoadInfo) {
void WorkerScriptLoader::MaybeMoveToLoadedList(ScriptLoadInfo* aLoadInfo) {
mWorkerPrivate->AssertIsOnWorkerThread();
MOZ_ASSERT(!aLoadInfo->mExecutionScheduled);
aLoadInfo->mExecutionScheduled = true;
while (mLoadingRequests.Length() > 0) {
if (!mLoadingRequests[0]->mExecutionScheduled) {
while (!mLoadingRequests.isEmpty()) {
ScriptLoadRequest* request = mLoadingRequests.getFirst();
if (!AsWorkerRequest(request)->mExecutionScheduled) {
break;
}
ScriptLoadInfo* loadInfo = mLoadingRequests[0];
mLoadedRequests.AppendElement(loadInfo);
mLoadingRequests.RemoveElementAt(0);
}
return true;
RefPtr<ScriptLoadRequest> req = mLoadingRequests.Steal(request);
mLoadedRequests.AppendElement(req);
}
}
bool WorkerScriptLoader::StoreCSP() {
@@ -595,7 +600,7 @@ bool WorkerScriptLoader::ProcessPendingRequests(JSContext* aCx) {
mWorkerPrivate->AssertIsOnWorkerThread();
// Don't run if something else has already failed.
if (mExecutionAborted) {
mLoadedRequests.Clear();
mLoadedRequests.CancelRequestsAndClear();
return true;
}
@@ -608,8 +613,9 @@ bool WorkerScriptLoader::ProcessPendingRequests(JSContext* aCx) {
JS::Rooted<JSObject*> global(aCx, JS::CurrentGlobalOrNull(aCx));
MOZ_ASSERT(global);
while (mLoadedRequests.Length()) {
ScriptLoadInfo* loadInfo = mLoadedRequests[0];
while (!mLoadedRequests.isEmpty()) {
RefPtr<ScriptLoadRequest> req = mLoadedRequests.StealFirst();
ScriptLoadInfo* loadInfo = AsWorkerRequest(req);
// We don't have a ProcessRequest method (like we do on the DOM), as there
// isn't much processing that we need to do per request that isn't related
// to evaluation (the processsing done for the DOM is handled in
@@ -619,10 +625,9 @@ bool WorkerScriptLoader::ProcessPendingRequests(JSContext* aCx) {
if (!EvaluateScript(aCx, loadInfo)) {
mExecutionAborted = true;
mMutedErrorFlag = loadInfo->mMutedErrorFlag.valueOr(true);
mLoadedRequests.Clear();
mLoadedRequests.CancelRequestsAndClear();
break;
}
mLoadedRequests.RemoveElement(loadInfo);
}
return true;
@@ -661,7 +666,9 @@ nsresult WorkerScriptLoader::LoadScripts() {
}
if (!mWorkerPrivate->IsServiceWorker() || IsDebuggerScript()) {
for (ScriptLoadInfo* loadInfo : mLoadingRequests) {
for (ScriptLoadRequest* req = mLoadingRequests.getFirst(); req;
req = req->getNext()) {
ScriptLoadInfo* loadInfo = AsWorkerRequest(req);
nsresult rv = LoadScript(loadInfo);
if (NS_WARN_IF(NS_FAILED(rv))) {
LoadingFinished(loadInfo, rv);
@@ -674,7 +681,9 @@ nsresult WorkerScriptLoader::LoadScripts() {
RefPtr<CacheCreator> cacheCreator = new CacheCreator(mWorkerPrivate);
for (ScriptLoadInfo* loadInfo : mLoadingRequests) {
for (ScriptLoadRequest* req = mLoadingRequests.getFirst(); req;
req = req->getNext()) {
ScriptLoadInfo* loadInfo = AsWorkerRequest(req);
loadInfo->SetCacheCreator(cacheCreator);
loadInfo->GetCacheCreator()->AddLoader(
MakeNotNull<RefPtr<CacheLoadHandler>>(mWorkerPrivate, loadInfo,
@@ -773,12 +782,14 @@ nsresult WorkerScriptLoader::LoadScript(ScriptLoadInfo* aLoadInfo) {
->CloneWithNewPolicy(parentWorker->GetReferrerPolicy());
}
rv = ChannelFromScriptURL(
principal, parentDoc, mWorkerPrivate, loadGroup, ios, secMan,
aLoadInfo->mURI, mClientInfo, mController, IsMainWorkerScript(),
mWorkerScriptType, mWorkerPrivate->ContentPolicyType(), loadFlags,
mWorkerPrivate->CookieJarSettings(), referrerInfo,
getter_AddRefs(channel));
ScriptLoadRequest* req = AsScriptRequest(aLoadInfo);
rv = ChannelFromScriptURL(principal, parentDoc, mWorkerPrivate, loadGroup,
ios, secMan, req->mURI, mClientInfo, mController,
IsMainWorkerScript(), mWorkerScriptType,
mWorkerPrivate->ContentPolicyType(), loadFlags,
mWorkerPrivate->CookieJarSettings(), referrerInfo,
getter_AddRefs(channel));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}