[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