Backed out changeset 6a14206eb5a9 (bug 1299271) for causing python taskgraph-tests...
[gecko.git] / parser / html / nsHtml5SpeculativeLoad.h
blob9aedb5fb95355f8073286bd54f566a5dc82625ee
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 eSpeculativeLoadStyle,
28 eSpeculativeLoadManifest,
29 eSpeculativeLoadSetDocumentCharset,
30 eSpeculativeLoadSetDocumentMode,
31 eSpeculativeLoadPreconnect,
32 eSpeculativeLoadFont,
33 eSpeculativeLoadFetch,
34 eSpeculativeLoadMaybeComplainAboutCharset
37 class nsHtml5SpeculativeLoad {
38 using Encoding = mozilla::Encoding;
39 template <typename T>
40 using NotNull = mozilla::NotNull<T>;
42 public:
43 nsHtml5SpeculativeLoad();
44 ~nsHtml5SpeculativeLoad();
46 inline void InitBase(nsHtml5String aUrl) {
47 MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized,
48 "Trying to reinitialize a speculative load!");
49 mOpCode = eSpeculativeLoadBase;
50 aUrl.ToString(mUrlOrSizes);
53 inline void InitMetaCSP(nsHtml5String aCSP) {
54 MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized,
55 "Trying to reinitialize a speculative load!");
56 mOpCode = eSpeculativeLoadCSP;
57 nsString csp; // Not Auto, because using it to hold nsStringBuffer*
58 aCSP.ToString(csp);
59 mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity.Assign(
60 nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>(csp));
63 inline void InitMetaReferrerPolicy(nsHtml5String aReferrerPolicy) {
64 MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized,
65 "Trying to reinitialize a speculative load!");
66 mOpCode = eSpeculativeLoadMetaReferrer;
67 nsString
68 referrerPolicy; // Not Auto, because using it to hold nsStringBuffer*
69 aReferrerPolicy.ToString(referrerPolicy);
70 mReferrerPolicyOrIntegrity.Assign(
71 nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>(
72 referrerPolicy));
75 inline void InitImage(nsHtml5String aUrl, nsHtml5String aCrossOrigin,
76 nsHtml5String aMedia, nsHtml5String aReferrerPolicy,
77 nsHtml5String aSrcset, nsHtml5String aSizes,
78 bool aLinkPreload) {
79 MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized,
80 "Trying to reinitialize a speculative load!");
81 mOpCode = eSpeculativeLoadImage;
82 aUrl.ToString(mUrlOrSizes);
83 aCrossOrigin.ToString(mCrossOrigin);
84 aMedia.ToString(mMedia);
85 nsString
86 referrerPolicy; // Not Auto, because using it to hold nsStringBuffer*
87 aReferrerPolicy.ToString(referrerPolicy);
88 mReferrerPolicyOrIntegrity.Assign(
89 nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>(
90 referrerPolicy));
91 aSrcset.ToString(mCharsetOrSrcset);
92 aSizes.ToString(
93 mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity);
94 mIsLinkPreload = aLinkPreload;
97 inline void InitFont(nsHtml5String aUrl, nsHtml5String aCrossOrigin,
98 nsHtml5String aMedia, nsHtml5String aReferrerPolicy) {
99 MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized,
100 "Trying to reinitialize a speculative load!");
101 mOpCode = eSpeculativeLoadFont;
102 aUrl.ToString(mUrlOrSizes);
103 aCrossOrigin.ToString(mCrossOrigin);
104 aMedia.ToString(mMedia);
105 nsString
106 referrerPolicy; // Not Auto, because using it to hold nsStringBuffer*
107 aReferrerPolicy.ToString(referrerPolicy);
108 mReferrerPolicyOrIntegrity.Assign(
109 nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>(
110 referrerPolicy));
111 // This can be only triggered by <link rel=preload type=font>
112 mIsLinkPreload = true;
115 inline void InitFetch(nsHtml5String aUrl, nsHtml5String aCrossOrigin,
116 nsHtml5String aMedia, nsHtml5String aReferrerPolicy) {
117 MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized,
118 "Trying to reinitialize a speculative load!");
119 mOpCode = eSpeculativeLoadFetch;
120 aUrl.ToString(mUrlOrSizes);
121 aCrossOrigin.ToString(mCrossOrigin);
122 aMedia.ToString(mMedia);
123 nsString
124 referrerPolicy; // Not Auto, because using it to hold nsStringBuffer*
125 aReferrerPolicy.ToString(referrerPolicy);
126 mReferrerPolicyOrIntegrity.Assign(
127 nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>(
128 referrerPolicy));
130 // This method can be only be triggered by <link rel=preload type=fetch>,
131 // hence this operation is always a preload.
132 mIsLinkPreload = true;
135 // <picture> elements have multiple <source> nodes followed by an <img>,
136 // where we use the first valid source, which may be the img. Because we
137 // can't determine validity at this point without parsing CSS and getting
138 // main thread state, we push preload operations for picture pushed and
139 // popped, so that the target of the preload ops can determine what picture
140 // and nesting level each source/img from the main preloading code exists
141 // at.
142 inline void InitOpenPicture() {
143 MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized,
144 "Trying to reinitialize a speculative load!");
145 mOpCode = eSpeculativeLoadOpenPicture;
148 inline void InitEndPicture() {
149 MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized,
150 "Trying to reinitialize a speculative load!");
151 mOpCode = eSpeculativeLoadEndPicture;
154 inline void InitPictureSource(nsHtml5String aSrcset, nsHtml5String aSizes,
155 nsHtml5String aType, nsHtml5String aMedia) {
156 MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized,
157 "Trying to reinitialize a speculative load!");
158 mOpCode = eSpeculativeLoadPictureSource;
159 aSrcset.ToString(mCharsetOrSrcset);
160 aSizes.ToString(mUrlOrSizes);
161 aType.ToString(
162 mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity);
163 aMedia.ToString(mMedia);
166 inline void InitScript(nsHtml5String aUrl, nsHtml5String aCharset,
167 nsHtml5String aType, nsHtml5String aCrossOrigin,
168 nsHtml5String aMedia, nsHtml5String aNonce,
169 nsHtml5String aFetchPriority, nsHtml5String aIntegrity,
170 nsHtml5String aReferrerPolicy, bool aParserInHead,
171 bool aAsync, bool aDefer, bool aLinkPreload) {
172 MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized,
173 "Trying to reinitialize a speculative load!");
174 mOpCode =
175 aParserInHead ? eSpeculativeLoadScriptFromHead : eSpeculativeLoadScript;
176 aUrl.ToString(mUrlOrSizes);
177 aCharset.ToString(mCharsetOrSrcset);
178 aType.ToString(
179 mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity);
180 aCrossOrigin.ToString(mCrossOrigin);
181 aMedia.ToString(mMedia);
182 aNonce.ToString(mNonce);
183 aFetchPriority.ToString(mFetchPriority);
184 aIntegrity.ToString(mReferrerPolicyOrIntegrity);
185 nsAutoString referrerPolicy;
186 aReferrerPolicy.ToString(referrerPolicy);
187 referrerPolicy =
188 nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>(
189 referrerPolicy);
190 mScriptReferrerPolicy =
191 mozilla::dom::ReferrerInfo::ReferrerPolicyAttributeFromString(
192 referrerPolicy);
194 mIsAsync = aAsync;
195 mIsDefer = aDefer;
196 mIsLinkPreload = aLinkPreload;
199 inline void InitImportStyle(nsString&& aUrl) {
200 MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized,
201 "Trying to reinitialize a speculative load!");
202 mOpCode = eSpeculativeLoadStyle;
203 mUrlOrSizes = std::move(aUrl);
204 mCharsetOrSrcset.SetIsVoid(true);
205 mCrossOrigin.SetIsVoid(true);
206 mMedia.SetIsVoid(true);
207 mReferrerPolicyOrIntegrity.SetIsVoid(true);
208 mNonce.SetIsVoid(true);
209 mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity.SetIsVoid(
210 true);
213 inline void InitStyle(nsHtml5String aUrl, nsHtml5String aCharset,
214 nsHtml5String aCrossOrigin, nsHtml5String aMedia,
215 nsHtml5String aReferrerPolicy, nsHtml5String aNonce,
216 nsHtml5String aIntegrity, bool aLinkPreload) {
217 MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized,
218 "Trying to reinitialize a speculative load!");
219 mOpCode = eSpeculativeLoadStyle;
220 aUrl.ToString(mUrlOrSizes);
221 aCharset.ToString(mCharsetOrSrcset);
222 aCrossOrigin.ToString(mCrossOrigin);
223 aMedia.ToString(mMedia);
224 nsString
225 referrerPolicy; // Not Auto, because using it to hold nsStringBuffer*
226 aReferrerPolicy.ToString(referrerPolicy);
227 mReferrerPolicyOrIntegrity.Assign(
228 nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>(
229 referrerPolicy));
230 aNonce.ToString(mNonce);
231 aIntegrity.ToString(
232 mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity);
233 mIsLinkPreload = aLinkPreload;
237 * "Speculative" manifest loads aren't truly speculative--if a manifest
238 * gets loaded, we are committed to it. There can never be a <script>
239 * before the manifest, so the situation of having to undo a manifest due
240 * to document.write() never arises. The reason why a parser
241 * thread-discovered manifest gets loaded via the speculative load queue
242 * as opposed to tree operation queue is that the manifest must get
243 * processed before any actual speculative loads such as scripts. Thus,
244 * manifests seen by the parser thread have to maintain the queue order
245 * relative to true speculative loads. See bug 541079.
247 inline void InitManifest(nsHtml5String aUrl) {
248 MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized,
249 "Trying to reinitialize a speculative load!");
250 mOpCode = eSpeculativeLoadManifest;
251 aUrl.ToString(mUrlOrSizes);
255 * We communicate the encoding change via the speculative operation
256 * queue in order to act upon it as soon as possible and so as not to
257 * have speculative loads generated after an encoding change fail to
258 * make use of the encoding change.
260 inline void InitSetDocumentCharset(NotNull<const Encoding*> aEncoding,
261 int32_t aCharsetSource,
262 bool aCommitEncodingSpeculation) {
263 MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized,
264 "Trying to reinitialize a speculative load!");
265 mOpCode = eSpeculativeLoadSetDocumentCharset;
266 mCharsetOrSrcset.~nsString();
267 mEncoding = aEncoding;
268 mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity.Assign(
269 (char16_t)aCharsetSource);
270 mCommitEncodingSpeculation = aCommitEncodingSpeculation;
273 inline void InitMaybeComplainAboutCharset(const char* aMsgId, bool aError,
274 int32_t aLineNumber) {
275 MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized,
276 "Trying to reinitialize a speculative load!");
277 mOpCode = eSpeculativeLoadMaybeComplainAboutCharset;
278 mCharsetOrSrcset.~nsString();
279 mMsgId = aMsgId;
280 mIsError = aError;
281 // Transport a 32-bit integer as two 16-bit code units of a string
282 // in order to avoid adding an integer field to the object.
283 // See https://bugzilla.mozilla.org/show_bug.cgi?id=1733043 for a better
284 // eventual approach.
285 char16_t high = (char16_t)(((uint32_t)aLineNumber) >> 16);
286 char16_t low = (char16_t)(((uint32_t)aLineNumber) & 0xFFFF);
287 mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity.Assign(high);
288 mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity.Append(low);
292 * Speculative document mode setting isn't really speculative. Once it
293 * happens, we are committed to it. However, this information needs to
294 * travel in the speculation queue in order to have this information
295 * available before parsing the speculatively loaded style sheets.
297 inline void InitSetDocumentMode(nsHtml5DocumentMode aMode) {
298 MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized,
299 "Trying to reinitialize a speculative load!");
300 mOpCode = eSpeculativeLoadSetDocumentMode;
301 mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity.Assign(
302 (char16_t)aMode);
305 inline void InitPreconnect(nsHtml5String aUrl, nsHtml5String aCrossOrigin) {
306 MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized,
307 "Trying to reinitialize a speculative load!");
308 mOpCode = eSpeculativeLoadPreconnect;
309 aUrl.ToString(mUrlOrSizes);
310 aCrossOrigin.ToString(mCrossOrigin);
313 void Perform(nsHtml5TreeOpExecutor* aExecutor);
315 private:
316 nsHtml5SpeculativeLoad(const nsHtml5SpeculativeLoad&) = delete;
317 nsHtml5SpeculativeLoad& operator=(const nsHtml5SpeculativeLoad&) = delete;
319 eHtml5SpeculativeLoad mOpCode;
322 * Whether the refering element has async attribute.
324 bool mIsAsync;
327 * Whether the refering element has defer attribute.
329 bool mIsDefer;
332 * True if and only if this is a speculative load initiated by <link
333 * rel="preload"> or <link rel="modulepreload"> tag encounter. Passed to the
334 * handling loader as an indication to raise the priority.
336 bool mIsLinkPreload;
339 * Whether the charset complaint is an error.
341 bool mIsError;
344 * Whether setting document encoding involves also committing to an encoding
345 * speculation.
347 bool mCommitEncodingSpeculation;
349 /* If mOpCode is eSpeculativeLoadPictureSource, this is the value of the
350 * "sizes" attribute. If the attribute is not set, this will be a void
351 * string. Otherwise it empty or the value of the url.
353 nsString mUrlOrSizes;
355 * If mOpCode is eSpeculativeLoadScript[FromHead], this is the value of the
356 * "integrity" attribute. If the attribute is not set, this will be a void
357 * string. Otherwise it is empty or the value of the referrer policy.
359 nsString mReferrerPolicyOrIntegrity;
361 * If mOpCode is eSpeculativeLoadStyle or eSpeculativeLoadScript[FromHead]
362 * then this is the value of the "charset" attribute. For
363 * eSpeculativeLoadSetDocumentCharset it is the charset that the
364 * document's charset is being set to. If mOpCode is eSpeculativeLoadImage
365 * or eSpeculativeLoadPictureSource, this is the value of the "srcset"
366 * attribute. If the attribute is not set, this will be a void string.
367 * Otherwise it's empty.
368 * For eSpeculativeLoadMaybeComplainAboutCharset mMsgId is used.
370 union {
371 nsString mCharsetOrSrcset;
372 const Encoding* mEncoding;
373 const char* mMsgId;
376 * If mOpCode is eSpeculativeLoadSetDocumentCharset, this is a
377 * one-character string whose single character's code point is to be
378 * interpreted as a charset source integer. If mOpCode is
379 * eSpeculativeLoadSetDocumentMode, this is a one-character string whose
380 * single character's code point is to be interpreted as an
381 * nsHtml5DocumentMode. If mOpCode is eSpeculativeLoadCSP, this is a meta
382 * element's CSP value. If mOpCode is eSpeculativeLoadImage, this is the
383 * value of the "sizes" attribute. If the attribute is not set, this will
384 * be a void string. If mOpCode is eSpeculativeLoadStyle, this
385 * is the value of the "integrity" attribute. If the attribute is not set,
386 * this will be a void string. Otherwise, it is empty or the value of the type
387 * attribute.
389 nsString mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity;
391 * If mOpCode is eSpeculativeLoadImage or eSpeculativeLoadScript[FromHead]
392 * or eSpeculativeLoadPreconnect or eSpeculativeLoadStyle this is the value of
393 * the "crossorigin" attribute. If the attribute is not set, this will be a
394 * void string.
396 nsString mCrossOrigin;
398 * If mOpCode is eSpeculativeLoadPictureSource or eSpeculativeLoadStyle or
399 * Fetch or Image or Media or Script this is the value of the relevant "media"
400 * attribute of the <link rel="preload"> or <link rel="stylesheet">. If the
401 * attribute is not set, or the preload didn't originate from a <link>, this
402 * will be a void string.
404 nsString mMedia;
406 * If mOpCode is eSpeculativeLoadScript[FromHead] this represents the value
407 * of the "nonce" attribute.
409 nsString mNonce;
411 * If mOpCode is eSpeculativeLoadNoModuleScript[FromHead] or
412 * eSpeculativeLoadScript[FromHead] this represents the value of the
413 * "fetchpriority" attribute.
415 nsString mFetchPriority;
417 * If mOpCode is eSpeculativeLoadScript[FromHead] this represents the value
418 * of the "referrerpolicy" attribute. This field holds one of the values
419 * (REFERRER_POLICY_*) defined in nsIHttpChannel.
421 mozilla::dom::ReferrerPolicy mScriptReferrerPolicy;
424 #endif // nsHtml5SpeculativeLoad_h