Bug 1294299 part 11 - Implement getting and removing property. r=SimonSapin,heycam
MozReview-Commit-ID: 4xvfXR8mkfN
--- a/layout/style/DeclarationBlock.h
+++ b/layout/style/DeclarationBlock.h
@@ -10,16 +10,18 @@
*/
#ifndef mozilla_DeclarationBlock_h
#define mozilla_DeclarationBlock_h
#include "mozilla/ServoUtils.h"
#include "mozilla/StyleBackendType.h"
+#include "nsCSSPropertyID.h"
+
class nsHTMLCSSStyleSheet;
namespace mozilla {
class ServoDeclarationBlock;
namespace css {
class Declaration;
@@ -99,16 +101,26 @@ public:
return c.mHTMLCSSStyleSheet;
}
inline void ToString(nsAString& aString) const;
inline uint32_t Count() const;
inline bool GetNthProperty(uint32_t aIndex, nsAString& aReturn) const;
+ inline void GetPropertyValue(const nsAString& aProperty,
+ nsAString& aValue) const;
+ inline void GetPropertyValueByID(nsCSSPropertyID aPropID,
+ nsAString& aValue) const;
+ inline void GetAuthoredPropertyValue(const nsAString& aProperty,
+ nsAString& aValue) const;
+ inline bool GetPropertyIsImportant(const nsAString& aProperty) const;
+ inline void RemoveProperty(const nsAString& aProperty);
+ inline void RemovePropertyByID(nsCSSPropertyID aProperty);
+
private:
union {
// We only ever have one of these since we have an
// nsHTMLCSSStyleSheet only for style attributes, and style
// attributes never have an owning rule.
// It's an nsHTMLCSSStyleSheet if the low bit is set.
--- a/layout/style/DeclarationBlockInlines.h
+++ b/layout/style/DeclarationBlockInlines.h
@@ -65,11 +65,50 @@ DeclarationBlock::Count() const
}
bool
DeclarationBlock::GetNthProperty(uint32_t aIndex, nsAString& aReturn) const
{
MOZ_STYLO_FORWARD(GetNthProperty, (aIndex, aReturn))
}
+void
+DeclarationBlock::GetPropertyValue(const nsAString& aProperty,
+ nsAString& aValue) const
+{
+ MOZ_STYLO_FORWARD(GetPropertyValue, (aProperty, aValue))
+}
+
+void
+DeclarationBlock::GetPropertyValueByID(nsCSSPropertyID aPropID,
+ nsAString& aValue) const
+{
+ MOZ_STYLO_FORWARD(GetPropertyValueByID, (aPropID, aValue))
+}
+
+void
+DeclarationBlock::GetAuthoredPropertyValue(const nsAString& aProperty,
+ nsAString& aValue) const
+{
+ MOZ_STYLO_FORWARD(GetAuthoredPropertyValue, (aProperty, aValue))
+}
+
+bool
+DeclarationBlock::GetPropertyIsImportant(const nsAString& aProperty) const
+{
+ MOZ_STYLO_FORWARD(GetPropertyIsImportant, (aProperty))
+}
+
+void
+DeclarationBlock::RemoveProperty(const nsAString& aProperty)
+{
+ MOZ_STYLO_FORWARD(RemoveProperty, (aProperty))
+}
+
+void
+DeclarationBlock::RemovePropertyByID(nsCSSPropertyID aProperty)
+{
+ MOZ_STYLO_FORWARD(RemovePropertyByID, (aProperty))
+}
+
} // namespace mozilla
#endif // mozilla_DeclarationBlockInlines_h
--- a/layout/style/ServoBindingList.h
+++ b/layout/style/ServoBindingList.h
@@ -79,16 +79,25 @@ SERVO_BINDING_FUNC(Servo_DeclarationBloc
SERVO_BINDING_FUNC(Servo_DeclarationBlock_SerializeOneValue, void,
RawServoDeclarationBlockBorrowed declarations,
nsString* buffer)
SERVO_BINDING_FUNC(Servo_DeclarationBlock_Count, uint32_t,
RawServoDeclarationBlockBorrowed declarations)
SERVO_BINDING_FUNC(Servo_DeclarationBlock_GetNthProperty, bool,
RawServoDeclarationBlockBorrowed declarations,
uint32_t index, nsAString* result)
+SERVO_BINDING_FUNC(Servo_DeclarationBlock_GetPropertyValue, void,
+ RawServoDeclarationBlockBorrowed declarations,
+ nsIAtom* property, bool is_custom, nsAString* value)
+SERVO_BINDING_FUNC(Servo_DeclarationBlock_GetPropertyIsImportant, bool,
+ RawServoDeclarationBlockBorrowed declarations,
+ nsIAtom* property, bool is_custom)
+SERVO_BINDING_FUNC(Servo_DeclarationBlock_RemoveProperty, void,
+ RawServoDeclarationBlockBorrowed declarations,
+ nsIAtom* property, bool is_custom)
// CSS supports()
SERVO_BINDING_FUNC(Servo_CSSSupports, bool,
const nsACString* name, const nsACString* value)
// Computed style data
SERVO_BINDING_FUNC(Servo_ComputedValues_Get, ServoComputedValuesStrong,
RawGeckoNodeBorrowed node)
--- a/layout/style/ServoDeclarationBlock.cpp
+++ b/layout/style/ServoDeclarationBlock.cpp
@@ -2,21 +2,109 @@
/* 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/ServoDeclarationBlock.h"
#include "mozilla/ServoBindings.h"
+#include "nsCSSProps.h"
+
namespace mozilla {
/* static */ already_AddRefed<ServoDeclarationBlock>
ServoDeclarationBlock::FromCssText(const nsAString& aCssText)
{
NS_ConvertUTF16toUTF8 value(aCssText);
RefPtr<RawServoDeclarationBlock>
raw = Servo_ParseStyleAttribute(&value).Consume();
RefPtr<ServoDeclarationBlock> decl = new ServoDeclarationBlock(raw.forget());
return decl.forget();
}
+/**
+ * An RAII class holding an atom for the given property.
+ */
+class MOZ_STACK_CLASS PropertyAtomHolder
+{
+public:
+ explicit PropertyAtomHolder(const nsAString& aProperty)
+ {
+ nsCSSPropertyID propID =
+ nsCSSProps::LookupProperty(aProperty, CSSEnabledState::eForAllContent);
+ if (propID == eCSSPropertyExtra_variable) {
+ mIsCustomProperty = true;
+ mAtom = NS_Atomize(
+ Substring(aProperty, CSS_CUSTOM_NAME_PREFIX_LENGTH)).take();
+ } else {
+ mIsCustomProperty = false;
+ if (propID != eCSSProperty_UNKNOWN) {
+ mAtom = nsCSSProps::AtomForProperty(propID);
+ } else {
+ mAtom = nullptr;
+ }
+ }
+ }
+
+ ~PropertyAtomHolder()
+ {
+ if (mIsCustomProperty) {
+ NS_RELEASE(mAtom);
+ }
+ }
+
+ explicit operator bool() const { return !!mAtom; }
+ nsIAtom* Atom() const { MOZ_ASSERT(mAtom); return mAtom; }
+ bool IsCustomProperty() const { return mIsCustomProperty; }
+
+private:
+ nsIAtom* mAtom;
+ bool mIsCustomProperty;
+};
+
+void
+ServoDeclarationBlock::GetPropertyValue(const nsAString& aProperty,
+ nsAString& aValue) const
+{
+ if (PropertyAtomHolder holder{aProperty}) {
+ Servo_DeclarationBlock_GetPropertyValue(
+ mRaw, holder.Atom(), holder.IsCustomProperty(), &aValue);
+ }
+}
+
+void
+ServoDeclarationBlock::GetPropertyValueByID(nsCSSPropertyID aPropID,
+ nsAString& aValue) const
+{
+ nsIAtom* atom = nsCSSProps::AtomForProperty(aPropID);
+ Servo_DeclarationBlock_GetPropertyValue(mRaw, atom, false, &aValue);
+}
+
+bool
+ServoDeclarationBlock::GetPropertyIsImportant(const nsAString& aProperty) const
+{
+ if (PropertyAtomHolder holder{aProperty}) {
+ return Servo_DeclarationBlock_GetPropertyIsImportant(
+ mRaw, holder.Atom(), holder.IsCustomProperty());
+ }
+ return false;
+}
+
+void
+ServoDeclarationBlock::RemoveProperty(const nsAString& aProperty)
+{
+ AssertMutable();
+ if (PropertyAtomHolder holder{aProperty}) {
+ Servo_DeclarationBlock_RemoveProperty(mRaw, holder.Atom(),
+ holder.IsCustomProperty());
+ }
+}
+
+void
+ServoDeclarationBlock::RemovePropertyByID(nsCSSPropertyID aPropID)
+{
+ AssertMutable();
+ nsIAtom* atom = nsCSSProps::AtomForProperty(aPropID);
+ Servo_DeclarationBlock_RemoveProperty(mRaw, atom, false);
+}
+
} // namespace mozilla
--- a/layout/style/ServoDeclarationBlock.h
+++ b/layout/style/ServoDeclarationBlock.h
@@ -40,16 +40,26 @@ public:
uint32_t Count() const {
return Servo_DeclarationBlock_Count(mRaw);
}
bool GetNthProperty(uint32_t aIndex, nsAString& aReturn) const {
aReturn.Truncate();
return Servo_DeclarationBlock_GetNthProperty(mRaw, aIndex, &aReturn);
}
+ void GetPropertyValue(const nsAString& aProperty, nsAString& aValue) const;
+ void GetPropertyValueByID(nsCSSPropertyID aPropID, nsAString& aValue) const;
+ void GetAuthoredPropertyValue(const nsAString& aProperty,
+ nsAString& aValue) const {
+ GetPropertyValue(aProperty, aValue);
+ }
+ bool GetPropertyIsImportant(const nsAString& aProperty) const;
+ void RemoveProperty(const nsAString& aProperty);
+ void RemovePropertyByID(nsCSSPropertyID aPropID);
+
protected:
explicit ServoDeclarationBlock(
already_AddRefed<RawServoDeclarationBlock> aRaw)
: DeclarationBlock(StyleBackendType::Servo), mRaw(aRaw) {}
private:
~ServoDeclarationBlock() {}
--- a/layout/style/nsDOMCSSDeclaration.cpp
+++ b/layout/style/nsDOMCSSDeclaration.cpp
@@ -44,17 +44,17 @@ NS_INTERFACE_MAP_END
NS_IMETHODIMP
nsDOMCSSDeclaration::GetPropertyValue(const nsCSSPropertyID aPropID,
nsAString& aValue)
{
NS_PRECONDITION(aPropID != eCSSProperty_UNKNOWN,
"Should never pass eCSSProperty_UNKNOWN around");
aValue.Truncate();
- if (css::Declaration* decl = GetCSSDeclaration(eOperation_Read)->AsGecko()) {
+ if (DeclarationBlock* decl = GetCSSDeclaration(eOperation_Read)) {
decl->GetPropertyValueByID(aPropID, aValue);
}
return NS_OK;
}
NS_IMETHODIMP
nsDOMCSSDeclaration::SetPropertyValue(const nsCSSPropertyID aPropID,
const nsAString& aValue)
@@ -178,37 +178,37 @@ nsDOMCSSDeclaration::IndexedGetter(uint3
aFound = decl && decl->GetNthProperty(aIndex, aPropName);
}
NS_IMETHODIMP
nsDOMCSSDeclaration::GetPropertyValue(const nsAString& aPropertyName,
nsAString& aReturn)
{
aReturn.Truncate();
- if (css::Declaration* decl = GetCSSDeclaration(eOperation_Read)->AsGecko()) {
+ if (DeclarationBlock* decl = GetCSSDeclaration(eOperation_Read)) {
decl->GetPropertyValue(aPropertyName, aReturn);
}
return NS_OK;
}
NS_IMETHODIMP
nsDOMCSSDeclaration::GetAuthoredPropertyValue(const nsAString& aPropertyName,
nsAString& aReturn)
{
- if (css::Declaration* decl = GetCSSDeclaration(eOperation_Read)->AsGecko()) {
+ if (DeclarationBlock* decl = GetCSSDeclaration(eOperation_Read)) {
decl->GetAuthoredPropertyValue(aPropertyName, aReturn);
}
return NS_OK;
}
NS_IMETHODIMP
nsDOMCSSDeclaration::GetPropertyPriority(const nsAString& aPropertyName,
nsAString& aReturn)
{
- css::Declaration* decl = GetCSSDeclaration(eOperation_Read)->AsGecko();
+ DeclarationBlock* decl = GetCSSDeclaration(eOperation_Read);
aReturn.Truncate();
if (decl && decl->GetPropertyIsImportant(aPropertyName)) {
aReturn.AssignLiteral("important");
}
return NS_OK;
}
@@ -363,17 +363,17 @@ nsDOMCSSDeclaration::RemovePropertyInter
// For nsDOMCSSAttributeDeclaration, SetCSSDeclaration will lead to
// Attribute setting code, which leads in turn to BeginUpdate. We
// need to start the update now so that the old rule doesn't get used
// between when we mutate the declaration and when we set the new
// rule (see stack in bug 209575).
mozAutoDocConditionalContentUpdateBatch autoUpdate(DocToUpdate(), true);
RefPtr<DeclarationBlock> decl = olddecl->EnsureMutable();
- decl->AsGecko()->RemovePropertyByID(aPropID);
+ decl->RemovePropertyByID(aPropID);
return SetCSSDeclaration(decl);
}
nsresult
nsDOMCSSDeclaration::RemovePropertyInternal(const nsAString& aPropertyName)
{
DeclarationBlock* olddecl = GetCSSDeclaration(eOperation_RemoveProperty);
if (!olddecl) {
@@ -383,11 +383,11 @@ nsDOMCSSDeclaration::RemovePropertyInter
// For nsDOMCSSAttributeDeclaration, SetCSSDeclaration will lead to
// Attribute setting code, which leads in turn to BeginUpdate. We
// need to start the update now so that the old rule doesn't get used
// between when we mutate the declaration and when we set the new
// rule (see stack in bug 209575).
mozAutoDocConditionalContentUpdateBatch autoUpdate(DocToUpdate(), true);
RefPtr<DeclarationBlock> decl = olddecl->EnsureMutable();
- decl->AsGecko()->RemoveProperty(aPropertyName);
+ decl->RemoveProperty(aPropertyName);
return SetCSSDeclaration(decl);
}
--- a/servo/components/style/gecko_bindings/bindings.rs
+++ b/servo/components/style/gecko_bindings/bindings.rs
@@ -956,16 +956,38 @@ extern "C" {
pub fn Servo_DeclarationBlock_GetNthProperty(declarations:
RawServoDeclarationBlockBorrowed,
index: u32,
result:
*mut nsAString_internal)
-> bool;
}
extern "C" {
+ pub fn Servo_DeclarationBlock_GetPropertyValue(declarations:
+ RawServoDeclarationBlockBorrowed,
+ property: *mut nsIAtom,
+ is_custom: bool,
+ value:
+ *mut nsAString_internal);
+}
+extern "C" {
+ pub fn Servo_DeclarationBlock_GetPropertyIsImportant(declarations:
+ RawServoDeclarationBlockBorrowed,
+ property:
+ *mut nsIAtom,
+ is_custom: bool)
+ -> bool;
+}
+extern "C" {
+ pub fn Servo_DeclarationBlock_RemoveProperty(declarations:
+ RawServoDeclarationBlockBorrowed,
+ property: *mut nsIAtom,
+ is_custom: bool);
+}
+extern "C" {
pub fn Servo_CSSSupports(name: *const nsACString_internal,
value: *const nsACString_internal) -> bool;
}
extern "C" {
pub fn Servo_ComputedValues_Get(node: RawGeckoNodeBorrowed)
-> ServoComputedValuesStrong;
}
extern "C" {
--- a/servo/ports/geckolib/glue.rs
+++ b/servo/ports/geckolib/glue.rs
@@ -503,16 +503,54 @@ pub extern "C" fn Servo_DeclarationBlock
let result = unsafe { result.as_mut().unwrap() };
write!(result, "{}", decl.name()).unwrap();
true
} else {
false
}
}
+// FIXME Methods of PropertyDeclarationBlock should take atoms directly.
+// This function is just a temporary workaround before that finishes.
+fn get_property_name_from_atom(atom: *mut nsIAtom, is_custom: bool) -> String {
+ let atom = Atom::from(atom);
+ if !is_custom {
+ atom.to_string()
+ } else {
+ let mut result = String::with_capacity(atom.len() as usize + 2);
+ write!(result, "--{}", atom).unwrap();
+ result
+ }
+}
+
+#[no_mangle]
+pub extern "C" fn Servo_DeclarationBlock_GetPropertyValue(declarations: RawServoDeclarationBlockBorrowed,
+ property: *mut nsIAtom, is_custom: bool,
+ value: *mut nsAString) {
+ let declarations = RwLock::<PropertyDeclarationBlock>::as_arc(&declarations);
+ let property = get_property_name_from_atom(property, is_custom);
+ declarations.read().property_value_to_css(&property, unsafe { value.as_mut().unwrap() }).unwrap();
+}
+
+#[no_mangle]
+pub extern "C" fn Servo_DeclarationBlock_GetPropertyIsImportant(declarations: RawServoDeclarationBlockBorrowed,
+ property: *mut nsIAtom, is_custom: bool) -> bool {
+ let declarations = RwLock::<PropertyDeclarationBlock>::as_arc(&declarations);
+ let property = get_property_name_from_atom(property, is_custom);
+ declarations.read().property_priority(&property).important()
+}
+
+#[no_mangle]
+pub extern "C" fn Servo_DeclarationBlock_RemoveProperty(declarations: RawServoDeclarationBlockBorrowed,
+ property: *mut nsIAtom, is_custom: bool) {
+ let declarations = RwLock::<PropertyDeclarationBlock>::as_arc(&declarations);
+ let property = get_property_name_from_atom(property, is_custom);
+ declarations.write().remove_property(&property);
+}
+
#[no_mangle]
pub extern "C" fn Servo_CSSSupports(property: *const nsACString, value: *const nsACString) -> bool {
let property = unsafe { property.as_ref().unwrap().as_str_unchecked() };
let value = unsafe { value.as_ref().unwrap().as_str_unchecked() };
let base_url = &*DUMMY_BASE_URL;
let extra_data = ParserContextExtraData::default();