CSSKeyframeRule.cpp (6307B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "mozilla/dom/CSSKeyframeRule.h" 8 9 #include "mozilla/DeclarationBlock.h" 10 #include "mozilla/dom/CSSKeyframeRuleBinding.h" 11 #include "nsDOMCSSDeclaration.h" 12 13 namespace mozilla::dom { 14 15 // ------------------------------------------- 16 // CSSKeyframeDeclaration 17 // 18 19 class CSSKeyframeDeclaration final : public nsDOMCSSDeclaration { 20 public: 21 explicit CSSKeyframeDeclaration(CSSKeyframeRule* aRule) : mRule(aRule) { 22 mDecls = 23 new DeclarationBlock(Servo_Keyframe_GetStyle(aRule->Raw()).Consume()); 24 mDecls->SetOwningRule(aRule); 25 } 26 27 NS_DECL_CYCLE_COLLECTING_ISUPPORTS 28 NS_DECL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS_AMBIGUOUS(CSSKeyframeDeclaration, 29 nsICSSDeclaration) 30 31 css::Rule* GetParentRule() final { return mRule; } 32 33 void DropReference() { 34 mRule = nullptr; 35 mDecls->SetOwningRule(nullptr); 36 } 37 38 DeclarationBlock* GetOrCreateCSSDeclaration( 39 Operation aOperation, DeclarationBlock** aCreated) final { 40 if (aOperation != Operation::Read && mRule) { 41 if (StyleSheet* sheet = mRule->GetStyleSheet()) { 42 sheet->WillDirty(); 43 } 44 } 45 return mDecls; 46 } 47 nsresult SetCSSDeclaration(DeclarationBlock* aDecls, 48 MutationClosureData* aClosureData) final { 49 if (!mRule) { 50 return NS_OK; 51 } 52 mRule->UpdateRule([this, aDecls]() { 53 if (mDecls != aDecls) { 54 mDecls->SetOwningRule(nullptr); 55 mDecls = aDecls; 56 mDecls->SetOwningRule(mRule); 57 Servo_Keyframe_SetStyle(mRule->Raw(), mDecls->Raw()); 58 } 59 }); 60 return NS_OK; 61 } 62 ParsingEnvironment GetParsingEnvironment( 63 nsIPrincipal* aSubjectPrincipal) const final { 64 return GetParsingEnvironmentForRule(mRule, StyleCssRuleType::Keyframe); 65 } 66 67 nsINode* GetAssociatedNode() const final { 68 return mRule ? mRule->GetAssociatedDocumentOrShadowRoot() : nullptr; 69 } 70 71 nsISupports* GetParentObject() const final { 72 return mRule ? mRule->GetParentObject() : nullptr; 73 } 74 75 size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const { 76 size_t n = aMallocSizeOf(this); 77 // TODO we may want to add size of mDecls as well 78 return n; 79 } 80 81 void SetRawAfterClone(StyleLockedKeyframe* aKeyframe) { 82 mDecls->SetOwningRule(nullptr); 83 mDecls = new DeclarationBlock(Servo_Keyframe_GetStyle(aKeyframe).Consume()); 84 mDecls->SetOwningRule(mRule); 85 } 86 87 private: 88 virtual ~CSSKeyframeDeclaration() { 89 MOZ_ASSERT(!mRule, "Backpointer should have been cleared"); 90 } 91 92 CSSKeyframeRule* mRule; 93 RefPtr<DeclarationBlock> mDecls; 94 }; 95 96 NS_IMPL_CYCLE_COLLECTING_ADDREF(CSSKeyframeDeclaration) 97 NS_IMPL_CYCLE_COLLECTING_RELEASE(CSSKeyframeDeclaration) 98 99 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(CSSKeyframeDeclaration) 100 101 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(CSSKeyframeDeclaration) 102 NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY 103 NS_INTERFACE_MAP_END_INHERITING(nsDOMCSSDeclaration) 104 105 // ------------------------------------------- 106 // CSSKeyframeRule 107 // 108 109 CSSKeyframeRule::CSSKeyframeRule(already_AddRefed<StyleLockedKeyframe> aRaw, 110 StyleSheet* aSheet, css::Rule* aParentRule, 111 uint32_t aLine, uint32_t aColumn) 112 : css::Rule(aSheet, aParentRule, aLine, aColumn), mRaw(aRaw) {} 113 114 CSSKeyframeRule::~CSSKeyframeRule() { 115 if (mDeclaration) { 116 mDeclaration->DropReference(); 117 } 118 } 119 120 NS_IMPL_ADDREF_INHERITED(CSSKeyframeRule, css::Rule) 121 NS_IMPL_RELEASE_INHERITED(CSSKeyframeRule, css::Rule) 122 123 // QueryInterface implementation for nsCSSKeyframeRule 124 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(CSSKeyframeRule) 125 NS_INTERFACE_MAP_END_INHERITING(css::Rule) 126 127 NS_IMPL_CYCLE_COLLECTION_CLASS(CSSKeyframeRule) 128 129 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(CSSKeyframeRule, css::Rule) 130 if (tmp->mDeclaration) { 131 tmp->mDeclaration->DropReference(); 132 tmp->mDeclaration = nullptr; 133 } 134 NS_IMPL_CYCLE_COLLECTION_UNLINK_END 135 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(CSSKeyframeRule, css::Rule) 136 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDeclaration) 137 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END 138 139 bool CSSKeyframeRule::IsCCLeaf() const { 140 return Rule::IsCCLeaf() && !mDeclaration; 141 } 142 143 StyleCssRuleType CSSKeyframeRule::Type() const { 144 return StyleCssRuleType::Keyframe; 145 } 146 147 void CSSKeyframeRule::SetRawAfterClone(RefPtr<StyleLockedKeyframe> aRaw) { 148 mRaw = std::move(aRaw); 149 150 if (mDeclaration) { 151 mDeclaration->SetRawAfterClone(mRaw); 152 } 153 } 154 155 #ifdef DEBUG 156 /* virtual */ 157 void CSSKeyframeRule::List(FILE* out, int32_t aIndent) const { 158 nsAutoCString str; 159 for (int32_t i = 0; i < aIndent; i++) { 160 str.AppendLiteral(" "); 161 } 162 Servo_Keyframe_Debug(mRaw, &str); 163 fprintf_stderr(out, "%s\n", str.get()); 164 } 165 #endif 166 167 template <typename Func> 168 void CSSKeyframeRule::UpdateRule(Func aCallback) { 169 if (IsReadOnly()) { 170 return; 171 } 172 173 StyleSheet* sheet = GetStyleSheet(); 174 if (sheet) { 175 sheet->WillDirty(); 176 } 177 178 aCallback(); 179 180 if (sheet) { 181 sheet->RuleChanged(this, StyleRuleChangeKind::Generic); 182 } 183 } 184 185 void CSSKeyframeRule::GetKeyText(nsACString& aKeyText) { 186 Servo_Keyframe_GetKeyText(mRaw, &aKeyText); 187 } 188 189 void CSSKeyframeRule::SetKeyText(const nsACString& aKeyText) { 190 UpdateRule( 191 [this, &aKeyText]() { Servo_Keyframe_SetKeyText(mRaw, &aKeyText); }); 192 } 193 194 void CSSKeyframeRule::GetCssText(nsACString& aCssText) const { 195 Servo_Keyframe_GetCssText(mRaw, &aCssText); 196 } 197 198 nsDOMCSSDeclaration* CSSKeyframeRule::Style() { 199 if (!mDeclaration) { 200 mDeclaration = new CSSKeyframeDeclaration(this); 201 } 202 return mDeclaration; 203 } 204 205 size_t CSSKeyframeRule::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const { 206 size_t n = aMallocSizeOf(this); 207 if (mDeclaration) { 208 n += mDeclaration->SizeOfIncludingThis(aMallocSizeOf); 209 } 210 return n; 211 } 212 213 /* virtual */ 214 JSObject* CSSKeyframeRule::WrapObject(JSContext* aCx, 215 JS::Handle<JSObject*> aGivenProto) { 216 return CSSKeyframeRule_Binding::Wrap(aCx, this, aGivenProto); 217 } 218 219 } // namespace mozilla::dom