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/DocumentType.h"
15 #include "mozilla/dom/Element.h"
16 #include "mozilla/dom/LinkStyle.h"
17 #include "mozilla/dom/HTMLFormElement.h"
18 #include "mozilla/dom/HTMLImageElement.h"
19 #include "mozilla/dom/HTMLTemplateElement.h"
20 #include "mozilla/dom/MutationObservers.h"
21 #include "mozilla/dom/Text.h"
22 #include "nsAttrName.h"
23 #include "nsContentCreatorFunctions.h"
24 #include "nsContentUtils.h"
25 #include "nsDocElementCreatedNotificationRunner.h"
27 #include "nsHtml5AutoPauseUpdate.h"
28 #include "nsHtml5DocumentMode.h"
29 #include "nsHtml5HtmlAttributes.h"
30 #include "nsHtml5SVGLoadDispatcher.h"
31 #include "nsHtml5TreeBuilder.h"
33 #include "nsIFormControl.h"
34 #include "nsIMutationObserver.h"
36 #include "nsIProtocolHandler.h"
37 #include "nsIScriptElement.h"
38 #include "nsISupportsImpl.h"
40 #include "nsNetUtil.h"
41 #include "nsTextNode.h"
43 using namespace mozilla
;
44 using namespace mozilla::dom
;
45 using mozilla::dom::Document
;
48 * Helper class that opens a notification batch if the current doc
49 * is different from the executor doc.
51 class MOZ_STACK_CLASS nsHtml5OtherDocUpdate
{
53 nsHtml5OtherDocUpdate(Document
* aCurrentDoc
, Document
* aExecutorDoc
) {
54 MOZ_ASSERT(aCurrentDoc
, "Node has no doc?");
55 MOZ_ASSERT(aExecutorDoc
, "Executor has no doc?");
56 if (MOZ_LIKELY(aCurrentDoc
== aExecutorDoc
)) {
59 mDocument
= aCurrentDoc
;
60 aCurrentDoc
->BeginUpdate();
64 ~nsHtml5OtherDocUpdate() {
65 if (MOZ_UNLIKELY(mDocument
)) {
66 mDocument
->EndUpdate();
71 RefPtr
<Document
> mDocument
;
74 nsHtml5TreeOperation::nsHtml5TreeOperation() : mOperation(uninitialized()) {
75 MOZ_COUNT_CTOR(nsHtml5TreeOperation
);
78 nsHtml5TreeOperation::~nsHtml5TreeOperation() {
79 MOZ_COUNT_DTOR(nsHtml5TreeOperation
);
81 struct TreeOperationMatcher
{
82 void operator()(const opAppend
& aOperation
) {}
84 void operator()(const opDetach
& aOperation
) {}
86 void operator()(const opAppendChildrenToNewParent
& aOperation
) {}
88 void operator()(const opFosterParent
& aOperation
) {}
90 void operator()(const opAppendToDocument
& aOperation
) {}
92 void operator()(const opAddAttributes
& aOperation
) {
93 delete aOperation
.mAttributes
;
96 void operator()(const nsHtml5DocumentMode
& aMode
) {}
98 void operator()(const opCreateHTMLElement
& aOperation
) {
99 aOperation
.mName
->Release();
100 delete aOperation
.mAttributes
;
103 void operator()(const opCreateSVGElement
& aOperation
) {
104 aOperation
.mName
->Release();
105 delete aOperation
.mAttributes
;
108 void operator()(const opCreateMathMLElement
& aOperation
) {
109 aOperation
.mName
->Release();
110 delete aOperation
.mAttributes
;
113 void operator()(const opSetFormElement
& aOperation
) {}
115 void operator()(const opAppendText
& aOperation
) {
116 delete[] aOperation
.mBuffer
;
119 void operator()(const opFosterParentText
& aOperation
) {
120 delete[] aOperation
.mBuffer
;
123 void operator()(const opAppendComment
& aOperation
) {
124 delete[] aOperation
.mBuffer
;
127 void operator()(const opAppendCommentToDocument
& aOperation
) {
128 delete[] aOperation
.mBuffer
;
131 void operator()(const opAppendDoctypeToDocument
& aOperation
) {
132 aOperation
.mName
->Release();
133 delete aOperation
.mStringPair
;
136 void operator()(const opGetDocumentFragmentForTemplate
& aOperation
) {}
138 void operator()(const opGetFosterParent
& aOperation
) {}
140 void operator()(const opMarkAsBroken
& aOperation
) {}
142 void operator()(const opRunScript
& aOperation
) {}
144 void operator()(const opRunScriptAsyncDefer
& aOperation
) {}
146 void operator()(const opPreventScriptExecution
& aOperation
) {}
148 void operator()(const opDoneAddingChildren
& aOperation
) {}
150 void operator()(const opDoneCreatingElement
& aOperation
) {}
152 void operator()(const opUpdateCharsetSource
& aOperation
) {}
154 void operator()(const opCharsetSwitchTo
& aOperation
) {}
156 void operator()(const opUpdateStyleSheet
& aOperation
) {}
158 void operator()(const opProcessOfflineManifest
& aOperation
) {
159 free(aOperation
.mUrl
);
162 void operator()(const opMarkMalformedIfScript
& aOperation
) {}
164 void operator()(const opStreamEnded
& aOperation
) {}
166 void operator()(const opSetStyleLineNumber
& aOperation
) {}
168 void operator()(const opSetScriptLineAndColumnNumberAndFreeze
& aOperation
) {
171 void operator()(const opSvgLoad
& aOperation
) {}
173 void operator()(const opMaybeComplainAboutCharset
& aOperation
) {}
175 void operator()(const opMaybeComplainAboutDeepTree
& aOperation
) {}
177 void operator()(const opAddClass
& aOperation
) {}
179 void operator()(const opAddViewSourceHref
& aOperation
) {
180 delete[] aOperation
.mBuffer
;
183 void operator()(const opAddViewSourceBase
& aOperation
) {
184 delete[] aOperation
.mBuffer
;
187 void operator()(const opAddErrorType
& aOperation
) {
188 if (aOperation
.mName
) {
189 aOperation
.mName
->Release();
191 if (aOperation
.mOther
) {
192 aOperation
.mOther
->Release();
196 void operator()(const opAddLineNumberId
& aOperation
) {}
198 void operator()(const opStartLayout
& aOperation
) {}
200 void operator()(const opEnableEncodingMenu
& aOperation
) {}
202 void operator()(const uninitialized
& aOperation
) {
203 NS_WARNING("Uninitialized tree op.");
207 mOperation
.match(TreeOperationMatcher());
210 nsresult
nsHtml5TreeOperation::AppendTextToTextNode(
211 const char16_t
* aBuffer
, uint32_t aLength
, dom::Text
* aTextNode
,
212 nsHtml5DocumentBuilder
* aBuilder
) {
213 MOZ_ASSERT(aTextNode
, "Got null text node.");
214 MOZ_ASSERT(aBuilder
);
215 MOZ_ASSERT(aBuilder
->IsInDocUpdate());
216 uint32_t oldLength
= aTextNode
->TextLength();
217 CharacterDataChangeInfo info
= {true, oldLength
, oldLength
, aLength
};
218 MutationObservers::NotifyCharacterDataWillChange(aTextNode
, info
);
220 nsresult rv
= aTextNode
->AppendText(aBuffer
, aLength
, false);
221 NS_ENSURE_SUCCESS(rv
, rv
);
223 MutationObservers::NotifyCharacterDataChanged(aTextNode
, info
);
227 nsresult
nsHtml5TreeOperation::AppendText(const char16_t
* aBuffer
,
228 uint32_t aLength
, nsIContent
* aParent
,
229 nsHtml5DocumentBuilder
* aBuilder
) {
231 nsIContent
* lastChild
= aParent
->GetLastChild();
232 if (lastChild
&& lastChild
->IsText()) {
233 nsHtml5OtherDocUpdate
update(aParent
->OwnerDoc(), aBuilder
->GetDocument());
234 return AppendTextToTextNode(aBuffer
, aLength
, lastChild
->GetAsText(),
238 nsNodeInfoManager
* nodeInfoManager
= aParent
->OwnerDoc()->NodeInfoManager();
239 RefPtr
<nsTextNode
> text
= new (nodeInfoManager
) nsTextNode(nodeInfoManager
);
240 NS_ASSERTION(text
, "Infallible malloc failed?");
241 rv
= text
->SetText(aBuffer
, aLength
, false);
242 NS_ENSURE_SUCCESS(rv
, rv
);
244 return Append(text
, aParent
, aBuilder
);
247 nsresult
nsHtml5TreeOperation::Append(nsIContent
* aNode
, nsIContent
* aParent
,
248 nsHtml5DocumentBuilder
* aBuilder
) {
249 MOZ_ASSERT(aBuilder
);
250 MOZ_ASSERT(aBuilder
->IsInDocUpdate());
252 nsHtml5OtherDocUpdate
update(aParent
->OwnerDoc(), aBuilder
->GetDocument());
253 aParent
->AppendChildTo(aNode
, false, rv
);
255 aNode
->SetParserHasNotified();
256 MutationObservers::NotifyContentAppended(aParent
, aNode
);
258 return rv
.StealNSResult();
261 nsresult
nsHtml5TreeOperation::Append(nsIContent
* aNode
, nsIContent
* aParent
,
262 mozilla::dom::FromParser aFromParser
,
263 nsHtml5DocumentBuilder
* aBuilder
) {
264 Maybe
<nsHtml5AutoPauseUpdate
> autoPause
;
265 Maybe
<dom::AutoCEReaction
> autoCEReaction
;
266 dom::DocGroup
* docGroup
= aParent
->OwnerDoc()->GetDocGroup();
267 if (docGroup
&& aFromParser
!= mozilla::dom::FROM_PARSER_FRAGMENT
) {
268 autoCEReaction
.emplace(docGroup
->CustomElementReactionsStack(), nullptr);
270 nsresult rv
= Append(aNode
, aParent
, aBuilder
);
271 // Pause the parser only when there are reactions to be invoked to avoid
272 // pausing parsing too aggressive.
273 if (autoCEReaction
.isSome() && docGroup
&&
274 docGroup
->CustomElementReactionsStack()
275 ->IsElementQueuePushedForCurrentRecursionDepth()) {
276 autoPause
.emplace(aBuilder
);
281 nsresult
nsHtml5TreeOperation::AppendToDocument(
282 nsIContent
* aNode
, nsHtml5DocumentBuilder
* aBuilder
) {
283 MOZ_ASSERT(aBuilder
);
284 MOZ_ASSERT(aBuilder
->GetDocument() == aNode
->OwnerDoc());
285 MOZ_ASSERT(aBuilder
->IsInDocUpdate());
288 Document
* doc
= aBuilder
->GetDocument();
289 doc
->AppendChildTo(aNode
, false, rv
);
290 if (rv
.ErrorCodeIs(NS_ERROR_DOM_HIERARCHY_REQUEST_ERR
)) {
291 aNode
->SetParserHasNotified();
295 return rv
.StealNSResult();
298 aNode
->SetParserHasNotified();
299 MutationObservers::NotifyContentInserted(doc
, aNode
);
301 NS_ASSERTION(!nsContentUtils::IsSafeToRunScript(),
302 "Someone forgot to block scripts");
303 if (aNode
->IsElement()) {
304 nsContentUtils::AddScriptRunner(
305 new nsDocElementCreatedNotificationRunner(doc
));
310 static bool IsElementOrTemplateContent(nsINode
* aNode
) {
312 if (aNode
->IsElement()) {
315 if (aNode
->IsDocumentFragment()) {
316 // Check if the node is a template content.
317 nsIContent
* fragHost
= aNode
->AsDocumentFragment()->GetHost();
318 if (fragHost
&& fragHost
->IsTemplateElement()) {
326 void nsHtml5TreeOperation::Detach(nsIContent
* aNode
,
327 nsHtml5DocumentBuilder
* aBuilder
) {
328 MOZ_ASSERT(aBuilder
);
329 MOZ_ASSERT(aBuilder
->IsInDocUpdate());
330 nsCOMPtr
<nsINode
> parent
= aNode
->GetParentNode();
332 nsHtml5OtherDocUpdate
update(parent
->OwnerDoc(), aBuilder
->GetDocument());
333 parent
->RemoveChildNode(aNode
, true);
337 nsresult
nsHtml5TreeOperation::AppendChildrenToNewParent(
338 nsIContent
* aNode
, nsIContent
* aParent
, nsHtml5DocumentBuilder
* aBuilder
) {
339 MOZ_ASSERT(aBuilder
);
340 MOZ_ASSERT(aBuilder
->IsInDocUpdate());
341 nsHtml5OtherDocUpdate
update(aParent
->OwnerDoc(), aBuilder
->GetDocument());
343 bool didAppend
= false;
344 while (aNode
->HasChildren()) {
345 nsCOMPtr
<nsIContent
> child
= aNode
->GetFirstChild();
346 aNode
->RemoveChildNode(child
, true);
349 aParent
->AppendChildTo(child
, false, rv
);
351 return rv
.StealNSResult();
356 MutationObservers::NotifyContentAppended(aParent
, aParent
->GetLastChild());
361 nsresult
nsHtml5TreeOperation::FosterParent(nsIContent
* aNode
,
364 nsHtml5DocumentBuilder
* aBuilder
) {
365 MOZ_ASSERT(aBuilder
);
366 MOZ_ASSERT(aBuilder
->IsInDocUpdate());
367 nsIContent
* foster
= aTable
->GetParent();
369 if (IsElementOrTemplateContent(foster
)) {
370 nsHtml5OtherDocUpdate
update(foster
->OwnerDoc(), aBuilder
->GetDocument());
373 foster
->InsertChildBefore(aNode
, aTable
, false, rv
);
375 return rv
.StealNSResult();
378 MutationObservers::NotifyContentInserted(foster
, aNode
);
382 return Append(aNode
, aParent
, aBuilder
);
385 nsresult
nsHtml5TreeOperation::AddAttributes(nsIContent
* aNode
,
386 nsHtml5HtmlAttributes
* aAttributes
,
387 nsHtml5DocumentBuilder
* aBuilder
) {
388 dom::Element
* node
= aNode
->AsElement();
389 nsHtml5OtherDocUpdate
update(node
->OwnerDoc(), aBuilder
->GetDocument());
391 int32_t len
= aAttributes
->getLength();
392 for (int32_t i
= len
; i
> 0;) {
394 nsAtom
* localName
= aAttributes
->getLocalNameNoBoundsCheck(i
);
395 int32_t nsuri
= aAttributes
->getURINoBoundsCheck(i
);
396 if (!node
->HasAttr(nsuri
, localName
)) {
397 nsString value
; // Not Auto, because using it to hold nsStringBuffer*
398 aAttributes
->getValueNoBoundsCheck(i
).ToString(value
);
399 node
->SetAttr(nsuri
, localName
, aAttributes
->getPrefixNoBoundsCheck(i
),
401 // XXX what to do with nsresult?
407 void nsHtml5TreeOperation::SetHTMLElementAttributes(
408 dom::Element
* aElement
, nsAtom
* aName
, nsHtml5HtmlAttributes
* aAttributes
) {
409 int32_t len
= aAttributes
->getLength();
410 for (int32_t i
= 0; i
< len
; i
++) {
411 nsHtml5String val
= aAttributes
->getValueNoBoundsCheck(i
);
412 nsAtom
* klass
= val
.MaybeAsAtom();
414 aElement
->SetSingleClassFromParser(klass
);
416 nsAtom
* localName
= aAttributes
->getLocalNameNoBoundsCheck(i
);
417 nsAtom
* prefix
= aAttributes
->getPrefixNoBoundsCheck(i
);
418 int32_t nsuri
= aAttributes
->getURINoBoundsCheck(i
);
420 nsString value
; // Not Auto, because using it to hold nsStringBuffer*
422 if (nsGkAtoms::a
== aName
&& nsGkAtoms::name
== localName
) {
423 // This is an HTML5-incompliant Geckoism.
424 // Remove when fixing bug 582361
425 NS_ConvertUTF16toUTF8
cname(value
);
426 NS_ConvertUTF8toUTF16
uv(nsUnescape(cname
.BeginWriting()));
427 aElement
->SetAttr(nsuri
, localName
, prefix
, uv
, false);
429 aElement
->SetAttr(nsuri
, localName
, prefix
, value
, false);
435 nsIContent
* nsHtml5TreeOperation::CreateHTMLElement(
436 nsAtom
* aName
, nsHtml5HtmlAttributes
* aAttributes
,
437 mozilla::dom::FromParser aFromParser
, nsNodeInfoManager
* aNodeInfoManager
,
438 nsHtml5DocumentBuilder
* aBuilder
,
439 mozilla::dom::HTMLContentCreatorFunction aCreator
) {
440 RefPtr
<dom::NodeInfo
> nodeInfo
= aNodeInfoManager
->GetNodeInfo(
441 aName
, nullptr, kNameSpaceID_XHTML
, nsINode::ELEMENT_NODE
);
442 NS_ASSERTION(nodeInfo
, "Got null nodeinfo.");
444 dom::Element
* newContent
= nullptr;
445 Document
* document
= nodeInfo
->GetDocument();
446 bool willExecuteScript
= false;
447 bool isCustomElement
= false;
448 RefPtr
<nsAtom
> isAtom
;
449 dom::CustomElementDefinition
* definition
= nullptr;
452 nsHtml5String is
= aAttributes
->getValue(nsHtml5AttributeName::ATTR_IS
);
454 nsAutoString isValue
;
455 is
.ToString(isValue
);
456 isAtom
= NS_Atomize(isValue
);
460 isCustomElement
= (aCreator
== NS_NewCustomElement
|| isAtom
);
461 if (isCustomElement
&& aFromParser
!= dom::FROM_PARSER_FRAGMENT
) {
462 RefPtr
<nsAtom
> tagAtom
= nodeInfo
->NameAtom();
463 RefPtr
<nsAtom
> typeAtom
=
464 (aCreator
== NS_NewCustomElement
) ? tagAtom
: isAtom
;
466 MOZ_ASSERT(nodeInfo
->NameAtom()->Equals(nodeInfo
->LocalName()));
467 definition
= nsContentUtils::LookupCustomElementDefinition(
468 document
, nodeInfo
->NameAtom(), nodeInfo
->NamespaceID(), typeAtom
);
471 willExecuteScript
= true;
475 if (willExecuteScript
) { // This will cause custom element constructors to
477 mozilla::dom::AutoSetThrowOnDynamicMarkupInsertionCounter
478 throwOnDynamicMarkupInsertionCounter(document
);
479 nsHtml5AutoPauseUpdate
autoPauseContentUpdate(aBuilder
);
480 { nsAutoMicroTask mt
; }
481 dom::AutoCEReaction
autoCEReaction(
482 document
->GetDocGroup()->CustomElementReactionsStack(), nullptr);
484 nsCOMPtr
<dom::Element
> newElement
;
485 NS_NewHTMLElement(getter_AddRefs(newElement
), nodeInfo
.forget(),
486 aFromParser
, isAtom
, definition
);
488 MOZ_ASSERT(newElement
, "Element creation created null pointer.");
489 newContent
= newElement
;
490 aBuilder
->HoldElement(newElement
.forget());
492 if (MOZ_UNLIKELY(aName
== nsGkAtoms::style
|| aName
== nsGkAtoms::link
)) {
493 if (auto* linkStyle
= dom::LinkStyle::FromNode(*newContent
)) {
494 linkStyle
->SetEnableUpdates(false);
502 SetHTMLElementAttributes(newContent
, aName
, aAttributes
);
504 nsCOMPtr
<dom::Element
> newElement
;
506 if (isCustomElement
) {
507 NS_NewHTMLElement(getter_AddRefs(newElement
), nodeInfo
.forget(),
508 aFromParser
, isAtom
, definition
);
510 newElement
= aCreator(nodeInfo
.forget(), aFromParser
);
513 MOZ_ASSERT(newElement
, "Element creation created null pointer.");
515 newContent
= newElement
;
516 aBuilder
->HoldElement(newElement
.forget());
518 if (MOZ_UNLIKELY(aName
== nsGkAtoms::style
|| aName
== nsGkAtoms::link
)) {
519 if (auto* linkStyle
= dom::LinkStyle::FromNode(*newContent
)) {
520 linkStyle
->SetEnableUpdates(false);
528 SetHTMLElementAttributes(newContent
, aName
, aAttributes
);
534 nsIContent
* nsHtml5TreeOperation::CreateSVGElement(
535 nsAtom
* aName
, nsHtml5HtmlAttributes
* aAttributes
,
536 mozilla::dom::FromParser aFromParser
, nsNodeInfoManager
* aNodeInfoManager
,
537 nsHtml5DocumentBuilder
* aBuilder
,
538 mozilla::dom::SVGContentCreatorFunction aCreator
) {
539 nsCOMPtr
<nsIContent
> newElement
;
540 if (MOZ_LIKELY(aNodeInfoManager
->SVGEnabled())) {
541 RefPtr
<dom::NodeInfo
> nodeInfo
= aNodeInfoManager
->GetNodeInfo(
542 aName
, nullptr, kNameSpaceID_SVG
, nsINode::ELEMENT_NODE
);
543 MOZ_ASSERT(nodeInfo
, "Got null nodeinfo.");
545 mozilla::DebugOnly
<nsresult
> rv
=
546 aCreator(getter_AddRefs(newElement
), nodeInfo
.forget(), aFromParser
);
547 MOZ_ASSERT(NS_SUCCEEDED(rv
) && newElement
);
549 RefPtr
<dom::NodeInfo
> nodeInfo
= aNodeInfoManager
->GetNodeInfo(
550 aName
, nullptr, kNameSpaceID_disabled_SVG
, nsINode::ELEMENT_NODE
);
551 MOZ_ASSERT(nodeInfo
, "Got null nodeinfo.");
553 // The mismatch between NS_NewXMLElement and SVGContentCreatorFunction
554 // argument types is annoying.
555 nsCOMPtr
<dom::Element
> xmlElement
;
556 mozilla::DebugOnly
<nsresult
> rv
=
557 NS_NewXMLElement(getter_AddRefs(xmlElement
), nodeInfo
.forget());
558 MOZ_ASSERT(NS_SUCCEEDED(rv
) && xmlElement
);
559 newElement
= xmlElement
;
562 dom::Element
* newContent
= newElement
->AsElement();
563 aBuilder
->HoldElement(newElement
.forget());
565 if (MOZ_UNLIKELY(aName
== nsGkAtoms::style
)) {
566 if (auto* linkStyle
= dom::LinkStyle::FromNode(*newContent
)) {
567 linkStyle
->SetEnableUpdates(false);
575 int32_t len
= aAttributes
->getLength();
576 for (int32_t i
= 0; i
< len
; i
++) {
577 nsHtml5String val
= aAttributes
->getValueNoBoundsCheck(i
);
578 nsAtom
* klass
= val
.MaybeAsAtom();
580 newContent
->SetSingleClassFromParser(klass
);
582 nsAtom
* localName
= aAttributes
->getLocalNameNoBoundsCheck(i
);
583 nsAtom
* prefix
= aAttributes
->getPrefixNoBoundsCheck(i
);
584 int32_t nsuri
= aAttributes
->getURINoBoundsCheck(i
);
586 nsString value
; // Not Auto, because using it to hold nsStringBuffer*
588 newContent
->SetAttr(nsuri
, localName
, prefix
, value
, false);
594 nsIContent
* nsHtml5TreeOperation::CreateMathMLElement(
595 nsAtom
* aName
, nsHtml5HtmlAttributes
* aAttributes
,
596 nsNodeInfoManager
* aNodeInfoManager
, nsHtml5DocumentBuilder
* aBuilder
) {
597 nsCOMPtr
<dom::Element
> newElement
;
598 if (MOZ_LIKELY(aNodeInfoManager
->MathMLEnabled())) {
599 RefPtr
<dom::NodeInfo
> nodeInfo
= aNodeInfoManager
->GetNodeInfo(
600 aName
, nullptr, kNameSpaceID_MathML
, nsINode::ELEMENT_NODE
);
601 NS_ASSERTION(nodeInfo
, "Got null nodeinfo.");
603 mozilla::DebugOnly
<nsresult
> rv
=
604 NS_NewMathMLElement(getter_AddRefs(newElement
), nodeInfo
.forget());
605 MOZ_ASSERT(NS_SUCCEEDED(rv
) && newElement
);
607 RefPtr
<dom::NodeInfo
> nodeInfo
= aNodeInfoManager
->GetNodeInfo(
608 aName
, nullptr, kNameSpaceID_disabled_MathML
, nsINode::ELEMENT_NODE
);
609 NS_ASSERTION(nodeInfo
, "Got null nodeinfo.");
611 mozilla::DebugOnly
<nsresult
> rv
=
612 NS_NewXMLElement(getter_AddRefs(newElement
), nodeInfo
.forget());
613 MOZ_ASSERT(NS_SUCCEEDED(rv
) && newElement
);
616 dom::Element
* newContent
= newElement
;
617 aBuilder
->HoldElement(newElement
.forget());
623 int32_t len
= aAttributes
->getLength();
624 for (int32_t i
= 0; i
< len
; i
++) {
625 nsHtml5String val
= aAttributes
->getValueNoBoundsCheck(i
);
626 nsAtom
* klass
= val
.MaybeAsAtom();
628 newContent
->SetSingleClassFromParser(klass
);
630 nsAtom
* localName
= aAttributes
->getLocalNameNoBoundsCheck(i
);
631 nsAtom
* prefix
= aAttributes
->getPrefixNoBoundsCheck(i
);
632 int32_t nsuri
= aAttributes
->getURINoBoundsCheck(i
);
634 nsString value
; // Not Auto, because using it to hold nsStringBuffer*
636 newContent
->SetAttr(nsuri
, localName
, prefix
, value
, false);
642 void nsHtml5TreeOperation::SetFormElement(nsIContent
* aNode
,
643 nsIContent
* aParent
) {
644 RefPtr
<dom::HTMLFormElement
> formElement
=
645 dom::HTMLFormElement::FromNodeOrNull(aParent
);
646 NS_ASSERTION(formElement
,
647 "The form element doesn't implement HTMLFormElement.");
648 nsCOMPtr
<nsIFormControl
> formControl(do_QueryInterface(aNode
));
650 formControl
->ControlType() !=
651 FormControlType::FormAssociatedCustomElement
&&
652 !aNode
->AsElement()->HasAttr(nsGkAtoms::form
)) {
653 formControl
->SetForm(formElement
);
654 } else if (HTMLImageElement
* domImageElement
=
655 dom::HTMLImageElement::FromNodeOrNull(aNode
)) {
656 domImageElement
->SetForm(formElement
);
660 nsresult
nsHtml5TreeOperation::FosterParentText(
661 nsIContent
* aStackParent
, char16_t
* aBuffer
, uint32_t aLength
,
662 nsIContent
* aTable
, nsHtml5DocumentBuilder
* aBuilder
) {
663 MOZ_ASSERT(aBuilder
);
664 MOZ_ASSERT(aBuilder
->IsInDocUpdate());
666 nsIContent
* foster
= aTable
->GetParent();
668 if (IsElementOrTemplateContent(foster
)) {
669 nsHtml5OtherDocUpdate
update(foster
->OwnerDoc(), aBuilder
->GetDocument());
671 nsIContent
* previousSibling
= aTable
->GetPreviousSibling();
672 if (previousSibling
&& previousSibling
->IsText()) {
673 return AppendTextToTextNode(aBuffer
, aLength
,
674 previousSibling
->GetAsText(), aBuilder
);
677 nsNodeInfoManager
* nodeInfoManager
=
678 aStackParent
->OwnerDoc()->NodeInfoManager();
679 RefPtr
<nsTextNode
> text
= new (nodeInfoManager
) nsTextNode(nodeInfoManager
);
680 NS_ASSERTION(text
, "Infallible malloc failed?");
681 rv
= text
->SetText(aBuffer
, aLength
, false);
682 NS_ENSURE_SUCCESS(rv
, rv
);
685 foster
->InsertChildBefore(text
, aTable
, false, error
);
686 if (error
.Failed()) {
687 return error
.StealNSResult();
690 MutationObservers::NotifyContentInserted(foster
, text
);
694 return AppendText(aBuffer
, aLength
, aStackParent
, aBuilder
);
697 nsresult
nsHtml5TreeOperation::AppendComment(nsIContent
* aParent
,
698 char16_t
* aBuffer
, int32_t aLength
,
699 nsHtml5DocumentBuilder
* aBuilder
) {
700 nsNodeInfoManager
* nodeInfoManager
= aParent
->OwnerDoc()->NodeInfoManager();
701 RefPtr
<dom::Comment
> comment
=
702 new (nodeInfoManager
) dom::Comment(nodeInfoManager
);
703 NS_ASSERTION(comment
, "Infallible malloc failed?");
704 nsresult rv
= comment
->SetText(aBuffer
, aLength
, false);
705 NS_ENSURE_SUCCESS(rv
, rv
);
707 return Append(comment
, aParent
, aBuilder
);
710 nsresult
nsHtml5TreeOperation::AppendCommentToDocument(
711 char16_t
* aBuffer
, int32_t aLength
, nsHtml5DocumentBuilder
* aBuilder
) {
712 RefPtr
<dom::Comment
> comment
= new (aBuilder
->GetNodeInfoManager())
713 dom::Comment(aBuilder
->GetNodeInfoManager());
714 NS_ASSERTION(comment
, "Infallible malloc failed?");
715 nsresult rv
= comment
->SetText(aBuffer
, aLength
, false);
716 NS_ENSURE_SUCCESS(rv
, rv
);
718 return AppendToDocument(comment
, aBuilder
);
721 nsresult
nsHtml5TreeOperation::AppendDoctypeToDocument(
722 nsAtom
* aName
, const nsAString
& aPublicId
, const nsAString
& aSystemId
,
723 nsHtml5DocumentBuilder
* aBuilder
) {
724 // Adapted from nsXMLContentSink
725 // Create a new doctype node
726 RefPtr
<dom::DocumentType
> docType
=
727 NS_NewDOMDocumentType(aBuilder
->GetNodeInfoManager(), aName
, aPublicId
,
728 aSystemId
, VoidString());
729 return AppendToDocument(docType
, aBuilder
);
732 nsIContent
* nsHtml5TreeOperation::GetDocumentFragmentForTemplate(
734 dom::HTMLTemplateElement
* tempElem
=
735 static_cast<dom::HTMLTemplateElement
*>(aNode
);
736 RefPtr
<dom::DocumentFragment
> frag
= tempElem
->Content();
740 nsIContent
* nsHtml5TreeOperation::GetFosterParent(nsIContent
* aTable
,
741 nsIContent
* aStackParent
) {
742 nsIContent
* tableParent
= aTable
->GetParent();
743 return IsElementOrTemplateContent(tableParent
) ? tableParent
: aStackParent
;
746 void nsHtml5TreeOperation::PreventScriptExecution(nsIContent
* aNode
) {
747 nsCOMPtr
<nsIScriptElement
> sele
= do_QueryInterface(aNode
);
749 sele
->PreventExecution();
751 MOZ_ASSERT(nsNameSpaceManager::GetInstance()->mSVGDisabled
,
752 "Node didn't QI to script, but SVG wasn't disabled.");
756 void nsHtml5TreeOperation::DoneAddingChildren(nsIContent
* aNode
) {
757 aNode
->DoneAddingChildren(aNode
->HasParserNotified());
760 void nsHtml5TreeOperation::DoneCreatingElement(nsIContent
* aNode
) {
761 aNode
->DoneCreatingElement();
764 void nsHtml5TreeOperation::SvgLoad(nsIContent
* aNode
) {
765 nsCOMPtr
<nsIRunnable
> event
= new nsHtml5SVGLoadDispatcher(aNode
);
767 aNode
->OwnerDoc()->Dispatch(TaskCategory::Network
, event
.forget()))) {
768 NS_WARNING("failed to dispatch svg load dispatcher");
772 void nsHtml5TreeOperation::MarkMalformedIfScript(nsIContent
* aNode
) {
773 nsCOMPtr
<nsIScriptElement
> sele
= do_QueryInterface(aNode
);
775 // Make sure to serialize this script correctly, for nice round tripping.
776 sele
->SetIsMalformed();
780 nsresult
nsHtml5TreeOperation::Perform(nsHtml5TreeOpExecutor
* aBuilder
,
781 nsIContent
** aScriptElement
,
782 bool* aInterrupted
, bool* aStreamEnded
) {
783 struct TreeOperationMatcher
{
784 TreeOperationMatcher(nsHtml5TreeOpExecutor
* aBuilder
,
785 nsIContent
** aScriptElement
, bool* aInterrupted
,
787 : mBuilder(aBuilder
),
788 mScriptElement(aScriptElement
),
789 mInterrupted(aInterrupted
),
790 mStreamEnded(aStreamEnded
) {}
792 nsHtml5TreeOpExecutor
* mBuilder
;
793 nsIContent
** mScriptElement
;
797 nsresult
operator()(const opAppend
& aOperation
) {
798 return Append(*(aOperation
.mChild
), *(aOperation
.mParent
),
799 aOperation
.mFromNetwork
, mBuilder
);
802 nsresult
operator()(const opDetach
& aOperation
) {
803 Detach(*(aOperation
.mElement
), mBuilder
);
807 nsresult
operator()(const opAppendChildrenToNewParent
& aOperation
) {
808 nsCOMPtr
<nsIContent
> node
= *(aOperation
.mOldParent
);
809 nsIContent
* parent
= *(aOperation
.mNewParent
);
810 return AppendChildrenToNewParent(node
, parent
, mBuilder
);
813 nsresult
operator()(const opFosterParent
& aOperation
) {
814 nsIContent
* node
= *(aOperation
.mChild
);
815 nsIContent
* parent
= *(aOperation
.mStackParent
);
816 nsIContent
* table
= *(aOperation
.mTable
);
817 return FosterParent(node
, parent
, table
, mBuilder
);
820 nsresult
operator()(const opAppendToDocument
& aOperation
) {
821 nsresult rv
= AppendToDocument(*(aOperation
.mContent
), mBuilder
);
822 mBuilder
->PauseDocUpdate(mInterrupted
);
826 nsresult
operator()(const opAddAttributes
& aOperation
) {
827 nsIContent
* node
= *(aOperation
.mElement
);
828 nsHtml5HtmlAttributes
* attributes
= aOperation
.mAttributes
;
829 return AddAttributes(node
, attributes
, mBuilder
);
832 nsresult
operator()(const nsHtml5DocumentMode
& aMode
) {
833 mBuilder
->SetDocumentMode(aMode
);
837 nsresult
operator()(const opCreateHTMLElement
& aOperation
) {
838 nsIContent
** target
= aOperation
.mContent
;
839 mozilla::dom::HTMLContentCreatorFunction creator
= aOperation
.mCreator
;
840 nsAtom
* name
= aOperation
.mName
;
841 nsHtml5HtmlAttributes
* attributes
= aOperation
.mAttributes
;
842 nsIContent
* intendedParent
=
843 aOperation
.mIntendedParent
? *(aOperation
.mIntendedParent
) : nullptr;
845 // intendedParent == nullptr is a special case where the
846 // intended parent is the document.
847 nsNodeInfoManager
* nodeInfoManager
=
848 intendedParent
? intendedParent
->OwnerDoc()->NodeInfoManager()
849 : mBuilder
->GetNodeInfoManager();
851 *target
= CreateHTMLElement(name
, attributes
, aOperation
.mFromNetwork
,
852 nodeInfoManager
, mBuilder
, creator
);
856 nsresult
operator()(const opCreateSVGElement
& aOperation
) {
857 nsIContent
** target
= aOperation
.mContent
;
858 mozilla::dom::SVGContentCreatorFunction creator
= aOperation
.mCreator
;
859 nsAtom
* name
= aOperation
.mName
;
860 nsHtml5HtmlAttributes
* attributes
= aOperation
.mAttributes
;
861 nsIContent
* intendedParent
=
862 aOperation
.mIntendedParent
? *(aOperation
.mIntendedParent
) : nullptr;
864 // intendedParent == nullptr is a special case where the
865 // intended parent is the document.
866 nsNodeInfoManager
* nodeInfoManager
=
867 intendedParent
? intendedParent
->OwnerDoc()->NodeInfoManager()
868 : mBuilder
->GetNodeInfoManager();
870 *target
= CreateSVGElement(name
, attributes
, aOperation
.mFromNetwork
,
871 nodeInfoManager
, mBuilder
, creator
);
875 nsresult
operator()(const opCreateMathMLElement
& aOperation
) {
876 nsIContent
** target
= aOperation
.mContent
;
877 nsAtom
* name
= aOperation
.mName
;
878 nsHtml5HtmlAttributes
* attributes
= aOperation
.mAttributes
;
879 nsIContent
* intendedParent
=
880 aOperation
.mIntendedParent
? *(aOperation
.mIntendedParent
) : nullptr;
882 // intendedParent == nullptr is a special case where the
883 // intended parent is the document.
884 nsNodeInfoManager
* nodeInfoManager
=
885 intendedParent
? intendedParent
->OwnerDoc()->NodeInfoManager()
886 : mBuilder
->GetNodeInfoManager();
889 CreateMathMLElement(name
, attributes
, nodeInfoManager
, mBuilder
);
893 nsresult
operator()(const opSetFormElement
& aOperation
) {
894 SetFormElement(*(aOperation
.mContent
), *(aOperation
.mFormElement
));
898 nsresult
operator()(const opAppendText
& aOperation
) {
899 nsIContent
* parent
= *aOperation
.mParent
;
900 char16_t
* buffer
= aOperation
.mBuffer
;
901 uint32_t length
= aOperation
.mLength
;
902 return AppendText(buffer
, length
, parent
, mBuilder
);
905 nsresult
operator()(const opFosterParentText
& aOperation
) {
906 nsIContent
* stackParent
= *aOperation
.mStackParent
;
907 char16_t
* buffer
= aOperation
.mBuffer
;
908 uint32_t length
= aOperation
.mLength
;
909 nsIContent
* table
= *aOperation
.mTable
;
910 return FosterParentText(stackParent
, buffer
, length
, table
, mBuilder
);
913 nsresult
operator()(const opAppendComment
& aOperation
) {
914 nsIContent
* parent
= *aOperation
.mParent
;
915 char16_t
* buffer
= aOperation
.mBuffer
;
916 uint32_t length
= aOperation
.mLength
;
917 return AppendComment(parent
, buffer
, length
, mBuilder
);
920 nsresult
operator()(const opAppendCommentToDocument
& aOperation
) {
921 char16_t
* buffer
= aOperation
.mBuffer
;
922 int32_t length
= aOperation
.mLength
;
923 return AppendCommentToDocument(buffer
, length
, mBuilder
);
926 nsresult
operator()(const opAppendDoctypeToDocument
& aOperation
) {
927 nsAtom
* name
= aOperation
.mName
;
928 nsHtml5TreeOperationStringPair
* pair
= aOperation
.mStringPair
;
931 pair
->Get(publicId
, systemId
);
932 return AppendDoctypeToDocument(name
, publicId
, systemId
, mBuilder
);
935 nsresult
operator()(const opGetDocumentFragmentForTemplate
& aOperation
) {
936 nsIContent
* node
= *(aOperation
.mTemplate
);
937 *(aOperation
.mFragHandle
) = GetDocumentFragmentForTemplate(node
);
941 nsresult
operator()(const opGetFosterParent
& aOperation
) {
942 nsIContent
* table
= *(aOperation
.mTable
);
943 nsIContent
* stackParent
= *(aOperation
.mStackParent
);
944 nsIContent
* fosterParent
= GetFosterParent(table
, stackParent
);
945 *aOperation
.mParentHandle
= fosterParent
;
949 nsresult
operator()(const opMarkAsBroken
& aOperation
) {
950 return aOperation
.mResult
;
953 nsresult
operator()(const opRunScript
& aOperation
) {
954 nsIContent
* node
= *(aOperation
.mElement
);
955 nsAHtml5TreeBuilderState
* snapshot
= aOperation
.mBuilderState
;
957 mBuilder
->InitializeDocWriteParserState(snapshot
,
958 aOperation
.mLineNumber
);
960 *mScriptElement
= node
;
964 nsresult
operator()(const opRunScriptAsyncDefer
& aOperation
) {
965 mBuilder
->RunScript(*(aOperation
.mElement
));
969 nsresult
operator()(const opPreventScriptExecution
& aOperation
) {
970 PreventScriptExecution(*(aOperation
.mElement
));
974 nsresult
operator()(const opDoneAddingChildren
& aOperation
) {
975 nsIContent
* node
= *(aOperation
.mElement
);
976 node
->DoneAddingChildren(node
->HasParserNotified());
980 nsresult
operator()(const opDoneCreatingElement
& aOperation
) {
981 DoneCreatingElement(*(aOperation
.mElement
));
985 nsresult
operator()(const opUpdateCharsetSource
& aOperation
) {
986 mBuilder
->UpdateCharsetSource(aOperation
.mCharsetSource
);
990 nsresult
operator()(const opCharsetSwitchTo
& aOperation
) {
991 auto encoding
= WrapNotNull(aOperation
.mEncoding
);
992 mBuilder
->NeedsCharsetSwitchTo(encoding
, aOperation
.mCharsetSource
,
993 (uint32_t)aOperation
.mLineNumber
);
997 nsresult
operator()(const opUpdateStyleSheet
& aOperation
) {
998 mBuilder
->UpdateStyleSheet(*(aOperation
.mElement
));
1002 nsresult
operator()(const opProcessOfflineManifest
& aOperation
) {
1003 // TODO: remove this
1007 nsresult
operator()(const opMarkMalformedIfScript
& aOperation
) {
1008 MarkMalformedIfScript(*(aOperation
.mElement
));
1012 nsresult
operator()(const opStreamEnded
& aOperation
) {
1013 *mStreamEnded
= true;
1017 nsresult
operator()(const opSetStyleLineNumber
& aOperation
) {
1018 nsIContent
* node
= *(aOperation
.mContent
);
1019 if (auto* linkStyle
= dom::LinkStyle::FromNode(*node
)) {
1020 linkStyle
->SetLineNumber(aOperation
.mLineNumber
);
1022 MOZ_ASSERT(nsNameSpaceManager::GetInstance()->mSVGDisabled
,
1023 "Node didn't QI to style, but SVG wasn't disabled.");
1028 nsresult
operator()(
1029 const opSetScriptLineAndColumnNumberAndFreeze
& aOperation
) {
1030 nsIContent
* node
= *(aOperation
.mContent
);
1031 nsCOMPtr
<nsIScriptElement
> sele
= do_QueryInterface(node
);
1033 sele
->SetScriptLineNumber(aOperation
.mLineNumber
);
1034 sele
->SetScriptColumnNumber(aOperation
.mColumnNumber
);
1035 sele
->FreezeExecutionAttrs(node
->OwnerDoc());
1037 MOZ_ASSERT(nsNameSpaceManager::GetInstance()->mSVGDisabled
,
1038 "Node didn't QI to script, but SVG wasn't disabled.");
1043 nsresult
operator()(const opSvgLoad
& aOperation
) {
1044 SvgLoad(*(aOperation
.mElement
));
1048 nsresult
operator()(const opMaybeComplainAboutCharset
& aOperation
) {
1049 char* msgId
= aOperation
.mMsgId
;
1050 bool error
= aOperation
.mError
;
1051 int32_t lineNumber
= aOperation
.mLineNumber
;
1052 mBuilder
->MaybeComplainAboutCharset(msgId
, error
, (uint32_t)lineNumber
);
1056 nsresult
operator()(const opMaybeComplainAboutDeepTree
& aOperation
) {
1057 mBuilder
->MaybeComplainAboutDeepTree((uint32_t)aOperation
.mLineNumber
);
1061 nsresult
operator()(const opAddClass
& aOperation
) {
1062 Element
* element
= (*(aOperation
.mElement
))->AsElement();
1063 char16_t
* str
= aOperation
.mClass
;
1064 nsDependentString
depStr(str
);
1065 // See viewsource.css for the possible classes
1067 element
->GetAttr(nsGkAtoms::_class
, klass
);
1068 if (!klass
.IsEmpty()) {
1070 klass
.Append(depStr
);
1071 element
->SetAttr(kNameSpaceID_None
, nsGkAtoms::_class
, klass
, true);
1073 element
->SetAttr(kNameSpaceID_None
, nsGkAtoms::_class
, depStr
, true);
1078 nsresult
operator()(const opAddViewSourceHref
& aOperation
) {
1079 Element
* element
= (*aOperation
.mElement
)->AsElement();
1080 char16_t
* buffer
= aOperation
.mBuffer
;
1081 int32_t length
= aOperation
.mLength
;
1082 nsDependentString
relative(buffer
, length
);
1084 Document
* doc
= mBuilder
->GetDocument();
1086 auto encoding
= doc
->GetDocumentCharacterSet();
1087 nsCOMPtr
<nsIURI
> uri
;
1088 nsresult rv
= NS_NewURI(getter_AddRefs(uri
), relative
, encoding
,
1089 mBuilder
->GetViewSourceBaseURI());
1090 NS_ENSURE_SUCCESS(rv
, NS_OK
);
1092 // Reuse the fix for bug 467852
1093 // URLs that execute script (e.g. "javascript:" URLs) should just be
1094 // ignored. There's nothing reasonable we can do with them, and allowing
1095 // them to execute in the context of the view-source window presents a
1096 // security risk. Just return the empty string in this case.
1097 bool openingExecutesScript
= false;
1098 rv
= NS_URIChainHasFlags(uri
,
1099 nsIProtocolHandler::URI_OPENING_EXECUTES_SCRIPT
,
1100 &openingExecutesScript
);
1101 if (NS_FAILED(rv
) || openingExecutesScript
) {
1105 nsAutoCString viewSourceUrl
;
1107 // URLs that return data (e.g. "http:" URLs) should be prefixed with
1108 // "view-source:". URLs that don't return data should just be returned
1110 if (!nsContentUtils::IsExternalProtocol(uri
)) {
1111 viewSourceUrl
.AssignLiteral("view-source:");
1115 rv
= uri
->GetSpec(spec
);
1116 NS_ENSURE_SUCCESS(rv
, rv
);
1118 viewSourceUrl
.Append(spec
);
1121 CopyUTF8toUTF16(viewSourceUrl
, utf16
);
1123 element
->SetAttr(kNameSpaceID_None
, nsGkAtoms::href
, utf16
, true);
1127 nsresult
operator()(const opAddViewSourceBase
& aOperation
) {
1128 nsDependentString
baseUrl(aOperation
.mBuffer
, aOperation
.mLength
);
1129 mBuilder
->AddBase(baseUrl
);
1133 nsresult
operator()(const opAddErrorType
& aOperation
) {
1134 Element
* element
= (*(aOperation
.mElement
))->AsElement();
1135 char* msgId
= aOperation
.mMsgId
;
1136 nsAtom
* atom
= aOperation
.mName
;
1137 nsAtom
* otherAtom
= aOperation
.mOther
;
1138 // See viewsource.css for the possible classes in addition to "error".
1140 element
->GetAttr(nsGkAtoms::_class
, klass
);
1141 if (!klass
.IsEmpty()) {
1142 klass
.AppendLiteral(" error");
1143 element
->SetAttr(kNameSpaceID_None
, nsGkAtoms::_class
, klass
, true);
1145 element
->SetAttr(kNameSpaceID_None
, nsGkAtoms::_class
, u
"error"_ns
,
1150 nsAutoString message
;
1152 rv
= nsContentUtils::FormatLocalizedString(
1153 message
, nsContentUtils::eHTMLPARSER_PROPERTIES
, msgId
,
1154 nsDependentAtomString(atom
), nsDependentAtomString(otherAtom
));
1155 NS_ENSURE_SUCCESS(rv
, NS_OK
);
1157 rv
= nsContentUtils::FormatLocalizedString(
1158 message
, nsContentUtils::eHTMLPARSER_PROPERTIES
, msgId
,
1159 nsDependentAtomString(atom
));
1160 NS_ENSURE_SUCCESS(rv
, NS_OK
);
1162 rv
= nsContentUtils::GetLocalizedString(
1163 nsContentUtils::eHTMLPARSER_PROPERTIES
, msgId
, message
);
1164 NS_ENSURE_SUCCESS(rv
, NS_OK
);
1168 element
->GetAttr(nsGkAtoms::title
, title
);
1169 if (!title
.IsEmpty()) {
1171 title
.Append(message
);
1172 element
->SetAttr(kNameSpaceID_None
, nsGkAtoms::title
, title
, true);
1174 element
->SetAttr(kNameSpaceID_None
, nsGkAtoms::title
, message
, true);
1179 nsresult
operator()(const opAddLineNumberId
& aOperation
) {
1180 Element
* element
= (*(aOperation
.mElement
))->AsElement();
1181 int32_t lineNumber
= aOperation
.mLineNumber
;
1182 nsAutoString
val(u
"line"_ns
);
1183 val
.AppendInt(lineNumber
);
1184 element
->SetAttr(kNameSpaceID_None
, nsGkAtoms::id
, val
, true);
1188 nsresult
operator()(const opStartLayout
& aOperation
) {
1189 mBuilder
->StartLayout(
1190 mInterrupted
); // this causes a notification flush anyway
1194 nsresult
operator()(const opEnableEncodingMenu
& aOperation
) {
1195 Document
* doc
= mBuilder
->GetDocument();
1196 doc
->EnableEncodingMenu();
1200 nsresult
operator()(const uninitialized
& aOperation
) {
1201 MOZ_CRASH("uninitialized");
1206 return mOperation
.match(TreeOperationMatcher(aBuilder
, aScriptElement
,
1207 aInterrupted
, aStreamEnded
));