ScriptLoadRequest.cpp (7917B)
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/. */ 6 7 #include "ScriptLoadRequest.h" 8 #include "GeckoProfiler.h" 9 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/StaticPrefs_dom.h" 15 #include "mozilla/Utf8.h" // mozilla::Utf8Unit 16 17 #include "js/SourceText.h" 18 19 #include "ModuleLoadRequest.h" 20 #include "nsContentUtils.h" 21 #include "nsIClassOfService.h" 22 #include "nsISupportsPriority.h" 23 24 using JS::SourceText; 25 26 namespace JS::loader { 27 28 ////////////////////////////////////////////////////////////// 29 // ScriptFetchOptions 30 ////////////////////////////////////////////////////////////// 31 32 NS_IMPL_CYCLE_COLLECTION(ScriptFetchOptions, mTriggeringPrincipal) 33 34 ScriptFetchOptions::ScriptFetchOptions( 35 mozilla::CORSMode aCORSMode, const nsAString& aNonce, 36 mozilla::dom::RequestPriority aFetchPriority, 37 const ParserMetadata aParserMetadata, nsIPrincipal* aTriggeringPrincipal) 38 : mCORSMode(aCORSMode), 39 mFetchPriority(aFetchPriority), 40 mParserMetadata(aParserMetadata), 41 mTriggeringPrincipal(aTriggeringPrincipal), 42 mNonce(aNonce) {} 43 44 void ScriptFetchOptions::SetTriggeringPrincipal( 45 nsIPrincipal* aTriggeringPrincipal) { 46 MOZ_ASSERT(!mTriggeringPrincipal); 47 mTriggeringPrincipal = aTriggeringPrincipal; 48 } 49 50 // static 51 already_AddRefed<ScriptFetchOptions> ScriptFetchOptions::CreateDefault() { 52 RefPtr<ScriptFetchOptions> options = new ScriptFetchOptions( 53 mozilla::CORS_NONE, /* aNonce = */ u""_ns, 54 mozilla::dom::RequestPriority::Auto, ParserMetadata::NotParserInserted); 55 return options.forget(); 56 } 57 58 ScriptFetchOptions::~ScriptFetchOptions() = default; 59 60 ////////////////////////////////////////////////////////////// 61 // ScriptLoadRequest 62 ////////////////////////////////////////////////////////////// 63 64 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ScriptLoadRequest) 65 NS_INTERFACE_MAP_ENTRY(nsISupports) 66 NS_INTERFACE_MAP_END 67 68 NS_IMPL_CYCLE_COLLECTING_ADDREF(ScriptLoadRequest) 69 NS_IMPL_CYCLE_COLLECTING_RELEASE(ScriptLoadRequest) 70 71 // ScriptLoadRequest can be accessed from multiple threads. 72 // 73 // For instance, worker script loader passes the ScriptLoadRequest to 74 // the main thread to perform the actual load. 75 // Even while it's handled by the main thread, the ScriptLoadRequest is 76 // the target of the worker thread's cycle collector. 77 // 78 // Fields that can be modified by the main thread shouldn't be touched by 79 // the cycle collection. 80 // 81 // NOTE: nsIURI and nsIPrincipal doesn't have to be touched here because 82 // they cannot be a part of cycle. 83 NS_IMPL_CYCLE_COLLECTION(ScriptLoadRequest, mLoadedScript, mLoadContext) 84 85 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(ScriptLoadRequest) 86 NS_IMPL_CYCLE_COLLECTION_TRACE_END 87 88 ScriptLoadRequest::ScriptLoadRequest(ScriptKind aKind, 89 const SRIMetadata& aIntegrity, 90 nsIURI* aReferrer, 91 LoadContextBase* aContext) 92 : mKind(aKind), 93 mState(State::CheckingCache), 94 mFetchSourceOnly(false), 95 mHasSourceMapURL_(false), 96 mHasDirtyCache_(false), 97 mHadPostponed_(false), 98 mDiskCachingPlan(CachingPlan::Uninitialized), 99 mMemoryCachingPlan(CachingPlan::Uninitialized), 100 mIntegrity(aIntegrity), 101 mReferrer(aReferrer), 102 mLoadContext(aContext), 103 mEarlyHintPreloaderId(0) { 104 if (mLoadContext) { 105 mLoadContext->SetRequest(this); 106 } 107 } 108 109 ScriptLoadRequest::~ScriptLoadRequest() {} 110 111 void ScriptLoadRequest::SetReady() { 112 MOZ_ASSERT(!IsFinished()); 113 mState = State::Ready; 114 } 115 116 void ScriptLoadRequest::Cancel() { 117 mState = State::Canceled; 118 if (HasScriptLoadContext()) { 119 GetScriptLoadContext()->MaybeCancelOffThreadScript(); 120 } 121 } 122 123 bool ScriptLoadRequest::HasScriptLoadContext() const { 124 return HasLoadContext() && mLoadContext->IsWindowContext(); 125 } 126 127 bool ScriptLoadRequest::HasWorkerLoadContext() const { 128 return HasLoadContext() && mLoadContext->IsWorkerContext(); 129 } 130 131 mozilla::dom::ScriptLoadContext* ScriptLoadRequest::GetScriptLoadContext() { 132 MOZ_ASSERT(mLoadContext); 133 return mLoadContext->AsWindowContext(); 134 } 135 136 const mozilla::dom::ScriptLoadContext* ScriptLoadRequest::GetScriptLoadContext() 137 const { 138 MOZ_ASSERT(mLoadContext); 139 return mLoadContext->AsWindowContext(); 140 } 141 142 mozilla::loader::SyncLoadContext* ScriptLoadRequest::GetSyncLoadContext() { 143 MOZ_ASSERT(mLoadContext); 144 return mLoadContext->AsSyncContext(); 145 } 146 147 mozilla::dom::WorkerLoadContext* ScriptLoadRequest::GetWorkerLoadContext() { 148 MOZ_ASSERT(mLoadContext); 149 return mLoadContext->AsWorkerContext(); 150 } 151 152 mozilla::dom::WorkletLoadContext* ScriptLoadRequest::GetWorkletLoadContext() { 153 MOZ_ASSERT(mLoadContext); 154 return mLoadContext->AsWorkletContext(); 155 } 156 157 ModuleLoadRequest* ScriptLoadRequest::AsModuleRequest() { 158 MOZ_ASSERT(IsModuleRequest()); 159 return static_cast<ModuleLoadRequest*>(this); 160 } 161 162 const ModuleLoadRequest* ScriptLoadRequest::AsModuleRequest() const { 163 MOZ_ASSERT(IsModuleRequest()); 164 return static_cast<const ModuleLoadRequest*>(this); 165 } 166 167 void ScriptLoadRequest::CacheEntryFound(LoadedScript* aLoadedScript) { 168 MOZ_ASSERT(IsCheckingCache()); 169 170 SetCacheEntry(aLoadedScript); 171 } 172 173 void ScriptLoadRequest::CacheEntryRevived(LoadedScript* aLoadedScript) { 174 MOZ_ASSERT(IsFetching()); 175 176 SetCacheEntry(aLoadedScript); 177 178 // NOTE: The caller should keep using the "fetching" path, with the 179 // cached stencil, and skip the compilation. 180 mState = State::Fetching; 181 } 182 183 void ScriptLoadRequest::SetCacheEntry(LoadedScript* aLoadedScript) { 184 switch (mKind) { 185 case ScriptKind::eClassic: 186 MOZ_ASSERT(aLoadedScript->IsClassicScript()); 187 188 mLoadedScript = aLoadedScript; 189 190 // Classic scripts can be set ready once the script itself is ready. 191 mState = State::Ready; 192 break; 193 case ScriptKind::eImportMap: 194 MOZ_ASSERT(aLoadedScript->IsImportMapScript()); 195 196 mLoadedScript = aLoadedScript; 197 198 mState = State::Ready; 199 break; 200 case ScriptKind::eModule: 201 // NOTE: The cache entry has "module" kind, but it's not ModuleScript 202 // instance, given ModuleScript has GC pointers. 203 MOZ_ASSERT(aLoadedScript->IsModuleScript()); 204 205 mLoadedScript = ModuleScript::FromCache(*aLoadedScript); 206 207 // Modules need to wait for fetching dependencies before setting to 208 // Ready. 209 mState = State::Fetching; 210 break; 211 case ScriptKind::eEvent: 212 MOZ_ASSERT_UNREACHABLE("EventScripts are not using ScriptLoadRequest"); 213 break; 214 } 215 } 216 217 void ScriptLoadRequest::NoCacheEntryFound( 218 mozilla::dom::ReferrerPolicy aReferrerPolicy, 219 ScriptFetchOptions* aFetchOptions, nsIURI* aURI) { 220 MOZ_ASSERT(IsCheckingCache()); 221 // At the time where we check in the cache, the BaseURL() is not set, as this 222 // is resolved by the network. Thus we use the aURI passed by the consumer, 223 // which is the original URI used for the request, for checking the cache 224 // and later replace the BaseURL() using what the Channel->GetURI will 225 // provide. 226 switch (mKind) { 227 case ScriptKind::eClassic: 228 mLoadedScript = new ClassicScript(aReferrerPolicy, aFetchOptions, aURI); 229 break; 230 case ScriptKind::eImportMap: 231 mLoadedScript = new ImportMapScript(aReferrerPolicy, aFetchOptions, aURI); 232 break; 233 case ScriptKind::eModule: 234 mLoadedScript = new ModuleScript(aReferrerPolicy, aFetchOptions, aURI); 235 break; 236 case ScriptKind::eEvent: 237 MOZ_ASSERT_UNREACHABLE("EventScripts are not using ScriptLoadRequest"); 238 break; 239 } 240 mState = State::Fetching; 241 } 242 243 } // namespace JS::loader