content/base/src/nsDOMAttributeMap.cpp

Thu, 15 Jan 2015 21:03:48 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 15 Jan 2015 21:03:48 +0100
branch
TOR_BUG_9701
changeset 11
deefc01c0e14
permissions
-rw-r--r--

Integrate friendly tips from Tor colleagues to make (or not) 4.5 alpha 3;
This includes removal of overloaded (but unused) methods, and addition of
a overlooked call to DataStruct::SetData(nsISupports, uint32_t, bool.)

michael@0 1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 /*
michael@0 7 * Implementation of the |attributes| property of DOM Core's Element object.
michael@0 8 */
michael@0 9
michael@0 10 #include "nsDOMAttributeMap.h"
michael@0 11
michael@0 12 #include "mozilla/MemoryReporting.h"
michael@0 13 #include "mozilla/dom/Attr.h"
michael@0 14 #include "mozilla/dom/Element.h"
michael@0 15 #include "mozilla/dom/MozNamedAttrMapBinding.h"
michael@0 16 #include "nsAttrName.h"
michael@0 17 #include "nsContentUtils.h"
michael@0 18 #include "nsError.h"
michael@0 19 #include "nsIContentInlines.h"
michael@0 20 #include "nsIDocument.h"
michael@0 21 #include "nsNameSpaceManager.h"
michael@0 22 #include "nsNodeInfoManager.h"
michael@0 23 #include "nsUnicharUtils.h"
michael@0 24 #include "nsWrapperCacheInlines.h"
michael@0 25
michael@0 26 using namespace mozilla;
michael@0 27 using namespace mozilla::dom;
michael@0 28
michael@0 29 //----------------------------------------------------------------------
michael@0 30
michael@0 31 nsDOMAttributeMap::nsDOMAttributeMap(Element* aContent)
michael@0 32 : mContent(aContent)
michael@0 33 {
michael@0 34 // We don't add a reference to our content. If it goes away,
michael@0 35 // we'll be told to drop our reference
michael@0 36 SetIsDOMBinding();
michael@0 37 }
michael@0 38
michael@0 39 /**
michael@0 40 * Clear map pointer for attributes.
michael@0 41 */
michael@0 42 PLDHashOperator
michael@0 43 RemoveMapRef(nsAttrHashKey::KeyType aKey, nsRefPtr<Attr>& aData,
michael@0 44 void* aUserArg)
michael@0 45 {
michael@0 46 aData->SetMap(nullptr);
michael@0 47
michael@0 48 return PL_DHASH_REMOVE;
michael@0 49 }
michael@0 50
michael@0 51 nsDOMAttributeMap::~nsDOMAttributeMap()
michael@0 52 {
michael@0 53 mAttributeCache.Enumerate(RemoveMapRef, nullptr);
michael@0 54 }
michael@0 55
michael@0 56 void
michael@0 57 nsDOMAttributeMap::DropReference()
michael@0 58 {
michael@0 59 mAttributeCache.Enumerate(RemoveMapRef, nullptr);
michael@0 60 mContent = nullptr;
michael@0 61 }
michael@0 62
michael@0 63 NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMAttributeMap)
michael@0 64
michael@0 65 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDOMAttributeMap)
michael@0 66 tmp->DropReference();
michael@0 67 NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
michael@0 68 NS_IMPL_CYCLE_COLLECTION_UNLINK(mContent)
michael@0 69 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
michael@0 70
michael@0 71
michael@0 72 PLDHashOperator
michael@0 73 TraverseMapEntry(nsAttrHashKey::KeyType aKey, nsRefPtr<Attr>& aData,
michael@0 74 void* aUserArg)
michael@0 75 {
michael@0 76 nsCycleCollectionTraversalCallback *cb =
michael@0 77 static_cast<nsCycleCollectionTraversalCallback*>(aUserArg);
michael@0 78
michael@0 79 cb->NoteXPCOMChild(static_cast<nsINode*>(aData.get()));
michael@0 80
michael@0 81 return PL_DHASH_NEXT;
michael@0 82 }
michael@0 83
michael@0 84 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsDOMAttributeMap)
michael@0 85 tmp->mAttributeCache.Enumerate(TraverseMapEntry, &cb);
michael@0 86 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
michael@0 87 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mContent)
michael@0 88 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
michael@0 89
michael@0 90 NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(nsDOMAttributeMap)
michael@0 91
michael@0 92 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(nsDOMAttributeMap)
michael@0 93 if (tmp->IsBlack()) {
michael@0 94 if (tmp->mContent) {
michael@0 95 // The map owns the element so we can mark it when the
michael@0 96 // map itself is certainly alive.
michael@0 97 mozilla::dom::FragmentOrElement::MarkNodeChildren(tmp->mContent);
michael@0 98 }
michael@0 99 return true;
michael@0 100 }
michael@0 101 if (tmp->mContent &&
michael@0 102 mozilla::dom::FragmentOrElement::CanSkip(tmp->mContent, true)) {
michael@0 103 return true;
michael@0 104 }
michael@0 105 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_END
michael@0 106
michael@0 107 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_BEGIN(nsDOMAttributeMap)
michael@0 108 return tmp->IsBlackAndDoesNotNeedTracing(tmp);
michael@0 109 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_END
michael@0 110
michael@0 111 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_BEGIN(nsDOMAttributeMap)
michael@0 112 return tmp->IsBlack();
michael@0 113 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_END
michael@0 114
michael@0 115 // QueryInterface implementation for nsDOMAttributeMap
michael@0 116 NS_INTERFACE_TABLE_HEAD(nsDOMAttributeMap)
michael@0 117 NS_INTERFACE_TABLE(nsDOMAttributeMap, nsIDOMMozNamedAttrMap)
michael@0 118 NS_INTERFACE_TABLE_TO_MAP_SEGUE
michael@0 119 NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
michael@0 120 NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(nsDOMAttributeMap)
michael@0 121 NS_INTERFACE_MAP_END
michael@0 122
michael@0 123 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDOMAttributeMap)
michael@0 124 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsDOMAttributeMap)
michael@0 125
michael@0 126 PLDHashOperator
michael@0 127 SetOwnerDocumentFunc(nsAttrHashKey::KeyType aKey,
michael@0 128 nsRefPtr<Attr>& aData,
michael@0 129 void* aUserArg)
michael@0 130 {
michael@0 131 nsresult rv = aData->SetOwnerDocument(static_cast<nsIDocument*>(aUserArg));
michael@0 132
michael@0 133 return NS_FAILED(rv) ? PL_DHASH_STOP : PL_DHASH_NEXT;
michael@0 134 }
michael@0 135
michael@0 136 nsresult
michael@0 137 nsDOMAttributeMap::SetOwnerDocument(nsIDocument* aDocument)
michael@0 138 {
michael@0 139 uint32_t n = mAttributeCache.Enumerate(SetOwnerDocumentFunc, aDocument);
michael@0 140 NS_ENSURE_TRUE(n == mAttributeCache.Count(), NS_ERROR_FAILURE);
michael@0 141
michael@0 142 return NS_OK;
michael@0 143 }
michael@0 144
michael@0 145 void
michael@0 146 nsDOMAttributeMap::DropAttribute(int32_t aNamespaceID, nsIAtom* aLocalName)
michael@0 147 {
michael@0 148 nsAttrKey attr(aNamespaceID, aLocalName);
michael@0 149 Attr *node = mAttributeCache.GetWeak(attr);
michael@0 150 if (node) {
michael@0 151 // Break link to map
michael@0 152 node->SetMap(nullptr);
michael@0 153
michael@0 154 // Remove from cache
michael@0 155 mAttributeCache.Remove(attr);
michael@0 156 }
michael@0 157 }
michael@0 158
michael@0 159 already_AddRefed<Attr>
michael@0 160 nsDOMAttributeMap::RemoveAttribute(nsINodeInfo* aNodeInfo)
michael@0 161 {
michael@0 162 NS_ASSERTION(aNodeInfo, "RemoveAttribute() called with aNodeInfo == nullptr!");
michael@0 163
michael@0 164 nsAttrKey attr(aNodeInfo->NamespaceID(), aNodeInfo->NameAtom());
michael@0 165
michael@0 166 nsRefPtr<Attr> node;
michael@0 167 if (!mAttributeCache.Get(attr, getter_AddRefs(node))) {
michael@0 168 nsAutoString value;
michael@0 169 // As we are removing the attribute we need to set the current value in
michael@0 170 // the attribute node.
michael@0 171 mContent->GetAttr(aNodeInfo->NamespaceID(), aNodeInfo->NameAtom(), value);
michael@0 172 nsCOMPtr<nsINodeInfo> ni = aNodeInfo;
michael@0 173 node = new Attr(nullptr, ni.forget(), value, true);
michael@0 174 }
michael@0 175 else {
michael@0 176 // Break link to map
michael@0 177 node->SetMap(nullptr);
michael@0 178
michael@0 179 // Remove from cache
michael@0 180 mAttributeCache.Remove(attr);
michael@0 181 }
michael@0 182
michael@0 183 return node.forget();
michael@0 184 }
michael@0 185
michael@0 186 Attr*
michael@0 187 nsDOMAttributeMap::GetAttribute(nsINodeInfo* aNodeInfo, bool aNsAware)
michael@0 188 {
michael@0 189 NS_ASSERTION(aNodeInfo, "GetAttribute() called with aNodeInfo == nullptr!");
michael@0 190
michael@0 191 nsAttrKey attr(aNodeInfo->NamespaceID(), aNodeInfo->NameAtom());
michael@0 192
michael@0 193 Attr* node = mAttributeCache.GetWeak(attr);
michael@0 194 if (!node) {
michael@0 195 nsCOMPtr<nsINodeInfo> ni = aNodeInfo;
michael@0 196 nsRefPtr<Attr> newAttr =
michael@0 197 new Attr(this, ni.forget(), EmptyString(), aNsAware);
michael@0 198 mAttributeCache.Put(attr, newAttr);
michael@0 199 node = newAttr;
michael@0 200 }
michael@0 201
michael@0 202 return node;
michael@0 203 }
michael@0 204
michael@0 205 Attr*
michael@0 206 nsDOMAttributeMap::NamedGetter(const nsAString& aAttrName, bool& aFound)
michael@0 207 {
michael@0 208 aFound = false;
michael@0 209 NS_ENSURE_TRUE(mContent, nullptr);
michael@0 210
michael@0 211 nsCOMPtr<nsINodeInfo> ni = mContent->GetExistingAttrNameFromQName(aAttrName);
michael@0 212 if (!ni) {
michael@0 213 return nullptr;
michael@0 214 }
michael@0 215
michael@0 216 aFound = true;
michael@0 217 return GetAttribute(ni, false);
michael@0 218 }
michael@0 219
michael@0 220 bool
michael@0 221 nsDOMAttributeMap::NameIsEnumerable(const nsAString& aName)
michael@0 222 {
michael@0 223 return true;
michael@0 224 }
michael@0 225
michael@0 226 Attr*
michael@0 227 nsDOMAttributeMap::GetNamedItem(const nsAString& aAttrName)
michael@0 228 {
michael@0 229 bool dummy;
michael@0 230 return NamedGetter(aAttrName, dummy);
michael@0 231 }
michael@0 232
michael@0 233 NS_IMETHODIMP
michael@0 234 nsDOMAttributeMap::GetNamedItem(const nsAString& aAttrName,
michael@0 235 nsIDOMAttr** aAttribute)
michael@0 236 {
michael@0 237 NS_ENSURE_ARG_POINTER(aAttribute);
michael@0 238
michael@0 239 NS_IF_ADDREF(*aAttribute = GetNamedItem(aAttrName));
michael@0 240
michael@0 241 return NS_OK;
michael@0 242 }
michael@0 243
michael@0 244 NS_IMETHODIMP
michael@0 245 nsDOMAttributeMap::SetNamedItem(nsIDOMAttr* aAttr, nsIDOMAttr** aReturn)
michael@0 246 {
michael@0 247 Attr* attribute = static_cast<Attr*>(aAttr);
michael@0 248 NS_ENSURE_ARG(attribute);
michael@0 249
michael@0 250 ErrorResult rv;
michael@0 251 *aReturn = SetNamedItem(*attribute, rv).take();
michael@0 252 return rv.ErrorCode();
michael@0 253 }
michael@0 254
michael@0 255 NS_IMETHODIMP
michael@0 256 nsDOMAttributeMap::SetNamedItemNS(nsIDOMAttr* aAttr, nsIDOMAttr** aReturn)
michael@0 257 {
michael@0 258 Attr* attribute = static_cast<Attr*>(aAttr);
michael@0 259 NS_ENSURE_ARG(attribute);
michael@0 260
michael@0 261 ErrorResult rv;
michael@0 262 *aReturn = SetNamedItemNS(*attribute, rv).take();
michael@0 263 return rv.ErrorCode();
michael@0 264 }
michael@0 265
michael@0 266 already_AddRefed<Attr>
michael@0 267 nsDOMAttributeMap::SetNamedItemInternal(Attr& aAttr,
michael@0 268 bool aWithNS,
michael@0 269 ErrorResult& aError)
michael@0 270 {
michael@0 271 NS_ENSURE_TRUE(mContent, nullptr);
michael@0 272
michael@0 273 // XXX should check same-origin between mContent and aAttr however
michael@0 274 // nsContentUtils::CheckSameOrigin can't deal with attributenodes yet
michael@0 275
michael@0 276 // Check that attribute is not owned by somebody else
michael@0 277 nsDOMAttributeMap* owner = aAttr.GetMap();
michael@0 278 if (owner) {
michael@0 279 if (owner != this) {
michael@0 280 aError.Throw(NS_ERROR_DOM_INUSE_ATTRIBUTE_ERR);
michael@0 281 return nullptr;
michael@0 282 }
michael@0 283
michael@0 284 // setting a preexisting attribute is a no-op, just return the same
michael@0 285 // node.
michael@0 286 nsRefPtr<Attr> attribute = &aAttr;
michael@0 287 return attribute.forget();
michael@0 288 }
michael@0 289
michael@0 290 nsresult rv;
michael@0 291 if (mContent->OwnerDoc() != aAttr.OwnerDoc()) {
michael@0 292 nsCOMPtr<nsINode> adoptedNode =
michael@0 293 mContent->OwnerDoc()->AdoptNode(aAttr, aError);
michael@0 294 if (aError.Failed()) {
michael@0 295 return nullptr;
michael@0 296 }
michael@0 297
michael@0 298 NS_ASSERTION(adoptedNode == &aAttr, "Uh, adopt node changed nodes?");
michael@0 299 }
michael@0 300
michael@0 301 // Get nodeinfo and preexisting attribute (if it exists)
michael@0 302 nsAutoString name;
michael@0 303 nsCOMPtr<nsINodeInfo> ni;
michael@0 304
michael@0 305 nsRefPtr<Attr> attr;
michael@0 306 // SetNamedItemNS()
michael@0 307 if (aWithNS) {
michael@0 308 // Return existing attribute, if present
michael@0 309 ni = aAttr.NodeInfo();
michael@0 310
michael@0 311 if (mContent->HasAttr(ni->NamespaceID(), ni->NameAtom())) {
michael@0 312 attr = RemoveAttribute(ni);
michael@0 313 }
michael@0 314 } else { // SetNamedItem()
michael@0 315 aAttr.GetName(name);
michael@0 316
michael@0 317 // get node-info of old attribute
michael@0 318 ni = mContent->GetExistingAttrNameFromQName(name);
michael@0 319 if (ni) {
michael@0 320 attr = RemoveAttribute(ni);
michael@0 321 }
michael@0 322 else {
michael@0 323 if (mContent->IsInHTMLDocument() &&
michael@0 324 mContent->IsHTML()) {
michael@0 325 nsContentUtils::ASCIIToLower(name);
michael@0 326 }
michael@0 327
michael@0 328 rv = mContent->NodeInfo()->NodeInfoManager()->
michael@0 329 GetNodeInfo(name, nullptr, kNameSpaceID_None,
michael@0 330 nsIDOMNode::ATTRIBUTE_NODE, getter_AddRefs(ni));
michael@0 331 if (NS_FAILED(rv)) {
michael@0 332 aError.Throw(rv);
michael@0 333 return nullptr;
michael@0 334 }
michael@0 335 // value is already empty
michael@0 336 }
michael@0 337 }
michael@0 338
michael@0 339 nsAutoString value;
michael@0 340 aAttr.GetValue(value);
michael@0 341
michael@0 342 // Add the new attribute to the attribute map before updating
michael@0 343 // its value in the element. @see bug 364413.
michael@0 344 nsAttrKey attrkey(ni->NamespaceID(), ni->NameAtom());
michael@0 345 mAttributeCache.Put(attrkey, &aAttr);
michael@0 346 aAttr.SetMap(this);
michael@0 347
michael@0 348 rv = mContent->SetAttr(ni->NamespaceID(), ni->NameAtom(),
michael@0 349 ni->GetPrefixAtom(), value, true);
michael@0 350 if (NS_FAILED(rv)) {
michael@0 351 aError.Throw(rv);
michael@0 352 DropAttribute(ni->NamespaceID(), ni->NameAtom());
michael@0 353 }
michael@0 354
michael@0 355 return attr.forget();
michael@0 356 }
michael@0 357
michael@0 358 NS_IMETHODIMP
michael@0 359 nsDOMAttributeMap::RemoveNamedItem(const nsAString& aName,
michael@0 360 nsIDOMAttr** aReturn)
michael@0 361 {
michael@0 362 NS_ENSURE_ARG_POINTER(aReturn);
michael@0 363
michael@0 364 ErrorResult rv;
michael@0 365 *aReturn = RemoveNamedItem(aName, rv).take();
michael@0 366 return rv.ErrorCode();
michael@0 367 }
michael@0 368
michael@0 369 already_AddRefed<Attr>
michael@0 370 nsDOMAttributeMap::RemoveNamedItem(const nsAString& aName, ErrorResult& aError)
michael@0 371 {
michael@0 372 if (!mContent) {
michael@0 373 aError.Throw(NS_ERROR_DOM_NOT_FOUND_ERR);
michael@0 374 return nullptr;
michael@0 375 }
michael@0 376
michael@0 377 nsCOMPtr<nsINodeInfo> ni = mContent->GetExistingAttrNameFromQName(aName);
michael@0 378 if (!ni) {
michael@0 379 aError.Throw(NS_ERROR_DOM_NOT_FOUND_ERR);
michael@0 380 return nullptr;
michael@0 381 }
michael@0 382
michael@0 383 nsRefPtr<Attr> attribute = GetAttribute(ni, true);
michael@0 384
michael@0 385 // This removes the attribute node from the attribute map.
michael@0 386 aError = mContent->UnsetAttr(ni->NamespaceID(), ni->NameAtom(), true);
michael@0 387 return attribute.forget();
michael@0 388 }
michael@0 389
michael@0 390
michael@0 391 Attr*
michael@0 392 nsDOMAttributeMap::IndexedGetter(uint32_t aIndex, bool& aFound)
michael@0 393 {
michael@0 394 aFound = false;
michael@0 395 NS_ENSURE_TRUE(mContent, nullptr);
michael@0 396
michael@0 397 const nsAttrName* name = mContent->GetAttrNameAt(aIndex);
michael@0 398 NS_ENSURE_TRUE(name, nullptr);
michael@0 399
michael@0 400 aFound = true;
michael@0 401 // Don't use the nodeinfo even if one exists since it can have the wrong
michael@0 402 // owner document.
michael@0 403 nsCOMPtr<nsINodeInfo> ni = mContent->NodeInfo()->NodeInfoManager()->
michael@0 404 GetNodeInfo(name->LocalName(), name->GetPrefix(), name->NamespaceID(),
michael@0 405 nsIDOMNode::ATTRIBUTE_NODE);
michael@0 406 return GetAttribute(ni, true);
michael@0 407 }
michael@0 408
michael@0 409 Attr*
michael@0 410 nsDOMAttributeMap::Item(uint32_t aIndex)
michael@0 411 {
michael@0 412 bool dummy;
michael@0 413 return IndexedGetter(aIndex, dummy);
michael@0 414 }
michael@0 415
michael@0 416 NS_IMETHODIMP
michael@0 417 nsDOMAttributeMap::Item(uint32_t aIndex, nsIDOMAttr** aReturn)
michael@0 418 {
michael@0 419 NS_IF_ADDREF(*aReturn = Item(aIndex));
michael@0 420 return NS_OK;
michael@0 421 }
michael@0 422
michael@0 423 uint32_t
michael@0 424 nsDOMAttributeMap::Length() const
michael@0 425 {
michael@0 426 NS_ENSURE_TRUE(mContent, 0);
michael@0 427
michael@0 428 return mContent->GetAttrCount();
michael@0 429 }
michael@0 430
michael@0 431 nsresult
michael@0 432 nsDOMAttributeMap::GetLength(uint32_t *aLength)
michael@0 433 {
michael@0 434 NS_ENSURE_ARG_POINTER(aLength);
michael@0 435 *aLength = Length();
michael@0 436 return NS_OK;
michael@0 437 }
michael@0 438
michael@0 439 NS_IMETHODIMP
michael@0 440 nsDOMAttributeMap::GetNamedItemNS(const nsAString& aNamespaceURI,
michael@0 441 const nsAString& aLocalName,
michael@0 442 nsIDOMAttr** aReturn)
michael@0 443 {
michael@0 444 NS_IF_ADDREF(*aReturn = GetNamedItemNS(aNamespaceURI, aLocalName));
michael@0 445 return NS_OK;
michael@0 446 }
michael@0 447
michael@0 448 Attr*
michael@0 449 nsDOMAttributeMap::GetNamedItemNS(const nsAString& aNamespaceURI,
michael@0 450 const nsAString& aLocalName)
michael@0 451 {
michael@0 452 nsCOMPtr<nsINodeInfo> ni = GetAttrNodeInfo(aNamespaceURI, aLocalName);
michael@0 453 if (!ni) {
michael@0 454 return nullptr;
michael@0 455 }
michael@0 456
michael@0 457 return GetAttribute(ni, true);
michael@0 458 }
michael@0 459
michael@0 460 already_AddRefed<nsINodeInfo>
michael@0 461 nsDOMAttributeMap::GetAttrNodeInfo(const nsAString& aNamespaceURI,
michael@0 462 const nsAString& aLocalName)
michael@0 463 {
michael@0 464 if (!mContent) {
michael@0 465 return nullptr;
michael@0 466 }
michael@0 467
michael@0 468 int32_t nameSpaceID = kNameSpaceID_None;
michael@0 469
michael@0 470 if (!aNamespaceURI.IsEmpty()) {
michael@0 471 nameSpaceID =
michael@0 472 nsContentUtils::NameSpaceManager()->GetNameSpaceID(aNamespaceURI);
michael@0 473
michael@0 474 if (nameSpaceID == kNameSpaceID_Unknown) {
michael@0 475 return nullptr;
michael@0 476 }
michael@0 477 }
michael@0 478
michael@0 479 uint32_t i, count = mContent->GetAttrCount();
michael@0 480 for (i = 0; i < count; ++i) {
michael@0 481 const nsAttrName* name = mContent->GetAttrNameAt(i);
michael@0 482 int32_t attrNS = name->NamespaceID();
michael@0 483 nsIAtom* nameAtom = name->LocalName();
michael@0 484
michael@0 485 if (nameSpaceID == attrNS &&
michael@0 486 nameAtom->Equals(aLocalName)) {
michael@0 487 nsCOMPtr<nsINodeInfo> ni;
michael@0 488 ni = mContent->NodeInfo()->NodeInfoManager()->
michael@0 489 GetNodeInfo(nameAtom, name->GetPrefix(), nameSpaceID,
michael@0 490 nsIDOMNode::ATTRIBUTE_NODE);
michael@0 491
michael@0 492 return ni.forget();
michael@0 493 }
michael@0 494 }
michael@0 495
michael@0 496 return nullptr;
michael@0 497 }
michael@0 498
michael@0 499 NS_IMETHODIMP
michael@0 500 nsDOMAttributeMap::RemoveNamedItemNS(const nsAString& aNamespaceURI,
michael@0 501 const nsAString& aLocalName,
michael@0 502 nsIDOMAttr** aReturn)
michael@0 503 {
michael@0 504 NS_ENSURE_ARG_POINTER(aReturn);
michael@0 505 ErrorResult rv;
michael@0 506 *aReturn = RemoveNamedItemNS(aNamespaceURI, aLocalName, rv).take();
michael@0 507 return rv.ErrorCode();
michael@0 508 }
michael@0 509
michael@0 510 already_AddRefed<Attr>
michael@0 511 nsDOMAttributeMap::RemoveNamedItemNS(const nsAString& aNamespaceURI,
michael@0 512 const nsAString& aLocalName,
michael@0 513 ErrorResult& aError)
michael@0 514 {
michael@0 515 nsCOMPtr<nsINodeInfo> ni = GetAttrNodeInfo(aNamespaceURI, aLocalName);
michael@0 516 if (!ni) {
michael@0 517 aError.Throw(NS_ERROR_DOM_NOT_FOUND_ERR);
michael@0 518 return nullptr;
michael@0 519 }
michael@0 520
michael@0 521 nsRefPtr<Attr> attr = RemoveAttribute(ni);
michael@0 522 nsINodeInfo* attrNi = attr->NodeInfo();
michael@0 523 mContent->UnsetAttr(attrNi->NamespaceID(), attrNi->NameAtom(), true);
michael@0 524
michael@0 525 return attr.forget();
michael@0 526 }
michael@0 527
michael@0 528 uint32_t
michael@0 529 nsDOMAttributeMap::Count() const
michael@0 530 {
michael@0 531 return mAttributeCache.Count();
michael@0 532 }
michael@0 533
michael@0 534 uint32_t
michael@0 535 nsDOMAttributeMap::Enumerate(AttrCache::EnumReadFunction aFunc,
michael@0 536 void *aUserArg) const
michael@0 537 {
michael@0 538 return mAttributeCache.EnumerateRead(aFunc, aUserArg);
michael@0 539 }
michael@0 540
michael@0 541 size_t
michael@0 542 AttrCacheSizeEnumerator(const nsAttrKey& aKey,
michael@0 543 const nsRefPtr<Attr>& aValue,
michael@0 544 MallocSizeOf aMallocSizeOf,
michael@0 545 void* aUserArg)
michael@0 546 {
michael@0 547 return aMallocSizeOf(aValue.get());
michael@0 548 }
michael@0 549
michael@0 550 size_t
michael@0 551 nsDOMAttributeMap::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
michael@0 552 {
michael@0 553 size_t n = aMallocSizeOf(this);
michael@0 554 n += mAttributeCache.SizeOfExcludingThis(AttrCacheSizeEnumerator,
michael@0 555 aMallocSizeOf);
michael@0 556
michael@0 557 // NB: mContent is non-owning and thus not counted.
michael@0 558 return n;
michael@0 559 }
michael@0 560
michael@0 561 /* virtual */ JSObject*
michael@0 562 nsDOMAttributeMap::WrapObject(JSContext* aCx)
michael@0 563 {
michael@0 564 return MozNamedAttrMapBinding::Wrap(aCx, this);
michael@0 565 }

mercurial