tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit 4a691496e764f7d9935454a3126745dad99be714
parent 202ae50fb8ff23ab8e855e2971df577cb7d62975
Author: Nicolas Chevobbe <nchevobbe@mozilla.com>
Date:   Tue, 16 Dec 2025 07:05:30 +0000

Bug 2006255 - [devtools] Add chrome-only CSSStyleDeclaration#hasLonghandProperty(propertyName). r=emilio,webidl,firefox-style-system-reviewers,layout-reviewers.

Differential Revision: https://phabricator.services.mozilla.com/D274933

Diffstat:
Mdom/webidl/CSSStyleDeclaration.webidl | 2++
Mlayout/inspector/InspectorUtils.cpp | 3+++
Mlayout/inspector/tests/chrome/chrome.toml | 2++
Alayout/inspector/tests/chrome/test_CSSStyleDeclaration_hasLonghandProperty.html | 145+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mlayout/style/nsDOMCSSDeclaration.cpp | 9+++++++++
Mlayout/style/nsDOMCSSDeclaration.h | 1+
Mlayout/style/nsICSSDeclaration.h | 5+++++
Mservo/components/style/properties/properties.mako.rs | 2+-
Mservo/ports/geckolib/glue.rs | 17+++++++++++++++++
9 files changed, 185 insertions(+), 1 deletion(-)

diff --git a/dom/webidl/CSSStyleDeclaration.webidl b/dom/webidl/CSSStyleDeclaration.webidl @@ -30,6 +30,8 @@ interface CSSStyleDeclaration { undefined setProperty(UTF8String property, [LegacyNullToEmptyString] UTF8String value, optional [LegacyNullToEmptyString] UTF8String priority = ""); [CEReactions, Throws] UTF8String removeProperty(UTF8String property); + [ChromeOnly] + boolean hasLonghandProperty(UTF8String property); readonly attribute CSSRule? parentRule; }; diff --git a/layout/inspector/InspectorUtils.cpp b/layout/inspector/InspectorUtils.cpp @@ -289,6 +289,9 @@ class ReadOnlyInspectorDeclaration final : public nsDOMCSSDeclaration { void GetPropertyValue(NonCustomCSSPropertyId aId, nsACString& aValue) final { Servo_DeclarationBlock_GetPropertyValueByNonCustomId(mRaw, aId, &aValue); } + bool HasLonghandProperty(const nsACString& aPropName) final { + return Servo_DeclarationBlock_HasLonghandProperty(mRaw, &aPropName); + } void IndexedGetter(uint32_t aIndex, bool& aFound, nsACString& aPropName) final { aFound = Servo_DeclarationBlock_GetNthProperty(mRaw, aIndex, &aPropName); diff --git a/layout/inspector/tests/chrome/chrome.toml b/layout/inspector/tests/chrome/chrome.toml @@ -4,6 +4,8 @@ prefs = [ ] support-files = ["GentiumPlus-R.woff"] +["test_CSSStyleDeclaration_hasLonghandProperty.html"] + ["test_CSSStyleRule_getScopeRootFor.html"] ["test_CSSStyleRule_querySelectorAll.html"] diff --git a/layout/inspector/tests/chrome/test_CSSStyleDeclaration_hasLonghandProperty.html b/layout/inspector/tests/chrome/test_CSSStyleDeclaration_hasLonghandProperty.html @@ -0,0 +1,145 @@ +<!DOCTYPE html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1894251 +--> +<title>Test for CSSStyleDeclaration::hasLonghandProperty</title> +<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> +<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/> + +<div + id="target" + align="right" + style=" + --in-style-attribute:red; + --in-style-attribute-empty: ; + color: blue; + outline: 1px solid lime; + caret-color: var(--in-style-attribute);" +></div> + +<style> + #target { + --in-rule: hotpink; + --in-rule-empty: ; + background-color: peachpuff; + text-decoration-color: var(--in-rule); + padding: 1em; + } + + @property --my-color { + syntax: "<color>"; + inherits: false; + initial-value: #c0ffee; + } +</style> + +<script> +add_task(async () => { + const InspectorUtils = SpecialPowers.InspectorUtils; + const el = document.querySelector("#target"); + // Use InspectorUtils.getMatchingCSSRules so we get InspectorDeclaration instances, like + // we do in DevTools. + const rules = InspectorUtils.getMatchingCSSRules(el); + + info("Check that hasProperty returns expected values for regular rule CSSStyleProperties") + const targetRule = rules.find(r => r.selectorText === "#target"); + ok( + targetRule.style.hasLonghandProperty("background-color"), + `hasProperty returned true for "background-color" property on #target rule` + ); + ok( + targetRule.style.hasLonghandProperty("text-decoration-color"), + `hasProperty returned true for property with a CSS variable value on #target rule` + ); + ok( + !targetRule.style.hasLonghandProperty("caret-color"), + `hasProperty returned false for non-defined "caret-color" property on #target rule` + ); + ok( + !targetRule.style.hasLonghandProperty("my-amazing-property"), + `hasProperty returned false for invalid property on #target rule` + ); + ok( + targetRule.style.hasLonghandProperty("--in-rule"), + `hasProperty returned true for "--in-rule" property on #target rule` + ); + ok( + targetRule.style.hasLonghandProperty("--in-rule-empty"), + `hasProperty returned true for "--in-rule-empty" property on #target rule` + ); + ok( + !targetRule.style.hasLonghandProperty("--my-color"), + `hasProperty returned false for registered but unset "--my-color" property on #target rule` + ); + ok( + !targetRule.style.hasLonghandProperty("--unknown"), + `hasProperty returned false for "--unknown" property on #target rule` + ); + ok( + !targetRule.style.hasLonghandProperty("padding"), + `hasProperty returned false for shorthand property (padding) on #target rule` + ); + ok( + targetRule.style.hasLonghandProperty("padding-top"), + `hasProperty returned true for longhand property (padding-top) on #target rule` + ); + + info("Check that hasProperty returns expected values for style attribute InspectorDeclaration CSSStyleProperties") + const styleAttributeInspectorDeclaration = rules.find(r => r.declarationOrigin === "style-attribute"); + ok( + styleAttributeInspectorDeclaration.style.hasLonghandProperty("color"), + `hasProperty returned true for "color" property on style attribute` + ); + ok( + styleAttributeInspectorDeclaration.style.hasLonghandProperty("caret-color"), + `hasProperty returned true for property with a CSS variable value on style attribute` + ); + ok( + !styleAttributeInspectorDeclaration.style.hasLonghandProperty("background-color"), + `hasProperty returned false for non-defined "background-color" property on style attribute` + ); + ok( + styleAttributeInspectorDeclaration.style.hasLonghandProperty("--in-style-attribute"), + `hasProperty returned true for "--in-style-attribute" property on style attribute` + ); + ok( + styleAttributeInspectorDeclaration.style.hasLonghandProperty("--in-style-attribute-empty"), + `hasProperty returned true for "--in-style-attribute-empty" property on style attribute` + ); + ok( + !styleAttributeInspectorDeclaration.style.hasLonghandProperty("--my-color"), + `hasProperty returned false for registered but unset "--my-color" property on style attribute` + ); + ok( + !styleAttributeInspectorDeclaration.style.hasLonghandProperty("--unknown"), + `hasProperty returned false for "--unknown" property on style attribute` + ); + ok( + !styleAttributeInspectorDeclaration.style.hasLonghandProperty("outline"), + `hasProperty returned false for shorthand property (outline) on style attribute` + ); + ok( + styleAttributeInspectorDeclaration.style.hasLonghandProperty("outline-color"), + `hasProperty returned true for longhand property (outline-color) on style attribute` + ); + + info("Check that hasProperty returns expected values for pres hints InspectorDeclaration CSSStyleProperties") + const presHintsInspectorDeclaration = rules.find(r => r.declarationOrigin === "pres-hints"); + ok( + presHintsInspectorDeclaration.style.hasLonghandProperty("text-align"), + `hasProperty returned true for "text-align" property on pres-hints style` + ); + ok( + !presHintsInspectorDeclaration.style.hasLonghandProperty("background-color"), + `hasProperty returned false for non-defined "background-color" property on pres-hints style` + ); + ok( + !presHintsInspectorDeclaration.style.hasLonghandProperty("--my-color"), + `hasProperty returned false for registered but unset "--my-color" property on pres-hints style` + ); + ok( + !presHintsInspectorDeclaration.style.hasLonghandProperty("--unknown"), + `hasProperty returned false for "--unknown" property on pres-hints style` + ); +}); +</script> diff --git a/layout/style/nsDOMCSSDeclaration.cpp b/layout/style/nsDOMCSSDeclaration.cpp @@ -140,6 +140,15 @@ void nsDOMCSSDeclaration::GetPropertyValue(const nsACString& aPropertyName, } } +bool nsDOMCSSDeclaration::HasLonghandProperty(const nsACString& aPropertyName) { + if (auto* decl = GetOrCreateCSSDeclaration(Operation::Read, nullptr)) { + return Servo_DeclarationBlock_HasLonghandProperty(decl->Raw(), + &aPropertyName); + } + + return false; +} + void nsDOMCSSDeclaration::GetPropertyPriority(const nsACString& aPropertyName, nsACString& aPriority) { MOZ_ASSERT(aPriority.IsEmpty()); diff --git a/layout/style/nsDOMCSSDeclaration.h b/layout/style/nsDOMCSSDeclaration.h @@ -87,6 +87,7 @@ class nsDOMCSSDeclaration : public nsICSSDeclaration { mozilla::ErrorResult& aRv) override; void GetPropertyValue(const nsACString& propertyName, nsACString& _retval) override; + bool HasLonghandProperty(const nsACString& propertyName) override; void RemoveProperty(const nsACString& propertyName, nsACString& _retval, mozilla::ErrorResult& aRv) override; void GetPropertyPriority(const nsACString& propertyName, diff --git a/layout/style/nsICSSDeclaration.h b/layout/style/nsICSSDeclaration.h @@ -101,6 +101,11 @@ class nsICSSDeclaration : public nsISupports, public nsWrapperCache { nsACString& aPriority) = 0; virtual mozilla::css::Rule* GetParentRule() = 0; + // [Chrome only] + virtual bool HasLonghandProperty(const nsACString& aPropName) { + return false; + }; + protected: bool IsReadOnly(); }; diff --git a/servo/components/style/properties/properties.mako.rs b/servo/components/style/properties/properties.mako.rs @@ -1258,7 +1258,7 @@ impl CountedUnknownProperty { impl PropertyId { /// Returns a given property from the given name, _regardless of whether it /// is enabled or not_, or Err(()) for unknown properties. - pub(super) fn parse_unchecked( + pub fn parse_unchecked( property_name: &str, use_counters: Option<&UseCounters>, ) -> Result<Self, ()> { diff --git a/servo/ports/geckolib/glue.rs b/servo/ports/geckolib/glue.rs @@ -5881,6 +5881,23 @@ pub extern "C" fn Servo_DeclarationBlock_PropertyIsSet( } #[no_mangle] +pub unsafe extern "C" fn Servo_DeclarationBlock_HasLonghandProperty( + declarations: &LockedDeclarationBlock, + property: &nsACString, +) -> bool { + read_locked_arc(declarations, |decls: &PropertyDeclarationBlock| { + let prop_name = property.as_str_unchecked(); + if let Ok(property_id) = PropertyId::parse_unchecked(prop_name, None) { + if let Err(longhand_or_custom) = property_id.as_shorthand() { + return decls.contains(longhand_or_custom); + } + } + + false + }) +} + +#[no_mangle] pub unsafe extern "C" fn Servo_DeclarationBlock_SetIdentStringValue( declarations: &LockedDeclarationBlock, property: NonCustomCSSPropertyId,