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/. */
7 #include "nsHtml5TreeOperation.h"
8 #include "mozAutoDocUpdate.h"
9 #include "mozilla/CycleCollectedJSContext.h"
10 #include "mozilla/Likely.h"
11 #include "mozilla/dom/Comment.h"
12 #include "mozilla/dom/CustomElementRegistry.h"
13 #include "mozilla/dom/DocGroup.h"
14 #include "mozilla/dom/DocumentFragment.h"
15 #include "mozilla/dom/DocumentType.h"
16 #include "mozilla/dom/Element.h"
17 #include "mozilla/dom/LinkStyle.h"
18 #include "mozilla/dom/HTMLFormElement.h"
19 #include "mozilla/dom/HTMLImageElement.h"
20 #include "mozilla/dom/HTMLTemplateElement.h"
21 #include "mozilla/dom/MutationObservers.h"
22 #include "mozilla/dom/ShadowRoot.h"
23 #include "mozilla/dom/Text.h"
24 #include "nsAttrName.h"
25 #include "nsContentCreatorFunctions.h"
26 #include "nsContentUtils.h"
27 #include "nsDocElementCreatedNotificationRunner.h"
29 #include "nsGenericHTMLElement.h"
30 #include "nsHtml5AutoPauseUpdate.h"
31 #include "nsHtml5DocumentMode.h"
32 #include "nsHtml5HtmlAttributes.h"
33 #include "nsHtml5SVGLoadDispatcher.h"
34 #include "nsHtml5TreeBuilder.h"
36 #include "nsIFormControl.h"
37 #include "nsIMutationObserver.h"
39 #include "nsIProtocolHandler.h"
40 #include "nsIScriptElement.h"
41 #include "nsISupportsImpl.h"
43 #include "nsNetUtil.h"
44 #include "nsTextNode.h"
45 #include "js/ColumnNumber.h" // JS::ColumnNumberOneOrigin
47 using namespace mozilla
;
48 using namespace mozilla::dom
;
51 * Helper class that opens a notification batch if the current doc
52 * is different from the executor doc.
54 class MOZ_STACK_CLASS nsHtml5OtherDocUpdate
{
56 nsHtml5OtherDocUpdate(Document
* aCurrentDoc
, Document
* aExecutorDoc
) {
57 MOZ_ASSERT(aCurrentDoc
, "Node has no doc?");
58 MOZ_ASSERT(aExecutorDoc
, "Executor has no doc?");
59 if (MOZ_LIKELY(aCurrentDoc
== aExecutorDoc
)) {
62 mDocument
= aCurrentDoc
;
63 aCurrentDoc
->BeginUpdate();
67 ~nsHtml5OtherDocUpdate() {
68 if (MOZ_UNLIKELY(mDocument
)) {
69 mDocument
->EndUpdate();
74 RefPtr
<Document
> mDocument
;
77 nsHtml5TreeOperation::nsHtml5TreeOperation() : mOperation(uninitialized()) {
78 MOZ_COUNT_CTOR(nsHtml5TreeOperation
);
81 nsHtml5TreeOperation::~nsHtml5TreeOperation() {
82 MOZ_COUNT_DTOR(nsHtml5TreeOperation
);
84 struct TreeOperationMatcher
{
85 void operator()(const opAppend
& aOperation
) {}
87 void operator()(const opDetach
& aOperation
) {}
89 void operator()(const opAppendChildrenToNewParent
& aOperation
) {}
91 void operator()(const opFosterParent
& aOperation
) {}
93 void operator()(const opAppendToDocument
& aOperation
) {}
95 void operator()(const opAddAttributes
& aOperation
) {
96 delete aOperation
.mAttributes
;
99 void operator()(const nsHtml5DocumentMode
& aMode
) {}
101 void operator()(const opCreateHTMLElement
& aOperation
) {
102 aOperation
.mName
->Release();
103 delete aOperation
.mAttributes
;
106 void operator()(const opCreateSVGElement
& aOperation
) {
107 aOperation
.mName
->Release();
108 delete aOperation
.mAttributes
;
111 void operator()(const opCreateMathMLElement
& aOperation
) {
112 aOperation
.mName
->Release();
113 delete aOperation
.mAttributes
;
116 void operator()(const opSetFormElement
& aOperation
) {}
118 void operator()(const opAppendText
& aOperation
) {
119 delete[] aOperation
.mBuffer
;
122 void operator()(const opFosterParentText
& aOperation
) {
123 delete[] aOperation
.mBuffer
;
126 void operator()(const opAppendComment
& aOperation
) {
127 delete[] aOperation
.mBuffer
;
130 void operator()(const opAppendCommentToDocument
& aOperation
) {
131 delete[] aOperation
.mBuffer
;
134 void operator()(const opAppendDoctypeToDocument
& aOperation
) {
135 aOperation
.mName
->Release();
136 delete aOperation
.mStringPair
;
139 void operator()(const opGetDocumentFragmentForTemplate
& aOperation
) {}
141 void operator()(const opSetDocumentFragmentForTemplate
& aOperation
) {}
143 void operator()(const opGetShadowRootFromHost
& aOperation
) {}
145 void operator()(const opGetFosterParent
& aOperation
) {}
147 void operator()(const opMarkAsBroken
& aOperation
) {}
149 void operator()(const opRunScriptThatMayDocumentWriteOrBlock
& aOperation
) {}
152 const opRunScriptThatCannotDocumentWriteOrBlock
& aOperation
) {}
154 void operator()(const opPreventScriptExecution
& aOperation
) {}
156 void operator()(const opDoneAddingChildren
& aOperation
) {}
158 void operator()(const opDoneCreatingElement
& aOperation
) {}
160 void operator()(const opUpdateCharsetSource
& aOperation
) {}
162 void operator()(const opCharsetSwitchTo
& aOperation
) {}
164 void operator()(const opUpdateStyleSheet
& aOperation
) {}
166 void operator()(const opProcessOfflineManifest
& aOperation
) {
167 free(aOperation
.mUrl
);
170 void operator()(const opMarkMalformedIfScript
& aOperation
) {}
172 void operator()(const opStreamEnded
& aOperation
) {}
174 void operator()(const opSetStyleLineNumber
& aOperation
) {}
176 void operator()(const opSetScriptLineAndColumnNumberAndFreeze
& aOperation
) {
179 void operator()(const opSvgLoad
& aOperation
) {}
181 void operator()(const opMaybeComplainAboutCharset
& aOperation
) {}
183 void operator()(const opMaybeComplainAboutDeepTree
& aOperation
) {}
185 void operator()(const opAddClass
& aOperation
) {}
187 void operator()(const opAddViewSourceHref
& aOperation
) {
188 delete[] aOperation
.mBuffer
;
191 void operator()(const opAddViewSourceBase
& aOperation
) {
192 delete[] aOperation
.mBuffer
;
195 void operator()(const opAddErrorType
& aOperation
) {
196 if (aOperation
.mName
) {
197 aOperation
.mName
->Release();
199 if (aOperation
.mOther
) {
200 aOperation
.mOther
->Release();
204 void operator()(const opAddLineNumberId
& aOperation
) {}
206 void operator()(const opShallowCloneInto
& aOperation
) {}
208 void operator()(const opStartLayout
& aOperation
) {}
210 void operator()(const opEnableEncodingMenu
& aOperation
) {}
212 void operator()(const uninitialized
& aOperation
) {
213 NS_WARNING("Uninitialized tree op.");
217 mOperation
.match(TreeOperationMatcher());
220 nsresult
nsHtml5TreeOperation::AppendTextToTextNode(
221 const char16_t
* aBuffer
, uint32_t aLength
, Text
* aTextNode
,
222 nsHtml5DocumentBuilder
* aBuilder
) {
223 MOZ_ASSERT(aTextNode
, "Got null text node.");
224 MOZ_ASSERT(aBuilder
);
225 MOZ_ASSERT(aBuilder
->IsInDocUpdate());
226 uint32_t oldLength
= aTextNode
->TextLength();
227 CharacterDataChangeInfo info
= {true, oldLength
, oldLength
, aLength
};
228 MutationObservers::NotifyCharacterDataWillChange(aTextNode
, info
);
230 nsresult rv
= aTextNode
->AppendText(aBuffer
, aLength
, false);
231 NS_ENSURE_SUCCESS(rv
, rv
);
233 MutationObservers::NotifyCharacterDataChanged(aTextNode
, info
);
237 nsresult
nsHtml5TreeOperation::AppendText(const char16_t
* aBuffer
,
238 uint32_t aLength
, nsIContent
* aParent
,
239 nsHtml5DocumentBuilder
* aBuilder
) {
241 nsIContent
* lastChild
= aParent
->GetLastChild();
242 if (lastChild
&& lastChild
->IsText()) {
243 nsHtml5OtherDocUpdate
update(aParent
->OwnerDoc(), aBuilder
->GetDocument());
244 return AppendTextToTextNode(aBuffer
, aLength
, lastChild
->GetAsText(),
248 nsNodeInfoManager
* nodeInfoManager
= aParent
->OwnerDoc()->NodeInfoManager();
249 RefPtr
<nsTextNode
> text
= new (nodeInfoManager
) nsTextNode(nodeInfoManager
);
250 NS_ASSERTION(text
, "Infallible malloc failed?");
251 rv
= text
->SetText(aBuffer
, aLength
, false);
252 NS_ENSURE_SUCCESS(rv
, rv
);
254 return Append(text
, aParent
, aBuilder
);
257 nsresult
nsHtml5TreeOperation::Append(nsIContent
* aNode
, nsIContent
* aParent
,
258 nsHtml5DocumentBuilder
* aBuilder
) {
259 MOZ_ASSERT(aBuilder
);
260 MOZ_ASSERT(aBuilder
->IsInDocUpdate());
262 Document
* ownerDoc
= aParent
->OwnerDoc();
263 nsHtml5OtherDocUpdate
update(ownerDoc
, aBuilder
->GetDocument());
264 aParent
->AppendChildTo(aNode
, false, rv
);
265 if (!rv
.Failed() && !ownerDoc
->DOMNotificationsSuspended()) {
266 aNode
->SetParserHasNotified();
267 MutationObservers::NotifyContentAppended(aParent
, aNode
);
269 return rv
.StealNSResult();
272 nsresult
nsHtml5TreeOperation::Append(nsIContent
* aNode
, nsIContent
* aParent
,
273 FromParser aFromParser
,
274 nsHtml5DocumentBuilder
* aBuilder
) {
275 Maybe
<nsHtml5AutoPauseUpdate
> autoPause
;
276 Maybe
<AutoCEReaction
> autoCEReaction
;
277 DocGroup
* docGroup
= aParent
->OwnerDoc()->GetDocGroup();
278 if (docGroup
&& aFromParser
!= FROM_PARSER_FRAGMENT
) {
279 autoCEReaction
.emplace(docGroup
->CustomElementReactionsStack(), nullptr);
281 nsresult rv
= Append(aNode
, aParent
, aBuilder
);
282 // Pause the parser only when there are reactions to be invoked to avoid
283 // pausing parsing too aggressive.
284 if (autoCEReaction
.isSome() && docGroup
&&
285 docGroup
->CustomElementReactionsStack()
286 ->IsElementQueuePushedForCurrentRecursionDepth()) {
287 autoPause
.emplace(aBuilder
);
292 nsresult
nsHtml5TreeOperation::AppendToDocument(
293 nsIContent
* aNode
, nsHtml5DocumentBuilder
* aBuilder
) {
294 MOZ_ASSERT(aBuilder
);
295 MOZ_ASSERT(aBuilder
->GetDocument() == aNode
->OwnerDoc());
296 MOZ_ASSERT(aBuilder
->IsInDocUpdate());
299 Document
* doc
= aBuilder
->GetDocument();
300 doc
->AppendChildTo(aNode
, false, rv
);
301 if (rv
.ErrorCodeIs(NS_ERROR_DOM_HIERARCHY_REQUEST_ERR
)) {
302 aNode
->SetParserHasNotified();
306 return rv
.StealNSResult();
309 if (!doc
->DOMNotificationsSuspended()) {
310 aNode
->SetParserHasNotified();
311 MutationObservers::NotifyContentInserted(doc
, aNode
);
314 NS_ASSERTION(!nsContentUtils::IsSafeToRunScript(),
315 "Someone forgot to block scripts");
316 if (aNode
->IsElement()) {
317 nsContentUtils::AddScriptRunner(
318 new nsDocElementCreatedNotificationRunner(doc
));
323 static bool IsElementOrTemplateContent(nsINode
* aNode
) {
325 if (aNode
->IsElement()) {
328 if (aNode
->IsDocumentFragment()) {
329 // Check if the node is a template content.
330 nsIContent
* fragHost
= aNode
->AsDocumentFragment()->GetHost();
331 if (fragHost
&& fragHost
->IsTemplateElement()) {
339 void nsHtml5TreeOperation::Detach(nsIContent
* aNode
,
340 nsHtml5DocumentBuilder
* aBuilder
) {
341 MOZ_ASSERT(aBuilder
);
342 MOZ_ASSERT(aBuilder
->IsInDocUpdate());
343 nsCOMPtr
<nsINode
> parent
= aNode
->GetParentNode();
345 nsHtml5OtherDocUpdate
update(parent
->OwnerDoc(), aBuilder
->GetDocument());
346 parent
->RemoveChildNode(aNode
, true);
350 nsresult
nsHtml5TreeOperation::AppendChildrenToNewParent(
351 nsIContent
* aNode
, nsIContent
* aParent
, nsHtml5DocumentBuilder
* aBuilder
) {
352 MOZ_ASSERT(aBuilder
);
353 MOZ_ASSERT(aBuilder
->IsInDocUpdate());
354 nsHtml5OtherDocUpdate
update(aParent
->OwnerDoc(), aBuilder
->GetDocument());
356 bool didAppend
= false;
357 while (aNode
->HasChildren()) {
358 nsCOMPtr
<nsIContent
> child
= aNode
->GetFirstChild();
359 aNode
->RemoveChildNode(child
, true);
362 aParent
->AppendChildTo(child
, false, rv
);
364 return rv
.StealNSResult();
369 MutationObservers::NotifyContentAppended(aParent
, aParent
->GetLastChild());
374 nsresult
nsHtml5TreeOperation::FosterParent(nsIContent
* aNode
,
377 nsHtml5DocumentBuilder
* aBuilder
) {
378 MOZ_ASSERT(aBuilder
);
379 MOZ_ASSERT(aBuilder
->IsInDocUpdate());
380 nsIContent
* foster
= aTable
->GetParent();
382 if (IsElementOrTemplateContent(foster
)) {
383 nsHtml5OtherDocUpdate
update(foster
->OwnerDoc(), aBuilder
->GetDocument());
386 foster
->InsertChildBefore(aNode
, aTable
, false, rv
);
388 return rv
.StealNSResult();
391 MutationObservers::NotifyContentInserted(foster
, aNode
);
395 return Append(aNode
, aParent
, aBuilder
);
398 nsresult
nsHtml5TreeOperation::AddAttributes(nsIContent
* aNode
,
399 nsHtml5HtmlAttributes
* aAttributes
,
400 nsHtml5DocumentBuilder
* aBuilder
) {
401 MOZ_ASSERT(aNode
->IsAnyOfHTMLElements(nsGkAtoms::body
, nsGkAtoms::html
));
403 Element
* node
= aNode
->AsElement();
404 nsHtml5OtherDocUpdate
update(node
->OwnerDoc(), aBuilder
->GetDocument());
406 int32_t len
= aAttributes
->getLength();
407 for (int32_t i
= len
; i
> 0;) {
409 nsAtom
* localName
= aAttributes
->getLocalNameNoBoundsCheck(i
);
410 int32_t nsuri
= aAttributes
->getURINoBoundsCheck(i
);
411 if (!node
->HasAttr(nsuri
, localName
) &&
412 !(nsuri
== kNameSpaceID_None
&& localName
== nsGkAtoms::nonce
)) {
413 nsString value
; // Not Auto, because using it to hold nsStringBuffer*
414 aAttributes
->getValueNoBoundsCheck(i
).ToString(value
);
415 node
->SetAttr(nsuri
, localName
, aAttributes
->getPrefixNoBoundsCheck(i
),
417 // XXX what to do with nsresult?
423 void nsHtml5TreeOperation::SetHTMLElementAttributes(
424 Element
* aElement
, nsAtom
* aName
, nsHtml5HtmlAttributes
* aAttributes
) {
425 int32_t len
= aAttributes
->getLength();
426 aElement
->TryReserveAttributeCount((uint32_t)len
);
427 if (aAttributes
->getDuplicateAttributeError()) {
428 aElement
->SetParserHadDuplicateAttributeError();
430 for (int32_t i
= 0; i
< len
; i
++) {
431 nsHtml5String val
= aAttributes
->getValueNoBoundsCheck(i
);
432 nsAtom
* klass
= val
.MaybeAsAtom();
434 aElement
->SetClassAttrFromParser(klass
);
436 nsAtom
* localName
= aAttributes
->getLocalNameNoBoundsCheck(i
);
437 nsAtom
* prefix
= aAttributes
->getPrefixNoBoundsCheck(i
);
438 int32_t nsuri
= aAttributes
->getURINoBoundsCheck(i
);
439 nsString value
; // Not Auto, because using it to hold nsStringBuffer*
441 aElement
->SetAttr(nsuri
, localName
, prefix
, value
, false);
446 nsIContent
* nsHtml5TreeOperation::CreateHTMLElement(
447 nsAtom
* aName
, nsHtml5HtmlAttributes
* aAttributes
, FromParser aFromParser
,
448 nsNodeInfoManager
* aNodeInfoManager
, nsHtml5DocumentBuilder
* aBuilder
,
449 HTMLContentCreatorFunction aCreator
) {
450 RefPtr
<NodeInfo
> nodeInfo
= aNodeInfoManager
->GetNodeInfo(
451 aName
, nullptr, kNameSpaceID_XHTML
, nsINode::ELEMENT_NODE
);
452 NS_ASSERTION(nodeInfo
, "Got null nodeinfo.");
454 Document
* document
= nodeInfo
->GetDocument();
455 RefPtr
<nsAtom
> isAtom
;
457 nsHtml5String is
= aAttributes
->getValue(nsHtml5AttributeName::ATTR_IS
);
459 nsAutoString isValue
;
460 is
.ToString(isValue
);
461 isAtom
= NS_Atomize(isValue
);
465 const bool isCustomElement
= aCreator
== NS_NewCustomElement
|| isAtom
;
466 CustomElementDefinition
* customElementDefinition
= nullptr;
467 if (isCustomElement
&& aFromParser
!= FROM_PARSER_FRAGMENT
) {
468 RefPtr
<nsAtom
> tagAtom
= nodeInfo
->NameAtom();
469 RefPtr
<nsAtom
> typeAtom
=
470 aCreator
== NS_NewCustomElement
? tagAtom
: isAtom
;
472 MOZ_ASSERT(nodeInfo
->NameAtom()->Equals(nodeInfo
->LocalName()));
473 customElementDefinition
= nsContentUtils::LookupCustomElementDefinition(
474 document
, nodeInfo
->NameAtom(), nodeInfo
->NamespaceID(), typeAtom
);
477 auto DoCreateElement
= [&](HTMLContentCreatorFunction aCreator
) -> Element
* {
478 nsCOMPtr
<Element
> newElement
;
480 newElement
= aCreator(nodeInfo
.forget(), aFromParser
);
482 NS_NewHTMLElement(getter_AddRefs(newElement
), nodeInfo
.forget(),
483 aFromParser
, isAtom
, customElementDefinition
);
486 MOZ_ASSERT(newElement
, "Element creation created null pointer.");
487 Element
* element
= newElement
.get();
488 aBuilder
->HoldElement(newElement
.forget());
490 if (auto* linkStyle
= LinkStyle::FromNode(*element
)) {
491 linkStyle
->DisableUpdates();
498 SetHTMLElementAttributes(element
, aName
, aAttributes
);
502 if (customElementDefinition
) {
503 // This will cause custom element constructors to run.
504 AutoSetThrowOnDynamicMarkupInsertionCounter
505 throwOnDynamicMarkupInsertionCounter(document
);
506 nsHtml5AutoPauseUpdate
autoPauseContentUpdate(aBuilder
);
507 { nsAutoMicroTask mt
; }
508 AutoCEReaction
autoCEReaction(
509 document
->GetDocGroup()->CustomElementReactionsStack(), nullptr);
510 return DoCreateElement(nullptr);
512 return DoCreateElement(isCustomElement
? nullptr : aCreator
);
515 nsIContent
* nsHtml5TreeOperation::CreateSVGElement(
516 nsAtom
* aName
, nsHtml5HtmlAttributes
* aAttributes
, FromParser aFromParser
,
517 nsNodeInfoManager
* aNodeInfoManager
, nsHtml5DocumentBuilder
* aBuilder
,
518 SVGContentCreatorFunction aCreator
) {
519 nsCOMPtr
<nsIContent
> newElement
;
520 if (MOZ_LIKELY(aNodeInfoManager
->SVGEnabled())) {
521 RefPtr
<NodeInfo
> nodeInfo
= aNodeInfoManager
->GetNodeInfo(
522 aName
, nullptr, kNameSpaceID_SVG
, nsINode::ELEMENT_NODE
);
523 MOZ_ASSERT(nodeInfo
, "Got null nodeinfo.");
525 DebugOnly
<nsresult
> rv
=
526 aCreator(getter_AddRefs(newElement
), nodeInfo
.forget(), aFromParser
);
527 MOZ_ASSERT(NS_SUCCEEDED(rv
) && newElement
);
529 RefPtr
<NodeInfo
> nodeInfo
= aNodeInfoManager
->GetNodeInfo(
530 aName
, nullptr, kNameSpaceID_disabled_SVG
, nsINode::ELEMENT_NODE
);
531 MOZ_ASSERT(nodeInfo
, "Got null nodeinfo.");
533 // The mismatch between NS_NewXMLElement and SVGContentCreatorFunction
534 // argument types is annoying.
535 nsCOMPtr
<Element
> xmlElement
;
536 DebugOnly
<nsresult
> rv
=
537 NS_NewXMLElement(getter_AddRefs(xmlElement
), nodeInfo
.forget());
538 MOZ_ASSERT(NS_SUCCEEDED(rv
) && xmlElement
);
539 newElement
= xmlElement
;
542 Element
* newContent
= newElement
->AsElement();
543 aBuilder
->HoldElement(newElement
.forget());
545 if (MOZ_UNLIKELY(aName
== nsGkAtoms::style
)) {
546 if (auto* linkStyle
= LinkStyle::FromNode(*newContent
)) {
547 linkStyle
->DisableUpdates();
555 if (aAttributes
->getDuplicateAttributeError()) {
556 newContent
->SetParserHadDuplicateAttributeError();
559 int32_t len
= aAttributes
->getLength();
560 for (int32_t i
= 0; i
< len
; i
++) {
561 nsHtml5String val
= aAttributes
->getValueNoBoundsCheck(i
);
562 nsAtom
* klass
= val
.MaybeAsAtom();
564 newContent
->SetClassAttrFromParser(klass
);
566 nsAtom
* localName
= aAttributes
->getLocalNameNoBoundsCheck(i
);
567 nsAtom
* prefix
= aAttributes
->getPrefixNoBoundsCheck(i
);
568 int32_t nsuri
= aAttributes
->getURINoBoundsCheck(i
);
570 nsString value
; // Not Auto, because using it to hold nsStringBuffer*
572 newContent
->SetAttr(nsuri
, localName
, prefix
, value
, false);
578 nsIContent
* nsHtml5TreeOperation::CreateMathMLElement(
579 nsAtom
* aName
, nsHtml5HtmlAttributes
* aAttributes
,
580 nsNodeInfoManager
* aNodeInfoManager
, nsHtml5DocumentBuilder
* aBuilder
) {
581 nsCOMPtr
<Element
> newElement
;
582 if (MOZ_LIKELY(aNodeInfoManager
->MathMLEnabled())) {
583 RefPtr
<NodeInfo
> nodeInfo
= aNodeInfoManager
->GetNodeInfo(
584 aName
, nullptr, kNameSpaceID_MathML
, nsINode::ELEMENT_NODE
);
585 NS_ASSERTION(nodeInfo
, "Got null nodeinfo.");
587 DebugOnly
<nsresult
> rv
=
588 NS_NewMathMLElement(getter_AddRefs(newElement
), nodeInfo
.forget());
589 MOZ_ASSERT(NS_SUCCEEDED(rv
) && newElement
);
591 RefPtr
<NodeInfo
> nodeInfo
= aNodeInfoManager
->GetNodeInfo(
592 aName
, nullptr, kNameSpaceID_disabled_MathML
, nsINode::ELEMENT_NODE
);
593 NS_ASSERTION(nodeInfo
, "Got null nodeinfo.");
595 DebugOnly
<nsresult
> rv
=
596 NS_NewXMLElement(getter_AddRefs(newElement
), nodeInfo
.forget());
597 MOZ_ASSERT(NS_SUCCEEDED(rv
) && newElement
);
600 Element
* newContent
= newElement
;
601 aBuilder
->HoldElement(newElement
.forget());
607 if (aAttributes
->getDuplicateAttributeError()) {
608 newContent
->SetParserHadDuplicateAttributeError();
611 int32_t len
= aAttributes
->getLength();
612 for (int32_t i
= 0; i
< len
; i
++) {
613 nsHtml5String val
= aAttributes
->getValueNoBoundsCheck(i
);
614 nsAtom
* klass
= val
.MaybeAsAtom();
616 newContent
->SetClassAttrFromParser(klass
);
618 nsAtom
* localName
= aAttributes
->getLocalNameNoBoundsCheck(i
);
619 nsAtom
* prefix
= aAttributes
->getPrefixNoBoundsCheck(i
);
620 int32_t nsuri
= aAttributes
->getURINoBoundsCheck(i
);
622 nsString value
; // Not Auto, because using it to hold nsStringBuffer*
624 newContent
->SetAttr(nsuri
, localName
, prefix
, value
, false);
630 void nsHtml5TreeOperation::SetFormElement(nsIContent
* aNode
, nsIContent
* aForm
,
631 nsIContent
* aParent
) {
632 RefPtr formElement
= HTMLFormElement::FromNodeOrNull(aForm
);
633 NS_ASSERTION(formElement
,
634 "The form element doesn't implement HTMLFormElement.");
635 nsCOMPtr
<nsIFormControl
> formControl
= nsIFormControl::FromNodeOrNull(aNode
);
637 formControl
->ControlType() !=
638 FormControlType::FormAssociatedCustomElement
&&
639 !aNode
->AsElement()->HasAttr(nsGkAtoms::form
) &&
640 aForm
->SubtreeRoot() == aParent
->SubtreeRoot()) {
641 formControl
->SetForm(formElement
);
642 } else if (auto* image
= HTMLImageElement::FromNodeOrNull(aNode
)) {
643 image
->SetForm(formElement
);
647 nsresult
nsHtml5TreeOperation::FosterParentText(
648 nsIContent
* aStackParent
, char16_t
* aBuffer
, uint32_t aLength
,
649 nsIContent
* aTable
, nsHtml5DocumentBuilder
* aBuilder
) {
650 MOZ_ASSERT(aBuilder
);
651 MOZ_ASSERT(aBuilder
->IsInDocUpdate());
653 nsIContent
* foster
= aTable
->GetParent();
655 if (IsElementOrTemplateContent(foster
)) {
656 nsHtml5OtherDocUpdate
update(foster
->OwnerDoc(), aBuilder
->GetDocument());
658 nsIContent
* previousSibling
= aTable
->GetPreviousSibling();
659 if (previousSibling
&& previousSibling
->IsText()) {
660 return AppendTextToTextNode(aBuffer
, aLength
,
661 previousSibling
->GetAsText(), aBuilder
);
664 nsNodeInfoManager
* nodeInfoManager
=
665 aStackParent
->OwnerDoc()->NodeInfoManager();
666 RefPtr
<nsTextNode
> text
= new (nodeInfoManager
) nsTextNode(nodeInfoManager
);
667 NS_ASSERTION(text
, "Infallible malloc failed?");
668 rv
= text
->SetText(aBuffer
, aLength
, false);
669 NS_ENSURE_SUCCESS(rv
, rv
);
672 foster
->InsertChildBefore(text
, aTable
, false, error
);
673 if (error
.Failed()) {
674 return error
.StealNSResult();
677 MutationObservers::NotifyContentInserted(foster
, text
);
681 return AppendText(aBuffer
, aLength
, aStackParent
, aBuilder
);
684 nsresult
nsHtml5TreeOperation::AppendComment(nsIContent
* aParent
,
685 char16_t
* aBuffer
, int32_t aLength
,
686 nsHtml5DocumentBuilder
* aBuilder
) {
687 nsNodeInfoManager
* nodeInfoManager
= aParent
->OwnerDoc()->NodeInfoManager();
688 RefPtr
<Comment
> comment
= new (nodeInfoManager
) Comment(nodeInfoManager
);
689 NS_ASSERTION(comment
, "Infallible malloc failed?");
690 nsresult rv
= comment
->SetText(aBuffer
, aLength
, false);
691 NS_ENSURE_SUCCESS(rv
, rv
);
693 return Append(comment
, aParent
, aBuilder
);
696 nsresult
nsHtml5TreeOperation::AppendCommentToDocument(
697 char16_t
* aBuffer
, int32_t aLength
, nsHtml5DocumentBuilder
* aBuilder
) {
698 RefPtr
<Comment
> comment
= new (aBuilder
->GetNodeInfoManager())
699 Comment(aBuilder
->GetNodeInfoManager());
700 NS_ASSERTION(comment
, "Infallible malloc failed?");
701 nsresult rv
= comment
->SetText(aBuffer
, aLength
, false);
702 NS_ENSURE_SUCCESS(rv
, rv
);
704 return AppendToDocument(comment
, aBuilder
);
707 nsresult
nsHtml5TreeOperation::AppendDoctypeToDocument(
708 nsAtom
* aName
, const nsAString
& aPublicId
, const nsAString
& aSystemId
,
709 nsHtml5DocumentBuilder
* aBuilder
) {
710 // Adapted from nsXMLContentSink
711 // Create a new doctype node
712 RefPtr
<DocumentType
> docType
=
713 NS_NewDOMDocumentType(aBuilder
->GetNodeInfoManager(), aName
, aPublicId
,
714 aSystemId
, VoidString());
715 return AppendToDocument(docType
, aBuilder
);
718 nsIContent
* nsHtml5TreeOperation::GetDocumentFragmentForTemplate(
720 auto* tempElem
= static_cast<HTMLTemplateElement
*>(aNode
);
721 return tempElem
->Content();
724 void nsHtml5TreeOperation::SetDocumentFragmentForTemplate(
725 nsIContent
* aNode
, nsIContent
* aDocumentFragment
) {
726 auto* tempElem
= static_cast<HTMLTemplateElement
*>(aNode
);
727 tempElem
->SetContent(static_cast<DocumentFragment
*>(aDocumentFragment
));
730 nsIContent
* nsHtml5TreeOperation::GetFosterParent(nsIContent
* aTable
,
731 nsIContent
* aStackParent
) {
732 nsIContent
* tableParent
= aTable
->GetParent();
733 return IsElementOrTemplateContent(tableParent
) ? tableParent
: aStackParent
;
736 void nsHtml5TreeOperation::PreventScriptExecution(nsIContent
* aNode
) {
737 nsCOMPtr
<nsIScriptElement
> sele
= do_QueryInterface(aNode
);
739 sele
->PreventExecution();
741 MOZ_ASSERT(nsNameSpaceManager::GetInstance()->mSVGDisabled
,
742 "Node didn't QI to script, but SVG wasn't disabled.");
746 void nsHtml5TreeOperation::DoneAddingChildren(nsIContent
* aNode
) {
747 aNode
->DoneAddingChildren(aNode
->HasParserNotified());
750 void nsHtml5TreeOperation::DoneCreatingElement(nsIContent
* aNode
) {
751 aNode
->DoneCreatingElement();
754 void nsHtml5TreeOperation::SvgLoad(nsIContent
* aNode
) {
755 nsCOMPtr
<nsIRunnable
> event
= new nsHtml5SVGLoadDispatcher(aNode
);
756 if (NS_FAILED(aNode
->OwnerDoc()->Dispatch(event
.forget()))) {
757 NS_WARNING("failed to dispatch svg load dispatcher");
761 void nsHtml5TreeOperation::MarkMalformedIfScript(nsIContent
* aNode
) {
762 nsCOMPtr
<nsIScriptElement
> sele
= do_QueryInterface(aNode
);
764 // Make sure to serialize this script correctly, for nice round tripping.
765 sele
->SetIsMalformed();
769 nsresult
nsHtml5TreeOperation::Perform(nsHtml5TreeOpExecutor
* aBuilder
,
770 nsIContent
** aScriptElement
,
771 bool* aInterrupted
, bool* aStreamEnded
) {
772 struct TreeOperationMatcher
{
773 TreeOperationMatcher(nsHtml5TreeOpExecutor
* aBuilder
,
774 nsIContent
** aScriptElement
, bool* aInterrupted
,
776 : mBuilder(aBuilder
),
777 mScriptElement(aScriptElement
),
778 mInterrupted(aInterrupted
),
779 mStreamEnded(aStreamEnded
) {}
781 nsHtml5TreeOpExecutor
* mBuilder
;
782 nsIContent
** mScriptElement
;
786 nsresult
operator()(const opAppend
& aOperation
) {
787 return Append(*(aOperation
.mChild
), *(aOperation
.mParent
),
788 aOperation
.mFromNetwork
, mBuilder
);
791 nsresult
operator()(const opDetach
& aOperation
) {
792 Detach(*(aOperation
.mElement
), mBuilder
);
796 nsresult
operator()(const opAppendChildrenToNewParent
& aOperation
) {
797 nsCOMPtr
<nsIContent
> node
= *(aOperation
.mOldParent
);
798 nsIContent
* parent
= *(aOperation
.mNewParent
);
799 return AppendChildrenToNewParent(node
, parent
, mBuilder
);
802 nsresult
operator()(const opFosterParent
& aOperation
) {
803 nsIContent
* node
= *(aOperation
.mChild
);
804 nsIContent
* parent
= *(aOperation
.mStackParent
);
805 nsIContent
* table
= *(aOperation
.mTable
);
806 return FosterParent(node
, parent
, table
, mBuilder
);
809 nsresult
operator()(const opAppendToDocument
& aOperation
) {
810 nsresult rv
= AppendToDocument(*(aOperation
.mContent
), mBuilder
);
811 mBuilder
->PauseDocUpdate(mInterrupted
);
815 nsresult
operator()(const opAddAttributes
& aOperation
) {
816 nsIContent
* node
= *(aOperation
.mElement
);
817 nsHtml5HtmlAttributes
* attributes
= aOperation
.mAttributes
;
818 return AddAttributes(node
, attributes
, mBuilder
);
821 nsresult
operator()(const nsHtml5DocumentMode
& aMode
) {
822 mBuilder
->SetDocumentMode(aMode
);
826 nsresult
operator()(const opCreateHTMLElement
& aOperation
) {
827 nsIContent
** target
= aOperation
.mContent
;
828 HTMLContentCreatorFunction creator
= aOperation
.mCreator
;
829 nsAtom
* name
= aOperation
.mName
;
830 nsHtml5HtmlAttributes
* attributes
= aOperation
.mAttributes
;
831 nsIContent
* intendedParent
=
832 aOperation
.mIntendedParent
? *(aOperation
.mIntendedParent
) : nullptr;
834 // intendedParent == nullptr is a special case where the
835 // intended parent is the document.
836 nsNodeInfoManager
* nodeInfoManager
=
837 intendedParent
? intendedParent
->OwnerDoc()->NodeInfoManager()
838 : mBuilder
->GetNodeInfoManager();
840 *target
= CreateHTMLElement(name
, attributes
, aOperation
.mFromNetwork
,
841 nodeInfoManager
, mBuilder
, creator
);
845 nsresult
operator()(const opCreateSVGElement
& aOperation
) {
846 nsIContent
** target
= aOperation
.mContent
;
847 SVGContentCreatorFunction creator
= aOperation
.mCreator
;
848 nsAtom
* name
= aOperation
.mName
;
849 nsHtml5HtmlAttributes
* attributes
= aOperation
.mAttributes
;
850 nsIContent
* intendedParent
=
851 aOperation
.mIntendedParent
? *(aOperation
.mIntendedParent
) : nullptr;
853 // intendedParent == nullptr is a special case where the
854 // intended parent is the document.
855 nsNodeInfoManager
* nodeInfoManager
=
856 intendedParent
? intendedParent
->OwnerDoc()->NodeInfoManager()
857 : mBuilder
->GetNodeInfoManager();
859 *target
= CreateSVGElement(name
, attributes
, aOperation
.mFromNetwork
,
860 nodeInfoManager
, mBuilder
, creator
);
864 nsresult
operator()(const opCreateMathMLElement
& aOperation
) {
865 nsIContent
** target
= aOperation
.mContent
;
866 nsAtom
* name
= aOperation
.mName
;
867 nsHtml5HtmlAttributes
* attributes
= aOperation
.mAttributes
;
868 nsIContent
* intendedParent
=
869 aOperation
.mIntendedParent
? *(aOperation
.mIntendedParent
) : nullptr;
871 // intendedParent == nullptr is a special case where the
872 // intended parent is the document.
873 nsNodeInfoManager
* nodeInfoManager
=
874 intendedParent
? intendedParent
->OwnerDoc()->NodeInfoManager()
875 : mBuilder
->GetNodeInfoManager();
878 CreateMathMLElement(name
, attributes
, nodeInfoManager
, mBuilder
);
882 nsresult
operator()(const opSetFormElement
& aOperation
) {
883 SetFormElement(*(aOperation
.mContent
), *(aOperation
.mFormElement
),
884 *(aOperation
.mIntendedParent
));
888 nsresult
operator()(const opAppendText
& aOperation
) {
889 nsIContent
* parent
= *aOperation
.mParent
;
890 char16_t
* buffer
= aOperation
.mBuffer
;
891 uint32_t length
= aOperation
.mLength
;
892 return AppendText(buffer
, length
, parent
, mBuilder
);
895 nsresult
operator()(const opFosterParentText
& aOperation
) {
896 nsIContent
* stackParent
= *aOperation
.mStackParent
;
897 char16_t
* buffer
= aOperation
.mBuffer
;
898 uint32_t length
= aOperation
.mLength
;
899 nsIContent
* table
= *aOperation
.mTable
;
900 return FosterParentText(stackParent
, buffer
, length
, table
, mBuilder
);
903 nsresult
operator()(const opAppendComment
& aOperation
) {
904 nsIContent
* parent
= *aOperation
.mParent
;
905 char16_t
* buffer
= aOperation
.mBuffer
;
906 uint32_t length
= aOperation
.mLength
;
907 return AppendComment(parent
, buffer
, length
, mBuilder
);
910 nsresult
operator()(const opAppendCommentToDocument
& aOperation
) {
911 char16_t
* buffer
= aOperation
.mBuffer
;
912 int32_t length
= aOperation
.mLength
;
913 return AppendCommentToDocument(buffer
, length
, mBuilder
);
916 nsresult
operator()(const opAppendDoctypeToDocument
& aOperation
) {
917 nsAtom
* name
= aOperation
.mName
;
918 nsHtml5TreeOperationStringPair
* pair
= aOperation
.mStringPair
;
921 pair
->Get(publicId
, systemId
);
922 return AppendDoctypeToDocument(name
, publicId
, systemId
, mBuilder
);
925 nsresult
operator()(const opGetDocumentFragmentForTemplate
& aOperation
) {
926 nsIContent
* node
= *(aOperation
.mTemplate
);
927 *(aOperation
.mFragHandle
) = GetDocumentFragmentForTemplate(node
);
931 nsresult
operator()(const opSetDocumentFragmentForTemplate
& aOperation
) {
932 SetDocumentFragmentForTemplate(*aOperation
.mTemplate
,
933 *aOperation
.mFragment
);
937 nsresult
operator()(const opGetShadowRootFromHost
& aOperation
) {
938 nsIContent
* root
= nsContentUtils::AttachDeclarativeShadowRoot(
939 *aOperation
.mHost
, aOperation
.mShadowRootMode
,
940 aOperation
.mShadowRootIsClonable
,
941 aOperation
.mShadowRootIsSerializable
,
942 aOperation
.mShadowRootDelegatesFocus
);
944 *aOperation
.mFragHandle
= root
;
948 // We failed to attach a new shadow root, so instead attach a template
949 // element and return its content.
950 nsHtml5TreeOperation::Append(*aOperation
.mTemplateNode
, *aOperation
.mHost
,
952 *aOperation
.mFragHandle
=
953 static_cast<HTMLTemplateElement
*>(*aOperation
.mTemplateNode
)
955 nsContentUtils::LogSimpleConsoleError(
956 u
"Failed to attach Declarative Shadow DOM."_ns
, "DOM"_ns
,
957 mBuilder
->GetDocument()->IsInPrivateBrowsing(),
958 mBuilder
->GetDocument()->IsInChromeDocShell());
962 nsresult
operator()(const opGetFosterParent
& aOperation
) {
963 nsIContent
* table
= *(aOperation
.mTable
);
964 nsIContent
* stackParent
= *(aOperation
.mStackParent
);
965 nsIContent
* fosterParent
= GetFosterParent(table
, stackParent
);
966 *aOperation
.mParentHandle
= fosterParent
;
970 nsresult
operator()(const opMarkAsBroken
& aOperation
) {
971 return aOperation
.mResult
;
975 const opRunScriptThatMayDocumentWriteOrBlock
& aOperation
) {
976 nsIContent
* node
= *(aOperation
.mElement
);
977 nsAHtml5TreeBuilderState
* snapshot
= aOperation
.mBuilderState
;
979 mBuilder
->InitializeDocWriteParserState(snapshot
,
980 aOperation
.mLineNumber
);
982 *mScriptElement
= node
;
987 const opRunScriptThatCannotDocumentWriteOrBlock
& aOperation
) {
988 mBuilder
->RunScript(*(aOperation
.mElement
), false);
992 nsresult
operator()(const opPreventScriptExecution
& aOperation
) {
993 PreventScriptExecution(*(aOperation
.mElement
));
997 nsresult
operator()(const opDoneAddingChildren
& aOperation
) {
998 nsIContent
* node
= *(aOperation
.mElement
);
999 node
->DoneAddingChildren(node
->HasParserNotified());
1003 nsresult
operator()(const opDoneCreatingElement
& aOperation
) {
1004 DoneCreatingElement(*(aOperation
.mElement
));
1008 nsresult
operator()(const opUpdateCharsetSource
& aOperation
) {
1009 mBuilder
->UpdateCharsetSource(aOperation
.mCharsetSource
);
1013 nsresult
operator()(const opCharsetSwitchTo
& aOperation
) {
1014 auto encoding
= WrapNotNull(aOperation
.mEncoding
);
1015 mBuilder
->NeedsCharsetSwitchTo(encoding
, aOperation
.mCharsetSource
,
1016 (uint32_t)aOperation
.mLineNumber
);
1020 nsresult
operator()(const opUpdateStyleSheet
& aOperation
) {
1021 mBuilder
->UpdateStyleSheet(*(aOperation
.mElement
));
1025 nsresult
operator()(const opProcessOfflineManifest
& aOperation
) {
1026 // TODO: remove this
1030 nsresult
operator()(const opMarkMalformedIfScript
& aOperation
) {
1031 MarkMalformedIfScript(*(aOperation
.mElement
));
1035 nsresult
operator()(const opStreamEnded
& aOperation
) {
1036 *mStreamEnded
= true;
1040 nsresult
operator()(const opSetStyleLineNumber
& aOperation
) {
1041 nsIContent
* node
= *(aOperation
.mContent
);
1042 if (auto* linkStyle
= LinkStyle::FromNode(*node
)) {
1043 linkStyle
->SetLineNumber(aOperation
.mLineNumber
);
1045 MOZ_ASSERT(nsNameSpaceManager::GetInstance()->mSVGDisabled
,
1046 "Node didn't QI to style, but SVG wasn't disabled.");
1051 nsresult
operator()(
1052 const opSetScriptLineAndColumnNumberAndFreeze
& aOperation
) {
1053 nsIContent
* node
= *(aOperation
.mContent
);
1054 nsCOMPtr
<nsIScriptElement
> sele
= do_QueryInterface(node
);
1056 sele
->SetScriptLineNumber(aOperation
.mLineNumber
);
1057 sele
->SetScriptColumnNumber(
1058 JS::ColumnNumberOneOrigin(aOperation
.mColumnNumber
));
1059 sele
->FreezeExecutionAttrs(node
->OwnerDoc());
1061 MOZ_ASSERT(nsNameSpaceManager::GetInstance()->mSVGDisabled
,
1062 "Node didn't QI to script, but SVG wasn't disabled.");
1067 nsresult
operator()(const opSvgLoad
& aOperation
) {
1068 SvgLoad(*(aOperation
.mElement
));
1072 nsresult
operator()(const opMaybeComplainAboutCharset
& aOperation
) {
1073 char* msgId
= aOperation
.mMsgId
;
1074 bool error
= aOperation
.mError
;
1075 int32_t lineNumber
= aOperation
.mLineNumber
;
1076 mBuilder
->MaybeComplainAboutCharset(msgId
, error
, (uint32_t)lineNumber
);
1080 nsresult
operator()(const opMaybeComplainAboutDeepTree
& aOperation
) {
1081 mBuilder
->MaybeComplainAboutDeepTree((uint32_t)aOperation
.mLineNumber
);
1085 nsresult
operator()(const opAddClass
& aOperation
) {
1086 Element
* element
= (*(aOperation
.mElement
))->AsElement();
1087 char16_t
* str
= aOperation
.mClass
;
1088 nsDependentString
depStr(str
);
1089 // See viewsource.css for the possible classes
1091 element
->GetAttr(nsGkAtoms::_class
, klass
);
1092 if (!klass
.IsEmpty()) {
1094 klass
.Append(depStr
);
1095 element
->SetAttr(kNameSpaceID_None
, nsGkAtoms::_class
, klass
, true);
1097 element
->SetAttr(kNameSpaceID_None
, nsGkAtoms::_class
, depStr
, true);
1102 nsresult
operator()(const opAddViewSourceHref
& aOperation
) {
1103 Element
* element
= (*aOperation
.mElement
)->AsElement();
1104 char16_t
* buffer
= aOperation
.mBuffer
;
1105 int32_t length
= aOperation
.mLength
;
1106 nsDependentString
relative(buffer
, length
);
1108 Document
* doc
= mBuilder
->GetDocument();
1110 auto encoding
= doc
->GetDocumentCharacterSet();
1111 nsCOMPtr
<nsIURI
> uri
;
1112 nsresult rv
= NS_NewURI(getter_AddRefs(uri
), relative
, encoding
,
1113 mBuilder
->GetViewSourceBaseURI());
1114 NS_ENSURE_SUCCESS(rv
, NS_OK
);
1116 // Reuse the fix for bug 467852
1117 // URLs that execute script (e.g. "javascript:" URLs) should just be
1118 // ignored. There's nothing reasonable we can do with them, and allowing
1119 // them to execute in the context of the view-source window presents a
1120 // security risk. Just return the empty string in this case.
1121 bool openingExecutesScript
= false;
1122 rv
= NS_URIChainHasFlags(uri
,
1123 nsIProtocolHandler::URI_OPENING_EXECUTES_SCRIPT
,
1124 &openingExecutesScript
);
1125 if (NS_FAILED(rv
) || openingExecutesScript
) {
1129 nsAutoCString viewSourceUrl
;
1131 // URLs that return data (e.g. "http:" URLs) should be prefixed with
1132 // "view-source:". URLs that don't return data should just be returned
1134 if (!nsContentUtils::IsExternalProtocol(uri
)) {
1135 viewSourceUrl
.AssignLiteral("view-source:");
1139 rv
= uri
->GetSpec(spec
);
1140 NS_ENSURE_SUCCESS(rv
, rv
);
1142 viewSourceUrl
.Append(spec
);
1145 CopyUTF8toUTF16(viewSourceUrl
, utf16
);
1147 element
->SetAttr(kNameSpaceID_None
, nsGkAtoms::href
, utf16
, true);
1151 nsresult
operator()(const opAddViewSourceBase
& aOperation
) {
1152 nsDependentString
baseUrl(aOperation
.mBuffer
, aOperation
.mLength
);
1153 mBuilder
->AddBase(baseUrl
);
1157 nsresult
operator()(const opAddErrorType
& aOperation
) {
1158 Element
* element
= (*(aOperation
.mElement
))->AsElement();
1159 char* msgId
= aOperation
.mMsgId
;
1160 nsAtom
* atom
= aOperation
.mName
;
1161 nsAtom
* otherAtom
= aOperation
.mOther
;
1162 // See viewsource.css for the possible classes in addition to "error".
1164 element
->GetAttr(nsGkAtoms::_class
, klass
);
1165 if (!klass
.IsEmpty()) {
1166 klass
.AppendLiteral(" error");
1167 element
->SetAttr(kNameSpaceID_None
, nsGkAtoms::_class
, klass
, true);
1169 element
->SetAttr(kNameSpaceID_None
, nsGkAtoms::_class
, u
"error"_ns
,
1174 nsAutoString message
;
1176 rv
= nsContentUtils::FormatLocalizedString(
1177 message
, nsContentUtils::eHTMLPARSER_PROPERTIES
, msgId
,
1178 nsDependentAtomString(atom
), nsDependentAtomString(otherAtom
));
1179 NS_ENSURE_SUCCESS(rv
, NS_OK
);
1181 rv
= nsContentUtils::FormatLocalizedString(
1182 message
, nsContentUtils::eHTMLPARSER_PROPERTIES
, msgId
,
1183 nsDependentAtomString(atom
));
1184 NS_ENSURE_SUCCESS(rv
, NS_OK
);
1186 rv
= nsContentUtils::GetLocalizedString(
1187 nsContentUtils::eHTMLPARSER_PROPERTIES
, msgId
, message
);
1188 NS_ENSURE_SUCCESS(rv
, NS_OK
);
1192 element
->GetAttr(nsGkAtoms::title
, title
);
1193 if (!title
.IsEmpty()) {
1195 title
.Append(message
);
1196 element
->SetAttr(kNameSpaceID_None
, nsGkAtoms::title
, title
, true);
1198 element
->SetAttr(kNameSpaceID_None
, nsGkAtoms::title
, message
, true);
1203 nsresult
operator()(const opAddLineNumberId
& aOperation
) {
1204 Element
* element
= (*(aOperation
.mElement
))->AsElement();
1205 int32_t lineNumber
= aOperation
.mLineNumber
;
1206 nsAutoString
val(u
"line"_ns
);
1207 val
.AppendInt(lineNumber
);
1208 element
->SetAttr(kNameSpaceID_None
, nsGkAtoms::id
, val
, true);
1212 nsresult
operator()(const opShallowCloneInto
& aOperation
) {
1213 nsIContent
* src
= *aOperation
.mSrc
;
1215 RefPtr
<nsINode
> clone
= src
->CloneNode(false, rv
);
1216 if (NS_WARN_IF(rv
.Failed())) {
1217 return rv
.StealNSResult();
1219 *aOperation
.mDst
= clone
->AsContent();
1220 mBuilder
->HoldElement(clone
.forget().downcast
<nsIContent
>());
1221 return Append(*aOperation
.mDst
, *aOperation
.mIntendedParent
,
1222 aOperation
.mFromParser
, mBuilder
);
1225 nsresult
operator()(const opStartLayout
& aOperation
) {
1226 mBuilder
->StartLayout(
1227 mInterrupted
); // this causes a notification flush anyway
1231 nsresult
operator()(const opEnableEncodingMenu
& aOperation
) {
1232 Document
* doc
= mBuilder
->GetDocument();
1233 doc
->EnableEncodingMenu();
1237 nsresult
operator()(const uninitialized
& aOperation
) {
1238 MOZ_CRASH("uninitialized");
1243 return mOperation
.match(TreeOperationMatcher(aBuilder
, aScriptElement
,
1244 aInterrupted
, aStreamEnded
));