Bug 1845715 - Check for failure when getting RegExp match result template r=iain
[gecko.git] / parser / html / nsHtml5TreeOperation.cpp
blob86098294957d581154f1d1c867ead66d1d52ddc3
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"
26 #include "nsEscape.h"
27 #include "nsHtml5AutoPauseUpdate.h"
28 #include "nsHtml5DocumentMode.h"
29 #include "nsHtml5HtmlAttributes.h"
30 #include "nsHtml5SVGLoadDispatcher.h"
31 #include "nsHtml5TreeBuilder.h"
32 #include "nsIDTD.h"
33 #include "nsIFormControl.h"
34 #include "nsIMutationObserver.h"
35 #include "nsINode.h"
36 #include "nsIProtocolHandler.h"
37 #include "nsIScriptElement.h"
38 #include "nsISupportsImpl.h"
39 #include "nsIURI.h"
40 #include "nsNetUtil.h"
41 #include "nsTextNode.h"
43 using namespace mozilla;
44 using namespace mozilla::dom;
45 using mozilla::dom::Document;
47 /**
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 {
52 public:
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)) {
57 mDocument = nullptr;
58 } else {
59 mDocument = aCurrentDoc;
60 aCurrentDoc->BeginUpdate();
64 ~nsHtml5OtherDocUpdate() {
65 if (MOZ_UNLIKELY(mDocument)) {
66 mDocument->EndUpdate();
70 private:
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);
224 return rv;
227 nsresult nsHtml5TreeOperation::AppendText(const char16_t* aBuffer,
228 uint32_t aLength, nsIContent* aParent,
229 nsHtml5DocumentBuilder* aBuilder) {
230 nsresult rv = NS_OK;
231 nsIContent* lastChild = aParent->GetLastChild();
232 if (lastChild && lastChild->IsText()) {
233 nsHtml5OtherDocUpdate update(aParent->OwnerDoc(), aBuilder->GetDocument());
234 return AppendTextToTextNode(aBuffer, aLength, lastChild->GetAsText(),
235 aBuilder);
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());
251 ErrorResult rv;
252 nsHtml5OtherDocUpdate update(aParent->OwnerDoc(), aBuilder->GetDocument());
253 aParent->AppendChildTo(aNode, false, rv);
254 if (!rv.Failed()) {
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);
278 return rv;
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());
287 ErrorResult rv;
288 Document* doc = aBuilder->GetDocument();
289 doc->AppendChildTo(aNode, false, rv);
290 if (rv.ErrorCodeIs(NS_ERROR_DOM_HIERARCHY_REQUEST_ERR)) {
291 aNode->SetParserHasNotified();
292 return NS_OK;
294 if (rv.Failed()) {
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));
307 return NS_OK;
310 static bool IsElementOrTemplateContent(nsINode* aNode) {
311 if (aNode) {
312 if (aNode->IsElement()) {
313 return true;
315 if (aNode->IsDocumentFragment()) {
316 // Check if the node is a template content.
317 nsIContent* fragHost = aNode->AsDocumentFragment()->GetHost();
318 if (fragHost && fragHost->IsTemplateElement()) {
319 return true;
323 return false;
326 void nsHtml5TreeOperation::Detach(nsIContent* aNode,
327 nsHtml5DocumentBuilder* aBuilder) {
328 MOZ_ASSERT(aBuilder);
329 MOZ_ASSERT(aBuilder->IsInDocUpdate());
330 nsCOMPtr<nsINode> parent = aNode->GetParentNode();
331 if (parent) {
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);
348 ErrorResult rv;
349 aParent->AppendChildTo(child, false, rv);
350 if (rv.Failed()) {
351 return rv.StealNSResult();
353 didAppend = true;
355 if (didAppend) {
356 MutationObservers::NotifyContentAppended(aParent, aParent->GetLastChild());
358 return NS_OK;
361 nsresult nsHtml5TreeOperation::FosterParent(nsIContent* aNode,
362 nsIContent* aParent,
363 nsIContent* aTable,
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());
372 ErrorResult rv;
373 foster->InsertChildBefore(aNode, aTable, false, rv);
374 if (rv.Failed()) {
375 return rv.StealNSResult();
378 MutationObservers::NotifyContentInserted(foster, aNode);
379 return NS_OK;
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;) {
393 --i;
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),
400 value, true);
401 // XXX what to do with nsresult?
404 return NS_OK;
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();
413 if (klass) {
414 aElement->SetSingleClassFromParser(klass);
415 } else {
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*
421 val.ToString(value);
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);
428 } else {
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;
451 if (aAttributes) {
452 nsHtml5String is = aAttributes->getValue(nsHtml5AttributeName::ATTR_IS);
453 if (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);
470 if (definition) {
471 willExecuteScript = true;
475 if (willExecuteScript) { // This will cause custom element constructors to
476 // run
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);
498 if (!aAttributes) {
499 return newContent;
502 SetHTMLElementAttributes(newContent, aName, aAttributes);
503 } else {
504 nsCOMPtr<dom::Element> newElement;
506 if (isCustomElement) {
507 NS_NewHTMLElement(getter_AddRefs(newElement), nodeInfo.forget(),
508 aFromParser, isAtom, definition);
509 } else {
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);
524 if (!aAttributes) {
525 return newContent;
528 SetHTMLElementAttributes(newContent, aName, aAttributes);
531 return newContent;
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);
548 } else {
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);
571 if (!aAttributes) {
572 return newContent;
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();
579 if (klass) {
580 newContent->SetSingleClassFromParser(klass);
581 } else {
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*
587 val.ToString(value);
588 newContent->SetAttr(nsuri, localName, prefix, value, false);
591 return newContent;
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);
606 } else {
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());
619 if (!aAttributes) {
620 return newContent;
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();
627 if (klass) {
628 newContent->SetSingleClassFromParser(klass);
629 } else {
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*
635 val.ToString(value);
636 newContent->SetAttr(nsuri, localName, prefix, value, false);
639 return newContent;
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));
649 if (formControl &&
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());
665 nsresult rv = NS_OK;
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);
684 ErrorResult error;
685 foster->InsertChildBefore(text, aTable, false, error);
686 if (error.Failed()) {
687 return error.StealNSResult();
690 MutationObservers::NotifyContentInserted(foster, text);
691 return rv;
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(
733 nsIContent* aNode) {
734 dom::HTMLTemplateElement* tempElem =
735 static_cast<dom::HTMLTemplateElement*>(aNode);
736 RefPtr<dom::DocumentFragment> frag = tempElem->Content();
737 return frag;
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);
748 if (sele) {
749 sele->PreventExecution();
750 } else {
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);
766 if (NS_FAILED(
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);
774 if (sele) {
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,
786 bool* aStreamEnded)
787 : mBuilder(aBuilder),
788 mScriptElement(aScriptElement),
789 mInterrupted(aInterrupted),
790 mStreamEnded(aStreamEnded) {}
792 nsHtml5TreeOpExecutor* mBuilder;
793 nsIContent** mScriptElement;
794 bool* mInterrupted;
795 bool* mStreamEnded;
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);
804 return NS_OK;
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);
823 return rv;
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);
834 return NS_OK;
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);
853 return NS_OK;
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);
872 return NS_OK;
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();
888 *target =
889 CreateMathMLElement(name, attributes, nodeInfoManager, mBuilder);
890 return NS_OK;
893 nsresult operator()(const opSetFormElement& aOperation) {
894 SetFormElement(*(aOperation.mContent), *(aOperation.mFormElement));
895 return NS_OK;
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;
929 nsString publicId;
930 nsString systemId;
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);
938 return NS_OK;
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;
946 return NS_OK;
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;
956 if (snapshot) {
957 mBuilder->InitializeDocWriteParserState(snapshot,
958 aOperation.mLineNumber);
960 *mScriptElement = node;
961 return NS_OK;
964 nsresult operator()(const opRunScriptAsyncDefer& aOperation) {
965 mBuilder->RunScript(*(aOperation.mElement));
966 return NS_OK;
969 nsresult operator()(const opPreventScriptExecution& aOperation) {
970 PreventScriptExecution(*(aOperation.mElement));
971 return NS_OK;
974 nsresult operator()(const opDoneAddingChildren& aOperation) {
975 nsIContent* node = *(aOperation.mElement);
976 node->DoneAddingChildren(node->HasParserNotified());
977 return NS_OK;
980 nsresult operator()(const opDoneCreatingElement& aOperation) {
981 DoneCreatingElement(*(aOperation.mElement));
982 return NS_OK;
985 nsresult operator()(const opUpdateCharsetSource& aOperation) {
986 mBuilder->UpdateCharsetSource(aOperation.mCharsetSource);
987 return NS_OK;
990 nsresult operator()(const opCharsetSwitchTo& aOperation) {
991 auto encoding = WrapNotNull(aOperation.mEncoding);
992 mBuilder->NeedsCharsetSwitchTo(encoding, aOperation.mCharsetSource,
993 (uint32_t)aOperation.mLineNumber);
994 return NS_OK;
997 nsresult operator()(const opUpdateStyleSheet& aOperation) {
998 mBuilder->UpdateStyleSheet(*(aOperation.mElement));
999 return NS_OK;
1002 nsresult operator()(const opProcessOfflineManifest& aOperation) {
1003 // TODO: remove this
1004 return NS_OK;
1007 nsresult operator()(const opMarkMalformedIfScript& aOperation) {
1008 MarkMalformedIfScript(*(aOperation.mElement));
1009 return NS_OK;
1012 nsresult operator()(const opStreamEnded& aOperation) {
1013 *mStreamEnded = true;
1014 return NS_OK;
1017 nsresult operator()(const opSetStyleLineNumber& aOperation) {
1018 nsIContent* node = *(aOperation.mContent);
1019 if (auto* linkStyle = dom::LinkStyle::FromNode(*node)) {
1020 linkStyle->SetLineNumber(aOperation.mLineNumber);
1021 } else {
1022 MOZ_ASSERT(nsNameSpaceManager::GetInstance()->mSVGDisabled,
1023 "Node didn't QI to style, but SVG wasn't disabled.");
1025 return NS_OK;
1028 nsresult operator()(
1029 const opSetScriptLineAndColumnNumberAndFreeze& aOperation) {
1030 nsIContent* node = *(aOperation.mContent);
1031 nsCOMPtr<nsIScriptElement> sele = do_QueryInterface(node);
1032 if (sele) {
1033 sele->SetScriptLineNumber(aOperation.mLineNumber);
1034 sele->SetScriptColumnNumber(aOperation.mColumnNumber);
1035 sele->FreezeExecutionAttrs(node->OwnerDoc());
1036 } else {
1037 MOZ_ASSERT(nsNameSpaceManager::GetInstance()->mSVGDisabled,
1038 "Node didn't QI to script, but SVG wasn't disabled.");
1040 return NS_OK;
1043 nsresult operator()(const opSvgLoad& aOperation) {
1044 SvgLoad(*(aOperation.mElement));
1045 return NS_OK;
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);
1053 return NS_OK;
1056 nsresult operator()(const opMaybeComplainAboutDeepTree& aOperation) {
1057 mBuilder->MaybeComplainAboutDeepTree((uint32_t)aOperation.mLineNumber);
1058 return NS_OK;
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
1066 nsAutoString klass;
1067 element->GetAttr(nsGkAtoms::_class, klass);
1068 if (!klass.IsEmpty()) {
1069 klass.Append(' ');
1070 klass.Append(depStr);
1071 element->SetAttr(kNameSpaceID_None, nsGkAtoms::_class, klass, true);
1072 } else {
1073 element->SetAttr(kNameSpaceID_None, nsGkAtoms::_class, depStr, true);
1075 return NS_OK;
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) {
1102 return NS_OK;
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
1109 // undecorated.
1110 if (!nsContentUtils::IsExternalProtocol(uri)) {
1111 viewSourceUrl.AssignLiteral("view-source:");
1114 nsAutoCString spec;
1115 rv = uri->GetSpec(spec);
1116 NS_ENSURE_SUCCESS(rv, rv);
1118 viewSourceUrl.Append(spec);
1120 nsAutoString utf16;
1121 CopyUTF8toUTF16(viewSourceUrl, utf16);
1123 element->SetAttr(kNameSpaceID_None, nsGkAtoms::href, utf16, true);
1124 return NS_OK;
1127 nsresult operator()(const opAddViewSourceBase& aOperation) {
1128 nsDependentString baseUrl(aOperation.mBuffer, aOperation.mLength);
1129 mBuilder->AddBase(baseUrl);
1130 return NS_OK;
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".
1139 nsAutoString klass;
1140 element->GetAttr(nsGkAtoms::_class, klass);
1141 if (!klass.IsEmpty()) {
1142 klass.AppendLiteral(" error");
1143 element->SetAttr(kNameSpaceID_None, nsGkAtoms::_class, klass, true);
1144 } else {
1145 element->SetAttr(kNameSpaceID_None, nsGkAtoms::_class, u"error"_ns,
1146 true);
1149 nsresult rv;
1150 nsAutoString message;
1151 if (otherAtom) {
1152 rv = nsContentUtils::FormatLocalizedString(
1153 message, nsContentUtils::eHTMLPARSER_PROPERTIES, msgId,
1154 nsDependentAtomString(atom), nsDependentAtomString(otherAtom));
1155 NS_ENSURE_SUCCESS(rv, NS_OK);
1156 } else if (atom) {
1157 rv = nsContentUtils::FormatLocalizedString(
1158 message, nsContentUtils::eHTMLPARSER_PROPERTIES, msgId,
1159 nsDependentAtomString(atom));
1160 NS_ENSURE_SUCCESS(rv, NS_OK);
1161 } else {
1162 rv = nsContentUtils::GetLocalizedString(
1163 nsContentUtils::eHTMLPARSER_PROPERTIES, msgId, message);
1164 NS_ENSURE_SUCCESS(rv, NS_OK);
1167 nsAutoString title;
1168 element->GetAttr(nsGkAtoms::title, title);
1169 if (!title.IsEmpty()) {
1170 title.Append('\n');
1171 title.Append(message);
1172 element->SetAttr(kNameSpaceID_None, nsGkAtoms::title, title, true);
1173 } else {
1174 element->SetAttr(kNameSpaceID_None, nsGkAtoms::title, message, true);
1176 return rv;
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);
1185 return NS_OK;
1188 nsresult operator()(const opStartLayout& aOperation) {
1189 mBuilder->StartLayout(
1190 mInterrupted); // this causes a notification flush anyway
1191 return NS_OK;
1194 nsresult operator()(const opEnableEncodingMenu& aOperation) {
1195 Document* doc = mBuilder->GetDocument();
1196 doc->EnableEncodingMenu();
1197 return NS_OK;
1200 nsresult operator()(const uninitialized& aOperation) {
1201 MOZ_CRASH("uninitialized");
1202 return NS_OK;
1206 return mOperation.match(TreeOperationMatcher(aBuilder, aScriptElement,
1207 aInterrupted, aStreamEnded));