Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/base/Attr.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
 * Implementation of DOM Core's Attr node.
9
 */
10
11
#include "mozilla/dom/Attr.h"
12
#include "mozilla/dom/AttrBinding.h"
13
#include "mozilla/dom/Element.h"
14
#include "mozilla/EventDispatcher.h"
15
#include "mozilla/InternalMutationEvent.h"
16
#include "nsContentCreatorFunctions.h"
17
#include "nsError.h"
18
#include "nsUnicharUtils.h"
19
#include "nsDOMString.h"
20
#include "nsIContentInlines.h"
21
#include "nsIDocument.h"
22
#include "nsGkAtoms.h"
23
#include "nsCOMArray.h"
24
#include "nsNameSpaceManager.h"
25
#include "nsNodeUtils.h"
26
#include "nsTextNode.h"
27
#include "mozAutoDocUpdate.h"
28
#include "nsWrapperCacheInlines.h"
29
#include "NodeUbiReporting.h"
30
31
namespace mozilla {
32
namespace dom {
33
34
//----------------------------------------------------------------------
35
bool Attr::sInitialized;
36
37
Attr::Attr(nsDOMAttributeMap *aAttrMap,
38
           already_AddRefed<dom::NodeInfo>&& aNodeInfo,
39
           const nsAString& aValue)
40
  : nsINode(std::move(aNodeInfo)), mAttrMap(aAttrMap), mValue(aValue)
41
0
{
42
0
  MOZ_ASSERT(mNodeInfo, "We must get a nodeinfo here!");
43
0
  MOZ_ASSERT(mNodeInfo->NodeType() == ATTRIBUTE_NODE,
44
0
             "Wrong nodeType");
45
0
46
0
  // We don't add a reference to our content. It will tell us
47
0
  // to drop our reference when it goes away.
48
0
}
49
50
NS_IMPL_CYCLE_COLLECTION_CLASS(Attr)
51
52
0
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Attr)
53
0
  if (!nsINode::Traverse(tmp, cb)) {
54
0
    return NS_SUCCESS_INTERRUPTED_TRAVERSE;
55
0
  }
56
0
  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAttrMap)
57
0
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
58
59
NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(Attr)
60
61
0
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Attr)
62
0
  nsINode::Unlink(tmp);
63
0
  NS_IMPL_CYCLE_COLLECTION_UNLINK(mAttrMap)
64
0
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
65
66
0
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(Attr)
67
0
  Element* ownerElement = tmp->GetElement();
68
0
  if (tmp->HasKnownLiveWrapper()) {
69
0
    if (ownerElement) {
70
0
      // The attribute owns the element via attribute map so we can
71
0
      // mark it when the attribute is certainly alive.
72
0
      mozilla::dom::FragmentOrElement::MarkNodeChildren(ownerElement);
73
0
    }
74
0
    return true;
75
0
  }
76
0
  if (ownerElement &&
77
0
      mozilla::dom::FragmentOrElement::CanSkip(ownerElement, true)) {
78
0
    return true;
79
0
  }
80
0
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_END
81
0
82
0
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_BEGIN(Attr)
83
0
  return tmp->HasKnownLiveWrapperAndDoesNotNeedTracing(tmp);
84
0
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_END
85
86
0
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_BEGIN(Attr)
87
0
  return tmp->HasKnownLiveWrapper();
88
0
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_END
89
90
// QueryInterface implementation for Attr
91
0
NS_INTERFACE_TABLE_HEAD(Attr)
92
0
  NS_WRAPPERCACHE_INTERFACE_TABLE_ENTRY
93
0
  NS_INTERFACE_TABLE(Attr, nsINode, EventTarget)
94
0
  NS_INTERFACE_TABLE_TO_MAP_SEGUE_CYCLE_COLLECTION(Attr)
95
0
  NS_INTERFACE_MAP_ENTRY_TEAROFF(nsISupportsWeakReference,
96
0
                                 new nsNodeSupportsWeakRefTearoff(this))
97
0
NS_INTERFACE_MAP_END
98
99
NS_IMPL_CYCLE_COLLECTING_ADDREF(Attr)
100
NS_IMPL_CYCLE_COLLECTING_RELEASE_WITH_LAST_RELEASE(Attr,
101
                                                   nsNodeUtils::LastRelease(this))
102
103
void
104
Attr::SetMap(nsDOMAttributeMap *aMap)
105
0
{
106
0
  if (mAttrMap && !aMap && sInitialized) {
107
0
    // We're breaking a relationship with content and not getting a new one,
108
0
    // need to locally cache value. GetValue() does that.
109
0
    GetValue(mValue);
110
0
  }
111
0
112
0
  mAttrMap = aMap;
113
0
}
114
115
Element*
116
Attr::GetElement() const
117
0
{
118
0
  if (!mAttrMap) {
119
0
    return nullptr;
120
0
  }
121
0
  nsIContent* content = mAttrMap->GetContent();
122
0
  return content ? content->AsElement() : nullptr;
123
0
}
124
125
nsresult
126
Attr::SetOwnerDocument(nsIDocument* aDocument)
127
0
{
128
0
  NS_ASSERTION(aDocument, "Missing document");
129
0
130
0
  nsIDocument *doc = OwnerDoc();
131
0
  NS_ASSERTION(doc != aDocument, "bad call to Attr::SetOwnerDocument");
132
0
  doc->DeleteAllPropertiesFor(this);
133
0
134
0
  RefPtr<dom::NodeInfo> newNodeInfo =
135
0
    aDocument->NodeInfoManager()->
136
0
      GetNodeInfo(mNodeInfo->NameAtom(), mNodeInfo->GetPrefixAtom(),
137
0
                  mNodeInfo->NamespaceID(), ATTRIBUTE_NODE);
138
0
  NS_ASSERTION(newNodeInfo, "GetNodeInfo lies");
139
0
  mNodeInfo.swap(newNodeInfo);
140
0
141
0
  return NS_OK;
142
0
}
143
144
void
145
Attr::GetName(nsAString& aName)
146
0
{
147
0
  aName = NodeName();
148
0
}
149
150
void
151
Attr::GetValue(nsAString& aValue)
152
0
{
153
0
  Element* element = GetElement();
154
0
  if (element) {
155
0
    RefPtr<nsAtom> nameAtom = mNodeInfo->NameAtom();
156
0
    element->GetAttr(mNodeInfo->NamespaceID(), nameAtom, aValue);
157
0
  }
158
0
  else {
159
0
    aValue = mValue;
160
0
  }
161
0
}
162
163
void
164
Attr::SetValue(const nsAString& aValue, nsIPrincipal* aTriggeringPrincipal, ErrorResult& aRv)
165
0
{
166
0
  Element* element = GetElement();
167
0
  if (!element) {
168
0
    mValue = aValue;
169
0
    return;
170
0
  }
171
0
172
0
  RefPtr<nsAtom> nameAtom = mNodeInfo->NameAtom();
173
0
  aRv = element->SetAttr(mNodeInfo->NamespaceID(),
174
0
                         nameAtom,
175
0
                         mNodeInfo->GetPrefixAtom(),
176
0
                         aValue,
177
0
                         aTriggeringPrincipal,
178
0
                         true);
179
0
}
180
181
void
182
Attr::SetValue(const nsAString& aValue, ErrorResult& aRv)
183
0
{
184
0
  SetValue(aValue, nullptr, aRv);
185
0
}
186
187
bool
188
Attr::Specified() const
189
0
{
190
0
  return true;
191
0
}
192
193
Element*
194
Attr::GetOwnerElement(ErrorResult& aRv)
195
0
{
196
0
  return GetElement();
197
0
}
198
199
void
200
Attr::GetNodeValueInternal(nsAString& aNodeValue)
201
0
{
202
0
  GetValue(aNodeValue);
203
0
}
204
205
void
206
Attr::SetNodeValueInternal(const nsAString& aNodeValue, ErrorResult& aError)
207
0
{
208
0
  SetValue(aNodeValue, nullptr, aError);
209
0
}
210
211
nsresult
212
Attr::Clone(dom::NodeInfo* aNodeInfo, nsINode** aResult) const
213
0
{
214
0
  nsAutoString value;
215
0
  const_cast<Attr*>(this)->GetValue(value);
216
0
217
0
  *aResult = new Attr(nullptr, do_AddRef(aNodeInfo), value);
218
0
  if (!*aResult) {
219
0
    return NS_ERROR_OUT_OF_MEMORY;
220
0
  }
221
0
222
0
  NS_ADDREF(*aResult);
223
0
224
0
  return NS_OK;
225
0
}
226
227
already_AddRefed<nsIURI>
228
Attr::GetBaseURI(bool aTryUseXHRDocBaseURI) const
229
0
{
230
0
  Element* parent = GetElement();
231
0
232
0
  return parent ? parent->GetBaseURI(aTryUseXHRDocBaseURI) : nullptr;
233
0
}
234
235
void
236
Attr::GetTextContentInternal(nsAString& aTextContent,
237
                             OOMReporter& aError)
238
0
{
239
0
  GetValue(aTextContent);
240
0
}
241
242
void
243
Attr::SetTextContentInternal(const nsAString& aTextContent,
244
                             nsIPrincipal* aSubjectPrincipal,
245
                             ErrorResult& aError)
246
0
{
247
0
  SetNodeValueInternal(aTextContent, aError);
248
0
}
249
250
bool
251
Attr::IsNodeOfType(uint32_t aFlags) const
252
0
{
253
0
    return false;
254
0
}
255
256
void
257
Attr::GetEventTargetParent(EventChainPreVisitor& aVisitor)
258
0
{
259
0
  aVisitor.mCanHandle = true;
260
0
}
261
262
void
263
Attr::Initialize()
264
3
{
265
3
  sInitialized = true;
266
3
}
267
268
void
269
Attr::Shutdown()
270
0
{
271
0
  sInitialized = false;
272
0
}
273
274
JSObject*
275
Attr::WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
276
0
{
277
0
  return Attr_Binding::Wrap(aCx, this, aGivenProto);
278
0
}
279
280
void
281
Attr::ConstructUbiNode(void* storage)
282
0
{
283
0
  JS::ubi::Concrete<Attr>::construct(storage, this);
284
0
}
285
286
} // namespace dom
287
} // namespace mozilla