1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/content/base/src/Attr.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,409 @@ 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 DOM Core's nsIDOMAttr node. 1.11 + */ 1.12 + 1.13 +#include "mozilla/dom/Attr.h" 1.14 +#include "mozilla/dom/AttrBinding.h" 1.15 +#include "mozilla/dom/Element.h" 1.16 +#include "mozilla/EventDispatcher.h" 1.17 +#include "mozilla/InternalMutationEvent.h" 1.18 +#include "nsContentCreatorFunctions.h" 1.19 +#include "nsError.h" 1.20 +#include "nsUnicharUtils.h" 1.21 +#include "nsDOMString.h" 1.22 +#include "nsIContentInlines.h" 1.23 +#include "nsIDocument.h" 1.24 +#include "nsIDOMUserDataHandler.h" 1.25 +#include "nsGkAtoms.h" 1.26 +#include "nsCOMArray.h" 1.27 +#include "nsNameSpaceManager.h" 1.28 +#include "nsNodeUtils.h" 1.29 +#include "nsTextNode.h" 1.30 +#include "mozAutoDocUpdate.h" 1.31 +#include "nsWrapperCacheInlines.h" 1.32 + 1.33 +nsIAttribute::nsIAttribute(nsDOMAttributeMap* aAttrMap, 1.34 + already_AddRefed<nsINodeInfo>& aNodeInfo, 1.35 + bool aNsAware) 1.36 +: nsINode(aNodeInfo), mAttrMap(aAttrMap), mNsAware(aNsAware) 1.37 +{ 1.38 +} 1.39 + 1.40 +nsIAttribute::~nsIAttribute() 1.41 +{ 1.42 +} 1.43 + 1.44 +namespace mozilla { 1.45 +namespace dom { 1.46 + 1.47 +//---------------------------------------------------------------------- 1.48 +bool Attr::sInitialized; 1.49 + 1.50 +Attr::Attr(nsDOMAttributeMap *aAttrMap, 1.51 + already_AddRefed<nsINodeInfo>&& aNodeInfo, 1.52 + const nsAString &aValue, bool aNsAware) 1.53 + : nsIAttribute(aAttrMap, aNodeInfo, aNsAware), mValue(aValue) 1.54 +{ 1.55 + NS_ABORT_IF_FALSE(mNodeInfo, "We must get a nodeinfo here!"); 1.56 + NS_ABORT_IF_FALSE(mNodeInfo->NodeType() == nsIDOMNode::ATTRIBUTE_NODE, 1.57 + "Wrong nodeType"); 1.58 + 1.59 + // We don't add a reference to our content. It will tell us 1.60 + // to drop our reference when it goes away. 1.61 + 1.62 + SetIsDOMBinding(); 1.63 +} 1.64 + 1.65 +NS_IMPL_CYCLE_COLLECTION_CLASS(Attr) 1.66 + 1.67 +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Attr) 1.68 + NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS 1.69 + 1.70 + if (!nsINode::Traverse(tmp, cb)) { 1.71 + return NS_SUCCESS_INTERRUPTED_TRAVERSE; 1.72 + } 1.73 + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAttrMap) 1.74 +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END 1.75 + 1.76 +NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(Attr) 1.77 + 1.78 +NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Attr) 1.79 + nsINode::Unlink(tmp); 1.80 + NS_IMPL_CYCLE_COLLECTION_UNLINK(mAttrMap) 1.81 +NS_IMPL_CYCLE_COLLECTION_UNLINK_END 1.82 + 1.83 +NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(Attr) 1.84 + Element* ownerElement = tmp->GetElement(); 1.85 + if (tmp->IsBlack()) { 1.86 + if (ownerElement) { 1.87 + // The attribute owns the element via attribute map so we can 1.88 + // mark it when the attribute is certainly alive. 1.89 + mozilla::dom::FragmentOrElement::MarkNodeChildren(ownerElement); 1.90 + } 1.91 + return true; 1.92 + } 1.93 + if (ownerElement && 1.94 + mozilla::dom::FragmentOrElement::CanSkip(ownerElement, true)) { 1.95 + return true; 1.96 + } 1.97 +NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_END 1.98 + 1.99 +NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_BEGIN(Attr) 1.100 + return tmp->IsBlackAndDoesNotNeedTracing(static_cast<nsIAttribute*>(tmp)); 1.101 +NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_END 1.102 + 1.103 +NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_BEGIN(Attr) 1.104 + return tmp->IsBlack(); 1.105 +NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_END 1.106 + 1.107 +// QueryInterface implementation for Attr 1.108 +NS_INTERFACE_TABLE_HEAD(Attr) 1.109 + NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY 1.110 + NS_INTERFACE_TABLE(Attr, nsINode, nsIDOMAttr, nsIAttribute, nsIDOMNode, 1.111 + nsIDOMEventTarget, EventTarget) 1.112 + NS_INTERFACE_TABLE_TO_MAP_SEGUE_CYCLE_COLLECTION(Attr) 1.113 + NS_INTERFACE_MAP_ENTRY_TEAROFF(nsISupportsWeakReference, 1.114 + new nsNodeSupportsWeakRefTearoff(this)) 1.115 + NS_INTERFACE_MAP_ENTRY_TEAROFF(nsIDOMXPathNSResolver, 1.116 + new nsNode3Tearoff(this)) 1.117 +NS_INTERFACE_MAP_END 1.118 + 1.119 +NS_IMPL_CYCLE_COLLECTING_ADDREF(Attr) 1.120 +NS_IMPL_CYCLE_COLLECTING_RELEASE_WITH_LAST_RELEASE(Attr, 1.121 + nsNodeUtils::LastRelease(this)) 1.122 + 1.123 +void 1.124 +Attr::SetMap(nsDOMAttributeMap *aMap) 1.125 +{ 1.126 + if (mAttrMap && !aMap && sInitialized) { 1.127 + // We're breaking a relationship with content and not getting a new one, 1.128 + // need to locally cache value. GetValue() does that. 1.129 + GetValue(mValue); 1.130 + } 1.131 + 1.132 + mAttrMap = aMap; 1.133 +} 1.134 + 1.135 +Element* 1.136 +Attr::GetElement() const 1.137 +{ 1.138 + if (!mAttrMap) { 1.139 + return nullptr; 1.140 + } 1.141 + nsIContent* content = mAttrMap->GetContent(); 1.142 + return content ? content->AsElement() : nullptr; 1.143 +} 1.144 + 1.145 +nsresult 1.146 +Attr::SetOwnerDocument(nsIDocument* aDocument) 1.147 +{ 1.148 + NS_ASSERTION(aDocument, "Missing document"); 1.149 + 1.150 + nsIDocument *doc = OwnerDoc(); 1.151 + NS_ASSERTION(doc != aDocument, "bad call to Attr::SetOwnerDocument"); 1.152 + doc->DeleteAllPropertiesFor(this); 1.153 + 1.154 + nsCOMPtr<nsINodeInfo> newNodeInfo; 1.155 + newNodeInfo = aDocument->NodeInfoManager()-> 1.156 + GetNodeInfo(mNodeInfo->NameAtom(), mNodeInfo->GetPrefixAtom(), 1.157 + mNodeInfo->NamespaceID(), 1.158 + nsIDOMNode::ATTRIBUTE_NODE); 1.159 + NS_ASSERTION(newNodeInfo, "GetNodeInfo lies"); 1.160 + mNodeInfo.swap(newNodeInfo); 1.161 + 1.162 + return NS_OK; 1.163 +} 1.164 + 1.165 +NS_IMETHODIMP 1.166 +Attr::GetName(nsAString& aName) 1.167 +{ 1.168 + aName = NodeName(); 1.169 + return NS_OK; 1.170 +} 1.171 + 1.172 +already_AddRefed<nsIAtom> 1.173 +Attr::GetNameAtom(nsIContent* aContent) 1.174 +{ 1.175 + if (!mNsAware && 1.176 + mNodeInfo->NamespaceID() == kNameSpaceID_None && 1.177 + aContent->IsInHTMLDocument() && 1.178 + aContent->IsHTML()) { 1.179 + nsString name; 1.180 + mNodeInfo->GetName(name); 1.181 + nsAutoString lowercaseName; 1.182 + nsContentUtils::ASCIIToLower(name, lowercaseName); 1.183 + return do_GetAtom(lowercaseName); 1.184 + } 1.185 + nsCOMPtr<nsIAtom> nameAtom = mNodeInfo->NameAtom(); 1.186 + return nameAtom.forget(); 1.187 +} 1.188 + 1.189 +NS_IMETHODIMP 1.190 +Attr::GetValue(nsAString& aValue) 1.191 +{ 1.192 + Element* element = GetElement(); 1.193 + if (element) { 1.194 + nsCOMPtr<nsIAtom> nameAtom = GetNameAtom(element); 1.195 + element->GetAttr(mNodeInfo->NamespaceID(), nameAtom, aValue); 1.196 + } 1.197 + else { 1.198 + aValue = mValue; 1.199 + } 1.200 + 1.201 + return NS_OK; 1.202 +} 1.203 + 1.204 +void 1.205 +Attr::SetValue(const nsAString& aValue, ErrorResult& aRv) 1.206 +{ 1.207 + Element* element = GetElement(); 1.208 + if (!element) { 1.209 + mValue = aValue; 1.210 + return; 1.211 + } 1.212 + 1.213 + nsCOMPtr<nsIAtom> nameAtom = GetNameAtom(element); 1.214 + aRv = element->SetAttr(mNodeInfo->NamespaceID(), 1.215 + nameAtom, 1.216 + mNodeInfo->GetPrefixAtom(), 1.217 + aValue, 1.218 + true); 1.219 +} 1.220 + 1.221 +NS_IMETHODIMP 1.222 +Attr::SetValue(const nsAString& aValue) 1.223 +{ 1.224 + ErrorResult rv; 1.225 + SetValue(aValue, rv); 1.226 + return rv.ErrorCode(); 1.227 +} 1.228 + 1.229 +bool 1.230 +Attr::Specified() const 1.231 +{ 1.232 + return true; 1.233 +} 1.234 + 1.235 +NS_IMETHODIMP 1.236 +Attr::GetSpecified(bool* aSpecified) 1.237 +{ 1.238 + NS_ENSURE_ARG_POINTER(aSpecified); 1.239 + *aSpecified = Specified(); 1.240 + return NS_OK; 1.241 +} 1.242 + 1.243 +Element* 1.244 +Attr::GetOwnerElement(ErrorResult& aRv) 1.245 +{ 1.246 + OwnerDoc()->WarnOnceAbout(nsIDocument::eOwnerElement); 1.247 + return GetElement(); 1.248 +} 1.249 + 1.250 +NS_IMETHODIMP 1.251 +Attr::GetOwnerElement(nsIDOMElement** aOwnerElement) 1.252 +{ 1.253 + NS_ENSURE_ARG_POINTER(aOwnerElement); 1.254 + OwnerDoc()->WarnOnceAbout(nsIDocument::eOwnerElement); 1.255 + 1.256 + Element* element = GetElement(); 1.257 + if (element) { 1.258 + return CallQueryInterface(element, aOwnerElement); 1.259 + } 1.260 + 1.261 + *aOwnerElement = nullptr; 1.262 + 1.263 + return NS_OK; 1.264 +} 1.265 + 1.266 +void 1.267 +Attr::GetNodeValueInternal(nsAString& aNodeValue) 1.268 +{ 1.269 + OwnerDoc()->WarnOnceAbout(nsIDocument::eNodeValue); 1.270 + 1.271 + GetValue(aNodeValue); 1.272 +} 1.273 + 1.274 +void 1.275 +Attr::SetNodeValueInternal(const nsAString& aNodeValue, ErrorResult& aError) 1.276 +{ 1.277 + OwnerDoc()->WarnOnceAbout(nsIDocument::eNodeValue); 1.278 + 1.279 + aError = SetValue(aNodeValue); 1.280 +} 1.281 + 1.282 +nsresult 1.283 +Attr::Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const 1.284 +{ 1.285 + nsAutoString value; 1.286 + const_cast<Attr*>(this)->GetValue(value); 1.287 + 1.288 + nsCOMPtr<nsINodeInfo> ni = aNodeInfo; 1.289 + *aResult = new Attr(nullptr, ni.forget(), value, mNsAware); 1.290 + if (!*aResult) { 1.291 + return NS_ERROR_OUT_OF_MEMORY; 1.292 + } 1.293 + 1.294 + NS_ADDREF(*aResult); 1.295 + 1.296 + return NS_OK; 1.297 +} 1.298 + 1.299 +already_AddRefed<nsIURI> 1.300 +Attr::GetBaseURI(bool aTryUseXHRDocBaseURI) const 1.301 +{ 1.302 + Element* parent = GetElement(); 1.303 + 1.304 + return parent ? parent->GetBaseURI(aTryUseXHRDocBaseURI) : nullptr; 1.305 +} 1.306 + 1.307 +void 1.308 +Attr::GetTextContentInternal(nsAString& aTextContent) 1.309 +{ 1.310 + OwnerDoc()->WarnOnceAbout(nsIDocument::eTextContent); 1.311 + 1.312 + GetValue(aTextContent); 1.313 +} 1.314 + 1.315 +void 1.316 +Attr::SetTextContentInternal(const nsAString& aTextContent, 1.317 + ErrorResult& aError) 1.318 +{ 1.319 + OwnerDoc()->WarnOnceAbout(nsIDocument::eTextContent); 1.320 + 1.321 + SetNodeValueInternal(aTextContent, aError); 1.322 +} 1.323 + 1.324 +NS_IMETHODIMP 1.325 +Attr::GetIsId(bool* aReturn) 1.326 +{ 1.327 + Element* element = GetElement(); 1.328 + if (!element) { 1.329 + *aReturn = false; 1.330 + return NS_OK; 1.331 + } 1.332 + 1.333 + nsIAtom* idAtom = element->GetIDAttributeName(); 1.334 + if (!idAtom) { 1.335 + *aReturn = false; 1.336 + return NS_OK; 1.337 + } 1.338 + 1.339 + *aReturn = mNodeInfo->Equals(idAtom, kNameSpaceID_None); 1.340 + return NS_OK; 1.341 +} 1.342 + 1.343 +bool 1.344 +Attr::IsNodeOfType(uint32_t aFlags) const 1.345 +{ 1.346 + return !(aFlags & ~eATTRIBUTE); 1.347 +} 1.348 + 1.349 +uint32_t 1.350 +Attr::GetChildCount() const 1.351 +{ 1.352 + return 0; 1.353 +} 1.354 + 1.355 +nsIContent * 1.356 +Attr::GetChildAt(uint32_t aIndex) const 1.357 +{ 1.358 + return nullptr; 1.359 +} 1.360 + 1.361 +nsIContent * const * 1.362 +Attr::GetChildArray(uint32_t* aChildCount) const 1.363 +{ 1.364 + *aChildCount = 0; 1.365 + return nullptr; 1.366 +} 1.367 + 1.368 +int32_t 1.369 +Attr::IndexOf(const nsINode* aPossibleChild) const 1.370 +{ 1.371 + return -1; 1.372 +} 1.373 + 1.374 +nsresult 1.375 +Attr::InsertChildAt(nsIContent* aKid, uint32_t aIndex, 1.376 + bool aNotify) 1.377 +{ 1.378 + return NS_ERROR_NOT_IMPLEMENTED; 1.379 +} 1.380 + 1.381 +void 1.382 +Attr::RemoveChildAt(uint32_t aIndex, bool aNotify) 1.383 +{ 1.384 +} 1.385 + 1.386 +nsresult 1.387 +Attr::PreHandleEvent(EventChainPreVisitor& aVisitor) 1.388 +{ 1.389 + aVisitor.mCanHandle = true; 1.390 + return NS_OK; 1.391 +} 1.392 + 1.393 +void 1.394 +Attr::Initialize() 1.395 +{ 1.396 + sInitialized = true; 1.397 +} 1.398 + 1.399 +void 1.400 +Attr::Shutdown() 1.401 +{ 1.402 + sInitialized = false; 1.403 +} 1.404 + 1.405 +JSObject* 1.406 +Attr::WrapObject(JSContext* aCx) 1.407 +{ 1.408 + return AttrBinding::Wrap(aCx, this); 1.409 +} 1.410 + 1.411 +} // namespace dom 1.412 +} // namespace mozilla