Source/WebCore/ChangeLog

 12011-04-13 Roland Steiner <rolandsteiner@chromium.org>
 2
 3 Reviewed by NOBODY (OOPS!).
 4
 5 Bug 52963 - Enable O(1) access to root from any node in shadow DOM subtree
 6 https://bugs.webkit.org/show_bug.cgi?id=52963
 7
 8 .) Change base class of ShadowRoot from DocumentFragment to TreeScope.
 9 .) Re-enable tree scope handling in Node (had ASSERT_NOT_REACHED, etc.).
 10 .) Merged setTreeScope() with setTreeScopeRecursively()
 11 .) Call setTreeScopeRecursively in DOM manipulation functions where applicable.
 12
 13 No new tests. (No new functionality)
 14
 15 * dom/ContainerNode.cpp: call setTreeScopeRecursively() to update current containing scope
 16 (WebCore::ContainerNode::removeAllChildren):
 17 (WebCore::ContainerNode::takeAllChildrenFrom):
 18 (WebCore::ContainerNode::removeBetween):
 19 (WebCore::ContainerNode::removeChildren):
 20 (WebCore::ContainerNode::parserAddChild):
 21 * dom/Document.cpp:
 22 (WebCore::Document::Document):
 23 (WebCore::Document::~Document):
 24 (WebCore::Document::removedLastRef):
 25 (WebCore::Document::setDocType):
 26 * dom/Document.h:
 27 * dom/Element.h:
 28 * dom/Node.cpp:
 29 (WebCore::Node::treeScope):
 30 (WebCore::Node::setTreeScopeRecursively): merge setTreeScope()
 31 * dom/Node.h:
 32 (WebCore::Node::document):
 33 * dom/ShadowRoot.cpp:
 34 (WebCore::ShadowRoot::ShadowRoot):
 35 (WebCore::ShadowRoot::~ShadowRoot):
 36 (WebCore::ShadowRoot::nodeName):
 37 (WebCore::ShadowRoot::nodeType):
 38 (WebCore::ShadowRoot::cloneNode):
 39 (WebCore::ShadowRoot::childTypeAllowed):
 40 * dom/ShadowRoot.h:
 41 (WebCore::toShadowRoot):
 42 * dom/TreeScope.cpp:
 43 (WebCore::TreeScope::TreeScope):
 44 (WebCore::TreeScope::setParentTreeScope):
 45 * dom/TreeScope.h:
 46 * rendering/RenderSlider.cpp:
 47
1482011-04-12 Pavel Podivilov <podivilov@chromium.org>
249
350 Reviewed by Pavel Feldman.

Source/WebCore/dom/ContainerNode.cpp

@@static void collectTargetNodes(Node* node, NodeVector& nodes)
7373
7474void ContainerNode::removeAllChildren()
7575{
 76 // Note that we do NOT set the tree scope to document here, because this function is usu. called
 77 // when the children should be destroyed anyway. Call setTreeScopeRecursively where this is not the case.
7678 removeAllChildrenInContainer<Node, ContainerNode>(this);
7779}
7880

@@void ContainerNode::takeAllChildrenFrom(ContainerNode* oldParent)
9092 RefPtr<Node> child = document()->adoptNode(children[i].release(), ec);
9193 ASSERT(!ec);
9294 parserAddChild(child.get());
 95 // FIXME: Together with adoptNode above, the tree scope might get updated recursively twice
 96 // (if the document changed or oldParent was in a shadow tree, AND *this is in a shadow tree).
 97 // Can we do better?
 98 child->setTreeScopeRecursively(treeScope());
9399 if (attached() && !child->attached())
94100 child->attach();
95101 }

@@void ContainerNode::removeBetween(Node* previousChild, Node* nextChild, Node* ol
481487 oldChild->setNextSibling(0);
482488 oldChild->setParent(0);
483489
 490 oldChild->setTreeScopeRecursively(document());
 491
484492 allowEventDispatch();
485493}
486494

@@void ContainerNode::removeChildren()
530538 n->setPreviousSibling(0);
531539 n->setNextSibling(0);
532540 n->setParent(0);
 541 n->setTreeScopeRecursively(document());
533542
534543 m_firstChild = next;
535544 if (n == m_lastChild)

@@void ContainerNode::parserAddChild(PassRefPtr<Node> newChild)
648657 Node* last = m_lastChild;
649658 // FIXME: This method should take a PassRefPtr.
650659 appendChildToContainer<Node, ContainerNode>(newChild.get(), this);
 660 newChild->setTreeScopeRecursively(treeScope());
 661
651662 allowEventDispatch();
652663
653664 // FIXME: Why doesn't this use notifyChildInserted(newChild) instead?

Source/WebCore/dom/Document.cpp

@@private:
377377uint64_t Document::s_globalTreeVersion = 0;
378378
379379Document::Document(Frame* frame, const KURL& url, bool isXHTML, bool isHTML)
380  : TreeScope(this)
 380 : TreeScope(0)
381381 , m_guardRefCount(0)
382382 , m_compatibilityMode(NoQuirksMode)
383383 , m_compatibilityModeLocked(false)

@@Document::Document(Frame* frame, const KURL& url, bool isXHTML, bool isHTML)
436436 , m_writingModeSetOnDocumentElement(false)
437437 , m_writeRecursionIsTooDeep(false)
438438 , m_writeRecursionDepth(0)
 439#ifndef NDEBUG
 440 , m_tearDownHasBegun(false)
 441#endif
439442{
 443
440444 m_document = this;
441445
442446 m_pageGroupUserSheetCacheValid = false;

@@Document::Document(Frame* frame, const KURL& url, bool isXHTML, bool isHTML)
511515
512516Document::~Document()
513517{
 518 ASSERT(m_tearDownHasBegun);
514519 ASSERT(!renderer());
515520 ASSERT(!m_inPageCache);
516521 ASSERT(!m_savedRenderer);
517522 ASSERT(m_ranges.isEmpty());
518523 ASSERT(!m_styleRecalcTimer.isActive());
519524 ASSERT(!m_parentTreeScope);
 525 ASSERT(m_guardRefCount == 0);
520526
521527 m_scriptRunner.clear();
522528

@@Document::~Document()
572578void Document::removedLastRef()
573579{
574580 ASSERT(!m_deletionHasBegun);
 581 ASSERT(!m_tearDownHasBegun);
 582#ifndef NDEBUG
 583 m_tearDownHasBegun = true;
 584#endif
575585 if (m_guardRefCount) {
576586 // If removing a child removes the last self-only ref, we don't
577587 // want the scope to be destructed until after

@@void Document::removedLastRef()
596606 destroyTreeScopeData();
597607 removeAllChildren();
598608
 609 ASSERT(m_markers);
599610 m_markers->detach();
 611 m_markers = 0;
600612
601613 detachParser();
602614

@@void Document::setDocType(PassRefPtr<DocumentType> docType)
701713 ASSERT(!m_docType || !docType);
702714 m_docType = docType;
703715 if (m_docType)
704  m_docType->setTreeScope(this);
 716 m_docType->setTreeScopeRecursively(this);
705717}
706718
707719DOMImplementation* Document::implementation()

Source/WebCore/dom/Document.h

@@private:
14081408#endif
14091409
14101410 RefPtr<ContentSecurityPolicy> m_contentSecurityPolicy;
 1411
 1412#ifndef NDEBUG
 1413 bool m_tearDownHasBegun;
 1414#endif
14111415};
14121416
14131417// Put these methods here, because they require the Document definition, but we really want to inline them.

Source/WebCore/dom/Element.h

@@class DOMStringMap;
3939class DOMTokenList;
4040class ElementRareData;
4141class IntSize;
 42class ShadowRoot;
4243class WebKitAnimationList;
4344
4445enum SpellcheckAttributeState {

@@public:
229230 virtual RenderObject* createRenderer(RenderArena*, RenderStyle*);
230231 virtual void recalcStyle(StyleChange = NoChange);
231232
 233 // FIXME: Make these return a proper ShadowRoot* (requires changes wrt. WebDOMOperations.h).
232234 ContainerNode* shadowRoot() const;
233235 ContainerNode* ensureShadowRoot();
234236 void removeShadowRoot();

Source/WebCore/dom/Node.cpp

7777#include "ScopedEventQueue.h"
7878#include "ScriptController.h"
7979#include "SelectorNodeList.h"
 80#include "ShadowRoot.h"
8081#include "StaticNodeList.h"
8182#include "TagNodeList.h"
8283#include "Text.h"

@@void Node::setDocument(Document* document)
472473
473474TreeScope* Node::treeScope() const
474475{
 476 // FIXME: Using m_document directly is not good -> see comment with document() in the header file.
475477 if (!hasRareData())
476  return document();
 478 return m_document;
477479 TreeScope* scope = rareData()->treeScope();
478  // FIXME: Until we land shadow scopes, there should be no non-document scopes.
479  ASSERT(!scope);
480  return scope ? scope : document();
 480 return scope ? scope : m_document;
481481}
482482
483 void Node::setTreeScope(TreeScope* newTreeScope)
 483void Node::setTreeScopeRecursively(TreeScope* newTreeScope, bool includeRoot)
484484{
485  ASSERT(!isDocumentNode());
 485 ASSERT(this);
 486 ASSERT(!includeRoot || !isDocumentNode());
486487 ASSERT(newTreeScope);
487  ASSERT(!inDocument() || treeScope() == newTreeScope);
 488 ASSERT(!m_deletionHasBegun);
488489
489  if (newTreeScope->isDocumentNode()) {
490  if (hasRareData())
491  rareData()->setTreeScope(0);
492  // Setting the new document scope will be handled implicitly
493  // by setDocument() below.
494  } else {
495  // FIXME: Until we land shadow scopes, this branch should be inert.
496  ASSERT_NOT_REACHED();
497  ensureRareData()->setTreeScope(newTreeScope);
498  }
499 
500  setDocument(newTreeScope->document());
501 }
502 
503 void Node::setTreeScopeRecursively(TreeScope* newTreeScope)
504 {
505  ASSERT(!isDocumentNode());
506  ASSERT(newTreeScope);
507  if (treeScope() == newTreeScope)
 490 TreeScope* currentTreeScope = treeScope();
 491 if (currentTreeScope == newTreeScope)
508492 return;
509493
510494 Document* currentDocument = document();

@@void Node::setTreeScopeRecursively(TreeScope* newTreeScope)
516500 if (currentDocument && currentDocument != newDocument)
517501 currentDocument->incDOMTreeVersion();
518502
519  for (Node* node = this; node; node = node->traverseNextNode(this)) {
520  node->setTreeScope(newTreeScope);
521  // FIXME: Once shadow scopes are landed, update parent scope, etc.
 503 for (Node* node = includeRoot ? this : traverseNextNode(this); node; node = node->traverseNextNode(this)) {
 504 if (newTreeScope == newDocument) {
 505 if (node->hasRareData())
 506 node->rareData()->setTreeScope(0);
 507 // Setting the new document tree scope will be handled implicitly
 508 // by setDocument() below.
 509 } else {
 510 node->ensureRareData()->setTreeScope(newTreeScope);
 511 }
 512
 513 node->setDocument(newDocument);
 514
 515 if (!node->isElementNode())
 516 continue;
 517 // FIXME: Remove toShadowRoot() once shadowRoot() returns a proper ShadowRoot*.
 518 if (ShadowRoot* shadowRoot = toShadowRoot(toElement(node)->shadowRoot())) {
 519 shadowRoot->setParentTreeScope(newTreeScope);
 520 if (currentDocument != newDocument)
 521 shadowRoot->setDocumentRecursively(newDocument);
 522 }
522523 }
523524}
524525

Source/WebCore/dom/Node.h

@@public:
350350 Document* document() const
351351 {
352352 ASSERT(this);
 353 // FIXME: below ASSERT is useful, but prevents the use of document() in the constructor or destructor
 354 // due to the virtual function call to nodeType().
353355 ASSERT(m_document || (nodeType() == DOCUMENT_TYPE_NODE && !inDocument()));
354356 return m_document;
355357 }
356358
357359 TreeScope* treeScope() const;
358360
359  // Do not use this method to change the scope of a node until after the node has been
360  // removed from its previous scope. Do not use to change documents.
361  void setTreeScope(TreeScope*);
362 
363361 // Used by the basic DOM methods (e.g., appendChild()).
364  void setTreeScopeRecursively(TreeScope*);
 362 void setTreeScopeRecursively(TreeScope*, bool includeRoot = true);
365363
366364 // Returns true if this node is associated with a document and is in its associated document's
367365 // node tree, false otherwise.

Source/WebCore/dom/ShadowRoot.cpp

2727#include "config.h"
2828#include "ShadowRoot.h"
2929
 30#include "Document.h"
 31#include "NodeRareData.h"
 32
3033namespace WebCore {
3134
3235ShadowRoot::ShadowRoot(Document* document)
33  : DocumentFragment(document)
 36 : TreeScope(document)
3437{
3538 ASSERT(document);
 39
 40 // Assume document as parent scope.
 41 setParentTreeScope(document);
 42 // Shadow tree scopes have the scope pointer point to themselves.
 43 // This way, direct children will receive the correct scope pointer.
 44 ensureRareData()->setTreeScope(this);
 45}
 46
 47ShadowRoot::~ShadowRoot()
 48{
 49}
 50
 51String ShadowRoot::nodeName() const
 52{
 53 // FIXME: Decide correct node name.
 54 return "#shadow-root";
 55}
 56
 57Node::NodeType ShadowRoot::nodeType() const
 58{
 59 // FIXME: Decide correct node type.
 60 return DOCUMENT_FRAGMENT_NODE;
 61}
 62
 63PassRefPtr<Node> ShadowRoot::cloneNode(bool /*deep*/)
 64{
 65 // ShadowRoot should not be arbitrarily cloned.
 66 return 0;
 67}
 68
 69bool ShadowRoot::childTypeAllowed(NodeType type)
 70{
 71 switch (type) {
 72 case ELEMENT_NODE:
 73 case PROCESSING_INSTRUCTION_NODE:
 74 case COMMENT_NODE:
 75 case TEXT_NODE:
 76 case CDATA_SECTION_NODE:
 77 case ENTITY_REFERENCE_NODE:
 78 return true;
 79 default:
 80 return false;
 81 }
3682}
3783
3884void ShadowRoot::recalcStyle(StyleChange change)

Source/WebCore/dom/ShadowRoot.h

2727#ifndef ShadowRoot_h
2828#define ShadowRoot_h
2929
30 #include "DocumentFragment.h"
 30#include "TreeScope.h"
3131
3232namespace WebCore {
3333
3434class Document;
3535
36 class ShadowRoot : public DocumentFragment {
 36class ShadowRoot : public TreeScope {
3737public:
3838 static PassRefPtr<ShadowRoot> create(Document*);
3939

@@public:
4242
4343private:
4444 ShadowRoot(Document*);
 45 virtual ~ShadowRoot();
 46
 47 virtual String nodeName() const;
 48 virtual NodeType nodeType() const;
 49 virtual PassRefPtr<Node> cloneNode(bool deep);
 50 virtual bool childTypeAllowed(NodeType);
4551};
4652
4753inline PassRefPtr<ShadowRoot> ShadowRoot::create(Document* document)

@@inline PassRefPtr<ShadowRoot> ShadowRoot::create(Document* document)
4955 return adoptRef(new ShadowRoot(document));
5056}
5157
 58inline ShadowRoot* toShadowRoot(Node* node)
 59{
 60 ASSERT(!node || node->isShadowBoundary());
 61 return static_cast<ShadowRoot*>(node);
 62}
 63
 64inline const ShadowRoot* toShadowRoot(const Node* node)
 65{
 66 ASSERT(!node || node->isShadowBoundary());
 67 return static_cast<const ShadowRoot*>(node);
 68}
 69
5270} // namespace
5371
5472#endif

Source/WebCore/dom/TreeScope.cpp

@@namespace WebCore {
3636
3737using namespace HTMLNames;
3838
39 TreeScope::TreeScope(Document* document, ConstructionType constructionType)
40  : ContainerNode(0, constructionType)
 39TreeScope::TreeScope(Document* document)
 40 : ContainerNode(document)
4141 , m_parentTreeScope(0)
4242 , m_accessKeyMapValid(false)
4343 , m_numNodeListCaches(0)
4444{
45  m_document = document;
46  if (document != this) {
47  // Assume document as parent scope
48  m_parentTreeScope = document;
49  // FIXME: This branch should be inert until shadow scopes are landed.
50  ASSERT_NOT_REACHED();
51  }
5245}
5346
5447TreeScope::~TreeScope()

@@void TreeScope::setParentTreeScope(TreeScope* newParentScope)
6962 // A document node cannot be re-parented.
7063 ASSERT(!isDocumentNode());
7164 // Every scope other than document needs a parent scope.
72  ASSERT(m_parentTreeScope);
7365 ASSERT(newParentScope);
7466
7567 m_parentTreeScope = newParentScope;

Source/WebCore/dom/TreeScope.h

@@class HTMLMapElement;
3636
3737class TreeScope : public ContainerNode {
3838 friend class Document;
 39 friend class Node;
3940
4041public:
4142 TreeScope* parentTreeScope() const { return m_parentTreeScope; }

@@public:
6566 Element* findAnchor(const String& name);
6667
6768protected:
68  TreeScope(Document*, ConstructionType = CreateContainer);
 69 TreeScope(Document*);
6970
7071 virtual ~TreeScope();
7172

Source/WebCore/rendering/RenderSlider.cpp

3737#include "RenderLayer.h"
3838#include "RenderTheme.h"
3939#include "RenderView.h"
40 #include "ShadowElement.h"
 40#include "ShadowRoot.h"
4141#include "SliderThumbElement.h"
4242#include "StepRange.h"
4343#include <wtf/MathExtras.h>