Bug 851892 part 12. Convert CSSStyleRule to WebIDL. r=peterv,heycam,mccr8
authorBoris Zbarsky <bzbarsky@mit.edu>
Fri, 13 Jan 2017 10:41:03 -0500
changeset 374338 4e48a59adc5ebc39d93d928ab35d10bbb9e65795
parent 374337 2a5a9437777ffd046070cdaef8874be6d3e87c95
child 374339 d50c9372cc2ed012118859b07105bde4bddb8561
push id6996
push userjlorenzo@mozilla.com
push dateMon, 06 Mar 2017 20:48:21 +0000
treeherdermozilla-beta@d89512dab048 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspeterv, heycam, mccr8
bugs851892
milestone53.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 851892 part 12. Convert CSSStyleRule to WebIDL. r=peterv,heycam,mccr8 The .style PutForwards bit is coming along for the ride; I did check that Chrome already implements this, so we're not the only ones.
dom/base/nsDOMClassInfo.cpp
dom/base/nsDOMClassInfoID.h
dom/base/nsWrapperCache.h
dom/bindings/Bindings.conf
dom/webidl/CSSStyleRule.webidl
dom/webidl/LegacyQueryInterface.webidl
dom/webidl/moz.build
js/xpconnect/tests/mochitest/file_crosscompartment_weakmap.html
js/xpconnect/tests/mochitest/test_crosscompartment_weakmap.html
layout/style/BindingStyleRule.cpp
layout/style/BindingStyleRule.h
layout/style/ServoStyleRule.cpp
layout/style/ServoStyleRule.h
layout/style/StyleRule.cpp
layout/style/StyleRule.h
layout/style/moz.build
layout/style/nsICSSStyleRuleDOMWrapper.h
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -77,17 +77,16 @@
 #include "nsIDOMCSSKeyframeRule.h"
 #include "nsIDOMCSSKeyframesRule.h"
 #include "nsIDOMCSSMediaRule.h"
 #include "nsIDOMCSSFontFaceRule.h"
 #include "nsIDOMCSSMozDocumentRule.h"
 #include "nsIDOMCSSSupportsRule.h"
 #include "nsIDOMCSSCounterStyleRule.h"
 #include "nsIDOMCSSPageRule.h"
-#include "nsIDOMCSSStyleRule.h"
 #include "nsIDOMXULCommandDispatcher.h"
 #include "nsIControllers.h"
 #ifdef MOZ_XUL
 #include "nsITreeSelection.h"
 #include "nsITreeContentView.h"
 #include "nsITreeView.h"
 #include "nsIXULTemplateBuilder.h"
 #endif
@@ -184,19 +183,16 @@ static nsDOMClassInfoData sClassInfoData
                            nsIXPCScriptable::WANT_HASINSTANCE |
                            nsIXPCScriptable::WANT_CALL |
                            nsIXPCScriptable::WANT_CONSTRUCT |
                            nsIXPCScriptable::DONT_ENUM_QUERY_INTERFACE)
 
   // Misc Core related classes
 
   // CSS classes
-  NS_DEFINE_CLASSINFO_DATA(CSSStyleRule, nsCSSRuleSH,
-                           DOM_DEFAULT_SCRIPTABLE_FLAGS |
-                           nsIXPCScriptable::WANT_PRECREATE)
   NS_DEFINE_CLASSINFO_DATA(CSSMediaRule, nsCSSRuleSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS |
                            nsIXPCScriptable::WANT_PRECREATE)
 
   // XUL classes
 #ifdef MOZ_XUL
   NS_DEFINE_CHROME_XBL_CLASSINFO_DATA(XULCommandDispatcher, nsDOMGenericSH,
                                       DOM_DEFAULT_SCRIPTABLE_FLAGS)
@@ -512,21 +508,16 @@ nsDOMClassInfo::Init()
   DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(DOMPrototype, nsIDOMDOMConstructor)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMDOMConstructor)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(DOMConstructor, nsIDOMDOMConstructor)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMDOMConstructor)
   DOM_CLASSINFO_MAP_END
 
-  DOM_CLASSINFO_MAP_BEGIN(CSSStyleRule, nsIDOMCSSStyleRule)
-    DOM_CLASSINFO_MAP_ENTRY(nsIDOMCSSRule)
-    DOM_CLASSINFO_MAP_ENTRY(nsIDOMCSSStyleRule)
-  DOM_CLASSINFO_MAP_END
-
   DOM_CLASSINFO_MAP_BEGIN(CSSMediaRule, nsIDOMCSSMediaRule)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMCSSRule)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMCSSMediaRule)
   DOM_CLASSINFO_MAP_END
 
 #ifdef MOZ_XUL
   DOM_CLASSINFO_MAP_BEGIN(XULCommandDispatcher, nsIDOMXULCommandDispatcher)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMXULCommandDispatcher)
@@ -1997,24 +1988,17 @@ nsCSSRuleSH::PreCreate(nsISupports *nati
                        JSObject *aGlobalObj, JSObject **parentObj)
 {
   JS::Rooted<JSObject*> globalObj(cx, aGlobalObj);
   nsCOMPtr<nsIDOMCSSRule> rule = do_QueryInterface(nativeObj);
   if (!rule) {
     return NS_ERROR_UNEXPECTED;
   }
   css::Rule* cssRule = rule->GetCSSRule();
-  if (!cssRule) {
-    // A DOMCSSStyleRule whose actual underlying rule has gone away.  There
-    // isn't much a caller can do with this thing anyway, and only chrome code
-    // can get its hands on it to start with, so just wrap in the current
-    // global.
-    *parentObj = globalObj;
-    return NS_OK;
-  }
+  MOZ_ASSERT(cssRule);
   nsIDocument* doc = cssRule->GetDocument();
   if (!doc) {
     *parentObj = globalObj;
     return NS_OK;
   }
 
   nsIGlobalObject* global = doc->GetScopeObject();
   if (!global) {
--- a/dom/base/nsDOMClassInfoID.h
+++ b/dom/base/nsDOMClassInfoID.h
@@ -15,17 +15,16 @@
 #include "nsIXPCScriptable.h"
 
 enum nsDOMClassInfoID
 {
   eDOMClassInfo_DOMPrototype_id,
   eDOMClassInfo_DOMConstructor_id,
 
   // CSS classes
-  eDOMClassInfo_CSSStyleRule_id,
   eDOMClassInfo_CSSMediaRule_id,
 
   // XUL classes
 #ifdef MOZ_XUL
   eDOMClassInfo_XULCommandDispatcher_id,
 #endif
   eDOMClassInfo_XULControllers_id,
 #ifdef MOZ_XUL
--- a/dom/base/nsWrapperCache.h
+++ b/dom/base/nsWrapperCache.h
@@ -15,21 +15,19 @@
 #include "js/TracingAPI.h"
 
 namespace mozilla {
 namespace dom {
 class TabChildGlobal;
 class ProcessGlobal;
 } // namespace dom
 namespace css {
-class StyleRule;
 class MediaRule;
 class DocumentRule;
 } // namespace css
-class ServoStyleRule;
 class CSSSupportsRule;
 } // namespace mozilla
 class SandboxPrivate;
 class nsInProcessTabChildGlobal;
 class nsWindowRoot;
 class nsCSSFontFaceRule;
 class nsCSSFontFeatureValuesRule;
 class nsCSSKeyframeRule;
@@ -288,20 +286,18 @@ private:
   // Friend declarations for things that need to be able to call
   // SetIsNotDOMBinding().  The goal is to get rid of all of these, and
   // SetIsNotDOMBinding() too.
   friend class mozilla::dom::TabChildGlobal;
   friend class mozilla::dom::ProcessGlobal;
   friend class SandboxPrivate;
   friend class nsInProcessTabChildGlobal;
   friend class nsWindowRoot;
-  friend class mozilla::css::StyleRule;
   friend class mozilla::css::MediaRule;
   friend class mozilla::css::DocumentRule;
-  friend class mozilla::ServoStyleRule;
   friend class mozilla::CSSSupportsRule;
   friend class nsCSSFontFaceRule;
   friend class nsCSSFontFeatureValuesRule;
   friend class nsCSSKeyframeRule;
   friend class nsCSSKeyframesRule;
   friend class nsCSSPageRule;
   friend class nsCSSCounterStyleRule;
   void SetIsNotDOMBinding()
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -217,16 +217,20 @@ DOMInterfaces = {
     'concrete': False,
     'nativeType': 'mozilla::css::Rule'
 },
 
 'CSSStyleDeclaration': {
     'nativeType': 'nsICSSDeclaration'
 },
 
+'CSSStyleRule': {
+    'nativeType': 'mozilla::BindingStyleRule',
+},
+
 'CSSStyleSheet': {
     'nativeType': 'mozilla::StyleSheet',
     'binaryNames': { 'ownerRule': 'DOMOwnerRule' },
 },
 
 'CSSValue': {
     'concrete': False
 },
new file mode 100644
--- /dev/null
+++ b/dom/webidl/CSSStyleRule.webidl
@@ -0,0 +1,14 @@
+/* -*- 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/.
+ *
+ * The origin of this IDL file is
+ * https://drafts.csswg.org/cssom/#the-cssstylerule-interface
+ */
+
+// https://drafts.csswg.org/cssom/#the-cssstylerule-interface
+interface CSSStyleRule : CSSRule {
+  attribute DOMString selectorText;
+  [SameObject, PutForwards=cssText] readonly attribute CSSStyleDeclaration style;
+};
--- a/dom/webidl/LegacyQueryInterface.webidl
+++ b/dom/webidl/LegacyQueryInterface.webidl
@@ -21,16 +21,17 @@ interface LegacyQueryInterface {
 Attr implements LegacyQueryInterface;
 BarProp implements LegacyQueryInterface;
 BoxObject implements LegacyQueryInterface;
 CaretPosition implements LegacyQueryInterface;
 Comment implements LegacyQueryInterface;
 Crypto implements LegacyQueryInterface;
 CSSPrimitiveValue implements LegacyQueryInterface;
 CSSStyleDeclaration implements LegacyQueryInterface;
+CSSStyleRule implements LegacyQueryInterface;
 CSSValueList implements LegacyQueryInterface;
 DOMImplementation implements LegacyQueryInterface;
 DOMParser implements LegacyQueryInterface;
 DOMStringMap implements LegacyQueryInterface;
 DOMTokenList implements LegacyQueryInterface;
 Document implements LegacyQueryInterface;
 DocumentFragment implements LegacyQueryInterface;
 DocumentType implements LegacyQueryInterface;
--- a/dom/webidl/moz.build
+++ b/dom/webidl/moz.build
@@ -92,16 +92,17 @@ WEBIDL_FILES = [
     'CSSImportRule.webidl',
     'CSSLexer.webidl',
     'CSSNamespaceRule.webidl',
     'CSSPrimitiveValue.webidl',
     'CSSPseudoElement.webidl',
     'CSSRule.webidl',
     'CSSRuleList.webidl',
     'CSSStyleDeclaration.webidl',
+    'CSSStyleRule.webidl',
     'CSSStyleSheet.webidl',
     'CSSTransition.webidl',
     'CSSValue.webidl',
     'CSSValueList.webidl',
     'CustomElementRegistry.webidl',
     'DataContainerEvent.webidl',
     'DataTransfer.webidl',
     'DataTransferItem.webidl',
--- a/js/xpconnect/tests/mochitest/file_crosscompartment_weakmap.html
+++ b/js/xpconnect/tests/mochitest/file_crosscompartment_weakmap.html
@@ -1,9 +1,8 @@
 <!DOCTYPE HTML>
 <html>
 <head>
-  <link rel="stylesheet" href="data:text/css,div {}">
   <title>Test Cross-Compartment DOM WeakMaps</title>
 </head>
 <body>
 </body>
 </html>
--- a/js/xpconnect/tests/mochitest/test_crosscompartment_weakmap.html
+++ b/js/xpconnect/tests/mochitest/test_crosscompartment_weakmap.html
@@ -10,24 +10,16 @@
 <script type="application/javascript">
 
 var my_map = new WeakMap();
 
 function setup() {
   var item = window.frames[0].document.querySelector("body");
 
   my_map.set(item, "success_string");
-
-  var rule_fail = false;
-  try {
-    my_map.set(window.frames[0].document.styleSheets[0].cssRules[0], 1);
-  } catch (e) {
-    rule_fail = true;
-  }
-  ok(rule_fail, "Using rule as a weak map key across compartments should produce an exception because it can't be wrapper preserved.");
 }
 
 function runTest() {
   setup();
   SpecialPowers.forceGC();
   SpecialPowers.forceCC();
   SpecialPowers.forceGC();
   SpecialPowers.forceCC();
new file mode 100644
--- /dev/null
+++ b/layout/style/BindingStyleRule.cpp
@@ -0,0 +1,18 @@
+/* -*- Mode: C++; 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/. */
+
+#include "mozilla/BindingStyleRule.h"
+#include "mozilla/dom/CSSStyleRuleBinding.h"
+
+namespace mozilla {
+
+/* virtual */ JSObject*
+BindingStyleRule::WrapObject(JSContext* aCx,
+			     JS::Handle<JSObject*> aGivenProto)
+{
+  return dom::CSSStyleRuleBinding::Wrap(aCx, this, aGivenProto);
+}
+
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/layout/style/BindingStyleRule.h
@@ -0,0 +1,51 @@
+/* -*- Mode: C++; 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/. */
+
+#ifndef mozilla_BindingStyleRule_h__
+#define mozilla_BindingStyleRule_h__
+
+#include "nscore.h"
+#include "nsStringGlue.h"
+#include "mozilla/css/Rule.h"
+
+/**
+ * Shared superclass for mozilla::css::StyleRule and mozilla::ServoStyleRule,
+ * for use from bindings code.
+ */
+
+class nsICSSDeclaration;
+
+namespace mozilla {
+
+class BindingStyleRule : public css::Rule
+{
+protected:
+  BindingStyleRule(uint32_t aLineNumber, uint32_t aColumnNumber)
+    : css::Rule(aLineNumber, aColumnNumber)
+  {
+  }
+  BindingStyleRule(const BindingStyleRule& aCopy)
+    : css::Rule(aCopy)
+  {
+  }
+  virtual ~BindingStyleRule() {}
+
+public:
+  // WebIDL API
+  // For GetSelectorText/SetSelectorText, we purposefully use a signature that
+  // matches the nsIDOMCSSStyleRule one for now, so subclasses can just
+  // implement both at once.  The actual implementations must never return
+  // anything other than NS_OK;
+  NS_IMETHOD GetSelectorText(nsAString& aSelectorText) = 0;
+  NS_IMETHOD SetSelectorText(const nsAString& aSelectorText) = 0;
+  virtual nsICSSDeclaration* Style() = 0;
+
+  virtual JSObject* WrapObject(JSContext* aCx,
+                               JS::Handle<JSObject*> aGivenProto) override;
+};
+
+} // namespace mozilla
+
+#endif // mozilla_BindingStyleRule_h__
--- a/layout/style/ServoStyleRule.cpp
+++ b/layout/style/ServoStyleRule.cpp
@@ -6,18 +6,18 @@
 
 /* representation of CSSStyleRule for stylo */
 
 #include "mozilla/ServoStyleRule.h"
 
 #include "mozilla/DeclarationBlockInlines.h"
 #include "mozilla/ServoBindings.h"
 #include "mozilla/ServoDeclarationBlock.h"
+#include "mozilla/dom/CSSStyleRuleBinding.h"
 
-#include "nsDOMClassInfoID.h"
 #include "mozAutoDocUpdate.h"
 
 namespace mozilla {
 
 // -- ServoStyleRuleDeclaration ---------------------------------------
 
 ServoStyleRuleDeclaration::ServoStyleRuleDeclaration(
   already_AddRefed<RawServoDeclarationBlock> aDecls)
@@ -95,27 +95,25 @@ ServoStyleRuleDeclaration::GetCSSParsing
   CSSParsingEnvironment& aCSSParseEnv)
 {
   GetCSSParsingEnvironmentForRule(Rule(), aCSSParseEnv);
 }
 
 // -- ServoStyleRule --------------------------------------------------
 
 ServoStyleRule::ServoStyleRule(already_AddRefed<RawServoStyleRule> aRawRule)
-  : css::Rule(0, 0)
+  : BindingStyleRule(0, 0)
   , mRawRule(aRawRule)
   , mDecls(Servo_StyleRule_GetStyle(mRawRule).Consume())
 {
-  SetIsNotDOMBinding();
 }
 
 // QueryInterface implementation for ServoStyleRule
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(ServoStyleRule)
   NS_INTERFACE_MAP_ENTRY(nsIDOMCSSStyleRule)
-  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CSSStyleRule)
 NS_INTERFACE_MAP_END_INHERITING(css::Rule)
 
 NS_IMPL_ADDREF_INHERITED(ServoStyleRule, css::Rule)
 NS_IMPL_RELEASE_INHERITED(ServoStyleRule, css::Rule)
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(ServoStyleRule)
 
 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(ServoStyleRule, css::Rule)
@@ -147,24 +145,16 @@ ServoStyleRule::Clone() const
 
 size_t
 ServoStyleRule::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
 {
   // TODO Implement this!
   return aMallocSizeOf(this);
 }
 
-/* virtual */ JSObject*
-ServoStyleRule::WrapObject(JSContext* aCx,
-                           JS::Handle<JSObject*> aGivenProto)
-{
-  NS_NOTREACHED("We called SetIsNotDOMBinding() in our constructor");
-  return nullptr;
-}
-
 #ifdef DEBUG
 void
 ServoStyleRule::List(FILE* out, int32_t aIndent) const
 {
   nsAutoCString str;
   for (int32_t i = 0; i < aIndent; i++) {
     str.AppendLiteral("  ");
   }
@@ -182,16 +172,22 @@ ServoStyleRule::Type() const
 }
 
 void
 ServoStyleRule::GetCssTextImpl(nsAString& aCssText) const
 {
   Servo_StyleRule_GetCssText(mRawRule, &aCssText);
 }
 
+nsICSSDeclaration*
+ServoStyleRule::Style()
+{
+  return &mDecls;
+}
+
 /* CSSStyleRule implementation */
 
 NS_IMETHODIMP
 ServoStyleRule::GetSelectorText(nsAString& aSelectorText)
 {
   Servo_StyleRule_GetSelectorText(mRawRule, &aSelectorText);
   return NS_OK;
 }
--- a/layout/style/ServoStyleRule.h
+++ b/layout/style/ServoStyleRule.h
@@ -4,17 +4,17 @@
  * 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/. */
 
 /* representation of CSSStyleRule for stylo */
 
 #ifndef mozilla_ServoStyleRule_h
 #define mozilla_ServoStyleRule_h
 
-#include "mozilla/css/Rule.h"
+#include "mozilla/BindingStyleRule.h"
 #include "mozilla/ServoBindingTypes.h"
 
 #include "nsIDOMCSSStyleRule.h"
 #include "nsDOMCSSDeclaration.h"
 
 namespace mozilla {
 
 class ServoDeclarationBlock;
@@ -42,40 +42,39 @@ private:
     already_AddRefed<RawServoDeclarationBlock> aDecls);
   ~ServoStyleRuleDeclaration();
 
   inline ServoStyleRule* Rule();
 
   RefPtr<ServoDeclarationBlock> mDecls;
 };
 
-class ServoStyleRule final : public css::Rule
+class ServoStyleRule final : public BindingStyleRule
                            , public nsIDOMCSSStyleRule
 {
 public:
   explicit ServoStyleRule(already_AddRefed<RawServoStyleRule> aRawRule);
 
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(ServoStyleRule,
                                                          css::Rule)
   NS_DECL_NSIDOMCSSSTYLERULE
 
   // WebIDL interface
   uint16_t Type() const override;
   void GetCssTextImpl(nsAString& aCssText) const override;
+  virtual nsICSSDeclaration* Style() override;
 
   RawServoStyleRule* Raw() const { return mRawRule; }
 
   // Methods of mozilla::css::Rule
   int32_t GetType() const final { return css::Rule::STYLE_RULE; }
   using Rule::GetType;
   already_AddRefed<Rule> Clone() const final;
   size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const final;
-  virtual JSObject* WrapObject(JSContext* aCx,
-                               JS::Handle<JSObject*> aGivenProto) override;
 #ifdef DEBUG
   void List(FILE* out = stdout, int32_t aIndent = 0) const final;
 #endif
 
 private:
   ~ServoStyleRule() {}
 
   // For computing the offset of mDecls.
--- a/layout/style/StyleRule.cpp
+++ b/layout/style/StyleRule.cpp
@@ -11,27 +11,27 @@
 
 #include "mozilla/css/StyleRule.h"
 
 #include "mozilla/DeclarationBlockInlines.h"
 #include "mozilla/StyleSheetInlines.h"
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/css/GroupRule.h"
 #include "mozilla/css/Declaration.h"
+#include "mozilla/dom/CSSStyleRuleBinding.h"
 #include "nsIDocument.h"
 #include "nsIAtom.h"
 #include "nsString.h"
 #include "nsStyleUtil.h"
 #include "nsDOMCSSDeclaration.h"
 #include "nsNameSpaceManager.h"
 #include "nsXMLNameSpaceMap.h"
 #include "nsCSSPseudoClasses.h"
 #include "nsCSSAnonBoxes.h"
 #include "nsTArray.h"
-#include "nsDOMClassInfoID.h"
 #include "nsContentUtils.h"
 #include "nsError.h"
 #include "mozAutoDocUpdate.h"
 
 class nsIDOMCSSStyleDeclaration;
 class nsIDOMCSSStyleSheet;
 
 using namespace mozilla;
@@ -1170,53 +1170,56 @@ uint16_t
 StyleRule::Type() const
 {
   return nsIDOMCSSRule::STYLE_RULE;
 }
 
 NS_IMETHODIMP
 StyleRule::GetStyle(nsIDOMCSSStyleDeclaration** aStyle)
 {
+  NS_ADDREF(*aStyle = Style());
+  return NS_OK;
+}
+
+nsICSSDeclaration*
+StyleRule::Style()
+{
   if (!mDOMDeclaration) {
     mDOMDeclaration.reset(new DOMCSSDeclarationImpl(this));
   }
-  *aStyle = mDOMDeclaration.get();
-  NS_ADDREF(*aStyle);
-  return NS_OK;
+  return mDOMDeclaration.get();
 }
 
 NS_IMETHODIMP
 StyleRule::GetCSSStyleRule(StyleRule **aResult)
 {
   *aResult = this;
   NS_ADDREF(*aResult);
   return NS_OK;
 }
 
 StyleRule::StyleRule(nsCSSSelectorList* aSelector,
                      Declaration* aDeclaration,
                      uint32_t aLineNumber,
                      uint32_t aColumnNumber)
-  : Rule(aLineNumber, aColumnNumber),
+  : BindingStyleRule(aLineNumber, aColumnNumber),
     mSelector(aSelector),
     mDeclaration(aDeclaration)
 {
-  SetIsNotDOMBinding();
   NS_PRECONDITION(aDeclaration, "must have a declaration");
 
   mDeclaration->SetOwningRule(this);
 }
 
 // for |Clone|
 StyleRule::StyleRule(const StyleRule& aCopy)
-  : Rule(aCopy),
+  : BindingStyleRule(aCopy),
     mSelector(aCopy.mSelector ? aCopy.mSelector->Clone() : nullptr),
     mDeclaration(new Declaration(*aCopy.mDeclaration))
 {
-  SetIsNotDOMBinding();
   mDeclaration->SetOwningRule(this);
   // rest is constructed lazily on existing data
 }
 
 StyleRule::~StyleRule()
 {
   delete mSelector;
   DropReferences();
@@ -1236,17 +1239,16 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_
   if (aIID.Equals(NS_GET_IID(mozilla::css::StyleRule))) {
     *aInstancePtr = this;
     NS_ADDREF_THIS();
     return NS_OK;
   }
   else
   NS_INTERFACE_MAP_ENTRY(nsICSSStyleRuleDOMWrapper)
   NS_INTERFACE_MAP_ENTRY(nsIDOMCSSStyleRule)
-  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CSSStyleRule)
 NS_INTERFACE_MAP_END_INHERITING(Rule)
 
 NS_IMPL_ADDREF_INHERITED(StyleRule, Rule)
 NS_IMPL_RELEASE_INHERITED(StyleRule, Rule)
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(StyleRule)
 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(StyleRule, Rule)
   // Trace the wrapper for our declaration.  This just expands out
@@ -1383,19 +1385,10 @@ StyleRule::SizeOfIncludingThis(mozilla::
 
   // Measurement of the following members may be added later if DMD finds it is
   // worthwhile:
   // - mDOMRule;
 
   return n;
 }
 
-/* virtual */ JSObject*
-StyleRule::WrapObject(JSContext* aCx,
-                      JS::Handle<JSObject*> aGivenProto)
-{
-  NS_NOTREACHED("We called SetIsNotDOMBinding() in our constructor");
-  return nullptr;
-}
-
-
 } // namespace css
 } // namespace mozilla
--- a/layout/style/StyleRule.h
+++ b/layout/style/StyleRule.h
@@ -9,17 +9,17 @@
  */
 
 #ifndef mozilla_css_StyleRule_h__
 #define mozilla_css_StyleRule_h__
 
 #include "mozilla/Attributes.h"
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/UniquePtr.h"
-#include "mozilla/css/Rule.h"
+#include "mozilla/BindingStyleRule.h"
 
 #include "nsString.h"
 #include "nsCOMPtr.h"
 #include "nsCSSPseudoElements.h"
 #include "nsIStyleRule.h"
 #include "nsICSSStyleRuleDOMWrapper.h"
 
 class nsIAtom;
@@ -306,17 +306,17 @@ private:
 
 class DOMCSSDeclarationImpl;
 
 namespace mozilla {
 namespace css {
 
 class Declaration;
 
-class StyleRule final : public Rule
+class StyleRule final : public BindingStyleRule
                       , public nsICSSStyleRuleDOMWrapper
 {
  public:
   StyleRule(nsCSSSelectorList* aSelector,
             Declaration *aDeclaration,
             uint32_t aLineNumber, uint32_t aColumnNumber);
 private:
   // for |Clone|
@@ -329,16 +329,17 @@ public:
   NS_DECL_NSIDOMCSSSTYLERULE
 
   // nsICSSStyleRuleDOMWrapper
   NS_IMETHOD GetCSSStyleRule(StyleRule **aResult) override;
 
   // WebIDL interface
   uint16_t Type() const override;
   void GetCssTextImpl(nsAString& aCssText) const override;
+  virtual nsICSSDeclaration* Style() override;
 
   // null for style attribute
   nsCSSSelectorList* Selector() { return mSelector; }
 
   Declaration* GetDeclaration() const { return mDeclaration; }
 
   void SetDeclaration(Declaration* aDecl);
 
@@ -354,19 +355,16 @@ public:
   virtual already_AddRefed<Rule> Clone() const override;
 
 #ifdef DEBUG
   virtual void List(FILE* out = stdout, int32_t aIndent = 0) const override;
 #endif
 
   virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const override;
 
-  virtual JSObject* WrapObject(JSContext* aCx,
-                               JS::Handle<JSObject*> aGivenProto) override;
-
 private:
   ~StyleRule();
 
   // Drop our references to mDeclaration and mRule, and let them know we're
   // doing that.
   void DropReferences();
 
 private:
--- a/layout/style/moz.build
+++ b/layout/style/moz.build
@@ -76,16 +76,17 @@ EXPORTS += [
     'nsStyleStructFwd.h',
     'nsStyleStructInlines.h',
     'nsStyleTransformMatrix.h',
     'nsStyleUtil.h',
 ]
 
 EXPORTS.mozilla += [
     'AnimationCollection.h',
+    'BindingStyleRule.h',
     'CSSEnabledState.h',
     'CSSStyleSheet.h',
     'CSSVariableDeclarations.h',
     'CSSVariableResolver.h',
     'CSSVariableValues.h',
     'DeclarationBlock.h',
     'DeclarationBlockInlines.h',
     'DocumentStyleRootIterator.h',
@@ -141,16 +142,17 @@ EXPORTS.mozilla.css += [
     'Rule.h',
     'SheetParsingMode.h',
     'StyleRule.h',
 ]
 
 UNIFIED_SOURCES += [
     'AnimationCollection.cpp',
     'AnimationCommon.cpp',
+    'BindingStyleRule.cpp',
     'CounterStyleManager.cpp',
     'CSS.cpp',
     'CSSLexer.cpp',
     'CSSRuleList.cpp',
     'CSSStyleSheet.cpp',
     'CSSVariableDeclarations.cpp',
     'CSSVariableResolver.cpp',
     'CSSVariableValues.cpp',
--- a/layout/style/nsICSSStyleRuleDOMWrapper.h
+++ b/layout/style/nsICSSStyleRuleDOMWrapper.h
@@ -13,16 +13,21 @@
 
 #include "nsIDOMCSSStyleRule.h"
 
 // IID for the nsICSSStyleRuleDOMWrapper interface
 // {cee1bbb6-0a32-4cf3-8d42-ba3938e9ecaa}
 #define NS_ICSS_STYLE_RULE_DOM_WRAPPER_IID \
 {0xcee1bbb6, 0x0a32, 0x4cf3, {0x8d, 0x42, 0xba, 0x39, 0x38, 0xe9, 0xec, 0xaa}}
 
+namespace mozilla {
+namespace css {
+class StyleRule;
+} // namespace css
+} // namespace mozilla
 
 class nsICSSStyleRuleDOMWrapper : public nsIDOMCSSStyleRule {
 public:
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_ICSS_STYLE_RULE_DOM_WRAPPER_IID)
 
   NS_IMETHOD GetCSSStyleRule(mozilla::css::StyleRule** aResult) = 0;
 };