gecko/content/base/src/ShadowRoot.cpp

153 lines
4.4 KiB
C++
Raw Normal View History

/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
#include "mozilla/Preferences.h"
#include "mozilla/dom/ShadowRoot.h"
#include "mozilla/dom/ShadowRootBinding.h"
#include "mozilla/dom/DocumentFragment.h"
#include "nsContentUtils.h"
#include "nsDOMClassInfoID.h"
#include "nsIDOMHTMLElement.h"
#include "mozilla/dom/Element.h"
#include "nsXBLPrototypeBinding.h"
using namespace mozilla;
using namespace mozilla::dom;
static PLDHashOperator
IdentifierMapEntryTraverse(nsIdentifierMapEntry *aEntry, void *aArg)
{
nsCycleCollectionTraversalCallback *cb =
static_cast<nsCycleCollectionTraversalCallback*>(aArg);
aEntry->Traverse(cb);
return PL_DHASH_NEXT;
}
NS_IMPL_CYCLE_COLLECTION_CLASS(ShadowRoot)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(ShadowRoot,
DocumentFragment)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mHost)
tmp->mIdentifierMap.EnumerateEntries(IdentifierMapEntryTraverse, &cb);
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(ShadowRoot,
DocumentFragment)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mHost)
tmp->mIdentifierMap.Clear();
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
DOMCI_DATA(ShadowRoot, ShadowRoot)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(ShadowRoot)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIContent)
NS_INTERFACE_MAP_END_INHERITING(DocumentFragment)
NS_IMPL_ADDREF_INHERITED(ShadowRoot, DocumentFragment)
NS_IMPL_RELEASE_INHERITED(ShadowRoot, DocumentFragment)
ShadowRoot::ShadowRoot(nsIContent* aContent,
already_AddRefed<nsINodeInfo> aNodeInfo)
: DocumentFragment(aNodeInfo), mHost(aContent)
{
SetHost(aContent);
SetFlags(NODE_IS_IN_SHADOW_TREE);
// ShadowRoot isn't really in the document but it behaves like it is.
SetInDocument();
DOMSlots()->mBindingParent = aContent;
DOMSlots()->mContainingShadow = this;
}
ShadowRoot::~ShadowRoot()
{
ClearInDocument();
SetHost(nullptr);
}
JSObject*
ShadowRoot::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
{
return mozilla::dom::ShadowRootBinding::Wrap(aCx, aScope, this);
}
ShadowRoot*
ShadowRoot::FromNode(nsINode* aNode)
{
if (aNode->HasFlag(NODE_IS_IN_SHADOW_TREE) && !aNode->GetParentNode()) {
MOZ_ASSERT(aNode->NodeType() == nsIDOMNode::DOCUMENT_FRAGMENT_NODE,
"ShadowRoot is a document fragment.");
return static_cast<ShadowRoot*>(aNode);
}
return nullptr;
}
Element*
ShadowRoot::GetElementById(const nsAString& aElementId)
{
nsIdentifierMapEntry *entry = mIdentifierMap.GetEntry(aElementId);
return entry ? entry->GetIdElement() : nullptr;
}
already_AddRefed<nsContentList>
ShadowRoot::GetElementsByTagName(const nsAString& aTagName)
{
return NS_GetContentList(this, kNameSpaceID_Unknown, aTagName);
}
already_AddRefed<nsContentList>
ShadowRoot::GetElementsByTagNameNS(const nsAString& aNamespaceURI,
const nsAString& aLocalName)
{
int32_t nameSpaceId = kNameSpaceID_Wildcard;
if (!aNamespaceURI.EqualsLiteral("*")) {
nsresult rv =
nsContentUtils::NameSpaceManager()->RegisterNameSpace(aNamespaceURI,
nameSpaceId);
NS_ENSURE_SUCCESS(rv, nullptr);
}
NS_ASSERTION(nameSpaceId != kNameSpaceID_Unknown, "Unexpected namespace ID!");
return NS_GetContentList(this, nameSpaceId, aLocalName);
}
void
ShadowRoot::AddToIdTable(Element* aElement, nsIAtom* aId)
{
nsIdentifierMapEntry *entry =
mIdentifierMap.PutEntry(nsDependentAtomString(aId));
if (entry) {
entry->AddIdElement(aElement);
}
}
void
ShadowRoot::RemoveFromIdTable(Element* aElement, nsIAtom* aId)
{
nsIdentifierMapEntry *entry =
mIdentifierMap.GetEntry(nsDependentAtomString(aId));
if (entry) {
entry->RemoveIdElement(aElement);
if (entry->IsEmpty()) {
mIdentifierMap.RawRemoveEntry(entry);
}
}
}
already_AddRefed<nsContentList>
ShadowRoot::GetElementsByClassName(const nsAString& aClasses)
{
return nsContentUtils::GetElementsByClassName(this, aClasses);
}
bool
ShadowRoot::PrefEnabled()
{
return Preferences::GetBool("dom.webcomponents.enabled", false);
}