1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=2 sw=2 et tw=78: */
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/. */
10 #include "mozilla/CheckedInt.h"
11 #include "mozilla/Likely.h"
12 #include "mozilla/StaticPrefs_dom.h"
13 #include "mozilla/StaticPrefs_network.h"
14 #include "mozilla/UniquePtr.h"
15 #include "mozilla/UniquePtrExtensions.h"
17 nsHtml5TreeBuilder::nsHtml5TreeBuilder(nsHtml5OplessBuilder
* aBuilder
)
22 scriptingEnabled(false),
26 contextNamespace(kNameSpaceID_None
),
43 mSpeculativeLoadStage(nullptr),
45 mCurrentHtmlScriptIsAsyncOrDefer(false),
46 mPreventScriptExecution(false),
47 mGenerateSpeculativeLoads(false),
48 mHasSeenImportMap(false)
54 MOZ_COUNT_CTOR(nsHtml5TreeBuilder
);
57 nsHtml5TreeBuilder::nsHtml5TreeBuilder(nsAHtml5TreeOpSink
* aOpSink
,
58 nsHtml5TreeOpStage
* aStage
,
59 bool aGenerateSpeculativeLoads
)
64 scriptingEnabled(false),
68 contextNamespace(kNameSpaceID_None
),
83 mHandles(new nsIContent
*[NS_HTML5_TREE_BUILDER_HANDLE_ARRAY_LENGTH
]),
85 mSpeculativeLoadStage(aStage
),
87 mCurrentHtmlScriptIsAsyncOrDefer(false),
88 mPreventScriptExecution(false),
89 mGenerateSpeculativeLoads(aGenerateSpeculativeLoads
),
90 mHasSeenImportMap(false)
96 MOZ_ASSERT(!(!aStage
&& aGenerateSpeculativeLoads
),
97 "Must not generate speculative loads without a stage");
98 MOZ_COUNT_CTOR(nsHtml5TreeBuilder
);
101 nsHtml5TreeBuilder::~nsHtml5TreeBuilder() {
102 MOZ_COUNT_DTOR(nsHtml5TreeBuilder
);
103 NS_ASSERTION(!mActive
,
104 "nsHtml5TreeBuilder deleted without ever calling end() on it!");
108 nsIContentHandle
* nsHtml5TreeBuilder::createElement(
109 int32_t aNamespace
, nsAtom
* aName
, nsHtml5HtmlAttributes
* aAttributes
,
110 nsIContentHandle
* aIntendedParent
, nsHtml5ContentCreatorFunction aCreator
) {
111 MOZ_ASSERT(aAttributes
, "Got null attributes.");
112 MOZ_ASSERT(aName
, "Got null name.");
113 MOZ_ASSERT(aNamespace
== kNameSpaceID_XHTML
||
114 aNamespace
== kNameSpaceID_SVG
||
115 aNamespace
== kNameSpaceID_MathML
,
119 nsIContent
* intendedParent
=
120 aIntendedParent
? static_cast<nsIContent
*>(aIntendedParent
) : nullptr;
122 // intendedParent == nullptr is a special case where the
123 // intended parent is the document.
124 nsNodeInfoManager
* nodeInfoManager
=
125 intendedParent
? intendedParent
->OwnerDoc()->NodeInfoManager()
126 : mBuilder
->GetNodeInfoManager();
129 if (aNamespace
== kNameSpaceID_XHTML
) {
130 elem
= nsHtml5TreeOperation::CreateHTMLElement(
131 aName
, aAttributes
, mozilla::dom::FROM_PARSER_FRAGMENT
,
132 nodeInfoManager
, mBuilder
, aCreator
.html
);
133 } else if (aNamespace
== kNameSpaceID_SVG
) {
134 elem
= nsHtml5TreeOperation::CreateSVGElement(
135 aName
, aAttributes
, mozilla::dom::FROM_PARSER_FRAGMENT
,
136 nodeInfoManager
, mBuilder
, aCreator
.svg
);
138 MOZ_ASSERT(aNamespace
== kNameSpaceID_MathML
);
139 elem
= nsHtml5TreeOperation::CreateMathMLElement(
140 aName
, aAttributes
, nodeInfoManager
, mBuilder
);
142 if (MOZ_UNLIKELY(aAttributes
!= tokenizer
->GetAttributes() &&
143 aAttributes
!= nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES
)) {
149 nsIContentHandle
* content
= AllocateContentHandle();
150 nsHtml5TreeOperation
* treeOp
= mOpQueue
.AppendElement(mozilla::fallible
);
151 if (MOZ_UNLIKELY(!treeOp
)) {
152 MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY
);
156 if (aNamespace
== kNameSpaceID_XHTML
) {
157 opCreateHTMLElement
opeation(
158 content
, aName
, aAttributes
, aCreator
.html
, aIntendedParent
,
159 (!!mSpeculativeLoadStage
) ? mozilla::dom::FROM_PARSER_NETWORK
160 : mozilla::dom::FROM_PARSER_DOCUMENT_WRITE
);
161 treeOp
->Init(mozilla::AsVariant(opeation
));
162 } else if (aNamespace
== kNameSpaceID_SVG
) {
163 opCreateSVGElement
operation(
164 content
, aName
, aAttributes
, aCreator
.svg
, aIntendedParent
,
165 (!!mSpeculativeLoadStage
) ? mozilla::dom::FROM_PARSER_NETWORK
166 : mozilla::dom::FROM_PARSER_DOCUMENT_WRITE
);
167 treeOp
->Init(mozilla::AsVariant(operation
));
169 // kNameSpaceID_MathML
170 opCreateMathMLElement
operation(content
, aName
, aAttributes
,
172 treeOp
->Init(mozilla::AsVariant(operation
));
175 // mSpeculativeLoadStage is non-null only in the off-the-main-thread
176 // tree builder, which handles the network stream
178 // Start wall of code for speculative loading and line numbers
180 if (mGenerateSpeculativeLoads
&& mode
!= IN_TEMPLATE
) {
181 switch (aNamespace
) {
182 case kNameSpaceID_XHTML
:
183 if (nsGkAtoms::img
== aName
) {
184 nsHtml5String loading
=
185 aAttributes
->getValue(nsHtml5AttributeName::ATTR_LOADING
);
186 if (!mozilla::StaticPrefs::dom_image_lazy_loading_enabled() ||
187 !loading
.LowerCaseEqualsASCII("lazy")) {
189 aAttributes
->getValue(nsHtml5AttributeName::ATTR_SRC
);
190 nsHtml5String srcset
=
191 aAttributes
->getValue(nsHtml5AttributeName::ATTR_SRCSET
);
192 nsHtml5String crossOrigin
=
193 aAttributes
->getValue(nsHtml5AttributeName::ATTR_CROSSORIGIN
);
194 nsHtml5String referrerPolicy
= aAttributes
->getValue(
195 nsHtml5AttributeName::ATTR_REFERRERPOLICY
);
196 nsHtml5String sizes
=
197 aAttributes
->getValue(nsHtml5AttributeName::ATTR_SIZES
);
198 mSpeculativeLoadQueue
.AppendElement()->InitImage(
199 url
, crossOrigin
, /* aMedia = */ nullptr, referrerPolicy
,
200 srcset
, sizes
, false);
202 } else if (nsGkAtoms::source
== aName
) {
203 nsHtml5String srcset
=
204 aAttributes
->getValue(nsHtml5AttributeName::ATTR_SRCSET
);
205 // Sources without srcset cannot be selected. The source could also be
206 // for a media element, but in that context doesn't use srcset. See
207 // comments in nsHtml5SpeculativeLoad.h about <picture> preloading
209 nsHtml5String sizes
=
210 aAttributes
->getValue(nsHtml5AttributeName::ATTR_SIZES
);
212 aAttributes
->getValue(nsHtml5AttributeName::ATTR_TYPE
);
213 nsHtml5String media
=
214 aAttributes
->getValue(nsHtml5AttributeName::ATTR_MEDIA
);
215 mSpeculativeLoadQueue
.AppendElement()->InitPictureSource(
216 srcset
, sizes
, type
, media
);
218 } else if (nsGkAtoms::script
== aName
) {
219 nsHtml5TreeOperation
* treeOp
=
220 mOpQueue
.AppendElement(mozilla::fallible
);
221 if (MOZ_UNLIKELY(!treeOp
)) {
222 MarkAsBrokenAndRequestSuspensionWithoutBuilder(
223 NS_ERROR_OUT_OF_MEMORY
);
226 opSetScriptLineAndColumnNumberAndFreeze
operation(
227 content
, tokenizer
->getLineNumber(),
228 tokenizer
->getColumnNumber());
229 treeOp
->Init(mozilla::AsVariant(operation
));
232 aAttributes
->getValue(nsHtml5AttributeName::ATTR_TYPE
);
233 nsAutoString typeString
;
234 type
.ToString(typeString
);
235 if (!mHasSeenImportMap
) {
236 // If we see an importmap, we don't want to later start speculative
237 // loads for modulepreloads, since such load might finish before
238 // the importmap is created. This also applies to module scripts so
239 // that any modulepreload integrity checks can be performed before
240 // the modules scripts are loaded.
242 typeString
.LowerCaseFindASCII("importmap") != kNotFound
;
245 aAttributes
->getValue(nsHtml5AttributeName::ATTR_SRC
);
246 if (url
&& !(mHasSeenImportMap
&&
247 typeString
.LowerCaseFindASCII("module") != kNotFound
)) {
248 nsHtml5String charset
=
249 aAttributes
->getValue(nsHtml5AttributeName::ATTR_CHARSET
);
250 nsHtml5String crossOrigin
=
251 aAttributes
->getValue(nsHtml5AttributeName::ATTR_CROSSORIGIN
);
252 nsHtml5String nonce
=
253 aAttributes
->getValue(nsHtml5AttributeName::ATTR_NONCE
);
254 nsHtml5String integrity
=
255 aAttributes
->getValue(nsHtml5AttributeName::ATTR_INTEGRITY
);
256 nsHtml5String referrerPolicy
= aAttributes
->getValue(
257 nsHtml5AttributeName::ATTR_REFERRERPOLICY
);
259 aAttributes
->contains(nsHtml5AttributeName::ATTR_ASYNC
);
261 aAttributes
->contains(nsHtml5AttributeName::ATTR_DEFER
);
263 aAttributes
->contains(nsHtml5AttributeName::ATTR_NOMODULE
);
264 mSpeculativeLoadQueue
.AppendElement()->InitScript(
265 url
, charset
, type
, crossOrigin
, /* aMedia = */ nullptr, nonce
,
266 integrity
, referrerPolicy
, mode
== nsHtml5TreeBuilder::IN_HEAD
,
267 async
, defer
, noModule
, false);
268 mCurrentHtmlScriptIsAsyncOrDefer
= async
|| defer
;
270 } else if (nsGkAtoms::link
== aName
) {
272 aAttributes
->getValue(nsHtml5AttributeName::ATTR_REL
);
273 // Not splitting on space here is bogus but the old parser didn't even
274 // do a case-insensitive check.
276 if (rel
.LowerCaseEqualsASCII("stylesheet")) {
278 aAttributes
->getValue(nsHtml5AttributeName::ATTR_HREF
);
280 nsHtml5String charset
=
281 aAttributes
->getValue(nsHtml5AttributeName::ATTR_CHARSET
);
282 nsHtml5String crossOrigin
= aAttributes
->getValue(
283 nsHtml5AttributeName::ATTR_CROSSORIGIN
);
284 nsHtml5String nonce
=
285 aAttributes
->getValue(nsHtml5AttributeName::ATTR_NONCE
);
286 nsHtml5String integrity
=
287 aAttributes
->getValue(nsHtml5AttributeName::ATTR_INTEGRITY
);
288 nsHtml5String referrerPolicy
= aAttributes
->getValue(
289 nsHtml5AttributeName::ATTR_REFERRERPOLICY
);
290 nsHtml5String media
=
291 aAttributes
->getValue(nsHtml5AttributeName::ATTR_MEDIA
);
292 mSpeculativeLoadQueue
.AppendElement()->InitStyle(
293 url
, charset
, crossOrigin
, media
, referrerPolicy
, nonce
,
296 } else if (rel
.LowerCaseEqualsASCII("preconnect")) {
298 aAttributes
->getValue(nsHtml5AttributeName::ATTR_HREF
);
300 nsHtml5String crossOrigin
= aAttributes
->getValue(
301 nsHtml5AttributeName::ATTR_CROSSORIGIN
);
302 mSpeculativeLoadQueue
.AppendElement()->InitPreconnect(
305 } else if (mozilla::StaticPrefs::network_preload() &&
306 rel
.LowerCaseEqualsASCII("preload")) {
308 aAttributes
->getValue(nsHtml5AttributeName::ATTR_HREF
);
311 aAttributes
->getValue(nsHtml5AttributeName::ATTR_AS
);
312 nsHtml5String charset
=
313 aAttributes
->getValue(nsHtml5AttributeName::ATTR_CHARSET
);
314 nsHtml5String crossOrigin
= aAttributes
->getValue(
315 nsHtml5AttributeName::ATTR_CROSSORIGIN
);
316 nsHtml5String nonce
=
317 aAttributes
->getValue(nsHtml5AttributeName::ATTR_NONCE
);
318 nsHtml5String integrity
=
319 aAttributes
->getValue(nsHtml5AttributeName::ATTR_INTEGRITY
);
320 nsHtml5String referrerPolicy
= aAttributes
->getValue(
321 nsHtml5AttributeName::ATTR_REFERRERPOLICY
);
322 nsHtml5String media
=
323 aAttributes
->getValue(nsHtml5AttributeName::ATTR_MEDIA
);
325 // Note that respective speculative loaders for scripts and
326 // styles check all additional attributes to be equal to use the
327 // speculative load. So, if any of them is specified and the
328 // preload has to take the expected effect, those attributes
329 // must also be specified on the actual tag to use the preload.
330 // Omitting an attribute on both will make the values equal
331 // (empty) and thus use the preload.
332 if (as
.LowerCaseEqualsASCII("script")) {
334 aAttributes
->getValue(nsHtml5AttributeName::ATTR_TYPE
);
335 mSpeculativeLoadQueue
.AppendElement()->InitScript(
336 url
, charset
, type
, crossOrigin
, media
, nonce
, integrity
,
337 referrerPolicy
, mode
== nsHtml5TreeBuilder::IN_HEAD
,
338 false, false, false, true);
339 } else if (as
.LowerCaseEqualsASCII("style")) {
340 mSpeculativeLoadQueue
.AppendElement()->InitStyle(
341 url
, charset
, crossOrigin
, media
, referrerPolicy
, nonce
,
343 } else if (as
.LowerCaseEqualsASCII("image")) {
344 nsHtml5String srcset
= aAttributes
->getValue(
345 nsHtml5AttributeName::ATTR_IMAGESRCSET
);
346 nsHtml5String sizes
= aAttributes
->getValue(
347 nsHtml5AttributeName::ATTR_IMAGESIZES
);
348 mSpeculativeLoadQueue
.AppendElement()->InitImage(
349 url
, crossOrigin
, media
, referrerPolicy
, srcset
, sizes
,
351 } else if (as
.LowerCaseEqualsASCII("font")) {
352 mSpeculativeLoadQueue
.AppendElement()->InitFont(
353 url
, crossOrigin
, media
, referrerPolicy
);
354 } else if (as
.LowerCaseEqualsASCII("fetch")) {
355 mSpeculativeLoadQueue
.AppendElement()->InitFetch(
356 url
, crossOrigin
, media
, referrerPolicy
);
358 // Other "as" values will be supported later.
360 } else if (mozilla::StaticPrefs::network_modulepreload() &&
361 rel
.LowerCaseEqualsASCII("modulepreload") &&
362 !mHasSeenImportMap
) {
364 aAttributes
->getValue(nsHtml5AttributeName::ATTR_HREF
);
365 if (url
&& url
.Length() != 0) {
367 aAttributes
->getValue(nsHtml5AttributeName::ATTR_AS
);
368 nsAutoString asString
;
369 as
.ToString(asString
);
370 if (mozilla::net::IsScriptLikeOrInvalid(asString
)) {
371 nsHtml5String charset
=
372 aAttributes
->getValue(nsHtml5AttributeName::ATTR_CHARSET
);
373 RefPtr
<nsAtom
> moduleType
= nsGkAtoms::_module
;
375 nsHtml5String::FromAtom(moduleType
.forget());
376 nsHtml5String crossOrigin
= aAttributes
->getValue(
377 nsHtml5AttributeName::ATTR_CROSSORIGIN
);
378 nsHtml5String media
=
379 aAttributes
->getValue(nsHtml5AttributeName::ATTR_MEDIA
);
380 nsHtml5String nonce
=
381 aAttributes
->getValue(nsHtml5AttributeName::ATTR_NONCE
);
382 nsHtml5String integrity
= aAttributes
->getValue(
383 nsHtml5AttributeName::ATTR_INTEGRITY
);
384 nsHtml5String referrerPolicy
= aAttributes
->getValue(
385 nsHtml5AttributeName::ATTR_REFERRERPOLICY
);
386 mSpeculativeLoadQueue
.AppendElement()->InitScript(
387 url
, charset
, type
, crossOrigin
, media
, nonce
, integrity
,
388 referrerPolicy
, mode
== nsHtml5TreeBuilder::IN_HEAD
,
389 false, false, false, true);
394 } else if (nsGkAtoms::video
== aName
) {
396 aAttributes
->getValue(nsHtml5AttributeName::ATTR_POSTER
);
398 mSpeculativeLoadQueue
.AppendElement()->InitImage(
399 url
, nullptr, nullptr, nullptr, nullptr, nullptr, false);
401 } else if (nsGkAtoms::style
== aName
) {
402 mImportScanner
.Start();
403 nsHtml5TreeOperation
* treeOp
=
404 mOpQueue
.AppendElement(mozilla::fallible
);
405 if (MOZ_UNLIKELY(!treeOp
)) {
406 MarkAsBrokenAndRequestSuspensionWithoutBuilder(
407 NS_ERROR_OUT_OF_MEMORY
);
410 opSetStyleLineNumber
operation(content
, tokenizer
->getLineNumber());
411 treeOp
->Init(mozilla::AsVariant(operation
));
412 } else if (nsGkAtoms::html
== aName
) {
414 aAttributes
->getValue(nsHtml5AttributeName::ATTR_MANIFEST
);
415 mSpeculativeLoadQueue
.AppendElement()->InitManifest(url
);
416 } else if (nsGkAtoms::base
== aName
) {
418 aAttributes
->getValue(nsHtml5AttributeName::ATTR_HREF
);
420 mSpeculativeLoadQueue
.AppendElement()->InitBase(url
);
422 } else if (nsGkAtoms::meta
== aName
) {
423 if (nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString(
424 "content-security-policy",
425 aAttributes
->getValue(
426 nsHtml5AttributeName::ATTR_HTTP_EQUIV
))) {
428 aAttributes
->getValue(nsHtml5AttributeName::ATTR_CONTENT
);
430 mSpeculativeLoadQueue
.AppendElement()->InitMetaCSP(csp
);
432 } else if (nsHtml5Portability::
433 lowerCaseLiteralEqualsIgnoreAsciiCaseString(
435 aAttributes
->getValue(
436 nsHtml5AttributeName::ATTR_NAME
))) {
437 nsHtml5String referrerPolicy
=
438 aAttributes
->getValue(nsHtml5AttributeName::ATTR_CONTENT
);
439 if (referrerPolicy
) {
440 mSpeculativeLoadQueue
.AppendElement()->InitMetaReferrerPolicy(
446 case kNameSpaceID_SVG
:
447 if (nsGkAtoms::image
== aName
) {
449 aAttributes
->getValue(nsHtml5AttributeName::ATTR_HREF
);
451 url
= aAttributes
->getValue(nsHtml5AttributeName::ATTR_XLINK_HREF
);
454 mSpeculativeLoadQueue
.AppendElement()->InitImage(
455 url
, nullptr, nullptr, nullptr, nullptr, nullptr, false);
457 } else if (nsGkAtoms::script
== aName
) {
458 nsHtml5TreeOperation
* treeOp
=
459 mOpQueue
.AppendElement(mozilla::fallible
);
460 if (MOZ_UNLIKELY(!treeOp
)) {
461 MarkAsBrokenAndRequestSuspensionWithoutBuilder(
462 NS_ERROR_OUT_OF_MEMORY
);
465 opSetScriptLineAndColumnNumberAndFreeze
operation(
466 content
, tokenizer
->getLineNumber(),
467 tokenizer
->getColumnNumber());
468 treeOp
->Init(mozilla::AsVariant(operation
));
471 aAttributes
->getValue(nsHtml5AttributeName::ATTR_HREF
);
473 url
= aAttributes
->getValue(nsHtml5AttributeName::ATTR_XLINK_HREF
);
477 aAttributes
->getValue(nsHtml5AttributeName::ATTR_TYPE
);
478 nsHtml5String crossOrigin
=
479 aAttributes
->getValue(nsHtml5AttributeName::ATTR_CROSSORIGIN
);
480 nsHtml5String nonce
=
481 aAttributes
->getValue(nsHtml5AttributeName::ATTR_NONCE
);
482 nsHtml5String integrity
=
483 aAttributes
->getValue(nsHtml5AttributeName::ATTR_INTEGRITY
);
484 nsHtml5String referrerPolicy
= aAttributes
->getValue(
485 nsHtml5AttributeName::ATTR_REFERRERPOLICY
);
486 mSpeculativeLoadQueue
.AppendElement()->InitScript(
487 url
, nullptr, type
, crossOrigin
, /* aMedia = */ nullptr, nonce
,
488 integrity
, referrerPolicy
, mode
== nsHtml5TreeBuilder::IN_HEAD
,
489 false, false, false, false);
491 } else if (nsGkAtoms::style
== aName
) {
492 mImportScanner
.Start();
493 nsHtml5TreeOperation
* treeOp
=
494 mOpQueue
.AppendElement(mozilla::fallible
);
495 if (MOZ_UNLIKELY(!treeOp
)) {
496 MarkAsBrokenAndRequestSuspensionWithoutBuilder(
497 NS_ERROR_OUT_OF_MEMORY
);
500 opSetStyleLineNumber
operation(content
, tokenizer
->getLineNumber());
501 treeOp
->Init(mozilla::AsVariant(operation
));
505 } else if (aNamespace
!= kNameSpaceID_MathML
) {
506 // No speculative loader--just line numbers and defer/async check
507 if (nsGkAtoms::style
== aName
) {
508 nsHtml5TreeOperation
* treeOp
= mOpQueue
.AppendElement(mozilla::fallible
);
509 if (MOZ_UNLIKELY(!treeOp
)) {
510 MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY
);
513 opSetStyleLineNumber
operation(content
, tokenizer
->getLineNumber());
514 treeOp
->Init(mozilla::AsVariant(operation
));
515 } else if (nsGkAtoms::script
== aName
) {
516 nsHtml5TreeOperation
* treeOp
= mOpQueue
.AppendElement(mozilla::fallible
);
517 if (MOZ_UNLIKELY(!treeOp
)) {
518 MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY
);
521 opSetScriptLineAndColumnNumberAndFreeze
operation(
522 content
, tokenizer
->getLineNumber(), tokenizer
->getColumnNumber());
523 treeOp
->Init(mozilla::AsVariant(operation
));
524 if (aNamespace
== kNameSpaceID_XHTML
) {
525 mCurrentHtmlScriptIsAsyncOrDefer
=
526 aAttributes
->contains(nsHtml5AttributeName::ATTR_SRC
) &&
527 (aAttributes
->contains(nsHtml5AttributeName::ATTR_ASYNC
) ||
528 aAttributes
->contains(nsHtml5AttributeName::ATTR_DEFER
));
530 } else if (aNamespace
== kNameSpaceID_XHTML
) {
531 if (nsGkAtoms::html
== aName
) {
533 aAttributes
->getValue(nsHtml5AttributeName::ATTR_MANIFEST
);
534 nsHtml5TreeOperation
* treeOp
=
535 mOpQueue
.AppendElement(mozilla::fallible
);
536 if (MOZ_UNLIKELY(!treeOp
)) {
537 MarkAsBrokenAndRequestSuspensionWithoutBuilder(
538 NS_ERROR_OUT_OF_MEMORY
);
543 urlString
; // Not Auto, because using it to hold nsStringBuffer*
544 url
.ToString(urlString
);
545 opProcessOfflineManifest
operation(ToNewUnicode(urlString
));
546 treeOp
->Init(mozilla::AsVariant(operation
));
548 opProcessOfflineManifest
operation(ToNewUnicode(u
""_ns
));
549 treeOp
->Init(mozilla::AsVariant(operation
));
551 } else if (nsGkAtoms::base
== aName
&& mViewSource
) {
553 aAttributes
->getValue(nsHtml5AttributeName::ATTR_HREF
);
555 mViewSource
->AddBase(url
);
561 // End wall of code for speculative loading
566 nsIContentHandle
* nsHtml5TreeBuilder::createElement(
567 int32_t aNamespace
, nsAtom
* aName
, nsHtml5HtmlAttributes
* aAttributes
,
568 nsIContentHandle
* aFormElement
, nsIContentHandle
* aIntendedParent
,
569 nsHtml5ContentCreatorFunction aCreator
) {
570 nsIContentHandle
* content
=
571 createElement(aNamespace
, aName
, aAttributes
, aIntendedParent
, aCreator
);
574 nsHtml5TreeOperation::SetFormElement(
575 static_cast<nsIContent
*>(content
),
576 static_cast<nsIContent
*>(aFormElement
));
578 nsHtml5TreeOperation
* treeOp
= mOpQueue
.AppendElement(mozilla::fallible
);
579 if (MOZ_UNLIKELY(!treeOp
)) {
580 MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY
);
583 opSetFormElement
operation(content
, aFormElement
);
584 treeOp
->Init(mozilla::AsVariant(operation
));
590 nsIContentHandle
* nsHtml5TreeBuilder::createHtmlElementSetAsRoot(
591 nsHtml5HtmlAttributes
* aAttributes
) {
592 nsHtml5ContentCreatorFunction creator
;
593 // <html> uses NS_NewHTMLSharedElement creator
594 creator
.html
= NS_NewHTMLSharedElement
;
595 nsIContentHandle
* content
= createElement(kNameSpaceID_XHTML
, nsGkAtoms::html
,
596 aAttributes
, nullptr, creator
);
598 nsresult rv
= nsHtml5TreeOperation::AppendToDocument(
599 static_cast<nsIContent
*>(content
), mBuilder
);
601 MarkAsBrokenAndRequestSuspensionWithBuilder(rv
);
604 nsHtml5TreeOperation
* treeOp
= mOpQueue
.AppendElement(mozilla::fallible
);
605 if (MOZ_UNLIKELY(!treeOp
)) {
606 MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY
);
609 opAppendToDocument
operation(content
);
610 treeOp
->Init(mozilla::AsVariant(operation
));
615 nsIContentHandle
* nsHtml5TreeBuilder::createAndInsertFosterParentedElement(
616 int32_t aNamespace
, nsAtom
* aName
, nsHtml5HtmlAttributes
* aAttributes
,
617 nsIContentHandle
* aFormElement
, nsIContentHandle
* aTable
,
618 nsIContentHandle
* aStackParent
, nsHtml5ContentCreatorFunction aCreator
) {
619 MOZ_ASSERT(aTable
, "Null table");
620 MOZ_ASSERT(aStackParent
, "Null stack parent");
623 // Get the foster parent to use as the intended parent when creating
624 // the child element.
625 nsIContent
* fosterParent
= nsHtml5TreeOperation::GetFosterParent(
626 static_cast<nsIContent
*>(aTable
),
627 static_cast<nsIContent
*>(aStackParent
));
629 nsIContentHandle
* child
= createElement(
630 aNamespace
, aName
, aAttributes
, aFormElement
, fosterParent
, aCreator
);
632 insertFosterParentedChild(child
, aTable
, aStackParent
);
637 // Tree op to get the foster parent that we use as the intended parent
638 // when creating the child element.
639 nsHtml5TreeOperation
* fosterParentTreeOp
= mOpQueue
.AppendElement();
640 NS_ASSERTION(fosterParentTreeOp
, "Tree op allocation failed.");
641 nsIContentHandle
* fosterParentHandle
= AllocateContentHandle();
642 opGetFosterParent
operation(aTable
, aStackParent
, fosterParentHandle
);
643 fosterParentTreeOp
->Init(mozilla::AsVariant(operation
));
645 // Create the element with the correct intended parent.
646 nsIContentHandle
* child
=
647 createElement(aNamespace
, aName
, aAttributes
, aFormElement
,
648 fosterParentHandle
, aCreator
);
650 // Insert the child into the foster parent.
651 insertFosterParentedChild(child
, aTable
, aStackParent
);
656 void nsHtml5TreeBuilder::detachFromParent(nsIContentHandle
* aElement
) {
657 MOZ_ASSERT(aElement
, "Null element");
660 nsHtml5TreeOperation::Detach(static_cast<nsIContent
*>(aElement
), mBuilder
);
664 nsHtml5TreeOperation
* treeOp
= mOpQueue
.AppendElement(mozilla::fallible
);
665 if (MOZ_UNLIKELY(!treeOp
)) {
666 MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY
);
669 opDetach
operation(aElement
);
670 treeOp
->Init(mozilla::AsVariant(operation
));
673 void nsHtml5TreeBuilder::appendElement(nsIContentHandle
* aChild
,
674 nsIContentHandle
* aParent
) {
675 MOZ_ASSERT(aChild
, "Null child");
676 MOZ_ASSERT(aParent
, "Null parent");
679 nsresult rv
= nsHtml5TreeOperation::Append(
680 static_cast<nsIContent
*>(aChild
), static_cast<nsIContent
*>(aParent
),
681 mozilla::dom::FROM_PARSER_FRAGMENT
, mBuilder
);
683 MarkAsBrokenAndRequestSuspensionWithBuilder(rv
);
688 nsHtml5TreeOperation
* treeOp
= mOpQueue
.AppendElement(mozilla::fallible
);
689 if (MOZ_UNLIKELY(!treeOp
)) {
690 MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY
);
694 opAppend
operation(aChild
, aParent
,
695 (!!mSpeculativeLoadStage
)
696 ? mozilla::dom::FROM_PARSER_NETWORK
697 : mozilla::dom::FROM_PARSER_DOCUMENT_WRITE
);
698 treeOp
->Init(mozilla::AsVariant(operation
));
701 void nsHtml5TreeBuilder::appendChildrenToNewParent(
702 nsIContentHandle
* aOldParent
, nsIContentHandle
* aNewParent
) {
703 MOZ_ASSERT(aOldParent
, "Null old parent");
704 MOZ_ASSERT(aNewParent
, "Null new parent");
707 nsresult rv
= nsHtml5TreeOperation::AppendChildrenToNewParent(
708 static_cast<nsIContent
*>(aOldParent
),
709 static_cast<nsIContent
*>(aNewParent
), mBuilder
);
711 MarkAsBrokenAndRequestSuspensionWithBuilder(rv
);
716 nsHtml5TreeOperation
* treeOp
= mOpQueue
.AppendElement(mozilla::fallible
);
717 if (MOZ_UNLIKELY(!treeOp
)) {
718 MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY
);
721 opAppendChildrenToNewParent
operation(aOldParent
, aNewParent
);
722 treeOp
->Init(mozilla::AsVariant(operation
));
725 void nsHtml5TreeBuilder::insertFosterParentedCharacters(
726 char16_t
* aBuffer
, int32_t aStart
, int32_t aLength
,
727 nsIContentHandle
* aTable
, nsIContentHandle
* aStackParent
) {
728 MOZ_ASSERT(aBuffer
, "Null buffer");
729 MOZ_ASSERT(aTable
, "Null table");
730 MOZ_ASSERT(aStackParent
, "Null stack parent");
731 MOZ_ASSERT(!aStart
, "aStart must always be zero.");
734 nsresult rv
= nsHtml5TreeOperation::FosterParentText(
735 static_cast<nsIContent
*>(aStackParent
),
736 aBuffer
, // XXX aStart always ignored???
737 aLength
, static_cast<nsIContent
*>(aTable
), mBuilder
);
739 MarkAsBrokenAndRequestSuspensionWithBuilder(rv
);
744 auto bufferCopy
= mozilla::MakeUniqueFallible
<char16_t
[]>(aLength
);
746 // Just assigning mBroken instead of generating tree op. The caller
747 // of tokenizeBuffer() will call MarkAsBroken() as appropriate.
748 mBroken
= NS_ERROR_OUT_OF_MEMORY
;
753 memcpy(bufferCopy
.get(), aBuffer
, aLength
* sizeof(char16_t
));
755 nsHtml5TreeOperation
* treeOp
= mOpQueue
.AppendElement(mozilla::fallible
);
756 if (MOZ_UNLIKELY(!treeOp
)) {
757 MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY
);
760 opFosterParentText
operation(aStackParent
, bufferCopy
.release(), aTable
,
762 treeOp
->Init(mozilla::AsVariant(operation
));
765 void nsHtml5TreeBuilder::insertFosterParentedChild(
766 nsIContentHandle
* aChild
, nsIContentHandle
* aTable
,
767 nsIContentHandle
* aStackParent
) {
768 MOZ_ASSERT(aChild
, "Null child");
769 MOZ_ASSERT(aTable
, "Null table");
770 MOZ_ASSERT(aStackParent
, "Null stack parent");
773 nsresult rv
= nsHtml5TreeOperation::FosterParent(
774 static_cast<nsIContent
*>(aChild
),
775 static_cast<nsIContent
*>(aStackParent
),
776 static_cast<nsIContent
*>(aTable
), mBuilder
);
778 MarkAsBrokenAndRequestSuspensionWithBuilder(rv
);
783 nsHtml5TreeOperation
* treeOp
= mOpQueue
.AppendElement(mozilla::fallible
);
784 if (MOZ_UNLIKELY(!treeOp
)) {
785 MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY
);
788 opFosterParent
operation(aChild
, aStackParent
, aTable
);
789 treeOp
->Init(mozilla::AsVariant(operation
));
792 void nsHtml5TreeBuilder::appendCharacters(nsIContentHandle
* aParent
,
793 char16_t
* aBuffer
, int32_t aStart
,
795 MOZ_ASSERT(aBuffer
, "Null buffer");
796 MOZ_ASSERT(aParent
, "Null parent");
797 MOZ_ASSERT(!aStart
, "aStart must always be zero.");
800 nsresult rv
= nsHtml5TreeOperation::AppendText(
801 aBuffer
, // XXX aStart always ignored???
802 aLength
, static_cast<nsIContent
*>(aParent
), mBuilder
);
804 MarkAsBrokenAndRequestSuspensionWithBuilder(rv
);
809 auto bufferCopy
= mozilla::MakeUniqueFallible
<char16_t
[]>(aLength
);
811 // Just assigning mBroken instead of generating tree op. The caller
812 // of tokenizeBuffer() will call MarkAsBroken() as appropriate.
813 mBroken
= NS_ERROR_OUT_OF_MEMORY
;
818 memcpy(bufferCopy
.get(), aBuffer
, aLength
* sizeof(char16_t
));
820 if (mImportScanner
.ShouldScan()) {
821 nsTArray
<nsString
> imports
=
822 mImportScanner
.Scan(mozilla::Span(aBuffer
, aLength
));
823 for (nsString
& url
: imports
) {
824 mSpeculativeLoadQueue
.AppendElement()->InitImportStyle(std::move(url
));
828 nsHtml5TreeOperation
* treeOp
= mOpQueue
.AppendElement(mozilla::fallible
);
829 if (MOZ_UNLIKELY(!treeOp
)) {
830 MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY
);
833 opAppendText
operation(aParent
, bufferCopy
.release(), aLength
);
834 treeOp
->Init(mozilla::AsVariant(operation
));
837 void nsHtml5TreeBuilder::appendComment(nsIContentHandle
* aParent
,
838 char16_t
* aBuffer
, int32_t aStart
,
840 MOZ_ASSERT(aBuffer
, "Null buffer");
841 MOZ_ASSERT(aParent
, "Null parent");
842 MOZ_ASSERT(!aStart
, "aStart must always be zero.");
845 nsresult rv
= nsHtml5TreeOperation::AppendComment(
846 static_cast<nsIContent
*>(aParent
),
847 aBuffer
, // XXX aStart always ignored???
850 MarkAsBrokenAndRequestSuspensionWithBuilder(rv
);
855 auto bufferCopy
= mozilla::MakeUniqueFallible
<char16_t
[]>(aLength
);
857 // Just assigning mBroken instead of generating tree op. The caller
858 // of tokenizeBuffer() will call MarkAsBroken() as appropriate.
859 mBroken
= NS_ERROR_OUT_OF_MEMORY
;
864 memcpy(bufferCopy
.get(), aBuffer
, aLength
* sizeof(char16_t
));
866 nsHtml5TreeOperation
* treeOp
= mOpQueue
.AppendElement(mozilla::fallible
);
867 if (MOZ_UNLIKELY(!treeOp
)) {
868 MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY
);
871 opAppendComment
operation(aParent
, bufferCopy
.release(), aLength
);
872 treeOp
->Init(mozilla::AsVariant(operation
));
875 void nsHtml5TreeBuilder::appendCommentToDocument(char16_t
* aBuffer
,
878 MOZ_ASSERT(aBuffer
, "Null buffer");
879 MOZ_ASSERT(!aStart
, "aStart must always be zero.");
882 nsresult rv
= nsHtml5TreeOperation::AppendCommentToDocument(
883 aBuffer
, // XXX aStart always ignored???
886 MarkAsBrokenAndRequestSuspensionWithBuilder(rv
);
891 auto bufferCopy
= mozilla::MakeUniqueFallible
<char16_t
[]>(aLength
);
893 // Just assigning mBroken instead of generating tree op. The caller
894 // of tokenizeBuffer() will call MarkAsBroken() as appropriate.
895 mBroken
= NS_ERROR_OUT_OF_MEMORY
;
900 memcpy(bufferCopy
.get(), aBuffer
, aLength
* sizeof(char16_t
));
902 nsHtml5TreeOperation
* treeOp
= mOpQueue
.AppendElement(mozilla::fallible
);
903 if (MOZ_UNLIKELY(!treeOp
)) {
904 MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY
);
907 opAppendCommentToDocument
data(bufferCopy
.release(), aLength
);
908 treeOp
->Init(mozilla::AsVariant(data
));
911 void nsHtml5TreeBuilder::addAttributesToElement(
912 nsIContentHandle
* aElement
, nsHtml5HtmlAttributes
* aAttributes
) {
913 MOZ_ASSERT(aElement
, "Null element");
914 MOZ_ASSERT(aAttributes
, "Null attributes");
916 if (aAttributes
== nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES
) {
922 aAttributes
== tokenizer
->GetAttributes(),
923 "Using attribute other than the tokenizer's to add to body or html.");
924 nsresult rv
= nsHtml5TreeOperation::AddAttributes(
925 static_cast<nsIContent
*>(aElement
), aAttributes
, mBuilder
);
927 MarkAsBrokenAndRequestSuspensionWithBuilder(rv
);
932 nsHtml5TreeOperation
* treeOp
= mOpQueue
.AppendElement(mozilla::fallible
);
933 if (MOZ_UNLIKELY(!treeOp
)) {
934 MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY
);
937 opAddAttributes
opeation(aElement
, aAttributes
);
938 treeOp
->Init(mozilla::AsVariant(opeation
));
941 void nsHtml5TreeBuilder::markMalformedIfScript(nsIContentHandle
* aElement
) {
942 MOZ_ASSERT(aElement
, "Null element");
945 nsHtml5TreeOperation::MarkMalformedIfScript(
946 static_cast<nsIContent
*>(aElement
));
950 nsHtml5TreeOperation
* treeOp
= mOpQueue
.AppendElement(mozilla::fallible
);
951 if (MOZ_UNLIKELY(!treeOp
)) {
952 MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY
);
955 opMarkMalformedIfScript
operation(aElement
);
956 treeOp
->Init(mozilla::AsVariant(operation
));
959 void nsHtml5TreeBuilder::start(bool fragment
) {
960 mCurrentHtmlScriptIsAsyncOrDefer
= false;
966 void nsHtml5TreeBuilder::end() {
973 void nsHtml5TreeBuilder::appendDoctypeToDocument(nsAtom
* aName
,
974 nsHtml5String aPublicId
,
975 nsHtml5String aSystemId
) {
976 MOZ_ASSERT(aName
, "Null name");
977 nsString publicId
; // Not Auto, because using it to hold nsStringBuffer*
978 nsString systemId
; // Not Auto, because using it to hold nsStringBuffer*
979 aPublicId
.ToString(publicId
);
980 aSystemId
.ToString(systemId
);
982 nsresult rv
= nsHtml5TreeOperation::AppendDoctypeToDocument(
983 aName
, publicId
, systemId
, mBuilder
);
985 MarkAsBrokenAndRequestSuspensionWithBuilder(rv
);
990 nsHtml5TreeOperation
* treeOp
= mOpQueue
.AppendElement(mozilla::fallible
);
991 if (MOZ_UNLIKELY(!treeOp
)) {
992 MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY
);
995 opAppendDoctypeToDocument
operation(aName
, publicId
, systemId
);
996 treeOp
->Init(mozilla::AsVariant(operation
));
997 // nsXMLContentSink can flush here, but what's the point?
998 // It can also interrupt here, but we can't.
1001 void nsHtml5TreeBuilder::elementPushed(int32_t aNamespace
, nsAtom
* aName
,
1002 nsIContentHandle
* aElement
) {
1003 NS_ASSERTION(aNamespace
== kNameSpaceID_XHTML
||
1004 aNamespace
== kNameSpaceID_SVG
||
1005 aNamespace
== kNameSpaceID_MathML
,
1006 "Element isn't HTML, SVG or MathML!");
1007 NS_ASSERTION(aName
, "Element doesn't have local name!");
1008 NS_ASSERTION(aElement
, "No element!");
1010 * The frame constructor uses recursive algorithms, so it can't deal with
1011 * arbitrarily deep trees. This is especially a problem on Windows where
1012 * the permitted depth of the runtime stack is rather small.
1014 * The following is a protection against author incompetence--not against
1015 * malice. There are other ways to make the DOM deep anyway.
1017 * The basic idea is that when the tree builder stack gets too deep,
1018 * append operations no longer append to the node that the HTML parsing
1019 * algorithm says they should but instead text nodes are append to the last
1020 * element that was seen before a magic tree builder stack threshold was
1021 * reached and element and comment nodes aren't appended to the DOM at all.
1023 * However, for security reasons, non-child descendant text nodes inside an
1024 * SVG script or style element should not become children. Also, non-cell
1025 * table elements shouldn't be used as surrogate parents for user experience
1028 if (aNamespace
!= kNameSpaceID_XHTML
) {
1031 if (aName
== nsGkAtoms::body
|| aName
== nsGkAtoms::frameset
) {
1033 // InnerHTML and DOMParser shouldn't start layout anyway
1036 nsHtml5TreeOperation
* treeOp
= mOpQueue
.AppendElement(mozilla::fallible
);
1037 if (MOZ_UNLIKELY(!treeOp
)) {
1038 MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY
);
1041 treeOp
->Init(mozilla::AsVariant(opStartLayout()));
1044 if (nsIContent::RequiresDoneCreatingElement(kNameSpaceID_XHTML
, aName
)) {
1046 nsHtml5TreeOperation::DoneCreatingElement(
1047 static_cast<nsIContent
*>(aElement
));
1049 opDoneCreatingElement
operation(aElement
);
1050 mOpQueue
.AppendElement()->Init(mozilla::AsVariant(operation
));
1054 if (mGenerateSpeculativeLoads
&& aName
== nsGkAtoms::picture
) {
1055 // See comments in nsHtml5SpeculativeLoad.h about <picture> preloading
1056 mSpeculativeLoadQueue
.AppendElement()->InitOpenPicture();
1059 if (aName
== nsGkAtoms::_template
) {
1060 if (tokenizer
->TemplatePushedOrHeadPopped()) {
1061 requestSuspension();
1066 void nsHtml5TreeBuilder::elementPopped(int32_t aNamespace
, nsAtom
* aName
,
1067 nsIContentHandle
* aElement
) {
1068 NS_ASSERTION(aNamespace
== kNameSpaceID_XHTML
||
1069 aNamespace
== kNameSpaceID_SVG
||
1070 aNamespace
== kNameSpaceID_MathML
,
1071 "Element isn't HTML, SVG or MathML!");
1072 NS_ASSERTION(aName
, "Element doesn't have local name!");
1073 NS_ASSERTION(aElement
, "No element!");
1074 if (aNamespace
== kNameSpaceID_MathML
) {
1077 // we now have only SVG and HTML
1078 if (aName
== nsGkAtoms::script
) {
1079 if (mPreventScriptExecution
) {
1081 nsHtml5TreeOperation::PreventScriptExecution(
1082 static_cast<nsIContent
*>(aElement
));
1085 opPreventScriptExecution
operation(aElement
);
1086 mOpQueue
.AppendElement()->Init(mozilla::AsVariant(operation
));
1092 if (mCurrentHtmlScriptIsAsyncOrDefer
) {
1093 NS_ASSERTION(aNamespace
== kNameSpaceID_XHTML
,
1094 "Only HTML scripts may be async/defer.");
1095 nsHtml5TreeOperation
* treeOp
= mOpQueue
.AppendElement(mozilla::fallible
);
1096 if (MOZ_UNLIKELY(!treeOp
)) {
1097 MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY
);
1100 opRunScriptAsyncDefer
operation(aElement
);
1101 treeOp
->Init(mozilla::AsVariant(operation
));
1102 mCurrentHtmlScriptIsAsyncOrDefer
= false;
1105 requestSuspension();
1106 nsHtml5TreeOperation
* treeOp
= mOpQueue
.AppendElement(mozilla::fallible
);
1107 if (MOZ_UNLIKELY(!treeOp
)) {
1108 MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY
);
1111 opRunScript
operation(aElement
, nullptr);
1112 treeOp
->Init(mozilla::AsVariant(operation
));
1115 // Some nodes need DoneAddingChildren() called to initialize
1116 // properly (e.g. form state restoration).
1117 if (nsIContent::RequiresDoneAddingChildren(aNamespace
, aName
)) {
1119 nsHtml5TreeOperation::DoneAddingChildren(
1120 static_cast<nsIContent
*>(aElement
));
1123 nsHtml5TreeOperation
* treeOp
= mOpQueue
.AppendElement(mozilla::fallible
);
1124 if (MOZ_UNLIKELY(!treeOp
)) {
1125 MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY
);
1128 opDoneAddingChildren
operation(aElement
);
1129 treeOp
->Init(mozilla::AsVariant(operation
));
1130 if (aNamespace
== kNameSpaceID_XHTML
&& aName
== nsGkAtoms::head
) {
1131 if (tokenizer
->TemplatePushedOrHeadPopped()) {
1132 requestSuspension();
1137 if (aName
== nsGkAtoms::style
||
1138 (aNamespace
== kNameSpaceID_XHTML
&& aName
== nsGkAtoms::link
)) {
1140 MOZ_ASSERT(!nsContentUtils::IsSafeToRunScript(),
1141 "Scripts must be blocked.");
1142 mBuilder
->UpdateStyleSheet(static_cast<nsIContent
*>(aElement
));
1146 if (aName
== nsGkAtoms::style
) {
1147 nsTArray
<nsString
> imports
= mImportScanner
.Stop();
1148 for (nsString
& url
: imports
) {
1149 mSpeculativeLoadQueue
.AppendElement()->InitImportStyle(std::move(url
));
1153 nsHtml5TreeOperation
* treeOp
= mOpQueue
.AppendElement(mozilla::fallible
);
1154 if (MOZ_UNLIKELY(!treeOp
)) {
1155 MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY
);
1158 opUpdateStyleSheet
operation(aElement
);
1159 treeOp
->Init(mozilla::AsVariant(operation
));
1162 if (aNamespace
== kNameSpaceID_SVG
) {
1163 if (aName
== nsGkAtoms::svg
) {
1164 if (!scriptingEnabled
|| mPreventScriptExecution
) {
1168 nsHtml5TreeOperation::SvgLoad(static_cast<nsIContent
*>(aElement
));
1171 nsHtml5TreeOperation
* treeOp
= mOpQueue
.AppendElement(mozilla::fallible
);
1172 if (MOZ_UNLIKELY(!treeOp
)) {
1173 MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY
);
1176 opSvgLoad
operation(aElement
);
1177 treeOp
->Init(mozilla::AsVariant(operation
));
1182 if (mGenerateSpeculativeLoads
&& aName
== nsGkAtoms::picture
) {
1183 // See comments in nsHtml5SpeculativeLoad.h about <picture> preloading
1184 mSpeculativeLoadQueue
.AppendElement()->InitEndPicture();
1189 void nsHtml5TreeBuilder::accumulateCharacters(const char16_t
* aBuf
,
1190 int32_t aStart
, int32_t aLength
) {
1191 MOZ_RELEASE_ASSERT(charBufferLen
+ aLength
<= charBuffer
.length
,
1192 "About to memcpy past the end of the buffer!");
1193 memcpy(charBuffer
+ charBufferLen
, aBuf
+ aStart
, sizeof(char16_t
) * aLength
);
1194 charBufferLen
+= aLength
;
1197 // INT32_MAX is (2^31)-1. Therefore, the highest power-of-two that fits
1198 // is 2^30. Note that this is counting char16_t units. The underlying
1199 // bytes will be twice that, but they fit even in 32-bit size_t even
1200 // if a contiguous chunk of memory of that size is pretty unlikely to
1201 // be available on a 32-bit system.
1202 #define MAX_POWER_OF_TWO_IN_INT32 0x40000000
1204 bool nsHtml5TreeBuilder::EnsureBufferSpace(int32_t aLength
) {
1205 // TODO: Unify nsHtml5Tokenizer::strBuf and nsHtml5TreeBuilder::charBuffer
1206 // so that this method becomes unnecessary.
1207 mozilla::CheckedInt
<int32_t> worstCase(charBufferLen
);
1208 worstCase
+= aLength
;
1209 if (!worstCase
.isValid()) {
1212 if (worstCase
.value() > MAX_POWER_OF_TWO_IN_INT32
) {
1216 if (worstCase
.value() < MAX_POWER_OF_TWO_IN_INT32
) {
1217 // Add one to round to the next power of two to avoid immediate
1218 // reallocation once there are a few characters in the buffer.
1221 charBuffer
= jArray
<char16_t
, int32_t>::newFallibleJArray(
1222 mozilla::RoundUpPow2(worstCase
.value()));
1226 } else if (worstCase
.value() > charBuffer
.length
) {
1227 jArray
<char16_t
, int32_t> newBuf
=
1228 jArray
<char16_t
, int32_t>::newFallibleJArray(
1229 mozilla::RoundUpPow2(worstCase
.value()));
1233 memcpy(newBuf
, charBuffer
, sizeof(char16_t
) * size_t(charBufferLen
));
1234 charBuffer
= newBuf
;
1239 nsIContentHandle
* nsHtml5TreeBuilder::AllocateContentHandle() {
1240 if (MOZ_UNLIKELY(mBuilder
)) {
1241 MOZ_ASSERT_UNREACHABLE("Must never allocate a handle with builder.");
1244 if (mHandlesUsed
== NS_HTML5_TREE_BUILDER_HANDLE_ARRAY_LENGTH
) {
1245 mOldHandles
.AppendElement(std::move(mHandles
));
1246 mHandles
= mozilla::MakeUnique
<nsIContent
*[]>(
1247 NS_HTML5_TREE_BUILDER_HANDLE_ARRAY_LENGTH
);
1251 mHandles
[mHandlesUsed
] = reinterpret_cast<nsIContent
*>(uintptr_t(0xC0DEDBAD));
1253 return &mHandles
[mHandlesUsed
++];
1256 bool nsHtml5TreeBuilder::HasScript() {
1257 uint32_t len
= mOpQueue
.Length();
1261 return mOpQueue
.ElementAt(len
- 1).IsRunScript();
1264 mozilla::Result
<bool, nsresult
> nsHtml5TreeBuilder::Flush(bool aDiscretionary
) {
1265 if (MOZ_UNLIKELY(mBuilder
)) {
1266 MOZ_ASSERT_UNREACHABLE("Must never flush with builder.");
1269 if (NS_SUCCEEDED(mBroken
)) {
1270 if (!aDiscretionary
|| !(charBufferLen
&& currentPtr
>= 0 &&
1271 stack
[currentPtr
]->isFosterParenting())) {
1272 // Don't flush text on discretionary flushes if the current element on
1273 // the stack is a foster-parenting element and there's pending text,
1274 // because flushing in that case would make the tree shape dependent on
1275 // where the flush points fall.
1281 bool hasOps
= !mOpQueue
.IsEmpty();
1283 // If the builder is broken and mOpQueue is not empty, there must be
1284 // one op and it must be eTreeOpMarkAsBroken.
1285 if (NS_FAILED(mBroken
)) {
1286 MOZ_ASSERT(mOpQueue
.Length() == 1,
1287 "Tree builder is broken with a non-empty op queue whose "
1289 MOZ_ASSERT(mOpQueue
[0].IsMarkAsBroken(),
1290 "Tree builder is broken but the op in queue is not marked "
1293 if (!mOpSink
->MoveOpsFrom(mOpQueue
)) {
1294 return mozilla::Err(NS_ERROR_OUT_OF_MEMORY
);
1299 // no op sink: throw away ops
1304 void nsHtml5TreeBuilder::FlushLoads() {
1305 if (MOZ_UNLIKELY(mBuilder
)) {
1306 MOZ_ASSERT_UNREACHABLE("Must never flush loads with builder.");
1309 if (!mSpeculativeLoadQueue
.IsEmpty()) {
1310 mSpeculativeLoadStage
->MoveSpeculativeLoadsFrom(mSpeculativeLoadQueue
);
1314 void nsHtml5TreeBuilder::SetDocumentCharset(NotNull
<const Encoding
*> aEncoding
,
1315 nsCharsetSource aCharsetSource
,
1316 bool aCommitEncodingSpeculation
) {
1317 MOZ_ASSERT(!mBuilder
, "How did we call this with builder?");
1318 MOZ_ASSERT(mSpeculativeLoadStage
,
1319 "How did we call this without a speculative load stage?");
1320 mSpeculativeLoadQueue
.AppendElement()->InitSetDocumentCharset(
1321 aEncoding
, aCharsetSource
, aCommitEncodingSpeculation
);
1324 void nsHtml5TreeBuilder::UpdateCharsetSource(nsCharsetSource aCharsetSource
) {
1325 MOZ_ASSERT(!mBuilder
, "How did we call this with builder?");
1326 MOZ_ASSERT(mSpeculativeLoadStage
,
1327 "How did we call this without a speculative load stage (even "
1328 "though we don't need it right here)?");
1330 mViewSource
->UpdateCharsetSource(aCharsetSource
);
1333 opUpdateCharsetSource
operation(aCharsetSource
);
1334 mOpQueue
.AppendElement()->Init(mozilla::AsVariant(operation
));
1337 void nsHtml5TreeBuilder::StreamEnded() {
1338 MOZ_ASSERT(!mBuilder
, "Must not call StreamEnded with builder.");
1339 MOZ_ASSERT(!fragment
, "Must not parse fragments off the main thread.");
1340 nsHtml5TreeOperation
* treeOp
= mOpQueue
.AppendElement(mozilla::fallible
);
1341 if (MOZ_UNLIKELY(!treeOp
)) {
1342 MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY
);
1345 treeOp
->Init(mozilla::AsVariant(opStreamEnded()));
1348 void nsHtml5TreeBuilder::NeedsCharsetSwitchTo(
1349 NotNull
<const Encoding
*> aEncoding
, int32_t aCharsetSource
,
1350 int32_t aLineNumber
) {
1351 if (MOZ_UNLIKELY(mBuilder
)) {
1352 MOZ_ASSERT_UNREACHABLE("Must never switch charset with builder.");
1355 nsHtml5TreeOperation
* treeOp
= mOpQueue
.AppendElement(mozilla::fallible
);
1356 if (MOZ_UNLIKELY(!treeOp
)) {
1357 MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY
);
1360 opCharsetSwitchTo
opeation(aEncoding
, aCharsetSource
, aLineNumber
);
1361 treeOp
->Init(mozilla::AsVariant(opeation
));
1364 void nsHtml5TreeBuilder::MaybeComplainAboutCharset(const char* aMsgId
,
1366 int32_t aLineNumber
) {
1367 if (MOZ_UNLIKELY(mBuilder
)) {
1368 MOZ_ASSERT_UNREACHABLE("Must never complain about charset with builder.");
1372 if (mSpeculativeLoadStage
) {
1373 mSpeculativeLoadQueue
.AppendElement()->InitMaybeComplainAboutCharset(
1374 aMsgId
, aError
, aLineNumber
);
1376 opMaybeComplainAboutCharset
opeartion(const_cast<char*>(aMsgId
), aError
,
1378 mOpQueue
.AppendElement()->Init(mozilla::AsVariant(opeartion
));
1382 void nsHtml5TreeBuilder::TryToEnableEncodingMenu() {
1383 if (MOZ_UNLIKELY(mBuilder
)) {
1384 MOZ_ASSERT_UNREACHABLE("Must never disable encoding menu with builder.");
1387 nsHtml5TreeOperation
* treeOp
= mOpQueue
.AppendElement();
1388 NS_ASSERTION(treeOp
, "Tree op allocation failed.");
1389 treeOp
->Init(mozilla::AsVariant(opEnableEncodingMenu()));
1392 void nsHtml5TreeBuilder::AddSnapshotToScript(
1393 nsAHtml5TreeBuilderState
* aSnapshot
, int32_t aLine
) {
1394 if (MOZ_UNLIKELY(mBuilder
)) {
1395 MOZ_ASSERT_UNREACHABLE("Must never use snapshots with builder.");
1398 MOZ_ASSERT(HasScript(), "No script to add a snapshot to!");
1399 MOZ_ASSERT(aSnapshot
, "Got null snapshot.");
1400 mOpQueue
.ElementAt(mOpQueue
.Length() - 1).SetSnapshot(aSnapshot
, aLine
);
1403 void nsHtml5TreeBuilder::DropHandles() {
1404 MOZ_ASSERT(!mBuilder
, "Must not drop handles with builder.");
1405 mOldHandles
.Clear();
1409 void nsHtml5TreeBuilder::MarkAsBroken(nsresult aRv
) {
1410 if (MOZ_UNLIKELY(mBuilder
)) {
1411 MOZ_ASSERT_UNREACHABLE("Must not call this with builder.");
1415 mOpQueue
.Clear(); // Previous ops don't matter anymore
1416 opMarkAsBroken
operation(aRv
);
1417 mOpQueue
.AppendElement()->Init(mozilla::AsVariant(operation
));
1420 void nsHtml5TreeBuilder::MarkAsBrokenFromPortability(nsresult aRv
) {
1422 MarkAsBrokenAndRequestSuspensionWithBuilder(aRv
);
1426 requestSuspension();
1429 void nsHtml5TreeBuilder::StartPlainTextViewSource(const nsAutoString
& aTitle
) {
1430 MOZ_ASSERT(!mBuilder
, "Must not view source with builder.");
1432 startTag(nsHtml5ElementName::ELT_META
,
1433 nsHtml5ViewSourceUtils::NewMetaViewportAttributes(), false);
1435 startTag(nsHtml5ElementName::ELT_TITLE
,
1436 nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES
, false);
1438 // XUL will add the "Source of: " prefix.
1439 uint32_t length
= aTitle
.Length();
1440 if (length
> INT32_MAX
) {
1443 characters(aTitle
.get(), 0, (int32_t)length
);
1444 endTag(nsHtml5ElementName::ELT_TITLE
);
1446 startTag(nsHtml5ElementName::ELT_LINK
,
1447 nsHtml5ViewSourceUtils::NewLinkAttributes(), false);
1449 startTag(nsHtml5ElementName::ELT_BODY
,
1450 nsHtml5ViewSourceUtils::NewBodyAttributes(), false);
1452 StartPlainTextBody();
1455 void nsHtml5TreeBuilder::StartPlainText() {
1456 MOZ_ASSERT(!mBuilder
, "Must not view source with builder.");
1457 setForceNoQuirks(true);
1458 startTag(nsHtml5ElementName::ELT_LINK
,
1459 nsHtml5PlainTextUtils::NewLinkAttributes(), false);
1461 startTag(nsHtml5ElementName::ELT_BODY
,
1462 nsHtml5PlainTextUtils::NewBodyAttributes(), false);
1464 StartPlainTextBody();
1467 void nsHtml5TreeBuilder::StartPlainTextBody() {
1468 MOZ_ASSERT(!mBuilder
, "Must not view source with builder.");
1469 startTag(nsHtml5ElementName::ELT_PRE
, nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES
,
1471 needToDropLF
= false;
1474 // DocumentModeHandler
1475 void nsHtml5TreeBuilder::documentMode(nsHtml5DocumentMode m
) {
1477 mBuilder
->SetDocumentMode(m
);
1480 if (mSpeculativeLoadStage
) {
1481 mSpeculativeLoadQueue
.AppendElement()->InitSetDocumentMode(m
);
1484 nsHtml5TreeOperation
* treeOp
= mOpQueue
.AppendElement(mozilla::fallible
);
1485 if (MOZ_UNLIKELY(!treeOp
)) {
1486 MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY
);
1489 treeOp
->Init(mozilla::AsVariant(m
));
1492 nsIContentHandle
* nsHtml5TreeBuilder::getDocumentFragmentForTemplate(
1493 nsIContentHandle
* aTemplate
) {
1495 return nsHtml5TreeOperation::GetDocumentFragmentForTemplate(
1496 static_cast<nsIContent
*>(aTemplate
));
1498 nsHtml5TreeOperation
* treeOp
= mOpQueue
.AppendElement(mozilla::fallible
);
1499 if (MOZ_UNLIKELY(!treeOp
)) {
1500 MarkAsBrokenAndRequestSuspensionWithoutBuilder(NS_ERROR_OUT_OF_MEMORY
);
1503 nsIContentHandle
* fragHandle
= AllocateContentHandle();
1504 opGetDocumentFragmentForTemplate
operation(aTemplate
, fragHandle
);
1505 treeOp
->Init(mozilla::AsVariant(operation
));
1509 nsIContentHandle
* nsHtml5TreeBuilder::getFormPointerForContext(
1510 nsIContentHandle
* aContext
) {
1511 MOZ_ASSERT(mBuilder
, "Must have builder.");
1516 MOZ_ASSERT(NS_IsMainThread());
1518 // aContext must always be an element that already exists
1520 nsIContent
* contextNode
= static_cast<nsIContent
*>(aContext
);
1521 nsIContent
* currentAncestor
= contextNode
;
1523 // We traverse the ancestors of the context node to find the nearest
1524 // form pointer. This traversal is why aContext must not be an emtpy handle.
1525 nsIContent
* nearestForm
= nullptr;
1526 while (currentAncestor
) {
1527 if (currentAncestor
->IsHTMLElement(nsGkAtoms::form
)) {
1528 nearestForm
= currentAncestor
;
1531 currentAncestor
= currentAncestor
->GetParent();
1543 void nsHtml5TreeBuilder::EnableViewSource(nsHtml5Highlighter
* aHighlighter
) {
1544 MOZ_ASSERT(!mBuilder
, "Must not view source with builder.");
1545 mViewSource
= aHighlighter
;
1548 void nsHtml5TreeBuilder::errDeepTree() {
1549 if (MOZ_UNLIKELY(mViewSource
)) {
1550 mViewSource
->AddErrorToCurrentRun("errDeepTree");
1551 } else if (!mBuilder
) {
1552 nsHtml5TreeOperation
* treeOp
= mOpQueue
.AppendElement();
1553 MOZ_ASSERT(treeOp
, "Tree op allocation failed.");
1554 opMaybeComplainAboutDeepTree
operation(tokenizer
->getLineNumber());
1555 treeOp
->Init(mozilla::AsVariant(operation
));
1559 void nsHtml5TreeBuilder::errStrayStartTag(nsAtom
* aName
) {
1560 if (MOZ_UNLIKELY(mViewSource
)) {
1561 mViewSource
->AddErrorToCurrentRun("errStrayStartTag2", aName
);
1565 void nsHtml5TreeBuilder::errStrayEndTag(nsAtom
* aName
) {
1566 if (MOZ_UNLIKELY(mViewSource
)) {
1567 mViewSource
->AddErrorToCurrentRun("errStrayEndTag", aName
);
1571 void nsHtml5TreeBuilder::errUnclosedElements(int32_t aIndex
, nsAtom
* aName
) {
1572 if (MOZ_UNLIKELY(mViewSource
)) {
1573 mViewSource
->AddErrorToCurrentRun("errUnclosedElements", aName
);
1577 void nsHtml5TreeBuilder::errUnclosedElementsImplied(int32_t aIndex
,
1579 if (MOZ_UNLIKELY(mViewSource
)) {
1580 mViewSource
->AddErrorToCurrentRun("errUnclosedElementsImplied", aName
);
1584 void nsHtml5TreeBuilder::errUnclosedElementsCell(int32_t aIndex
) {
1585 if (MOZ_UNLIKELY(mViewSource
)) {
1586 mViewSource
->AddErrorToCurrentRun("errUnclosedElementsCell");
1590 void nsHtml5TreeBuilder::errStrayDoctype() {
1591 if (MOZ_UNLIKELY(mViewSource
)) {
1592 mViewSource
->AddErrorToCurrentRun("errStrayDoctype");
1596 void nsHtml5TreeBuilder::errAlmostStandardsDoctype() {
1597 if (MOZ_UNLIKELY(mViewSource
) && !forceNoQuirks
) {
1598 mViewSource
->AddErrorToCurrentRun("errAlmostStandardsDoctype");
1602 void nsHtml5TreeBuilder::errQuirkyDoctype() {
1603 if (MOZ_UNLIKELY(mViewSource
) && !forceNoQuirks
) {
1604 mViewSource
->AddErrorToCurrentRun("errQuirkyDoctype");
1608 void nsHtml5TreeBuilder::errNonSpaceInTrailer() {
1609 if (MOZ_UNLIKELY(mViewSource
)) {
1610 mViewSource
->AddErrorToCurrentRun("errNonSpaceInTrailer");
1614 void nsHtml5TreeBuilder::errNonSpaceAfterFrameset() {
1615 if (MOZ_UNLIKELY(mViewSource
)) {
1616 mViewSource
->AddErrorToCurrentRun("errNonSpaceAfterFrameset");
1620 void nsHtml5TreeBuilder::errNonSpaceInFrameset() {
1621 if (MOZ_UNLIKELY(mViewSource
)) {
1622 mViewSource
->AddErrorToCurrentRun("errNonSpaceInFrameset");
1626 void nsHtml5TreeBuilder::errNonSpaceAfterBody() {
1627 if (MOZ_UNLIKELY(mViewSource
)) {
1628 mViewSource
->AddErrorToCurrentRun("errNonSpaceAfterBody");
1632 void nsHtml5TreeBuilder::errNonSpaceInColgroupInFragment() {
1633 if (MOZ_UNLIKELY(mViewSource
)) {
1634 mViewSource
->AddErrorToCurrentRun("errNonSpaceInColgroupInFragment");
1638 void nsHtml5TreeBuilder::errNonSpaceInNoscriptInHead() {
1639 if (MOZ_UNLIKELY(mViewSource
)) {
1640 mViewSource
->AddErrorToCurrentRun("errNonSpaceInNoscriptInHead");
1644 void nsHtml5TreeBuilder::errFooBetweenHeadAndBody(nsAtom
* aName
) {
1645 if (MOZ_UNLIKELY(mViewSource
)) {
1646 mViewSource
->AddErrorToCurrentRun("errFooBetweenHeadAndBody", aName
);
1650 void nsHtml5TreeBuilder::errStartTagWithoutDoctype() {
1651 if (MOZ_UNLIKELY(mViewSource
) && !forceNoQuirks
) {
1652 mViewSource
->AddErrorToCurrentRun("errStartTagWithoutDoctype");
1656 void nsHtml5TreeBuilder::errNoSelectInTableScope() {
1657 if (MOZ_UNLIKELY(mViewSource
)) {
1658 mViewSource
->AddErrorToCurrentRun("errNoSelectInTableScope");
1662 void nsHtml5TreeBuilder::errStartSelectWhereEndSelectExpected() {
1663 if (MOZ_UNLIKELY(mViewSource
)) {
1664 mViewSource
->AddErrorToCurrentRun("errStartSelectWhereEndSelectExpected");
1668 void nsHtml5TreeBuilder::errStartTagWithSelectOpen(nsAtom
* aName
) {
1669 if (MOZ_UNLIKELY(mViewSource
)) {
1670 mViewSource
->AddErrorToCurrentRun("errStartTagWithSelectOpen", aName
);
1674 void nsHtml5TreeBuilder::errBadStartTagInNoscriptInHead(nsAtom
* aName
) {
1675 if (MOZ_UNLIKELY(mViewSource
)) {
1676 mViewSource
->AddErrorToCurrentRun("errBadStartTagInNoscriptInHead", aName
);
1680 void nsHtml5TreeBuilder::errImage() {
1681 if (MOZ_UNLIKELY(mViewSource
)) {
1682 mViewSource
->AddErrorToCurrentRun("errImage");
1686 void nsHtml5TreeBuilder::errIsindex() {
1687 if (MOZ_UNLIKELY(mViewSource
)) {
1688 mViewSource
->AddErrorToCurrentRun("errIsindex");
1692 void nsHtml5TreeBuilder::errFooSeenWhenFooOpen(nsAtom
* aName
) {
1693 if (MOZ_UNLIKELY(mViewSource
)) {
1694 mViewSource
->AddErrorToCurrentRun("errFooSeenWhenFooOpen2", aName
);
1698 void nsHtml5TreeBuilder::errHeadingWhenHeadingOpen() {
1699 if (MOZ_UNLIKELY(mViewSource
)) {
1700 mViewSource
->AddErrorToCurrentRun("errHeadingWhenHeadingOpen");
1704 void nsHtml5TreeBuilder::errFramesetStart() {
1705 if (MOZ_UNLIKELY(mViewSource
)) {
1706 mViewSource
->AddErrorToCurrentRun("errFramesetStart");
1710 void nsHtml5TreeBuilder::errNoCellToClose() {
1711 if (MOZ_UNLIKELY(mViewSource
)) {
1712 mViewSource
->AddErrorToCurrentRun("errNoCellToClose");
1716 void nsHtml5TreeBuilder::errStartTagInTable(nsAtom
* aName
) {
1717 if (MOZ_UNLIKELY(mViewSource
)) {
1718 mViewSource
->AddErrorToCurrentRun("errStartTagInTable", aName
);
1722 void nsHtml5TreeBuilder::errFormWhenFormOpen() {
1723 if (MOZ_UNLIKELY(mViewSource
)) {
1724 mViewSource
->AddErrorToCurrentRun("errFormWhenFormOpen");
1728 void nsHtml5TreeBuilder::errTableSeenWhileTableOpen() {
1729 if (MOZ_UNLIKELY(mViewSource
)) {
1730 mViewSource
->AddErrorToCurrentRun("errTableSeenWhileTableOpen");
1734 void nsHtml5TreeBuilder::errStartTagInTableBody(nsAtom
* aName
) {
1735 if (MOZ_UNLIKELY(mViewSource
)) {
1736 mViewSource
->AddErrorToCurrentRun("errStartTagInTableBody", aName
);
1740 void nsHtml5TreeBuilder::errEndTagSeenWithoutDoctype() {
1741 if (MOZ_UNLIKELY(mViewSource
) && !forceNoQuirks
) {
1742 mViewSource
->AddErrorToCurrentRun("errEndTagSeenWithoutDoctype");
1746 void nsHtml5TreeBuilder::errEndTagAfterBody() {
1747 if (MOZ_UNLIKELY(mViewSource
)) {
1748 mViewSource
->AddErrorToCurrentRun("errEndTagAfterBody");
1752 void nsHtml5TreeBuilder::errEndTagSeenWithSelectOpen(nsAtom
* aName
) {
1753 if (MOZ_UNLIKELY(mViewSource
)) {
1754 mViewSource
->AddErrorToCurrentRun("errEndTagSeenWithSelectOpen", aName
);
1758 void nsHtml5TreeBuilder::errGarbageInColgroup() {
1759 if (MOZ_UNLIKELY(mViewSource
)) {
1760 mViewSource
->AddErrorToCurrentRun("errGarbageInColgroup");
1764 void nsHtml5TreeBuilder::errEndTagBr() {
1765 if (MOZ_UNLIKELY(mViewSource
)) {
1766 mViewSource
->AddErrorToCurrentRun("errEndTagBr");
1770 void nsHtml5TreeBuilder::errNoElementToCloseButEndTagSeen(nsAtom
* aName
) {
1771 if (MOZ_UNLIKELY(mViewSource
)) {
1772 mViewSource
->AddErrorToCurrentRun("errNoElementToCloseButEndTagSeen",
1777 void nsHtml5TreeBuilder::errHtmlStartTagInForeignContext(nsAtom
* aName
) {
1778 if (MOZ_UNLIKELY(mViewSource
)) {
1779 mViewSource
->AddErrorToCurrentRun("errHtmlStartTagInForeignContext", aName
);
1783 void nsHtml5TreeBuilder::errNoTableRowToClose() {
1784 if (MOZ_UNLIKELY(mViewSource
)) {
1785 mViewSource
->AddErrorToCurrentRun("errNoTableRowToClose");
1789 void nsHtml5TreeBuilder::errNonSpaceInTable() {
1790 if (MOZ_UNLIKELY(mViewSource
)) {
1791 mViewSource
->AddErrorToCurrentRun("errNonSpaceInTable");
1795 void nsHtml5TreeBuilder::errUnclosedChildrenInRuby() {
1796 if (MOZ_UNLIKELY(mViewSource
)) {
1797 mViewSource
->AddErrorToCurrentRun("errUnclosedChildrenInRuby");
1801 void nsHtml5TreeBuilder::errStartTagSeenWithoutRuby(nsAtom
* aName
) {
1802 if (MOZ_UNLIKELY(mViewSource
)) {
1803 mViewSource
->AddErrorToCurrentRun("errStartTagSeenWithoutRuby", aName
);
1807 void nsHtml5TreeBuilder::errSelfClosing() {
1808 if (MOZ_UNLIKELY(mViewSource
)) {
1809 mViewSource
->AddErrorToCurrentSlash("errSelfClosing");
1813 void nsHtml5TreeBuilder::errNoCheckUnclosedElementsOnStack() {
1814 if (MOZ_UNLIKELY(mViewSource
)) {
1815 mViewSource
->AddErrorToCurrentRun("errNoCheckUnclosedElementsOnStack");
1819 void nsHtml5TreeBuilder::errEndTagDidNotMatchCurrentOpenElement(
1820 nsAtom
* aName
, nsAtom
* aOther
) {
1821 if (MOZ_UNLIKELY(mViewSource
)) {
1822 mViewSource
->AddErrorToCurrentRun("errEndTagDidNotMatchCurrentOpenElement",
1827 void nsHtml5TreeBuilder::errEndTagViolatesNestingRules(nsAtom
* aName
) {
1828 if (MOZ_UNLIKELY(mViewSource
)) {
1829 mViewSource
->AddErrorToCurrentRun("errEndTagViolatesNestingRules", aName
);
1833 void nsHtml5TreeBuilder::errEndWithUnclosedElements(nsAtom
* aName
) {
1834 if (MOZ_UNLIKELY(mViewSource
)) {
1835 mViewSource
->AddErrorToCurrentRun("errEndWithUnclosedElements", aName
);
1839 void nsHtml5TreeBuilder::errListUnclosedStartTags(int32_t aIgnored
) {
1840 if (MOZ_UNLIKELY(mViewSource
)) {
1841 mViewSource
->AddErrorToCurrentRun("errListUnclosedStartTags");