Bug Summary

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