/work/obj-fuzz/dist/include/mozilla/dom/ScriptLoadRequest.h
Line | Count | Source (jump to first uncovered line) |
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 | | #ifndef mozilla_dom_ScriptLoadRequest_h |
8 | | #define mozilla_dom_ScriptLoadRequest_h |
9 | | |
10 | | #include "mozilla/CORSMode.h" |
11 | | #include "mozilla/dom/SRIMetadata.h" |
12 | | #include "mozilla/LinkedList.h" |
13 | | #include "mozilla/Maybe.h" |
14 | | #include "mozilla/net/ReferrerPolicy.h" |
15 | | #include "mozilla/Variant.h" |
16 | | #include "mozilla/Vector.h" |
17 | | #include "nsCOMPtr.h" |
18 | | #include "nsCycleCollectionParticipant.h" |
19 | | #include "nsIScriptElement.h" |
20 | | |
21 | | class nsICacheInfoChannel; |
22 | | |
23 | | namespace mozilla { |
24 | | namespace dom { |
25 | | |
26 | | class ModuleLoadRequest; |
27 | | class ScriptLoadRequestList; |
28 | | |
29 | | enum class ScriptKind { |
30 | | eClassic, |
31 | | eModule |
32 | | }; |
33 | | |
34 | | /* |
35 | | * Some options used when fetching script resources. This only loosely |
36 | | * corresponds to HTML's "script fetch options". |
37 | | * |
38 | | * These are common to all modules in a module graph, and hence a single |
39 | | * instance is shared by all ModuleLoadRequest objects in a graph. |
40 | | */ |
41 | | |
42 | | class ScriptFetchOptions |
43 | | { |
44 | | ~ScriptFetchOptions(); |
45 | | |
46 | | public: |
47 | | NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(ScriptFetchOptions) |
48 | | NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(ScriptFetchOptions) |
49 | | |
50 | | ScriptFetchOptions(mozilla::CORSMode aCORSMode, |
51 | | mozilla::net::ReferrerPolicy aReferrerPolicy, |
52 | | nsIScriptElement* aElement, |
53 | | nsIPrincipal* aTriggeringPrincipal); |
54 | | |
55 | | const mozilla::CORSMode mCORSMode; |
56 | | const mozilla::net::ReferrerPolicy mReferrerPolicy; |
57 | | nsCOMPtr<nsIScriptElement> mElement; |
58 | | nsCOMPtr<nsIPrincipal> mTriggeringPrincipal; |
59 | | }; |
60 | | |
61 | | /* |
62 | | * A class that handles loading and evaluation of <script> elements. |
63 | | */ |
64 | | |
65 | | class ScriptLoadRequest : public nsISupports, |
66 | | private mozilla::LinkedListElement<ScriptLoadRequest> |
67 | | { |
68 | | typedef LinkedListElement<ScriptLoadRequest> super; |
69 | | |
70 | | // Allow LinkedListElement<ScriptLoadRequest> to cast us to itself as needed. |
71 | | friend class mozilla::LinkedListElement<ScriptLoadRequest>; |
72 | | friend class ScriptLoadRequestList; |
73 | | |
74 | | protected: |
75 | | virtual ~ScriptLoadRequest(); |
76 | | |
77 | | public: |
78 | | ScriptLoadRequest(ScriptKind aKind, |
79 | | nsIURI* aURI, |
80 | | ScriptFetchOptions* aFetchOptions, |
81 | | const SRIMetadata &aIntegrity, |
82 | | nsIURI* aReferrer); |
83 | | |
84 | | NS_DECL_CYCLE_COLLECTING_ISUPPORTS |
85 | | NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(ScriptLoadRequest) |
86 | | |
87 | | bool IsModuleRequest() const |
88 | 0 | { |
89 | 0 | return mKind == ScriptKind::eModule; |
90 | 0 | } |
91 | | |
92 | | ModuleLoadRequest* AsModuleRequest(); |
93 | | |
94 | | void FireScriptAvailable(nsresult aResult) |
95 | 0 | { |
96 | 0 | bool isInlineClassicScript = mIsInline && !IsModuleRequest(); |
97 | 0 | Element()->ScriptAvailable(aResult, Element(), isInlineClassicScript, mURI, |
98 | 0 | mLineNo); |
99 | 0 | } |
100 | | void FireScriptEvaluated(nsresult aResult) |
101 | 0 | { |
102 | 0 | Element()->ScriptEvaluated(aResult, Element(), mIsInline); |
103 | 0 | } |
104 | | |
105 | | bool IsPreload() |
106 | 0 | { |
107 | 0 | return Element() == nullptr; |
108 | 0 | } |
109 | | |
110 | | virtual void Cancel(); |
111 | | |
112 | | bool IsCanceled() const |
113 | 0 | { |
114 | 0 | return mIsCanceled; |
115 | 0 | } |
116 | | |
117 | | virtual void SetReady(); |
118 | | |
119 | | JS::OffThreadToken** OffThreadTokenPtr() |
120 | 0 | { |
121 | 0 | return mOffThreadToken ? &mOffThreadToken : nullptr; |
122 | 0 | } |
123 | | |
124 | | bool IsTracking() const |
125 | 0 | { |
126 | 0 | return mIsTracking; |
127 | 0 | } |
128 | | void SetIsTracking() |
129 | 0 | { |
130 | 0 | MOZ_ASSERT(!mIsTracking); |
131 | 0 | mIsTracking = true; |
132 | 0 | } |
133 | | |
134 | | enum class Progress : uint8_t { |
135 | | eLoading, // Request either source or bytecode |
136 | | eLoading_Source, // Explicitly Request source stream |
137 | | eCompiling, |
138 | | eFetchingImports, |
139 | | eReady |
140 | | }; |
141 | | |
142 | | bool IsReadyToRun() const |
143 | 0 | { |
144 | 0 | return mProgress == Progress::eReady; |
145 | 0 | } |
146 | | bool IsLoading() const |
147 | 0 | { |
148 | 0 | return mProgress == Progress::eLoading || |
149 | 0 | mProgress == Progress::eLoading_Source; |
150 | 0 | } |
151 | | bool IsLoadingSource() const |
152 | 0 | { |
153 | 0 | return mProgress == Progress::eLoading_Source; |
154 | 0 | } |
155 | | bool InCompilingStage() const |
156 | 0 | { |
157 | 0 | return mProgress == Progress::eCompiling || |
158 | 0 | (IsReadyToRun() && mWasCompiledOMT); |
159 | 0 | } |
160 | | |
161 | | // Type of data provided by the nsChannel. |
162 | | enum class DataType : uint8_t { |
163 | | eUnknown, |
164 | | eTextSource, |
165 | | eBinASTSource, |
166 | | eBytecode |
167 | | }; |
168 | | |
169 | | bool IsUnknownDataType() const |
170 | 0 | { |
171 | 0 | return mDataType == DataType::eUnknown; |
172 | 0 | } |
173 | | bool IsTextSource() const |
174 | 0 | { |
175 | 0 | return mDataType == DataType::eTextSource; |
176 | 0 | } |
177 | | bool IsBinASTSource() const |
178 | 0 | { |
179 | 0 | #ifdef JS_BUILD_BINAST |
180 | 0 | return mDataType == DataType::eBinASTSource; |
181 | | #else |
182 | | return false; |
183 | | #endif |
184 | | } |
185 | | bool IsSource() const |
186 | 0 | { |
187 | 0 | return IsTextSource() || IsBinASTSource(); |
188 | 0 | } |
189 | | bool IsBytecode() const |
190 | 0 | { |
191 | 0 | return mDataType == DataType::eBytecode; |
192 | 0 | } |
193 | | |
194 | | void SetUnknownDataType(); |
195 | | void SetTextSource(); |
196 | | void SetBinASTSource(); |
197 | | void SetBytecode(); |
198 | | |
199 | | using ScriptTextBuffer = Vector<char16_t, 0, JSMallocAllocPolicy>; |
200 | | using BinASTSourceBuffer = Vector<uint8_t>; |
201 | | |
202 | | const ScriptTextBuffer& ScriptText() const |
203 | 0 | { |
204 | 0 | MOZ_ASSERT(IsTextSource()); |
205 | 0 | return mScriptData->as<ScriptTextBuffer>(); |
206 | 0 | } |
207 | | ScriptTextBuffer& ScriptText() |
208 | 0 | { |
209 | 0 | MOZ_ASSERT(IsTextSource()); |
210 | 0 | return mScriptData->as<ScriptTextBuffer>(); |
211 | 0 | } |
212 | | const BinASTSourceBuffer& ScriptBinASTData() const |
213 | 0 | { |
214 | 0 | MOZ_ASSERT(IsBinASTSource()); |
215 | 0 | return mScriptData->as<BinASTSourceBuffer>(); |
216 | 0 | } |
217 | | BinASTSourceBuffer& ScriptBinASTData() |
218 | 0 | { |
219 | 0 | MOZ_ASSERT(IsBinASTSource()); |
220 | 0 | return mScriptData->as<BinASTSourceBuffer>(); |
221 | 0 | } |
222 | | |
223 | | enum class ScriptMode : uint8_t { |
224 | | eBlocking, |
225 | | eDeferred, |
226 | | eAsync |
227 | | }; |
228 | | |
229 | | void SetScriptMode(bool aDeferAttr, bool aAsyncAttr); |
230 | | |
231 | | bool IsBlockingScript() const |
232 | 0 | { |
233 | 0 | return mScriptMode == ScriptMode::eBlocking; |
234 | 0 | } |
235 | | |
236 | | bool IsDeferredScript() const |
237 | 0 | { |
238 | 0 | return mScriptMode == ScriptMode::eDeferred; |
239 | 0 | } |
240 | | |
241 | | bool IsAsyncScript() const |
242 | 0 | { |
243 | 0 | return mScriptMode == ScriptMode::eAsync; |
244 | 0 | } |
245 | | |
246 | | virtual bool IsTopLevel() const |
247 | 0 | { |
248 | 0 | // Classic scripts are always top level. |
249 | 0 | return true; |
250 | 0 | } |
251 | | |
252 | | mozilla::CORSMode CORSMode() const |
253 | 0 | { |
254 | 0 | return mFetchOptions->mCORSMode; |
255 | 0 | } |
256 | | mozilla::net::ReferrerPolicy ReferrerPolicy() const |
257 | 0 | { |
258 | 0 | return mFetchOptions->mReferrerPolicy; |
259 | 0 | } |
260 | | nsIScriptElement* Element() const |
261 | 0 | { |
262 | 0 | return mFetchOptions->mElement; |
263 | 0 | } |
264 | | nsIPrincipal* TriggeringPrincipal() const |
265 | 0 | { |
266 | 0 | return mFetchOptions->mTriggeringPrincipal; |
267 | 0 | } |
268 | | |
269 | | void SetElement(nsIScriptElement* aElement) |
270 | 0 | { |
271 | 0 | // Called when a preload request is later used for an actual request. |
272 | 0 | MOZ_ASSERT(aElement); |
273 | 0 | MOZ_ASSERT(!Element()); |
274 | 0 | mFetchOptions->mElement = aElement; |
275 | 0 | } |
276 | | |
277 | | bool ShouldAcceptBinASTEncoding() const; |
278 | | |
279 | | void ClearScriptSource(); |
280 | | |
281 | | void MaybeCancelOffThreadScript(); |
282 | | void DropBytecodeCacheReferences(); |
283 | | |
284 | | using super::getNext; |
285 | | using super::isInList; |
286 | | |
287 | | const ScriptKind mKind; // Whether this is a classic script or a module script. |
288 | | ScriptMode mScriptMode; // Whether this is a blocking, defer or async script. |
289 | | Progress mProgress; // Are we still waiting for a load to complete? |
290 | | DataType mDataType; // Does this contain Source or Bytecode? |
291 | | bool mScriptFromHead; // Synchronous head script block loading of other non js/css content. |
292 | | bool mIsInline; // Is the script inline or loaded? |
293 | | bool mHasSourceMapURL; // Does the HTTP header have a source map url? |
294 | | bool mInDeferList; // True if we live in mDeferRequests. |
295 | | bool mInAsyncList; // True if we live in mLoadingAsyncRequests or mLoadedAsyncRequests. |
296 | | bool mIsNonAsyncScriptInserted; // True if we live in mNonAsyncExternalScriptInsertedRequests |
297 | | bool mIsXSLT; // True if we live in mXSLTRequests. |
298 | | bool mIsCanceled; // True if we have been explicitly canceled. |
299 | | bool mWasCompiledOMT; // True if the script has been compiled off main thread. |
300 | | bool mIsTracking; // True if the script comes from a source on our tracking protection list. |
301 | | |
302 | | RefPtr<ScriptFetchOptions> mFetchOptions; |
303 | | |
304 | | JS::OffThreadToken* mOffThreadToken; // Off-thread parsing token. |
305 | | nsString mSourceMapURL; // Holds source map url for loaded scripts |
306 | | |
307 | | // Holds the top-level JSScript that corresponds to the current source, once |
308 | | // it is parsed, and planned to be saved in the bytecode cache. |
309 | | JS::Heap<JSScript*> mScript; |
310 | | |
311 | | // Holds script source data for non-inline scripts. Don't use nsString so we |
312 | | // can give ownership to jsapi. Holds either char16_t source text characters |
313 | | // or BinAST encoded bytes depending on mSourceEncoding. |
314 | | Maybe<Variant<ScriptTextBuffer, BinASTSourceBuffer>> mScriptData; |
315 | | |
316 | | // The length of script source text, set when reading completes. This is used |
317 | | // since mScriptData is cleared when the source is passed to the JS engine. |
318 | | size_t mScriptTextLength; |
319 | | |
320 | | // Holds the SRI serialized hash and the script bytecode for non-inline |
321 | | // scripts. |
322 | | mozilla::Vector<uint8_t> mScriptBytecode; |
323 | | uint32_t mBytecodeOffset; // Offset of the bytecode in mScriptBytecode |
324 | | |
325 | | const nsCOMPtr<nsIURI> mURI; |
326 | | nsCOMPtr<nsIPrincipal> mOriginPrincipal; |
327 | | nsAutoCString mURL; // Keep the URI's filename alive during off thread parsing. |
328 | | int32_t mLineNo; |
329 | | const SRIMetadata mIntegrity; |
330 | | const nsCOMPtr<nsIURI> mReferrer; |
331 | | |
332 | | // Holds the Cache information, which is used to register the bytecode |
333 | | // on the cache entry, such that we can load it the next time. |
334 | | nsCOMPtr<nsICacheInfoChannel> mCacheInfo; |
335 | | }; |
336 | | |
337 | | class ScriptLoadRequestList : private mozilla::LinkedList<ScriptLoadRequest> |
338 | | { |
339 | | typedef mozilla::LinkedList<ScriptLoadRequest> super; |
340 | | |
341 | | public: |
342 | | ~ScriptLoadRequestList(); |
343 | | |
344 | | void Clear(); |
345 | | |
346 | | #ifdef DEBUG |
347 | | bool Contains(ScriptLoadRequest* aElem) const; |
348 | | #endif // DEBUG |
349 | | |
350 | | using super::getFirst; |
351 | | using super::isEmpty; |
352 | | |
353 | | void AppendElement(ScriptLoadRequest* aElem) |
354 | 0 | { |
355 | 0 | MOZ_ASSERT(!aElem->isInList()); |
356 | 0 | NS_ADDREF(aElem); |
357 | 0 | insertBack(aElem); |
358 | 0 | } |
359 | | |
360 | | MOZ_MUST_USE |
361 | | already_AddRefed<ScriptLoadRequest> Steal(ScriptLoadRequest* aElem) |
362 | 0 | { |
363 | 0 | aElem->removeFrom(*this); |
364 | 0 | return dont_AddRef(aElem); |
365 | 0 | } |
366 | | |
367 | | MOZ_MUST_USE |
368 | | already_AddRefed<ScriptLoadRequest> StealFirst() |
369 | 0 | { |
370 | 0 | MOZ_ASSERT(!isEmpty()); |
371 | 0 | return Steal(getFirst()); |
372 | 0 | } |
373 | | |
374 | | void Remove(ScriptLoadRequest* aElem) |
375 | 0 | { |
376 | 0 | aElem->removeFrom(*this); |
377 | 0 | NS_RELEASE(aElem); |
378 | 0 | } |
379 | | }; |
380 | | |
381 | | void |
382 | | ImplCycleCollectionUnlink(ScriptLoadRequestList& aField); |
383 | | |
384 | | void |
385 | | ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback, |
386 | | ScriptLoadRequestList& aField, |
387 | | const char* aName, |
388 | | uint32_t aFlags); |
389 | | |
390 | | } // namespace dom |
391 | | } // namespace mozilla |
392 | | |
393 | | #endif // mozilla_dom_ScriptLoadRequest_h |