Bug 708572 - back out bug 335998 from Beta/FF9, r+a=jst
authorOlli Pettay <Olli.Pettay@helsinki.fi>
Fri, 09 Dec 2011 15:56:07 +0200
changeset 79028 1b302e06c6b1819b8147a14b2b29b51a32c4e157
parent 79027 f4e11a42ed9a3efdef686a8fa142a8678c9293e2
child 79029 535fd87e8a09008cb86a39565a8aba2d9c633b29
push id420
push useropettay@mozilla.com
push dateFri, 09 Dec 2011 14:42:33 +0000
treeherdermozilla-beta@1b302e06c6b1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs708572, 335998
milestone9.0
Bug 708572 - back out bug 335998 from Beta/FF9, r+a=jst
content/base/src/nsDocument.cpp
content/base/src/nsGenericDOMDataNode.cpp
content/base/src/nsGenericDOMDataNode.h
content/base/src/nsGenericElement.cpp
content/base/src/nsNodeInfo.cpp
content/base/src/nsNodeInfoManager.cpp
content/base/src/nsNodeInfoManager.h
content/html/content/src/nsHTMLBodyElement.cpp
content/html/content/src/nsHTMLFrameSetElement.cpp
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -1634,16 +1634,17 @@ nsDocument::~nsDocument()
     // Could be null here if Init() failed
     mCSSLoader->DropDocumentReference();
     NS_RELEASE(mCSSLoader);
   }
 
   // XXX Ideally we'd do this cleanup in the nsIDocument destructor.
   if (mNodeInfoManager) {
     mNodeInfoManager->DropDocumentReference();
+    NS_RELEASE(mNodeInfoManager);
   }
 
   if (mAttrStyleSheet) {
     mAttrStyleSheet->SetOwningDocument(nsnull);
   }
   
   if (mStyleAttrStyleSheet) {
     mStyleAttrStyleSheet->SetOwningDocument(nsnull);
@@ -1817,16 +1818,18 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_
   // Traverse the mChildren nsAttrAndChildArray.
   for (PRInt32 indx = PRInt32(tmp->mChildren.ChildCount()); indx > 0; --indx) {
     NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mChildren[i]");
     cb.NoteXPCOMChild(tmp->mChildren.ChildAt(indx - 1));
   }
 
   // Traverse all nsIDocument pointer members.
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mCachedRootElement)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_MEMBER(mNodeInfoManager,
+                                                  nsNodeInfoManager)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mSecurityInfo)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDisplayDocument)
 
   // Traverse all nsDocument nsCOMPtrs.
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mParser)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mScriptGlobalObject)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_MEMBER(mListenerManager,
                                                   nsEventListenerManager)
@@ -1982,20 +1985,21 @@ nsDocument::Init()
   NS_ENSURE_TRUE(mCSSLoader, NS_ERROR_OUT_OF_MEMORY);
   NS_ADDREF(mCSSLoader);
   // Assume we're not quirky, until we know otherwise
   mCSSLoader->SetCompatibilityMode(eCompatibility_FullStandards);
 
   mNodeInfoManager = new nsNodeInfoManager();
   NS_ENSURE_TRUE(mNodeInfoManager, NS_ERROR_OUT_OF_MEMORY);
 
+  NS_ADDREF(mNodeInfoManager);
+
   nsresult  rv = mNodeInfoManager->Init(this);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  // mNodeInfo keeps NodeInfoManager alive!
   mNodeInfo = mNodeInfoManager->GetDocumentNodeInfo();
   NS_ENSURE_TRUE(mNodeInfo, NS_ERROR_OUT_OF_MEMORY);
   NS_ABORT_IF_FALSE(mNodeInfo->NodeType() == nsIDOMNode::DOCUMENT_NODE,
                     "Bad NodeType in aNodeInfo");
 
   NS_ASSERTION(GetOwnerDoc() == this, "Our nodeinfo is busted!");
 
   mScriptLoader = new nsScriptLoader(this);
--- a/content/base/src/nsGenericDOMDataNode.cpp
+++ b/content/base/src/nsGenericDOMDataNode.cpp
@@ -80,19 +80,16 @@ nsGenericDOMDataNode::nsGenericDOMDataNo
                     mNodeInfo->NodeType() == nsIDOMNode::DOCUMENT_TYPE_NODE,
                     "Bad NodeType in aNodeInfo");
 }
 
 nsGenericDOMDataNode::~nsGenericDOMDataNode()
 {
   NS_PRECONDITION(!IsInDoc(),
                   "Please remove this from the document properly");
-  if (GetParent()) {
-    NS_RELEASE(mParent);
-  }
 }
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsGenericDOMDataNode)
 
 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsGenericDOMDataNode)
   nsINode::Trace(tmp, aCallback, aClosure);
 NS_IMPL_CYCLE_COLLECTION_TRACE_END
 
@@ -495,19 +492,16 @@ nsGenericDOMDataNode::BindToTree(nsIDocu
     slots->mBindingParent = aBindingParent; // Weak, so no addref happens.
     if (aParent->IsInNativeAnonymousSubtree()) {
       SetFlags(NODE_IS_IN_ANONYMOUS_SUBTREE);
     }
   }
 
   // Set parent
   if (aParent) {
-    if (!GetParent()) {
-      NS_ADDREF(aParent);
-    }
     mParent = aParent;
   }
   else {
     mParent = aDocument;
   }
   SetParentIsContent(aParent);
 
   // XXXbz sXBL/XBL2 issue!
@@ -546,21 +540,17 @@ nsGenericDOMDataNode::UnbindFromTree(PRB
   if (document) {
     // Notify XBL- & nsIAnonymousContentCreator-generated
     // anonymous content that the document is changing.
     // This is needed to update the insertion point.
     document->BindingManager()->RemovedFromDocument(this, document);
   }
 
   if (aNullParent) {
-    if (GetParent()) {
-      NS_RELEASE(mParent);
-    } else {
-      mParent = nsnull;
-    }
+    mParent = nsnull;
     SetParentIsContent(false);
   }
   ClearInDocument();
 
   nsDataSlots *slots = GetExistingDataSlots();
   if (slots) {
     slots->mBindingParent = nsnull;
   }
@@ -841,17 +831,19 @@ nsGenericDOMDataNode::GetWholeText(nsASt
 }
 
 nsresult
 nsGenericDOMDataNode::ReplaceWholeText(const nsAString& aContent,
                                        nsIDOMText **aResult)
 {
   *aResult = nsnull;
 
-  GetOwnerDoc()->WarnOnceAbout(nsIDocument::eReplaceWholeText);
+  if (GetOwnerDoc()) {
+    GetOwnerDoc()->WarnOnceAbout(nsIDocument::eReplaceWholeText);
+  }
 
   // Handle parent-less nodes
   nsCOMPtr<nsIContent> parent = GetParent();
   if (!parent) {
     if (aContent.IsEmpty()) {
       return NS_OK;
     }
 
--- a/content/base/src/nsGenericDOMDataNode.h
+++ b/content/base/src/nsGenericDOMDataNode.h
@@ -329,17 +329,19 @@ protected:
   nsresult SplitText(PRUint32 aOffset, nsIDOMText** aReturn);
 
   nsresult GetWholeText(nsAString& aWholeText);
 
   nsresult ReplaceWholeText(const nsAString& aContent, nsIDOMText **aReturn);
 
   nsresult GetIsElementContentWhitespace(PRBool *aReturn)
   {
-    GetOwnerDoc()->WarnOnceAbout(nsIDocument::eIsElementContentWhitespace);
+    if (GetOwnerDoc()) {
+      GetOwnerDoc()->WarnOnceAbout(nsIDocument::eIsElementContentWhitespace);
+    }
     *aReturn = TextIsOnlyWhitespace();
     return NS_OK;
   }
 
   static PRInt32 FirstLogicallyAdjacentTextNode(nsIContent* aParent,
                                                 PRInt32 aIndex);
 
   static PRInt32 LastLogicallyAdjacentTextNode(nsIContent* aParent,
--- a/content/base/src/nsGenericElement.cpp
+++ b/content/base/src/nsGenericElement.cpp
@@ -1179,17 +1179,16 @@ nsINode::Traverse(nsINode *tmp, nsCycleC
 {
   nsIDocument *currentDoc = tmp->GetCurrentDoc();
   if (currentDoc &&
       nsCCUncollectableMarker::InGeneration(cb, currentDoc->GetMarkedCCGeneration())) {
     return false;
   }
 
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mNodeInfo)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_RAWPTR(GetParent())
 
   nsSlots *slots = tmp->GetExistingSlots();
   if (slots) {
     slots->Traverse(cb);
   }
 
   if (tmp->HasProperties()) {
     nsNodeUtils::TraverseUserData(tmp, cb);
@@ -2327,19 +2326,16 @@ nsGenericElement::nsGenericElement(alrea
   SetFlags((nsIProgrammingLanguage::JAVASCRIPT << NODE_SCRIPT_TYPE_OFFSET));
   SetIsElement();
 }
 
 nsGenericElement::~nsGenericElement()
 {
   NS_PRECONDITION(!IsInDoc(),
                   "Please remove this from the document properly");
-  if (GetParent()) {
-    NS_RELEASE(mParent);
-  }
 }
 
 NS_IMETHODIMP
 nsGenericElement::GetNodeName(nsAString& aNodeName)
 {
   aNodeName = NodeName();
   return NS_OK;
 }
@@ -2952,19 +2948,16 @@ nsGenericElement::BindToTree(nsIDocument
   if (aParent && aParent->IsInNativeAnonymousSubtree()) {
     SetFlags(NODE_IS_IN_ANONYMOUS_SUBTREE);
   }
 
   PRBool hadForceXBL = HasFlag(NODE_FORCE_XBL_BINDINGS);
 
   // Now set the parent and set the "Force attach xbl" flag if needed.
   if (aParent) {
-    if (!GetParent()) {
-      NS_ADDREF(aParent);
-    }
     mParent = aParent;
 
     if (aParent->HasFlag(NODE_FORCE_XBL_BINDINGS)) {
       SetFlags(NODE_FORCE_XBL_BINDINGS);
     }
   }
   else {
     mParent = aDocument;
@@ -3063,21 +3056,17 @@ nsGenericElement::UnbindFromTree(PRBool 
   NS_PRECONDITION(aDeep || (!GetCurrentDoc() && !GetBindingParent()),
                   "Shallow unbind won't clear document and binding parent on "
                   "kids!");
   // Make sure to unbind this node before doing the kids
   nsIDocument *document =
     HasFlag(NODE_FORCE_XBL_BINDINGS) ? GetOwnerDoc() : GetCurrentDoc();
 
   if (aNullParent) {
-    if (GetParent()) {
-      NS_RELEASE(mParent);
-    } else {
-      mParent = nsnull;
-    }
+    mParent = nsnull;
     SetParentIsContent(false);
   }
   ClearInDocument();
 
   if (document) {
     // Notify XBL- & nsIAnonymousContentCreator-generated
     // anonymous content that the document is changing.
     document->BindingManager()->RemovedFromDocument(this, document);
--- a/content/base/src/nsNodeInfo.cpp
+++ b/content/base/src/nsNodeInfo.cpp
@@ -94,21 +94,21 @@ nsNodeInfo::Create(nsIAtom *aName, nsIAt
     new (place) nsNodeInfo(aName, aPrefix, aNamespaceID, aNodeType, aExtraName,
                            aOwnerManager) :
     nsnull;
 }
 
 nsNodeInfo::~nsNodeInfo()
 {
   mOwnerManager->RemoveNodeInfo(this);
+  NS_RELEASE(mOwnerManager);
 
   NS_RELEASE(mInner.mName);
   NS_IF_RELEASE(mInner.mPrefix);
   NS_IF_RELEASE(mInner.mExtraName);
-  NS_RELEASE(mOwnerManager);
 }
 
 
 nsNodeInfo::nsNodeInfo(nsIAtom *aName, nsIAtom *aPrefix, PRInt32 aNamespaceID,
                        PRUint16 aNodeType, nsIAtom* aExtraName,
                        nsNodeInfoManager *aOwnerManager)
 {
   CHECK_VALID_NODEINFO(aNodeType, aName, aNamespaceID, aExtraName);
--- a/content/base/src/nsNodeInfoManager.cpp
+++ b/content/base/src/nsNodeInfoManager.cpp
@@ -107,17 +107,16 @@ nsNodeInfoManager::NodeInfoInnerKeyCompa
     return (node2->mName->Equals(*(node1->mNameString)));
   }
   return (node1->mNameString->Equals(*(node2->mNameString)));
 }
 
 
 nsNodeInfoManager::nsNodeInfoManager()
   : mDocument(nsnull),
-    mNonDocumentNodeInfos(0),
     mPrincipal(nsnull),
     mTextNodeInfo(nsnull),
     mCommentNodeInfo(nsnull),
     mDocumentNodeInfo(nsnull),
     mBindingManager(nsnull)
 {
   nsLayoutStatics::AddRef();
 
@@ -156,19 +155,16 @@ nsNodeInfoManager::~nsNodeInfoManager()
 }
 
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsNodeInfoManager)
 NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(nsNodeInfoManager, AddRef)
 NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(nsNodeInfoManager, Release)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_NATIVE_0(nsNodeInfoManager)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_BEGIN(nsNodeInfoManager)
-  if (tmp->mNonDocumentNodeInfos) {
-    NS_IMPL_CYCLE_COLLECTION_TRAVERSE_RAWPTR(mDocument)
-  }
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_RAWPTR(mBindingManager)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 nsresult
 nsNodeInfoManager::Init(nsIDocument *aDocument)
 {
   NS_ENSURE_TRUE(mNodeInfoHash, NS_ERROR_OUT_OF_MEMORY);
 
@@ -208,20 +204,18 @@ nsNodeInfoManager::DropNodeInfoDocument(
 
 void
 nsNodeInfoManager::DropDocumentReference()
 {
   if (mBindingManager) {
     mBindingManager->DropDocumentReference();
   }
 
-  // This is probably not needed anymore.
   PL_HashTableEnumerateEntries(mNodeInfoHash, DropNodeInfoDocument, nsnull);
 
-  NS_ASSERTION(!mNonDocumentNodeInfos, "Shouldn't have non-document nodeinfos!");
   mDocument = nsnull;
 }
 
 
 already_AddRefed<nsINodeInfo>
 nsNodeInfoManager::GetNodeInfo(nsIAtom *aName, nsIAtom *aPrefix,
                                PRInt32 aNamespaceID, PRUint16 aNodeType,
                                nsIAtom* aExtraName /* = nsnull */)
@@ -247,21 +241,16 @@ nsNodeInfoManager::GetNodeInfo(nsIAtom *
   NS_ENSURE_TRUE(newNodeInfo, nsnull);
   
   PLHashEntry *he;
   he = PL_HashTableAdd(mNodeInfoHash, &newNodeInfo->mInner, newNodeInfo);
   NS_ENSURE_TRUE(he, nsnull);
 
   // Have to do the swap thing, because already_AddRefed<nsNodeInfo>
   // doesn't cast to already_AddRefed<nsINodeInfo>
-  ++mNonDocumentNodeInfos;
-  if (mNonDocumentNodeInfos == 1) {
-    NS_IF_ADDREF(mDocument);
-  }
-
   nsNodeInfo *nodeInfo = nsnull;
   newNodeInfo.swap(nodeInfo);
 
   return nodeInfo;
 }
 
 
 nsresult
@@ -296,21 +285,16 @@ nsNodeInfoManager::GetNodeInfo(const nsA
       nsNodeInfo::Create(nameAtom, aPrefix, aNamespaceID, aNodeType, nsnull,
                          this);
   NS_ENSURE_TRUE(newNodeInfo, NS_ERROR_OUT_OF_MEMORY);
 
   PLHashEntry *he;
   he = PL_HashTableAdd(mNodeInfoHash, &newNodeInfo->mInner, newNodeInfo);
   NS_ENSURE_TRUE(he, NS_ERROR_FAILURE);
 
-  ++mNonDocumentNodeInfos;
-  if (mNonDocumentNodeInfos == 1) {
-    NS_IF_ADDREF(mDocument);
-  }
-
   newNodeInfo.forget(aNodeInfo);
 
   return NS_OK;
 }
 
 
 nsresult
 nsNodeInfoManager::GetNodeInfo(const nsAString& aName, nsIAtom *aPrefix,
@@ -358,24 +342,19 @@ nsNodeInfoManager::GetCommentNodeInfo()
 
   return mCommentNodeInfo;
 }
 
 already_AddRefed<nsINodeInfo>
 nsNodeInfoManager::GetDocumentNodeInfo()
 {
   if (!mDocumentNodeInfo) {
-    NS_ASSERTION(mDocument, "Should have mDocument!");
     mDocumentNodeInfo = GetNodeInfo(nsGkAtoms::documentNodeName, nsnull,
                                     kNameSpaceID_None,
                                     nsIDOMNode::DOCUMENT_NODE, nsnull).get();
-    --mNonDocumentNodeInfos;
-    if (!mNonDocumentNodeInfos) {
-      mDocument->Release(); // Don't set mDocument to null!
-    }
   }
   else {
     NS_ADDREF(mDocumentNodeInfo);
   }
 
   return mDocumentNodeInfo;
 }
 
@@ -392,34 +371,25 @@ nsNodeInfoManager::SetDocumentPrincipal(
   NS_ADDREF(mPrincipal = aPrincipal);
 }
 
 void
 nsNodeInfoManager::RemoveNodeInfo(nsNodeInfo *aNodeInfo)
 {
   NS_PRECONDITION(aNodeInfo, "Trying to remove null nodeinfo from manager!");
 
-  if (aNodeInfo == mDocumentNodeInfo) {
+  // Drop weak reference if needed
+  if (aNodeInfo == mTextNodeInfo) {
+    mTextNodeInfo = nsnull;
+  }
+  else if (aNodeInfo == mCommentNodeInfo) {
+    mCommentNodeInfo = nsnull;
+  }
+  else if (aNodeInfo == mDocumentNodeInfo) {
     mDocumentNodeInfo = nsnull;
-    mDocument = nsnull;
-  } else {
-    if (--mNonDocumentNodeInfos == 0) {
-      if (mDocument) {
-        // Note, whoever calls this method should keep NodeInfoManager alive,
-        // even if mDocument gets deleted.
-        mDocument->Release();
-      }
-    }
-    // Drop weak reference if needed
-    if (aNodeInfo == mTextNodeInfo) {
-      mTextNodeInfo = nsnull;
-    }
-    else if (aNodeInfo == mCommentNodeInfo) {
-      mCommentNodeInfo = nsnull;
-    }
   }
 
 #ifdef DEBUG
   PRBool ret =
 #endif
   PL_HashTableRemove(mNodeInfoHash, &aNodeInfo->mInner);
 
   NS_POSTCONDITION(ret, "Can't find nsINodeInfo to remove!!!");
--- a/content/base/src/nsNodeInfoManager.h
+++ b/content/base/src/nsNodeInfoManager.h
@@ -152,17 +152,16 @@ protected:
 private:
   static PRIntn NodeInfoInnerKeyCompare(const void *key1, const void *key2);
   static PLHashNumber GetNodeInfoInnerHashValue(const void *key);
   static PRIntn DropNodeInfoDocument(PLHashEntry *he, PRIntn hashIndex,
                                      void *arg);
 
   PLHashTable *mNodeInfoHash;
   nsIDocument *mDocument; // WEAK
-  PRUint32 mNonDocumentNodeInfos;
   nsIPrincipal *mPrincipal; // STRONG, but not nsCOMPtr to avoid include hell
                             // while inlining DocumentPrincipal().  Never null
                             // after Init() succeeds.
   nsCOMPtr<nsIPrincipal> mDefaultPrincipal; // Never null after Init() succeeds
   nsINodeInfo *mTextNodeInfo; // WEAK to avoid circular ownership
   nsINodeInfo *mCommentNodeInfo; // WEAK to avoid circular ownership
   nsINodeInfo *mDocumentNodeInfo; // WEAK to avoid circular ownership
   nsBindingManager* mBindingManager; // STRONG, but not nsCOMPtr to avoid
--- a/content/html/content/src/nsHTMLBodyElement.cpp
+++ b/content/html/content/src/nsHTMLBodyElement.cpp
@@ -506,46 +506,50 @@ nsHTMLBodyElement::GetAssociatedEditor()
 // cases.  We don't want to stick an event listener on an outer
 // window, so bail if it does.  See also similar code in
 // nsGenericHTMLElement::GetEventListenerManagerForAttr.
 #define EVENT(name_, id_, type_, struct_) /* nothing; handled by the superclass */
 #define FORWARDED_EVENT(name_, id_, type_, struct_)                 \
   NS_IMETHODIMP nsHTMLBodyElement::GetOn##name_(JSContext *cx,      \
                                            jsval *vp) {             \
     /* XXXbz note to self: add tests for this! */                   \
-    nsPIDOMWindow* win = GetOwnerDoc()->GetInnerWindow();           \
+    nsPIDOMWindow* win =                                            \
+      GetOwnerDoc() ? GetOwnerDoc()->GetInnerWindow() : nsnull;     \
     if (win && win->IsInnerWindow()) {                              \
       nsCOMPtr<nsIInlineEventHandlers> ev = do_QueryInterface(win); \
       return ev->GetOn##name_(cx, vp);                              \
     }                                                               \
     *vp = JSVAL_NULL;                                               \
     return NS_OK;                                                   \
   }                                                                 \
   NS_IMETHODIMP nsHTMLBodyElement::SetOn##name_(JSContext *cx,      \
                                            const jsval &v) {        \
-    nsPIDOMWindow* win = GetOwnerDoc()->GetInnerWindow();           \
+    nsPIDOMWindow* win =                                            \
+      GetOwnerDoc() ? GetOwnerDoc()->GetInnerWindow() : nsnull;     \
     if (win && win->IsInnerWindow()) {                              \
       nsCOMPtr<nsIInlineEventHandlers> ev = do_QueryInterface(win); \
       return ev->SetOn##name_(cx, v);                               \
     }                                                               \
     return NS_OK;                                                   \
   }
 #define WINDOW_EVENT(name_, id_, type_, struct_)                  \
   NS_IMETHODIMP nsHTMLBodyElement::GetOn##name_(JSContext *cx,    \
                                                 jsval *vp) {      \
-    nsPIDOMWindow* win = GetOwnerDoc()->GetInnerWindow();         \
+    nsPIDOMWindow* win =                                          \
+      GetOwnerDoc() ? GetOwnerDoc()->GetInnerWindow() : nsnull;   \
     if (win && win->IsInnerWindow()) {                            \
       return win->GetOn##name_(cx, vp);                           \
     }                                                             \
     *vp = JSVAL_NULL;                                             \
     return NS_OK;                                                 \
   }                                                               \
   NS_IMETHODIMP nsHTMLBodyElement::SetOn##name_(JSContext *cx,    \
                                                 const jsval &v) { \
-    nsPIDOMWindow* win = GetOwnerDoc()->GetInnerWindow();         \
+    nsPIDOMWindow* win =                                          \
+      GetOwnerDoc() ? GetOwnerDoc()->GetInnerWindow() : nsnull;   \
     if (win && win->IsInnerWindow()) {                            \
       return win->SetOn##name_(cx, v);                            \
     }                                                             \
     return NS_OK;                                                 \
   }
 #include "nsEventNameList.h"
 #undef WINDOW_EVENT
 #undef FORWARDED_EVENT
--- a/content/html/content/src/nsHTMLFrameSetElement.cpp
+++ b/content/html/content/src/nsHTMLFrameSetElement.cpp
@@ -355,47 +355,51 @@ nsHTMLFrameSetElement::ParseRowCol(const
 // cases.  We don't want to stick an event listener on an outer
 // window, so bail if it does.  See also similar code in
 // nsGenericHTMLElement::GetEventListenerManagerForAttr.
 #define EVENT(name_, id_, type_, struct_) /* nothing; handled by the shim */
 #define FORWARDED_EVENT(name_, id_, type_, struct_)                   \
   NS_IMETHODIMP nsHTMLFrameSetElement::GetOn##name_(JSContext *cx,    \
                                                jsval *vp) {           \
     /* XXXbz note to self: add tests for this! */                     \
-    nsPIDOMWindow* win = GetOwnerDoc()->GetInnerWindow();             \
+    nsPIDOMWindow* win =                                              \
+      GetOwnerDoc() ? GetOwnerDoc()->GetInnerWindow() : nsnull;       \
     if (win && win->IsInnerWindow()) {                                \
       nsCOMPtr<nsIInlineEventHandlers> ev = do_QueryInterface(win);   \
       return ev->GetOn##name_(cx, vp);                                \
     }                                                                 \
     *vp = JSVAL_NULL;                                                 \
     return NS_OK;                                                     \
   }                                                                   \
   NS_IMETHODIMP nsHTMLFrameSetElement::SetOn##name_(JSContext *cx,    \
                                                const jsval &v) {      \
-    nsPIDOMWindow* win = GetOwnerDoc()->GetInnerWindow();             \
+    nsPIDOMWindow* win =                                              \
+      GetOwnerDoc() ? GetOwnerDoc()->GetInnerWindow() : nsnull;       \
     if (win && win->IsInnerWindow()) {                                \
       nsCOMPtr<nsIInlineEventHandlers> ev = do_QueryInterface(win);   \
       return ev->SetOn##name_(cx, v);                                 \
     }                                                                 \
     return NS_OK;                                                     \
   }
 #define WINDOW_EVENT(name_, id_, type_, struct_)                      \
   NS_IMETHODIMP nsHTMLFrameSetElement::GetOn##name_(JSContext *cx,    \
                                                     jsval *vp) {      \
     /* XXXbz note to self: add tests for this! */                     \
-    nsPIDOMWindow* win = GetOwnerDoc()->GetInnerWindow();             \
+    nsPIDOMWindow* win =                                              \
+      GetOwnerDoc() ? GetOwnerDoc()->GetInnerWindow() : nsnull;       \
     if (win && win->IsInnerWindow()) {                                \
       return win->GetOn##name_(cx, vp);                               \
     }                                                                 \
     *vp = JSVAL_NULL;                                                 \
     return NS_OK;                                                     \
   }                                                                   \
   NS_IMETHODIMP nsHTMLFrameSetElement::SetOn##name_(JSContext *cx,    \
                                                     const jsval &v) { \
-    nsPIDOMWindow* win = GetOwnerDoc()->GetInnerWindow();             \
+    nsPIDOMWindow* win =                                              \
+      GetOwnerDoc() ? GetOwnerDoc()->GetInnerWindow() : nsnull;       \
     if (win && win->IsInnerWindow()) {                                \
       return win->SetOn##name_(cx, v);                                \
     }                                                                 \
     return NS_OK;                                                     \
   }
 #include "nsEventNameList.h"
 #undef WINDOW_EVENT
 #undef FORWARDED_EVENT