Bug 1907704 - Update android nightly application-services version bump to 8fd08c6f2f8...
[gecko.git] / dom / script / ScriptLoadContext.h
blobb92294cef56b1f3c783ba734b7e69e8eb6cc6939
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 #ifndef mozilla_dom_ScriptLoadContext_h
8 #define mozilla_dom_ScriptLoadContext_h
10 #include "js/AllocPolicy.h"
11 #include "js/ColumnNumber.h" // JS::ColumnNumberOneOrigin
12 #include "js/CompileOptions.h" // JS::OwningCompileOptions
13 #include "js/experimental/JSStencil.h" // JS::FrontendContext, JS::Stencil, JS::InstantiationStorage
14 #include "js/RootingAPI.h"
15 #include "js/SourceText.h"
16 #include "js/Transcoding.h" // JS::TranscodeResult
17 #include "js/TypeDecls.h"
18 #include "js/loader/LoadContextBase.h"
19 #include "js/loader/ScriptKind.h"
20 #include "mozilla/AlreadyAddRefed.h"
21 #include "mozilla/Atomics.h"
22 #include "mozilla/Assertions.h"
23 #include "mozilla/CORSMode.h"
24 #include "mozilla/dom/SRIMetadata.h"
25 #include "mozilla/LinkedList.h"
26 #include "mozilla/Maybe.h"
27 #include "mozilla/MaybeOneOf.h"
28 #include "mozilla/Mutex.h"
29 #include "mozilla/PreloaderBase.h"
30 #include "mozilla/RefPtr.h"
31 #include "mozilla/StaticPrefs_dom.h"
32 #include "mozilla/TaskController.h" // mozilla::Task
33 #include "mozilla/Utf8.h" // mozilla::Utf8Unit
34 #include "mozilla/Variant.h"
35 #include "mozilla/Vector.h"
36 #include "nsCOMPtr.h"
37 #include "nsCycleCollectionParticipant.h"
38 #include "nsIScriptElement.h"
40 class nsICacheInfoChannel;
41 struct JSContext;
43 namespace mozilla::dom {
45 class Element;
48 * DOM specific ScriptLoadContext.
50 * ScriptLoadContexts augment the loading of a ScriptLoadRequest. They
51 * describe how a ScriptLoadRequests loading and evaluation needs to be
52 * augmented, based on the information provided by the loading context. In
53 * the case of the DOM, the ScriptLoadContext is used to identify how a script
54 * should be loaded according to information found in the HTML document into
55 * which it will be loaded. The following fields describe how the
56 * ScriptLoadRequest will be loaded.
58 * * mScriptMode
59 * stores the mode (Async, Sync, Deferred), and preload, which
60 * allows the ScriptLoader to decide if the script should be pushed
61 * offThread, or if the preloaded request should be used.
62 * * mScriptFromHead
63 * Set when the script tag is in the head, and should be treated as
64 * a blocking script
65 * * mIsInline
66 * Set for scripts whose bodies are inline in the html. In this case,
67 * the script does not need to be fetched first.
68 * * mIsXSLT
69 * Set if we are in an XSLT request.
70 * * mIsPreload
71 * Set for scripts that are preloaded in a
72 * <link rel="preload" as="script"> or <link rel="modulepreload">
73 * element.
75 * In addition to describing how the ScriptLoadRequest will be loaded by the
76 * DOM ScriptLoader, the ScriptLoadContext contains fields that facilitate
77 * those custom behaviors, including support for offthread parsing and preload
78 * element specific controls.
82 // Base class for the off-thread compile or off-thread decode tasks.
83 class CompileOrDecodeTask : public mozilla::Task {
84 protected:
85 CompileOrDecodeTask();
86 virtual ~CompileOrDecodeTask();
88 nsresult InitFrontendContext();
90 void DidRunTask(const MutexAutoLock& aProofOfLock,
91 RefPtr<JS::Stencil>&& aStencil);
93 bool IsCancelled(const MutexAutoLock& aProofOfLock) const {
94 return mIsCancelled;
97 public:
98 // Returns the result of the compilation or decode if it was successful.
99 // Returns nullptr otherwise, and sets pending exception on JSContext.
101 // aInstantiationStorage receives the storage allocated off main thread
102 // on successful case.
103 already_AddRefed<JS::Stencil> StealResult(
104 JSContext* aCx, JS::InstantiationStorage* aInstantiationStorage);
106 // Cancel the task.
107 // If the task is already running, this waits for the task to finish.
108 void Cancel();
110 protected:
111 // This mutex is locked during running the task or cancelling task.
112 mozilla::Mutex mMutex;
114 // The result of decode task, to distinguish throwing case and decode error.
115 JS::TranscodeResult mResult = JS::TranscodeResult::Ok;
117 // An option used to compile the code, or the equivalent for decode.
118 // This holds the filename pointed by errors reported to JS::FrontendContext.
119 JS::OwningCompileOptions mOptions;
121 // Owning-pointer for the context associated with the script compilation.
123 // The context is allocated on main thread in InitFrontendContext method,
124 // and is freed on any thread in the destructor.
125 JS::FrontendContext* mFrontendContext = nullptr;
127 bool mIsCancelled = false;
129 private:
130 // The result of the compilation or decode.
131 RefPtr<JS::Stencil> mStencil;
133 JS::InstantiationStorage mInstantiationStorage;
136 class ScriptLoadContext : public JS::loader::LoadContextBase,
137 public PreloaderBase {
138 protected:
139 virtual ~ScriptLoadContext();
141 public:
142 explicit ScriptLoadContext(nsIScriptElement* aScriptElement = nullptr);
144 NS_DECL_ISUPPORTS_INHERITED
145 NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(ScriptLoadContext,
146 JS::loader::LoadContextBase)
148 static void PrioritizeAsPreload(nsIChannel* aChannel);
150 bool IsPreload() const override;
152 bool CompileStarted() const;
154 bool IsTracking() const { return mIsTracking; }
155 void SetIsTracking() {
156 MOZ_ASSERT(!mIsTracking);
157 mIsTracking = true;
160 void BlockOnload(Document* aDocument);
162 void MaybeUnblockOnload();
164 enum class ScriptMode : uint8_t {
165 eBlocking,
166 eDeferred,
167 eAsync,
168 eLinkPreload // this is a load initiated by <link rel="preload"
169 // as="script"> or <link rel="modulepreload"> tag
172 void SetScriptMode(bool aDeferAttr, bool aAsyncAttr, bool aLinkPreload);
174 bool IsLinkPreloadScript() const {
175 return mScriptMode == ScriptMode::eLinkPreload;
178 bool IsBlockingScript() const { return mScriptMode == ScriptMode::eBlocking; }
180 bool IsDeferredScript() const { return mScriptMode == ScriptMode::eDeferred; }
182 bool IsAsyncScript() const { return mScriptMode == ScriptMode::eAsync; }
184 // Accessors for the script element, for each purpose.
186 // The script element reference is guaranteed to be available only for:
187 // * inline/external classic script
188 // * inline/external top-level module
190 // The reference is valid only for specific purpose explained below.
192 // For aLoadingNode parameter of a new channel.
193 // TODO: This is basically unnecessary and a document can be used instead.
194 // Remove this.
195 inline nsIScriptElement* GetScriptElementForLoadingNode() const {
196 MOZ_ASSERT(mScriptElement);
197 return mScriptElement;
200 // For TRACE_FOR_TEST macros.
201 // NOTE: This is called also for imported modules.
202 // The consumer allows nullptr.
203 inline nsIScriptElement* GetScriptElementForTrace() const {
204 return mScriptElement;
207 // Event target for beforescriptexecute/afterscriptexecute events.
208 inline nsIScriptElement* GetScriptElementForExecuteEvents() const {
209 MOZ_ASSERT(mScriptElement);
210 return mScriptElement;
213 // For ScriptLoader::mCurrentParserInsertedScript.
214 inline nsIScriptElement* GetScriptElementForCurrentParserInsertedScript()
215 const {
216 MOZ_ASSERT(mScriptElement);
217 return mScriptElement;
220 // For nsIScriptLoaderObserver.
221 inline nsIScriptElement* GetScriptElementForObserver() const {
222 MOZ_ASSERT(mScriptElement);
223 return mScriptElement;
226 // For URL classifier.
227 inline nsIScriptElement* GetScriptElementForUrlClassifier() const {
228 return mScriptElement;
231 // For AutoCurrentScriptUpdater.
232 // This is valid only for classic script.
233 inline nsIScriptElement* GetScriptElementForCurrentScript() const {
234 MOZ_ASSERT(mScriptElement);
235 return mScriptElement;
238 bool HasScriptElement() const;
240 void GetInlineScriptText(nsAString& aText) const;
242 void GetHintCharset(nsAString& aCharset) const;
244 // TODO: Reimplement with mLineNo/mColumnNo.
245 uint32_t GetScriptLineNumber() const;
246 JS::ColumnNumberOneOrigin GetScriptColumnNumber() const;
248 void BeginEvaluatingTopLevel() const;
249 void EndEvaluatingTopLevel() const;
251 void UnblockParser() const;
252 void ContinueParserAsync() const;
254 Document* GetScriptOwnerDocument() const;
256 // Make this request a preload (speculative) request.
257 void SetIsPreloadRequest() {
258 MOZ_ASSERT(!HasScriptElement());
259 MOZ_ASSERT(!IsPreload());
260 mIsPreload = true;
263 // Make a preload request into an actual load request for the given element.
264 void SetIsLoadRequest(nsIScriptElement* aElement);
266 FromParser GetParserCreated() const {
267 if (!mScriptElement) {
268 return NOT_FROM_PARSER;
270 return mScriptElement->GetParserCreated();
273 // Used to output a string for the Gecko Profiler.
274 void GetProfilerLabel(nsACString& aOutString) override;
276 void MaybeCancelOffThreadScript();
278 // Finish the off-main-thread compilation and return the result, or
279 // convert the compilation error to runtime error.
280 already_AddRefed<JS::Stencil> StealOffThreadResult(
281 JSContext* aCx, JS::InstantiationStorage* aInstantiationStorage);
283 ScriptMode mScriptMode; // Whether this is a blocking, defer or async script.
284 bool mScriptFromHead; // Synchronous head script block loading of other non
285 // js/css content.
286 bool mIsInline; // Is the script inline or loaded?
287 bool mInDeferList; // True if we live in mDeferRequests.
288 bool mInAsyncList; // True if we live in mLoadingAsyncRequests or
289 // mLoadedAsyncRequests.
290 bool mIsNonAsyncScriptInserted; // True if we live in
291 // mNonAsyncExternalScriptInsertedRequests
292 bool mIsXSLT; // True if we live in mXSLTRequests.
293 bool mInCompilingList; // True if we are in mOffThreadCompilingRequests.
294 bool mIsTracking; // True if the script comes from a source on our
295 // tracking protection list.
296 bool mWasCompiledOMT; // True if the script has been compiled off main
297 // thread.
299 // Task that performs off-thread compilation or off-thread decode.
300 // This field is used to take the result of the task, or cancel the task.
302 // Set to non-null on the task creation, and set to null when taking the
303 // result or cancelling the task.
304 RefPtr<CompileOrDecodeTask> mCompileOrDecodeTask;
306 uint32_t mLineNo;
307 JS::ColumnNumberOneOrigin mColumnNo;
309 // Set on scripts and top level modules.
310 bool mIsPreload;
312 // Non-null if there is a document that this request is blocking from loading.
313 RefPtr<Document> mLoadBlockedDocument;
315 // The script element which trigerred this script load.
316 // This is valid only for classic script and top-level module script.
317 nsCOMPtr<nsIScriptElement> mScriptElement;
319 // For preload requests, we defer reporting errors to the console until the
320 // request is used.
321 nsresult mUnreportedPreloadError;
324 } // namespace mozilla::dom
326 #endif // mozilla_dom_ScriptLoadContext_h