1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/content/base/src/nsDOMAttributeMap.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,565 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +/* 1.10 + * Implementation of the |attributes| property of DOM Core's Element object. 1.11 + */ 1.12 + 1.13 +#include "nsDOMAttributeMap.h" 1.14 + 1.15 +#include "mozilla/MemoryReporting.h" 1.16 +#include "mozilla/dom/Attr.h" 1.17 +#include "mozilla/dom/Element.h" 1.18 +#include "mozilla/dom/MozNamedAttrMapBinding.h" 1.19 +#include "nsAttrName.h" 1.20 +#include "nsContentUtils.h" 1.21 +#include "nsError.h" 1.22 +#include "nsIContentInlines.h" 1.23 +#include "nsIDocument.h" 1.24 +#include "nsNameSpaceManager.h" 1.25 +#include "nsNodeInfoManager.h" 1.26 +#include "nsUnicharUtils.h" 1.27 +#include "nsWrapperCacheInlines.h" 1.28 + 1.29 +using namespace mozilla; 1.30 +using namespace mozilla::dom; 1.31 + 1.32 +//---------------------------------------------------------------------- 1.33 + 1.34 +nsDOMAttributeMap::nsDOMAttributeMap(Element* aContent) 1.35 + : mContent(aContent) 1.36 +{ 1.37 + // We don't add a reference to our content. If it goes away, 1.38 + // we'll be told to drop our reference 1.39 + SetIsDOMBinding(); 1.40 +} 1.41 + 1.42 +/** 1.43 + * Clear map pointer for attributes. 1.44 + */ 1.45 +PLDHashOperator 1.46 +RemoveMapRef(nsAttrHashKey::KeyType aKey, nsRefPtr<Attr>& aData, 1.47 + void* aUserArg) 1.48 +{ 1.49 + aData->SetMap(nullptr); 1.50 + 1.51 + return PL_DHASH_REMOVE; 1.52 +} 1.53 + 1.54 +nsDOMAttributeMap::~nsDOMAttributeMap() 1.55 +{ 1.56 + mAttributeCache.Enumerate(RemoveMapRef, nullptr); 1.57 +} 1.58 + 1.59 +void 1.60 +nsDOMAttributeMap::DropReference() 1.61 +{ 1.62 + mAttributeCache.Enumerate(RemoveMapRef, nullptr); 1.63 + mContent = nullptr; 1.64 +} 1.65 + 1.66 +NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMAttributeMap) 1.67 + 1.68 +NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDOMAttributeMap) 1.69 + tmp->DropReference(); 1.70 + NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER 1.71 + NS_IMPL_CYCLE_COLLECTION_UNLINK(mContent) 1.72 +NS_IMPL_CYCLE_COLLECTION_UNLINK_END 1.73 + 1.74 + 1.75 +PLDHashOperator 1.76 +TraverseMapEntry(nsAttrHashKey::KeyType aKey, nsRefPtr<Attr>& aData, 1.77 + void* aUserArg) 1.78 +{ 1.79 + nsCycleCollectionTraversalCallback *cb = 1.80 + static_cast<nsCycleCollectionTraversalCallback*>(aUserArg); 1.81 + 1.82 + cb->NoteXPCOMChild(static_cast<nsINode*>(aData.get())); 1.83 + 1.84 + return PL_DHASH_NEXT; 1.85 +} 1.86 + 1.87 +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsDOMAttributeMap) 1.88 + tmp->mAttributeCache.Enumerate(TraverseMapEntry, &cb); 1.89 + NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS 1.90 + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mContent) 1.91 +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END 1.92 + 1.93 +NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(nsDOMAttributeMap) 1.94 + 1.95 +NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(nsDOMAttributeMap) 1.96 + if (tmp->IsBlack()) { 1.97 + if (tmp->mContent) { 1.98 + // The map owns the element so we can mark it when the 1.99 + // map itself is certainly alive. 1.100 + mozilla::dom::FragmentOrElement::MarkNodeChildren(tmp->mContent); 1.101 + } 1.102 + return true; 1.103 + } 1.104 + if (tmp->mContent && 1.105 + mozilla::dom::FragmentOrElement::CanSkip(tmp->mContent, true)) { 1.106 + return true; 1.107 + } 1.108 +NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_END 1.109 + 1.110 +NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_BEGIN(nsDOMAttributeMap) 1.111 + return tmp->IsBlackAndDoesNotNeedTracing(tmp); 1.112 +NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_END 1.113 + 1.114 +NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_BEGIN(nsDOMAttributeMap) 1.115 + return tmp->IsBlack(); 1.116 +NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_END 1.117 + 1.118 +// QueryInterface implementation for nsDOMAttributeMap 1.119 +NS_INTERFACE_TABLE_HEAD(nsDOMAttributeMap) 1.120 + NS_INTERFACE_TABLE(nsDOMAttributeMap, nsIDOMMozNamedAttrMap) 1.121 + NS_INTERFACE_TABLE_TO_MAP_SEGUE 1.122 + NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY 1.123 + NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(nsDOMAttributeMap) 1.124 +NS_INTERFACE_MAP_END 1.125 + 1.126 +NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDOMAttributeMap) 1.127 +NS_IMPL_CYCLE_COLLECTING_RELEASE(nsDOMAttributeMap) 1.128 + 1.129 +PLDHashOperator 1.130 +SetOwnerDocumentFunc(nsAttrHashKey::KeyType aKey, 1.131 + nsRefPtr<Attr>& aData, 1.132 + void* aUserArg) 1.133 +{ 1.134 + nsresult rv = aData->SetOwnerDocument(static_cast<nsIDocument*>(aUserArg)); 1.135 + 1.136 + return NS_FAILED(rv) ? PL_DHASH_STOP : PL_DHASH_NEXT; 1.137 +} 1.138 + 1.139 +nsresult 1.140 +nsDOMAttributeMap::SetOwnerDocument(nsIDocument* aDocument) 1.141 +{ 1.142 + uint32_t n = mAttributeCache.Enumerate(SetOwnerDocumentFunc, aDocument); 1.143 + NS_ENSURE_TRUE(n == mAttributeCache.Count(), NS_ERROR_FAILURE); 1.144 + 1.145 + return NS_OK; 1.146 +} 1.147 + 1.148 +void 1.149 +nsDOMAttributeMap::DropAttribute(int32_t aNamespaceID, nsIAtom* aLocalName) 1.150 +{ 1.151 + nsAttrKey attr(aNamespaceID, aLocalName); 1.152 + Attr *node = mAttributeCache.GetWeak(attr); 1.153 + if (node) { 1.154 + // Break link to map 1.155 + node->SetMap(nullptr); 1.156 + 1.157 + // Remove from cache 1.158 + mAttributeCache.Remove(attr); 1.159 + } 1.160 +} 1.161 + 1.162 +already_AddRefed<Attr> 1.163 +nsDOMAttributeMap::RemoveAttribute(nsINodeInfo* aNodeInfo) 1.164 +{ 1.165 + NS_ASSERTION(aNodeInfo, "RemoveAttribute() called with aNodeInfo == nullptr!"); 1.166 + 1.167 + nsAttrKey attr(aNodeInfo->NamespaceID(), aNodeInfo->NameAtom()); 1.168 + 1.169 + nsRefPtr<Attr> node; 1.170 + if (!mAttributeCache.Get(attr, getter_AddRefs(node))) { 1.171 + nsAutoString value; 1.172 + // As we are removing the attribute we need to set the current value in 1.173 + // the attribute node. 1.174 + mContent->GetAttr(aNodeInfo->NamespaceID(), aNodeInfo->NameAtom(), value); 1.175 + nsCOMPtr<nsINodeInfo> ni = aNodeInfo; 1.176 + node = new Attr(nullptr, ni.forget(), value, true); 1.177 + } 1.178 + else { 1.179 + // Break link to map 1.180 + node->SetMap(nullptr); 1.181 + 1.182 + // Remove from cache 1.183 + mAttributeCache.Remove(attr); 1.184 + } 1.185 + 1.186 + return node.forget(); 1.187 +} 1.188 + 1.189 +Attr* 1.190 +nsDOMAttributeMap::GetAttribute(nsINodeInfo* aNodeInfo, bool aNsAware) 1.191 +{ 1.192 + NS_ASSERTION(aNodeInfo, "GetAttribute() called with aNodeInfo == nullptr!"); 1.193 + 1.194 + nsAttrKey attr(aNodeInfo->NamespaceID(), aNodeInfo->NameAtom()); 1.195 + 1.196 + Attr* node = mAttributeCache.GetWeak(attr); 1.197 + if (!node) { 1.198 + nsCOMPtr<nsINodeInfo> ni = aNodeInfo; 1.199 + nsRefPtr<Attr> newAttr = 1.200 + new Attr(this, ni.forget(), EmptyString(), aNsAware); 1.201 + mAttributeCache.Put(attr, newAttr); 1.202 + node = newAttr; 1.203 + } 1.204 + 1.205 + return node; 1.206 +} 1.207 + 1.208 +Attr* 1.209 +nsDOMAttributeMap::NamedGetter(const nsAString& aAttrName, bool& aFound) 1.210 +{ 1.211 + aFound = false; 1.212 + NS_ENSURE_TRUE(mContent, nullptr); 1.213 + 1.214 + nsCOMPtr<nsINodeInfo> ni = mContent->GetExistingAttrNameFromQName(aAttrName); 1.215 + if (!ni) { 1.216 + return nullptr; 1.217 + } 1.218 + 1.219 + aFound = true; 1.220 + return GetAttribute(ni, false); 1.221 +} 1.222 + 1.223 +bool 1.224 +nsDOMAttributeMap::NameIsEnumerable(const nsAString& aName) 1.225 +{ 1.226 + return true; 1.227 +} 1.228 + 1.229 +Attr* 1.230 +nsDOMAttributeMap::GetNamedItem(const nsAString& aAttrName) 1.231 +{ 1.232 + bool dummy; 1.233 + return NamedGetter(aAttrName, dummy); 1.234 +} 1.235 + 1.236 +NS_IMETHODIMP 1.237 +nsDOMAttributeMap::GetNamedItem(const nsAString& aAttrName, 1.238 + nsIDOMAttr** aAttribute) 1.239 +{ 1.240 + NS_ENSURE_ARG_POINTER(aAttribute); 1.241 + 1.242 + NS_IF_ADDREF(*aAttribute = GetNamedItem(aAttrName)); 1.243 + 1.244 + return NS_OK; 1.245 +} 1.246 + 1.247 +NS_IMETHODIMP 1.248 +nsDOMAttributeMap::SetNamedItem(nsIDOMAttr* aAttr, nsIDOMAttr** aReturn) 1.249 +{ 1.250 + Attr* attribute = static_cast<Attr*>(aAttr); 1.251 + NS_ENSURE_ARG(attribute); 1.252 + 1.253 + ErrorResult rv; 1.254 + *aReturn = SetNamedItem(*attribute, rv).take(); 1.255 + return rv.ErrorCode(); 1.256 +} 1.257 + 1.258 +NS_IMETHODIMP 1.259 +nsDOMAttributeMap::SetNamedItemNS(nsIDOMAttr* aAttr, nsIDOMAttr** aReturn) 1.260 +{ 1.261 + Attr* attribute = static_cast<Attr*>(aAttr); 1.262 + NS_ENSURE_ARG(attribute); 1.263 + 1.264 + ErrorResult rv; 1.265 + *aReturn = SetNamedItemNS(*attribute, rv).take(); 1.266 + return rv.ErrorCode(); 1.267 +} 1.268 + 1.269 +already_AddRefed<Attr> 1.270 +nsDOMAttributeMap::SetNamedItemInternal(Attr& aAttr, 1.271 + bool aWithNS, 1.272 + ErrorResult& aError) 1.273 +{ 1.274 + NS_ENSURE_TRUE(mContent, nullptr); 1.275 + 1.276 + // XXX should check same-origin between mContent and aAttr however 1.277 + // nsContentUtils::CheckSameOrigin can't deal with attributenodes yet 1.278 + 1.279 + // Check that attribute is not owned by somebody else 1.280 + nsDOMAttributeMap* owner = aAttr.GetMap(); 1.281 + if (owner) { 1.282 + if (owner != this) { 1.283 + aError.Throw(NS_ERROR_DOM_INUSE_ATTRIBUTE_ERR); 1.284 + return nullptr; 1.285 + } 1.286 + 1.287 + // setting a preexisting attribute is a no-op, just return the same 1.288 + // node. 1.289 + nsRefPtr<Attr> attribute = &aAttr; 1.290 + return attribute.forget(); 1.291 + } 1.292 + 1.293 + nsresult rv; 1.294 + if (mContent->OwnerDoc() != aAttr.OwnerDoc()) { 1.295 + nsCOMPtr<nsINode> adoptedNode = 1.296 + mContent->OwnerDoc()->AdoptNode(aAttr, aError); 1.297 + if (aError.Failed()) { 1.298 + return nullptr; 1.299 + } 1.300 + 1.301 + NS_ASSERTION(adoptedNode == &aAttr, "Uh, adopt node changed nodes?"); 1.302 + } 1.303 + 1.304 + // Get nodeinfo and preexisting attribute (if it exists) 1.305 + nsAutoString name; 1.306 + nsCOMPtr<nsINodeInfo> ni; 1.307 + 1.308 + nsRefPtr<Attr> attr; 1.309 + // SetNamedItemNS() 1.310 + if (aWithNS) { 1.311 + // Return existing attribute, if present 1.312 + ni = aAttr.NodeInfo(); 1.313 + 1.314 + if (mContent->HasAttr(ni->NamespaceID(), ni->NameAtom())) { 1.315 + attr = RemoveAttribute(ni); 1.316 + } 1.317 + } else { // SetNamedItem() 1.318 + aAttr.GetName(name); 1.319 + 1.320 + // get node-info of old attribute 1.321 + ni = mContent->GetExistingAttrNameFromQName(name); 1.322 + if (ni) { 1.323 + attr = RemoveAttribute(ni); 1.324 + } 1.325 + else { 1.326 + if (mContent->IsInHTMLDocument() && 1.327 + mContent->IsHTML()) { 1.328 + nsContentUtils::ASCIIToLower(name); 1.329 + } 1.330 + 1.331 + rv = mContent->NodeInfo()->NodeInfoManager()-> 1.332 + GetNodeInfo(name, nullptr, kNameSpaceID_None, 1.333 + nsIDOMNode::ATTRIBUTE_NODE, getter_AddRefs(ni)); 1.334 + if (NS_FAILED(rv)) { 1.335 + aError.Throw(rv); 1.336 + return nullptr; 1.337 + } 1.338 + // value is already empty 1.339 + } 1.340 + } 1.341 + 1.342 + nsAutoString value; 1.343 + aAttr.GetValue(value); 1.344 + 1.345 + // Add the new attribute to the attribute map before updating 1.346 + // its value in the element. @see bug 364413. 1.347 + nsAttrKey attrkey(ni->NamespaceID(), ni->NameAtom()); 1.348 + mAttributeCache.Put(attrkey, &aAttr); 1.349 + aAttr.SetMap(this); 1.350 + 1.351 + rv = mContent->SetAttr(ni->NamespaceID(), ni->NameAtom(), 1.352 + ni->GetPrefixAtom(), value, true); 1.353 + if (NS_FAILED(rv)) { 1.354 + aError.Throw(rv); 1.355 + DropAttribute(ni->NamespaceID(), ni->NameAtom()); 1.356 + } 1.357 + 1.358 + return attr.forget(); 1.359 +} 1.360 + 1.361 +NS_IMETHODIMP 1.362 +nsDOMAttributeMap::RemoveNamedItem(const nsAString& aName, 1.363 + nsIDOMAttr** aReturn) 1.364 +{ 1.365 + NS_ENSURE_ARG_POINTER(aReturn); 1.366 + 1.367 + ErrorResult rv; 1.368 + *aReturn = RemoveNamedItem(aName, rv).take(); 1.369 + return rv.ErrorCode(); 1.370 +} 1.371 + 1.372 +already_AddRefed<Attr> 1.373 +nsDOMAttributeMap::RemoveNamedItem(const nsAString& aName, ErrorResult& aError) 1.374 +{ 1.375 + if (!mContent) { 1.376 + aError.Throw(NS_ERROR_DOM_NOT_FOUND_ERR); 1.377 + return nullptr; 1.378 + } 1.379 + 1.380 + nsCOMPtr<nsINodeInfo> ni = mContent->GetExistingAttrNameFromQName(aName); 1.381 + if (!ni) { 1.382 + aError.Throw(NS_ERROR_DOM_NOT_FOUND_ERR); 1.383 + return nullptr; 1.384 + } 1.385 + 1.386 + nsRefPtr<Attr> attribute = GetAttribute(ni, true); 1.387 + 1.388 + // This removes the attribute node from the attribute map. 1.389 + aError = mContent->UnsetAttr(ni->NamespaceID(), ni->NameAtom(), true); 1.390 + return attribute.forget(); 1.391 +} 1.392 + 1.393 + 1.394 +Attr* 1.395 +nsDOMAttributeMap::IndexedGetter(uint32_t aIndex, bool& aFound) 1.396 +{ 1.397 + aFound = false; 1.398 + NS_ENSURE_TRUE(mContent, nullptr); 1.399 + 1.400 + const nsAttrName* name = mContent->GetAttrNameAt(aIndex); 1.401 + NS_ENSURE_TRUE(name, nullptr); 1.402 + 1.403 + aFound = true; 1.404 + // Don't use the nodeinfo even if one exists since it can have the wrong 1.405 + // owner document. 1.406 + nsCOMPtr<nsINodeInfo> ni = mContent->NodeInfo()->NodeInfoManager()-> 1.407 + GetNodeInfo(name->LocalName(), name->GetPrefix(), name->NamespaceID(), 1.408 + nsIDOMNode::ATTRIBUTE_NODE); 1.409 + return GetAttribute(ni, true); 1.410 +} 1.411 + 1.412 +Attr* 1.413 +nsDOMAttributeMap::Item(uint32_t aIndex) 1.414 +{ 1.415 + bool dummy; 1.416 + return IndexedGetter(aIndex, dummy); 1.417 +} 1.418 + 1.419 +NS_IMETHODIMP 1.420 +nsDOMAttributeMap::Item(uint32_t aIndex, nsIDOMAttr** aReturn) 1.421 +{ 1.422 + NS_IF_ADDREF(*aReturn = Item(aIndex)); 1.423 + return NS_OK; 1.424 +} 1.425 + 1.426 +uint32_t 1.427 +nsDOMAttributeMap::Length() const 1.428 +{ 1.429 + NS_ENSURE_TRUE(mContent, 0); 1.430 + 1.431 + return mContent->GetAttrCount(); 1.432 +} 1.433 + 1.434 +nsresult 1.435 +nsDOMAttributeMap::GetLength(uint32_t *aLength) 1.436 +{ 1.437 + NS_ENSURE_ARG_POINTER(aLength); 1.438 + *aLength = Length(); 1.439 + return NS_OK; 1.440 +} 1.441 + 1.442 +NS_IMETHODIMP 1.443 +nsDOMAttributeMap::GetNamedItemNS(const nsAString& aNamespaceURI, 1.444 + const nsAString& aLocalName, 1.445 + nsIDOMAttr** aReturn) 1.446 +{ 1.447 + NS_IF_ADDREF(*aReturn = GetNamedItemNS(aNamespaceURI, aLocalName)); 1.448 + return NS_OK; 1.449 +} 1.450 + 1.451 +Attr* 1.452 +nsDOMAttributeMap::GetNamedItemNS(const nsAString& aNamespaceURI, 1.453 + const nsAString& aLocalName) 1.454 +{ 1.455 + nsCOMPtr<nsINodeInfo> ni = GetAttrNodeInfo(aNamespaceURI, aLocalName); 1.456 + if (!ni) { 1.457 + return nullptr; 1.458 + } 1.459 + 1.460 + return GetAttribute(ni, true); 1.461 +} 1.462 + 1.463 +already_AddRefed<nsINodeInfo> 1.464 +nsDOMAttributeMap::GetAttrNodeInfo(const nsAString& aNamespaceURI, 1.465 + const nsAString& aLocalName) 1.466 +{ 1.467 + if (!mContent) { 1.468 + return nullptr; 1.469 + } 1.470 + 1.471 + int32_t nameSpaceID = kNameSpaceID_None; 1.472 + 1.473 + if (!aNamespaceURI.IsEmpty()) { 1.474 + nameSpaceID = 1.475 + nsContentUtils::NameSpaceManager()->GetNameSpaceID(aNamespaceURI); 1.476 + 1.477 + if (nameSpaceID == kNameSpaceID_Unknown) { 1.478 + return nullptr; 1.479 + } 1.480 + } 1.481 + 1.482 + uint32_t i, count = mContent->GetAttrCount(); 1.483 + for (i = 0; i < count; ++i) { 1.484 + const nsAttrName* name = mContent->GetAttrNameAt(i); 1.485 + int32_t attrNS = name->NamespaceID(); 1.486 + nsIAtom* nameAtom = name->LocalName(); 1.487 + 1.488 + if (nameSpaceID == attrNS && 1.489 + nameAtom->Equals(aLocalName)) { 1.490 + nsCOMPtr<nsINodeInfo> ni; 1.491 + ni = mContent->NodeInfo()->NodeInfoManager()-> 1.492 + GetNodeInfo(nameAtom, name->GetPrefix(), nameSpaceID, 1.493 + nsIDOMNode::ATTRIBUTE_NODE); 1.494 + 1.495 + return ni.forget(); 1.496 + } 1.497 + } 1.498 + 1.499 + return nullptr; 1.500 +} 1.501 + 1.502 +NS_IMETHODIMP 1.503 +nsDOMAttributeMap::RemoveNamedItemNS(const nsAString& aNamespaceURI, 1.504 + const nsAString& aLocalName, 1.505 + nsIDOMAttr** aReturn) 1.506 +{ 1.507 + NS_ENSURE_ARG_POINTER(aReturn); 1.508 + ErrorResult rv; 1.509 + *aReturn = RemoveNamedItemNS(aNamespaceURI, aLocalName, rv).take(); 1.510 + return rv.ErrorCode(); 1.511 +} 1.512 + 1.513 +already_AddRefed<Attr> 1.514 +nsDOMAttributeMap::RemoveNamedItemNS(const nsAString& aNamespaceURI, 1.515 + const nsAString& aLocalName, 1.516 + ErrorResult& aError) 1.517 +{ 1.518 + nsCOMPtr<nsINodeInfo> ni = GetAttrNodeInfo(aNamespaceURI, aLocalName); 1.519 + if (!ni) { 1.520 + aError.Throw(NS_ERROR_DOM_NOT_FOUND_ERR); 1.521 + return nullptr; 1.522 + } 1.523 + 1.524 + nsRefPtr<Attr> attr = RemoveAttribute(ni); 1.525 + nsINodeInfo* attrNi = attr->NodeInfo(); 1.526 + mContent->UnsetAttr(attrNi->NamespaceID(), attrNi->NameAtom(), true); 1.527 + 1.528 + return attr.forget(); 1.529 +} 1.530 + 1.531 +uint32_t 1.532 +nsDOMAttributeMap::Count() const 1.533 +{ 1.534 + return mAttributeCache.Count(); 1.535 +} 1.536 + 1.537 +uint32_t 1.538 +nsDOMAttributeMap::Enumerate(AttrCache::EnumReadFunction aFunc, 1.539 + void *aUserArg) const 1.540 +{ 1.541 + return mAttributeCache.EnumerateRead(aFunc, aUserArg); 1.542 +} 1.543 + 1.544 +size_t 1.545 +AttrCacheSizeEnumerator(const nsAttrKey& aKey, 1.546 + const nsRefPtr<Attr>& aValue, 1.547 + MallocSizeOf aMallocSizeOf, 1.548 + void* aUserArg) 1.549 +{ 1.550 + return aMallocSizeOf(aValue.get()); 1.551 +} 1.552 + 1.553 +size_t 1.554 +nsDOMAttributeMap::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const 1.555 +{ 1.556 + size_t n = aMallocSizeOf(this); 1.557 + n += mAttributeCache.SizeOfExcludingThis(AttrCacheSizeEnumerator, 1.558 + aMallocSizeOf); 1.559 + 1.560 + // NB: mContent is non-owning and thus not counted. 1.561 + return n; 1.562 +} 1.563 + 1.564 +/* virtual */ JSObject* 1.565 +nsDOMAttributeMap::WrapObject(JSContext* aCx) 1.566 +{ 1.567 + return MozNamedAttrMapBinding::Wrap(aCx, this); 1.568 +}