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 * Class that represents a prefix/namespace/localName triple; a single
9 * nodeinfo is shared by all elements in a document that have that
10 * prefix, namespace, and localName.
13 #include "mozilla/dom/NodeInfo.h"
14 #include "mozilla/dom/NodeInfoInlines.h"
16 #include "mozilla/ArrayUtils.h"
17 #include "mozilla/Likely.h"
19 #include "nsNodeInfoManager.h"
23 #include "nsDOMString.h"
25 #include "nsContentUtils.h"
26 #include "nsReadableUtils.h"
27 #include "nsAutoPtr.h"
29 #include "nsIDocument.h"
30 #include "nsGkAtoms.h"
31 #include "nsCCUncollectableMarker.h"
32 #include "nsNameSpaceManager.h"
34 using namespace mozilla
;
35 using mozilla::dom::NodeInfo
;
39 mOwnerManager
->RemoveNodeInfo(this);
41 NS_RELEASE(mInner
.mName
);
42 NS_IF_RELEASE(mInner
.mPrefix
);
43 NS_IF_RELEASE(mInner
.mExtraName
);
46 NodeInfo::NodeInfo(nsIAtom
*aName
, nsIAtom
*aPrefix
, int32_t aNamespaceID
,
47 uint16_t aNodeType
, nsIAtom
* aExtraName
,
48 nsNodeInfoManager
*aOwnerManager
)
50 CheckValidNodeInfo(aNodeType
, aName
, aNamespaceID
, aExtraName
);
51 NS_ABORT_IF_FALSE(aOwnerManager
, "Invalid aOwnerManager");
54 NS_ADDREF(mInner
.mName
= aName
);
55 NS_IF_ADDREF(mInner
.mPrefix
= aPrefix
);
56 mInner
.mNamespaceID
= aNamespaceID
;
57 mInner
.mNodeType
= aNodeType
;
58 mOwnerManager
= aOwnerManager
;
59 NS_IF_ADDREF(mInner
.mExtraName
= aExtraName
);
61 mDocument
= aOwnerManager
->GetDocument();
63 // Now compute our cached members.
65 // Qualified name. If we have no prefix, use ToString on
66 // mInner.mName so that we get to share its buffer.
68 mQualifiedName
= nsDependentAtomString(mInner
.mPrefix
) +
69 NS_LITERAL_STRING(":") +
70 nsDependentAtomString(mInner
.mName
);
72 mInner
.mName
->ToString(mQualifiedName
);
75 MOZ_ASSERT_IF(aNodeType
!= nsIDOMNode::ELEMENT_NODE
&&
76 aNodeType
!= nsIDOMNode::ATTRIBUTE_NODE
&&
77 aNodeType
!= UINT16_MAX
,
78 aNamespaceID
== kNameSpaceID_None
&& !aPrefix
);
81 case nsIDOMNode::ELEMENT_NODE
:
82 case nsIDOMNode::ATTRIBUTE_NODE
:
83 // Correct the case for HTML
84 if (aNodeType
== nsIDOMNode::ELEMENT_NODE
&&
85 aNamespaceID
== kNameSpaceID_XHTML
&& GetDocument() &&
86 GetDocument()->IsHTML()) {
87 nsContentUtils::ASCIIToUpper(mQualifiedName
, mNodeName
);
89 mNodeName
= mQualifiedName
;
91 mInner
.mName
->ToString(mLocalName
);
93 case nsIDOMNode::TEXT_NODE
:
94 case nsIDOMNode::CDATA_SECTION_NODE
:
95 case nsIDOMNode::COMMENT_NODE
:
96 case nsIDOMNode::DOCUMENT_NODE
:
97 case nsIDOMNode::DOCUMENT_FRAGMENT_NODE
:
98 mInner
.mName
->ToString(mNodeName
);
99 SetDOMStringToNull(mLocalName
);
101 case nsIDOMNode::PROCESSING_INSTRUCTION_NODE
:
102 case nsIDOMNode::DOCUMENT_TYPE_NODE
:
103 mInner
.mExtraName
->ToString(mNodeName
);
104 SetDOMStringToNull(mLocalName
);
107 NS_ABORT_IF_FALSE(aNodeType
== UINT16_MAX
,
108 "Unknown node type");
115 NS_IMPL_CYCLE_COLLECTION_CLASS(NodeInfo
)
117 NS_IMPL_CYCLE_COLLECTION_UNLINK_0(NodeInfo
)
119 static const char* kNSURIs
[] = {
132 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(NodeInfo
)
133 if (MOZ_UNLIKELY(cb
.WantDebugInfo())) {
135 uint32_t nsid
= tmp
->NamespaceID();
136 nsAtomCString
localName(tmp
->NameAtom());
137 if (nsid
< ArrayLength(kNSURIs
)) {
138 PR_snprintf(name
, sizeof(name
), "NodeInfo%s %s", kNSURIs
[nsid
],
142 PR_snprintf(name
, sizeof(name
), "NodeInfo %s", localName
.get());
145 cb
.DescribeRefCountedNode(tmp
->mRefCnt
.get(), name
);
148 NS_IMPL_CYCLE_COLLECTION_DESCRIBE(NodeInfo
, tmp
->mRefCnt
.get())
151 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOwnerManager
)
152 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
154 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(NodeInfo
)
155 return nsCCUncollectableMarker::sGeneration
&& tmp
->CanSkip();
156 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_END
158 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_BEGIN(NodeInfo
)
159 return nsCCUncollectableMarker::sGeneration
&& tmp
->CanSkip();
160 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_END
162 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_BEGIN(NodeInfo
)
163 return nsCCUncollectableMarker::sGeneration
&& tmp
->CanSkip();
164 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_END
167 NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(NodeInfo
, AddRef
)
168 NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(NodeInfo
, Release
)
171 NodeInfo::GetName(nsAString
& aName
) const
173 mInner
.mName
->ToString(aName
);
177 NodeInfo::GetPrefix(nsAString
& aPrefix
) const
179 if (mInner
.mPrefix
) {
180 mInner
.mPrefix
->ToString(aPrefix
);
182 SetDOMStringToNull(aPrefix
);
187 NodeInfo::GetNamespaceURI(nsAString
& aNameSpaceURI
) const
189 if (mInner
.mNamespaceID
> 0) {
191 nsContentUtils::NameSpaceManager()->GetNameSpaceURI(mInner
.mNamespaceID
,
193 // How can we possibly end up with a bogus namespace ID here?
198 SetDOMStringToNull(aNameSpaceURI
);
203 NodeInfo::NamespaceEquals(const nsAString
& aNamespaceURI
) const
206 nsContentUtils::NameSpaceManager()->GetNameSpaceID(aNamespaceURI
);
208 return mozilla::dom::NodeInfo::NamespaceEquals(nsid
);
212 NodeInfo::DeleteCycleCollectable()
214 nsRefPtr
<nsNodeInfoManager
> kungFuDeathGrip
= mOwnerManager
;
222 nsCCUncollectableMarker::InGeneration(mDocument
->GetMarkedCCGeneration());