2011-04-19 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.
        .) Adapt JavaScript Node wrappers (temporary code - see https://bugs.webkit.org/show_bug.cgi?id=58704).

        No new tests. (refactoring)

        * bindings/js/JSNodeCustom.cpp:
        (WebCore::createWrapperInline):
        * bindings/v8/custom/V8NodeCustom.cpp:
        (WebCore::toV8Slow):
        * 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:

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@84394 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent c8ea137e
2011-04-19 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.
.) Adapt JavaScript Node wrappers (temporary code - see https://bugs.webkit.org/show_bug.cgi?id=58704).
No new tests. (refactoring)
* bindings/js/JSNodeCustom.cpp:
(WebCore::createWrapperInline):
* bindings/v8/custom/V8NodeCustom.cpp:
(WebCore::toV8Slow):
* 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:
2011-04-20 Vsevolod Vlasov <vsevik@chromium.org>
Reviewed by Pavel Feldman.
......@@ -63,6 +63,7 @@
#include "Notation.h"
#include "ProcessingInstruction.h"
#include "RegisteredEventListener.h"
#include "ShadowRoot.h"
#include "StyleSheet.h"
#include "StyledElement.h"
#include "Text.h"
......@@ -290,7 +291,11 @@ static ALWAYS_INLINE JSValue createWrapperInline(ExecState* exec, JSDOMGlobalObj
wrapper = CREATE_DOM_NODE_WRAPPER(exec, globalObject, Notation, node);
break;
case Node::DOCUMENT_FRAGMENT_NODE:
wrapper = CREATE_DOM_NODE_WRAPPER(exec, globalObject, DocumentFragment, node);
// FIXME: remove 'if' once ShadowRoot gets its own node type (see bug 58704)
if (node->isShadowBoundary())
wrapper = CREATE_DOM_NODE_WRAPPER(exec, globalObject, Node, node);
else
wrapper = CREATE_DOM_NODE_WRAPPER(exec, globalObject, DocumentFragment, node);
break;
case Node::ENTITY_REFERENCE_NODE:
wrapper = CREATE_DOM_NODE_WRAPPER(exec, globalObject, EntityReference, node);
......
......@@ -33,6 +33,7 @@
#include "Document.h"
#include "EventListener.h"
#include "ShadowRoot.h"
#include "V8AbstractEventListener.h"
#include "V8Attr.h"
......@@ -162,6 +163,9 @@ v8::Handle<v8::Value> toV8Slow(Node* impl, bool forceNewObject)
case Node::DOCUMENT_TYPE_NODE:
return toV8(static_cast<DocumentType*>(impl), forceNewObject);
case Node::DOCUMENT_FRAGMENT_NODE:
// FIXME: remove 'if' once ShadowRoot gets its own node type (see bug 58704)
if (impl->isShadowBoundary())
return toV8(static_cast<ShadowRoot*>(impl), forceNewObject);
return toV8(static_cast<DocumentFragment*>(impl), forceNewObject);
case Node::NOTATION_NODE:
return toV8(static_cast<Notation*>(impl), forceNewObject);
......
......@@ -90,6 +90,10 @@ void ContainerNode::takeAllChildrenFrom(ContainerNode* oldParent)
RefPtr<Node> child = document()->adoptNode(children[i].release(), ec);
ASSERT(!ec);
parserAddChild(child.get());
// FIXME: Together with adoptNode above, the tree scope might get updated recursively twice
// (if the document changed or oldParent was in a shadow tree, AND *this is in a shadow tree).
// Can we do better?
child->setTreeScopeRecursively(treeScope());
if (attached() && !child->attached())
child->attach();
}
......@@ -481,6 +485,8 @@ void ContainerNode::removeBetween(Node* previousChild, Node* nextChild, Node* ol
oldChild->setNextSibling(0);
oldChild->setParent(0);
oldChild->setTreeScopeRecursively(document());
allowEventDispatch();
}
......@@ -530,6 +536,7 @@ void ContainerNode::removeChildren()
n->setPreviousSibling(0);
n->setNextSibling(0);
n->setParent(0);
n->setTreeScopeRecursively(document());
m_firstChild = next;
if (n == m_lastChild)
......@@ -648,6 +655,8 @@ void ContainerNode::parserAddChild(PassRefPtr<Node> newChild)
Node* last = m_lastChild;
// FIXME: This method should take a PassRefPtr.
appendChildToContainer<Node, ContainerNode>(newChild.get(), this);
newChild->setTreeScopeRecursively(treeScope());
allowEventDispatch();
// FIXME: Why doesn't this use notifyChildInserted(newChild) instead?
......
......@@ -377,7 +377,7 @@ private:
uint64_t Document::s_globalTreeVersion = 0;
Document::Document(Frame* frame, const KURL& url, bool isXHTML, bool isHTML)
: TreeScope(this)
: TreeScope(0)
, m_guardRefCount(0)
, m_compatibilityMode(NoQuirksMode)
, m_compatibilityModeLocked(false)
......@@ -513,6 +513,7 @@ Document::~Document()
ASSERT(m_ranges.isEmpty());
ASSERT(!m_styleRecalcTimer.isActive());
ASSERT(!m_parentTreeScope);
ASSERT(!m_guardRefCount);
m_scriptRunner.clear();
......@@ -670,7 +671,7 @@ void Document::setDocType(PassRefPtr<DocumentType> docType)
ASSERT(!m_docType || !docType);
m_docType = docType;
if (m_docType)
m_docType->setTreeScope(this);
m_docType->setTreeScopeRecursively(this);
}
DOMImplementation* Document::implementation()
......
......@@ -39,6 +39,7 @@ class DOMStringMap;
class DOMTokenList;
class ElementRareData;
class IntSize;
class ShadowRoot;
class WebKitAnimationList;
enum SpellcheckAttributeState {
......@@ -229,6 +230,7 @@ public:
virtual RenderObject* createRenderer(RenderArena*, RenderStyle*);
virtual void recalcStyle(StyleChange = NoChange);
// FIXME: Make these return a proper ShadowRoot* (bug 58703).
ContainerNode* shadowRoot() const;
ContainerNode* ensureShadowRoot();
void removeShadowRoot();
......
......@@ -76,6 +76,7 @@
#include "RenderView.h"
#include "ScopedEventQueue.h"
#include "SelectorNodeList.h"
#include "ShadowRoot.h"
#include "StaticNodeList.h"
#include "TagNodeList.h"
#include "Text.h"
......@@ -467,39 +468,22 @@ void Node::setDocument(Document* document)
TreeScope* Node::treeScope() const
{
// FIXME: Using m_document directly is not good -> see comment with document() in the header file.
if (!hasRareData())
return document();
return m_document;
TreeScope* scope = rareData()->treeScope();
// FIXME: Until we land shadow scopes, there should be no non-document scopes.
ASSERT(!scope);
return scope ? scope : document();
return scope ? scope : m_document;
}
void Node::setTreeScope(TreeScope* newTreeScope)
void Node::setTreeScopeRecursively(TreeScope* newTreeScope, bool includeRoot)
{
ASSERT(!isDocumentNode());
ASSERT(this);
ASSERT(!includeRoot || !isDocumentNode());
ASSERT(newTreeScope);
ASSERT(!inDocument() || treeScope() == newTreeScope);
ASSERT(!m_deletionHasBegun);
if (newTreeScope->isDocumentNode()) {
if (hasRareData())
rareData()->setTreeScope(0);
// Setting the new document scope will be handled implicitly
// by setDocument() below.
} else {
// FIXME: Until we land shadow scopes, this branch should be inert.
ASSERT_NOT_REACHED();
ensureRareData()->setTreeScope(newTreeScope);
}
setDocument(newTreeScope->document());
}
void Node::setTreeScopeRecursively(TreeScope* newTreeScope)
{
ASSERT(!isDocumentNode());
ASSERT(newTreeScope);
if (treeScope() == newTreeScope)
TreeScope* currentTreeScope = treeScope();
if (currentTreeScope == newTreeScope)
return;
Document* currentDocument = document();
......@@ -511,9 +495,25 @@ void Node::setTreeScopeRecursively(TreeScope* newTreeScope)
if (currentDocument && currentDocument != newDocument)
currentDocument->incDOMTreeVersion();
for (Node* node = this; node; node = node->traverseNextNode(this)) {
node->setTreeScope(newTreeScope);
// FIXME: Once shadow scopes are landed, update parent scope, etc.
for (Node* node = includeRoot ? this : traverseNextNode(this); node; node = node->traverseNextNode(this)) {
if (newTreeScope == newDocument) {
if (node->hasRareData())
node->rareData()->setTreeScope(0);
// Setting the new document tree scope will be handled implicitly
// by setDocument() below.
} else
node->ensureRareData()->setTreeScope(newTreeScope);
node->setDocument(newDocument);
if (!node->isElementNode())
continue;
// FIXME: Remove toShadowRoot() once shadowRoot() returns a proper ShadowRoot* (bug 58703).
if (ShadowRoot* shadowRoot = toShadowRoot(toElement(node)->shadowRoot())) {
shadowRoot->setParentTreeScope(newTreeScope);
if (currentDocument != newDocument)
shadowRoot->setDocumentRecursively(newDocument);
}
}
}
......
......@@ -359,18 +359,16 @@ public:
Document* document() const
{
ASSERT(this);
// FIXME: below ASSERT is useful, but prevents the use of document() in the constructor or destructor
// due to the virtual function call to nodeType().
ASSERT(m_document || (nodeType() == DOCUMENT_TYPE_NODE && !inDocument()));
return m_document;
}
TreeScope* treeScope() const;
// Do not use this method to change the scope of a node until after the node has been
// removed from its previous scope. Do not use to change documents.
void setTreeScope(TreeScope*);
// Used by the basic DOM methods (e.g., appendChild()).
void setTreeScopeRecursively(TreeScope*);
void setTreeScopeRecursively(TreeScope*, bool includeRoot = true);
// Returns true if this node is associated with a document and is in its associated document's
// node tree, false otherwise.
......
......@@ -27,12 +27,25 @@
#include "config.h"
#include "ShadowRoot.h"
#include "Document.h"
#include "NodeRareData.h"
namespace WebCore {
ShadowRoot::ShadowRoot(Document* document)
: DocumentFragment(document)
: TreeScope(document)
{
ASSERT(document);
// Assume document as parent scope.
setParentTreeScope(document);
// Shadow tree scopes have the scope pointer point to themselves.
// This way, direct children will receive the correct scope pointer.
ensureRareData()->setTreeScope(this);
}
ShadowRoot::~ShadowRoot()
{
}
String ShadowRoot::nodeName() const
......@@ -40,6 +53,33 @@ String ShadowRoot::nodeName() const
return "#shadow-root";
}
Node::NodeType ShadowRoot::nodeType() const
{
// FIXME: Decide correct node type (bug 58704).
return DOCUMENT_FRAGMENT_NODE;
}
PassRefPtr<Node> ShadowRoot::cloneNode(bool)
{
// ShadowRoot should not be arbitrarily cloned.
return 0;
}
bool ShadowRoot::childTypeAllowed(NodeType type) const
{
switch (type) {
case ELEMENT_NODE:
case PROCESSING_INSTRUCTION_NODE:
case COMMENT_NODE:
case TEXT_NODE:
case CDATA_SECTION_NODE:
case ENTITY_REFERENCE_NODE:
return true;
default:
return false;
}
}
void ShadowRoot::recalcStyle(StyleChange change)
{
for (Node* n = firstChild(); n; n = n->nextSibling())
......
......@@ -27,13 +27,13 @@
#ifndef ShadowRoot_h
#define ShadowRoot_h
#include "DocumentFragment.h"
#include "TreeScope.h"
namespace WebCore {
class Document;
class ShadowRoot : public DocumentFragment {
class ShadowRoot : public TreeScope {
public:
static PassRefPtr<ShadowRoot> create(Document*);
......@@ -42,7 +42,12 @@ public:
private:
ShadowRoot(Document*);
virtual ~ShadowRoot();
virtual String nodeName() const;
virtual NodeType nodeType() const;
virtual PassRefPtr<Node> cloneNode(bool deep);
virtual bool childTypeAllowed(NodeType) const;
};
inline PassRefPtr<ShadowRoot> ShadowRoot::create(Document* document)
......@@ -50,6 +55,12 @@ inline PassRefPtr<ShadowRoot> ShadowRoot::create(Document* document)
return adoptRef(new ShadowRoot(document));
}
inline ShadowRoot* toShadowRoot(Node* node)
{
ASSERT(!node || node->isShadowBoundary());
return static_cast<ShadowRoot*>(node);
}
} // namespace
#endif
......@@ -36,19 +36,12 @@ namespace WebCore {
using namespace HTMLNames;
TreeScope::TreeScope(Document* document, ConstructionType constructionType)
: ContainerNode(0, constructionType)
TreeScope::TreeScope(Document* document)
: ContainerNode(document)
, m_parentTreeScope(0)
, m_accessKeyMapValid(false)
, m_numNodeListCaches(0)
{
m_document = document;
if (document != this) {
// Assume document as parent scope
m_parentTreeScope = document;
// FIXME: This branch should be inert until shadow scopes are landed.
ASSERT_NOT_REACHED();
}
}
TreeScope::~TreeScope()
......@@ -69,7 +62,6 @@ void TreeScope::setParentTreeScope(TreeScope* newParentScope)
// A document node cannot be re-parented.
ASSERT(!isDocumentNode());
// Every scope other than document needs a parent scope.
ASSERT(m_parentTreeScope);
ASSERT(newParentScope);
m_parentTreeScope = newParentScope;
......
......@@ -39,6 +39,7 @@ class TreeScope : public ContainerNode {
public:
TreeScope* parentTreeScope() const { return m_parentTreeScope; }
void setParentTreeScope(TreeScope*);
Element* getElementById(const AtomicString&) const;
bool hasElementWithId(AtomicStringImpl* id) const;
......@@ -65,14 +66,11 @@ public:
Element* findAnchor(const String& name);
protected:
TreeScope(Document*, ConstructionType = CreateContainer);
TreeScope(Document*);
virtual ~TreeScope();
void destroyTreeScopeData();
void setParentTreeScope(TreeScope*);
private:
TreeScope* m_parentTreeScope;
......
......@@ -37,7 +37,7 @@
#include "RenderLayer.h"
#include "RenderTheme.h"
#include "RenderView.h"
#include "ShadowElement.h"
#include "ShadowRoot.h"
#include "SliderThumbElement.h"
#include "StepRange.h"
#include <wtf/MathExtras.h>
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment