diff -r 000000000000 -r 6474c204b198 content/base/src/ShadowRoot.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/content/base/src/ShadowRoot.cpp Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,705 @@ +/* -*- 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 "ChildIterator.h" +#include "nsContentUtils.h" +#include "nsDOMClassInfoID.h" +#include "nsIDOMHTMLElement.h" +#include "nsIStyleSheetLinkingElement.h" +#include "mozilla/dom/Element.h" +#include "mozilla/dom/HTMLContentElement.h" +#include "mozilla/dom/HTMLShadowElement.h" +#include "nsXBLPrototypeBinding.h" + +using namespace mozilla; +using namespace mozilla::dom; + +static PLDHashOperator +IdentifierMapEntryTraverse(nsIdentifierMapEntry *aEntry, void *aArg) +{ + nsCycleCollectionTraversalCallback *cb = + static_cast(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(mPoolHost) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mStyleSheetList) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOlderShadow) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mYoungerShadow) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAssociatedBinding) + tmp->mIdentifierMap.EnumerateEntries(IdentifierMapEntryTraverse, &cb); +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END + +NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(ShadowRoot, + DocumentFragment) + if (tmp->mPoolHost) { + tmp->mPoolHost->RemoveMutationObserver(tmp); + } + NS_IMPL_CYCLE_COLLECTION_UNLINK(mPoolHost) + NS_IMPL_CYCLE_COLLECTION_UNLINK(mStyleSheetList) + NS_IMPL_CYCLE_COLLECTION_UNLINK(mOlderShadow) + NS_IMPL_CYCLE_COLLECTION_UNLINK(mYoungerShadow) + NS_IMPL_CYCLE_COLLECTION_UNLINK(mAssociatedBinding) + 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_ENTRY(nsIMutationObserver) +NS_INTERFACE_MAP_END_INHERITING(DocumentFragment) + +NS_IMPL_ADDREF_INHERITED(ShadowRoot, DocumentFragment) +NS_IMPL_RELEASE_INHERITED(ShadowRoot, DocumentFragment) + +ShadowRoot::ShadowRoot(nsIContent* aContent, + already_AddRefed&& aNodeInfo, + nsXBLPrototypeBinding* aProtoBinding) + : DocumentFragment(aNodeInfo), mPoolHost(aContent), + mProtoBinding(aProtoBinding), mShadowElement(nullptr), + mInsertionPointChanged(false) +{ + 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; + + // Add the ShadowRoot as a mutation observer on the host to watch + // for mutations because the insertion points in this ShadowRoot + // may need to be updated when the host children are modified. + mPoolHost->AddMutationObserver(this); +} + +ShadowRoot::~ShadowRoot() +{ + if (mPoolHost) { + // mPoolHost may have been unlinked or a new ShadowRoot may have been + // creating, making this one obsolete. + mPoolHost->RemoveMutationObserver(this); + } + + ClearInDocument(); + SetHost(nullptr); +} + +JSObject* +ShadowRoot::WrapObject(JSContext* aCx) +{ + return mozilla::dom::ShadowRootBinding::Wrap(aCx, 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(aNode); + } + + return nullptr; +} + +void +ShadowRoot::Restyle() +{ + mProtoBinding->FlushSkinSheets(); + + nsIPresShell* shell = OwnerDoc()->GetShell(); + if (shell) { + OwnerDoc()->BeginUpdate(UPDATE_STYLE); + shell->RestyleShadowRoot(this); + OwnerDoc()->EndUpdate(UPDATE_STYLE); + } +} + +void +ShadowRoot::InsertSheet(nsCSSStyleSheet* aSheet, + nsIContent* aLinkingContent) +{ + nsCOMPtr + linkingElement = do_QueryInterface(aLinkingContent); + MOZ_ASSERT(linkingElement, "The only styles in a ShadowRoot should come " + "from