Bug 1690340 - Part 1: Hide all the panel tools in the developer tools menu. r=jdescottes
[gecko.git] / parser / html / nsHtml5TreeOperation.cpp
blobd29b5d2ff739790762e38dce37a4a3344c442c1b
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/DocumentType.h"
14 #include "mozilla/dom/Element.h"
15 #include "mozilla/dom/LinkStyle.h"
16 #include "mozilla/dom/HTMLFormElement.h"
17 #include "mozilla/dom/HTMLImageElement.h"
18 #include "mozilla/dom/HTMLTemplateElement.h"
19 #include "mozilla/dom/MutationObservers.h"
20 #include "mozilla/dom/Text.h"
21 #include "nsAttrName.h"
22 #include "nsContentCreatorFunctions.h"
23 #include "nsContentUtils.h"
24 #include "nsDocElementCreatedNotificationRunner.h"
25 #include "nsEscape.h"
26 #include "nsHtml5AutoPauseUpdate.h"
27 #include "nsHtml5DocumentMode.h"
28 #include "nsHtml5HtmlAttributes.h"
29 #include "nsHtml5SVGLoadDispatcher.h"
30 #include "nsHtml5TreeBuilder.h"
31 #include "nsIDTD.h"
32 #include "nsIFormControl.h"
33 #include "nsIMutationObserver.h"
34 #include "nsINode.h"
35 #include "nsIProtocolHandler.h"
36 #include "nsIScriptElement.h"
37 #include "nsISupportsImpl.h"
38 #include "nsIURI.h"
39 #include "nsNetUtil.h"
40 #include "nsTextNode.h"
42 using namespace mozilla;
43 using namespace mozilla::dom;
44 using mozilla::dom::Document;
46 /**
47 * Helper class that opens a notification batch if the current doc
48 * is different from the executor doc.
50 class MOZ_STACK_CLASS nsHtml5OtherDocUpdate {
51 public:
52 nsHtml5OtherDocUpdate(Document* aCurrentDoc, Document* aExecutorDoc) {
53 MOZ_ASSERT(aCurrentDoc, "Node has no doc?");
54 MOZ_ASSERT(aExecutorDoc, "Executor has no doc?");
55 if (MOZ_LIKELY(aCurrentDoc == aExecutorDoc)) {
56 mDocument = nullptr;
57 } else {
58 mDocument = aCurrentDoc;
59 aCurrentDoc->BeginUpdate();
63 ~nsHtml5OtherDocUpdate() {
64 if (MOZ_UNLIKELY(mDocument)) {
65 mDocument->EndUpdate();
69 private:
70 RefPtr<Document> mDocument;
73 nsHtml5TreeOperation::nsHtml5TreeOperation() : mOperation(uninitialized()) {
74 MOZ_COUNT_CTOR(nsHtml5TreeOperation);
77 nsHtml5TreeOperation::~nsHtml5TreeOperation() {
78 MOZ_COUNT_DTOR(nsHtml5TreeOperation);
80 struct TreeOperationMatcher {
81 void operator()(const opAppend& aOperation) {}
83 void operator()(const opDetach& aOperation) {}
85 void operator()(const opAppendChildrenToNewParent& aOperation) {}
87 void operator()(const opFosterParent& aOperation) {}
89 void operator()(const opAppendToDocument& aOperation) {}
91 void operator()(const opAddAttributes& aOperation) {
92 delete aOperation.mAttributes;
95 void operator()(const nsHtml5DocumentMode& aMode) {}
97 void operator()(const opCreateHTMLElement& aOperation) {
98 aOperation.mName->Release();
99 delete aOperation.mAttributes;
102 void operator()(const opCreateSVGElement& aOperation) {
103 aOperation.mName->Release();
104 delete aOperation.mAttributes;
107 void operator()(const opCreateMathMLElement& aOperation) {
108 aOperation.mName->Release();
109 delete aOperation.mAttributes;
112 void operator()(const opSetFormElement& aOperation) {}
114 void operator()(const opAppendText& aOperation) {
115 delete[] aOperation.mBuffer;
118 void operator()(const opFosterParentText& aOperation) {
119 delete[] aOperation.mBuffer;
122 void operator()(const opAppendComment& aOperation) {
123 delete[] aOperation.mBuffer;
126 void operator()(const opAppendCommentToDocument& aOperation) {
127 delete[] aOperation.mBuffer;
130 void operator()(const opAppendDoctypeToDocument& aOperation) {
131 aOperation.mName->Release();
132 delete aOperation.mStringPair;
135 void operator()(const opGetDocumentFragmentForTemplate& aOperation) {}
137 void operator()(const opGetFosterParent& aOperation) {}
139 void operator()(const opMarkAsBroken& aOperation) {}
141 void operator()(const opRunScript& aOperation) {}
143 void operator()(const opRunScriptAsyncDefer& aOperation) {}
145 void operator()(const opPreventScriptExecution& aOperation) {}
147 void operator()(const opDoneAddingChildren& aOperation) {}
149 void operator()(const opDoneCreatingElement& aOperation) {}
151 void operator()(const opSetDocumentCharset& aOperation) {}
153 void operator()(const opCharsetSwitchTo& aOperation) {}
155 void operator()(const opUpdateStyleSheet& aOperation) {}
157 void operator()(const opProcessOfflineManifest& aOperation) {
158 free(aOperation.mUrl);
161 void operator()(const opMarkMalformedIfScript& aOperation) {}
163 void operator()(const opStreamEnded& aOperation) {}
165 void operator()(const opSetStyleLineNumber& aOperation) {}
167 void operator()(const opSetScriptLineNumberAndFreeze& aOperation) {}
169 void operator()(const opSvgLoad& aOperation) {}
171 void operator()(const opMaybeComplainAboutCharset& aOperation) {}
173 void operator()(const opMaybeComplainAboutDeepTree& aOperation) {}
175 void operator()(const opAddClass& aOperation) {}
177 void operator()(const opAddViewSourceHref& aOperation) {
178 delete[] aOperation.mBuffer;
181 void operator()(const opAddViewSourceBase& aOperation) {
182 delete[] aOperation.mBuffer;
185 void operator()(const opAddErrorType& aOperation) {
186 if (aOperation.mName) {
187 aOperation.mName->Release();
189 if (aOperation.mOther) {
190 aOperation.mOther->Release();
194 void operator()(const opAddLineNumberId& aOperation) {}
196 void operator()(const opStartLayout& aOperation) {}
198 void operator()(const opEnableEncodingMenu& aOperation) {}
200 void operator()(const uninitialized& aOperation) {
201 NS_WARNING("Uninitialized tree op.");
205 mOperation.match(TreeOperationMatcher());
208 nsresult nsHtml5TreeOperation::AppendTextToTextNode(
209 const char16_t* aBuffer, uint32_t aLength, dom::Text* aTextNode,
210 nsHtml5DocumentBuilder* aBuilder) {
211 MOZ_ASSERT(aTextNode, "Got null text node.");
212 MOZ_ASSERT(aBuilder);
213 MOZ_ASSERT(aBuilder->IsInDocUpdate());
214 uint32_t oldLength = aTextNode->TextLength();
215 CharacterDataChangeInfo info = {true, oldLength, oldLength, aLength};
216 MutationObservers::NotifyCharacterDataWillChange(aTextNode, info);
218 nsresult rv = aTextNode->AppendText(aBuffer, aLength, false);
219 NS_ENSURE_SUCCESS(rv, rv);
221 MutationObservers::NotifyCharacterDataChanged(aTextNode, info);
222 return rv;
225 nsresult nsHtml5TreeOperation::AppendText(const char16_t* aBuffer,
226 uint32_t aLength, nsIContent* aParent,
227 nsHtml5DocumentBuilder* aBuilder) {
228 nsresult rv = NS_OK;
229 nsIContent* lastChild = aParent->GetLastChild();
230 if (lastChild && lastChild->IsText()) {
231 nsHtml5OtherDocUpdate update(aParent->OwnerDoc(), aBuilder->GetDocument());
232 return AppendTextToTextNode(aBuffer, aLength, lastChild->GetAsText(),
233 aBuilder);
236 nsNodeInfoManager* nodeInfoManager = aParent->OwnerDoc()->NodeInfoManager();
237 RefPtr<nsTextNode> text = new (nodeInfoManager) nsTextNode(nodeInfoManager);
238 NS_ASSERTION(text, "Infallible malloc failed?");
239 rv = text->SetText(aBuffer, aLength, false);
240 NS_ENSURE_SUCCESS(rv, rv);
242 return Append(text, aParent, aBuilder);
245 nsresult nsHtml5TreeOperation::Append(nsIContent* aNode, nsIContent* aParent,
246 nsHtml5DocumentBuilder* aBuilder) {
247 MOZ_ASSERT(aBuilder);
248 MOZ_ASSERT(aBuilder->IsInDocUpdate());
249 nsresult rv = NS_OK;
250 nsHtml5OtherDocUpdate update(aParent->OwnerDoc(), aBuilder->GetDocument());
251 rv = aParent->AppendChildTo(aNode, false);
252 if (NS_SUCCEEDED(rv)) {
253 aNode->SetParserHasNotified();
254 MutationObservers::NotifyContentAppended(aParent, aNode);
256 return rv;
259 nsresult nsHtml5TreeOperation::Append(nsIContent* aNode, nsIContent* aParent,
260 mozilla::dom::FromParser aFromParser,
261 nsHtml5DocumentBuilder* aBuilder) {
262 Maybe<nsHtml5AutoPauseUpdate> autoPause;
263 Maybe<dom::AutoCEReaction> autoCEReaction;
264 dom::DocGroup* docGroup = aParent->OwnerDoc()->GetDocGroup();
265 if (docGroup && aFromParser != mozilla::dom::FROM_PARSER_FRAGMENT) {
266 autoCEReaction.emplace(docGroup->CustomElementReactionsStack(), nullptr);
268 nsresult rv = Append(aNode, aParent, aBuilder);
269 // Pause the parser only when there are reactions to be invoked to avoid
270 // pausing parsing too aggressive.
271 if (autoCEReaction.isSome() && docGroup &&
272 docGroup->CustomElementReactionsStack()
273 ->IsElementQueuePushedForCurrentRecursionDepth()) {
274 autoPause.emplace(aBuilder);
276 return rv;
279 nsresult nsHtml5TreeOperation::AppendToDocument(
280 nsIContent* aNode, nsHtml5DocumentBuilder* aBuilder) {
281 MOZ_ASSERT(aBuilder);
282 MOZ_ASSERT(aBuilder->GetDocument() == aNode->OwnerDoc());
283 MOZ_ASSERT(aBuilder->IsInDocUpdate());
284 nsresult rv = NS_OK;
286 Document* doc = aBuilder->GetDocument();
287 rv = doc->AppendChildTo(aNode, false);
288 if (rv == NS_ERROR_DOM_HIERARCHY_REQUEST_ERR) {
289 aNode->SetParserHasNotified();
290 return NS_OK;
292 NS_ENSURE_SUCCESS(rv, rv);
293 aNode->SetParserHasNotified();
294 MutationObservers::NotifyContentInserted(doc, aNode);
296 NS_ASSERTION(!nsContentUtils::IsSafeToRunScript(),
297 "Someone forgot to block scripts");
298 if (aNode->IsElement()) {
299 nsContentUtils::AddScriptRunner(
300 new nsDocElementCreatedNotificationRunner(doc));
302 return rv;
305 static bool IsElementOrTemplateContent(nsINode* aNode) {
306 if (aNode) {
307 if (aNode->IsElement()) {
308 return true;
310 if (aNode->IsDocumentFragment()) {
311 // Check if the node is a template content.
312 nsIContent* fragHost = aNode->AsDocumentFragment()->GetHost();
313 if (fragHost && fragHost->IsTemplateElement()) {
314 return true;
318 return false;
321 void nsHtml5TreeOperation::Detach(nsIContent* aNode,
322 nsHtml5DocumentBuilder* aBuilder) {
323 MOZ_ASSERT(aBuilder);
324 MOZ_ASSERT(aBuilder->IsInDocUpdate());
325 nsCOMPtr<nsINode> parent = aNode->GetParentNode();
326 if (parent) {
327 nsHtml5OtherDocUpdate update(parent->OwnerDoc(), aBuilder->GetDocument());
328 parent->RemoveChildNode(aNode, true);
332 nsresult nsHtml5TreeOperation::AppendChildrenToNewParent(
333 nsIContent* aNode, nsIContent* aParent, nsHtml5DocumentBuilder* aBuilder) {
334 MOZ_ASSERT(aBuilder);
335 MOZ_ASSERT(aBuilder->IsInDocUpdate());
336 nsHtml5OtherDocUpdate update(aParent->OwnerDoc(), aBuilder->GetDocument());
338 bool didAppend = false;
339 while (aNode->HasChildren()) {
340 nsCOMPtr<nsIContent> child = aNode->GetFirstChild();
341 aNode->RemoveChildNode(child, true);
342 nsresult rv = aParent->AppendChildTo(child, false);
343 NS_ENSURE_SUCCESS(rv, rv);
344 didAppend = true;
346 if (didAppend) {
347 MutationObservers::NotifyContentAppended(aParent, aParent->GetLastChild());
349 return NS_OK;
352 nsresult nsHtml5TreeOperation::FosterParent(nsIContent* aNode,
353 nsIContent* aParent,
354 nsIContent* aTable,
355 nsHtml5DocumentBuilder* aBuilder) {
356 MOZ_ASSERT(aBuilder);
357 MOZ_ASSERT(aBuilder->IsInDocUpdate());
358 nsIContent* foster = aTable->GetParent();
360 if (IsElementOrTemplateContent(foster)) {
361 nsHtml5OtherDocUpdate update(foster->OwnerDoc(), aBuilder->GetDocument());
363 nsresult rv = foster->InsertChildBefore(aNode, aTable, false);
364 NS_ENSURE_SUCCESS(rv, rv);
365 MutationObservers::NotifyContentInserted(foster, aNode);
366 return rv;
369 return Append(aNode, aParent, aBuilder);
372 nsresult nsHtml5TreeOperation::AddAttributes(nsIContent* aNode,
373 nsHtml5HtmlAttributes* aAttributes,
374 nsHtml5DocumentBuilder* aBuilder) {
375 dom::Element* node = aNode->AsElement();
376 nsHtml5OtherDocUpdate update(node->OwnerDoc(), aBuilder->GetDocument());
378 int32_t len = aAttributes->getLength();
379 for (int32_t i = len; i > 0;) {
380 --i;
381 nsAtom* localName = aAttributes->getLocalNameNoBoundsCheck(i);
382 int32_t nsuri = aAttributes->getURINoBoundsCheck(i);
383 if (!node->HasAttr(nsuri, localName)) {
384 nsString value; // Not Auto, because using it to hold nsStringBuffer*
385 aAttributes->getValueNoBoundsCheck(i).ToString(value);
386 node->SetAttr(nsuri, localName, aAttributes->getPrefixNoBoundsCheck(i),
387 value, true);
388 // XXX what to do with nsresult?
391 return NS_OK;
394 void nsHtml5TreeOperation::SetHTMLElementAttributes(
395 dom::Element* aElement, nsAtom* aName, nsHtml5HtmlAttributes* aAttributes) {
396 int32_t len = aAttributes->getLength();
397 for (int32_t i = 0; i < len; i++) {
398 nsHtml5String val = aAttributes->getValueNoBoundsCheck(i);
399 nsAtom* klass = val.MaybeAsAtom();
400 if (klass) {
401 aElement->SetSingleClassFromParser(klass);
402 } else {
403 nsAtom* localName = aAttributes->getLocalNameNoBoundsCheck(i);
404 nsAtom* prefix = aAttributes->getPrefixNoBoundsCheck(i);
405 int32_t nsuri = aAttributes->getURINoBoundsCheck(i);
407 nsString value; // Not Auto, because using it to hold nsStringBuffer*
408 val.ToString(value);
409 if (nsGkAtoms::a == aName && nsGkAtoms::name == localName) {
410 // This is an HTML5-incompliant Geckoism.
411 // Remove when fixing bug 582361
412 NS_ConvertUTF16toUTF8 cname(value);
413 NS_ConvertUTF8toUTF16 uv(nsUnescape(cname.BeginWriting()));
414 aElement->SetAttr(nsuri, localName, prefix, uv, false);
415 } else {
416 aElement->SetAttr(nsuri, localName, prefix, value, false);
422 nsIContent* nsHtml5TreeOperation::CreateHTMLElement(
423 nsAtom* aName, nsHtml5HtmlAttributes* aAttributes,
424 mozilla::dom::FromParser aFromParser, nsNodeInfoManager* aNodeInfoManager,
425 nsHtml5DocumentBuilder* aBuilder,
426 mozilla::dom::HTMLContentCreatorFunction aCreator) {
427 RefPtr<dom::NodeInfo> nodeInfo = aNodeInfoManager->GetNodeInfo(
428 aName, nullptr, kNameSpaceID_XHTML, nsINode::ELEMENT_NODE);
429 NS_ASSERTION(nodeInfo, "Got null nodeinfo.");
431 dom::Element* newContent = nullptr;
432 Document* document = nodeInfo->GetDocument();
433 bool willExecuteScript = false;
434 bool isCustomElement = false;
435 RefPtr<nsAtom> isAtom;
436 dom::CustomElementDefinition* definition = nullptr;
438 if (aAttributes) {
439 nsHtml5String is = aAttributes->getValue(nsHtml5AttributeName::ATTR_IS);
440 if (is) {
441 nsAutoString isValue;
442 is.ToString(isValue);
443 isAtom = NS_Atomize(isValue);
447 isCustomElement = (aCreator == NS_NewCustomElement || isAtom);
448 if (isCustomElement && aFromParser != dom::FROM_PARSER_FRAGMENT) {
449 RefPtr<nsAtom> tagAtom = nodeInfo->NameAtom();
450 RefPtr<nsAtom> typeAtom =
451 (aCreator == NS_NewCustomElement) ? tagAtom : isAtom;
453 MOZ_ASSERT(nodeInfo->NameAtom()->Equals(nodeInfo->LocalName()));
454 definition = nsContentUtils::LookupCustomElementDefinition(
455 document, nodeInfo->NameAtom(), nodeInfo->NamespaceID(), typeAtom);
457 if (definition) {
458 willExecuteScript = true;
462 if (willExecuteScript) { // This will cause custom element constructors to
463 // run
464 mozilla::dom::AutoSetThrowOnDynamicMarkupInsertionCounter
465 throwOnDynamicMarkupInsertionCounter(document);
466 nsHtml5AutoPauseUpdate autoPauseContentUpdate(aBuilder);
467 { nsAutoMicroTask mt; }
468 dom::AutoCEReaction autoCEReaction(
469 document->GetDocGroup()->CustomElementReactionsStack(), nullptr);
471 nsCOMPtr<dom::Element> newElement;
472 NS_NewHTMLElement(getter_AddRefs(newElement), nodeInfo.forget(),
473 aFromParser, isAtom, definition);
475 MOZ_ASSERT(newElement, "Element creation created null pointer.");
476 newContent = newElement;
477 aBuilder->HoldElement(newElement.forget());
479 if (MOZ_UNLIKELY(aName == nsGkAtoms::style || aName == nsGkAtoms::link)) {
480 if (auto* linkStyle = dom::LinkStyle::FromNode(*newContent)) {
481 linkStyle->SetEnableUpdates(false);
485 if (!aAttributes) {
486 return newContent;
489 SetHTMLElementAttributes(newContent, aName, aAttributes);
490 } else {
491 nsCOMPtr<dom::Element> newElement;
493 if (isCustomElement) {
494 NS_NewHTMLElement(getter_AddRefs(newElement), nodeInfo.forget(),
495 aFromParser, isAtom, definition);
496 } else {
497 newElement = aCreator(nodeInfo.forget(), aFromParser);
500 MOZ_ASSERT(newElement, "Element creation created null pointer.");
502 newContent = newElement;
503 aBuilder->HoldElement(newElement.forget());
505 if (MOZ_UNLIKELY(aName == nsGkAtoms::style || aName == nsGkAtoms::link)) {
506 if (auto* linkStyle = dom::LinkStyle::FromNode(*newContent)) {
507 linkStyle->SetEnableUpdates(false);
511 if (!aAttributes) {
512 return newContent;
515 SetHTMLElementAttributes(newContent, aName, aAttributes);
518 return newContent;
521 nsIContent* nsHtml5TreeOperation::CreateSVGElement(
522 nsAtom* aName, nsHtml5HtmlAttributes* aAttributes,
523 mozilla::dom::FromParser aFromParser, nsNodeInfoManager* aNodeInfoManager,
524 nsHtml5DocumentBuilder* aBuilder,
525 mozilla::dom::SVGContentCreatorFunction aCreator) {
526 nsCOMPtr<nsIContent> newElement;
527 if (MOZ_LIKELY(aNodeInfoManager->SVGEnabled())) {
528 RefPtr<dom::NodeInfo> nodeInfo = aNodeInfoManager->GetNodeInfo(
529 aName, nullptr, kNameSpaceID_SVG, nsINode::ELEMENT_NODE);
530 MOZ_ASSERT(nodeInfo, "Got null nodeinfo.");
532 mozilla::DebugOnly<nsresult> rv =
533 aCreator(getter_AddRefs(newElement), nodeInfo.forget(), aFromParser);
534 MOZ_ASSERT(NS_SUCCEEDED(rv) && newElement);
535 } else {
536 RefPtr<dom::NodeInfo> nodeInfo = aNodeInfoManager->GetNodeInfo(
537 aName, nullptr, kNameSpaceID_disabled_SVG, nsINode::ELEMENT_NODE);
538 MOZ_ASSERT(nodeInfo, "Got null nodeinfo.");
540 // The mismatch between NS_NewXMLElement and SVGContentCreatorFunction
541 // argument types is annoying.
542 nsCOMPtr<dom::Element> xmlElement;
543 mozilla::DebugOnly<nsresult> rv =
544 NS_NewXMLElement(getter_AddRefs(xmlElement), nodeInfo.forget());
545 MOZ_ASSERT(NS_SUCCEEDED(rv) && xmlElement);
546 newElement = xmlElement;
549 dom::Element* newContent = newElement->AsElement();
550 aBuilder->HoldElement(newElement.forget());
552 if (MOZ_UNLIKELY(aName == nsGkAtoms::style)) {
553 if (auto* linkStyle = dom::LinkStyle::FromNode(*newContent)) {
554 linkStyle->SetEnableUpdates(false);
558 if (!aAttributes) {
559 return newContent;
562 int32_t len = aAttributes->getLength();
563 for (int32_t i = 0; i < len; i++) {
564 nsHtml5String val = aAttributes->getValueNoBoundsCheck(i);
565 nsAtom* klass = val.MaybeAsAtom();
566 if (klass) {
567 newContent->SetSingleClassFromParser(klass);
568 } else {
569 nsAtom* localName = aAttributes->getLocalNameNoBoundsCheck(i);
570 nsAtom* prefix = aAttributes->getPrefixNoBoundsCheck(i);
571 int32_t nsuri = aAttributes->getURINoBoundsCheck(i);
573 nsString value; // Not Auto, because using it to hold nsStringBuffer*
574 val.ToString(value);
575 newContent->SetAttr(nsuri, localName, prefix, value, false);
578 return newContent;
581 nsIContent* nsHtml5TreeOperation::CreateMathMLElement(
582 nsAtom* aName, nsHtml5HtmlAttributes* aAttributes,
583 nsNodeInfoManager* aNodeInfoManager, nsHtml5DocumentBuilder* aBuilder) {
584 nsCOMPtr<dom::Element> newElement;
585 if (MOZ_LIKELY(aNodeInfoManager->MathMLEnabled())) {
586 RefPtr<dom::NodeInfo> nodeInfo = aNodeInfoManager->GetNodeInfo(
587 aName, nullptr, kNameSpaceID_MathML, nsINode::ELEMENT_NODE);
588 NS_ASSERTION(nodeInfo, "Got null nodeinfo.");
590 mozilla::DebugOnly<nsresult> rv =
591 NS_NewMathMLElement(getter_AddRefs(newElement), nodeInfo.forget());
592 MOZ_ASSERT(NS_SUCCEEDED(rv) && newElement);
593 } else {
594 RefPtr<dom::NodeInfo> nodeInfo = aNodeInfoManager->GetNodeInfo(
595 aName, nullptr, kNameSpaceID_disabled_MathML, nsINode::ELEMENT_NODE);
596 NS_ASSERTION(nodeInfo, "Got null nodeinfo.");
598 mozilla::DebugOnly<nsresult> rv =
599 NS_NewXMLElement(getter_AddRefs(newElement), nodeInfo.forget());
600 MOZ_ASSERT(NS_SUCCEEDED(rv) && newElement);
603 dom::Element* newContent = newElement;
604 aBuilder->HoldElement(newElement.forget());
606 if (!aAttributes) {
607 return newContent;
610 int32_t len = aAttributes->getLength();
611 for (int32_t i = 0; i < len; i++) {
612 nsHtml5String val = aAttributes->getValueNoBoundsCheck(i);
613 nsAtom* klass = val.MaybeAsAtom();
614 if (klass) {
615 newContent->SetSingleClassFromParser(klass);
616 } else {
617 nsAtom* localName = aAttributes->getLocalNameNoBoundsCheck(i);
618 nsAtom* prefix = aAttributes->getPrefixNoBoundsCheck(i);
619 int32_t nsuri = aAttributes->getURINoBoundsCheck(i);
621 nsString value; // Not Auto, because using it to hold nsStringBuffer*
622 val.ToString(value);
623 newContent->SetAttr(nsuri, localName, prefix, value, false);
626 return newContent;
629 void nsHtml5TreeOperation::SetFormElement(nsIContent* aNode,
630 nsIContent* aParent) {
631 nsCOMPtr<nsIFormControl> formControl(do_QueryInterface(aNode));
632 RefPtr<dom::HTMLImageElement> domImageElement =
633 dom::HTMLImageElement::FromNodeOrNull(aNode);
634 // NS_ASSERTION(formControl, "Form-associated element did not implement
635 // nsIFormControl.");
636 // TODO: uncomment the above line when img doesn't cause an issue (bug
637 // 1558793)
638 RefPtr<dom::HTMLFormElement> formElement =
639 dom::HTMLFormElement::FromNodeOrNull(aParent);
640 NS_ASSERTION(formElement,
641 "The form element doesn't implement HTMLFormElement.");
642 // Avoid crashing on <img>
643 if (formControl &&
644 !aNode->AsElement()->HasAttr(kNameSpaceID_None, nsGkAtoms::form)) {
645 formControl->SetForm(formElement);
646 } else if (domImageElement) {
647 domImageElement->SetForm(formElement);
651 nsresult nsHtml5TreeOperation::FosterParentText(
652 nsIContent* aStackParent, char16_t* aBuffer, uint32_t aLength,
653 nsIContent* aTable, nsHtml5DocumentBuilder* aBuilder) {
654 MOZ_ASSERT(aBuilder);
655 MOZ_ASSERT(aBuilder->IsInDocUpdate());
656 nsresult rv = NS_OK;
657 nsIContent* foster = aTable->GetParent();
659 if (IsElementOrTemplateContent(foster)) {
660 nsHtml5OtherDocUpdate update(foster->OwnerDoc(), aBuilder->GetDocument());
662 nsIContent* previousSibling = aTable->GetPreviousSibling();
663 if (previousSibling && previousSibling->IsText()) {
664 return AppendTextToTextNode(aBuffer, aLength,
665 previousSibling->GetAsText(), aBuilder);
668 nsNodeInfoManager* nodeInfoManager =
669 aStackParent->OwnerDoc()->NodeInfoManager();
670 RefPtr<nsTextNode> text = new (nodeInfoManager) nsTextNode(nodeInfoManager);
671 NS_ASSERTION(text, "Infallible malloc failed?");
672 rv = text->SetText(aBuffer, aLength, false);
673 NS_ENSURE_SUCCESS(rv, rv);
675 rv = foster->InsertChildBefore(text, aTable, false);
676 NS_ENSURE_SUCCESS(rv, rv);
677 MutationObservers::NotifyContentInserted(foster, text);
678 return rv;
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<dom::Comment> comment =
689 new (nodeInfoManager) dom::Comment(nodeInfoManager);
690 NS_ASSERTION(comment, "Infallible malloc failed?");
691 nsresult rv = comment->SetText(aBuffer, aLength, false);
692 NS_ENSURE_SUCCESS(rv, rv);
694 return Append(comment, aParent, aBuilder);
697 nsresult nsHtml5TreeOperation::AppendCommentToDocument(
698 char16_t* aBuffer, int32_t aLength, nsHtml5DocumentBuilder* aBuilder) {
699 RefPtr<dom::Comment> comment = new (aBuilder->GetNodeInfoManager())
700 dom::Comment(aBuilder->GetNodeInfoManager());
701 NS_ASSERTION(comment, "Infallible malloc failed?");
702 nsresult rv = comment->SetText(aBuffer, aLength, false);
703 NS_ENSURE_SUCCESS(rv, rv);
705 return AppendToDocument(comment, aBuilder);
708 nsresult nsHtml5TreeOperation::AppendDoctypeToDocument(
709 nsAtom* aName, const nsAString& aPublicId, const nsAString& aSystemId,
710 nsHtml5DocumentBuilder* aBuilder) {
711 // Adapted from nsXMLContentSink
712 // Create a new doctype node
713 RefPtr<dom::DocumentType> docType =
714 NS_NewDOMDocumentType(aBuilder->GetNodeInfoManager(), aName, aPublicId,
715 aSystemId, VoidString());
716 return AppendToDocument(docType, aBuilder);
719 nsIContent* nsHtml5TreeOperation::GetDocumentFragmentForTemplate(
720 nsIContent* aNode) {
721 dom::HTMLTemplateElement* tempElem =
722 static_cast<dom::HTMLTemplateElement*>(aNode);
723 RefPtr<dom::DocumentFragment> frag = tempElem->Content();
724 return frag;
727 nsIContent* nsHtml5TreeOperation::GetFosterParent(nsIContent* aTable,
728 nsIContent* aStackParent) {
729 nsIContent* tableParent = aTable->GetParent();
730 return IsElementOrTemplateContent(tableParent) ? tableParent : aStackParent;
733 void nsHtml5TreeOperation::PreventScriptExecution(nsIContent* aNode) {
734 nsCOMPtr<nsIScriptElement> sele = do_QueryInterface(aNode);
735 if (sele) {
736 sele->PreventExecution();
737 } else {
738 MOZ_ASSERT(nsNameSpaceManager::GetInstance()->mSVGDisabled,
739 "Node didn't QI to script, but SVG wasn't disabled.");
743 void nsHtml5TreeOperation::DoneAddingChildren(nsIContent* aNode) {
744 aNode->DoneAddingChildren(aNode->HasParserNotified());
747 void nsHtml5TreeOperation::DoneCreatingElement(nsIContent* aNode) {
748 aNode->DoneCreatingElement();
751 void nsHtml5TreeOperation::SvgLoad(nsIContent* aNode) {
752 nsCOMPtr<nsIRunnable> event = new nsHtml5SVGLoadDispatcher(aNode);
753 if (NS_FAILED(
754 aNode->OwnerDoc()->Dispatch(TaskCategory::Network, event.forget()))) {
755 NS_WARNING("failed to dispatch svg load dispatcher");
759 void nsHtml5TreeOperation::MarkMalformedIfScript(nsIContent* aNode) {
760 nsCOMPtr<nsIScriptElement> sele = do_QueryInterface(aNode);
761 if (sele) {
762 // Make sure to serialize this script correctly, for nice round tripping.
763 sele->SetIsMalformed();
767 nsresult nsHtml5TreeOperation::Perform(nsHtml5TreeOpExecutor* aBuilder,
768 nsIContent** aScriptElement,
769 bool* aInterrupted, bool* aStreamEnded) {
770 struct TreeOperationMatcher {
771 TreeOperationMatcher(nsHtml5TreeOpExecutor* aBuilder,
772 nsIContent** aScriptElement, bool* aInterrupted,
773 bool* aStreamEnded)
774 : mBuilder(aBuilder),
775 mScriptElement(aScriptElement),
776 mInterrupted(aInterrupted),
777 mStreamEnded(aStreamEnded) {}
779 nsHtml5TreeOpExecutor* mBuilder;
780 nsIContent** mScriptElement;
781 bool* mInterrupted;
782 bool* mStreamEnded;
784 nsresult operator()(const opAppend& aOperation) {
785 return Append(*(aOperation.mChild), *(aOperation.mParent),
786 aOperation.mFromNetwork, mBuilder);
789 nsresult operator()(const opDetach& aOperation) {
790 Detach(*(aOperation.mElement), mBuilder);
791 return NS_OK;
794 nsresult operator()(const opAppendChildrenToNewParent& aOperation) {
795 nsCOMPtr<nsIContent> node = *(aOperation.mOldParent);
796 nsIContent* parent = *(aOperation.mNewParent);
797 return AppendChildrenToNewParent(node, parent, mBuilder);
800 nsresult operator()(const opFosterParent& aOperation) {
801 nsIContent* node = *(aOperation.mChild);
802 nsIContent* parent = *(aOperation.mStackParent);
803 nsIContent* table = *(aOperation.mTable);
804 return FosterParent(node, parent, table, mBuilder);
807 nsresult operator()(const opAppendToDocument& aOperation) {
808 nsresult rv = AppendToDocument(*(aOperation.mContent), mBuilder);
809 mBuilder->PauseDocUpdate(mInterrupted);
810 return rv;
813 nsresult operator()(const opAddAttributes& aOperation) {
814 nsIContent* node = *(aOperation.mElement);
815 nsHtml5HtmlAttributes* attributes = aOperation.mAttributes;
816 return AddAttributes(node, attributes, mBuilder);
819 nsresult operator()(const nsHtml5DocumentMode& aMode) {
820 mBuilder->SetDocumentMode(aMode);
821 return NS_OK;
824 nsresult operator()(const opCreateHTMLElement& aOperation) {
825 nsIContent** target = aOperation.mContent;
826 mozilla::dom::HTMLContentCreatorFunction creator = aOperation.mCreator;
827 nsAtom* name = aOperation.mName;
828 nsHtml5HtmlAttributes* attributes = aOperation.mAttributes;
829 nsIContent* intendedParent =
830 aOperation.mIntendedParent ? *(aOperation.mIntendedParent) : nullptr;
832 // intendedParent == nullptr is a special case where the
833 // intended parent is the document.
834 nsNodeInfoManager* nodeInfoManager =
835 intendedParent ? intendedParent->OwnerDoc()->NodeInfoManager()
836 : mBuilder->GetNodeInfoManager();
838 *target = CreateHTMLElement(name, attributes, aOperation.mFromNetwork,
839 nodeInfoManager, mBuilder, creator);
840 return NS_OK;
843 nsresult operator()(const opCreateSVGElement& aOperation) {
844 nsIContent** target = aOperation.mContent;
845 mozilla::dom::SVGContentCreatorFunction creator = aOperation.mCreator;
846 nsAtom* name = aOperation.mName;
847 nsHtml5HtmlAttributes* attributes = aOperation.mAttributes;
848 nsIContent* intendedParent =
849 aOperation.mIntendedParent ? *(aOperation.mIntendedParent) : nullptr;
851 // intendedParent == nullptr is a special case where the
852 // intended parent is the document.
853 nsNodeInfoManager* nodeInfoManager =
854 intendedParent ? intendedParent->OwnerDoc()->NodeInfoManager()
855 : mBuilder->GetNodeInfoManager();
857 *target = CreateSVGElement(name, attributes, aOperation.mFromNetwork,
858 nodeInfoManager, mBuilder, creator);
859 return NS_OK;
862 nsresult operator()(const opCreateMathMLElement& aOperation) {
863 nsIContent** target = aOperation.mContent;
864 nsAtom* name = aOperation.mName;
865 nsHtml5HtmlAttributes* attributes = aOperation.mAttributes;
866 nsIContent* intendedParent =
867 aOperation.mIntendedParent ? *(aOperation.mIntendedParent) : nullptr;
869 // intendedParent == nullptr is a special case where the
870 // intended parent is the document.
871 nsNodeInfoManager* nodeInfoManager =
872 intendedParent ? intendedParent->OwnerDoc()->NodeInfoManager()
873 : mBuilder->GetNodeInfoManager();
875 *target =
876 CreateMathMLElement(name, attributes, nodeInfoManager, mBuilder);
877 return NS_OK;
880 nsresult operator()(const opSetFormElement& aOperation) {
881 SetFormElement(*(aOperation.mContent), *(aOperation.mFormElement));
882 return NS_OK;
885 nsresult operator()(const opAppendText& aOperation) {
886 nsIContent* parent = *aOperation.mParent;
887 char16_t* buffer = aOperation.mBuffer;
888 uint32_t length = aOperation.mLength;
889 return AppendText(buffer, length, parent, mBuilder);
892 nsresult operator()(const opFosterParentText& aOperation) {
893 nsIContent* stackParent = *aOperation.mStackParent;
894 char16_t* buffer = aOperation.mBuffer;
895 uint32_t length = aOperation.mLength;
896 nsIContent* table = *aOperation.mTable;
897 return FosterParentText(stackParent, buffer, length, table, mBuilder);
900 nsresult operator()(const opAppendComment& aOperation) {
901 nsIContent* parent = *aOperation.mParent;
902 char16_t* buffer = aOperation.mBuffer;
903 uint32_t length = aOperation.mLength;
904 return AppendComment(parent, buffer, length, mBuilder);
907 nsresult operator()(const opAppendCommentToDocument& aOperation) {
908 char16_t* buffer = aOperation.mBuffer;
909 int32_t length = aOperation.mLength;
910 return AppendCommentToDocument(buffer, length, mBuilder);
913 nsresult operator()(const opAppendDoctypeToDocument& aOperation) {
914 nsAtom* name = aOperation.mName;
915 nsHtml5TreeOperationStringPair* pair = aOperation.mStringPair;
916 nsString publicId;
917 nsString systemId;
918 pair->Get(publicId, systemId);
919 return AppendDoctypeToDocument(name, publicId, systemId, mBuilder);
922 nsresult operator()(const opGetDocumentFragmentForTemplate& aOperation) {
923 nsIContent* node = *(aOperation.mTemplate);
924 *(aOperation.mFragHandle) = GetDocumentFragmentForTemplate(node);
925 return NS_OK;
928 nsresult operator()(const opGetFosterParent& aOperation) {
929 nsIContent* table = *(aOperation.mTable);
930 nsIContent* stackParent = *(aOperation.mStackParent);
931 nsIContent* fosterParent = GetFosterParent(table, stackParent);
932 *aOperation.mParentHandle = fosterParent;
933 return NS_OK;
936 nsresult operator()(const opMarkAsBroken& aOperation) {
937 return aOperation.mResult;
940 nsresult operator()(const opRunScript& aOperation) {
941 nsIContent* node = *(aOperation.mElement);
942 nsAHtml5TreeBuilderState* snapshot = aOperation.mBuilderState;
943 if (snapshot) {
944 mBuilder->InitializeDocWriteParserState(snapshot,
945 aOperation.mLineNumber);
947 *mScriptElement = node;
948 return NS_OK;
951 nsresult operator()(const opRunScriptAsyncDefer& aOperation) {
952 mBuilder->RunScript(*(aOperation.mElement));
953 return NS_OK;
956 nsresult operator()(const opPreventScriptExecution& aOperation) {
957 PreventScriptExecution(*(aOperation.mElement));
958 return NS_OK;
961 nsresult operator()(const opDoneAddingChildren& aOperation) {
962 nsIContent* node = *(aOperation.mElement);
963 node->DoneAddingChildren(node->HasParserNotified());
964 return NS_OK;
967 nsresult operator()(const opDoneCreatingElement& aOperation) {
968 DoneCreatingElement(*(aOperation.mElement));
969 return NS_OK;
972 nsresult operator()(const opSetDocumentCharset& aOperation) {
973 auto encoding = WrapNotNull(aOperation.mEncoding);
974 mBuilder->SetDocumentCharsetAndSource(encoding,
975 aOperation.mCharsetSource);
976 return NS_OK;
979 nsresult operator()(const opCharsetSwitchTo& aOperation) {
980 auto encoding = WrapNotNull(aOperation.mEncoding);
981 mBuilder->NeedsCharsetSwitchTo(encoding, aOperation.mCharsetSource,
982 (uint32_t)aOperation.mLineNumber);
983 return NS_OK;
986 nsresult operator()(const opUpdateStyleSheet& aOperation) {
987 mBuilder->UpdateStyleSheet(*(aOperation.mElement));
988 return NS_OK;
991 nsresult operator()(const opProcessOfflineManifest& aOperation) {
992 nsDependentString dependentString(aOperation.mUrl);
993 mBuilder->ProcessOfflineManifest(dependentString);
994 return NS_OK;
997 nsresult operator()(const opMarkMalformedIfScript& aOperation) {
998 MarkMalformedIfScript(*(aOperation.mElement));
999 return NS_OK;
1002 nsresult operator()(const opStreamEnded& aOperation) {
1003 *mStreamEnded = true;
1004 return NS_OK;
1007 nsresult operator()(const opSetStyleLineNumber& aOperation) {
1008 nsIContent* node = *(aOperation.mContent);
1009 if (auto* linkStyle = dom::LinkStyle::FromNode(*node)) {
1010 linkStyle->SetLineNumber(aOperation.mLineNumber);
1011 } else {
1012 MOZ_ASSERT(nsNameSpaceManager::GetInstance()->mSVGDisabled,
1013 "Node didn't QI to style, but SVG wasn't disabled.");
1015 return NS_OK;
1018 nsresult operator()(const opSetScriptLineNumberAndFreeze& aOperation) {
1019 nsIContent* node = *(aOperation.mContent);
1020 nsCOMPtr<nsIScriptElement> sele = do_QueryInterface(node);
1021 if (sele) {
1022 sele->SetScriptLineNumber(aOperation.mLineNumber);
1023 sele->FreezeExecutionAttrs(node->OwnerDoc());
1024 } else {
1025 MOZ_ASSERT(nsNameSpaceManager::GetInstance()->mSVGDisabled,
1026 "Node didn't QI to script, but SVG wasn't disabled.");
1028 return NS_OK;
1031 nsresult operator()(const opSvgLoad& aOperation) {
1032 SvgLoad(*(aOperation.mElement));
1033 return NS_OK;
1036 nsresult operator()(const opMaybeComplainAboutCharset& aOperation) {
1037 char* msgId = aOperation.mMsgId;
1038 bool error = aOperation.mError;
1039 int32_t lineNumber = aOperation.mLineNumber;
1040 mBuilder->MaybeComplainAboutCharset(msgId, error, (uint32_t)lineNumber);
1041 return NS_OK;
1044 nsresult operator()(const opMaybeComplainAboutDeepTree& aOperation) {
1045 mBuilder->MaybeComplainAboutDeepTree((uint32_t)aOperation.mLineNumber);
1046 return NS_OK;
1049 nsresult operator()(const opAddClass& aOperation) {
1050 Element* element = (*(aOperation.mElement))->AsElement();
1051 char16_t* str = aOperation.mClass;
1052 nsDependentString depStr(str);
1053 // See viewsource.css for the possible classes
1054 nsAutoString klass;
1055 element->GetAttr(kNameSpaceID_None, nsGkAtoms::_class, klass);
1056 if (!klass.IsEmpty()) {
1057 klass.Append(' ');
1058 klass.Append(depStr);
1059 element->SetAttr(kNameSpaceID_None, nsGkAtoms::_class, klass, true);
1060 } else {
1061 element->SetAttr(kNameSpaceID_None, nsGkAtoms::_class, depStr, true);
1063 return NS_OK;
1066 nsresult operator()(const opAddViewSourceHref& aOperation) {
1067 Element* element = (*aOperation.mElement)->AsElement();
1068 char16_t* buffer = aOperation.mBuffer;
1069 int32_t length = aOperation.mLength;
1070 nsDependentString relative(buffer, length);
1072 Document* doc = mBuilder->GetDocument();
1074 auto encoding = doc->GetDocumentCharacterSet();
1075 nsCOMPtr<nsIURI> uri;
1076 nsresult rv = NS_NewURI(getter_AddRefs(uri), relative, encoding,
1077 mBuilder->GetViewSourceBaseURI());
1078 NS_ENSURE_SUCCESS(rv, NS_OK);
1080 // Reuse the fix for bug 467852
1081 // URLs that execute script (e.g. "javascript:" URLs) should just be
1082 // ignored. There's nothing reasonable we can do with them, and allowing
1083 // them to execute in the context of the view-source window presents a
1084 // security risk. Just return the empty string in this case.
1085 bool openingExecutesScript = false;
1086 rv = NS_URIChainHasFlags(uri,
1087 nsIProtocolHandler::URI_OPENING_EXECUTES_SCRIPT,
1088 &openingExecutesScript);
1089 if (NS_FAILED(rv) || openingExecutesScript) {
1090 return NS_OK;
1093 nsAutoCString viewSourceUrl;
1095 // URLs that return data (e.g. "http:" URLs) should be prefixed with
1096 // "view-source:". URLs that don't return data should just be returned
1097 // undecorated.
1098 bool doesNotReturnData = false;
1099 rv =
1100 NS_URIChainHasFlags(uri, nsIProtocolHandler::URI_DOES_NOT_RETURN_DATA,
1101 &doesNotReturnData);
1102 NS_ENSURE_SUCCESS(rv, NS_OK);
1103 if (!doesNotReturnData) {
1104 viewSourceUrl.AssignLiteral("view-source:");
1107 nsAutoCString spec;
1108 rv = uri->GetSpec(spec);
1109 NS_ENSURE_SUCCESS(rv, rv);
1111 viewSourceUrl.Append(spec);
1113 nsAutoString utf16;
1114 CopyUTF8toUTF16(viewSourceUrl, utf16);
1116 element->SetAttr(kNameSpaceID_None, nsGkAtoms::href, utf16, true);
1117 return NS_OK;
1120 nsresult operator()(const opAddViewSourceBase& aOperation) {
1121 nsDependentString baseUrl(aOperation.mBuffer, aOperation.mLength);
1122 mBuilder->AddBase(baseUrl);
1123 return NS_OK;
1126 nsresult operator()(const opAddErrorType& aOperation) {
1127 Element* element = (*(aOperation.mElement))->AsElement();
1128 char* msgId = aOperation.mMsgId;
1129 nsAtom* atom = aOperation.mName;
1130 nsAtom* otherAtom = aOperation.mOther;
1131 // See viewsource.css for the possible classes in addition to "error".
1132 nsAutoString klass;
1133 element->GetAttr(kNameSpaceID_None, nsGkAtoms::_class, klass);
1134 if (!klass.IsEmpty()) {
1135 klass.AppendLiteral(" error");
1136 element->SetAttr(kNameSpaceID_None, nsGkAtoms::_class, klass, true);
1137 } else {
1138 element->SetAttr(kNameSpaceID_None, nsGkAtoms::_class, u"error"_ns,
1139 true);
1142 nsresult rv;
1143 nsAutoString message;
1144 if (otherAtom) {
1145 rv = nsContentUtils::FormatLocalizedString(
1146 message, nsContentUtils::eHTMLPARSER_PROPERTIES, msgId,
1147 nsDependentAtomString(atom), nsDependentAtomString(otherAtom));
1148 NS_ENSURE_SUCCESS(rv, NS_OK);
1149 } else if (atom) {
1150 rv = nsContentUtils::FormatLocalizedString(
1151 message, nsContentUtils::eHTMLPARSER_PROPERTIES, msgId,
1152 nsDependentAtomString(atom));
1153 NS_ENSURE_SUCCESS(rv, NS_OK);
1154 } else {
1155 rv = nsContentUtils::GetLocalizedString(
1156 nsContentUtils::eHTMLPARSER_PROPERTIES, msgId, message);
1157 NS_ENSURE_SUCCESS(rv, NS_OK);
1160 nsAutoString title;
1161 element->GetAttr(kNameSpaceID_None, nsGkAtoms::title, title);
1162 if (!title.IsEmpty()) {
1163 title.Append('\n');
1164 title.Append(message);
1165 element->SetAttr(kNameSpaceID_None, nsGkAtoms::title, title, true);
1166 } else {
1167 element->SetAttr(kNameSpaceID_None, nsGkAtoms::title, message, true);
1169 return rv;
1172 nsresult operator()(const opAddLineNumberId& aOperation) {
1173 Element* element = (*(aOperation.mElement))->AsElement();
1174 int32_t lineNumber = aOperation.mLineNumber;
1175 nsAutoString val(u"line"_ns);
1176 val.AppendInt(lineNumber);
1177 element->SetAttr(kNameSpaceID_None, nsGkAtoms::id, val, true);
1178 return NS_OK;
1181 nsresult operator()(const opStartLayout& aOperation) {
1182 mBuilder->StartLayout(
1183 mInterrupted); // this causes a notification flush anyway
1184 return NS_OK;
1187 nsresult operator()(const opEnableEncodingMenu& aOperation) {
1188 Document* doc = mBuilder->GetDocument();
1189 doc->EnableEncodingMenu();
1190 return NS_OK;
1193 nsresult operator()(const uninitialized& aOperation) {
1194 MOZ_CRASH("uninitialized");
1195 return NS_OK;
1199 return mOperation.match(TreeOperationMatcher(aBuilder, aScriptElement,
1200 aInterrupted, aStreamEnded));