--- a/layout/style/ServoArcTypeList.h
+++ b/layout/style/ServoArcTypeList.h
@@ -8,15 +8,17 @@
SERVO_ARC_TYPE(CssRules, ServoCssRules)
SERVO_ARC_TYPE(StyleSheet, RawServoStyleSheet)
SERVO_ARC_TYPE(ComputedValues, ServoComputedValues)
SERVO_ARC_TYPE(DeclarationBlock, RawServoDeclarationBlock)
SERVO_ARC_TYPE(StyleRule, RawServoStyleRule)
SERVO_ARC_TYPE(ImportRule, RawServoImportRule)
SERVO_ARC_TYPE(AnimationValue, RawServoAnimationValue)
+SERVO_ARC_TYPE(Keyframe, RawServoKeyframe)
+SERVO_ARC_TYPE(KeyframesRule, RawServoKeyframesRule)
SERVO_ARC_TYPE(MediaList, RawServoMediaList)
SERVO_ARC_TYPE(MediaRule, RawServoMediaRule)
SERVO_ARC_TYPE(NamespaceRule, RawServoNamespaceRule)
SERVO_ARC_TYPE(PageRule, RawServoPageRule)
SERVO_ARC_TYPE(SupportsRule, RawServoSupportsRule)
SERVO_ARC_TYPE(DocumentRule, RawServoDocumentRule)
SERVO_ARC_TYPE(RuleNode, RawServoRuleNode)
--- a/layout/style/ServoBindingList.h
+++ b/layout/style/ServoBindingList.h
@@ -99,48 +99,81 @@ SERVO_BINDING_FUNC(Servo_CssRules_Insert
RawServoStyleSheetBorrowed sheet, const nsACString* rule,
uint32_t index, bool nested, mozilla::css::Loader* loader,
mozilla::ServoStyleSheet* gecko_stylesheet,
uint16_t* rule_type)
SERVO_BINDING_FUNC(Servo_CssRules_DeleteRule, nsresult,
ServoCssRulesBorrowed rules, uint32_t index)
// CSS Rules
+#define BASIC_RULE_FUNCS_WITHOUT_GETTER(type_) \
+ SERVO_BINDING_FUNC(Servo_##type_##_Debug, void, \
+ RawServo##type_##Borrowed rule, nsACString* result) \
+ SERVO_BINDING_FUNC(Servo_##type_##_GetCssText, void, \
+ RawServo##type_##Borrowed rule, nsAString* result)
#define BASIC_RULE_FUNCS(type_) \
SERVO_BINDING_FUNC(Servo_CssRules_Get##type_##RuleAt, \
RawServo##type_##RuleStrong, \
ServoCssRulesBorrowed rules, uint32_t index, \
uint32_t* line, uint32_t* column) \
- SERVO_BINDING_FUNC(Servo_##type_##Rule_Debug, void, \
- RawServo##type_##RuleBorrowed rule, nsACString* result) \
- SERVO_BINDING_FUNC(Servo_##type_##Rule_GetCssText, void, \
- RawServo##type_##RuleBorrowed rule, nsAString* result)
+ BASIC_RULE_FUNCS_WITHOUT_GETTER(type_##Rule)
#define GROUP_RULE_FUNCS(type_) \
BASIC_RULE_FUNCS(type_) \
SERVO_BINDING_FUNC(Servo_##type_##Rule_GetRules, ServoCssRulesStrong, \
RawServo##type_##RuleBorrowed rule)
BASIC_RULE_FUNCS(Style)
+BASIC_RULE_FUNCS_WITHOUT_GETTER(Keyframe)
+BASIC_RULE_FUNCS(Keyframes)
GROUP_RULE_FUNCS(Media)
BASIC_RULE_FUNCS(Namespace)
BASIC_RULE_FUNCS(Page)
GROUP_RULE_FUNCS(Supports)
GROUP_RULE_FUNCS(Document)
#undef GROUP_RULE_FUNCS
#undef BASIC_RULE_FUNCS
+#undef BASIC_RULE_FUNCS_WITHOUT_GETTER
SERVO_BINDING_FUNC(Servo_CssRules_GetFontFaceRuleAt, nsCSSFontFaceRule*,
ServoCssRulesBorrowed rules, uint32_t index)
SERVO_BINDING_FUNC(Servo_CssRules_GetCounterStyleRuleAt, nsCSSCounterStyleRule*,
ServoCssRulesBorrowed rules, uint32_t index)
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_GetSelectorText, void,
RawServoStyleRuleBorrowed rule, nsAString* result)
+SERVO_BINDING_FUNC(Servo_Keyframe_GetKeyText, void,
+ RawServoKeyframeBorrowed keyframe, nsAString* result)
+// Returns whether it successfully changes the key text.
+SERVO_BINDING_FUNC(Servo_Keyframe_SetKeyText, bool,
+ RawServoKeyframeBorrowed keyframe, const nsACString* text)
+SERVO_BINDING_FUNC(Servo_Keyframe_GetStyle, RawServoDeclarationBlockStrong,
+ RawServoKeyframeBorrowed keyframe)
+SERVO_BINDING_FUNC(Servo_Keyframe_SetStyle, void,
+ RawServoKeyframeBorrowed keyframe,
+ RawServoDeclarationBlockBorrowed declarations)
+SERVO_BINDING_FUNC(Servo_KeyframesRule_GetName, nsIAtom*,
+ RawServoKeyframesRuleBorrowed rule)
+// This method takes an addrefed nsIAtom.
+SERVO_BINDING_FUNC(Servo_KeyframesRule_SetName, void,
+ RawServoKeyframesRuleBorrowed rule, nsIAtom* name)
+SERVO_BINDING_FUNC(Servo_KeyframesRule_GetCount, uint32_t,
+ RawServoKeyframesRuleBorrowed rule)
+SERVO_BINDING_FUNC(Servo_KeyframesRule_GetKeyframe, RawServoKeyframeStrong,
+ RawServoKeyframesRuleBorrowed rule, uint32_t index)
+// Returns the index of the rule, max value of uint32_t if nothing found.
+SERVO_BINDING_FUNC(Servo_KeyframesRule_FindRule, uint32_t,
+ RawServoKeyframesRuleBorrowed rule, const nsACString* key)
+// Returns whether it successfully appends the rule.
+SERVO_BINDING_FUNC(Servo_KeyframesRule_AppendRule, bool,
+ RawServoKeyframesRuleBorrowed rule,
+ RawServoStyleSheetBorrowed sheet, const nsACString* css)
+SERVO_BINDING_FUNC(Servo_KeyframesRule_DeleteRule, void,
+ RawServoKeyframesRuleBorrowed rule, uint32_t index)
SERVO_BINDING_FUNC(Servo_MediaRule_GetMedia, RawServoMediaListStrong,
RawServoMediaRuleBorrowed rule)
SERVO_BINDING_FUNC(Servo_NamespaceRule_GetPrefix, nsIAtom*,
RawServoNamespaceRuleBorrowed rule)
SERVO_BINDING_FUNC(Servo_NamespaceRule_GetURI, nsIAtom*,
RawServoNamespaceRuleBorrowed rule)
SERVO_BINDING_FUNC(Servo_PageRule_GetStyle, RawServoDeclarationBlockStrong,
RawServoPageRuleBorrowed rule)
--- a/layout/style/ServoCSSRuleList.cpp
+++ b/layout/style/ServoCSSRuleList.cpp
@@ -5,16 +5,17 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* representation of CSSRuleList for stylo */
#include "mozilla/ServoCSSRuleList.h"
#include "mozilla/ServoBindings.h"
#include "mozilla/ServoDocumentRule.h"
+#include "mozilla/ServoKeyframesRule.h"
#include "mozilla/ServoMediaRule.h"
#include "mozilla/ServoNamespaceRule.h"
#include "mozilla/ServoPageRule.h"
#include "mozilla/ServoStyleRule.h"
#include "mozilla/ServoSupportsRule.h"
#include "nsCSSCounterStyleRule.h"
#include "nsCSSFontFaceRule.h"
@@ -92,16 +93,17 @@ ServoCSSRuleList::GetRule(uint32_t aInde
RefPtr<RawServo##name_##Rule> rule = \
Servo_CssRules_Get##name_##RuleAt( \
mRawRules, aIndex, &line, &column \
).Consume(); \
ruleObj = new Servo##name_##Rule(rule.forget(), line, column); \
break; \
}
CASE_RULE(STYLE, Style)
+ CASE_RULE(KEYFRAMES, Keyframes)
CASE_RULE(MEDIA, Media)
CASE_RULE(NAMESPACE, Namespace)
CASE_RULE(PAGE, Page)
CASE_RULE(SUPPORTS, Supports)
CASE_RULE(DOCUMENT, Document)
#undef CASE_RULE
// For @font-face and @counter-style rules, the function returns
// a borrowed Gecko rule object directly, so we don't need to
@@ -110,18 +112,19 @@ ServoCSSRuleList::GetRule(uint32_t aInde
case nsIDOMCSSRule::FONT_FACE_RULE: {
ruleObj = Servo_CssRules_GetFontFaceRuleAt(mRawRules, aIndex);
break;
}
case nsIDOMCSSRule::COUNTER_STYLE_RULE: {
ruleObj = Servo_CssRules_GetCounterStyleRuleAt(mRawRules, aIndex);
break;
}
- case nsIDOMCSSRule::KEYFRAMES_RULE:
- // XXX create corresponding rules
+ case nsIDOMCSSRule::KEYFRAME_RULE:
+ MOZ_ASSERT_UNREACHABLE("keyframe rule cannot be here");
+ return nullptr;
default:
NS_WARNING("stylo: not implemented yet");
return nullptr;
}
ruleObj->SetStyleSheet(mStyleSheet);
ruleObj->SetParentRule(mParentRule);
rule = CastToUint(ruleObj.forget().take());
mRules[aIndex] = rule;
new file mode 100644
--- /dev/null
+++ b/layout/style/ServoKeyframeRule.cpp
@@ -0,0 +1,216 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* 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/ServoKeyframeRule.h"
+
+#include "nsDOMCSSDeclaration.h"
+#include "mozAutoDocUpdate.h"
+
+namespace mozilla {
+
+// -------------------------------------------
+// ServoKeyframeDeclaration
+//
+
+class ServoKeyframeDeclaration : public nsDOMCSSDeclaration
+{
+public:
+ explicit ServoKeyframeDeclaration(ServoKeyframeRule* aRule)
+ : mRule(aRule)
+ {
+ mDecls = new ServoDeclarationBlock(
+ Servo_Keyframe_GetStyle(aRule->Raw()).Consume());
+ }
+
+ NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+ NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(
+ ServoKeyframeDeclaration, nsICSSDeclaration)
+
+ NS_IMETHOD GetParentRule(nsIDOMCSSRule** aParent) final
+ {
+ *aParent = mRule;
+ return NS_OK;
+ }
+
+ void DropReference() { mRule = nullptr; }
+
+ DeclarationBlock* GetCSSDeclaration(Operation aOperation) final
+ {
+ return mDecls;
+ }
+ nsresult SetCSSDeclaration(DeclarationBlock* aDecls) final
+ {
+ if (!mRule) {
+ return NS_OK;
+ }
+ mRule->UpdateRule([this, aDecls]() {
+ if (mDecls != aDecls) {
+ mDecls->SetOwningRule(nullptr);
+ mDecls = aDecls->AsServo();
+ mDecls->SetOwningRule(mRule);
+ Servo_Keyframe_SetStyle(mRule->Raw(), mDecls->Raw());
+ }
+ });
+ return NS_OK;
+ }
+ void GetCSSParsingEnvironment(CSSParsingEnvironment& aCSSParseEnv) final
+ {
+ MOZ_ASSERT_UNREACHABLE("GetCSSParsingEnvironment "
+ "shouldn't be calling for a Servo rule");
+ GetCSSParsingEnvironmentForRule(mRule, aCSSParseEnv);
+ }
+ ServoCSSParsingEnvironment GetServoCSSParsingEnvironment() const final
+ {
+ return GetServoCSSParsingEnvironmentForRule(mRule);
+ }
+ nsIDocument* DocToUpdate() final { return nullptr; }
+
+ nsINode* GetParentObject() final
+ {
+ return mRule ? mRule->GetDocument() : nullptr;
+ }
+
+ size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
+ {
+ size_t n = aMallocSizeOf(this);
+ // TODO we may want to add size of mDecls as well
+ return n;
+ }
+
+private:
+ virtual ~ServoKeyframeDeclaration() {}
+
+ ServoKeyframeRule* mRule;
+ RefPtr<ServoDeclarationBlock> mDecls;
+};
+
+NS_IMPL_CYCLE_COLLECTING_ADDREF(ServoKeyframeDeclaration)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(ServoKeyframeDeclaration)
+
+NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(ServoKeyframeDeclaration)
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ServoKeyframeDeclaration)
+ NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
+NS_INTERFACE_MAP_END_INHERITING(nsDOMCSSDeclaration)
+
+// -------------------------------------------
+// ServoKeyframeRule
+//
+
+ServoKeyframeRule::~ServoKeyframeRule()
+{
+}
+
+NS_IMPL_ADDREF_INHERITED(ServoKeyframeRule, dom::CSSKeyframeRule)
+NS_IMPL_RELEASE_INHERITED(ServoKeyframeRule, dom::CSSKeyframeRule)
+
+// QueryInterface implementation for nsCSSKeyframeRule
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(ServoKeyframeRule)
+NS_INTERFACE_MAP_END_INHERITING(dom::CSSKeyframeRule)
+
+NS_IMPL_CYCLE_COLLECTION_CLASS(ServoKeyframeRule)
+
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(ServoKeyframeRule,
+ dom::CSSKeyframeRule)
+ if (tmp->mDeclaration) {
+ tmp->mDeclaration->DropReference();
+ tmp->mDeclaration = nullptr;
+ }
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(ServoKeyframeRule,
+ dom::CSSKeyframeRule)
+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDeclaration)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+bool
+ServoKeyframeRule::IsCCLeaf() const
+{
+ return Rule::IsCCLeaf() && !mDeclaration;
+}
+
+/* virtual */ already_AddRefed<css::Rule>
+ServoKeyframeRule::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 ServoKeyframeRule");
+ return nullptr;
+}
+
+#ifdef DEBUG
+/* virtual */ void
+ServoKeyframeRule::List(FILE* out, int32_t aIndent) const
+{
+ nsAutoCString str;
+ for (int32_t i = 0; i < aIndent; i++) {
+ str.AppendLiteral(" ");
+ }
+ Servo_Keyframe_Debug(mRaw, &str);
+ fprintf_stderr(out, "%s\n", str.get());
+}
+#endif
+
+template<typename Func>
+void
+ServoKeyframeRule::UpdateRule(Func aCallback)
+{
+ nsIDocument* doc = GetDocument();
+ MOZ_AUTO_DOC_UPDATE(doc, UPDATE_STYLE, true);
+
+ aCallback();
+
+ if (StyleSheet* sheet = GetStyleSheet()) {
+ // FIXME sheet->AsGecko()->SetModifiedByChildRule();
+ if (doc) {
+ doc->StyleRuleChanged(sheet, this);
+ }
+ }
+}
+
+NS_IMETHODIMP
+ServoKeyframeRule::GetKeyText(nsAString& aKeyText)
+{
+ Servo_Keyframe_GetKeyText(mRaw, &aKeyText);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+ServoKeyframeRule::SetKeyText(const nsAString& aKeyText)
+{
+ NS_ConvertUTF16toUTF8 keyText(aKeyText);
+ UpdateRule([this, &keyText]() {
+ Servo_Keyframe_SetKeyText(mRaw, &keyText);
+ });
+ return NS_OK;
+}
+
+void
+ServoKeyframeRule::GetCssTextImpl(nsAString& aCssText) const
+{
+ Servo_Keyframe_GetCssText(mRaw, &aCssText);
+}
+
+nsICSSDeclaration*
+ServoKeyframeRule::Style()
+{
+ if (!mDeclaration) {
+ mDeclaration = new ServoKeyframeDeclaration(this);
+ }
+ return mDeclaration;
+}
+
+size_t
+ServoKeyframeRule::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
+{
+ size_t n = aMallocSizeOf(this);
+ if (mDeclaration) {
+ n += mDeclaration->SizeOfIncludingThis(aMallocSizeOf);
+ }
+ return n;
+}
+
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/layout/style/ServoKeyframeRule.h
@@ -0,0 +1,62 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* 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/. */
+
+#ifndef mozilla_ServoKeyframeRule_h
+#define mozilla_ServoKeyframeRule_h
+
+#include "mozilla/dom/CSSKeyframeRule.h"
+#include "mozilla/ServoBindingTypes.h"
+
+namespace mozilla {
+
+class ServoDeclarationBlock;
+class ServoKeyframeDeclaration;
+
+class ServoKeyframeRule final : public dom::CSSKeyframeRule
+{
+public:
+ explicit ServoKeyframeRule(already_AddRefed<RawServoKeyframe> aRaw)
+ : CSSKeyframeRule(0, 0)
+ , mRaw(aRaw) {}
+
+ NS_DECL_ISUPPORTS_INHERITED
+ NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(ServoKeyframeRule,
+ dom::CSSKeyframeRule)
+
+ bool IsCCLeaf() const final;
+#ifdef DEBUG
+ void List(FILE* out = stdout, int32_t aIndent = 0) const final;
+#endif
+ already_AddRefed<mozilla::css::Rule> Clone() const final;
+
+ RawServoKeyframe* Raw() const { return mRaw; }
+
+ // nsIDOMCSSKeyframeRule interface
+ NS_IMETHOD GetKeyText(nsAString& aKeyText) final;
+ NS_IMETHOD SetKeyText(const nsAString& aKeyText) final;
+
+ // WebIDL interface
+ void GetCssTextImpl(nsAString& aCssText) const final;
+ nsICSSDeclaration* Style() final;
+
+ size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const final;
+
+private:
+ virtual ~ServoKeyframeRule();
+
+ friend class ServoKeyframeDeclaration;
+
+ template<typename Func>
+ void UpdateRule(Func aCallback);
+
+ RefPtr<RawServoKeyframe> mRaw;
+ // lazily created when needed
+ RefPtr<ServoKeyframeDeclaration> mDeclaration;
+};
+
+} // namespace mozilla
+
+#endif // mozilla_ServoKeyframeRule_h
new file mode 100644
--- /dev/null
+++ b/layout/style/ServoKeyframesRule.cpp
@@ -0,0 +1,349 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* 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/ServoKeyframesRule.h"
+
+#include "mozAutoDocUpdate.h"
+#include "mozilla/ServoBindings.h"
+#include "mozilla/ServoKeyframeRule.h"
+
+#include <limits>
+
+namespace mozilla {
+
+// -------------------------------------------
+// ServoKeyframeList
+//
+
+class ServoKeyframeList : public dom::CSSRuleList
+{
+public:
+ explicit ServoKeyframeList(already_AddRefed<RawServoKeyframesRule> aRawRule)
+ : mRawRule(aRawRule)
+ {
+ mRules.SetCount(Servo_KeyframesRule_GetCount(mRawRule));
+ }
+
+ NS_DECL_ISUPPORTS_INHERITED
+ NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(ServoKeyframeList, dom::CSSRuleList)
+
+ void SetParentRule(ServoKeyframesRule* aParentRule)
+ {
+ mParentRule = aParentRule;
+ for (css::Rule* rule : mRules) {
+ if (rule) {
+ rule->SetParentRule(aParentRule);
+ }
+ }
+ }
+ void SetStyleSheet(ServoStyleSheet* aSheet)
+ {
+ mStyleSheet = aSheet;
+ for (css::Rule* rule : mRules) {
+ if (rule) {
+ rule->SetStyleSheet(aSheet);
+ }
+ }
+ }
+
+ ServoStyleSheet* GetParentObject() final { return mStyleSheet; }
+
+ ServoKeyframeRule* GetRule(uint32_t aIndex) {
+ if (!mRules[aIndex]) {
+ ServoKeyframeRule* rule = new ServoKeyframeRule(
+ Servo_KeyframesRule_GetKeyframe(mRawRule, aIndex).Consume());
+ mRules.ReplaceObjectAt(rule, aIndex);
+ }
+ return static_cast<ServoKeyframeRule*>(mRules[aIndex]);
+ }
+
+ ServoKeyframeRule* IndexedGetter(uint32_t aIndex, bool& aFound) final
+ {
+ if (aIndex >= mRules.Length()) {
+ aFound = false;
+ return nullptr;
+ }
+ aFound = true;
+ return GetRule(aIndex);
+ }
+
+ void AppendRule() {
+ mRules.AppendObject(nullptr);
+ }
+ void RemoveRule(uint32_t aIndex) {
+ mRules.RemoveObjectAt(aIndex);
+ }
+
+ uint32_t Length() final { return mRules.Length(); }
+
+ void DropReference()
+ {
+ mStyleSheet = nullptr;
+ mParentRule = nullptr;
+ DropAllRules();
+ }
+
+ size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
+ {
+ size_t n = aMallocSizeOf(this);
+ for (const css::Rule* rule : mRules) {
+ n += rule ? rule->SizeOfIncludingThis(aMallocSizeOf) : 0;
+ }
+ return n;
+ }
+
+private:
+ virtual ~ServoKeyframeList() {}
+
+ void DropAllRules()
+ {
+ for (css::Rule* rule : mRules) {
+ if (rule) {
+ rule->SetStyleSheet(nullptr);
+ rule->SetParentRule(nullptr);
+ }
+ }
+ mRules.Clear();
+ mRawRule = nullptr;
+ }
+
+ // may be nullptr when the style sheet drops the reference to us.
+ ServoStyleSheet* mStyleSheet = nullptr;
+ ServoKeyframesRule* mParentRule = nullptr;
+ RefPtr<RawServoKeyframesRule> mRawRule;
+ nsCOMArray<css::Rule> mRules;
+};
+
+// QueryInterface implementation for ServoKeyframeList
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(ServoKeyframeList)
+NS_INTERFACE_MAP_END_INHERITING(dom::CSSRuleList)
+
+NS_IMPL_ADDREF_INHERITED(ServoKeyframeList, dom::CSSRuleList)
+NS_IMPL_RELEASE_INHERITED(ServoKeyframeList, dom::CSSRuleList)
+
+NS_IMPL_CYCLE_COLLECTION_CLASS(ServoKeyframeList)
+
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ServoKeyframeList)
+ tmp->DropAllRules();
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END_INHERITED(dom::CSSRuleList)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(ServoKeyframeList,
+ dom::CSSRuleList)
+ for (css::Rule* rule : tmp->mRules) {
+ if (rule) {
+ NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mRules[i]");
+ cb.NoteXPCOMChild(rule);
+ }
+ }
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+// -------------------------------------------
+// ServoKeyframesRule
+//
+
+ServoKeyframesRule::ServoKeyframesRule(RefPtr<RawServoKeyframesRule> aRawRule,
+ uint32_t aLine, uint32_t aColumn)
+ // Although this class inherits from GroupRule, we don't want to use
+ // it at all, so it is fine to call the constructor for Gecko. We can
+ // make CSSKeyframesRule inherit from Rule directly once we can get
+ // rid of nsCSSKeyframeRule.
+ : dom::CSSKeyframesRule(aLine, aColumn)
+ , mRawRule(Move(aRawRule))
+{
+}
+
+ServoKeyframesRule::~ServoKeyframesRule()
+{
+}
+
+NS_IMPL_ADDREF_INHERITED(ServoKeyframesRule, dom::CSSKeyframesRule)
+NS_IMPL_RELEASE_INHERITED(ServoKeyframesRule, dom::CSSKeyframesRule)
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(ServoKeyframesRule)
+NS_INTERFACE_MAP_END_INHERITING(dom::CSSKeyframesRule)
+
+NS_IMPL_CYCLE_COLLECTION_CLASS(ServoKeyframesRule)
+
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(ServoKeyframesRule,
+ dom::CSSKeyframesRule)
+ if (tmp->mKeyframeList) {
+ tmp->mKeyframeList->DropReference();
+ tmp->mKeyframeList = nullptr;
+ }
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(ServoKeyframesRule, Rule)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mKeyframeList)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+/* virtual */ bool
+ServoKeyframesRule::IsCCLeaf() const
+{
+ // If we don't have rule list constructed, we are a leaf.
+ return Rule::IsCCLeaf() && !mKeyframeList;
+}
+
+/* virtual */ already_AddRefed<css::Rule>
+ServoKeyframesRule::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 ServoKeyframesRule");
+ return nullptr;
+}
+
+#ifdef DEBUG
+/* virtual */ void
+ServoKeyframesRule::List(FILE* out, int32_t aIndent) const
+{
+ nsAutoCString str;
+ for (int32_t i = 0; i < aIndent; i++) {
+ str.AppendLiteral(" ");
+ }
+ Servo_KeyframesRule_Debug(mRawRule, &str);
+ fprintf_stderr(out, "%s\n", str.get());
+}
+#endif
+
+/* virtual */ void
+ServoKeyframesRule::SetStyleSheet(StyleSheet* aSheet)
+{
+ if (mKeyframeList) {
+ mKeyframeList->SetStyleSheet(aSheet ? aSheet->AsServo() : nullptr);
+ }
+ dom::CSSKeyframesRule::SetStyleSheet(aSheet);
+}
+
+static const uint32_t kRuleNotFound = std::numeric_limits<uint32_t>::max();
+
+uint32_t
+ServoKeyframesRule::FindRuleIndexForKey(const nsAString& aKey)
+{
+ NS_ConvertUTF16toUTF8 key(aKey);
+ return Servo_KeyframesRule_FindRule(mRawRule, &key);
+}
+
+template<typename Func>
+void
+ServoKeyframesRule::UpdateRule(Func aCallback)
+{
+ nsIDocument* doc = GetDocument();
+ MOZ_AUTO_DOC_UPDATE(doc, UPDATE_STYLE, true);
+
+ aCallback();
+
+ if (StyleSheet* sheet = GetStyleSheet()) {
+ // FIXME sheet->AsGecko()->SetModifiedByChildRule();
+ if (doc) {
+ doc->StyleRuleChanged(sheet, this);
+ }
+ }
+}
+
+NS_IMETHODIMP
+ServoKeyframesRule::GetName(nsAString& aName)
+{
+ nsIAtom* name = Servo_KeyframesRule_GetName(mRawRule);
+ aName = nsDependentAtomString(name);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+ServoKeyframesRule::SetName(const nsAString& aName)
+{
+ nsCOMPtr<nsIAtom> name = NS_Atomize(aName);
+ nsIAtom* oldName = Servo_KeyframesRule_GetName(mRawRule);
+ if (name == oldName) {
+ return NS_OK;
+ }
+
+ UpdateRule([this, &name]() {
+ Servo_KeyframesRule_SetName(mRawRule, name.forget().take());
+ });
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+ServoKeyframesRule::AppendRule(const nsAString& aRule)
+{
+ StyleSheet* sheet = GetStyleSheet();
+ if (!sheet) {
+ // We cannot parse the rule if we don't have a stylesheet.
+ return NS_OK;
+ }
+
+ NS_ConvertUTF16toUTF8 rule(aRule);
+ UpdateRule([this, sheet, &rule]() {
+ if (Servo_KeyframesRule_AppendRule(mRawRule, sheet->AsServo()->RawSheet(),
+ &rule)) {
+ if (mKeyframeList) {
+ mKeyframeList->AppendRule();
+ }
+ }
+ });
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+ServoKeyframesRule::DeleteRule(const nsAString& aKey)
+{
+ auto index = FindRuleIndexForKey(aKey);
+ if (index == kRuleNotFound) {
+ return NS_OK;
+ }
+
+ UpdateRule([this, index]() {
+ Servo_KeyframesRule_DeleteRule(mRawRule, index);
+ if (mKeyframeList) {
+ mKeyframeList->RemoveRule(index);
+ }
+ });
+ return NS_OK;
+}
+
+/* virtual */ void
+ServoKeyframesRule::GetCssTextImpl(nsAString& aCssText) const
+{
+ Servo_KeyframesRule_GetCssText(mRawRule, &aCssText);
+}
+
+/* virtual */ dom::CSSRuleList*
+ServoKeyframesRule::CssRules()
+{
+ if (!mKeyframeList) {
+ mKeyframeList = new ServoKeyframeList(do_AddRef(mRawRule));
+ mKeyframeList->SetParentRule(this);
+ if (StyleSheet* sheet = GetStyleSheet()) {
+ mKeyframeList->SetStyleSheet(sheet->AsServo());
+ }
+ }
+ return mKeyframeList;
+}
+
+/* virtual */ dom::CSSKeyframeRule*
+ServoKeyframesRule::FindRule(const nsAString& aKey)
+{
+ auto index = FindRuleIndexForKey(aKey);
+ if (index != kRuleNotFound) {
+ // Construct mKeyframeList but ignore the result.
+ CssRules();
+ return mKeyframeList->GetRule(index);
+ }
+ return nullptr;
+}
+
+/* virtual */ size_t
+ServoKeyframesRule::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
+{
+ size_t n = aMallocSizeOf(this);
+ n += GroupRule::SizeOfExcludingThis(aMallocSizeOf);
+ if (mKeyframeList) {
+ n += mKeyframeList->SizeOfIncludingThis(aMallocSizeOf);
+ }
+ return n;
+}
+
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/layout/style/ServoKeyframesRule.h
@@ -0,0 +1,62 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* 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/. */
+
+#ifndef mozilla_ServoKeyframesRule_h
+#define mozilla_ServoKeyframesRule_h
+
+#include "mozilla/dom/CSSKeyframesRule.h"
+#include "mozilla/ServoBindingTypes.h"
+
+namespace mozilla {
+
+class ServoKeyframeList;
+
+class ServoKeyframesRule final : public dom::CSSKeyframesRule
+{
+public:
+ ServoKeyframesRule(RefPtr<RawServoKeyframesRule> aRawRule,
+ uint32_t aLine, uint32_t aColumn);
+
+ NS_DECL_ISUPPORTS_INHERITED
+ NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(ServoKeyframesRule,
+ dom::CSSKeyframesRule)
+ bool IsCCLeaf() const final;
+
+ already_AddRefed<css::Rule> Clone() const final;
+#ifdef DEBUG
+ void List(FILE* out = stdout, int32_t aIndent = 0) const final;
+#endif
+ void SetStyleSheet(StyleSheet* aSheet) final;
+
+ // nsIDOMCSSKeyframesRule interface
+ NS_IMETHOD GetName(nsAString& aName) final;
+ NS_IMETHOD SetName(const nsAString& aName) final;
+ NS_IMETHOD AppendRule(const nsAString& aRule) final;
+ NS_IMETHOD DeleteRule(const nsAString& aKey) final;
+ using nsIDOMCSSKeyframesRule::FindRule;
+
+ // WebIDL interface
+ void GetCssTextImpl(nsAString& aCssText) const final;
+ dom::CSSRuleList* CssRules() final;
+ dom::CSSKeyframeRule* FindRule(const nsAString& aKey) final;
+
+ size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const final;
+
+private:
+ uint32_t FindRuleIndexForKey(const nsAString& aKey);
+
+ template<typename Func>
+ void UpdateRule(Func aCallback);
+
+ virtual ~ServoKeyframesRule();
+
+ RefPtr<RawServoKeyframesRule> mRawRule;
+ RefPtr<ServoKeyframeList> mKeyframeList; // lazily constructed
+};
+
+} // namespace mozilla
+
+#endif // mozilla_ServoKeyframesRule_h
--- a/layout/style/moz.build
+++ b/layout/style/moz.build
@@ -102,16 +102,18 @@ EXPORTS.mozilla += [
'ServoBindingList.h',
'ServoBindings.h',
'ServoBindingTypes.h',
'ServoCSSRuleList.h',
'ServoDeclarationBlock.h',
'ServoDocumentRule.h',
'ServoElementSnapshot.h',
'ServoElementSnapshotTable.h',
+ 'ServoKeyframeRule.h',
+ 'ServoKeyframesRule.h',
'ServoMediaList.h',
'ServoMediaRule.h',
'ServoNamespaceRule.h',
'ServoPageRule.h',
'ServoPropPrefList.h',
'ServoSpecifiedValues.h',
'ServoStyleRule.h',
'ServoStyleSet.h',
@@ -234,16 +236,18 @@ UNIFIED_SOURCES += [
'PreloadedStyleSheet.cpp',
'RuleNodeCacheConditions.cpp',
'RuleProcessorCache.cpp',
'ServoBindings.cpp',
'ServoCSSRuleList.cpp',
'ServoDeclarationBlock.cpp',
'ServoDocumentRule.cpp',
'ServoElementSnapshot.cpp',
+ 'ServoKeyframeRule.cpp',
+ 'ServoKeyframesRule.cpp',
'ServoMediaList.cpp',
'ServoMediaRule.cpp',
'ServoNamespaceRule.cpp',
'ServoPageRule.cpp',
'ServoSpecifiedValues.cpp',
'ServoStyleRule.cpp',
'ServoStyleSet.cpp',
'ServoStyleSheet.cpp',