content/base/src/nsNodeInfo.cpp

changeset 0
6474c204b198
     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 +}

mercurial