Bug 861880 - Move TreeColumns to WebIDL; r=bz
authorMs2ger <ms2ger@gmail.com>
Sun, 21 Apr 2013 08:42:26 +0200
changeset 129364 0d50cb959c46f21d0e0e7d884f97127794a78c5d
parent 129363 047132a1517fb17d0c8e6dce3649a31e4e74ed51
child 129430 a09acc1ed63514a395981e5d4db2d5232327aa3f
push id24571
push userMs2ger@gmail.com
push dateSun, 21 Apr 2013 06:44:13 +0000
treeherdermozilla-central@0d50cb959c46 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz
bugs861880
milestone23.0a1
first release with
nightly linux32
0d50cb959c46 / 23.0a1 / 20130421031002 / files
nightly linux64
0d50cb959c46 / 23.0a1 / 20130421031002 / files
nightly mac
0d50cb959c46 / 23.0a1 / 20130421031002 / files
nightly win32
0d50cb959c46 / 23.0a1 / 20130421031002 / files
nightly win64
0d50cb959c46 / 23.0a1 / 20130421031002 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 861880 - Move TreeColumns to WebIDL; r=bz
dom/base/nsDOMClassInfo.cpp
dom/base/nsDOMClassInfo.h
dom/base/nsDOMClassInfoClasses.h
dom/bindings/Bindings.conf
dom/webidl/TreeColumns.webidl
dom/webidl/WebIDL.mk
layout/xul/tree/nsTreeColumns.cpp
layout/xul/tree/nsTreeColumns.h
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -683,19 +683,16 @@ static nsDOMClassInfoData sClassInfoData
 #endif
 
   NS_DEFINE_CLASSINFO_DATA(DOMStringList, nsStringListSH,
                            ARRAY_SCRIPTABLE_FLAGS)
 
 #ifdef MOZ_XUL
   NS_DEFINE_CLASSINFO_DATA(TreeColumn, nsDOMGenericSH,
                            DEFAULT_SCRIPTABLE_FLAGS)
-
-  NS_DEFINE_CLASSINFO_DATA(TreeColumns, nsTreeColumnsSH,
-                           ARRAY_SCRIPTABLE_FLAGS)
 #endif
 
   NS_DEFINE_CLASSINFO_DATA(CSSMozDocumentRule, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 
   NS_DEFINE_CLASSINFO_DATA(CSSSupportsRule, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 
@@ -1941,20 +1938,16 @@ nsDOMClassInfo::Init()
   DOM_CLASSINFO_MAP_BEGIN(DOMStringList, nsIDOMDOMStringList)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMDOMStringList)
   DOM_CLASSINFO_MAP_END
 
 #ifdef MOZ_XUL
   DOM_CLASSINFO_MAP_BEGIN(TreeColumn, nsITreeColumn)
     DOM_CLASSINFO_MAP_ENTRY(nsITreeColumn)
   DOM_CLASSINFO_MAP_END
-
-  DOM_CLASSINFO_MAP_BEGIN(TreeColumns, nsITreeColumns)
-    DOM_CLASSINFO_MAP_ENTRY(nsITreeColumns)
-  DOM_CLASSINFO_MAP_END
 #endif
 
   DOM_CLASSINFO_MAP_BEGIN(CSSMozDocumentRule, nsIDOMCSSMozDocumentRule)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMCSSMozDocumentRule)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(CSSSupportsRule, nsIDOMCSSSupportsRule)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMCSSSupportsRule)
@@ -7204,40 +7197,16 @@ nsCSSRuleListSH::GetItemAt(nsISupports *
     // pointer. That must be fixed, or we'll crash...
     NS_ABORT_IF_FALSE(list_qi == list, "Uh, fix QI!");
   }
 #endif
 
   return list->GetItemAt(aIndex, aResult);
 }
 
-#ifdef MOZ_XUL
-// TreeColumns helper
-
-nsISupports*
-nsTreeColumnsSH::GetItemAt(nsISupports *aNative, uint32_t aIndex,
-                           nsWrapperCache **aCache, nsresult *aResult)
-{
-  nsTreeColumns* columns = nsTreeColumns::FromSupports(aNative);
-
-  return columns->GetColumnAt(aIndex);
-}
-
-nsISupports*
-nsTreeColumnsSH::GetNamedItem(nsISupports *aNative,
-                              const nsAString& aName,
-                              nsWrapperCache **aCache,
-                              nsresult *aResult)
-{
-  nsTreeColumns* columns = nsTreeColumns::FromSupports(aNative);
-
-  return columns->GetNamedColumn(aName);
-}
-#endif
-
 
 // Storage2SH
 
 // One reason we need a newResolve hook is that in order for
 // enumeration of storage object keys to work the keys we're
 // enumerating need to exist on the storage object for the JS engine
 // to find them.
 
--- a/dom/base/nsDOMClassInfo.h
+++ b/dom/base/nsDOMClassInfo.h
@@ -984,47 +984,16 @@ class nsDOMTouchListSH : public nsArrayS
 
   public:
   static nsIClassInfo* doCreate(nsDOMClassInfoData* aData)
   {
     return new nsDOMTouchListSH(aData);
   }
 };
 
-#ifdef MOZ_XUL
-// TreeColumns helper
-
-class nsTreeColumnsSH : public nsNamedArraySH
-{
-protected:
-  nsTreeColumnsSH(nsDOMClassInfoData* aData) : nsNamedArraySH(aData)
-  {
-  }
-
-  virtual ~nsTreeColumnsSH()
-  {
-  }
-
-  virtual nsISupports* GetItemAt(nsISupports *aNative, uint32_t aIndex,
-                                 nsWrapperCache **aCache, nsresult *aResult);
-
-  // Override nsNamedArraySH::GetNamedItem()
-  virtual nsISupports* GetNamedItem(nsISupports *aNative,
-                                    const nsAString& aName,
-                                    nsWrapperCache **cache,
-                                    nsresult *aResult);
-
-public:
-  static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
-  {
-    return new nsTreeColumnsSH(aData);
-  }
-};
-#endif
-
 // WebApps Storage helpers
 
 class nsStorage2SH : public nsDOMGenericSH
 {
 protected:
   nsStorage2SH(nsDOMClassInfoData* aData) : nsDOMGenericSH(aData)
   {
   }
--- a/dom/base/nsDOMClassInfoClasses.h
+++ b/dom/base/nsDOMClassInfoClasses.h
@@ -91,17 +91,16 @@ DOMCI_CLASS(XULTemplateBuilder)
 DOMCI_CLASS(XULTreeBuilder)
 #endif
 
 // DOMStringList object
 DOMCI_CLASS(DOMStringList)
 
 #ifdef MOZ_XUL
 DOMCI_CLASS(TreeColumn)
-DOMCI_CLASS(TreeColumns)
 #endif
 
 DOMCI_CLASS(CSSMozDocumentRule)
 DOMCI_CLASS(CSSSupportsRule)
 
 DOMCI_CLASS(BeforeUnloadEvent)
 
 DOMCI_CLASS(TimeEvent)
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -1014,16 +1014,20 @@ DOMInterfaces = {
 'TouchEvent': {
     'nativeType': 'nsDOMTouchEvent',
 },
 
 'TransitionEvent': {
     'nativeType': 'nsDOMTransitionEvent',
 },
 
+'TreeColumns': {
+    'nativeType': 'nsTreeColumns',
+},
+
 'TreeWalker': {
     'wrapperCache': False,
     'resultNotAddRefed': [ 'root', 'currentNode' ],
 },
 
 'UIEvent': {
     'nativeType': 'nsDOMUIEvent',
     'hasXPConnectImpls': True
@@ -1507,16 +1511,20 @@ addExternalIface('MediaList')
 addExternalIface('MenuBuilder', nativeType='nsIMenuBuilder', notflattened=True)
 addExternalIface('MozBoxObject', nativeType='nsIBoxObject')
 addExternalIface('MozControllers', nativeType='nsIControllers')
 addExternalIface('MozFrameLoader', nativeType='nsIFrameLoader', notflattened=True)
 addExternalIface('MozObserver', nativeType='nsIObserver', notflattened=True)
 addExternalIface('MozRDFCompositeDataSource', nativeType='nsIRDFCompositeDataSource',
                  notflattened=True)
 addExternalIface('MozRDFResource', nativeType='nsIRDFResource', notflattened=True)
+addExternalIface('MozTreeBoxObject', nativeType='nsITreeBoxObject',
+                 notflattened=True)
+addExternalIface('MozTreeColumn', nativeType='nsITreeColumn',
+                 headerFile='nsITreeColumns.h')
 addExternalIface('MozXULTemplateBuilder', nativeType='nsIXULTemplateBuilder')
 addExternalIface('MozNamedAttrMap')
 addExternalIface('nsIControllers', nativeType='nsIControllers')
 addExternalIface('nsIInputStreamCallback', nativeType='nsIInputStreamCallback',
                  headerFile='nsIAsyncInputStream.h')
 addExternalIface('nsIStreamListener', nativeType='nsIStreamListener', notflattened=True)
 addExternalIface('nsISupports', nativeType='nsISupports')
 addExternalIface('nsIEditor', nativeType='nsIEditor', notflattened=True)
new file mode 100644
--- /dev/null
+++ b/dom/webidl/TreeColumns.webidl
@@ -0,0 +1,56 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtaone at http://mozilla.org/MPL/2.0/. */
+
+interface MozTreeBoxObject;
+interface MozTreeColumn;
+
+interface TreeColumns {
+  /**
+   * The tree widget for these columns.
+   */
+  readonly attribute MozTreeBoxObject? tree;
+
+  /**
+   * The number of columns.
+   */
+  readonly attribute unsigned long count;
+
+  /**
+   * An alias for count (for the benefit of scripts which treat this as an
+   * array).
+   */
+  readonly attribute unsigned long length;
+
+  /**
+   * Get the first/last column.
+   */
+  MozTreeColumn? getFirstColumn();
+  MozTreeColumn? getLastColumn();
+
+  /**
+   * Attribute based column getters.
+   */
+  MozTreeColumn? getPrimaryColumn();
+  MozTreeColumn? getSortedColumn();
+  MozTreeColumn? getKeyColumn();
+
+  /**
+   * Get the column for the given element.
+   */
+  MozTreeColumn? getColumnFor(Element? element);
+
+  /**
+   * Parametric column getters.
+   */
+  getter MozTreeColumn? getNamedColumn(DOMString id);
+  getter MozTreeColumn? getColumnAt(unsigned long index);
+
+  /**
+   * This method is called whenever a treecol is added or removed and
+   * the column cache needs to be rebuilt.
+   */
+  void invalidateColumns();
+
+  void restoreNaturalOrder();
+};
--- a/dom/webidl/WebIDL.mk
+++ b/dom/webidl/WebIDL.mk
@@ -286,16 +286,17 @@ webidl_files = \
   SVGZoomAndPan.webidl \
   Text.webidl \
   TextDecoder.webidl \
   TextEncoder.webidl \
   TimeRanges.webidl \
   Touch.webidl \
   TouchEvent.webidl \
   TransitionEvent.webidl \
+  TreeColumns.webidl \
   TreeWalker.webidl \
   UIEvent.webidl \
   URL.webidl \
   ValidityState.webidl \
   WebComponents.webidl \
   WebSocket.webidl \
   WheelEvent.webidl \
   UndoManager.webidl \
--- a/layout/xul/tree/nsTreeColumns.cpp
+++ b/layout/xul/tree/nsTreeColumns.cpp
@@ -9,16 +9,20 @@
 #include "nsIBoxObject.h"
 #include "nsTreeColumns.h"
 #include "nsTreeUtils.h"
 #include "nsStyleContext.h"
 #include "nsDOMClassInfoID.h"
 #include "nsINodeInfo.h"
 #include "nsContentUtils.h"
 #include "nsTreeBodyFrame.h"
+#include "mozilla/dom/Element.h"
+#include "mozilla/dom/TreeColumnsBinding.h"
+
+using namespace mozilla;
 
 // Column class that caches all the info about our column.
 nsTreeColumn::nsTreeColumn(nsTreeColumns* aColumns, nsIContent* aContent)
   : mContent(aContent),
     mColumns(aColumns),
     mPrevious(nullptr)
 {
   NS_ASSERTION(aContent &&
@@ -338,116 +342,151 @@ nsTreeColumn::Invalidate()
   return NS_OK;
 }
 
 
 nsTreeColumns::nsTreeColumns(nsTreeBodyFrame* aTree)
   : mTree(aTree),
     mFirstColumn(nullptr)
 {
+  SetIsDOMBinding();
 }
 
 nsTreeColumns::~nsTreeColumns()
 {
   nsTreeColumns::InvalidateColumns();
 }
 
-DOMCI_DATA(TreeColumns, nsTreeColumns)
+NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(nsTreeColumns)
 
 // QueryInterface implementation for nsTreeColumns
-NS_INTERFACE_MAP_BEGIN(nsTreeColumns)
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsTreeColumns)
+  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_INTERFACE_MAP_ENTRY(nsITreeColumns)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
-  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(TreeColumns)
 NS_INTERFACE_MAP_END
                                                                                 
-NS_IMPL_ADDREF(nsTreeColumns)
-NS_IMPL_RELEASE(nsTreeColumns)
+NS_IMPL_CYCLE_COLLECTING_ADDREF(nsTreeColumns)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(nsTreeColumns)
+
+nsIContent*
+nsTreeColumns::GetParentObject() const
+{
+  return mTree ? mTree->GetBaseElement() : nullptr;
+}
+
+/* virtual */ JSObject*
+nsTreeColumns::WrapObject(JSContext* aCx, JSObject* aScope)
+{
+  return dom::TreeColumnsBinding::Wrap(aCx, aScope, this);
+}
+
+nsITreeBoxObject*
+nsTreeColumns::GetTree() const
+{
+  return mTree ? mTree->GetTreeBoxObject() : nullptr;
+}
 
 NS_IMETHODIMP
 nsTreeColumns::GetTree(nsITreeBoxObject** _retval)
 {
-  NS_IF_ADDREF(*_retval = mTree ? mTree->GetTreeBoxObject() : nullptr);
+  NS_IF_ADDREF(*_retval = GetTree());
   return NS_OK;
 }
 
+uint32_t
+nsTreeColumns::Count()
+{
+  EnsureColumns();
+  uint32_t count = 0;
+  for (nsTreeColumn* currCol = mFirstColumn; currCol; currCol = currCol->GetNext()) {
+    ++count;
+  }
+  return count;
+}
+
 NS_IMETHODIMP
 nsTreeColumns::GetCount(int32_t* _retval)
 {
-  EnsureColumns();
-  *_retval = 0;
-  for (nsTreeColumn* currCol = mFirstColumn; currCol; currCol = currCol->GetNext()) {
-    ++(*_retval);
-  }
+  *_retval = Count();
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsTreeColumns::GetLength(int32_t* _retval)
 {
-  return GetCount(_retval);
+  *_retval = Length();
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 nsTreeColumns::GetFirstColumn(nsITreeColumn** _retval)
 {
   NS_IF_ADDREF(*_retval = GetFirstColumn());
   return NS_OK;
 }
 
-NS_IMETHODIMP
-nsTreeColumns::GetLastColumn(nsITreeColumn** _retval)
+nsTreeColumn*
+nsTreeColumns::GetLastColumn()
 {
   EnsureColumns();
-  *_retval = nullptr;
   nsTreeColumn* currCol = mFirstColumn;
   while (currCol) {
     nsTreeColumn* next = currCol->GetNext();
     if (!next) {
-      NS_ADDREF(*_retval = currCol);
-      break;
+      return currCol;
     }
     currCol = next;
   }
+  return nullptr;
+}
+
+NS_IMETHODIMP
+nsTreeColumns::GetLastColumn(nsITreeColumn** _retval)
+{
+  NS_IF_ADDREF(*_retval = GetLastColumn());
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsTreeColumns::GetPrimaryColumn(nsITreeColumn** _retval)
 {
   NS_IF_ADDREF(*_retval = GetPrimaryColumn());
   return NS_OK;
 }
 
-NS_IMETHODIMP
-nsTreeColumns::GetSortedColumn(nsITreeColumn** _retval)
+nsTreeColumn*
+nsTreeColumns::GetSortedColumn()
 {
   EnsureColumns();
-  *_retval = nullptr;
   for (nsTreeColumn* currCol = mFirstColumn; currCol; currCol = currCol->GetNext()) {
     if (currCol->mContent &&
         nsContentUtils::HasNonEmptyAttr(currCol->mContent, kNameSpaceID_None,
                                         nsGkAtoms::sortDirection)) {
-      NS_ADDREF(*_retval = currCol);
-      return NS_OK;
+      return currCol;
     }
   }
-  return NS_OK;
+  return nullptr;
 }
 
 NS_IMETHODIMP
-nsTreeColumns::GetKeyColumn(nsITreeColumn** _retval)
+nsTreeColumns::GetSortedColumn(nsITreeColumn** _retval)
+{
+  NS_IF_ADDREF(*_retval = GetSortedColumn());
+  return NS_OK;
+}
+
+nsTreeColumn*
+nsTreeColumns::GetKeyColumn()
 {
   EnsureColumns();
-  *_retval = nullptr;
 
-  nsTreeColumn* first;
-  nsTreeColumn* primary;
-  nsTreeColumn* sorted;
-  first = primary = sorted = nullptr;
+  nsTreeColumn* first = nullptr;
+  nsTreeColumn* primary = nullptr;
+  nsTreeColumn* sorted = nullptr;
 
   for (nsTreeColumn* currCol = mFirstColumn; currCol; currCol = currCol->GetNext()) {
     // Skip hidden columns.
     if (!currCol->mContent ||
         currCol->mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::hidden,
                                        nsGkAtoms::_true, eCaseMatters))
       continue;
 
@@ -466,77 +505,111 @@ nsTreeColumns::GetKeyColumn(nsITreeColum
     }
 
     if (currCol->IsPrimary())
       if (!primary)
         primary = currCol;
   }
 
   if (sorted)
-    *_retval = sorted;
-  else if (primary)
-    *_retval = primary;
-  else
-    *_retval = first;
+    return sorted;
+  if (primary)
+    return primary;
+  return first;
+}
 
-  NS_IF_ADDREF(*_retval);
+NS_IMETHODIMP
+nsTreeColumns::GetKeyColumn(nsITreeColumn** _retval)
+{
+  NS_IF_ADDREF(*_retval = GetKeyColumn());
   return NS_OK;
 }
 
+nsTreeColumn*
+nsTreeColumns::GetColumnFor(dom::Element* aElement)
+{
+  EnsureColumns();
+  for (nsTreeColumn* currCol = mFirstColumn; currCol; currCol = currCol->GetNext()) {
+    if (currCol->mContent == aElement) {
+      return currCol;
+    }
+  }
+  return nullptr;
+}
+
 NS_IMETHODIMP
 nsTreeColumns::GetColumnFor(nsIDOMElement* aElement, nsITreeColumn** _retval)
 {
-  EnsureColumns();
-  *_retval = nullptr;
-  nsCOMPtr<nsIContent> element = do_QueryInterface(aElement);
-  for (nsTreeColumn* currCol = mFirstColumn; currCol; currCol = currCol->GetNext()) {
-    if (currCol->mContent == element) {
-      NS_ADDREF(*_retval = currCol);
-      break;
-    }
-  }
-
+  nsCOMPtr<dom::Element> element = do_QueryInterface(aElement);
+  NS_ADDREF(*_retval = GetColumnFor(element));
   return NS_OK;
 }
 
-nsITreeColumn*
-nsTreeColumns::GetNamedColumn(const nsAString& aId)
+nsTreeColumn*
+nsTreeColumns::NamedGetter(const nsAString& aId, bool& aFound)
 {
   EnsureColumns();
   for (nsTreeColumn* currCol = mFirstColumn; currCol; currCol = currCol->GetNext()) {
     if (currCol->GetId().Equals(aId)) {
+      aFound = true;
       return currCol;
     }
   }
+  aFound = false;
   return nullptr;
 }
 
+nsTreeColumn*
+nsTreeColumns::GetNamedColumn(const nsAString& aId)
+{
+  bool dummy;
+  return NamedGetter(aId, dummy);
+}
+
 NS_IMETHODIMP
 nsTreeColumns::GetNamedColumn(const nsAString& aId, nsITreeColumn** _retval)
 {
   NS_IF_ADDREF(*_retval = GetNamedColumn(aId));
   return NS_OK;
 }
 
-nsITreeColumn*
-nsTreeColumns::GetColumnAt(int32_t aIndex)
+void
+nsTreeColumns::GetSupportedNames(nsTArray<nsString>& aNames)
+{
+  for (nsTreeColumn* currCol = mFirstColumn; currCol; currCol = currCol->GetNext()) {
+    aNames.AppendElement(currCol->GetId());
+  }
+}
+
+
+nsTreeColumn*
+nsTreeColumns::IndexedGetter(uint32_t aIndex, bool& aFound)
 {
   EnsureColumns();
   for (nsTreeColumn* currCol = mFirstColumn; currCol; currCol = currCol->GetNext()) {
-    if (currCol->GetIndex() == aIndex) {
+    if (currCol->GetIndex() == static_cast<int32_t>(aIndex)) {
+      aFound = true;
       return currCol;
     }
   }
+  aFound = false;
   return nullptr;
 }
 
+nsTreeColumn*
+nsTreeColumns::GetColumnAt(uint32_t aIndex)
+{
+  bool dummy;
+  return IndexedGetter(aIndex, dummy);
+}
+
 NS_IMETHODIMP
 nsTreeColumns::GetColumnAt(int32_t aIndex, nsITreeColumn** _retval)
 {
-  NS_IF_ADDREF(*_retval = GetColumnAt(aIndex));
+  NS_IF_ADDREF(*_retval = GetColumnAt(static_cast<uint32_t>(aIndex)));
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsTreeColumns::InvalidateColumns()
 {
   for (nsTreeColumn* currCol = mFirstColumn; currCol;
        currCol = currCol->GetNext()) {
--- a/layout/xul/tree/nsTreeColumns.h
+++ b/layout/xul/tree/nsTreeColumns.h
@@ -7,23 +7,30 @@
 #define nsTreeColumns_h__
 
 #include "nsITreeColumns.h"
 #include "nsITreeBoxObject.h"
 #include "mozilla/Attributes.h"
 #include "nsCoord.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsAutoPtr.h"
+#include "nsWrapperCache.h"
 
 class nsTreeBodyFrame;
 class nsTreeColumns;
 class nsIFrame;
 class nsIContent;
 struct nsRect;
 
+namespace mozilla {
+namespace dom {
+class Element;
+} // namespace dom
+} // namespace mozilla
+
 #define NS_TREECOLUMN_IMPL_CID                       \
 { /* 02cd1963-4b5d-4a6c-9223-814d3ade93a3 */         \
     0x02cd1963,                                      \
     0x4b5d,                                          \
     0x4a6c,                                          \
     {0x92, 0x23, 0x81, 0x4d, 0x3a, 0xde, 0x93, 0xa3} \
 }
 
@@ -110,54 +117,63 @@ private:
   int8_t mTextAlignment;
 
   nsRefPtr<nsTreeColumn> mNext;
   nsTreeColumn* mPrevious;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsTreeColumn, NS_TREECOLUMN_IMPL_CID)
 
-class nsTreeColumns MOZ_FINAL : public nsITreeColumns {
+class nsTreeColumns MOZ_FINAL : public nsITreeColumns
+                              , public nsWrapperCache
+{
 public:
   nsTreeColumns(nsTreeBodyFrame* aTree);
   ~nsTreeColumns();
 
-  NS_DECL_ISUPPORTS
+  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsTreeColumns)
   NS_DECL_NSITREECOLUMNS
 
-  nsITreeColumn* GetColumnAt(int32_t aIndex);
-  nsITreeColumn* GetNamedColumn(const nsAString& aId);
+  nsIContent* GetParentObject() const;
+  virtual JSObject* WrapObject(JSContext* aCx, JSObject* aScope) MOZ_OVERRIDE;
 
-  static nsTreeColumns* FromSupports(nsISupports* aSupports)
+  // WebIDL
+  nsITreeBoxObject* GetTree() const;
+  uint32_t Count();
+  uint32_t Length()
   {
-#ifdef DEBUG
-    {
-      nsCOMPtr<nsITreeColumns> columns_qi = do_QueryInterface(aSupports);
+    return Count();
+  }
+
+  nsTreeColumn* GetFirstColumn() { EnsureColumns(); return mFirstColumn; }
+  nsTreeColumn* GetLastColumn();
 
-      // If this assertion fires the QI implementation for the object in
-      // question doesn't use the nsITreeColumns pointer as the nsISupports
-      // pointer. That must be fixed, or we'll crash...
-      NS_ASSERTION(columns_qi == static_cast<nsITreeColumns*>(aSupports),
-                   "Uh, fix QI!");
-    }
-#endif
+  nsTreeColumn* GetPrimaryColumn();
+  nsTreeColumn* GetSortedColumn();
+  nsTreeColumn* GetKeyColumn();
+
+  nsTreeColumn* GetColumnFor(mozilla::dom::Element* aElement);
 
-    return static_cast<nsTreeColumns*>(aSupports);
-  }
+  nsTreeColumn* IndexedGetter(uint32_t aIndex, bool& aFound);
+  nsTreeColumn* GetColumnAt(uint32_t aIndex);
+  nsTreeColumn* NamedGetter(const nsAString& aId, bool& aFound);
+  nsTreeColumn* GetNamedColumn(const nsAString& aId);
+  void GetSupportedNames(nsTArray<nsString>& aNames);
+
+  // Uses XPCOM InvalidateColumns().
+  // Uses XPCOM RestoreNaturalOrder().
 
   friend class nsTreeBodyFrame;
 protected:
   void SetTree(nsTreeBodyFrame* aTree) { mTree = aTree; }
 
   // Builds our cache of column info.
   void EnsureColumns();
 
-  nsTreeColumn* GetFirstColumn() { EnsureColumns(); return mFirstColumn; }
-  nsTreeColumn* GetPrimaryColumn();
-
 private:
   nsTreeBodyFrame* mTree;
 
   /**
    * The first column in the list of columns. All of the columns are supposed
    * to be "alive", i.e. have a frame. This is achieved by clearing the columns
    * list each time an nsTreeColFrame is destroyed.
    *