2008-07-07 Simon Fraser <simon.fraser@apple.com>
authordino@apple.com <dino@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 8 Jul 2008 03:19:30 +0000 (03:19 +0000)
committerdino@apple.com <dino@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 8 Jul 2008 03:19:30 +0000 (03:19 +0000)
        Reviewed by Darin.

        Fix for https://bugs.webkit.org/show_bug.cgi?id=19933
        nodeIterator with filter fails on documents not in a frame

        Tests: traversal/node-iterator-009.html
               traversal/tree-walker-006.html

        * bindings/js/JSNodeFilterCondition.cpp:
        * bindings/js/JSNodeFilterCondition.h:
        * bindings/js/JSNodeFilterCustom.cpp:
        * bindings/js/JSNodeIteratorCustom.cpp:
        * bindings/js/JSTreeWalkerCustom.cpp:
        * bindings/objc/DOM.mm:
        * dom/NodeFilter.cpp:
        * dom/NodeFilter.h:
        * dom/NodeFilterCondition.cpp:
        * dom/NodeFilterCondition.h:
        * dom/NodeIterator.cpp:
        * dom/NodeIterator.h:
        * dom/Traversal.cpp:
        * dom/Traversal.h:
        * dom/TreeWalker.cpp:
        * dom/TreeWalker.h:

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

22 files changed:
LayoutTests/ChangeLog
LayoutTests/traversal/node-iterator-009-expected.txt [new file with mode: 0644]
LayoutTests/traversal/node-iterator-009.html [new file with mode: 0644]
LayoutTests/traversal/tree-walker-006-expected.txt [new file with mode: 0644]
LayoutTests/traversal/tree-walker-006.html [new file with mode: 0644]
WebCore/ChangeLog
WebCore/bindings/js/JSNodeFilterCondition.cpp
WebCore/bindings/js/JSNodeFilterCondition.h
WebCore/bindings/js/JSNodeFilterCustom.cpp
WebCore/bindings/js/JSNodeIteratorCustom.cpp
WebCore/bindings/js/JSTreeWalkerCustom.cpp
WebCore/bindings/objc/DOM.mm
WebCore/dom/NodeFilter.cpp
WebCore/dom/NodeFilter.h
WebCore/dom/NodeFilterCondition.cpp
WebCore/dom/NodeFilterCondition.h
WebCore/dom/NodeIterator.cpp
WebCore/dom/NodeIterator.h
WebCore/dom/Traversal.cpp
WebCore/dom/Traversal.h
WebCore/dom/TreeWalker.cpp
WebCore/dom/TreeWalker.h

index 136bb6b..823fb7d 100644 (file)
@@ -1,3 +1,15 @@
+2008-07-07  Simon Fraser  <simon.fraser@apple.com>
+
+        Reviewed by Darin.
+
+        Tests for https://bugs.webkit.org/show_bug.cgi?id=19933
+        nodeIterator with filter fails on documents not in a frame
+
+        * traversal/node-iterator-009-expected.txt: Added.
+        * traversal/node-iterator-009.html: Added.
+        * traversal/tree-walker-006-expected.txt: Added.
+        * traversal/tree-walker-006.html: Added.
+
 2008-07-07  Adele Peterson  <adele@apple.com>
 
         Reviewed by Dan Bernstein.
diff --git a/LayoutTests/traversal/node-iterator-009-expected.txt b/LayoutTests/traversal/node-iterator-009-expected.txt
new file mode 100644 (file)
index 0000000..e462acb
--- /dev/null
@@ -0,0 +1,33 @@
+XML doc elements:
+
+records
+
+Across the Universe 2:30 Not yet rated Sony Pictures 2007-02-15 2007-09-28
+
+movieinfo
+
+Across the Universe 2:30 Not yet rated Sony Pictures 2007-02-15 2007-09-28
+
+info
+
+Across the Universe 2:30 Not yet rated Sony Pictures 2007-02-15 2007-09-28
+
+title
+
+Across the Universe
+
+runtime
+
+2:30
+
+rating
+
+Not yet rated
+
+postdate
+
+2007-02-15
+
+releasedate
+
+2007-09-28
diff --git a/LayoutTests/traversal/node-iterator-009.html b/LayoutTests/traversal/node-iterator-009.html
new file mode 100644 (file)
index 0000000..9541f92
--- /dev/null
@@ -0,0 +1,48 @@
+<html> 
+<head>
+<title>Traversal Test</title> 
+</head> 
+<body>
+
+  <h2>XML doc elements:</h2>
+  <div style="font-family: Courier; font-size: 14;">
+    <script type="text/javascript" charset="utf-8">
+
+    if (window.layoutTestController)
+        layoutTestController.dumpAsText();
+
+      var dataURL = 'resources/node-iterator-009-data.xml';
+      function fetchXML()
+      {
+        var request = new XMLHttpRequest();
+        request.open("GET", dataURL, false /* sync */);
+        request.overrideMimeType("application/xml");
+        request.send();
+
+        if (request.readyState == 4) {
+          // only if "OK"
+          if (request.status == 200 || (request.status == 0 && request.responseText.length > 0))
+              walkXML(request.responseXML);
+        }
+      }
+
+      function testNodeFiter(n)
+      {
+          if (n.tagName == 'studio') return NodeFilter.FILTER_SKIP;
+          return NodeFilter.FILTER_ACCEPT;
+      }
+
+      function walkXML(xmlDoc)
+      {
+        var iter = document.createNodeIterator(xmlDoc, NodeFilter.SHOW_ELEMENT, testNodeFiter);
+        var curNode;
+        while (curNode = iter.nextNode()) {
+          document.write('<h3>' + curNode.tagName + '</h3><p>' + curNode.textContent + '</p>');
+        }
+      }
+      fetchXML();
+
+    </script>
+  </div>
+</body>
+</html>
diff --git a/LayoutTests/traversal/tree-walker-006-expected.txt b/LayoutTests/traversal/tree-walker-006-expected.txt
new file mode 100644 (file)
index 0000000..e462acb
--- /dev/null
@@ -0,0 +1,33 @@
+XML doc elements:
+
+records
+
+Across the Universe 2:30 Not yet rated Sony Pictures 2007-02-15 2007-09-28
+
+movieinfo
+
+Across the Universe 2:30 Not yet rated Sony Pictures 2007-02-15 2007-09-28
+
+info
+
+Across the Universe 2:30 Not yet rated Sony Pictures 2007-02-15 2007-09-28
+
+title
+
+Across the Universe
+
+runtime
+
+2:30
+
+rating
+
+Not yet rated
+
+postdate
+
+2007-02-15
+
+releasedate
+
+2007-09-28
diff --git a/LayoutTests/traversal/tree-walker-006.html b/LayoutTests/traversal/tree-walker-006.html
new file mode 100644 (file)
index 0000000..09ec0dd
--- /dev/null
@@ -0,0 +1,48 @@
+<html> 
+<head>
+<title>Traversal Test</title> 
+</head> 
+<body>
+
+  <h2>XML doc elements:</h2>
+  <div style="font-family: Courier; font-size: 14;">
+    <script type="text/javascript" charset="utf-8">
+
+    if (window.layoutTestController)
+        layoutTestController.dumpAsText();
+
+      var dataURL = 'resources/node-iterator-009-data.xml';
+      function fetchXML()
+      {
+        var request = new XMLHttpRequest();
+        request.open("GET", dataURL, false /* sync */);
+        request.overrideMimeType("application/xml");
+        request.send();
+
+        if (request.readyState == 4) {
+          // only if "OK"
+          if (request.status == 200 || (request.status == 0 && request.responseText.length > 0))
+              walkXML(request.responseXML);
+        }
+      }
+
+      function testNodeFiter(n)
+      {
+          if (n.tagName == 'studio') return NodeFilter.FILTER_SKIP;
+          return NodeFilter.FILTER_ACCEPT;
+      }
+
+      function walkXML(xmlDoc)
+      {
+        var iter = document.createTreeWalker(xmlDoc, NodeFilter.SHOW_ELEMENT, testNodeFiter, false);
+        var curNode;
+        while (curNode = iter.nextNode()) {
+          document.write('<h3>' + curNode.tagName + '</h3><p>' + curNode.textContent + '</p>');
+        }
+      }
+      fetchXML();
+
+    </script>
+  </div>
+</body>
+</html>
index 3ac0bd9..6c24fea 100644 (file)
@@ -1,3 +1,30 @@
+2008-07-07  Simon Fraser  <simon.fraser@apple.com>
+
+        Reviewed by Darin.
+
+        Fix for https://bugs.webkit.org/show_bug.cgi?id=19933
+        nodeIterator with filter fails on documents not in a frame
+
+        Tests: traversal/node-iterator-009.html
+               traversal/tree-walker-006.html
+
+        * bindings/js/JSNodeFilterCondition.cpp:
+        * bindings/js/JSNodeFilterCondition.h:
+        * bindings/js/JSNodeFilterCustom.cpp:
+        * bindings/js/JSNodeIteratorCustom.cpp:
+        * bindings/js/JSTreeWalkerCustom.cpp:
+        * bindings/objc/DOM.mm:
+        * dom/NodeFilter.cpp:
+        * dom/NodeFilter.h:
+        * dom/NodeFilterCondition.cpp:
+        * dom/NodeFilterCondition.h:
+        * dom/NodeIterator.cpp:
+        * dom/NodeIterator.h:
+        * dom/Traversal.cpp:
+        * dom/Traversal.h:
+        * dom/TreeWalker.cpp:
+        * dom/TreeWalker.h:
+
 2008-07-07  Adele Peterson  <adele@apple.com>
 
         Reviewed by Dan Bernstein.
index 61c394a..bb60078 100644 (file)
 #include "config.h"
 #include "JSNodeFilterCondition.h"
 
-#include "Document.h"
-#include "Frame.h"
 #include "JSNode.h"
 #include "JSNodeFilter.h"
 #include "NodeFilter.h"
-#include "ScriptController.h"
 #include <kjs/JSLock.h>
 
 namespace WebCore {
 
 using namespace KJS;
 
-// FIXME: Add takeException as a member of ExecState?
-static JSValue* takeException(ExecState* exec)
-{
-    JSValue* exception = exec->exception();
-    exec->clearException();
-    return exception;
-}
-
 JSNodeFilterCondition::JSNodeFilterCondition(JSValue* filter)
     : m_filter(filter)
 {
@@ -51,13 +40,8 @@ void JSNodeFilterCondition::mark()
         m_filter->mark();
 }
 
-short JSNodeFilterCondition::acceptNode(Node* filterNode, JSValue*& exception) const
+short JSNodeFilterCondition::acceptNode(KJS::ExecState* exec, Node* filterNode) const
 {
-    // FIXME: It makes no sense for this to depend on the document being in a frame!
-    Frame* frame = filterNode->document()->frame();
-    if (!frame)
-        return NodeFilter::FILTER_REJECT;
-
     JSLock lock(false);
 
     CallData callData;
@@ -65,23 +49,28 @@ short JSNodeFilterCondition::acceptNode(Node* filterNode, JSValue*& exception) c
     if (callType == CallTypeNone)
         return NodeFilter::FILTER_ACCEPT;
 
-    ExecState* exec = frame->script()->globalObject()->globalExec();
+   // The exec argument here should only be null if this was called from a
+   // non-JavaScript language, and this is a JavaScript filter, and the document
+   // in question is not associated with the frame. In that case, we're going to
+   // behave incorrectly, and just reject nodes instead of calling the filter function.
+   // To fix that we'd need to come up with a way to find a suitable JavaScript
+   // execution context for the filter function to run in.
+    if (!exec)
+        return NodeFilter::FILTER_REJECT;
+
     ArgList args;
     args.append(toJS(exec, filterNode));
-    if (exec->hadException()) {
-        exception = takeException(exec);
+    if (exec->hadException())
         return NodeFilter::FILTER_REJECT;
-    }
+
     JSValue* result = call(exec, m_filter, callType, callData, m_filter, args);
-    if (exec->hadException()) {
-        exception = takeException(exec);
+    if (exec->hadException())
         return NodeFilter::FILTER_REJECT;
-    }
+
     int intResult = result->toInt32(exec);
-    if (exec->hadException()) {
-        exception = takeException(exec);
+    if (exec->hadException())
         return NodeFilter::FILTER_REJECT;
-    }
+
     return intResult;
 }
 
index 3a47470..bd31650 100644 (file)
@@ -41,7 +41,7 @@ namespace WebCore {
     private:
         JSNodeFilterCondition(KJS::JSValue* filter);
 
-        virtual short acceptNode(Node*, KJS::JSValue*& exception) const;
+        virtual short acceptNode(KJS::ExecState*, Node*) const;
         virtual void mark();
 
         KJS::JSValue* m_filter;
index cae1d54..4b3740e 100644 (file)
@@ -43,11 +43,7 @@ void JSNodeFilter::mark()
 
 JSValue* JSNodeFilter::acceptNode(ExecState* exec, const ArgList& args)
 {
-    JSValue* exception = 0;
-    short result = impl()->acceptNode(toNode(args[0]), exception);
-    if (exception)
-        exec->setException(exception);
-    return jsNumber(exec, result);
+    return jsNumber(exec, impl()->acceptNode(exec, toNode(args[0])));
 }
 
 PassRefPtr<NodeFilter> toNodeFilter(JSValue* value)
index 01600bf..e76141c 100644 (file)
@@ -40,32 +40,30 @@ void JSNodeIterator::mark()
 JSValue* JSNodeIterator::nextNode(ExecState* exec, const ArgList& args)
 {
     ExceptionCode ec = 0;
-    JSValue* exception = 0;
-    RefPtr<Node> node = impl()->nextNode(ec, exception);
+    RefPtr<Node> node = impl()->nextNode(exec, ec);
     if (ec) {
         setDOMException(exec, ec);
         return jsUndefined();
     }
-    if (exception) {
-        exec->setException(exception);
+
+    if (exec->hadException())
         return jsUndefined();
-    }
+
     return toJS(exec, node.get());
 }
 
 JSValue* JSNodeIterator::previousNode(ExecState* exec, const ArgList& args)
 {
     ExceptionCode ec = 0;
-    JSValue* exception = 0;
-    RefPtr<Node> node = impl()->previousNode(ec, exception);
+    RefPtr<Node> node = impl()->previousNode(exec, ec);
     if (ec) {
         setDOMException(exec, ec);
         return jsUndefined();
     }
-    if (exception) {
-        exec->setException(exception);
+
+    if (exec->hadException())
         return jsUndefined();
-    }
+
     return toJS(exec, node.get());
 }
 
index 7e692c0..769671b 100644 (file)
@@ -39,78 +39,57 @@ void JSTreeWalker::mark()
     
 JSValue* JSTreeWalker::parentNode(ExecState* exec, const ArgList& args)
 {
-    JSValue* exception = 0;
-    Node* node = impl()->parentNode(exception);
-    if (exception) {
-        exec->setException(exception);
+    Node* node = impl()->parentNode(exec);
+    if (exec->hadException())
         return jsUndefined();
-    }
     return toJS(exec, node);
 }
     
 JSValue* JSTreeWalker::firstChild(ExecState* exec, const ArgList& args)
 {
-    JSValue* exception = 0;
-    Node* node = impl()->firstChild(exception);
-    if (exception) {
-        exec->setException(exception);
+    Node* node = impl()->firstChild(exec);
+    if (exec->hadException())
         return jsUndefined();
-    }
     return toJS(exec, node);
 }
     
 JSValue* JSTreeWalker::lastChild(ExecState* exec, const ArgList& args)
 {
-    JSValue* exception = 0;
-    Node* node = impl()->lastChild(exception);
-    if (exception) {
-        exec->setException(exception);
+    Node* node = impl()->lastChild(exec);
+    if (exec->hadException())
         return jsUndefined();
-    }
     return toJS(exec, node);
 }
     
 JSValue* JSTreeWalker::nextSibling(ExecState* exec, const ArgList& args)
 {
-    JSValue* exception = 0;
-    Node* node = impl()->nextSibling(exception);
-    if (exception) {
-        exec->setException(exception);
+    Node* node = impl()->nextSibling(exec);
+    if (exec->hadException())
         return jsUndefined();
-    }
     return toJS(exec, node);
 }
     
 JSValue* JSTreeWalker::previousSibling(ExecState* exec, const ArgList& args)
 {
-    JSValue* exception = 0;
-    Node* node = impl()->previousSibling(exception);
-    if (exception) {
-        exec->setException(exception);
+    Node* node = impl()->previousSibling(exec);
+    if (exec->hadException())
         return jsUndefined();
-    }
     return toJS(exec, node);
 }
     
 JSValue* JSTreeWalker::previousNode(ExecState* exec, const ArgList& args)
 {
-    JSValue* exception = 0;
-    Node* node = impl()->previousNode(exception);
-    if (exception) {
-        exec->setException(exception);
+    Node* node = impl()->previousNode(exec);
+    if (exec->hadException())
         return jsUndefined();
-    }
     return toJS(exec, node);
 }
     
 JSValue* JSTreeWalker::nextNode(ExecState* exec, const ArgList& args)
 {
-    JSValue* exception = 0;
-    Node* node = impl()->nextNode(exception);
-    if (exception) {
-        exec->setException(exception);
+    Node* node = impl()->nextNode(exec);
+    if (exec->hadException())
         return jsUndefined();
-    }
     return toJS(exec, node);
 }
 
index 7fb42f6..33cb35c 100644 (file)
@@ -697,7 +697,7 @@ public:
         return adoptRef(new ObjCNodeFilterCondition(filter));
     }
 
-    virtual short acceptNode(Node*, JSValue*& exception) const;
+    virtual short acceptNode(ExecState*, Node*) const;
 
 private:
     ObjCNodeFilterCondition(id <DOMNodeFilter> filter)
@@ -708,7 +708,7 @@ private:
     RetainPtr<id <DOMNodeFilter> > m_filter;
 };
 
-short ObjCNodeFilterCondition::acceptNode(Node* node, JSValue*&) const
+short ObjCNodeFilterCondition::acceptNode(ExecState*, Node* node) const
 {
     if (!node)
         return NodeFilter::FILTER_REJECT;
index 1844a2d..0a85fb3 100644 (file)
 #include "config.h"
 #include "NodeFilter.h"
 
+#include "Document.h"
+#include "Frame.h"
+#include "Node.h"
+#include "ScriptController.h"
+
 using namespace KJS;
 
 namespace WebCore {
 
-short NodeFilter::acceptNode(Node* node, JSValue*& exception) const
+short NodeFilter::acceptNode(ExecState* exec, Node* node) const
 {
     // cast to short silences "enumeral and non-enumeral types in return" warning
-    return m_condition ? m_condition->acceptNode(node, exception) : static_cast<short>(FILTER_ACCEPT);
+    return m_condition ? m_condition->acceptNode(exec, node) : static_cast<short>(FILTER_ACCEPT);
 }
 
+ExecState* NodeFilter::execStateFromNode(Node* node)
+{
+    if (!node)
+        return 0;
+    Document* document = node->document();
+    if (!document)
+        return 0;
+    Frame* frame = document->frame();
+    if (!frame)
+        return 0;
+
+    if (!frame->script()->isEnabled())
+        return 0;
+
+    return frame->script()->globalObject()->globalExec();
+}
+
+
 } // namespace WebCore
index e9f25e6..d0afb9c 100644 (file)
@@ -70,14 +70,18 @@ namespace WebCore {
             return adoptRef(new NodeFilter(condition));
         }
 
-        short acceptNode(Node*, KJS::JSValue*& exception) const;
+        short acceptNode(KJS::ExecState*, Node*) const;
         void mark() { m_condition->mark(); };
 
         // For non-JS bindings. Silently ignores the JavaScript exception if any.
-        short acceptNode(Node* node) const { KJS::JSValue* exception; return acceptNode(node, exception); }
+        short acceptNode(Node* node) const { return acceptNode(execStateFromNode(node), node); }
+
+    public:
+        static KJS::ExecState* execStateFromNode(Node*);
 
     private:
         NodeFilter(PassRefPtr<NodeFilterCondition> condition) : m_condition(condition) { }
+
         RefPtr<NodeFilterCondition> m_condition;
     };
 
index 48bdcb4..0fd3513 100644 (file)
@@ -31,7 +31,7 @@ using namespace KJS;
 
 namespace WebCore {
 
-short NodeFilterCondition::acceptNode(Node*, JSValue*&) const
+short NodeFilterCondition::acceptNode(ExecState*, Node*) const
 {
     return NodeFilter::FILTER_ACCEPT;
 }
index 69250a5..85a958a 100644 (file)
@@ -28,7 +28,7 @@
 #include <wtf/RefCounted.h>
 
 namespace KJS {
-    class JSValue;
+    class ExecState;
 }
 
 namespace WebCore {
@@ -38,7 +38,7 @@ namespace WebCore {
     class NodeFilterCondition : public RefCounted<NodeFilterCondition> {
     public:
         virtual ~NodeFilterCondition() { }
-        virtual short acceptNode(Node*, KJS::JSValue*& exception) const = 0;
+        virtual short acceptNode(KJS::ExecState*, Node*) const = 0;
         virtual void mark() { }
     };
 
index e22e8e6..ef49a7d 100644 (file)
@@ -25,6 +25,7 @@
 #include "config.h"
 #include "NodeIterator.h"
 
+#include <kjs/ExecState.h>
 #include "Document.h"
 #include "ExceptionCode.h"
 #include "NodeFilter.h"
@@ -85,7 +86,7 @@ NodeIterator::~NodeIterator()
     root()->document()->detachNodeIterator(this);
 }
 
-PassRefPtr<Node> NodeIterator::nextNode(ExceptionCode& ec, JSValue*& exception)
+PassRefPtr<Node> NodeIterator::nextNode(ExecState* exec, ExceptionCode& ec)
 {
     if (m_detached) {
         ec = INVALID_STATE_ERR;
@@ -99,10 +100,9 @@ PassRefPtr<Node> NodeIterator::nextNode(ExceptionCode& ec, JSValue*& exception)
         // NodeIterators treat the DOM tree as a flat list of nodes.
         // In other words, FILTER_REJECT does not pass over descendants
         // of the rejected node. Hence, FILTER_REJECT is the same as FILTER_SKIP.
-        exception = 0;
         RefPtr<Node> provisionalResult = m_candidateNode.node;
-        bool nodeWasAccepted = acceptNode(provisionalResult.get(), exception) == NodeFilter::FILTER_ACCEPT;
-        if (exception)
+        bool nodeWasAccepted = acceptNode(exec, provisionalResult.get()) == NodeFilter::FILTER_ACCEPT;
+        if (exec && exec->hadException())
             break;
         if (nodeWasAccepted) {
             m_referenceNode = m_candidateNode;
@@ -115,7 +115,7 @@ PassRefPtr<Node> NodeIterator::nextNode(ExceptionCode& ec, JSValue*& exception)
     return result.release();
 }
 
-PassRefPtr<Node> NodeIterator::previousNode(ExceptionCode& ec, JSValue*& exception)
+PassRefPtr<Node> NodeIterator::previousNode(ExecState* exec, ExceptionCode& ec)
 {
     if (m_detached) {
         ec = INVALID_STATE_ERR;
@@ -129,10 +129,9 @@ PassRefPtr<Node> NodeIterator::previousNode(ExceptionCode& ec, JSValue*& excepti
         // NodeIterators treat the DOM tree as a flat list of nodes.
         // In other words, FILTER_REJECT does not pass over descendants
         // of the rejected node. Hence, FILTER_REJECT is the same as FILTER_SKIP.
-        exception = 0;
         RefPtr<Node> provisionalResult = m_candidateNode.node;
-        bool nodeWasAccepted = acceptNode(provisionalResult.get(), exception) == NodeFilter::FILTER_ACCEPT;
-        if (exception)
+        bool nodeWasAccepted = acceptNode(exec, provisionalResult.get()) == NodeFilter::FILTER_ACCEPT;
+        if (exec && exec->hadException())
             break;
         if (nodeWasAccepted) {
             m_referenceNode = m_candidateNode;
@@ -227,4 +226,5 @@ void NodeIterator::updateForNodeRemoval(Node* removedNode, NodePointer& referenc
     }
 }
 
+
 } // namespace WebCore
index 758c1ca..d2c6075 100644 (file)
@@ -25,6 +25,7 @@
 #ifndef NodeIterator_h
 #define NodeIterator_h
 
+#include "NodeFilter.h"
 #include "Traversal.h"
 #include <wtf/PassRefPtr.h>
 #include <wtf/RefCounted.h>
@@ -41,8 +42,8 @@ namespace WebCore {
         }
         ~NodeIterator();
 
-        PassRefPtr<Node> nextNode(ExceptionCode&, KJS::JSValue*& exception);
-        PassRefPtr<Node> previousNode(ExceptionCode&, KJS::JSValue*& exception);
+        PassRefPtr<Node> nextNode(KJS::ExecState*, ExceptionCode&);
+        PassRefPtr<Node> previousNode(KJS::ExecState*, ExceptionCode&);
         void detach();
 
         Node* referenceNode() const { return m_referenceNode.node.get(); }
@@ -52,8 +53,8 @@ namespace WebCore {
         void nodeWillBeRemoved(Node*);
 
         // For non-JS bindings. Silently ignores the JavaScript exception if any.
-        PassRefPtr<Node> nextNode(ExceptionCode& ec) { KJS::JSValue* exception; return nextNode(ec, exception); }
-        PassRefPtr<Node> previousNode(ExceptionCode& ec) { KJS::JSValue* exception; return previousNode(ec, exception); }
+        PassRefPtr<Node> nextNode(ExceptionCode& ec) { return nextNode(NodeFilter::execStateFromNode(referenceNode()), ec); }
+        PassRefPtr<Node> previousNode(ExceptionCode& ec) { return previousNode(NodeFilter::execStateFromNode(referenceNode()), ec); }
 
     private:
         NodeIterator(PassRefPtr<Node>, unsigned whatToShow, PassRefPtr<NodeFilter>, bool expandEntityReferences);
index cf44d15..3909c7f 100644 (file)
@@ -40,17 +40,17 @@ Traversal::Traversal(PassRefPtr<Node> rootNode, unsigned whatToShow, PassRefPtr<
 {
 }
 
-short Traversal::acceptNode(Node* node, JSValue*& exception) const
+short Traversal::acceptNode(ExecState* exec, Node* node) const
 {
     // FIXME: To handle XML properly we would have to check m_expandEntityReferences.
 
-    // The bid twiddling here is done to map DOM node types, which are given as integers from
+    // The bit twiddling here is done to map DOM node types, which are given as integers from
     // 1 through 12, to whatToShow bit masks.
     if (!(((1 << (node->nodeType() - 1)) & m_whatToShow)))
         return NodeFilter::FILTER_SKIP;
     if (!m_filter)
         return NodeFilter::FILTER_ACCEPT;
-    return m_filter->acceptNode(node, exception);
+    return m_filter->acceptNode(exec, node);
 }
 
 } // namespace WebCore
index ca54797..7a922b0 100644 (file)
@@ -30,6 +30,7 @@
 
 namespace KJS {
     class JSValue;
+    class ExecState;
 }
 
 namespace WebCore {
@@ -46,7 +47,7 @@ namespace WebCore {
 
     protected:
         Traversal(PassRefPtr<Node>, unsigned whatToShow, PassRefPtr<NodeFilter>, bool expandEntityReferences);
-        short acceptNode(Node*, KJS::JSValue*& jsException) const;
+        short acceptNode(KJS::ExecState*, Node*) const;
 
     private:
         RefPtr<Node> m_root;
index 09c1c95..449cb61 100644 (file)
@@ -25,6 +25,7 @@
 #include "config.h"
 #include "TreeWalker.h"
 
+#include <kjs/ExecState.h>
 #include "ExceptionCode.h"
 #include "Node.h"
 #include "NodeFilter.h"
@@ -55,16 +56,15 @@ inline Node* TreeWalker::setCurrent(PassRefPtr<Node> node)
     return m_current.get();
 }
 
-Node* TreeWalker::parentNode(JSValue*& exception)
+Node* TreeWalker::parentNode(ExecState* exec)
 {
-    exception = 0;
     RefPtr<Node> node = m_current;
     while (node != root()) {
         node = node->parentNode();
         if (!node)
             return 0;
-        short acceptNodeResult = acceptNode(node.get(), exception);
-        if (exception)
+        short acceptNodeResult = acceptNode(exec, node.get());
+        if (exec && exec->hadException())
             return 0;
         if (acceptNodeResult == NodeFilter::FILTER_ACCEPT)
             return setCurrent(node.release());
@@ -72,12 +72,11 @@ Node* TreeWalker::parentNode(JSValue*& exception)
     return 0;
 }
 
-Node* TreeWalker::firstChild(JSValue*& exception)
+Node* TreeWalker::firstChild(ExecState* exec)
 {
-    exception = 0;
     for (RefPtr<Node> node = m_current->firstChild(); node; ) {
-        short acceptNodeResult = acceptNode(node.get(), exception);
-        if (exception)
+        short acceptNodeResult = acceptNode(exec, node.get());
+        if (exec && exec->hadException())
             return 0;
         switch (acceptNodeResult) {
             case NodeFilter::FILTER_ACCEPT:
@@ -106,12 +105,11 @@ Node* TreeWalker::firstChild(JSValue*& exception)
     return 0;
 }
 
-Node* TreeWalker::lastChild(JSValue*& exception)
+Node* TreeWalker::lastChild(ExecState* exec)
 {
-    exception = 0;
     for (RefPtr<Node> node = m_current->lastChild(); node; ) {
-        short acceptNodeResult = acceptNode(node.get(), exception);
-        if (exception)
+        short acceptNodeResult = acceptNode(exec, node.get());
+        if (exec && exec->hadException())
             return 0;
         switch (acceptNodeResult) {
             case NodeFilter::FILTER_ACCEPT:
@@ -140,16 +138,15 @@ Node* TreeWalker::lastChild(JSValue*& exception)
     return 0;
 }
 
-Node* TreeWalker::previousSibling(JSValue*& exception)
+Node* TreeWalker::previousSibling(ExecState* exec)
 {
-    exception = 0;
     RefPtr<Node> node = m_current;
     if (node == root())
         return 0;
     while (1) {
         for (RefPtr<Node> sibling = node->previousSibling(); sibling; ) {
-            short acceptNodeResult = acceptNode(sibling.get(), exception);
-            if (exception)
+            short acceptNodeResult = acceptNode(exec, sibling.get());
+            if (exec && exec->hadException())
                 return 0;
             switch (acceptNodeResult) {
                 case NodeFilter::FILTER_ACCEPT:
@@ -169,24 +166,23 @@ Node* TreeWalker::previousSibling(JSValue*& exception)
         node = node->parentNode();
         if (!node || node == root())
             return 0;
-        short acceptNodeResult = acceptNode(node.get(), exception);
-        if (exception)
+        short acceptNodeResult = acceptNode(exec, node.get());
+        if (exec && exec->hadException())
             return 0;
         if (acceptNodeResult == NodeFilter::FILTER_ACCEPT)
             return 0;
     }
 }
 
-Node* TreeWalker::nextSibling(JSValue*& exception)
+Node* TreeWalker::nextSibling(ExecState* exec)
 {
-    exception = 0;
     RefPtr<Node> node = m_current;
     if (node == root())
         return 0;
     while (1) {
         for (RefPtr<Node> sibling = node->nextSibling(); sibling; ) {
-            short acceptNodeResult = acceptNode(sibling.get(), exception);
-            if (exception)
+            short acceptNodeResult = acceptNode(exec, sibling.get());
+            if (exec && exec->hadException())
                 return 0;
             switch (acceptNodeResult) {
                 case NodeFilter::FILTER_ACCEPT:
@@ -206,30 +202,29 @@ Node* TreeWalker::nextSibling(JSValue*& exception)
         node = node->parentNode();
         if (!node || node == root())
             return 0;
-        short acceptNodeResult = acceptNode(node.get(), exception);
-        if (exception)
+        short acceptNodeResult = acceptNode(exec, node.get());
+        if (exec && exec->hadException())
             return 0;
         if (acceptNodeResult == NodeFilter::FILTER_ACCEPT)
             return 0;
     }
 }
 
-Node* TreeWalker::previousNode(JSValue*& exception)
+Node* TreeWalker::previousNode(ExecState* exec)
 {
-    exception = 0;
     RefPtr<Node> node = m_current;
     while (node != root()) {
         while (Node* previousSibling = node->previousSibling()) {
             node = previousSibling;
-            short acceptNodeResult = acceptNode(node.get(), exception);
-            if (exception)
+            short acceptNodeResult = acceptNode(exec, node.get());
+            if (exec && exec->hadException())
                 return 0;
             if (acceptNodeResult == NodeFilter::FILTER_REJECT)
                 continue;
             while (Node* lastChild = node->lastChild()) {
                 node = lastChild;
-                acceptNodeResult = acceptNode(node.get(), exception);
-                if (exception)
+                acceptNodeResult = acceptNode(exec, node.get());
+                if (exec && exec->hadException())
                     return 0;
                 if (acceptNodeResult == NodeFilter::FILTER_ACCEPT)
                     continue;
@@ -245,8 +240,8 @@ Node* TreeWalker::previousNode(JSValue*& exception)
         if (!parent)
             return 0;
         node = parent;
-        short acceptNodeResult = acceptNode(node.get(), exception);
-        if (exception)
+        short acceptNodeResult = acceptNode(exec, node.get());
+        if (exec && exec->hadException())
             return 0;
         if (acceptNodeResult == NodeFilter::FILTER_ACCEPT)
             return setCurrent(node.release());
@@ -254,15 +249,14 @@ Node* TreeWalker::previousNode(JSValue*& exception)
     return 0;
 }
 
-Node* TreeWalker::nextNode(JSValue*& exception)
+Node* TreeWalker::nextNode(ExecState* exec)
 {
-    exception = 0;
     RefPtr<Node> node = m_current;
 Children:
     while (Node* firstChild = node->firstChild()) {
         node = firstChild;
-        short acceptNodeResult = acceptNode(node.get(), exception);
-        if (exception)
+        short acceptNodeResult = acceptNode(exec, node.get());
+        if (exec && exec->hadException())
             return 0;
         if (acceptNodeResult == NodeFilter::FILTER_ACCEPT)
             return setCurrent(node.release());
@@ -271,8 +265,8 @@ Children:
     }
     while (Node* nextSibling = node->traverseNextSibling(root())) {
         node = nextSibling;
-        short acceptNodeResult = acceptNode(node.get(), exception);
-        if (exception)
+        short acceptNodeResult = acceptNode(exec, node.get());
+        if (exec && exec->hadException())
             return 0;
         if (acceptNodeResult == NodeFilter::FILTER_ACCEPT)
             return setCurrent(node.release());
index 41388be..90bbf96 100644 (file)
@@ -25,6 +25,7 @@
 #ifndef TreeWalker_h
 #define TreeWalker_h
 
+#include "NodeFilter.h"
 #include "Traversal.h"
 #include <wtf/PassRefPtr.h>
 #include <wtf/RefCounted.h>
@@ -43,22 +44,22 @@ namespace WebCore {
         Node* currentNode() const { return m_current.get(); }
         void setCurrentNode(PassRefPtr<Node>, ExceptionCode&);
 
-        Node* parentNode(KJS::JSValue*& exception);
-        Node* firstChild(KJS::JSValue*& exception);
-        Node* lastChild(KJS::JSValue*& exception);
-        Node* previousSibling(KJS::JSValue*& exception);
-        Node* nextSibling(KJS::JSValue*& exception);
-        Node* previousNode(KJS::JSValue*& exception);
-        Node* nextNode(KJS::JSValue*& exception);
+        Node* parentNode(KJS::ExecState*);
+        Node* firstChild(KJS::ExecState*);
+        Node* lastChild(KJS::ExecState*);
+        Node* previousSibling(KJS::ExecState*);
+        Node* nextSibling(KJS::ExecState*);
+        Node* previousNode(KJS::ExecState*);
+        Node* nextNode(KJS::ExecState*);
 
         // For non-JS bindings. Silently ignores the JavaScript exception if any.
-        Node* parentNode() { KJS::JSValue* exception; return parentNode(exception); }
-        Node* firstChild() { KJS::JSValue* exception; return firstChild(exception); }
-        Node* lastChild() { KJS::JSValue* exception; return lastChild(exception); }
-        Node* previousSibling() { KJS::JSValue* exception; return previousSibling(exception); }
-        Node* nextSibling() { KJS::JSValue* exception; return nextSibling(exception); }
-        Node* previousNode() { KJS::JSValue* exception; return previousNode(exception); }
-        Node* nextNode() { KJS::JSValue* exception; return nextNode(exception); }
+        Node* parentNode() { return parentNode(NodeFilter::execStateFromNode(m_current.get())); }
+        Node* firstChild() { return firstChild(NodeFilter::execStateFromNode(m_current.get())); }
+        Node* lastChild() { return lastChild(NodeFilter::execStateFromNode(m_current.get())); }
+        Node* previousSibling() { return previousSibling(NodeFilter::execStateFromNode(m_current.get())); }
+        Node* nextSibling() { return nextSibling(NodeFilter::execStateFromNode(m_current.get())); }
+        Node* previousNode() { return previousNode(NodeFilter::execStateFromNode(m_current.get())); }
+        Node* nextNode() { return nextNode(NodeFilter::execStateFromNode(m_current.get())); }
 
     private:
         TreeWalker(PassRefPtr<Node>, unsigned whatToShow, PassRefPtr<NodeFilter>, bool expandEntityReferences);