Bug 1833854 - Part 7: Add the FOR_EACH_GC_TUNABLE macro to describe tunable GC parame...
[gecko.git] / parser / html / nsHtml5SpeculativeLoad.h
blob4b2f755857057231a90b0f33753adafe7b463492
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 #ifndef nsHtml5SpeculativeLoad_h
6 #define nsHtml5SpeculativeLoad_h
8 #include "nsString.h"
9 #include "nsContentUtils.h"
10 #include "nsHtml5DocumentMode.h"
11 #include "nsHtml5String.h"
12 #include "ReferrerInfo.h"
14 class nsHtml5TreeOpExecutor;
16 enum eHtml5SpeculativeLoad {
17 eSpeculativeLoadUninitialized,
18 eSpeculativeLoadBase,
19 eSpeculativeLoadCSP,
20 eSpeculativeLoadMetaReferrer,
21 eSpeculativeLoadImage,
22 eSpeculativeLoadOpenPicture,
23 eSpeculativeLoadEndPicture,
24 eSpeculativeLoadPictureSource,
25 eSpeculativeLoadScript,
26 eSpeculativeLoadScriptFromHead,
27 eSpeculativeLoadNoModuleScript,
28 eSpeculativeLoadNoModuleScriptFromHead,
29 eSpeculativeLoadStyle,
30 eSpeculativeLoadManifest,
31 eSpeculativeLoadSetDocumentCharset,
32 eSpeculativeLoadSetDocumentMode,
33 eSpeculativeLoadPreconnect,
34 eSpeculativeLoadFont,
35 eSpeculativeLoadFetch,
36 eSpeculativeLoadMaybeComplainAboutCharset
39 class nsHtml5SpeculativeLoad {
40 using Encoding = mozilla::Encoding;
41 template <typename T>
42 using NotNull = mozilla::NotNull<T>;
44 public:
45 nsHtml5SpeculativeLoad();
46 ~nsHtml5SpeculativeLoad();
48 inline void InitBase(nsHtml5String aUrl) {
49 MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized,
50 "Trying to reinitialize a speculative load!");
51 mOpCode = eSpeculativeLoadBase;
52 aUrl.ToString(mUrlOrSizes);
55 inline void InitMetaCSP(nsHtml5String aCSP) {
56 MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized,
57 "Trying to reinitialize a speculative load!");
58 mOpCode = eSpeculativeLoadCSP;
59 nsString csp; // Not Auto, because using it to hold nsStringBuffer*
60 aCSP.ToString(csp);
61 mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity.Assign(
62 nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>(csp));
65 inline void InitMetaReferrerPolicy(nsHtml5String aReferrerPolicy) {
66 MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized,
67 "Trying to reinitialize a speculative load!");
68 mOpCode = eSpeculativeLoadMetaReferrer;
69 nsString
70 referrerPolicy; // Not Auto, because using it to hold nsStringBuffer*
71 aReferrerPolicy.ToString(referrerPolicy);
72 mReferrerPolicyOrIntegrity.Assign(
73 nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>(
74 referrerPolicy));
77 inline void InitImage(nsHtml5String aUrl, nsHtml5String aCrossOrigin,
78 nsHtml5String aMedia, nsHtml5String aReferrerPolicy,
79 nsHtml5String aSrcset, nsHtml5String aSizes,
80 bool aLinkPreload) {
81 MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized,
82 "Trying to reinitialize a speculative load!");
83 mOpCode = eSpeculativeLoadImage;
84 aUrl.ToString(mUrlOrSizes);
85 aCrossOrigin.ToString(mCrossOrigin);
86 aMedia.ToString(mMedia);
87 nsString
88 referrerPolicy; // Not Auto, because using it to hold nsStringBuffer*
89 aReferrerPolicy.ToString(referrerPolicy);
90 mReferrerPolicyOrIntegrity.Assign(
91 nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>(
92 referrerPolicy));
93 aSrcset.ToString(mCharsetOrSrcset);
94 aSizes.ToString(
95 mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity);
96 mIsLinkPreload = aLinkPreload;
97 mInitTimestamp = mozilla::TimeStamp::Now();
100 inline void InitFont(nsHtml5String aUrl, nsHtml5String aCrossOrigin,
101 nsHtml5String aMedia, nsHtml5String aReferrerPolicy) {
102 MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized,
103 "Trying to reinitialize a speculative load!");
104 mOpCode = eSpeculativeLoadFont;
105 aUrl.ToString(mUrlOrSizes);
106 aCrossOrigin.ToString(mCrossOrigin);
107 aMedia.ToString(mMedia);
108 nsString
109 referrerPolicy; // Not Auto, because using it to hold nsStringBuffer*
110 aReferrerPolicy.ToString(referrerPolicy);
111 mReferrerPolicyOrIntegrity.Assign(
112 nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>(
113 referrerPolicy));
114 // This can be only triggered by <link rel=preload type=font>
115 mIsLinkPreload = true;
118 inline void InitFetch(nsHtml5String aUrl, nsHtml5String aCrossOrigin,
119 nsHtml5String aMedia, nsHtml5String aReferrerPolicy) {
120 MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized,
121 "Trying to reinitialize a speculative load!");
122 mOpCode = eSpeculativeLoadFetch;
123 aUrl.ToString(mUrlOrSizes);
124 aCrossOrigin.ToString(mCrossOrigin);
125 aMedia.ToString(mMedia);
126 nsString
127 referrerPolicy; // Not Auto, because using it to hold nsStringBuffer*
128 aReferrerPolicy.ToString(referrerPolicy);
129 mReferrerPolicyOrIntegrity.Assign(
130 nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>(
131 referrerPolicy));
133 // This method can be only be triggered by <link rel=preload type=fetch>,
134 // hence this operation is always a preload.
135 mIsLinkPreload = true;
138 // <picture> elements have multiple <source> nodes followed by an <img>,
139 // where we use the first valid source, which may be the img. Because we
140 // can't determine validity at this point without parsing CSS and getting
141 // main thread state, we push preload operations for picture pushed and
142 // popped, so that the target of the preload ops can determine what picture
143 // and nesting level each source/img from the main preloading code exists
144 // at.
145 inline void InitOpenPicture() {
146 MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized,
147 "Trying to reinitialize a speculative load!");
148 mOpCode = eSpeculativeLoadOpenPicture;
151 inline void InitEndPicture() {
152 MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized,
153 "Trying to reinitialize a speculative load!");
154 mOpCode = eSpeculativeLoadEndPicture;
157 inline void InitPictureSource(nsHtml5String aSrcset, nsHtml5String aSizes,
158 nsHtml5String aType, nsHtml5String aMedia) {
159 MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized,
160 "Trying to reinitialize a speculative load!");
161 mOpCode = eSpeculativeLoadPictureSource;
162 aSrcset.ToString(mCharsetOrSrcset);
163 aSizes.ToString(mUrlOrSizes);
164 aType.ToString(
165 mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity);
166 aMedia.ToString(mMedia);
169 inline void InitScript(nsHtml5String aUrl, nsHtml5String aCharset,
170 nsHtml5String aType, nsHtml5String aCrossOrigin,
171 nsHtml5String aMedia, nsHtml5String aIntegrity,
172 nsHtml5String aReferrerPolicy, bool aParserInHead,
173 bool aAsync, bool aDefer, bool aNoModule,
174 bool aLinkPreload) {
175 MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized,
176 "Trying to reinitialize a speculative load!");
177 if (aNoModule) {
178 mOpCode = aParserInHead ? eSpeculativeLoadNoModuleScriptFromHead
179 : eSpeculativeLoadNoModuleScript;
180 } else {
181 mOpCode = aParserInHead ? eSpeculativeLoadScriptFromHead
182 : eSpeculativeLoadScript;
184 aUrl.ToString(mUrlOrSizes);
185 aCharset.ToString(mCharsetOrSrcset);
186 aType.ToString(
187 mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity);
188 aCrossOrigin.ToString(mCrossOrigin);
189 aMedia.ToString(mMedia);
190 aIntegrity.ToString(mReferrerPolicyOrIntegrity);
191 nsAutoString referrerPolicy;
192 aReferrerPolicy.ToString(referrerPolicy);
193 referrerPolicy =
194 nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>(
195 referrerPolicy);
196 mScriptReferrerPolicy =
197 mozilla::dom::ReferrerInfo::ReferrerPolicyAttributeFromString(
198 referrerPolicy);
200 mIsAsync = aAsync;
201 mIsDefer = aDefer;
202 mIsLinkPreload = aLinkPreload;
205 inline void InitImportStyle(nsString&& aUrl) {
206 MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized,
207 "Trying to reinitialize a speculative load!");
208 mOpCode = eSpeculativeLoadStyle;
209 mUrlOrSizes = std::move(aUrl);
210 mCharsetOrSrcset.SetIsVoid(true);
211 mCrossOrigin.SetIsVoid(true);
212 mMedia.SetIsVoid(true);
213 mReferrerPolicyOrIntegrity.SetIsVoid(true);
214 mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity.SetIsVoid(
215 true);
218 inline void InitStyle(nsHtml5String aUrl, nsHtml5String aCharset,
219 nsHtml5String aCrossOrigin, nsHtml5String aMedia,
220 nsHtml5String aReferrerPolicy, nsHtml5String aIntegrity,
221 bool aLinkPreload) {
222 MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized,
223 "Trying to reinitialize a speculative load!");
224 mOpCode = eSpeculativeLoadStyle;
225 aUrl.ToString(mUrlOrSizes);
226 aCharset.ToString(mCharsetOrSrcset);
227 aCrossOrigin.ToString(mCrossOrigin);
228 aMedia.ToString(mMedia);
229 nsString
230 referrerPolicy; // Not Auto, because using it to hold nsStringBuffer*
231 aReferrerPolicy.ToString(referrerPolicy);
232 mReferrerPolicyOrIntegrity.Assign(
233 nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>(
234 referrerPolicy));
235 aIntegrity.ToString(
236 mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity);
237 mIsLinkPreload = aLinkPreload;
241 * "Speculative" manifest loads aren't truly speculative--if a manifest
242 * gets loaded, we are committed to it. There can never be a <script>
243 * before the manifest, so the situation of having to undo a manifest due
244 * to document.write() never arises. The reason why a parser
245 * thread-discovered manifest gets loaded via the speculative load queue
246 * as opposed to tree operation queue is that the manifest must get
247 * processed before any actual speculative loads such as scripts. Thus,
248 * manifests seen by the parser thread have to maintain the queue order
249 * relative to true speculative loads. See bug 541079.
251 inline void InitManifest(nsHtml5String aUrl) {
252 MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized,
253 "Trying to reinitialize a speculative load!");
254 mOpCode = eSpeculativeLoadManifest;
255 aUrl.ToString(mUrlOrSizes);
259 * We communicate the encoding change via the speculative operation
260 * queue in order to act upon it as soon as possible and so as not to
261 * have speculative loads generated after an encoding change fail to
262 * make use of the encoding change.
264 inline void InitSetDocumentCharset(NotNull<const Encoding*> aEncoding,
265 int32_t aCharsetSource,
266 bool aCommitEncodingSpeculation) {
267 MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized,
268 "Trying to reinitialize a speculative load!");
269 mOpCode = eSpeculativeLoadSetDocumentCharset;
270 mCharsetOrSrcset.~nsString();
271 mEncoding = aEncoding;
272 mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity.Assign(
273 (char16_t)aCharsetSource);
274 mCommitEncodingSpeculation = aCommitEncodingSpeculation;
277 inline void InitMaybeComplainAboutCharset(const char* aMsgId, bool aError,
278 int32_t aLineNumber) {
279 MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized,
280 "Trying to reinitialize a speculative load!");
281 mOpCode = eSpeculativeLoadMaybeComplainAboutCharset;
282 mCharsetOrSrcset.~nsString();
283 mMsgId = aMsgId;
284 mIsError = aError;
285 // Transport a 32-bit integer as two 16-bit code units of a string
286 // in order to avoid adding an integer field to the object.
287 // See https://bugzilla.mozilla.org/show_bug.cgi?id=1733043 for a better
288 // eventual approach.
289 char16_t high = (char16_t)(((uint32_t)aLineNumber) >> 16);
290 char16_t low = (char16_t)(((uint32_t)aLineNumber) & 0xFFFF);
291 mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity.Assign(high);
292 mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity.Append(low);
296 * Speculative document mode setting isn't really speculative. Once it
297 * happens, we are committed to it. However, this information needs to
298 * travel in the speculation queue in order to have this information
299 * available before parsing the speculatively loaded style sheets.
301 inline void InitSetDocumentMode(nsHtml5DocumentMode aMode) {
302 MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized,
303 "Trying to reinitialize a speculative load!");
304 mOpCode = eSpeculativeLoadSetDocumentMode;
305 mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity.Assign(
306 (char16_t)aMode);
309 inline void InitPreconnect(nsHtml5String aUrl, nsHtml5String aCrossOrigin) {
310 MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized,
311 "Trying to reinitialize a speculative load!");
312 mOpCode = eSpeculativeLoadPreconnect;
313 aUrl.ToString(mUrlOrSizes);
314 aCrossOrigin.ToString(mCrossOrigin);
317 void Perform(nsHtml5TreeOpExecutor* aExecutor);
319 private:
320 nsHtml5SpeculativeLoad(const nsHtml5SpeculativeLoad&) = delete;
321 nsHtml5SpeculativeLoad& operator=(const nsHtml5SpeculativeLoad&) = delete;
323 eHtml5SpeculativeLoad mOpCode;
326 * Whether the refering element has async attribute.
328 bool mIsAsync;
331 * Whether the refering element has defer attribute.
333 bool mIsDefer;
336 * True if and only if this is a speculative load initiated by <link
337 * rel="preload"> or <link rel="modulepreload"> tag encounter. Passed to the
338 * handling loader as an indication to raise the priority.
340 bool mIsLinkPreload;
343 * Whether the charset complaint is an error.
345 bool mIsError;
348 * Whether setting document encoding involves also committing to an encoding
349 * speculation.
351 bool mCommitEncodingSpeculation;
353 /* If mOpCode is eSpeculativeLoadPictureSource, this is the value of the
354 * "sizes" attribute. If the attribute is not set, this will be a void
355 * string. Otherwise it empty or the value of the url.
357 nsString mUrlOrSizes;
359 * If mOpCode is eSpeculativeLoadScript[FromHead], this is the value of the
360 * "integrity" attribute. If the attribute is not set, this will be a void
361 * string. Otherwise it is empty or the value of the referrer policy.
363 nsString mReferrerPolicyOrIntegrity;
365 * If mOpCode is eSpeculativeLoadStyle or eSpeculativeLoadScript[FromHead]
366 * then this is the value of the "charset" attribute. For
367 * eSpeculativeLoadSetDocumentCharset it is the charset that the
368 * document's charset is being set to. If mOpCode is eSpeculativeLoadImage
369 * or eSpeculativeLoadPictureSource, this is the value of the "srcset"
370 * attribute. If the attribute is not set, this will be a void string.
371 * Otherwise it's empty.
372 * For eSpeculativeLoadMaybeComplainAboutCharset mMsgId is used.
374 union {
375 nsString mCharsetOrSrcset;
376 const Encoding* mEncoding;
377 const char* mMsgId;
380 * If mOpCode is eSpeculativeLoadSetDocumentCharset, this is a
381 * one-character string whose single character's code point is to be
382 * interpreted as a charset source integer. If mOpCode is
383 * eSpeculativeLoadSetDocumentMode, this is a one-character string whose
384 * single character's code point is to be interpreted as an
385 * nsHtml5DocumentMode. If mOpCode is eSpeculativeLoadCSP, this is a meta
386 * element's CSP value. If mOpCode is eSpeculativeLoadImage, this is the
387 * value of the "sizes" attribute. If the attribute is not set, this will
388 * be a void string. If mOpCode is eSpeculativeLoadStyle, this
389 * is the value of the "integrity" attribute. If the attribute is not set,
390 * this will be a void string. Otherwise, it is empty or the value of the type
391 * attribute.
393 nsString mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity;
395 * If mOpCode is eSpeculativeLoadImage or eSpeculativeLoadScript[FromHead]
396 * or eSpeculativeLoadPreconnect or eSpeculativeLoadStyle this is the value of
397 * the "crossorigin" attribute. If the attribute is not set, this will be a
398 * void string.
400 nsString mCrossOrigin;
402 * If mOpCode is eSpeculativeLoadPictureSource or eSpeculativeLoadStyle or
403 * Fetch or Image or Media or Script this is the value of the relevant "media"
404 * attribute of the <link rel="preload"> or <link rel="stylesheet">. If the
405 * attribute is not set, or the preload didn't originate from a <link>, this
406 * will be a void string.
408 nsString mMedia;
410 * If mOpCode is eSpeculativeLoadScript[FromHead] this represents the value
411 * of the "referrerpolicy" attribute. This field holds one of the values
412 * (REFERRER_POLICY_*) defined in nsIHttpChannel.
414 mozilla::dom::ReferrerPolicy mScriptReferrerPolicy;
416 mozilla::TimeStamp mInitTimestamp;
419 #endif // nsHtml5SpeculativeLoad_h