Bug 1687263: part 4) Defer and in some cases avoid removing spellchecking-ranges...
[gecko.git] / parser / html / nsHtml5SpeculativeLoad.h
blobaec3d1ff7223a230baf3e79ed747fa3284c0cc1f
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
38 class nsHtml5SpeculativeLoad {
39 using Encoding = mozilla::Encoding;
40 template <typename T>
41 using NotNull = mozilla::NotNull<T>;
43 public:
44 nsHtml5SpeculativeLoad();
45 ~nsHtml5SpeculativeLoad();
47 inline void InitBase(nsHtml5String aUrl) {
48 MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized,
49 "Trying to reinitialize a speculative load!");
50 mOpCode = eSpeculativeLoadBase;
51 aUrl.ToString(mUrlOrSizes);
54 inline void InitMetaCSP(nsHtml5String aCSP) {
55 MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized,
56 "Trying to reinitialize a speculative load!");
57 mOpCode = eSpeculativeLoadCSP;
58 nsString csp; // Not Auto, because using it to hold nsStringBuffer*
59 aCSP.ToString(csp);
60 mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity.Assign(
61 nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>(csp));
64 inline void InitMetaReferrerPolicy(nsHtml5String aReferrerPolicy) {
65 MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized,
66 "Trying to reinitialize a speculative load!");
67 mOpCode = eSpeculativeLoadMetaReferrer;
68 nsString
69 referrerPolicy; // Not Auto, because using it to hold nsStringBuffer*
70 aReferrerPolicy.ToString(referrerPolicy);
71 mReferrerPolicyOrIntegrity.Assign(
72 nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>(
73 referrerPolicy));
76 inline void InitImage(nsHtml5String aUrl, nsHtml5String aCrossOrigin,
77 nsHtml5String aMedia, nsHtml5String aReferrerPolicy,
78 nsHtml5String aSrcset, nsHtml5String aSizes,
79 bool aLinkPreload) {
80 MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized,
81 "Trying to reinitialize a speculative load!");
82 mOpCode = eSpeculativeLoadImage;
83 aUrl.ToString(mUrlOrSizes);
84 aCrossOrigin.ToString(mCrossOrigin);
85 aMedia.ToString(mMedia);
86 nsString
87 referrerPolicy; // Not Auto, because using it to hold nsStringBuffer*
88 aReferrerPolicy.ToString(referrerPolicy);
89 mReferrerPolicyOrIntegrity.Assign(
90 nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>(
91 referrerPolicy));
92 aSrcset.ToString(mCharsetOrSrcset);
93 aSizes.ToString(
94 mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity);
95 mIsLinkPreload = aLinkPreload;
98 inline void InitFont(nsHtml5String aUrl, nsHtml5String aCrossOrigin,
99 nsHtml5String aMedia, nsHtml5String aReferrerPolicy) {
100 MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized,
101 "Trying to reinitialize a speculative load!");
102 mOpCode = eSpeculativeLoadFont;
103 aUrl.ToString(mUrlOrSizes);
104 aCrossOrigin.ToString(mCrossOrigin);
105 aMedia.ToString(mMedia);
106 nsString
107 referrerPolicy; // Not Auto, because using it to hold nsStringBuffer*
108 aReferrerPolicy.ToString(referrerPolicy);
109 mReferrerPolicyOrIntegrity.Assign(
110 nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>(
111 referrerPolicy));
112 // This can be only triggered by <link rel=preload type=font>
113 mIsLinkPreload = true;
116 inline void InitFetch(nsHtml5String aUrl, nsHtml5String aCrossOrigin,
117 nsHtml5String aMedia, nsHtml5String aReferrerPolicy) {
118 MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized,
119 "Trying to reinitialize a speculative load!");
120 mOpCode = eSpeculativeLoadFetch;
121 aUrl.ToString(mUrlOrSizes);
122 aCrossOrigin.ToString(mCrossOrigin);
123 aMedia.ToString(mMedia);
124 nsString
125 referrerPolicy; // Not Auto, because using it to hold nsStringBuffer*
126 aReferrerPolicy.ToString(referrerPolicy);
127 mReferrerPolicyOrIntegrity.Assign(
128 nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>(
129 referrerPolicy));
131 // This method can be only be triggered by <link rel=preload type=fetch>,
132 // hence this operation is always a preload.
133 mIsLinkPreload = true;
136 // <picture> elements have multiple <source> nodes followed by an <img>,
137 // where we use the first valid source, which may be the img. Because we
138 // can't determine validity at this point without parsing CSS and getting
139 // main thread state, we push preload operations for picture pushed and
140 // popped, so that the target of the preload ops can determine what picture
141 // and nesting level each source/img from the main preloading code exists
142 // at.
143 inline void InitOpenPicture() {
144 MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized,
145 "Trying to reinitialize a speculative load!");
146 mOpCode = eSpeculativeLoadOpenPicture;
149 inline void InitEndPicture() {
150 MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized,
151 "Trying to reinitialize a speculative load!");
152 mOpCode = eSpeculativeLoadEndPicture;
155 inline void InitPictureSource(nsHtml5String aSrcset, nsHtml5String aSizes,
156 nsHtml5String aType, nsHtml5String aMedia) {
157 MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized,
158 "Trying to reinitialize a speculative load!");
159 mOpCode = eSpeculativeLoadPictureSource;
160 aSrcset.ToString(mCharsetOrSrcset);
161 aSizes.ToString(mUrlOrSizes);
162 aType.ToString(
163 mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity);
164 aMedia.ToString(mMedia);
167 inline void InitScript(nsHtml5String aUrl, nsHtml5String aCharset,
168 nsHtml5String aType, nsHtml5String aCrossOrigin,
169 nsHtml5String aMedia, nsHtml5String aIntegrity,
170 nsHtml5String aReferrerPolicy, bool aParserInHead,
171 bool aAsync, bool aDefer, bool aNoModule,
172 bool aLinkPreload) {
173 MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized,
174 "Trying to reinitialize a speculative load!");
175 if (aNoModule) {
176 mOpCode = aParserInHead ? eSpeculativeLoadNoModuleScriptFromHead
177 : eSpeculativeLoadNoModuleScript;
178 } else {
179 mOpCode = aParserInHead ? eSpeculativeLoadScriptFromHead
180 : eSpeculativeLoadScript;
182 aUrl.ToString(mUrlOrSizes);
183 aCharset.ToString(mCharsetOrSrcset);
184 aType.ToString(
185 mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity);
186 aCrossOrigin.ToString(mCrossOrigin);
187 aMedia.ToString(mMedia);
188 aIntegrity.ToString(mReferrerPolicyOrIntegrity);
189 nsAutoString referrerPolicy;
190 aReferrerPolicy.ToString(referrerPolicy);
191 referrerPolicy =
192 nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>(
193 referrerPolicy);
194 mScriptReferrerPolicy =
195 mozilla::dom::ReferrerInfo::ReferrerPolicyAttributeFromString(
196 referrerPolicy);
198 mIsAsync = aAsync;
199 mIsDefer = aDefer;
200 mIsLinkPreload = aLinkPreload;
203 inline void InitImportStyle(nsString&& aUrl) {
204 MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized,
205 "Trying to reinitialize a speculative load!");
206 mOpCode = eSpeculativeLoadStyle;
207 mUrlOrSizes = std::move(aUrl);
208 mCharsetOrSrcset.SetIsVoid(true);
209 mCrossOrigin.SetIsVoid(true);
210 mMedia.SetIsVoid(true);
211 mReferrerPolicyOrIntegrity.SetIsVoid(true);
212 mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity.SetIsVoid(
213 true);
216 inline void InitStyle(nsHtml5String aUrl, nsHtml5String aCharset,
217 nsHtml5String aCrossOrigin, nsHtml5String aMedia,
218 nsHtml5String aReferrerPolicy, nsHtml5String aIntegrity,
219 bool aLinkPreload) {
220 MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized,
221 "Trying to reinitialize a speculative load!");
222 mOpCode = eSpeculativeLoadStyle;
223 aUrl.ToString(mUrlOrSizes);
224 aCharset.ToString(mCharsetOrSrcset);
225 aCrossOrigin.ToString(mCrossOrigin);
226 aMedia.ToString(mMedia);
227 nsString
228 referrerPolicy; // Not Auto, because using it to hold nsStringBuffer*
229 aReferrerPolicy.ToString(referrerPolicy);
230 mReferrerPolicyOrIntegrity.Assign(
231 nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>(
232 referrerPolicy));
233 aIntegrity.ToString(
234 mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity);
235 mIsLinkPreload = aLinkPreload;
239 * "Speculative" manifest loads aren't truly speculative--if a manifest
240 * gets loaded, we are committed to it. There can never be a <script>
241 * before the manifest, so the situation of having to undo a manifest due
242 * to document.write() never arises. The reason why a parser
243 * thread-discovered manifest gets loaded via the speculative load queue
244 * as opposed to tree operation queue is that the manifest must get
245 * processed before any actual speculative loads such as scripts. Thus,
246 * manifests seen by the parser thread have to maintain the queue order
247 * relative to true speculative loads. See bug 541079.
249 inline void InitManifest(nsHtml5String aUrl) {
250 MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized,
251 "Trying to reinitialize a speculative load!");
252 mOpCode = eSpeculativeLoadManifest;
253 aUrl.ToString(mUrlOrSizes);
257 * "Speculative" charset setting isn't truly speculative. If the charset
258 * is set via this operation, we are committed to it unless chardet or
259 * a late meta cause a reload. The reason why a parser
260 * thread-discovered charset gets communicated via the speculative load
261 * queue as opposed to tree operation queue is that the charset change
262 * must get processed before any actual speculative loads such as style
263 * sheets. Thus, encoding decisions by the parser thread have to maintain
264 * the queue order relative to true speculative loads. See bug 675499.
266 inline void InitSetDocumentCharset(NotNull<const Encoding*> aEncoding,
267 int32_t aCharsetSource) {
268 MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized,
269 "Trying to reinitialize a speculative load!");
270 mOpCode = eSpeculativeLoadSetDocumentCharset;
271 mCharsetOrSrcset.~nsString();
272 mEncoding = aEncoding;
273 mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity.Assign(
274 (char16_t)aCharsetSource);
278 * Speculative document mode setting isn't really speculative. Once it
279 * happens, we are committed to it. However, this information needs to
280 * travel in the speculation queue in order to have this information
281 * available before parsing the speculatively loaded style sheets.
283 inline void InitSetDocumentMode(nsHtml5DocumentMode aMode) {
284 MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized,
285 "Trying to reinitialize a speculative load!");
286 mOpCode = eSpeculativeLoadSetDocumentMode;
287 mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity.Assign(
288 (char16_t)aMode);
291 inline void InitPreconnect(nsHtml5String aUrl, nsHtml5String aCrossOrigin) {
292 MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized,
293 "Trying to reinitialize a speculative load!");
294 mOpCode = eSpeculativeLoadPreconnect;
295 aUrl.ToString(mUrlOrSizes);
296 aCrossOrigin.ToString(mCrossOrigin);
299 void Perform(nsHtml5TreeOpExecutor* aExecutor);
301 private:
302 nsHtml5SpeculativeLoad(const nsHtml5SpeculativeLoad&) = delete;
303 nsHtml5SpeculativeLoad& operator=(const nsHtml5SpeculativeLoad&) = delete;
305 eHtml5SpeculativeLoad mOpCode;
308 * Whether the refering element has async and/or defer attributes.
310 bool mIsAsync;
311 bool mIsDefer;
314 * True if and only if this is a speculative load initiated by <link
315 * rel="preload"> tag encounter. Passed to the handling loader as an
316 * indication to raise the priority.
318 bool mIsLinkPreload;
320 /* If mOpCode is eSpeculativeLoadPictureSource, this is the value of the
321 * "sizes" attribute. If the attribute is not set, this will be a void
322 * string. Otherwise it empty or the value of the url.
324 nsString mUrlOrSizes;
326 * If mOpCode is eSpeculativeLoadScript[FromHead], this is the value of the
327 * "integrity" attribute. If the attribute is not set, this will be a void
328 * string. Otherwise it is empty or the value of the referrer policy.
330 nsString mReferrerPolicyOrIntegrity;
332 * If mOpCode is eSpeculativeLoadStyle or eSpeculativeLoadScript[FromHead]
333 * then this is the value of the "charset" attribute. For
334 * eSpeculativeLoadSetDocumentCharset it is the charset that the
335 * document's charset is being set to. If mOpCode is eSpeculativeLoadImage
336 * or eSpeculativeLoadPictureSource, this is the value of the "srcset"
337 * attribute. If the attribute is not set, this will be a void string.
338 * Otherwise it's empty.
340 union {
341 nsString mCharsetOrSrcset;
342 const Encoding* mEncoding;
345 * If mOpCode is eSpeculativeLoadSetDocumentCharset, this is a
346 * one-character string whose single character's code point is to be
347 * interpreted as a charset source integer. If mOpCode is
348 * eSpeculativeLoadSetDocumentMode, this is a one-character string whose
349 * single character's code point is to be interpreted as an
350 * nsHtml5DocumentMode. If mOpCode is eSpeculativeLoadCSP, this is a meta
351 * element's CSP value. If mOpCode is eSpeculativeLoadImage, this is the
352 * value of the "sizes" attribute. If the attribute is not set, this will
353 * be a void string. If mOpCode is eSpeculativeLoadStyle, this
354 * is the value of the "integrity" attribute. If the attribute is not set,
355 * this will be a void string. Otherwise it is empty or the value of the
356 * referrer policy. Otherwise, it is empty or the value of the type attribute.
358 nsString mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity;
360 * If mOpCode is eSpeculativeLoadImage or eSpeculativeLoadScript[FromHead]
361 * or eSpeculativeLoadPreconnect or eSpeculativeLoadStyle this is the value of
362 * the "crossorigin" attribute. If the attribute is not set, this will be a
363 * void string.
365 nsString mCrossOrigin;
367 * If mOpCode is eSpeculativeLoadPictureSource or eSpeculativeLoadStyle or
368 * Fetch or Image or Media or Script this is the value of the relevant "media"
369 * attribute of the <link rel="preload"> or <link rel="stylesheet">. If the
370 * attribute is not set, or the preload didn't originate from a <link>, this
371 * will be a void string.
373 nsString mMedia;
375 * If mOpCode is eSpeculativeLoadScript[FromHead] this represents the value
376 * of the "referrerpolicy" attribute. This field holds one of the values
377 * (REFERRER_POLICY_*) defined in nsIHttpChannel.
379 mozilla::dom::ReferrerPolicy mScriptReferrerPolicy;
382 #endif // nsHtml5SpeculativeLoad_h