Bug 1874684 - Part 38: Enable now passing tests. r=allstarschh
[gecko.git] / dom / script / ScriptLoadContext.h
blobd32553c4d44b1b73f7539ceae9b587de8044d4cd
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();
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 nsIScriptElement* GetScriptElement() const;
186 // Make this request a preload (speculative) request.
187 void SetIsPreloadRequest() {
188 MOZ_ASSERT(!GetScriptElement());
189 MOZ_ASSERT(!IsPreload());
190 mIsPreload = true;
193 // Make a preload request into an actual load request for the given element.
194 void SetIsLoadRequest(nsIScriptElement* aElement);
196 FromParser GetParserCreated() const {
197 nsIScriptElement* element = GetScriptElement();
198 if (!element) {
199 return NOT_FROM_PARSER;
201 return element->GetParserCreated();
204 // Used to output a string for the Gecko Profiler.
205 void GetProfilerLabel(nsACString& aOutString) override;
207 void MaybeCancelOffThreadScript();
209 // Finish the off-main-thread compilation and return the result, or
210 // convert the compilation error to runtime error.
211 already_AddRefed<JS::Stencil> StealOffThreadResult(
212 JSContext* aCx, JS::InstantiationStorage* aInstantiationStorage);
214 ScriptMode mScriptMode; // Whether this is a blocking, defer or async script.
215 bool mScriptFromHead; // Synchronous head script block loading of other non
216 // js/css content.
217 bool mIsInline; // Is the script inline or loaded?
218 bool mInDeferList; // True if we live in mDeferRequests.
219 bool mInAsyncList; // True if we live in mLoadingAsyncRequests or
220 // mLoadedAsyncRequests.
221 bool mIsNonAsyncScriptInserted; // True if we live in
222 // mNonAsyncExternalScriptInsertedRequests
223 bool mIsXSLT; // True if we live in mXSLTRequests.
224 bool mInCompilingList; // True if we are in mOffThreadCompilingRequests.
225 bool mIsTracking; // True if the script comes from a source on our
226 // tracking protection list.
227 bool mWasCompiledOMT; // True if the script has been compiled off main
228 // thread.
230 // Task that performs off-thread compilation or off-thread decode.
231 // This field is used to take the result of the task, or cancel the task.
233 // Set to non-null on the task creation, and set to null when taking the
234 // result or cancelling the task.
235 RefPtr<CompileOrDecodeTask> mCompileOrDecodeTask;
237 uint32_t mLineNo;
238 JS::ColumnNumberOneOrigin mColumnNo;
240 // Set on scripts and top level modules.
241 bool mIsPreload;
243 // Non-null if there is a document that this request is blocking from loading.
244 RefPtr<Document> mLoadBlockedDocument;
246 // For preload requests, we defer reporting errors to the console until the
247 // request is used.
248 nsresult mUnreportedPreloadError;
251 } // namespace mozilla::dom
253 #endif // mozilla_dom_ScriptLoadContext_h