Bug Summary

File:root/firefox-clang/obj-x86_64-pc-linux-gnu/dom/script/./../../../dom/script/ScriptLoader.cpp
Warning:line 4782, column 9
Value stored to 'rv' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -O2 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name Unified_cpp_dom_script0.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -ffp-contract=off -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/dom/script -fcoverage-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/dom/script -resource-dir /usr/lib/llvm-23/lib/clang/23 -include /root/firefox-clang/config/gcc_hidden.h -include /root/firefox-clang/obj-x86_64-pc-linux-gnu/mozilla-config.h -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/stl_wrappers -D _GLIBCXX_ASSERTIONS=1 -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/system_wrappers -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D DEBUG=1 -D MOZ_HAS_MOZGLUE -D MOZILLA_INTERNAL_API -D IMPL_LIBXUL -D MOZ_SUPPORT_LEAKCHECKING -D STATIC_EXPORTABLE_JS_API -I /root/firefox-clang/dom/script -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dom/script -I /root/firefox-clang/dom/base -I /root/firefox-clang/js/loader -I /root/firefox-clang/netwerk/base -I /root/firefox-clang/netwerk/protocol/http -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/ipc/ipdl/_ipdlheaders -I /root/firefox-clang/ipc/chromium/src -I /root/firefox-clang/third_party/abseil-cpp -I /root/firefox-clang/toolkit/components/telemetry -I /root/firefox-clang/xpcom/base -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nspr -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nss -D MOZILLA_CLIENT -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/c++/16 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/x86_64-linux-gnu/c++/16 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/c++/16/backward -internal-isystem /usr/lib/llvm-23/lib/clang/23/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wno-error=pessimizing-move -Wno-error=large-by-value-copy=128 -Wno-error=implicit-int-float-conversion -Wno-error=thread-safety-analysis -Wno-error=tautological-type-limit-compare -Wno-invalid-offsetof -Wno-range-loop-analysis -Wno-deprecated-anon-enum-enum-conversion -Wno-deprecated-enum-enum-conversion -Wno-inline-new-delete -Wno-error=deprecated-declarations -Wno-error=array-bounds -Wno-error=free-nonheap-object -Wno-error=atomic-alignment -Wno-error=deprecated-builtins -Wno-psabi -Wno-error=builtin-macro-redefined -Wno-vla-cxx-extension -Wno-unknown-warning-option -Wno-character-conversion -std=gnu++20 -fdeprecated-macro -ferror-limit 19 -fstrict-flex-arrays=1 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fno-rtti -fgnuc-version=4.2.1 -fno-implicit-modules -fskip-odr-check-in-gmf -fno-sized-deallocation -fno-aligned-allocation -fdiagnostics-absolute-paths -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -mllvm -dwarf-linkage-names=Abstract -faddrsig -fdwarf2-cfi-asm -o /tmp/scan-build-2026-09-01-224014-2642839-1 -x c++ Unified_cpp_dom_script0.cpp
1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5#include "ScriptLoader.h"
6
7#include "GeckoProfiler.h"
8#include "ModuleLoader.h"
9#include "ReferrerInfo.h"
10#include "ScriptCompression.h"
11#include "ScriptLoadHandler.h"
12#include "ScriptTrace.h"
13#include "SharedScriptCache.h"
14#include "js/ColumnNumber.h" // JS::ColumnNumberOneOrigin
15#include "js/CompilationAndEvaluation.h"
16#include "js/CompileOptions.h" // JS::CompileOptions, JS::OwningCompileOptions, JS::DecodeOptions, JS::OwningDecodeOptions, JS::DelazificationOption
17#include "js/ContextOptions.h" // JS::ContextOptionsRef
18#include "js/MemoryFunctions.h"
19#include "js/Modules.h"
20#include "js/PropertyAndElement.h" // JS_DefineProperty
21#include "js/Transcoding.h" // JS::TranscodeRange, JS::TranscodeResult, JS::IsTranscodeFailureResult
22#include "js/Utility.h"
23#include "js/experimental/CompileScript.h" // JS::FrontendContext, JS::NewFrontendContext, JS::DestroyFrontendContext, JS::SetNativeStackQuota, JS::ThreadStackQuotaForSize, JS::CompilationStorage, JS::CompileGlobalScriptToStencil, JS::CompileModuleScriptToStencil, JS::DecodeStencil, JS::PrepareForInstantiate
24#include "js/experimental/JSStencil.h" // JS::Stencil, JS::InstantiationStorage, JS::StartCollectingDelazifications, JS::IsStencilCacheable
25#include "js/loader/LoadedScript.h"
26#include "js/loader/ModuleLoadRequest.h"
27#include "js/loader/ModuleLoaderBase.h"
28#include "js/loader/ScriptLoadRequest.h"
29#include "mozilla/Assertions.h"
30#include "mozilla/AsyncEventDispatcher.h"
31#include "mozilla/Attributes.h"
32#include "mozilla/ConsoleReportCollector.h"
33#include "mozilla/CycleCollectedJSContext.h"
34#include "mozilla/EventQueue.h"
35#include "mozilla/LoadInfo.h"
36#include "mozilla/Logging.h"
37#include "mozilla/Maybe.h"
38#include "mozilla/Mutex.h" // mozilla::Mutex
39#include "mozilla/PreloadHashKey.h"
40#include "mozilla/ProfilerMarkers.h"
41#include "mozilla/ScopeExit.h"
42#include "mozilla/StaticPrefs_browser.h"
43#include "mozilla/StaticPrefs_dom.h"
44#include "mozilla/StaticPrefs_javascript.h"
45#include "mozilla/StaticPrefs_network.h"
46#include "mozilla/TaskController.h"
47#include "mozilla/Telemetry.h"
48#include "mozilla/TimeStamp.h"
49#include "mozilla/UniquePtr.h"
50#include "mozilla/Utf8.h" // mozilla::Utf8Unit
51#include "mozilla/dom/AutoEntryScript.h"
52#include "mozilla/dom/DocGroup.h"
53#include "mozilla/dom/DocumentInlines.h" // Document::GetPresContext
54#include "mozilla/dom/Element.h"
55#include "mozilla/dom/FetchPriority.h"
56#include "mozilla/dom/SpeculationRules.h"
57#ifdef NIGHTLY_BUILD1
58# include "mozilla/dom/IntegrityPolicyWAICT.h"
59#endif
60#include "mozilla/FlowMarkers.h"
61#include "mozilla/dom/JSExecutionUtils.h" // mozilla::dom::Compile, mozilla::dom::InstantiateStencil, mozilla::dom::EvaluationExceptionToNSResult
62#include "mozilla/dom/PolicyContainer.h"
63#include "mozilla/dom/RequestBinding.h"
64#include "mozilla/dom/SRILogHelper.h"
65#include "mozilla/dom/ScriptDecoding.h" // mozilla::dom::ScriptDecoding
66#include "mozilla/dom/ScriptSettings.h"
67#include "mozilla/dom/SpeculationRuleSet.h"
68#include "mozilla/dom/WindowContext.h"
69#include "mozilla/glean/DomMetrics.h"
70#include "mozilla/net/ChannelClassifierUtils.h"
71#include "mozilla/net/HttpBaseChannel.h"
72#include "nsAboutProtocolUtils.h"
73#include "nsCRT.h"
74#include "nsContentCreatorFunctions.h"
75#include "nsContentPolicyUtils.h"
76#include "nsContentSecurityManager.h"
77#include "nsContentSecurityUtils.h"
78#include "nsContentUtils.h"
79#include "nsCycleCollectionParticipant.h"
80#include "nsError.h"
81#include "nsGenericHTMLElement.h"
82#include "nsGkAtoms.h"
83#include "nsIAsyncOutputStream.h"
84#include "nsICacheInfoChannel.h"
85#include "nsIClassOfService.h"
86#include "nsIClassifiedChannel.h"
87#include "nsIContent.h"
88#include "nsIContentSecurityPolicy.h"
89#include "nsIDocShell.h"
90#include "nsIHttpChannel.h"
91#include "nsIHttpChannelInternal.h"
92#include "nsIPrincipal.h"
93#include "nsIScriptContext.h"
94#include "nsIScriptElement.h"
95#include "nsIScriptError.h"
96#include "nsIScriptGlobalObject.h"
97#include "nsISupportsPriority.h"
98#include "nsITimedChannel.h"
99#include "nsITimer.h"
100#include "nsJSPrincipals.h"
101#include "nsJSUtils.h"
102#include "nsNetUtil.h"
103#include "nsPresContext.h" // nsPresContext
104#include "nsProxyRelease.h"
105#include "nsQueryObject.h"
106#include "nsThreadUtils.h"
107#include "nsUnicharUtils.h"
108#include "prsystem.h"
109#include "xpcpublic.h"
110
111using namespace JS::loader;
112
113namespace mozilla::dom {
114
115LazyLogModule ScriptLoader::gCspPRLog("CSP");
116LazyLogModule ScriptLoader::gScriptLoaderLog("ScriptLoader");
117
118#undef LOG
119#define LOG(args) \
120 MOZ_LOG(ScriptLoader::gScriptLoaderLog, mozilla::LogLevel::Debug, args)do { const ::mozilla::LogModule* moz_real_module = ScriptLoader
::gScriptLoaderLog; if ((__builtin_expect(!!(mozilla::detail::
log_test(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Debug
, MOZ_LOG_EXPAND_ARGS args); } } while (0)
121
122#define LOG_ENABLED()(__builtin_expect(!!(mozilla::detail::log_test(ScriptLoader::
gScriptLoaderLog, mozilla::LogLevel::Debug)), 0))
\
123 MOZ_LOG_TEST(ScriptLoader::gScriptLoaderLog, mozilla::LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(ScriptLoader::
gScriptLoaderLog, mozilla::LogLevel::Debug)), 0))
124
125// Alternate Data MIME type used by the ScriptLoader to register that we want to
126// store the disk cache without reading it.
127static constexpr auto kNullMimeType = "javascript/null"_ns;
128
129/////////////////////////////////////////////////////////////
130// ShutdownAndMemoryPressureObserver
131/////////////////////////////////////////////////////////////
132
133NS_IMPL_ISUPPORTS(ShutdownAndMemoryPressureObserver, nsIObserver)MozExternalRefCountType ShutdownAndMemoryPressureObserver::AddRef
(void) { static_assert(!std::is_destructible_v<ShutdownAndMemoryPressureObserver
>, "Reference-counted class " "ShutdownAndMemoryPressureObserver"
" should not have a public destructor. " "Make this class's destructor non-public"
); do { static_assert( mozilla::detail::AssertionConditionType
<decltype(int32_t(mRefCnt) >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0"
" (" "illegal refcnt" ")", "./../../../dom/script/ScriptLoader.cpp"
, 133); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 133
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("ShutdownAndMemoryPressureObserver" != nullptr)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!("ShutdownAndMemoryPressureObserver" != nullptr))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("\"ShutdownAndMemoryPressureObserver\" != nullptr"
" (" "Must specify a name" ")", "./../../../dom/script/ScriptLoader.cpp"
, 133); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"ShutdownAndMemoryPressureObserver\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 133); __attribute__((nomerge)) ::abort(); } while (false); }
} while (false); if (!mRefCnt.isThreadSafe) _mOwningThread.AssertOwnership
("ShutdownAndMemoryPressureObserver" " not thread-safe"); nsrefcnt
count = ++mRefCnt; NS_LogAddRef((this), (count), ("ShutdownAndMemoryPressureObserver"
), (uint32_t)(sizeof(*this))); return count; } MozExternalRefCountType
ShutdownAndMemoryPressureObserver::Release(void) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(int32_t
(mRefCnt) > 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) > 0))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0"
" (" "dup release" ")", "./../../../dom/script/ScriptLoader.cpp"
, 133); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 133
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("ShutdownAndMemoryPressureObserver" != nullptr)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!("ShutdownAndMemoryPressureObserver" != nullptr))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("\"ShutdownAndMemoryPressureObserver\" != nullptr"
" (" "Must specify a name" ")", "./../../../dom/script/ScriptLoader.cpp"
, 133); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"ShutdownAndMemoryPressureObserver\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 133); __attribute__((nomerge)) ::abort(); } while (false); }
} while (false); if (!mRefCnt.isThreadSafe) _mOwningThread.AssertOwnership
("ShutdownAndMemoryPressureObserver" " not thread-safe"); const
char* const nametmp = "ShutdownAndMemoryPressureObserver"; nsrefcnt
count = --mRefCnt; NS_LogRelease((this), (count), (nametmp))
; if (count == 0) { mRefCnt = 1; delete (this); return 0; } return
count; } nsresult ShutdownAndMemoryPressureObserver::QueryInterface
(const nsIID& aIID, void** aInstancePtr) { do { if (!(aInstancePtr
)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "QueryInterface requires a non-NULL destination!"
, "aInstancePtr", "./../../../dom/script/ScriptLoader.cpp", 133
); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE
; static_assert(1 > 0, "Need more arguments to NS_INTERFACE_TABLE"
); static const QITableEntry table[] = { {&mozilla::detail
::kImplementedIID<ShutdownAndMemoryPressureObserver, nsIObserver
>, int32_t( reinterpret_cast<char*>(static_cast<nsIObserver
*>((ShutdownAndMemoryPressureObserver*)0x1000)) - reinterpret_cast
<char*>((ShutdownAndMemoryPressureObserver*)0x1000))}, {
&mozilla::detail::kImplementedIID<ShutdownAndMemoryPressureObserver
, nsISupports>, int32_t(reinterpret_cast<char*>(static_cast
<nsISupports*>( static_cast<nsIObserver*>((ShutdownAndMemoryPressureObserver
*)0x1000))) - reinterpret_cast<char*>((ShutdownAndMemoryPressureObserver
*)0x1000))}, { nullptr, 0 } } ; static_assert(std::size(table
) > 1, "need at least 1 interface"); rv = NS_TableDrivenQI
(static_cast<void*>(this), aIID, aInstancePtr, table); return
rv; }
134
135void ShutdownAndMemoryPressureObserver::OnShutdown() {
136 if (mScriptLoader) {
137 mScriptLoader->Destroy();
138 MOZ_ASSERT(!mScriptLoader)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mScriptLoader)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mScriptLoader))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("!mScriptLoader"
, "./../../../dom/script/ScriptLoader.cpp", 138); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!mScriptLoader" ")"); do { MOZ_CrashSequence
(__null, 138); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
139 }
140}
141
142void ShutdownAndMemoryPressureObserver::OnMemoryPressure() {
143 if (mScriptLoader) {
144 mScriptLoader->OnMemoryPressure();
145 }
146}
147
148void ShutdownAndMemoryPressureObserver::Unregister() {
149 if (mScriptLoader) {
150 mScriptLoader = nullptr;
151 nsContentUtils::UnregisterShutdownObserver(this);
152
153 nsCOMPtr<nsIObserverService> obsService = services::GetObserverService();
154 if (obsService) {
155 obsService->RemoveObserver(this, "memory-pressure");
156 }
157 }
158}
159
160NS_IMETHODIMPnsresult
161ShutdownAndMemoryPressureObserver::Observe(nsISupports* aSubject,
162 const char* aTopic,
163 const char16_t* aData) {
164 if (strcmp(aTopic, "xpcom-shutdown") == 0) {
165 OnShutdown();
166 return NS_OK;
167 }
168
169 if (strcmp(aTopic, "memory-pressure") == 0) {
170 OnMemoryPressure();
171 return NS_OK;
172 }
173
174 return NS_OK;
175}
176
177//////////////////////////////////////////////////////////////
178// ScriptLoader::PreloadInfo
179//////////////////////////////////////////////////////////////
180
181inline void ImplCycleCollectionUnlink(ScriptLoader::PreloadInfo& aField) {
182 ImplCycleCollectionUnlink(aField.mRequest);
183}
184
185inline void ImplCycleCollectionTraverse(
186 nsCycleCollectionTraversalCallback& aCallback,
187 ScriptLoader::PreloadInfo& aField, const char* aName, uint32_t aFlags = 0) {
188 ImplCycleCollectionTraverse(aCallback, aField.mRequest, aName, aFlags);
189}
190
191//////////////////////////////////////////////////////////////
192// ScriptLoader
193//////////////////////////////////////////////////////////////
194
195NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ScriptLoader)nsresult ScriptLoader::QueryInterface(const nsIID& aIID, void
** aInstancePtr) { do { if (!(aInstancePtr)) { NS_DebugBreak(
NS_DEBUG_ASSERTION, "QueryInterface requires a non-NULL destination!"
, "aInstancePtr", "./../../../dom/script/ScriptLoader.cpp", 195
); MOZ_PretendNoReturn(); } } while (0); nsISupports* foundInterface
; if (TopThreeWordsEquals( aIID, (nsXPCOMCycleCollectionParticipant
::kIID), (nsCycleCollectionISupports::kIID)) && (LowWordEquals
(aIID, (nsXPCOMCycleCollectionParticipant::kIID)) || LowWordEquals
(aIID, (nsCycleCollectionISupports::kIID)))) { if (LowWordEquals
(aIID, (nsXPCOMCycleCollectionParticipant::kIID))) { *aInstancePtr
= ScriptLoader::cycleCollection::GetParticipant(); return NS_OK
; } if (LowWordEquals(aIID, (nsCycleCollectionISupports::kIID
))) { *aInstancePtr = ScriptLoader::cycleCollection::Upcast(this
); return NS_OK; } foundInterface = nullptr; } else
196NS_INTERFACE_MAP_ENDfoundInterface = 0; nsresult status; if (!foundInterface) { do
{ static_assert( mozilla::detail::AssertionConditionType<
decltype(!aIID.Equals((nsISupports::kIID)))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aIID.Equals((nsISupports::kIID
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!aIID.Equals((nsISupports::kIID))", "./../../../dom/script/ScriptLoader.cpp"
, 196); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aIID.Equals((nsISupports::kIID))"
")"); do { MOZ_CrashSequence(__null, 196); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); status = NS_NOINTERFACE
; } else { (foundInterface)->AddRef(); status = NS_OK; } *
aInstancePtr = foundInterface; return status; }
197
198NS_IMPL_CYCLE_COLLECTION_CLASS(ScriptLoader)ScriptLoader::cycleCollection ScriptLoader::_cycleCollectorGlobal
;
199
200NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ScriptLoader)void ScriptLoader::cycleCollection::Unlink(void* p) { ScriptLoader
* tmp = DowncastCCParticipant<ScriptLoader>(p);
201 if (tmp->mDocument) {
202 tmp->DropDocumentReference();
203 }
204 NS_IMPL_CYCLE_COLLECTION_UNLINK(ImplCycleCollectionUnlink(tmp->mNonAsyncExternalScriptInsertedRequests
); ImplCycleCollectionUnlink(tmp->mLoadingAsyncRequests); ImplCycleCollectionUnlink
(tmp->mLoadedAsyncRequests); ImplCycleCollectionUnlink(tmp
->mDeferRequests); ImplCycleCollectionUnlink(tmp->mXSLTRequests
); ImplCycleCollectionUnlink(tmp->mParserBlockingRequest);
ImplCycleCollectionUnlink(tmp->mOffThreadCompilingRequests
); ImplCycleCollectionUnlink(tmp->mDiskCacheableDependencyModules
); ImplCycleCollectionUnlink(tmp->mDiskCacheQueue); ImplCycleCollectionUnlink
(tmp->mPreloads); ImplCycleCollectionUnlink(tmp->mPendingChildLoaders
); ImplCycleCollectionUnlink(tmp->mModuleLoader); ImplCycleCollectionUnlink
(tmp->mWebExtModuleLoaders);
205 mNonAsyncExternalScriptInsertedRequests, mLoadingAsyncRequests,ImplCycleCollectionUnlink(tmp->mNonAsyncExternalScriptInsertedRequests
); ImplCycleCollectionUnlink(tmp->mLoadingAsyncRequests); ImplCycleCollectionUnlink
(tmp->mLoadedAsyncRequests); ImplCycleCollectionUnlink(tmp
->mDeferRequests); ImplCycleCollectionUnlink(tmp->mXSLTRequests
); ImplCycleCollectionUnlink(tmp->mParserBlockingRequest);
ImplCycleCollectionUnlink(tmp->mOffThreadCompilingRequests
); ImplCycleCollectionUnlink(tmp->mDiskCacheableDependencyModules
); ImplCycleCollectionUnlink(tmp->mDiskCacheQueue); ImplCycleCollectionUnlink
(tmp->mPreloads); ImplCycleCollectionUnlink(tmp->mPendingChildLoaders
); ImplCycleCollectionUnlink(tmp->mModuleLoader); ImplCycleCollectionUnlink
(tmp->mWebExtModuleLoaders);
206 mLoadedAsyncRequests, mDeferRequests, mXSLTRequests,ImplCycleCollectionUnlink(tmp->mNonAsyncExternalScriptInsertedRequests
); ImplCycleCollectionUnlink(tmp->mLoadingAsyncRequests); ImplCycleCollectionUnlink
(tmp->mLoadedAsyncRequests); ImplCycleCollectionUnlink(tmp
->mDeferRequests); ImplCycleCollectionUnlink(tmp->mXSLTRequests
); ImplCycleCollectionUnlink(tmp->mParserBlockingRequest);
ImplCycleCollectionUnlink(tmp->mOffThreadCompilingRequests
); ImplCycleCollectionUnlink(tmp->mDiskCacheableDependencyModules
); ImplCycleCollectionUnlink(tmp->mDiskCacheQueue); ImplCycleCollectionUnlink
(tmp->mPreloads); ImplCycleCollectionUnlink(tmp->mPendingChildLoaders
); ImplCycleCollectionUnlink(tmp->mModuleLoader); ImplCycleCollectionUnlink
(tmp->mWebExtModuleLoaders);
207 mParserBlockingRequest, mOffThreadCompilingRequests,ImplCycleCollectionUnlink(tmp->mNonAsyncExternalScriptInsertedRequests
); ImplCycleCollectionUnlink(tmp->mLoadingAsyncRequests); ImplCycleCollectionUnlink
(tmp->mLoadedAsyncRequests); ImplCycleCollectionUnlink(tmp
->mDeferRequests); ImplCycleCollectionUnlink(tmp->mXSLTRequests
); ImplCycleCollectionUnlink(tmp->mParserBlockingRequest);
ImplCycleCollectionUnlink(tmp->mOffThreadCompilingRequests
); ImplCycleCollectionUnlink(tmp->mDiskCacheableDependencyModules
); ImplCycleCollectionUnlink(tmp->mDiskCacheQueue); ImplCycleCollectionUnlink
(tmp->mPreloads); ImplCycleCollectionUnlink(tmp->mPendingChildLoaders
); ImplCycleCollectionUnlink(tmp->mModuleLoader); ImplCycleCollectionUnlink
(tmp->mWebExtModuleLoaders);
208 mDiskCacheableDependencyModules, mDiskCacheQueue, mPreloads,ImplCycleCollectionUnlink(tmp->mNonAsyncExternalScriptInsertedRequests
); ImplCycleCollectionUnlink(tmp->mLoadingAsyncRequests); ImplCycleCollectionUnlink
(tmp->mLoadedAsyncRequests); ImplCycleCollectionUnlink(tmp
->mDeferRequests); ImplCycleCollectionUnlink(tmp->mXSLTRequests
); ImplCycleCollectionUnlink(tmp->mParserBlockingRequest);
ImplCycleCollectionUnlink(tmp->mOffThreadCompilingRequests
); ImplCycleCollectionUnlink(tmp->mDiskCacheableDependencyModules
); ImplCycleCollectionUnlink(tmp->mDiskCacheQueue); ImplCycleCollectionUnlink
(tmp->mPreloads); ImplCycleCollectionUnlink(tmp->mPendingChildLoaders
); ImplCycleCollectionUnlink(tmp->mModuleLoader); ImplCycleCollectionUnlink
(tmp->mWebExtModuleLoaders);
209 mPendingChildLoaders, mModuleLoader, mWebExtModuleLoaders)ImplCycleCollectionUnlink(tmp->mNonAsyncExternalScriptInsertedRequests
); ImplCycleCollectionUnlink(tmp->mLoadingAsyncRequests); ImplCycleCollectionUnlink
(tmp->mLoadedAsyncRequests); ImplCycleCollectionUnlink(tmp
->mDeferRequests); ImplCycleCollectionUnlink(tmp->mXSLTRequests
); ImplCycleCollectionUnlink(tmp->mParserBlockingRequest);
ImplCycleCollectionUnlink(tmp->mOffThreadCompilingRequests
); ImplCycleCollectionUnlink(tmp->mDiskCacheableDependencyModules
); ImplCycleCollectionUnlink(tmp->mDiskCacheQueue); ImplCycleCollectionUnlink
(tmp->mPreloads); ImplCycleCollectionUnlink(tmp->mPendingChildLoaders
); ImplCycleCollectionUnlink(tmp->mModuleLoader); ImplCycleCollectionUnlink
(tmp->mWebExtModuleLoaders);
210NS_IMPL_CYCLE_COLLECTION_UNLINK_END(void)tmp; }
211
212NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(ScriptLoader)nsresult ScriptLoader::cycleCollection::TraverseNative( void*
p, nsCycleCollectionTraversalCallback& cb) { ScriptLoader
* tmp = DowncastCCParticipant<ScriptLoader>(p); cb.DescribeRefCountedNode
(tmp->mRefCnt.get(), "ScriptLoader");
213 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(ImplCycleCollectionTraverse(cb, tmp->mNonAsyncExternalScriptInsertedRequests
, "mNonAsyncExternalScriptInsertedRequests", 0); ImplCycleCollectionTraverse
(cb, tmp->mLoadingAsyncRequests, "mLoadingAsyncRequests", 0
); ImplCycleCollectionTraverse(cb, tmp->mLoadedAsyncRequests
, "mLoadedAsyncRequests", 0); ImplCycleCollectionTraverse(cb,
tmp->mDeferRequests, "mDeferRequests", 0); ImplCycleCollectionTraverse
(cb, tmp->mXSLTRequests, "mXSLTRequests", 0); ImplCycleCollectionTraverse
(cb, tmp->mParserBlockingRequest, "mParserBlockingRequest"
, 0); ImplCycleCollectionTraverse(cb, tmp->mOffThreadCompilingRequests
, "mOffThreadCompilingRequests", 0); ImplCycleCollectionTraverse
(cb, tmp->mDiskCacheableDependencyModules, "mDiskCacheableDependencyModules"
, 0); ImplCycleCollectionTraverse(cb, tmp->mDiskCacheQueue
, "mDiskCacheQueue", 0); ImplCycleCollectionTraverse(cb, tmp->
mPreloads, "mPreloads", 0); ImplCycleCollectionTraverse(cb, tmp
->mPendingChildLoaders, "mPendingChildLoaders", 0); ImplCycleCollectionTraverse
(cb, tmp->mModuleLoader, "mModuleLoader", 0); ImplCycleCollectionTraverse
(cb, tmp->mWebExtModuleLoaders, "mWebExtModuleLoaders", 0)
;
214 mNonAsyncExternalScriptInsertedRequests, mLoadingAsyncRequests,ImplCycleCollectionTraverse(cb, tmp->mNonAsyncExternalScriptInsertedRequests
, "mNonAsyncExternalScriptInsertedRequests", 0); ImplCycleCollectionTraverse
(cb, tmp->mLoadingAsyncRequests, "mLoadingAsyncRequests", 0
); ImplCycleCollectionTraverse(cb, tmp->mLoadedAsyncRequests
, "mLoadedAsyncRequests", 0); ImplCycleCollectionTraverse(cb,
tmp->mDeferRequests, "mDeferRequests", 0); ImplCycleCollectionTraverse
(cb, tmp->mXSLTRequests, "mXSLTRequests", 0); ImplCycleCollectionTraverse
(cb, tmp->mParserBlockingRequest, "mParserBlockingRequest"
, 0); ImplCycleCollectionTraverse(cb, tmp->mOffThreadCompilingRequests
, "mOffThreadCompilingRequests", 0); ImplCycleCollectionTraverse
(cb, tmp->mDiskCacheableDependencyModules, "mDiskCacheableDependencyModules"
, 0); ImplCycleCollectionTraverse(cb, tmp->mDiskCacheQueue
, "mDiskCacheQueue", 0); ImplCycleCollectionTraverse(cb, tmp->
mPreloads, "mPreloads", 0); ImplCycleCollectionTraverse(cb, tmp
->mPendingChildLoaders, "mPendingChildLoaders", 0); ImplCycleCollectionTraverse
(cb, tmp->mModuleLoader, "mModuleLoader", 0); ImplCycleCollectionTraverse
(cb, tmp->mWebExtModuleLoaders, "mWebExtModuleLoaders", 0)
;
215 mLoadedAsyncRequests, mDeferRequests, mXSLTRequests,ImplCycleCollectionTraverse(cb, tmp->mNonAsyncExternalScriptInsertedRequests
, "mNonAsyncExternalScriptInsertedRequests", 0); ImplCycleCollectionTraverse
(cb, tmp->mLoadingAsyncRequests, "mLoadingAsyncRequests", 0
); ImplCycleCollectionTraverse(cb, tmp->mLoadedAsyncRequests
, "mLoadedAsyncRequests", 0); ImplCycleCollectionTraverse(cb,
tmp->mDeferRequests, "mDeferRequests", 0); ImplCycleCollectionTraverse
(cb, tmp->mXSLTRequests, "mXSLTRequests", 0); ImplCycleCollectionTraverse
(cb, tmp->mParserBlockingRequest, "mParserBlockingRequest"
, 0); ImplCycleCollectionTraverse(cb, tmp->mOffThreadCompilingRequests
, "mOffThreadCompilingRequests", 0); ImplCycleCollectionTraverse
(cb, tmp->mDiskCacheableDependencyModules, "mDiskCacheableDependencyModules"
, 0); ImplCycleCollectionTraverse(cb, tmp->mDiskCacheQueue
, "mDiskCacheQueue", 0); ImplCycleCollectionTraverse(cb, tmp->
mPreloads, "mPreloads", 0); ImplCycleCollectionTraverse(cb, tmp
->mPendingChildLoaders, "mPendingChildLoaders", 0); ImplCycleCollectionTraverse
(cb, tmp->mModuleLoader, "mModuleLoader", 0); ImplCycleCollectionTraverse
(cb, tmp->mWebExtModuleLoaders, "mWebExtModuleLoaders", 0)
;
216 mParserBlockingRequest, mOffThreadCompilingRequests,ImplCycleCollectionTraverse(cb, tmp->mNonAsyncExternalScriptInsertedRequests
, "mNonAsyncExternalScriptInsertedRequests", 0); ImplCycleCollectionTraverse
(cb, tmp->mLoadingAsyncRequests, "mLoadingAsyncRequests", 0
); ImplCycleCollectionTraverse(cb, tmp->mLoadedAsyncRequests
, "mLoadedAsyncRequests", 0); ImplCycleCollectionTraverse(cb,
tmp->mDeferRequests, "mDeferRequests", 0); ImplCycleCollectionTraverse
(cb, tmp->mXSLTRequests, "mXSLTRequests", 0); ImplCycleCollectionTraverse
(cb, tmp->mParserBlockingRequest, "mParserBlockingRequest"
, 0); ImplCycleCollectionTraverse(cb, tmp->mOffThreadCompilingRequests
, "mOffThreadCompilingRequests", 0); ImplCycleCollectionTraverse
(cb, tmp->mDiskCacheableDependencyModules, "mDiskCacheableDependencyModules"
, 0); ImplCycleCollectionTraverse(cb, tmp->mDiskCacheQueue
, "mDiskCacheQueue", 0); ImplCycleCollectionTraverse(cb, tmp->
mPreloads, "mPreloads", 0); ImplCycleCollectionTraverse(cb, tmp
->mPendingChildLoaders, "mPendingChildLoaders", 0); ImplCycleCollectionTraverse
(cb, tmp->mModuleLoader, "mModuleLoader", 0); ImplCycleCollectionTraverse
(cb, tmp->mWebExtModuleLoaders, "mWebExtModuleLoaders", 0)
;
217 mDiskCacheableDependencyModules, mDiskCacheQueue, mPreloads,ImplCycleCollectionTraverse(cb, tmp->mNonAsyncExternalScriptInsertedRequests
, "mNonAsyncExternalScriptInsertedRequests", 0); ImplCycleCollectionTraverse
(cb, tmp->mLoadingAsyncRequests, "mLoadingAsyncRequests", 0
); ImplCycleCollectionTraverse(cb, tmp->mLoadedAsyncRequests
, "mLoadedAsyncRequests", 0); ImplCycleCollectionTraverse(cb,
tmp->mDeferRequests, "mDeferRequests", 0); ImplCycleCollectionTraverse
(cb, tmp->mXSLTRequests, "mXSLTRequests", 0); ImplCycleCollectionTraverse
(cb, tmp->mParserBlockingRequest, "mParserBlockingRequest"
, 0); ImplCycleCollectionTraverse(cb, tmp->mOffThreadCompilingRequests
, "mOffThreadCompilingRequests", 0); ImplCycleCollectionTraverse
(cb, tmp->mDiskCacheableDependencyModules, "mDiskCacheableDependencyModules"
, 0); ImplCycleCollectionTraverse(cb, tmp->mDiskCacheQueue
, "mDiskCacheQueue", 0); ImplCycleCollectionTraverse(cb, tmp->
mPreloads, "mPreloads", 0); ImplCycleCollectionTraverse(cb, tmp
->mPendingChildLoaders, "mPendingChildLoaders", 0); ImplCycleCollectionTraverse
(cb, tmp->mModuleLoader, "mModuleLoader", 0); ImplCycleCollectionTraverse
(cb, tmp->mWebExtModuleLoaders, "mWebExtModuleLoaders", 0)
;
218 mPendingChildLoaders, mModuleLoader, mWebExtModuleLoaders)ImplCycleCollectionTraverse(cb, tmp->mNonAsyncExternalScriptInsertedRequests
, "mNonAsyncExternalScriptInsertedRequests", 0); ImplCycleCollectionTraverse
(cb, tmp->mLoadingAsyncRequests, "mLoadingAsyncRequests", 0
); ImplCycleCollectionTraverse(cb, tmp->mLoadedAsyncRequests
, "mLoadedAsyncRequests", 0); ImplCycleCollectionTraverse(cb,
tmp->mDeferRequests, "mDeferRequests", 0); ImplCycleCollectionTraverse
(cb, tmp->mXSLTRequests, "mXSLTRequests", 0); ImplCycleCollectionTraverse
(cb, tmp->mParserBlockingRequest, "mParserBlockingRequest"
, 0); ImplCycleCollectionTraverse(cb, tmp->mOffThreadCompilingRequests
, "mOffThreadCompilingRequests", 0); ImplCycleCollectionTraverse
(cb, tmp->mDiskCacheableDependencyModules, "mDiskCacheableDependencyModules"
, 0); ImplCycleCollectionTraverse(cb, tmp->mDiskCacheQueue
, "mDiskCacheQueue", 0); ImplCycleCollectionTraverse(cb, tmp->
mPreloads, "mPreloads", 0); ImplCycleCollectionTraverse(cb, tmp
->mPendingChildLoaders, "mPendingChildLoaders", 0); ImplCycleCollectionTraverse
(cb, tmp->mModuleLoader, "mModuleLoader", 0); ImplCycleCollectionTraverse
(cb, tmp->mWebExtModuleLoaders, "mWebExtModuleLoaders", 0)
;
219NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END(void)tmp; return NS_OK; }
220
221NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(ScriptLoader)void ScriptLoader::cycleCollection::Trace( void* p, const TraceCallbacks
& aCallbacks, void* aClosure) { ScriptLoader* tmp = DowncastCCParticipant
<ScriptLoader>(p);
222 for (size_t i = 0; i < tmp->mDelazificationCollectingScripts.Length(); ++i) {
223 NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(ImplCycleCollectionTrace(aCallbacks, tmp->mDelazificationCollectingScripts
[i], "mDelazificationCollectingScripts[i]", aClosure);
224 mDelazificationCollectingScripts[i])ImplCycleCollectionTrace(aCallbacks, tmp->mDelazificationCollectingScripts
[i], "mDelazificationCollectingScripts[i]", aClosure);
225 }
226 for (size_t i = 0; i < tmp->mDelazificationCollectingModules.Length(); ++i) {
227 NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(ImplCycleCollectionTrace(aCallbacks, tmp->mDelazificationCollectingModules
[i], "mDelazificationCollectingModules[i]", aClosure);
228 mDelazificationCollectingModules[i])ImplCycleCollectionTrace(aCallbacks, tmp->mDelazificationCollectingModules
[i], "mDelazificationCollectingModules[i]", aClosure);
229 }
230NS_IMPL_CYCLE_COLLECTION_TRACE_END(void)tmp; }
231
232NS_IMPL_CYCLE_COLLECTING_ADDREF(ScriptLoader)MozExternalRefCountType ScriptLoader::AddRef(void) { static_assert
(!std::is_destructible_v<ScriptLoader>, "Reference-counted class "
"ScriptLoader" " should not have a public destructor. " "Make this class's destructor non-public"
); do { static_assert( mozilla::detail::AssertionConditionType
<decltype(int32_t(mRefCnt) >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0"
" (" "illegal refcnt" ")", "./../../../dom/script/ScriptLoader.cpp"
, 232); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 232
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); _mOwningThread.AssertOwnership("ScriptLoader" " not thread-safe"
); nsISupports* base = ScriptLoader::cycleCollection::Upcast(
this); nsrefcnt count = mRefCnt.incr(base); NS_LogAddRef((this
), (count), ("ScriptLoader"), (uint32_t)(sizeof(*this))); return
count; }
233NS_IMPL_CYCLE_COLLECTING_RELEASE(ScriptLoader)MozExternalRefCountType ScriptLoader::Release(void) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(int32_t
(mRefCnt) > 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) > 0))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0"
" (" "dup release" ")", "./../../../dom/script/ScriptLoader.cpp"
, 233); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 233
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); _mOwningThread.AssertOwnership("ScriptLoader" " not thread-safe"
); nsISupports* base = ScriptLoader::cycleCollection::Upcast(
this); nsrefcnt count = mRefCnt.decr(base); if (count == 0) {
NS_CycleCollectableHasRefCntZero(); } NS_LogRelease((this), (
count), ("ScriptLoader")); return count; } void ScriptLoader::
DeleteCycleCollectable(void) { delete (this); }
234
235ScriptLoader::ScriptLoader(Document* aDocument)
236 : mDocument(aDocument), mReporter(new ConsoleReportCollector()) {
237 LOG(("ScriptLoader::ScriptLoader %p", this));
238
239 mSpeculativeOMTParsingEnabled = StaticPrefs::
240 dom_script_loader_external_scripts_speculative_omt_parse_enabled();
241
242 // NOTE: The loader for the system principal aren't supposed to
243 // load remote contents, and it doesn't have to use the in-memory cache.
244 // A non-system-principal document can also load internal resources,
245 // and those cases should be filtered out by
246 // ScriptLoader::GetCacheBehavior.
247 if (!LoaderPrincipal()->IsSystemPrincipal() &&
248 StaticPrefs::dom_script_loader_experimental_navigation_cache()) {
249 mCache = SharedScriptCache::Get();
250 RegisterToCache();
251 LOG(("ScriptLoader (%p): Using in-memory cache.", this));
252 }
253
254 mObserver = new ShutdownAndMemoryPressureObserver(this);
255 nsContentUtils::RegisterShutdownObserver(mObserver);
256
257 nsCOMPtr<nsIObserverService> obsService = services::GetObserverService();
258 if (obsService) {
259 obsService->AddObserver(mObserver, "memory-pressure", false);
260 }
261}
262
263ScriptLoader::~ScriptLoader() {
264 LOG(("ScriptLoader::~ScriptLoader %p", this));
265
266 if (!mDelazificationCollectingScripts.IsEmpty() ||
267 !mDelazificationCollectingModules.IsEmpty()) {
268 mDelazificationCollectingScripts.Clear();
269 mDelazificationCollectingModules.Clear();
270
271 mozilla::DropJSObjects(this);
272 }
273
274 mObservers.Clear();
275
276 if (mParserBlockingRequest) {
277 const RefPtr<ScriptLoadRequest> parserBlockRequest = mParserBlockingRequest;
278 FireScriptAvailable(NS_ERROR_ABORT, parserBlockRequest);
279 }
280
281 for (RefPtr<ScriptLoadRequest> req = mXSLTRequests.getFirst(); req;
282 req = req->getNext()) {
283 FireScriptAvailable(NS_ERROR_ABORT, req);
284 }
285
286 for (RefPtr<ScriptLoadRequest> req = mDeferRequests.getFirst(); req;
287 req = req->getNext()) {
288 FireScriptAvailable(NS_ERROR_ABORT, req);
289 }
290
291 for (RefPtr<ScriptLoadRequest> req = mLoadingAsyncRequests.getFirst(); req;
292 req = req->getNext()) {
293 FireScriptAvailable(NS_ERROR_ABORT, req);
294 }
295
296 for (RefPtr<ScriptLoadRequest> req = mLoadedAsyncRequests.getFirst(); req;
297 req = req->getNext()) {
298 FireScriptAvailable(NS_ERROR_ABORT, req);
299 }
300
301 for (RefPtr<ScriptLoadRequest> req =
302 mNonAsyncExternalScriptInsertedRequests.getFirst();
303 req; req = req->getNext()) {
304 FireScriptAvailable(NS_ERROR_ABORT, req);
305 }
306
307 // Unblock the kids, in case any of them moved to a different document
308 // subtree in the meantime and therefore aren't actually going away.
309 for (uint32_t j = 0; j < mPendingChildLoaders.Length(); ++j) {
310 mPendingChildLoaders[j]->RemoveParserBlockingScriptExecutionBlocker();
311 }
312
313 if (mObserver) {
314 mObserver->Unregister();
315 mObserver = nullptr;
316 }
317
318 mModuleLoader = nullptr;
319
320 if (mProcessPendingRequestsAsyncBypassParserBlocking) {
321 mProcessPendingRequestsAsyncBypassParserBlocking->Cancel();
322 }
323}
324
325void ScriptLoader::SetGlobalObject(nsIGlobalObject* aGlobalObject) {
326 if (!aGlobalObject) {
327 // The document is being detached.
328 CancelAndClearScriptLoadRequests();
329 return;
330 }
331
332 MOZ_ASSERT(!HasPendingRequests())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!HasPendingRequests())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!HasPendingRequests()))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("!HasPendingRequests()"
, "./../../../dom/script/ScriptLoader.cpp", 332); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!HasPendingRequests()" ")"); do { MOZ_CrashSequence
(__null, 332); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
333
334 if (!mModuleLoader) {
335 // The module loader is associated with a global object, so don't create it
336 // until we have a global set.
337 mModuleLoader = new ModuleLoader(this, aGlobalObject, ModuleLoader::Normal);
338 }
339
340 MOZ_ASSERT(mModuleLoader->GetGlobalObject() == aGlobalObject)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mModuleLoader->GetGlobalObject() == aGlobalObject
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(mModuleLoader->GetGlobalObject() == aGlobalObject
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"mModuleLoader->GetGlobalObject() == aGlobalObject", "./../../../dom/script/ScriptLoader.cpp"
, 340); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mModuleLoader->GetGlobalObject() == aGlobalObject"
")"); do { MOZ_CrashSequence(__null, 340); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
341 MOZ_ASSERT(aGlobalObject->GetModuleLoader(dom::danger::GetJSContext()) ==do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aGlobalObject->GetModuleLoader(dom::danger::GetJSContext
()) == mModuleLoader)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aGlobalObject->GetModuleLoader
(dom::danger::GetJSContext()) == mModuleLoader))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("aGlobalObject->GetModuleLoader(dom::danger::GetJSContext()) == mModuleLoader"
, "./../../../dom/script/ScriptLoader.cpp", 342); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aGlobalObject->GetModuleLoader(dom::danger::GetJSContext()) == mModuleLoader"
")"); do { MOZ_CrashSequence(__null, 342); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
342 mModuleLoader)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aGlobalObject->GetModuleLoader(dom::danger::GetJSContext
()) == mModuleLoader)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aGlobalObject->GetModuleLoader
(dom::danger::GetJSContext()) == mModuleLoader))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("aGlobalObject->GetModuleLoader(dom::danger::GetJSContext()) == mModuleLoader"
, "./../../../dom/script/ScriptLoader.cpp", 342); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aGlobalObject->GetModuleLoader(dom::danger::GetJSContext()) == mModuleLoader"
")"); do { MOZ_CrashSequence(__null, 342); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
343}
344
345void ScriptLoader::DropDocumentReference() {
346 if (mDocument && mCache) {
347 DeregisterFromCache();
348 }
349
350 mDocument = nullptr;
351}
352
353void ScriptLoader::RegisterToCache() {
354 if (mCache) {
355 MOZ_ASSERT(mDocument)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mDocument)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mDocument))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mDocument", "./../../../dom/script/ScriptLoader.cpp"
, 355); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mDocument" ")"
); do { MOZ_CrashSequence(__null, 355); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
356 mCache->RegisterLoader(*this);
357 }
358}
359
360void ScriptLoader::DeregisterFromCache() {
361 if (mCache) {
362 MOZ_ASSERT(mDocument)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mDocument)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mDocument))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mDocument", "./../../../dom/script/ScriptLoader.cpp"
, 362); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mDocument" ")"
); do { MOZ_CrashSequence(__null, 362); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
363 mCache->CancelLoadsForLoader(*this);
364 mCache->UnregisterLoader(*this);
365 }
366}
367
368nsIPrincipal* ScriptLoader::LoaderPrincipal() const {
369 return mDocument->NodePrincipal();
370}
371
372nsIPrincipal* ScriptLoader::PartitionedPrincipal() const {
373 return mDocument->PartitionedPrincipal();
374}
375
376bool ScriptLoader::ShouldBypassCache() const {
377 return mDocument && nsContentUtils::ShouldBypassSubResourceCache(mDocument);
378}
379
380#ifdef NIGHTLY_BUILD1
381bool ScriptLoader::WAICTHandlesScripts() const {
382 if (!mDocument) {
383 return false;
384 }
385 auto* policy =
386 PolicyContainer::GetIntegrityPolicyWAICT(mDocument->GetPolicyContainer());
387 return policy &&
388 policy->ShouldHandle(IntegrityPolicy::DestinationType::Script);
389}
390#endif
391
392void ScriptLoader::RegisterContentScriptModuleLoader(ModuleLoader* aLoader) {
393 MOZ_ASSERT(aLoader)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoader)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLoader))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aLoader", "./../../../dom/script/ScriptLoader.cpp"
, 393); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoader" ")"
); do { MOZ_CrashSequence(__null, 393); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
394 MOZ_ASSERT(aLoader->GetScriptLoader() == this)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoader->GetScriptLoader() == this)>::isValid,
"invalid assertion condition"); if ((__builtin_expect(!!(!(!
!(aLoader->GetScriptLoader() == this))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aLoader->GetScriptLoader() == this"
, "./../../../dom/script/ScriptLoader.cpp", 394); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aLoader->GetScriptLoader() == this" ")"
); do { MOZ_CrashSequence(__null, 394); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
395
396 mWebExtModuleLoaders.AppendElement(aLoader);
397}
398
399// Collect telemtry data about the cache information, and the kind of source
400// which are being loaded, and where it is being loaded from.
401static void CollectScriptTelemetry(ScriptLoadRequest* aRequest) {
402 using namespace mozilla::glean::dom;
403
404 MOZ_ASSERT(aRequest->IsFetching())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aRequest->IsFetching())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aRequest->IsFetching())))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("aRequest->IsFetching()"
, "./../../../dom/script/ScriptLoader.cpp", 404); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aRequest->IsFetching()" ")"); do { MOZ_CrashSequence
(__null, 404); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
405
406 // Skip this function if we are not running telemetry.
407 if (!mozilla::Telemetry::CanRecordExtended()) {
408 return;
409 }
410
411 if (aRequest->IsRetrievedFromMemoryCache()) {
412 // This is revived from the cache.
413 return;
414 }
415
416 // Report the type of source. This is used to monitor the status of the
417 // JavaScript Start-up Bytecode Cache, with the expectation of an almost zero
418 // source-fallback and alternate-data being roughtly equal to source loads.
419 if (aRequest->mFetchSourceOnly) {
420 if (aRequest->GetScriptLoadContext()->mIsInline) {
421 script_loading_source.EnumGet(ScriptLoadingSourceLabel::eInline).Add();
422 } else if (aRequest->IsFetchedAsTextSource()) {
423 script_loading_source.EnumGet(ScriptLoadingSourceLabel::eSourcefallback)
424 .Add();
425 }
426 } else {
427 if (aRequest->IsFetchedAsTextSource()) {
428 script_loading_source.EnumGet(ScriptLoadingSourceLabel::eSource).Add();
429 } else if (aRequest->IsRetrievedAsSerializedStencil()) {
430 script_loading_source.EnumGet(ScriptLoadingSourceLabel::eAltdata).Add();
431 }
432 }
433}
434
435static void AddMemoryCacheRefCountTelemetry(
436 JS::loader::LoadedScript* aLoadedScript) {
437 using namespace mozilla::glean::dom;
438
439 // Skip this function if we are not running telemetry.
440 if (!mozilla::Telemetry::CanRecordExtended()) {
441 return;
442 }
443
444 uint16_t count = aLoadedScript->ClampedRefCountForTelemetry();
445 script_memory_cache_ref_count.AccumulateSingleSample(count);
446}
447
448// Helper method for checking if the script element is an event-handler
449// This means that it has both a for-attribute and a event-attribute.
450// Also, if the for-attribute has a value that matches "\s*window\s*",
451// and the event-attribute matches "\s*onload([ \(].*)?" then it isn't an
452// eventhandler. (both matches are case insensitive).
453// This is how IE seems to filter out a window's onload handler from a
454// <script for=... event=...> element.
455
456static bool IsScriptEventHandler(ScriptKind kind, nsIContent* aScriptElement) {
457 if (kind != ScriptKind::eClassic) {
458 return false;
459 }
460
461 if (!aScriptElement->IsHTMLElement()) {
462 return false;
463 }
464
465 nsAutoString forAttr, eventAttr;
466 if (!aScriptElement->AsElement()->GetAttr(nsGkAtoms::_for, forAttr) ||
467 !aScriptElement->AsElement()->GetAttr(nsGkAtoms::event, eventAttr)) {
468 return false;
469 }
470
471 const nsAString& for_str =
472 nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>(forAttr);
473 if (!for_str.LowerCaseEqualsLiteral("window")) {
474 return true;
475 }
476
477 // We found for="window", now check for event="onload".
478 const nsAString& event_str =
479 nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>(
480 eventAttr);
481 if (!event_str.LowerCaseEqualsLiteral("onload") &&
482 !event_str.LowerCaseEqualsLiteral("onload()")) {
483 return true;
484 }
485
486 // If the `for` attribute has the value "window" and the `event` attribute is
487 // either "onload" or "onload()", then it isn't an event handler.
488 return false;
489}
490
491nsContentPolicyType ScriptLoadRequestToContentPolicyType(
492 ScriptLoadRequest* aRequest) {
493 if (aRequest->GetScriptLoadContext()->IsPreload()) {
494 if (aRequest->IsModuleRequest()) {
495 switch (aRequest->AsModuleRequest()->mModuleType) {
496 case JS::ModuleType::JavaScript:
497 return nsIContentPolicy::TYPE_INTERNAL_MODULE_PRELOAD;
498 case JS::ModuleType::JSON:
499 return nsIContentPolicy::TYPE_INTERNAL_JSON_PRELOAD;
500 case JS::ModuleType::CSS:
501 return nsIContentPolicy::TYPE_INTERNAL_STYLESHEET_PRELOAD;
502 case JS::ModuleType::Text:
503 return nsIContentPolicy::TYPE_INTERNAL_TEXT_PRELOAD;
504 case JS::ModuleType::Bytes:
505 case JS::ModuleType::Unknown:
506 MOZ_ASSERT_UNREACHABLE("Unknown module type")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: "
"Unknown module type" ")", "./../../../dom/script/ScriptLoader.cpp"
, 506); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Unknown module type" ")"); do { MOZ_CrashSequence
(__null, 506); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
507 }
508 }
509
510 return nsIContentPolicy::TYPE_INTERNAL_SCRIPT_PRELOAD;
511 }
512
513 if (aRequest->IsModuleRequest()) {
514 switch (aRequest->AsModuleRequest()->mModuleType) {
515 case JS::ModuleType::Unknown:
516 case JS::ModuleType::Bytes:
517 MOZ_CRASH("Unexpected module type")do { do { } while (false); MOZ_ReportCrash("" "Unexpected module type"
, "./../../../dom/script/ScriptLoader.cpp", 517); AnnotateMozCrashReason
("MOZ_CRASH(" "Unexpected module type" ")"); do { MOZ_CrashSequence
(__null, 517); __attribute__((nomerge)) ::abort(); } while (false
); } while (false)
;
518 case JS::ModuleType::JavaScript:
519 return nsIContentPolicy::TYPE_INTERNAL_MODULE;
520 case JS::ModuleType::JSON:
521 return nsIContentPolicy::TYPE_JSON;
522 case JS::ModuleType::CSS:
523 return nsIContentPolicy::TYPE_STYLESHEET;
524 case JS::ModuleType::Text:
525 return nsIContentPolicy::TYPE_TEXT;
526 }
527 }
528
529 return nsIContentPolicy::TYPE_INTERNAL_SCRIPT;
530}
531
532RequestMode ComputeRequestModeForContentPolicy(
533 const ScriptLoadRequest* aRequest, ScriptFetchOptions* aFetchOptions) {
534 auto corsMapping =
535 aRequest->IsModuleRequest()
536 ? nsContentSecurityManager::REQUIRE_CORS_CHECKS
537 : nsContentSecurityManager::CORS_NONE_MAPS_TO_DISABLED_CORS_CHECKS;
538 return nsContentSecurityManager::SecurityModeToRequestMode(
539 nsContentSecurityManager::ComputeSecurityMode(
540 nsContentSecurityManager::ComputeSecurityFlags(
541 aFetchOptions->mCORSMode, corsMapping)));
542}
543
544nsresult ScriptLoader::CheckContentPolicy(nsIScriptElement* aElement,
545 const nsAString& aNonce,
546 ScriptLoadRequest* aRequest,
547 ScriptFetchOptions* aFetchOptions,
548 nsIURI* aURI) {
549 MOZ_ASSERT(aRequest)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aRequest)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aRequest))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aRequest", "./../../../dom/script/ScriptLoader.cpp"
, 549); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aRequest" ")"
); do { MOZ_CrashSequence(__null, 549); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
550 MOZ_ASSERT(aFetchOptions)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aFetchOptions)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aFetchOptions))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("aFetchOptions",
"./../../../dom/script/ScriptLoader.cpp", 550); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aFetchOptions" ")"); do { MOZ_CrashSequence
(__null, 550); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
551 MOZ_ASSERT(aURI)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aURI)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(aURI))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("aURI", "./../../../dom/script/ScriptLoader.cpp"
, 551); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ")"); do
{ MOZ_CrashSequence(__null, 551); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
552
553 nsContentPolicyType contentPolicyType =
554 ScriptLoadRequestToContentPolicyType(aRequest);
555
556 nsCOMPtr<nsINode> requestingNode;
557 if (aElement) {
558 requestingNode = do_QueryInterface(aElement);
559 }
560 nsCOMPtr<nsILoadInfo> secCheckLoadInfo = MOZ_TRY(net::LoadInfo::Create(__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult
(net::LoadInfo::Create( mDocument->NodePrincipal(), mDocument
->NodePrincipal(), requestingNode, nsILoadInfo::SEC_ONLY_FOR_EXPLICIT_CONTENTSEC_CHECK
, contentPolicyType)); if ((__builtin_expect(!!(mozTryVarTempResult
.isErr()), 0))) { return mozTryVarTempResult.propagateErr(); }
mozTryVarTempResult.unwrap(); })
561 mDocument->NodePrincipal(), // loading principal__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult
(net::LoadInfo::Create( mDocument->NodePrincipal(), mDocument
->NodePrincipal(), requestingNode, nsILoadInfo::SEC_ONLY_FOR_EXPLICIT_CONTENTSEC_CHECK
, contentPolicyType)); if ((__builtin_expect(!!(mozTryVarTempResult
.isErr()), 0))) { return mozTryVarTempResult.propagateErr(); }
mozTryVarTempResult.unwrap(); })
562 mDocument->NodePrincipal(), // triggering principal__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult
(net::LoadInfo::Create( mDocument->NodePrincipal(), mDocument
->NodePrincipal(), requestingNode, nsILoadInfo::SEC_ONLY_FOR_EXPLICIT_CONTENTSEC_CHECK
, contentPolicyType)); if ((__builtin_expect(!!(mozTryVarTempResult
.isErr()), 0))) { return mozTryVarTempResult.propagateErr(); }
mozTryVarTempResult.unwrap(); })
563 requestingNode, nsILoadInfo::SEC_ONLY_FOR_EXPLICIT_CONTENTSEC_CHECK,__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult
(net::LoadInfo::Create( mDocument->NodePrincipal(), mDocument
->NodePrincipal(), requestingNode, nsILoadInfo::SEC_ONLY_FOR_EXPLICIT_CONTENTSEC_CHECK
, contentPolicyType)); if ((__builtin_expect(!!(mozTryVarTempResult
.isErr()), 0))) { return mozTryVarTempResult.propagateErr(); }
mozTryVarTempResult.unwrap(); })
564 contentPolicyType))__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult
(net::LoadInfo::Create( mDocument->NodePrincipal(), mDocument
->NodePrincipal(), requestingNode, nsILoadInfo::SEC_ONLY_FOR_EXPLICIT_CONTENTSEC_CHECK
, contentPolicyType)); if ((__builtin_expect(!!(mozTryVarTempResult
.isErr()), 0))) { return mozTryVarTempResult.propagateErr(); }
mozTryVarTempResult.unwrap(); })
;
565 secCheckLoadInfo->SetParserCreatedScript(aElement &&
566 aElement->GetParserCreated() !=
567 mozilla::dom::NOT_FROM_PARSER);
568 Maybe<RequestMode> requestMode =
569 Some(ComputeRequestModeForContentPolicy(aRequest, aFetchOptions));
570 secCheckLoadInfo->SetRequestMode(requestMode);
571 // Use nonce of the current element, instead of the preload, because those
572 // are allowed to differ.
573 secCheckLoadInfo->SetCspNonce(aNonce);
574 secCheckLoadInfo->SetIntegrityMetadata(
575 aRequest->mIntegrity.GetIntegrityString());
576
577 int16_t shouldLoad = nsIContentPolicy::ACCEPT;
578 nsresult rv = NS_CheckContentLoadPolicy(aURI, secCheckLoadInfo, &shouldLoad,
579 nsContentUtils::GetContentPolicy());
580 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || NS_CP_REJECTED(shouldLoad)((shouldLoad) != nsIContentPolicy::ACCEPT)) {
581 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || shouldLoad != nsIContentPolicy::REJECT_TYPE) {
582 return NS_ERROR_CONTENT_BLOCKED;
583 }
584 return NS_ERROR_CONTENT_BLOCKED_SHOW_ALT;
585 }
586
587 return NS_OK;
588}
589
590/* static */
591bool ScriptLoader::IsAboutPageLoadingChromeURI(ScriptLoadRequest* aRequest,
592 Document* aDocument) {
593 // if the uri to be loaded is not of scheme chrome:, there is nothing to do.
594 if (!aRequest->URI()->SchemeIs("chrome")) {
595 return false;
596 }
597
598 // we can either get here with a regular contentPrincipal or with a
599 // NullPrincipal in case we are showing an error page in a sandboxed iframe.
600 // In either case if the about: page is linkable from content, there is
601 // nothing to do.
602 uint32_t aboutModuleFlags = 0;
603 nsresult rv = NS_OK;
604
605 nsCOMPtr<nsIPrincipal> triggeringPrincipal = aRequest->TriggeringPrincipal();
606 if (triggeringPrincipal->GetIsContentPrincipal()) {
607 if (!triggeringPrincipal->SchemeIs("about")) {
608 return false;
609 }
610 rv = triggeringPrincipal->GetAboutModuleFlags(&aboutModuleFlags);
611 NS_ENSURE_SUCCESS(rv, false)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "false", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../dom/script/ScriptLoader.cpp"
, 611); return false; } } while (false)
;
612 } else if (triggeringPrincipal->GetIsNullPrincipal()) {
613 nsCOMPtr<nsIURI> docURI = aDocument->GetDocumentURI();
614 if (!docURI->SchemeIs("about")) {
615 return false;
616 }
617
618 nsCOMPtr<nsIAboutModule> aboutModule;
619 rv = NS_GetAboutModule(docURI, getter_AddRefs(aboutModule));
620 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || !aboutModule) {
621 return false;
622 }
623 rv = aboutModule->GetURIFlags(docURI, &aboutModuleFlags);
624 NS_ENSURE_SUCCESS(rv, false)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "false", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../dom/script/ScriptLoader.cpp"
, 624); return false; } } while (false)
;
625 } else {
626 return false;
627 }
628
629 if (aboutModuleFlags & nsIAboutModule::MAKE_LINKABLE) {
630 return false;
631 }
632
633 // seems like an about page wants to load a chrome URI.
634 return true;
635}
636
637nsIURI* ScriptLoader::GetBaseURI() const {
638 MOZ_ASSERT(mDocument)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mDocument)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mDocument))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mDocument", "./../../../dom/script/ScriptLoader.cpp"
, 638); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mDocument" ")"
); do { MOZ_CrashSequence(__null, 638); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
639 return mDocument->GetDocBaseURI();
640}
641
642class ScriptRequestProcessor : public Runnable {
643 private:
644 MOZ_KNOWN_LIVE const RefPtr<ScriptLoader> mLoader;
645 MOZ_KNOWN_LIVE const RefPtr<ScriptLoadRequest> mRequest;
646
647 public:
648 ScriptRequestProcessor(ScriptLoader* aLoader, ScriptLoadRequest* aRequest)
649 : Runnable("dom::ScriptRequestProcessor"),
650 mLoader(aLoader),
651 mRequest(aRequest) {}
652 MOZ_CAN_RUN_SCRIPT_BOUNDARY NS_IMETHODvirtual nsresult Run() override {
653 return mLoader->ProcessRequest(mRequest);
654 }
655};
656
657void ScriptLoader::RunScriptWhenSafe(ScriptLoadRequest* aRequest) {
658 auto* runnable = new ScriptRequestProcessor(this, aRequest);
659 nsContentUtils::AddScriptRunner(runnable);
660}
661
662nsresult ScriptLoader::RestartLoad(ScriptLoadRequest* aRequest) {
663 aRequest->getLoadedScript()->DropSRIOrSRIAndSerializedStencil();
664 TRACE_FOR_TEST(aRequest, "load:fallback")do { mozilla::dom::script::TestingNotifyObserver(aRequest, "load:fallback"
); } while (0)
;
665
666 // Notify preload restart so that we can register this preload request again.
667 aRequest->GetScriptLoadContext()->NotifyRestart(mDocument);
668
669 // Start a new channel from which we explicitly request to stream the source
670 // instead of the serialized stencil.
671 aRequest->mFetchSourceOnly = true;
672 nsresult rv;
673 if (aRequest->IsModuleRequest()) {
674 rv = aRequest->AsModuleRequest()->RestartModuleLoad();
675 } else {
676 rv = StartLoad(aRequest, Nothing());
677 }
678 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
679 return rv;
680 }
681
682 // Close the current channel and this ScriptLoadHandler as we created a new
683 // one for the same request.
684 return NS_BINDING_RETARGETED;
685}
686
687nsresult ScriptLoader::StartLoad(
688 ScriptLoadRequest* aRequest,
689 const Maybe<nsAutoString>& aCharsetForPreload) {
690 if (aRequest->IsModuleRequest()) {
691 return aRequest->AsModuleRequest()->StartModuleLoad();
692 }
693
694 return StartClassicLoad(aRequest, aCharsetForPreload);
695}
696
697static nsSecurityFlags CORSModeToSecurityFlags(CORSMode aCORSMode) {
698 nsSecurityFlags securityFlags =
699 nsContentSecurityManager::ComputeSecurityFlags(
700 aCORSMode, nsContentSecurityManager::CORSSecurityMapping::
701 CORS_NONE_MAPS_TO_DISABLED_CORS_CHECKS);
702
703 securityFlags |= nsILoadInfo::SEC_ALLOW_CHROME;
704
705 return securityFlags;
706}
707
708void ScriptLoader::OnDelayedReady(
709 ScriptLoadRequest* aRequest,
710 const Maybe<nsAutoString>& aCharsetForPreload) {
711 if (!mDocument) {
712 return;
713 }
714
715 if (aRequest->IsCanceled()) {
716 return;
717 }
718
719 MOZ_ASSERT(aRequest->IsRetrievedFromMemoryCache())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aRequest->IsRetrievedFromMemoryCache())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(aRequest->IsRetrievedFromMemoryCache()))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("aRequest->IsRetrievedFromMemoryCache()"
, "./../../../dom/script/ScriptLoader.cpp", 719); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aRequest->IsRetrievedFromMemoryCache()"
")"); do { MOZ_CrashSequence(__null, 719); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
720 MOZ_ASSERT(aRequest->IsDelayingReady())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aRequest->IsDelayingReady())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aRequest->IsDelayingReady
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aRequest->IsDelayingReady()", "./../../../dom/script/ScriptLoader.cpp"
, 720); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aRequest->IsDelayingReady()"
")"); do { MOZ_CrashSequence(__null, 720); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
721
722 aRequest->SetReady();
723 MaybeMoveToLoadedList(aRequest);
724 ProcessPendingRequests();
725}
726
727nsresult ScriptLoader::StartClassicLoad(
728 ScriptLoadRequest* aRequest,
729 const Maybe<nsAutoString>& aCharsetForPreload) {
730 if (aRequest->IsRetrievedFromMemoryCache()) {
731 // NOTE: The network event need to be dispatched in the current call stack,
732 // in order to reflect it in the DevTools Network Monitor.
733 EmulateNetworkEvents(aRequest, aCharsetForPreload);
734
735 nsCOMPtr<nsIRunnable> runnable =
736 mozilla::NewRunnableMethod<RefPtr<ScriptLoadRequest>,
737 const Maybe<nsAutoString>>(
738 "ScriptLoader::OnDelayedReady", this, &ScriptLoader::OnDelayedReady,
739 aRequest, aCharsetForPreload);
740 mDocument->Dispatch(runnable.forget());
741 return NS_OK;
742 }
743
744 MOZ_ASSERT(aRequest->IsFetching())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aRequest->IsFetching())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aRequest->IsFetching())))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("aRequest->IsFetching()"
, "./../../../dom/script/ScriptLoader.cpp", 744); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aRequest->IsFetching()" ")"); do { MOZ_CrashSequence
(__null, 744); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
745 NS_ENSURE_TRUE(mDocument, NS_ERROR_NULL_POINTER)do { if ((__builtin_expect(!!(!(mDocument)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mDocument" ") failed", nullptr
, "./../../../dom/script/ScriptLoader.cpp", 745); return NS_ERROR_NULL_POINTER
; } } while (false)
;
746 aRequest->SetUnknownDataType();
747
748 // If this document is sandboxed without 'allow-scripts', abort.
749 if (mDocument->HasScriptsBlockedBySandbox()) {
750 return NS_OK;
751 }
752
753 if (LOG_ENABLED()(__builtin_expect(!!(mozilla::detail::log_test(ScriptLoader::
gScriptLoaderLog, mozilla::LogLevel::Debug)), 0))
) {
754 nsAutoCString url;
755 aRequest->URI()->GetAsciiSpec(url);
756 LOG(("ScriptLoadRequest (%p): Start Classic Load (url = %s)", aRequest,
757 url.get()));
758 }
759
760 nsSecurityFlags securityFlags = CORSModeToSecurityFlags(aRequest->CORSMode());
761
762 nsresult rv = StartLoadInternal(aRequest, securityFlags, aCharsetForPreload);
763
764 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../dom/script/ScriptLoader.cpp"
, 764); return rv; } } while (false)
;
765
766 return NS_OK;
767}
768
769static bool IsWebExtensionRequest(ScriptLoadRequest* aRequest) {
770 if (!aRequest->IsModuleRequest()) {
771 return false;
772 }
773
774 ModuleLoader* loader =
775 ModuleLoader::From(aRequest->AsModuleRequest()->mLoader);
776 return loader->GetKind() == ModuleLoader::WebExtension;
777}
778
779static nsresult CreateChannelForScriptLoading(
780 nsIChannel** aOutChannel, Document* aDocument, nsIURI* aURI,
781 nsINode* aContext, nsIPrincipal* aTriggeringPrincipal,
782 nsSecurityFlags aSecurityFlags, nsContentPolicyType aContentPolicyType) {
783 nsCOMPtr<nsILoadGroup> loadGroup = aDocument->GetDocumentLoadGroup();
784 nsCOMPtr<nsPIDOMWindowOuter> window = aDocument->GetWindow();
785 NS_ENSURE_TRUE(window, NS_ERROR_NULL_POINTER)do { if ((__builtin_expect(!!(!(window)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "window" ") failed", nullptr
, "./../../../dom/script/ScriptLoader.cpp", 785); return NS_ERROR_NULL_POINTER
; } } while (false)
;
786 nsIDocShell* docshell = window->GetDocShell();
787 nsCOMPtr<nsIInterfaceRequestor> prompter(do_QueryInterface(docshell));
788
789 return NS_NewChannelWithTriggeringPrincipal(
790 aOutChannel, aURI, aContext, aTriggeringPrincipal, aSecurityFlags,
791 aContentPolicyType,
792 /* aPerformanceStorage = */ nullptr, loadGroup, prompter);
793}
794
795static nsresult CreateChannelForScriptLoading(nsIChannel** aOutChannel,
796 Document* aDocument,
797 ScriptLoadRequest* aRequest,
798 nsSecurityFlags aSecurityFlags) {
799 nsContentPolicyType contentPolicyType =
800 ScriptLoadRequestToContentPolicyType(aRequest);
801 nsCOMPtr<nsINode> context;
802 if (aRequest->GetScriptLoadContext()->HasScriptElement()) {
803 context = do_QueryInterface(
804 aRequest->GetScriptLoadContext()->GetScriptElementForLoadingNode());
805 } else {
806 context = aDocument;
807 }
808
809 return CreateChannelForScriptLoading(aOutChannel, aDocument, aRequest->URI(),
810 context, aRequest->TriggeringPrincipal(),
811 aSecurityFlags, contentPolicyType);
812}
813
814static void PrepareLoadInfoForScriptLoading(nsIChannel* aChannel,
815 const ScriptLoadRequest* aRequest) {
816 nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
817 loadInfo->SetParserCreatedScript(aRequest->ParserMetadata() ==
818 ParserMetadata::ParserInserted);
819 loadInfo->SetCspNonce(aRequest->Nonce());
820 loadInfo->SetIntegrityMetadata(aRequest->mIntegrity.GetIntegrityString());
821}
822
823// static
824void ScriptLoader::PrepareCacheInfoChannel(nsIChannel* aChannel,
825 ScriptLoadRequest* aRequest) {
826 // To avoid decoding issues, the build-id is part of the disk cache MIME type
827 // constant.
828 aRequest->getLoadedScript()->DropDiskCacheReference();
829 nsCOMPtr<nsICacheInfoChannel> cic(do_QueryInterface(aChannel));
830 if (cic && StaticPrefs::dom_script_loader_bytecode_cache_enabled()) {
831 MOZ_ASSERT(!IsWebExtensionRequest(aRequest),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!IsWebExtensionRequest(aRequest))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!IsWebExtensionRequest(aRequest
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!IsWebExtensionRequest(aRequest)" " (" "Web extension scripts are not compatible with the disk cache"
")", "./../../../dom/script/ScriptLoader.cpp", 832); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!IsWebExtensionRequest(aRequest)" ") (" "Web extension scripts are not compatible with the disk cache"
")"); do { MOZ_CrashSequence(__null, 832); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
832 "Web extension scripts are not compatible with the disk cache")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!IsWebExtensionRequest(aRequest))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!IsWebExtensionRequest(aRequest
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!IsWebExtensionRequest(aRequest)" " (" "Web extension scripts are not compatible with the disk cache"
")", "./../../../dom/script/ScriptLoader.cpp", 832); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!IsWebExtensionRequest(aRequest)" ") (" "Web extension scripts are not compatible with the disk cache"
")"); do { MOZ_CrashSequence(__null, 832); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
833 if (!aRequest->mFetchSourceOnly) {
834 // Inform the HTTP cache that we prefer to have information coming from
835 // the serialized stencil disk cache instead of the sources, if such entry
836 // is already registered.
837 LOG(("ScriptLoadRequest (%p): Maybe request the disk cache", aRequest));
838 cic->PreferAlternativeDataType(
839 ScriptLoader::BytecodeMimeTypeFor(aRequest), ""_ns,
840 nsICacheInfoChannel::PreferredAlternativeDataDeliveryType::ASYNC);
841 } else {
842 // If we are explicitly loading from the sources, such as after a
843 // restarted request, we might still want to save to the disk cache after.
844 //
845 // The following tell the cache to look for an alternative data type which
846 // does not exist, such that we can later save the serialized Stencil
847 // with a different alternative data type.
848 LOG(("ScriptLoadRequest (%p): Request saving to the disk cache later",
849 aRequest));
850 cic->PreferAlternativeDataType(
851 kNullMimeType, ""_ns,
852 nsICacheInfoChannel::PreferredAlternativeDataDeliveryType::ASYNC);
853 }
854 }
855}
856
857static void AdjustPriorityAndClassOfServiceForLinkPreloadScripts(
858 nsIChannel* aChannel, ScriptLoadRequest* aRequest) {
859 MOZ_ASSERT(aRequest->GetScriptLoadContext()->IsLinkPreloadScript())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aRequest->GetScriptLoadContext()->IsLinkPreloadScript
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aRequest->GetScriptLoadContext()->IsLinkPreloadScript
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aRequest->GetScriptLoadContext()->IsLinkPreloadScript()"
, "./../../../dom/script/ScriptLoader.cpp", 859); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aRequest->GetScriptLoadContext()->IsLinkPreloadScript()"
")"); do { MOZ_CrashSequence(__null, 859); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
860
861 // Put it to the group that is not blocked by leaders and doesn't block
862 // follower at the same time.
863 // Giving it a much higher priority will make this request be processed
864 // ahead of other Unblocked requests, but with the same weight as
865 // Leaders. This will make us behave similar way for both http2 and http1.
866 ScriptLoadContext::PrioritizeAsPreload(aChannel);
867
868 if (!StaticPrefs::network_fetchpriority_enabled()) {
869 return;
870 }
871
872 const auto fetchPriority = ToFetchPriority(aRequest->FetchPriority());
873 if (nsCOMPtr<nsISupportsPriority> supportsPriority =
874 do_QueryInterface(aChannel)) {
875 LOG(("Is <link rel=[module]preload"));
876
877 // The spec defines the priority to be set in an implementation defined
878 // manner (<https://fetch.spec.whatwg.org/#concept-fetch>, step 15 and
879 // <https://html.spec.whatwg.org/#concept-script-fetch-options-fetch-priority>).
880 // See corresponding preferences in StaticPrefList.yaml for more context.
881 const int32_t supportsPriorityDelta =
882 FETCH_PRIORITY_ADJUSTMENT_FOR(link_preload_script, fetchPriority)(fetchPriority == FetchPriority::Auto ? StaticPrefs::network_fetchpriority_adjustments_link_preload_script_auto
() : (fetchPriority == FetchPriority::High ? StaticPrefs:: network_fetchpriority_adjustments_link_preload_script_high
() : (fetchPriority == FetchPriority::Low ? StaticPrefs:: network_fetchpriority_adjustments_link_preload_script_low
() : 0)))
;
883 supportsPriority->AdjustPriority(supportsPriorityDelta);
884#ifdef DEBUG1
885 int32_t adjustedPriority;
886 supportsPriority->GetPriority(&adjustedPriority);
887 LogPriorityMapping(ScriptLoader::gScriptLoaderLog, fetchPriority,
888 adjustedPriority);
889#endif
890 }
891
892 if (nsCOMPtr<nsIClassOfService> cos = do_QueryInterface(aChannel)) {
893 cos->SetFetchPriorityDOM(fetchPriority);
894 }
895}
896
897void AdjustPriorityForNonLinkPreloadScripts(nsIChannel* aChannel,
898 ScriptLoadRequest* aRequest) {
899 MOZ_ASSERT(!aRequest->GetScriptLoadContext()->IsLinkPreloadScript())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aRequest->GetScriptLoadContext()->IsLinkPreloadScript
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!aRequest->GetScriptLoadContext()->IsLinkPreloadScript
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!aRequest->GetScriptLoadContext()->IsLinkPreloadScript()"
, "./../../../dom/script/ScriptLoader.cpp", 899); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!aRequest->GetScriptLoadContext()->IsLinkPreloadScript()"
")"); do { MOZ_CrashSequence(__null, 899); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
900
901 if (!StaticPrefs::network_fetchpriority_enabled()) {
902 return;
903 }
904
905 const auto fetchPriority = ToFetchPriority(aRequest->FetchPriority());
906 if (nsCOMPtr<nsISupportsPriority> supportsPriority =
907 do_QueryInterface(aChannel)) {
908 LOG(("Is not <link rel=[module]preload"));
909
910 // The spec defines the priority to be set in an implementation defined
911 // manner (<https://fetch.spec.whatwg.org/#concept-fetch>, step 15 and
912 // <https://html.spec.whatwg.org/#concept-script-fetch-options-fetch-priority>).
913 // See corresponding preferences in StaticPrefList.yaml for more context.
914 const int32_t supportsPriorityDelta = [&]() {
915 const ScriptLoadContext* scriptLoadContext =
916 aRequest->GetScriptLoadContext();
917 if (aRequest->IsModuleRequest()) {
918 return FETCH_PRIORITY_ADJUSTMENT_FOR(module_script, fetchPriority)(fetchPriority == FetchPriority::Auto ? StaticPrefs::network_fetchpriority_adjustments_module_script_auto
() : (fetchPriority == FetchPriority::High ? StaticPrefs:: network_fetchpriority_adjustments_module_script_high
() : (fetchPriority == FetchPriority::Low ? StaticPrefs:: network_fetchpriority_adjustments_module_script_low
() : 0)))
;
919 }
920
921 if (scriptLoadContext->IsAsyncScript() ||
922 scriptLoadContext->IsDeferredScript()) {
923 return FETCH_PRIORITY_ADJUSTMENT_FOR(async_or_defer_script,(fetchPriority == FetchPriority::Auto ? StaticPrefs::network_fetchpriority_adjustments_async_or_defer_script_auto
() : (fetchPriority == FetchPriority::High ? StaticPrefs:: network_fetchpriority_adjustments_async_or_defer_script_high
() : (fetchPriority == FetchPriority::Low ? StaticPrefs:: network_fetchpriority_adjustments_async_or_defer_script_low
() : 0)))
924 fetchPriority)(fetchPriority == FetchPriority::Auto ? StaticPrefs::network_fetchpriority_adjustments_async_or_defer_script_auto
() : (fetchPriority == FetchPriority::High ? StaticPrefs:: network_fetchpriority_adjustments_async_or_defer_script_high
() : (fetchPriority == FetchPriority::Low ? StaticPrefs:: network_fetchpriority_adjustments_async_or_defer_script_low
() : 0)))
;
925 }
926
927 if (scriptLoadContext->mScriptFromHead) {
928 return FETCH_PRIORITY_ADJUSTMENT_FOR(script_in_head, fetchPriority)(fetchPriority == FetchPriority::Auto ? StaticPrefs::network_fetchpriority_adjustments_script_in_head_auto
() : (fetchPriority == FetchPriority::High ? StaticPrefs:: network_fetchpriority_adjustments_script_in_head_high
() : (fetchPriority == FetchPriority::Low ? StaticPrefs:: network_fetchpriority_adjustments_script_in_head_low
() : 0)))
;
929 }
930
931 return FETCH_PRIORITY_ADJUSTMENT_FOR(other_script, fetchPriority)(fetchPriority == FetchPriority::Auto ? StaticPrefs::network_fetchpriority_adjustments_other_script_auto
() : (fetchPriority == FetchPriority::High ? StaticPrefs:: network_fetchpriority_adjustments_other_script_high
() : (fetchPriority == FetchPriority::Low ? StaticPrefs:: network_fetchpriority_adjustments_other_script_low
() : 0)))
;
932 }();
933
934 if (supportsPriorityDelta) {
935 supportsPriority->AdjustPriority(supportsPriorityDelta);
936#ifdef DEBUG1
937 int32_t adjustedPriority;
938 supportsPriority->GetPriority(&adjustedPriority);
939 LogPriorityMapping(ScriptLoader::gScriptLoaderLog, fetchPriority,
940 adjustedPriority);
941#endif
942 }
943 }
944 if (nsCOMPtr<nsIClassOfService> cos = do_QueryInterface(aChannel)) {
945 cos->SetFetchPriorityDOM(fetchPriority);
946 }
947}
948
949// static
950void ScriptLoader::PrepareRequestPriorityAndRequestDependencies(
951 nsIChannel* aChannel, ScriptLoadRequest* aRequest) {
952 if (aRequest->GetScriptLoadContext()->IsLinkPreloadScript()) {
953 // This is <link rel="preload" as="script"> or <link rel="modulepreload">
954 // initiated speculative load
955 // (https://developer.mozilla.org/en-US/docs/Web/Performance/Speculative_loading).
956 AdjustPriorityAndClassOfServiceForLinkPreloadScripts(aChannel, aRequest);
957 ScriptLoadContext::AddLoadBackgroundFlag(aChannel);
958 } else if (nsCOMPtr<nsIClassOfService> cos = do_QueryInterface(aChannel)) {
959 AdjustPriorityForNonLinkPreloadScripts(aChannel, aRequest);
960
961 if (aRequest->GetScriptLoadContext()->mScriptFromHead &&
962 aRequest->GetScriptLoadContext()->IsBlockingScript()) {
963 // synchronous head scripts block loading of most other non js/css
964 // content such as images, Leader implicitely disallows tailing
965 cos->AddClassFlags(nsIClassOfService::Leader);
966 } else if (aRequest->GetScriptLoadContext()->IsDeferredScript() &&
967 !StaticPrefs::network_http_tailing_enabled()) {
968 // Bug 1395525 and the !StaticPrefs::network_http_tailing_enabled() bit:
969 // We want to make sure that turing tailing off by the pref makes the
970 // browser behave exactly the same way as before landing the tailing
971 // patch.
972
973 // head/body deferred scripts are blocked by leaders but are not
974 // allowed tailing because they block DOMContentLoaded
975 cos->AddClassFlags(nsIClassOfService::TailForbidden);
976 } else {
977 // other scripts (=body sync or head/body async) are neither blocked
978 // nor prioritized
979 cos->AddClassFlags(nsIClassOfService::Unblocked);
980
981 if (aRequest->GetScriptLoadContext()->IsAsyncScript()) {
982 // async scripts are allowed tailing, since those and only those
983 // don't block DOMContentLoaded; this flag doesn't enforce tailing,
984 // just overweights the Unblocked flag when the channel is found
985 // to be a thrird-party tracker and thus set the Tail flag to engage
986 // tailing.
987 cos->AddClassFlags(nsIClassOfService::TailAllowed);
988 }
989 }
990 }
991}
992
993inline nsLiteralString GetInitiatorType(ScriptLoadRequest* aRequest) {
994 if (aRequest->mEarlyHintPreloaderId) {
995 return u"early-hints"_ns;
996 }
997
998 if (aRequest->GetScriptLoadContext()->IsLinkPreloadScript()) {
999 return u"link"_ns;
1000 }
1001
1002 return u"script"_ns;
1003}
1004
1005// static
1006nsresult ScriptLoader::PrepareHttpRequestAndInitiatorType(
1007 nsIChannel* aChannel, ScriptLoadRequest* aRequest,
1008 const Maybe<nsAutoString>& aCharsetForPreload) {
1009 nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aChannel));
1010 nsresult rv = NS_OK;
1011
1012 if (httpChannel) {
1013 // The 'Accept' HTTP header should be set in
1014 // nsHttpHandler::AddStandardRequestHeaders.
1015
1016 nsCOMPtr<nsIReferrerInfo> referrerInfo =
1017 new ReferrerInfo(aRequest->mReferrer, aRequest->ReferrerPolicy());
1018 rv = httpChannel->SetReferrerInfoWithoutClone(referrerInfo);
1019 MOZ_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "./../../../dom/script/ScriptLoader.cpp"
, 1019); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 1019); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1020
1021 nsAutoString hintCharset;
1022 if (!aRequest->GetScriptLoadContext()->IsPreload() &&
1023 aRequest->GetScriptLoadContext()->HasScriptElement()) {
1024 aRequest->GetScriptLoadContext()->GetHintCharset(hintCharset);
1025 } else if (aCharsetForPreload.isSome()) {
1026 hintCharset = aCharsetForPreload.ref();
1027 }
1028
1029 rv = httpChannel->SetClassicScriptHintCharset(hintCharset);
1030 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../dom/script/ScriptLoader.cpp"
, 1030); return rv; } } while (false)
;
1031 }
1032
1033 // Set the initiator type
1034 nsCOMPtr<nsITimedChannel> timedChannel(do_QueryInterface(httpChannel));
1035 if (timedChannel) {
1036 timedChannel->SetInitiatorType(GetInitiatorType(aRequest));
1037 }
1038
1039 return rv;
1040}
1041
1042nsresult ScriptLoader::PrepareIncrementalStreamLoader(
1043 nsIIncrementalStreamLoader** aOutLoader, nsIChannel* aChannel,
1044 ScriptLoadRequest* aRequest) {
1045 UniquePtr<mozilla::dom::SRICheckDataVerifier> sriDataVerifier;
1046 if (!aRequest->mIntegrity.IsEmpty()) {
1047 sriDataVerifier = MakeUnique<SRICheckDataVerifier>(aRequest->mIntegrity,
1048 aChannel, mReporter);
1049 }
1050
1051 RefPtr<ScriptLoadHandler> handler =
1052 new ScriptLoadHandler(this, aRequest, std::move(sriDataVerifier));
1053
1054 aChannel->SetNotificationCallbacks(handler);
1055
1056 nsresult rv = NS_NewIncrementalStreamLoader(aOutLoader, handler);
1057 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../dom/script/ScriptLoader.cpp"
, 1057); return rv; } } while (false)
;
1058 return rv;
1059}
1060
1061void ScriptLoader::NotifyPreloadCoalescing(ModuleLoadRequest* aRequest) {
1062 ScriptLoadContext* context = aRequest->GetScriptLoadContext();
1063 MOZ_ASSERT(aRequest->IsTopLevel())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aRequest->IsTopLevel())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aRequest->IsTopLevel())))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("aRequest->IsTopLevel()"
, "./../../../dom/script/ScriptLoader.cpp", 1063); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aRequest->IsTopLevel()" ")"); do { MOZ_CrashSequence
(__null, 1063); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1064 MOZ_ASSERT(context->IsLinkPreloadScript())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(context->IsLinkPreloadScript())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(context->IsLinkPreloadScript
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("context->IsLinkPreloadScript()", "./../../../dom/script/ScriptLoader.cpp"
, 1064); AnnotateMozCrashReason("MOZ_ASSERT" "(" "context->IsLinkPreloadScript()"
")"); do { MOZ_CrashSequence(__null, 1064); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1065 MOZ_ASSERT(!context->Channel())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!context->Channel())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!context->Channel()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("!context->Channel()"
, "./../../../dom/script/ScriptLoader.cpp", 1065); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!context->Channel()" ")"); do { MOZ_CrashSequence
(__null, 1065); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1066
1067 auto key = PreloadHashKey::CreateAsScript(
1068 aRequest->URI(), aRequest->CORSMode(), JS::loader::ScriptKind::eModule);
1069 context->SetIsCoalescedModulePreload();
1070 context->NotifyOpen(key, mDocument, /* aIsPreload = */ true,
1071 /* aIsModule = */ true);
1072 context->NotifyPreloadCoalescingResult();
1073}
1074
1075nsresult ScriptLoader::StartLoadInternal(
1076 ScriptLoadRequest* aRequest, nsSecurityFlags securityFlags,
1077 const Maybe<nsAutoString>& aCharsetForPreload) {
1078 nsCOMPtr<nsIChannel> channel;
1079 nsresult rv = CreateChannelForScriptLoading(
1080 getter_AddRefs(channel), mDocument, aRequest, securityFlags);
1081
1082 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../dom/script/ScriptLoader.cpp"
, 1082); return rv; } } while (false)
;
1083
1084 if (aRequest->mEarlyHintPreloaderId) {
1085 nsCOMPtr<nsIHttpChannelInternal> channelInternal =
1086 do_QueryInterface(channel);
1087 NS_ENSURE_TRUE(channelInternal != nullptr, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(channelInternal != nullptr)),
0))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "channelInternal != nullptr"
") failed", nullptr, "./../../../dom/script/ScriptLoader.cpp"
, 1087); return NS_ERROR_FAILURE; } } while (false)
;
1088
1089 rv = channelInternal->SetEarlyHintPreloaderId(
1090 aRequest->mEarlyHintPreloaderId);
1091 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../dom/script/ScriptLoader.cpp"
, 1091); return rv; } } while (false)
;
1092 }
1093
1094 PrepareLoadInfoForScriptLoading(channel, aRequest);
1095
1096 nsCOMPtr<nsIScriptGlobalObject> scriptGlobal = GetScriptGlobalObject();
1097 if (!scriptGlobal) {
1098 return NS_ERROR_FAILURE;
1099 }
1100
1101#ifdef NIGHTLY_BUILD1
1102 if (WAICTHandlesScripts()) {
1103 aRequest->mFetchSourceOnly = true;
1104 }
1105#endif
1106
1107 ScriptLoader::PrepareCacheInfoChannel(channel, aRequest);
1108
1109 LOG(("ScriptLoadRequest (%p): mode=%u tracking=%d", aRequest,
1110 unsigned(aRequest->GetScriptLoadContext()->mScriptMode),
1111 net::ChannelClassifierUtils::IsTrackingClassificationFlag(
1112 aRequest->GetScriptLoadContext()
1113 ->GetClassificationFlags()
1114 .thirdPartyFlags,
1115 NS_UsePrivateBrowsing(channel))));
1116
1117 PrepareRequestPriorityAndRequestDependencies(channel, aRequest);
1118
1119 rv =
1120 PrepareHttpRequestAndInitiatorType(channel, aRequest, aCharsetForPreload);
1121 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../dom/script/ScriptLoader.cpp"
, 1121); return rv; } } while (false)
;
1122
1123 nsCOMPtr<nsIIncrementalStreamLoader> loader;
1124 rv =
1125 PrepareIncrementalStreamLoader(getter_AddRefs(loader), channel, aRequest);
1126 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../dom/script/ScriptLoader.cpp"
, 1126); return rv; } } while (false)
;
1127
1128 auto key = PreloadHashKey::CreateAsScript(
1129 aRequest->URI(), aRequest->CORSMode(), aRequest->mKind);
1130 aRequest->GetScriptLoadContext()->NotifyOpen(
1131 key, channel, mDocument,
1132 aRequest->GetScriptLoadContext()->IsLinkPreloadScript(),
1133 aRequest->IsModuleRequest());
1134
1135 rv = channel->AsyncOpen(loader);
1136
1137 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1138 // Make sure to inform any <link preload> tags about failure to load the
1139 // resource.
1140 aRequest->GetScriptLoadContext()->NotifyStart(channel);
1141 aRequest->GetScriptLoadContext()->NotifyStop(rv);
1142 // If this was a preload that failed to start, deregister it so a
1143 // subsequent attempt to load the same URL can succeed.
1144 if (aRequest->GetScriptLoadContext()->IsPreload()) {
1145 mDocument->Preloads().DeregisterPreload(key);
1146 }
1147 }
1148
1149 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../dom/script/ScriptLoader.cpp"
, 1149); return rv; } } while (false)
;
1150
1151 return NS_OK;
1152}
1153
1154bool ScriptLoader::PreloadURIComparator::Equals(const PreloadInfo& aPi,
1155 nsIURI* const& aURI) const {
1156 bool same;
1157 return NS_SUCCEEDED(aPi.mRequest->URI()->Equals(aURI, &same))((bool)(__builtin_expect(!!(!NS_FAILED_impl(aPi.mRequest->
URI()->Equals(aURI, &same))), 1)))
&& same;
1158}
1159
1160static bool CSPAllowsInlineScript(nsIScriptElement* aElement,
1161 const nsAString& aSourceText,
1162 const nsAString& aNonce,
1163 Document* aDocument) {
1164 nsCOMPtr<nsIContentSecurityPolicy> csp =
1165 PolicyContainer::GetCSP(aDocument->GetPolicyContainer());
1166 if (!csp) {
1167 // no CSP --> allow
1168 return true;
1169 }
1170
1171 bool parserCreated =
1172 aElement->GetParserCreated() != mozilla::dom::NOT_FROM_PARSER;
1173 nsCOMPtr<Element> element = do_QueryInterface(aElement);
1174
1175 bool allowInlineScript = false;
1176 nsresult rv = csp->GetAllowsInline(
1177 nsIContentSecurityPolicy::SCRIPT_SRC_ELEM_DIRECTIVE,
1178 false /* aHasUnsafeHash */, aNonce, parserCreated, element,
1179 nullptr /* nsICSPEventListener */, aSourceText,
1180 aElement->GetScriptLineNumber(),
1181 aElement->GetScriptColumnNumber().oneOriginValue(), &allowInlineScript);
1182 return NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && allowInlineScript;
1183}
1184
1185namespace {
1186RequestPriority FetchPriorityToRequestPriority(
1187 const FetchPriority aFetchPriority) {
1188 switch (aFetchPriority) {
1189 case FetchPriority::High:
1190 return RequestPriority::High;
1191 case FetchPriority::Low:
1192 return RequestPriority::Low;
1193 case FetchPriority::Auto:
1194 return RequestPriority::Auto;
1195 }
1196
1197 MOZ_ASSERT_UNREACHABLE()do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: "
")", "./../../../dom/script/ScriptLoader.cpp", 1197); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " ")"
); do { MOZ_CrashSequence(__null, 1197); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1198 return RequestPriority::Auto;
1199}
1200} // namespace
1201
1202void ScriptLoader::NotifyObserversForCachedScript(
1203 ScriptLoadRequest* aRequest,
1204 const Maybe<nsAutoString>& aCharsetForPreload) {
1205 nsCOMPtr<nsIObserverService> obsService = services::GetObserverService();
1206
1207 if (!obsService->HasObservers("http-on-resource-cache-response")) {
1208 return;
1209 }
1210
1211 nsIScriptElement* element = aRequest->GetScriptLoadContext()->mScriptElement;
1212
1213 nsCOMPtr<nsINode> context;
1214 if (element) {
1215 context = do_QueryInterface(element);
1216 } else {
1217 context = mDocument;
1218 }
1219
1220 nsCOMPtr<nsIChannel> channel;
1221 nsresult rv = CreateChannelForScriptLoading(
1222 getter_AddRefs(channel), mDocument, aRequest->URI(), context,
1223 aRequest->FetchOptions()->mTriggeringPrincipal,
1224 CORSModeToSecurityFlags(aRequest->FetchOptions()->mCORSMode),
1225 nsIContentPolicy::TYPE_INTERNAL_SCRIPT);
1226 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1227 return;
1228 }
1229
1230 RefPtr<net::HttpBaseChannel> httpBaseChannel = do_QueryObject(channel);
1231 if (httpBaseChannel) {
1232 const net::nsHttpResponseHead* responseHead = nullptr;
1233 if (aRequest->mNetworkMetadata) {
1234 responseHead = aRequest->mNetworkMetadata->GetResponseHead();
1235 }
1236 httpBaseChannel->SetDummyChannelForCachedResource(responseHead);
1237 }
1238
1239 // Populate channel and loadInfo fields, in the same way as
1240 // StartLoadInternal, but skip unnecessary things.
1241
1242 PrepareLoadInfoForScriptLoading(channel, aRequest);
1243
1244 rv =
1245 PrepareHttpRequestAndInitiatorType(channel, aRequest, aCharsetForPreload);
1246 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1247 return;
1248 }
1249
1250 ScriptHashKey key(this, aRequest, aRequest->ReferrerPolicy(),
1251 aRequest->FetchOptions(),
1252 aRequest->getLoadedScript()->GetURI());
1253 nsAutoCString keyStr;
1254 key.ToStringForLookup(keyStr);
1255
1256 obsService->NotifyObservers(channel, "http-on-resource-cache-response",
1257 NS_ConvertUTF8toUTF16(keyStr).get());
1258}
1259
1260already_AddRefed<ScriptLoadRequest> ScriptLoader::CreateLoadRequest(
1261 ScriptKind aKind, nsIURI* aURI, nsIScriptElement* aElement,
1262 const nsAString& aScriptContent, nsIPrincipal* aTriggeringPrincipal,
1263 CORSMode aCORSMode, const nsAString& aNonce,
1264 RequestPriority aRequestPriority, const SRIMetadata& aIntegrity,
1265 ReferrerPolicy aReferrerPolicy, ParserMetadata aParserMetadata,
1266 ScriptLoadRequestType aRequestType) {
1267 nsIURI* referrer = mDocument->GetDocumentURIAsReferrer();
1268 RefPtr<ScriptFetchOptions> fetchOptions =
1269 new ScriptFetchOptions(aCORSMode, aNonce, aRequestPriority,
1270 aParserMetadata, aTriggeringPrincipal);
1271 RefPtr<ScriptLoadContext> context =
1272 new ScriptLoadContext(aElement, aScriptContent);
1273
1274 if (aKind == ScriptKind::eModule) {
1275 RefPtr<ModuleLoadRequest> request = mModuleLoader->CreateTopLevel(
1276 aURI, aElement, aReferrerPolicy, fetchOptions, aIntegrity, referrer,
1277 context, aRequestType);
1278
1279 return request.forget();
1280 }
1281
1282 MOZ_ASSERT(aKind == ScriptKind::eClassic || aKind == ScriptKind::eImportMap ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aKind == ScriptKind::eClassic || aKind == ScriptKind
::eImportMap || (StaticPrefs::dom_speculation_rules_enabled()
&& aKind == ScriptKind::eSpeculationRules))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(aKind == ScriptKind::eClassic || aKind == ScriptKind::eImportMap
|| (StaticPrefs::dom_speculation_rules_enabled() && aKind
== ScriptKind::eSpeculationRules)))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("aKind == ScriptKind::eClassic || aKind == ScriptKind::eImportMap || (StaticPrefs::dom_speculation_rules_enabled() && aKind == ScriptKind::eSpeculationRules)"
, "./../../../dom/script/ScriptLoader.cpp", 1284); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aKind == ScriptKind::eClassic || aKind == ScriptKind::eImportMap || (StaticPrefs::dom_speculation_rules_enabled() && aKind == ScriptKind::eSpeculationRules)"
")"); do { MOZ_CrashSequence(__null, 1284); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1283 (StaticPrefs::dom_speculation_rules_enabled() &&do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aKind == ScriptKind::eClassic || aKind == ScriptKind
::eImportMap || (StaticPrefs::dom_speculation_rules_enabled()
&& aKind == ScriptKind::eSpeculationRules))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(aKind == ScriptKind::eClassic || aKind == ScriptKind::eImportMap
|| (StaticPrefs::dom_speculation_rules_enabled() && aKind
== ScriptKind::eSpeculationRules)))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("aKind == ScriptKind::eClassic || aKind == ScriptKind::eImportMap || (StaticPrefs::dom_speculation_rules_enabled() && aKind == ScriptKind::eSpeculationRules)"
, "./../../../dom/script/ScriptLoader.cpp", 1284); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aKind == ScriptKind::eClassic || aKind == ScriptKind::eImportMap || (StaticPrefs::dom_speculation_rules_enabled() && aKind == ScriptKind::eSpeculationRules)"
")"); do { MOZ_CrashSequence(__null, 1284); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1284 aKind == ScriptKind::eSpeculationRules))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aKind == ScriptKind::eClassic || aKind == ScriptKind
::eImportMap || (StaticPrefs::dom_speculation_rules_enabled()
&& aKind == ScriptKind::eSpeculationRules))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(aKind == ScriptKind::eClassic || aKind == ScriptKind::eImportMap
|| (StaticPrefs::dom_speculation_rules_enabled() && aKind
== ScriptKind::eSpeculationRules)))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("aKind == ScriptKind::eClassic || aKind == ScriptKind::eImportMap || (StaticPrefs::dom_speculation_rules_enabled() && aKind == ScriptKind::eSpeculationRules)"
, "./../../../dom/script/ScriptLoader.cpp", 1284); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aKind == ScriptKind::eClassic || aKind == ScriptKind::eImportMap || (StaticPrefs::dom_speculation_rules_enabled() && aKind == ScriptKind::eSpeculationRules)"
")"); do { MOZ_CrashSequence(__null, 1284); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1285
1286 RefPtr<ScriptLoadRequest> request =
1287 new ScriptLoadRequest(aKind, aIntegrity, referrer, context);
1288
1289 TryUseCache(aReferrerPolicy, fetchOptions, aURI, request, aElement, aNonce,
1290 aRequestType);
1291
1292 return request.forget();
1293}
1294
1295void ScriptLoader::TryUseCache(ReferrerPolicy aReferrerPolicy,
1296 ScriptFetchOptions* aFetchOptions, nsIURI* aURI,
1297 ScriptLoadRequest* aRequest,
1298 nsIScriptElement* aElement,
1299 const nsAString& aNonce,
1300 ScriptLoadRequestType aRequestType) {
1301 if (aRequestType == ScriptLoadRequestType::Inline) {
1302 aRequest->NoCacheEntryFound(aReferrerPolicy, aFetchOptions, aURI);
1303 LOG(
1304 ("ScriptLoader (%p): Created LoadedScript (%p) for "
1305 "ScriptLoadRequest(%p) because inline %s.",
1306 this, aRequest->getLoadedScript(), aRequest,
1307 aRequest->URI()->GetSpecOrDefault().get()));
1308 return;
1309 }
1310
1311 if (!mCache) {
1312 aRequest->NoCacheEntryFound(aReferrerPolicy, aFetchOptions, aURI);
1313 LOG(
1314 ("ScriptLoader (%p): Created LoadedScript (%p) for "
1315 "ScriptLoadRequest(%p) %s.",
1316 this, aRequest->getLoadedScript(), aRequest,
1317 aRequest->URI()->GetSpecOrDefault().get()));
1318 return;
1319 }
1320
1321 // NOTE: Some ScriptLoadRequest fields aren't yet accessible until
1322 // either NoCacheEntryFound or CacheEntryFound is called,
1323 // which constructs ScriptFetchInfo and LoadedScript.
1324 // aRequest->FetchOptions() and aRequest->ReferrerPolicy() are
1325 // backed by ScriptFetchInfo, and aRequest->URI() is backed by
1326 // LoadedScript, and we cannot use them here.
1327 ScriptHashKey key(this, aRequest, aReferrerPolicy, aFetchOptions, aURI);
1328 auto cacheResult = mCache->Lookup(*this, key, /* aSyncLoad = */ true);
1329 MOZ_ASSERT_IF(cacheResult.mState == CachedSubResourceState::Complete,do { if (cacheResult.mState == CachedSubResourceState::Complete
) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(cacheResult.mCompleteValue->IsCachedStencil()
|| cacheResult.mCompleteValue->IsInvalidatedCachedStencil
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(cacheResult.mCompleteValue->IsCachedStencil() || cacheResult
.mCompleteValue->IsInvalidatedCachedStencil()))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("cacheResult.mCompleteValue->IsCachedStencil() || cacheResult.mCompleteValue->IsInvalidatedCachedStencil()"
, "./../../../dom/script/ScriptLoader.cpp", 1331); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "cacheResult.mCompleteValue->IsCachedStencil() || cacheResult.mCompleteValue->IsInvalidatedCachedStencil()"
")"); do { MOZ_CrashSequence(__null, 1331); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
1330 cacheResult.mCompleteValue->IsCachedStencil() ||do { if (cacheResult.mState == CachedSubResourceState::Complete
) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(cacheResult.mCompleteValue->IsCachedStencil()
|| cacheResult.mCompleteValue->IsInvalidatedCachedStencil
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(cacheResult.mCompleteValue->IsCachedStencil() || cacheResult
.mCompleteValue->IsInvalidatedCachedStencil()))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("cacheResult.mCompleteValue->IsCachedStencil() || cacheResult.mCompleteValue->IsInvalidatedCachedStencil()"
, "./../../../dom/script/ScriptLoader.cpp", 1331); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "cacheResult.mCompleteValue->IsCachedStencil() || cacheResult.mCompleteValue->IsInvalidatedCachedStencil()"
")"); do { MOZ_CrashSequence(__null, 1331); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
1331 cacheResult.mCompleteValue->IsInvalidatedCachedStencil())do { if (cacheResult.mState == CachedSubResourceState::Complete
) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(cacheResult.mCompleteValue->IsCachedStencil()
|| cacheResult.mCompleteValue->IsInvalidatedCachedStencil
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(cacheResult.mCompleteValue->IsCachedStencil() || cacheResult
.mCompleteValue->IsInvalidatedCachedStencil()))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("cacheResult.mCompleteValue->IsCachedStencil() || cacheResult.mCompleteValue->IsInvalidatedCachedStencil()"
, "./../../../dom/script/ScriptLoader.cpp", 1331); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "cacheResult.mCompleteValue->IsCachedStencil() || cacheResult.mCompleteValue->IsInvalidatedCachedStencil()"
")"); do { MOZ_CrashSequence(__null, 1331); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
1332 if (cacheResult.mState != CachedSubResourceState::Complete ||
1333 !cacheResult.mCompleteValue->IsCachedStencil()) {
1334 aRequest->NoCacheEntryFound(aReferrerPolicy, aFetchOptions, aURI);
1335 LOG(
1336 ("ScriptLoader (%p): Created LoadedScript (%p) for "
1337 "ScriptLoadRequest(%p) because cache is not found %s.",
1338 this, aRequest->getLoadedScript(), aRequest,
1339 aRequest->URI()->GetSpecOrDefault().get()));
1340 return;
1341 }
1342
1343 if (!cacheResult.mCompleteValue->IsSRIMetadataReusableBy(
1344 aRequest->mIntegrity)) {
1345 mCache->Evict(key);
1346 aRequest->NoCacheEntryFound(aReferrerPolicy, aFetchOptions, aURI);
1347 LOG(
1348 ("ScriptLoader (%p): Created LoadedScript (%p) for "
1349 "ScriptLoadRequest(%p) because of SRI metadata mismatch %s",
1350 this, aRequest->getLoadedScript(), aRequest,
1351 aRequest->URI()->GetSpecOrDefault().get()));
1352 return;
1353 }
1354
1355 if (cacheResult.mCompleteValue->IsDirty()) {
1356 // The cache entry needs revalidation.
1357 // Fetch from necko and validate in ScriptLoader::OnStreamComplete.
1358 TRACE_FOR_TEST(aRequest, "memorycache:dirty:hit")do { mozilla::dom::script::TestingNotifyObserver(aRequest, "memorycache:dirty:hit"
); } while (0)
;
1359 aRequest->SetHasDirtyCache();
1360 aRequest->NoCacheEntryFound(aReferrerPolicy, aFetchOptions, aURI);
1361 LOG(
1362 ("ScriptLoader (%p): Created LoadedScript (%p) for "
1363 "ScriptLoadRequest(%p) because of dirty flag %s.",
1364 this, aRequest->getLoadedScript(), aRequest,
1365 aRequest->URI()->GetSpecOrDefault().get()));
1366 return;
1367 }
1368
1369 if (aRequestType == ScriptLoadRequestType::External) {
1370 // NOTE: The preload case checks the same after the
1371 // LookupPreloadRequest call.
1372 if (NS_FAILED(CheckContentPolicy(aElement, aNonce, aRequest, aFetchOptions,((bool)(__builtin_expect(!!(NS_FAILED_impl(CheckContentPolicy
(aElement, aNonce, aRequest, aFetchOptions, aURI))), 0)))
1373 aURI))((bool)(__builtin_expect(!!(NS_FAILED_impl(CheckContentPolicy
(aElement, aNonce, aRequest, aFetchOptions, aURI))), 0)))
) {
1374 aRequest->NoCacheEntryFound(aReferrerPolicy, aFetchOptions, aURI);
1375 LOG(
1376 ("ScriptLoader (%p): Created LoadedScript (%p) for "
1377 "ScriptLoadRequest(%p) because content policy violation %s.",
1378 this, aRequest->getLoadedScript(), aRequest,
1379 aRequest->URI()->GetSpecOrDefault().get()));
1380 return;
1381 }
1382 }
1383
1384 aRequest->mNetworkMetadata = cacheResult.mNetworkMetadata;
1385
1386 MOZ_ASSERT(cacheResult.mCompleteValue->CachedReferrerPolicy() ==do { static_assert( mozilla::detail::AssertionConditionType<
decltype(cacheResult.mCompleteValue->CachedReferrerPolicy(
) == aReferrerPolicy)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(cacheResult.mCompleteValue->
CachedReferrerPolicy() == aReferrerPolicy))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("cacheResult.mCompleteValue->CachedReferrerPolicy() == aReferrerPolicy"
, "./../../../dom/script/ScriptLoader.cpp", 1387); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "cacheResult.mCompleteValue->CachedReferrerPolicy() == aReferrerPolicy"
")"); do { MOZ_CrashSequence(__null, 1387); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1387 aReferrerPolicy)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(cacheResult.mCompleteValue->CachedReferrerPolicy(
) == aReferrerPolicy)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(cacheResult.mCompleteValue->
CachedReferrerPolicy() == aReferrerPolicy))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("cacheResult.mCompleteValue->CachedReferrerPolicy() == aReferrerPolicy"
, "./../../../dom/script/ScriptLoader.cpp", 1387); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "cacheResult.mCompleteValue->CachedReferrerPolicy() == aReferrerPolicy"
")"); do { MOZ_CrashSequence(__null, 1387); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1388
1389 mMemoryCacheUsed++;
1390 if (!cacheResult.mCompleteValue->IsEverHitFromMemoryCache()) {
1391 cacheResult.mCompleteValue->SetIsEverHitFromMemoryCache();
1392 mCache->OnEntryEverHit();
1393 }
1394 AddMemoryCacheRefCountTelemetry(cacheResult.mCompleteValue);
1395
1396 aRequest->CacheEntryFound(cacheResult.mCompleteValue, aFetchOptions);
1397 MOZ_ASSERT_IF(!aRequest->IsModuleRequest(), aRequest->IsDelayingReady())do { if (!aRequest->IsModuleRequest()) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(aRequest
->IsDelayingReady())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aRequest->IsDelayingReady
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aRequest->IsDelayingReady()", "./../../../dom/script/ScriptLoader.cpp"
, 1397); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aRequest->IsDelayingReady()"
")"); do { MOZ_CrashSequence(__null, 1397); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
1398 MOZ_ASSERT_IF(aRequest->IsModuleRequest(), aRequest->IsFetching())do { if (aRequest->IsModuleRequest()) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(aRequest
->IsFetching())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aRequest->IsFetching())))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("aRequest->IsFetching()"
, "./../../../dom/script/ScriptLoader.cpp", 1398); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aRequest->IsFetching()" ")"); do { MOZ_CrashSequence
(__null, 1398); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false); } } while (false)
;
1399 LOG(
1400 ("ScriptLoader (%p): Found in-memory cache LoadedScript (%p) for "
1401 "ScriptLoadRequest(%p) %s.",
1402 this, aRequest->getLoadedScript(), aRequest,
1403 aRequest->URI()->GetSpecOrDefault().get()));
1404 TRACE_FOR_TEST(aRequest, "load:memorycache")do { mozilla::dom::script::TestingNotifyObserver(aRequest, "load:memorycache"
); } while (0)
;
1405
1406 cacheResult.mCompleteValue->AddFetchCount();
1407 return;
1408}
1409
1410void ScriptLoader::EmulateNetworkEvents(
1411 ScriptLoadRequest* aRequest,
1412 const Maybe<nsAutoString>& aCharsetForPreload) {
1413 MOZ_ASSERT(aRequest->IsRetrievedFromMemoryCache())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aRequest->IsRetrievedFromMemoryCache())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(aRequest->IsRetrievedFromMemoryCache()))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("aRequest->IsRetrievedFromMemoryCache()"
, "./../../../dom/script/ScriptLoader.cpp", 1413); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aRequest->IsRetrievedFromMemoryCache()"
")"); do { MOZ_CrashSequence(__null, 1413); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1414 MOZ_ASSERT(aRequest->mNetworkMetadata)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aRequest->mNetworkMetadata)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aRequest->mNetworkMetadata
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"aRequest->mNetworkMetadata", "./../../../dom/script/ScriptLoader.cpp"
, 1414); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aRequest->mNetworkMetadata"
")"); do { MOZ_CrashSequence(__null, 1414); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1415 MOZ_ASSERT(!aRequest->IsWasmBytes())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aRequest->IsWasmBytes())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aRequest->IsWasmBytes())
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!aRequest->IsWasmBytes()"
, "./../../../dom/script/ScriptLoader.cpp", 1415); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!aRequest->IsWasmBytes()" ")"); do { MOZ_CrashSequence
(__null, 1415); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1416
1417 NotifyObserversForCachedScript(aRequest, aCharsetForPreload);
1418
1419 {
1420 nsAutoCString name;
1421 nsString entryName;
1422 aRequest->URI()->GetSpec(name);
1423 CopyUTF8toUTF16(name, entryName);
1424
1425 auto now = TimeStamp::Now();
1426
1427 SharedSubResourceCacheUtils::AddPerformanceEntryForCache(
1428 entryName, GetInitiatorType(aRequest), aRequest->mNetworkMetadata, now,
1429 now, mDocument);
1430 }
1431}
1432
1433bool ScriptLoader::ProcessScriptElement(nsIScriptElement* aElement,
1434 const nsAString& aSourceText) {
1435 // We need a document to evaluate scripts.
1436 NS_ENSURE_TRUE(mDocument, false)do { if ((__builtin_expect(!!(!(mDocument)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mDocument" ") failed", nullptr
, "./../../../dom/script/ScriptLoader.cpp", 1436); return false
; } } while (false)
;
1437
1438 // Check to see if scripts has been turned off.
1439 if (!mEnabled || !mDocument->IsScriptEnabled()) {
1440 return false;
1441 }
1442
1443 NS_ASSERTION(!aElement->IsMalformed(), "Executing malformed script")do { if (!(!aElement->IsMalformed())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Executing malformed script", "!aElement->IsMalformed()"
, "./../../../dom/script/ScriptLoader.cpp", 1443); MOZ_PretendNoReturn
(); } } while (0)
;
1444
1445 nsCOMPtr<nsIContent> scriptContent = do_QueryInterface(aElement);
1446
1447 ScriptKind scriptKind;
1448 if (aElement->GetScriptIsModule()) {
1449 scriptKind = ScriptKind::eModule;
1450 } else if (aElement->GetScriptIsImportMap()) {
1451 scriptKind = ScriptKind::eImportMap;
1452 } else if (aElement->GetScriptIsSpeculationRules()) {
1453 scriptKind = ScriptKind::eSpeculationRules;
1454 } else {
1455 scriptKind = ScriptKind::eClassic;
1456 }
1457
1458 // Step 13. Check that the script is not an eventhandler
1459 if (IsScriptEventHandler(scriptKind, scriptContent)) {
1460 return false;
1461 }
1462
1463 // "In modern user agents that support module scripts, the script element with
1464 // the nomodule attribute will be ignored".
1465 // "The nomodule attribute must not be specified on module scripts (and will
1466 // be ignored if it is)."
1467 if (scriptKind == ScriptKind::eClassic && scriptContent->IsHTMLElement() &&
1468 scriptContent->AsElement()->HasAttr(nsGkAtoms::nomodule)) {
1469 return false;
1470 }
1471
1472 // Step 15. and later in the HTML5 spec
1473 if (aElement->GetScriptExternal()) {
1474 return ProcessExternalScript(aElement, scriptKind, scriptContent);
1475 }
1476
1477 return ProcessInlineScript(aElement, scriptKind, aSourceText);
1478}
1479
1480static ParserMetadata GetParserMetadata(nsIScriptElement* aElement) {
1481 return aElement->GetParserCreated() == mozilla::dom::NOT_FROM_PARSER
1482 ? ParserMetadata::NotParserInserted
1483 : ParserMetadata::ParserInserted;
1484}
1485
1486bool ScriptLoader::ProcessExternalScript(nsIScriptElement* aElement,
1487 ScriptKind aScriptKind,
1488 nsIContent* aScriptContent) {
1489 LOG(("ScriptLoader (%p): Process external script for element %p", this,
1490 aElement));
1491
1492 // https://html.spec.whatwg.org/multipage/scripting.html#prepare-the-script-element
1493 // Step 33.1. If el's type is "importmap" or "speculationrules", then queue an
1494 // element task on the DOM manipulation task source given el to fire an event
1495 // named error at el, and return.
1496 if (aScriptKind == ScriptKind::eImportMap ||
1497 aScriptKind == ScriptKind::eSpeculationRules) {
1498 NS_DispatchToCurrentThread(
1499 NewRunnableMethod("nsIScriptElement::FireErrorEvent", aElement,
1500 &nsIScriptElement::FireErrorEvent));
1501 nsContentUtils::ReportToConsole(
1502 nsIScriptError::warningFlag, "Script Loader"_ns, mDocument,
1503 PropertiesFile::DOM_PROPERTIES,
1504 aScriptKind == ScriptKind::eImportMap
1505 ? "ImportMapExternalNotSupported"
1506 : "SpeculationRulesExternalNotSupported");
1507 return false;
1508 }
1509
1510 nsCOMPtr<nsIURI> scriptURI = aElement->GetScriptURI();
1511 if (!scriptURI) {
1512 // Asynchronously report the failure to create a URI object
1513 NS_DispatchToCurrentThread(
1514 NewRunnableMethod("nsIScriptElement::FireErrorEvent", aElement,
1515 &nsIScriptElement::FireErrorEvent));
1516 return false;
1517 }
1518
1519 nsString nonce = nsContentSecurityUtils::GetIsElementNonceableNonce(
1520 *aScriptContent->AsElement());
1521 SRIMetadata sriMetadata;
1522 {
1523 // https://html.spec.whatwg.org/multipage/scripting.html#prepare-the-script-element
1524 // Step 31.11.
1525 // - module: If el does not have an integrity attribute, then set options's
1526 // integrity metadata to the result of resolving a module integrity metadata
1527 // with url and settings object.
1528 nsAutoString integrity;
1529 if (aScriptContent->AsElement()->GetAttr(nsGkAtoms::integrity, integrity)) {
1530 GetSRIMetadata(integrity, &sriMetadata);
1531 } else if (aScriptKind == ScriptKind::eModule) {
1532 mModuleLoader->GetImportMapSRI(scriptURI,
1533 mDocument->GetDocumentURIAsReferrer(),
1534 mReporter, &sriMetadata);
1535 }
1536 }
1537
1538 RefPtr<ScriptLoadRequest> request =
1539 LookupPreloadRequest(aElement, aScriptKind, sriMetadata);
1540 if (request) {
1541 PROFILER_MARKER("ScriptLoader::ProcessExternalScript PreloadRequest", JS,do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("ScriptLoader::ProcessExternalScript PreloadRequest", ::geckoprofiler
::category::JS, {mozilla::MarkerStack::Capture()}, ::geckoprofiler
::markers::FlowMarker{}, Flow::FromPointer(request.get())); }
} while (false); } while (false)
1542 {mozilla::MarkerStack::Capture()}, FlowMarker,do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("ScriptLoader::ProcessExternalScript PreloadRequest", ::geckoprofiler
::category::JS, {mozilla::MarkerStack::Capture()}, ::geckoprofiler
::markers::FlowMarker{}, Flow::FromPointer(request.get())); }
} while (false); } while (false)
1543 Flow::FromPointer(request.get()))do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("ScriptLoader::ProcessExternalScript PreloadRequest", ::geckoprofiler
::category::JS, {mozilla::MarkerStack::Capture()}, ::geckoprofiler
::markers::FlowMarker{}, Flow::FromPointer(request.get())); }
} while (false); } while (false)
;
1544
1545 if (NS_FAILED(CheckContentPolicy(aElement, nonce, request,((bool)(__builtin_expect(!!(NS_FAILED_impl(CheckContentPolicy
(aElement, nonce, request, request->FetchOptions(), request
->URI()))), 0)))
1546 request->FetchOptions(),((bool)(__builtin_expect(!!(NS_FAILED_impl(CheckContentPolicy
(aElement, nonce, request, request->FetchOptions(), request
->URI()))), 0)))
1547 request->URI()))((bool)(__builtin_expect(!!(NS_FAILED_impl(CheckContentPolicy
(aElement, nonce, request, request->FetchOptions(), request
->URI()))), 0)))
) {
1548 LOG(("ScriptLoader (%p): content policy check failed for preload", this));
1549
1550 // Probably plans have changed; even though the preload was allowed seems
1551 // like the actual load is not; let's cancel the preload request.
1552 request->Cancel();
1553 return false;
1554 }
1555
1556 // Use the preload request.
1557
1558 LOG(("ScriptLoadRequest (%p): Using preload request", request.get()));
1559
1560 // https://html.spec.whatwg.org/multipage/webappapis.html#fetch-a-module-script-tree
1561 // Step 1. Disallow further import maps given settings object.
1562 if (request->IsModuleRequest() &&
1563 !StaticPrefs::dom_multiple_import_maps_enabled()) {
1564 LOG(("ScriptLoadRequest (%p): Disallow further import maps.",
1565 request.get()));
1566 mModuleLoader->DisallowImportMaps();
1567 }
1568
1569 // It's possible these attributes changed since we started the preload so
1570 // update them here.
1571 request->GetScriptLoadContext()->SetScriptMode(
1572 aElement->GetScriptDeferred(), aElement->GetScriptAsync(), false);
1573
1574 // The request will be added to another list or set as
1575 // mParserBlockingRequest below.
1576 if (request->GetScriptLoadContext()->mInCompilingList) {
1577 mOffThreadCompilingRequests.Remove(request);
1578 request->GetScriptLoadContext()->mInCompilingList = false;
1579 }
1580 } else {
1581 // No usable preload found.
1582
1583 nsCOMPtr<nsIPrincipal> principal =
1584 aElement->GetScriptURITriggeringPrincipal();
1585 if (!principal) {
1586 principal = aScriptContent->NodePrincipal();
1587 }
1588
1589 CORSMode ourCORSMode = aElement->GetCORSMode();
1590 const FetchPriority fetchPriority = aElement->GetFetchPriority();
1591 ReferrerPolicy referrerPolicy = GetReferrerPolicy(aElement);
1592 ParserMetadata parserMetadata = GetParserMetadata(aElement);
1593
1594 request = CreateLoadRequest(
1595 aScriptKind, scriptURI, aElement, VoidString(), principal, ourCORSMode,
1596 nonce, FetchPriorityToRequestPriority(fetchPriority), sriMetadata,
1597 referrerPolicy, parserMetadata, ScriptLoadRequestType::External);
1598
1599 PROFILER_MARKER("ScriptLoader::ProcessExternalScript CreateLoadRequest", JS,do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("ScriptLoader::ProcessExternalScript CreateLoadRequest", ::geckoprofiler
::category::JS, {mozilla::MarkerStack::Capture()}, ::geckoprofiler
::markers::FlowMarker{}, Flow::FromPointer(request.get())); }
} while (false); } while (false)
1600 {mozilla::MarkerStack::Capture()}, FlowMarker,do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("ScriptLoader::ProcessExternalScript CreateLoadRequest", ::geckoprofiler
::category::JS, {mozilla::MarkerStack::Capture()}, ::geckoprofiler
::markers::FlowMarker{}, Flow::FromPointer(request.get())); }
} while (false); } while (false)
1601 Flow::FromPointer(request.get()))do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("ScriptLoader::ProcessExternalScript CreateLoadRequest", ::geckoprofiler
::category::JS, {mozilla::MarkerStack::Capture()}, ::geckoprofiler
::markers::FlowMarker{}, Flow::FromPointer(request.get())); }
} while (false); } while (false)
;
1602
1603 request->GetScriptLoadContext()->mIsInline = false;
1604 request->GetScriptLoadContext()->SetScriptMode(
1605 aElement->GetScriptDeferred(), aElement->GetScriptAsync(), false);
1606 // keep request->GetScriptLoadContext()->mScriptFromHead to false so we
1607 // don't treat non preloaded scripts as blockers for full page load. See bug
1608 // 792438.
1609
1610 LOG(("ScriptLoadRequest (%p): Created request for external script",
1611 request.get()));
1612
1613 nsresult rv = StartLoad(request, Nothing());
1614 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1615 ReportErrorToConsole(request, rv);
1616
1617 // If this is a script element that with an https URL scheme would block
1618 // the parser, we need to block the parser.
1619 bool block = !(request->GetScriptLoadContext()->IsAsyncScript() ||
1620 !aElement->GetParserCreated() ||
1621 request->GetScriptLoadContext()->IsDeferredScript());
1622
1623 // Asynchronously report the load failure
1624 nsCOMPtr<nsIRunnable> runnable;
1625 if (block) {
1626 mParserBlockingRequest = request;
1627 runnable = NewRunnableMethod<RefPtr<ScriptLoadRequest>, nsresult>(
1628 "ScriptLoader::HandleLoadErrorAndProcessPendingRequests", this,
1629 &ScriptLoader::HandleLoadErrorAndProcessPendingRequests, request,
1630 rv);
1631 } else {
1632 runnable =
1633 NewRunnableMethod("nsIScriptElement::FireErrorEvent", aElement,
1634 &nsIScriptElement::FireErrorEvent);
1635 }
1636
1637 if (mDocument) {
1638 mDocument->Dispatch(runnable.forget());
1639 } else {
1640 NS_DispatchToCurrentThread(runnable.forget());
1641 }
1642 return block;
1643 }
1644
1645 if (request->IsRetrievedFromMemoryCache()) {
1646 // https://html.spec.whatwg.org/#prepare-the-script-element
1647 //
1648 // Step 33. If el's type is "classic" and el has a src attribute, or el's
1649 // type is "module":
1650 // ...
1651 // Step 33.2. If el has an async attribute or el's force async is true:
1652 // Step 33.2.1. Let scripts be el's preparation-time document's set of
1653 // scripts that will execute as soon as possible.
1654 // Step 33.2.2. Append el to scripts.
1655 // ...
1656 // Step 33.3. Otherwise, if el is not parser-inserted:
1657 // Step 33.3.1. Let scripts be el's preparation-time document's list of
1658 // scripts that will execute in order as soon as possible.
1659 // Step 33.3.2. Append el to scripts.
1660 // ...
1661 //
1662 // https://html.spec.whatwg.org/#the-end
1663 //
1664 // Step 7. Spin the event loop until the set of scripts that will execute
1665 // as soon as possible and the list of scripts that will execute
1666 // in order as soon as possible are empty.
1667 //
1668 // For scripts that creates the actual necko channel, the request is
1669 // associated with the document's load group, and the load group manages
1670 // the script set and the script list above implicitly, and the above
1671 // "spin the event loop" is handled by IsBusy() check inside
1672 // nsDocLoader::DocLoaderIsEmpty.
1673 //
1674 // https://searchfox.org/mozilla-central/rev/e85232b4b28ecc970240d39203e417d1c320623c/uriloader/base/nsDocLoader.cpp#704
1675 //
1676 // For in-memory-cached scripts, no channel is created, and those scripts
1677 // should explicitly block the step 7 above.
1678 //
1679 // NOTE: IsAsyncScript represents both "async" and "force async".
1680 if (request->GetScriptLoadContext()->IsAsyncScript() ||
1681 parserMetadata == ParserMetadata::NotParserInserted) {
1682 request->GetScriptLoadContext()->BlockOnload(mDocument);
1683 }
1684 }
1685 }
1686
1687 // We should still be in loading stage of script unless we're loading a
1688 // module or speculatively off-main-thread parsing a script.
1689 NS_ASSERTION(SpeculativeOMTParsingEnabled() ||do { if (!(SpeculativeOMTParsingEnabled() || !request->GetScriptLoadContext
()->CompileStarted() || request->IsModuleRequest())) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "Request should not yet be in compiling stage."
, "SpeculativeOMTParsingEnabled() || !request->GetScriptLoadContext()->CompileStarted() || request->IsModuleRequest()"
, "./../../../dom/script/ScriptLoader.cpp", 1692); MOZ_PretendNoReturn
(); } } while (0)
1690 !request->GetScriptLoadContext()->CompileStarted() ||do { if (!(SpeculativeOMTParsingEnabled() || !request->GetScriptLoadContext
()->CompileStarted() || request->IsModuleRequest())) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "Request should not yet be in compiling stage."
, "SpeculativeOMTParsingEnabled() || !request->GetScriptLoadContext()->CompileStarted() || request->IsModuleRequest()"
, "./../../../dom/script/ScriptLoader.cpp", 1692); MOZ_PretendNoReturn
(); } } while (0)
1691 request->IsModuleRequest(),do { if (!(SpeculativeOMTParsingEnabled() || !request->GetScriptLoadContext
()->CompileStarted() || request->IsModuleRequest())) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "Request should not yet be in compiling stage."
, "SpeculativeOMTParsingEnabled() || !request->GetScriptLoadContext()->CompileStarted() || request->IsModuleRequest()"
, "./../../../dom/script/ScriptLoader.cpp", 1692); MOZ_PretendNoReturn
(); } } while (0)
1692 "Request should not yet be in compiling stage.")do { if (!(SpeculativeOMTParsingEnabled() || !request->GetScriptLoadContext
()->CompileStarted() || request->IsModuleRequest())) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "Request should not yet be in compiling stage."
, "SpeculativeOMTParsingEnabled() || !request->GetScriptLoadContext()->CompileStarted() || request->IsModuleRequest()"
, "./../../../dom/script/ScriptLoader.cpp", 1692); MOZ_PretendNoReturn
(); } } while (0)
;
1693
1694 if (request->GetScriptLoadContext()->IsAsyncScript()) {
1695 AddAsyncRequest(request);
1696 if (request->IsFinished()) {
1697 // The script is available already. Run it ASAP when the event
1698 // loop gets a chance to spin.
1699
1700 // KVKV TODO: Instead of processing immediately, try off-thread-parsing
1701 // it and only schedule a pending ProcessRequest if that fails.
1702 ProcessPendingRequestsAsync();
1703 }
1704 return false;
1705 }
1706 if (!aElement->GetParserCreated()) {
1707 // Violate the HTML5 spec in order to make LABjs and the "order" plug-in
1708 // for RequireJS work with their Gecko-sniffed code path. See
1709 // http://lists.w3.org/Archives/Public/public-html/2010Oct/0088.html
1710 request->GetScriptLoadContext()->mIsNonAsyncScriptInserted = true;
1711 mNonAsyncExternalScriptInsertedRequests.AppendElement(request);
1712 if (request->IsFinished()) {
1713 // The script is available already. Run it ASAP when the event
1714 // loop gets a chance to spin.
1715 ProcessPendingRequestsAsync();
1716 }
1717 return false;
1718 }
1719 // we now have a parser-inserted request that may or may not be still
1720 // loading
1721 if (request->GetScriptLoadContext()->IsDeferredScript()) {
1722 // We don't want to run this yet.
1723 // If we come here, the script is a parser-created script and it has
1724 // the defer attribute but not the async attribute OR it is a module
1725 // script without the async attribute. Since a
1726 // a parser-inserted script is being run, we came here by the parser
1727 // running the script, which means the parser is still alive and the
1728 // parse is ongoing.
1729 NS_ASSERTION(mDocument->GetCurrentContentSink() ||do { if (!(mDocument->GetCurrentContentSink() || aElement->
GetParserCreated() == FROM_PARSER_XSLT)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Non-XSLT Defer script on a document without an active " "parser; bug 592366."
, "mDocument->GetCurrentContentSink() || aElement->GetParserCreated() == FROM_PARSER_XSLT"
, "./../../../dom/script/ScriptLoader.cpp", 1732); MOZ_PretendNoReturn
(); } } while (0)
1730 aElement->GetParserCreated() == FROM_PARSER_XSLT,do { if (!(mDocument->GetCurrentContentSink() || aElement->
GetParserCreated() == FROM_PARSER_XSLT)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Non-XSLT Defer script on a document without an active " "parser; bug 592366."
, "mDocument->GetCurrentContentSink() || aElement->GetParserCreated() == FROM_PARSER_XSLT"
, "./../../../dom/script/ScriptLoader.cpp", 1732); MOZ_PretendNoReturn
(); } } while (0)
1731 "Non-XSLT Defer script on a document without an active "do { if (!(mDocument->GetCurrentContentSink() || aElement->
GetParserCreated() == FROM_PARSER_XSLT)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Non-XSLT Defer script on a document without an active " "parser; bug 592366."
, "mDocument->GetCurrentContentSink() || aElement->GetParserCreated() == FROM_PARSER_XSLT"
, "./../../../dom/script/ScriptLoader.cpp", 1732); MOZ_PretendNoReturn
(); } } while (0)
1732 "parser; bug 592366.")do { if (!(mDocument->GetCurrentContentSink() || aElement->
GetParserCreated() == FROM_PARSER_XSLT)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Non-XSLT Defer script on a document without an active " "parser; bug 592366."
, "mDocument->GetCurrentContentSink() || aElement->GetParserCreated() == FROM_PARSER_XSLT"
, "./../../../dom/script/ScriptLoader.cpp", 1732); MOZ_PretendNoReturn
(); } } while (0)
;
1733 AddDeferRequest(request);
1734 return false;
1735 }
1736
1737 if (aElement->GetParserCreated() == FROM_PARSER_XSLT) {
1738 // Need to maintain order for XSLT-inserted scripts
1739 NS_ASSERTION(!mParserBlockingRequest,do { if (!(!mParserBlockingRequest)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Parser-blocking scripts and XSLT scripts in the same doc!"
, "!mParserBlockingRequest", "./../../../dom/script/ScriptLoader.cpp"
, 1740); MOZ_PretendNoReturn(); } } while (0)
1740 "Parser-blocking scripts and XSLT scripts in the same doc!")do { if (!(!mParserBlockingRequest)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Parser-blocking scripts and XSLT scripts in the same doc!"
, "!mParserBlockingRequest", "./../../../dom/script/ScriptLoader.cpp"
, 1740); MOZ_PretendNoReturn(); } } while (0)
;
1741 request->GetScriptLoadContext()->mIsXSLT = true;
1742 mXSLTRequests.AppendElement(request);
1743 if (request->IsFinished()) {
1744 // The script is available already. Run it ASAP when the event
1745 // loop gets a chance to spin.
1746 ProcessPendingRequestsAsync();
1747 }
1748 return true;
1749 }
1750
1751 if (request->IsFinished() && ReadyToExecuteParserBlockingScripts()) {
1752 // The request has already been loaded and there are no pending style
1753 // sheets. If the script comes from the network stream, cheat for
1754 // performance reasons and avoid a trip through the event loop.
1755 if (aElement->GetParserCreated() == FROM_PARSER_NETWORK) {
1756 return ProcessRequest(request) == NS_ERROR_HTMLPARSER_BLOCK;
1757 }
1758 // Otherwise, we've got a document.written script, make a trip through
1759 // the event loop to hide the preload effects from the scripts on the
1760 // Web page.
1761 NS_ASSERTION(!mParserBlockingRequest,do { if (!(!mParserBlockingRequest)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "There can be only one parser-blocking script at a time", "!mParserBlockingRequest"
, "./../../../dom/script/ScriptLoader.cpp", 1762); MOZ_PretendNoReturn
(); } } while (0)
1762 "There can be only one parser-blocking script at a time")do { if (!(!mParserBlockingRequest)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "There can be only one parser-blocking script at a time", "!mParserBlockingRequest"
, "./../../../dom/script/ScriptLoader.cpp", 1762); MOZ_PretendNoReturn
(); } } while (0)
;
1763 NS_ASSERTION(mXSLTRequests.isEmpty(),do { if (!(mXSLTRequests.isEmpty())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Parser-blocking scripts and XSLT scripts in the same doc!"
, "mXSLTRequests.isEmpty()", "./../../../dom/script/ScriptLoader.cpp"
, 1764); MOZ_PretendNoReturn(); } } while (0)
1764 "Parser-blocking scripts and XSLT scripts in the same doc!")do { if (!(mXSLTRequests.isEmpty())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Parser-blocking scripts and XSLT scripts in the same doc!"
, "mXSLTRequests.isEmpty()", "./../../../dom/script/ScriptLoader.cpp"
, 1764); MOZ_PretendNoReturn(); } } while (0)
;
1765 mParserBlockingRequest = request;
1766 ProcessPendingRequestsAsync();
1767 return true;
1768 }
1769
1770 // The script hasn't loaded yet or there's a style sheet blocking it.
1771 // The script will be run when it loads or the style sheet loads.
1772 NS_ASSERTION(!mParserBlockingRequest,do { if (!(!mParserBlockingRequest)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "There can be only one parser-blocking script at a time", "!mParserBlockingRequest"
, "./../../../dom/script/ScriptLoader.cpp", 1773); MOZ_PretendNoReturn
(); } } while (0)
1773 "There can be only one parser-blocking script at a time")do { if (!(!mParserBlockingRequest)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "There can be only one parser-blocking script at a time", "!mParserBlockingRequest"
, "./../../../dom/script/ScriptLoader.cpp", 1773); MOZ_PretendNoReturn
(); } } while (0)
;
1774 NS_ASSERTION(mXSLTRequests.isEmpty(),do { if (!(mXSLTRequests.isEmpty())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Parser-blocking scripts and XSLT scripts in the same doc!"
, "mXSLTRequests.isEmpty()", "./../../../dom/script/ScriptLoader.cpp"
, 1775); MOZ_PretendNoReturn(); } } while (0)
1775 "Parser-blocking scripts and XSLT scripts in the same doc!")do { if (!(mXSLTRequests.isEmpty())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Parser-blocking scripts and XSLT scripts in the same doc!"
, "mXSLTRequests.isEmpty()", "./../../../dom/script/ScriptLoader.cpp"
, 1775); MOZ_PretendNoReturn(); } } while (0)
;
1776 mParserBlockingRequest = request;
1777 return true;
1778}
1779
1780bool ScriptLoader::ProcessInlineScript(nsIScriptElement* aElement,
1781 ScriptKind aScriptKind,
1782 const nsAString& aSourceText) {
1783 // Is this document sandboxed without 'allow-scripts'?
1784 if (mDocument->HasScriptsBlockedBySandbox()) {
1785 return false;
1786 }
1787
1788 nsCOMPtr<Element> element = do_QueryInterface(aElement);
1789 nsString nonce = nsContentSecurityUtils::GetIsElementNonceableNonce(*element);
1790
1791 // Does CSP allow this inline script to run?
1792 if (!CSPAllowsInlineScript(aElement, aSourceText, nonce, mDocument)) {
1793 return false;
1794 }
1795
1796 // Check if adding an import map script is allowed. If not, we bail out
1797 // early to prevent creating a load request.
1798 if (aScriptKind == ScriptKind::eImportMap) {
1799 // https://html.spec.whatwg.org/multipage/scripting.html#prepare-the-script-element
1800 // Step 31.2 type is "importmap":
1801 // Step 1. If el's relevant global object's import maps allowed is false,
1802 // then queue an element task on the DOM manipulation task source given el
1803 // to fire an event named error at el, and return.
1804 if (!mModuleLoader->IsImportMapAllowed()) {
1805 NS_WARNING("ScriptLoader: import maps allowed is false.")NS_DebugBreak(NS_DEBUG_WARNING, "ScriptLoader: import maps allowed is false."
, nullptr, "./../../../dom/script/ScriptLoader.cpp", 1805)
;
1806 const char* msg = mModuleLoader->HasImportMapRegistered()
1807 ? "ImportMapNotAllowedMultiple"
1808 : "ImportMapNotAllowedAfterModuleLoad";
1809 nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
1810 "Script Loader"_ns, mDocument,
1811 PropertiesFile::DOM_PROPERTIES, msg);
1812 NS_DispatchToCurrentThread(
1813 NewRunnableMethod("nsIScriptElement::FireErrorEvent", aElement,
1814 &nsIScriptElement::FireErrorEvent));
1815 return false;
1816 }
1817 }
1818
1819 // Inline classic scripts ignore their CORS mode and are always CORS_NONE.
1820 CORSMode corsMode = CORS_NONE;
1821 if (aScriptKind == ScriptKind::eModule) {
1822 corsMode = aElement->GetCORSMode();
1823 }
1824 // <https://html.spec.whatwg.org/multipage/scripting.html#prepare-the-script-element>
1825 // step 29 specifies to use the fetch priority. Presumably it has no effect
1826 // for inline scripts.
1827 const auto fetchPriority = aElement->GetFetchPriority();
1828
1829 ReferrerPolicy referrerPolicy = GetReferrerPolicy(aElement);
1830 ParserMetadata parserMetadata = GetParserMetadata(aElement);
1831
1832 // NOTE: The `nonce` as specified here is significant, because it's inherited
1833 // by other scripts (e.g. modules created via dynamic imports).
1834 RefPtr<ScriptLoadRequest> request = CreateLoadRequest(
1835 aScriptKind, mDocument->GetDocumentURI(), aElement, aSourceText,
1836 mDocument->NodePrincipal(), corsMode, nonce,
1837 FetchPriorityToRequestPriority(fetchPriority),
1838 SRIMetadata(), // SRI doesn't apply
1839 referrerPolicy, parserMetadata, ScriptLoadRequestType::Inline);
1840 request->GetScriptLoadContext()->mIsInline = true;
1841 request->GetScriptLoadContext()->mLineNo = aElement->GetScriptLineNumber();
1842 request->GetScriptLoadContext()->mColumnNo =
1843 aElement->GetScriptColumnNumber();
1844 request->mFetchSourceOnly = true;
1845 request->SetTextSource(request->mLoadContext.get());
1846 TRACE_FOR_TEST(request, "load:source")do { mozilla::dom::script::TestingNotifyObserver(request, "load:source"
); } while (0)
;
1847 CollectScriptTelemetry(request);
1848
1849 // Only the 'async' attribute is heeded on an inline module script and
1850 // inline classic scripts ignore both these attributes.
1851 MOZ_ASSERT(!aElement->GetScriptDeferred())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aElement->GetScriptDeferred())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aElement->GetScriptDeferred
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!aElement->GetScriptDeferred()", "./../../../dom/script/ScriptLoader.cpp"
, 1851); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aElement->GetScriptDeferred()"
")"); do { MOZ_CrashSequence(__null, 1851); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1852 MOZ_ASSERT_IF(!request->IsModuleRequest(), !aElement->GetScriptAsync())do { if (!request->IsModuleRequest()) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(!aElement
->GetScriptAsync())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aElement->GetScriptAsync
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!aElement->GetScriptAsync()", "./../../../dom/script/ScriptLoader.cpp"
, 1852); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aElement->GetScriptAsync()"
")"); do { MOZ_CrashSequence(__null, 1852); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
1853 request->GetScriptLoadContext()->SetScriptMode(
1854 false, aElement->GetScriptAsync(), false);
1855
1856 LOG(("ScriptLoadRequest (%p): Created request for inline script",
1857 request.get()));
1858
1859 request->SetBaseURL(mDocument->GetDocBaseURI());
1860
1861 const bool multiImportMapsEnabled =
1862 StaticPrefs::dom_multiple_import_maps_enabled();
1863 if (request->IsModuleRequest()) {
1864 if (!multiImportMapsEnabled) {
1865 // https://html.spec.whatwg.org/multipage/webappapis.html#fetch-an-inline-module-script-graph
1866 // Step 1. Disallow further import maps given settings object.
1867 mModuleLoader->DisallowImportMaps();
1868 }
1869
1870 ModuleLoadRequest* const modReq = request->AsModuleRequest();
1871 if (aElement->GetParserCreated() != NOT_FROM_PARSER) {
1872 if (aElement->GetScriptAsync()) {
1873 AddAsyncRequest(modReq);
1874 } else {
1875 AddDeferRequest(modReq);
1876 }
1877 }
1878
1879 // This calls OnFetchComplete directly since there's no need to start
1880 // fetching an inline script.
1881 nsresult rv = modReq->OnFetchComplete(NS_OK);
1882 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1883 ReportErrorToConsole(modReq, rv);
1884 HandleLoadError(MOZ_KnownLive(modReq)(modReq), rv);
1885 }
1886
1887 return false;
1888 }
1889
1890 if (request->IsImportMapRequest()) {
1891 if (!multiImportMapsEnabled) {
1892 // https://html.spec.whatwg.org/multipage/scripting.html#prepare-the-script-element
1893 // Step 31.2 type is "importmap":
1894 // Impl note: Step 1 is done above before creating a ScriptLoadRequest.
1895 MOZ_ASSERT(mModuleLoader->IsImportMapAllowed())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mModuleLoader->IsImportMapAllowed())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(mModuleLoader->IsImportMapAllowed()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mModuleLoader->IsImportMapAllowed()"
, "./../../../dom/script/ScriptLoader.cpp", 1895); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "mModuleLoader->IsImportMapAllowed()" ")"
); do { MOZ_CrashSequence(__null, 1895); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1896
1897 // Step 2. Set el's relevant global object's import maps allowed to
1898 // false.
1899 mModuleLoader->DisallowImportMaps();
1900 }
1901
1902 // Step 3. Let result be the result of creating an import map parse result
1903 // given source text and base URL.
1904 UniquePtr<ImportMap> importMap = mModuleLoader->ParseImportMap(request);
1905 if (!importMap) {
1906 // If parsing import maps fails, the exception will be reported in
1907 // ModuleLoaderBase::ParseImportMap, and the registration of the import
1908 // map will bail out early.
1909 return false;
1910 }
1911
1912 // Remove any module preloads. Module specifier resolution is invalidated by
1913 // adding an import map, and incorrect dependencies may have been loaded.
1914 mPreloads.RemoveElementsBy(
1915 [this, multiImportMapsEnabled](const PreloadInfo& info) {
1916 if (!info.mRequest->IsModuleRequest()) {
1917 return false;
1918 }
1919
1920 info.mRequest->Cancel();
1921 if (multiImportMapsEnabled) {
1922 mModuleLoader->ClearPreloadedModuleGraph(
1923 info.mRequest->AsModuleRequest());
1924 }
1925
1926 return true;
1927 });
1928
1929 // TODO: Bug 1781758: Move RegisterImportMap into EvaluateScriptElement.
1930 //
1931 // https://html.spec.whatwg.org/multipage/scripting.html#execute-the-script-element
1932 // The spec defines 'register an import map' should be done in
1933 // 'execute the script element', because inside 'execute the script element'
1934 // it will perform a 'preparation-time document check'.
1935 // However, as import maps could be only inline scripts by now, the
1936 // 'preparation-time document check' will never fail for import maps.
1937 // So we simply call 'register an import map' here.
1938 mModuleLoader->RegisterImportMap(std::move(importMap), request);
1939 return false;
1940 }
1941
1942 if (request->IsSpeculationRulesRequest()) {
1943 MOZ_ASSERT(StaticPrefs::dom_speculation_rules_enabled())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(StaticPrefs::dom_speculation_rules_enabled())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(StaticPrefs::dom_speculation_rules_enabled()))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("StaticPrefs::dom_speculation_rules_enabled()"
, "./../../../dom/script/ScriptLoader.cpp", 1943); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "StaticPrefs::dom_speculation_rules_enabled()"
")"); do { MOZ_CrashSequence(__null, 1943); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1944 mDocument->SetUseCounter(eUseCounter_custom_SpeculationRulesScriptTag);
1945
1946 // https://html.spec.whatwg.org/#prepare-the-script-element
1947 // Step 34.2. Switch on el's type:
1948 // ...
1949 // "speculationrules":
1950 // 1. Let result be the result of creating a speculation rules parse
1951 // result given source text and el's node document.
1952 nsAutoString source;
1953 aElement->GetScriptText(source);
1954 auto speculationRuleSetResult = SpeculationRuleSet::Parse(
1955 NS_ConvertUTF16toUTF8(source), request->BaseURL(), request->BaseURL());
1956
1957 // Like in the import map case above, we register the speculation rules here
1958 // instead of later in EvaluateScriptElement.
1959
1960 // https://html.spec.whatwg.org/#execute-the-script-element
1961 // Step 6. Switch on el's type:
1962 // ...
1963 // "speculationrules":
1964 // 1. Register speculation rules given el's relevant global object and
1965 // el's result.
1966 if (speculationRuleSetResult.isErr()) {
1967 // https://html.spec.whatwg.org/#register-speculation-rules
1968 // Step 1.2.
1969 nsCOMPtr<nsIScriptGlobalObject> global = GetScriptGlobalObject();
1970 if (!global) {
1971 return false;
1972 }
1973 SpeculationRuleSet::ReportParseError(
1974 global, speculationRuleSetResult.unwrapErr());
1975 return false;
1976 }
1977
1978 mDocument->SpeculationRules().RegisterFromScript(
1979 aElement, speculationRuleSetResult.unwrap());
1980 return false;
1981 }
1982
1983 request->mState = ScriptLoadRequest::State::Ready;
1984 if (aElement->GetParserCreated() == FROM_PARSER_XSLT &&
1985 (!ReadyToExecuteParserBlockingScripts() || !mXSLTRequests.isEmpty())) {
1986 // Need to maintain order for XSLT-inserted scripts
1987 NS_ASSERTION(!mParserBlockingRequest,do { if (!(!mParserBlockingRequest)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Parser-blocking scripts and XSLT scripts in the same doc!"
, "!mParserBlockingRequest", "./../../../dom/script/ScriptLoader.cpp"
, 1988); MOZ_PretendNoReturn(); } } while (0)
1988 "Parser-blocking scripts and XSLT scripts in the same doc!")do { if (!(!mParserBlockingRequest)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Parser-blocking scripts and XSLT scripts in the same doc!"
, "!mParserBlockingRequest", "./../../../dom/script/ScriptLoader.cpp"
, 1988); MOZ_PretendNoReturn(); } } while (0)
;
1989 mXSLTRequests.AppendElement(request);
1990 return true;
1991 }
1992 if (aElement->GetParserCreated() == NOT_FROM_PARSER) {
1993 RunScriptWhenSafe(request);
1994 return false;
1995 }
1996 if (aElement->GetParserCreated() == FROM_PARSER_NETWORK &&
1997 !ReadyToExecuteParserBlockingScripts()) {
1998 NS_ASSERTION(!mParserBlockingRequest,do { if (!(!mParserBlockingRequest)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "There can be only one parser-blocking script at a time", "!mParserBlockingRequest"
, "./../../../dom/script/ScriptLoader.cpp", 1999); MOZ_PretendNoReturn
(); } } while (0)
1999 "There can be only one parser-blocking script at a time")do { if (!(!mParserBlockingRequest)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "There can be only one parser-blocking script at a time", "!mParserBlockingRequest"
, "./../../../dom/script/ScriptLoader.cpp", 1999); MOZ_PretendNoReturn
(); } } while (0)
;
2000 mParserBlockingRequest = request;
2001 NS_ASSERTION(mXSLTRequests.isEmpty(),do { if (!(mXSLTRequests.isEmpty())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Parser-blocking scripts and XSLT scripts in the same doc!"
, "mXSLTRequests.isEmpty()", "./../../../dom/script/ScriptLoader.cpp"
, 2002); MOZ_PretendNoReturn(); } } while (0)
2002 "Parser-blocking scripts and XSLT scripts in the same doc!")do { if (!(mXSLTRequests.isEmpty())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Parser-blocking scripts and XSLT scripts in the same doc!"
, "mXSLTRequests.isEmpty()", "./../../../dom/script/ScriptLoader.cpp"
, 2002); MOZ_PretendNoReturn(); } } while (0)
;
2003 return true;
2004 }
2005 // We now have a document.written inline script or we have an inline script
2006 // from the network but there is no style sheet that is blocking scripts.
2007 // Don't check for style sheets blocking scripts in the document.write
2008 // case to avoid style sheet network activity affecting when
2009 // document.write returns. It's not really necessary to do this if
2010 // there's no document.write currently on the call stack. However,
2011 // this way matches IE more closely than checking if document.write
2012 // is on the call stack.
2013 NS_ASSERTION(nsContentUtils::IsSafeToRunScript(),do { if (!(nsContentUtils::IsSafeToRunScript())) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "Not safe to run a parser-inserted script?"
, "nsContentUtils::IsSafeToRunScript()", "./../../../dom/script/ScriptLoader.cpp"
, 2014); MOZ_PretendNoReturn(); } } while (0)
2014 "Not safe to run a parser-inserted script?")do { if (!(nsContentUtils::IsSafeToRunScript())) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "Not safe to run a parser-inserted script?"
, "nsContentUtils::IsSafeToRunScript()", "./../../../dom/script/ScriptLoader.cpp"
, 2014); MOZ_PretendNoReturn(); } } while (0)
;
2015 return ProcessRequest(request) == NS_ERROR_HTMLPARSER_BLOCK;
2016}
2017
2018ScriptLoadRequest* ScriptLoader::LookupPreloadRequest(
2019 nsIScriptElement* aElement, ScriptKind aScriptKind,
2020 const SRIMetadata& aSRIMetadata) {
2021 MOZ_ASSERT(aElement)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aElement)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aElement))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aElement", "./../../../dom/script/ScriptLoader.cpp"
, 2021); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aElement" ")"
); do { MOZ_CrashSequence(__null, 2021); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2022
2023 nsTArray<PreloadInfo>::index_type i =
2024 mPreloads.IndexOf(aElement->GetScriptURI(), 0, PreloadURIComparator());
2025 if (i == nsTArray<PreloadInfo>::NoIndex) {
2026 return nullptr;
2027 }
2028 RefPtr<ScriptLoadRequest> request = mPreloads[i].mRequest;
2029 if (aScriptKind != request->mKind) {
2030 return nullptr;
2031 }
2032
2033#ifdef NIGHTLY_BUILD1
2034 if (WAICTHandlesScripts()) {
2035 return nullptr;
2036 }
2037#endif
2038
2039 // Found preloaded request. Note that a script-inserted script can steal a
2040 // preload!
2041 request->GetScriptLoadContext()->SetIsLoadRequest(aElement);
2042
2043 if (request->GetScriptLoadContext()->mWasCompiledOMT &&
2044 !request->IsModuleRequest()) {
2045 request->SetReady();
2046 }
2047
2048 nsString preloadCharset(mPreloads[i].mCharset);
2049 mPreloads.RemoveElementAt(i);
2050
2051 // Double-check that the charset the preload used is the same as the charset
2052 // we have now.
2053 nsAutoString elementCharset;
2054 aElement->GetScriptCharset(elementCharset);
2055
2056 // Bug 1832361: charset and crossorigin attributes shouldn't affect matching
2057 // of module scripts and modulepreload
2058 if (!request->IsModuleRequest() &&
2059 (!elementCharset.Equals(preloadCharset) ||
2060 aElement->GetCORSMode() != request->CORSMode())) {
2061 // Drop the preload.
2062 request->Cancel();
2063 return nullptr;
2064 }
2065
2066 if (!aSRIMetadata.CanTrustBeDelegatedTo(request->mIntegrity)) {
2067 // Don't cancel link preload requests, we want to deliver onload according
2068 // the result of the load, cancellation would unexpectedly lead to error
2069 // notification.
2070 if (!request->GetScriptLoadContext()->IsLinkPreloadScript()) {
2071 request->Cancel();
2072 }
2073 return nullptr;
2074 }
2075
2076 if (StaticPrefs::dom_multiple_import_maps_enabled()) {
2077 // During preload, the resolved module specifiers are stored in the module
2078 // script. Now the preload request is reused, so adding the resolved
2079 // specifiers into the global's resolved module set.
2080 if (request->IsModuleRequest()) {
2081 mModuleLoader->MovePreloadedSetToResolvedSet(request->AsModuleRequest());
2082 }
2083 }
2084
2085 // Report any errors that we skipped while preloading.
2086 ReportPreloadErrorsToConsole(request);
2087
2088 // This makes sure the pending preload (if exists) for this resource is
2089 // properly marked as used and thus not notified in the console as unused.
2090 request->GetScriptLoadContext()->NotifyUsage(mDocument);
2091 // A used preload must no longer be found in the Document's hash table. Any
2092 // <link preload> tag after the <script> tag will start a new request, that
2093 // can be satisfied from a different cache, but not from the preload cache.
2094 request->GetScriptLoadContext()->RemoveSelf(mDocument);
2095
2096 return request;
2097}
2098
2099void ScriptLoader::GetSRIMetadata(const nsAString& aIntegrityAttr,
2100 SRIMetadata* aMetadataOut) {
2101 MOZ_ASSERT(aMetadataOut->IsEmpty())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aMetadataOut->IsEmpty())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aMetadataOut->IsEmpty()))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aMetadataOut->IsEmpty()"
, "./../../../dom/script/ScriptLoader.cpp", 2101); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aMetadataOut->IsEmpty()" ")"); do { MOZ_CrashSequence
(__null, 2101); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
2102
2103 if (aIntegrityAttr.IsEmpty()) {
2104 return;
2105 }
2106
2107 MOZ_LOG(SRILogHelper::GetSriLog(), mozilla::LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = SRILogHelper
::GetSriLog(); if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "ScriptLoader::GetSRIMetadata, integrity=%s"
, NS_ConvertUTF16toUTF8(aIntegrityAttr).get()); } } while (0)
2108 ("ScriptLoader::GetSRIMetadata, integrity=%s",do { const ::mozilla::LogModule* moz_real_module = SRILogHelper
::GetSriLog(); if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "ScriptLoader::GetSRIMetadata, integrity=%s"
, NS_ConvertUTF16toUTF8(aIntegrityAttr).get()); } } while (0)
2109 NS_ConvertUTF16toUTF8(aIntegrityAttr).get()))do { const ::mozilla::LogModule* moz_real_module = SRILogHelper
::GetSriLog(); if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "ScriptLoader::GetSRIMetadata, integrity=%s"
, NS_ConvertUTF16toUTF8(aIntegrityAttr).get()); } } while (0)
;
2110
2111 nsAutoCString sourceUri;
2112 if (mDocument->GetDocumentURI()) {
2113 mDocument->GetDocumentURI()->GetAsciiSpec(sourceUri);
2114 }
2115 SRICheck::IntegrityMetadata(aIntegrityAttr, sourceUri, mReporter,
2116 aMetadataOut);
2117}
2118
2119ReferrerPolicy ScriptLoader::GetReferrerPolicy(nsIScriptElement* aElement) {
2120 ReferrerPolicy scriptReferrerPolicy = aElement->GetReferrerPolicy();
2121 if (scriptReferrerPolicy != ReferrerPolicy::_empty) {
2122 return scriptReferrerPolicy;
2123 }
2124 return mDocument->GetReferrerPolicy();
2125}
2126
2127void ScriptLoader::CancelAndClearScriptLoadRequests() {
2128 // Cancel all requests that have not been executed and remove them.
2129
2130 if (mParserBlockingRequest) {
2131 mParserBlockingRequest->Cancel();
2132 mParserBlockingRequest = nullptr;
2133 }
2134
2135 mDeferRequests.CancelRequestsAndClear();
2136 mLoadingAsyncRequests.CancelRequestsAndClear();
2137 mLoadedAsyncRequests.CancelRequestsAndClear();
2138 mNonAsyncExternalScriptInsertedRequests.CancelRequestsAndClear();
2139 mXSLTRequests.CancelRequestsAndClear();
2140 mOffThreadCompilingRequests.CancelRequestsAndClear();
2141
2142 if (mModuleLoader) {
2143 mModuleLoader->CancelFetchingModules();
2144 mModuleLoader->CancelAndClearDynamicImports();
2145 }
2146
2147 for (ModuleLoader* loader : mWebExtModuleLoaders) {
2148 loader->CancelAndClearDynamicImports();
2149 }
2150
2151 for (size_t i = 0; i < mPreloads.Length(); i++) {
2152 mPreloads[i].mRequest->Cancel();
2153 }
2154 mPreloads.Clear();
2155}
2156
2157nsresult ScriptLoader::CompileOffThreadOrProcessRequest(
2158 ScriptLoadRequest* aRequest) {
2159 NS_ASSERTION(nsContentUtils::IsSafeToRunScript(),do { if (!(nsContentUtils::IsSafeToRunScript())) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "Processing requests when running scripts is unsafe."
, "nsContentUtils::IsSafeToRunScript()", "./../../../dom/script/ScriptLoader.cpp"
, 2160); MOZ_PretendNoReturn(); } } while (0)
2160 "Processing requests when running scripts is unsafe.")do { if (!(nsContentUtils::IsSafeToRunScript())) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "Processing requests when running scripts is unsafe."
, "nsContentUtils::IsSafeToRunScript()", "./../../../dom/script/ScriptLoader.cpp"
, 2160); MOZ_PretendNoReturn(); } } while (0)
;
2161
2162 if (!aRequest->IsRetrievedFromMemoryCache() &&
2163 !aRequest->GetScriptLoadContext()->mCompileOrDecodeTask &&
2164 !aRequest->GetScriptLoadContext()->CompileStarted()) {
2165 bool couldCompile = false;
2166 nsresult rv = AttemptOffThreadScriptCompile(aRequest, &couldCompile);
2167 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2168 HandleLoadError(aRequest, rv);
2169 return rv;
2170 }
2171
2172 if (couldCompile) {
2173 return NS_OK;
2174 }
2175 }
2176
2177 return ProcessRequest(aRequest);
2178}
2179
2180namespace {
2181
2182class OffThreadCompilationCompleteTask : public Task {
2183 public:
2184 OffThreadCompilationCompleteTask(ScriptLoadRequest* aRequest,
2185 ScriptLoader* aLoader)
2186 : Task(Kind::MainThreadOnly, EventQueuePriority::Normal),
2187 mRequest(aRequest),
2188 mLoader(aLoader) {
2189 MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "./../../../dom/script/ScriptLoader.cpp", 2189); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 2189); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
2190 }
2191
2192 void RecordStartTime() { mStartTime = TimeStamp::Now(); }
2193 void RecordStopTime() { mStopTime = TimeStamp::Now(); }
2194
2195#ifdef MOZ_COLLECTING_RUNNABLE_TELEMETRY
2196 bool GetName(nsACString& aName) override {
2197 aName.AssignLiteral("dom::OffThreadCompilationCompleteTask");
2198 return true;
2199 }
2200#endif
2201
2202 MOZ_CAN_RUN_SCRIPT_BOUNDARY TaskResult Run() override {
2203 MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "./../../../dom/script/ScriptLoader.cpp", 2203); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 2203); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
2204
2205 RefPtr<ScriptLoadContext> context = mRequest->GetScriptLoadContext();
2206
2207 if (!context->mCompileOrDecodeTask) {
2208 // Request has been cancelled by MaybeCancelOffThreadScript.
2209 return TaskResult::Complete;
2210 }
2211
2212 RecordStopTime();
2213
2214 if (profiler_is_active()) {
2215 ProfilerString8View scriptSourceString;
2216 if (mRequest->IsFetchedAsTextSource()) {
2217 scriptSourceString = "ScriptCompileOffThread";
2218 } else if (mRequest->IsWasmBytes()) {
2219 scriptSourceString = "WasmCompileOffThread";
2220 } else {
2221 MOZ_ASSERT(mRequest->IsRetrievedAsSerializedStencil())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mRequest->IsRetrievedAsSerializedStencil())>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(mRequest->IsRetrievedAsSerializedStencil()))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("mRequest->IsRetrievedAsSerializedStencil()"
, "./../../../dom/script/ScriptLoader.cpp", 2221); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "mRequest->IsRetrievedAsSerializedStencil()"
")"); do { MOZ_CrashSequence(__null, 2221); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2222 scriptSourceString = "DecodeStencilOffThread";
2223 }
2224
2225 nsAutoCString profilerLabelString;
2226 mRequest->GetScriptLoadContext()->GetProfilerLabel(profilerLabelString);
2227 PROFILER_MARKER_TEXT(scriptSourceString, JS,do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
(scriptSourceString, ::geckoprofiler::category::JS, MarkerTiming
::Interval(mStartTime, mStopTime), ::geckoprofiler::markers::
TextMarker{}, profilerLabelString); } } while (false); } while
(false)
2228 MarkerTiming::Interval(mStartTime, mStopTime),do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
(scriptSourceString, ::geckoprofiler::category::JS, MarkerTiming
::Interval(mStartTime, mStopTime), ::geckoprofiler::markers::
TextMarker{}, profilerLabelString); } } while (false); } while
(false)
2229 profilerLabelString)do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
(scriptSourceString, ::geckoprofiler::category::JS, MarkerTiming
::Interval(mStartTime, mStopTime), ::geckoprofiler::markers::
TextMarker{}, profilerLabelString); } } while (false); } while
(false)
;
2230 }
2231
2232 const RefPtr<ScriptLoadRequest> request = std::move(mRequest);
2233 const RefPtr<ScriptLoader> loader = std::move(mLoader);
2234 (void)loader->ProcessOffThreadRequest(request);
2235 return TaskResult::Complete;
2236 }
2237
2238 private:
2239 // NOTE:
2240 // These fields are main-thread only, and this task shouldn't be freed off
2241 // main thread.
2242 //
2243 // This is guaranteed by not having off-thread tasks which depends on this
2244 // task, because otherwise the off-thread task's mDependencies can be the
2245 // last reference, which results in freeing this task off main thread.
2246 //
2247 // If such task is added, these fields must be moved to separate storage.
2248 RefPtr<ScriptLoadRequest> mRequest;
2249 RefPtr<ScriptLoader> mLoader;
2250
2251 TimeStamp mStartTime;
2252 TimeStamp mStopTime;
2253};
2254
2255} /* anonymous namespace */
2256
2257// TODO: This uses the same heuristics and the same threshold as the
2258// JS::CanCompileOffThread / JS::CanDecodeOffThread APIs, but the
2259// heuristics needs to be updated to reflect the change regarding the
2260// Stencil API, and also the thread management on the consumer side
2261// (bug 1846160).
2262static constexpr size_t OffThreadMinimumTextLength = 5 * 1000;
2263static constexpr size_t OffThreadMinimumSerializedStencilLength = 5 * 1000;
2264static constexpr size_t OffThreadMinimumWasmLength = 16 * 1024;
2265
2266nsresult ScriptLoader::AttemptOffThreadScriptCompile(
2267 ScriptLoadRequest* aRequest, bool* aCouldCompileOut) {
2268 // If speculative parsing is enabled, the request may not be ready to run if
2269 // the element is not yet available.
2270 MOZ_ASSERT_IF(!SpeculativeOMTParsingEnabled() && !aRequest->IsModuleRequest(),do { if (!SpeculativeOMTParsingEnabled() && !aRequest
->IsModuleRequest()) { do { static_assert( mozilla::detail
::AssertionConditionType<decltype(aRequest->IsFinished(
))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aRequest->IsFinished()))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("aRequest->IsFinished()", "./../../../dom/script/ScriptLoader.cpp"
, 2271); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aRequest->IsFinished()"
")"); do { MOZ_CrashSequence(__null, 2271); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
2271 aRequest->IsFinished())do { if (!SpeculativeOMTParsingEnabled() && !aRequest
->IsModuleRequest()) { do { static_assert( mozilla::detail
::AssertionConditionType<decltype(aRequest->IsFinished(
))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aRequest->IsFinished()))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("aRequest->IsFinished()", "./../../../dom/script/ScriptLoader.cpp"
, 2271); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aRequest->IsFinished()"
")"); do { MOZ_CrashSequence(__null, 2271); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
2272 MOZ_ASSERT(!aRequest->GetScriptLoadContext()->mWasCompiledOMT)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aRequest->GetScriptLoadContext()->mWasCompiledOMT
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!aRequest->GetScriptLoadContext()->mWasCompiledOMT
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"!aRequest->GetScriptLoadContext()->mWasCompiledOMT", "./../../../dom/script/ScriptLoader.cpp"
, 2272); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aRequest->GetScriptLoadContext()->mWasCompiledOMT"
")"); do { MOZ_CrashSequence(__null, 2272); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2273 MOZ_ASSERT(aCouldCompileOut && !*aCouldCompileOut)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aCouldCompileOut && !*aCouldCompileOut)>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aCouldCompileOut && !*aCouldCompileOut))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("aCouldCompileOut && !*aCouldCompileOut"
, "./../../../dom/script/ScriptLoader.cpp", 2273); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aCouldCompileOut && !*aCouldCompileOut"
")"); do { MOZ_CrashSequence(__null, 2273); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2274
2275 // Don't off-thread compile inline scripts.
2276 if (aRequest->GetScriptLoadContext()->mIsInline) {
2277 return NS_OK;
2278 }
2279
2280 if (aRequest->IsRetrievedFromMemoryCache()) {
2281 // This is a revived cache.
2282 return NS_OK;
2283 }
2284
2285 // Don't off-thread compile JSON or CSS modules.
2286 // https://bugzilla.mozilla.org/show_bug.cgi?id=1912112 (JSON)
2287 // https://bugzilla.mozilla.org/show_bug.cgi?id=1987143 (CSS)
2288 if (aRequest->IsModuleRequest() &&
2289 (aRequest->AsModuleRequest()->mModuleType == JS::ModuleType::JSON ||
2290 aRequest->AsModuleRequest()->mModuleType == JS::ModuleType::CSS)) {
2291 return NS_OK;
2292 }
2293
2294 nsCOMPtr<nsIGlobalObject> globalObject = GetGlobalForRequest(aRequest);
2295 if (!globalObject) {
2296 return NS_ERROR_FAILURE;
2297 }
2298
2299 AutoJSAPI jsapi;
2300 if (!jsapi.Init(globalObject)) {
2301 return NS_ERROR_FAILURE;
2302 }
2303
2304 JSContext* cx = jsapi.cx();
2305 JS::CompileOptions options(cx);
2306
2307 // Introduction script will actually be computed and set when the script is
2308 // collected from offthread
2309 JS::Rooted<JSScript*> dummyIntroductionScript(cx);
2310 nsresult rv = FillCompileOptionsForRequest(cx, aRequest, &options,
2311 &dummyIntroductionScript);
2312 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "./../../../dom/script/ScriptLoader.cpp"
, 2312)
) {
2313 return rv;
2314 }
2315
2316 if (aRequest->IsFetchedAsTextSource()) {
2317 if (!StaticPrefs::javascript_options_parallel_parsing() ||
2318 aRequest->ScriptTextLength() < OffThreadMinimumTextLength) {
2319 TRACE_FOR_TEST(aRequest, "compile:main thread")do { mozilla::dom::script::TestingNotifyObserver(aRequest, "compile:main thread"
); } while (0)
;
2320 return NS_OK;
2321 }
2322 } else if (aRequest->IsWasmBytes()) {
2323 if (!StaticPrefs::javascript_options_parallel_parsing() ||
2324 aRequest->WasmBytes().length() < OffThreadMinimumWasmLength) {
2325 TRACE_FOR_TEST(aRequest, "compile:main thread")do { mozilla::dom::script::TestingNotifyObserver(aRequest, "compile:main thread"
); } while (0)
;
2326 return NS_OK;
2327 }
2328
2329 // Only source phase modules are compiled off-thread. Compilation of
2330 // evaluation phase modules is not yet implemented (Bug 2030454).
2331 if (!aRequest->AsModuleRequest()->IsSourcePhaseRequest(cx)) {
2332 TRACE_FOR_TEST(aRequest, "compile:main thread")do { mozilla::dom::script::TestingNotifyObserver(aRequest, "compile:main thread"
); } while (0)
;
2333 return NS_OK;
2334 }
2335 } else {
2336 MOZ_ASSERT(aRequest->IsRetrievedAsSerializedStencil())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aRequest->IsRetrievedAsSerializedStencil())>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aRequest->IsRetrievedAsSerializedStencil()))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("aRequest->IsRetrievedAsSerializedStencil()"
, "./../../../dom/script/ScriptLoader.cpp", 2336); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aRequest->IsRetrievedAsSerializedStencil()"
")"); do { MOZ_CrashSequence(__null, 2336); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2337
2338 JS::TranscodeRange range = aRequest->SerializedStencil();
2339 if (!StaticPrefs::javascript_options_parallel_parsing() ||
2340 range.length() < OffThreadMinimumSerializedStencilLength) {
2341 return NS_OK;
2342 }
2343 }
2344
2345 RefPtr<CompileOrDecodeTask> compileOrDecodeTask;
2346 rv = CreateOffThreadTask(cx, aRequest, options,
2347 getter_AddRefs(compileOrDecodeTask));
2348 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../dom/script/ScriptLoader.cpp"
, 2348); return rv; } } while (false)
;
2349
2350 RefPtr<OffThreadCompilationCompleteTask> completeTask =
2351 new OffThreadCompilationCompleteTask(aRequest, this);
2352
2353 completeTask->RecordStartTime();
2354
2355 aRequest->GetScriptLoadContext()->mCompileOrDecodeTask = compileOrDecodeTask;
2356 completeTask->AddDependency(compileOrDecodeTask);
2357
2358 TaskController::Get()->AddTask(compileOrDecodeTask.forget());
2359 TaskController::Get()->AddTask(completeTask.forget());
2360
2361 TRACE_FOR_TEST(aRequest, "compile:off thread")do { mozilla::dom::script::TestingNotifyObserver(aRequest, "compile:off thread"
); } while (0)
;
2362
2363 aRequest->GetScriptLoadContext()->BlockOnload(mDocument);
2364
2365 // Once the compilation is finished, the completeTask will be run on
2366 // the main thread to call ScriptLoader::ProcessOffThreadRequest for the
2367 // request.
2368 aRequest->mState = ScriptLoadRequest::State::Compiling;
2369
2370 // Requests that are not tracked elsewhere are added to a list while they are
2371 // being compiled off-thread, so we can cancel the compilation later if
2372 // necessary.
2373 //
2374 // Non-top-level modules not tracked because these are cancelled from their
2375 // importing module.
2376 if (aRequest->IsTopLevel() && !aRequest->isInList()) {
2377 mOffThreadCompilingRequests.AppendElement(aRequest);
2378 aRequest->GetScriptLoadContext()->mInCompilingList = true;
2379 }
2380
2381 *aCouldCompileOut = true;
2382
2383 return NS_OK;
2384}
2385
2386CompileOrDecodeTask::CompileOrDecodeTask(Type aType)
2387 : Task(Kind::OffMainThreadOnly, EventQueuePriority::Normal),
2388 mMutex("CompileOrDecodeTask"),
2389 mType(aType) {}
2390
2391void CompileOrDecodeTask::Cancel() {
2392 MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "./../../../dom/script/ScriptLoader.cpp", 2392); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 2392); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
2393
2394 MutexAutoLock lock(mMutex);
2395
2396 mIsCancelled = true;
2397}
2398
2399StencilCompileOrDecodeTask::StencilCompileOrDecodeTask()
2400 : CompileOrDecodeTask(Type::Stencil),
2401 mOptions(JS::OwningCompileOptions::ForFrontendContext()) {}
2402
2403StencilCompileOrDecodeTask::~StencilCompileOrDecodeTask() {
2404 if (mFrontendContext) {
2405 JS::DestroyFrontendContext(mFrontendContext);
2406 mFrontendContext = nullptr;
2407 }
2408}
2409
2410nsresult StencilCompileOrDecodeTask::InitFrontendContext() {
2411 mFrontendContext = JS::NewFrontendContext();
2412 if (!mFrontendContext) {
2413 mIsCancelled = true;
2414 return NS_ERROR_OUT_OF_MEMORY;
2415 }
2416 return NS_OK;
2417}
2418
2419void StencilCompileOrDecodeTask::DidRunTask(const MutexAutoLock& aProofOfLock,
2420 RefPtr<JS::Stencil>&& aStencil) {
2421 if (aStencil) {
2422 if (!JS::PrepareForInstantiate(mFrontendContext, *aStencil,
2423 mInstantiationStorage)) {
2424 aStencil = nullptr;
2425 }
2426 }
2427
2428 mStencil = std::move(aStencil);
2429}
2430
2431already_AddRefed<JS::Stencil> StencilCompileOrDecodeTask::StealResult(
2432 JSContext* aCx, JS::InstantiationStorage* aInstantiationStorage) {
2433 JS::FrontendContext* fc = mFrontendContext;
2434 mFrontendContext = nullptr;
2435 auto destroyFrontendContext =
2436 mozilla::MakeScopeExit([&]() { JS::DestroyFrontendContext(fc); });
2437
2438 MOZ_ASSERT(fc)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(fc)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(fc))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("fc", "./../../../dom/script/ScriptLoader.cpp"
, 2438); AnnotateMozCrashReason("MOZ_ASSERT" "(" "fc" ")"); do
{ MOZ_CrashSequence(__null, 2438); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
2439
2440 if (JS::HadFrontendErrors(fc)) {
2441 (void)JS::ConvertFrontendErrorsToRuntimeErrors(aCx, fc, mOptions);
2442 return nullptr;
2443 }
2444
2445 if (!mStencil && JS::IsTranscodeFailureResult(mResult)) {
2446 // Decode failure with bad content isn't reported as error.
2447 JS_ReportErrorASCII(aCx, "failed to decode cache");
2448 return nullptr;
2449 }
2450
2451 // Report warnings.
2452 if (!JS::ConvertFrontendErrorsToRuntimeErrors(aCx, fc, mOptions)) {
2453 return nullptr;
2454 }
2455
2456 MOZ_ASSERT(mStencil,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mStencil)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mStencil))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mStencil" " (" "If this task is cancelled, StealResult shouldn't be called"
")", "./../../../dom/script/ScriptLoader.cpp", 2457); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "mStencil" ") (" "If this task is cancelled, StealResult shouldn't be called"
")"); do { MOZ_CrashSequence(__null, 2457); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2457 "If this task is cancelled, StealResult shouldn't be called")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mStencil)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mStencil))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mStencil" " (" "If this task is cancelled, StealResult shouldn't be called"
")", "./../../../dom/script/ScriptLoader.cpp", 2457); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "mStencil" ") (" "If this task is cancelled, StealResult shouldn't be called"
")"); do { MOZ_CrashSequence(__null, 2457); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2458
2459 // This task is started and finished successfully.
2460 *aInstantiationStorage = std::move(mInstantiationStorage);
2461
2462 return mStencil.forget();
2463}
2464
2465enum class CompilationTarget { Script, Module };
2466
2467template <CompilationTarget target>
2468class ScriptOrModuleCompileTask final : public StencilCompileOrDecodeTask {
2469 public:
2470 explicit ScriptOrModuleCompileTask(
2471 ScriptLoader::MaybeSourceText&& aMaybeSource)
2472 : StencilCompileOrDecodeTask(), mMaybeSource(std::move(aMaybeSource)) {}
2473
2474 nsresult Init(JS::CompileOptions& aOptions) {
2475 nsresult rv = InitFrontendContext();
2476 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../dom/script/ScriptLoader.cpp"
, 2476); return rv; } } while (false)
;
2477
2478 if (!mOptions.copy(mFrontendContext, aOptions)) {
2479 mIsCancelled = true;
2480 return NS_ERROR_OUT_OF_MEMORY;
2481 }
2482
2483 return NS_OK;
2484 }
2485
2486 TaskResult Run() override {
2487 MutexAutoLock lock(mMutex);
2488
2489 if (IsCancelled(lock)) {
2490 return TaskResult::Complete;
2491 }
2492 RefPtr<JS::Stencil> stencil = Compile();
2493
2494 DidRunTask(lock, std::move(stencil));
2495 return TaskResult::Complete;
2496 }
2497
2498 private:
2499 already_AddRefed<JS::Stencil> Compile() {
2500 size_t stackSize = TaskController::GetThreadStackSize();
2501 JS::SetNativeStackQuota(mFrontendContext,
2502 JS::ThreadStackQuotaForSize(stackSize));
2503
2504 auto compile = [&](auto& source) {
2505 if constexpr (target == CompilationTarget::Script) {
2506 return JS::CompileGlobalScriptToStencil(mFrontendContext, mOptions,
2507 source);
2508 }
2509 return JS::CompileModuleScriptToStencil(mFrontendContext, mOptions,
2510 source);
2511 };
2512 return mMaybeSource.mapNonEmpty(compile);
2513 }
2514
2515 public:
2516#ifdef MOZ_COLLECTING_RUNNABLE_TELEMETRY
2517 bool GetName(nsACString& aName) override {
2518 if constexpr (target == CompilationTarget::Script) {
2519 aName.AssignLiteral("ScriptCompileTask");
2520 } else {
2521 aName.AssignLiteral("ModuleCompileTask");
2522 }
2523 return true;
2524 }
2525#endif
2526
2527 private:
2528 ScriptLoader::MaybeSourceText mMaybeSource;
2529};
2530
2531using ScriptCompileTask =
2532 class ScriptOrModuleCompileTask<CompilationTarget::Script>;
2533using ModuleCompileTask =
2534 class ScriptOrModuleCompileTask<CompilationTarget::Module>;
2535
2536class ScriptDecodeTask final : public StencilCompileOrDecodeTask {
2537 public:
2538 explicit ScriptDecodeTask(const JS::TranscodeRange& aRange)
2539 : mRange(aRange) {}
2540
2541 nsresult Init(JS::DecodeOptions& aOptions) {
2542 nsresult rv = InitFrontendContext();
2543 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../dom/script/ScriptLoader.cpp"
, 2543); return rv; } } while (false)
;
2544
2545 if (!mDecodeOptions.copy(mFrontendContext, aOptions)) {
2546 mIsCancelled = true;
2547 return NS_ERROR_OUT_OF_MEMORY;
2548 }
2549
2550 return NS_OK;
2551 }
2552
2553 TaskResult Run() override {
2554 MutexAutoLock lock(mMutex);
2555
2556 if (IsCancelled(lock)) {
2557 return TaskResult::Complete;
2558 }
2559
2560 RefPtr<JS::Stencil> stencil = Decode();
2561
2562 JS::OwningCompileOptions compileOptions(
2563 (JS::OwningCompileOptions::ForFrontendContext()));
2564 mOptions.steal(std::move(mDecodeOptions));
2565
2566 DidRunTask(lock, std::move(stencil));
2567 return TaskResult::Complete;
2568 }
2569
2570 private:
2571 already_AddRefed<JS::Stencil> Decode() {
2572 // NOTE: JS::DecodeStencil doesn't need the stack quota.
2573
2574 RefPtr<JS::Stencil> stencil;
2575 mResult = JS::DecodeStencil(mFrontendContext, mDecodeOptions, mRange,
2576 getter_AddRefs(stencil));
2577 return stencil.forget();
2578 }
2579
2580 public:
2581#ifdef MOZ_COLLECTING_RUNNABLE_TELEMETRY
2582 bool GetName(nsACString& aName) override {
2583 aName.AssignLiteral("ScriptDecodeTask");
2584 return true;
2585 }
2586#endif
2587
2588 private:
2589 JS::OwningDecodeOptions mDecodeOptions;
2590
2591 JS::TranscodeRange mRange;
2592};
2593
2594nsresult WasmCompileTask::Init(JSContext* aCx, JS::CompileOptions& aOptions) {
2595 mCompileArgs = JS::BuildCompileArgsForESM(aCx, aOptions);
2596 if (!mCompileArgs) {
2597 mIsCancelled = true;
2598 return NS_ERROR_OUT_OF_MEMORY;
2599 }
2600
2601 return NS_OK;
2602}
2603
2604Task::TaskResult WasmCompileTask::Run() {
2605 MutexAutoLock lock(mMutex);
2606
2607 if (IsCancelled(lock)) {
2608 return TaskResult::Complete;
2609 }
2610
2611 mCompileResult =
2612 JS::CompileForESM(*mCompileArgs, mBytes.begin(), mBytes.length());
2613
2614 return TaskResult::Complete;
2615}
2616
2617bool WasmCompileTask::StealResult(JSContext* aCx,
2618 JS::MutableHandle<JSObject*> aModuleOut) {
2619 JS::Rooted<JSObject*> wasmModuleObject(aCx);
2620 if (!JS::FinishCompileForESM(aCx, *mCompileArgs, mCompileResult,
2621 &wasmModuleObject)) {
2622 return false;
2623 }
2624
2625 aModuleOut.set(JS::CreateWasmSourcePhaseModule(aCx, wasmModuleObject));
2626 return !!aModuleOut;
2627}
2628
2629nsresult ScriptLoader::CreateOffThreadTask(
2630 JSContext* aCx, ScriptLoadRequest* aRequest, JS::CompileOptions& aOptions,
2631 CompileOrDecodeTask** aCompileOrDecodeTask) {
2632 if (aRequest->IsWasmBytes()) {
2633 RefPtr<WasmCompileTask> compileTask =
2634 new WasmCompileTask(std::move(aRequest->WasmBytes()));
2635 nsresult rv = compileTask->Init(aCx, aOptions);
2636 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../dom/script/ScriptLoader.cpp"
, 2636); return rv; } } while (false)
;
2637 compileTask.forget(aCompileOrDecodeTask);
2638 return NS_OK;
2639 }
2640
2641 if (aRequest->IsRetrievedAsSerializedStencil()) {
2642 JS::TranscodeRange range = aRequest->SerializedStencil();
2643 JS::DecodeOptions decodeOptions(aOptions);
2644 RefPtr<ScriptDecodeTask> decodeTask = new ScriptDecodeTask(range);
2645 nsresult rv = decodeTask->Init(decodeOptions);
2646 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../dom/script/ScriptLoader.cpp"
, 2646); return rv; } } while (false)
;
2647 decodeTask.forget(aCompileOrDecodeTask);
2648 return NS_OK;
2649 }
2650
2651 MaybeSourceText maybeSource;
2652 nsresult rv = aRequest->GetScriptSource(aCx, &maybeSource,
2653 aRequest->mLoadContext.get());
2654 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../dom/script/ScriptLoader.cpp"
, 2654); return rv; } } while (false)
;
2655
2656 if (ShouldApplyDelazifyStrategy(aRequest)) {
2657 ApplyDelazifyStrategy(&aOptions);
2658 mTotalFullParseSize +=
2659 aRequest->ScriptTextLength() > 0
2660 ? static_cast<uint32_t>(aRequest->ScriptTextLength())
2661 : 0;
2662
2663 LOG(
2664 ("ScriptLoadRequest (%p): non-on-demand-only (omt) Parsing Enabled "
2665 "for url=%s mTotalFullParseSize=%u",
2666 aRequest, aRequest->URI()->GetSpecOrDefault().get(),
2667 mTotalFullParseSize));
2668 }
2669
2670 if (aRequest->IsModuleRequest()) {
2671 RefPtr<ModuleCompileTask> compileTask =
2672 new ModuleCompileTask(std::move(maybeSource));
2673 rv = compileTask->Init(aOptions);
2674 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../dom/script/ScriptLoader.cpp"
, 2674); return rv; } } while (false)
;
2675 compileTask.forget(aCompileOrDecodeTask);
2676 return NS_OK;
2677 }
2678 MOZ_ASSERT(!aRequest->IsWasmBytes())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aRequest->IsWasmBytes())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aRequest->IsWasmBytes())
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!aRequest->IsWasmBytes()"
, "./../../../dom/script/ScriptLoader.cpp", 2678); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!aRequest->IsWasmBytes()" ")"); do { MOZ_CrashSequence
(__null, 2678); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
2679
2680 if (StaticPrefs::dom_expose_test_interfaces()) {
2681 switch (aOptions.eagerDelazificationStrategy()) {
2682 case JS::DelazificationOption::OnDemandOnly:
2683 TRACE_FOR_TEST(aRequest, "delazification:OnDemandOnly")do { mozilla::dom::script::TestingNotifyObserver(aRequest, "delazification:OnDemandOnly"
); } while (0)
;
2684 break;
2685 case JS::DelazificationOption::CheckConcurrentWithOnDemand:
2686 case JS::DelazificationOption::ConcurrentDepthFirst:
2687 TRACE_FOR_TEST(aRequest, "delazification:ConcurrentDepthFirst")do { mozilla::dom::script::TestingNotifyObserver(aRequest, "delazification:ConcurrentDepthFirst"
); } while (0)
;
2688 break;
2689 case JS::DelazificationOption::ConcurrentLargeFirst:
2690 TRACE_FOR_TEST(aRequest, "delazification:ConcurrentLargeFirst")do { mozilla::dom::script::TestingNotifyObserver(aRequest, "delazification:ConcurrentLargeFirst"
); } while (0)
;
2691 break;
2692 case JS::DelazificationOption::ParseEverythingEagerly:
2693 TRACE_FOR_TEST(aRequest, "delazification:ParseEverythingEagerly")do { mozilla::dom::script::TestingNotifyObserver(aRequest, "delazification:ParseEverythingEagerly"
); } while (0)
;
2694 break;
2695 }
2696 }
2697
2698 RefPtr<ScriptCompileTask> compileTask =
2699 new ScriptCompileTask(std::move(maybeSource));
2700 rv = compileTask->Init(aOptions);
2701 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../dom/script/ScriptLoader.cpp"
, 2701); return rv; } } while (false)
;
2702 compileTask.forget(aCompileOrDecodeTask);
2703 return NS_OK;
2704}
2705
2706nsresult ScriptLoader::ProcessOffThreadRequest(ScriptLoadRequest* aRequest) {
2707 MOZ_ASSERT(aRequest->IsCompiling())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aRequest->IsCompiling())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aRequest->IsCompiling()))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aRequest->IsCompiling()"
, "./../../../dom/script/ScriptLoader.cpp", 2707); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aRequest->IsCompiling()" ")"); do { MOZ_CrashSequence
(__null, 2707); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
2708 MOZ_ASSERT(!aRequest->GetScriptLoadContext()->mWasCompiledOMT)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aRequest->GetScriptLoadContext()->mWasCompiledOMT
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!aRequest->GetScriptLoadContext()->mWasCompiledOMT
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"!aRequest->GetScriptLoadContext()->mWasCompiledOMT", "./../../../dom/script/ScriptLoader.cpp"
, 2708); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aRequest->GetScriptLoadContext()->mWasCompiledOMT"
")"); do { MOZ_CrashSequence(__null, 2708); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2709
2710 PROFILER_MARKER("ScriptLoader::ProcessOffThreadRequest", JS,do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("ScriptLoader::ProcessOffThreadRequest", ::geckoprofiler::category
::JS, {mozilla::MarkerStack::Capture()}, ::geckoprofiler::markers
::FlowMarker{}, Flow::FromPointer(aRequest)); } } while (false
); } while (false)
2711 {mozilla::MarkerStack::Capture()}, FlowMarker,do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("ScriptLoader::ProcessOffThreadRequest", ::geckoprofiler::category
::JS, {mozilla::MarkerStack::Capture()}, ::geckoprofiler::markers
::FlowMarker{}, Flow::FromPointer(aRequest)); } } while (false
); } while (false)
2712 Flow::FromPointer(aRequest))do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("ScriptLoader::ProcessOffThreadRequest", ::geckoprofiler::category
::JS, {mozilla::MarkerStack::Capture()}, ::geckoprofiler::markers
::FlowMarker{}, Flow::FromPointer(aRequest)); } } while (false
); } while (false)
;
2713
2714 if (aRequest->IsCanceled()) {
2715 return NS_OK;
2716 }
2717
2718 aRequest->GetScriptLoadContext()->mWasCompiledOMT = true;
2719
2720 if (aRequest->GetScriptLoadContext()->mInCompilingList) {
2721 mOffThreadCompilingRequests.Remove(aRequest);
2722 aRequest->GetScriptLoadContext()->mInCompilingList = false;
2723 }
2724
2725 if (aRequest->IsModuleRequest()) {
2726 MOZ_ASSERT(aRequest->GetScriptLoadContext()->mCompileOrDecodeTask)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aRequest->GetScriptLoadContext()->mCompileOrDecodeTask
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aRequest->GetScriptLoadContext()->mCompileOrDecodeTask
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"aRequest->GetScriptLoadContext()->mCompileOrDecodeTask"
, "./../../../dom/script/ScriptLoader.cpp", 2726); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aRequest->GetScriptLoadContext()->mCompileOrDecodeTask"
")"); do { MOZ_CrashSequence(__null, 2726); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2727 ModuleLoadRequest* request = aRequest->AsModuleRequest();
2728 return request->OnFetchComplete(NS_OK);
2729 }
2730
2731 // Element may not be ready yet if speculatively compiling, so process the
2732 // request in ProcessPendingRequests when it is available.
2733 MOZ_ASSERT_IF(!SpeculativeOMTParsingEnabled(),do { if (!SpeculativeOMTParsingEnabled()) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(aRequest
->GetScriptLoadContext()->HasScriptElement())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(aRequest->GetScriptLoadContext()->HasScriptElement()
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"aRequest->GetScriptLoadContext()->HasScriptElement()",
"./../../../dom/script/ScriptLoader.cpp", 2734); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aRequest->GetScriptLoadContext()->HasScriptElement()"
")"); do { MOZ_CrashSequence(__null, 2734); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
2734 aRequest->GetScriptLoadContext()->HasScriptElement())do { if (!SpeculativeOMTParsingEnabled()) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(aRequest
->GetScriptLoadContext()->HasScriptElement())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(aRequest->GetScriptLoadContext()->HasScriptElement()
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"aRequest->GetScriptLoadContext()->HasScriptElement()",
"./../../../dom/script/ScriptLoader.cpp", 2734); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aRequest->GetScriptLoadContext()->HasScriptElement()"
")"); do { MOZ_CrashSequence(__null, 2734); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
2735 if (!aRequest->GetScriptLoadContext()->HasScriptElement()) {
2736 // Unblock onload here in case this request never gets executed.
2737 aRequest->GetScriptLoadContext()->MaybeUnblockOnload();
2738 return NS_OK;
2739 }
2740
2741 aRequest->SetReady();
2742
2743 // Move async scripts to mLoadedAsyncRequests and process them by calling
2744 // ProcessPendingRequests.
2745 if (aRequest != mParserBlockingRequest &&
2746 (aRequest->GetScriptLoadContext()->IsAsyncScript() ||
2747 aRequest->GetScriptLoadContext()->IsBlockingScript()) &&
2748 !aRequest->isInList()) {
2749 if (aRequest->GetScriptLoadContext()->IsAsyncScript()) {
2750 // We're adding the request back to async list so that it can be executed
2751 // later.
2752 aRequest->GetScriptLoadContext()->mInAsyncList = false;
2753 AddAsyncRequest(aRequest);
2754 } else {
2755 MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "This should not run ever with the current default prefs. The "
"request should not run synchronously but added to some queue."
")", "./../../../dom/script/ScriptLoader.cpp", 2758); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "false" ") (" "This should not run ever with the current default prefs. The "
"request should not run synchronously but added to some queue."
")"); do { MOZ_CrashSequence(__null, 2758); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2756 false,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "This should not run ever with the current default prefs. The "
"request should not run synchronously but added to some queue."
")", "./../../../dom/script/ScriptLoader.cpp", 2758); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "false" ") (" "This should not run ever with the current default prefs. The "
"request should not run synchronously but added to some queue."
")"); do { MOZ_CrashSequence(__null, 2758); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2757 "This should not run ever with the current default prefs. The "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "This should not run ever with the current default prefs. The "
"request should not run synchronously but added to some queue."
")", "./../../../dom/script/ScriptLoader.cpp", 2758); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "false" ") (" "This should not run ever with the current default prefs. The "
"request should not run synchronously but added to some queue."
")"); do { MOZ_CrashSequence(__null, 2758); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2758 "request should not run synchronously but added to some queue.")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "This should not run ever with the current default prefs. The "
"request should not run synchronously but added to some queue."
")", "./../../../dom/script/ScriptLoader.cpp", 2758); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "false" ") (" "This should not run ever with the current default prefs. The "
"request should not run synchronously but added to some queue."
")"); do { MOZ_CrashSequence(__null, 2758); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2759 return ProcessRequest(aRequest);
2760 }
2761 } else if (aRequest->GetScriptLoadContext()->mInAsyncList) {
2762 // This async request may already be in mLoadingAsyncRequests while its
2763 // off-thread compilation finishes. Now that it is ready, move it to
2764 // mLoadedAsyncRequests so ProcessPendingRequests can execute it.
2765 MaybeMoveToLoadedList(aRequest);
2766 }
2767
2768 // Process other scripts in the proper order.
2769 ProcessPendingRequests();
2770 return NS_OK;
2771}
2772
2773nsresult ScriptLoader::ProcessRequest(ScriptLoadRequest* aRequest) {
2774 LOG(("ScriptLoadRequest (%p): Process request", aRequest));
2775
2776 NS_ASSERTION(nsContentUtils::IsSafeToRunScript(),do { if (!(nsContentUtils::IsSafeToRunScript())) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "Processing requests when running scripts is unsafe."
, "nsContentUtils::IsSafeToRunScript()", "./../../../dom/script/ScriptLoader.cpp"
, 2777); MOZ_PretendNoReturn(); } } while (0)
2777 "Processing requests when running scripts is unsafe.")do { if (!(nsContentUtils::IsSafeToRunScript())) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "Processing requests when running scripts is unsafe."
, "nsContentUtils::IsSafeToRunScript()", "./../../../dom/script/ScriptLoader.cpp"
, 2777); MOZ_PretendNoReturn(); } } while (0)
;
2778 NS_ASSERTION(aRequest->IsFinished(),do { if (!(aRequest->IsFinished())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Processing a request that is not ready to run.", "aRequest->IsFinished()"
, "./../../../dom/script/ScriptLoader.cpp", 2779); MOZ_PretendNoReturn
(); } } while (0)
2779 "Processing a request that is not ready to run.")do { if (!(aRequest->IsFinished())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Processing a request that is not ready to run.", "aRequest->IsFinished()"
, "./../../../dom/script/ScriptLoader.cpp", 2779); MOZ_PretendNoReturn
(); } } while (0)
;
2780
2781 NS_ENSURE_ARG(aRequest)do { if ((__builtin_expect(!!(!(aRequest)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aRequest" ") failed", nullptr
, "./../../../dom/script/ScriptLoader.cpp", 2781); return NS_ERROR_INVALID_ARG
; } } while (false)
;
2782
2783 auto unblockOnload = MakeScopeExit(
2784 [&] { aRequest->GetScriptLoadContext()->MaybeUnblockOnload(); });
2785
2786 if (aRequest->IsModuleRequest()) {
2787 ModuleLoadRequest* request = aRequest->AsModuleRequest();
2788 if (request->IsDynamicImport()) {
2789 request->ProcessDynamicImport();
2790 return NS_OK;
2791 }
2792
2793 if (request->mModuleScript &&
2794 !request->mModuleScript->HasErrorToRethrow()) {
2795 if (!request->InstantiateModuleGraph()) {
2796 request->mModuleScript = nullptr;
2797 }
2798 }
2799
2800 if (!request->mModuleScript) {
2801 // There was an error fetching a module script. Nothing to do here.
2802 LOG(("ScriptLoadRequest (%p): Error loading request, firing error",
2803 aRequest));
2804 FireScriptAvailable(NS_ERROR_FAILURE, aRequest);
2805 return NS_OK;
2806 }
2807 }
2808
2809 nsCOMPtr<nsIScriptElement> oldParserInsertedScript;
2810 uint32_t parserCreated = aRequest->GetScriptLoadContext()->GetParserCreated();
2811 if (parserCreated) {
2812 oldParserInsertedScript = mCurrentParserInsertedScript;
2813 mCurrentParserInsertedScript =
2814 aRequest->GetScriptLoadContext()
2815 ->GetScriptElementForCurrentParserInsertedScript();
2816 }
2817
2818 aRequest->GetScriptLoadContext()->BeginEvaluatingTopLevel();
2819
2820 FireScriptAvailable(NS_OK, aRequest);
2821
2822 {
2823 // Try to perform a microtask checkpoint
2824 nsAutoMicroTask mt;
2825 }
2826
2827 nsresult rv = EvaluateScriptElement(aRequest);
2828
2829 FireScriptEvaluated(rv, aRequest);
2830
2831 aRequest->GetScriptLoadContext()->EndEvaluatingTopLevel();
2832
2833 if (parserCreated) {
2834 mCurrentParserInsertedScript = oldParserInsertedScript;
2835 }
2836
2837 if (aRequest->GetScriptLoadContext()->mCompileOrDecodeTask) {
2838 // The request was parsed off-main-thread, but the result of the off
2839 // thread parse was not actually needed to process the request
2840 // (disappearing window, some other error, ...). Finish the
2841 // request to avoid leaks.
2842 MOZ_ASSERT(!aRequest->IsModuleRequest())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aRequest->IsModuleRequest())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aRequest->IsModuleRequest
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!aRequest->IsModuleRequest()", "./../../../dom/script/ScriptLoader.cpp"
, 2842); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aRequest->IsModuleRequest()"
")"); do { MOZ_CrashSequence(__null, 2842); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2843 aRequest->GetScriptLoadContext()->MaybeCancelOffThreadScript();
2844 }
2845
2846 // If the script is in-memory cached, it should already be converted to
2847 // CachedStencil in ScriptLoader::TryCacheRequest.
2848 //
2849 // If the navigation cache is not enabled and the script is going to be
2850 // saved to disk, it's also converted to CachedStencil in
2851 // ScriptLoader::RegisterForDiskCache.
2852 //
2853 // If the LoadedScript is still eTextSource or eSerializedStencil at this
2854 // point, they're not going to be cached, and the received data is
2855 // no longer necessary.
2856 if (aRequest->getLoadedScript()->IsTextSource()) {
2857 aRequest->getLoadedScript()->ClearScriptText();
2858 aRequest->getLoadedScript()->DropSRI();
2859 } else if (aRequest->getLoadedScript()->IsSerializedStencil()) {
2860 MOZ_ASSERT(!aRequest->HasStencil())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aRequest->HasStencil())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aRequest->HasStencil()))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!aRequest->HasStencil()"
, "./../../../dom/script/ScriptLoader.cpp", 2860); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!aRequest->HasStencil()" ")"); do { MOZ_CrashSequence
(__null, 2860); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
2861 aRequest->getLoadedScript()->DropSRIOrSRIAndSerializedStencil();
2862 }
2863
2864 return rv;
2865}
2866
2867void ScriptLoader::FireScriptAvailable(nsresult aResult,
2868 ScriptLoadRequest* aRequest) {
2869 const nsCOMPtr<nsIScriptElement> scriptElement =
2870 aRequest->GetScriptLoadContext()->GetScriptElementForObserver();
2871 const nsCOMPtr<nsIURI> uri = aRequest->URI();
2872 for (int32_t i = 0; i < mObservers.Count(); i++) {
2873 nsCOMPtr<nsIScriptLoaderObserver> obs = mObservers[i];
2874 obs->ScriptAvailable(aResult, scriptElement,
2875 aRequest->GetScriptLoadContext()->mIsInline, uri,
2876 aRequest->GetScriptLoadContext()->mLineNo);
2877 }
2878
2879 const bool isInlineClassicScript =
2880 aRequest->GetScriptLoadContext()->mIsInline &&
2881 !aRequest->IsModuleRequest();
2882 scriptElement->ScriptAvailable(aResult, scriptElement, isInlineClassicScript,
2883 uri,
2884 aRequest->GetScriptLoadContext()->mLineNo);
2885}
2886
2887// TODO: Convert this to MOZ_CAN_RUN_SCRIPT (bug 1415230)
2888MOZ_CAN_RUN_SCRIPT_BOUNDARY void ScriptLoader::FireScriptEvaluated(
2889 nsresult aResult, ScriptLoadRequest* aRequest) {
2890 for (int32_t i = 0; i < mObservers.Count(); i++) {
2891 nsCOMPtr<nsIScriptLoaderObserver> obs = mObservers[i];
2892 RefPtr<nsIScriptElement> scriptElement =
2893 aRequest->GetScriptLoadContext()->GetScriptElementForObserver();
2894 obs->ScriptEvaluated(aResult, scriptElement,
2895 aRequest->GetScriptLoadContext()->mIsInline);
2896 }
2897
2898 RefPtr<nsIScriptElement> scriptElement =
2899 aRequest->GetScriptLoadContext()->GetScriptElementForObserver();
2900 scriptElement->ScriptEvaluated(aResult, scriptElement,
2901 aRequest->GetScriptLoadContext()->mIsInline);
2902}
2903
2904already_AddRefed<nsIGlobalObject> ScriptLoader::GetGlobalForRequest(
2905 ScriptLoadRequest* aRequest) {
2906 if (aRequest->IsModuleRequest()) {
2907 ModuleLoader* loader =
2908 ModuleLoader::From(aRequest->AsModuleRequest()->mLoader);
2909 nsCOMPtr<nsIGlobalObject> global = loader->GetGlobalObject();
2910 return global.forget();
2911 }
2912
2913 return GetScriptGlobalObject();
2914}
2915
2916already_AddRefed<nsIScriptGlobalObject> ScriptLoader::GetScriptGlobalObject() {
2917 if (!mDocument) {
2918 return nullptr;
2919 }
2920
2921 nsPIDOMWindowInner* pwin = mDocument->GetInnerWindow();
2922 if (!pwin) {
2923 return nullptr;
2924 }
2925
2926 nsCOMPtr<nsIScriptGlobalObject> globalObject = do_QueryInterface(pwin);
2927 NS_ASSERTION(globalObject, "windows must be global objects")do { if (!(globalObject)) { NS_DebugBreak(NS_DEBUG_ASSERTION,
"windows must be global objects", "globalObject", "./../../../dom/script/ScriptLoader.cpp"
, 2927); MOZ_PretendNoReturn(); } } while (0)
;
2928
2929 // and make sure we are setup for this type of script.
2930 nsresult rv = globalObject->EnsureScriptEnvironment();
2931 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2932 return nullptr;
2933 }
2934
2935 return globalObject.forget();
2936}
2937
2938static void ApplyEagerBaselineStrategy(JS::CompileOptions* aOptions) {
2939 uint32_t strategyIndex = StaticPrefs::
2940 javascript_options_baselinejit_offthread_compilation_strategy();
2941
2942 JS::EagerBaselineOption strategy;
2943 switch (strategyIndex) {
2944 // Values of 2 and 3 indicate to eagerly baseline compile, but only
2945 // if JitHints are available.
2946 case 2:
2947 case 3:
2948 strategy = JS::EagerBaselineOption::JitHints;
2949 break;
2950 case 4:
2951 strategy = JS::EagerBaselineOption::Aggressive;
2952 break;
2953 default:
2954 // Value of 0 indicates omt baseline compilation should be disabled.
2955 // Value of 1 indicates omt baseline compilation should be on demand only,
2956 // so set the eager baseline strategy to None.
2957 strategy = JS::EagerBaselineOption::None;
2958 break;
2959 }
2960
2961 aOptions->setEagerBaselineStrategy(strategy);
2962}
2963
2964nsresult ScriptLoader::FillCompileOptionsForRequest(
2965 JSContext* aCx, ScriptLoadRequest* aRequest, JS::CompileOptions* aOptions,
2966 JS::MutableHandle<JSScript*> aIntroductionScript) {
2967 // It's very important to use aRequest->URI(), not the final URI of the
2968 // channel aRequest ended up getting script data from, as the script filename.
2969 nsresult rv = aRequest->URI()->GetSpec(aRequest->mURL);
2970 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "./../../../dom/script/ScriptLoader.cpp"
, 2970)
) {
2971 return rv;
2972 }
2973
2974 if (mDocument) {
2975 mDocument->NoteScriptTrackingStatus(
2976 aRequest->mURL,
2977 aRequest->GetScriptLoadContext()->GetClassificationFlags());
2978 }
2979
2980 const char* introductionType;
2981 if (aRequest->IsModuleRequest() &&
2982 !aRequest->AsModuleRequest()->IsTopLevel()) {
2983 introductionType = "importedModule";
2984 } else if (!aRequest->GetScriptLoadContext()->mIsInline) {
2985 introductionType = "srcScript";
2986 } else if (aRequest->GetScriptLoadContext()->GetParserCreated() ==
2987 FROM_PARSER_NETWORK) {
2988 introductionType = "inlineScript";
2989 } else {
2990 introductionType = "injectedScript";
2991 }
2992 aOptions->setIntroductionInfoToCaller(aCx, introductionType,
2993 aIntroductionScript);
2994 aOptions->setFileAndLine(aRequest->mURL.get(),
2995 aRequest->GetScriptLoadContext()->mLineNo);
2996 // The column is only relevant for inline scripts in order for SpiderMonkey to
2997 // properly compute offsets relatively to the script position within the HTML
2998 // file. injectedScript are not concerned and are always considered to start
2999 // at column 0.
3000 if (aRequest->GetScriptLoadContext()->mIsInline &&
3001 aRequest->GetScriptLoadContext()->GetParserCreated() ==
3002 FROM_PARSER_NETWORK) {
3003 aOptions->setColumn(aRequest->GetScriptLoadContext()->mColumnNo);
3004 }
3005 aOptions->setIsRunOnce(true);
3006 aOptions->setNoScriptRval(true);
3007 if (aRequest->HasSourceMapURL()) {
3008 aOptions->setSourceMapURL(aRequest->GetSourceMapURL().get());
3009 }
3010 if (aRequest->mOriginPrincipal) {
3011 nsCOMPtr<nsIGlobalObject> globalObject = GetGlobalForRequest(aRequest);
3012 nsIPrincipal* scriptPrin = globalObject->PrincipalOrNull();
3013 MOZ_ASSERT(scriptPrin)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(scriptPrin)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(scriptPrin))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("scriptPrin", "./../../../dom/script/ScriptLoader.cpp"
, 3013); AnnotateMozCrashReason("MOZ_ASSERT" "(" "scriptPrin"
")"); do { MOZ_CrashSequence(__null, 3013); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3014 bool subsumes = scriptPrin->Subsumes(aRequest->mOriginPrincipal);
3015 aOptions->setMutedErrors(!subsumes);
3016 }
3017
3018 aOptions->setDeferDebugMetadata(true);
3019
3020 if (!mCache) {
3021 aOptions->borrowBuffer = true;
3022 }
3023
3024 ApplyEagerBaselineStrategy(aOptions);
3025
3026 return NS_OK;
3027}
3028
3029/* static */
3030ScriptLoader::DiskCacheStrategy ScriptLoader::GetDiskCacheStrategy() {
3031 int32_t strategyPref =
3032 StaticPrefs::dom_script_loader_bytecode_cache_strategy();
3033 LOG(("Bytecode-cache: disk cache strategy = %d.", strategyPref));
3034
3035 DiskCacheStrategy strategy;
3036 switch (strategyPref) {
3037 case -2: {
3038 strategy.mIsDisabled = true;
3039 break;
3040 }
3041 case -1: {
3042 // Eager mode, skip heuristics!
3043 strategy.mHasSourceLengthMin = false;
3044 strategy.mHasFetchCountMin = false;
3045 break;
3046 }
3047 case 1: {
3048 strategy.mHasSourceLengthMin = true;
3049 strategy.mHasFetchCountMin = true;
3050 strategy.mSourceLengthMin = 1024;
3051 // fetchCountMin is optimized for speed in exchange for additional
3052 // memory and cache use.
3053 strategy.mFetchCountMin = 2;
3054 break;
3055 }
3056 default:
3057 case 0: {
3058 strategy.mHasSourceLengthMin = true;
3059 strategy.mHasFetchCountMin = true;
3060 strategy.mSourceLengthMin = 1024;
3061 // If we were to optimize only for speed, without considering the impact
3062 // on memory, we should set this threshold to 2. (Bug 900784 comment 120)
3063 strategy.mFetchCountMin = 4;
3064 break;
3065 }
3066 }
3067
3068 return strategy;
3069}
3070
3071void ScriptLoader::CalculateCacheFlag(ScriptLoadRequest* aRequest) {
3072 using mozilla::TimeDuration;
3073 using mozilla::TimeStamp;
3074
3075#ifdef NIGHTLY_BUILD1
3076 // For WAICT we always need to be able to hash the script source,
3077 // which might not be possible when caching only the stencil.
3078 if (WAICTHandlesScripts()) {
3079 aRequest->MarkNotCacheable();
3080 return;
3081 }
3082#endif
3083
3084 if (aRequest->GetScriptLoadContext()->mIsInline) {
3085 LOG(("ScriptLoadRequest (%p): Bytecode-cache: Skip all: Inline script",
3086 aRequest));
3087 aRequest->MarkNotCacheable();
3088 MOZ_ASSERT(!aRequest->getLoadedScript()->HasDiskCacheReference())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aRequest->getLoadedScript()->HasDiskCacheReference
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!aRequest->getLoadedScript()->HasDiskCacheReference
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!aRequest->getLoadedScript()->HasDiskCacheReference()"
, "./../../../dom/script/ScriptLoader.cpp", 3088); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!aRequest->getLoadedScript()->HasDiskCacheReference()"
")"); do { MOZ_CrashSequence(__null, 3088); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3089 // NOTE: An inline script tag can have an SRI, but we don't calculate it
3090 // for this case.
3091 MOZ_ASSERT(aRequest->HasNoSRIOrSRIAndSerializedStencil())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aRequest->HasNoSRIOrSRIAndSerializedStencil())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aRequest->HasNoSRIOrSRIAndSerializedStencil()))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("aRequest->HasNoSRIOrSRIAndSerializedStencil()"
, "./../../../dom/script/ScriptLoader.cpp", 3091); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aRequest->HasNoSRIOrSRIAndSerializedStencil()"
")"); do { MOZ_CrashSequence(__null, 3091); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3092 return;
3093 }
3094
3095 if (!aRequest->URI()->SchemeIs("http") &&
3096 !aRequest->URI()->SchemeIs("https")) {
3097 LOG(("ScriptLoadRequest (%p): Bytecode-cache: Skip all: Unsupported scheme",
3098 aRequest));
3099 // Internal resources can be exposed to the web content, but they don't
3100 // have to be cached.
3101 aRequest->MarkNotCacheable();
3102 MOZ_ASSERT(!aRequest->getLoadedScript()->HasDiskCacheReference())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aRequest->getLoadedScript()->HasDiskCacheReference
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!aRequest->getLoadedScript()->HasDiskCacheReference
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!aRequest->getLoadedScript()->HasDiskCacheReference()"
, "./../../../dom/script/ScriptLoader.cpp", 3102); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!aRequest->getLoadedScript()->HasDiskCacheReference()"
")"); do { MOZ_CrashSequence(__null, 3102); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3103 MOZ_ASSERT(aRequest->HasNoSRIOrSRIAndSerializedStencil())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aRequest->HasNoSRIOrSRIAndSerializedStencil())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aRequest->HasNoSRIOrSRIAndSerializedStencil()))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("aRequest->HasNoSRIOrSRIAndSerializedStencil()"
, "./../../../dom/script/ScriptLoader.cpp", 3103); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aRequest->HasNoSRIOrSRIAndSerializedStencil()"
")"); do { MOZ_CrashSequence(__null, 3103); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3104 return;
3105 }
3106
3107 if (aRequest->IsModuleRequest()) {
3108 ModuleLoadRequest* moduleLoadRequest = aRequest->AsModuleRequest();
3109 if (moduleLoadRequest->mModuleType == JS::ModuleType::JavaScriptOrWasm) {
3110#ifdef NIGHTLY_BUILD1
3111 // See https://bugzilla.mozilla.org/show_bug.cgi?id=1998240
3112 // For now, we don't support caching wasm modules.
3113 if (moduleLoadRequest->HasWasmMimeTypeEssence()) {
3114 MOZ_ASSERT(aRequest->IsWasmBytes())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aRequest->IsWasmBytes())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aRequest->IsWasmBytes()))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aRequest->IsWasmBytes()"
, "./../../../dom/script/ScriptLoader.cpp", 3114); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aRequest->IsWasmBytes()" ")"); do { MOZ_CrashSequence
(__null, 3114); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
3115 LOG(("ScriptLoadRequest (%p): Bytecode-cache: Skip all: wasm module",
3116 aRequest));
3117 aRequest->MarkNotCacheable();
3118 // The disk reference is cleared when we do the mime essense check
3119 // in PrepareLoadedRequest.
3120 MOZ_ASSERT(!aRequest->getLoadedScript()->HasDiskCacheReference())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aRequest->getLoadedScript()->HasDiskCacheReference
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!aRequest->getLoadedScript()->HasDiskCacheReference
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!aRequest->getLoadedScript()->HasDiskCacheReference()"
, "./../../../dom/script/ScriptLoader.cpp", 3120); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!aRequest->getLoadedScript()->HasDiskCacheReference()"
")"); do { MOZ_CrashSequence(__null, 3120); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3121 return;
3122 }
3123#endif
3124 } else {
3125 LOG(("ScriptLoadRequest (%p): Bytecode-cache: Skip all: synthetic module",
3126 aRequest));
3127 aRequest->MarkNotCacheable();
3128 MOZ_ASSERT(!aRequest->getLoadedScript()->HasDiskCacheReference())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aRequest->getLoadedScript()->HasDiskCacheReference
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!aRequest->getLoadedScript()->HasDiskCacheReference
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!aRequest->getLoadedScript()->HasDiskCacheReference()"
, "./../../../dom/script/ScriptLoader.cpp", 3128); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!aRequest->getLoadedScript()->HasDiskCacheReference()"
")"); do { MOZ_CrashSequence(__null, 3128); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3129 MOZ_ASSERT_IF(aRequest->IsFetchedAsTextSource(),do { if (aRequest->IsFetchedAsTextSource()) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(aRequest
->HasNoSRIOrSRIAndSerializedStencil())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aRequest->HasNoSRIOrSRIAndSerializedStencil
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aRequest->HasNoSRIOrSRIAndSerializedStencil()", "./../../../dom/script/ScriptLoader.cpp"
, 3130); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aRequest->HasNoSRIOrSRIAndSerializedStencil()"
")"); do { MOZ_CrashSequence(__null, 3130); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3130 aRequest->HasNoSRIOrSRIAndSerializedStencil())do { if (aRequest->IsFetchedAsTextSource()) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(aRequest
->HasNoSRIOrSRIAndSerializedStencil())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aRequest->HasNoSRIOrSRIAndSerializedStencil
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aRequest->HasNoSRIOrSRIAndSerializedStencil()", "./../../../dom/script/ScriptLoader.cpp"
, 3130); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aRequest->HasNoSRIOrSRIAndSerializedStencil()"
")"); do { MOZ_CrashSequence(__null, 3130); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
3131 return;
3132 }
3133 }
3134
3135 MOZ_ASSERT(!aRequest->IsWasmBytes())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aRequest->IsWasmBytes())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aRequest->IsWasmBytes())
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!aRequest->IsWasmBytes()"
, "./../../../dom/script/ScriptLoader.cpp", 3135); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!aRequest->IsWasmBytes()" ")"); do { MOZ_CrashSequence
(__null, 3135); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
3136
3137 if (!aRequest->IsRetrievedFromMemoryCache() &&
3138 aRequest->ExpirationTime().IsExpired()) {
3139 LOG(("ScriptLoadRequest (%p): Bytecode-cache: Skip all: Expired",
3140 aRequest));
3141 // NOTE: The expiration for in-memory-cached case should be handled by
3142 // SharedScriptCache.
3143 aRequest->MarkSkippedAllCaching();
3144 aRequest->getLoadedScript()->DropDiskCacheReferenceAndSRI();
3145 return;
3146 }
3147
3148 if (strcmp(aRequest->URI()->GetSpecOrDefault().get(),
3149 "https://snap.licdn.com/li.lms-analytics/insight.min.js") == 0) {
3150 // See bug 2042605 and
3151 // https://github.com/linkedin/linkedin-gtm-community-template/commit/d6d31ee6f8880ffd8037e4aea7146ccd7cbba27b
3152 //
3153 // There are outdated copies of the above template, which reloads the same
3154 // script infinitely and recursively in the onload event handler for the
3155 // same script.
3156 //
3157 // Applying cache reduces the turnaround time between the next load and the
3158 // onload handler, and especially the in-memory cache makes it immediate
3159 // recursion. As a workaround for this issue, we do not apply any cache
3160 // for this script.
3161 LOG(("ScriptLoadRequest (%p): Bytecode-cache: Skip all: bug 2042605",
3162 aRequest));
3163 aRequest->MarkNotCacheable();
3164 aRequest->getLoadedScript()->DropDiskCacheReferenceAndSRI();
3165 return;
3166 }
3167
3168 if (mCache) {
3169 if (mCache->IsLowMemory()) {
3170 // During the low-memory situation, we avoid creating another cache,
3171 // with the following rationale.
3172 //
3173 // If there are multiple tabs that share single cache entry, the existence
3174 // of the cache effectively reduces the memory consumption, but the
3175 // most common use case is with a single tab, and in that case the cache
3176 // does not reduce the memory consumption but only reduces the cost of
3177 // the calculation across navigation.
3178 LOG(
3179 ("ScriptLoadRequest (%p): Bytecode-cache: Skip in-memory: memory "
3180 "pressure",
3181 aRequest));
3182 aRequest->MarkSkippedMemoryCaching();
3183 } else {
3184 LOG(("ScriptLoadRequest (%p): Bytecode-cache: Mark in-memory: Stencil",
3185 aRequest));
3186 aRequest->MarkPassedConditionForMemoryCache();
3187 }
3188
3189 // Disk cache is handled by SharedScriptCache.
3190 return;
3191 }
3192
3193 aRequest->MarkSkippedMemoryCaching();
3194
3195 // The following conditions apply only to the disk cache.
3196
3197 if (aRequest->IsRetrievedAsSerializedStencil()) {
3198 LOG(
3199 ("ScriptLoadRequest (%p): Bytecode-cache: Skip disk: "
3200 "IsRetrievedAsSerializedStencil",
3201 aRequest));
3202 aRequest->MarkSkippedDiskCaching();
3203 MOZ_ASSERT(!aRequest->getLoadedScript()->HasDiskCacheReference())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aRequest->getLoadedScript()->HasDiskCacheReference
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!aRequest->getLoadedScript()->HasDiskCacheReference
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!aRequest->getLoadedScript()->HasDiskCacheReference()"
, "./../../../dom/script/ScriptLoader.cpp", 3203); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!aRequest->getLoadedScript()->HasDiskCacheReference()"
")"); do { MOZ_CrashSequence(__null, 3203); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3204 return;
3205 }
3206
3207 // We need the nsICacheInfoChannel to exist to be able to open the alternate
3208 // data output stream.
3209 if (!aRequest->getLoadedScript()->HasDiskCacheReference()) {
3210 LOG(
3211 ("ScriptLoadRequest (%p): Bytecode-cache: Skip disk: "
3212 "!LoadedScript::HasDiskCacheReference",
3213 aRequest));
3214 aRequest->MarkSkippedDiskCaching();
3215 MOZ_ASSERT_IF(aRequest->IsFetchedAsTextSource(),do { if (aRequest->IsFetchedAsTextSource()) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(aRequest
->HasNoSRIOrSRIAndSerializedStencil())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aRequest->HasNoSRIOrSRIAndSerializedStencil
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aRequest->HasNoSRIOrSRIAndSerializedStencil()", "./../../../dom/script/ScriptLoader.cpp"
, 3216); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aRequest->HasNoSRIOrSRIAndSerializedStencil()"
")"); do { MOZ_CrashSequence(__null, 3216); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3216 aRequest->HasNoSRIOrSRIAndSerializedStencil())do { if (aRequest->IsFetchedAsTextSource()) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(aRequest
->HasNoSRIOrSRIAndSerializedStencil())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aRequest->HasNoSRIOrSRIAndSerializedStencil
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aRequest->HasNoSRIOrSRIAndSerializedStencil()", "./../../../dom/script/ScriptLoader.cpp"
, 3216); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aRequest->HasNoSRIOrSRIAndSerializedStencil()"
")"); do { MOZ_CrashSequence(__null, 3216); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
3217 return;
3218 }
3219
3220 auto strategy = GetDiskCacheStrategy();
3221
3222 if (strategy.mIsDisabled) {
3223 // Reader mode, keep requesting alternate data but no longer save it.
3224 LOG(
3225 ("ScriptLoadRequest (%p): Bytecode-cache: Skip disk: Disabled by "
3226 "pref.",
3227 aRequest));
3228 aRequest->MarkSkippedDiskCaching();
3229
3230 aRequest->getLoadedScript()->DropDiskCacheReferenceAndSRI();
3231 return;
3232 }
3233
3234 // If the script is too small/large, do not attempt at creating a disk
3235 // cache for this script, as the overhead of parsing it might not be worth the
3236 // effort.
3237 size_t sourceLength;
3238 if (aRequest->IsRetrievedFromMemoryCache()) {
3239 sourceLength = JS::GetScriptSourceLength(aRequest->GetStencil());
3240 } else {
3241 MOZ_ASSERT(aRequest->IsFetchedAsTextSource())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aRequest->IsFetchedAsTextSource())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aRequest->IsFetchedAsTextSource
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aRequest->IsFetchedAsTextSource()", "./../../../dom/script/ScriptLoader.cpp"
, 3241); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aRequest->IsFetchedAsTextSource()"
")"); do { MOZ_CrashSequence(__null, 3241); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3242 sourceLength = aRequest->ReceivedScriptTextLength();
3243 }
3244 if (strategy.mHasSourceLengthMin) {
3245 if (sourceLength < strategy.mSourceLengthMin) {
3246 LOG(
3247 ("ScriptLoadRequest (%p): Bytecode-cache: Skip disk: Script is too "
3248 "small.",
3249 aRequest));
3250 aRequest->MarkSkippedDiskCaching();
3251 aRequest->getLoadedScript()->DropDiskCacheReferenceAndSRI();
3252 return;
3253 }
3254 }
3255
3256 // The disk cache size is limited by the pref, and also the disk capacity.
3257 // Assuming the disk capacity is sufficient, we use the pref to limit the
3258 // maximum size, to avoid processing the too large cache, which will
3259 // ultimately be rejected when saving the cache.
3260 //
3261 // The actual disk cache is the concatenation of the main data and the
3262 // alternate data.
3263 //
3264 // The main data is the JavaScript source transferred over the network,
3265 // which can be compressed, but it's at most sourceLength bytes.
3266 //
3267 // The alternate data is the serialized Stencil, which also contains the
3268 // raw uncompressed JavaScript source in addition to the compiled data.
3269 //
3270 // The serialized Stencil takes ~3.8x size of the source length.
3271 // (gathered from scripts used in the top 50 websites)
3272 size_t expectedDiskCacheSize = sourceLength * 5;
3273 int32_t diskCacheMaxSizeInKb =
3274 StaticPrefs::browser_cache_disk_max_entry_size();
3275 // The pref being -1 means "no limit".
3276 if (diskCacheMaxSizeInKb > 0) {
3277 if (expectedDiskCacheSize > size_t(diskCacheMaxSizeInKb) * 1024) {
3278 LOG(
3279 ("ScriptLoadRequest (%p): Bytecode-cache: Skip disk: Script is too "
3280 "large.",
3281 aRequest));
3282 aRequest->MarkSkippedDiskCaching();
3283 aRequest->getLoadedScript()->DropDiskCacheReferenceAndSRI();
3284 return;
3285 }
3286 }
3287
3288 // Check that we loaded the cache entry a few times before attempting any
3289 // disk cache optimization, such that we do not waste time on entry which
3290 // are going to be dropped soon.
3291 if (strategy.mHasFetchCountMin) {
3292 uint8_t fetchCount = aRequest->mLoadedScript->mFetchCount;
3293 LOG(("ScriptLoadRequest (%p): Bytecode-cache: fetchCount = %d.", aRequest,
3294 fetchCount));
3295 if (fetchCount < strategy.mFetchCountMin) {
3296 LOG(("ScriptLoadRequest (%p): Bytecode-cache: Skip disk: fetchCount",
3297 aRequest));
3298 aRequest->MarkSkippedDiskCaching();
3299
3300 if (!mCache) {
3301 // If in-memory cache is not enabled, the disk cache reference
3302 // and the SRI data is necessary only when the current request
3303 // reaches the minimum fetch count. And they can be discarded here
3304 // if the fetch count is less than the minimum.
3305 //
3306 // If in-memory cache is enabled, the disk cache reference and the
3307 // SRI data is cached with the LoadedScript, and the LoadedScript
3308 // is reused by the subsequent requests, and the fetch count
3309 // can reach the minimum later. We need to keep the disk cache
3310 // reference and the SRI data until then.
3311 aRequest->getLoadedScript()->DropDiskCacheReferenceAndSRI();
3312 }
3313 return;
3314 }
3315 }
3316
3317 LOG(("ScriptLoadRequest (%p): Bytecode-cache: Mark disk: Passed condition",
3318 aRequest));
3319 aRequest->MarkPassedConditionForDiskCache();
3320
3321 if (aRequest->IsModuleRequest() &&
3322 aRequest->AsModuleRequest()->IsStaticImport()) {
3323 MOZ_ASSERT(!aRequest->isInList())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aRequest->isInList())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aRequest->isInList()))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("!aRequest->isInList()"
, "./../../../dom/script/ScriptLoader.cpp", 3323); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!aRequest->isInList()" ")"); do { MOZ_CrashSequence
(__null, 3323); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
3324 mDiskCacheableDependencyModules.AppendElement(aRequest);
3325 }
3326}
3327
3328class MOZ_RAII AutoSetProcessingScriptTag {
3329 nsCOMPtr<nsIScriptContext> mContext;
3330 bool mOldTag;
3331
3332 public:
3333 explicit AutoSetProcessingScriptTag(nsIScriptContext* aContext)
3334 : mContext(aContext), mOldTag(mContext->GetProcessingScriptTag()) {
3335 mContext->SetProcessingScriptTag(true);
3336 }
3337
3338 ~AutoSetProcessingScriptTag() { mContext->SetProcessingScriptTag(mOldTag); }
3339};
3340
3341static void ExecuteCompiledScript(JSContext* aCx, JS::Handle<JSScript*> aScript,
3342 ErrorResult& aRv) {
3343 if (!aScript) {
3344 // Compilation succeeds without producing a script if scripting is
3345 // disabled for the global.
3346 return;
3347 }
3348
3349 if (!JS_ExecuteScript(aCx, aScript)) {
3350 aRv.NoteJSContextException(aCx);
3351 }
3352}
3353
3354// https://html.spec.whatwg.org/#execute-the-script-element
3355nsresult ScriptLoader::EvaluateScriptElement(ScriptLoadRequest* aRequest) {
3356 MOZ_ASSERT(aRequest->IsFinished())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aRequest->IsFinished())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aRequest->IsFinished())))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("aRequest->IsFinished()"
, "./../../../dom/script/ScriptLoader.cpp", 3356); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aRequest->IsFinished()" ")"); do { MOZ_CrashSequence
(__null, 3356); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
3357 MOZ_ASSERT(mDocument)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mDocument)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mDocument))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mDocument", "./../../../dom/script/ScriptLoader.cpp"
, 3357); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mDocument" ")"
); do { MOZ_CrashSequence(__null, 3357); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3358
3359 // The window may have gone away by this point, in which case there's no point
3360 // in trying to run the script.
3361 if (!mDocument->GetInnerWindow()) {
3362 return NS_OK;
3363 }
3364
3365 // 2. If el's preparation-time document is not equal to document, then return.
3366 Document* ownerDoc =
3367 aRequest->GetScriptLoadContext()->GetScriptOwnerDocument();
3368 if (ownerDoc != mDocument) {
3369 return NS_ERROR_FAILURE;
3370 }
3371
3372 nsCOMPtr<nsIGlobalObject> globalObject;
3373 nsCOMPtr<nsIScriptContext> context;
3374 if (!IsWebExtensionRequest(aRequest)) {
3375 // Otherwise we have to ensure that there is a nsIScriptContext.
3376 nsCOMPtr<nsIScriptGlobalObject> scriptGlobal = GetScriptGlobalObject();
3377 if (!scriptGlobal) {
3378 return NS_ERROR_FAILURE;
3379 }
3380
3381 MOZ_ASSERT_IF(do { if (aRequest->IsModuleRequest()) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(aRequest
->AsModuleRequest()->GetGlobalObject() == scriptGlobal)
>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aRequest->AsModuleRequest()->GetGlobalObject()
== scriptGlobal))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aRequest->AsModuleRequest()->GetGlobalObject() == scriptGlobal"
, "./../../../dom/script/ScriptLoader.cpp", 3383); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aRequest->AsModuleRequest()->GetGlobalObject() == scriptGlobal"
")"); do { MOZ_CrashSequence(__null, 3383); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3382 aRequest->IsModuleRequest(),do { if (aRequest->IsModuleRequest()) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(aRequest
->AsModuleRequest()->GetGlobalObject() == scriptGlobal)
>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aRequest->AsModuleRequest()->GetGlobalObject()
== scriptGlobal))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aRequest->AsModuleRequest()->GetGlobalObject() == scriptGlobal"
, "./../../../dom/script/ScriptLoader.cpp", 3383); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aRequest->AsModuleRequest()->GetGlobalObject() == scriptGlobal"
")"); do { MOZ_CrashSequence(__null, 3383); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3383 aRequest->AsModuleRequest()->GetGlobalObject() == scriptGlobal)do { if (aRequest->IsModuleRequest()) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(aRequest
->AsModuleRequest()->GetGlobalObject() == scriptGlobal)
>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aRequest->AsModuleRequest()->GetGlobalObject()
== scriptGlobal))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aRequest->AsModuleRequest()->GetGlobalObject() == scriptGlobal"
, "./../../../dom/script/ScriptLoader.cpp", 3383); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aRequest->AsModuleRequest()->GetGlobalObject() == scriptGlobal"
")"); do { MOZ_CrashSequence(__null, 3383); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
3384
3385 // Make sure context is a strong reference since we access it after
3386 // we've executed a script, which may cause all other references to
3387 // the context to go away.
3388 context = scriptGlobal->GetScriptContext();
3389 if (!context) {
3390 return NS_ERROR_FAILURE;
3391 }
3392
3393 globalObject = scriptGlobal;
3394 }
3395
3396 // 5. If el's from an external file is true, or el's type is "module", then
3397 // increment document's ignore-destructive-writes counter.
3398 const bool ignoreDestructiveWrites =
3399 !aRequest->GetScriptLoadContext()->mIsInline ||
3400 aRequest->IsModuleRequest();
3401 if (ignoreDestructiveWrites) {
3402 if (mDocument) {
3403 mDocument->IncrementIgnoreDestructiveWritesCounter();
3404 }
3405 }
3406
3407 auto afterScript = MakeScopeExit([&] {
3408 if (mContinueParsingDocumentAfterCurrentScript) {
3409 // This mechanism is currently only used when the parser returns
3410 // early due to this script loader having a current script. However,
3411 // now that we have this, we could migrate continuing after a
3412 // parser-blocking script to this same mechanism. Not doing it right
3413 // away to reduce risk of introducing bugs.
3414 mContinueParsingDocumentAfterCurrentScript = false;
3415 if (mDocument) {
3416 nsCOMPtr<nsIParser> parser = mDocument->CreatorParserOrNull();
3417 if (parser) {
3418 parser->ContinueInterruptedParsingAsync();
3419 }
3420 }
3421 }
3422 // 7. Decrement the ignore-destructive-writes counter of document, if it was
3423 // incremented in the earlier step.
3424 if (ignoreDestructiveWrites) {
3425 if (mDocument) {
3426 mDocument->DecrementIgnoreDestructiveWritesCounter();
3427 }
3428 }
3429 });
3430
3431 // Update our current script.
3432 // This must be destroyed after destroying nsAutoMicroTask, see:
3433 // https://bugzilla.mozilla.org/show_bug.cgi?id=1620505#c4
3434 nsIScriptElement* currentScript =
3435 aRequest->IsModuleRequest() ? nullptr
3436 : aRequest->GetScriptLoadContext()
3437 ->GetScriptElementForCurrentScript();
3438 AutoCurrentScriptUpdater scriptUpdater(this, currentScript);
3439
3440 Maybe<AutoSetProcessingScriptTag> setProcessingScriptTag;
3441 if (context) {
3442 setProcessingScriptTag.emplace(context);
3443 }
3444
3445 // https://wicg.github.io/import-maps/#integration-script-type
3446 // Switch on the script's type for scriptElement:
3447 // "importmap"
3448 // Assert: Never reached.
3449 MOZ_ASSERT(!aRequest->IsImportMapRequest())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aRequest->IsImportMapRequest())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aRequest->IsImportMapRequest
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!aRequest->IsImportMapRequest()", "./../../../dom/script/ScriptLoader.cpp"
, 3449); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aRequest->IsImportMapRequest()"
")"); do { MOZ_CrashSequence(__null, 3449); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3450
3451 auto start = TimeStamp::Now();
3452
3453 nsresult rv;
3454 if (aRequest->IsModuleRequest()) {
3455 rv = aRequest->AsModuleRequest()->EvaluateModule();
3456 } else {
3457 MOZ_ASSERT(!aRequest->IsWasmBytes())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aRequest->IsWasmBytes())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aRequest->IsWasmBytes())
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!aRequest->IsWasmBytes()"
, "./../../../dom/script/ScriptLoader.cpp", 3457); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!aRequest->IsWasmBytes()" ")"); do { MOZ_CrashSequence
(__null, 3457); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
3458 rv = EvaluateScript(globalObject, aRequest);
3459 }
3460
3461 auto end = TimeStamp::Now();
3462 auto duration = (end - start).ToMilliseconds();
3463
3464 static constexpr double LongScriptThresholdInMilliseconds = 1.0;
3465 if (duration > LongScriptThresholdInMilliseconds) {
3466 aRequest->SetTookLongInPreviousRuns();
3467 }
3468
3469 return rv;
3470}
3471
3472// Decode a script contained in a buffer.
3473void ScriptLoader::Decode(JSContext* aCx, JS::CompileOptions& aCompileOptions,
3474 const JS::TranscodeRange& aRange,
3475 RefPtr<JS::Stencil>& aStencil, ErrorResult& aRv) {
3476 JS::DecodeOptions decodeOptions(aCompileOptions);
3477 if (!mCache) {
3478 decodeOptions.borrowBuffer = true;
3479 }
3480
3481 MOZ_ASSERT(aCompileOptions.noScriptRval)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aCompileOptions.noScriptRval)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aCompileOptions.noScriptRval
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"aCompileOptions.noScriptRval", "./../../../dom/script/ScriptLoader.cpp"
, 3481); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aCompileOptions.noScriptRval"
")"); do { MOZ_CrashSequence(__null, 3481); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3482 JS::TranscodeResult tr =
3483 JS::DecodeStencil(aCx, decodeOptions, aRange, getter_AddRefs(aStencil));
3484 // These errors are external parameters which should be handled before the
3485 // decoding phase, and which are the only reasons why you might want to
3486 // fallback on decoding failures.
3487 MOZ_ASSERT(tr != JS::TranscodeResult::Failure_BadBuildId)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(tr != JS::TranscodeResult::Failure_BadBuildId)>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(tr != JS::TranscodeResult::Failure_BadBuildId))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("tr != JS::TranscodeResult::Failure_BadBuildId"
, "./../../../dom/script/ScriptLoader.cpp", 3487); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "tr != JS::TranscodeResult::Failure_BadBuildId"
")"); do { MOZ_CrashSequence(__null, 3487); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3488 if (tr != JS::TranscodeResult::Ok) {
3489 aRv = NS_ERROR_DOM_JS_DECODING_ERROR;
3490 return;
3491 }
3492}
3493
3494bool ScriptLoader::StartCollectingDelazifications(JSContext* aCx,
3495 JS::Handle<JSScript*> aScript,
3496 JS::Stencil* aStencil) {
3497 JS::CollectDelazificationsResult result;
3498 if (!JS::StartCollectingDelazifications(aCx, aScript, aStencil, result)) {
3499 return false;
3500 }
3501 if (result == JS::CollectDelazificationsResult::NewlyStarted) {
3502 AppendDelazificationCollection(aScript);
3503 }
3504 return true;
3505}
3506
3507bool ScriptLoader::StartCollectingDelazifications(JSContext* aCx,
3508 JS::Handle<JSObject*> aModule,
3509 JS::Stencil* aStencil) {
3510 JS::CollectDelazificationsResult result;
3511 if (!JS::StartCollectingDelazifications(aCx, aModule, aStencil, result)) {
3512 return false;
3513 }
3514 if (result == JS::CollectDelazificationsResult::NewlyStarted) {
3515 AppendDelazificationCollection(aModule);
3516 }
3517 return true;
3518}
3519
3520void ScriptLoader::AppendDelazificationCollection(
3521 JS::Handle<JSScript*> aScript) {
3522 if (mDelazificationCollectingScripts.IsEmpty() &&
3523 mDelazificationCollectingModules.IsEmpty()) {
3524 mozilla::HoldJSObjects(this);
3525 }
3526 mDelazificationCollectingScripts.AppendElement(aScript);
3527}
3528
3529void ScriptLoader::AppendDelazificationCollection(
3530 JS::Handle<JSObject*> aModule) {
3531 if (mDelazificationCollectingScripts.IsEmpty() &&
3532 mDelazificationCollectingModules.IsEmpty()) {
3533 mozilla::HoldJSObjects(this);
3534 }
3535 mDelazificationCollectingModules.AppendElement(aModule);
3536}
3537
3538// Instantiate (on main-thread) a JS::Stencil generated by off-thread or
3539// main-thread parsing or decoding.
3540void ScriptLoader::InstantiateStencil(
3541 JSContext* aCx, JS::CompileOptions& aCompileOptions, JS::Stencil* aStencil,
3542 JS::MutableHandle<JSScript*> aScript,
3543 JS::Handle<JSScript*> aDebuggerIntroductionScript, ErrorResult& aRv,
3544 const nsAutoCString& aProfilerLabelString,
3545 JS::InstantiationStorage* aStorage /* = nullptr */,
3546 CollectDelazifications aCollectDelazifications
3547 /* = CollectDelazifications::No */) {
3548 AUTO_PROFILER_MARKER_TEXT("ScriptInstantiation", JS,AutoProfilerTextMarker raiiObject3550( "ScriptInstantiation",
::mozilla::baseprofiler::category::JS, MarkerInnerWindowIdFromJSContext
(aCx), aProfilerLabelString)
3549 MarkerInnerWindowIdFromJSContext(aCx),AutoProfilerTextMarker raiiObject3550( "ScriptInstantiation",
::mozilla::baseprofiler::category::JS, MarkerInnerWindowIdFromJSContext
(aCx), aProfilerLabelString)
3550 aProfilerLabelString)AutoProfilerTextMarker raiiObject3550( "ScriptInstantiation",
::mozilla::baseprofiler::category::JS, MarkerInnerWindowIdFromJSContext
(aCx), aProfilerLabelString)
;
3551
3552 JS::InstantiateOptions instantiateOptions(aCompileOptions);
3553 JS::Rooted<JSScript*> script(
3554 aCx, JS::InstantiateGlobalStencil(aCx, instantiateOptions, aStencil,
3555 aStorage));
3556 if (!script) {
3557 aRv.NoteJSContextException(aCx);
3558 return;
3559 }
3560
3561 if (aCollectDelazifications == CollectDelazifications::Yes) {
3562 if (!StartCollectingDelazifications(aCx, script, aStencil)) {
3563 aRv.NoteJSContextException(aCx);
3564 return;
3565 }
3566 }
3567
3568 aScript.set(script);
3569
3570 if (instantiateOptions.deferDebugMetadata) {
3571 // The private value is updated by the
3572 // ScriptFetchInfo::AssociateWithScript call done after
3573 // InstantiateClassicScriptFromAny in ScriptLoader::EvaluateScript.
3574 JS::Rooted<JS::Value> unused(aCx);
3575 if (!JS::UpdateDebugMetadata(aCx, aScript, instantiateOptions, unused,
3576 nullptr, aDebuggerIntroductionScript,
3577 nullptr)) {
3578 aRv = NS_ERROR_OUT_OF_MEMORY;
3579 }
3580 }
3581}
3582
3583void ScriptLoader::InstantiateClassicScriptFromMaybeEncodedSource(
3584 JSContext* aCx, JS::CompileOptions& aCompileOptions,
3585 ScriptLoadRequest* aRequest, JS::MutableHandle<JSScript*> aScript,
3586 JS::Handle<JSScript*> aDebuggerIntroductionScript, ErrorResult& aRv) {
3587 MOZ_ASSERT(!aRequest->IsWasmBytes())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aRequest->IsWasmBytes())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aRequest->IsWasmBytes())
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!aRequest->IsWasmBytes()"
, "./../../../dom/script/ScriptLoader.cpp", 3587); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!aRequest->IsWasmBytes()" ")"); do { MOZ_CrashSequence
(__null, 3587); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
3588 nsAutoCString profilerLabelString;
3589 aRequest->GetScriptLoadContext()->GetProfilerLabel(profilerLabelString);
3590
3591 CalculateCacheFlag(aRequest);
3592
3593 if (aRequest->IsRetrievedAsSerializedStencil()) {
3594 if (aRequest->GetScriptLoadContext()->mCompileOrDecodeTask) {
3595 LOG(("ScriptLoadRequest (%p): Decode & instantiate and Execute",
3596 aRequest));
3597 RefPtr<JS::Stencil> stencil;
3598 JS::InstantiationStorage storage;
3599 MOZ_ASSERT(aCompileOptions.noScriptRval)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aCompileOptions.noScriptRval)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aCompileOptions.noScriptRval
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"aCompileOptions.noScriptRval", "./../../../dom/script/ScriptLoader.cpp"
, 3599); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aCompileOptions.noScriptRval"
")"); do { MOZ_CrashSequence(__null, 3599); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3600 stencil =
3601 aRequest->GetScriptLoadContext()->StealOffThreadResult(aCx, &storage);
3602 if (!stencil) {
3603 aRv.NoteJSContextException(aCx);
3604 return;
3605 }
3606
3607 aRequest->SetStencil(stencil);
3608
3609 InstantiateStencil(aCx, aCompileOptions, stencil, aScript,
3610 aDebuggerIntroductionScript, aRv, profilerLabelString,
3611 &storage);
3612 } else {
3613 LOG(("ScriptLoadRequest (%p): Decode and Execute", aRequest));
3614
3615 RefPtr<JS::Stencil> stencil;
3616 {
3617 AUTO_PROFILER_MARKER_TEXT("DecodeStencilMainThread", JS,AutoProfilerTextMarker raiiObject3619( "DecodeStencilMainThread"
, ::mozilla::baseprofiler::category::JS, MarkerInnerWindowIdFromJSContext
(aCx), profilerLabelString)
3618 MarkerInnerWindowIdFromJSContext(aCx),AutoProfilerTextMarker raiiObject3619( "DecodeStencilMainThread"
, ::mozilla::baseprofiler::category::JS, MarkerInnerWindowIdFromJSContext
(aCx), profilerLabelString)
3619 profilerLabelString)AutoProfilerTextMarker raiiObject3619( "DecodeStencilMainThread"
, ::mozilla::baseprofiler::category::JS, MarkerInnerWindowIdFromJSContext
(aCx), profilerLabelString)
;
3620 Decode(aCx, aCompileOptions, aRequest->SerializedStencil(), stencil,
3621 aRv);
3622 }
3623
3624 if (stencil) {
3625 aRequest->SetStencil(stencil);
3626
3627 InstantiateStencil(aCx, aCompileOptions, stencil, aScript,
3628 aDebuggerIntroductionScript, aRv,
3629 profilerLabelString);
3630 }
3631 }
3632
3633 // We do not expect to be saving anything when we already have some
3634 // serialized Stencil.
3635 MOZ_ASSERT(!aRequest->getLoadedScript()->HasDiskCacheReference())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aRequest->getLoadedScript()->HasDiskCacheReference
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!aRequest->getLoadedScript()->HasDiskCacheReference
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!aRequest->getLoadedScript()->HasDiskCacheReference()"
, "./../../../dom/script/ScriptLoader.cpp", 3635); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!aRequest->getLoadedScript()->HasDiskCacheReference()"
")"); do { MOZ_CrashSequence(__null, 3635); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3636 return;
3637 }
3638
3639 MOZ_ASSERT(aRequest->IsFetchedAsTextSource())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aRequest->IsFetchedAsTextSource())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aRequest->IsFetchedAsTextSource
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aRequest->IsFetchedAsTextSource()", "./../../../dom/script/ScriptLoader.cpp"
, 3639); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aRequest->IsFetchedAsTextSource()"
")"); do { MOZ_CrashSequence(__null, 3639); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3640 CollectDelazifications collectDelazifications =
3641 aRequest->PassedConditionForEitherCache() ? CollectDelazifications::Yes
3642 : CollectDelazifications::No;
3643
3644 if (aRequest->GetScriptLoadContext()->mCompileOrDecodeTask) {
3645 // Off-main-thread parsing.
3646 LOG(
3647 ("ScriptLoadRequest (%p): instantiate off-thread result and "
3648 "Execute",
3649 aRequest));
3650 MOZ_ASSERT(aRequest->IsFetchedAsTextSource())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aRequest->IsFetchedAsTextSource())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aRequest->IsFetchedAsTextSource
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aRequest->IsFetchedAsTextSource()", "./../../../dom/script/ScriptLoader.cpp"
, 3650); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aRequest->IsFetchedAsTextSource()"
")"); do { MOZ_CrashSequence(__null, 3650); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3651 RefPtr<JS::Stencil> stencil;
3652 JS::InstantiationStorage storage;
3653 MOZ_ASSERT(aCompileOptions.noScriptRval)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aCompileOptions.noScriptRval)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aCompileOptions.noScriptRval
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"aCompileOptions.noScriptRval", "./../../../dom/script/ScriptLoader.cpp"
, 3653); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aCompileOptions.noScriptRval"
")"); do { MOZ_CrashSequence(__null, 3653); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3654 stencil =
3655 aRequest->GetScriptLoadContext()->StealOffThreadResult(aCx, &storage);
3656 if (!stencil) {
3657 aRv.NoteJSContextException(aCx);
3658 return;
3659 }
3660
3661 aRequest->SetStencil(stencil);
3662
3663 InstantiateStencil(aCx, aCompileOptions, stencil, aScript,
3664 aDebuggerIntroductionScript, aRv, profilerLabelString,
3665 &storage, collectDelazifications);
3666 } else {
3667 // Main thread parsing (inline and small scripts)
3668 LOG(("ScriptLoadRequest (%p): Compile And Exec", aRequest));
3669 MOZ_ASSERT(aRequest->IsFetchedAsTextSource())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aRequest->IsFetchedAsTextSource())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aRequest->IsFetchedAsTextSource
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aRequest->IsFetchedAsTextSource()", "./../../../dom/script/ScriptLoader.cpp"
, 3669); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aRequest->IsFetchedAsTextSource()"
")"); do { MOZ_CrashSequence(__null, 3669); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3670 MaybeSourceText maybeSource;
3671 aRv = aRequest->GetScriptSource(aCx, &maybeSource,
3672 aRequest->mLoadContext.get());
3673 if (!aRv.Failed()) {
3674 RefPtr<JS::Stencil> stencil;
3675 ErrorResult erv;
3676 auto compile = [&](auto& source) {
3677 AUTO_PROFILER_MARKER_TEXT("ScriptCompileMainThread", JS,AutoProfilerTextMarker raiiObject3679( "ScriptCompileMainThread"
, ::mozilla::baseprofiler::category::JS, MarkerInnerWindowIdFromJSContext
(aCx), profilerLabelString)
3678 MarkerInnerWindowIdFromJSContext(aCx),AutoProfilerTextMarker raiiObject3679( "ScriptCompileMainThread"
, ::mozilla::baseprofiler::category::JS, MarkerInnerWindowIdFromJSContext
(aCx), profilerLabelString)
3679 profilerLabelString)AutoProfilerTextMarker raiiObject3679( "ScriptCompileMainThread"
, ::mozilla::baseprofiler::category::JS, MarkerInnerWindowIdFromJSContext
(aCx), profilerLabelString)
;
3680
3681 stencil = CompileGlobalScriptToStencil(aCx, aCompileOptions, source);
3682 if (!stencil) {
3683 erv.NoteJSContextException(aCx);
3684 }
3685 };
3686
3687 MOZ_ASSERT(!maybeSource.empty())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!maybeSource.empty())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!maybeSource.empty()))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("!maybeSource.empty()"
, "./../../../dom/script/ScriptLoader.cpp", 3687); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!maybeSource.empty()" ")"); do { MOZ_CrashSequence
(__null, 3687); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
3688 maybeSource.mapNonEmpty(compile);
3689
3690 if (stencil) {
3691 aRequest->SetStencil(stencil);
3692
3693 InstantiateStencil(aCx, aCompileOptions, stencil, aScript,
3694 aDebuggerIntroductionScript, erv,
3695 profilerLabelString, /* aStorage = */ nullptr,
3696 collectDelazifications);
3697 }
3698
3699 aRv = std::move(erv);
3700 }
3701 }
3702}
3703
3704void ScriptLoader::InstantiateClassicScriptFromCachedStencil(
3705 JSContext* aCx, JS::CompileOptions& aCompileOptions,
3706 ScriptLoadRequest* aRequest, JS::Stencil* aStencil,
3707 JS::MutableHandle<JSScript*> aScript,
3708 JS::Handle<JSScript*> aDebuggerIntroductionScript, ErrorResult& aRv) {
3709 MOZ_ASSERT(!aRequest->IsWasmBytes())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aRequest->IsWasmBytes())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aRequest->IsWasmBytes())
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!aRequest->IsWasmBytes()"
, "./../../../dom/script/ScriptLoader.cpp", 3709); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!aRequest->IsWasmBytes()" ")"); do { MOZ_CrashSequence
(__null, 3709); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
3710 nsAutoCString profilerLabelString;
3711 aRequest->GetScriptLoadContext()->GetProfilerLabel(profilerLabelString);
3712
3713 CalculateCacheFlag(aRequest);
3714
3715 MOZ_ASSERT(aRequest->PassedConditionForMemoryCache())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aRequest->PassedConditionForMemoryCache())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(aRequest->PassedConditionForMemoryCache()))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("aRequest->PassedConditionForMemoryCache()"
, "./../../../dom/script/ScriptLoader.cpp", 3715); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aRequest->PassedConditionForMemoryCache()"
")"); do { MOZ_CrashSequence(__null, 3715); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3716
3717 // For cached stencils, there can be already ongoing work for the in-memory
3718 // cache and the disk cache.
3719 //
3720 // For collecting delazifications, it's detected by
3721 // JS::StartCollectingDelazifications API and it's not a problem.
3722 //
3723 // For disk cache, ScriptLoader::UpdateDiskCache checks the
3724 // HasDiskCacheReference condition, and that filters out any loaded scripts
3725 // queued multiple times.
3726 InstantiateStencil(aCx, aCompileOptions, aStencil, aScript,
3727 aDebuggerIntroductionScript, aRv, profilerLabelString,
3728 /* aStorage = */ nullptr, CollectDelazifications::Yes);
3729}
3730
3731void ScriptLoader::InstantiateClassicScriptFromAny(
3732 JSContext* aCx, JS::CompileOptions& aCompileOptions,
3733 ScriptLoadRequest* aRequest, JS::MutableHandle<JSScript*> aScript,
3734 JS::Handle<JSScript*> aDebuggerIntroductionScript, ErrorResult& aRv) {
3735 MOZ_ASSERT(!aRequest->IsWasmBytes())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aRequest->IsWasmBytes())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aRequest->IsWasmBytes())
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!aRequest->IsWasmBytes()"
, "./../../../dom/script/ScriptLoader.cpp", 3735); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!aRequest->IsWasmBytes()" ")"); do { MOZ_CrashSequence
(__null, 3735); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
3736 if (aRequest->IsRetrievedFromMemoryCache()) {
3737 RefPtr<JS::Stencil> stencil = aRequest->GetStencil();
3738 InstantiateClassicScriptFromCachedStencil(aCx, aCompileOptions, aRequest,
3739 stencil, aScript,
3740 aDebuggerIntroductionScript, aRv);
3741 return;
3742 }
3743
3744 InstantiateClassicScriptFromMaybeEncodedSource(
3745 aCx, aCompileOptions, aRequest, aScript, aDebuggerIntroductionScript,
3746 aRv);
3747 if (aRv.Failed()) {
3748 return;
3749 }
3750
3751 TryCacheRequest(aRequest);
3752}
3753
3754ScriptLoader::CacheBehavior ScriptLoader::GetCacheBehavior(
3755 ScriptLoadRequest* aRequest) {
3756 if (!mCache) {
3757 return CacheBehavior::DoNothingDisabled;
3758 }
3759
3760 if (aRequest->ExpirationTime().IsExpired()) {
3761 return CacheBehavior::Evict;
3762 }
3763
3764 // NOTE: A new response may arrive even if the exiting cache is still valid,
3765 // for example when the request is performed with bypassing the cache.
3766 //
3767 // If the response is cacheable, it should overwrite the existing cache
3768 // if any. If the response is not cacheable, that should just evict the
3769 // existing cache if any, so that the next request will also reach the
3770 // server.
3771 if (ShouldBypassCache()) {
3772 // If the request bypasses the cache, the response should always
3773 // overwrite the cache, regardless of the content.
3774 return CacheBehavior::Insert;
3775 }
3776
3777 ScriptHashKey key(this, aRequest, aRequest->ReferrerPolicy(),
3778 aRequest->FetchOptions(),
3779 aRequest->getLoadedScript()->GetURI());
3780 auto cacheResult = mCache->Lookup(*this, key,
3781 /* aSyncLoad = */ true);
3782 MOZ_ASSERT_IF(cacheResult.mState == CachedSubResourceState::Complete,do { if (cacheResult.mState == CachedSubResourceState::Complete
) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(cacheResult.mCompleteValue->IsCachedStencil()
|| cacheResult.mCompleteValue->IsInvalidatedCachedStencil
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(cacheResult.mCompleteValue->IsCachedStencil() || cacheResult
.mCompleteValue->IsInvalidatedCachedStencil()))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("cacheResult.mCompleteValue->IsCachedStencil() || cacheResult.mCompleteValue->IsInvalidatedCachedStencil()"
, "./../../../dom/script/ScriptLoader.cpp", 3784); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "cacheResult.mCompleteValue->IsCachedStencil() || cacheResult.mCompleteValue->IsInvalidatedCachedStencil()"
")"); do { MOZ_CrashSequence(__null, 3784); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3783 cacheResult.mCompleteValue->IsCachedStencil() ||do { if (cacheResult.mState == CachedSubResourceState::Complete
) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(cacheResult.mCompleteValue->IsCachedStencil()
|| cacheResult.mCompleteValue->IsInvalidatedCachedStencil
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(cacheResult.mCompleteValue->IsCachedStencil() || cacheResult
.mCompleteValue->IsInvalidatedCachedStencil()))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("cacheResult.mCompleteValue->IsCachedStencil() || cacheResult.mCompleteValue->IsInvalidatedCachedStencil()"
, "./../../../dom/script/ScriptLoader.cpp", 3784); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "cacheResult.mCompleteValue->IsCachedStencil() || cacheResult.mCompleteValue->IsInvalidatedCachedStencil()"
")"); do { MOZ_CrashSequence(__null, 3784); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3784 cacheResult.mCompleteValue->IsInvalidatedCachedStencil())do { if (cacheResult.mState == CachedSubResourceState::Complete
) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(cacheResult.mCompleteValue->IsCachedStencil()
|| cacheResult.mCompleteValue->IsInvalidatedCachedStencil
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(cacheResult.mCompleteValue->IsCachedStencil() || cacheResult
.mCompleteValue->IsInvalidatedCachedStencil()))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("cacheResult.mCompleteValue->IsCachedStencil() || cacheResult.mCompleteValue->IsInvalidatedCachedStencil()"
, "./../../../dom/script/ScriptLoader.cpp", 3784); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "cacheResult.mCompleteValue->IsCachedStencil() || cacheResult.mCompleteValue->IsInvalidatedCachedStencil()"
")"); do { MOZ_CrashSequence(__null, 3784); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
3785 if (cacheResult.mState == CachedSubResourceState::Complete &&
3786 cacheResult.mCompleteValue->IsCachedStencil()) {
3787 if (!cacheResult.mCompleteValue->IsSRIMetadataReusableBy(
3788 aRequest->mIntegrity)) {
3789 mCache->Evict(key);
3790 return CacheBehavior::Insert;
3791 }
3792
3793 return CacheBehavior::DoNothingExisting;
3794 }
3795
3796 return CacheBehavior::Insert;
3797}
3798
3799void ScriptLoader::TryCacheRequest(ScriptLoadRequest* aRequest) {
3800 MOZ_ASSERT(aRequest->HasStencil())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aRequest->HasStencil())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aRequest->HasStencil())))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("aRequest->HasStencil()"
, "./../../../dom/script/ScriptLoader.cpp", 3800); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aRequest->HasStencil()" ")"); do { MOZ_CrashSequence
(__null, 3800); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
3801 MOZ_ASSERT(!aRequest->IsWasmBytes())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aRequest->IsWasmBytes())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aRequest->IsWasmBytes())
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!aRequest->IsWasmBytes()"
, "./../../../dom/script/ScriptLoader.cpp", 3801); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!aRequest->IsWasmBytes()" ")"); do { MOZ_CrashSequence
(__null, 3801); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
3802
3803 if (aRequest->IsMarkedNotCacheable()) {
3804 aRequest->ClearStencil();
3805 return;
3806 }
3807
3808 CacheBehavior cacheBehavior = GetCacheBehavior(aRequest);
3809
3810 if (cacheBehavior == CacheBehavior::DoNothingDisabled) {
3811 // If the in-memory cache is not enabled, the disk cache is handled by
3812 // ScriptLoader, and it needs the stencil if this script is going to be
3813 // saved to the disk cache.
3814 if (!aRequest->PassedConditionForDiskCache()) {
3815 aRequest->ClearStencil();
3816 }
3817 return;
3818 }
3819
3820 if (cacheBehavior == CacheBehavior::DoNothingExisting) {
3821 // If there's a compatible cache entry, we'll keep the existing entry.
3822 aRequest->ClearStencil();
3823 return;
3824 }
3825
3826 MOZ_ASSERT(mCache)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mCache)>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(mCache))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mCache", "./../../../dom/script/ScriptLoader.cpp"
, 3826); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mCache" ")"
); do { MOZ_CrashSequence(__null, 3826); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3827
3828 if (mCache->IsLowMemory()) {
3829 // If we're in the low-memory situation, do not create new cache entries.
3830 TRACE_FOR_TEST(aRequest, "memorycache:memorypressure")do { mozilla::dom::script::TestingNotifyObserver(aRequest, "memorycache:memorypressure"
); } while (0)
;
3831 aRequest->ClearStencil();
3832 return;
3833 }
3834
3835 if (!JS::IsStencilCacheable(aRequest->GetStencil())) {
3836 // If the stencil is not compatible with the cache, this should also evict
3837 // any existing cache.
3838 cacheBehavior = CacheBehavior::Evict;
3839 }
3840
3841 if (cacheBehavior == CacheBehavior::Insert) {
3842 LoadedScript* loadedScript = aRequest->getLoadedScript();
3843 CacheExpirationTime expirationTime = aRequest->ExpirationTime();
3844 loadedScript->ConvertToCachedStencil(aRequest->GetStencil(),
3845 aRequest->ReferrerPolicy(),
3846 aRequest->BaseURL());
3847 if (loadedScript->mFetchCount == 0) {
3848 loadedScript->mFetchCount = 1;
3849 }
3850 loadedScript->SetSRIMetadata(aRequest->mIntegrity);
3851 auto loadData = MakeRefPtr<ScriptLoadData>(this, aRequest, expirationTime,
3852 loadedScript);
3853 mCache->Insert(*loadData);
3854 mCache->OnEntryInserted();
3855 LOG(("ScriptLoader (%p): Inserting in-memory cache for %s.", this,
3856 aRequest->URI()->GetSpecOrDefault().get()));
3857 TRACE_FOR_TEST(aRequest, "memorycache:saved")do { mozilla::dom::script::TestingNotifyObserver(aRequest, "memorycache:saved"
); } while (0)
;
3858 } else {
3859 // The server response is not cacheable.
3860 // Evict any existing cache.
3861
3862 MOZ_ASSERT(cacheBehavior == CacheBehavior::Evict)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(cacheBehavior == CacheBehavior::Evict)>::isValid,
"invalid assertion condition"); if ((__builtin_expect(!!(!(!
!(cacheBehavior == CacheBehavior::Evict))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("cacheBehavior == CacheBehavior::Evict"
, "./../../../dom/script/ScriptLoader.cpp", 3862); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "cacheBehavior == CacheBehavior::Evict" ")"
); do { MOZ_CrashSequence(__null, 3862); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3863 ScriptHashKey key(this, aRequest, aRequest->ReferrerPolicy(),
3864 aRequest->FetchOptions(), aRequest->URI());
3865 mCache->Evict(key);
3866 LOG(("ScriptLoader (%p): Evicting in-memory cache for %s.", this,
3867 aRequest->URI()->GetSpecOrDefault().get()));
3868
3869 TRACE_FOR_TEST(aRequest, "memorycache:evict")do { mozilla::dom::script::TestingNotifyObserver(aRequest, "memorycache:evict"
); } while (0)
;
3870 }
3871
3872 aRequest->ClearStencil();
3873}
3874
3875/* static */
3876nsCString& ScriptLoader::BytecodeMimeTypeFor(
3877 const ScriptLoadRequest* aRequest) {
3878 if (aRequest->IsModuleRequest()) {
3879 return nsContentUtils::JSModuleBytecodeMimeType();
3880 }
3881 return nsContentUtils::JSScriptBytecodeMimeType();
3882}
3883
3884/* static */
3885nsCString& ScriptLoader::BytecodeMimeTypeFor(
3886 const JS::loader::LoadedScript* aLoadedScript) {
3887 if (aLoadedScript->IsModuleScript()) {
3888 return nsContentUtils::JSModuleBytecodeMimeType();
3889 }
3890 return nsContentUtils::JSScriptBytecodeMimeType();
3891}
3892
3893nsresult ScriptLoader::MaybePrepareForDiskCacheAfterExecute(
3894 ScriptLoadRequest* aRequest, nsresult aRv) {
3895 MOZ_ASSERT(!aRequest->IsWasmBytes())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aRequest->IsWasmBytes())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aRequest->IsWasmBytes())
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!aRequest->IsWasmBytes()"
, "./../../../dom/script/ScriptLoader.cpp", 3895); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!aRequest->IsWasmBytes()" ")"); do { MOZ_CrashSequence
(__null, 3895); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
3896 if (mCache) {
3897 // Disk cache is handled by SharedScriptCache.
3898 return NS_OK;
3899 }
3900
3901 if (!aRequest->PassedConditionForDiskCache() || !aRequest->HasStencil()) {
3902 LOG(("ScriptLoadRequest (%p): Bytecode-cache: disabled (rv = %X)", aRequest,
3903 unsigned(aRv)));
3904 TRACE_FOR_TEST(aRequest, "diskcache:disabled")do { mozilla::dom::script::TestingNotifyObserver(aRequest, "diskcache:disabled"
); } while (0)
;
3905
3906 // For in-memory cached requests, the disk cache references are necessary
3907 // for later load.
3908 if (aRequest->HasStencil()) {
3909 MOZ_ASSERT_IF(!aRequest->PassedConditionForMemoryCache(),do { if (!aRequest->PassedConditionForMemoryCache()) { do {
static_assert( mozilla::detail::AssertionConditionType<decltype
(!aRequest->getLoadedScript()->HasDiskCacheReference())
>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!aRequest->getLoadedScript()->HasDiskCacheReference
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!aRequest->getLoadedScript()->HasDiskCacheReference()"
, "./../../../dom/script/ScriptLoader.cpp", 3910); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!aRequest->getLoadedScript()->HasDiskCacheReference()"
")"); do { MOZ_CrashSequence(__null, 3910); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3910 !aRequest->getLoadedScript()->HasDiskCacheReference())do { if (!aRequest->PassedConditionForMemoryCache()) { do {
static_assert( mozilla::detail::AssertionConditionType<decltype
(!aRequest->getLoadedScript()->HasDiskCacheReference())
>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!aRequest->getLoadedScript()->HasDiskCacheReference
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!aRequest->getLoadedScript()->HasDiskCacheReference()"
, "./../../../dom/script/ScriptLoader.cpp", 3910); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!aRequest->getLoadedScript()->HasDiskCacheReference()"
")"); do { MOZ_CrashSequence(__null, 3910); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
3911 } else {
3912 // This hits compile error.
3913 aRequest->getLoadedScript()->DropDiskCacheReferenceAndSRI();
3914 }
3915
3916 return aRv;
3917 }
3918
3919 TRACE_FOR_TEST(aRequest, "diskcache:register")do { mozilla::dom::script::TestingNotifyObserver(aRequest, "diskcache:register"
); } while (0)
;
3920 MOZ_ASSERT(aRequest->GetSRILength() == aRequest->SRI().length())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aRequest->GetSRILength() == aRequest->SRI().length
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aRequest->GetSRILength() == aRequest->SRI().length
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aRequest->GetSRILength() == aRequest->SRI().length()"
, "./../../../dom/script/ScriptLoader.cpp", 3920); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aRequest->GetSRILength() == aRequest->SRI().length()"
")"); do { MOZ_CrashSequence(__null, 3920); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3921 RegisterForDiskCache(aRequest);
3922
3923 return aRv;
3924}
3925
3926nsresult ScriptLoader::MaybePrepareModuleForDiskCacheAfterExecute(
3927 ModuleLoadRequest* aRequest, nsresult aRv) {
3928 MOZ_ASSERT(aRequest->IsTopLevel() || aRequest->IsDynamicImport())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aRequest->IsTopLevel() || aRequest->IsDynamicImport
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aRequest->IsTopLevel() || aRequest->IsDynamicImport
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aRequest->IsTopLevel() || aRequest->IsDynamicImport()"
, "./../../../dom/script/ScriptLoader.cpp", 3928); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aRequest->IsTopLevel() || aRequest->IsDynamicImport()"
")"); do { MOZ_CrashSequence(__null, 3928); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3929 MOZ_ASSERT(!aRequest->IsWasmBytes())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aRequest->IsWasmBytes())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aRequest->IsWasmBytes())
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!aRequest->IsWasmBytes()"
, "./../../../dom/script/ScriptLoader.cpp", 3929); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!aRequest->IsWasmBytes()" ")"); do { MOZ_CrashSequence
(__null, 3929); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
3930
3931 if (mCache) {
3932 // Disk cache is handled by SharedScriptCache.
3933 return NS_OK;
3934 }
3935
3936 // NOTE: If a module is passed to this multiple times, it can be
3937 // enqueued multiple times.
3938 // This is okay because ScriptLoader::UpdateDiskCache filters out
3939 // any script without the disk cache reference.
3940
3941 aRv = MaybePrepareForDiskCacheAfterExecute(aRequest, aRv);
3942
3943 for (auto* r = mDiskCacheableDependencyModules.getFirst(); r;) {
3944 auto* dep = r->AsModuleRequest();
3945 MOZ_ASSERT(dep->PassedConditionForDiskCache())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(dep->PassedConditionForDiskCache())>::isValid,
"invalid assertion condition"); if ((__builtin_expect(!!(!(!
!(dep->PassedConditionForDiskCache()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("dep->PassedConditionForDiskCache()"
, "./../../../dom/script/ScriptLoader.cpp", 3945); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "dep->PassedConditionForDiskCache()" ")"
); do { MOZ_CrashSequence(__null, 3945); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3946
3947 r = r->getNext();
3948
3949 if (dep->GetRootModule() != aRequest) {
3950 continue;
3951 }
3952
3953 mDiskCacheableDependencyModules.Remove(dep);
3954
3955 aRv = MaybePrepareForDiskCacheAfterExecute(dep, aRv);
3956 }
3957
3958 return aRv;
3959}
3960
3961nsresult ScriptLoader::EvaluateScript(nsIGlobalObject* aGlobalObject,
3962 ScriptLoadRequest* aRequest) {
3963 MOZ_ASSERT(!aRequest->IsWasmBytes())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aRequest->IsWasmBytes())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aRequest->IsWasmBytes())
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!aRequest->IsWasmBytes()"
, "./../../../dom/script/ScriptLoader.cpp", 3963); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!aRequest->IsWasmBytes()" ")"); do { MOZ_CrashSequence
(__null, 3963); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
3964 nsAutoMicroTask mt;
3965 AutoEntryScript aes(aGlobalObject, "EvaluateScript", true);
3966 JSContext* cx = aes.cx();
3967
3968 nsAutoCString profilerLabelString;
3969 aRequest->GetScriptLoadContext()->GetProfilerLabel(profilerLabelString);
3970
3971 // Create a ClassicScript object and associate it with the JSScript.
3972 MOZ_ASSERT(aRequest->mLoadedScript->IsClassicScript())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aRequest->mLoadedScript->IsClassicScript())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aRequest->mLoadedScript->IsClassicScript()))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("aRequest->mLoadedScript->IsClassicScript()"
, "./../../../dom/script/ScriptLoader.cpp", 3972); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aRequest->mLoadedScript->IsClassicScript()"
")"); do { MOZ_CrashSequence(__null, 3972); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3973
3974 JS::CompileOptions options(cx);
3975 JS::Rooted<JSScript*> introductionScript(cx);
3976 nsresult rv =
3977 FillCompileOptionsForRequest(cx, aRequest, &options, &introductionScript);
3978
3979 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3980 return rv;
3981 }
3982
3983 // Apply the delazify strategy if the script is small.
3984 if (!aRequest->IsRetrievedFromMemoryCache() &&
3985 aRequest->IsFetchedAsTextSource() &&
3986 aRequest->ScriptTextLength() < OffThreadMinimumTextLength &&
3987 ShouldApplyDelazifyStrategy(aRequest)) {
3988 ApplyDelazifyStrategy(&options);
3989 mTotalFullParseSize +=
3990 aRequest->ScriptTextLength() > 0
3991 ? static_cast<uint32_t>(aRequest->ScriptTextLength())
3992 : 0;
3993
3994 LOG(
3995 ("ScriptLoadRequest (%p): non-on-demand-only (non-omt) Parsing Enabled "
3996 "for url=%s mTotalFullParseSize=%u",
3997 aRequest, aRequest->URI()->GetSpecOrDefault().get(),
3998 mTotalFullParseSize));
3999 }
4000
4001 JS::Rooted<JSObject*> global(cx, aGlobalObject->GetGlobalJSObject());
4002 if (MOZ_UNLIKELY(!xpc::Scriptability::Get(global).Allowed())(__builtin_expect(!!(!xpc::Scriptability::Get(global).Allowed
()), 0))
) {
4003 return NS_OK;
4004 }
4005 ErrorResult erv;
4006 mozilla::AutoProfilerLabel autoProfilerLabel("JSExecutionContext",
4007 /* dynamicStr */ nullptr,
4008 JS::ProfilingCategoryPair::JS);
4009 JSAutoRealm autoRealm(cx, global);
4010 JS::Rooted<JSScript*> script(cx);
4011 InstantiateClassicScriptFromAny(cx, options, aRequest, &script,
4012 introductionScript, erv);
4013
4014 if (!erv.Failed()) {
4015 LOG(("ScriptLoadRequest (%p): Evaluate Script", aRequest));
4016 AUTO_PROFILER_FLOW_MARKER_TEXT(AutoProfilerFlowTextMarker raiiObject4018( "ScriptExecution",
::mozilla::baseprofiler::category::JS, MarkerInnerWindowIdFromJSContext
(cx), profilerLabelString, Flow::FromPointer(aRequest))
4017 "ScriptExecution", JS, MarkerInnerWindowIdFromJSContext(cx),AutoProfilerFlowTextMarker raiiObject4018( "ScriptExecution",
::mozilla::baseprofiler::category::JS, MarkerInnerWindowIdFromJSContext
(cx), profilerLabelString, Flow::FromPointer(aRequest))
4018 profilerLabelString, Flow::FromPointer(aRequest))AutoProfilerFlowTextMarker raiiObject4018( "ScriptExecution",
::mozilla::baseprofiler::category::JS, MarkerInnerWindowIdFromJSContext
(cx), profilerLabelString, Flow::FromPointer(aRequest))
;
4019
4020 MOZ_ASSERT(options.noScriptRval)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(options.noScriptRval)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(options.noScriptRval))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("options.noScriptRval"
, "./../../../dom/script/ScriptLoader.cpp", 4020); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "options.noScriptRval" ")"); do { MOZ_CrashSequence
(__null, 4020); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4021 TRACE_FOR_TEST(aRequest, "evaluate:classic")do { mozilla::dom::script::TestingNotifyObserver(aRequest, "evaluate:classic"
); } while (0)
;
4022
4023 if (script && JS::GetScriptPrivate(script).isUndefined()) {
4024 aRequest->FetchInfo()->AssociateWithScript(script);
4025 }
4026
4027 ExecuteCompiledScript(cx, script, erv);
4028 }
4029 rv = EvaluationExceptionToNSResult(erv);
4030
4031 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4032 return rv;
4033 }
4034
4035 // This must be called also for compilation failure case, in order to
4036 // dispatch test-only event.
4037 rv = MaybePrepareForDiskCacheAfterExecute(aRequest, rv);
4038
4039 // Even if we are not saving the current script to the disk cache, we have
4040 // to trigger the disk cache encoding, as the current script can be blocking
4041 // the other encoding, or the current script can delazify more functions
4042 // which we are recording the disk cache.
4043 LOG(("ScriptLoadRequest (%p): ScriptLoader = %p", aRequest, this));
4044 MaybeUpdateDiskCache();
4045
4046 return rv;
4047}
4048
4049/* static */
4050ScriptFetchInfo* ScriptLoader::GetActiveScriptFetchInfo(JSContext* aCx) {
4051 JS::Value value = JS::GetScriptedCallerPrivate(aCx);
4052 if (value.isUndefined()) {
4053 return nullptr;
4054 }
4055
4056 return static_cast<ScriptFetchInfo*>(value.toPrivate());
4057}
4058
4059void ScriptLoader::RegisterForDiskCache(ScriptLoadRequest* aRequest) {
4060 MOZ_ASSERT(!mCache)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mCache)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mCache))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("!mCache", "./../../../dom/script/ScriptLoader.cpp"
, 4060); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCache" ")"
); do { MOZ_CrashSequence(__null, 4060); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4061 MOZ_ASSERT(aRequest->PassedConditionForDiskCache())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aRequest->PassedConditionForDiskCache())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(aRequest->PassedConditionForDiskCache()))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("aRequest->PassedConditionForDiskCache()"
, "./../../../dom/script/ScriptLoader.cpp", 4061); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aRequest->PassedConditionForDiskCache()"
")"); do { MOZ_CrashSequence(__null, 4061); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4062 MOZ_ASSERT(aRequest->HasStencil())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aRequest->HasStencil())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aRequest->HasStencil())))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("aRequest->HasStencil()"
, "./../../../dom/script/ScriptLoader.cpp", 4062); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aRequest->HasStencil()" ")"); do { MOZ_CrashSequence
(__null, 4062); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4063 MOZ_ASSERT(aRequest->getLoadedScript()->HasDiskCacheReference())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aRequest->getLoadedScript()->HasDiskCacheReference
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aRequest->getLoadedScript()->HasDiskCacheReference
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aRequest->getLoadedScript()->HasDiskCacheReference()"
, "./../../../dom/script/ScriptLoader.cpp", 4063); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aRequest->getLoadedScript()->HasDiskCacheReference()"
")"); do { MOZ_CrashSequence(__null, 4063); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4064 MOZ_DIAGNOSTIC_ASSERT(!aRequest->isInList())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aRequest->isInList())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aRequest->isInList()))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("!aRequest->isInList()"
, "./../../../dom/script/ScriptLoader.cpp", 4064); AnnotateMozCrashReason
("MOZ_DIAGNOSTIC_ASSERT" "(" "!aRequest->isInList()" ")");
do { MOZ_CrashSequence(__null, 4064); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4065 MOZ_ASSERT(!IsWebExtensionRequest(aRequest),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!IsWebExtensionRequest(aRequest))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!IsWebExtensionRequest(aRequest
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!IsWebExtensionRequest(aRequest)" " (" "Web extension scripts are not compatible with the disk cache"
")", "./../../../dom/script/ScriptLoader.cpp", 4066); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!IsWebExtensionRequest(aRequest)" ") (" "Web extension scripts are not compatible with the disk cache"
")"); do { MOZ_CrashSequence(__null, 4066); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4066 "Web extension scripts are not compatible with the disk cache")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!IsWebExtensionRequest(aRequest))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!IsWebExtensionRequest(aRequest
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!IsWebExtensionRequest(aRequest)" " (" "Web extension scripts are not compatible with the disk cache"
")", "./../../../dom/script/ScriptLoader.cpp", 4066); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!IsWebExtensionRequest(aRequest)" ") (" "Web extension scripts are not compatible with the disk cache"
")"); do { MOZ_CrashSequence(__null, 4066); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4067
4068 LoadedScript* loadedScript = aRequest->getLoadedScript();
4069 MOZ_ASSERT(loadedScript->IsTextSource(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(loadedScript->IsTextSource())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(loadedScript->IsTextSource
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("loadedScript->IsTextSource()" " (" "Serialized stencil case shouldn't be saved again"
")", "./../../../dom/script/ScriptLoader.cpp", 4070); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "loadedScript->IsTextSource()" ") (" "Serialized stencil case shouldn't be saved again"
")"); do { MOZ_CrashSequence(__null, 4070); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4070 "Serialized stencil case shouldn't be saved again")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(loadedScript->IsTextSource())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(loadedScript->IsTextSource
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("loadedScript->IsTextSource()" " (" "Serialized stencil case shouldn't be saved again"
")", "./../../../dom/script/ScriptLoader.cpp", 4070); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "loadedScript->IsTextSource()" ") (" "Serialized stencil case shouldn't be saved again"
")"); do { MOZ_CrashSequence(__null, 4070); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4071 loadedScript->ConvertToCachedStencil(
4072 aRequest->GetStencil(), aRequest->ReferrerPolicy(), aRequest->BaseURL());
4073 mDiskCacheQueue.AppendElement(loadedScript);
4074
4075 aRequest->ClearStencil();
4076}
4077
4078void ScriptLoader::LoadEventFired() {
4079 mLoadEventFired = true;
4080 MaybeUpdateDiskCache();
4081}
4082
4083void ScriptLoader::Destroy() {
4084 if (mCache) {
4085 mCache->UpdateEverHitTelemetry();
4086 }
4087
4088 if (mObserver) {
4089 mObserver->Unregister();
4090 mObserver = nullptr;
4091 }
4092
4093 CancelAndClearScriptLoadRequests();
4094 GiveUpDiskCaching();
4095 StopCollectingDelazifications();
4096}
4097
4098void ScriptLoader::OnMemoryPressure() {
4099 // When memory pressure is detected, release the stencils held by the
4100 // ongoing delazification collection.
4101 // SharedScriptCache will also clear the cache, and then those stencils
4102 // will no longer held by anything live long and will be collected
4103 // shortly.
4104
4105 StopCollectingDelazifications();
4106}
4107
4108void ScriptLoader::StopCollectingDelazifications() {
4109 // NOTE: There's no difference between JS::FinishCollectingDelazifications
4110 // and JS::AbortCollectingDelazifications, except for whether
4111 // to return the stencil or not.
4112 // The stencil pointer is held by LoadedScript, and thus we call
4113 // JS::AbortCollectingDelazifications here, which is more light-weight.
4114
4115 for (size_t i = 0; i < mDelazificationCollectingScripts.Length(); ++i) {
4116 JSScript* script = mDelazificationCollectingScripts[i];
4117 JS::AbortCollectingDelazifications(script);
4118 }
4119 mDelazificationCollectingScripts.Clear();
4120
4121 for (size_t i = 0; i < mDelazificationCollectingModules.Length(); ++i) {
4122 JSObject* module = mDelazificationCollectingModules[i];
4123 JS::AbortCollectingDelazifications(module);
4124 }
4125 mDelazificationCollectingModules.Clear();
4126
4127 mozilla::DropJSObjects(this);
4128}
4129
4130void ScriptLoader::MaybeUpdateDiskCache() {
4131 // We wait for the load event to be fired before saving any script to the
4132 // disk cache. It is quite common to have load event listeners trigger more
4133 // JavaScript execution, that we want to save as part of disk cache, to
4134 // improve the load time in subsequent loads.
4135 if (!mLoadEventFired) {
4136 LOG(("ScriptLoader (%p): Wait for the load-end event to fire.", this));
4137 return;
4138 }
4139
4140 // Wait until all scripts are loaded before saving to the disk cache, such
4141 // that we capture most of the intialization of the page.
4142 if (HasPendingRequests()) {
4143 LOG(("ScriptLoader (%p): Wait for other pending request to finish.", this));
4144 return;
4145 }
4146
4147 if (mCache) {
4148 if (!mCache->MaybeScheduleUpdateDiskCache()) {
4149 TRACE_FOR_TEST_0("diskcache:noschedule")do { mozilla::dom::script::TestingNotifyObserver("diskcache:noschedule"
); } while (0)
;
4150 }
4151
4152 StopCollectingDelazifications();
4153 return;
4154 }
4155
4156 // If we already gave up, ensure that we are not going to enqueue any script,
4157 // and that we finalize them properly.
4158 if (mGiveUpDiskCaching) {
4159 LOG(("ScriptLoader (%p): Keep giving-up saving to the disk cache.", this));
4160 GiveUpDiskCaching();
4161 return;
4162 }
4163
4164 // No need to fire any event if there is no script to be saved.
4165 if (mDiskCacheQueue.IsEmpty()) {
4166 LOG(("ScriptLoader (%p): No script in queue to be saved to the disk.",
4167 this));
4168 return;
4169 }
4170
4171 // Create a new runnable dedicated to encoding all enqueued scripts when the
4172 // document is idle. In case of failure, we give-up on saving the disk cache.
4173 nsCOMPtr<nsIRunnable> encoder = NewRunnableMethod(
4174 "ScriptLoader::UpdateCache", this, &ScriptLoader::UpdateDiskCache);
4175 if (NS_FAILED(NS_DispatchToCurrentThreadQueue(encoder.forget(),((bool)(__builtin_expect(!!(NS_FAILED_impl(NS_DispatchToCurrentThreadQueue
(encoder.forget(), EventQueuePriority::Idle))), 0)))
4176 EventQueuePriority::Idle))((bool)(__builtin_expect(!!(NS_FAILED_impl(NS_DispatchToCurrentThreadQueue
(encoder.forget(), EventQueuePriority::Idle))), 0)))
) {
4177 GiveUpDiskCaching();
4178 return;
4179 }
4180
4181 StopCollectingDelazifications();
4182
4183 LOG(("ScriptLoader (%p): Schedule the disk cache encoding.", this));
4184}
4185
4186void ScriptLoader::UpdateDiskCache() {
4187 MOZ_ASSERT(!mCache)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mCache)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mCache))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("!mCache", "./../../../dom/script/ScriptLoader.cpp"
, 4187); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCache" ")"
); do { MOZ_CrashSequence(__null, 4187); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4188 LOG(("ScriptLoader (%p): Start the disk cache encoding.", this));
4189
4190 // If any script got added in the previous loop cycle, wait until all
4191 // remaining script executions are completed, such that we capture most of
4192 // the initialization.
4193 if (HasPendingRequests()) {
4194 return;
4195 }
4196
4197 JS::FrontendContext* fc = JS::NewFrontendContext();
4198 if (!fc) {
4199 LOG(
4200 ("ScriptLoader (%p): Cannot create FrontendContext for the disk cache "
4201 "encoding.",
4202 this));
4203 return;
4204 }
4205
4206 int32_t diskCacheMaxSizeInKb =
4207 StaticPrefs::browser_cache_disk_max_entry_size();
4208
4209 for (auto& loadedScript : mDiskCacheQueue) {
4210 // The encoding is performed only when there was no disk cache stored in
4211 // the necko cache.
4212 if (!loadedScript->HasDiskCacheReference()) {
4213 continue;
4214 }
4215
4216 if (loadedScript->IsInvalidatedCachedStencil()) {
4217 continue;
4218 }
4219
4220 RefPtr<JS::Stencil> stencil = loadedScript->GetCachedStencil();
4221
4222 Vector<uint8_t> compressed;
4223 if (!EncodeAndCompress(fc, loadedScript, stencil, loadedScript->SRI(),
4224 compressed)) {
4225 loadedScript->DropDiskCacheReference();
4226 loadedScript->DropSRIOrSRIAndSerializedStencil();
4227 TRACE_FOR_TEST(loadedScript, "diskcache:failed")do { mozilla::dom::script::TestingNotifyObserver(loadedScript
, "diskcache:failed"); } while (0)
;
4228 continue;
4229 }
4230
4231 // The pref being -1 means "no limit".
4232 if (diskCacheMaxSizeInKb > 0) {
4233 size_t sourceLength = JS::GetScriptSourceLength(stencil);
4234 size_t expectedDiskCacheSize = sourceLength + compressed.length();
4235 if (expectedDiskCacheSize > size_t(diskCacheMaxSizeInKb) * 1024) {
4236 loadedScript->DropDiskCacheReference();
4237 loadedScript->DropSRIOrSRIAndSerializedStencil();
4238 TRACE_FOR_TEST(loadedScript, "diskcache:toolarge")do { mozilla::dom::script::TestingNotifyObserver(loadedScript
, "diskcache:toolarge"); } while (0)
;
4239 continue;
4240 }
4241 }
4242
4243 if (!SaveToDiskCache(loadedScript, compressed)) {
4244 loadedScript->DropDiskCacheReference();
4245 loadedScript->DropSRIOrSRIAndSerializedStencil();
4246 TRACE_FOR_TEST(loadedScript, "diskcache:failed")do { mozilla::dom::script::TestingNotifyObserver(loadedScript
, "diskcache:failed"); } while (0)
;
4247 continue;
4248 }
4249
4250 loadedScript->DropDiskCacheReference();
4251 loadedScript->DropSRIOrSRIAndSerializedStencil();
4252 TRACE_FOR_TEST(loadedScript, "diskcache:saved")do { mozilla::dom::script::TestingNotifyObserver(loadedScript
, "diskcache:saved"); } while (0)
;
4253 }
4254 mDiskCacheQueue.Clear();
4255
4256 JS::DestroyFrontendContext(fc);
4257}
4258
4259/* static */
4260bool ScriptLoader::EncodeAndCompress(
4261 JS::FrontendContext* aFc, const JS::loader::LoadedScript* aLoadedScript,
4262 JS::Stencil* aStencil, const JS::TranscodeBuffer& aSRI,
4263 Vector<uint8_t>& aCompressed) {
4264 size_t SRILength = aSRI.length();
4265 MOZ_ASSERT(JS::IsTranscodingBytecodeOffsetAligned(SRILength))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(JS::IsTranscodingBytecodeOffsetAligned(SRILength))>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(JS::IsTranscodingBytecodeOffsetAligned(SRILength))))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("JS::IsTranscodingBytecodeOffsetAligned(SRILength)"
, "./../../../dom/script/ScriptLoader.cpp", 4265); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "JS::IsTranscodingBytecodeOffsetAligned(SRILength)"
")"); do { MOZ_CrashSequence(__null, 4265); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4266
4267 JS::TranscodeBuffer SRIAndSerializedStencil;
4268 if (!SRIAndSerializedStencil.appendAll(aSRI)) {
4269 LOG(("LoadedScript (%p): Cannot allocate buffer", aLoadedScript));
4270 return false;
4271 }
4272
4273 JS::TranscodeResult result =
4274 JS::EncodeStencil(aFc, aStencil, SRIAndSerializedStencil);
4275
4276 if (result != JS::TranscodeResult::Ok) {
4277 // Encoding can be aborted for any internal error.
4278 // We don't care the error and just give up encoding.
4279 JS::ClearFrontendErrors(aFc);
4280
4281 LOG(("LoadedScript (%p): Cannot encode stencil", aLoadedScript));
4282 return false;
4283 }
4284
4285 // TODO probably need to move this to a helper thread
4286 if (!ScriptBytecodeCompress(SRIAndSerializedStencil, SRILength,
4287 aCompressed)) {
4288 return false;
4289 }
4290
4291 if (aCompressed.length() >= UINT32_MAX(4294967295U)) {
4292 LOG(
4293 ("LoadedScript (%p): Serialized stencil is too large to be decoded "
4294 "correctly.",
4295 aLoadedScript));
4296 return false;
4297 }
4298
4299 return true;
4300}
4301
4302/* static */
4303bool ScriptLoader::SaveToDiskCache(
4304 const JS::loader::LoadedScript* aLoadedScript,
4305 const Vector<uint8_t>& aCompressed) {
4306 MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "./../../../dom/script/ScriptLoader.cpp", 4306); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 4306); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4307
4308 // Open the output stream to the cache entry alternate data storage. This
4309 // might fail if the stream is already open by another request, in which
4310 // case, we just ignore the current one.
4311 //
4312 // OpenAlternativeOutputStream doesn't immediately report errors on the
4313 // parent process, but instead it sets the error state and asynchronously
4314 // send it over IPC to report it as Write/Close result. If all the
4315 // operations finish before the error arrives, no error will be reported.
4316 //
4317 // We don't wait for the parent process here because there's nothing we can
4318 // do for the error case.
4319 nsCOMPtr<nsIAsyncOutputStream> output;
4320 nsresult rv = aLoadedScript->mCacheEntry->OpenAlternativeOutputStream(
4321 BytecodeMimeTypeFor(aLoadedScript),
4322 static_cast<int64_t>(aCompressed.length()), getter_AddRefs(output));
4323 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4324 LOG(
4325 ("LoadedScript (%p): Cannot open the disk cache (rv = %X, output "
4326 "= %p)",
4327 aLoadedScript, unsigned(rv), output.get()));
4328 return false;
4329 }
4330 MOZ_ASSERT(output)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(output)>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(output))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("output", "./../../../dom/script/ScriptLoader.cpp"
, 4330); AnnotateMozCrashReason("MOZ_ASSERT" "(" "output" ")"
); do { MOZ_CrashSequence(__null, 4330); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4331
4332 auto closeOutStream = mozilla::MakeScopeExit([&]() {
4333 rv = output->CloseWithStatus(rv);
4334 LOG(("LoadedScript (%p): Closing (rv = %X)", aLoadedScript, unsigned(rv)));
4335 });
4336
4337 uint32_t n;
4338 rv = output->Write(reinterpret_cast<const char*>(aCompressed.begin()),
4339 aCompressed.length(), &n);
4340 LOG(
4341 ("LoadedScript (%p): Write the disk cache (rv = %X, length = %u, "
4342 "written = %u)",
4343 aLoadedScript, unsigned(rv), unsigned(aCompressed.length()), n));
4344 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4345 return false;
4346 }
4347
4348 MOZ_RELEASE_ASSERT(aCompressed.length() == n)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aCompressed.length() == n)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aCompressed.length() == n)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("aCompressed.length() == n"
, "./../../../dom/script/ScriptLoader.cpp", 4348); AnnotateMozCrashReason
("MOZ_RELEASE_ASSERT" "(" "aCompressed.length() == n" ")"); do
{ MOZ_CrashSequence(__null, 4348); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
4349 return true;
4350}
4351
4352void ScriptLoader::GiveUpDiskCaching() {
4353 if (mCache) {
4354 // Disk cache is handled by SharedScriptCache.
4355 MOZ_ASSERT(mDiskCacheQueue.IsEmpty())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mDiskCacheQueue.IsEmpty())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mDiskCacheQueue.IsEmpty())))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("mDiskCacheQueue.IsEmpty()"
, "./../../../dom/script/ScriptLoader.cpp", 4355); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "mDiskCacheQueue.IsEmpty()" ")"); do { MOZ_CrashSequence
(__null, 4355); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4356 MOZ_ASSERT(mDiskCacheableDependencyModules.isEmpty())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mDiskCacheableDependencyModules.isEmpty())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(mDiskCacheableDependencyModules.isEmpty()))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("mDiskCacheableDependencyModules.isEmpty()"
, "./../../../dom/script/ScriptLoader.cpp", 4356); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "mDiskCacheableDependencyModules.isEmpty()"
")"); do { MOZ_CrashSequence(__null, 4356); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4357 return;
4358 }
4359
4360 // If the document went away prematurely, we still want to set this, in order
4361 // to avoid queuing more scripts.
4362 mGiveUpDiskCaching = true;
4363
4364 for (auto& loadedScript : mDiskCacheQueue) {
4365 LOG(("LoadedScript (%p): Giving up encoding the disk cache",
4366 loadedScript.get()));
4367 TRACE_FOR_TEST(loadedScript, "diskcache:giveup")do { mozilla::dom::script::TestingNotifyObserver(loadedScript
, "diskcache:giveup"); } while (0)
;
4368
4369 loadedScript->DropDiskCacheReference();
4370 loadedScript->DropSRIOrSRIAndSerializedStencil();
4371 }
4372 mDiskCacheQueue.Clear();
4373
4374 while (!mDiskCacheableDependencyModules.isEmpty()) {
4375 RefPtr<ScriptLoadRequest> request =
4376 mDiskCacheableDependencyModules.StealFirst();
4377 }
4378}
4379
4380bool ScriptLoader::HasPendingRequests() const {
4381 return mParserBlockingRequest || !mXSLTRequests.isEmpty() ||
4382 !mLoadedAsyncRequests.isEmpty() ||
4383 !mNonAsyncExternalScriptInsertedRequests.isEmpty() ||
4384 !mDeferRequests.isEmpty() || HasPendingDynamicImports() ||
4385 !mPendingChildLoaders.IsEmpty();
4386 // mOffThreadCompilingRequests are already being processed.
4387}
4388
4389bool ScriptLoader::HasPendingDynamicImports() const {
4390 if (mModuleLoader && mModuleLoader->HasPendingDynamicImports()) {
4391 return true;
4392 }
4393
4394 for (ModuleLoader* loader : mWebExtModuleLoaders) {
4395 if (loader->HasPendingDynamicImports()) {
4396 return true;
4397 }
4398 }
4399
4400 return false;
4401}
4402
4403void ScriptLoader::ProcessPendingRequestsAsync() {
4404 if (HasPendingRequests()) {
4405 nsCOMPtr<nsIRunnable> task = NewRunnableMethod<bool>(
4406 "dom::ScriptLoader::ProcessPendingRequests", this,
4407 &ScriptLoader::ProcessPendingRequests, false);
4408 if (mDocument) {
4409 mDocument->Dispatch(task.forget());
4410 } else {
4411 NS_DispatchToCurrentThread(task.forget());
4412 }
4413 }
4414}
4415
4416void ProcessPendingRequestsCallback(nsITimer* aTimer, void* aClosure)
4417 MOZ_CAN_RUN_SCRIPT_BOUNDARY {
4418 RefPtr<ScriptLoader> sl = static_cast<ScriptLoader*>(aClosure);
4419 sl->ProcessPendingRequests(true);
4420}
4421
4422void ScriptLoader::ProcessPendingRequestsAsyncBypassParserBlocking() {
4423 MOZ_ASSERT(HasPendingRequests())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(HasPendingRequests())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(HasPendingRequests()))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("HasPendingRequests()"
, "./../../../dom/script/ScriptLoader.cpp", 4423); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "HasPendingRequests()" ")"); do { MOZ_CrashSequence
(__null, 4423); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4424
4425 if (!mProcessPendingRequestsAsyncBypassParserBlocking) {
4426 mProcessPendingRequestsAsyncBypassParserBlocking = NS_NewTimer();
4427 }
4428
4429 // test_bug503481b.html tests the unlikely edge case where loading parser
4430 // blocking script depends on async script to be executed. So don't block
4431 // async scripts forever.
4432 mProcessPendingRequestsAsyncBypassParserBlocking->InitWithNamedFuncCallback(
4433 ProcessPendingRequestsCallback, this, 2500, nsITimer::TYPE_ONE_SHOT,
4434 "ProcessPendingRequestsAsyncBypassParserBlocking"_ns);
4435}
4436
4437void ScriptLoader::ProcessPendingRequests(bool aAllowBypassingParserBlocking) {
4438 RefPtr<ScriptLoadRequest> request;
4439
4440 if (mProcessPendingRequestsAsyncBypassParserBlocking) {
4441 mProcessPendingRequestsAsyncBypassParserBlocking->Cancel();
4442 }
4443
4444 if (mParserBlockingRequest) {
4445 if (mParserBlockingRequest->IsFinished() &&
4446 ReadyToExecuteParserBlockingScripts()) {
4447 request.swap(mParserBlockingRequest);
4448 UnblockParser(request);
4449 ProcessRequest(request);
4450 ContinueParserAsync(request);
4451 ProcessPendingRequestsAsync();
4452 return;
4453 }
4454
4455 if (!aAllowBypassingParserBlocking) {
4456 ProcessPendingRequestsAsyncBypassParserBlocking();
4457 return;
4458 }
4459 }
4460
4461 while (ReadyToExecuteParserBlockingScripts() && !mXSLTRequests.isEmpty() &&
4462 mXSLTRequests.getFirst()->IsFinished()) {
4463 request = mXSLTRequests.StealFirst();
4464 ProcessRequest(request);
4465 }
4466
4467 while (ReadyToExecuteScripts() && !mLoadedAsyncRequests.isEmpty()) {
4468 if (mLoadedAsyncRequests.getFirst()->TookLongInPreviousRuns() &&
4469 !mLoadedAsyncRequests.getFirst()->HadPostponed() && IsBeforeFCP()) {
4470 mLoadedAsyncRequests.getFirst()->SetHadPostponed();
4471 ProcessPendingRequestsAsync();
4472 return;
4473 }
4474
4475 request = mLoadedAsyncRequests.StealFirst();
4476 if (request->IsModuleRequest()) {
4477 ProcessRequest(request);
4478 } else {
4479 CompileOffThreadOrProcessRequest(request);
4480 }
4481 }
4482
4483 while (ReadyToExecuteScripts() &&
4484 !mNonAsyncExternalScriptInsertedRequests.isEmpty() &&
4485 mNonAsyncExternalScriptInsertedRequests.getFirst()->IsFinished()) {
4486 // Violate the HTML5 spec and execute these in the insertion order in
4487 // order to make LABjs and the "order" plug-in for RequireJS work with
4488 // their Gecko-sniffed code path. See
4489 // http://lists.w3.org/Archives/Public/public-html/2010Oct/0088.html
4490 request = mNonAsyncExternalScriptInsertedRequests.StealFirst();
4491 ProcessRequest(request);
4492 }
4493
4494 if (mDeferCheckpointReached && mXSLTRequests.isEmpty()) {
4495 while (ReadyToExecuteScripts() && !mDeferRequests.isEmpty() &&
4496 mDeferRequests.getFirst()->IsFinished()) {
4497 if (mDeferRequests.getFirst()->TookLongInPreviousRuns() &&
4498 !mDeferRequests.getFirst()->HadPostponed() && IsBeforeFCP()) {
4499 mDeferRequests.getFirst()->SetHadPostponed();
4500 ProcessPendingRequestsAsync();
4501 return;
4502 }
4503
4504 request = mDeferRequests.StealFirst();
4505 ProcessRequest(request);
4506 }
4507 }
4508
4509 while (!mPendingChildLoaders.IsEmpty() &&
4510 ReadyToExecuteParserBlockingScripts()) {
4511 RefPtr<ScriptLoader> child = mPendingChildLoaders[0];
4512 mPendingChildLoaders.RemoveElementAt(0);
4513 child->RemoveParserBlockingScriptExecutionBlocker();
4514 }
4515
4516 if (mDeferCheckpointReached && mDocument && !mParserBlockingRequest &&
4517 mNonAsyncExternalScriptInsertedRequests.isEmpty() &&
4518 mXSLTRequests.isEmpty() && mDeferRequests.isEmpty() &&
4519 MaybeRemovedDeferRequests()) {
4520 return ProcessPendingRequests();
4521 }
4522
4523 if (mDeferCheckpointReached && mDocument && !mParserBlockingRequest &&
4524 mLoadingAsyncRequests.isEmpty() && mLoadedAsyncRequests.isEmpty() &&
4525 mNonAsyncExternalScriptInsertedRequests.isEmpty() &&
4526 mXSLTRequests.isEmpty() && mDeferRequests.isEmpty()) {
4527 // No more pending scripts; time to unblock onload.
4528 // OK to unblock onload synchronously here, since callers must be
4529 // prepared for the world changing anyway.
4530 mDeferCheckpointReached = false;
4531 mDocument->UnblockOnload(true);
4532 }
4533}
4534
4535bool ScriptLoader::IsBeforeFCP() {
4536 if (mHadFCPDoNotUseDirectly) {
4537 return false;
4538 }
4539
4540 if (mLoadEventFired) {
4541 return false;
4542 }
4543
4544 if (!mDocument) {
4545 return false;
4546 }
4547
4548 nsPresContext* context = mDocument->GetPresContext();
4549 if (!context) {
4550 return false;
4551 }
4552
4553 if (context->HadFirstContentfulPaint()) {
4554 mHadFCPDoNotUseDirectly = true;
4555 return false;
4556 }
4557
4558 return true;
4559}
4560
4561bool ScriptLoader::ReadyToExecuteParserBlockingScripts() {
4562 // Make sure the SelfReadyToExecuteParserBlockingScripts check is first, so
4563 // that we don't block twice on an ancestor.
4564 if (!SelfReadyToExecuteParserBlockingScripts()) {
4565 return false;
4566 }
4567
4568 if (mDocument && mDocument->GetWindowContext()) {
4569 for (WindowContext* wc =
4570 mDocument->GetWindowContext()->GetParentWindowContext();
4571 wc; wc = wc->GetParentWindowContext()) {
4572 if (Document* doc = wc->GetDocument()) {
4573 ScriptLoader* ancestor = doc->GetScriptLoader();
4574 if (ancestor && !ancestor->SelfReadyToExecuteParserBlockingScripts() &&
4575 ancestor->AddPendingChildLoader(this)) {
4576 AddParserBlockingScriptExecutionBlocker();
4577 return false;
4578 }
4579 }
4580 }
4581 }
4582
4583 return true;
4584}
4585
4586template <typename Unit>
4587static nsresult ConvertToUnicode(nsIChannel* aChannel, const uint8_t* aData,
4588 uint32_t aLength,
4589 const nsAString& aHintCharset,
4590 Document* aDocument, Unit*& aBufOut,
4591 size_t& aLengthOut) {
4592 if (!aLength) {
4593 aBufOut = nullptr;
4594 aLengthOut = 0;
4595 return NS_OK;
4596 }
4597
4598 auto data = Span(aData, aLength);
4599
4600 // The encoding info precedence is as follows from high to low:
4601 // The BOM
4602 // HTTP Content-Type (if name recognized)
4603 // charset attribute (if name recognized)
4604 // The encoding of the document
4605
4606 UniquePtr<Decoder> unicodeDecoder;
4607
4608 const Encoding* encoding;
4609 std::tie(encoding, std::ignore) = Encoding::ForBOM(data);
4610 if (encoding) {
4611 unicodeDecoder = encoding->NewDecoderWithBOMRemoval();
4612 }
4613
4614 if (!unicodeDecoder && aChannel) {
4615 nsAutoCString label;
4616 if (NS_SUCCEEDED(aChannel->GetContentCharset(label))((bool)(__builtin_expect(!!(!NS_FAILED_impl(aChannel->GetContentCharset
(label))), 1)))
&&
4617 (encoding = Encoding::ForLabel(label))) {
4618 unicodeDecoder = encoding->NewDecoderWithoutBOMHandling();
4619 }
4620 }
4621
4622 if (!unicodeDecoder && (encoding = Encoding::ForLabel(aHintCharset))) {
4623 unicodeDecoder = encoding->NewDecoderWithoutBOMHandling();
4624 }
4625
4626 if (!unicodeDecoder && aDocument) {
4627 unicodeDecoder =
4628 aDocument->GetDocumentCharacterSet()->NewDecoderWithoutBOMHandling();
4629 }
4630
4631 if (!unicodeDecoder) {
4632 // Curiously, there are various callers that don't pass aDocument. The
4633 // fallback in the old code was ISO-8859-1, which behaved like
4634 // windows-1252.
4635 unicodeDecoder = WINDOWS_1252_ENCODING->NewDecoderWithoutBOMHandling();
4636 }
4637
4638 auto signalOOM = mozilla::MakeScopeExit([&aBufOut, &aLengthOut]() {
4639 aBufOut = nullptr;
4640 aLengthOut = 0;
4641 });
4642
4643 CheckedInt<size_t> bufferLength =
4644 ScriptDecoding<Unit>::MaxBufferLength(unicodeDecoder, aLength);
4645 if (!bufferLength.isValid()) {
4646 return NS_ERROR_OUT_OF_MEMORY;
4647 }
4648
4649 CheckedInt<size_t> bufferByteSize = bufferLength * sizeof(Unit);
4650 if (!bufferByteSize.isValid()) {
4651 return NS_ERROR_OUT_OF_MEMORY;
4652 }
4653
4654 aBufOut = static_cast<Unit*>(js_malloc(bufferByteSize.value()));
4655 if (!aBufOut) {
4656 return NS_ERROR_OUT_OF_MEMORY;
4657 }
4658
4659 signalOOM.release();
4660 aLengthOut = ScriptDecoding<Unit>::DecodeInto(
4661 unicodeDecoder, data, Span(aBufOut, bufferLength.value()),
4662 /* aEndOfSource = */ true);
4663 return NS_OK;
4664}
4665
4666/* static */
4667nsresult ScriptLoader::ConvertToUTF16(
4668 nsIChannel* aChannel, const uint8_t* aData, uint32_t aLength,
4669 const nsAString& aHintCharset, Document* aDocument,
4670 UniquePtr<char16_t[], JS::FreePolicy>& aBufOut, size_t& aLengthOut) {
4671 char16_t* bufOut;
4672 nsresult rv = ConvertToUnicode(aChannel, aData, aLength, aHintCharset,
4673 aDocument, bufOut, aLengthOut);
4674 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
4675 aBufOut.reset(bufOut);
4676 }
4677 return rv;
4678}
4679
4680/* static */
4681nsresult ScriptLoader::ConvertToUTF8(
4682 nsIChannel* aChannel, const uint8_t* aData, uint32_t aLength,
4683 const nsAString& aHintCharset, Document* aDocument,
4684 UniquePtr<Utf8Unit[], JS::FreePolicy>& aBufOut, size_t& aLengthOut) {
4685 Utf8Unit* bufOut;
4686 nsresult rv = ConvertToUnicode(aChannel, aData, aLength, aHintCharset,
4687 aDocument, bufOut, aLengthOut);
4688 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
4689 aBufOut.reset(bufOut);
4690 }
4691 return rv;
4692}
4693
4694nsresult ScriptLoader::OnStreamComplete(
4695 nsIChannel* aChannel, ScriptLoadRequest* aRequest, nsresult aChannelStatus,
4696 nsresult aSRIStatus, SRICheckDataVerifier* aSRIDataVerifier) {
4697 NS_ASSERTION(aRequest, "null request in stream complete handler")do { if (!(aRequest)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "null request in stream complete handler"
, "aRequest", "./../../../dom/script/ScriptLoader.cpp", 4697)
; MOZ_PretendNoReturn(); } } while (0)
;
4698 NS_ENSURE_TRUE(aRequest, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(aRequest)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aRequest" ") failed", nullptr
, "./../../../dom/script/ScriptLoader.cpp", 4698); return NS_ERROR_FAILURE
; } } while (false)
;
4699
4700 if (aRequest->IsCanceled()) {
4701 return NS_BINDING_ABORTED;
4702 }
4703
4704 nsresult rv = VerifySRI(aRequest, aChannel, aSRIStatus, aSRIDataVerifier);
4705
4706 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
4707 // These flags can be modified by the CacheEntryRevived.
4708 bool IsFetchedAsTextSource = aRequest->IsFetchedAsTextSource();
4709 bool IsRetrievedAsSerializedStencil =
4710 aRequest->IsRetrievedAsSerializedStencil();
4711
4712 nsCOMPtr<nsICacheInfoChannel> cacheInfo = do_QueryInterface(aChannel);
4713 nsCOMPtr<nsICacheEntryWriteHandle> cacheEntry;
4714 if (cacheInfo && NS_SUCCEEDED(cacheInfo->GetCacheEntryWriteHandle(((bool)(__builtin_expect(!!(!NS_FAILED_impl(cacheInfo->GetCacheEntryWriteHandle
( getter_AddRefs(cacheEntry)))), 1)))
4715 getter_AddRefs(cacheEntry)))((bool)(__builtin_expect(!!(!NS_FAILED_impl(cacheInfo->GetCacheEntryWriteHandle
( getter_AddRefs(cacheEntry)))), 1)))
) {
4716 uint64_t id;
4717 nsresult rv = cacheInfo->GetCacheEntryId(&id);
4718 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
4719 LOG(("ScriptLoadRequest (%p): cacheEntryId = %zx", aRequest,
4720 size_t(id)));
4721
4722 if (aRequest->HasDirtyCache()) {
4723 // This request found a dirty cache.
4724 // Validate the cache with the response's cache ID.
4725 ScriptHashKey key(this, aRequest, aRequest->ReferrerPolicy(),
4726 aRequest->FetchOptions(), aRequest->URI());
4727 auto cacheResult = mCache->Lookup(*this, key, /* aSyncLoad = */ true);
4728 MOZ_ASSERT_IF(do { if (cacheResult.mState == CachedSubResourceState::Complete
) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(cacheResult.mCompleteValue->IsCachedStencil()
|| cacheResult.mCompleteValue->IsInvalidatedCachedStencil
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(cacheResult.mCompleteValue->IsCachedStencil() || cacheResult
.mCompleteValue->IsInvalidatedCachedStencil()))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("cacheResult.mCompleteValue->IsCachedStencil() || cacheResult.mCompleteValue->IsInvalidatedCachedStencil()"
, "./../../../dom/script/ScriptLoader.cpp", 4731); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "cacheResult.mCompleteValue->IsCachedStencil() || cacheResult.mCompleteValue->IsInvalidatedCachedStencil()"
")"); do { MOZ_CrashSequence(__null, 4731); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4729 cacheResult.mState == CachedSubResourceState::Complete,do { if (cacheResult.mState == CachedSubResourceState::Complete
) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(cacheResult.mCompleteValue->IsCachedStencil()
|| cacheResult.mCompleteValue->IsInvalidatedCachedStencil
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(cacheResult.mCompleteValue->IsCachedStencil() || cacheResult
.mCompleteValue->IsInvalidatedCachedStencil()))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("cacheResult.mCompleteValue->IsCachedStencil() || cacheResult.mCompleteValue->IsInvalidatedCachedStencil()"
, "./../../../dom/script/ScriptLoader.cpp", 4731); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "cacheResult.mCompleteValue->IsCachedStencil() || cacheResult.mCompleteValue->IsInvalidatedCachedStencil()"
")"); do { MOZ_CrashSequence(__null, 4731); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4730 cacheResult.mCompleteValue->IsCachedStencil() ||do { if (cacheResult.mState == CachedSubResourceState::Complete
) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(cacheResult.mCompleteValue->IsCachedStencil()
|| cacheResult.mCompleteValue->IsInvalidatedCachedStencil
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(cacheResult.mCompleteValue->IsCachedStencil() || cacheResult
.mCompleteValue->IsInvalidatedCachedStencil()))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("cacheResult.mCompleteValue->IsCachedStencil() || cacheResult.mCompleteValue->IsInvalidatedCachedStencil()"
, "./../../../dom/script/ScriptLoader.cpp", 4731); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "cacheResult.mCompleteValue->IsCachedStencil() || cacheResult.mCompleteValue->IsInvalidatedCachedStencil()"
")"); do { MOZ_CrashSequence(__null, 4731); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4731 cacheResult.mCompleteValue->IsInvalidatedCachedStencil())do { if (cacheResult.mState == CachedSubResourceState::Complete
) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(cacheResult.mCompleteValue->IsCachedStencil()
|| cacheResult.mCompleteValue->IsInvalidatedCachedStencil
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(cacheResult.mCompleteValue->IsCachedStencil() || cacheResult
.mCompleteValue->IsInvalidatedCachedStencil()))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("cacheResult.mCompleteValue->IsCachedStencil() || cacheResult.mCompleteValue->IsInvalidatedCachedStencil()"
, "./../../../dom/script/ScriptLoader.cpp", 4731); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "cacheResult.mCompleteValue->IsCachedStencil() || cacheResult.mCompleteValue->IsInvalidatedCachedStencil()"
")"); do { MOZ_CrashSequence(__null, 4731); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
4732 if (cacheResult.mState == CachedSubResourceState::Complete &&
4733 cacheResult.mCompleteValue->IsCachedStencil() &&
4734 cacheResult.mCompleteValue->IsSRIMetadataReusableBy(
4735 aRequest->mIntegrity) &&
4736 cacheResult.mCompleteValue->CacheEntryId() == id) {
4737 cacheResult.mCompleteValue->UnsetDirty();
4738 // This keeps the request as "fetching" state.
4739 // PrepareLoadedRequest below will set it to "ready" state.
4740 //
4741 // Off-thread compilation is skipped for the revived cache.
4742 // See AttemptOffThreadScriptCompile.
4743 //
4744 // Main thread compilation is skipped in the same way as
4745 // non-dirty cache.
4746 aRequest->CacheEntryRevived(cacheResult.mCompleteValue);
4747
4748 MOZ_ASSERT(aRequest->IsFetching())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aRequest->IsFetching())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aRequest->IsFetching())))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("aRequest->IsFetching()"
, "./../../../dom/script/ScriptLoader.cpp", 4748); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aRequest->IsFetching()" ")"); do { MOZ_CrashSequence
(__null, 4748); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4749
4750 cacheResult.mCompleteValue->AddFetchCount();
4751
4752 TRACE_FOR_TEST(aRequest, "memorycache:dirty:revived")do { mozilla::dom::script::TestingNotifyObserver(aRequest, "memorycache:dirty:revived"
); } while (0)
;
4753 mMemoryCacheRevived++;
4754 } else {
4755 mCache->Evict(key);
4756 TRACE_FOR_TEST(aRequest, "memorycache:dirty:evicted")do { mozilla::dom::script::TestingNotifyObserver(aRequest, "memorycache:dirty:evicted"
); } while (0)
;
4757 mMemoryCacheEvictedDirty++;
4758 }
4759 }
4760
4761 aRequest->getLoadedScript()->SetCacheEntryId(id);
4762 }
4763
4764 // If we are loading from source, store the cache info channel and
4765 // save the computed SRI hash or a dummy SRI hash in case we are going to
4766 // save the this script in the disk cache.
4767 if (!aRequest->IsRetrievedFromMemoryCache() && IsFetchedAsTextSource &&
4768 StaticPrefs::dom_script_loader_bytecode_cache_enabled()) {
4769 uint32_t fetchCount;
4770 if (NS_SUCCEEDED(cacheInfo->GetCacheTokenFetchCount(&fetchCount))((bool)(__builtin_expect(!!(!NS_FAILED_impl(cacheInfo->GetCacheTokenFetchCount
(&fetchCount))), 1)))
) {
4771 if (fetchCount < UINT8_MAX(255)) {
4772 aRequest->getLoadedScript()->mFetchCount = fetchCount;
4773 } else {
4774 aRequest->getLoadedScript()->mFetchCount = UINT8_MAX(255);
4775 }
4776 }
4777
4778 aRequest->getLoadedScript()->mCacheEntry = cacheEntry;
4779 LOG(("ScriptLoadRequest (%p): nsICacheEntryWriteHandle = %p", aRequest,
4780 (void*)cacheEntry));
4781
4782 rv = SaveSRIHash(aRequest, aSRIDataVerifier);
Value stored to 'rv' is never read
4783 }
4784 }
4785
4786 if (IsFetchedAsTextSource) {
4787 mLoadedFromNeckoAsText++;
4788 } else if (IsRetrievedAsSerializedStencil) {
4789 mLoadedFromNeckoAsSerializedStencil++;
4790 }
4791 // NOTE: IsCachedStencil() and IsInvalidatedCachedStencil() cases are
4792 // handled above by incrementing mMemoryCacheRevived.
4793
4794 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
4795 rv = PrepareLoadedRequest(aRequest, aChannel, aChannelStatus);
4796 }
4797
4798 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4799 aRequest->getLoadedScript()->DropDiskCacheReference();
4800 ReportErrorToConsole(aRequest, rv);
4801 }
4802 }
4803
4804 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4805 // When loading the disk cache, we verify the SRI hash. If it does not match
4806 // the one from the document we restart the load, forcing us to load the
4807 // source instead. If this happens do not remove the current request from
4808 // script loader's data structures or fire any events.
4809 if (aChannelStatus != NS_BINDING_RETARGETED) {
4810 HandleLoadError(aRequest, rv);
4811 }
4812 }
4813
4814 // Process our request and/or any pending ones
4815 ProcessPendingRequests();
4816
4817 return rv;
4818}
4819
4820nsresult ScriptLoader::VerifySRI(ScriptLoadRequest* aRequest,
4821 nsIChannel* aChannel, nsresult aSRIStatus,
4822 SRICheckDataVerifier* aSRIDataVerifier) const {
4823 nsresult rv = NS_OK;
4824
4825 if (!aRequest->mIntegrity.IsEmpty() && NS_SUCCEEDED((rv = aSRIStatus))((bool)(__builtin_expect(!!(!NS_FAILED_impl((rv = aSRIStatus)
)), 1)))
) {
4826 MOZ_ASSERT(aSRIDataVerifier)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aSRIDataVerifier)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aSRIDataVerifier))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("aSRIDataVerifier"
, "./../../../dom/script/ScriptLoader.cpp", 4826); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aSRIDataVerifier" ")"); do { MOZ_CrashSequence
(__null, 4826); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4827 MOZ_ASSERT(mReporter)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mReporter)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mReporter))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mReporter", "./../../../dom/script/ScriptLoader.cpp"
, 4827); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mReporter" ")"
); do { MOZ_CrashSequence(__null, 4827); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4828 rv = aSRIDataVerifier->Verify(aRequest->mIntegrity, aChannel, mReporter);
4829
4830 mReporter->FlushReportsToConsole(
4831 nsContentUtils::GetInnerWindowID(aChannel));
4832
4833 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4834 rv = NS_ERROR_SRI_CORRUPT;
4835 TRACE_FOR_TEST(aRequest, "sri:corrupt")do { mozilla::dom::script::TestingNotifyObserver(aRequest, "sri:corrupt"
); } while (0)
;
4836 }
4837 }
4838
4839 return rv;
4840}
4841
4842nsresult ScriptLoader::SaveSRIHash(
4843 ScriptLoadRequest* aRequest, SRICheckDataVerifier* aSRIDataVerifier) const {
4844 MOZ_ASSERT(aRequest->IsFetchedAsTextSource())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aRequest->IsFetchedAsTextSource())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aRequest->IsFetchedAsTextSource
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aRequest->IsFetchedAsTextSource()", "./../../../dom/script/ScriptLoader.cpp"
, 4844); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aRequest->IsFetchedAsTextSource()"
")"); do { MOZ_CrashSequence(__null, 4844); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4845 JS::TranscodeBuffer& sri = aRequest->SRI();
4846 MOZ_ASSERT(sri.empty())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(sri.empty())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(sri.empty()))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("sri.empty()", "./../../../dom/script/ScriptLoader.cpp"
, 4846); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sri.empty()"
")"); do { MOZ_CrashSequence(__null, 4846); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4847
4848 uint32_t len = 0;
4849
4850 // If the integrity metadata does not correspond to a valid hash function,
4851 // IsComplete would be false.
4852 if (!aRequest->mIntegrity.IsEmpty() && aSRIDataVerifier->IsComplete()) {
4853 MOZ_ASSERT(sri.length() == 0)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(sri.length() == 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(sri.length() == 0))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("sri.length() == 0"
, "./../../../dom/script/ScriptLoader.cpp", 4853); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "sri.length() == 0" ")"); do { MOZ_CrashSequence
(__null, 4853); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4854
4855 // Encode the SRI computed hash.
4856 len = aSRIDataVerifier->DataSummaryLength();
4857
4858 if (!sri.resize(len)) {
4859 return NS_ERROR_OUT_OF_MEMORY;
4860 }
4861
4862 DebugOnly<nsresult> res =
4863 aSRIDataVerifier->ExportDataSummary(len, sri.begin());
4864 MOZ_ASSERT(NS_SUCCEEDED(res))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(res)), 1
))))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(res)), 1
)))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(res)), 1)))", "./../../../dom/script/ScriptLoader.cpp"
, 4864); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(res)), 1)))"
")"); do { MOZ_CrashSequence(__null, 4864); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4865 } else {
4866 MOZ_ASSERT(sri.length() == 0)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(sri.length() == 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(sri.length() == 0))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("sri.length() == 0"
, "./../../../dom/script/ScriptLoader.cpp", 4866); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "sri.length() == 0" ")"); do { MOZ_CrashSequence
(__null, 4866); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4867
4868 // Encode a dummy SRI hash.
4869 len = SRICheckDataVerifier::EmptyDataSummaryLength();
4870
4871 if (!sri.resize(len)) {
4872 return NS_ERROR_OUT_OF_MEMORY;
4873 }
4874
4875 DebugOnly<nsresult> res =
4876 SRICheckDataVerifier::ExportEmptyDataSummary(len, sri.begin());
4877 MOZ_ASSERT(NS_SUCCEEDED(res))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(res)), 1
))))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(res)), 1
)))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(res)), 1)))", "./../../../dom/script/ScriptLoader.cpp"
, 4877); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(res)), 1)))"
")"); do { MOZ_CrashSequence(__null, 4877); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4878 }
4879
4880 // Verify that the exported and predicted length correspond.
4881 DebugOnly<uint32_t> srilen{};
4882 MOZ_ASSERT(NS_SUCCEEDED(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(SRICheckDataVerifier
::DataSummaryLength(len, sri.begin(), &srilen))), 1))))>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(SRICheckDataVerifier
::DataSummaryLength(len, sri.begin(), &srilen))), 1))))))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("((bool)(__builtin_expect(!!(!NS_FAILED_impl(SRICheckDataVerifier::DataSummaryLength(len, sri.begin(), &srilen))), 1)))"
, "./../../../dom/script/ScriptLoader.cpp", 4883); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(SRICheckDataVerifier::DataSummaryLength(len, sri.begin(), &srilen))), 1)))"
")"); do { MOZ_CrashSequence(__null, 4883); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4883 SRICheckDataVerifier::DataSummaryLength(len, sri.begin(), &srilen)))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(SRICheckDataVerifier
::DataSummaryLength(len, sri.begin(), &srilen))), 1))))>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(SRICheckDataVerifier
::DataSummaryLength(len, sri.begin(), &srilen))), 1))))))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("((bool)(__builtin_expect(!!(!NS_FAILED_impl(SRICheckDataVerifier::DataSummaryLength(len, sri.begin(), &srilen))), 1)))"
, "./../../../dom/script/ScriptLoader.cpp", 4883); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(SRICheckDataVerifier::DataSummaryLength(len, sri.begin(), &srilen))), 1)))"
")"); do { MOZ_CrashSequence(__null, 4883); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4884 MOZ_ASSERT(srilen == len)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(srilen == len)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(srilen == len))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("srilen == len",
"./../../../dom/script/ScriptLoader.cpp", 4884); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "srilen == len" ")"); do { MOZ_CrashSequence
(__null, 4884); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4885
4886 MOZ_ASSERT(sri.length() == len)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(sri.length() == len)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(sri.length() == len))), 0)))
{ do { } while (false); MOZ_ReportAssertionFailure("sri.length() == len"
, "./../../../dom/script/ScriptLoader.cpp", 4886); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "sri.length() == len" ")"); do { MOZ_CrashSequence
(__null, 4886); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4887 aRequest->SetSRILength(len);
4888
4889 if (aRequest->GetSRILength() != len) {
4890 // The serialized stencil is aligned in the buffer, and space might be
4891 // reserved for padding after the SRI hash.
4892 if (!sri.resize(aRequest->GetSRILength())) {
4893 return NS_ERROR_OUT_OF_MEMORY;
4894 }
4895 }
4896
4897 return NS_OK;
4898}
4899
4900void ScriptLoader::ReportErrorToConsole(ScriptLoadRequest* aRequest,
4901 nsresult aResult) const {
4902 MOZ_ASSERT(aRequest)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aRequest)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aRequest))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aRequest", "./../../../dom/script/ScriptLoader.cpp"
, 4902); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aRequest" ")"
); do { MOZ_CrashSequence(__null, 4902); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4903
4904 if (aRequest->GetScriptLoadContext()->IsPreload()) {
4905 // Skip reporting errors in preload requests. If the request is actually
4906 // used then we will report the error in ReportPreloadErrorsToConsole below.
4907 aRequest->GetScriptLoadContext()->mUnreportedPreloadError = aResult;
4908 return;
4909 }
4910
4911 if (!mDocument) {
4912 return;
4913 }
4914
4915 bool isScript = !aRequest->IsModuleRequest();
4916 const char* message;
4917 if (aResult == NS_ERROR_MALFORMED_URI) {
4918 message = isScript ? "ScriptSourceMalformed" : "ModuleSourceMalformed";
4919 } else if (aResult == NS_ERROR_DOM_BAD_URI) {
4920 message = isScript ? "ScriptSourceNotAllowed" : "ModuleSourceNotAllowed";
4921 } else if (aResult == NS_ERROR_DOM_WEBEXT_CONTENT_SCRIPT_URI) {
4922 MOZ_ASSERT(!isScript)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!isScript)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!isScript))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("!isScript", "./../../../dom/script/ScriptLoader.cpp"
, 4922); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!isScript" ")"
); do { MOZ_CrashSequence(__null, 4922); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4923 message = "WebExtContentScriptModuleSourceNotAllowed";
4924 } else if (net::ChannelClassifierUtils::IsClassifierBlockingErrorCode(
4925 aResult)) {
4926 // Blocking classifier error codes already show their own console messages.
4927 return;
4928 } else {
4929 message = isScript ? "ScriptSourceLoadFailed" : "ModuleSourceLoadFailed";
4930 }
4931
4932 AutoTArray<nsString, 1> params;
4933 CopyUTF8toUTF16(aRequest->URI()->GetSpecOrDefault(), *params.AppendElement());
4934
4935 Maybe<SourceLocation> loc;
4936 if (!isScript && !aRequest->IsTopLevel()) {
4937 MOZ_ASSERT(aRequest->mReferrer)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aRequest->mReferrer)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aRequest->mReferrer))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("aRequest->mReferrer"
, "./../../../dom/script/ScriptLoader.cpp", 4937); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aRequest->mReferrer" ")"); do { MOZ_CrashSequence
(__null, 4937); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4938 loc.emplace(aRequest->mReferrer.get());
4939 } else {
4940 uint32_t lineNo = aRequest->GetScriptLoadContext()->GetScriptLineNumber();
4941 JS::ColumnNumberOneOrigin columnNo =
4942 aRequest->GetScriptLoadContext()->GetScriptColumnNumber();
4943 loc.emplace(mDocument->GetDocumentURI(), lineNo, columnNo.oneOriginValue());
4944 }
4945
4946 nsContentUtils::ReportToConsole(
4947 nsIScriptError::warningFlag, "Script Loader"_ns, mDocument,
4948 PropertiesFile::DOM_PROPERTIES, message, params, loc.ref());
4949}
4950
4951void ScriptLoader::ReportWarningToConsole(
4952 ScriptLoadRequest* aRequest, const char* aMessageName,
4953 const nsTArray<nsString>& aParams) const {
4954 if (!mDocument) {
4955 return;
4956 }
4957 uint32_t lineNo = aRequest->GetScriptLoadContext()->GetScriptLineNumber();
4958 JS::ColumnNumberOneOrigin columnNo =
4959 aRequest->GetScriptLoadContext()->GetScriptColumnNumber();
4960 nsContentUtils::ReportToConsole(
4961 nsIScriptError::warningFlag, "Script Loader"_ns, mDocument,
4962 PropertiesFile::DOM_PROPERTIES, aMessageName, aParams,
4963 SourceLocation{mDocument->GetDocumentURI(), lineNo,
4964 columnNo.oneOriginValue()});
4965}
4966
4967void ScriptLoader::ReportPreloadErrorsToConsole(ScriptLoadRequest* aRequest) {
4968 if (NS_FAILED(aRequest->GetScriptLoadContext()->mUnreportedPreloadError)((bool)(__builtin_expect(!!(NS_FAILED_impl(aRequest->GetScriptLoadContext
()->mUnreportedPreloadError)), 0)))
) {
4969 ReportErrorToConsole(
4970 aRequest, aRequest->GetScriptLoadContext()->mUnreportedPreloadError);
4971 aRequest->GetScriptLoadContext()->mUnreportedPreloadError = NS_OK;
4972 }
4973
4974 // TODO:
4975 // Bug 1973466, check the child request's error that happened during
4976 // preload is reported.
4977}
4978
4979void ScriptLoader::HandleLoadError(ScriptLoadRequest* aRequest,
4980 nsresult aResult) {
4981 /*
4982 * Handle script not loading error because source was an tracking URL (or
4983 * fingerprinting, cryptomining, etc).
4984 * We make a note of this script node by including it in a dedicated
4985 * array of blocked tracking nodes under its parent document.
4986 */
4987 if (net::ChannelClassifierUtils::IsClassifierBlockingErrorCode(aResult)) {
4988 nsCOMPtr<nsIContent> cont = do_QueryInterface(
4989 aRequest->GetScriptLoadContext()->GetScriptElementForUrlClassifier());
4990 mDocument->AddBlockedNodeByClassifier(cont);
4991 }
4992
4993 bool wasHandled = false;
4994
4995 // A ModuleLoadRequest will be stored either in mDeferRequests or
4996 // mLoadingAsyncRequests, but the onerror handler should be triggered later in
4997 // ProcessRequests, so we handle ModuleLoadRequest before mDeferRequestrs and
4998 // mLoadingAsyncRequests.
4999 if (aRequest->IsModuleRequest()) {
5000 MOZ_ASSERT(!aRequest->GetScriptLoadContext()->mIsInline)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aRequest->GetScriptLoadContext()->mIsInline)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!aRequest->GetScriptLoadContext()->mIsInline))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!aRequest->GetScriptLoadContext()->mIsInline"
, "./../../../dom/script/ScriptLoader.cpp", 5000); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!aRequest->GetScriptLoadContext()->mIsInline"
")"); do { MOZ_CrashSequence(__null, 5000); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5001 wasHandled = true;
5002
5003 ModuleLoadRequest* modReq = aRequest->AsModuleRequest();
5004 modReq->OnFetchComplete(aResult);
5005
5006 MOZ_ASSERT(modReq->IsErrored())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(modReq->IsErrored())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(modReq->IsErrored()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("modReq->IsErrored()"
, "./../../../dom/script/ScriptLoader.cpp", 5006); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "modReq->IsErrored()" ")"); do { MOZ_CrashSequence
(__null, 5006); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
5007 } else if (aRequest->GetScriptLoadContext()->mInDeferList) {
5008 wasHandled = true;
5009 if (aRequest->isInList()) {
5010 RefPtr<ScriptLoadRequest> req = mDeferRequests.Steal(aRequest);
5011 FireScriptAvailable(aResult, req);
5012 }
5013 } else if (aRequest->GetScriptLoadContext()->mInAsyncList) {
5014 wasHandled = true;
5015 if (aRequest->isInList()) {
5016 RefPtr<ScriptLoadRequest> req = mLoadingAsyncRequests.Steal(aRequest);
5017 FireScriptAvailable(aResult, req);
5018 }
5019 }
5020
5021 if (aRequest->GetScriptLoadContext()->mIsNonAsyncScriptInserted) {
5022 if (aRequest->isInList()) {
5023 RefPtr<ScriptLoadRequest> req =
5024 mNonAsyncExternalScriptInsertedRequests.Steal(aRequest);
5025 FireScriptAvailable(aResult, req);
5026 }
5027 } else if (aRequest->GetScriptLoadContext()->mIsXSLT) {
5028 if (aRequest->isInList()) {
5029 RefPtr<ScriptLoadRequest> req = mXSLTRequests.Steal(aRequest);
5030 FireScriptAvailable(aResult, req);
5031 }
5032 } else if (aRequest->GetScriptLoadContext()->IsPreload()) {
5033 if (aRequest->IsTopLevel()) {
5034 // Request may already have been removed by
5035 // CancelAndClearScriptLoadRequests.
5036 mPreloads.RemoveElement(aRequest, PreloadRequestComparator());
5037 }
5038 MOZ_ASSERT(!aRequest->isInList())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aRequest->isInList())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aRequest->isInList()))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("!aRequest->isInList()"
, "./../../../dom/script/ScriptLoader.cpp", 5038); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!aRequest->isInList()" ")"); do { MOZ_CrashSequence
(__null, 5038); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
5039 } else if (mParserBlockingRequest == aRequest) {
5040 MOZ_ASSERT(!aRequest->isInList())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aRequest->isInList())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aRequest->isInList()))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("!aRequest->isInList()"
, "./../../../dom/script/ScriptLoader.cpp", 5040); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!aRequest->isInList()" ")"); do { MOZ_CrashSequence
(__null, 5040); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
5041 mParserBlockingRequest = nullptr;
5042 UnblockParser(aRequest);
5043
5044 // Ensure that we treat the script as our current parser-inserted script
5045 // while firing onerror on it.
5046 MOZ_ASSERT(aRequest->GetScriptLoadContext()->GetParserCreated())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aRequest->GetScriptLoadContext()->GetParserCreated
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aRequest->GetScriptLoadContext()->GetParserCreated
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aRequest->GetScriptLoadContext()->GetParserCreated()"
, "./../../../dom/script/ScriptLoader.cpp", 5046); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aRequest->GetScriptLoadContext()->GetParserCreated()"
")"); do { MOZ_CrashSequence(__null, 5046); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5047 nsCOMPtr<nsIScriptElement> oldParserInsertedScript =
5048 mCurrentParserInsertedScript;
5049 mCurrentParserInsertedScript =
5050 aRequest->GetScriptLoadContext()
5051 ->GetScriptElementForCurrentParserInsertedScript();
5052 FireScriptAvailable(aResult, aRequest);
5053 ContinueParserAsync(aRequest);
5054 mCurrentParserInsertedScript = std::move(oldParserInsertedScript);
5055 } else if (!wasHandled) {
5056 // This happens for blocking requests cancelled by ParsingComplete().
5057 // Ignore cancellation status for link-preload requests, as cancellation can
5058 // be omitted for them when SRI is stronger on consumer tags.
5059 MOZ_ASSERT(aRequest->IsCanceled() ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aRequest->IsCanceled() || aRequest->GetScriptLoadContext
()->IsLinkPreloadScript())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aRequest->IsCanceled() ||
aRequest->GetScriptLoadContext()->IsLinkPreloadScript(
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aRequest->IsCanceled() || aRequest->GetScriptLoadContext()->IsLinkPreloadScript()"
, "./../../../dom/script/ScriptLoader.cpp", 5060); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aRequest->IsCanceled() || aRequest->GetScriptLoadContext()->IsLinkPreloadScript()"
")"); do { MOZ_CrashSequence(__null, 5060); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5060 aRequest->GetScriptLoadContext()->IsLinkPreloadScript())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aRequest->IsCanceled() || aRequest->GetScriptLoadContext
()->IsLinkPreloadScript())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aRequest->IsCanceled() ||
aRequest->GetScriptLoadContext()->IsLinkPreloadScript(
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aRequest->IsCanceled() || aRequest->GetScriptLoadContext()->IsLinkPreloadScript()"
, "./../../../dom/script/ScriptLoader.cpp", 5060); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aRequest->IsCanceled() || aRequest->GetScriptLoadContext()->IsLinkPreloadScript()"
")"); do { MOZ_CrashSequence(__null, 5060); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5061 MOZ_ASSERT(!aRequest->isInList())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aRequest->isInList())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aRequest->isInList()))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("!aRequest->isInList()"
, "./../../../dom/script/ScriptLoader.cpp", 5061); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!aRequest->isInList()" ")"); do { MOZ_CrashSequence
(__null, 5061); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
5062 }
5063}
5064
5065void ScriptLoader::HandleLoadErrorAndProcessPendingRequests(
5066 ScriptLoadRequest* aRequest, nsresult aResult) {
5067 HandleLoadError(aRequest, aResult);
5068 // Process in case some other requests have finished meanwhile.
5069 ProcessPendingRequests();
5070}
5071
5072void ScriptLoader::UnblockParser(ScriptLoadRequest* aParserBlockingRequest) {
5073 aParserBlockingRequest->GetScriptLoadContext()->UnblockParser();
5074}
5075
5076void ScriptLoader::ContinueParserAsync(
5077 ScriptLoadRequest* aParserBlockingRequest) {
5078 aParserBlockingRequest->GetScriptLoadContext()->ContinueParserAsync();
5079}
5080
5081uint32_t ScriptLoader::NumberOfProcessors() {
5082 if (mNumberOfProcessors > 0) {
5083 return mNumberOfProcessors;
5084 }
5085
5086 int32_t numProcs = PR_GetNumberOfProcessors();
5087 if (numProcs > 0) {
5088 mNumberOfProcessors = numProcs;
5089 }
5090 return mNumberOfProcessors;
5091}
5092
5093int32_t ScriptLoader::PhysicalSizeOfMemoryInGB() {
5094 // 0 is a valid result from PR_GetPhysicalMemorySize() which
5095 // means a failure occured.
5096 if (mPhysicalSizeOfMemory >= 0) {
5097 return mPhysicalSizeOfMemory;
5098 }
5099
5100 // Save the size in GB.
5101 mPhysicalSizeOfMemory =
5102 static_cast<int32_t>(PR_GetPhysicalMemorySize() >> 30);
5103 return mPhysicalSizeOfMemory;
5104}
5105
5106bool ScriptLoader::ShouldApplyDelazifyStrategy(ScriptLoadRequest* aRequest) {
5107 // Full parse everything if negative.
5108 if (StaticPrefs::dom_script_loader_delazification_max_size() < 0) {
5109 return true;
5110 }
5111
5112 // Be conservative on machines with 2GB or less of memory.
5113 if (PhysicalSizeOfMemoryInGB() <=
5114 StaticPrefs::dom_script_loader_delazification_min_mem()) {
5115 return false;
5116 }
5117
5118 uint32_t max_size = static_cast<uint32_t>(
5119 StaticPrefs::dom_script_loader_delazification_max_size());
5120 uint32_t script_size =
5121 aRequest->ScriptTextLength() > 0
5122 ? static_cast<uint32_t>(aRequest->ScriptTextLength())
5123 : 0;
5124
5125 if (mTotalFullParseSize + script_size < max_size) {
5126 return true;
5127 }
5128
5129 if (LOG_ENABLED()(__builtin_expect(!!(mozilla::detail::log_test(ScriptLoader::
gScriptLoaderLog, mozilla::LogLevel::Debug)), 0))
) {
5130 nsCString url = aRequest->URI()->GetSpecOrDefault();
5131 LOG(
5132 ("ScriptLoadRequest (%p): non-on-demand-only Parsing Disabled for (%s) "
5133 "with size=%u because mTotalFullParseSize=%u would exceed max_size=%u",
5134 aRequest, url.get(), script_size, mTotalFullParseSize, max_size));
5135 }
5136
5137 return false;
5138}
5139
5140void ScriptLoader::ApplyDelazifyStrategy(JS::CompileOptions* aOptions) {
5141 JS::DelazificationOption strategy =
5142 JS::DelazificationOption::ParseEverythingEagerly;
5143 uint32_t strategyIndex =
5144 StaticPrefs::dom_script_loader_delazification_strategy();
5145
5146 // Assert that all enumerated values of DelazificationOption are dense between
5147 // OnDemandOnly and ParseEverythingEagerly.
5148#ifdef DEBUG1
5149 uint32_t count = 0;
5150 uint32_t mask = 0;
5151# define _COUNT_ENTRIES(Name) count++;
5152# define _MASK_ENTRIES(Name) \
5153 mask |= 1 << uint32_t(JS::DelazificationOption::Name);
5154
5155 FOREACH_DELAZIFICATION_STRATEGY(_COUNT_ENTRIES)_COUNT_ENTRIES(OnDemandOnly) _COUNT_ENTRIES(CheckConcurrentWithOnDemand
) _COUNT_ENTRIES(ConcurrentDepthFirst) _COUNT_ENTRIES(ConcurrentLargeFirst
) _COUNT_ENTRIES(ParseEverythingEagerly)
;
5156 MOZ_ASSERT(count == uint32_t(strategy) + 1)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(count == uint32_t(strategy) + 1)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(count == uint32_t(strategy) +
1))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("count == uint32_t(strategy) + 1", "./../../../dom/script/ScriptLoader.cpp"
, 5156); AnnotateMozCrashReason("MOZ_ASSERT" "(" "count == uint32_t(strategy) + 1"
")"); do { MOZ_CrashSequence(__null, 5156); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5157 FOREACH_DELAZIFICATION_STRATEGY(_MASK_ENTRIES)_MASK_ENTRIES(OnDemandOnly) _MASK_ENTRIES(CheckConcurrentWithOnDemand
) _MASK_ENTRIES(ConcurrentDepthFirst) _MASK_ENTRIES(ConcurrentLargeFirst
) _MASK_ENTRIES(ParseEverythingEagerly)
;
5158 MOZ_ASSERT(((mask + 1) & mask) == 0)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((mask + 1) & mask) == 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(((mask + 1) & mask) == 0
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"((mask + 1) & mask) == 0", "./../../../dom/script/ScriptLoader.cpp"
, 5158); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((mask + 1) & mask) == 0"
")"); do { MOZ_CrashSequence(__null, 5158); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5159# undef _COUNT_ENTRIES
5160# undef _MASK_ENTRIES
5161#endif
5162
5163 // Any strategy index larger than ParseEverythingEagerly would default to
5164 // ParseEverythingEagerly.
5165 if (strategyIndex <= uint32_t(strategy)) {
5166 strategy = JS::DelazificationOption(uint8_t(strategyIndex));
5167 }
5168
5169 aOptions->setEagerDelazificationStrategy(strategy);
5170}
5171
5172bool ScriptLoader::ShouldCompileOffThread(ScriptLoadRequest* aRequest) {
5173 if (NumberOfProcessors() <= 1) {
5174 return false;
5175 }
5176 if (aRequest == mParserBlockingRequest) {
5177 return true;
5178 }
5179 if (SpeculativeOMTParsingEnabled()) {
5180 // Processing non async inserted scripts too early can potentially delay the
5181 // load event from firing so focus on other scripts instead.
5182 if (aRequest->GetScriptLoadContext()->mIsNonAsyncScriptInserted &&
5183 !StaticPrefs::
5184 dom_script_loader_external_scripts_speculate_non_parser_inserted_enabled()) {
5185 return false;
5186 }
5187
5188 // Async and link preload scripts do not need to be parsed right away.
5189 if (aRequest->GetScriptLoadContext()->IsAsyncScript() &&
5190 !StaticPrefs::
5191 dom_script_loader_external_scripts_speculate_async_enabled()) {
5192 return false;
5193 }
5194
5195 if (aRequest->GetScriptLoadContext()->IsLinkPreloadScript() &&
5196 !StaticPrefs::
5197 dom_script_loader_external_scripts_speculate_link_preload_enabled()) {
5198 return false;
5199 }
5200
5201 return true;
5202 }
5203 return false;
5204}
5205
5206static bool MimeTypeMatchesExpectedModuleType(
5207 nsIChannel* aChannel, JS::ModuleType expectedModuleType) {
5208 nsAutoCString mimeType;
5209 aChannel->GetContentType(mimeType);
5210 NS_ConvertUTF8toUTF16 typeString(mimeType);
5211
5212 switch (expectedModuleType) {
5213 case JS::ModuleType::JavaScriptOrWasm:
5214#ifdef NIGHTLY_BUILD1
5215 if (StaticPrefs::javascript_options_experimental_wasm_esm_integration()) {
5216 return nsContentUtils::IsJavascriptMIMEType(typeString) ||
5217 nsContentUtils::HasWasmMimeTypeEssence(typeString);
5218 }
5219#endif
5220 return nsContentUtils::IsJavascriptMIMEType(typeString);
5221 case JS::ModuleType::JSON:
5222 return nsContentUtils::IsJsonMimeType(typeString);
5223 case JS::ModuleType::CSS:
5224 return nsContentUtils::HasCssMimeTypeEssence(typeString);
5225 case JS::ModuleType::Text:
5226 return true;
5227 case JS::ModuleType::Unknown:
5228 case JS::ModuleType::Bytes:
5229 break;
5230 }
5231
5232 return false;
5233}
5234
5235nsresult ScriptLoader::PrepareLoadedRequest(ScriptLoadRequest* aRequest,
5236 nsIChannel* aChannel,
5237 nsresult aStatus) {
5238 PROFILER_MARKER("ScriptLoader::PrepareLoadedRequest", JS,do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("ScriptLoader::PrepareLoadedRequest", ::geckoprofiler::category
::JS, {mozilla::MarkerStack::Capture()}, ::geckoprofiler::markers
::FlowMarker{}, Flow::FromPointer(aRequest)); } } while (false
); } while (false)
5239 {mozilla::MarkerStack::Capture()}, FlowMarker,do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("ScriptLoader::PrepareLoadedRequest", ::geckoprofiler::category
::JS, {mozilla::MarkerStack::Capture()}, ::geckoprofiler::markers
::FlowMarker{}, Flow::FromPointer(aRequest)); } } while (false
); } while (false)
5240 Flow::FromPointer(aRequest))do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("ScriptLoader::PrepareLoadedRequest", ::geckoprofiler::category
::JS, {mozilla::MarkerStack::Capture()}, ::geckoprofiler::markers
::FlowMarker{}, Flow::FromPointer(aRequest)); } } while (false
); } while (false)
;
5241
5242 if (NS_FAILED(aStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(aStatus)), 0)))) {
5243 return aStatus;
5244 }
5245
5246 MOZ_ASSERT(aRequest->IsFetching())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aRequest->IsFetching())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aRequest->IsFetching())))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("aRequest->IsFetching()"
, "./../../../dom/script/ScriptLoader.cpp", 5246); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aRequest->IsFetching()" ")"); do { MOZ_CrashSequence
(__null, 5246); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
5247 CollectScriptTelemetry(aRequest);
5248
5249 // If we don't have a document, then we need to abort further
5250 // evaluation.
5251 if (!mDocument) {
5252 return NS_ERROR_NOT_AVAILABLE;
5253 }
5254
5255 // If the load returned an error page, then we need to abort
5256 if (nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aChannel)) {
5257 bool requestSucceeded;
5258 if (NS_SUCCEEDED(httpChannel->GetRequestSucceeded(&requestSucceeded))((bool)(__builtin_expect(!!(!NS_FAILED_impl(httpChannel->GetRequestSucceeded
(&requestSucceeded))), 1)))
&&
5259 !requestSucceeded) {
5260 return NS_ERROR_NOT_AVAILABLE;
5261 }
5262
5263 if (aRequest->IsModuleRequest()) {
5264 // https://html.spec.whatwg.org/multipage/webappapis.html#fetch-a-single-module-script
5265 // Update script's referrer-policy if there's a Referrer-Policy header in
5266 // the HTTP response.
5267 ReferrerPolicy policy =
5268 nsContentUtils::GetReferrerPolicyFromChannel(httpChannel);
5269 if (policy != ReferrerPolicy::_empty) {
5270 aRequest->AsModuleRequest()->UpdateReferrerPolicy(policy);
5271 }
5272 }
5273
5274 nsAutoCString sourceMapURL;
5275 if (nsContentUtils::GetSourceMapURL(httpChannel, sourceMapURL)) {
5276 aRequest->SetSourceMapURL(NS_ConvertUTF8toUTF16(sourceMapURL));
5277 }
5278
5279 nsCOMPtr<nsIClassifiedChannel> classifiedChannel =
5280 do_QueryInterface(aChannel);
5281 MOZ_ASSERT(classifiedChannel)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(classifiedChannel)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(classifiedChannel))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("classifiedChannel"
, "./../../../dom/script/ScriptLoader.cpp", 5281); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "classifiedChannel" ")"); do { MOZ_CrashSequence
(__null, 5281); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
5282 if (classifiedChannel &&
5283 classifiedChannel->IsThirdPartyTrackingResource()) {
5284 net::ClassificationFlags flags{
5285 classifiedChannel->GetFirstPartyClassificationFlags(),
5286 classifiedChannel->GetThirdPartyClassificationFlags()};
5287 aRequest->GetScriptLoadContext()->SetClassificationFlags(flags);
5288 }
5289 }
5290
5291 // If this load was subject to a CORS check, don't flag it with a separate
5292 // origin principal, so that it will treat our document's principal as the
5293 // origin principal. Module loads always use CORS.
5294 if (!aRequest->IsModuleRequest() && aRequest->CORSMode() == CORS_NONE) {
5295 MOZ_TRY(nsContentUtils::GetSecurityManager()->GetChannelResultPrincipal(__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult
(nsContentUtils::GetSecurityManager()->GetChannelResultPrincipal
( aChannel, getter_AddRefs(aRequest->mOriginPrincipal))); if
((__builtin_expect(!!(mozTryVarTempResult.isErr()), 0))) { return
mozTryVarTempResult.propagateErr(); } mozTryVarTempResult.unwrap
(); })
5296 aChannel, getter_AddRefs(aRequest->mOriginPrincipal)))__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult
(nsContentUtils::GetSecurityManager()->GetChannelResultPrincipal
( aChannel, getter_AddRefs(aRequest->mOriginPrincipal))); if
((__builtin_expect(!!(mozTryVarTempResult.isErr()), 0))) { return
mozTryVarTempResult.propagateErr(); } mozTryVarTempResult.unwrap
(); })
;
5297 }
5298
5299 // This assertion could fire errorously if we ran out of memory when
5300 // inserting the request in the array. However it's an unlikely case
5301 // so if you see this assertion it is likely something else that is
5302 // wrong, especially if you see it more than once.
5303 NS_ASSERTION(mDeferRequests.Contains(aRequest) ||do { if (!(mDeferRequests.Contains(aRequest) || mLoadingAsyncRequests
.Contains(aRequest) || mNonAsyncExternalScriptInsertedRequests
.Contains(aRequest) || mXSLTRequests.Contains(aRequest) || (aRequest
->IsModuleRequest() && (aRequest->AsModuleRequest
()->IsRegisteredDynamicImport() || !aRequest->AsModuleRequest
()->IsTopLevel())) || mPreloads.Contains(aRequest, PreloadRequestComparator
()) || mParserBlockingRequest == aRequest)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "aRequest should be pending!", "mDeferRequests.Contains(aRequest) || mLoadingAsyncRequests.Contains(aRequest) || mNonAsyncExternalScriptInsertedRequests.Contains(aRequest) || mXSLTRequests.Contains(aRequest) || (aRequest->IsModuleRequest() && (aRequest->AsModuleRequest()->IsRegisteredDynamicImport() || !aRequest->AsModuleRequest()->IsTopLevel())) || mPreloads.Contains(aRequest, PreloadRequestComparator()) || mParserBlockingRequest == aRequest"
, "./../../../dom/script/ScriptLoader.cpp", 5312); MOZ_PretendNoReturn
(); } } while (0)
5304 mLoadingAsyncRequests.Contains(aRequest) ||do { if (!(mDeferRequests.Contains(aRequest) || mLoadingAsyncRequests
.Contains(aRequest) || mNonAsyncExternalScriptInsertedRequests
.Contains(aRequest) || mXSLTRequests.Contains(aRequest) || (aRequest
->IsModuleRequest() && (aRequest->AsModuleRequest
()->IsRegisteredDynamicImport() || !aRequest->AsModuleRequest
()->IsTopLevel())) || mPreloads.Contains(aRequest, PreloadRequestComparator
()) || mParserBlockingRequest == aRequest)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "aRequest should be pending!", "mDeferRequests.Contains(aRequest) || mLoadingAsyncRequests.Contains(aRequest) || mNonAsyncExternalScriptInsertedRequests.Contains(aRequest) || mXSLTRequests.Contains(aRequest) || (aRequest->IsModuleRequest() && (aRequest->AsModuleRequest()->IsRegisteredDynamicImport() || !aRequest->AsModuleRequest()->IsTopLevel())) || mPreloads.Contains(aRequest, PreloadRequestComparator()) || mParserBlockingRequest == aRequest"
, "./../../../dom/script/ScriptLoader.cpp", 5312); MOZ_PretendNoReturn
(); } } while (0)
5305 mNonAsyncExternalScriptInsertedRequests.Contains(aRequest) ||do { if (!(mDeferRequests.Contains(aRequest) || mLoadingAsyncRequests
.Contains(aRequest) || mNonAsyncExternalScriptInsertedRequests
.Contains(aRequest) || mXSLTRequests.Contains(aRequest) || (aRequest
->IsModuleRequest() && (aRequest->AsModuleRequest
()->IsRegisteredDynamicImport() || !aRequest->AsModuleRequest
()->IsTopLevel())) || mPreloads.Contains(aRequest, PreloadRequestComparator
()) || mParserBlockingRequest == aRequest)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "aRequest should be pending!", "mDeferRequests.Contains(aRequest) || mLoadingAsyncRequests.Contains(aRequest) || mNonAsyncExternalScriptInsertedRequests.Contains(aRequest) || mXSLTRequests.Contains(aRequest) || (aRequest->IsModuleRequest() && (aRequest->AsModuleRequest()->IsRegisteredDynamicImport() || !aRequest->AsModuleRequest()->IsTopLevel())) || mPreloads.Contains(aRequest, PreloadRequestComparator()) || mParserBlockingRequest == aRequest"
, "./../../../dom/script/ScriptLoader.cpp", 5312); MOZ_PretendNoReturn
(); } } while (0)
5306 mXSLTRequests.Contains(aRequest) ||do { if (!(mDeferRequests.Contains(aRequest) || mLoadingAsyncRequests
.Contains(aRequest) || mNonAsyncExternalScriptInsertedRequests
.Contains(aRequest) || mXSLTRequests.Contains(aRequest) || (aRequest
->IsModuleRequest() && (aRequest->AsModuleRequest
()->IsRegisteredDynamicImport() || !aRequest->AsModuleRequest
()->IsTopLevel())) || mPreloads.Contains(aRequest, PreloadRequestComparator
()) || mParserBlockingRequest == aRequest)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "aRequest should be pending!", "mDeferRequests.Contains(aRequest) || mLoadingAsyncRequests.Contains(aRequest) || mNonAsyncExternalScriptInsertedRequests.Contains(aRequest) || mXSLTRequests.Contains(aRequest) || (aRequest->IsModuleRequest() && (aRequest->AsModuleRequest()->IsRegisteredDynamicImport() || !aRequest->AsModuleRequest()->IsTopLevel())) || mPreloads.Contains(aRequest, PreloadRequestComparator()) || mParserBlockingRequest == aRequest"
, "./../../../dom/script/ScriptLoader.cpp", 5312); MOZ_PretendNoReturn
(); } } while (0)
5307 (aRequest->IsModuleRequest() &&do { if (!(mDeferRequests.Contains(aRequest) || mLoadingAsyncRequests
.Contains(aRequest) || mNonAsyncExternalScriptInsertedRequests
.Contains(aRequest) || mXSLTRequests.Contains(aRequest) || (aRequest
->IsModuleRequest() && (aRequest->AsModuleRequest
()->IsRegisteredDynamicImport() || !aRequest->AsModuleRequest
()->IsTopLevel())) || mPreloads.Contains(aRequest, PreloadRequestComparator
()) || mParserBlockingRequest == aRequest)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "aRequest should be pending!", "mDeferRequests.Contains(aRequest) || mLoadingAsyncRequests.Contains(aRequest) || mNonAsyncExternalScriptInsertedRequests.Contains(aRequest) || mXSLTRequests.Contains(aRequest) || (aRequest->IsModuleRequest() && (aRequest->AsModuleRequest()->IsRegisteredDynamicImport() || !aRequest->AsModuleRequest()->IsTopLevel())) || mPreloads.Contains(aRequest, PreloadRequestComparator()) || mParserBlockingRequest == aRequest"
, "./../../../dom/script/ScriptLoader.cpp", 5312); MOZ_PretendNoReturn
(); } } while (0)
5308 (aRequest->AsModuleRequest()->IsRegisteredDynamicImport() ||do { if (!(mDeferRequests.Contains(aRequest) || mLoadingAsyncRequests
.Contains(aRequest) || mNonAsyncExternalScriptInsertedRequests
.Contains(aRequest) || mXSLTRequests.Contains(aRequest) || (aRequest
->IsModuleRequest() && (aRequest->AsModuleRequest
()->IsRegisteredDynamicImport() || !aRequest->AsModuleRequest
()->IsTopLevel())) || mPreloads.Contains(aRequest, PreloadRequestComparator
()) || mParserBlockingRequest == aRequest)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "aRequest should be pending!", "mDeferRequests.Contains(aRequest) || mLoadingAsyncRequests.Contains(aRequest) || mNonAsyncExternalScriptInsertedRequests.Contains(aRequest) || mXSLTRequests.Contains(aRequest) || (aRequest->IsModuleRequest() && (aRequest->AsModuleRequest()->IsRegisteredDynamicImport() || !aRequest->AsModuleRequest()->IsTopLevel())) || mPreloads.Contains(aRequest, PreloadRequestComparator()) || mParserBlockingRequest == aRequest"
, "./../../../dom/script/ScriptLoader.cpp", 5312); MOZ_PretendNoReturn
(); } } while (0)
5309 !aRequest->AsModuleRequest()->IsTopLevel())) ||do { if (!(mDeferRequests.Contains(aRequest) || mLoadingAsyncRequests
.Contains(aRequest) || mNonAsyncExternalScriptInsertedRequests
.Contains(aRequest) || mXSLTRequests.Contains(aRequest) || (aRequest
->IsModuleRequest() && (aRequest->AsModuleRequest
()->IsRegisteredDynamicImport() || !aRequest->AsModuleRequest
()->IsTopLevel())) || mPreloads.Contains(aRequest, PreloadRequestComparator
()) || mParserBlockingRequest == aRequest)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "aRequest should be pending!", "mDeferRequests.Contains(aRequest) || mLoadingAsyncRequests.Contains(aRequest) || mNonAsyncExternalScriptInsertedRequests.Contains(aRequest) || mXSLTRequests.Contains(aRequest) || (aRequest->IsModuleRequest() && (aRequest->AsModuleRequest()->IsRegisteredDynamicImport() || !aRequest->AsModuleRequest()->IsTopLevel())) || mPreloads.Contains(aRequest, PreloadRequestComparator()) || mParserBlockingRequest == aRequest"
, "./../../../dom/script/ScriptLoader.cpp", 5312); MOZ_PretendNoReturn
(); } } while (0)
5310 mPreloads.Contains(aRequest, PreloadRequestComparator()) ||do { if (!(mDeferRequests.Contains(aRequest) || mLoadingAsyncRequests
.Contains(aRequest) || mNonAsyncExternalScriptInsertedRequests
.Contains(aRequest) || mXSLTRequests.Contains(aRequest) || (aRequest
->IsModuleRequest() && (aRequest->AsModuleRequest
()->IsRegisteredDynamicImport() || !aRequest->AsModuleRequest
()->IsTopLevel())) || mPreloads.Contains(aRequest, PreloadRequestComparator
()) || mParserBlockingRequest == aRequest)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "aRequest should be pending!", "mDeferRequests.Contains(aRequest) || mLoadingAsyncRequests.Contains(aRequest) || mNonAsyncExternalScriptInsertedRequests.Contains(aRequest) || mXSLTRequests.Contains(aRequest) || (aRequest->IsModuleRequest() && (aRequest->AsModuleRequest()->IsRegisteredDynamicImport() || !aRequest->AsModuleRequest()->IsTopLevel())) || mPreloads.Contains(aRequest, PreloadRequestComparator()) || mParserBlockingRequest == aRequest"
, "./../../../dom/script/ScriptLoader.cpp", 5312); MOZ_PretendNoReturn
(); } } while (0)
5311 mParserBlockingRequest == aRequest,do { if (!(mDeferRequests.Contains(aRequest) || mLoadingAsyncRequests
.Contains(aRequest) || mNonAsyncExternalScriptInsertedRequests
.Contains(aRequest) || mXSLTRequests.Contains(aRequest) || (aRequest
->IsModuleRequest() && (aRequest->AsModuleRequest
()->IsRegisteredDynamicImport() || !aRequest->AsModuleRequest
()->IsTopLevel())) || mPreloads.Contains(aRequest, PreloadRequestComparator
()) || mParserBlockingRequest == aRequest)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "aRequest should be pending!", "mDeferRequests.Contains(aRequest) || mLoadingAsyncRequests.Contains(aRequest) || mNonAsyncExternalScriptInsertedRequests.Contains(aRequest) || mXSLTRequests.Contains(aRequest) || (aRequest->IsModuleRequest() && (aRequest->AsModuleRequest()->IsRegisteredDynamicImport() || !aRequest->AsModuleRequest()->IsTopLevel())) || mPreloads.Contains(aRequest, PreloadRequestComparator()) || mParserBlockingRequest == aRequest"
, "./../../../dom/script/ScriptLoader.cpp", 5312); MOZ_PretendNoReturn
(); } } while (0)
5312 "aRequest should be pending!")do { if (!(mDeferRequests.Contains(aRequest) || mLoadingAsyncRequests
.Contains(aRequest) || mNonAsyncExternalScriptInsertedRequests
.Contains(aRequest) || mXSLTRequests.Contains(aRequest) || (aRequest
->IsModuleRequest() && (aRequest->AsModuleRequest
()->IsRegisteredDynamicImport() || !aRequest->AsModuleRequest
()->IsTopLevel())) || mPreloads.Contains(aRequest, PreloadRequestComparator
()) || mParserBlockingRequest == aRequest)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "aRequest should be pending!", "mDeferRequests.Contains(aRequest) || mLoadingAsyncRequests.Contains(aRequest) || mNonAsyncExternalScriptInsertedRequests.Contains(aRequest) || mXSLTRequests.Contains(aRequest) || (aRequest->IsModuleRequest() && (aRequest->AsModuleRequest()->IsRegisteredDynamicImport() || !aRequest->AsModuleRequest()->IsTopLevel())) || mPreloads.Contains(aRequest, PreloadRequestComparator()) || mParserBlockingRequest == aRequest"
, "./../../../dom/script/ScriptLoader.cpp", 5312); MOZ_PretendNoReturn
(); } } while (0)
;
5313
5314 nsCOMPtr<nsIURI> uri;
5315 MOZ_TRY(aChannel->GetOriginalURI(getter_AddRefs(uri)))__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult
(aChannel->GetOriginalURI(getter_AddRefs(uri))); if ((__builtin_expect
(!!(mozTryVarTempResult.isErr()), 0))) { return mozTryVarTempResult
.propagateErr(); } mozTryVarTempResult.unwrap(); })
;
5316
5317 aRequest->SetBaseURLFromChannelAndOriginalURI(aChannel, uri);
5318
5319 if (aRequest->IsModuleRequest()) {
5320 ModuleLoadRequest* request = aRequest->AsModuleRequest();
5321
5322 // When loading a module, only responses with an expected MIME type are
5323 // acceptable.
5324 if (!MimeTypeMatchesExpectedModuleType(aChannel, request->mModuleType)) {
5325 if (LOG_ENABLED()(__builtin_expect(!!(mozilla::detail::log_test(ScriptLoader::
gScriptLoaderLog, mozilla::LogLevel::Debug)), 0))
) {
5326 nsAutoCString spec;
5327 uri->GetAsciiSpec(spec);
5328 LOG(
5329 ("ScriptLoadRequest (%p): MimeTypeMatchesExpectedModuleType check "
5330 "failed for: %s",
5331 aRequest, spec.get()));
5332 }
5333 return NS_ERROR_FAILURE;
5334 }
5335
5336 // Attempt to compile off main thread.
5337 bool couldCompile = false;
5338 MOZ_TRY(AttemptOffThreadScriptCompile(request, &couldCompile))__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult
(AttemptOffThreadScriptCompile(request, &couldCompile)); if
((__builtin_expect(!!(mozTryVarTempResult.isErr()), 0))) { return
mozTryVarTempResult.propagateErr(); } mozTryVarTempResult.unwrap
(); })
;
5339 if (couldCompile) {
5340 return NS_OK;
5341 }
5342
5343 // Otherwise compile it right away and start fetching descendents.
5344 return request->OnFetchComplete(NS_OK);
5345 }
5346
5347 // The script is now loaded and ready to run.
5348 aRequest->SetReady();
5349
5350 // If speculative parsing is enabled attempt to compile all
5351 // external scripts off-main-thread. Otherwise, only omt compile scripts
5352 // blocking the parser.
5353 if (ShouldCompileOffThread(aRequest)) {
5354 MOZ_ASSERT(!aRequest->IsModuleRequest())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aRequest->IsModuleRequest())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aRequest->IsModuleRequest
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!aRequest->IsModuleRequest()", "./../../../dom/script/ScriptLoader.cpp"
, 5354); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aRequest->IsModuleRequest()"
")"); do { MOZ_CrashSequence(__null, 5354); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5355 bool couldCompile = false;
5356 MOZ_TRY(AttemptOffThreadScriptCompile(aRequest, &couldCompile))__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult
(AttemptOffThreadScriptCompile(aRequest, &couldCompile));
if ((__builtin_expect(!!(mozTryVarTempResult.isErr()), 0))) {
return mozTryVarTempResult.propagateErr(); } mozTryVarTempResult
.unwrap(); })
;
5357 if (couldCompile) {
5358 MOZ_ASSERT(aRequest->mState == ScriptLoadRequest::State::Compiling,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aRequest->mState == ScriptLoadRequest::State::Compiling
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aRequest->mState == ScriptLoadRequest::State::Compiling
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"aRequest->mState == ScriptLoadRequest::State::Compiling" " ("
"Request should be off-thread compiling now." ")", "./../../../dom/script/ScriptLoader.cpp"
, 5359); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aRequest->mState == ScriptLoadRequest::State::Compiling"
") (" "Request should be off-thread compiling now." ")"); do
{ MOZ_CrashSequence(__null, 5359); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
5359 "Request should be off-thread compiling now.")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aRequest->mState == ScriptLoadRequest::State::Compiling
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aRequest->mState == ScriptLoadRequest::State::Compiling
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"aRequest->mState == ScriptLoadRequest::State::Compiling" " ("
"Request should be off-thread compiling now." ")", "./../../../dom/script/ScriptLoader.cpp"
, 5359); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aRequest->mState == ScriptLoadRequest::State::Compiling"
") (" "Request should be off-thread compiling now." ")"); do
{ MOZ_CrashSequence(__null, 5359); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
5360 return NS_OK;
5361 }
5362
5363 // If off-thread compile was rejected, continue with regular processing.
5364 }
5365
5366 MaybeMoveToLoadedList(aRequest);
5367
5368 return NS_OK;
5369}
5370
5371void ScriptLoader::DeferCheckpointReached() {
5372 if (mDeferEnabled) {
5373 // Have to check because we apparently get ParsingComplete
5374 // without BeginDeferringScripts in some cases
5375 mDeferCheckpointReached = true;
5376 }
5377
5378 mDeferEnabled = false;
5379 ProcessPendingRequests();
5380}
5381
5382void ScriptLoader::ParsingComplete(bool aTerminated) {
5383 if (aTerminated) {
5384 CancelAndClearScriptLoadRequests();
5385
5386 // Have to call this even if aTerminated so we'll correctly unblock onload.
5387 DeferCheckpointReached();
5388 }
5389}
5390
5391void ScriptLoader::PreloadURI(
5392 nsIURI* aURI, const nsAString& aCharset, const nsAString& aType,
5393 const nsAString& aCrossOrigin, const nsAString& aNonce,
5394 const nsAString& aFetchPriority, const nsAString& aIntegrity,
5395 bool aScriptFromHead, bool aAsync, bool aDefer, bool aLinkPreload,
5396 const ReferrerPolicy aReferrerPolicy, uint64_t aEarlyHintPreloaderId) {
5397 NS_ENSURE_TRUE_VOID(mDocument)do { if ((__builtin_expect(!!(!(mDocument)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mDocument" ") failed", nullptr
, "./../../../dom/script/ScriptLoader.cpp", 5397); return; } }
while (false)
;
5398 // Check to see if scripts has been turned off.
5399 if (!mEnabled || !mDocument->IsScriptEnabled()) {
5400 return;
5401 }
5402
5403 ScriptKind scriptKind = ScriptKind::eClassic;
5404
5405 static const char kASCIIWhitespace[] = "\t\n\f\r ";
5406
5407 nsAutoString type(aType);
5408 type.Trim(kASCIIWhitespace);
5409 if (type.LowerCaseEqualsASCII("module")) {
5410 scriptKind = ScriptKind::eModule;
5411 }
5412
5413 if (scriptKind == ScriptKind::eClassic && !aType.IsEmpty() &&
5414 !nsContentUtils::IsJavascriptMIMEType(aType)) {
5415 // Unknown type. Don't load it.
5416 return;
5417 }
5418
5419 SRIMetadata sriMetadata;
5420 GetSRIMetadata(aIntegrity, &sriMetadata);
5421 if (aIntegrity.IsVoid() && scriptKind == ScriptKind::eModule) {
5422 mModuleLoader->GetImportMapSRI(aURI, mDocument->GetDocumentURIAsReferrer(),
5423 mReporter, &sriMetadata);
5424 }
5425
5426 const auto requestPriority = FetchPriorityToRequestPriority(
5427 nsGenericHTMLElement::ToFetchPriority(aFetchPriority));
5428
5429 // For link type "modulepreload":
5430 // https://html.spec.whatwg.org/multipage/links.html#link-type-modulepreload
5431 // Step 11. Let options be a script fetch options whose cryptographic nonce is
5432 // cryptographic nonce, integrity metadata is integrity metadata, parser
5433 // metadata is "not-parser-inserted", credentials mode is credentials mode,
5434 // referrer policy is referrer policy, and fetch priority is fetch priority.
5435 //
5436 // We treat speculative <script> loads as parser-inserted, because they
5437 // come from a parser. This will also match how they should be treated
5438 // as a normal load.
5439 RefPtr<ScriptLoadRequest> request = CreateLoadRequest(
5440 scriptKind, aURI, nullptr, VoidString(), mDocument->NodePrincipal(),
5441 Element::StringToCORSMode(aCrossOrigin), aNonce, requestPriority,
5442 sriMetadata, aReferrerPolicy,
5443 aLinkPreload ? ParserMetadata::NotParserInserted
5444 : ParserMetadata::ParserInserted,
5445 ScriptLoadRequestType::Preload);
5446 request->GetScriptLoadContext()->mIsInline = false;
5447 request->GetScriptLoadContext()->mScriptFromHead = aScriptFromHead;
5448 request->GetScriptLoadContext()->SetScriptMode(aDefer, aAsync, aLinkPreload);
5449 request->GetScriptLoadContext()->SetIsPreloadRequest();
5450 request->mEarlyHintPreloaderId = aEarlyHintPreloaderId;
5451
5452 if (LOG_ENABLED()(__builtin_expect(!!(mozilla::detail::log_test(ScriptLoader::
gScriptLoaderLog, mozilla::LogLevel::Debug)), 0))
) {
5453 nsAutoCString url;
5454 aURI->GetAsciiSpec(url);
5455 LOG(("ScriptLoadRequest (%p): Created preload request for %s",
5456 request.get(), url.get()));
5457 }
5458
5459 nsAutoString charset(aCharset);
5460 nsresult rv = StartLoad(request, Some(charset));
5461 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
5462 return;
5463 }
5464
5465 // For a <link rel="modulepreload">, if the module is already fetching,
5466 // fetched, or in the in-memory navigation cache, no channel is created for a
5467 // network request, and so StartLoadInternal has not registered the request
5468 // with the PreloadService. We use context->Channel() to identify these cases,
5469 // and have to register before we return: PreloadService::PreloadOrCoalesce
5470 // looks the preload up by key right after this and would otherwise find
5471 // nothing and fire a spurious error event.
5472 if (request->IsModuleRequest()) {
5473 ModuleLoadRequest* moduleRequest = request->AsModuleRequest();
5474 ScriptLoadContext* context = moduleRequest->GetScriptLoadContext();
5475 MOZ_ASSERT_IF(moduleRequest->IsRetrievedFromMemoryCache(),do { if (moduleRequest->IsRetrievedFromMemoryCache()) { do
{ static_assert( mozilla::detail::AssertionConditionType<
decltype(!context->Channel())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!context->Channel()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("!context->Channel()"
, "./../../../dom/script/ScriptLoader.cpp", 5476); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!context->Channel()" ")"); do { MOZ_CrashSequence
(__null, 5476); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false); } } while (false)
5476 !context->Channel())do { if (moduleRequest->IsRetrievedFromMemoryCache()) { do
{ static_assert( mozilla::detail::AssertionConditionType<
decltype(!context->Channel())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!context->Channel()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("!context->Channel()"
, "./../../../dom/script/ScriptLoader.cpp", 5476); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!context->Channel()" ")"); do { MOZ_CrashSequence
(__null, 5476); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false); } } while (false)
;
5477 if (context->IsLinkPreloadScript() && !context->Channel()) {
5478 NotifyPreloadCoalescing(moduleRequest);
5479 }
5480 }
5481
5482 PreloadInfo* pi = mPreloads.AppendElement();
5483 pi->mRequest = request;
5484 pi->mCharset = aCharset;
5485}
5486
5487void ScriptLoader::AddDeferRequest(ScriptLoadRequest* aRequest) {
5488 MOZ_ASSERT(aRequest->GetScriptLoadContext()->IsDeferredScript())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aRequest->GetScriptLoadContext()->IsDeferredScript
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aRequest->GetScriptLoadContext()->IsDeferredScript
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aRequest->GetScriptLoadContext()->IsDeferredScript()"
, "./../../../dom/script/ScriptLoader.cpp", 5488); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aRequest->GetScriptLoadContext()->IsDeferredScript()"
")"); do { MOZ_CrashSequence(__null, 5488); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5489 MOZ_ASSERT(!aRequest->GetScriptLoadContext()->mInDeferList &&do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aRequest->GetScriptLoadContext()->mInDeferList
&& !aRequest->GetScriptLoadContext()->mInAsyncList
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!aRequest->GetScriptLoadContext()->mInDeferList
&& !aRequest->GetScriptLoadContext()->mInAsyncList
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"!aRequest->GetScriptLoadContext()->mInDeferList && !aRequest->GetScriptLoadContext()->mInAsyncList"
, "./../../../dom/script/ScriptLoader.cpp", 5490); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!aRequest->GetScriptLoadContext()->mInDeferList && !aRequest->GetScriptLoadContext()->mInAsyncList"
")"); do { MOZ_CrashSequence(__null, 5490); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5490 !aRequest->GetScriptLoadContext()->mInAsyncList)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aRequest->GetScriptLoadContext()->mInDeferList
&& !aRequest->GetScriptLoadContext()->mInAsyncList
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!aRequest->GetScriptLoadContext()->mInDeferList
&& !aRequest->GetScriptLoadContext()->mInAsyncList
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"!aRequest->GetScriptLoadContext()->mInDeferList && !aRequest->GetScriptLoadContext()->mInAsyncList"
, "./../../../dom/script/ScriptLoader.cpp", 5490); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!aRequest->GetScriptLoadContext()->mInDeferList && !aRequest->GetScriptLoadContext()->mInAsyncList"
")"); do { MOZ_CrashSequence(__null, 5490); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5491 MOZ_ASSERT(!aRequest->GetScriptLoadContext()->mInCompilingList)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aRequest->GetScriptLoadContext()->mInCompilingList
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!aRequest->GetScriptLoadContext()->mInCompilingList
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"!aRequest->GetScriptLoadContext()->mInCompilingList", "./../../../dom/script/ScriptLoader.cpp"
, 5491); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aRequest->GetScriptLoadContext()->mInCompilingList"
")"); do { MOZ_CrashSequence(__null, 5491); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5492
5493 aRequest->GetScriptLoadContext()->mInDeferList = true;
5494 mDeferRequests.AppendElement(aRequest);
5495 if (mDeferEnabled && aRequest == mDeferRequests.getFirst() && mDocument &&
5496 !mBlockingDOMContentLoaded) {
5497 MOZ_ASSERT(mDocument->GetReadyStateEnum() == Document::READYSTATE_LOADING)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mDocument->GetReadyStateEnum() == Document::READYSTATE_LOADING
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(mDocument->GetReadyStateEnum() == Document::READYSTATE_LOADING
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"mDocument->GetReadyStateEnum() == Document::READYSTATE_LOADING"
, "./../../../dom/script/ScriptLoader.cpp", 5497); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "mDocument->GetReadyStateEnum() == Document::READYSTATE_LOADING"
")"); do { MOZ_CrashSequence(__null, 5497); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5498 mBlockingDOMContentLoaded = true;
5499 mDocument->BlockDOMContentLoaded();
5500 }
5501}
5502
5503void ScriptLoader::AddAsyncRequest(ScriptLoadRequest* aRequest) {
5504 MOZ_ASSERT(aRequest->GetScriptLoadContext()->IsAsyncScript())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aRequest->GetScriptLoadContext()->IsAsyncScript
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aRequest->GetScriptLoadContext()->IsAsyncScript
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aRequest->GetScriptLoadContext()->IsAsyncScript()", "./../../../dom/script/ScriptLoader.cpp"
, 5504); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aRequest->GetScriptLoadContext()->IsAsyncScript()"
")"); do { MOZ_CrashSequence(__null, 5504); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5505 MOZ_ASSERT(!aRequest->GetScriptLoadContext()->mInDeferList &&do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aRequest->GetScriptLoadContext()->mInDeferList
&& !aRequest->GetScriptLoadContext()->mInAsyncList
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!aRequest->GetScriptLoadContext()->mInDeferList
&& !aRequest->GetScriptLoadContext()->mInAsyncList
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"!aRequest->GetScriptLoadContext()->mInDeferList && !aRequest->GetScriptLoadContext()->mInAsyncList"
, "./../../../dom/script/ScriptLoader.cpp", 5506); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!aRequest->GetScriptLoadContext()->mInDeferList && !aRequest->GetScriptLoadContext()->mInAsyncList"
")"); do { MOZ_CrashSequence(__null, 5506); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5506 !aRequest->GetScriptLoadContext()->mInAsyncList)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aRequest->GetScriptLoadContext()->mInDeferList
&& !aRequest->GetScriptLoadContext()->mInAsyncList
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!aRequest->GetScriptLoadContext()->mInDeferList
&& !aRequest->GetScriptLoadContext()->mInAsyncList
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"!aRequest->GetScriptLoadContext()->mInDeferList && !aRequest->GetScriptLoadContext()->mInAsyncList"
, "./../../../dom/script/ScriptLoader.cpp", 5506); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!aRequest->GetScriptLoadContext()->mInDeferList && !aRequest->GetScriptLoadContext()->mInAsyncList"
")"); do { MOZ_CrashSequence(__null, 5506); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5507 MOZ_ASSERT(!aRequest->GetScriptLoadContext()->mInCompilingList)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aRequest->GetScriptLoadContext()->mInCompilingList
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!aRequest->GetScriptLoadContext()->mInCompilingList
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"!aRequest->GetScriptLoadContext()->mInCompilingList", "./../../../dom/script/ScriptLoader.cpp"
, 5507); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aRequest->GetScriptLoadContext()->mInCompilingList"
")"); do { MOZ_CrashSequence(__null, 5507); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5508
5509 aRequest->GetScriptLoadContext()->mInAsyncList = true;
5510 if (aRequest->IsFinished()) {
5511 mLoadedAsyncRequests.AppendElement(aRequest);
5512 } else {
5513 mLoadingAsyncRequests.AppendElement(aRequest);
5514 }
5515}
5516
5517void ScriptLoader::MaybeMoveToLoadedList(ScriptLoadRequest* aRequest) {
5518 MOZ_ASSERT(aRequest->IsFinished())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aRequest->IsFinished())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aRequest->IsFinished())))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("aRequest->IsFinished()"
, "./../../../dom/script/ScriptLoader.cpp", 5518); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aRequest->IsFinished()" ")"); do { MOZ_CrashSequence
(__null, 5518); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
5519
5520 bool isDynamicImport = false;
5521 if (aRequest->IsModuleRequest()) {
5522 ModuleLoadRequest* modReq = aRequest->AsModuleRequest();
5523 isDynamicImport = modReq->IsDynamicImport();
5524 }
5525
5526 MOZ_ASSERT(aRequest->IsTopLevel() || isDynamicImport)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aRequest->IsTopLevel() || isDynamicImport)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(aRequest->IsTopLevel() || isDynamicImport))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("aRequest->IsTopLevel() || isDynamicImport"
, "./../../../dom/script/ScriptLoader.cpp", 5526); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aRequest->IsTopLevel() || isDynamicImport"
")"); do { MOZ_CrashSequence(__null, 5526); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5527
5528 // If it's async, move it to the loaded list.
5529 // aRequest->GetScriptLoadContext()->mInAsyncList really _should_ be in a
5530 // list, but the consequences if it's not are bad enough we want to avoid
5531 // trying to move it if it's not.
5532 if (aRequest->GetScriptLoadContext()->mInAsyncList) {
5533 MOZ_ASSERT(aRequest->isInList())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aRequest->isInList())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aRequest->isInList()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("aRequest->isInList()"
, "./../../../dom/script/ScriptLoader.cpp", 5533); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aRequest->isInList()" ")"); do { MOZ_CrashSequence
(__null, 5533); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
5534 if (aRequest->isInList()) {
5535 RefPtr<ScriptLoadRequest> req = mLoadingAsyncRequests.Steal(aRequest);
5536 mLoadedAsyncRequests.AppendElement(req);
5537 }
5538 } else if (isDynamicImport) {
5539 // Process dynamic imports with async scripts.
5540 MOZ_ASSERT(!aRequest->isInList())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aRequest->isInList())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aRequest->isInList()))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("!aRequest->isInList()"
, "./../../../dom/script/ScriptLoader.cpp", 5540); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!aRequest->isInList()" ")"); do { MOZ_CrashSequence
(__null, 5540); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
5541 mLoadedAsyncRequests.AppendElement(aRequest);
5542 }
5543}
5544
5545bool ScriptLoader::MaybeRemovedDeferRequests() {
5546 if (mDeferRequests.isEmpty() && mDocument && mBlockingDOMContentLoaded) {
5547 mBlockingDOMContentLoaded = false;
5548 mDocument->UnblockDOMContentLoaded();
5549 return true;
5550 }
5551 return false;
5552}
5553
5554DocGroup* ScriptLoader::GetDocGroup() const { return mDocument->GetDocGroup(); }
5555
5556void ScriptLoader::BeginDeferringScripts() {
5557 if (mDeferEnabled || mDeferCheckpointReached) {
5558 // We already started loading. Now, document.open() happened and we're doing
5559 // a new parse.
5560 // If mDeferEnabled, we haven't reached the defer checkpoint and if
5561 // mDeferCheckpointReached, we did but still have pending scripts. Either
5562 // way, the load event is still blocked, so we shouldn't block again.
5563 // If set, reset mDeferCheckpointReached. It'll get set again when the
5564 // DeferCheckpointReached call corresponding to this BeginDeferringScripts
5565 // call happens (on document.close()), since we will set mDeferEnabled.
5566 mDeferCheckpointReached = false;
5567 } else if (mDocument) {
5568 mDocument->BlockOnload();
5569 }
5570 mDeferEnabled = true;
5571}
5572
5573nsAutoScriptLoaderDisabler::nsAutoScriptLoaderDisabler(Document* aDoc) {
5574 mLoader = aDoc->GetScriptLoader();
5575 mWasEnabled = mLoader && mLoader->GetEnabled();
5576 if (mWasEnabled) {
5577 mLoader->SetEnabled(false);
5578 }
5579}
5580
5581nsAutoScriptLoaderDisabler::~nsAutoScriptLoaderDisabler() {
5582 if (mWasEnabled) {
5583 MOZ_ASSERT(mLoader, "mWasEnabled can be true only if we have a loader")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mLoader)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mLoader))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mLoader" " (" "mWasEnabled can be true only if we have a loader"
")", "./../../../dom/script/ScriptLoader.cpp", 5583); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "mLoader" ") (" "mWasEnabled can be true only if we have a loader"
")"); do { MOZ_CrashSequence(__null, 5583); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5584 mLoader->SetEnabled(true);
5585 }
5586}
5587
5588#undef LOG
5589
5590} // namespace mozilla::dom