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 /* ***** BEGIN LICENSE BLOCK *****
4 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 * The contents of this file are subject to the Mozilla Public License Version
7 * 1.1 (the "License"); you may not use this file except in compliance with
8 * the License. You may obtain a copy of the License at
9 * http://www.mozilla.org/MPL/
11 * Software distributed under the License is distributed on an "AS IS" basis,
12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 * for the specific language governing rights and limitations under the
16 * The Original Code is Mozilla Communicator client code.
18 * The Initial Developer of the Original Code is
19 * Netscape Communications Corporation.
20 * Portions created by the Initial Developer are Copyright (C) 1998
21 * the Initial Developer. All Rights Reserved.
24 * Pierre Phaneuf <pp@ludusdesign.com>
25 * Henri Sivonen <hsivonen@iki.fi>
27 * Alternatively, the contents of this file may be used under the terms of
28 * either of the GNU General Public License Version 2 or later (the "GPL"),
29 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
30 * in which case the provisions of the GPL or the LGPL are applicable instead
31 * of those above. If you wish to allow use of your version of this file only
32 * under the terms of either the GPL or the LGPL, and not to allow others to
33 * use your version of this file under the terms of the MPL, indicate your
34 * decision by deleting the provisions above and replace them with the notice
35 * and other provisions required by the GPL or the LGPL. If you do not delete
36 * the provisions above, a recipient may use your version of this file under
37 * the terms of any one of the MPL, the GPL or the LGPL.
39 * ***** END LICENSE BLOCK ***** */
41 #include "nsHtml5TreeOperation.h"
42 #include "nsContentUtils.h"
43 #include "nsNodeUtils.h"
44 #include "nsAttrName.h"
45 #include "nsHtml5TreeBuilder.h"
46 #include "nsIDOMMutationEvent.h"
47 #include "mozAutoDocUpdate.h"
48 #include "nsBindingManager.h"
49 #include "nsXBLBinding.h"
50 #include "nsHtml5DocumentMode.h"
51 #include "nsHtml5HtmlAttributes.h"
52 #include "nsContentCreatorFunctions.h"
53 #include "nsIScriptElement.h"
55 #include "nsTraceRefcnt.h"
56 #include "nsIDOMHTMLFormElement.h"
57 #include "nsIFormControl.h"
58 #include "nsIStyleSheetLinkingElement.h"
59 #include "nsIDOMDocumentType.h"
60 #include "nsIObserverService.h"
61 #include "mozilla/Services.h"
62 #include "nsIMutationObserver.h"
63 #include "nsIFormProcessor.h"
64 #include "nsIServiceManager.h"
66 #include "mozilla/dom/Element.h"
69 #include "nsHtml5SVGLoadDispatcher.h"
72 namespace dom
= mozilla::dom
;
74 static NS_DEFINE_CID(kFormProcessorCID
, NS_FORMPROCESSOR_CID
);
77 * Helper class that opens a notification batch if the current doc
78 * is different from the executor doc.
80 class NS_STACK_CLASS nsHtml5OtherDocUpdate
{
82 nsHtml5OtherDocUpdate(nsIDocument
* aCurrentDoc
, nsIDocument
* aExecutorDoc
)
84 NS_PRECONDITION(aCurrentDoc
, "Node has no doc?");
85 NS_PRECONDITION(aExecutorDoc
, "Executor has no doc?");
86 if (NS_LIKELY(aCurrentDoc
== aExecutorDoc
)) {
89 mDocument
= aCurrentDoc
;
90 aCurrentDoc
->BeginUpdate(UPDATE_CONTENT_MODEL
);
94 ~nsHtml5OtherDocUpdate()
96 if (NS_UNLIKELY(mDocument
)) {
97 mDocument
->EndUpdate(UPDATE_CONTENT_MODEL
);
101 nsIDocument
* mDocument
;
104 nsHtml5TreeOperation::nsHtml5TreeOperation()
106 : mOpCode(eTreeOpUninitialized
)
109 MOZ_COUNT_CTOR(nsHtml5TreeOperation
);
112 nsHtml5TreeOperation::~nsHtml5TreeOperation()
114 MOZ_COUNT_DTOR(nsHtml5TreeOperation
);
115 NS_ASSERTION(mOpCode
!= eTreeOpUninitialized
, "Uninitialized tree op.");
117 case eTreeOpAddAttributes
:
118 delete mTwo
.attributes
;
120 case eTreeOpCreateElementNetwork
:
121 case eTreeOpCreateElementNotNetwork
:
122 delete mThree
.attributes
;
124 case eTreeOpAppendDoctypeToDocument
:
125 delete mTwo
.stringPair
;
127 case eTreeOpFosterParentText
:
128 case eTreeOpAppendText
:
129 case eTreeOpAppendComment
:
130 case eTreeOpAppendCommentToDocument
:
131 delete[] mTwo
.unicharPtr
;
133 case eTreeOpSetDocumentCharset
:
134 case eTreeOpNeedsCharsetSwitchTo
:
135 delete[] mOne
.charPtr
;
137 case eTreeOpProcessOfflineManifest
:
138 nsMemory::Free(mOne
.unicharPtr
);
140 default: // keep the compiler happy
146 nsHtml5TreeOperation::AppendTextToTextNode(const PRUnichar
* aBuffer
,
148 nsIContent
* aTextNode
,
149 nsHtml5TreeOpExecutor
* aBuilder
)
151 NS_PRECONDITION(aTextNode
, "Got null text node.");
153 if (aBuilder
->HaveNotified(aTextNode
)) {
154 // This text node has already been notified on, so it's necessary to
155 // notify on the append
157 PRUint32 oldLength
= aTextNode
->TextLength();
158 CharacterDataChangeInfo info
= {
164 nsNodeUtils::CharacterDataWillChange(aTextNode
, &info
);
166 rv
= aTextNode
->AppendText(aBuffer
, aLength
, PR_FALSE
);
167 NS_ENSURE_SUCCESS(rv
, rv
);
169 nsNodeUtils::CharacterDataChanged(aTextNode
, &info
);
173 return aTextNode
->AppendText(aBuffer
, aLength
, PR_FALSE
);
178 nsHtml5TreeOperation::AppendText(const PRUnichar
* aBuffer
,
181 nsHtml5TreeOpExecutor
* aBuilder
)
184 nsIContent
* lastChild
= aParent
->GetLastChild();
185 if (lastChild
&& lastChild
->IsNodeOfType(nsINode::eTEXT
)) {
186 nsHtml5OtherDocUpdate
update(aParent
->GetOwnerDoc(),
187 aBuilder
->GetDocument());
188 return AppendTextToTextNode(aBuffer
,
194 nsCOMPtr
<nsIContent
> text
;
195 NS_NewTextNode(getter_AddRefs(text
), aBuilder
->GetNodeInfoManager());
196 NS_ASSERTION(text
, "Infallible malloc failed?");
197 rv
= text
->SetText(aBuffer
, aLength
, PR_FALSE
);
198 NS_ENSURE_SUCCESS(rv
, rv
);
200 return Append(text
, aParent
, aBuilder
);
204 nsHtml5TreeOperation::Append(nsIContent
* aNode
,
206 nsHtml5TreeOpExecutor
* aBuilder
)
209 nsIDocument
* executorDoc
= aBuilder
->GetDocument();
210 NS_ASSERTION(executorDoc
, "Null doc on executor");
211 nsIDocument
* parentDoc
= aParent
->GetOwnerDoc();
212 NS_ASSERTION(parentDoc
, "Null owner doc on old node.");
214 if (NS_LIKELY(executorDoc
== parentDoc
)) {
215 // the usual case. the parent is in the parser's doc
216 aBuilder
->PostPendingAppendNotification(aParent
, aNode
);
217 rv
= aParent
->AppendChildTo(aNode
, PR_FALSE
);
221 // The parent has been moved to another doc
222 parentDoc
->BeginUpdate(UPDATE_CONTENT_MODEL
);
224 PRUint32 childCount
= aParent
->GetChildCount();
225 rv
= aParent
->AppendChildTo(aNode
, PR_FALSE
);
226 nsNodeUtils::ContentAppended(aParent
, aNode
, childCount
);
228 parentDoc
->EndUpdate(UPDATE_CONTENT_MODEL
);
232 class nsDocElementCreatedNotificationRunner
: public nsRunnable
235 nsDocElementCreatedNotificationRunner(nsIDocument
* aDoc
)
242 nsContentSink::NotifyDocElementCreated(mDoc
);
246 nsCOMPtr
<nsIDocument
> mDoc
;
250 nsHtml5TreeOperation::AppendToDocument(nsIContent
* aNode
,
251 nsHtml5TreeOpExecutor
* aBuilder
)
254 aBuilder
->FlushPendingAppendNotifications();
255 nsIDocument
* doc
= aBuilder
->GetDocument();
256 PRUint32 childCount
= doc
->GetChildCount();
257 rv
= doc
->AppendChildTo(aNode
, PR_FALSE
);
258 NS_ENSURE_SUCCESS(rv
, rv
);
259 nsNodeUtils::ContentInserted(doc
, aNode
, childCount
);
261 NS_ASSERTION(!nsContentUtils::IsSafeToRunScript(),
262 "Someone forgot to block scripts");
263 nsContentUtils::AddScriptRunner(
264 new nsDocElementCreatedNotificationRunner(doc
));
270 nsHtml5TreeOperation::Perform(nsHtml5TreeOpExecutor
* aBuilder
,
271 nsIContent
** aScriptElement
)
275 case eTreeOpAppend
: {
276 nsIContent
* node
= *(mOne
.node
);
277 nsIContent
* parent
= *(mTwo
.node
);
278 return Append(node
, parent
, aBuilder
);
280 case eTreeOpDetach
: {
281 nsIContent
* node
= *(mOne
.node
);
282 aBuilder
->FlushPendingAppendNotifications();
283 nsIContent
* parent
= node
->GetParent();
285 nsHtml5OtherDocUpdate
update(parent
->GetOwnerDoc(),
286 aBuilder
->GetDocument());
287 PRUint32 pos
= parent
->IndexOf(node
);
288 NS_ASSERTION((pos
>= 0), "Element not found as child of its parent");
289 rv
= parent
->RemoveChildAt(pos
, PR_TRUE
, PR_FALSE
);
290 NS_ENSURE_SUCCESS(rv
, rv
);
294 case eTreeOpAppendChildrenToNewParent
: {
295 nsIContent
* node
= *(mOne
.node
);
296 nsIContent
* parent
= *(mTwo
.node
);
297 aBuilder
->FlushPendingAppendNotifications();
299 nsHtml5OtherDocUpdate
update(parent
->GetOwnerDoc(),
300 aBuilder
->GetDocument());
302 PRUint32 childCount
= parent
->GetChildCount();
303 PRBool didAppend
= PR_FALSE
;
304 while (node
->GetChildCount()) {
305 nsCOMPtr
<nsIContent
> child
= node
->GetChildAt(0);
306 rv
= node
->RemoveChildAt(0, PR_TRUE
, PR_FALSE
);
307 NS_ENSURE_SUCCESS(rv
, rv
);
308 rv
= parent
->AppendChildTo(child
, PR_FALSE
);
309 NS_ENSURE_SUCCESS(rv
, rv
);
313 nsNodeUtils::ContentAppended(parent
, parent
->GetChildAt(childCount
),
318 case eTreeOpFosterParent
: {
319 nsIContent
* node
= *(mOne
.node
);
320 nsIContent
* parent
= *(mTwo
.node
);
321 nsIContent
* table
= *(mThree
.node
);
322 nsIContent
* foster
= table
->GetParent();
324 if (foster
&& foster
->IsElement()) {
325 aBuilder
->FlushPendingAppendNotifications();
327 nsHtml5OtherDocUpdate
update(foster
->GetOwnerDoc(),
328 aBuilder
->GetDocument());
330 PRUint32 pos
= foster
->IndexOf(table
);
331 rv
= foster
->InsertChildAt(node
, pos
, PR_FALSE
);
332 NS_ENSURE_SUCCESS(rv
, rv
);
333 nsNodeUtils::ContentInserted(foster
, node
, pos
);
337 return Append(node
, parent
, aBuilder
);
339 case eTreeOpAppendToDocument
: {
340 nsIContent
* node
= *(mOne
.node
);
341 return AppendToDocument(node
, aBuilder
);
343 case eTreeOpAddAttributes
: {
344 dom::Element
* node
= (*(mOne
.node
))->AsElement();
345 nsHtml5HtmlAttributes
* attributes
= mTwo
.attributes
;
347 nsHtml5OtherDocUpdate
update(node
->GetOwnerDoc(),
348 aBuilder
->GetDocument());
350 nsIDocument
* document
= node
->GetCurrentDoc();
352 PRInt32 len
= attributes
->getLength();
353 for (PRInt32 i
= len
; i
> 0;) {
355 // prefix doesn't need regetting. it is always null or a static atom
356 // local name is never null
357 nsCOMPtr
<nsIAtom
> localName
= Reget(attributes
->getLocalName(i
));
358 PRInt32 nsuri
= attributes
->getURI(i
);
359 if (!node
->HasAttr(nsuri
, localName
)) {
361 // the manual notification code is based on nsGenericElement
363 nsEventStates stateMask
= node
->IntrinsicState();
364 nsNodeUtils::AttributeWillChange(node
,
367 static_cast<PRUint8
>(nsIDOMMutationEvent::ADDITION
));
369 // prefix doesn't need regetting. it is always null or a static atom
370 // local name is never null
371 node
->SetAttr(nsuri
, localName
, attributes
->getPrefix(i
), *(attributes
->getValue(i
)), PR_FALSE
);
372 // XXX what to do with nsresult?
374 if (document
|| node
->HasFlag(NODE_FORCE_XBL_BINDINGS
)) {
375 nsIDocument
* ownerDoc
= node
->GetOwnerDoc();
377 nsRefPtr
<nsXBLBinding
> binding
=
378 ownerDoc
->BindingManager()->GetBinding(node
);
380 binding
->AttributeChanged(localName
, nsuri
, PR_FALSE
, PR_FALSE
);
385 stateMask
^= node
->IntrinsicState();
386 if (!stateMask
.IsEmpty() && document
) {
387 MOZ_AUTO_DOC_UPDATE(document
, UPDATE_CONTENT_STATE
, PR_TRUE
);
388 document
->ContentStatesChanged(node
, nsnull
, stateMask
);
390 nsNodeUtils::AttributeChanged(node
,
393 static_cast<PRUint8
>(nsIDOMMutationEvent::ADDITION
));
399 case eTreeOpCreateElementNetwork
:
400 case eTreeOpCreateElementNotNetwork
: {
401 nsIContent
** target
= mOne
.node
;
403 nsCOMPtr
<nsIAtom
> name
= Reget(mTwo
.atom
);
404 nsHtml5HtmlAttributes
* attributes
= mThree
.attributes
;
406 PRBool isKeygen
= (name
== nsHtml5Atoms::keygen
&& ns
== kNameSpaceID_XHTML
);
407 if (NS_UNLIKELY(isKeygen
)) {
408 name
= nsHtml5Atoms::select
;
411 nsCOMPtr
<nsIContent
> newContent
;
412 nsCOMPtr
<nsINodeInfo
> nodeInfo
= aBuilder
->GetNodeInfoManager()->GetNodeInfo(name
, nsnull
, ns
);
413 NS_ASSERTION(nodeInfo
, "Got null nodeinfo.");
414 NS_NewElement(getter_AddRefs(newContent
),
415 ns
, nodeInfo
.forget(),
416 (mOpCode
== eTreeOpCreateElementNetwork
?
417 dom::FROM_PARSER_NETWORK
418 : (aBuilder
->IsFragmentMode() ?
419 dom::FROM_PARSER_FRAGMENT
:
420 dom::FROM_PARSER_DOCUMENT_WRITE
)));
421 NS_ASSERTION(newContent
, "Element creation created null pointer.");
423 aBuilder
->HoldElement(*target
= newContent
);
425 if (NS_UNLIKELY(name
== nsHtml5Atoms::style
|| name
== nsHtml5Atoms::link
)) {
426 nsCOMPtr
<nsIStyleSheetLinkingElement
> ssle(do_QueryInterface(newContent
));
428 ssle
->InitStyleLinkElement(PR_FALSE
);
429 ssle
->SetEnableUpdates(PR_FALSE
);
431 } else if (NS_UNLIKELY(isKeygen
)) {
432 // Adapted from CNavDTD
433 nsCOMPtr
<nsIFormProcessor
> theFormProcessor
=
434 do_GetService(kFormProcessorCID
, &rv
);
435 NS_ENSURE_SUCCESS(rv
, rv
);
437 nsTArray
<nsString
> theContent
;
438 nsAutoString theAttribute
;
440 (void) theFormProcessor
->ProvideContent(NS_LITERAL_STRING("select"),
444 newContent
->SetAttr(kNameSpaceID_None
,
450 nsCOMPtr
<nsINodeInfo
> optionNodeInfo
=
451 aBuilder
->GetNodeInfoManager()->GetNodeInfo(nsHtml5Atoms::option
,
455 for (PRUint32 i
= 0; i
< theContent
.Length(); ++i
) {
456 nsCOMPtr
<nsIContent
> optionElt
;
457 nsCOMPtr
<nsINodeInfo
> ni
= optionNodeInfo
;
458 NS_NewElement(getter_AddRefs(optionElt
),
459 optionNodeInfo
->NamespaceID(),
461 (mOpCode
== eTreeOpCreateElementNetwork
?
462 dom::FROM_PARSER_NETWORK
463 : (aBuilder
->IsFragmentMode() ?
464 dom::FROM_PARSER_FRAGMENT
:
465 dom::FROM_PARSER_DOCUMENT_WRITE
)));
466 nsCOMPtr
<nsIContent
> optionText
;
467 NS_NewTextNode(getter_AddRefs(optionText
),
468 aBuilder
->GetNodeInfoManager());
469 (void) optionText
->SetText(theContent
[i
], PR_FALSE
);
470 optionElt
->AppendChildTo(optionText
, PR_FALSE
);
471 newContent
->AppendChildTo(optionElt
, PR_FALSE
);
472 newContent
->DoneAddingChildren(PR_FALSE
);
474 } else if (name
== nsHtml5Atoms::frameset
&& ns
== kNameSpaceID_XHTML
) {
475 nsIDocument
* doc
= aBuilder
->GetDocument();
476 nsCOMPtr
<nsIHTMLDocument
> htmlDocument
= do_QueryInterface(doc
);
478 // It seems harmless to call this multiple times, since this
479 // is a simple field setter
480 htmlDocument
->SetIsFrameset(PR_TRUE
);
488 PRInt32 len
= attributes
->getLength();
489 for (PRInt32 i
= len
; i
> 0;) {
491 // prefix doesn't need regetting. it is always null or a static atom
492 // local name is never null
493 nsCOMPtr
<nsIAtom
> localName
= Reget(attributes
->getLocalName(i
));
494 if (ns
== kNameSpaceID_XHTML
&&
495 nsHtml5Atoms::a
== name
&&
496 nsHtml5Atoms::name
== localName
) {
497 // This is an HTML5-incompliant Geckoism.
498 // Remove when fixing bug 582361
499 NS_ConvertUTF16toUTF8
cname(*(attributes
->getValue(i
)));
500 NS_ConvertUTF8toUTF16
uv(nsUnescape(cname
.BeginWriting()));
501 newContent
->SetAttr(attributes
->getURI(i
), localName
,
502 attributes
->getPrefix(i
), uv
, PR_FALSE
);
504 newContent
->SetAttr(attributes
->getURI(i
), localName
,
505 attributes
->getPrefix(i
), *(attributes
->getValue(i
)), PR_FALSE
);
511 case eTreeOpSetFormElement
: {
512 nsIContent
* node
= *(mOne
.node
);
513 nsIContent
* parent
= *(mTwo
.node
);
514 nsCOMPtr
<nsIFormControl
> formControl(do_QueryInterface(node
));
515 // NS_ASSERTION(formControl, "Form-associated element did not implement nsIFormControl.");
516 // TODO: uncomment the above line when <keygen> (bug 101019) is supported by Gecko
517 nsCOMPtr
<nsIDOMHTMLFormElement
> formElement(do_QueryInterface(parent
));
518 NS_ASSERTION(formElement
, "The form element doesn't implement nsIDOMHTMLFormElement.");
519 // avoid crashing on <keygen>
521 !node
->HasAttr(kNameSpaceID_None
, nsGkAtoms::form
)) {
522 formControl
->SetForm(formElement
);
526 case eTreeOpAppendText
: {
527 nsIContent
* parent
= *mOne
.node
;
528 PRUnichar
* buffer
= mTwo
.unicharPtr
;
529 PRInt32 length
= mInt
;
530 return AppendText(buffer
, length
, parent
, aBuilder
);
532 case eTreeOpAppendIsindexPrompt
: {
533 nsIContent
* parent
= *mOne
.node
;
534 nsXPIDLString prompt
;
536 nsContentUtils::GetLocalizedString(nsContentUtils::eFORMS_PROPERTIES
,
537 "IsIndexPromptWithSpace", prompt
);
538 PRUint32 len
= prompt
.Length();
543 // Don't bother appending a zero-length text node.
546 return AppendText(prompt
.BeginReading(), len
, parent
, aBuilder
);
548 case eTreeOpFosterParentText
: {
549 nsIContent
* stackParent
= *mOne
.node
;
550 PRUnichar
* buffer
= mTwo
.unicharPtr
;
551 PRInt32 length
= mInt
;
552 nsIContent
* table
= *mThree
.node
;
554 nsIContent
* foster
= table
->GetParent();
556 if (foster
&& foster
->IsElement()) {
557 aBuilder
->FlushPendingAppendNotifications();
559 nsHtml5OtherDocUpdate
update(foster
->GetOwnerDoc(),
560 aBuilder
->GetDocument());
562 PRUint32 pos
= foster
->IndexOf(table
);
564 nsIContent
* previousSibling
= foster
->GetChildAt(pos
- 1);
565 if (previousSibling
&& previousSibling
->IsNodeOfType(nsINode::eTEXT
)) {
566 return AppendTextToTextNode(buffer
,
572 nsCOMPtr
<nsIContent
> text
;
573 NS_NewTextNode(getter_AddRefs(text
), aBuilder
->GetNodeInfoManager());
574 NS_ASSERTION(text
, "Infallible malloc failed?");
575 rv
= text
->SetText(buffer
, length
, PR_FALSE
);
576 NS_ENSURE_SUCCESS(rv
, rv
);
578 rv
= foster
->InsertChildAt(text
, pos
, PR_FALSE
);
579 NS_ENSURE_SUCCESS(rv
, rv
);
580 nsNodeUtils::ContentInserted(foster
, text
, pos
);
584 return AppendText(buffer
, length
, stackParent
, aBuilder
);
586 case eTreeOpAppendComment
: {
587 nsIContent
* parent
= *mOne
.node
;
588 PRUnichar
* buffer
= mTwo
.unicharPtr
;
589 PRInt32 length
= mInt
;
591 nsCOMPtr
<nsIContent
> comment
;
592 NS_NewCommentNode(getter_AddRefs(comment
), aBuilder
->GetNodeInfoManager());
593 NS_ASSERTION(comment
, "Infallible malloc failed?");
594 rv
= comment
->SetText(buffer
, length
, PR_FALSE
);
595 NS_ENSURE_SUCCESS(rv
, rv
);
597 return Append(comment
, parent
, aBuilder
);
599 case eTreeOpAppendCommentToDocument
: {
600 PRUnichar
* buffer
= mTwo
.unicharPtr
;
601 PRInt32 length
= mInt
;
603 nsCOMPtr
<nsIContent
> comment
;
604 NS_NewCommentNode(getter_AddRefs(comment
), aBuilder
->GetNodeInfoManager());
605 NS_ASSERTION(comment
, "Infallible malloc failed?");
606 rv
= comment
->SetText(buffer
, length
, PR_FALSE
);
607 NS_ENSURE_SUCCESS(rv
, rv
);
609 return AppendToDocument(comment
, aBuilder
);
611 case eTreeOpAppendDoctypeToDocument
: {
612 nsCOMPtr
<nsIAtom
> name
= Reget(mOne
.atom
);
613 nsHtml5TreeOperationStringPair
* pair
= mTwo
.stringPair
;
616 pair
->Get(publicId
, systemId
);
618 // Adapted from nsXMLContentSink
619 // Create a new doctype node
620 nsCOMPtr
<nsIDOMDocumentType
> docType
;
621 nsAutoString voidString
;
622 voidString
.SetIsVoid(PR_TRUE
);
623 NS_NewDOMDocumentType(getter_AddRefs(docType
),
624 aBuilder
->GetNodeInfoManager(),
632 NS_ASSERTION(docType
, "Doctype creation failed.");
633 nsCOMPtr
<nsIContent
> asContent
= do_QueryInterface(docType
);
634 return AppendToDocument(asContent
, aBuilder
);
636 case eTreeOpRunScript
: {
637 nsIContent
* node
= *(mOne
.node
);
638 nsAHtml5TreeBuilderState
* snapshot
= mTwo
.state
;
640 aBuilder
->InitializeDocWriteParserState(snapshot
, mInt
);
642 *aScriptElement
= node
;
645 case eTreeOpRunScriptAsyncDefer
: {
646 nsIContent
* node
= *(mOne
.node
);
647 aBuilder
->RunScript(node
);
650 case eTreeOpDoneAddingChildren
: {
651 nsIContent
* node
= *(mOne
.node
);
652 node
->DoneAddingChildren(aBuilder
->HaveNotified(node
));
655 case eTreeOpDoneCreatingElement
: {
656 nsIContent
* node
= *(mOne
.node
);
657 node
->DoneCreatingElement();
660 case eTreeOpFlushPendingAppendNotifications
: {
661 aBuilder
->FlushPendingAppendNotifications();
664 case eTreeOpSetDocumentCharset
: {
665 char* str
= mOne
.charPtr
;
666 PRInt32 charsetSource
= mInt
;
667 nsDependentCString
dependentString(str
);
668 aBuilder
->SetDocumentCharsetAndSource(dependentString
, charsetSource
);
671 case eTreeOpNeedsCharsetSwitchTo
: {
672 char* str
= mOne
.charPtr
;
673 aBuilder
->NeedsCharsetSwitchTo(str
);
676 case eTreeOpUpdateStyleSheet
: {
677 nsIContent
* node
= *(mOne
.node
);
678 aBuilder
->FlushPendingAppendNotifications();
679 aBuilder
->UpdateStyleSheet(node
);
682 case eTreeOpProcessMeta
: {
683 nsIContent
* node
= *(mOne
.node
);
684 rv
= aBuilder
->ProcessMETATag(node
);
687 case eTreeOpProcessOfflineManifest
: {
688 PRUnichar
* str
= mOne
.unicharPtr
;
689 nsDependentString
dependentString(str
);
690 aBuilder
->ProcessOfflineManifest(dependentString
);
693 case eTreeOpMarkMalformedIfScript
: {
694 nsIContent
* node
= *(mOne
.node
);
695 nsCOMPtr
<nsIScriptElement
> sele
= do_QueryInterface(node
);
697 // Make sure to serialize this script correctly, for nice round tripping.
698 sele
->SetIsMalformed();
702 case eTreeOpStreamEnded
: {
703 aBuilder
->DidBuildModel(PR_FALSE
); // this causes a notifications flush anyway
706 case eTreeOpStartLayout
: {
707 aBuilder
->StartLayout(); // this causes a notification flush anyway
710 case eTreeOpDocumentMode
: {
711 aBuilder
->SetDocumentMode(mOne
.mode
);
714 case eTreeOpSetStyleLineNumber
: {
715 nsIContent
* node
= *(mOne
.node
);
716 nsCOMPtr
<nsIStyleSheetLinkingElement
> ssle
= do_QueryInterface(node
);
717 NS_ASSERTION(ssle
, "Node didn't QI to style.");
718 ssle
->SetLineNumber(mInt
);
721 case eTreeOpSetScriptLineNumberAndFreeze
: {
722 nsIContent
* node
= *(mOne
.node
);
723 nsCOMPtr
<nsIScriptElement
> sele
= do_QueryInterface(node
);
724 NS_ASSERTION(sele
, "Node didn't QI to script.");
725 sele
->SetScriptLineNumber(mInt
);
726 sele
->FreezeUriAsyncDefer();
730 case eTreeOpSvgLoad
: {
731 nsIContent
* node
= *(mOne
.node
);
732 nsCOMPtr
<nsIRunnable
> event
= new nsHtml5SVGLoadDispatcher(node
);
733 if (NS_FAILED(NS_DispatchToMainThread(event
))) {
734 NS_WARNING("failed to dispatch svg load dispatcher");
740 NS_NOTREACHED("Bogus tree op");
743 return rv
; // keep compiler happy