Diff
Modified: trunk/Source/WebCore/ChangeLog (165102 => 165103)
--- trunk/Source/WebCore/ChangeLog 2014-03-05 10:35:14 UTC (rev 165102)
+++ trunk/Source/WebCore/ChangeLog 2014-03-05 10:41:48 UTC (rev 165103)
@@ -1,3 +1,78 @@
+2014-03-05 Ryosuke Niwa <[email protected]>
+
+ appendChild shouldn't invalidate LiveNodeLists and HTMLCollections if they don't have valid caches
+ https://bugs.webkit.org/show_bug.cgi?id=129727
+
+ Reviewed by Andreas Kling.
+
+ Before this patch, invalidateNodeListAndCollectionCachesInAncestors invalidated node lists and HTML
+ collections on ancestors of a node whenever we're inserting or removing a child node. This patch
+ makes HTMLCollections and LiveNodeLists register themselves with Document only when they have valid
+ caches.
+
+ Each user of CollectionIndexCache now implements willValidateIndexCache member function that gets
+ called when CollectionIndexCache caches any state and necessitates the registration with document.
+
+ * dom/ChildNodeList.h: Added an empty willValidateIndexCache since child node lists are never
+ registered with document.
+
+ * dom/CollectionIndexCache.h:
+ (WebCore::CollectionIndexCache::hasValidCache): Added.
+ (WebCore::CollectionIndexCache::nodeCount): Calls willValidateIndexCache when caching node count.
+ (WebCore::CollectionIndexCache::nodeAfterCached): Ditto. Also assert that hasValidCache() true in
+ the cases where we're simply updating our caches or adding more caches.
+ (WebCore::CollectionIndexCache::nodeAt): Ditto. Also added a code to set the length cache when
+ we've reached the end of the list. This should be a slight speed up on some cases.
+
+ * dom/Document.cpp:
+ (WebCore::Document::Document): Initializes a variable used by assertions.
+ (WebCore::Document::unregisterNodeList): Added an early exit for when m_listsInvalidatedAtDocument
+ is empty since invalidateNodeListAndCollectionCaches swaps out the list.
+ (WebCore::Document::registerCollection): Removed the boolean hasIdNameMap since we now explicitly
+ call collectionCachedIdNameMap in HTMLCollection.
+ (WebCore::Document::unregisterCollection): Ditto. Exit early if m_collectionsInvalidatedAtDocument
+ is empty since invalidateNodeListAndCollectionCaches swaps out the list.
+ * dom/Document.h:
+
+ * dom/LiveNodeList.cpp:
+ (WebCore::LiveNodeList::invalidateCache): Unregister the node list with document if we had caches.
+ * dom/LiveNodeList.h:
+ (WebCore::LiveNodeList::LiveNodeList):
+ (WebCore::LiveNodeList::~LiveNodeList): Ditto.
+ (WebCore::LiveNodeList::invalidateCache): Pass around document. This is necessary since document()
+ had already moved to the new document inside NodeListsNodeData::invalidateCaches.
+ (WebCore::LiveNodeList::willValidateIndexCache): Added. Registers itself with document.
+
+ * dom/Node.cpp:
+ (WebCore::Document::invalidateNodeListAndCollectionCaches): Swap the lists since invalidateCache
+ tries to unregister node lists and HTML collections with document. Since this is the only case in
+ which node lists and HTML collections being removed may not be in the lists in unregisterNodeList
+ and unregisterCollection, assert this condition via m_inInvalidateNodeListAndCollectionCaches.
+ (WebCore::NodeListsNodeData::invalidateCaches):
+
+ * dom/NodeRareData.h:
+ (WebCore::NodeListsNodeData::adoptDocument): Unregister node lists and HTML collections from old
+ document via invalidateCache. We need to explicitly pass in oldDocument here since owner node's
+ document had already been changed to newDocument at this point. Since we're invalidating caches,
+ there is no need to register node lists and HTML collections with newDocument.
+
+ * html/HTMLCollection.cpp:
+ (WebCore::HTMLCollection::HTMLCollection):
+ (WebCore::HTMLCollection::~HTMLCollection): Unregister the node list with document if we had caches.
+ (WebCore::HTMLCollection::invalidateCache): Ditto.
+ (WebCore::HTMLCollection::invalidateNamedElementCache):
+ * html/HTMLCollection.h:
+ (WebCore::HTMLCollection::invalidateCache): Pass around document as done in LiveNodeList.
+ (WebCore::HTMLCollection::willValidateIndexCache): Ditto.
+
+ * html/HTMLFormControlsCollection.cpp:
+ (WebCore::HTMLFormControlsCollection::invalidateCache): Ditto.
+ * html/HTMLFormControlsCollection.h:
+
+ * html/HTMLSelectElement.cpp:
+ (WebCore::HTMLSelectElement::invalidateSelectedItems): Ditto.
+ (WebCore::HTMLSelectElement::setRecalcListItems): Ditto.
+
2014-03-05 Jon Lee <[email protected]>
Fix linker error after r165087
Modified: trunk/Source/WebCore/dom/ChildNodeList.h (165102 => 165103)
--- trunk/Source/WebCore/dom/ChildNodeList.h 2014-03-05 10:35:14 UTC (rev 165102)
+++ trunk/Source/WebCore/dom/ChildNodeList.h 2014-03-05 10:41:48 UTC (rev 165103)
@@ -75,6 +75,7 @@
Node* collectionTraverseForward(Node&, unsigned count, unsigned& traversedCount) const;
Node* collectionTraverseBackward(Node&, unsigned count) const;
bool collectionCanTraverseBackward() const { return true; }
+ void willValidateIndexCache() const { }
private:
explicit ChildNodeList(ContainerNode& parent);
Modified: trunk/Source/WebCore/dom/CollectionIndexCache.h (165102 => 165103)
--- trunk/Source/WebCore/dom/CollectionIndexCache.h 2014-03-05 10:35:14 UTC (rev 165102)
+++ trunk/Source/WebCore/dom/CollectionIndexCache.h 2014-03-05 10:41:48 UTC (rev 165103)
@@ -40,10 +40,12 @@
unsigned nodeCount(const Collection&);
NodeType* nodeAt(const Collection&, unsigned index);
+ bool hasValidCache() const { return m_currentNode || m_nodeCountValid || m_listValid; }
void invalidate();
size_t memoryCost() { return m_cachedList.capacity() * sizeof(NodeType*); }
private:
+
unsigned computeNodeCountUpdatingListCache(const Collection&);
NodeType* nodeBeforeCached(const Collection&, unsigned);
NodeType* nodeAfterCached(const Collection&, unsigned);
@@ -70,6 +72,8 @@
inline unsigned CollectionIndexCache<Collection, NodeType>::nodeCount(const Collection& collection)
{
if (!m_nodeCountValid) {
+ if (!hasValidCache())
+ collection.willValidateIndexCache();
m_nodeCount = computeNodeCountUpdatingListCache(collection);
m_nodeCountValid = true;
}
@@ -132,6 +136,7 @@
bool lastIsCloser = m_nodeCountValid && m_nodeCount - index < index - m_currentIndex;
if (lastIsCloser && collection.collectionCanTraverseBackward()) {
+ ASSERT(hasValidCache());
m_currentNode = collection.collectionLast();
if (index < m_nodeCount - 1)
m_currentNode = collection.collectionTraverseBackward(*m_currentNode, m_nodeCount - index - 1);
@@ -140,6 +145,9 @@
return m_currentNode;
}
+ if (!hasValidCache())
+ collection.willValidateIndexCache();
+
unsigned traversedCount;
m_currentNode = collection.collectionTraverseForward(*m_currentNode, index - m_currentIndex, traversedCount);
m_currentIndex = m_currentIndex + traversedCount;
@@ -151,6 +159,7 @@
m_nodeCount = m_currentIndex + 1;
m_nodeCountValid = true;
}
+ ASSERT(hasValidCache());
return m_currentNode;
}
@@ -173,6 +182,7 @@
bool lastIsCloser = m_nodeCountValid && m_nodeCount - index < index;
if (lastIsCloser && collection.collectionCanTraverseBackward()) {
+ ASSERT(hasValidCache());
m_currentNode = collection.collectionLast();
if (index < m_nodeCount - 1)
m_currentNode = collection.collectionTraverseBackward(*m_currentNode, m_nodeCount - index - 1);
@@ -181,12 +191,21 @@
return m_currentNode;
}
+ if (!hasValidCache())
+ collection.willValidateIndexCache();
+
m_currentNode = collection.collectionFirst();
m_currentIndex = 0;
if (index && m_currentNode) {
m_currentNode = collection.collectionTraverseForward(*m_currentNode, index, m_currentIndex);
ASSERT(m_currentNode || m_currentIndex < index);
}
+ if (!m_currentNode && !m_nodeCountValid) {
+ // Failed to find the index but at least we now know the size.
+ m_nodeCount = m_currentIndex + 1;
+ m_nodeCountValid = true;
+ }
+ ASSERT(hasValidCache());
return m_currentNode;
}
Modified: trunk/Source/WebCore/dom/Document.cpp (165102 => 165103)
--- trunk/Source/WebCore/dom/Document.cpp 2014-03-05 10:35:14 UTC (rev 165102)
+++ trunk/Source/WebCore/dom/Document.cpp 2014-03-05 10:41:48 UTC (rev 165103)
@@ -454,6 +454,9 @@
, m_xmlStandalone(StandaloneUnspecified)
, m_hasXMLDeclaration(false)
, m_designMode(inherit)
+#if !ASSERT_DISABLED
+ , m_inInvalidateNodeListAndCollectionCaches(false)
+#endif
#if ENABLE(DASHBOARD_SUPPORT)
, m_hasAnnotatedRegions(false)
, m_annotatedRegionsDirty(false)
@@ -3459,27 +3462,31 @@
{
m_nodeListAndCollectionCounts[list.invalidationType()]--;
if (list.isRootedAtDocument()) {
+ if (!m_listsInvalidatedAtDocument.size()) {
+ ASSERT(m_inInvalidateNodeListAndCollectionCaches);
+ return;
+ }
ASSERT(m_listsInvalidatedAtDocument.contains(&list));
m_listsInvalidatedAtDocument.remove(&list);
}
}
-void Document::registerCollection(HTMLCollection& collection, bool hasIdNameMap)
+void Document::registerCollection(HTMLCollection& collection)
{
- if (hasIdNameMap)
- collectionCachedIdNameMap(collection);
m_nodeListAndCollectionCounts[collection.invalidationType()]++;
if (collection.isRootedAtDocument())
m_collectionsInvalidatedAtDocument.add(&collection);
}
-void Document::unregisterCollection(HTMLCollection& collection, bool hasIdNameMap)
+void Document::unregisterCollection(HTMLCollection& collection)
{
- if (hasIdNameMap)
- collectionWillClearIdNameMap(collection);
ASSERT(m_nodeListAndCollectionCounts[collection.invalidationType()]);
m_nodeListAndCollectionCounts[collection.invalidationType()]--;
if (collection.isRootedAtDocument()) {
+ if (!m_collectionsInvalidatedAtDocument.size()) {
+ ASSERT(m_inInvalidateNodeListAndCollectionCaches);
+ return;
+ }
ASSERT(m_collectionsInvalidatedAtDocument.contains(&collection));
m_collectionsInvalidatedAtDocument.remove(&collection);
}
Modified: trunk/Source/WebCore/dom/Document.h (165102 => 165103)
--- trunk/Source/WebCore/dom/Document.h 2014-03-05 10:35:14 UTC (rev 165102)
+++ trunk/Source/WebCore/dom/Document.h 2014-03-05 10:41:48 UTC (rev 165103)
@@ -766,8 +766,8 @@
void registerNodeList(LiveNodeList&);
void unregisterNodeList(LiveNodeList&);
- void registerCollection(HTMLCollection&, bool hasNamedElementCache);
- void unregisterCollection(HTMLCollection&, bool hasNamedElementCache);
+ void registerCollection(HTMLCollection&);
+ void unregisterCollection(HTMLCollection&);
void collectionCachedIdNameMap(const HTMLCollection&);
void collectionWillClearIdNameMap(const HTMLCollection&);
bool shouldInvalidateNodeListAndCollectionCaches(const QualifiedName* attrName = nullptr) const;
@@ -1506,6 +1506,9 @@
HashSet<LiveNodeList*> m_listsInvalidatedAtDocument;
HashSet<HTMLCollection*> m_collectionsInvalidatedAtDocument;
+#if !ASSERT_DISABLED
+ bool m_inInvalidateNodeListAndCollectionCaches;
+#endif
unsigned m_nodeListAndCollectionCounts[numNodeListInvalidationTypes];
Modified: trunk/Source/WebCore/dom/LiveNodeList.cpp (165102 => 165103)
--- trunk/Source/WebCore/dom/LiveNodeList.cpp 2014-03-05 10:35:14 UTC (rev 165102)
+++ trunk/Source/WebCore/dom/LiveNodeList.cpp 2014-03-05 10:41:48 UTC (rev 165103)
@@ -148,8 +148,11 @@
return m_indexCache.memoryCost();
}
-void LiveNodeList::invalidateCache() const
+void LiveNodeList::invalidateCache(Document& document) const
{
+ if (!m_indexCache.hasValidCache())
+ return;
+ document.unregisterNodeList(const_cast<LiveNodeList&>(*this));
m_indexCache.invalidate();
}
Modified: trunk/Source/WebCore/dom/LiveNodeList.h (165102 => 165103)
--- trunk/Source/WebCore/dom/LiveNodeList.h 2014-03-05 10:35:14 UTC (rev 165102)
+++ trunk/Source/WebCore/dom/LiveNodeList.h 2014-03-05 10:41:48 UTC (rev 165103)
@@ -63,15 +63,14 @@
ASSERT(m_rootType == static_cast<unsigned>(rootType));
ASSERT(m_invalidationType == static_cast<unsigned>(invalidationType));
ASSERT(m_type == static_cast<unsigned>(type));
-
- document().registerNodeList(*this);
}
virtual Node* namedItem(const AtomicString&) const override final;
virtual bool nodeMatches(Element*) const = 0;
virtual ~LiveNodeList()
{
- document().unregisterNodeList(*this);
+ if (m_indexCache.hasValidCache())
+ document().unregisterNodeList(*this);
}
// DOM API
@@ -86,9 +85,9 @@
ALWAYS_INLINE void invalidateCache(const QualifiedName* attrName) const
{
if (!attrName || shouldInvalidateTypeOnAttributeChange(invalidationType(), *attrName))
- invalidateCache();
+ invalidateCache(document());
}
- void invalidateCache() const;
+ void invalidateCache(Document&) const;
// For CollectionIndexCache
Element* collectionFirst() const;
@@ -96,6 +95,7 @@
Element* collectionTraverseForward(Element&, unsigned count, unsigned& traversedCount) const;
Element* collectionTraverseBackward(Element&, unsigned count) const;
bool collectionCanTraverseBackward() const { return true; }
+ void willValidateIndexCache() const { document().registerNodeList(const_cast<LiveNodeList&>(*this)); }
protected:
Document& document() const { return m_ownerNode->document(); }
Modified: trunk/Source/WebCore/dom/Node.cpp (165102 => 165103)
--- trunk/Source/WebCore/dom/Node.cpp 2014-03-05 10:35:14 UTC (rev 165102)
+++ trunk/Source/WebCore/dom/Node.cpp 2014-03-05 10:41:48 UTC (rev 165103)
@@ -721,10 +721,19 @@
void Document::invalidateNodeListAndCollectionCaches(const QualifiedName* attrName)
{
- for (HashSet<LiveNodeList*>::iterator it = m_listsInvalidatedAtDocument.begin(), end = m_listsInvalidatedAtDocument.end(); it != end; ++it)
- (*it)->invalidateCache(attrName);
- for (HashSet<HTMLCollection*>::iterator it = m_collectionsInvalidatedAtDocument.begin(), end = m_collectionsInvalidatedAtDocument.end(); it != end; ++it)
- (*it)->invalidateCache(attrName);
+#if !ASSERT_DISABLED
+ m_inInvalidateNodeListAndCollectionCaches = true;
+#endif
+ HashSet<LiveNodeList*> liveNodeLists = std::move(m_listsInvalidatedAtDocument);
+ for (auto it : liveNodeLists)
+ it->invalidateCache(attrName);
+
+ HashSet<HTMLCollection*> collectionLists = std::move(m_collectionsInvalidatedAtDocument);
+ for (auto it : collectionLists)
+ it->invalidateCache(attrName);
+#if !ASSERT_DISABLED
+ m_inInvalidateNodeListAndCollectionCaches = false;
+#endif
}
void Node::invalidateNodeListAndCollectionCachesInAncestors(const QualifiedName* attrName, Element* attributeOwnerElement)
@@ -1689,7 +1698,7 @@
return;
for (auto& tagNodeList : m_tagNodeListCacheNS)
- tagNodeList.value->invalidateCache();
+ tagNodeList.value->invalidateCache(nullptr);
}
void Node::getSubresourceURLs(ListHashSet<URL>& urls) const
Modified: trunk/Source/WebCore/dom/NodeRareData.h (165102 => 165103)
--- trunk/Source/WebCore/dom/NodeRareData.h 2014-03-05 10:35:14 UTC (rev 165102)
+++ trunk/Source/WebCore/dom/NodeRareData.h 2014-03-05 10:41:48 UTC (rev 165103)
@@ -225,39 +225,26 @@
void adoptDocument(Document* oldDocument, Document* newDocument)
{
+ ASSERT(oldDocument);
if (oldDocument == newDocument) {
invalidateCaches();
return;
}
- for (auto it : m_atomicNameCaches) {
- LiveNodeList& list = *it.value;
- oldDocument->unregisterNodeList(list);
- newDocument->registerNodeList(list);
- list.invalidateCache();
- }
+ for (auto it : m_atomicNameCaches)
+ it.value->invalidateCache(*oldDocument);
- for (auto it : m_nameCaches) {
- LiveNodeList& list = *it.value;
- oldDocument->unregisterNodeList(list);
- newDocument->registerNodeList(list);
- list.invalidateCache();
- }
+ for (auto it : m_nameCaches)
+ it.value->invalidateCache(*oldDocument);
for (auto it : m_tagNodeListCacheNS) {
LiveNodeList& list = *it.value;
ASSERT(!list.isRootedAtDocument());
- oldDocument->unregisterNodeList(list);
- newDocument->registerNodeList(list);
- list.invalidateCache();
+ list.invalidateCache(*oldDocument);
}
- for (auto it : m_cachedCollections) {
- HTMLCollection& collection = *it.value;
- oldDocument->unregisterCollection(collection, collection.hasNamedElementCache());
- newDocument->registerCollection(collection, collection.hasNamedElementCache());
- collection.invalidateCache();
- }
+ for (auto it : m_cachedCollections)
+ it.value->invalidateCache(*oldDocument);
}
private:
Modified: trunk/Source/WebCore/html/HTMLCollection.cpp (165102 => 165103)
--- trunk/Source/WebCore/html/HTMLCollection.cpp 2014-03-05 10:35:14 UTC (rev 165102)
+++ trunk/Source/WebCore/html/HTMLCollection.cpp 2014-03-05 10:41:48 UTC (rev 165103)
@@ -142,8 +142,6 @@
ASSERT(m_rootType == static_cast<unsigned>(rootTypeFromCollectionType(type)));
ASSERT(m_invalidationType == static_cast<unsigned>(invalidationTypeExcludingIdAndNameAttributes(type)));
ASSERT(m_collectionType == static_cast<unsigned>(type));
-
- document().registerCollection(*this, hasNamedElementCache());
}
PassRefPtr<HTMLCollection> HTMLCollection::create(ContainerNode& base, CollectionType type)
@@ -153,7 +151,10 @@
HTMLCollection::~HTMLCollection()
{
- document().unregisterCollection(*this, hasNamedElementCache());
+ if (m_indexCache.hasValidCache())
+ document().unregisterCollection(*this);
+ if (hasNamedElementCache())
+ document().collectionWillClearIdNameMap(*this);
// HTMLNameCollection removes cache by itself.
if (type() != WindowNamedItems && type() != DocumentNamedItems)
ownerNode().nodeLists()->removeCachedCollection(this);
@@ -362,17 +363,20 @@
return element;
}
-void HTMLCollection::invalidateCache() const
+void HTMLCollection::invalidateCache(Document& document) const
{
- m_indexCache.invalidate();
+ if (m_indexCache.hasValidCache()) {
+ document.unregisterCollection(const_cast<HTMLCollection&>(*this));
+ m_indexCache.invalidate();
+ }
if (hasNamedElementCache())
- invalidateNamedElementCache();
+ invalidateNamedElementCache(document);
}
-void HTMLCollection::invalidateNamedElementCache() const
+void HTMLCollection::invalidateNamedElementCache(Document& document) const
{
ASSERT(hasNamedElementCache());
- document().collectionWillClearIdNameMap(*this);
+ document.collectionWillClearIdNameMap(*this);
m_namedElementCache = nullptr;
}
Modified: trunk/Source/WebCore/html/HTMLCollection.h (165102 => 165103)
--- trunk/Source/WebCore/html/HTMLCollection.h 2014-03-05 10:35:14 UTC (rev 165102)
+++ trunk/Source/WebCore/html/HTMLCollection.h 2014-03-05 10:41:48 UTC (rev 165103)
@@ -107,11 +107,11 @@
void invalidateCache(const QualifiedName* attrName) const
{
if (!attrName || shouldInvalidateTypeOnAttributeChange(invalidationType(), *attrName))
- invalidateCache();
+ invalidateCache(document());
else if (hasNamedElementCache() && (*attrName == HTMLNames::idAttr || *attrName == HTMLNames::nameAttr))
- invalidateNamedElementCache();
+ invalidateNamedElementCache(document());
}
- virtual void invalidateCache() const;
+ virtual void invalidateCache(Document&) const;
// For CollectionIndexCache
Element* collectionFirst() const;
@@ -119,6 +119,7 @@
Element* collectionTraverseForward(Element&, unsigned count, unsigned& traversedCount) const;
Element* collectionTraverseBackward(Element&, unsigned count) const;
bool collectionCanTraverseBackward() const { return !m_usesCustomForwardOnlyTraversal; }
+ void willValidateIndexCache() const { document().registerCollection(const_cast<HTMLCollection&>(*this)); }
bool hasNamedElementCache() const { return !!m_namedElementCache; }
@@ -155,7 +156,7 @@
virtual Element* customElementAfter(Element*) const { ASSERT_NOT_REACHED(); return nullptr; }
- void invalidateNamedElementCache() const;
+ void invalidateNamedElementCache(Document&) const;
Ref<ContainerNode> m_ownerNode;
Modified: trunk/Source/WebCore/html/HTMLFormControlsCollection.cpp (165102 => 165103)
--- trunk/Source/WebCore/html/HTMLFormControlsCollection.cpp 2014-03-05 10:35:14 UTC (rev 165102)
+++ trunk/Source/WebCore/html/HTMLFormControlsCollection.cpp 2014-03-05 10:41:48 UTC (rev 165103)
@@ -177,9 +177,9 @@
cache.didPopulate();
}
-void HTMLFormControlsCollection::invalidateCache() const
+void HTMLFormControlsCollection::invalidateCache(Document& document) const
{
- HTMLCollection::invalidateCache();
+ HTMLCollection::invalidateCache(document);
m_cachedElement = nullptr;
m_cachedElementOffsetInArray = 0;
}
Modified: trunk/Source/WebCore/html/HTMLFormControlsCollection.h (165102 => 165103)
--- trunk/Source/WebCore/html/HTMLFormControlsCollection.h 2014-03-05 10:35:14 UTC (rev 165102)
+++ trunk/Source/WebCore/html/HTMLFormControlsCollection.h 2014-03-05 10:41:48 UTC (rev 165103)
@@ -46,7 +46,7 @@
private:
explicit HTMLFormControlsCollection(ContainerNode&);
- virtual void invalidateCache() const override;
+ virtual void invalidateCache(Document&) const override;
virtual void updateNamedElementCache() const override;
const Vector<FormAssociatedElement*>& formControlElements() const;
Modified: trunk/Source/WebCore/html/HTMLSelectElement.cpp (165102 => 165103)
--- trunk/Source/WebCore/html/HTMLSelectElement.cpp 2014-03-05 10:35:14 UTC (rev 165102)
+++ trunk/Source/WebCore/html/HTMLSelectElement.cpp 2014-03-05 10:41:48 UTC (rev 165103)
@@ -750,7 +750,7 @@
void HTMLSelectElement::invalidateSelectedItems()
{
if (HTMLCollection* collection = cachedHTMLCollection(SelectedOptions))
- collection->invalidateCache();
+ collection->invalidateCache(document());
}
void HTMLSelectElement::setRecalcListItems()
@@ -762,7 +762,7 @@
setNeedsStyleRecalc();
if (!inDocument()) {
if (HTMLCollection* collection = cachedHTMLCollection(SelectOptions))
- collection->invalidateCache();
+ collection->invalidateCache(document());
}
if (!inDocument())
invalidateSelectedItems();