- landed fix for <http://bugzilla.opendarwin.org/show_bug.cgi?id=3677>
authorggaren <ggaren@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 14 Jul 2005 17:58:17 +0000 (17:58 +0000)
committerggaren <ggaren@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 14 Jul 2005 17:58:17 +0000 (17:58 +0000)
        Safari fail to access a second time an element whose content was dynamically modified.

        - patch by Anders Carlsson <andersca@mac.com>.

        Reviewed by mjs + darin.

        Test cases added:
        * layout-tests/fast/dom/ids/duplicate-ids-expected.txt: Added.
        * layout-tests/fast/dom/ids/duplicate-ids.html: Added.

        * khtml/xml/dom_docimpl.cpp:
        (DocumentImpl::getElementById):
        If no element in the id dict can be found and we know that there's
        at least one other element with the same id around, then traverse the document
        and insert the new element in the id table.

        (DocumentImpl::addElementById):
        (DocumentImpl::removeElementById):
        Increment and decrement the id count accordingly.

        * khtml/xml/dom_docimpl.h:
        Add QDict for id counts. Make element QDict mutable.

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

LayoutTests/fast/dom/duplicate-ids-expected.txt [new file with mode: 0644]
LayoutTests/fast/dom/duplicate-ids.html [new file with mode: 0644]
WebCore/ChangeLog-2005-08-23
WebCore/khtml/xml/dom_docimpl.cpp
WebCore/khtml/xml/dom_docimpl.h

diff --git a/LayoutTests/fast/dom/duplicate-ids-expected.txt b/LayoutTests/fast/dom/duplicate-ids-expected.txt
new file mode 100644 (file)
index 0000000..2a28a33
--- /dev/null
@@ -0,0 +1,4 @@
+This tests that getElementById works as elements with duplicate ids are added and removed. If the test is successful, the text "success" should be shown below.
+This is the first duplicate div
+This is the second duplicate div
+Success!
diff --git a/LayoutTests/fast/dom/duplicate-ids.html b/LayoutTests/fast/dom/duplicate-ids.html
new file mode 100644 (file)
index 0000000..9b1f14b
--- /dev/null
@@ -0,0 +1,59 @@
+<html>
+<head>
+<script>
+function debug(str) {
+       console = document.getElementById('console');
+
+       li = document.createElement('li');
+       console.appendChild(li);
+       li.appendChild(document.createTextNode(str));   
+}
+
+function runTests() { 
+       if (window.layoutTestController) { 
+               layoutTestController.dumpAsText();
+       }
+       div = document.getElementById('duplicate');
+       dup1 = div.parentNode.removeChild(div);
+
+       div = document.getElementById('duplicate');
+       if (!div) {
+               debug('Failed: getElementById returned null');
+               return;
+       }
+       
+       if (div.firstChild.nodeValue != 'This is the second duplicate div') {
+               debug('Failed: getElementById returned the wrong div');
+               return;
+       }
+       
+       dup2 = div.parentNode.removeChild(div);
+       if (document.getElementById('duplicate')) {
+               debug('Failed: getElementById did not return null');
+               return;
+       }
+       
+       // Now insert the nodes again
+       container = document.getElementById('container');
+       container.appendChild(dup1);
+       container.appendChild(dup2);
+       
+       if (!document.getElementById('duplicate')) {
+               debug('Failed: getElementById returned null');
+               return;
+       }
+       
+       debug('Success!');
+}
+</script>
+</head>
+<body onLoad="runTests()">
+This tests that getElementById works as elements with duplicate ids are added and removed. If the test is successful, the text "success" should be shown below.
+<div id="container">
+<div id="duplicate">This is the first duplicate div</div>
+<div id="duplicate">This is the second duplicate div</div>
+</div>
+<ul id="console">
+</li>
+</body>
+</html>
index 6ad0ffd4e559f3f54026c70d0ab98afc6fa10bee..871e9e55c2515170cc2605a9960ac75f2e0f8209 100644 (file)
@@ -1,7 +1,33 @@
 2005-07-14  Geoffrey Garen  <ggaren@apple.com>
 
-       -landed layout test for http://bugzilla.opendarwin.org/show_bug.cgi?id=3412
-       Object.prototype is missing toLocaleString
+        - landed fix for <http://bugzilla.opendarwin.org/show_bug.cgi?id=3677>
+        Safari fail to access a second time an element whose content was dynamically modified.
+        
+        - patch by Anders Carlsson <andersca@mac.com>.
+
+        Reviewed by mjs + darin.
+
+        Test cases added:
+        * layout-tests/fast/dom/ids/duplicate-ids-expected.txt: Added.
+        * layout-tests/fast/dom/ids/duplicate-ids.html: Added.
+        
+        * khtml/xml/dom_docimpl.cpp:
+        (DocumentImpl::getElementById):
+        If no element in the id dict can be found and we know that there's
+        at least one other element with the same id around, then traverse the document
+        and insert the new element in the id table.
+        
+        (DocumentImpl::addElementById):
+        (DocumentImpl::removeElementById):
+        Increment and decrement the id count accordingly.
+        
+        * khtml/xml/dom_docimpl.h:
+        Add QDict for id counts. Make element QDict mutable.
+
+2005-07-14  Geoffrey Garen  <ggaren@apple.com>
+
+        -landed layout test for http://bugzilla.opendarwin.org/show_bug.cgi?id=3412
+        Object.prototype is missing toLocaleString
 
         Reviewed by mjs.
 
index c145cf870f7f21aa09dce9b1d91ac2726109cd27..ebf7148976c9716111c6140b6380c1d2d750689b 100644 (file)
@@ -662,11 +662,37 @@ ElementImpl *DocumentImpl::createElementNS( const DOMString &_namespaceURI, cons
 
 ElementImpl *DocumentImpl::getElementById( const DOMString &elementId ) const
 {
+    ElementImpl *element;
+    QString qId = elementId.string();
+
     if (elementId.length() == 0) {
-       return 0;
+        return 0;
     }
 
-    return m_elementsById.find(elementId.string());
+    element = m_elementsById.find(qId);
+    
+    if (element)
+        return element;
+        
+    if (int idCount = (int)m_idCount.find(qId)) {
+        for (NodeImpl *n = traverseNextNode(); n != 0; n = n->traverseNextNode()) {
+            if (!n->isElementNode())
+                continue;
+            
+            element = static_cast<ElementImpl *>(n);
+            
+            if (element->hasID() && element->getAttribute(ATTR_ID) == elementId) {
+                if (idCount == 1) 
+                    m_idCount.remove(qId);
+                else
+                    m_idCount.insert(qId, (char *)idCount - 1);
+                
+                m_elementsById.insert(qId, element);
+                return element;
+            }
+        }
+    }
+    return 0;
 }
 
 ElementImpl *DocumentImpl::elementFromPoint( const int _x, const int _y ) const
@@ -687,10 +713,13 @@ ElementImpl *DocumentImpl::elementFromPoint( const int _x, const int _y ) const
 void DocumentImpl::addElementById(const DOMString &elementId, ElementImpl *element)
 {
     QString qId = elementId.string();
-
+    
     if (m_elementsById.find(qId) == NULL) {
-       m_elementsById.insert(qId, element);
+        m_elementsById.insert(qId, element);
         m_accessKeyDictValid = false;
+    } else {
+        int idCount = (int)m_idCount.find(qId);
+        m_idCount.insert(qId, (char *)(idCount + 1));
     }
 }
 
@@ -699,8 +728,15 @@ void DocumentImpl::removeElementById(const DOMString &elementId, ElementImpl *el
     QString qId = elementId.string();
 
     if (m_elementsById.find(qId) == element) {
-       m_elementsById.remove(qId);
+        m_elementsById.remove(qId);
         m_accessKeyDictValid = false;
+    } else {
+        int idCount = (int)m_idCount.find(qId);        
+        assert(idCount > 0);
+        if (idCount == 1) 
+            m_idCount.remove(qId);
+        else
+            m_idCount.insert(qId, (char *)(idCount - 1));
     }
 }
 
index ec6da125ab6a55c6d0ed1d4fdab8da44db3fcb2d..c23e960a6d8a94fe8f15dc0d0aac0bae0254d05a 100644 (file)
@@ -755,7 +755,8 @@ private:
     
     khtml::Decoder *m_decoder;
 
-    QDict<ElementImpl> m_elementsById;
+    mutable QDict<ElementImpl> m_elementsById;
+    mutable QDict<char> m_idCount;
     
     QDict<ElementImpl> m_elementsByAccessKey;
     bool m_accessKeyDictValid;