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/. */
8 #include "nsIPresShell.h"
9 #include "nsNodeUtils.h"
11 #include "mozilla/Likely.h"
12 #include "mozilla/UniquePtr.h"
14 nsHtml5TreeBuilder::nsHtml5TreeBuilder(nsHtml5OplessBuilder
* aBuilder
)
15 : scriptingEnabled(false)
17 , contextName(nullptr)
18 , contextNamespace(kNameSpaceID_None
)
19 , contextNode(nullptr)
20 , formPointer(nullptr)
21 , headPointer(nullptr)
23 , mViewSource(nullptr)
27 , mSpeculativeLoadStage(nullptr)
29 , mCurrentHtmlScriptIsAsyncOrDefer(false)
30 , mPreventScriptExecution(false)
35 MOZ_COUNT_CTOR(nsHtml5TreeBuilder
);
38 nsHtml5TreeBuilder::nsHtml5TreeBuilder(nsAHtml5TreeOpSink
* aOpSink
,
39 nsHtml5TreeOpStage
* aStage
)
40 : scriptingEnabled(false)
42 , contextName(nullptr)
43 , contextNamespace(kNameSpaceID_None
)
44 , contextNode(nullptr)
45 , formPointer(nullptr)
46 , headPointer(nullptr)
48 , mViewSource(nullptr)
50 , mHandles(new nsIContent
*[NS_HTML5_TREE_BUILDER_HANDLE_ARRAY_LENGTH
])
52 , mSpeculativeLoadStage(aStage
)
54 , mCurrentHtmlScriptIsAsyncOrDefer(false)
55 , mPreventScriptExecution(false)
60 MOZ_COUNT_CTOR(nsHtml5TreeBuilder
);
63 nsHtml5TreeBuilder::~nsHtml5TreeBuilder()
65 MOZ_COUNT_DTOR(nsHtml5TreeBuilder
);
66 NS_ASSERTION(!mActive
, "nsHtml5TreeBuilder deleted without ever calling end() on it!");
71 nsHtml5TreeBuilder::createElement(int32_t aNamespace
, nsIAtom
* aName
,
72 nsHtml5HtmlAttributes
* aAttributes
,
73 nsIContentHandle
* aIntendedParent
)
75 NS_PRECONDITION(aAttributes
, "Got null attributes.");
76 NS_PRECONDITION(aName
, "Got null name.");
77 NS_PRECONDITION(aNamespace
== kNameSpaceID_XHTML
||
78 aNamespace
== kNameSpaceID_SVG
||
79 aNamespace
== kNameSpaceID_MathML
,
83 nsCOMPtr
<nsIAtom
> name
= nsHtml5TreeOperation::Reget(aName
);
85 nsIContent
* intendedParent
= aIntendedParent
?
86 static_cast<nsIContent
*>(aIntendedParent
) : nullptr;
88 // intendedParent == nullptr is a special case where the
89 // intended parent is the document.
90 nsNodeInfoManager
* nodeInfoManager
= intendedParent
?
91 intendedParent
->OwnerDoc()->NodeInfoManager() :
92 mBuilder
->GetNodeInfoManager();
95 nsHtml5TreeOperation::CreateElement(aNamespace
,
98 mozilla::dom::FROM_PARSER_FRAGMENT
,
101 if (MOZ_UNLIKELY(aAttributes
!= tokenizer
->GetAttributes() &&
102 aAttributes
!= nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES
)) {
108 nsIContentHandle
* content
= AllocateContentHandle();
109 nsHtml5TreeOperation
* treeOp
= mOpQueue
.AppendElement();
110 NS_ASSERTION(treeOp
, "Tree op allocation failed.");
111 treeOp
->Init(aNamespace
,
116 !!mSpeculativeLoadStage
);
117 // mSpeculativeLoadStage is non-null only in the off-the-main-thread
118 // tree builder, which handles the network stream
120 // Start wall of code for speculative loading and line numbers
122 if (mSpeculativeLoadStage
) {
123 switch (aNamespace
) {
124 case kNameSpaceID_XHTML
:
125 if (nsHtml5Atoms::img
== aName
) {
126 nsString
* url
= aAttributes
->getValue(nsHtml5AttributeName::ATTR_SRC
);
128 aAttributes
->getValue(nsHtml5AttributeName::ATTR_SRCSET
);
129 nsString
* crossOrigin
=
130 aAttributes
->getValue(nsHtml5AttributeName::ATTR_CROSSORIGIN
);
131 nsString
* referrerPolicy
=
132 aAttributes
->getValue(nsHtml5AttributeName::ATTR_REFERRERPOLICY
);
134 aAttributes
->getValue(nsHtml5AttributeName::ATTR_SIZES
);
135 mSpeculativeLoadQueue
.AppendElement()->
136 InitImage(url
? *url
: NullString(),
137 crossOrigin
? *crossOrigin
: NullString(),
138 referrerPolicy
? *referrerPolicy
: NullString(),
139 srcset
? *srcset
: NullString(),
140 sizes
? *sizes
: NullString());
141 } else if (nsHtml5Atoms::source
== aName
) {
143 aAttributes
->getValue(nsHtml5AttributeName::ATTR_SRCSET
);
144 // Sources without srcset cannot be selected. The source could also be
145 // for a media element, but in that context doesn't use srcset. See
146 // comments in nsHtml5SpeculativeLoad.h about <picture> preloading
149 aAttributes
->getValue(nsHtml5AttributeName::ATTR_SIZES
);
151 aAttributes
->getValue(nsHtml5AttributeName::ATTR_TYPE
);
153 aAttributes
->getValue(nsHtml5AttributeName::ATTR_MEDIA
);
154 mSpeculativeLoadQueue
.AppendElement()->
155 InitPictureSource(*srcset
,
156 sizes
? *sizes
: NullString(),
157 type
? *type
: NullString(),
158 media
? *media
: NullString());
160 } else if (nsHtml5Atoms::script
== aName
) {
161 nsHtml5TreeOperation
* treeOp
= mOpQueue
.AppendElement();
162 NS_ASSERTION(treeOp
, "Tree op allocation failed.");
163 treeOp
->Init(eTreeOpSetScriptLineNumberAndFreeze
, content
, tokenizer
->getLineNumber());
165 nsString
* url
= aAttributes
->getValue(nsHtml5AttributeName::ATTR_SRC
);
167 nsString
* charset
= aAttributes
->getValue(nsHtml5AttributeName::ATTR_CHARSET
);
168 nsString
* type
= aAttributes
->getValue(nsHtml5AttributeName::ATTR_TYPE
);
169 nsString
* crossOrigin
=
170 aAttributes
->getValue(nsHtml5AttributeName::ATTR_CROSSORIGIN
);
171 nsString
* integrity
=
172 aAttributes
->getValue(nsHtml5AttributeName::ATTR_INTEGRITY
);
173 mSpeculativeLoadQueue
.AppendElement()->
175 (charset
) ? *charset
: EmptyString(),
176 (type
) ? *type
: EmptyString(),
177 (crossOrigin
) ? *crossOrigin
: NullString(),
178 (integrity
) ? *integrity
: NullString(),
179 mode
== NS_HTML5TREE_BUILDER_IN_HEAD
);
180 mCurrentHtmlScriptIsAsyncOrDefer
=
181 aAttributes
->contains(nsHtml5AttributeName::ATTR_ASYNC
) ||
182 aAttributes
->contains(nsHtml5AttributeName::ATTR_DEFER
);
184 } else if (nsHtml5Atoms::link
== aName
) {
185 nsString
* rel
= aAttributes
->getValue(nsHtml5AttributeName::ATTR_REL
);
186 // Not splitting on space here is bogus but the old parser didn't even
187 // do a case-insensitive check.
189 if (rel
->LowerCaseEqualsASCII("stylesheet")) {
190 nsString
* url
= aAttributes
->getValue(nsHtml5AttributeName::ATTR_HREF
);
192 nsString
* charset
= aAttributes
->getValue(nsHtml5AttributeName::ATTR_CHARSET
);
193 nsString
* crossOrigin
=
194 aAttributes
->getValue(nsHtml5AttributeName::ATTR_CROSSORIGIN
);
195 nsString
* integrity
=
196 aAttributes
->getValue(nsHtml5AttributeName::ATTR_INTEGRITY
);
197 mSpeculativeLoadQueue
.AppendElement()->
199 (charset
) ? *charset
: EmptyString(),
200 (crossOrigin
) ? *crossOrigin
: NullString(),
201 (integrity
) ? *integrity
: NullString());
203 } else if (rel
->LowerCaseEqualsASCII("preconnect")) {
204 nsString
* url
= aAttributes
->getValue(nsHtml5AttributeName::ATTR_HREF
);
206 nsString
* crossOrigin
=
207 aAttributes
->getValue(nsHtml5AttributeName::ATTR_CROSSORIGIN
);
208 mSpeculativeLoadQueue
.AppendElement()->
209 InitPreconnect(*url
, (crossOrigin
) ? *crossOrigin
: NullString());
213 } else if (nsHtml5Atoms::video
== aName
) {
214 nsString
* url
= aAttributes
->getValue(nsHtml5AttributeName::ATTR_POSTER
);
216 mSpeculativeLoadQueue
.AppendElement()->InitImage(*url
, NullString(),
221 } else if (nsHtml5Atoms::style
== aName
) {
222 nsHtml5TreeOperation
* treeOp
= mOpQueue
.AppendElement();
223 NS_ASSERTION(treeOp
, "Tree op allocation failed.");
224 treeOp
->Init(eTreeOpSetStyleLineNumber
, content
, tokenizer
->getLineNumber());
225 } else if (nsHtml5Atoms::html
== aName
) {
226 nsString
* url
= aAttributes
->getValue(nsHtml5AttributeName::ATTR_MANIFEST
);
228 mSpeculativeLoadQueue
.AppendElement()->InitManifest(*url
);
230 mSpeculativeLoadQueue
.AppendElement()->InitManifest(EmptyString());
232 } else if (nsHtml5Atoms::base
== aName
) {
234 aAttributes
->getValue(nsHtml5AttributeName::ATTR_HREF
);
236 mSpeculativeLoadQueue
.AppendElement()->InitBase(*url
);
238 } else if (nsHtml5Atoms::meta
== aName
) {
239 if (nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString(
240 "content-security-policy",
241 aAttributes
->getValue(nsHtml5AttributeName::ATTR_HTTP_EQUIV
))) {
242 nsString
* csp
= aAttributes
->getValue(nsHtml5AttributeName::ATTR_CONTENT
);
244 mSpeculativeLoadQueue
.AppendElement()->InitMetaCSP(*csp
);
247 else if (nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString(
249 aAttributes
->getValue(nsHtml5AttributeName::ATTR_NAME
))) {
250 nsString
* referrerPolicy
= aAttributes
->getValue(nsHtml5AttributeName::ATTR_CONTENT
);
251 if (referrerPolicy
) {
252 mSpeculativeLoadQueue
.AppendElement()->InitMetaReferrerPolicy(*referrerPolicy
);
257 case kNameSpaceID_SVG
:
258 if (nsHtml5Atoms::image
== aName
) {
259 nsString
* url
= aAttributes
->getValue(nsHtml5AttributeName::ATTR_XLINK_HREF
);
261 mSpeculativeLoadQueue
.AppendElement()->InitImage(*url
, NullString(),
266 } else if (nsHtml5Atoms::script
== aName
) {
267 nsHtml5TreeOperation
* treeOp
= mOpQueue
.AppendElement();
268 NS_ASSERTION(treeOp
, "Tree op allocation failed.");
269 treeOp
->Init(eTreeOpSetScriptLineNumberAndFreeze
, content
, tokenizer
->getLineNumber());
271 nsString
* url
= aAttributes
->getValue(nsHtml5AttributeName::ATTR_XLINK_HREF
);
273 nsString
* type
= aAttributes
->getValue(nsHtml5AttributeName::ATTR_TYPE
);
274 nsString
* crossOrigin
=
275 aAttributes
->getValue(nsHtml5AttributeName::ATTR_CROSSORIGIN
);
276 nsString
* integrity
=
277 aAttributes
->getValue(nsHtml5AttributeName::ATTR_INTEGRITY
);
278 mSpeculativeLoadQueue
.AppendElement()->
281 (type
) ? *type
: EmptyString(),
282 (crossOrigin
) ? *crossOrigin
: NullString(),
283 (integrity
) ? *integrity
: NullString(),
284 mode
== NS_HTML5TREE_BUILDER_IN_HEAD
);
286 } else if (nsHtml5Atoms::style
== aName
) {
287 nsHtml5TreeOperation
* treeOp
= mOpQueue
.AppendElement();
288 NS_ASSERTION(treeOp
, "Tree op allocation failed.");
289 treeOp
->Init(eTreeOpSetStyleLineNumber
, content
, tokenizer
->getLineNumber());
291 nsString
* url
= aAttributes
->getValue(nsHtml5AttributeName::ATTR_XLINK_HREF
);
293 nsString
* crossOrigin
=
294 aAttributes
->getValue(nsHtml5AttributeName::ATTR_CROSSORIGIN
);
295 nsString
* integrity
=
296 aAttributes
->getValue(nsHtml5AttributeName::ATTR_INTEGRITY
);
297 mSpeculativeLoadQueue
.AppendElement()->
298 InitStyle(*url
, EmptyString(),
299 (crossOrigin
) ? *crossOrigin
: NullString(),
300 (integrity
) ? *integrity
: NullString());
305 } else if (aNamespace
!= kNameSpaceID_MathML
) {
306 // No speculative loader--just line numbers and defer/async check
307 if (nsHtml5Atoms::style
== aName
) {
308 nsHtml5TreeOperation
* treeOp
= mOpQueue
.AppendElement();
309 NS_ASSERTION(treeOp
, "Tree op allocation failed.");
310 treeOp
->Init(eTreeOpSetStyleLineNumber
, content
, tokenizer
->getLineNumber());
311 } else if (nsHtml5Atoms::script
== aName
) {
312 nsHtml5TreeOperation
* treeOp
= mOpQueue
.AppendElement();
313 NS_ASSERTION(treeOp
, "Tree op allocation failed.");
314 treeOp
->Init(eTreeOpSetScriptLineNumberAndFreeze
, content
, tokenizer
->getLineNumber());
315 if (aNamespace
== kNameSpaceID_XHTML
) {
316 mCurrentHtmlScriptIsAsyncOrDefer
=
317 aAttributes
->contains(nsHtml5AttributeName::ATTR_SRC
) &&
318 (aAttributes
->contains(nsHtml5AttributeName::ATTR_ASYNC
) ||
319 aAttributes
->contains(nsHtml5AttributeName::ATTR_DEFER
));
321 } else if (aNamespace
== kNameSpaceID_XHTML
) {
322 if (nsHtml5Atoms::html
== aName
) {
323 nsString
* url
= aAttributes
->getValue(nsHtml5AttributeName::ATTR_MANIFEST
);
324 nsHtml5TreeOperation
* treeOp
= mOpQueue
.AppendElement();
325 NS_ASSERTION(treeOp
, "Tree op allocation failed.");
327 treeOp
->Init(eTreeOpProcessOfflineManifest
, *url
);
329 treeOp
->Init(eTreeOpProcessOfflineManifest
, EmptyString());
331 } else if (nsHtml5Atoms::base
== aName
&& mViewSource
) {
332 nsString
* url
= aAttributes
->getValue(nsHtml5AttributeName::ATTR_HREF
);
334 mViewSource
->AddBase(*url
);
340 // End wall of code for speculative loading
346 nsHtml5TreeBuilder::createElement(int32_t aNamespace
, nsIAtom
* aName
,
347 nsHtml5HtmlAttributes
* aAttributes
,
348 nsIContentHandle
* aFormElement
,
349 nsIContentHandle
* aIntendedParent
)
351 nsIContentHandle
* content
= createElement(aNamespace
, aName
, aAttributes
,
355 nsHtml5TreeOperation::SetFormElement(static_cast<nsIContent
*>(content
),
356 static_cast<nsIContent
*>(aFormElement
));
358 nsHtml5TreeOperation
* treeOp
= mOpQueue
.AppendElement();
359 NS_ASSERTION(treeOp
, "Tree op allocation failed.");
360 treeOp
->Init(eTreeOpSetFormElement
, content
, aFormElement
);
367 nsHtml5TreeBuilder::createHtmlElementSetAsRoot(nsHtml5HtmlAttributes
* aAttributes
)
369 nsIContentHandle
* content
= createElement(kNameSpaceID_XHTML
,
374 nsresult rv
= nsHtml5TreeOperation::AppendToDocument(static_cast<nsIContent
*>(content
),
377 MarkAsBrokenAndRequestSuspension(rv
);
380 nsHtml5TreeOperation
* treeOp
= mOpQueue
.AppendElement();
381 NS_ASSERTION(treeOp
, "Tree op allocation failed.");
382 treeOp
->Init(eTreeOpAppendToDocument
, content
);
388 nsHtml5TreeBuilder::createAndInsertFosterParentedElement(int32_t aNamespace
, nsIAtom
* aName
,
389 nsHtml5HtmlAttributes
* aAttributes
,
390 nsIContentHandle
* aFormElement
,
391 nsIContentHandle
* aTable
,
392 nsIContentHandle
* aStackParent
)
394 NS_PRECONDITION(aTable
, "Null table");
395 NS_PRECONDITION(aStackParent
, "Null stack parent");
398 // Get the foster parent to use as the intended parent when creating
399 // the child element.
400 nsIContent
* fosterParent
= nsHtml5TreeOperation::GetFosterParent(
401 static_cast<nsIContent
*>(aTable
),
402 static_cast<nsIContent
*>(aStackParent
));
404 nsIContentHandle
* child
= createElement(aNamespace
, aName
, aAttributes
,
405 aFormElement
, fosterParent
);
407 insertFosterParentedChild(child
, aTable
, aStackParent
);
412 // Tree op to get the foster parent that we use as the intended parent
413 // when creating the child element.
414 nsHtml5TreeOperation
* fosterParentTreeOp
= mOpQueue
.AppendElement();
415 NS_ASSERTION(fosterParentTreeOp
, "Tree op allocation failed.");
416 nsIContentHandle
* fosterParentHandle
= AllocateContentHandle();
417 fosterParentTreeOp
->Init(eTreeOpGetFosterParent
, aTable
,
418 aStackParent
, fosterParentHandle
);
420 // Create the element with the correct intended parent.
421 nsIContentHandle
* child
= createElement(aNamespace
, aName
, aAttributes
,
422 aFormElement
, fosterParentHandle
);
424 // Insert the child into the foster parent.
425 insertFosterParentedChild(child
, aTable
, aStackParent
);
431 nsHtml5TreeBuilder::detachFromParent(nsIContentHandle
* aElement
)
433 NS_PRECONDITION(aElement
, "Null element");
436 nsHtml5TreeOperation::Detach(static_cast<nsIContent
*>(aElement
),
441 nsHtml5TreeOperation
* treeOp
= mOpQueue
.AppendElement();
442 NS_ASSERTION(treeOp
, "Tree op allocation failed.");
443 treeOp
->Init(eTreeOpDetach
, aElement
);
447 nsHtml5TreeBuilder::appendElement(nsIContentHandle
* aChild
, nsIContentHandle
* aParent
)
449 NS_PRECONDITION(aChild
, "Null child");
450 NS_PRECONDITION(aParent
, "Null parent");
451 if (deepTreeSurrogateParent
) {
456 nsresult rv
= nsHtml5TreeOperation::Append(static_cast<nsIContent
*>(aChild
),
457 static_cast<nsIContent
*>(aParent
),
460 MarkAsBrokenAndRequestSuspension(rv
);
465 nsHtml5TreeOperation
* treeOp
= mOpQueue
.AppendElement();
466 NS_ASSERTION(treeOp
, "Tree op allocation failed.");
467 treeOp
->Init(eTreeOpAppend
, aChild
, aParent
);
471 nsHtml5TreeBuilder::appendChildrenToNewParent(nsIContentHandle
* aOldParent
, nsIContentHandle
* aNewParent
)
473 NS_PRECONDITION(aOldParent
, "Null old parent");
474 NS_PRECONDITION(aNewParent
, "Null new parent");
477 nsresult rv
= nsHtml5TreeOperation::AppendChildrenToNewParent(
478 static_cast<nsIContent
*>(aOldParent
),
479 static_cast<nsIContent
*>(aNewParent
),
482 MarkAsBrokenAndRequestSuspension(rv
);
487 nsHtml5TreeOperation
* treeOp
= mOpQueue
.AppendElement();
488 NS_ASSERTION(treeOp
, "Tree op allocation failed.");
489 treeOp
->Init(eTreeOpAppendChildrenToNewParent
, aOldParent
, aNewParent
);
493 nsHtml5TreeBuilder::insertFosterParentedCharacters(char16_t
* aBuffer
, int32_t aStart
, int32_t aLength
, nsIContentHandle
* aTable
, nsIContentHandle
* aStackParent
)
495 NS_PRECONDITION(aBuffer
, "Null buffer");
496 NS_PRECONDITION(aTable
, "Null table");
497 NS_PRECONDITION(aStackParent
, "Null stack parent");
498 MOZ_ASSERT(!aStart
, "aStart must always be zero.");
501 nsresult rv
= nsHtml5TreeOperation::FosterParentText(
502 static_cast<nsIContent
*>(aStackParent
),
503 aBuffer
, // XXX aStart always ignored???
505 static_cast<nsIContent
*>(aTable
),
508 MarkAsBrokenAndRequestSuspension(rv
);
513 char16_t
* bufferCopy
= new (mozilla::fallible
) char16_t
[aLength
];
515 // Just assigning mBroken instead of generating tree op. The caller
516 // of tokenizeBuffer() will call MarkAsBroken() as appropriate.
517 mBroken
= NS_ERROR_OUT_OF_MEMORY
;
522 memcpy(bufferCopy
, aBuffer
, aLength
* sizeof(char16_t
));
524 nsHtml5TreeOperation
* treeOp
= mOpQueue
.AppendElement();
525 NS_ASSERTION(treeOp
, "Tree op allocation failed.");
526 treeOp
->Init(eTreeOpFosterParentText
, bufferCopy
, aLength
, aStackParent
, aTable
);
530 nsHtml5TreeBuilder::insertFosterParentedChild(nsIContentHandle
* aChild
, nsIContentHandle
* aTable
, nsIContentHandle
* aStackParent
)
532 NS_PRECONDITION(aChild
, "Null child");
533 NS_PRECONDITION(aTable
, "Null table");
534 NS_PRECONDITION(aStackParent
, "Null stack parent");
537 nsresult rv
= nsHtml5TreeOperation::FosterParent(
538 static_cast<nsIContent
*>(aChild
),
539 static_cast<nsIContent
*>(aStackParent
),
540 static_cast<nsIContent
*>(aTable
),
543 MarkAsBrokenAndRequestSuspension(rv
);
548 nsHtml5TreeOperation
* treeOp
= mOpQueue
.AppendElement();
549 NS_ASSERTION(treeOp
, "Tree op allocation failed.");
550 treeOp
->Init(eTreeOpFosterParent
, aChild
, aStackParent
, aTable
);
554 nsHtml5TreeBuilder::appendCharacters(nsIContentHandle
* aParent
, char16_t
* aBuffer
, int32_t aStart
, int32_t aLength
)
556 NS_PRECONDITION(aBuffer
, "Null buffer");
557 NS_PRECONDITION(aParent
, "Null parent");
558 MOZ_ASSERT(!aStart
, "aStart must always be zero.");
561 nsresult rv
= nsHtml5TreeOperation::AppendText(
562 aBuffer
, // XXX aStart always ignored???
564 static_cast<nsIContent
*>(deepTreeSurrogateParent
?
565 deepTreeSurrogateParent
: aParent
),
568 MarkAsBrokenAndRequestSuspension(rv
);
573 char16_t
* bufferCopy
= new (mozilla::fallible
) char16_t
[aLength
];
575 // Just assigning mBroken instead of generating tree op. The caller
576 // of tokenizeBuffer() will call MarkAsBroken() as appropriate.
577 mBroken
= NS_ERROR_OUT_OF_MEMORY
;
582 memcpy(bufferCopy
, aBuffer
, aLength
* sizeof(char16_t
));
584 nsHtml5TreeOperation
* treeOp
= mOpQueue
.AppendElement();
585 NS_ASSERTION(treeOp
, "Tree op allocation failed.");
586 treeOp
->Init(eTreeOpAppendText
, bufferCopy
, aLength
,
587 deepTreeSurrogateParent
? deepTreeSurrogateParent
: aParent
);
591 nsHtml5TreeBuilder::appendIsindexPrompt(nsIContentHandle
* aParent
)
593 NS_PRECONDITION(aParent
, "Null parent");
596 nsresult rv
= nsHtml5TreeOperation::AppendIsindexPrompt(
597 static_cast<nsIContent
*>(aParent
),
600 MarkAsBrokenAndRequestSuspension(rv
);
605 nsHtml5TreeOperation
* treeOp
= mOpQueue
.AppendElement();
606 NS_ASSERTION(treeOp
, "Tree op allocation failed.");
607 treeOp
->Init(eTreeOpAppendIsindexPrompt
, aParent
);
611 nsHtml5TreeBuilder::appendComment(nsIContentHandle
* aParent
, char16_t
* aBuffer
, int32_t aStart
, int32_t aLength
)
613 NS_PRECONDITION(aBuffer
, "Null buffer");
614 NS_PRECONDITION(aParent
, "Null parent");
615 MOZ_ASSERT(!aStart
, "aStart must always be zero.");
617 if (deepTreeSurrogateParent
) {
622 nsresult rv
= nsHtml5TreeOperation::AppendComment(
623 static_cast<nsIContent
*>(aParent
),
624 aBuffer
, // XXX aStart always ignored???
628 MarkAsBrokenAndRequestSuspension(rv
);
633 char16_t
* bufferCopy
= new (mozilla::fallible
) char16_t
[aLength
];
635 // Just assigning mBroken instead of generating tree op. The caller
636 // of tokenizeBuffer() will call MarkAsBroken() as appropriate.
637 mBroken
= NS_ERROR_OUT_OF_MEMORY
;
642 memcpy(bufferCopy
, aBuffer
, aLength
* sizeof(char16_t
));
644 nsHtml5TreeOperation
* treeOp
= mOpQueue
.AppendElement();
645 NS_ASSERTION(treeOp
, "Tree op allocation failed.");
646 treeOp
->Init(eTreeOpAppendComment
, bufferCopy
, aLength
, aParent
);
650 nsHtml5TreeBuilder::appendCommentToDocument(char16_t
* aBuffer
, int32_t aStart
, int32_t aLength
)
652 NS_PRECONDITION(aBuffer
, "Null buffer");
653 MOZ_ASSERT(!aStart
, "aStart must always be zero.");
656 nsresult rv
= nsHtml5TreeOperation::AppendCommentToDocument(
657 aBuffer
, // XXX aStart always ignored???
661 MarkAsBrokenAndRequestSuspension(rv
);
666 char16_t
* bufferCopy
= new (mozilla::fallible
) char16_t
[aLength
];
668 // Just assigning mBroken instead of generating tree op. The caller
669 // of tokenizeBuffer() will call MarkAsBroken() as appropriate.
670 mBroken
= NS_ERROR_OUT_OF_MEMORY
;
675 memcpy(bufferCopy
, aBuffer
, aLength
* sizeof(char16_t
));
677 nsHtml5TreeOperation
* treeOp
= mOpQueue
.AppendElement();
678 NS_ASSERTION(treeOp
, "Tree op allocation failed.");
679 treeOp
->Init(eTreeOpAppendCommentToDocument
, bufferCopy
, aLength
);
683 nsHtml5TreeBuilder::addAttributesToElement(nsIContentHandle
* aElement
, nsHtml5HtmlAttributes
* aAttributes
)
685 NS_PRECONDITION(aElement
, "Null element");
686 NS_PRECONDITION(aAttributes
, "Null attributes");
688 if (aAttributes
== nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES
) {
693 MOZ_ASSERT(aAttributes
== tokenizer
->GetAttributes(),
694 "Using attribute other than the tokenizer's to add to body or html.");
695 nsresult rv
= nsHtml5TreeOperation::AddAttributes(
696 static_cast<nsIContent
*>(aElement
),
700 MarkAsBrokenAndRequestSuspension(rv
);
705 nsHtml5TreeOperation
* treeOp
= mOpQueue
.AppendElement();
706 NS_ASSERTION(treeOp
, "Tree op allocation failed.");
707 treeOp
->Init(aElement
, aAttributes
);
711 nsHtml5TreeBuilder::markMalformedIfScript(nsIContentHandle
* aElement
)
713 NS_PRECONDITION(aElement
, "Null element");
716 nsHtml5TreeOperation::MarkMalformedIfScript(
717 static_cast<nsIContent
*>(aElement
));
721 nsHtml5TreeOperation
* treeOp
= mOpQueue
.AppendElement();
722 NS_ASSERTION(treeOp
, "Tree op allocation failed.");
723 treeOp
->Init(eTreeOpMarkMalformedIfScript
, aElement
);
727 nsHtml5TreeBuilder::start(bool fragment
)
729 mCurrentHtmlScriptIsAsyncOrDefer
= false;
730 deepTreeSurrogateParent
= nullptr;
737 nsHtml5TreeBuilder::end()
746 nsHtml5TreeBuilder::appendDoctypeToDocument(nsIAtom
* aName
, nsString
* aPublicId
, nsString
* aSystemId
)
748 NS_PRECONDITION(aName
, "Null name");
751 nsCOMPtr
<nsIAtom
> name
= nsHtml5TreeOperation::Reget(aName
);
753 nsHtml5TreeOperation::AppendDoctypeToDocument(name
,
758 MarkAsBrokenAndRequestSuspension(rv
);
763 nsHtml5TreeOperation
* treeOp
= mOpQueue
.AppendElement();
764 NS_ASSERTION(treeOp
, "Tree op allocation failed.");
765 treeOp
->Init(aName
, *aPublicId
, *aSystemId
);
766 // nsXMLContentSink can flush here, but what's the point?
767 // It can also interrupt here, but we can't.
771 nsHtml5TreeBuilder::elementPushed(int32_t aNamespace
, nsIAtom
* aName
, nsIContentHandle
* aElement
)
773 NS_ASSERTION(aNamespace
== kNameSpaceID_XHTML
|| aNamespace
== kNameSpaceID_SVG
|| aNamespace
== kNameSpaceID_MathML
, "Element isn't HTML, SVG or MathML!");
774 NS_ASSERTION(aName
, "Element doesn't have local name!");
775 NS_ASSERTION(aElement
, "No element!");
777 * The frame constructor uses recursive algorithms, so it can't deal with
778 * arbitrarily deep trees. This is especially a problem on Windows where
779 * the permitted depth of the runtime stack is rather small.
781 * The following is a protection against author incompetence--not against
782 * malice. There are other ways to make the DOM deep anyway.
784 * The basic idea is that when the tree builder stack gets too deep,
785 * append operations no longer append to the node that the HTML parsing
786 * algorithm says they should but instead text nodes are append to the last
787 * element that was seen before a magic tree builder stack threshold was
788 * reached and element and comment nodes aren't appended to the DOM at all.
790 * However, for security reasons, non-child descendant text nodes inside an
791 * SVG script or style element should not become children. Also, non-cell
792 * table elements shouldn't be used as surrogate parents for user experience
795 if (!deepTreeSurrogateParent
&& currentPtr
>= MAX_REFLOW_DEPTH
&&
796 !(aName
== nsHtml5Atoms::script
||
797 aName
== nsHtml5Atoms::table
||
798 aName
== nsHtml5Atoms::thead
||
799 aName
== nsHtml5Atoms::tfoot
||
800 aName
== nsHtml5Atoms::tbody
||
801 aName
== nsHtml5Atoms::tr
||
802 aName
== nsHtml5Atoms::colgroup
||
803 aName
== nsHtml5Atoms::style
)) {
804 deepTreeSurrogateParent
= aElement
;
806 if (aNamespace
!= kNameSpaceID_XHTML
) {
809 if (aName
== nsHtml5Atoms::body
|| aName
== nsHtml5Atoms::frameset
) {
811 // InnerHTML and DOMParser shouldn't start layout anyway
814 nsHtml5TreeOperation
* treeOp
= mOpQueue
.AppendElement();
815 NS_ASSERTION(treeOp
, "Tree op allocation failed.");
816 treeOp
->Init(eTreeOpStartLayout
);
819 if (aName
== nsHtml5Atoms::input
||
820 aName
== nsHtml5Atoms::button
) {
822 nsHtml5TreeOperation::DoneCreatingElement(static_cast<nsIContent
*>(aElement
));
824 mOpQueue
.AppendElement()->Init(eTreeOpDoneCreatingElement
, aElement
);
828 if (aName
== nsHtml5Atoms::audio
||
829 aName
== nsHtml5Atoms::video
||
830 aName
== nsHtml5Atoms::menuitem
) {
832 nsHtml5TreeOperation::DoneCreatingElement(static_cast<nsIContent
*>(aElement
));
834 mOpQueue
.AppendElement()->Init(eTreeOpDoneCreatingElement
, aElement
);
838 if (mSpeculativeLoadStage
&& aName
== nsHtml5Atoms::picture
) {
839 // mSpeculativeLoadStage is non-null only in the off-the-main-thread
840 // tree builder, which handles the network stream
842 // See comments in nsHtml5SpeculativeLoad.h about <picture> preloading
843 mSpeculativeLoadQueue
.AppendElement()->InitOpenPicture();
848 nsHtml5TreeBuilder::elementPopped(int32_t aNamespace
, nsIAtom
* aName
, nsIContentHandle
* aElement
)
850 NS_ASSERTION(aNamespace
== kNameSpaceID_XHTML
|| aNamespace
== kNameSpaceID_SVG
|| aNamespace
== kNameSpaceID_MathML
, "Element isn't HTML, SVG or MathML!");
851 NS_ASSERTION(aName
, "Element doesn't have local name!");
852 NS_ASSERTION(aElement
, "No element!");
853 if (deepTreeSurrogateParent
&& currentPtr
<= MAX_REFLOW_DEPTH
) {
854 deepTreeSurrogateParent
= nullptr;
856 if (aNamespace
== kNameSpaceID_MathML
) {
859 // we now have only SVG and HTML
860 if (aName
== nsHtml5Atoms::script
) {
861 if (mPreventScriptExecution
) {
863 nsHtml5TreeOperation::PreventScriptExecution(static_cast<nsIContent
*>(aElement
));
866 mOpQueue
.AppendElement()->Init(eTreeOpPreventScriptExecution
, aElement
);
872 if (mCurrentHtmlScriptIsAsyncOrDefer
) {
873 NS_ASSERTION(aNamespace
== kNameSpaceID_XHTML
,
874 "Only HTML scripts may be async/defer.");
875 nsHtml5TreeOperation
* treeOp
= mOpQueue
.AppendElement();
876 NS_ASSERTION(treeOp
, "Tree op allocation failed.");
877 treeOp
->Init(eTreeOpRunScriptAsyncDefer
, aElement
);
878 mCurrentHtmlScriptIsAsyncOrDefer
= false;
882 nsHtml5TreeOperation
* treeOp
= mOpQueue
.AppendElement();
883 NS_ASSERTION(treeOp
, "Tree op allocation failed.");
884 treeOp
->InitScript(aElement
);
887 if (aName
== nsHtml5Atoms::title
) {
889 nsHtml5TreeOperation::DoneAddingChildren(static_cast<nsIContent
*>(aElement
));
892 nsHtml5TreeOperation
* treeOp
= mOpQueue
.AppendElement();
893 NS_ASSERTION(treeOp
, "Tree op allocation failed.");
894 treeOp
->Init(eTreeOpDoneAddingChildren
, aElement
);
897 if (aName
== nsHtml5Atoms::style
|| (aNamespace
== kNameSpaceID_XHTML
&& aName
== nsHtml5Atoms::link
)) {
899 MOZ_ASSERT(!nsContentUtils::IsSafeToRunScript(),
900 "Scripts must be blocked.");
901 mBuilder
->UpdateStyleSheet(static_cast<nsIContent
*>(aElement
));
904 nsHtml5TreeOperation
* treeOp
= mOpQueue
.AppendElement();
905 NS_ASSERTION(treeOp
, "Tree op allocation failed.");
906 treeOp
->Init(eTreeOpUpdateStyleSheet
, aElement
);
909 if (aNamespace
== kNameSpaceID_SVG
) {
910 if (aName
== nsHtml5Atoms::svg
) {
912 nsHtml5TreeOperation::SvgLoad(static_cast<nsIContent
*>(aElement
));
915 nsHtml5TreeOperation
* treeOp
= mOpQueue
.AppendElement();
916 NS_ASSERTION(treeOp
, "Tree op allocation failed.");
917 treeOp
->Init(eTreeOpSvgLoad
, aElement
);
921 // we now have only HTML
922 // Some HTML nodes need DoneAddingChildren() called to initialize
923 // properly (e.g. form state restoration).
924 // XXX expose ElementName group here and do switch
925 if (aName
== nsHtml5Atoms::object
||
926 aName
== nsHtml5Atoms::applet
||
927 aName
== nsHtml5Atoms::select
||
928 aName
== nsHtml5Atoms::textarea
||
929 aName
== nsHtml5Atoms::output
) {
931 nsHtml5TreeOperation::DoneAddingChildren(static_cast<nsIContent
*>(aElement
));
934 nsHtml5TreeOperation
* treeOp
= mOpQueue
.AppendElement();
935 NS_ASSERTION(treeOp
, "Tree op allocation failed.");
936 treeOp
->Init(eTreeOpDoneAddingChildren
, aElement
);
939 if (aName
== nsHtml5Atoms::meta
&& !fragment
&& !mBuilder
) {
940 nsHtml5TreeOperation
* treeOp
= mOpQueue
.AppendElement();
941 NS_ASSERTION(treeOp
, "Tree op allocation failed.");
942 treeOp
->Init(eTreeOpProcessMeta
, aElement
);
945 if (mSpeculativeLoadStage
&& aName
== nsHtml5Atoms::picture
) {
946 // mSpeculativeLoadStage is non-null only in the off-the-main-thread
947 // tree builder, which handles the network stream
949 // See comments in nsHtml5SpeculativeLoad.h about <picture> preloading
950 mSpeculativeLoadQueue
.AppendElement()->InitEndPicture();
956 nsHtml5TreeBuilder::accumulateCharacters(const char16_t
* aBuf
, int32_t aStart
, int32_t aLength
)
958 MOZ_ASSERT(charBufferLen
+ aLength
<= charBuffer
.length
,
959 "About to memcpy past the end of the buffer!");
960 memcpy(charBuffer
+ charBufferLen
, aBuf
+ aStart
, sizeof(char16_t
) * aLength
);
961 charBufferLen
+= aLength
;
965 nsHtml5TreeBuilder::EnsureBufferSpace(size_t aLength
)
967 // TODO: Unify nsHtml5Tokenizer::strBuf and nsHtml5TreeBuilder::charBuffer
968 // so that this method becomes unnecessary.
969 size_t worstCase
= size_t(charBufferLen
) + aLength
;
970 if (worstCase
> INT32_MAX
) {
971 // Since we index into the buffer using int32_t due to the Java heritage
972 // of the code, let's treat this as OOM.
976 // Add one to round to the next power of two to avoid immediate
977 // reallocation once there are a few characters in the buffer.
978 charBuffer
= jArray
<char16_t
,int32_t>::newFallibleJArray(mozilla::RoundUpPow2(worstCase
+ 1));
982 } else if (worstCase
> size_t(charBuffer
.length
)) {
983 jArray
<char16_t
,int32_t> newBuf
= jArray
<char16_t
,int32_t>::newFallibleJArray(mozilla::RoundUpPow2(worstCase
));
987 memcpy(newBuf
, charBuffer
, sizeof(char16_t
) * charBufferLen
);
994 nsHtml5TreeBuilder::AllocateContentHandle()
996 if (MOZ_UNLIKELY(mBuilder
)) {
997 MOZ_ASSERT_UNREACHABLE("Must never allocate a handle with builder.");
1000 if (mHandlesUsed
== NS_HTML5_TREE_BUILDER_HANDLE_ARRAY_LENGTH
) {
1001 mOldHandles
.AppendElement(Move(mHandles
));
1002 mHandles
= MakeUnique
<nsIContent
*[]>(NS_HTML5_TREE_BUILDER_HANDLE_ARRAY_LENGTH
);
1006 mHandles
[mHandlesUsed
] = (nsIContent
*)0xC0DEDBAD;
1008 return &mHandles
[mHandlesUsed
++];
1012 nsHtml5TreeBuilder::HasScript()
1014 uint32_t len
= mOpQueue
.Length();
1018 return mOpQueue
.ElementAt(len
- 1).IsRunScript();
1022 nsHtml5TreeBuilder::Flush(bool aDiscretionary
)
1024 if (MOZ_UNLIKELY(mBuilder
)) {
1025 MOZ_ASSERT_UNREACHABLE("Must never flush with builder.");
1028 if (NS_SUCCEEDED(mBroken
)) {
1029 if (!aDiscretionary
||
1032 stack
[currentPtr
]->isFosterParenting())) {
1033 // Don't flush text on discretionary flushes if the current element on
1034 // the stack is a foster-parenting element and there's pending text,
1035 // because flushing in that case would make the tree shape dependent on
1036 // where the flush points fall.
1042 bool hasOps
= !mOpQueue
.IsEmpty();
1044 // If the builder is broken and mOpQueue is not empty, there must be
1045 // one op and it must be eTreeOpMarkAsBroken.
1046 if (NS_FAILED(mBroken
)) {
1047 MOZ_ASSERT(mOpQueue
.Length() == 1,
1048 "Tree builder is broken with a non-empty op queue whose length isn't 1.");
1049 MOZ_ASSERT(mOpQueue
[0].IsMarkAsBroken(),
1050 "Tree builder is broken but the op in queue is not marked as broken.");
1052 mOpSink
->MoveOpsFrom(mOpQueue
);
1056 // no op sink: throw away ops
1062 nsHtml5TreeBuilder::FlushLoads()
1064 if (MOZ_UNLIKELY(mBuilder
)) {
1065 MOZ_ASSERT_UNREACHABLE("Must never flush loads with builder.");
1068 if (!mSpeculativeLoadQueue
.IsEmpty()) {
1069 mSpeculativeLoadStage
->MoveSpeculativeLoadsFrom(mSpeculativeLoadQueue
);
1074 nsHtml5TreeBuilder::SetDocumentCharset(nsACString
& aCharset
,
1075 int32_t aCharsetSource
)
1078 mBuilder
->SetDocumentCharsetAndSource(aCharset
, aCharsetSource
);
1079 } else if (mSpeculativeLoadStage
) {
1080 mSpeculativeLoadQueue
.AppendElement()->InitSetDocumentCharset(
1081 aCharset
, aCharsetSource
);
1083 mOpQueue
.AppendElement()->Init(
1084 eTreeOpSetDocumentCharset
, aCharset
, aCharsetSource
);
1089 nsHtml5TreeBuilder::StreamEnded()
1091 MOZ_ASSERT(!mBuilder
, "Must not call StreamEnded with builder.");
1092 MOZ_ASSERT(!fragment
, "Must not parse fragments off the main thread.");
1093 nsHtml5TreeOperation
* treeOp
= mOpQueue
.AppendElement();
1094 NS_ASSERTION(treeOp
, "Tree op allocation failed.");
1095 treeOp
->Init(eTreeOpStreamEnded
);
1099 nsHtml5TreeBuilder::NeedsCharsetSwitchTo(const nsACString
& aCharset
,
1100 int32_t aCharsetSource
,
1101 int32_t aLineNumber
)
1103 if (MOZ_UNLIKELY(mBuilder
)) {
1104 MOZ_ASSERT_UNREACHABLE("Must never switch charset with builder.");
1107 nsHtml5TreeOperation
* treeOp
= mOpQueue
.AppendElement();
1108 NS_ASSERTION(treeOp
, "Tree op allocation failed.");
1109 treeOp
->Init(eTreeOpNeedsCharsetSwitchTo
,
1116 nsHtml5TreeBuilder::MaybeComplainAboutCharset(const char* aMsgId
,
1118 int32_t aLineNumber
)
1120 if (MOZ_UNLIKELY(mBuilder
)) {
1121 MOZ_ASSERT_UNREACHABLE("Must never complain about charset with builder.");
1124 mOpQueue
.AppendElement()->Init(aMsgId
, aError
, aLineNumber
);
1128 nsHtml5TreeBuilder::AddSnapshotToScript(nsAHtml5TreeBuilderState
* aSnapshot
, int32_t aLine
)
1130 if (MOZ_UNLIKELY(mBuilder
)) {
1131 MOZ_ASSERT_UNREACHABLE("Must never use snapshots with builder.");
1134 NS_PRECONDITION(HasScript(), "No script to add a snapshot to!");
1135 NS_PRECONDITION(aSnapshot
, "Got null snapshot.");
1136 mOpQueue
.ElementAt(mOpQueue
.Length() - 1).SetSnapshot(aSnapshot
, aLine
);
1140 nsHtml5TreeBuilder::DropHandles()
1142 MOZ_ASSERT(!mBuilder
, "Must not drop handles with builder.");
1143 mOldHandles
.Clear();
1148 nsHtml5TreeBuilder::MarkAsBroken(nsresult aRv
)
1150 if (MOZ_UNLIKELY(mBuilder
)) {
1151 MOZ_ASSERT_UNREACHABLE("Must not call this with builder.");
1155 mOpQueue
.Clear(); // Previous ops don't matter anymore
1156 mOpQueue
.AppendElement()->Init(aRv
);
1160 nsHtml5TreeBuilder::MarkAsBrokenFromPortability(nsresult aRv
)
1163 MarkAsBrokenAndRequestSuspension(aRv
);
1167 requestSuspension();
1171 nsHtml5TreeBuilder::StartPlainTextViewSource(const nsAutoString
& aTitle
)
1173 MOZ_ASSERT(!mBuilder
, "Must not view source with builder.");
1174 startTag(nsHtml5ElementName::ELT_TITLE
,
1175 nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES
,
1178 // XUL will add the "Source of: " prefix.
1179 uint32_t length
= aTitle
.Length();
1180 if (length
> INT32_MAX
) {
1183 characters(aTitle
.get(), 0, (int32_t)length
);
1184 endTag(nsHtml5ElementName::ELT_TITLE
);
1186 startTag(nsHtml5ElementName::ELT_LINK
,
1187 nsHtml5ViewSourceUtils::NewLinkAttributes(),
1190 startTag(nsHtml5ElementName::ELT_BODY
,
1191 nsHtml5ViewSourceUtils::NewBodyAttributes(),
1194 StartPlainTextBody();
1198 nsHtml5TreeBuilder::StartPlainText()
1200 MOZ_ASSERT(!mBuilder
, "Must not view source with builder.");
1201 startTag(nsHtml5ElementName::ELT_LINK
,
1202 nsHtml5PlainTextUtils::NewLinkAttributes(),
1205 StartPlainTextBody();
1209 nsHtml5TreeBuilder::StartPlainTextBody()
1211 MOZ_ASSERT(!mBuilder
, "Must not view source with builder.");
1212 startTag(nsHtml5ElementName::ELT_PRE
,
1213 nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES
,
1215 needToDropLF
= false;
1218 // DocumentModeHandler
1220 nsHtml5TreeBuilder::documentMode(nsHtml5DocumentMode m
)
1223 mBuilder
->SetDocumentMode(m
);
1226 nsHtml5TreeOperation
* treeOp
= mOpQueue
.AppendElement();
1227 NS_ASSERTION(treeOp
, "Tree op allocation failed.");
1232 nsHtml5TreeBuilder::getDocumentFragmentForTemplate(nsIContentHandle
* aTemplate
)
1235 return nsHtml5TreeOperation::GetDocumentFragmentForTemplate(static_cast<nsIContent
*>(aTemplate
));
1237 nsHtml5TreeOperation
* treeOp
= mOpQueue
.AppendElement();
1238 NS_ASSERTION(treeOp
, "Tree op allocation failed.");
1239 nsIContentHandle
* fragHandle
= AllocateContentHandle();
1240 treeOp
->Init(eTreeOpGetDocumentFragmentForTemplate
, aTemplate
, fragHandle
);
1245 nsHtml5TreeBuilder::getFormPointerForContext(nsIContentHandle
* aContext
)
1247 MOZ_ASSERT(mBuilder
, "Must have builder.");
1252 MOZ_ASSERT(NS_IsMainThread());
1254 // aContext must always be an element that already exists
1256 nsIContent
* contextNode
= static_cast<nsIContent
*>(aContext
);
1257 nsIContent
* currentAncestor
= contextNode
;
1259 // We traverse the ancestors of the context node to find the nearest
1260 // form pointer. This traversal is why aContext must not be an emtpy handle.
1261 nsIContent
* nearestForm
= nullptr;
1262 while (currentAncestor
) {
1263 if (currentAncestor
->IsHTMLElement(nsGkAtoms::form
)) {
1264 nearestForm
= currentAncestor
;
1267 currentAncestor
= currentAncestor
->GetParent();
1280 nsHtml5TreeBuilder::EnableViewSource(nsHtml5Highlighter
* aHighlighter
)
1282 MOZ_ASSERT(!mBuilder
, "Must not view source with builder.");
1283 mViewSource
= aHighlighter
;
1287 nsHtml5TreeBuilder::errStrayStartTag(nsIAtom
* aName
)
1289 if (MOZ_UNLIKELY(mViewSource
)) {
1290 mViewSource
->AddErrorToCurrentRun("errStrayStartTag2", aName
);
1295 nsHtml5TreeBuilder::errStrayEndTag(nsIAtom
* aName
)
1297 if (MOZ_UNLIKELY(mViewSource
)) {
1298 mViewSource
->AddErrorToCurrentRun("errStrayEndTag", aName
);
1303 nsHtml5TreeBuilder::errUnclosedElements(int32_t aIndex
, nsIAtom
* aName
)
1305 if (MOZ_UNLIKELY(mViewSource
)) {
1306 mViewSource
->AddErrorToCurrentRun("errUnclosedElements", aName
);
1311 nsHtml5TreeBuilder::errUnclosedElementsImplied(int32_t aIndex
, nsIAtom
* aName
)
1313 if (MOZ_UNLIKELY(mViewSource
)) {
1314 mViewSource
->AddErrorToCurrentRun("errUnclosedElementsImplied",
1320 nsHtml5TreeBuilder::errUnclosedElementsCell(int32_t aIndex
)
1322 if (MOZ_UNLIKELY(mViewSource
)) {
1323 mViewSource
->AddErrorToCurrentRun("errUnclosedElementsCell");
1328 nsHtml5TreeBuilder::errStrayDoctype()
1330 if (MOZ_UNLIKELY(mViewSource
)) {
1331 mViewSource
->AddErrorToCurrentRun("errStrayDoctype");
1336 nsHtml5TreeBuilder::errAlmostStandardsDoctype()
1338 if (MOZ_UNLIKELY(mViewSource
) && !isSrcdocDocument
) {
1339 mViewSource
->AddErrorToCurrentRun("errAlmostStandardsDoctype");
1344 nsHtml5TreeBuilder::errQuirkyDoctype()
1346 if (MOZ_UNLIKELY(mViewSource
) && !isSrcdocDocument
) {
1347 mViewSource
->AddErrorToCurrentRun("errQuirkyDoctype");
1352 nsHtml5TreeBuilder::errNonSpaceInTrailer()
1354 if (MOZ_UNLIKELY(mViewSource
)) {
1355 mViewSource
->AddErrorToCurrentRun("errNonSpaceInTrailer");
1360 nsHtml5TreeBuilder::errNonSpaceAfterFrameset()
1362 if (MOZ_UNLIKELY(mViewSource
)) {
1363 mViewSource
->AddErrorToCurrentRun("errNonSpaceAfterFrameset");
1368 nsHtml5TreeBuilder::errNonSpaceInFrameset()
1370 if (MOZ_UNLIKELY(mViewSource
)) {
1371 mViewSource
->AddErrorToCurrentRun("errNonSpaceInFrameset");
1376 nsHtml5TreeBuilder::errNonSpaceAfterBody()
1378 if (MOZ_UNLIKELY(mViewSource
)) {
1379 mViewSource
->AddErrorToCurrentRun("errNonSpaceAfterBody");
1384 nsHtml5TreeBuilder::errNonSpaceInColgroupInFragment()
1386 if (MOZ_UNLIKELY(mViewSource
)) {
1387 mViewSource
->AddErrorToCurrentRun("errNonSpaceInColgroupInFragment");
1392 nsHtml5TreeBuilder::errNonSpaceInNoscriptInHead()
1394 if (MOZ_UNLIKELY(mViewSource
)) {
1395 mViewSource
->AddErrorToCurrentRun("errNonSpaceInNoscriptInHead");
1400 nsHtml5TreeBuilder::errFooBetweenHeadAndBody(nsIAtom
* aName
)
1402 if (MOZ_UNLIKELY(mViewSource
)) {
1403 mViewSource
->AddErrorToCurrentRun("errFooBetweenHeadAndBody", aName
);
1408 nsHtml5TreeBuilder::errStartTagWithoutDoctype()
1410 if (MOZ_UNLIKELY(mViewSource
) && !isSrcdocDocument
) {
1411 mViewSource
->AddErrorToCurrentRun("errStartTagWithoutDoctype");
1416 nsHtml5TreeBuilder::errNoSelectInTableScope()
1418 if (MOZ_UNLIKELY(mViewSource
)) {
1419 mViewSource
->AddErrorToCurrentRun("errNoSelectInTableScope");
1424 nsHtml5TreeBuilder::errStartSelectWhereEndSelectExpected()
1426 if (MOZ_UNLIKELY(mViewSource
)) {
1427 mViewSource
->AddErrorToCurrentRun(
1428 "errStartSelectWhereEndSelectExpected");
1433 nsHtml5TreeBuilder::errStartTagWithSelectOpen(nsIAtom
* aName
)
1435 if (MOZ_UNLIKELY(mViewSource
)) {
1436 mViewSource
->AddErrorToCurrentRun("errStartTagWithSelectOpen", aName
);
1441 nsHtml5TreeBuilder::errBadStartTagInHead(nsIAtom
* aName
)
1443 if (MOZ_UNLIKELY(mViewSource
)) {
1444 mViewSource
->AddErrorToCurrentRun("errBadStartTagInHead2", aName
);
1449 nsHtml5TreeBuilder::errImage()
1451 if (MOZ_UNLIKELY(mViewSource
)) {
1452 mViewSource
->AddErrorToCurrentRun("errImage");
1457 nsHtml5TreeBuilder::errIsindex()
1459 if (MOZ_UNLIKELY(mViewSource
)) {
1460 mViewSource
->AddErrorToCurrentRun("errIsindex");
1465 nsHtml5TreeBuilder::errFooSeenWhenFooOpen(nsIAtom
* aName
)
1467 if (MOZ_UNLIKELY(mViewSource
)) {
1468 mViewSource
->AddErrorToCurrentRun("errFooSeenWhenFooOpen", aName
);
1473 nsHtml5TreeBuilder::errHeadingWhenHeadingOpen()
1475 if (MOZ_UNLIKELY(mViewSource
)) {
1476 mViewSource
->AddErrorToCurrentRun("errHeadingWhenHeadingOpen");
1481 nsHtml5TreeBuilder::errFramesetStart()
1483 if (MOZ_UNLIKELY(mViewSource
)) {
1484 mViewSource
->AddErrorToCurrentRun("errFramesetStart");
1489 nsHtml5TreeBuilder::errNoCellToClose()
1491 if (MOZ_UNLIKELY(mViewSource
)) {
1492 mViewSource
->AddErrorToCurrentRun("errNoCellToClose");
1497 nsHtml5TreeBuilder::errStartTagInTable(nsIAtom
* aName
)
1499 if (MOZ_UNLIKELY(mViewSource
)) {
1500 mViewSource
->AddErrorToCurrentRun("errStartTagInTable", aName
);
1505 nsHtml5TreeBuilder::errFormWhenFormOpen()
1507 if (MOZ_UNLIKELY(mViewSource
)) {
1508 mViewSource
->AddErrorToCurrentRun("errFormWhenFormOpen");
1513 nsHtml5TreeBuilder::errTableSeenWhileTableOpen()
1515 if (MOZ_UNLIKELY(mViewSource
)) {
1516 mViewSource
->AddErrorToCurrentRun("errTableSeenWhileTableOpen");
1521 nsHtml5TreeBuilder::errStartTagInTableBody(nsIAtom
* aName
)
1523 if (MOZ_UNLIKELY(mViewSource
)) {
1524 mViewSource
->AddErrorToCurrentRun("errStartTagInTableBody", aName
);
1529 nsHtml5TreeBuilder::errEndTagSeenWithoutDoctype()
1531 if (MOZ_UNLIKELY(mViewSource
) && !isSrcdocDocument
) {
1532 mViewSource
->AddErrorToCurrentRun("errEndTagSeenWithoutDoctype");
1537 nsHtml5TreeBuilder::errEndTagAfterBody()
1539 if (MOZ_UNLIKELY(mViewSource
)) {
1540 mViewSource
->AddErrorToCurrentRun("errEndTagAfterBody");
1545 nsHtml5TreeBuilder::errEndTagSeenWithSelectOpen(nsIAtom
* aName
)
1547 if (MOZ_UNLIKELY(mViewSource
)) {
1548 mViewSource
->AddErrorToCurrentRun("errEndTagSeenWithSelectOpen",
1554 nsHtml5TreeBuilder::errGarbageInColgroup()
1556 if (MOZ_UNLIKELY(mViewSource
)) {
1557 mViewSource
->AddErrorToCurrentRun("errGarbageInColgroup");
1562 nsHtml5TreeBuilder::errEndTagBr()
1564 if (MOZ_UNLIKELY(mViewSource
)) {
1565 mViewSource
->AddErrorToCurrentRun("errEndTagBr");
1570 nsHtml5TreeBuilder::errNoElementToCloseButEndTagSeen(nsIAtom
* aName
)
1572 if (MOZ_UNLIKELY(mViewSource
)) {
1573 mViewSource
->AddErrorToCurrentRun(
1574 "errNoElementToCloseButEndTagSeen", aName
);
1579 nsHtml5TreeBuilder::errHtmlStartTagInForeignContext(nsIAtom
* aName
)
1581 if (MOZ_UNLIKELY(mViewSource
)) {
1582 mViewSource
->AddErrorToCurrentRun("errHtmlStartTagInForeignContext",
1588 nsHtml5TreeBuilder::errTableClosedWhileCaptionOpen()
1590 if (MOZ_UNLIKELY(mViewSource
)) {
1591 mViewSource
->AddErrorToCurrentRun("errTableClosedWhileCaptionOpen");
1596 nsHtml5TreeBuilder::errNoTableRowToClose()
1598 if (MOZ_UNLIKELY(mViewSource
)) {
1599 mViewSource
->AddErrorToCurrentRun("errNoTableRowToClose");
1604 nsHtml5TreeBuilder::errNonSpaceInTable()
1606 if (MOZ_UNLIKELY(mViewSource
)) {
1607 mViewSource
->AddErrorToCurrentRun("errNonSpaceInTable");
1612 nsHtml5TreeBuilder::errUnclosedChildrenInRuby()
1614 if (MOZ_UNLIKELY(mViewSource
)) {
1615 mViewSource
->AddErrorToCurrentRun("errUnclosedChildrenInRuby");
1620 nsHtml5TreeBuilder::errStartTagSeenWithoutRuby(nsIAtom
* aName
)
1622 if (MOZ_UNLIKELY(mViewSource
)) {
1623 mViewSource
->AddErrorToCurrentRun("errStartTagSeenWithoutRuby",
1629 nsHtml5TreeBuilder::errSelfClosing()
1631 if (MOZ_UNLIKELY(mViewSource
)) {
1632 mViewSource
->AddErrorToCurrentSlash("errSelfClosing");
1637 nsHtml5TreeBuilder::errNoCheckUnclosedElementsOnStack()
1639 if (MOZ_UNLIKELY(mViewSource
)) {
1640 mViewSource
->AddErrorToCurrentRun(
1641 "errNoCheckUnclosedElementsOnStack");
1646 nsHtml5TreeBuilder::errEndTagDidNotMatchCurrentOpenElement(nsIAtom
* aName
,
1649 if (MOZ_UNLIKELY(mViewSource
)) {
1650 mViewSource
->AddErrorToCurrentRun(
1651 "errEndTagDidNotMatchCurrentOpenElement", aName
, aOther
);
1656 nsHtml5TreeBuilder::errEndTagViolatesNestingRules(nsIAtom
* aName
)
1658 if (MOZ_UNLIKELY(mViewSource
)) {
1659 mViewSource
->AddErrorToCurrentRun("errEndTagViolatesNestingRules", aName
);
1664 nsHtml5TreeBuilder::errEndWithUnclosedElements(nsIAtom
* aName
)
1666 if (MOZ_UNLIKELY(mViewSource
)) {
1667 mViewSource
->AddErrorToCurrentRun("errEndWithUnclosedElements", aName
);