Reviewed by Darin.
authormjs <mjs@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 14 Dec 2003 23:50:33 +0000 (23:50 +0000)
committermjs <mjs@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 14 Dec 2003 23:50:33 +0000 (23:50 +0000)
<rdar://problem/3269212>: FILEMAKER: can't use Option objects created in a different window

        * khtml/ecma/kjs_binding.cpp:
        (ScriptInterpreter::updateDOMObjectDocument): Update per-document
caching for the DOM object - let it be protected by both the old
and the new document.
        * khtml/ecma/kjs_binding.h: Prototype new method.
        * khtml/xml/dom_nodeimpl.cpp:
        (NodeImpl::setDocument): New method to change a node's document pointer.
        (NodeImpl::checkAddChild): If the new child node is owned by the
wrong document but not actually in it, change its document (using
the two aforementioned methods) instead of throwing an exception.
* khtml/xml/dom_nodeimpl.h: Prototype new method.

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

WebCore/ChangeLog-2005-08-23
WebCore/khtml/ecma/kjs_binding.cpp
WebCore/khtml/ecma/kjs_binding.h
WebCore/khtml/xml/dom_nodeimpl.cpp
WebCore/khtml/xml/dom_nodeimpl.h

index b45ac7f..c67a233 100644 (file)
@@ -1,3 +1,21 @@
+2003-12-13  Maciej Stachowiak  <mjs@apple.com>
+
+        Reviewed by Darin.
+
+       <rdar://problem/3269212>: FILEMAKER: can't use Option objects created in a different window
+
+        * khtml/ecma/kjs_binding.cpp:
+        (ScriptInterpreter::updateDOMObjectDocument): Update per-document
+       caching for the DOM object - let it be protected by both the old
+       and the new document.
+        * khtml/ecma/kjs_binding.h: Prototype new method.
+        * khtml/xml/dom_nodeimpl.cpp:
+        (NodeImpl::setDocument): New method to change a node's document pointer.
+        (NodeImpl::checkAddChild): If the new child node is owned by the
+       wrong document but not actually in it, change its document (using
+       the two aforementioned methods) instead of throwing an exception.
+       * khtml/xml/dom_nodeimpl.h: Prototype new method.
+
 2003-12-14  Darin Adler  <darin@apple.com>
 
         Reviewed by Maciej.
index 00818f8..aef11db 100644 (file)
@@ -226,6 +226,25 @@ void ScriptInterpreter::forgetDOMObjectsForDocument( DOM::DocumentImpl* document
   }
 }
 
+void ScriptInterpreter::updateDOMObjectDocument(void *objectHandle, DOM::DocumentImpl *oldDoc, DOM::DocumentImpl *newDoc)
+{
+  InterpreterImp *first = InterpreterImp::firstInterpreter();
+  if (first) {
+    InterpreterImp *scr = first;
+    do {
+      if ( scr->interpreter()->rtti() == 1 ) {
+       ScriptInterpreter *interp = static_cast<ScriptInterpreter *>(scr->interpreter());
+       
+       DOMObject* cachedObject = interp->getDOMObjectForDocument(oldDoc, objectHandle);
+       if (cachedObject) {
+         interp->putDOMObjectForDocument(newDoc, objectHandle, cachedObject);
+       }
+      }
+       
+      scr = scr->nextInterpreter();
+    } while (scr != first);
+  }
+}
 
 bool ScriptInterpreter::wasRunByUserGesture() const
 {
index d8e9f7a..bddd990 100644 (file)
@@ -109,6 +109,9 @@ namespace KJS {
     static void forgetDOMObject( void* objectHandle );
     static void forgetDOMObjectsForDocument( DOM::DocumentImpl* documentHandle );
 
+    static void updateDOMObjectDocument(void *objectHandle, DOM::DocumentImpl *oldDoc, DOM::DocumentImpl *newDoc);
+
+
     KHTMLPart* part() const { return m_part; }
 
     virtual int rtti() { return 1; }
index 6c467f5..0c4a942 100644 (file)
@@ -38,6 +38,7 @@
 
 #include "rendering/render_text.h"
 
+#include "ecma/kjs_binding.h"
 #include "ecma/kjs_proxy.h"
 #include "khtmlview.h"
 #include "khtml_part.h"
@@ -75,6 +76,20 @@ NodeImpl::NodeImpl(DocumentPtr *doc)
         document->ref();
 }
 
+void NodeImpl::setDocument(DocumentPtr *doc)
+{
+    if (inDocument())
+       return;
+    
+    if (doc)
+       doc->ref();
+    
+    if (document)
+       document->deref();
+
+    document = doc;
+}
+
 NodeImpl::~NodeImpl()
 {
     if (m_render)
@@ -881,13 +896,23 @@ void NodeImpl::checkAddChild(NodeImpl *newChild, int &exceptioncode)
         return;
     }
 
+    bool shouldAdoptChild = false;
+
     // WRONG_DOCUMENT_ERR: Raised if newChild was created from a different document than the one that
     // created this node.
     // We assume that if newChild is a DocumentFragment, all children are created from the same document
     // as the fragment itself (otherwise they could not have been added as children)
     if (newChild->getDocument() != getDocument()) {
-        exceptioncode = DOMException::WRONG_DOCUMENT_ERR;
-        return;
+       // but if the child is not in a document yet then loosen the
+       // restriction, so that e.g. creating an element with the Option()
+       // constructor and then adding it to a different document works,
+       // as it does in Mozilla and Mac IE.
+       if (!newChild->inDocument()) {
+           shouldAdoptChild = true;
+       } else {
+           exceptioncode = DOMException::WRONG_DOCUMENT_ERR;
+           return;
+       }
     }
 
     // HIERARCHY_REQUEST_ERR: Raised if this node is of a type that does not allow children of the type of the
@@ -917,6 +942,12 @@ void NodeImpl::checkAddChild(NodeImpl *newChild, int &exceptioncode)
             return;
         }
     }
+
+    // only do this once we know there won't be an exception
+    if (shouldAdoptChild) {
+       KJS::ScriptInterpreter::updateDOMObjectDocument(newChild, newChild->getDocument(), getDocument());
+       newChild->setDocument(getDocument()->docPtr());
+    }
 }
 
 bool NodeImpl::isAncestor( NodeImpl *other )
index 8312547..670747b 100644 (file)
@@ -222,6 +222,8 @@ public:
     // DOM's ownerDocument() which is null for Document nodes (and sometimes DocumentType nodes).
     DocumentImpl* getDocument() const { return document->document(); }
 
+    void setDocument(DocumentPtr *doc);
+
     void addEventListener(int id, EventListener *listener, const bool useCapture);
     void removeEventListener(int id, EventListener *listener, bool useCapture);
     void removeHTMLEventListener(int id);