Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/base/NodeInfo.cpp
Line
Count
Source (jump to first uncovered line)
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/. */
6
7
/*
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.
11
 */
12
13
#include "mozilla/dom/NodeInfo.h"
14
#include "mozilla/dom/NodeInfoInlines.h"
15
16
#include "mozilla/ArrayUtils.h"
17
#include "mozilla/Likely.h"
18
19
#include "nsNodeInfoManager.h"
20
#include "nsCOMPtr.h"
21
#include "nsString.h"
22
#include "nsAtom.h"
23
#include "nsDOMString.h"
24
#include "nsCRT.h"
25
#include "nsINode.h"
26
#include "nsContentUtils.h"
27
#include "nsReadableUtils.h"
28
#include "mozilla/Sprintf.h"
29
#include "nsIDocument.h"
30
#include "nsGkAtoms.h"
31
#include "nsCCUncollectableMarker.h"
32
#include "nsNameSpaceManager.h"
33
34
using namespace mozilla;
35
using mozilla::dom::NodeInfo;
36
37
NodeInfo::~NodeInfo()
38
0
{
39
0
  mOwnerManager->RemoveNodeInfo(this);
40
0
41
0
  // We can't use NS_IF_RELEASE because mName is const.
42
0
  if (mInner.mName) {
43
0
    mInner.mName->Release();
44
0
  }
45
0
  NS_IF_RELEASE(mInner.mPrefix);
46
0
  NS_IF_RELEASE(mInner.mExtraName);
47
0
}
48
49
NodeInfo::NodeInfo(nsAtom *aName, nsAtom *aPrefix, int32_t aNamespaceID,
50
                   uint16_t aNodeType, nsAtom* aExtraName,
51
                   nsNodeInfoManager *aOwnerManager)
52
  : mDocument(aOwnerManager->GetDocument()),
53
    mInner(aName, aPrefix, aNamespaceID, aNodeType, aExtraName),
54
    mOwnerManager(aOwnerManager)
55
0
{
56
0
  CheckValidNodeInfo(aNodeType, aName, aNamespaceID, aExtraName);
57
0
58
0
  NS_IF_ADDREF(mInner.mName);
59
0
  NS_IF_ADDREF(mInner.mPrefix);
60
0
  NS_IF_ADDREF(mInner.mExtraName);
61
0
62
0
  // Now compute our cached members.
63
0
64
0
  // Qualified name.  If we have no prefix, use ToString on
65
0
  // mInner.mName so that we get to share its buffer.
66
0
  if (aPrefix) {
67
0
    mQualifiedName = nsDependentAtomString(mInner.mPrefix) +
68
0
                     NS_LITERAL_STRING(":") +
69
0
                     nsDependentAtomString(mInner.mName);
70
0
  } else {
71
0
    mInner.mName->ToString(mQualifiedName);
72
0
  }
73
0
74
0
  MOZ_ASSERT_IF(aNodeType != nsINode::ELEMENT_NODE &&
75
0
                aNodeType != nsINode::ATTRIBUTE_NODE &&
76
0
                aNodeType != UINT16_MAX,
77
0
                aNamespaceID == kNameSpaceID_None && !aPrefix);
78
0
79
0
  switch (aNodeType) {
80
0
    case nsINode::ELEMENT_NODE:
81
0
    case nsINode::ATTRIBUTE_NODE:
82
0
      // Correct the case for HTML
83
0
      if (aNodeType == nsINode::ELEMENT_NODE &&
84
0
          aNamespaceID == kNameSpaceID_XHTML && GetDocument() &&
85
0
          GetDocument()->IsHTMLDocument()) {
86
0
        nsContentUtils::ASCIIToUpper(mQualifiedName, mNodeName);
87
0
      } else {
88
0
        mNodeName = mQualifiedName;
89
0
      }
90
0
      mInner.mName->ToString(mLocalName);
91
0
      break;
92
0
    case nsINode::TEXT_NODE:
93
0
    case nsINode::CDATA_SECTION_NODE:
94
0
    case nsINode::COMMENT_NODE:
95
0
    case nsINode::DOCUMENT_NODE:
96
0
    case nsINode::DOCUMENT_FRAGMENT_NODE:
97
0
      mInner.mName->ToString(mNodeName);
98
0
      SetDOMStringToNull(mLocalName);
99
0
      break;
100
0
    case nsINode::PROCESSING_INSTRUCTION_NODE:
101
0
    case nsINode::DOCUMENT_TYPE_NODE:
102
0
      mInner.mExtraName->ToString(mNodeName);
103
0
      SetDOMStringToNull(mLocalName);
104
0
      break;
105
0
    default:
106
0
      MOZ_ASSERT(aNodeType == UINT16_MAX, "Unknown node type");
107
0
  }
108
0
}
109
110
111
// nsISupports
112
113
NS_IMPL_CYCLE_COLLECTION_CLASS(NodeInfo)
114
115
NS_IMPL_CYCLE_COLLECTION_UNLINK_0(NodeInfo)
116
117
static const char* kNodeInfoNSURIs[] = {
118
  " ([none])",
119
  " (xmlns)",
120
  " (xml)",
121
  " (xhtml)",
122
  " (XLink)",
123
  " (XSLT)",
124
  " (XBL)",
125
  " (MathML)",
126
  " (RDF)",
127
  " (XUL)"
128
};
129
130
0
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(NodeInfo)
131
0
  if (MOZ_UNLIKELY(cb.WantDebugInfo())) {
132
0
    char name[72];
133
0
    uint32_t nsid = tmp->NamespaceID();
134
0
    nsAtomCString localName(tmp->NameAtom());
135
0
    if (nsid < ArrayLength(kNodeInfoNSURIs)) {
136
0
      SprintfLiteral(name, "NodeInfo%s %s", kNodeInfoNSURIs[nsid],
137
0
                     localName.get());
138
0
    }
139
0
    else {
140
0
      SprintfLiteral(name, "NodeInfo %s", localName.get());
141
0
    }
142
0
143
0
    cb.DescribeRefCountedNode(tmp->mRefCnt.get(), name);
144
0
  }
145
0
  else {
146
0
    NS_IMPL_CYCLE_COLLECTION_DESCRIBE(NodeInfo, tmp->mRefCnt.get())
147
0
  }
148
0
149
0
  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOwnerManager)
150
0
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
151
152
0
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(NodeInfo)
153
0
  return nsCCUncollectableMarker::sGeneration && tmp->CanSkip();
154
0
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_END
155
156
0
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_BEGIN(NodeInfo)
157
0
  return nsCCUncollectableMarker::sGeneration && tmp->CanSkip();
158
0
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_END
159
160
0
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_BEGIN(NodeInfo)
161
0
  return nsCCUncollectableMarker::sGeneration && tmp->CanSkip();
162
0
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_END
163
164
165
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(NodeInfo, AddRef)
166
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(NodeInfo, Release)
167
168
void
169
NodeInfo::GetName(nsAString& aName) const
170
0
{
171
0
  mInner.mName->ToString(aName);
172
0
}
173
174
void
175
NodeInfo::GetPrefix(nsAString& aPrefix) const
176
0
{
177
0
  if (mInner.mPrefix) {
178
0
    mInner.mPrefix->ToString(aPrefix);
179
0
  } else {
180
0
    SetDOMStringToNull(aPrefix);
181
0
  }
182
0
}
183
184
void
185
NodeInfo::GetNamespaceURI(nsAString& aNameSpaceURI) const
186
0
{
187
0
  if (mInner.mNamespaceID > 0) {
188
0
    nsresult rv =
189
0
      nsContentUtils::NameSpaceManager()->GetNameSpaceURI(mInner.mNamespaceID,
190
0
                                                          aNameSpaceURI);
191
0
    // How can we possibly end up with a bogus namespace ID here?
192
0
    if (NS_FAILED(rv)) {
193
0
      MOZ_CRASH();
194
0
    }
195
0
  } else {
196
0
    SetDOMStringToNull(aNameSpaceURI);
197
0
  }
198
0
}
199
200
bool
201
NodeInfo::NamespaceEquals(const nsAString& aNamespaceURI) const
202
0
{
203
0
  int32_t nsid =
204
0
    nsContentUtils::NameSpaceManager()->GetNameSpaceID(aNamespaceURI,
205
0
      nsContentUtils::IsChromeDoc(mOwnerManager->GetDocument()));
206
0
207
0
  return mozilla::dom::NodeInfo::NamespaceEquals(nsid);
208
0
}
209
210
void
211
NodeInfo::DeleteCycleCollectable()
212
0
{
213
0
  RefPtr<nsNodeInfoManager> kungFuDeathGrip = mOwnerManager;
214
0
  mozilla::Unused << kungFuDeathGrip; // Just keeping value alive for longer than this
215
0
  delete this;
216
0
}
217
218
bool
219
NodeInfo::CanSkip()
220
0
{
221
0
  return mDocument &&
222
0
    nsCCUncollectableMarker::InGeneration(mDocument->GetMarkedCCGeneration());
223
0
}