1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/content/base/src/nsNodeInfo.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,212 @@ 1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ 1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +/* 1.11 + * Class that represents a prefix/namespace/localName triple; a single 1.12 + * nodeinfo is shared by all elements in a document that have that 1.13 + * prefix, namespace, and localName. 1.14 + */ 1.15 + 1.16 +#include "mozilla/ArrayUtils.h" 1.17 +#include "mozilla/Likely.h" 1.18 + 1.19 +#include "nscore.h" 1.20 +#include "nsNodeInfo.h" 1.21 +#include "nsNodeInfoManager.h" 1.22 +#include "nsCOMPtr.h" 1.23 +#include "nsString.h" 1.24 +#include "nsIAtom.h" 1.25 +#include "nsDOMString.h" 1.26 +#include "nsCRT.h" 1.27 +#include "nsContentUtils.h" 1.28 +#include "nsReadableUtils.h" 1.29 +#include "nsAutoPtr.h" 1.30 +#include "prprf.h" 1.31 +#include "nsIDocument.h" 1.32 +#include "nsGkAtoms.h" 1.33 +#include "nsCCUncollectableMarker.h" 1.34 + 1.35 +using namespace mozilla; 1.36 + 1.37 +nsNodeInfo::~nsNodeInfo() 1.38 +{ 1.39 + mOwnerManager->RemoveNodeInfo(this); 1.40 + 1.41 + NS_RELEASE(mInner.mName); 1.42 + NS_IF_RELEASE(mInner.mPrefix); 1.43 + NS_IF_RELEASE(mInner.mExtraName); 1.44 +} 1.45 + 1.46 + 1.47 +nsNodeInfo::nsNodeInfo(nsIAtom *aName, nsIAtom *aPrefix, int32_t aNamespaceID, 1.48 + uint16_t aNodeType, nsIAtom* aExtraName, 1.49 + nsNodeInfoManager *aOwnerManager) 1.50 +{ 1.51 + CheckValidNodeInfo(aNodeType, aName, aNamespaceID, aExtraName); 1.52 + NS_ABORT_IF_FALSE(aOwnerManager, "Invalid aOwnerManager"); 1.53 + 1.54 + // Initialize mInner 1.55 + NS_ADDREF(mInner.mName = aName); 1.56 + NS_IF_ADDREF(mInner.mPrefix = aPrefix); 1.57 + mInner.mNamespaceID = aNamespaceID; 1.58 + mInner.mNodeType = aNodeType; 1.59 + mOwnerManager = aOwnerManager; 1.60 + NS_IF_ADDREF(mInner.mExtraName = aExtraName); 1.61 + 1.62 + mDocument = aOwnerManager->GetDocument(); 1.63 + 1.64 + // Now compute our cached members. 1.65 + 1.66 + // Qualified name. If we have no prefix, use ToString on 1.67 + // mInner.mName so that we get to share its buffer. 1.68 + if (aPrefix) { 1.69 + mQualifiedName = nsDependentAtomString(mInner.mPrefix) + 1.70 + NS_LITERAL_STRING(":") + 1.71 + nsDependentAtomString(mInner.mName); 1.72 + } else { 1.73 + mInner.mName->ToString(mQualifiedName); 1.74 + } 1.75 + 1.76 + MOZ_ASSERT_IF(aNodeType != nsIDOMNode::ELEMENT_NODE && 1.77 + aNodeType != nsIDOMNode::ATTRIBUTE_NODE && 1.78 + aNodeType != UINT16_MAX, 1.79 + aNamespaceID == kNameSpaceID_None && !aPrefix); 1.80 + 1.81 + switch (aNodeType) { 1.82 + case nsIDOMNode::ELEMENT_NODE: 1.83 + case nsIDOMNode::ATTRIBUTE_NODE: 1.84 + // Correct the case for HTML 1.85 + if (aNodeType == nsIDOMNode::ELEMENT_NODE && 1.86 + aNamespaceID == kNameSpaceID_XHTML && GetDocument() && 1.87 + GetDocument()->IsHTML()) { 1.88 + nsContentUtils::ASCIIToUpper(mQualifiedName, mNodeName); 1.89 + } else { 1.90 + mNodeName = mQualifiedName; 1.91 + } 1.92 + mInner.mName->ToString(mLocalName); 1.93 + break; 1.94 + case nsIDOMNode::TEXT_NODE: 1.95 + case nsIDOMNode::CDATA_SECTION_NODE: 1.96 + case nsIDOMNode::COMMENT_NODE: 1.97 + case nsIDOMNode::DOCUMENT_NODE: 1.98 + case nsIDOMNode::DOCUMENT_FRAGMENT_NODE: 1.99 + mInner.mName->ToString(mNodeName); 1.100 + SetDOMStringToNull(mLocalName); 1.101 + break; 1.102 + case nsIDOMNode::PROCESSING_INSTRUCTION_NODE: 1.103 + case nsIDOMNode::DOCUMENT_TYPE_NODE: 1.104 + mInner.mExtraName->ToString(mNodeName); 1.105 + SetDOMStringToNull(mLocalName); 1.106 + break; 1.107 + default: 1.108 + NS_ABORT_IF_FALSE(aNodeType == UINT16_MAX, 1.109 + "Unknown node type"); 1.110 + } 1.111 +} 1.112 + 1.113 + 1.114 +// nsISupports 1.115 + 1.116 +NS_IMPL_CYCLE_COLLECTION_CLASS(nsNodeInfo) 1.117 + 1.118 +NS_IMPL_CYCLE_COLLECTION_UNLINK_0(nsNodeInfo) 1.119 + 1.120 +static const char* kNSURIs[] = { 1.121 + " ([none])", 1.122 + " (xmlns)", 1.123 + " (xml)", 1.124 + " (xhtml)", 1.125 + " (XLink)", 1.126 + " (XSLT)", 1.127 + " (XBL)", 1.128 + " (MathML)", 1.129 + " (RDF)", 1.130 + " (XUL)" 1.131 +}; 1.132 + 1.133 +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsNodeInfo) 1.134 + if (MOZ_UNLIKELY(cb.WantDebugInfo())) { 1.135 + char name[72]; 1.136 + uint32_t nsid = tmp->NamespaceID(); 1.137 + nsAtomCString localName(tmp->NameAtom()); 1.138 + if (nsid < ArrayLength(kNSURIs)) { 1.139 + PR_snprintf(name, sizeof(name), "nsNodeInfo%s %s", kNSURIs[nsid], 1.140 + localName.get()); 1.141 + } 1.142 + else { 1.143 + PR_snprintf(name, sizeof(name), "nsNodeInfo %s", localName.get()); 1.144 + } 1.145 + 1.146 + cb.DescribeRefCountedNode(tmp->mRefCnt.get(), name); 1.147 + } 1.148 + else { 1.149 + NS_IMPL_CYCLE_COLLECTION_DESCRIBE(nsNodeInfo, tmp->mRefCnt.get()) 1.150 + } 1.151 + 1.152 + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOwnerManager) 1.153 +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END 1.154 + 1.155 +NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(nsNodeInfo) 1.156 + return nsCCUncollectableMarker::sGeneration && tmp->CanSkip(); 1.157 +NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_END 1.158 + 1.159 +NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_BEGIN(nsNodeInfo) 1.160 + return nsCCUncollectableMarker::sGeneration && tmp->CanSkip(); 1.161 +NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_END 1.162 + 1.163 +NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_BEGIN(nsNodeInfo) 1.164 + return nsCCUncollectableMarker::sGeneration && tmp->CanSkip(); 1.165 +NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_END 1.166 + 1.167 + 1.168 +NS_IMPL_CYCLE_COLLECTING_ADDREF(nsNodeInfo) 1.169 +NS_IMPL_CYCLE_COLLECTING_RELEASE_WITH_DESTROY(nsNodeInfo, LastRelease()) 1.170 +NS_INTERFACE_TABLE_HEAD(nsNodeInfo) 1.171 + NS_INTERFACE_TABLE(nsNodeInfo, nsINodeInfo) 1.172 + NS_INTERFACE_TABLE_TO_MAP_SEGUE_CYCLE_COLLECTION(nsNodeInfo) 1.173 +NS_INTERFACE_MAP_END 1.174 + 1.175 +// nsINodeInfo 1.176 + 1.177 +void 1.178 +nsNodeInfo::GetNamespaceURI(nsAString& aNameSpaceURI) const 1.179 +{ 1.180 + if (mInner.mNamespaceID > 0) { 1.181 + nsresult rv = 1.182 + nsContentUtils::NameSpaceManager()->GetNameSpaceURI(mInner.mNamespaceID, 1.183 + aNameSpaceURI); 1.184 + // How can we possibly end up with a bogus namespace ID here? 1.185 + if (NS_FAILED(rv)) { 1.186 + MOZ_CRASH(); 1.187 + } 1.188 + } else { 1.189 + SetDOMStringToNull(aNameSpaceURI); 1.190 + } 1.191 +} 1.192 + 1.193 + 1.194 +bool 1.195 +nsNodeInfo::NamespaceEquals(const nsAString& aNamespaceURI) const 1.196 +{ 1.197 + int32_t nsid = 1.198 + nsContentUtils::NameSpaceManager()->GetNameSpaceID(aNamespaceURI); 1.199 + 1.200 + return nsINodeInfo::NamespaceEquals(nsid); 1.201 +} 1.202 + 1.203 +void 1.204 +nsNodeInfo::LastRelease() 1.205 +{ 1.206 + nsRefPtr<nsNodeInfoManager> kungFuDeathGrip = mOwnerManager; 1.207 + delete this; 1.208 +} 1.209 + 1.210 +bool 1.211 +nsNodeInfo::CanSkip() 1.212 +{ 1.213 + return mDocument && 1.214 + nsCCUncollectableMarker::InGeneration(mDocument->GetMarkedCCGeneration()); 1.215 +}