diff --git a/layout/style/StyleRule.cpp b/layout/style/StyleRule.cpp index 13641915b59c..eb79dd8c216a 100644 --- a/layout/style/StyleRule.cpp +++ b/layout/style/StyleRule.cpp @@ -20,6 +20,7 @@ #include "nsIAtom.h" #include "nsString.h" #include "nsStyleUtil.h" +#include "nsICSSStyleRuleDOMWrapper.h" #include "nsDOMCSSDeclaration.h" #include "nsNameSpaceManager.h" #include "nsXMLNameSpaceMap.h" @@ -1046,26 +1047,30 @@ nsCSSSelectorList::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) cons // -------------------------------------------------------- +namespace mozilla { +namespace css { +class DOMCSSStyleRule; +} // namespace css +} // namespace mozilla + class DOMCSSDeclarationImpl : public nsDOMCSSDeclaration { protected: - // Needs to be protected so we can use NS_IMPL_ADDREF_USING_AGGREGATOR. virtual ~DOMCSSDeclarationImpl(void); - // But we need to allow UniquePtr to delete us. - friend class mozilla::DefaultDelete; - public: explicit DOMCSSDeclarationImpl(css::StyleRule *aRule); NS_IMETHOD GetParentRule(nsIDOMCSSRule **aParent) override; + void DropReference(void); virtual DeclarationBlock* GetCSSDeclaration(Operation aOperation) override; virtual nsresult SetCSSDeclaration(DeclarationBlock* aDecl) override; virtual void GetCSSParsingEnvironment(CSSParsingEnvironment& aCSSParseEnv) override; virtual nsIDocument* DocToUpdate() override; - // Override |AddRef| and |Release| for being owned by StyleRule. Also, we - // need to forward QI for cycle collection things to StyleRule. + // Override |AddRef| and |Release| for being a member of + // |DOMCSSStyleRule|. Also, we need to forward QI for cycle + // collection things to DOMCSSStyleRule. NS_DECL_ISUPPORTS_INHERITED virtual nsINode *GetParentObject() override @@ -1073,12 +1078,55 @@ public: return mRule ? mRule->GetDocument() : nullptr; } + friend class css::DOMCSSStyleRule; + protected: - // This reference is not reference-counted. The rule object owns us and we go - // away when it does. + // This reference is not reference-counted. The rule object tells us + // when it's about to go away. css::StyleRule *mRule; + + inline css::DOMCSSStyleRule* DomRule(); + +private: + // NOT TO BE IMPLEMENTED + // This object cannot be allocated on its own. It must be a member of + // DOMCSSStyleRule. + void* operator new(size_t size) CPP_THROW_NEW; }; +namespace mozilla { +namespace css { + +class DOMCSSStyleRule : public nsICSSStyleRuleDOMWrapper +{ +public: + explicit DOMCSSStyleRule(StyleRule *aRule); + + NS_DECL_CYCLE_COLLECTING_ISUPPORTS + NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(DOMCSSStyleRule) + NS_DECL_NSIDOMCSSRULE + NS_DECL_NSIDOMCSSSTYLERULE + + // nsICSSStyleRuleDOMWrapper + NS_IMETHOD GetCSSStyleRule(StyleRule **aResult) override; + + DOMCSSDeclarationImpl* DOMDeclaration() { return &mDOMDeclaration; } + + friend class ::DOMCSSDeclarationImpl; + +protected: + virtual ~DOMCSSStyleRule(); + + DOMCSSDeclarationImpl mDOMDeclaration; + + StyleRule* Rule() { + return mDOMDeclaration.mRule; + } +}; + +} // namespace css +} // namespace mozilla + DOMCSSDeclarationImpl::DOMCSSDeclarationImpl(css::StyleRule *aRule) : mRule(aRule) { @@ -1086,32 +1134,50 @@ DOMCSSDeclarationImpl::DOMCSSDeclarationImpl(css::StyleRule *aRule) DOMCSSDeclarationImpl::~DOMCSSDeclarationImpl(void) { + NS_ASSERTION(!mRule, "DropReference not called."); } -NS_IMPL_ADDREF_USING_AGGREGATOR(DOMCSSDeclarationImpl, mRule) -NS_IMPL_RELEASE_USING_AGGREGATOR(DOMCSSDeclarationImpl, mRule) +inline css::DOMCSSStyleRule* DOMCSSDeclarationImpl::DomRule() +{ + return reinterpret_cast + (reinterpret_cast(this) - + offsetof(css::DOMCSSStyleRule, mDOMDeclaration)); +} + +NS_IMPL_ADDREF_USING_AGGREGATOR(DOMCSSDeclarationImpl, DomRule()) +NS_IMPL_RELEASE_USING_AGGREGATOR(DOMCSSDeclarationImpl, DomRule()) NS_INTERFACE_MAP_BEGIN(DOMCSSDeclarationImpl) NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY - // We forward the cycle collection interfaces to mRule, which is - // never null. + // We forward the cycle collection interfaces to DomRule(), which is + // never null (in fact, we're part of that object!) if (aIID.Equals(NS_GET_IID(nsCycleCollectionISupports)) || aIID.Equals(NS_GET_IID(nsXPCOMCycleCollectionParticipant))) { - return mRule->QueryInterface(aIID, aInstancePtr); + return DomRule()->QueryInterface(aIID, aInstancePtr); } else NS_IMPL_QUERY_TAIL_INHERITING(nsDOMCSSDeclaration) +void +DOMCSSDeclarationImpl::DropReference(void) +{ + mRule = nullptr; +} + DeclarationBlock* DOMCSSDeclarationImpl::GetCSSDeclaration(Operation aOperation) { - if (aOperation != eOperation_Read) { - RefPtr sheet = mRule->GetStyleSheet(); - if (sheet) { - sheet->WillDirty(); + if (mRule) { + if (aOperation != eOperation_Read) { + RefPtr sheet = mRule->GetStyleSheet(); + if (sheet) { + sheet->WillDirty(); + } } + return mRule->GetDeclaration(); + } else { + return nullptr; } - return mRule->GetDeclaration(); } void @@ -1125,6 +1191,11 @@ DOMCSSDeclarationImpl::GetParentRule(nsIDOMCSSRule **aParent) { NS_ENSURE_ARG_POINTER(aParent); + if (!mRule) { + *aParent = nullptr; + return NS_OK; + } + NS_IF_ADDREF(*aParent = mRule->GetDOMRule()); return NS_OK; } @@ -1161,13 +1232,50 @@ DOMCSSDeclarationImpl::DocToUpdate() return nullptr; } -// -- StyleRule ------------------------------------ - namespace mozilla { namespace css { +DOMCSSStyleRule::DOMCSSStyleRule(StyleRule* aRule) + : mDOMDeclaration(aRule) +{ +} + +DOMCSSStyleRule::~DOMCSSStyleRule() +{ +} + +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DOMCSSStyleRule) + NS_INTERFACE_MAP_ENTRY(nsICSSStyleRuleDOMWrapper) + NS_INTERFACE_MAP_ENTRY(nsIDOMCSSStyleRule) + NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRule) + NS_INTERFACE_MAP_ENTRY(nsISupports) + NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CSSStyleRule) +NS_INTERFACE_MAP_END + +NS_IMPL_CYCLE_COLLECTING_ADDREF(DOMCSSStyleRule) +NS_IMPL_CYCLE_COLLECTING_RELEASE(DOMCSSStyleRule) + +NS_IMPL_CYCLE_COLLECTION_CLASS(DOMCSSStyleRule) + +NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(DOMCSSStyleRule) + // Trace the wrapper for our declaration. This just expands out + // NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER which we can't use + // directly because the wrapper is on the declaration, not on us. + tmp->DOMDeclaration()->TraceWrapper(aCallbacks, aClosure); +NS_IMPL_CYCLE_COLLECTION_TRACE_END + +NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DOMCSSStyleRule) + // Unlink the wrapper for our declaraton. This just expands out + // NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER which we can't use + // directly because the wrapper is on the declaration, not on us. + tmp->DOMDeclaration()->ReleaseWrapper(static_cast(p)); +NS_IMPL_CYCLE_COLLECTION_UNLINK_END + +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(DOMCSSStyleRule) +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END + NS_IMETHODIMP -StyleRule::GetType(uint16_t* aType) +DOMCSSStyleRule::GetType(uint16_t* aType) { *aType = nsIDOMCSSRule::STYLE_RULE; @@ -1175,42 +1283,95 @@ StyleRule::GetType(uint16_t* aType) } NS_IMETHODIMP -StyleRule::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet) +DOMCSSStyleRule::GetCssText(nsAString& aCssText) { - return Rule::GetParentStyleSheet(aSheet); + if (!Rule()) { + aCssText.Truncate(); + } else { + Rule()->GetCssText(aCssText); + } + return NS_OK; } NS_IMETHODIMP -StyleRule::GetParentRule(nsIDOMCSSRule** aParentRule) +DOMCSSStyleRule::SetCssText(const nsAString& aCssText) { - return Rule::GetParentRule(aParentRule); + if (Rule()) { + Rule()->SetCssText(aCssText); + } + return NS_OK; +} + +NS_IMETHODIMP +DOMCSSStyleRule::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet) +{ + if (!Rule()) { + *aSheet = nullptr; + return NS_OK; + } + return Rule()->GetParentStyleSheet(aSheet); +} + +NS_IMETHODIMP +DOMCSSStyleRule::GetParentRule(nsIDOMCSSRule** aParentRule) +{ + if (!Rule()) { + *aParentRule = nullptr; + return NS_OK; + } + return Rule()->GetParentRule(aParentRule); } css::Rule* -StyleRule::GetCSSRule() +DOMCSSStyleRule::GetCSSRule() { - return this; + return Rule(); } NS_IMETHODIMP -StyleRule::GetStyle(nsIDOMCSSStyleDeclaration** aStyle) +DOMCSSStyleRule::GetSelectorText(nsAString& aSelectorText) { - if (!mDOMDeclaration) { - mDOMDeclaration.reset(new DOMCSSDeclarationImpl(this)); + if (!Rule()) { + aSelectorText.Truncate(); + } else { + Rule()->GetSelectorText(aSelectorText); } - *aStyle = mDOMDeclaration.get(); + return NS_OK; +} + +NS_IMETHODIMP +DOMCSSStyleRule::SetSelectorText(const nsAString& aSelectorText) +{ + if (Rule()) { + Rule()->SetSelectorText(aSelectorText); + } + return NS_OK; +} + +NS_IMETHODIMP +DOMCSSStyleRule::GetStyle(nsIDOMCSSStyleDeclaration** aStyle) +{ + *aStyle = &mDOMDeclaration; NS_ADDREF(*aStyle); return NS_OK; } NS_IMETHODIMP -StyleRule::GetCSSStyleRule(StyleRule **aResult) +DOMCSSStyleRule::GetCSSStyleRule(StyleRule **aResult) { - *aResult = this; - NS_ADDREF(*aResult); + *aResult = Rule(); + NS_IF_ADDREF(*aResult); return NS_OK; } +} // namespace css +} // namespace mozilla + +// -- StyleRule ------------------------------------ + +namespace mozilla { +namespace css { + StyleRule::StyleRule(nsCSSSelectorList* aSelector, Declaration* aDeclaration, uint32_t aLineNumber, @@ -1245,6 +1406,11 @@ StyleRule::~StyleRule() void StyleRule::DropReferences() { + if (mDOMRule) { + mDOMRule->DOMDeclaration()->DropReference(); + mDOMRule = nullptr; + } + if (mDeclaration) { mDeclaration->SetOwningRule(nullptr); } @@ -1258,36 +1424,18 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(StyleRule) return NS_OK; } else - NS_INTERFACE_MAP_ENTRY(nsICSSStyleRuleDOMWrapper) - NS_INTERFACE_MAP_ENTRY(nsIDOMCSSStyleRule) - NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRule) - 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) - // Keep this in sync with IsCCLeaf. - // Trace the wrapper for our declaration. This just expands out - // NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER which we can't use - // directly because the wrapper is on the declaration, not on us. - if (tmp->mDOMDeclaration) { - tmp->mDOMDeclaration->TraceWrapper(aCallbacks, aClosure); - } -NS_IMPL_CYCLE_COLLECTION_TRACE_END NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(StyleRule, Rule) - // Unlink the wrapper for our declaraton. This just expands out - // NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER which we can't use - // directly because the wrapper is on the declaration, not on us. - if (tmp->mDOMDeclaration) { - tmp->mDOMDeclaration->ReleaseWrapper(static_cast(p)); - } tmp->DropReferences(); NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(StyleRule, Rule) // Keep this in sync with IsCCLeaf. + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDOMRule) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END bool @@ -1297,7 +1445,7 @@ StyleRule::IsCCLeaf() const return false; } - return !mDOMDeclaration || !mDOMDeclaration->PreservingWrapper(); + return !mDOMRule || !mDOMRule->DOMDeclaration()->PreservingWrapper(); } /* virtual */ int32_t @@ -1316,7 +1464,16 @@ StyleRule::Clone() const /* virtual */ nsIDOMCSSRule* StyleRule::GetDOMRule() { - return this; + if (!mDOMRule) { + if (!GetStyleSheet()) { + // Inline style rules aren't supposed to have a DOM rule object, only + // a declaration. But if we do have one already, from a style sheet + // rule that used to be in a document, we still want to return it. + return nullptr; + } + mDOMRule = new DOMCSSStyleRule(this); + } + return mDOMRule; } void @@ -1373,7 +1530,7 @@ StyleRule::List(FILE* out, int32_t aIndent) const } #endif -NS_IMETHODIMP +void StyleRule::GetCssText(nsAString& aCssText) { if (mSelector) { @@ -1390,33 +1547,29 @@ StyleRule::GetCssText(nsAString& aCssText) } aCssText.Append(char16_t(' ')); aCssText.Append(char16_t('}')); - return NS_OK; } -NS_IMETHODIMP +void StyleRule::SetCssText(const nsAString& aCssText) { // XXX TBI - need to re-parse rule & declaration - return NS_OK; } -NS_IMETHODIMP +void StyleRule::GetSelectorText(nsAString& aSelectorText) { if (mSelector) mSelector->ToString(aSelectorText, GetStyleSheet()); else aSelectorText.Truncate(); - return NS_OK; } -NS_IMETHODIMP +void StyleRule::SetSelectorText(const nsAString& aSelectorText) { // XXX TBI - get a parser and re-parse the selectors, // XXX then need to re-compute the cascade // XXX and dirty sheet - return NS_OK; } /* virtual */ size_t diff --git a/layout/style/StyleRule.h b/layout/style/StyleRule.h index 703f6108da67..7445f4d4812a 100644 --- a/layout/style/StyleRule.h +++ b/layout/style/StyleRule.h @@ -13,14 +13,12 @@ #include "mozilla/Attributes.h" #include "mozilla/MemoryReporting.h" -#include "mozilla/UniquePtr.h" #include "mozilla/css/Rule.h" #include "nsString.h" #include "nsCOMPtr.h" #include "nsCSSPseudoElements.h" #include "nsIStyleRule.h" -#include "nsICSSStyleRuleDOMWrapper.h" class nsIAtom; struct nsCSSSelectorList; @@ -304,15 +302,13 @@ private: { 0x464bab7a, 0x2fce, 0x4f30, \ { 0xab, 0x44, 0xb7, 0xa5, 0xf3, 0xaa, 0xe5, 0x7d } } -class DOMCSSDeclarationImpl; - namespace mozilla { namespace css { class Declaration; +class DOMCSSStyleRule; class StyleRule final : public Rule - , public nsICSSStyleRuleDOMWrapper { public: StyleRule(nsCSSSelectorList* aSelector, @@ -325,15 +321,9 @@ public: NS_DECLARE_STATIC_IID_ACCESSOR(NS_CSS_STYLE_RULE_IMPL_CID) NS_DECL_ISUPPORTS_INHERITED - NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(StyleRule, Rule) + NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(StyleRule, Rule) virtual bool IsCCLeaf() const override; - NS_DECL_NSIDOMCSSRULE - NS_DECL_NSIDOMCSSSTYLERULE - - // nsICSSStyleRuleDOMWrapper - NS_IMETHOD GetCSSStyleRule(StyleRule **aResult) override; - // null for style attribute nsCSSSelectorList* Selector() { return mSelector; } @@ -341,6 +331,12 @@ public: void SetDeclaration(Declaration* aDecl); + // hooks for DOM rule + void GetCssText(nsAString& aCssText); + void SetCssText(const nsAString& aCssText); + void GetSelectorText(nsAString& aSelectorText); + void SetSelectorText(const nsAString& aSelectorText); + virtual int32_t GetType() const override; CSSStyleSheet* GetStyleSheet() const @@ -372,9 +368,7 @@ private: private: nsCSSSelectorList* mSelector; // null for style attribute RefPtr mDeclaration; - - // We own it, and it aggregates its refcount with us. - UniquePtr mDOMDeclaration; + RefPtr mDOMRule; private: StyleRule& operator=(const StyleRule& aCopy) = delete;