1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "ScriptLoadRequest.h"
8 #include "GeckoProfiler.h"
10 #include "mozilla/dom/Document.h"
11 #include "mozilla/dom/ScriptLoadContext.h"
12 #include "mozilla/dom/WorkerLoadContext.h"
13 #include "mozilla/dom/ScriptSettings.h"
14 #include "mozilla/HoldDropJSObjects.h"
15 #include "mozilla/StaticPrefs_dom.h"
16 #include "mozilla/Unused.h"
17 #include "mozilla/Utf8.h" // mozilla::Utf8Unit
19 #include "js/SourceText.h"
21 #include "ModuleLoadRequest.h"
22 #include "nsContentUtils.h"
23 #include "nsICacheInfoChannel.h"
24 #include "nsIClassOfService.h"
25 #include "nsISupportsPriority.h"
29 namespace JS::loader
{
31 //////////////////////////////////////////////////////////////
33 //////////////////////////////////////////////////////////////
35 NS_IMPL_CYCLE_COLLECTION(ScriptFetchOptions
, mTriggeringPrincipal
, mElement
)
37 ScriptFetchOptions::ScriptFetchOptions(
38 mozilla::CORSMode aCORSMode
, const nsAString
& aNonce
,
39 mozilla::dom::RequestPriority aFetchPriority
,
40 const ParserMetadata aParserMetadata
, nsIPrincipal
* aTriggeringPrincipal
,
41 mozilla::dom::Element
* aElement
)
42 : mCORSMode(aCORSMode
),
44 mFetchPriority(aFetchPriority
),
45 mParserMetadata(aParserMetadata
),
46 mTriggeringPrincipal(aTriggeringPrincipal
),
49 ScriptFetchOptions::~ScriptFetchOptions() = default;
51 //////////////////////////////////////////////////////////////
53 //////////////////////////////////////////////////////////////
55 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ScriptLoadRequest
)
56 NS_INTERFACE_MAP_ENTRY(nsISupports
)
59 NS_IMPL_CYCLE_COLLECTING_ADDREF(ScriptLoadRequest
)
60 NS_IMPL_CYCLE_COLLECTING_RELEASE(ScriptLoadRequest
)
62 NS_IMPL_CYCLE_COLLECTION_CLASS(ScriptLoadRequest
)
64 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ScriptLoadRequest
)
65 NS_IMPL_CYCLE_COLLECTION_UNLINK(mFetchOptions
, mCacheInfo
, mLoadContext
,
67 tmp
->mScriptForBytecodeEncoding
= nullptr;
68 tmp
->DropBytecodeCacheReferences();
69 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
71 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(ScriptLoadRequest
)
72 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFetchOptions
, mCacheInfo
, mLoadContext
,
74 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
76 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(ScriptLoadRequest
)
77 NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mScriptForBytecodeEncoding
)
78 NS_IMPL_CYCLE_COLLECTION_TRACE_END
80 ScriptLoadRequest::ScriptLoadRequest(
81 ScriptKind aKind
, nsIURI
* aURI
,
82 mozilla::dom::ReferrerPolicy aReferrerPolicy
,
83 ScriptFetchOptions
* aFetchOptions
, const SRIMetadata
& aIntegrity
,
84 nsIURI
* aReferrer
, LoadContextBase
* aContext
)
86 mState(State::CheckingCache
),
87 mFetchSourceOnly(false),
88 mReferrerPolicy(aReferrerPolicy
),
89 mFetchOptions(aFetchOptions
),
90 mIntegrity(aIntegrity
),
93 mLoadContext(aContext
),
94 mEarlyHintPreloaderId(0) {
95 MOZ_ASSERT(mFetchOptions
);
97 mLoadContext
->SetRequest(this);
101 ScriptLoadRequest::~ScriptLoadRequest() { DropJSObjects(this); }
103 void ScriptLoadRequest::SetReady() {
104 MOZ_ASSERT(!IsFinished());
105 mState
= State::Ready
;
108 void ScriptLoadRequest::Cancel() {
109 mState
= State::Canceled
;
110 if (HasScriptLoadContext()) {
111 GetScriptLoadContext()->MaybeCancelOffThreadScript();
115 void ScriptLoadRequest::DropBytecodeCacheReferences() {
116 mCacheInfo
= nullptr;
120 bool ScriptLoadRequest::HasScriptLoadContext() const {
121 return HasLoadContext() && mLoadContext
->IsWindowContext();
124 bool ScriptLoadRequest::HasWorkerLoadContext() const {
125 return HasLoadContext() && mLoadContext
->IsWorkerContext();
128 mozilla::dom::ScriptLoadContext
* ScriptLoadRequest::GetScriptLoadContext() {
129 MOZ_ASSERT(mLoadContext
);
130 return mLoadContext
->AsWindowContext();
133 mozilla::loader::ComponentLoadContext
*
134 ScriptLoadRequest::GetComponentLoadContext() {
135 MOZ_ASSERT(mLoadContext
);
136 return mLoadContext
->AsComponentContext();
139 mozilla::dom::WorkerLoadContext
* ScriptLoadRequest::GetWorkerLoadContext() {
140 MOZ_ASSERT(mLoadContext
);
141 return mLoadContext
->AsWorkerContext();
144 mozilla::dom::WorkletLoadContext
* ScriptLoadRequest::GetWorkletLoadContext() {
145 MOZ_ASSERT(mLoadContext
);
146 return mLoadContext
->AsWorkletContext();
149 ModuleLoadRequest
* ScriptLoadRequest::AsModuleRequest() {
150 MOZ_ASSERT(IsModuleRequest());
151 return static_cast<ModuleLoadRequest
*>(this);
154 const ModuleLoadRequest
* ScriptLoadRequest::AsModuleRequest() const {
155 MOZ_ASSERT(IsModuleRequest());
156 return static_cast<const ModuleLoadRequest
*>(this);
159 void ScriptLoadRequest::NoCacheEntryFound() {
160 MOZ_ASSERT(IsCheckingCache());
162 // At the time where we check in the cache, the mBaseURL is not set, as this
163 // is resolved by the network. Thus we use the mURI, for checking the cache
164 // and later replace the mBaseURL using what the Channel->GetURI will provide.
166 case ScriptKind::eClassic
:
167 case ScriptKind::eImportMap
:
168 mLoadedScript
= new ClassicScript(mReferrerPolicy
, mFetchOptions
, mURI
);
170 case ScriptKind::eModule
:
171 mLoadedScript
= new ModuleScript(mReferrerPolicy
, mFetchOptions
, mURI
);
173 case ScriptKind::eEvent
:
174 MOZ_ASSERT_UNREACHABLE("EventScripts are not using ScriptLoadRequest");
177 mState
= State::Fetching
;
180 void ScriptLoadRequest::SetPendingFetchingError() {
181 MOZ_ASSERT(IsCheckingCache());
182 mState
= State::PendingFetchingError
;
185 void ScriptLoadRequest::MarkForBytecodeEncoding(JSScript
* aScript
) {
186 MOZ_ASSERT(!IsModuleRequest());
187 MOZ_ASSERT(!IsMarkedForBytecodeEncoding());
188 mScriptForBytecodeEncoding
= aScript
;
192 bool ScriptLoadRequest::IsMarkedForBytecodeEncoding() const {
193 if (IsModuleRequest()) {
194 return AsModuleRequest()->IsModuleMarkedForBytecodeEncoding();
197 return !!mScriptForBytecodeEncoding
;
200 //////////////////////////////////////////////////////////////
201 // ScriptLoadRequestList
202 //////////////////////////////////////////////////////////////
204 ScriptLoadRequestList::~ScriptLoadRequestList() { CancelRequestsAndClear(); }
206 void ScriptLoadRequestList::CancelRequestsAndClear() {
208 RefPtr
<ScriptLoadRequest
> first
= StealFirst();
210 // And just let it go out of scope and die.
215 bool ScriptLoadRequestList::Contains(ScriptLoadRequest
* aElem
) const {
216 for (const ScriptLoadRequest
* req
= getFirst(); req
; req
= req
->getNext()) {
226 } // namespace JS::loader