Bug 995664 - Move CSSRuleList to WebIDL; r=bz
authorMs2ger <ms2ger@gmail.com>
Sat, 03 May 2014 09:32:54 +0200
changeset 200657 cc42442f4728c36dcda8a2d833ac7f438d7ec6fa
parent 200656 8a21f9e10a754d6592867a66a473cbaf65ef1d65
child 200658 e50544d1d32d9d86f1db8a2c3338d5502773a402
push id3741
push userasasaki@mozilla.com
push dateMon, 21 Jul 2014 20:25:18 +0000
treeherdermozilla-beta@4d6f46f5af68 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz
bugs995664
milestone32.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 995664 - Move CSSRuleList to WebIDL; r=bz As CSSRuleList is the last consumer of nsArraySH and nsGenericArraySH, this also removes those classes.
dom/base/nsDOMClassInfo.cpp
dom/base/nsDOMClassInfo.h
dom/base/nsDOMClassInfoClasses.h
dom/bindings/Bindings.conf
dom/webidl/CSSRuleList.webidl
dom/webidl/CSSStyleSheet.webidl
dom/webidl/moz.build
layout/style/moz.build
layout/style/nsCSSRules.cpp
layout/style/nsCSSStyleSheet.cpp
layout/style/nsCSSStyleSheet.h
layout/style/nsICSSRuleList.cpp
layout/style/nsICSSRuleList.h
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -80,17 +80,16 @@
 #include "nsIDOMXULPopupElement.h"
 
 // Event related includes
 #include "nsIDOMEventTarget.h"
 
 // CSS related includes
 #include "nsCSSRules.h"
 #include "nsIDOMCSSRule.h"
-#include "nsICSSRuleList.h"
 #include "nsAutoPtr.h"
 #include "nsMemory.h"
 
 // Tranformiix
 #include "nsIXSLTProcessor.h"
 #include "nsIXSLTProcessorPrivate.h"
 
 // includes needed for the prototype chain interfaces
@@ -307,18 +306,16 @@ static nsDOMClassInfoData sClassInfoData
   NS_DEFINE_CLASSINFO_DATA(CSSCharsetRule, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(CSSImportRule, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(CSSMediaRule, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(CSSNameSpaceRule, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
-  NS_DEFINE_CLASSINFO_DATA(CSSRuleList, nsCSSRuleListSH,
-                           ARRAY_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(CSSStyleSheet, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 
   // XUL classes
 #ifdef MOZ_XUL
   NS_DEFINE_CHROME_XBL_CLASSINFO_DATA(XULCommandDispatcher, nsDOMGenericSH,
                                       DOM_DEFAULT_SCRIPTABLE_FLAGS)
 #endif
@@ -923,20 +920,16 @@ nsDOMClassInfo::Init()
   DOM_CLASSINFO_MAP_BEGIN(CSSMediaRule, nsIDOMCSSMediaRule)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMCSSMediaRule)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(CSSNameSpaceRule, nsIDOMCSSRule)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMCSSRule)
   DOM_CLASSINFO_MAP_END
 
-  DOM_CLASSINFO_MAP_BEGIN(CSSRuleList, nsIDOMCSSRuleList)
-    DOM_CLASSINFO_MAP_ENTRY(nsIDOMCSSRuleList)
-  DOM_CLASSINFO_MAP_END
-
   DOM_CLASSINFO_MAP_BEGIN(CSSStyleSheet, nsIDOMCSSStyleSheet)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMCSSStyleSheet)
   DOM_CLASSINFO_MAP_END
 
 #ifdef MOZ_XUL
   DOM_CLASSINFO_MAP_BEGIN(XULCommandDispatcher, nsIDOMXULCommandDispatcher)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMXULCommandDispatcher)
   DOM_CLASSINFO_MAP_END
@@ -3495,178 +3488,16 @@ nsEventTargetSH::AddProperty(nsIXPConnec
 
 void
 nsEventTargetSH::PreserveWrapper(nsISupports *aNative)
 {
   DOMEventTargetHelper* target = DOMEventTargetHelper::FromSupports(aNative);
   target->PreserveWrapper(aNative);
 }
 
-// Generic array scriptable helper.
-
-NS_IMETHODIMP
-nsGenericArraySH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
-                             JSObject *aObj, jsid aId, JSObject **objp,
-                             bool *_retval)
-{
-  JS::Rooted<JSObject*> obj(cx, aObj);
-  JS::Rooted<jsid> id(cx, aId);
-  if (id == sLength_id) {
-    // Bail early; this isn't something we're interested in
-    return NS_OK;
-  }
-
-  bool is_number = false;
-  int32_t n = GetArrayIndexFromId(cx, id, &is_number);
-
-  if (is_number && n >= 0) {
-    // XXX The following is a cheap optimization to avoid hitting xpconnect to
-    // get the length. We may want to consider asking our concrete
-    // implementation for the length, and falling back onto the GetProperty if
-    // it doesn't provide one.
-
-    uint32_t length;
-    nsresult rv = GetLength(wrapper, cx, obj, &length);
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    uint32_t index = uint32_t(n);
-    if (index < length) {
-      *_retval = ::JS_DefineElement(cx, obj, index, JS::UndefinedHandleValue,
-                                    JSPROP_ENUMERATE | JSPROP_SHARED);
-      *objp = obj;
-    }
-  }
-
-  return NS_OK;
-}
-
-nsresult
-nsGenericArraySH::GetLength(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
-                            JS::Handle<JSObject*> obj, uint32_t *length)
-{
-  *length = 0;
-
-  JS::Rooted<JS::Value> lenval(cx);
-  if (!JS_GetProperty(cx, obj, "length", &lenval)) {
-    return NS_ERROR_UNEXPECTED;
-  }
-
-  if (!lenval.isInt32()) {
-    // This can apparently happen with some sparse array impls falling back
-    // onto this code.
-    return NS_OK;
-  }
-
-  int32_t slen = lenval.toInt32();
-  if (slen < 0) {
-    return NS_OK;
-  }
-
-  *length = (uint32_t)slen;
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsGenericArraySH::Enumerate(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
-                            JSObject *aObj, bool *_retval)
-{
-  // Recursion protection in case someone tries to be smart and call
-  // the enumerate hook from a user defined .length getter, or
-  // somesuch.
-
-  JS::Rooted<JSObject*> obj(cx, aObj);
-  static bool sCurrentlyEnumerating;
-
-  if (sCurrentlyEnumerating) {
-    // Don't recurse to death.
-    return NS_OK;
-  }
-
-  sCurrentlyEnumerating = true;
-
-  JS::Rooted<JS::Value> len_val(cx);
-  bool ok = ::JS_GetProperty(cx, obj, "length", &len_val);
-
-  if (ok && len_val.isInt32()) {
-    int32_t length = len_val.toInt32();
-
-    for (int32_t i = 0; ok && i < length; ++i) {
-      ok = ::JS_DefineElement(cx, obj, i, JS::UndefinedHandleValue,
-                              JSPROP_ENUMERATE | JSPROP_SHARED);
-    }
-  }
-
-  sCurrentlyEnumerating = false;
-
-  return ok ? NS_OK : NS_ERROR_UNEXPECTED;
-}
-
-// Array scriptable helper
-
-NS_IMETHODIMP
-nsArraySH::GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
-                       JSObject *aObj, jsid aId, jsval *vp, bool *_retval)
-{
-  JS::Rooted<JSObject*> obj(cx, aObj);
-  JS::Rooted<jsid> id(cx, aId);
-  bool is_number = false;
-  int32_t n = GetArrayIndexFromId(cx, id, &is_number);
-
-  nsresult rv = NS_OK;
-
-  if (is_number) {
-    if (n < 0) {
-      return NS_ERROR_DOM_INDEX_SIZE_ERR;
-    }
-
-    // Make sure rv == NS_OK here, so GetItemAt implementations that never fail
-    // don't have to set rv.
-    rv = NS_OK;
-    nsWrapperCache *cache = nullptr;
-    nsISupports* array_item =
-      GetItemAt(GetNative(wrapper, obj), n, &cache, &rv);
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    if (array_item) {
-      JS::Rooted<JS::Value> rval(cx);
-      rv = WrapNative(cx, array_item, cache, true, &rval);
-      NS_ENSURE_SUCCESS(rv, rv);
-      *vp = rval;
-
-      rv = NS_SUCCESS_I_DID_SOMETHING;
-    }
-  }
-
-  return rv;
-}
-
-
-// CSSRuleList scriptable helper
-
-nsISupports*
-nsCSSRuleListSH::GetItemAt(nsISupports *aNative, uint32_t aIndex,
-                           nsWrapperCache **aCache, nsresult *aResult)
-{
-  nsICSSRuleList* list = static_cast<nsICSSRuleList*>(aNative);
-#ifdef DEBUG
-  {
-    nsCOMPtr<nsICSSRuleList> list_qi = do_QueryInterface(aNative);
-
-    // If this assertion fires the QI implementation for the object in
-    // question doesn't use the nsICSSRuleList pointer as the nsISupports
-    // pointer. That must be fixed, or we'll crash...
-    NS_ABORT_IF_FALSE(list_qi == list, "Uh, fix QI!");
-  }
-#endif
-
-  return list->Item(aIndex);
-}
-
-
 // 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.
 
 NS_IMETHODIMP
--- a/dom/base/nsDOMClassInfo.h
+++ b/dom/base/nsDOMClassInfo.h
@@ -305,97 +305,16 @@ public:
 
   static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
   {
     return new nsLocationSH(aData);
   }
 };
 
 
-// Generic array scriptable helper
-
-class nsGenericArraySH : public nsDOMClassInfo
-{
-protected:
-  nsGenericArraySH(nsDOMClassInfoData* aData) : nsDOMClassInfo(aData)
-  {
-  }
-
-  virtual ~nsGenericArraySH()
-  {
-  }
-
-public:
-  NS_IMETHOD NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
-                        JSObject *obj, jsid id, JSObject **objp,
-                        bool *_retval) MOZ_OVERRIDE;
-  NS_IMETHOD Enumerate(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
-                       JSObject *obj, bool *_retval) MOZ_OVERRIDE;
-
-  virtual nsresult GetLength(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
-                             JS::Handle<JSObject*> obj, uint32_t *length);
-
-  static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
-  {
-    return new nsGenericArraySH(aData);
-  }
-};
-
-
-// Array scriptable helper
-
-class nsArraySH : public nsGenericArraySH
-{
-protected:
-  nsArraySH(nsDOMClassInfoData* aData) : nsGenericArraySH(aData)
-  {
-  }
-
-  virtual ~nsArraySH()
-  {
-  }
-
-  // Subclasses need to override this, if the implementation can't fail it's
-  // allowed to not set *aResult.
-  virtual nsISupports* GetItemAt(nsISupports *aNative, uint32_t aIndex,
-                                 nsWrapperCache **aCache, nsresult *aResult) = 0;
-
-public:
-  NS_IMETHOD GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
-                         JSObject *obj, jsid id, JS::Value *vp, bool *_retval) MOZ_OVERRIDE;
-
-private:
-  // Not implemented, nothing should create an instance of this class.
-  static nsIClassInfo *doCreate(nsDOMClassInfoData* aData);
-};
-
-
-// CSSRuleList helper
-
-class nsCSSRuleListSH : public nsArraySH
-{
-protected:
-  nsCSSRuleListSH(nsDOMClassInfoData* aData) : nsArraySH(aData)
-  {
-  }
-
-  virtual ~nsCSSRuleListSH()
-  {
-  }
-
-  virtual nsISupports* GetItemAt(nsISupports *aNative, uint32_t aIndex,
-                                 nsWrapperCache **aCache, nsresult *aResult) MOZ_OVERRIDE;
-
-public:
-  static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
-  {
-    return new nsCSSRuleListSH(aData);
-  }
-};
-
 // WebApps Storage helpers
 
 class nsStorage2SH : public nsDOMGenericSH
 {
 protected:
   nsStorage2SH(nsDOMClassInfoData* aData) : nsDOMGenericSH(aData)
   {
   }
--- a/dom/base/nsDOMClassInfoClasses.h
+++ b/dom/base/nsDOMClassInfoClasses.h
@@ -10,17 +10,16 @@ DOMCI_CLASS(DOMPrototype)
 DOMCI_CLASS(DOMConstructor)
 
 // CSS classes
 DOMCI_CLASS(CSSStyleRule)
 DOMCI_CLASS(CSSCharsetRule)
 DOMCI_CLASS(CSSImportRule)
 DOMCI_CLASS(CSSMediaRule)
 DOMCI_CLASS(CSSNameSpaceRule)
-DOMCI_CLASS(CSSRuleList)
 DOMCI_CLASS(CSSStyleSheet)
 
 // XUL classes
 #ifdef MOZ_XUL
 DOMCI_CLASS(XULCommandDispatcher)
 #endif
 DOMCI_CLASS(XULControllers)
 DOMCI_CLASS(BoxObject)
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -257,16 +257,20 @@ DOMInterfaces = {
     'nativeType': 'nsDOMCSSDeclaration'
 },
 
 'CSSPrimitiveValue': {
     'nativeType': 'nsROCSSPrimitiveValue',
     'resultNotAddRefed': ['getRGBColorValue', 'getRectValue']
 },
 
+'CSSRuleList': {
+    'nativeType': 'nsICSSRuleList',
+},
+
 'CSSStyleDeclaration': {
     'nativeType': 'nsICSSDeclaration'
 },
 
 'CSSStyleSheet': {
     'nativeType': 'nsCSSStyleSheet',
     'binaryNames': { 'ownerRule': 'DOMOwnerRule' },
 },
@@ -1885,17 +1889,16 @@ def addExternalIface(iface, nativeType=N
         domInterface['headerFile'] = headerFile
     domInterface['notflattened'] = notflattened
     DOMInterfaces[iface] = domInterface
 
 addExternalIface('ApplicationCache', nativeType='nsIDOMOfflineResourceList')
 addExternalIface('Counter')
 addExternalIface('CSSRule')
 addExternalIface('mozIDOMApplication', nativeType='mozIDOMApplication', headerFile='nsIDOMApplicationRegistry.h')
-addExternalIface('CSSRuleList')
 addExternalIface('RTCDataChannel', nativeType='nsIDOMDataChannel')
 addExternalIface('File')
 addExternalIface('HitRegionOptions', nativeType='nsISupports')
 addExternalIface('imgINotificationObserver', nativeType='imgINotificationObserver')
 addExternalIface('imgIRequest', nativeType='imgIRequest', notflattened=True)
 addExternalIface('MenuBuilder', nativeType='nsIMenuBuilder', notflattened=True)
 addExternalIface('MozBoxObject', nativeType='nsIBoxObject')
 addExternalIface('MozControllers', nativeType='nsIControllers')
new file mode 100644
--- /dev/null
+++ b/dom/webidl/CSSRuleList.webidl
@@ -0,0 +1,10 @@
+/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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 obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+interface CSSRuleList {
+  readonly attribute unsigned long length;
+  getter CSSRule? item(unsigned long index);
+};
--- a/dom/webidl/CSSStyleSheet.webidl
+++ b/dom/webidl/CSSStyleSheet.webidl
@@ -2,17 +2,16 @@
 /* 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 obtain one at http://mozilla.org/MPL/2.0/.
  *
  * The origin of this IDL file is
  * http://dev.w3.org/csswg/cssom/
  */
 
-interface CSSRuleList;
 interface CSSRule;
 
 interface CSSStyleSheet : StyleSheet {
   [Pure]
   readonly attribute CSSRule? ownerRule;
   [Throws]
   readonly attribute CSSRuleList cssRules;
   [Throws]
--- a/dom/webidl/moz.build
+++ b/dom/webidl/moz.build
@@ -58,16 +58,17 @@ WEBIDL_FILES = [
     'CompositionEvent.webidl',
     'Console.webidl',
     'Constraints.webidl',
     'Contacts.webidl',
     'ConvolverNode.webidl',
     'Coordinates.webidl',
     'CSS.webidl',
     'CSSPrimitiveValue.webidl',
+    'CSSRuleList.webidl',
     'CSSStyleDeclaration.webidl',
     'CSSStyleSheet.webidl',
     'CSSValue.webidl',
     'CSSValueList.webidl',
     'DataContainerEvent.webidl',
     'DataStore.webidl',
     'DataStoreImpl.webidl',
     'DataTransfer.webidl',
--- a/layout/style/moz.build
+++ b/layout/style/moz.build
@@ -107,16 +107,17 @@ UNIFIED_SOURCES += [
     'nsCSSValue.cpp',
     'nsDOMCSSAttrDeclaration.cpp',
     'nsDOMCSSDeclaration.cpp',
     'nsDOMCSSRect.cpp',
     'nsDOMCSSRGBColor.cpp',
     'nsDOMCSSValueList.cpp',
     'nsHTMLCSSStyleSheet.cpp',
     'nsHTMLStyleSheet.cpp',
+    'nsICSSRuleList.cpp',
     'nsLayoutStylesheetCache.cpp',
     'nsMediaFeatures.cpp',
     'nsNthIndexCache.cpp',
     'nsROCSSPrimitiveValue.cpp',
     'nsRuleData.cpp',
     'nsRuleNode.cpp',
     'nsStyleAnimation.cpp',
     'nsStyleContext.cpp',
--- a/layout/style/nsCSSRules.cpp
+++ b/layout/style/nsCSSRules.cpp
@@ -130,17 +130,17 @@ Rule::SizeOfCOMArrayElementIncludingThis
 // Style Rule List for group rules
 //
 
 class GroupRuleRuleList MOZ_FINAL : public nsICSSRuleList
 {
 public:
   GroupRuleRuleList(GroupRule *aGroupRule);
 
-  NS_DECL_ISUPPORTS
+  virtual nsCSSStyleSheet* GetParentObject() MOZ_OVERRIDE;
 
   virtual nsIDOMCSSRule*
   IndexedGetter(uint32_t aIndex, bool& aFound) MOZ_OVERRIDE;
   virtual uint32_t
   Length() MOZ_OVERRIDE;
 
   void DropReference() { mGroupRule = nullptr; }
 
@@ -157,27 +157,25 @@ GroupRuleRuleList::GroupRuleRuleList(Gro
   // The rule will tell us when its going away.
   mGroupRule = aGroupRule;
 }
 
 GroupRuleRuleList::~GroupRuleRuleList()
 {
 }
 
-// QueryInterface implementation for GroupRuleRuleList
-NS_INTERFACE_MAP_BEGIN(GroupRuleRuleList)
-  NS_INTERFACE_MAP_ENTRY(nsICSSRuleList)
-  NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRuleList)
-  NS_INTERFACE_MAP_ENTRY(nsISupports)
-  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CSSRuleList)
-NS_INTERFACE_MAP_END
-
-
-NS_IMPL_ADDREF(GroupRuleRuleList)
-NS_IMPL_RELEASE(GroupRuleRuleList)
+nsCSSStyleSheet*
+GroupRuleRuleList::GetParentObject()
+{
+  if (!mGroupRule) {
+    return nullptr;
+  }
+
+  return mGroupRule->GetStyleSheet();
+}
 
 uint32_t
 GroupRuleRuleList::Length()
 {
   if (!mGroupRule) {
     return 0;
   }
 
--- a/layout/style/nsCSSStyleSheet.cpp
+++ b/layout/style/nsCSSStyleSheet.cpp
@@ -50,17 +50,17 @@ using namespace mozilla::dom;
 // -------------------------------
 // Style Rule List for the DOM
 //
 class CSSRuleListImpl : public nsICSSRuleList
 {
 public:
   CSSRuleListImpl(nsCSSStyleSheet *aStyleSheet);
 
-  NS_DECL_ISUPPORTS
+  virtual nsCSSStyleSheet* GetParentObject() MOZ_OVERRIDE;
 
   virtual nsIDOMCSSRule*
   IndexedGetter(uint32_t aIndex, bool& aFound) MOZ_OVERRIDE;
   virtual uint32_t
   Length() MOZ_OVERRIDE;
 
   void DropReference() { mStyleSheet = nullptr; }
 
@@ -76,30 +76,21 @@ CSSRuleListImpl::CSSRuleListImpl(nsCSSSt
   // The style sheet will tell us when its going away.
   mStyleSheet = aStyleSheet;
 }
 
 CSSRuleListImpl::~CSSRuleListImpl()
 {
 }
 
-DOMCI_DATA(CSSRuleList, CSSRuleListImpl)
-
-// QueryInterface implementation for CSSRuleList
-NS_INTERFACE_MAP_BEGIN(CSSRuleListImpl)
-  NS_INTERFACE_MAP_ENTRY(nsICSSRuleList)
-  NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRuleList)
-  NS_INTERFACE_MAP_ENTRY(nsISupports)
-  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CSSRuleList)
-NS_INTERFACE_MAP_END
-
-
-NS_IMPL_ADDREF(CSSRuleListImpl)
-NS_IMPL_RELEASE(CSSRuleListImpl)
-
+nsCSSStyleSheet*
+CSSRuleListImpl::GetParentObject()
+{
+  return mStyleSheet;
+}
 
 uint32_t
 CSSRuleListImpl::Length()
 {
   if (!mStyleSheet) {
     return 0;
   }
 
@@ -1785,17 +1776,17 @@ NS_IMETHODIMP
 nsCSSStyleSheet::GetCssRules(nsIDOMCSSRuleList** aCssRules)
 {
   ErrorResult rv;
   nsCOMPtr<nsIDOMCSSRuleList> rules = GetCssRules(rv);
   rules.forget(aCssRules);
   return rv.ErrorCode();
 }
 
-nsIDOMCSSRuleList*
+nsICSSRuleList*
 nsCSSStyleSheet::GetCssRules(ErrorResult& aRv)
 {
   // No doing this on incomplete sheets!
   if (!mInner->mComplete) {
     aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
     return nullptr;
   }
   
--- a/layout/style/nsCSSStyleSheet.h
+++ b/layout/style/nsCSSStyleSheet.h
@@ -91,16 +91,17 @@ private:
 };
 
 
 // -------------------------------
 // CSS Style Sheet
 //
 
 class CSSRuleListImpl;
+class nsICSSRuleList;
 
 // CID for the nsCSSStyleSheet class
 // ca926f30-2a7e-477e-8467-803fb32af20a
 #define NS_CSS_STYLE_SHEET_IMPL_CID     \
 { 0xca926f30, 0x2a7e, 0x477e, \
  { 0x84, 0x67, 0x80, 0x3f, 0xb3, 0x2a, 0xf2, 0x0a } }
 
 
@@ -270,17 +271,17 @@ public:
   bool Disabled() const { return mDisabled; }
   // The XPCOM SetDisabled is fine for WebIDL
 
   // WebIDL CSSStyleSheet API
   // Can't be inline because we can't include ImportRule here.  And can't be
   // called GetOwnerRule because that would be ambiguous with the ImportRule
   // version.
   nsIDOMCSSRule* GetDOMOwnerRule() const;
-  nsIDOMCSSRuleList* GetCssRules(mozilla::ErrorResult& aRv);
+  nsICSSRuleList* GetCssRules(mozilla::ErrorResult& aRv);
   uint32_t InsertRule(const nsAString& aRule, uint32_t aIndex,
                       mozilla::ErrorResult& aRv) {
     uint32_t retval;
     aRv = InsertRule(aRule, aIndex, &retval);
     return retval;
   }
   void DeleteRule(uint32_t aIndex, mozilla::ErrorResult& aRv) {
     aRv = DeleteRule(aIndex);
new file mode 100644
--- /dev/null
+++ b/layout/style/nsICSSRuleList.cpp
@@ -0,0 +1,30 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* 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 obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsICSSRuleList.h"
+
+#include "mozilla/dom/CSSRuleListBinding.h"
+
+using namespace mozilla;
+
+
+NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(nsICSSRuleList)
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsICSSRuleList)
+  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
+  NS_INTERFACE_MAP_ENTRY(nsICSSRuleList)
+  NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRuleList)
+  NS_INTERFACE_MAP_ENTRY(nsISupports)
+NS_INTERFACE_MAP_END
+
+NS_IMPL_CYCLE_COLLECTING_ADDREF(nsICSSRuleList)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(nsICSSRuleList)
+
+/* virtual */ JSObject*
+nsICSSRuleList::WrapObject(JSContext* aCx)
+{
+  return dom::CSSRuleListBinding::Wrap(aCx, this);
+}
--- a/layout/style/nsICSSRuleList.h
+++ b/layout/style/nsICSSRuleList.h
@@ -3,27 +3,43 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef nsICSSRuleList_h
 #define nsICSSRuleList_h
 
 #include "nsIDOMCSSRule.h"
 #include "nsIDOMCSSRuleList.h"
+#include "nsWrapperCache.h"
+
+class nsCSSStyleSheet;
 
 // IID for the nsICSSRuleList interface
 #define NS_ICSSRULELIST_IID \
-{ 0xccc0135a, 0xbcb6, 0x4654, \
-  { 0x8c, 0x78, 0x74, 0x35, 0x97, 0x9b, 0x88, 0x19 } }
+{ 0x56ac8d1c, 0xc1ed, 0x45fe, \
+  { 0x9a, 0x4d, 0x3a, 0xdc, 0xf9, 0xd1, 0xb9, 0x3f } }
 
 class nsICSSRuleList : public nsIDOMCSSRuleList
+                     , public nsWrapperCache
 {
 public:
+  nsICSSRuleList()
+  {
+    SetIsDOMBinding();
+  }
+  virtual ~nsICSSRuleList() {}
+
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_ICSSRULELIST_IID)
 
+  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsICSSRuleList)
+
+  virtual nsCSSStyleSheet* GetParentObject() = 0;
+  virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE MOZ_FINAL;
+
   NS_IMETHOD
   GetLength(uint32_t* aLength) MOZ_OVERRIDE MOZ_FINAL
   {
     *aLength = Length();
     return NS_OK;
   }
   NS_IMETHOD
   Item(uint32_t aIndex, nsIDOMCSSRule** aReturn) MOZ_OVERRIDE MOZ_FINAL