Bug 1742437 - Split ScriptLoadRequest into ScriptLoadRequest and DOMScriptLoadContext; r=jonco,smaug

Differential Revision: https://phabricator.services.mozilla.com/D134041
This commit is contained in:
Yulia Startsev
2022-02-17 15:57:48 +00:00
parent 472f907a6f
commit 70ff292d33
8 changed files with 592 additions and 393 deletions

View File

@@ -201,33 +201,34 @@ ScriptLoader::~ScriptLoader() {
mObservers.Clear();
if (mParserBlockingRequest) {
mParserBlockingRequest->FireScriptAvailable(NS_ERROR_ABORT);
mParserBlockingRequest->GetLoadContext()->FireScriptAvailable(
NS_ERROR_ABORT);
}
for (ScriptLoadRequest* req = mXSLTRequests.getFirst(); req;
req = req->getNext()) {
req->FireScriptAvailable(NS_ERROR_ABORT);
req->GetLoadContext()->FireScriptAvailable(NS_ERROR_ABORT);
}
for (ScriptLoadRequest* req = mDeferRequests.getFirst(); req;
req = req->getNext()) {
req->FireScriptAvailable(NS_ERROR_ABORT);
req->GetLoadContext()->FireScriptAvailable(NS_ERROR_ABORT);
}
for (ScriptLoadRequest* req = mLoadingAsyncRequests.getFirst(); req;
req = req->getNext()) {
req->FireScriptAvailable(NS_ERROR_ABORT);
req->GetLoadContext()->FireScriptAvailable(NS_ERROR_ABORT);
}
for (ScriptLoadRequest* req = mLoadedAsyncRequests.getFirst(); req;
req = req->getNext()) {
req->FireScriptAvailable(NS_ERROR_ABORT);
req->GetLoadContext()->FireScriptAvailable(NS_ERROR_ABORT);
}
for (ScriptLoadRequest* req =
mNonAsyncExternalScriptInsertedRequests.getFirst();
req; req = req->getNext()) {
req->FireScriptAvailable(NS_ERROR_ABORT);
req->GetLoadContext()->FireScriptAvailable(NS_ERROR_ABORT);
}
// Unblock the kids, in case any of them moved to a different document
@@ -269,7 +270,7 @@ static void CollectScriptTelemetry(ScriptLoadRequest* aRequest) {
// JavaScript Start-up Bytecode Cache, with the expectation of an almost zero
// source-fallback and alternate-data being roughtly equal to source loads.
if (aRequest->IsLoadingSource()) {
if (aRequest->mIsInline) {
if (aRequest->GetLoadContext()->mIsInline) {
AccumulateCategorical(LABELS_DOM_SCRIPT_LOADING_SOURCE::Inline);
} else if (aRequest->IsTextSource()) {
AccumulateCategorical(LABELS_DOM_SCRIPT_LOADING_SOURCE::SourceFallback);
@@ -343,7 +344,7 @@ static bool IsScriptEventHandler(ScriptKind kind, nsIContent* aScriptElement) {
nsContentPolicyType ScriptLoadRequestToContentPolicyType(
ScriptLoadRequest* aRequest) {
if (aRequest->IsPreload()) {
if (aRequest->GetLoadContext()->IsPreload()) {
return aRequest->IsModuleRequest()
? nsIContentPolicy::TYPE_INTERNAL_MODULE_PRELOAD
: nsIContentPolicy::TYPE_INTERNAL_SCRIPT_PRELOAD;
@@ -758,8 +759,9 @@ void ScriptLoader::ProcessLoadedModuleTree(ModuleLoadRequest* aRequest) {
RefPtr<ScriptLoadRequest> req =
mModuleLoader->mDynamicImportRequests.Steal(aRequest);
RunScriptWhenSafe(aRequest);
} else if (aRequest->mIsInline &&
aRequest->GetParserCreated() == NOT_FROM_PARSER) {
} else if (aRequest->GetLoadContext()->mIsInline &&
aRequest->GetLoadContext()->GetParserCreated() ==
NOT_FROM_PARSER) {
MOZ_ASSERT(!aRequest->isInList());
RunScriptWhenSafe(aRequest);
} else {
@@ -768,16 +770,17 @@ void ScriptLoader::ProcessLoadedModuleTree(ModuleLoadRequest* aRequest) {
}
}
aRequest->MaybeUnblockOnload();
aRequest->GetLoadContext()->MaybeUnblockOnload();
}
nsresult ScriptLoader::RestartLoad(ScriptLoadRequest* aRequest) {
MOZ_ASSERT(aRequest->IsBytecode());
aRequest->mScriptBytecode.clearAndFree();
TRACE_FOR_TEST(aRequest->GetScriptElement(), "scriptloader_fallback");
TRACE_FOR_TEST(aRequest->GetLoadContext()->GetScriptElement(),
"scriptloader_fallback");
// Notify preload restart so that we can register this preload request again.
aRequest->NotifyRestart(mDocument);
aRequest->GetLoadContext()->NotifyRestart(mDocument);
// Start a new channel from which we explicitly request to stream the source
// instead of the bytecode.
@@ -904,8 +907,8 @@ nsresult ScriptLoader::StartLoadInternal(ScriptLoadRequest* aRequest,
nsContentPolicyType contentPolicyType =
ScriptLoadRequestToContentPolicyType(aRequest);
nsCOMPtr<nsINode> context;
if (aRequest->GetScriptElement()) {
context = do_QueryInterface(aRequest->GetScriptElement());
if (aRequest->GetLoadContext()->GetScriptElement()) {
context = do_QueryInterface(aRequest->GetLoadContext()->GetScriptElement());
} else {
context = mDocument;
}
@@ -977,23 +980,25 @@ nsresult ScriptLoader::StartLoadInternal(ScriptLoadRequest* aRequest,
}
LOG(("ScriptLoadRequest (%p): mode=%u tracking=%d", aRequest,
unsigned(aRequest->mScriptMode), aRequest->IsTracking()));
unsigned(aRequest->GetLoadContext()->mScriptMode),
aRequest->GetLoadContext()->IsTracking()));
if (aRequest->IsLinkPreloadScript()) {
if (aRequest->GetLoadContext()->IsLinkPreloadScript()) {
// This is <link rel="preload" as="script"> initiated speculative load,
// put it to the group that is not blocked by leaders and doesn't block
// follower at the same time. Giving it a much higher priority will make
// this request be processed ahead of other Unblocked requests, but with
// the same weight as Leaders. This will make us behave similar way for
// both http2 and http1.
ScriptLoadRequest::PrioritizeAsPreload(channel);
ScriptLoadRequest::AddLoadBackgroundFlag(channel);
DOMScriptLoadContext::PrioritizeAsPreload(channel);
DOMScriptLoadContext::AddLoadBackgroundFlag(channel);
} else if (nsCOMPtr<nsIClassOfService> cos = do_QueryInterface(channel)) {
if (aRequest->mScriptFromHead && aRequest->IsBlockingScript()) {
if (aRequest->GetLoadContext()->mScriptFromHead &&
aRequest->GetLoadContext()->IsBlockingScript()) {
// synchronous head scripts block loading of most other non js/css
// content such as images, Leader implicitely disallows tailing
cos->AddClassFlags(nsIClassOfService::Leader);
} else if (aRequest->IsDeferredScript() &&
} else if (aRequest->GetLoadContext()->IsDeferredScript() &&
!StaticPrefs::network_http_tailing_enabled()) {
// Bug 1395525 and the !StaticPrefs::network_http_tailing_enabled() bit:
// We want to make sure that turing tailing off by the pref makes the
@@ -1008,7 +1013,7 @@ nsresult ScriptLoader::StartLoadInternal(ScriptLoadRequest* aRequest,
// nor prioritized
cos->AddClassFlags(nsIClassOfService::Unblocked);
if (aRequest->IsAsyncScript()) {
if (aRequest->GetLoadContext()->IsAsyncScript()) {
// async scripts are allowed tailing, since those and only those
// don't block DOMContentLoaded; this flag doesn't enforce tailing,
// just overweights the Unblocked flag when the channel is found
@@ -1048,7 +1053,7 @@ nsresult ScriptLoader::StartLoadInternal(ScriptLoadRequest* aRequest,
// Set the initiator type
nsCOMPtr<nsITimedChannel> timedChannel(do_QueryInterface(httpChannel));
if (timedChannel) {
if (aRequest->IsLinkPreloadScript()) {
if (aRequest->GetLoadContext()->IsLinkPreloadScript()) {
timedChannel->SetInitiatorType(u"link"_ns);
} else {
timedChannel->SetInitiatorType(u"script"_ns);
@@ -1074,16 +1079,17 @@ nsresult ScriptLoader::StartLoadInternal(ScriptLoadRequest* aRequest,
auto key = PreloadHashKey::CreateAsScript(
aRequest->mURI, aRequest->CORSMode(), aRequest->mKind);
aRequest->NotifyOpen(key, channel, mDocument,
aRequest->IsLinkPreloadScript());
aRequest->GetLoadContext()->NotifyOpen(
key, channel, mDocument,
aRequest->GetLoadContext()->IsLinkPreloadScript());
rv = channel->AsyncOpen(loader);
if (NS_FAILED(rv)) {
// Make sure to inform any <link preload> tags about failure to load the
// resource.
aRequest->NotifyStart(channel);
aRequest->NotifyStop(rv);
aRequest->GetLoadContext()->NotifyStart(channel);
aRequest->GetLoadContext()->NotifyStop(rv);
}
NS_ENSURE_SUCCESS(rv, rv);
@@ -1140,8 +1146,11 @@ ScriptLoadRequest* ScriptLoader::CreateLoadRequest(
aCORSMode, aReferrerPolicy, domElement, aTriggeringPrincipal, nullptr);
if (aKind == ScriptKind::eClassic) {
return new ScriptLoadRequest(aKind, aURI, fetchOptions, aIntegrity,
referrer);
ScriptLoadRequest* aRequest =
new ScriptLoadRequest(aKind, aURI, fetchOptions, aIntegrity, referrer);
DOMScriptLoadContext* aContext = new DOMScriptLoadContext(aRequest);
aRequest->mLoadContext = aContext;
return aRequest;
}
MOZ_ASSERT(aKind == ScriptKind::eModule);
@@ -1259,14 +1268,14 @@ bool ScriptLoader::ProcessExternalScript(nsIScriptElement* aElement,
// It's possible these attributes changed since we started the preload so
// update them here.
request->SetScriptMode(aElement->GetScriptDeferred(),
aElement->GetScriptAsync(), false);
request->GetLoadContext()->SetScriptMode(aElement->GetScriptDeferred(),
aElement->GetScriptAsync(), false);
// The request will be added to another list or set as
// mParserBlockingRequest below.
if (request->mInCompilingList) {
if (request->GetLoadContext()->mInCompilingList) {
mOffThreadCompilingRequests.Remove(request);
request->mInCompilingList = false;
request->GetLoadContext()->mInCompilingList = false;
}
AccumulateCategorical(LABELS_DOM_SCRIPT_PRELOAD_RESULT::Used);
@@ -1284,11 +1293,12 @@ bool ScriptLoader::ProcessExternalScript(nsIScriptElement* aElement,
request = CreateLoadRequest(aScriptKind, scriptURI, aElement, principal,
ourCORSMode, sriMetadata, referrerPolicy);
request->mIsInline = false;
request->SetScriptMode(aElement->GetScriptDeferred(),
aElement->GetScriptAsync(), false);
// keep request->mScriptFromHead to false so we don't treat non preloaded
// scripts as blockers for full page load. See bug 792438.
request->GetLoadContext()->mIsInline = false;
request->GetLoadContext()->SetScriptMode(aElement->GetScriptDeferred(),
aElement->GetScriptAsync(), false);
// keep request->GetLoadContext()->mScriptFromHead to false so we don't
// treat non preloaded scripts as blockers for full page load. See
// bug 792438.
LOG(("ScriptLoadRequest (%p): Created request for external script",
request.get()));
@@ -1312,11 +1322,12 @@ bool ScriptLoader::ProcessExternalScript(nsIScriptElement* aElement,
// We should still be in loading stage of script unless we're loading a
// module or speculatively off-main-thread parsing a script.
NS_ASSERTION(SpeculativeOMTParsingEnabled() || !request->InCompilingStage() ||
NS_ASSERTION(SpeculativeOMTParsingEnabled() ||
!request->GetLoadContext()->CompileStarted() ||
request->IsModuleRequest(),
"Request should not yet be in compiling stage.");
if (request->IsAsyncScript()) {
if (request->GetLoadContext()->IsAsyncScript()) {
AddAsyncRequest(request);
if (request->IsReadyToRun()) {
// The script is available already. Run it ASAP when the event
@@ -1332,7 +1343,7 @@ bool ScriptLoader::ProcessExternalScript(nsIScriptElement* aElement,
// Violate the HTML5 spec in order to make LABjs and the "order" plug-in
// for RequireJS work with their Gecko-sniffed code path. See
// http://lists.w3.org/Archives/Public/public-html/2010Oct/0088.html
request->mIsNonAsyncScriptInserted = true;
request->GetLoadContext()->mIsNonAsyncScriptInserted = true;
mNonAsyncExternalScriptInsertedRequests.AppendElement(request);
if (request->IsReadyToRun()) {
// The script is available already. Run it ASAP when the event
@@ -1343,7 +1354,7 @@ bool ScriptLoader::ProcessExternalScript(nsIScriptElement* aElement,
}
// we now have a parser-inserted request that may or may not be still
// loading
if (request->IsDeferredScript()) {
if (request->GetLoadContext()->IsDeferredScript()) {
// We don't want to run this yet.
// If we come here, the script is a parser-created script and it has
// the defer attribute but not the async attribute. Since a
@@ -1362,7 +1373,7 @@ bool ScriptLoader::ProcessExternalScript(nsIScriptElement* aElement,
// Need to maintain order for XSLT-inserted scripts
NS_ASSERTION(!mParserBlockingRequest,
"Parser-blocking scripts and XSLT scripts in the same doc!");
request->mIsXSLT = true;
request->GetLoadContext()->mIsXSLT = true;
mXSLTRequests.AppendElement(request);
if (request->IsReadyToRun()) {
// The script is available already. Run it ASAP when the event
@@ -1425,18 +1436,20 @@ bool ScriptLoader::ProcessInlineScript(nsIScriptElement* aElement,
mDocument->NodePrincipal(), corsMode,
SRIMetadata(), // SRI doesn't apply
referrerPolicy);
request->mIsInline = true;
request->GetLoadContext()->mIsInline = true;
request->mLineNo = aElement->GetScriptLineNumber();
request->mProgress = ScriptLoadRequest::Progress::eLoading_Source;
request->SetTextSource();
TRACE_FOR_TEST_BOOL(request->GetScriptElement(), "scriptloader_load_source");
TRACE_FOR_TEST_BOOL(request->GetLoadContext()->GetScriptElement(),
"scriptloader_load_source");
CollectScriptTelemetry(request);
// Only the 'async' attribute is heeded on an inline module script and
// inline classic scripts ignore both these attributes.
MOZ_ASSERT(!aElement->GetScriptDeferred());
MOZ_ASSERT_IF(!request->IsModuleRequest(), !aElement->GetScriptAsync());
request->SetScriptMode(false, aElement->GetScriptAsync(), false);
request->GetLoadContext()->SetScriptMode(false, aElement->GetScriptAsync(),
false);
LOG(("ScriptLoadRequest (%p): Created request for inline script",
request.get()));
@@ -1513,9 +1526,10 @@ ScriptLoadRequest* ScriptLoader::LookupPreloadRequest(
// Found preloaded request. Note that a script-inserted script can steal a
// preload!
RefPtr<ScriptLoadRequest> request = mPreloads[i].mRequest;
request->SetIsLoadRequest(aElement);
request->GetLoadContext()->SetIsLoadRequest(aElement);
if (request->mWasCompiledOMT && !request->IsModuleRequest()) {
if (request->GetLoadContext()->mWasCompiledOMT &&
!request->IsModuleRequest()) {
request->SetReady();
}
@@ -1540,7 +1554,7 @@ ScriptLoadRequest* ScriptLoader::LookupPreloadRequest(
// Don't cancel link preload requests, we want to deliver onload according
// the result of the load, cancellation would unexpectedly lead to error
// notification.
if (!request->IsLinkPreloadScript()) {
if (!request->GetLoadContext()->IsLinkPreloadScript()) {
request->Cancel();
}
return nullptr;
@@ -1551,11 +1565,11 @@ ScriptLoadRequest* ScriptLoader::LookupPreloadRequest(
// This makes sure the pending preload (if exists) for this resource is
// properly marked as used and thus not notified in the console as unused.
request->NotifyUsage();
request->GetLoadContext()->NotifyUsage();
// A used preload must no longer be found in the Document's hash table. Any
// <link preload> tag after the <script> tag will start a new request, that
// can be satisfied from a different cache, but not from the preload cache.
request->RemoveSelf(mDocument);
request->GetLoadContext()->RemoveSelf(mDocument);
return request;
}
@@ -1671,31 +1685,32 @@ void ScriptLoader::CancelScriptLoadRequests() {
nsresult ScriptLoader::ProcessOffThreadRequest(ScriptLoadRequest* aRequest) {
MOZ_ASSERT(aRequest->mProgress == ScriptLoadRequest::Progress::eCompiling);
MOZ_ASSERT(!aRequest->mWasCompiledOMT);
MOZ_ASSERT(!aRequest->GetLoadContext()->mWasCompiledOMT);
if (aRequest->IsCanceled()) {
return NS_OK;
}
aRequest->mWasCompiledOMT = true;
aRequest->GetLoadContext()->mWasCompiledOMT = true;
if (aRequest->mInCompilingList) {
if (aRequest->GetLoadContext()->mInCompilingList) {
mOffThreadCompilingRequests.Remove(aRequest);
aRequest->mInCompilingList = false;
aRequest->GetLoadContext()->mInCompilingList = false;
}
if (aRequest->IsModuleRequest()) {
MOZ_ASSERT(aRequest->mOffThreadToken);
MOZ_ASSERT(aRequest->GetLoadContext()->mOffThreadToken);
ModuleLoadRequest* request = aRequest->AsModuleRequest();
return mModuleLoader->ProcessFetchedModuleSource(request);
}
// Element may not be ready yet if speculatively compiling, so process the
// request in ProcessPendingRequests when it is available.
MOZ_ASSERT_IF(!SpeculativeOMTParsingEnabled(), aRequest->GetScriptElement());
if (!aRequest->GetScriptElement()) {
MOZ_ASSERT_IF(!SpeculativeOMTParsingEnabled(),
aRequest->GetLoadContext()->GetScriptElement());
if (!aRequest->GetLoadContext()->GetScriptElement()) {
// Unblock onload here in case this request never gets executed.
aRequest->MaybeUnblockOnload();
aRequest->GetLoadContext()->MaybeUnblockOnload();
return NS_OK;
}
@@ -1718,7 +1733,8 @@ nsresult ScriptLoader::ProcessOffThreadRequest(ScriptLoadRequest* aRequest) {
}
// Async scripts and blocking scripts can be executed right away.
if ((aRequest->IsAsyncScript() || aRequest->IsBlockingScript()) &&
if ((aRequest->GetLoadContext()->IsAsyncScript() ||
aRequest->GetLoadContext()->IsBlockingScript()) &&
!aRequest->isInList()) {
return ProcessRequest(aRequest);
}
@@ -1749,7 +1765,7 @@ NotifyOffThreadScriptLoadCompletedRunnable::Run() {
RefPtr<ScriptLoadRequest> request = std::move(mRequest);
// Runnable pointer should have been cleared in the offthread callback.
MOZ_ASSERT(!request->mRunnable);
MOZ_ASSERT(!request->GetLoadContext()->mRunnable);
if (profiler_is_active()) {
ProfilerString8View scriptSourceString;
@@ -1761,18 +1777,19 @@ NotifyOffThreadScriptLoadCompletedRunnable::Run() {
}
nsAutoCString profilerLabelString;
request->GetProfilerLabel(profilerLabelString);
request->GetLoadContext()->GetProfilerLabel(profilerLabelString);
PROFILER_MARKER_TEXT(
scriptSourceString, JS,
MarkerTiming::Interval(request->mOffThreadParseStartTime,
request->mOffThreadParseStopTime),
MarkerTiming::Interval(
request->GetLoadContext()->mOffThreadParseStartTime,
request->GetLoadContext()->mOffThreadParseStopTime),
profilerLabelString);
}
RefPtr<ScriptLoader> loader = std::move(mLoader);
// Request was already cancelled at some earlier point.
if (!request->mOffThreadToken) {
if (!request->GetLoadContext()->mOffThreadToken) {
return NS_OK;
}
@@ -1783,16 +1800,19 @@ static void OffThreadScriptLoaderCallback(JS::OffThreadToken* aToken,
void* aCallbackData) {
RefPtr<NotifyOffThreadScriptLoadCompletedRunnable> aRunnable = dont_AddRef(
static_cast<NotifyOffThreadScriptLoadCompletedRunnable*>(aCallbackData));
MOZ_ASSERT(aRunnable.get() == aRunnable->GetScriptLoadRequest()->mRunnable);
MOZ_ASSERT(aRunnable.get() ==
aRunnable->GetScriptLoadRequest()->GetLoadContext()->mRunnable);
aRunnable->GetScriptLoadRequest()->mOffThreadParseStopTime = TimeStamp::Now();
aRunnable->GetScriptLoadRequest()->GetLoadContext()->mOffThreadParseStopTime =
TimeStamp::Now();
LogRunnable::Run run(aRunnable);
aRunnable->SetToken(aToken);
// If mRunnable was cleared then request was canceled so do nothing.
if (!aRunnable->GetScriptLoadRequest()->mRunnable.exchange(nullptr)) {
if (!aRunnable->GetScriptLoadRequest()->GetLoadContext()->mRunnable.exchange(
nullptr)) {
return;
}
@@ -1805,11 +1825,11 @@ nsresult ScriptLoader::AttemptAsyncScriptCompile(ScriptLoadRequest* aRequest,
// the element is not yet available.
MOZ_ASSERT_IF(!SpeculativeOMTParsingEnabled() && !aRequest->IsModuleRequest(),
aRequest->IsReadyToRun());
MOZ_ASSERT(!aRequest->mWasCompiledOMT);
MOZ_ASSERT(!aRequest->GetLoadContext()->mWasCompiledOMT);
MOZ_ASSERT(aCouldCompileOut && !*aCouldCompileOut);
// Don't off-thread compile inline scripts.
if (aRequest->mIsInline) {
if (aRequest->GetLoadContext()->mIsInline) {
return NS_OK;
}
@@ -1858,12 +1878,12 @@ nsresult ScriptLoader::AttemptAsyncScriptCompile(ScriptLoadRequest* aRequest,
// OffThreadScriptLoaderCallback were we will emulate run.
LogRunnable::LogDispatch(runnable);
aRequest->mOffThreadParseStartTime = TimeStamp::Now();
aRequest->GetLoadContext()->mOffThreadParseStartTime = TimeStamp::Now();
// Save the runnable so it can be properly cleared during cancellation.
aRequest->mRunnable = runnable.get();
auto signalOOM =
mozilla::MakeScopeExit([&aRequest]() { aRequest->mRunnable = nullptr; });
aRequest->GetLoadContext()->mRunnable = runnable.get();
auto signalOOM = mozilla::MakeScopeExit(
[&aRequest]() { aRequest->GetLoadContext()->mRunnable = nullptr; });
if (aRequest->IsModuleRequest()) {
MOZ_ASSERT(aRequest->IsTextSource());
@@ -1871,7 +1891,7 @@ nsresult ScriptLoader::AttemptAsyncScriptCompile(ScriptLoadRequest* aRequest,
nsresult rv = aRequest->GetScriptSource(cx, &maybeSource);
NS_ENSURE_SUCCESS(rv, rv);
aRequest->mOffThreadToken =
aRequest->GetLoadContext()->mOffThreadToken =
maybeSource.constructed<SourceText<char16_t>>()
? JS::CompileModuleToStencilOffThread(
cx, options, maybeSource.ref<SourceText<char16_t>>(),
@@ -1879,15 +1899,15 @@ nsresult ScriptLoader::AttemptAsyncScriptCompile(ScriptLoadRequest* aRequest,
: JS::CompileModuleToStencilOffThread(
cx, options, maybeSource.ref<SourceText<Utf8Unit>>(),
OffThreadScriptLoaderCallback, static_cast<void*>(runnable));
if (!aRequest->mOffThreadToken) {
if (!aRequest->GetLoadContext()->mOffThreadToken) {
return NS_ERROR_OUT_OF_MEMORY;
}
} else if (aRequest->IsBytecode()) {
JS::DecodeOptions decodeOptions(options);
aRequest->mOffThreadToken = JS::DecodeStencilOffThread(
aRequest->GetLoadContext()->mOffThreadToken = JS::DecodeStencilOffThread(
cx, decodeOptions, aRequest->mScriptBytecode, aRequest->mBytecodeOffset,
OffThreadScriptLoaderCallback, static_cast<void*>(runnable));
if (!aRequest->mOffThreadToken) {
if (!aRequest->GetLoadContext()->mOffThreadToken) {
return NS_ERROR_OUT_OF_MEMORY;
}
} else {
@@ -1911,7 +1931,7 @@ nsresult ScriptLoader::AttemptAsyncScriptCompile(ScriptLoadRequest* aRequest,
nsresult rv = aRequest->GetScriptSource(cx, &maybeSource);
NS_ENSURE_SUCCESS(rv, rv);
aRequest->mOffThreadToken =
aRequest->GetLoadContext()->mOffThreadToken =
maybeSource.constructed<SourceText<char16_t>>()
? JS::CompileToStencilOffThread(
cx, options, maybeSource.ref<SourceText<char16_t>>(),
@@ -1919,13 +1939,13 @@ nsresult ScriptLoader::AttemptAsyncScriptCompile(ScriptLoadRequest* aRequest,
: JS::CompileToStencilOffThread(
cx, options, maybeSource.ref<SourceText<Utf8Unit>>(),
OffThreadScriptLoaderCallback, static_cast<void*>(runnable));
if (!aRequest->mOffThreadToken) {
if (!aRequest->GetLoadContext()->mOffThreadToken) {
return NS_ERROR_OUT_OF_MEMORY;
}
}
signalOOM.release();
aRequest->BlockOnload(mDocument);
aRequest->GetLoadContext()->BlockOnload(mDocument);
// Once the compilation is finished, an event would be added to the event loop
// to call ScriptLoader::ProcessOffThreadRequest with the same request.
@@ -1939,7 +1959,7 @@ nsresult ScriptLoader::AttemptAsyncScriptCompile(ScriptLoadRequest* aRequest,
// importing module.
if (aRequest->IsTopLevel() && !aRequest->isInList()) {
mOffThreadCompilingRequests.AppendElement(aRequest);
aRequest->mInCompilingList = true;
aRequest->GetLoadContext()->mInCompilingList = true;
}
*aCouldCompileOut = true;
@@ -1952,7 +1972,8 @@ nsresult ScriptLoader::CompileOffThreadOrProcessRequest(
NS_ASSERTION(nsContentUtils::IsSafeToRunScript(),
"Processing requests when running scripts is unsafe.");
if (!aRequest->mOffThreadToken && !aRequest->InCompilingStage()) {
if (!aRequest->GetLoadContext()->mOffThreadToken &&
!aRequest->GetLoadContext()->CompileStarted()) {
bool couldCompile = false;
nsresult rv = AttemptAsyncScriptCompile(aRequest, &couldCompile);
if (NS_FAILED(rv)) {
@@ -1978,7 +1999,8 @@ nsresult ScriptLoader::ProcessRequest(ScriptLoadRequest* aRequest) {
NS_ENSURE_ARG(aRequest);
auto unblockOnload = MakeScopeExit([&] { aRequest->MaybeUnblockOnload(); });
auto unblockOnload =
MakeScopeExit([&] { aRequest->GetLoadContext()->MaybeUnblockOnload(); });
if (aRequest->IsModuleRequest()) {
ModuleLoadRequest* request = aRequest->AsModuleRequest();
@@ -1998,21 +2020,22 @@ nsresult ScriptLoader::ProcessRequest(ScriptLoadRequest* aRequest) {
}
nsCOMPtr<nsINode> scriptElem =
do_QueryInterface(aRequest->GetScriptElement());
do_QueryInterface(aRequest->GetLoadContext()->GetScriptElement());
nsCOMPtr<Document> doc;
if (!aRequest->mIsInline || aRequest->IsModuleRequest()) {
if (!aRequest->GetLoadContext()->mIsInline || aRequest->IsModuleRequest()) {
doc = scriptElem->OwnerDoc();
}
nsCOMPtr<nsIScriptElement> oldParserInsertedScript;
uint32_t parserCreated = aRequest->GetParserCreated();
uint32_t parserCreated = aRequest->GetLoadContext()->GetParserCreated();
if (parserCreated) {
oldParserInsertedScript = mCurrentParserInsertedScript;
mCurrentParserInsertedScript = aRequest->GetScriptElement();
mCurrentParserInsertedScript =
aRequest->GetLoadContext()->GetScriptElement();
}
aRequest->GetScriptElement()->BeginEvaluating();
aRequest->GetLoadContext()->GetScriptElement()->BeginEvaluating();
FireScriptAvailable(NS_OK, aRequest);
@@ -2055,19 +2078,19 @@ nsresult ScriptLoader::ProcessRequest(ScriptLoadRequest* aRequest) {
FireScriptEvaluated(rv, aRequest);
aRequest->GetScriptElement()->EndEvaluating();
aRequest->GetLoadContext()->GetScriptElement()->EndEvaluating();
if (parserCreated) {
mCurrentParserInsertedScript = oldParserInsertedScript;
}
if (aRequest->mOffThreadToken) {
if (aRequest->GetLoadContext()->mOffThreadToken) {
// The request was parsed off-main-thread, but the result of the off
// thread parse was not actually needed to process the request
// (disappearing window, some other error, ...). Finish the
// request to avoid leaks in the JS engine.
MOZ_ASSERT(!aRequest->IsModuleRequest());
aRequest->MaybeCancelOffThreadScript();
aRequest->GetLoadContext()->MaybeCancelOffThreadScript();
}
// Free any source data, but keep the bytecode content as we might have to
@@ -2087,23 +2110,26 @@ void ScriptLoader::FireScriptAvailable(nsresult aResult,
ScriptLoadRequest* aRequest) {
for (int32_t i = 0; i < mObservers.Count(); i++) {
nsCOMPtr<nsIScriptLoaderObserver> obs = mObservers[i];
obs->ScriptAvailable(aResult, aRequest->GetScriptElement(),
aRequest->mIsInline, aRequest->mURI,
obs->ScriptAvailable(aResult,
aRequest->GetLoadContext()->GetScriptElement(),
aRequest->GetLoadContext()->mIsInline, aRequest->mURI,
aRequest->mLineNo);
}
aRequest->FireScriptAvailable(aResult);
aRequest->GetLoadContext()->FireScriptAvailable(aResult);
}
void ScriptLoader::FireScriptEvaluated(nsresult aResult,
ScriptLoadRequest* aRequest) {
for (int32_t i = 0; i < mObservers.Count(); i++) {
nsCOMPtr<nsIScriptLoaderObserver> obs = mObservers[i];
RefPtr<nsIScriptElement> scriptElement = aRequest->GetScriptElement();
obs->ScriptEvaluated(aResult, scriptElement, aRequest->mIsInline);
RefPtr<nsIScriptElement> scriptElement =
aRequest->GetLoadContext()->GetScriptElement();
obs->ScriptEvaluated(aResult, scriptElement,
aRequest->GetLoadContext()->mIsInline);
}
aRequest->FireScriptEvaluated(aResult);
aRequest->GetLoadContext()->FireScriptEvaluated(aResult);
}
already_AddRefed<nsIGlobalObject> ScriptLoader::GetGlobalForRequest(
@@ -2151,16 +2177,18 @@ nsresult ScriptLoader::FillCompileOptionsForRequest(
}
if (mDocument) {
mDocument->NoteScriptTrackingStatus(aRequest->mURL, aRequest->IsTracking());
mDocument->NoteScriptTrackingStatus(
aRequest->mURL, aRequest->GetLoadContext()->IsTracking());
}
const char* introductionType;
if (aRequest->IsModuleRequest() &&
!aRequest->AsModuleRequest()->IsTopLevel()) {
introductionType = "importedModule";
} else if (!aRequest->mIsInline) {
} else if (!aRequest->GetLoadContext()->mIsInline) {
introductionType = "srcScript";
} else if (aRequest->GetParserCreated() == FROM_PARSER_NETWORK) {
} else if (aRequest->GetLoadContext()->GetParserCreated() ==
FROM_PARSER_NETWORK) {
introductionType = "inlineScript";
} else {
introductionType = "injectedScript";
@@ -2321,7 +2349,7 @@ nsresult ScriptLoader::EvaluateScriptElement(ScriptLoadRequest* aRequest) {
}
nsCOMPtr<nsIContent> scriptContent(
do_QueryInterface(aRequest->GetScriptElement()));
do_QueryInterface(aRequest->GetLoadContext()->GetScriptElement()));
MOZ_ASSERT(scriptContent);
Document* ownerDoc = scriptContent->OwnerDoc();
if (ownerDoc != mDocument) {
@@ -2357,7 +2385,9 @@ nsresult ScriptLoader::EvaluateScriptElement(ScriptLoadRequest* aRequest) {
// This must be destroyed after destroying nsAutoMicroTask, see:
// https://bugzilla.mozilla.org/show_bug.cgi?id=1620505#c4
nsIScriptElement* currentScript =
aRequest->IsModuleRequest() ? nullptr : aRequest->GetScriptElement();
aRequest->IsModuleRequest()
? nullptr
: aRequest->GetLoadContext()->GetScriptElement();
AutoCurrentScriptUpdater scriptUpdater(this, currentScript);
Maybe<AutoSetProcessingScriptTag> setProcessingScriptTag;
@@ -2371,17 +2401,48 @@ nsresult ScriptLoader::EvaluateScriptElement(ScriptLoadRequest* aRequest) {
return EvaluateScript(globalObject, aRequest);
}
nsresult ScriptLoader::CompileOrFinishModuleScript(
JSContext* aCx, JS::Handle<JSObject*> aGlobal, JS::CompileOptions& aOptions,
ModuleLoadRequest* aRequest, JS::MutableHandle<JSObject*> aModule) {
if (aRequest->GetLoadContext()->mWasCompiledOMT) {
JS::Rooted<JS::InstantiationStorage> storage(aCx);
RefPtr<JS::Stencil> stencil = JS::FinishCompileModuleToStencilOffThread(
aCx, aRequest->GetLoadContext()->mOffThreadToken, storage.address());
if (stencil) {
JS::InstantiateOptions instantiateOptions(aOptions);
aModule.set(JS::InstantiateModuleStencil(aCx, instantiateOptions, stencil,
storage.address()));
}
aRequest->GetLoadContext()->mOffThreadToken = nullptr;
return aModule ? NS_OK : NS_ERROR_FAILURE;
}
MaybeSourceText maybeSource;
nsresult rv = aRequest->GetScriptSource(aCx, &maybeSource);
if (NS_SUCCEEDED(rv)) {
return maybeSource.constructed<SourceText<char16_t>>()
? nsJSUtils::CompileModule(
aCx, maybeSource.ref<SourceText<char16_t>>(), aGlobal,
aOptions, aModule)
: nsJSUtils::CompileModule(
aCx, maybeSource.ref<SourceText<Utf8Unit>>(), aGlobal,
aOptions, aModule);
}
return rv;
}
nsresult ScriptLoader::CompileOrDecodeClassicScript(
JSContext* aCx, JSExecutionContext& aExec, ScriptLoadRequest* aRequest) {
nsAutoCString profilerLabelString;
aRequest->GetProfilerLabel(profilerLabelString);
aRequest->GetLoadContext()->GetProfilerLabel(profilerLabelString);
nsresult rv;
if (aRequest->IsBytecode()) {
if (aRequest->mOffThreadToken) {
if (aRequest->GetLoadContext()->mOffThreadToken) {
LOG(("ScriptLoadRequest (%p): Decode Bytecode & Join and Execute",
aRequest));
rv = aExec.JoinDecode(&aRequest->mOffThreadToken);
rv = aExec.JoinDecode(&aRequest->GetLoadContext()->mOffThreadToken);
} else {
LOG(("ScriptLoadRequest (%p): Decode Bytecode and Execute", aRequest));
AUTO_PROFILER_MARKER_TEXT("BytecodeDecodeMainThread", JS,
@@ -2401,14 +2462,14 @@ nsresult ScriptLoader::CompileOrDecodeClassicScript(
bool encodeBytecode = ShouldCacheBytecode(aRequest);
aExec.SetEncodeBytecode(encodeBytecode);
if (aRequest->mOffThreadToken) {
if (aRequest->GetLoadContext()->mOffThreadToken) {
// Off-main-thread parsing.
LOG(
("ScriptLoadRequest (%p): Join (off-thread parsing) and "
"Execute",
aRequest));
MOZ_ASSERT(aRequest->IsTextSource());
rv = aExec.JoinCompile(&aRequest->mOffThreadToken);
rv = aExec.JoinCompile(&aRequest->GetLoadContext()->mOffThreadToken);
} else {
// Main thread parsing (inline and small scripts)
LOG(("ScriptLoadRequest (%p): Compile And Exec", aRequest));
@@ -2437,7 +2498,8 @@ nsresult ScriptLoader::MaybePrepareForBytecodeEncoding(
// Queue the current script load request to later save the bytecode.
if (aScript && encodeBytecode) {
aRequest->SetScript(aScript);
TRACE_FOR_TEST(aRequest->GetScriptElement(), "scriptloader_encode");
TRACE_FOR_TEST(aRequest->GetLoadContext()->GetScriptElement(),
"scriptloader_encode");
MOZ_ASSERT(aRequest->mBytecodeOffset == aRequest->mScriptBytecode.length());
RegisterForBytecodeEncoding(aRequest);
} else {
@@ -2445,7 +2507,8 @@ nsresult ScriptLoader::MaybePrepareForBytecodeEncoding(
("ScriptLoadRequest (%p): Bytecode-cache: disabled (rv = %X, "
"script = %p)",
aRequest, unsigned(aRv), aScript.get()));
TRACE_FOR_TEST_NONE(aRequest->GetScriptElement(), "scriptloader_no_encode");
TRACE_FOR_TEST_NONE(aRequest->GetLoadContext()->GetScriptElement(),
"scriptloader_no_encode");
aRequest->mCacheInfo = nullptr;
}
return aRv;
@@ -2459,7 +2522,7 @@ nsresult ScriptLoader::EvaluateScript(nsIGlobalObject* aGlobalObject,
JS::Rooted<JSObject*> global(cx, aGlobalObject->GetGlobalJSObject());
nsAutoCString profilerLabelString;
aRequest->GetProfilerLabel(profilerLabelString);
aRequest->GetLoadContext()->GetProfilerLabel(profilerLabelString);
// Create a ClassicScript object and associate it with the JSScript.
RefPtr<ClassicScript> classicScript =
@@ -2475,7 +2538,8 @@ nsresult ScriptLoader::EvaluateScript(nsIGlobalObject* aGlobalObject,
return rv;
}
TRACE_FOR_TEST(aRequest->GetScriptElement(), "scriptloader_execute");
TRACE_FOR_TEST(aRequest->GetLoadContext()->GetScriptElement(),
"scriptloader_execute");
JSExecutionContext exec(cx, global, options, classicScriptValue,
introductionScript);
@@ -2634,7 +2698,7 @@ void ScriptLoader::EncodeRequestBytecode(JSContext* aCx,
nsresult rv = NS_OK;
MOZ_ASSERT(aRequest->mCacheInfo);
auto bytecodeFailed = mozilla::MakeScopeExit([&]() {
TRACE_FOR_TEST_NONE(aRequest->GetScriptElement(),
TRACE_FOR_TEST_NONE(aRequest->GetLoadContext()->GetScriptElement(),
"scriptloader_bytecode_failed");
});
@@ -2692,7 +2756,7 @@ void ScriptLoader::EncodeRequestBytecode(JSContext* aCx,
MOZ_RELEASE_ASSERT(aRequest->mScriptBytecode.length() == n);
bytecodeFailed.release();
TRACE_FOR_TEST_NONE(aRequest->GetScriptElement(),
TRACE_FOR_TEST_NONE(aRequest->GetLoadContext()->GetScriptElement(),
"scriptloader_bytecode_saved");
}
@@ -2720,7 +2784,7 @@ void ScriptLoader::GiveUpBytecodeEncoding() {
while (!mBytecodeEncodingQueue.isEmpty()) {
RefPtr<ScriptLoadRequest> request = mBytecodeEncodingQueue.StealFirst();
LOG(("ScriptLoadRequest (%p): Cannot serialize bytecode", request.get()));
TRACE_FOR_TEST_NONE(request->GetScriptElement(),
TRACE_FOR_TEST_NONE(request->GetLoadContext()->GetScriptElement(),
"scriptloader_bytecode_failed");
MOZ_ASSERT(!request->IsModuleRequest());
MOZ_ASSERT(!request->GetWebExtGlobal());
@@ -3097,10 +3161,10 @@ void ScriptLoader::ReportErrorToConsole(ScriptLoadRequest* aRequest,
nsresult aResult) const {
MOZ_ASSERT(aRequest);
if (aRequest->IsPreload()) {
if (aRequest->GetLoadContext()->IsPreload()) {
// Skip reporting errors in preload requests. If the request is actually
// used then we will report the error in ReportPreloadErrorsToConsole below.
aRequest->mUnreportedPreloadError = aResult;
aRequest->GetLoadContext()->mUnreportedPreloadError = aResult;
return;
}
@@ -3124,7 +3188,7 @@ void ScriptLoader::ReportErrorToConsole(ScriptLoadRequest* aRequest,
AutoTArray<nsString, 1> params;
CopyUTF8toUTF16(aRequest->mURI->GetSpecOrDefault(), *params.AppendElement());
nsIScriptElement* element = aRequest->GetScriptElement();
nsIScriptElement* element = aRequest->GetLoadContext()->GetScriptElement();
uint32_t lineNo = element ? element->GetScriptLineNumber() : 0;
uint32_t columnNo = element ? element->GetScriptColumnNumber() : 0;
@@ -3135,9 +3199,10 @@ void ScriptLoader::ReportErrorToConsole(ScriptLoadRequest* aRequest,
}
void ScriptLoader::ReportPreloadErrorsToConsole(ScriptLoadRequest* aRequest) {
if (NS_FAILED(aRequest->mUnreportedPreloadError)) {
ReportErrorToConsole(aRequest, aRequest->mUnreportedPreloadError);
aRequest->mUnreportedPreloadError = NS_OK;
if (NS_FAILED(aRequest->GetLoadContext()->mUnreportedPreloadError)) {
ReportErrorToConsole(aRequest,
aRequest->GetLoadContext()->mUnreportedPreloadError);
aRequest->GetLoadContext()->mUnreportedPreloadError = NS_OK;
}
if (aRequest->IsModuleRequest()) {
@@ -3157,42 +3222,43 @@ void ScriptLoader::HandleLoadError(ScriptLoadRequest* aRequest,
*/
if (net::UrlClassifierFeatureFactory::IsClassifierBlockingErrorCode(
aResult)) {
nsCOMPtr<nsIContent> cont = do_QueryInterface(aRequest->GetScriptElement());
nsCOMPtr<nsIContent> cont =
do_QueryInterface(aRequest->GetLoadContext()->GetScriptElement());
mDocument->AddBlockedNodeByClassifier(cont);
}
if (aRequest->IsModuleRequest() && !aRequest->mIsInline) {
if (aRequest->IsModuleRequest() && !aRequest->GetLoadContext()->mIsInline) {
auto* request = aRequest->AsModuleRequest();
mModuleLoader->SetModuleFetchFinishedAndResumeWaitingRequests(request,
aResult);
}
if (aRequest->mInDeferList) {
if (aRequest->GetLoadContext()->mInDeferList) {
MOZ_ASSERT_IF(aRequest->IsModuleRequest(),
aRequest->AsModuleRequest()->IsTopLevel());
if (aRequest->isInList()) {
RefPtr<ScriptLoadRequest> req = mDeferRequests.Steal(aRequest);
FireScriptAvailable(aResult, req);
}
} else if (aRequest->mInAsyncList) {
} else if (aRequest->GetLoadContext()->mInAsyncList) {
MOZ_ASSERT_IF(aRequest->IsModuleRequest(),
aRequest->AsModuleRequest()->IsTopLevel());
if (aRequest->isInList()) {
RefPtr<ScriptLoadRequest> req = mLoadingAsyncRequests.Steal(aRequest);
FireScriptAvailable(aResult, req);
}
} else if (aRequest->mIsNonAsyncScriptInserted) {
} else if (aRequest->GetLoadContext()->mIsNonAsyncScriptInserted) {
if (aRequest->isInList()) {
RefPtr<ScriptLoadRequest> req =
mNonAsyncExternalScriptInsertedRequests.Steal(aRequest);
FireScriptAvailable(aResult, req);
}
} else if (aRequest->mIsXSLT) {
} else if (aRequest->GetLoadContext()->mIsXSLT) {
if (aRequest->isInList()) {
RefPtr<ScriptLoadRequest> req = mXSLTRequests.Steal(aRequest);
FireScriptAvailable(aResult, req);
}
} else if (aRequest->IsPreload()) {
} else if (aRequest->GetLoadContext()->IsPreload()) {
if (aRequest->IsModuleRequest()) {
aRequest->Cancel();
}
@@ -3226,12 +3292,14 @@ void ScriptLoader::HandleLoadError(ScriptLoadRequest* aRequest,
mParserBlockingRequest = nullptr;
UnblockParser(aRequest);
// Ensure that we treat aRequest->GetScriptElement() as our current
// parser-inserted script while firing onerror on it.
MOZ_ASSERT(aRequest->GetScriptElement()->GetParserCreated());
// Ensure that we treat aRequest->GetLoadContext()->GetScriptElement() as
// our current parser-inserted script while firing onerror on it.
MOZ_ASSERT(
aRequest->GetLoadContext()->GetScriptElement()->GetParserCreated());
nsCOMPtr<nsIScriptElement> oldParserInsertedScript =
mCurrentParserInsertedScript;
mCurrentParserInsertedScript = aRequest->GetScriptElement();
mCurrentParserInsertedScript =
aRequest->GetLoadContext()->GetScriptElement();
FireScriptAvailable(aResult, aRequest);
ContinueParserAsync(aRequest);
mCurrentParserInsertedScript = oldParserInsertedScript;
@@ -3239,18 +3307,21 @@ void ScriptLoader::HandleLoadError(ScriptLoadRequest* aRequest,
// This happens for blocking requests cancelled by ParsingComplete().
// Ignore cancellation status for link-preload requests, as cancellation can
// be omitted for them when SRI is stronger on consumer tags.
MOZ_ASSERT(aRequest->IsCanceled() || aRequest->IsLinkPreloadScript());
MOZ_ASSERT(aRequest->IsCanceled() ||
aRequest->GetLoadContext()->IsLinkPreloadScript());
MOZ_ASSERT(!aRequest->isInList());
}
}
void ScriptLoader::UnblockParser(ScriptLoadRequest* aParserBlockingRequest) {
aParserBlockingRequest->GetScriptElement()->UnblockParser();
aParserBlockingRequest->GetLoadContext()->GetScriptElement()->UnblockParser();
}
void ScriptLoader::ContinueParserAsync(
ScriptLoadRequest* aParserBlockingRequest) {
aParserBlockingRequest->GetScriptElement()->ContinueParserAsync();
aParserBlockingRequest->GetLoadContext()
->GetScriptElement()
->ContinueParserAsync();
}
uint32_t ScriptLoader::NumberOfProcessors() {
@@ -3327,20 +3398,20 @@ bool ScriptLoader::ShouldCompileOffThread(ScriptLoadRequest* aRequest) {
if (SpeculativeOMTParsingEnabled()) {
// Processing non async inserted scripts too early can potentially delay the
// load event from firing so focus on other scripts instead.
if (aRequest->mIsNonAsyncScriptInserted &&
if (aRequest->GetLoadContext()->mIsNonAsyncScriptInserted &&
!StaticPrefs::
dom_script_loader_external_scripts_speculate_non_parser_inserted_enabled()) {
return false;
}
// Async and link preload scripts do not need to be parsed right away.
if (aRequest->IsAsyncScript() &&
if (aRequest->GetLoadContext()->IsAsyncScript() &&
!StaticPrefs::
dom_script_loader_external_scripts_speculate_async_enabled()) {
return false;
}
if (aRequest->IsLinkPreloadScript() &&
if (aRequest->GetLoadContext()->IsLinkPreloadScript() &&
!StaticPrefs::
dom_script_loader_external_scripts_speculate_link_preload_enabled()) {
return false;
@@ -3393,7 +3464,7 @@ nsresult ScriptLoader::PrepareLoadedRequest(ScriptLoadRequest* aRequest,
MOZ_ASSERT(classifiedChannel);
if (classifiedChannel &&
classifiedChannel->IsThirdPartyTrackingResource()) {
aRequest->SetIsTracking();
aRequest->GetLoadContext()->SetIsTracking();
}
}
@@ -3515,7 +3586,7 @@ void ScriptLoader::ParsingComplete(bool aTerminated) {
// Cancel any unused scripts that were compiled speculatively
for (size_t i = 0; i < mPreloads.Length(); i++) {
mPreloads[i].mRequest->MaybeCancelOffThreadScript();
mPreloads[i].mRequest->GetLoadContext()->MaybeCancelOffThreadScript();
}
// Have to call this even if aTerminated so we'll correctly unblock
@@ -3565,10 +3636,10 @@ void ScriptLoader::PreloadURI(nsIURI* aURI, const nsAString& aCharset,
RefPtr<ScriptLoadRequest> request = CreateLoadRequest(
scriptKind, aURI, nullptr, mDocument->NodePrincipal(),
Element::StringToCORSMode(aCrossOrigin), sriMetadata, aReferrerPolicy);
request->mIsInline = false;
request->mScriptFromHead = aScriptFromHead;
request->SetScriptMode(aDefer, aAsync, aLinkPreload);
request->SetIsPreloadRequest();
request->GetLoadContext()->mIsInline = false;
request->GetLoadContext()->mScriptFromHead = aScriptFromHead;
request->GetLoadContext()->SetScriptMode(aDefer, aAsync, aLinkPreload);
request->GetLoadContext()->SetIsPreloadRequest();
if (LOG_ENABLED()) {
nsAutoCString url;
@@ -3588,11 +3659,12 @@ void ScriptLoader::PreloadURI(nsIURI* aURI, const nsAString& aCharset,
}
void ScriptLoader::AddDeferRequest(ScriptLoadRequest* aRequest) {
MOZ_ASSERT(aRequest->IsDeferredScript());
MOZ_ASSERT(!aRequest->mInDeferList && !aRequest->mInAsyncList);
MOZ_ASSERT(!aRequest->mInCompilingList);
MOZ_ASSERT(aRequest->GetLoadContext()->IsDeferredScript());
MOZ_ASSERT(!aRequest->GetLoadContext()->mInDeferList &&
!aRequest->GetLoadContext()->mInAsyncList);
MOZ_ASSERT(!aRequest->GetLoadContext()->mInCompilingList);
aRequest->mInDeferList = true;
aRequest->GetLoadContext()->mInDeferList = true;
mDeferRequests.AppendElement(aRequest);
if (mDeferEnabled && aRequest == mDeferRequests.getFirst() && mDocument &&
!mBlockingDOMContentLoaded) {
@@ -3603,11 +3675,12 @@ void ScriptLoader::AddDeferRequest(ScriptLoadRequest* aRequest) {
}
void ScriptLoader::AddAsyncRequest(ScriptLoadRequest* aRequest) {
MOZ_ASSERT(aRequest->IsAsyncScript());
MOZ_ASSERT(!aRequest->mInDeferList && !aRequest->mInAsyncList);
MOZ_ASSERT(!aRequest->mInCompilingList);
MOZ_ASSERT(aRequest->GetLoadContext()->IsAsyncScript());
MOZ_ASSERT(!aRequest->GetLoadContext()->mInDeferList &&
!aRequest->GetLoadContext()->mInAsyncList);
MOZ_ASSERT(!aRequest->GetLoadContext()->mInCompilingList);
aRequest->mInAsyncList = true;
aRequest->GetLoadContext()->mInAsyncList = true;
if (aRequest->IsReadyToRun()) {
mLoadedAsyncRequests.AppendElement(aRequest);
} else {
@@ -3618,10 +3691,11 @@ void ScriptLoader::AddAsyncRequest(ScriptLoadRequest* aRequest) {
void ScriptLoader::MaybeMoveToLoadedList(ScriptLoadRequest* aRequest) {
MOZ_ASSERT(aRequest->IsReadyToRun());
// If it's async, move it to the loaded list. aRequest->mInAsyncList really
// _should_ be in a list, but the consequences if it's not are bad enough we
// want to avoid trying to move it if it's not.
if (aRequest->mInAsyncList) {
// If it's async, move it to the loaded list.
// aRequest->GetLoadContext()->mInAsyncList really _should_ be in a list, but
// the consequences if it's not are bad enough we want to avoid trying to move
// it if it's not.
if (aRequest->GetLoadContext()->mInAsyncList) {
MOZ_ASSERT(aRequest->isInList());
if (aRequest->isInList()) {
RefPtr<ScriptLoadRequest> req = mLoadingAsyncRequests.Steal(aRequest);