forked from mirrors/gecko-dev
		
	 d2ed260822
			
		
	
	
		d2ed260822
		
	
	
	
	
		
			
			Summary: Really sorry for the size of the patch. It's mostly automatic s/nsIDocument/Document/ but I had to fix up in a bunch of places manually to add the right namespacing and such. Overall it's not a very interesting patch I think. nsDocument.cpp turns into Document.cpp, nsIDocument.h into Document.h and nsIDocumentInlines.h into DocumentInlines.h. I also changed a bunch of nsCOMPtr usage to RefPtr, but not all of it. While fixing up some of the bits I also removed some unneeded OwnerDoc() null checks and such, but I didn't do anything riskier than that.
		
			
				
	
	
		
			225 lines
		
	
	
	
		
			6.8 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			225 lines
		
	
	
	
		
			6.8 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 | |
| /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 | |
| /* This Source Code Form is subject to the terms of the Mozilla Public
 | |
|  * License, v. 2.0. If a copy of the MPL was not distributed with this
 | |
|  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 | |
| 
 | |
| /*
 | |
|  * Implementation of DOM Core's Attr node.
 | |
|  */
 | |
| 
 | |
| #include "mozilla/dom/Attr.h"
 | |
| #include "mozilla/dom/AttrBinding.h"
 | |
| #include "mozilla/dom/Element.h"
 | |
| #include "mozilla/EventDispatcher.h"
 | |
| #include "mozilla/InternalMutationEvent.h"
 | |
| #include "nsContentCreatorFunctions.h"
 | |
| #include "nsError.h"
 | |
| #include "nsUnicharUtils.h"
 | |
| #include "nsDOMString.h"
 | |
| #include "nsIContentInlines.h"
 | |
| #include "mozilla/dom/Document.h"
 | |
| #include "nsGkAtoms.h"
 | |
| #include "nsCOMArray.h"
 | |
| #include "nsNameSpaceManager.h"
 | |
| #include "nsNodeUtils.h"
 | |
| #include "nsTextNode.h"
 | |
| #include "mozAutoDocUpdate.h"
 | |
| #include "nsWrapperCacheInlines.h"
 | |
| #include "NodeUbiReporting.h"
 | |
| 
 | |
| namespace mozilla {
 | |
| namespace dom {
 | |
| 
 | |
| //----------------------------------------------------------------------
 | |
| bool Attr::sInitialized;
 | |
| 
 | |
| Attr::Attr(nsDOMAttributeMap* aAttrMap,
 | |
|            already_AddRefed<dom::NodeInfo>&& aNodeInfo, const nsAString& aValue)
 | |
|     : nsINode(std::move(aNodeInfo)), mAttrMap(aAttrMap), mValue(aValue) {
 | |
|   MOZ_ASSERT(mNodeInfo, "We must get a nodeinfo here!");
 | |
|   MOZ_ASSERT(mNodeInfo->NodeType() == ATTRIBUTE_NODE, "Wrong nodeType");
 | |
| 
 | |
|   // We don't add a reference to our content. It will tell us
 | |
|   // to drop our reference when it goes away.
 | |
| }
 | |
| 
 | |
| NS_IMPL_CYCLE_COLLECTION_CLASS(Attr)
 | |
| 
 | |
| NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Attr)
 | |
|   if (!nsINode::Traverse(tmp, cb)) {
 | |
|     return NS_SUCCESS_INTERRUPTED_TRAVERSE;
 | |
|   }
 | |
|   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAttrMap)
 | |
| NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 | |
| 
 | |
| NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(Attr)
 | |
| 
 | |
| NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Attr)
 | |
|   nsINode::Unlink(tmp);
 | |
|   NS_IMPL_CYCLE_COLLECTION_UNLINK(mAttrMap)
 | |
| NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 | |
| 
 | |
| NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(Attr)
 | |
|   Element* ownerElement = tmp->GetElement();
 | |
|   if (tmp->HasKnownLiveWrapper()) {
 | |
|     if (ownerElement) {
 | |
|       // The attribute owns the element via attribute map so we can
 | |
|       // mark it when the attribute is certainly alive.
 | |
|       mozilla::dom::FragmentOrElement::MarkNodeChildren(ownerElement);
 | |
|     }
 | |
|     return true;
 | |
|   }
 | |
|   if (ownerElement &&
 | |
|       mozilla::dom::FragmentOrElement::CanSkip(ownerElement, true)) {
 | |
|     return true;
 | |
|   }
 | |
| NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_END
 | |
| 
 | |
| NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_BEGIN(Attr)
 | |
|   return tmp->HasKnownLiveWrapperAndDoesNotNeedTracing(tmp);
 | |
| NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_END
 | |
| 
 | |
| NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_BEGIN(Attr)
 | |
|   return tmp->HasKnownLiveWrapper();
 | |
| NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_END
 | |
| 
 | |
| // QueryInterface implementation for Attr
 | |
| NS_INTERFACE_TABLE_HEAD(Attr)
 | |
|   NS_WRAPPERCACHE_INTERFACE_TABLE_ENTRY
 | |
|   NS_INTERFACE_TABLE(Attr, nsINode, EventTarget)
 | |
|   NS_INTERFACE_TABLE_TO_MAP_SEGUE_CYCLE_COLLECTION(Attr)
 | |
|   NS_INTERFACE_MAP_ENTRY_TEAROFF(nsISupportsWeakReference,
 | |
|                                  new nsNodeSupportsWeakRefTearoff(this))
 | |
| NS_INTERFACE_MAP_END
 | |
| 
 | |
| NS_IMPL_CYCLE_COLLECTING_ADDREF(Attr)
 | |
| NS_IMPL_CYCLE_COLLECTING_RELEASE_WITH_LAST_RELEASE(
 | |
|     Attr, nsNodeUtils::LastRelease(this))
 | |
| 
 | |
| void Attr::SetMap(nsDOMAttributeMap* aMap) {
 | |
|   if (mAttrMap && !aMap && sInitialized) {
 | |
|     // We're breaking a relationship with content and not getting a new one,
 | |
|     // need to locally cache value. GetValue() does that.
 | |
|     GetValue(mValue);
 | |
|   }
 | |
| 
 | |
|   mAttrMap = aMap;
 | |
| }
 | |
| 
 | |
| Element* Attr::GetElement() const {
 | |
|   if (!mAttrMap) {
 | |
|     return nullptr;
 | |
|   }
 | |
|   nsIContent* content = mAttrMap->GetContent();
 | |
|   return content ? content->AsElement() : nullptr;
 | |
| }
 | |
| 
 | |
| nsresult Attr::SetOwnerDocument(Document* aDocument) {
 | |
|   NS_ASSERTION(aDocument, "Missing document");
 | |
| 
 | |
|   Document* doc = OwnerDoc();
 | |
|   NS_ASSERTION(doc != aDocument, "bad call to Attr::SetOwnerDocument");
 | |
|   doc->DeleteAllPropertiesFor(this);
 | |
| 
 | |
|   RefPtr<dom::NodeInfo> newNodeInfo = aDocument->NodeInfoManager()->GetNodeInfo(
 | |
|       mNodeInfo->NameAtom(), mNodeInfo->GetPrefixAtom(),
 | |
|       mNodeInfo->NamespaceID(), ATTRIBUTE_NODE);
 | |
|   NS_ASSERTION(newNodeInfo, "GetNodeInfo lies");
 | |
|   mNodeInfo.swap(newNodeInfo);
 | |
| 
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| void Attr::GetName(nsAString& aName) { aName = NodeName(); }
 | |
| 
 | |
| void Attr::GetValue(nsAString& aValue) {
 | |
|   Element* element = GetElement();
 | |
|   if (element) {
 | |
|     RefPtr<nsAtom> nameAtom = mNodeInfo->NameAtom();
 | |
|     element->GetAttr(mNodeInfo->NamespaceID(), nameAtom, aValue);
 | |
|   } else {
 | |
|     aValue = mValue;
 | |
|   }
 | |
| }
 | |
| 
 | |
| void Attr::SetValue(const nsAString& aValue, nsIPrincipal* aTriggeringPrincipal,
 | |
|                     ErrorResult& aRv) {
 | |
|   Element* element = GetElement();
 | |
|   if (!element) {
 | |
|     mValue = aValue;
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   RefPtr<nsAtom> nameAtom = mNodeInfo->NameAtom();
 | |
|   aRv = element->SetAttr(mNodeInfo->NamespaceID(), nameAtom,
 | |
|                          mNodeInfo->GetPrefixAtom(), aValue,
 | |
|                          aTriggeringPrincipal, true);
 | |
| }
 | |
| 
 | |
| void Attr::SetValue(const nsAString& aValue, ErrorResult& aRv) {
 | |
|   SetValue(aValue, nullptr, aRv);
 | |
| }
 | |
| 
 | |
| bool Attr::Specified() const { return true; }
 | |
| 
 | |
| Element* Attr::GetOwnerElement(ErrorResult& aRv) { return GetElement(); }
 | |
| 
 | |
| void Attr::GetNodeValueInternal(nsAString& aNodeValue) { GetValue(aNodeValue); }
 | |
| 
 | |
| void Attr::SetNodeValueInternal(const nsAString& aNodeValue,
 | |
|                                 ErrorResult& aError) {
 | |
|   SetValue(aNodeValue, nullptr, aError);
 | |
| }
 | |
| 
 | |
| nsresult Attr::Clone(dom::NodeInfo* aNodeInfo, nsINode** aResult) const {
 | |
|   nsAutoString value;
 | |
|   const_cast<Attr*>(this)->GetValue(value);
 | |
| 
 | |
|   *aResult = new Attr(nullptr, do_AddRef(aNodeInfo), value);
 | |
|   if (!*aResult) {
 | |
|     return NS_ERROR_OUT_OF_MEMORY;
 | |
|   }
 | |
| 
 | |
|   NS_ADDREF(*aResult);
 | |
| 
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| already_AddRefed<nsIURI> Attr::GetBaseURI(bool aTryUseXHRDocBaseURI) const {
 | |
|   Element* parent = GetElement();
 | |
| 
 | |
|   return parent ? parent->GetBaseURI(aTryUseXHRDocBaseURI) : nullptr;
 | |
| }
 | |
| 
 | |
| void Attr::GetTextContentInternal(nsAString& aTextContent,
 | |
|                                   OOMReporter& aError) {
 | |
|   GetValue(aTextContent);
 | |
| }
 | |
| 
 | |
| void Attr::SetTextContentInternal(const nsAString& aTextContent,
 | |
|                                   nsIPrincipal* aSubjectPrincipal,
 | |
|                                   ErrorResult& aError) {
 | |
|   SetNodeValueInternal(aTextContent, aError);
 | |
| }
 | |
| 
 | |
| bool Attr::IsNodeOfType(uint32_t aFlags) const { return false; }
 | |
| 
 | |
| void Attr::GetEventTargetParent(EventChainPreVisitor& aVisitor) {
 | |
|   aVisitor.mCanHandle = true;
 | |
| }
 | |
| 
 | |
| void Attr::Initialize() { sInitialized = true; }
 | |
| 
 | |
| void Attr::Shutdown() { sInitialized = false; }
 | |
| 
 | |
| JSObject* Attr::WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) {
 | |
|   return Attr_Binding::Wrap(aCx, this, aGivenProto);
 | |
| }
 | |
| 
 | |
| void Attr::ConstructUbiNode(void* storage) {
 | |
|   JS::ubi::Concrete<Attr>::construct(storage, this);
 | |
| }
 | |
| 
 | |
| }  // namespace dom
 | |
| }  // namespace mozilla
 |