Bug 682460 - Fix leak when forcing layout during mutation event for table attribute; r=smaug
authorMs2ger <ms2ger@gmail.com>
Sun, 28 Aug 2011 11:59:34 +0100
changeset 77321 f1cf848b1ff22bad8980b673cc4410a21c8bdf28
parent 77320 9225d92382b84bf6887bdece059ad0842a73468f
child 77322 0be4a94258c28b97a7e6e87b099359c759941b22
push id78
push userclegnitto@mozilla.com
push dateFri, 16 Dec 2011 17:32:24 +0000
treeherdermozilla-release@79d24e644fdd [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs682460
milestone9.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 682460 - Fix leak when forcing layout during mutation event for table attribute; r=smaug
content/html/content/crashtests/682460.html
content/html/content/crashtests/crashtests.list
content/html/content/src/nsHTMLTableCellElement.cpp
content/html/content/src/nsHTMLTableElement.cpp
content/html/content/src/nsHTMLTableElement.h
new file mode 100644
--- /dev/null
+++ b/content/html/content/crashtests/682460.html
@@ -0,0 +1,21 @@
+<html>
+<head>
+<script>
+
+function boom()
+{
+  var f = function() {
+    document.documentElement.offsetHeight;
+  };
+  window.addEventListener("DOMSubtreeModified", f, true);
+
+  document.getElementsByTagName("table")[0].setAttribute("cellpadding", "2");
+}
+
+</script>
+</head>
+
+<body onload="boom();">
+<table><tr><td></td></tr></table>
+</body>
+</html>
--- a/content/html/content/crashtests/crashtests.list
+++ b/content/html/content/crashtests/crashtests.list
@@ -24,8 +24,9 @@ load 604807.html
 load 605264.html
 load 606430-1.html
 load 602117.html
 load 613027.html
 load 614279.html
 load 614988-1.html
 load 620078-1.html
 load 620078-2.html
+load 682460.html
--- a/content/html/content/src/nsHTMLTableCellElement.cpp
+++ b/content/html/content/src/nsHTMLTableCellElement.cpp
@@ -201,17 +201,17 @@ nsHTMLTableCellElement::GetCellIndex(PRI
 
 NS_IMETHODIMP
 nsHTMLTableCellElement::WalkContentStyleRules(nsRuleWalker* aRuleWalker)
 {
   nsresult rv = nsGenericHTMLElement::WalkContentStyleRules(aRuleWalker);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsIContent* node = GetTable();
-  if (node && node->IsHTML() && node->NodeInfo()->Equals(nsGkAtoms::table)) {
+  if (node && node->IsHTML(nsGkAtoms::table)) {
     nsHTMLTableElement* table = static_cast<nsHTMLTableElement*>(node);
     nsMappedAttributes* tableInheritedAttributes =
       table->GetAttributesMappedForCell();
     if (tableInheritedAttributes)
       aRuleWalker->Forward(tableInheritedAttributes);
   }
   return NS_OK;
 }
--- a/content/html/content/src/nsHTMLTableElement.cpp
+++ b/content/html/content/src/nsHTMLTableElement.cpp
@@ -1271,37 +1271,30 @@ nsHTMLTableElement::BindToTree(nsIDocume
 void
 nsHTMLTableElement::UnbindFromTree(PRBool aDeep, PRBool aNullParent)
 {
   ReleaseInheritedAttributes();
   nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent);
 }
 
 nsresult
-nsHTMLTableElement::SetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttribute,
-                            nsIAtom* aPrefix, const nsAString& aValue,
-                            PRBool aNotify)
+nsHTMLTableElement::BeforeSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
+                                  const nsAString* aValue,
+                                  PRBool aNotify)
 {
-  PRBool isCellPadding = (aAttribute == nsGkAtoms::cellpadding);
-  if (isCellPadding) {
+  if (aName == nsGkAtoms::cellpadding && aNameSpaceID == kNameSpaceID_None) {
     ReleaseInheritedAttributes();
   }
-
-  nsresult rv = nsGenericHTMLElement::SetAttr(aNameSpaceID, aAttribute,
-                                              aPrefix, aValue, aNotify);
-
-  if (isCellPadding) {
-    BuildInheritedAttributes();
-  }
-  return rv;
+  return nsGenericHTMLElement::BeforeSetAttr(aNameSpaceID, aName, aValue,
+                                             aNotify);
 }
 
 nsresult
-nsHTMLTableElement::UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttribute,
-                               PRBool aNotify)
+nsHTMLTableElement::AfterSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
+                                 const nsAString* aValue,
+                                 PRBool aNotify)
 {
-  PRBool isCellPadding = (aAttribute == nsGkAtoms::cellpadding);
-  if (isCellPadding) {
-    ReleaseInheritedAttributes();
+  if (aName == nsGkAtoms::cellpadding && aNameSpaceID == kNameSpaceID_None) {
+    BuildInheritedAttributes();
   }
-
-  return nsGenericHTMLElement::UnsetAttr(aNameSpaceID, aAttribute, aNotify);
+  return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, aValue,
+                                            aNotify);
 }
--- a/content/html/content/src/nsHTMLTableElement.h
+++ b/content/html/content/src/nsHTMLTableElement.h
@@ -1,116 +1,120 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Mozilla Communicator client code.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 1998
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either of the GNU General Public License Version 2 or later (the "GPL"),
- * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-#include "nsIDOMHTMLTableElement.h"
-#include "nsGenericHTMLElement.h"
-#include "nsMappedAttributes.h"
-
-#define TABLE_ATTRS_DIRTY ((nsMappedAttributes*)0x1)
-
-
-class TableRowsCollection;
-
-class nsHTMLTableElement :  public nsGenericHTMLElement,
-                            public nsIDOMHTMLTableElement
-{
-public:
-  nsHTMLTableElement(already_AddRefed<nsINodeInfo> aNodeInfo);
-  virtual ~nsHTMLTableElement();
-
-  // nsISupports
-  NS_DECL_ISUPPORTS_INHERITED
-
-  // nsIDOMNode
-  NS_FORWARD_NSIDOMNODE(nsGenericHTMLElement::)
-
-  // nsIDOMElement
-  NS_FORWARD_NSIDOMELEMENT(nsGenericHTMLElement::)
-
-  // nsIDOMHTMLElement
-  NS_FORWARD_NSIDOMHTMLELEMENT(nsGenericHTMLElement::)
-
-  // nsIDOMHTMLTableElement
-  NS_DECL_NSIDOMHTMLTABLEELEMENT
-
-  virtual PRBool ParseAttribute(PRInt32 aNamespaceID,
-                                nsIAtom* aAttribute,
-                                const nsAString& aValue,
-                                nsAttrValue& aResult);
-  virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const;
-  NS_IMETHOD_(PRBool) IsAttributeMapped(const nsIAtom* aAttribute) const;
-
-  virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
-
-  virtual nsXPCClassInfo* GetClassInfo();
-  virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
-                              nsIContent* aBindingParent,
-                              PRBool aCompileEventHandlers);
-  virtual void UnbindFromTree(PRBool aDeep = PR_TRUE,
-                              PRBool aNullParent = PR_TRUE);
-  virtual nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom *aName,
-                           nsIAtom *aPrefix, const nsAString &aValue,
-                           PRBool aNotify);
-  virtual nsresult UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttribute,
-                             PRBool aNotify);
-
-
-  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_NO_UNLINK(nsHTMLTableElement,
-                                                     nsGenericHTMLElement)
-  nsMappedAttributes* GetAttributesMappedForCell();
-  already_AddRefed<nsIDOMHTMLTableSectionElement> GetTHead() {
-    return GetSection(nsGkAtoms::thead);
-  }
-  already_AddRefed<nsIDOMHTMLTableSectionElement> GetTFoot() {
-    return GetSection(nsGkAtoms::tfoot);
-  }
-  nsContentList* TBodies();
-protected:
-  already_AddRefed<nsIDOMHTMLTableSectionElement> GetSection(nsIAtom *aTag);
-
-  nsRefPtr<nsContentList> mTBodies;
-  nsRefPtr<TableRowsCollection> mRows;
-  // Sentinel value of TABLE_ATTRS_DIRTY indicates that this is dirty and needs
-  // to be recalculated.
-  nsMappedAttributes *mTableInheritedAttributes;
-  void BuildInheritedAttributes();
-  void ReleaseInheritedAttributes() {
-    if (mTableInheritedAttributes &&
-        mTableInheritedAttributes != TABLE_ATTRS_DIRTY)
-      NS_RELEASE(mTableInheritedAttributes);
-      mTableInheritedAttributes = TABLE_ATTRS_DIRTY;
-  }
-};
-
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+#include "nsIDOMHTMLTableElement.h"
+#include "nsGenericHTMLElement.h"
+#include "nsMappedAttributes.h"
+
+#define TABLE_ATTRS_DIRTY ((nsMappedAttributes*)0x1)
+
+
+class TableRowsCollection;
+
+class nsHTMLTableElement :  public nsGenericHTMLElement,
+                            public nsIDOMHTMLTableElement
+{
+public:
+  nsHTMLTableElement(already_AddRefed<nsINodeInfo> aNodeInfo);
+  virtual ~nsHTMLTableElement();
+
+  // nsISupports
+  NS_DECL_ISUPPORTS_INHERITED
+
+  // nsIDOMNode
+  NS_FORWARD_NSIDOMNODE(nsGenericHTMLElement::)
+
+  // nsIDOMElement
+  NS_FORWARD_NSIDOMELEMENT(nsGenericHTMLElement::)
+
+  // nsIDOMHTMLElement
+  NS_FORWARD_NSIDOMHTMLELEMENT(nsGenericHTMLElement::)
+
+  // nsIDOMHTMLTableElement
+  NS_DECL_NSIDOMHTMLTABLEELEMENT
+
+  virtual PRBool ParseAttribute(PRInt32 aNamespaceID,
+                                nsIAtom* aAttribute,
+                                const nsAString& aValue,
+                                nsAttrValue& aResult);
+  virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const;
+  NS_IMETHOD_(PRBool) IsAttributeMapped(const nsIAtom* aAttribute) const;
+
+  virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
+
+  virtual nsXPCClassInfo* GetClassInfo();
+  virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
+                              nsIContent* aBindingParent,
+                              PRBool aCompileEventHandlers);
+  virtual void UnbindFromTree(PRBool aDeep = PR_TRUE,
+                              PRBool aNullParent = PR_TRUE);
+  /**
+   * Called when an attribute is about to be changed
+   */
+  virtual nsresult BeforeSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
+                                 const nsAString* aValue, PRBool aNotify);
+  /**
+   * Called when an attribute has just been changed
+   */
+  virtual nsresult AfterSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
+                                const nsAString* aValue, PRBool aNotify);
+
+  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_NO_UNLINK(nsHTMLTableElement,
+                                                     nsGenericHTMLElement)
+  nsMappedAttributes* GetAttributesMappedForCell();
+  already_AddRefed<nsIDOMHTMLTableSectionElement> GetTHead() {
+    return GetSection(nsGkAtoms::thead);
+  }
+  already_AddRefed<nsIDOMHTMLTableSectionElement> GetTFoot() {
+    return GetSection(nsGkAtoms::tfoot);
+  }
+  nsContentList* TBodies();
+protected:
+  already_AddRefed<nsIDOMHTMLTableSectionElement> GetSection(nsIAtom *aTag);
+
+  nsRefPtr<nsContentList> mTBodies;
+  nsRefPtr<TableRowsCollection> mRows;
+  // Sentinel value of TABLE_ATTRS_DIRTY indicates that this is dirty and needs
+  // to be recalculated.
+  nsMappedAttributes *mTableInheritedAttributes;
+  void BuildInheritedAttributes();
+  void ReleaseInheritedAttributes() {
+    if (mTableInheritedAttributes &&
+        mTableInheritedAttributes != TABLE_ATTRS_DIRTY)
+      NS_RELEASE(mTableInheritedAttributes);
+      mTableInheritedAttributes = TABLE_ATTRS_DIRTY;
+  }
+};
+