commit 4db5196484ee9a3977446d1552a973c69d090240 parent 42f606b1668787424c77283bf1512739dbcf1ab9 Author: sickl8 <sickl8@protonmail.com> Date: Wed, 17 Dec 2025 20:52:51 +0000 Bug 2004140 - Implement initial StylePropertyMap support for CSSStyleRule. r=emilio,firefox-style-system-reviewers,janv Differential Revision: https://phabricator.services.mozilla.com/D275366 Diffstat:
13 files changed, 105 insertions(+), 75 deletions(-)
diff --git a/layout/style/CSSStyleRule.cpp b/layout/style/CSSStyleRule.cpp @@ -203,6 +203,10 @@ const StyleLockedDeclarationBlock* CSSStyleRule::RawStyle() const { return mDecls.mDecls->Raw(); } +DeclarationBlock& CSSStyleRule::GetDeclarationBlock() const { + return *mDecls.mDecls; +} + void CSSStyleRule::GetSelectorText(nsACString& aSelectorText) { Servo_StyleRule_GetSelectorText(mRawRule, &aSelectorText); } @@ -405,7 +409,7 @@ already_AddRefed<nsINodeList> CSSStyleRule::QuerySelectorAll(nsINode& aRoot) { StylePropertyMap* CSSStyleRule::StyleMap() { if (!mStyleMap) { - mStyleMap = MakeRefPtr<StylePropertyMap>(this, /* aComputed */ false); + mStyleMap = MakeRefPtr<StylePropertyMap>(this); } return mStyleMap; diff --git a/layout/style/CSSStyleRule.h b/layout/style/CSSStyleRule.h @@ -73,7 +73,7 @@ class CSSStyleRule final : public css::GroupRule { bool aRelevantLinkVisited); Element* GetScopeRootFor(uint32_t aSelectorIndex, dom::Element&, const nsAString& aPseudo, bool aRelevantLinkVisited); - NotNull<DeclarationBlock*> GetDeclarationBlock() const; + DeclarationBlock& GetDeclarationBlock() const; void GetSelectorWarnings(nsTArray<SelectorWarning>& aResult) const; already_AddRefed<nsINodeList> QuerySelectorAll(nsINode& aRoot); diff --git a/layout/style/typedom/StylePropertyMap.cpp b/layout/style/typedom/StylePropertyMap.cpp @@ -24,12 +24,14 @@ namespace mozilla::dom { -StylePropertyMap::StylePropertyMap(nsCOMPtr<nsISupports> aParent, - bool aComputed) - : StylePropertyMapReadOnly(std::move(aParent), aComputed) { +StylePropertyMap::StylePropertyMap(Element* aElement, bool aComputed) + : StylePropertyMapReadOnly(aElement, aComputed) { MOZ_DIAGNOSTIC_ASSERT(!aComputed); } +StylePropertyMap::StylePropertyMap(CSSStyleRule* aRule) + : StylePropertyMapReadOnly(aRule) {} + JSObject* StylePropertyMap::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) { return StylePropertyMap_Binding::Wrap(aCx, this, aGivenProto); @@ -70,7 +72,7 @@ void StylePropertyMap::Set( // Step 4 - const auto valuePropertyId = styleValue.GetPropertyId(); + const auto* valuePropertyId = styleValue.GetPropertyId(); if (valuePropertyId && *valuePropertyId != propertyId) { aRv.ThrowTypeError("Invalid type for property"_ns); diff --git a/layout/style/typedom/StylePropertyMap.h b/layout/style/typedom/StylePropertyMap.h @@ -28,7 +28,8 @@ class Sequence; class StylePropertyMap final : public StylePropertyMapReadOnly { public: - StylePropertyMap(nsCOMPtr<nsISupports> aParent, bool aComputed); + StylePropertyMap(Element* aElement, bool aComputed); + explicit StylePropertyMap(CSSStyleRule* aRule); JSObject* WrapObject(JSContext*, JS::Handle<JSObject*> aGivenProto) override; diff --git a/layout/style/typedom/StylePropertyMapReadOnly.cpp b/layout/style/typedom/StylePropertyMapReadOnly.cpp @@ -16,6 +16,7 @@ #include "mozilla/dom/CSSKeywordValue.h" #include "mozilla/dom/CSSMathSum.h" #include "mozilla/dom/CSSNumericArray.h" +#include "mozilla/dom/CSSStyleRule.h" #include "mozilla/dom/CSSStyleValue.h" #include "mozilla/dom/CSSUnitValue.h" #include "mozilla/dom/Element.h" @@ -23,7 +24,6 @@ #include "nsCSSProps.h" #include "nsComputedDOMStyle.h" #include "nsCycleCollectionParticipant.h" -#include "nsQueryObject.h" #include "nsReadableUtils.h" namespace mozilla::dom { @@ -84,13 +84,36 @@ struct DeclarationTraits<ComputedStyleDeclarations> { } }; -// XXX StyleRuleDeclarations go here +// Specialization for style rule +struct StyleRuleDeclarations {}; +template <> +struct DeclarationTraits<StyleRuleDeclarations> { + static StylePropertyTypedValueResult Get(const CSSStyleRule* aRule, + const nsACString& aProperty, + ErrorResult& aRv) { + MOZ_ASSERT(aRule); + + auto result = StylePropertyTypedValueResult::None(); + + if (!aRule->GetDeclarationBlock().GetPropertyTypedValue(aProperty, + result)) { + return result; + } + + return result; + } +}; } // namespace -StylePropertyMapReadOnly::StylePropertyMapReadOnly( - nsCOMPtr<nsISupports> aParent, bool aComputed) - : mParent(std::move(aParent)), mDeclarations(aComputed) { +StylePropertyMapReadOnly::StylePropertyMapReadOnly(Element* aElement, + bool aComputed) + : mParent(aElement), mDeclarations(aElement, aComputed) { + MOZ_ASSERT(mParent); +} + +StylePropertyMapReadOnly::StylePropertyMapReadOnly(CSSStyleRule* aRule) + : mParent(aRule), mDeclarations(aRule) { MOZ_ASSERT(mParent); } @@ -101,7 +124,17 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(StylePropertyMapReadOnly) NS_INTERFACE_MAP_ENTRY(nsISupports) NS_INTERFACE_MAP_END -NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(StylePropertyMapReadOnly, mParent) +NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(StylePropertyMapReadOnly) +NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(StylePropertyMapReadOnly) + // Clear out our weak pointers. + tmp->mDeclarations.Unlink(); + + NS_IMPL_CYCLE_COLLECTION_UNLINK(mParent) + NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER +NS_IMPL_CYCLE_COLLECTION_UNLINK_END +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(StylePropertyMapReadOnly) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParent) +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END nsISupports* StylePropertyMapReadOnly::GetParentObject() const { return mParent; @@ -120,13 +153,10 @@ JSObject* StylePropertyMapReadOnly::WrapObject( void StylePropertyMapReadOnly::Get(const nsACString& aProperty, OwningUndefinedOrCSSStyleValue& aRetVal, ErrorResult& aRv) const { - // XXX This QO wouldn't be needed if we had RefPtr<Element> mElement - RefPtr<Element> element = do_QueryObject(mParent); - if (!element) { - aRv.Throw(NS_ERROR_NOT_IMPLEMENTED); + if (!mParent) { + aRv.Throw(NS_ERROR_UNEXPECTED); return; } - // Step 2. NonCustomCSSPropertyId id = nsCSSProps::LookupProperty(aProperty); @@ -141,7 +171,7 @@ void StylePropertyMapReadOnly::Get(const nsACString& aProperty, // Step 4. - auto result = declarations.Get(element, aProperty, aRv); + auto result = declarations.Get(aProperty, aRv); if (aRv.Failed()) { return; } @@ -276,14 +306,34 @@ size_t StylePropertyMapReadOnly::SizeOfIncludingThis( } StylePropertyTypedValueResult StylePropertyMapReadOnly::Declarations::Get( - Element* aElement, const nsACString& aProperty, ErrorResult& aRv) const { - if (mComputed) { - return DeclarationTraits<ComputedStyleDeclarations>::Get(aElement, + const nsACString& aProperty, ErrorResult& aRv) const { + switch (mKind) { + case Kind::Inline: + return DeclarationTraits<InlineStyleDeclarations>::Get(mElement, aProperty, aRv); + + case Kind::Computed: + return DeclarationTraits<ComputedStyleDeclarations>::Get(mElement, + aProperty, aRv); + + case Kind::Rule: + return DeclarationTraits<StyleRuleDeclarations>::Get(mRule, aProperty, + aRv); } + MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE("Bad kind value!"); +} + +void StylePropertyMapReadOnly::Declarations::Unlink() { + switch (mKind) { + case Kind::Inline: + case Kind::Computed: + mElement = nullptr; + break; - return DeclarationTraits<InlineStyleDeclarations>::Get(aElement, aProperty, - aRv); + case Kind::Rule: + mRule = nullptr; + break; + } } } // namespace mozilla::dom diff --git a/layout/style/typedom/StylePropertyMapReadOnly.h b/layout/style/typedom/StylePropertyMapReadOnly.h @@ -29,12 +29,14 @@ struct StylePropertyTypedValueResult; namespace dom { +class CSSStyleRule; class Element; class OwningUndefinedOrCSSStyleValue; class StylePropertyMapReadOnly : public nsISupports, public nsWrapperCache { public: - StylePropertyMapReadOnly(nsCOMPtr<nsISupports> aParent, bool aComputed); + StylePropertyMapReadOnly(Element* aElement, bool aComputed); + explicit StylePropertyMapReadOnly(CSSStyleRule* aRule); NS_DECL_CYCLE_COLLECTING_ISUPPORTS NS_DECL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(StylePropertyMapReadOnly) @@ -74,21 +76,33 @@ class StylePropertyMapReadOnly : public nsISupports, public nsWrapperCache { class Declarations { public: - explicit Declarations(bool aComputed) : mComputed(aComputed) {} - - // XXX This will have to be changed a bit when support for CSSStyleRule - // is added (There won't be Element in that case) - StylePropertyTypedValueResult Get(Element* aElement, - const nsACString& aProperty, + enum class Kind : uint8_t { + Inline, + Computed, + Rule, + }; + Declarations(Element* aElement, bool aComputed) + : mElement(aElement), + mKind(aComputed ? Kind::Computed : Kind::Inline) {} + + explicit Declarations(CSSStyleRule* aRule) + : mRule(aRule), mKind(Kind::Rule) {} + + StylePropertyTypedValueResult Get(const nsACString& aProperty, ErrorResult& aRv) const; + void Unlink(); + private: - const bool mComputed; + union { + Element* mElement; + CSSStyleRule* mRule; + }; + const Kind mKind; }; - // XXX Make this RefPtr<Element> nsCOMPtr<nsISupports> mParent; - const Declarations mDeclarations; + Declarations mDeclarations; }; } // namespace dom diff --git a/testing/web-platform/meta/css/css-typed-om/the-stylepropertymap/declared/declared.tentative.html.ini b/testing/web-platform/meta/css/css-typed-om/the-stylepropertymap/declared/declared.tentative.html.ini @@ -5,18 +5,11 @@ [Declared StylePropertyMap contains properties with their last valid value] expected: FAIL - [Declared StylePropertyMap does not contain properties with invalid values] - expected: FAIL - [Declared StylePropertyMap only contains properties in the style rule] expected: FAIL [Declared StylePropertyMap is live] expected: FAIL - [Declared StylePropertyMap does not contain inline styles] - expected: FAIL - [Declared StylePropertyMap contains CSS property declarations in style rules] expected: FAIL - diff --git a/testing/web-platform/meta/css/css-typed-om/the-stylepropertymap/declared/get-invalid.html.ini b/testing/web-platform/meta/css/css-typed-om/the-stylepropertymap/declared/get-invalid.html.ini @@ -1,3 +0,0 @@ -[get-invalid.html] - [Calling StylePropertyMap.get with an unsupported property throws a TypeError] - expected: FAIL diff --git a/testing/web-platform/meta/css/css-typed-om/the-stylepropertymap/declared/get-shorthand.html.ini b/testing/web-platform/meta/css/css-typed-om/the-stylepropertymap/declared/get-shorthand.html.ini @@ -1,6 +0,0 @@ -[get-shorthand.html] - [Getting a shorthand property set explicitly in css rule returns a base CSSStyleValue] - expected: FAIL - - [Getting a shorthand property that is partially set in css rule returns undefined] - expected: FAIL diff --git a/testing/web-platform/meta/css/css-typed-om/the-stylepropertymap/declared/get.html.ini b/testing/web-platform/meta/css/css-typed-om/the-stylepropertymap/declared/get.html.ini @@ -13,9 +13,3 @@ [Declared StylePropertyMap.get reflects changes in the CSS rule] expected: FAIL - - [Getting a custom property not in the CSS rule returns undefined] - expected: FAIL - - [Getting a valid property not in the CSS rule returns undefined] - expected: FAIL diff --git a/testing/web-platform/meta/css/css-typed-om/the-stylepropertymap/declared/getAll-shorthand.html.ini b/testing/web-platform/meta/css/css-typed-om/the-stylepropertymap/declared/getAll-shorthand.html.ini @@ -1,7 +0,0 @@ -[getAll-shorthand.html] - [StylePropertyMap.getAll() with a shorthand property set explicitly in css rule returns a base CSSStyleValue] - expected: FAIL - - [StylePropertyMap.getAll() with a shorthand property that is partially in css rule returns empty list] - expected: FAIL - diff --git a/testing/web-platform/meta/css/css-typed-om/the-stylepropertymap/declared/getAll.tentative.html.ini b/testing/web-platform/meta/css/css-typed-om/the-stylepropertymap/declared/getAll.tentative.html.ini @@ -1,10 +1,4 @@ [getAll.tentative.html] - [Calling StylePropertyMap.getAll with a property not in the property model returns an empty list] - expected: FAIL - - [Calling StylePropertyMap.getAll with a custom property not in the property model returns an empty list] - expected: FAIL - [Calling StylePropertyMap.getAll with a valid property returns a single element list with the correct entry] expected: FAIL @@ -16,6 +10,3 @@ [Calling StylePropertyMap.getAll with a list-valued property returns all the values] expected: FAIL - - [Calling StylePropertyMap.getAll with an unsupported property throws a TypeError] - expected: FAIL diff --git a/testing/web-platform/meta/css/css-typed-om/the-stylepropertymap/declared/set.tentative.html.ini b/testing/web-platform/meta/css/css-typed-om/the-stylepropertymap/declared/set.tentative.html.ini @@ -31,6 +31,3 @@ [StylePropertyMap.set is case-insensitive] expected: FAIL - - [Setting a property with a CSSStyleValue whose associated property does not match throws TypeError] - expected: FAIL