/* -*- 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 the |attributes| property of DOM Core's Element object.
*/
nsDOMAttributeMap::nsDOMAttributeMap(Element* aContent) : mContent(aContent) { // We don't add a reference to our content. If it goes away, // we'll be told to drop our reference
}
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(nsDOMAttributeMap) if (tmp->HasKnownLiveWrapper()) { if (tmp->mContent) { // The map owns the element so we can mark it when the // map itself is certainly alive.
mozilla::dom::FragmentOrElement::MarkNodeChildren(tmp->mContent);
} returntrue;
} if (tmp->mContent &&
mozilla::dom::FragmentOrElement::CanSkip(tmp->mContent, true)) { returntrue;
}
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_END
RefPtr<mozilla::dom::NodeInfo> ni =
mContent->GetExistingAttrNameFromQName(aAttrName); if (!ni) { return nullptr;
}
aFound = true; return GetAttribute(ni);
}
void nsDOMAttributeMap::GetSupportedNames(nsTArray<nsString>& aNames) { // For HTML elements in HTML documents, only include names that are still the // same after ASCII-lowercasing, since our named getter will end up // ASCII-lowercasing the given string. bool lowercaseNamesOnly =
mContent->IsHTMLElement() && mContent->IsInHTMLDocument();
const uint32_t count = mContent->GetAttrCount(); bool seenNonAtomName = false; for (uint32_t i = 0; i < count; i++) { const nsAttrName* name = mContent->GetAttrNameAt(i);
seenNonAtomName = seenNonAtomName || !name->IsAtom();
nsString qualifiedName;
name->GetQualifiedName(qualifiedName);
if (lowercaseNamesOnly &&
nsContentUtils::StringContainsASCIIUpper(qualifiedName)) { continue;
}
// Omit duplicates. We only need to do this check if we've seen a non-atom // name, because that's the only way we can have two identical qualified // names. if (seenNonAtomName && aNames.Contains(qualifiedName)) { continue;
}
// XXX should check same-origin between mContent and aAttr however // nsContentUtils::CheckSameOrigin can't deal with attributenodes yet
// Check that attribute is not owned by somebody else
nsDOMAttributeMap* owner = aAttr.GetMap(); if (owner) { if (owner != this) {
aError.Throw(NS_ERROR_DOM_INUSE_ATTRIBUTE_ERR); return nullptr;
}
// setting a preexisting attribute is a no-op, just return the same // node.
RefPtr<Attr> attribute = &aAttr; return attribute.forget();
}
nsresult rv; if (mContent->OwnerDoc() != aAttr.OwnerDoc()) {
DebugOnly<void*> adoptedNode =
mContent->OwnerDoc()->AdoptNode(aAttr, aError); if (aError.Failed()) { return nullptr;
}
// Get nodeinfo and preexisting attribute (if it exists)
RefPtr<NodeInfo> oldNi;
uint32_t i, count = mContent->GetAttrCount(); for (i = 0; i < count; ++i) { const nsAttrName* name = mContent->GetAttrNameAt(i);
int32_t attrNS = name->NamespaceID();
nsAtom* nameAtom = name->LocalName();
// we're purposefully ignoring the prefix. if (aAttr.NodeInfo()->Equals(nameAtom, attrNS)) {
oldNi = mContent->NodeInfo()->NodeInfoManager()->GetNodeInfo(
nameAtom, name->GetPrefix(), aAttr.NodeInfo()->NamespaceID(),
nsINode::ATTRIBUTE_NODE); break;
}
}
RefPtr<Attr> oldAttr;
if (oldNi) {
oldAttr = GetAttribute(oldNi);
if (oldAttr == &aAttr) { return oldAttr.forget();
}
if (oldAttr) { // Just remove it from our hashtable. This has no side-effects, so we // don't have to recheck anything after we do it. Then we'll add our new // Attr to the hashtable and do the actual attr set on the element. This // will make the whole thing look like a single attribute mutation (with // the new attr node in place) as opposed to a removal and addition.
DropAttribute(oldNi->NamespaceID(), oldNi->NameAtom());
}
}
nsAutoString value;
aAttr.GetValue(value);
RefPtr<NodeInfo> ni = aAttr.NodeInfo();
// Add the new attribute to the attribute map before updating // its value in the element. @see bug 364413.
nsAttrKey attrkey(ni->NamespaceID(), ni->NameAtom());
mAttributeCache.InsertOrUpdate(attrkey, RefPtr{&aAttr});
aAttr.SetMap(this);
const nsAttrName* name = mContent->GetAttrNameAt(aIndex);
NS_ENSURE_TRUE(name, nullptr);
aFound = true; // Don't use the nodeinfo even if one exists since it can have the wrong // owner document.
RefPtr<mozilla::dom::NodeInfo> ni =
mContent->NodeInfo()->NodeInfoManager()->GetNodeInfo(
name->LocalName(), name->GetPrefix(), name->NamespaceID(),
nsINode::ATTRIBUTE_NODE); return GetAttribute(ni);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.