1/* 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) 4 * (C) 2001 Dirk Mueller (mueller@kde.org) 5 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved. 6 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) 7 * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) 8 * Copyright (C) 2011 Google Inc. All rights reserved. 9 * 10 * This library is free software; you can redistribute it and/or 11 * modify it under the terms of the GNU Library General Public 12 * License as published by the Free Software Foundation; either 13 * version 2 of the License, or (at your option) any later version. 14 * 15 * This library is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 * Library General Public License for more details. 19 * 20 * You should have received a copy of the GNU Library General Public License 21 * along with this library; see the file COPYING.LIB. If not, write to 22 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 23 * Boston, MA 02110-1301, USA. 24 */ 25#include "config.h" 26#include "TreeScopeAdopter.h" 27 28#include "Attr.h" 29#include "Document.h" 30#include "ElementRareData.h" 31#include "ElementShadow.h" 32#include "NodeRareData.h" 33#include "NodeTraversal.h" 34#include "RenderStyle.h" 35#include "ShadowRoot.h" 36 37namespace WebCore { 38 39void TreeScopeAdopter::moveTreeToNewScope(Node* root) const 40{ 41 ASSERT(needsScopeChange()); 42 43 m_oldScope->guardRef(); 44 45 // If an element is moved from a document and then eventually back again the collection cache for 46 // that element may contain stale data as changes made to it will have updated the DOMTreeVersion 47 // of the document it was moved to. By increasing the DOMTreeVersion of the donating document here 48 // we ensure that the collection cache will be invalidated as needed when the element is moved back. 49 Document* oldDocument = m_oldScope->documentScope(); 50 Document* newDocument = m_newScope->documentScope(); 51 bool willMoveToNewDocument = oldDocument != newDocument; 52 if (oldDocument && willMoveToNewDocument) 53 oldDocument->incDOMTreeVersion(); 54 55 for (Node* node = root; node; node = NodeTraversal::next(node, root)) { 56 updateTreeScope(node); 57 58 if (willMoveToNewDocument) 59 moveNodeToNewDocument(node, oldDocument, newDocument); 60 else if (node->hasRareData()) { 61 NodeRareData* rareData = node->rareData(); 62 if (rareData->nodeLists()) 63 rareData->nodeLists()->adoptTreeScope(); 64 } 65 66 if (!node->isElementNode()) 67 continue; 68 69 if (node->hasSyntheticAttrChildNodes()) { 70 const Vector<RefPtr<Attr> >& attrs = toElement(node)->attrNodeList(); 71 for (unsigned i = 0; i < attrs.size(); ++i) 72 moveTreeToNewScope(attrs[i].get()); 73 } 74 75 if (ShadowRoot* shadow = node->shadowRoot()) { 76 shadow->setParentTreeScope(m_newScope); 77 if (willMoveToNewDocument) 78 moveTreeToNewDocument(shadow, oldDocument, newDocument); 79 } 80 } 81 82 m_oldScope->guardDeref(); 83} 84 85void TreeScopeAdopter::moveTreeToNewDocument(Node* root, Document* oldDocument, Document* newDocument) const 86{ 87 for (Node* node = root; node; node = NodeTraversal::next(node, root)) { 88 moveNodeToNewDocument(node, oldDocument, newDocument); 89 if (ShadowRoot* shadow = node->shadowRoot()) 90 moveTreeToNewDocument(shadow, oldDocument, newDocument); 91 } 92} 93 94#ifndef NDEBUG 95static bool didMoveToNewDocumentWasCalled = false; 96static Document* oldDocumentDidMoveToNewDocumentWasCalledWith = 0; 97 98void TreeScopeAdopter::ensureDidMoveToNewDocumentWasCalled(Document* oldDocument) 99{ 100 ASSERT(!didMoveToNewDocumentWasCalled); 101 ASSERT_UNUSED(oldDocument, oldDocument == oldDocumentDidMoveToNewDocumentWasCalledWith); 102 didMoveToNewDocumentWasCalled = true; 103} 104#endif 105 106inline void TreeScopeAdopter::updateTreeScope(Node* node) const 107{ 108 ASSERT(!node->isTreeScope()); 109 ASSERT(node->treeScope() == m_oldScope); 110 m_newScope->guardRef(); 111 m_oldScope->guardDeref(); 112 node->setTreeScope(m_newScope); 113} 114 115inline void TreeScopeAdopter::moveNodeToNewDocument(Node* node, Document* oldDocument, Document* newDocument) const 116{ 117 ASSERT(!node->inDocument() || oldDocument != newDocument); 118 119 if (node->hasRareData()) { 120 NodeRareData* rareData = node->rareData(); 121 if (rareData->nodeLists()) 122 rareData->nodeLists()->adoptDocument(oldDocument, newDocument); 123 } 124 125 if (oldDocument) 126 oldDocument->moveNodeIteratorsToNewDocument(node, newDocument); 127 128 if (node->isShadowRoot()) 129 toShadowRoot(node)->setDocumentScope(newDocument); 130 131#ifndef NDEBUG 132 didMoveToNewDocumentWasCalled = false; 133 oldDocumentDidMoveToNewDocumentWasCalledWith = oldDocument; 134#endif 135 136 node->didMoveToNewDocument(oldDocument); 137 ASSERT(didMoveToNewDocumentWasCalled); 138} 139 140} 141