Skip to content

Commit 3ee4a37

Browse files
author
Roland Steiner
committed
2011-04-15 Roland Steiner <rolandsteiner@chromium.org>
Reviewed by Dimitri Glazkov. Bug 52963 - Enable O(1) access to root from any node in shadow DOM subtree https://bugs.webkit.org/show_bug.cgi?id=52963 .) Change base class of ShadowRoot from DocumentFragment to TreeScope. .) Re-enable tree scope handling in Node (had ASSERT_NOT_REACHED, etc.). .) Merged setTreeScope() with setTreeScopeRecursively() .) Call setTreeScopeRecursively in DOM manipulation functions where applicable. No new tests. (refactoring) * dom/ContainerNode.cpp: (WebCore::ContainerNode::takeAllChildrenFrom): (WebCore::ContainerNode::removeBetween): (WebCore::ContainerNode::removeChildren): (WebCore::ContainerNode::parserAddChild): * dom/Document.cpp: (WebCore::Document::Document): (WebCore::Document::~Document): (WebCore::Document::setDocType): * dom/Element.h: * dom/Node.cpp: (WebCore::Node::treeScope): (WebCore::Node::setTreeScopeRecursively): * dom/Node.h: (WebCore::Node::document): * dom/ShadowRoot.cpp: (WebCore::ShadowRoot::ShadowRoot): (WebCore::ShadowRoot::~ShadowRoot): (WebCore::ShadowRoot::nodeType): (WebCore::ShadowRoot::cloneNode): (WebCore::ShadowRoot::childTypeAllowed): * dom/ShadowRoot.h: (WebCore::toShadowRoot): * dom/TreeScope.cpp: (WebCore::TreeScope::TreeScope): (WebCore::TreeScope::setParentTreeScope): * dom/TreeScope.h: * rendering/RenderSlider.cpp: Canonical link: https://commits.webkit.org/73791@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@84050 268f45cc-cd09-0410-ab3c-d52691b4dbfc
1 parent add2b39 commit 3ee4a37

11 files changed

Lines changed: 149 additions & 54 deletions

File tree

Source/WebCore/ChangeLog

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,46 @@
1+
2011-04-15 Roland Steiner <rolandsteiner@chromium.org>
2+
3+
Reviewed by Dimitri Glazkov.
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. (refactoring)
14+
15+
* dom/ContainerNode.cpp:
16+
(WebCore::ContainerNode::takeAllChildrenFrom):
17+
(WebCore::ContainerNode::removeBetween):
18+
(WebCore::ContainerNode::removeChildren):
19+
(WebCore::ContainerNode::parserAddChild):
20+
* dom/Document.cpp:
21+
(WebCore::Document::Document):
22+
(WebCore::Document::~Document):
23+
(WebCore::Document::setDocType):
24+
* dom/Element.h:
25+
* dom/Node.cpp:
26+
(WebCore::Node::treeScope):
27+
(WebCore::Node::setTreeScopeRecursively):
28+
* dom/Node.h:
29+
(WebCore::Node::document):
30+
* dom/ShadowRoot.cpp:
31+
(WebCore::ShadowRoot::ShadowRoot):
32+
(WebCore::ShadowRoot::~ShadowRoot):
33+
(WebCore::ShadowRoot::nodeType):
34+
(WebCore::ShadowRoot::cloneNode):
35+
(WebCore::ShadowRoot::childTypeAllowed):
36+
* dom/ShadowRoot.h:
37+
(WebCore::toShadowRoot):
38+
* dom/TreeScope.cpp:
39+
(WebCore::TreeScope::TreeScope):
40+
(WebCore::TreeScope::setParentTreeScope):
41+
* dom/TreeScope.h:
42+
* rendering/RenderSlider.cpp:
43+
144
2011-04-15 Geoffrey Garen <ggaren@apple.com>
245

346
Reviewed by Oliver Hunt.

Source/WebCore/dom/ContainerNode.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,10 @@ void ContainerNode::takeAllChildrenFrom(ContainerNode* oldParent)
9090
RefPtr<Node> child = document()->adoptNode(children[i].release(), ec);
9191
ASSERT(!ec);
9292
parserAddChild(child.get());
93+
// FIXME: Together with adoptNode above, the tree scope might get updated recursively twice
94+
// (if the document changed or oldParent was in a shadow tree, AND *this is in a shadow tree).
95+
// Can we do better?
96+
child->setTreeScopeRecursively(treeScope());
9397
if (attached() && !child->attached())
9498
child->attach();
9599
}
@@ -481,6 +485,8 @@ void ContainerNode::removeBetween(Node* previousChild, Node* nextChild, Node* ol
481485
oldChild->setNextSibling(0);
482486
oldChild->setParent(0);
483487

488+
oldChild->setTreeScopeRecursively(document());
489+
484490
allowEventDispatch();
485491
}
486492

@@ -530,6 +536,7 @@ void ContainerNode::removeChildren()
530536
n->setPreviousSibling(0);
531537
n->setNextSibling(0);
532538
n->setParent(0);
539+
n->setTreeScopeRecursively(document());
533540

534541
m_firstChild = next;
535542
if (n == m_lastChild)
@@ -648,6 +655,8 @@ void ContainerNode::parserAddChild(PassRefPtr<Node> newChild)
648655
Node* last = m_lastChild;
649656
// FIXME: This method should take a PassRefPtr.
650657
appendChildToContainer<Node, ContainerNode>(newChild.get(), this);
658+
newChild->setTreeScopeRecursively(treeScope());
659+
651660
allowEventDispatch();
652661

653662
// FIXME: Why doesn't this use notifyChildInserted(newChild) instead?

Source/WebCore/dom/Document.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -377,7 +377,7 @@ class DocumentWeakReference : public ThreadSafeRefCounted<DocumentWeakReference>
377377
uint64_t Document::s_globalTreeVersion = 0;
378378

379379
Document::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)
@@ -434,6 +434,7 @@ Document::Document(Frame* frame, const KURL& url, bool isXHTML, bool isHTML)
434434
, m_writeRecursionIsTooDeep(false)
435435
, m_writeRecursionDepth(0)
436436
{
437+
437438
m_document = this;
438439

439440
m_pageGroupUserSheetCacheValid = false;
@@ -514,6 +515,7 @@ Document::~Document()
514515
ASSERT(m_ranges.isEmpty());
515516
ASSERT(!m_styleRecalcTimer.isActive());
516517
ASSERT(!m_parentTreeScope);
518+
ASSERT(!m_guardRefCount);
517519

518520
m_scriptRunner.clear();
519521

@@ -665,7 +667,7 @@ void Document::setDocType(PassRefPtr<DocumentType> docType)
665667
ASSERT(!m_docType || !docType);
666668
m_docType = docType;
667669
if (m_docType)
668-
m_docType->setTreeScope(this);
670+
m_docType->setTreeScopeRecursively(this);
669671
}
670672

671673
DOMImplementation* Document::implementation()

Source/WebCore/dom/Element.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ class DOMStringMap;
3939
class DOMTokenList;
4040
class ElementRareData;
4141
class IntSize;
42+
class ShadowRoot;
4243
class WebKitAnimationList;
4344

4445
enum SpellcheckAttributeState {
@@ -229,6 +230,7 @@ class Element : public ContainerNode {
229230
virtual RenderObject* createRenderer(RenderArena*, RenderStyle*);
230231
virtual void recalcStyle(StyleChange = NoChange);
231232

233+
// FIXME: Make these return a proper ShadowRoot* (bug 58703).
232234
ContainerNode* shadowRoot() const;
233235
ContainerNode* ensureShadowRoot();
234236
void removeShadowRoot();

Source/WebCore/dom/Node.cpp

Lines changed: 29 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@
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"
@@ -468,39 +469,22 @@ void Node::setDocument(Document* document)
468469

469470
TreeScope* Node::treeScope() const
470471
{
472+
// FIXME: Using m_document directly is not good -> see comment with document() in the header file.
471473
if (!hasRareData())
472-
return document();
474+
return m_document;
473475
TreeScope* scope = rareData()->treeScope();
474-
// FIXME: Until we land shadow scopes, there should be no non-document scopes.
475-
ASSERT(!scope);
476-
return scope ? scope : document();
476+
return scope ? scope : m_document;
477477
}
478478

479-
void Node::setTreeScope(TreeScope* newTreeScope)
479+
void Node::setTreeScopeRecursively(TreeScope* newTreeScope, bool includeRoot)
480480
{
481-
ASSERT(!isDocumentNode());
481+
ASSERT(this);
482+
ASSERT(!includeRoot || !isDocumentNode());
482483
ASSERT(newTreeScope);
483-
ASSERT(!inDocument() || treeScope() == newTreeScope);
484+
ASSERT(!m_deletionHasBegun);
484485

485-
if (newTreeScope->isDocumentNode()) {
486-
if (hasRareData())
487-
rareData()->setTreeScope(0);
488-
// Setting the new document scope will be handled implicitly
489-
// by setDocument() below.
490-
} else {
491-
// FIXME: Until we land shadow scopes, this branch should be inert.
492-
ASSERT_NOT_REACHED();
493-
ensureRareData()->setTreeScope(newTreeScope);
494-
}
495-
496-
setDocument(newTreeScope->document());
497-
}
498-
499-
void Node::setTreeScopeRecursively(TreeScope* newTreeScope)
500-
{
501-
ASSERT(!isDocumentNode());
502-
ASSERT(newTreeScope);
503-
if (treeScope() == newTreeScope)
486+
TreeScope* currentTreeScope = treeScope();
487+
if (currentTreeScope == newTreeScope)
504488
return;
505489

506490
Document* currentDocument = document();
@@ -512,9 +496,25 @@ void Node::setTreeScopeRecursively(TreeScope* newTreeScope)
512496
if (currentDocument && currentDocument != newDocument)
513497
currentDocument->incDOMTreeVersion();
514498

515-
for (Node* node = this; node; node = node->traverseNextNode(this)) {
516-
node->setTreeScope(newTreeScope);
517-
// FIXME: Once shadow scopes are landed, update parent scope, etc.
499+
for (Node* node = includeRoot ? this : traverseNextNode(this); node; node = node->traverseNextNode(this)) {
500+
if (newTreeScope == newDocument) {
501+
if (node->hasRareData())
502+
node->rareData()->setTreeScope(0);
503+
// Setting the new document tree scope will be handled implicitly
504+
// by setDocument() below.
505+
} else
506+
node->ensureRareData()->setTreeScope(newTreeScope);
507+
508+
node->setDocument(newDocument);
509+
510+
if (!node->isElementNode())
511+
continue;
512+
// FIXME: Remove toShadowRoot() once shadowRoot() returns a proper ShadowRoot* (bug 58703).
513+
if (ShadowRoot* shadowRoot = toShadowRoot(toElement(node)->shadowRoot())) {
514+
shadowRoot->setParentTreeScope(newTreeScope);
515+
if (currentDocument != newDocument)
516+
shadowRoot->setDocumentRecursively(newDocument);
517+
}
518518
}
519519
}
520520

Source/WebCore/dom/Node.h

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -352,18 +352,16 @@ class Node : public EventTarget, public TreeShared<ContainerNode>, public Script
352352
Document* document() const
353353
{
354354
ASSERT(this);
355+
// FIXME: below ASSERT is useful, but prevents the use of document() in the constructor or destructor
356+
// due to the virtual function call to nodeType().
355357
ASSERT(m_document || (nodeType() == DOCUMENT_TYPE_NODE && !inDocument()));
356358
return m_document;
357359
}
358360

359361
TreeScope* treeScope() const;
360362

361-
// Do not use this method to change the scope of a node until after the node has been
362-
// removed from its previous scope. Do not use to change documents.
363-
void setTreeScope(TreeScope*);
364-
365363
// Used by the basic DOM methods (e.g., appendChild()).
366-
void setTreeScopeRecursively(TreeScope*);
364+
void setTreeScopeRecursively(TreeScope*, bool includeRoot = true);
367365

368366
// Returns true if this node is associated with a document and is in its associated document's
369367
// node tree, false otherwise.

Source/WebCore/dom/ShadowRoot.cpp

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,19 +27,59 @@
2727
#include "config.h"
2828
#include "ShadowRoot.h"
2929

30+
#include "Document.h"
31+
#include "NodeRareData.h"
32+
3033
namespace WebCore {
3134

3235
ShadowRoot::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+
47+
ShadowRoot::~ShadowRoot()
48+
{
3649
}
3750

3851
String ShadowRoot::nodeName() const
3952
{
4053
return "#shadow-root";
4154
}
4255

56+
Node::NodeType ShadowRoot::nodeType() const
57+
{
58+
// FIXME: Decide correct node type (bug 58704).
59+
return DOCUMENT_FRAGMENT_NODE;
60+
}
61+
62+
PassRefPtr<Node> ShadowRoot::cloneNode(bool)
63+
{
64+
// ShadowRoot should not be arbitrarily cloned.
65+
return 0;
66+
}
67+
68+
bool ShadowRoot::childTypeAllowed(NodeType type) const
69+
{
70+
switch (type) {
71+
case ELEMENT_NODE:
72+
case PROCESSING_INSTRUCTION_NODE:
73+
case COMMENT_NODE:
74+
case TEXT_NODE:
75+
case CDATA_SECTION_NODE:
76+
case ENTITY_REFERENCE_NODE:
77+
return true;
78+
default:
79+
return false;
80+
}
81+
}
82+
4383
void ShadowRoot::recalcStyle(StyleChange change)
4484
{
4585
for (Node* n = firstChild(); n; n = n->nextSibling())

Source/WebCore/dom/ShadowRoot.h

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,13 @@
2727
#ifndef ShadowRoot_h
2828
#define ShadowRoot_h
2929

30-
#include "DocumentFragment.h"
30+
#include "TreeScope.h"
3131

3232
namespace WebCore {
3333

3434
class Document;
3535

36-
class ShadowRoot : public DocumentFragment {
36+
class ShadowRoot : public TreeScope {
3737
public:
3838
static PassRefPtr<ShadowRoot> create(Document*);
3939

@@ -42,14 +42,25 @@ class ShadowRoot : public DocumentFragment {
4242

4343
private:
4444
ShadowRoot(Document*);
45+
virtual ~ShadowRoot();
46+
4547
virtual String nodeName() const;
48+
virtual NodeType nodeType() const;
49+
virtual PassRefPtr<Node> cloneNode(bool deep);
50+
virtual bool childTypeAllowed(NodeType) const;
4651
};
4752

4853
inline PassRefPtr<ShadowRoot> ShadowRoot::create(Document* document)
4954
{
5055
return adoptRef(new ShadowRoot(document));
5156
}
5257

58+
inline ShadowRoot* toShadowRoot(Node* node)
59+
{
60+
ASSERT(!node || node->isShadowBoundary());
61+
return static_cast<ShadowRoot*>(node);
62+
}
63+
5364
} // namespace
5465

5566
#endif

Source/WebCore/dom/TreeScope.cpp

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -36,19 +36,12 @@ namespace WebCore {
3636

3737
using namespace HTMLNames;
3838

39-
TreeScope::TreeScope(Document* document, ConstructionType constructionType)
40-
: ContainerNode(0, constructionType)
39+
TreeScope::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

5447
TreeScope::~TreeScope()
@@ -69,7 +62,6 @@ 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

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ class TreeScope : public ContainerNode {
3939

4040
public:
4141
TreeScope* parentTreeScope() const { return m_parentTreeScope; }
42+
void setParentTreeScope(TreeScope*);
4243

4344
Element* getElementById(const AtomicString&) const;
4445
bool hasElementWithId(AtomicStringImpl* id) const;
@@ -65,14 +66,11 @@ class TreeScope : public ContainerNode {
6566
Element* findAnchor(const String& name);
6667

6768
protected:
68-
TreeScope(Document*, ConstructionType = CreateContainer);
69-
69+
TreeScope(Document*);
7070
virtual ~TreeScope();
7171

7272
void destroyTreeScopeData();
7373

74-
void setParentTreeScope(TreeScope*);
75-
7674
private:
7775
TreeScope* m_parentTreeScope;
7876

0 commit comments

Comments
 (0)