https://bugs.webkit.org/show_bug.cgi?id=76693
Reviewed by Darin Adler.
Make ShadowRoot inherit DocumentFragment so that it matches the class hierarchy of IDL in the spec.
TreeScope becomes a separated class, which is now inherited by Document and ShadowRoot using multiple-inheritance.
This patch is pre-requirement for coming IDL change.
No tests. No change in behavior.
* dom/Document.cpp:
(WebCore::Document::Document):
(WebCore::Document::~Document):
(WebCore::Document::buildAccessKeyMap):
(WebCore::Document::childrenChanged):
(WebCore::Document::attach):
(WebCore::Document::detach):
* dom/Document.h:
(Document):
* dom/DocumentFragment.cpp:
(WebCore::DocumentFragment::DocumentFragment):
* dom/DocumentFragment.h:
(DocumentFragment):
* dom/DocumentOrderedMap.cpp:
(WebCore::DocumentOrderedMap::get):
* dom/ShadowRoot.cpp:
(WebCore::ShadowRoot::ShadowRoot):
(WebCore::ShadowRoot::~ShadowRoot):
(WebCore::ShadowRoot::attach):
* dom/ShadowRoot.h:
* dom/TreeScope.cpp:
(WebCore::TreeScope::TreeScope):
(WebCore::TreeScope::~TreeScope):
(WebCore::TreeScope::setParentTreeScope):
(WebCore::TreeScope::getImageMap):
(WebCore::TreeScope::findAnchor):
* dom/TreeScope.h:
(WebCore):
(WebCore::TreeScope::rootNode):
(TreeScope):
* dom/TreeScopeAdopter.cpp:
(WebCore::TreeScopeAdopter::moveTreeToNewScope):
* page/DragController.cpp:
(WebCore::asFileInput):
* page/FocusController.cpp:
(WebCore::ownerOfTreeScope):
(WebCore::FocusController::nextFocusableNode):
(WebCore::FocusController::previousFocusableNode):
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@106530
268f45cc-cd09-0410-ab3c-
d52691b4dbfc
+2012-02-01 Hayato Ito <hayato@chromium.org>
+
+ Change class hierarycy so that ShadowRoot can inherit DocumentFragment.
+ https://bugs.webkit.org/show_bug.cgi?id=76693
+
+ Reviewed by Darin Adler.
+
+ Make ShadowRoot inherit DocumentFragment so that it matches the class hierarchy of IDL in the spec.
+ TreeScope becomes a separated class, which is now inherited by Document and ShadowRoot using multiple-inheritance.
+ This patch is pre-requirement for coming IDL change.
+
+ No tests. No change in behavior.
+
+ * dom/Document.cpp:
+ (WebCore::Document::Document):
+ (WebCore::Document::~Document):
+ (WebCore::Document::buildAccessKeyMap):
+ (WebCore::Document::childrenChanged):
+ (WebCore::Document::attach):
+ (WebCore::Document::detach):
+ * dom/Document.h:
+ (Document):
+ * dom/DocumentFragment.cpp:
+ (WebCore::DocumentFragment::DocumentFragment):
+ * dom/DocumentFragment.h:
+ (DocumentFragment):
+ * dom/DocumentOrderedMap.cpp:
+ (WebCore::DocumentOrderedMap::get):
+ * dom/ShadowRoot.cpp:
+ (WebCore::ShadowRoot::ShadowRoot):
+ (WebCore::ShadowRoot::~ShadowRoot):
+ (WebCore::ShadowRoot::attach):
+ * dom/ShadowRoot.h:
+ * dom/TreeScope.cpp:
+ (WebCore::TreeScope::TreeScope):
+ (WebCore::TreeScope::~TreeScope):
+ (WebCore::TreeScope::setParentTreeScope):
+ (WebCore::TreeScope::getImageMap):
+ (WebCore::TreeScope::findAnchor):
+ * dom/TreeScope.h:
+ (WebCore):
+ (WebCore::TreeScope::rootNode):
+ (TreeScope):
+ * dom/TreeScopeAdopter.cpp:
+ (WebCore::TreeScopeAdopter::moveTreeToNewScope):
+ * page/DragController.cpp:
+ (WebCore::asFileInput):
+ * page/FocusController.cpp:
+ (WebCore::ownerOfTreeScope):
+ (WebCore::FocusController::nextFocusableNode):
+ (WebCore::FocusController::previousFocusableNode):
+
2012-02-01 Benjamin Poulain <bpoulain@apple.com>
WorkerScriptController::evaluate() should not return anything
uint64_t Document::s_globalTreeVersion = 0;
Document::Document(Frame* frame, const KURL& url, bool isXHTML, bool isHTML)
- : TreeScope(0)
+ : ContainerNode(0)
+ , TreeScope(this)
, m_guardRefCount(0)
, m_compatibilityMode(NoQuirksMode)
, m_compatibilityModeLocked(false)
if (m_mediaQueryMatcher)
m_mediaQueryMatcher->documentDestroyed();
+
+ // We must call clearRareData() here since a Document class inherits TreeScope
+ // as well as Node. See a comment on TreeScope.h for the reason.
+ if (hasRareData())
+ clearRareData();
}
void Document::removedLastRef()
return m_elementsByAccessKey.get(key.impl());
}
-void Document::buildAccessKeyMap(TreeScope* root)
+void Document::buildAccessKeyMap(TreeScope* scope)
{
- for (Node* n = root; n; n = n->traverseNextNode(root)) {
- if (!n->isElementNode())
+ ASSERT(scope);
+ Node* rootNode = scope->rootNode();
+ for (Node* node = rootNode; node; node = node->traverseNextNode(rootNode)) {
+ if (!node->isElementNode())
continue;
- Element* element = static_cast<Element*>(n);
+ Element* element = static_cast<Element*>(node);
const AtomicString& accessKey = element->getAttribute(accesskeyAttr);
if (!accessKey.isEmpty())
m_elementsByAccessKey.set(accessKey.impl(), element);
- buildAccessKeyMap(element->shadowRoot());
+ if (ShadowRoot* shadowRoot = element->shadowRoot())
+ buildAccessKeyMap(shadowRoot);
}
}
void Document::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta)
{
- TreeScope::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta);
+ ContainerNode::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta);
Element* newDocumentElement = firstElementChild(this);
if (newDocumentElement == m_documentElement)
RenderObject* render = renderer();
setRenderer(0);
- TreeScope::attach();
+ ContainerNode::attach();
setRenderer(render);
}
m_focusedNode = 0;
m_activeNode = 0;
- TreeScope::detach();
+ ContainerNode::detach();
unscheduleStyleRecalc();
#include "CheckedRadioButtons.h"
#include "CollectionType.h"
#include "Color.h"
+#include "ContainerNode.h"
#include "DOMTimeStamp.h"
#include "DocumentEventQueue.h"
#include "DocumentTiming.h"
enum StyleSelectorUpdateFlag { RecalcStyleImmediately, DeferRecalcStyle, RecalcStyleIfNeeded };
-class Document : public TreeScope, public ScriptExecutionContext {
+class Document : public ContainerNode, public TreeScope, public ScriptExecutionContext {
public:
static PassRefPtr<Document> create(Frame* frame, const KURL& url)
{
MediaQueryMatcher* mediaQueryMatcher();
- using TreeScope::ref;
- using TreeScope::deref;
+ using ContainerNode::ref;
+ using ContainerNode::deref;
// Nodes belonging to this document hold guard references -
// these are enough to keep the document from being destroyed, but
namespace WebCore {
-DocumentFragment::DocumentFragment(Document* document)
- : ContainerNode(document)
+DocumentFragment::DocumentFragment(Document* document, ConstructionType constructionType)
+ : ContainerNode(document, constructionType)
{
ASSERT(document);
}
virtual bool canContainRangeEndPoint() const { return true; }
protected:
- DocumentFragment(Document*);
+ DocumentFragment(Document*, ConstructionType = CreateContainer);
virtual String nodeName() const;
private:
inline Element* DocumentOrderedMap::get(AtomicStringImpl* key, const TreeScope* scope) const
{
ASSERT(key);
+ ASSERT(scope);
m_map.checkConsistency();
if (m_duplicateCounts.contains(key)) {
// We know there's at least one node that matches; iterate to find the first one.
- for (Node* node = scope->firstChild(); node; node = node->traverseNextNode()) {
+ for (Node* node = scope->rootNode()->firstChild(); node; node = node->traverseNextNode()) {
if (!node->isElementNode())
continue;
element = static_cast<Element*>(node);
namespace WebCore {
ShadowRoot::ShadowRoot(Document* document)
- : TreeScope(document, CreateShadowRoot)
+ : DocumentFragment(document, CreateShadowRoot)
+ , TreeScope(this)
, m_applyAuthorSheets(false)
, m_needsRecalculateContent(false)
{
ShadowRoot::~ShadowRoot()
{
+ // We must call clearRareData() here since a ShadowRoot class inherits TreeScope
+ // as well as Node. See a comment on TreeScope.h for the reason.
+ if (hasRareData())
+ clearRareData();
}
PassRefPtr<ShadowRoot> ShadowRoot::create(Element* element, ExceptionCode& ec)
// ensureInclusions(), and here we just ensure that
// it is in clean state.
ASSERT(!m_inclusions || !m_inclusions->hasCandidates());
- TreeScope::attach();
+ DocumentFragment::attach();
if (m_inclusions)
m_inclusions->didSelect();
}
#ifndef ShadowRoot_h
#define ShadowRoot_h
+#include "DocumentFragment.h"
#include "ExceptionCode.h"
#include "TreeScope.h"
class Document;
class HTMLContentElement;
-class ShadowRoot : public TreeScope {
+class ShadowRoot : public DocumentFragment, public TreeScope {
public:
static PassRefPtr<ShadowRoot> create(Document*);
static PassRefPtr<ShadowRoot> create(Element*, ExceptionCode&);
#include "config.h"
#include "TreeScope.h"
+#include "ContainerNode.h"
+#include "Document.h"
#include "Element.h"
#include "HTMLAnchorElement.h"
#include "HTMLMapElement.h"
#include "HTMLNames.h"
-#include "NodeRareData.h"
#include "TreeScopeAdopter.h"
+#include <wtf/text/AtomicString.h>
+#include <wtf/text/CString.h>
namespace WebCore {
using namespace HTMLNames;
-TreeScope::TreeScope(Document* document, ConstructionType constructionType)
- : ContainerNode(document, constructionType)
+TreeScope::TreeScope(ContainerNode* rootNode)
+ : m_rootNode(rootNode)
, m_parentTreeScope(0)
, m_numNodeListCaches(0)
{
+ ASSERT(rootNode);
}
TreeScope::~TreeScope()
{
- if (hasRareData())
- clearRareData();
}
void TreeScope::destroyTreeScopeData()
void TreeScope::setParentTreeScope(TreeScope* newParentScope)
{
// A document node cannot be re-parented.
- ASSERT(!isDocumentNode());
+ ASSERT(!rootNode()->isDocumentNode());
// Every scope other than document needs a parent scope.
ASSERT(newParentScope);
return 0;
size_t hashPos = url.find('#');
String name = (hashPos == notFound ? url : url.substring(hashPos + 1)).impl();
- if (document()->isHTMLDocument())
+ if (rootNode()->document()->isHTMLDocument())
return static_cast<HTMLMapElement*>(m_imageMapsByName.getElementByLowercasedMapName(AtomicString(name.lower()).impl(), this));
return static_cast<HTMLMapElement*>(m_imageMapsByName.getElementByMapName(AtomicString(name).impl(), this));
}
return 0;
if (Element* element = getElementById(name))
return element;
- for (Node* node = this; node; node = node->traverseNextNode()) {
+ for (Node* node = rootNode(); node; node = node->traverseNextNode()) {
if (node->hasTagName(aTag)) {
HTMLAnchorElement* anchor = static_cast<HTMLAnchorElement*>(node);
- if (document()->inQuirksMode()) {
+ if (rootNode()->document()->inQuirksMode()) {
// Quirks mode, case insensitive comparison of names.
if (equalIgnoringCase(anchor->name(), name))
return anchor;
#ifndef TreeScope_h
#define TreeScope_h
-#include "ContainerNode.h"
#include "DocumentOrderedMap.h"
+#include <wtf/Forward.h>
+#include <wtf/text/AtomicString.h>
namespace WebCore {
+class ContainerNode;
class Element;
class HTMLMapElement;
+class Node;
-class TreeScope : public ContainerNode {
+// A class which inherits both Node and TreeScope must call clearRareData() in its destructor
+// so that the Node destructor no longer does problematic NodeList cache manipulation in
+// the destructor.
+class TreeScope {
friend class Document;
public:
// Used by the basic DOM mutation methods (e.g., appendChild()).
void adoptIfNeeded(Node*);
+ ContainerNode* rootNode() const { return m_rootNode; }
+
protected:
- TreeScope(Document*, ConstructionType = CreateContainer);
+ TreeScope(ContainerNode*);
virtual ~TreeScope();
void destroyTreeScopeData();
private:
+ ContainerNode* m_rootNode;
TreeScope* m_parentTreeScope;
DocumentOrderedMap m_elementsById;
// that element may contain stale data as changes made to it will have updated the DOMTreeVersion
// of the document it was moved to. By increasing the DOMTreeVersion of the donating document here
// we ensure that the collection cache will be invalidated as needed when the element is moved back.
- Document* oldDocument = m_oldScope ? m_oldScope->document() : 0;
- Document* newDocument = m_newScope->document();
+ Document* oldDocument = m_oldScope ? m_oldScope->rootNode()->document() : 0;
+ Document* newDocument = m_newScope->rootNode()->document();
bool willMoveToNewDocument = oldDocument != newDocument;
if (oldDocument && willMoveToNewDocument)
oldDocument->incDOMTreeVersion();
HTMLInputElement* inputElement = node->toInputElement();
// If this is a button inside of the a file input, move up to the file input.
- if (inputElement && inputElement->isTextButton() && inputElement->treeScope()->isShadowRoot())
- inputElement = inputElement->treeScope()->shadowHost()->toInputElement();
+ if (inputElement && inputElement->isTextButton() && inputElement->treeScope()->rootNode()->isShadowRoot())
+ inputElement = inputElement->treeScope()->rootNode()->shadowHost()->toInputElement();
return inputElement && inputElement->isFileUpload() ? inputElement : 0;
}
static inline Node* ownerOfTreeScope(TreeScope* scope)
{
ASSERT(scope);
- if (scope->isShadowRoot())
- return scope->shadowHost();
- if (scope->document()->frame())
- return scope->document()->frame()->ownerElement();
+ if (scope->rootNode()->isShadowRoot())
+ return scope->rootNode()->shadowHost();
+ if (scope->rootNode()->document()->frame())
+ return scope->rootNode()->document()->frame()->ownerElement();
return 0;
}
// Look for the first node in the scope that:
// 1) has the lowest tabindex that is higher than start's tabindex (or 0, if start is null), and
// 2) comes first in the scope, if there's a tie.
- if (Node* winner = nextNodeWithGreaterTabIndex(scope, start ? start->tabIndex() : 0, event))
+ if (Node* winner = nextNodeWithGreaterTabIndex(scope->rootNode(), start ? start->tabIndex() : 0, event))
return winner;
// There are no nodes with a tabindex greater than start's tabindex,
// so find the first node with a tabindex of 0.
- return nextNodeWithExactTabIndex(scope, 0, event);
+ return nextNodeWithExactTabIndex(scope->rootNode(), 0, event);
}
Node* FocusController::previousFocusableNode(TreeScope* scope, Node* start, KeyboardEvent* event)
{
Node* last;
- for (last = scope; last->lastChild(); last = last->lastChild()) { }
+ for (last = scope->rootNode(); last->lastChild(); last = last->lastChild()) { }
// First try to find the last node in the scope that comes before start and has the same tabindex as start.
// If start is null, find the last node in the scope with a tabindex of 0.