1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
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/. */
8 * An implementation for a Gecko-style content sink that knows how
9 * to build a content model (the "prototype" document) from XUL.
11 * For more information on XUL,
12 * see http://developer.mozilla.org/en/docs/XUL
15 #include "nsXULContentSink.h"
17 #include "jsfriendapi.h"
20 #include "nsIContentSink.h"
21 #include "mozilla/dom/Document.h"
22 #include "nsIFormControl.h"
23 #include "mozilla/dom/NodeInfo.h"
24 #include "nsIScriptContext.h"
25 #include "nsIScriptGlobalObject.h"
26 #include "nsNameSpaceManager.h"
27 #include "nsParserBase.h"
28 #include "nsViewManager.h"
29 #include "nsIScriptSecurityManager.h"
30 #include "nsNetUtil.h"
32 #include "nsReadableUtils.h"
33 #include "nsXULElement.h"
34 #include "mozilla/Logging.h"
37 #include "nsXULPrototypeDocument.h" // XXXbe temporary
38 #include "mozilla/css/Loader.h"
40 #include "nsUnicharUtils.h"
41 #include "nsGkAtoms.h"
42 #include "nsContentUtils.h"
43 #include "nsAttrName.h"
44 #include "nsXMLContentSink.h"
45 #include "nsIScriptError.h"
46 #include "nsContentTypeParser.h"
48 static mozilla::LazyLogModule
gContentSinkLog("nsXULContentSink");
50 using namespace mozilla
;
51 using namespace mozilla::dom
;
52 //----------------------------------------------------------------------
54 XULContentSinkImpl::ContextStack::ContextStack() : mTop(nullptr), mDepth(0) {}
56 XULContentSinkImpl::ContextStack::~ContextStack() {
64 void XULContentSinkImpl::ContextStack::Push(RefPtr
<nsXULPrototypeNode
>&& aNode
,
66 mTop
= new Entry(std::move(aNode
), aState
, mTop
);
70 nsresult
XULContentSinkImpl::ContextStack::Pop(State
* aState
) {
71 if (mDepth
== 0) return NS_ERROR_UNEXPECTED
;
77 *aState
= entry
->mState
;
83 nsresult
XULContentSinkImpl::ContextStack::GetTopNode(
84 RefPtr
<nsXULPrototypeNode
>& aNode
) {
85 if (mDepth
== 0) return NS_ERROR_UNEXPECTED
;
91 nsresult
XULContentSinkImpl::ContextStack::GetTopChildren(
92 nsPrototypeArray
** aChildren
) {
93 if (mDepth
== 0) return NS_ERROR_UNEXPECTED
;
95 *aChildren
= &(mTop
->mChildren
);
99 void XULContentSinkImpl::ContextStack::Clear() {
102 // Release the root element (and its descendants).
103 Entry
* next
= cur
->mNext
;
112 void XULContentSinkImpl::ContextStack::Traverse(
113 nsCycleCollectionTraversalCallback
& aCb
) {
114 nsCycleCollectionTraversalCallback
& cb
= aCb
;
115 for (ContextStack::Entry
* tmp
= mTop
; tmp
; tmp
= tmp
->mNext
) {
116 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mNode
)
117 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChildren
)
121 //----------------------------------------------------------------------
123 XULContentSinkImpl::XULContentSinkImpl()
127 mConstrainSize(true),
130 XULContentSinkImpl::~XULContentSinkImpl() {
131 // The context stack _should_ be empty, unless something has gone wrong.
132 NS_ASSERTION(mContextStack
.Depth() == 0, "Context stack not empty?");
133 mContextStack
.Clear();
138 //----------------------------------------------------------------------
139 // nsISupports interface
141 NS_IMPL_CYCLE_COLLECTION_CLASS(XULContentSinkImpl
)
143 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(XULContentSinkImpl
)
144 NS_IMPL_CYCLE_COLLECTION_UNLINK(mNodeInfoManager
)
145 tmp
->mContextStack
.Clear();
146 NS_IMPL_CYCLE_COLLECTION_UNLINK(mPrototype
)
147 NS_IMPL_CYCLE_COLLECTION_UNLINK(mParser
)
148 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
150 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(XULContentSinkImpl
)
151 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mNodeInfoManager
)
152 tmp
->mContextStack
.Traverse(cb
);
153 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPrototype
)
154 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParser
)
155 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
157 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(XULContentSinkImpl
)
158 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports
, nsIXMLContentSink
)
159 NS_INTERFACE_MAP_ENTRY(nsIXMLContentSink
)
160 NS_INTERFACE_MAP_ENTRY(nsIExpatSink
)
161 NS_INTERFACE_MAP_ENTRY(nsIContentSink
)
164 NS_IMPL_CYCLE_COLLECTING_ADDREF(XULContentSinkImpl
)
165 NS_IMPL_CYCLE_COLLECTING_RELEASE(XULContentSinkImpl
)
167 //----------------------------------------------------------------------
168 // nsIContentSink interface
171 XULContentSinkImpl::DidBuildModel(bool aTerminated
) {
172 nsCOMPtr
<Document
> doc(mDocument
);
174 mPrototype
->NotifyLoadDone();
178 // Drop our reference to the parser to get rid of a circular
185 XULContentSinkImpl::WillInterrupt(void) {
186 // XXX Notify the docshell, if necessary
190 void XULContentSinkImpl::WillResume() {
191 // XXX Notify the docshell, if necessary
195 XULContentSinkImpl::SetParser(nsParserBase
* aParser
) {
200 void XULContentSinkImpl::SetDocumentCharset(
201 NotNull
<const Encoding
*> aEncoding
) {
202 nsCOMPtr
<Document
> doc(mDocument
);
204 doc
->SetDocumentCharacterSet(aEncoding
);
208 nsISupports
* XULContentSinkImpl::GetTarget() { return ToSupports(mDocument
); }
210 //----------------------------------------------------------------------
212 nsresult
XULContentSinkImpl::Init(Document
* aDocument
,
213 nsXULPrototypeDocument
* aPrototype
) {
214 MOZ_ASSERT(aDocument
!= nullptr, "null ptr");
215 if (!aDocument
) return NS_ERROR_NULL_POINTER
;
217 mDocument
= aDocument
;
218 mPrototype
= aPrototype
;
220 mDocumentURL
= mPrototype
->GetURI();
221 mNodeInfoManager
= aPrototype
->GetNodeInfoManager();
222 if (!mNodeInfoManager
) return NS_ERROR_UNEXPECTED
;
228 //----------------------------------------------------------------------
233 bool XULContentSinkImpl::IsDataInBuffer(char16_t
* buffer
, int32_t length
) {
234 for (int32_t i
= 0; i
< length
; ++i
) {
235 if (buffer
[i
] == ' ' || buffer
[i
] == '\t' || buffer
[i
] == '\n' ||
244 nsresult
XULContentSinkImpl::FlushText(bool aCreateTextNode
) {
248 // Don't do anything if there's no text to create a node from, or
249 // if they've told us not to create a text node
250 if (!mTextLength
) break;
252 if (!aCreateTextNode
) break;
254 RefPtr
<nsXULPrototypeNode
> node
;
255 rv
= mContextStack
.GetTopNode(node
);
256 if (NS_FAILED(rv
)) return rv
;
258 bool stripWhitespace
= false;
259 if (node
->mType
== nsXULPrototypeNode::eType_Element
) {
260 mozilla::dom::NodeInfo
* nodeInfo
=
261 static_cast<nsXULPrototypeElement
*>(node
.get())->mNodeInfo
;
263 if (nodeInfo
->NamespaceEquals(kNameSpaceID_XUL
))
264 stripWhitespace
= !nodeInfo
->Equals(nsGkAtoms::label
) &&
265 !nodeInfo
->Equals(nsGkAtoms::description
);
268 // Don't bother if there's nothing but whitespace.
269 if (stripWhitespace
&& !IsDataInBuffer(mText
, mTextLength
)) break;
271 // Don't bother if we're not in XUL document body
272 if (mState
!= eInDocumentElement
|| mContextStack
.Depth() == 0) break;
274 RefPtr
<nsXULPrototypeText
> text
= new nsXULPrototypeText();
275 text
->mValue
.Assign(mText
, mTextLength
);
276 if (stripWhitespace
) text
->mValue
.Trim(" \t\n\r");
279 nsPrototypeArray
* children
= nullptr;
280 rv
= mContextStack
.GetTopChildren(&children
);
281 if (NS_FAILED(rv
)) return rv
;
283 children
->AppendElement(text
.forget());
286 // Reset our text buffer
291 //----------------------------------------------------------------------
293 nsresult
XULContentSinkImpl::NormalizeAttributeString(
294 const char16_t
* aExpatName
, nsAttrName
& aName
) {
296 RefPtr
<nsAtom
> prefix
, localName
;
297 nsContentUtils::SplitExpatName(aExpatName
, getter_AddRefs(prefix
),
298 getter_AddRefs(localName
), &nameSpaceID
);
300 if (nameSpaceID
== kNameSpaceID_None
) {
301 aName
.SetTo(localName
);
306 RefPtr
<mozilla::dom::NodeInfo
> ni
;
307 ni
= mNodeInfoManager
->GetNodeInfo(localName
, prefix
, nameSpaceID
,
308 nsINode::ATTRIBUTE_NODE
);
314 /**** BEGIN NEW APIs ****/
317 XULContentSinkImpl::HandleStartElement(const char16_t
* aName
,
318 const char16_t
** aAtts
,
320 uint32_t aLineNumber
,
321 uint32_t aColumnNumber
) {
322 // XXX Hopefully the parser will flag this before we get here. If
323 // we're in the epilog, there should be no new elements
324 MOZ_ASSERT(mState
!= eInEpilog
, "tag in XUL doc epilog");
325 MOZ_ASSERT(aAttsCount
% 2 == 0, "incorrect aAttsCount");
327 // Adjust aAttsCount so it's the actual number of attributes
330 if (mState
== eInEpilog
) return NS_ERROR_UNEXPECTED
;
332 if (mState
!= eInScript
) {
337 RefPtr
<nsAtom
> prefix
, localName
;
338 nsContentUtils::SplitExpatName(aName
, getter_AddRefs(prefix
),
339 getter_AddRefs(localName
), &nameSpaceID
);
341 RefPtr
<mozilla::dom::NodeInfo
> nodeInfo
;
342 nodeInfo
= mNodeInfoManager
->GetNodeInfo(localName
, prefix
, nameSpaceID
,
343 nsINode::ELEMENT_NODE
);
348 // We're the root document element
349 rv
= OpenRoot(aAtts
, aAttsCount
, nodeInfo
);
352 case eInDocumentElement
:
353 rv
= OpenTag(aAtts
, aAttsCount
, aLineNumber
, nodeInfo
);
359 gContentSinkLog
, LogLevel::Warning
,
360 ("xul: warning: unexpected tags in epilog at line %d", aLineNumber
));
361 rv
= NS_ERROR_UNEXPECTED
; // XXX
369 XULContentSinkImpl::HandleEndElement(const char16_t
* aName
) {
370 // Never EVER return anything but NS_OK or
371 // NS_ERROR_HTMLPARSER_BLOCK from this method. Doing so will blow
372 // the parser's little mind all over the planet.
375 RefPtr
<nsXULPrototypeNode
> node
;
376 rv
= mContextStack
.GetTopNode(node
);
382 switch (node
->mType
) {
383 case nsXULPrototypeNode::eType_Element
: {
384 // Flush any text _now_, so that we'll get text nodes created
385 // before popping the stack.
388 // Pop the context stack and do prototype hookup.
389 nsPrototypeArray
* children
= nullptr;
390 rv
= mContextStack
.GetTopChildren(&children
);
391 if (NS_FAILED(rv
)) return rv
;
393 nsXULPrototypeElement
* element
=
394 static_cast<nsXULPrototypeElement
*>(node
.get());
396 int32_t count
= children
->Length();
398 element
->mChildren
.SetCapacity(count
);
400 for (int32_t i
= 0; i
< count
; ++i
)
401 element
->mChildren
.AppendElement(children
->ElementAt(i
));
405 case nsXULPrototypeNode::eType_Script
: {
406 nsXULPrototypeScript
* script
=
407 static_cast<nsXULPrototypeScript
*>(node
.get());
409 // If given a src= attribute, we must ignore script tag content.
410 if (!script
->mSrcURI
&& !script
->HasStencil()) {
411 nsCOMPtr
<Document
> doc(mDocument
);
413 script
->mOutOfLine
= false;
415 script
->Compile(mText
, mTextLength
, mDocumentURL
, script
->mLineNo
,
424 NS_ERROR("didn't expect that");
428 rv
= mContextStack
.Pop(&mState
);
429 NS_ASSERTION(NS_SUCCEEDED(rv
), "context stack corrupted");
430 if (NS_FAILED(rv
)) return rv
;
432 if (mContextStack
.Depth() == 0) {
433 // The root element should -always- be an element, because
434 // it'll have been created via XULContentSinkImpl::OpenRoot().
435 NS_ASSERTION(node
->mType
== nsXULPrototypeNode::eType_Element
,
436 "root is not an element");
437 if (node
->mType
!= nsXULPrototypeNode::eType_Element
)
438 return NS_ERROR_UNEXPECTED
;
440 // Now that we're done parsing, set the prototype document's
441 // root element. This transfers ownership of the prototype
442 // element tree to the prototype document.
443 nsXULPrototypeElement
* element
=
444 static_cast<nsXULPrototypeElement
*>(node
.get());
446 mPrototype
->SetRootElement(element
);
454 XULContentSinkImpl::HandleComment(const char16_t
* aName
) {
460 XULContentSinkImpl::HandleCDataSection(const char16_t
* aData
,
463 return AddText(aData
, aLength
);
467 XULContentSinkImpl::HandleDoctypeDecl(const nsAString
& aSubset
,
468 const nsAString
& aName
,
469 const nsAString
& aSystemId
,
470 const nsAString
& aPublicId
,
471 nsISupports
* aCatalogData
) {
476 XULContentSinkImpl::HandleCharacterData(const char16_t
* aData
,
478 if (aData
&& mState
!= eInProlog
&& mState
!= eInEpilog
) {
479 return AddText(aData
, aLength
);
485 XULContentSinkImpl::HandleProcessingInstruction(const char16_t
* aTarget
,
486 const char16_t
* aData
) {
489 const nsDependentString
target(aTarget
);
490 const nsDependentString
data(aData
);
492 // Note: the created nsXULPrototypePI has mRefCnt == 1
493 RefPtr
<nsXULPrototypePI
> pi
= new nsXULPrototypePI();
494 pi
->mTarget
= target
;
497 if (mState
== eInProlog
) {
498 // Note: passing in already addrefed pi
499 return mPrototype
->AddProcessingInstruction(pi
);
503 nsPrototypeArray
* children
= nullptr;
504 rv
= mContextStack
.GetTopChildren(&children
);
509 // XXX(Bug 1631371) Check if this should use a fallible operation as it
510 // pretended earlier.
511 children
->AppendElement(pi
);
517 XULContentSinkImpl::HandleXMLDeclaration(const char16_t
* aVersion
,
518 const char16_t
* aEncoding
,
519 int32_t aStandalone
) {
524 XULContentSinkImpl::ReportError(const char16_t
* aErrorText
,
525 const char16_t
* aSourceText
,
526 nsIScriptError
* aError
, bool* _retval
) {
527 MOZ_ASSERT(aError
&& aSourceText
&& aErrorText
, "Check arguments!!!");
529 // The expat driver should report the error.
534 // make sure to empty the context stack so that
535 // <parsererror> could become the root element.
536 mContextStack
.Clear();
540 // Clear any buffered-up text we have. It's enough to set the length to 0.
541 // The buffer itself is allocated when we're created and deleted in our
542 // destructor, so don't mess with it.
545 // return leaving the document empty if we're asked to not add a <parsererror>
547 nsCOMPtr
<Document
> idoc(mDocument
);
548 if (idoc
&& idoc
->SuppressParserErrorElement()) {
552 const char16_t
* noAtts
[] = {0, 0};
554 constexpr auto errorNs
=
555 u
"http://www.mozilla.org/newlayout/xml/parsererror.xml"_ns
;
557 nsAutoString
parsererror(errorNs
);
558 parsererror
.Append((char16_t
)0xFFFF);
559 parsererror
.AppendLiteral("parsererror");
561 rv
= HandleStartElement(parsererror
.get(), noAtts
, 0, 0, 0);
562 NS_ENSURE_SUCCESS(rv
, rv
);
564 rv
= HandleCharacterData(aErrorText
, NS_strlen(aErrorText
));
565 NS_ENSURE_SUCCESS(rv
, rv
);
567 nsAutoString
sourcetext(errorNs
);
568 sourcetext
.Append((char16_t
)0xFFFF);
569 sourcetext
.AppendLiteral("sourcetext");
571 rv
= HandleStartElement(sourcetext
.get(), noAtts
, 0, 0, 0);
572 NS_ENSURE_SUCCESS(rv
, rv
);
574 rv
= HandleCharacterData(aSourceText
, NS_strlen(aSourceText
));
575 NS_ENSURE_SUCCESS(rv
, rv
);
577 rv
= HandleEndElement(sourcetext
.get());
578 NS_ENSURE_SUCCESS(rv
, rv
);
580 rv
= HandleEndElement(parsererror
.get());
581 NS_ENSURE_SUCCESS(rv
, rv
);
586 nsresult
XULContentSinkImpl::OpenRoot(const char16_t
** aAttributes
,
587 const uint32_t aAttrLen
,
588 mozilla::dom::NodeInfo
* aNodeInfo
) {
589 NS_ASSERTION(mState
== eInProlog
, "how'd we get here?");
590 if (mState
!= eInProlog
) return NS_ERROR_UNEXPECTED
;
592 if (aNodeInfo
->Equals(nsGkAtoms::script
, kNameSpaceID_XHTML
) ||
593 aNodeInfo
->Equals(nsGkAtoms::script
, kNameSpaceID_XUL
)) {
594 MOZ_LOG(gContentSinkLog
, LogLevel::Error
,
595 ("xul: script tag not allowed as root content element"));
597 return NS_ERROR_UNEXPECTED
;
600 // Create the element
601 RefPtr
<nsXULPrototypeElement
> element
= new nsXULPrototypeElement(aNodeInfo
);
603 // Add the attributes
604 nsresult rv
= AddAttributes(aAttributes
, aAttrLen
, element
);
605 if (NS_FAILED(rv
)) return rv
;
607 // Push the element onto the context stack, so that child
608 // containers will hook up to us as their parent.
609 mContextStack
.Push(std::move(element
), mState
);
611 mState
= eInDocumentElement
;
615 nsresult
XULContentSinkImpl::OpenTag(const char16_t
** aAttributes
,
616 const uint32_t aAttrLen
,
617 const uint32_t aLineNumber
,
618 mozilla::dom::NodeInfo
* aNodeInfo
) {
619 // Create the element
620 RefPtr
<nsXULPrototypeElement
> element
= new nsXULPrototypeElement(aNodeInfo
);
622 // Link this element to its parent.
623 nsPrototypeArray
* children
= nullptr;
624 nsresult rv
= mContextStack
.GetTopChildren(&children
);
629 // Add the attributes
630 rv
= AddAttributes(aAttributes
, aAttrLen
, element
);
631 if (NS_FAILED(rv
)) return rv
;
633 children
->AppendElement(element
);
635 if (aNodeInfo
->Equals(nsGkAtoms::script
, kNameSpaceID_XHTML
) ||
636 aNodeInfo
->Equals(nsGkAtoms::script
, kNameSpaceID_XUL
)) {
637 // Do scripty things now
638 rv
= OpenScript(aAttributes
, aLineNumber
);
639 NS_ENSURE_SUCCESS(rv
, rv
);
641 NS_ASSERTION(mState
== eInScript
|| mState
== eInDocumentElement
,
643 if (mState
== eInScript
) {
644 // OpenScript has pushed the nsPrototypeScriptElement onto the
645 // stack, so we're done.
650 // Push the element onto the context stack, so that child
651 // containers will hook up to us as their parent.
652 mContextStack
.Push(std::move(element
), mState
);
654 mState
= eInDocumentElement
;
658 nsresult
XULContentSinkImpl::OpenScript(const char16_t
** aAttributes
,
659 const uint32_t aLineNumber
) {
660 bool isJavaScript
= true;
663 // Look for SRC attribute and look for a LANGUAGE attribute
665 while (*aAttributes
) {
666 const nsDependentString
key(aAttributes
[0]);
667 if (key
.EqualsLiteral("src")) {
668 src
.Assign(aAttributes
[1]);
669 } else if (key
.EqualsLiteral("type")) {
670 nsDependentString
str(aAttributes
[1]);
671 nsContentTypeParser
parser(str
);
672 nsAutoString mimeType
;
673 rv
= parser
.GetType(mimeType
);
675 if (rv
== NS_ERROR_INVALID_ARG
) {
676 // Fail immediately rather than checking if later things
680 // We do want the warning here
681 NS_ENSURE_SUCCESS(rv
, rv
);
684 // NOTE(emilio): Module scripts don't pass this test, aren't cached yet.
685 // If they become cached, then we need to tweak
686 // PrototypeDocumentContentSink and remove the special cases there.
687 if (nsContentUtils::IsJavascriptMIMEType(mimeType
)) {
690 // Get the version string, and ensure that JavaScript supports it.
691 nsAutoString versionName
;
692 rv
= parser
.GetParameter("version", versionName
);
694 if (NS_SUCCEEDED(rv
)) {
695 nsContentUtils::ReportToConsoleNonLocalized(
696 u
"Versioned JavaScripts are no longer supported. "
697 "Please remove the version parameter."_ns
,
698 nsIScriptError::errorFlag
, "XUL Document"_ns
, nullptr,
699 mDocumentURL
, u
""_ns
, aLineNumber
);
700 isJavaScript
= false;
701 } else if (rv
!= NS_ERROR_INVALID_ARG
) {
705 isJavaScript
= false;
707 } else if (key
.EqualsLiteral("language")) {
708 // Language is deprecated, and the impl in ScriptLoader ignores the
709 // various version strings anyway. So we make no attempt to support
710 // languages other than JS for language=
711 nsAutoString
lang(aAttributes
[1]);
712 if (nsContentUtils::IsJavaScriptLanguage(lang
)) {
719 // Don't process scripts that aren't JavaScript.
724 nsCOMPtr
<Document
> doc(mDocument
);
725 nsCOMPtr
<nsIScriptGlobalObject
> globalObject
;
726 if (doc
) globalObject
= do_QueryInterface(doc
->GetWindow());
727 RefPtr
<nsXULPrototypeScript
> script
= new nsXULPrototypeScript(aLineNumber
);
729 // If there is a SRC attribute...
730 if (!src
.IsEmpty()) {
731 // Use the SRC attribute value to load the URL
732 rv
= NS_NewURI(getter_AddRefs(script
->mSrcURI
), src
, nullptr, mDocumentURL
);
734 // Check if this document is allowed to load a script from this source
735 // NOTE: if we ever allow scripts added via the DOM to run, we need to
736 // add a CheckLoadURI call for that as well.
737 if (NS_SUCCEEDED(rv
)) {
739 mSecMan
= do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID
, &rv
);
740 if (NS_SUCCEEDED(rv
) && doc
) {
741 rv
= mSecMan
->CheckLoadURIWithPrincipal(
742 doc
->NodePrincipal(), script
->mSrcURI
,
743 nsIScriptSecurityManager::ALLOW_CHROME
, doc
->InnerWindowID());
751 // Attempt to deserialize an out-of-line script from the FastLoad
752 // file right away. Otherwise we'll end up reloading the script and
753 // corrupting the FastLoad file trying to serialize it, in the case
754 // where it's already there.
755 script
->DeserializeOutOfLine(nullptr, mPrototype
);
758 nsPrototypeArray
* children
= nullptr;
759 rv
= mContextStack
.GetTopChildren(&children
);
764 children
->AppendElement(script
);
766 mConstrainSize
= false;
768 mContextStack
.Push(script
, mState
);
774 nsresult
XULContentSinkImpl::AddAttributes(const char16_t
** aAttributes
,
775 const uint32_t aAttrLen
,
776 nsXULPrototypeElement
* aElement
) {
777 // Add tag attributes to the element
780 // Create storage for the attributes
781 nsXULPrototypeAttribute
* attrs
= nullptr;
783 attrs
= aElement
->mAttributes
.AppendElements(aAttrLen
);
786 // Copy the attributes into the prototype
788 for (i
= 0; i
< aAttrLen
; ++i
) {
789 rv
= NormalizeAttributeString(aAttributes
[i
* 2], attrs
[i
].mName
);
790 NS_ENSURE_SUCCESS(rv
, rv
);
792 rv
= aElement
->SetAttrAt(i
, nsDependentString(aAttributes
[i
* 2 + 1]),
794 NS_ENSURE_SUCCESS(rv
, rv
);
796 if (MOZ_LOG_TEST(gContentSinkLog
, LogLevel::Debug
)) {
797 nsAutoString extraWhiteSpace
;
798 int32_t cnt
= mContextStack
.Depth();
799 while (--cnt
>= 0) extraWhiteSpace
.AppendLiteral(" ");
800 nsAutoString qnameC
, valueC
;
801 qnameC
.Assign(aAttributes
[0]);
802 valueC
.Assign(aAttributes
[1]);
803 MOZ_LOG(gContentSinkLog
, LogLevel::Debug
,
804 ("xul: %.5d. %s %s=%s",
805 -1, // XXX pass in line number
806 NS_ConvertUTF16toUTF8(extraWhiteSpace
).get(),
807 NS_ConvertUTF16toUTF8(qnameC
).get(),
808 NS_ConvertUTF16toUTF8(valueC
).get()));
815 nsresult
XULContentSinkImpl::AddText(const char16_t
* aText
, int32_t aLength
) {
816 // Create buffer when we first need it
817 if (0 == mTextSize
) {
818 mText
= (char16_t
*)malloc(sizeof(char16_t
) * 4096);
819 if (nullptr == mText
) {
820 return NS_ERROR_OUT_OF_MEMORY
;
825 // Copy data from string into our buffer; flush buffer when it fills up
827 while (0 != aLength
) {
828 int32_t amount
= mTextSize
- mTextLength
;
829 if (amount
> aLength
) {
833 if (mConstrainSize
) {
834 nsresult rv
= FlushText();
839 CheckedInt32 size
= mTextSize
;
841 if (!size
.isValid()) {
842 return NS_ERROR_OUT_OF_MEMORY
;
844 mTextSize
= size
.value();
846 mText
= (char16_t
*)realloc(mText
, sizeof(char16_t
) * mTextSize
);
847 if (nullptr == mText
) {
848 return NS_ERROR_OUT_OF_MEMORY
;
852 memcpy(&mText
[mTextLength
], aText
+ offset
, sizeof(char16_t
) * amount
);
854 mTextLength
+= amount
;