Bug 1307357 part 6 - Implement CSSStyleRule.style. r?heycam
MozReview-Commit-ID: 8Qvzc74wveE
--- a/layout/style/ServoBindingList.h
+++ b/layout/style/ServoBindingList.h
@@ -54,16 +54,21 @@ SERVO_BINDING_FUNC(Servo_StyleSet_Insert
// CSSRuleList
SERVO_BINDING_FUNC(Servo_CssRules_ListTypes, void,
ServoCssRulesBorrowed rules,
nsTArrayBorrowed_uintptr_t result)
SERVO_BINDING_FUNC(Servo_CssRules_GetStyleRuleAt, RawServoStyleRuleStrong,
ServoCssRulesBorrowed rules, uint32_t index)
// CSS Rules
+SERVO_BINDING_FUNC(Servo_StyleRule_GetStyle, RawServoDeclarationBlockStrong,
+ RawServoStyleRuleBorrowed rule)
+SERVO_BINDING_FUNC(Servo_StyleRule_SetStyle, void,
+ RawServoStyleRuleBorrowed rule,
+ RawServoDeclarationBlockBorrowed declarations)
SERVO_BINDING_FUNC(Servo_StyleRule_GetCssText, void,
RawServoStyleRuleBorrowed rule, nsAString* result)
SERVO_BINDING_FUNC(Servo_StyleRule_GetSelectorText, void,
RawServoStyleRuleBorrowed rule, nsAString* result)
// Animations API
SERVO_BINDING_FUNC(Servo_ParseProperty,
RawServoDeclarationBlockStrong,
--- a/layout/style/ServoDeclarationBlock.h
+++ b/layout/style/ServoDeclarationBlock.h
@@ -9,16 +9,20 @@
#include "mozilla/ServoBindings.h"
#include "mozilla/DeclarationBlock.h"
namespace mozilla {
class ServoDeclarationBlock final : public DeclarationBlock
{
public:
+ explicit ServoDeclarationBlock(
+ already_AddRefed<RawServoDeclarationBlock> aRaw)
+ : DeclarationBlock(StyleBackendType::Servo), mRaw(aRaw) {}
+
ServoDeclarationBlock()
: ServoDeclarationBlock(Servo_DeclarationBlock_CreateEmpty().Consume()) {}
ServoDeclarationBlock(const ServoDeclarationBlock& aCopy)
: DeclarationBlock(aCopy)
, mRaw(Servo_DeclarationBlock_Clone(aCopy.mRaw).Consume()) {}
NS_INLINE_DECL_REFCOUNTING(ServoDeclarationBlock)
@@ -51,21 +55,16 @@ public:
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() {}
RefPtr<RawServoDeclarationBlock> mRaw;
};
} // namespace mozilla
--- a/layout/style/ServoStyleRule.cpp
+++ b/layout/style/ServoStyleRule.cpp
@@ -4,33 +4,145 @@
* 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 */
#include "mozilla/ServoStyleRule.h"
#include "mozilla/ServoBindings.h"
+#include "mozilla/ServoDeclarationBlock.h"
#include "nsDOMClassInfoID.h"
+#include "mozAutoDocUpdate.h"
namespace mozilla {
+// -- ServoStyleRuleDeclaration ---------------------------------------
+
+ServoStyleRuleDeclaration::ServoStyleRuleDeclaration(
+ already_AddRefed<RawServoDeclarationBlock> aDecls)
+ : mDecls(new ServoDeclarationBlock(Move(aDecls)))
+{
+}
+
+ServoStyleRuleDeclaration::~ServoStyleRuleDeclaration()
+{
+}
+
+// QueryInterface implementation for ServoStyleRuleDeclaration
+NS_INTERFACE_MAP_BEGIN(ServoStyleRuleDeclaration)
+ NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
+ // We forward the cycle collection interfaces to Rule(), 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 Rule()->QueryInterface(aIID, aInstancePtr);
+ }
+ else
+NS_IMPL_QUERY_TAIL_INHERITING(nsDOMCSSDeclaration)
+
+NS_IMPL_ADDREF_USING_AGGREGATOR(ServoStyleRuleDeclaration, Rule())
+NS_IMPL_RELEASE_USING_AGGREGATOR(ServoStyleRuleDeclaration, Rule())
+
+/* nsDOMCSSDeclaration implementation */
+
+NS_IMETHODIMP
+ServoStyleRuleDeclaration::GetParentRule(nsIDOMCSSRule** aParent)
+{
+ *aParent = do_AddRef(Rule()).take();
+ return NS_OK;
+}
+
+nsINode*
+ServoStyleRuleDeclaration::GetParentObject()
+{
+ return Rule()->GetDocument();
+}
+
+DeclarationBlock*
+ServoStyleRuleDeclaration::GetCSSDeclaration(Operation aOperation)
+{
+ return mDecls;
+}
+
+nsresult
+ServoStyleRuleDeclaration::SetCSSDeclaration(DeclarationBlock* aDecl)
+{
+ ServoStyleRule* rule = Rule();
+ if (RefPtr<ServoStyleSheet> sheet = rule->GetStyleSheet()->AsServo()) {
+ nsCOMPtr<nsIDocument> owningDoc = sheet->GetOwningDocument();
+ mozAutoDocUpdate updateBatch(owningDoc, UPDATE_STYLE, true);
+ if (aDecl != mDecls) {
+ RefPtr<ServoDeclarationBlock> decls = aDecl->AsServo();
+ Servo_StyleRule_SetStyle(rule->Raw(), decls->Raw());
+ mDecls = decls.forget();
+ }
+ if (owningDoc) {
+ owningDoc->StyleRuleChanged(sheet, rule);
+ }
+ }
+ return NS_OK;
+}
+
+nsIDocument*
+ServoStyleRuleDeclaration::DocToUpdate()
+{
+ return nullptr;
+}
+
+void
+ServoStyleRuleDeclaration::GetCSSParsingEnvironment(
+ CSSParsingEnvironment& aCSSParseEnv)
+{
+ GetCSSParsingEnvironmentForRule(Rule(), aCSSParseEnv);
+}
+
// -- ServoStyleRule --------------------------------------------------
+ServoStyleRule::ServoStyleRule(already_AddRefed<RawServoStyleRule> aRawRule)
+ : css::Rule(0, 0)
+ , mRawRule(aRawRule)
+ , mDecls(Servo_StyleRule_GetStyle(mRawRule).Consume())
+{
+}
+
// QueryInterface implementation for ServoStyleRule
-NS_INTERFACE_MAP_BEGIN(ServoStyleRule)
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ServoStyleRule)
NS_INTERFACE_MAP_ENTRY(nsIDOMCSSStyleRule)
NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRule)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, css::Rule)
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CSSStyleRule)
NS_INTERFACE_MAP_END
-NS_IMPL_ADDREF(ServoStyleRule)
-NS_IMPL_RELEASE(ServoStyleRule)
+NS_IMPL_CYCLE_COLLECTING_ADDREF(ServoStyleRule)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(ServoStyleRule)
+
+NS_IMPL_CYCLE_COLLECTION_CLASS(ServoStyleRule)
+
+NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(ServoStyleRule)
+ // 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->mDecls.TraceWrapper(aCallbacks, aClosure);
+NS_IMPL_CYCLE_COLLECTION_TRACE_END
+
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ServoStyleRule)
+ // 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->mDecls.ReleaseWrapper(static_cast<nsISupports*>(p));
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(ServoStyleRule)
+ // Just NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS here: that will call
+ // into our Trace hook, where we do the right thing with declarations
+ // already.
+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
already_AddRefed<css::Rule>
ServoStyleRule::Clone() const
{
// Rule::Clone is only used when CSSStyleSheetInner is cloned in
// preparation of being mutated. However, ServoStyleSheet never clones
// anything, so this method should never be called.
MOZ_ASSERT_UNREACHABLE("Shouldn't be cloning ServoStyleRule");
@@ -109,13 +221,13 @@ ServoStyleRule::SetSelectorText(const ns
// so it's probably okay to leave it unimplemented currently?
// See bug 37468 and mozilla::css::StyleRule::SetSelectorText.
return NS_OK;
}
NS_IMETHODIMP
ServoStyleRule::GetStyle(nsIDOMCSSStyleDeclaration** aStyle)
{
- *aStyle = nullptr;
- return NS_ERROR_NOT_IMPLEMENTED;
+ *aStyle = do_AddRef(&mDecls).take();
+ return NS_OK;
}
} // namespace mozilla
--- a/layout/style/ServoStyleRule.h
+++ b/layout/style/ServoStyleRule.h
@@ -8,43 +8,85 @@
#ifndef mozilla_ServoStyleRule_h
#define mozilla_ServoStyleRule_h
#include "mozilla/css/Rule.h"
#include "mozilla/ServoBindingTypes.h"
#include "nsIDOMCSSStyleRule.h"
+#include "nsDOMCSSDeclaration.h"
namespace mozilla {
+class ServoDeclarationBlock;
+
+class ServoStyleRuleDeclaration final : public nsDOMCSSDeclaration
+{
+public:
+ NS_DECL_ISUPPORTS_INHERITED
+
+ NS_IMETHOD GetParentRule(nsIDOMCSSRule** aParent) final;
+ nsINode* GetParentObject() final;
+
+protected:
+ DeclarationBlock* GetCSSDeclaration(Operation aOperation) final;
+ nsresult SetCSSDeclaration(DeclarationBlock* aDecl) final;
+ nsIDocument* DocToUpdate() final;
+ void GetCSSParsingEnvironment(CSSParsingEnvironment& aCSSParseEnv) final;
+
+private:
+ // For accessing the constructor.
+ friend class ServoStyleRule;
+
+ explicit ServoStyleRuleDeclaration(
+ already_AddRefed<RawServoDeclarationBlock> aDecls);
+ ~ServoStyleRuleDeclaration();
+
+ inline ServoStyleRule* Rule();
+
+ RefPtr<ServoDeclarationBlock> mDecls;
+};
+
class ServoStyleRule final : public css::Rule
, public nsIDOMCSSStyleRule
{
public:
- explicit ServoStyleRule(already_AddRefed<RawServoStyleRule> aRawRule)
- : css::Rule(0, 0)
- , mRawRule(aRawRule)
- {}
+ explicit ServoStyleRule(already_AddRefed<RawServoStyleRule> aRawRule);
- NS_DECL_ISUPPORTS
+ NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+ NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(ServoStyleRule,
+ css::Rule)
NS_DECL_NSIDOMCSSRULE
NS_DECL_NSIDOMCSSSTYLERULE
+ RawServoStyleRule* Raw() const { return mRawRule; }
+
// Methods of mozilla::css::Rule
int32_t GetType() const final { return css::Rule::STYLE_RULE; }
already_AddRefed<Rule> Clone() const final;
nsIDOMCSSRule* GetDOMRule() final { return this; }
nsIDOMCSSRule* GetExistingDOMRule() final { return this; }
size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const final;
#ifdef DEBUG
void List(FILE* out = stdout, int32_t aIndent = 0) const final;
#endif
private:
~ServoStyleRule() {}
+ // For computing the offset of mDecls.
+ friend class ServoStyleRuleDeclaration;
+
RefPtr<RawServoStyleRule> mRawRule;
+ ServoStyleRuleDeclaration mDecls;
};
+ServoStyleRule*
+ServoStyleRuleDeclaration::Rule()
+{
+ return reinterpret_cast<ServoStyleRule*>(reinterpret_cast<uint8_t*>(this) -
+ offsetof(ServoStyleRule, mDecls));
+}
+
} // namespace mozilla
#endif // mozilla_ServoStyleRule_h
--- a/servo/components/style/gecko_bindings/bindings.rs
+++ b/servo/components/style/gecko_bindings/bindings.rs
@@ -990,16 +990,25 @@ extern "C" {
reference:
RawServoStyleSheetBorrowed);
}
extern "C" {
pub fn Servo_CssRules_ListRuleTypes(rules: ServoCssRulesBorrowed,
result: nsTArrayBorrowed_uintptr_t);
}
extern "C" {
+ pub fn Servo_StyleRule_GetStyle(rule: RawServoStyleRuleBorrowed)
+ -> RawServoDeclarationBlockStrong;
+}
+extern "C" {
+ pub fn Servo_StyleRule_SetStyle(rule: RawServoStyleRuleBorrowed,
+ declarations:
+ RawServoDeclarationBlockBorrowed);
+}
+extern "C" {
pub fn Servo_StyleRule_GetCssText(rule: RawServoStyleRuleBorrowed,
result: *mut nsAString_internal);
}
extern "C" {
pub fn Servo_StyleRule_GetSelectorText(rule: RawServoStyleRuleBorrowed,
result: *mut nsAString_internal);
}
extern "C" {
--- a/servo/ports/geckolib/glue.rs
+++ b/servo/ports/geckolib/glue.rs
@@ -315,16 +315,30 @@ pub extern "C" fn Servo_StyleRule_AddRef
}
#[no_mangle]
pub extern "C" fn Servo_StyleRule_Release(rule: RawServoStyleRuleBorrowed) -> () {
unsafe { RwLock::<StyleRule>::release(rule) };
}
#[no_mangle]
+pub extern "C" fn Servo_StyleRule_GetStyle(rule: RawServoStyleRuleBorrowed) -> RawServoDeclarationBlockStrong {
+ let rule = RwLock::<StyleRule>::as_arc(&rule);
+ rule.read().block.clone().into_strong()
+}
+
+#[no_mangle]
+pub extern "C" fn Servo_StyleRule_SetStyle(rule: RawServoStyleRuleBorrowed,
+ declarations: RawServoDeclarationBlockBorrowed) -> () {
+ let rule = RwLock::<StyleRule>::as_arc(&rule);
+ let declarations = RwLock::<PropertyDeclarationBlock>::as_arc(&declarations);
+ rule.write().block = declarations.clone();
+}
+
+#[no_mangle]
pub extern "C" fn Servo_StyleRule_GetCssText(rule: RawServoStyleRuleBorrowed, result: *mut nsAString) -> () {
let rule = RwLock::<StyleRule>::as_arc(&rule);
rule.read().to_css(unsafe { result.as_mut().unwrap() }).unwrap();
}
#[no_mangle]
pub extern "C" fn Servo_StyleRule_GetSelectorText(rule: RawServoStyleRuleBorrowed, result: *mut nsAString) -> () {
let rule = RwLock::<StyleRule>::as_arc(&rule);