Reviewed by Darin.
authorap@webkit.org <ap@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 16 Nov 2007 06:04:45 +0000 (06:04 +0000)
committerap@webkit.org <ap@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 16 Nov 2007 06:04:45 +0000 (06:04 +0000)
        http://bugs.webkit.org/show_bug.cgi?id=15989
        XPath queries with predicates incorrectly retains the current node across unions

        Test: fast/xpath/union-context-node.xhtml

        * xml/XPathPath.cpp:
        (WebCore::XPath::LocationPath::evaluate): Restore context after evaluation.
        * xml/XPathStep.cpp:
        (WebCore::XPath::Step::evaluate): Do not backup context, as we can easily re-create it.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@27837 268f45cc-cd09-0410-ab3c-d52691b4dbfc

LayoutTests/ChangeLog
LayoutTests/fast/xpath/union-context-node-expected.txt [new file with mode: 0644]
LayoutTests/fast/xpath/union-context-node.xhtml [new file with mode: 0644]
WebCore/ChangeLog
WebCore/xml/XPathPath.cpp
WebCore/xml/XPathStep.cpp

index a08e912..0779214 100644 (file)
@@ -1,3 +1,13 @@
+2007-11-15  Khoo Yit Phang  <khooyp@cs.umd.edu>
+
+        Reviewed by Darin.
+
+        http://bugs.webkit.org/show_bug.cgi?id=15989
+        XPath queries with predicates incorrectly retains the current node across unions
+
+        * fast/xpath/union-context-node-expected.txt: Added.
+        * fast/xpath/union-context-node.xhtml: Added.
+
 2007-11-15  Alexey Proskuryakov  <ap@webkit.org>
 
         Reviewed by Darin.
diff --git a/LayoutTests/fast/xpath/union-context-node-expected.txt b/LayoutTests/fast/xpath/union-context-node-expected.txt
new file mode 100644 (file)
index 0000000..dad2dac
--- /dev/null
@@ -0,0 +1,62 @@
+ Querying in the following...
+
+<div xmlns="http://www.w3.org/1999/xhtml" id="test">
+    <span id="A">
+        <span id="B"></span>
+    </span>
+    <span id="C">
+        <span id="D"></span>
+    </span>
+</div>
+
+Query "ancestor::xhtml:span" from span#B
+Result: span#A
+Expected: span#A
+SUCCESS
+
+Query ".|ancestor::xhtml:span" from span#B
+Result: span#A span#B
+Expected: span#A span#B
+SUCCESS
+
+Query "ancestor::xhtml:span|." from span#B
+Result: span#A span#B
+Expected: span#A span#B
+SUCCESS
+
+Query "ancestor::xhtml:*[local-name()='span']" from span#B
+Result: span#A
+Expected: span#A
+SUCCESS
+
+Query ".|ancestor::xhtml:*[local-name()='span']" from span#B
+Result: span#A span#B
+Expected: span#A span#B
+SUCCESS
+
+Query "ancestor::xhtml:*[local-name()='span']|." from span#B
+Result: span#A span#B
+Expected: span#A span#B
+SUCCESS
+
+Query "(ancestor::xhtml:*[local-name()='span'])|." from span#B
+Result: span#A span#B
+Expected: span#A span#B
+SUCCESS
+
+Query "following::xhtml:*[local-name()='span']" from span#B
+Result: span#C span#D
+Expected: span#C span#D
+SUCCESS
+
+Query ".|following::xhtml:*[local-name()='span']" from span#B
+Result: span#B span#C span#D
+Expected: span#B span#C span#D
+SUCCESS
+
+Query "following::xhtml:*[local-name()='span']|." from span#B
+Result: span#B span#C span#D
+Expected: span#B span#C span#D
+SUCCESS
+
+
diff --git a/LayoutTests/fast/xpath/union-context-node.xhtml b/LayoutTests/fast/xpath/union-context-node.xhtml
new file mode 100644 (file)
index 0000000..5b91bd7
--- /dev/null
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
+<head>
+<title>XPath queries with predicates incorrectly retains the current node across unions</title>
+<style>div#msg { white-space: pre; }</style>
+<script>
+if (window.layoutTestController)
+    layoutTestController.dumpAsText();
+
+window.addEventListener("load", function() {
+    var msg = document.getElementById("msg");
+    function print(s) { msg.textContent += s; }
+    function id(el) { return el.tagName + (el.id ? "#" + el.id : ""); }
+    function query(el, xpath, expected) {
+        print("Query \"" + xpath + "\" from " + id(el) + "\n");
+        var res = document.evaluate(xpath,
+                                    el,
+                                    function() { return "http://www.w3.org/1999/xhtml"; },
+                                    XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,
+                                    null);
+
+        var resstr = "";
+        for (var i = 0; i &lt; res.snapshotLength; i++) {
+            var el = res.snapshotItem(i);
+            resstr += " " + id(el);
+        }
+        print("Result:" + resstr + "\n");
+        print("Expected: " + expected + "\n");
+        if (resstr != (" " + expected)) {
+            print("FAIL\n");
+        } else {
+            print("SUCCESS\n");
+        }
+        print("\n");
+    }
+    
+    print("Querying in the following...\n\n");
+    print(document.getElementById("test").outerHTML + "\n\n");
+    
+    query(document.getElementById("B"), "ancestor::xhtml:span", "span#A");
+    query(document.getElementById("B"), ".|ancestor::xhtml:span", "span#A span#B");
+    query(document.getElementById("B"), "ancestor::xhtml:span|.", "span#A span#B");
+
+    query(document.getElementById("B"), "ancestor::xhtml:*[local-name()='span']", "span#A");
+    query(document.getElementById("B"), ".|ancestor::xhtml:*[local-name()='span']", "span#A span#B");
+    query(document.getElementById("B"), "ancestor::xhtml:*[local-name()='span']|.", "span#A span#B");
+    query(document.getElementById("B"), "(ancestor::xhtml:*[local-name()='span'])|.", "span#A span#B");
+    
+    query(document.getElementById("B"), "following::xhtml:*[local-name()='span']", "span#C span#D");
+    query(document.getElementById("B"), ".|following::xhtml:*[local-name()='span']", "span#B span#C span#D");
+    query(document.getElementById("B"), "following::xhtml:*[local-name()='span']|.", "span#B span#C span#D");
+}, false);
+</script>
+</head>
+<body>
+<div id="test">
+    <span id="A">
+        <span id="B"/>
+    </span>
+    <span id="C">
+        <span id="D"/>
+    </span>
+</div>
+<div id="msg"/>
+</body>
+</html>
index 38c9e11..510a79c 100644 (file)
@@ -2,6 +2,20 @@
 
         Reviewed by Darin.
 
+        http://bugs.webkit.org/show_bug.cgi?id=15989
+        XPath queries with predicates incorrectly retains the current node across unions
+
+        Test: fast/xpath/union-context-node.xhtml
+
+        * xml/XPathPath.cpp:
+        (WebCore::XPath::LocationPath::evaluate): Restore context after evaluation.
+        * xml/XPathStep.cpp:
+        (WebCore::XPath::Step::evaluate): Do not backup context, as we can easily re-create it.
+
+2007-11-15  Alexey Proskuryakov  <ap@webkit.org>
+
+        Reviewed by Darin.
+
         http://bugs.webkit.org/show_bug.cgi?id=15988
         REGRESSION: XPath preceding-axis query misses nested elements
 
index a0a734a..bc7b153 100644 (file)
@@ -92,10 +92,12 @@ LocationPath::~LocationPath()
 
 Value LocationPath::evaluate() const
 {
+    EvaluationContext& evaluationContext = Expression::evaluationContext();
+    EvaluationContext backupContext = evaluationContext;
     /* For absolute location paths, the context node is ignored - the
      * document's root node is used instead.
      */
-    Node* context = Expression::evaluationContext().node.get();
+    Node* context = evaluationContext.node.get();
     if (m_absolute && context->nodeType() != Node::DOCUMENT_NODE) 
         context = context->ownerDocument();
 
@@ -103,6 +105,7 @@ Value LocationPath::evaluate() const
     nodes.append(context);
     evaluate(nodes);
     
+    evaluationContext = backupContext;
     return Value(nodes, Value::adopt);
 }
 
index a93a595..d728f9a 100644 (file)
@@ -65,18 +65,14 @@ void Step::evaluate(Node* context, NodeSet& nodes) const
         if (!nodes.isSorted())
             newNodes.markSorted(false);
 
-        evaluationContext.size = nodes.size();
-        evaluationContext.position = 1;
         for (unsigned j = 0; j < nodes.size(); j++) {
             Node* node = nodes[j];
 
             Expression::evaluationContext().node = node;
-            EvaluationContext backupCtx = evaluationContext;
+            evaluationContext.size = nodes.size();
+            evaluationContext.position = j + 1;
             if (predicate->evaluate())
                 newNodes.append(node);
-
-            evaluationContext = backupCtx;
-            ++evaluationContext.position;
         }
 
         nodes.swap(newNodes);