Backed out changeset 78df45be19d1 due to test failures caused by it but were hidden because of lack of support for adoptNode, which was fixed in a4813c8be814, a=orange
authorJohnny Stenback <jst@mozilla.com>
Thu, 02 Dec 2010 23:36:00 -0800
changeset 58537 e243ef4f1e0eed4279c5d7886d09108fe4c14e84
parent 58395 78df45be19d18b39bc8ce68d3eb23ff46d7cfa7a
child 58538 0ff6d59842870cf6c29e07f082a66d4e15306567
push id1
push usershaver@mozilla.com
push dateTue, 04 Jan 2011 17:58:04 +0000
reviewersorange
milestone2.0b8pre
backs out78df45be19d18b39bc8ce68d3eb23ff46d7cfa7a
Backed out changeset 78df45be19d1 due to test failures caused by it but were hidden because of lack of support for adoptNode, which was fixed in a4813c8be814, a=orange
content/base/public/nsContentUtils.h
content/base/src/nsContentUtils.cpp
content/base/src/nsDOMDocumentType.cpp
content/base/src/nsDocument.cpp
--- a/content/base/public/nsContentUtils.h
+++ b/content/base/public/nsContentUtils.h
@@ -187,28 +187,30 @@ struct nsShortcutCandidate {
 class nsContentUtils
 {
   typedef mozilla::dom::Element Element;
 
 public:
   static nsresult Init();
 
   /**
-   * Get a scope from aNewDocument. Also get a context through the scope of one
-   * of the documents, from the stack or the safe context.
+   * Get a scope from aOldDocument and one from aNewDocument. Also get a
+   * context through one of the scopes, from the stack or the safe context.
    *
-   * @param aOldDocument The document to try to get a context from. May be null.
+   * @param aOldDocument The document to get aOldScope from.
    * @param aNewDocument The document to get aNewScope from.
    * @param aCx [out] Context gotten through one of the scopes, from the stack
    *                  or the safe context.
+   * @param aOldScope [out] Scope gotten from aOldDocument.
    * @param aNewScope [out] Scope gotten from aNewDocument.
    */
-  static nsresult GetContextAndScope(nsIDocument *aOldDocument,
-                                     nsIDocument *aNewDocument,
-                                     JSContext **aCx, JSObject **aNewScope);
+  static nsresult GetContextAndScopes(nsIDocument *aOldDocument,
+                                      nsIDocument *aNewDocument,
+                                      JSContext **aCx, JSObject **aOldScope,
+                                      JSObject **aNewScope);
 
   /**
    * When a document's scope changes (e.g., from document.open(), call this
    * function to move all content wrappers from the old scope to the new one.
    */
   static nsresult ReparentContentWrappersInScope(nsIScriptGlobalObject *aOldScope,
                                                  nsIScriptGlobalObject *aNewScope);
 
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -1366,57 +1366,74 @@ nsContentUtils::InProlog(nsINode *aNode)
 
   nsIDocument* doc = static_cast<nsIDocument*>(parent);
   nsIContent* root = doc->GetRootElement();
 
   return !root || doc->IndexOf(aNode) < doc->IndexOf(root);
 }
 
 static JSContext *
-GetContextFromDocument(nsIDocument *aDocument)
+GetContextFromDocument(nsIDocument *aDocument, JSObject** aGlobalObject)
 {
   nsIScriptGlobalObject *sgo = aDocument->GetScopeObject();
   if (!sgo) {
     // No script global, no context.
+
+    *aGlobalObject = nsnull;
+
     return nsnull;
   }
 
+  *aGlobalObject = sgo->GetGlobalJSObject();
+
   nsIScriptContext *scx = sgo->GetContext();
   if (!scx) {
-    // No context left in the scope...
+    // No context left in the old scope...
 
     return nsnull;
   }
 
   return (JSContext *)scx->GetNativeContext();
 }
 
 // static
 nsresult
-nsContentUtils::GetContextAndScope(nsIDocument *aOldDocument,
-                                   nsIDocument *aNewDocument, JSContext **aCx,
-                                   JSObject **aNewScope)
+nsContentUtils::GetContextAndScopes(nsIDocument *aOldDocument,
+                                    nsIDocument *aNewDocument, JSContext **aCx,
+                                    JSObject **aOldScope, JSObject **aNewScope)
 {
   *aCx = nsnull;
+  *aOldScope = nsnull;
   *aNewScope = nsnull;
 
-  JSObject *newScope = aNewDocument->GetWrapper();
-  JSObject *global;
-  if (!newScope) {
-    nsIScriptGlobalObject *newSGO = aNewDocument->GetScopeObject();
-    if (!newSGO || !(global = newSGO->GetGlobalJSObject())) {
-      return NS_OK;
-    }
+  JSObject *newScope = nsnull;
+  nsIScriptGlobalObject *newSGO = aNewDocument->GetScopeObject();
+  if (!newSGO || !(newScope = newSGO->GetGlobalJSObject())) {
+    return NS_OK;
   }
 
   NS_ENSURE_TRUE(sXPConnect, NS_ERROR_NOT_INITIALIZED);
 
-  JSContext *cx = aOldDocument ? GetContextFromDocument(aOldDocument) : nsnull;
+  // Make sure to get our hands on the right scope object, since
+  // GetWrappedNativeOfNativeObject doesn't call PreCreate and hence won't get
+  // the right scope if we pass in something bogus.  The right scope lives on
+  // the script global of the old document.
+  // XXXbz note that if GetWrappedNativeOfNativeObject did call PreCreate it
+  // would get the wrong scope (that of the _new_ document), so we should be
+  // glad it doesn't!
+  JSObject *oldScope = nsnull;
+  JSContext *cx = GetContextFromDocument(aOldDocument, &oldScope);
+
+  if (!oldScope) {
+    return NS_OK;
+  }
+
   if (!cx) {
-    cx = GetContextFromDocument(aNewDocument);
+    JSObject *dummy;
+    cx = GetContextFromDocument(aNewDocument, &dummy);
 
     if (!cx) {
       // No context reachable from the old or new document, use the
       // calling context, or the safe context if no caller can be
       // found.
 
       sThreadJSContextStack->Peek(&cx);
 
@@ -1428,25 +1445,18 @@ nsContentUtils::GetContextAndScope(nsIDo
           NS_WARNING("No context reachable in GetContextAndScopes()!");
 
           return NS_ERROR_NOT_AVAILABLE;
         }
       }
     }
   }
 
-  if (!newScope && cx) {
-    jsval v;
-    nsresult rv = WrapNative(cx, global, aNewDocument, aNewDocument, &v);
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    newScope = JSVAL_TO_OBJECT(v);
-  }
-
   *aCx = cx;
+  *aOldScope = oldScope;
   *aNewScope = newScope;
 
   return NS_OK;
 }
 
 nsresult
 nsContentUtils::ReparentContentWrappersInScope(nsIScriptGlobalObject *aOldScope,
                                                nsIScriptGlobalObject *aNewScope)
--- a/content/base/src/nsDOMDocumentType.cpp
+++ b/content/base/src/nsDOMDocumentType.cpp
@@ -263,25 +263,26 @@ nsDOMDocumentType::BindToTree(nsIDocumen
     nsCOMPtr<nsINodeInfo> newNodeInfo;
     newNodeInfo = nimgr->GetNodeInfo(mNodeInfo->NameAtom(),
                                      mNodeInfo->GetPrefixAtom(),
                                      mNodeInfo->NamespaceID());
     NS_ENSURE_TRUE(newNodeInfo, NS_ERROR_OUT_OF_MEMORY);
 
     mNodeInfo.swap(newNodeInfo);
 
-    JSObject *oldScope = GetWrapper();
-    if (oldScope) {
+    nsCOMPtr<nsIDocument> oldOwnerDoc =
+      do_QueryInterface(nsContentUtils::GetDocumentFromContext());
+    nsIDocument *newOwnerDoc = nimgr->GetDocument();
+    if (oldOwnerDoc && newOwnerDoc) {
       nsIXPConnect *xpc = nsContentUtils::XPConnect();
 
       JSContext *cx = nsnull;
-      JSObject *newScope = nsnull;
-      nsresult rv = nsContentUtils::GetContextAndScope(nsnull,
-                                                       nimgr->GetDocument(),
-                                                       &cx, &newScope);
+      JSObject *oldScope = nsnull, *newScope = nsnull;
+      nsresult rv = nsContentUtils::GetContextAndScopes(oldOwnerDoc, newOwnerDoc, &cx,
+                                                        &oldScope, &newScope);
       if (cx && xpc) {
         nsISupports *node = NS_ISUPPORTS_CAST(nsIContent*, this);
         nsCOMPtr<nsIXPConnectJSObjectHolder> oldWrapper;
         rv = xpc->ReparentWrappedNativeIfFound(cx, oldScope, newScope, node,
                                                getter_AddRefs(oldWrapper));
       }
 
       if (NS_FAILED(rv)) {
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -6077,20 +6077,21 @@ nsDocument::AdoptNode(nsIDOMNode *aAdopt
       return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
     }
   }
 
   nsIDocument *oldDocument = adoptedNode->GetOwnerDoc();
   PRBool sameDocument = oldDocument == this;
 
   JSContext *cx = nsnull;
-  JSObject *oldScope = adoptedNode->GetWrapper();
+  JSObject *oldScope = nsnull;
   JSObject *newScope = nsnull;
-  if (oldScope && !sameDocument) {
-    rv = nsContentUtils::GetContextAndScope(oldDocument, this, &cx, &newScope);
+  if (!sameDocument && oldDocument) {
+    rv = nsContentUtils::GetContextAndScopes(oldDocument, this, &cx, &oldScope,
+                                             &newScope);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   nsCOMArray<nsINode> nodesWithProperties;
   rv = nsNodeUtils::Adopt(adoptedNode, sameDocument ? nsnull : mNodeInfoManager,
                           cx, oldScope, newScope, nodesWithProperties);
   if (NS_FAILED(rv)) {
     // Disconnect all nodes from their parents, since some have the old document