[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    branches/KDE/4.2/kdelibs/khtml
From:       Maks Orlovich <maksim () kde ! org>
Date:       2009-05-02 19:29:31
Message-ID: 1241292571.951835.10915.nullmailer () svn ! kde ! org
[Download RAW message or body]

SVN commit 962646 by orlovich:

Implement DOM3 core compareDocumentPosition; seems to be needed by GWT...

This passes the cases in the not-yet-commited domts update that don't trigger 
bugs in XML/entity notation handling (once I fixed a problem in their generation)

CCBUG:129398



 M  +7 -0      dom/dom_node.cpp  
 M  +36 -2     dom/dom_node.h  
 M  +15 -0     ecma/kjs_dom.cpp  
 M  +1 -1      ecma/kjs_dom.h  
 M  +100 -0    xml/dom_nodeimpl.cpp  
 M  +3 -0      xml/dom_nodeimpl.h  


--- branches/KDE/4.2/kdelibs/khtml/dom/dom_node.cpp #962645:962646
@@ -390,6 +390,13 @@
         throw DOMException(exceptioncode);
 }
 
+unsigned Node::compareDocumentPosition(const Node& other)
+{
+    if (!impl || !other.impl)
+	throw DOMException(DOMException::NOT_FOUND_ERR);
+    return impl->compareDocumentPosition(other.impl);
+}
+
 unsigned int Node::elementId() const
 {
     if (!impl) return 0;
--- branches/KDE/4.2/kdelibs/khtml/dom/dom_node.h #962645:962646
@@ -837,7 +837,7 @@
     bool dispatchEvent(const Event &evt);
 
     /**
-     * Introduced in DOM Level 2
+     * Introduced in DOM Level 3
      *
      * This attribute returns the text content of this node and its
      * descendants. When it is defined to be null, setting it has no
@@ -854,7 +854,7 @@
      * textual content.
      */
     DOMString textContent() const;
-    
+        
     /**
      * see textContent()
      * 
@@ -862,6 +862,40 @@
      * NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly.
      */
     void setTextContent(const DOMString& text);
+    
+    /**
+     * Introduced in DOM Level 3.
+     * 
+     * These constants represent bitflags returned by the compareDocumentPosition
+     * method.
+     *
+     * @since 4.2.4
+     */
+    enum DocumentPosition {
+	DOCUMENT_POSITION_DISCONNECTED = 0x01,
+	DOCUMENT_POSITION_PRECEDING    = 0x02,
+	DOCUMENT_POSITION_FOLLOWING    = 0x04,
+	DOCUMENT_POSITION_CONTAINS     = 0x08,
+	DOCUMENT_POSITION_CONTAINED_BY = 0x10,
+	DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC = 0x20
+    };
+    
+    /**
+     * Introduced in DOM Level 3.
+     * 
+     * This method compares the current node's position with that of 'other'
+     * and returns it as a combination of DocumentPosition bitfields.
+     * Here DOCUMENT_POSITION_FOLLOWING means that the 'other' is 
+     * after the current.
+     *
+     * The notion of order here is a logical one; for example attributes
+     * are viewed as if they were children of an element inserted
+     * right before the real children. The method will also assign
+     * some total order even if the nodes are not connected. 
+     *
+     * @since 4.2.4
+     */
+    unsigned compareDocumentPosition(const DOM::Node& other);
 
     /**
      * @internal
--- branches/KDE/4.2/kdelibs/khtml/ecma/kjs_dom.cpp #962645:962646
@@ -72,6 +72,12 @@
   DOCUMENT_TYPE_NODE    DOM::Node::DOCUMENT_TYPE_NODE   DontDelete|ReadOnly
   DOCUMENT_FRAGMENT_NODE DOM::Node::DOCUMENT_FRAGMENT_NODE  DontDelete|ReadOnly
   NOTATION_NODE     DOM::Node::NOTATION_NODE        DontDelete|ReadOnly
+  DOCUMENT_POSITION_DISCONNECTED                \
DOM::Node::DOCUMENT_POSITION_DISCONNECTED  DontDelete|ReadOnly +  \
DOCUMENT_POSITION_PRECEDING                   DOM::Node::DOCUMENT_POSITION_PRECEDING  \
DontDelete|ReadOnly +  DOCUMENT_POSITION_FOLLOWING                   \
DOM::Node::DOCUMENT_POSITION_FOLLOWING   DontDelete|ReadOnly +  \
DOCUMENT_POSITION_CONTAINS                    DOM::Node::DOCUMENT_POSITION_CONTAINS  \
DontDelete|ReadOnly +  DOCUMENT_POSITION_CONTAINED_BY                \
DOM::Node::DOCUMENT_POSITION_CONTAINED_BY  DontDelete|ReadOnly +  \
DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC     \
DOM::Node::DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC  DontDelete|ReadOnly  @end
 */
 IMPLEMENT_CONSTANT_TABLE(DOMNodeConstants,"DOMNodeConstants")
@@ -89,6 +95,8 @@
 # DOM2
   normalize	DOMNode::Normalize	DontDelete|Function 0
   isSupported   DOMNode::IsSupported	DontDelete|Function 2
+# DOM3
+  compareDocumentPosition 	DOMNode::CompareDocumentPosition	DontDelete|Function 1
 # from the EventTarget interface
   addEventListener	DOMNode::AddEventListener	DontDelete|Function 3
   removeEventListener	DOMNode::RemoveEventListener	DontDelete|Function 3
@@ -684,6 +692,13 @@
       SharedPtr<NodeListImpl> childNodes = node.childNodes();
       return getDOMNode(exec, childNodes->item(static_cast<unsigned \
long>(args[0]->toNumber(exec))));  }
+    case DOMNode::CompareDocumentPosition: {
+       DOM::NodeImpl* other = toNode(args[0]);
+       if (!other)
+          setDOMException(exec, DOMException::TYPE_MISMATCH_ERR);
+       else
+          return jsNumber(node.compareDocumentPosition(other));
+    }
   }
 
   return jsUndefined();
--- branches/KDE/4.2/kdelibs/khtml/ecma/kjs_dom.h #962645:962646
@@ -65,7 +65,7 @@
            OnResize, OnScroll, OnSelect, OnSubmit, OnUnload,
            OffsetLeft, OffsetTop, OffsetWidth, OffsetHeight, OffsetParent,
            ClientLeft, ClientTop, ClientWidth, ClientHeight, ScrollLeft, ScrollTop,
-           ScrollWidth, ScrollHeight, SourceIndex, TextContent };
+           ScrollWidth, ScrollHeight, SourceIndex, TextContent, \
CompareDocumentPosition };  
     //### toNode? virtual
     DOM::NodeImpl* impl() const { return m_impl.get(); }
--- branches/KDE/4.2/kdelibs/khtml/xml/dom_nodeimpl.cpp #962645:962646
@@ -1283,6 +1283,105 @@
         return doc;
 }
 
+// Helper for compareDocumentPosition --- this extends the notion of a parent node
+// beyond structural to also include elements containing attributes, etc.
+static const NodeImpl* logicalParentNode(const DOM::NodeImpl* node)
+{
+    NodeImpl* parent = node->parentNode();
+    if (parent)
+        return parent;
+        
+    switch (node->nodeType()) {
+        case Node::ATTRIBUTE_NODE:
+            return static_cast<const AttrImpl*>(node)->ownerElement();
+        
+        case Node::ENTITY_NODE:
+        case Node::NOTATION_NODE:
+            return node->ownerDocument()->doctype();
+            
+        default:
+            return 0;
+    }
+}
+
+unsigned NodeImpl::compareDocumentPosition(const DOM::NodeImpl* other)
+{
+    if (other == this)
+        return 0; 
+        
+    // First, collect paths of the parents of this and other to the root of their \
subtrees. +    // Root goes first, hence the use of QList, with its fast prepends
+    QList<const NodeImpl*> thisPath;
+    for (const NodeImpl* cur = this; cur; cur = logicalParentNode(cur))
+        thisPath.prepend(cur);
+        
+    QList<const NodeImpl*> otherPath;
+    for (const NodeImpl* cur = other; cur; cur = logicalParentNode(cur))
+        otherPath.prepend(cur);
+        
+    // if the roots aren't the same, we're disconnected. We're also supposed to 
+    // return IMPLEMENTATION_SPECIFIC here, and, reading tea leaves, make some 
+    // sort of a stable decision to get a total order.
+    if (thisPath[0] != otherPath[0]) {
+        return Node::DOCUMENT_POSITION_DISCONNECTED | \
Node::DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC | +               (this > other ? \
Node::DOCUMENT_POSITION_PRECEDING : Node::DOCUMENT_POSITION_FOLLOWING); +    }
+        
+    // Now find our common container.
+    const NodeImpl* common = 0;
+    int   diffPos = -1;
+    for (int pos = 0; pos < thisPath.size() && pos < otherPath.size(); ++pos) {
+        if (thisPath[pos] == otherPath[pos]) {
+            common = thisPath[pos];
+        } else {
+            diffPos = pos;
+            break;
+        }
+    }
+    
+    // Do we have direct containment? 
+    if (common == this)
+        return Node::DOCUMENT_POSITION_CONTAINED_BY | \
Node::DOCUMENT_POSITION_FOLLOWING; +    else if (common == other)
+        return Node::DOCUMENT_POSITION_CONTAINS | Node::DOCUMENT_POSITION_PRECEDING;
+        
+    // OK, so now we are not nested, so there are ancestors of both nodes
+    // below common that are different. Since some of those may be logically and not \
 +    // physically contained in common, we have to treat the logical containment \
case specially. +    const NodeImpl* thisAnc  = thisPath [diffPos];
+    const NodeImpl* otherAnc = otherPath[diffPos];
+    
+    bool thisAncLogical  = thisAnc->parentNode() == 0;
+    bool otherAncLogical = otherAnc->parentNode() == 0;
+    kDebug() << thisAncLogical << otherAncLogical;
+    
+    if (thisAncLogical && otherAncLogical) {
+        // First, try to order by nodeType.
+        if (thisAnc->nodeType() != otherAnc->nodeType())
+            return (thisAnc->nodeType() < otherAnc->nodeType()) ? 
+                Node::DOCUMENT_POSITION_FOLLOWING : \
Node::DOCUMENT_POSITION_PRECEDING; +                
+        // If not, another implementation-specific order.
+        return Node::DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC |
+               (this > other ? Node::DOCUMENT_POSITION_PRECEDING : \
Node::DOCUMENT_POSITION_FOLLOWING); +    }
+    
+    if (thisAncLogical)
+        return Node::DOCUMENT_POSITION_FOLLOWING;
+        
+    if (otherAncLogical)
+        return Node::DOCUMENT_POSITION_PRECEDING;
+        
+    // Uff. And now the normal case -- just order thisAnc and otherAnc based on \
their tree order +    // see if otherAnc follows thisAnc)
+    for (const NodeImpl* cur = thisAnc; cur; cur = cur->nextSibling()) {
+        if (cur == otherAnc)
+            return Node::DOCUMENT_POSITION_FOLLOWING;
+    }
+    
+    return Node::DOCUMENT_POSITION_PRECEDING;
+}
+
 void NodeImpl::setDocument(DocumentImpl* doc)
 {
     if (m_document == doc)
@@ -2190,3 +2289,4 @@
     delete listeners; listeners = 0;
 }
 
+// kate: indent-width 4; replace-tabs on; tab-width 4; space-indent on; 
--- branches/KDE/4.2/kdelibs/khtml/xml/dom_nodeimpl.h #962645:962646
@@ -111,6 +111,9 @@
 
     // HTML 5
     NodeListImpl* getElementsByClassName(const DOMString &name);
+    
+    // DOM3. See the wrapper (DOM::Node for the constants used in the return value
+    unsigned compareDocumentPosition(const DOM::NodeImpl* other);
 
     // insertBefore, replaceChild and appendChild also close newChild
     // unlike the speed optimized addChild (which is used by the parser)


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic