Bug 995664 - Move CSSRuleList to WebIDL; r=bz
authorMs2ger <ms2ger@gmail.com>
Sat, 03 May 2014 09:32:54 +0200
changeset 181839 cc42442f4728c36dcda8a2d833ac7f438d7ec6fa
parent 181838 8a21f9e10a754d6592867a66a473cbaf65ef1d65
child 181840 e50544d1d32d9d86f1db8a2c3338d5502773a402
push id272
push userpvanderbeken@mozilla.com
push dateMon, 05 May 2014 16:31:18 +0000
reviewersbz
bugs995664
milestone32.0a1
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