/src/mozilla-central/dom/animation/CSSPseudoElement.cpp
Line | Count | Source (jump to first uncovered line) |
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/CSSPseudoElement.h" |
8 | | #include "mozilla/dom/CSSPseudoElementBinding.h" |
9 | | #include "mozilla/dom/Element.h" |
10 | | #include "mozilla/dom/KeyframeEffectBinding.h" |
11 | | #include "mozilla/AnimationComparator.h" |
12 | | |
13 | | namespace mozilla { |
14 | | namespace dom { |
15 | | |
16 | | NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(CSSPseudoElement, mParentElement) |
17 | | |
18 | | NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(CSSPseudoElement, AddRef) |
19 | | NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(CSSPseudoElement, Release) |
20 | | |
21 | | CSSPseudoElement::CSSPseudoElement(Element* aElement, |
22 | | CSSPseudoElementType aType) |
23 | | : mParentElement(aElement) |
24 | | , mPseudoType(aType) |
25 | 0 | { |
26 | 0 | MOZ_ASSERT(aElement); |
27 | 0 | MOZ_ASSERT(aType == CSSPseudoElementType::after || |
28 | 0 | aType == CSSPseudoElementType::before, |
29 | 0 | "Unexpected Pseudo Type"); |
30 | 0 | } |
31 | | |
32 | | CSSPseudoElement::~CSSPseudoElement() |
33 | 0 | { |
34 | 0 | // Element might have been unlinked already, so we have to do null check. |
35 | 0 | if (mParentElement) { |
36 | 0 | mParentElement->DeleteProperty( |
37 | 0 | GetCSSPseudoElementPropertyAtom(mPseudoType)); |
38 | 0 | } |
39 | 0 | } |
40 | | |
41 | | ParentObject |
42 | | CSSPseudoElement::GetParentObject() const |
43 | 0 | { |
44 | 0 | return mParentElement->GetParentObject(); |
45 | 0 | } |
46 | | |
47 | | JSObject* |
48 | | CSSPseudoElement::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) |
49 | 0 | { |
50 | 0 | return CSSPseudoElement_Binding::Wrap(aCx, this, aGivenProto); |
51 | 0 | } |
52 | | |
53 | | void |
54 | | CSSPseudoElement::GetAnimations(const AnimationFilter& filter, |
55 | | nsTArray<RefPtr<Animation>>& aRetVal) |
56 | 0 | { |
57 | 0 | nsIDocument* doc = mParentElement->GetComposedDoc(); |
58 | 0 | if (doc) { |
59 | 0 | // We don't need to explicitly flush throttled animations here, since |
60 | 0 | // updating the animation style of (pseudo-)elements will never affect the |
61 | 0 | // set of running animations and it's only the set of running animations |
62 | 0 | // that is important here. |
63 | 0 | doc->FlushPendingNotifications( |
64 | 0 | ChangesToFlush(FlushType::Style, false /* flush animations */)); |
65 | 0 | } |
66 | 0 |
|
67 | 0 | Element::GetAnimationsUnsorted(mParentElement, mPseudoType, aRetVal); |
68 | 0 | aRetVal.Sort(AnimationPtrComparator<RefPtr<Animation>>()); |
69 | 0 | } |
70 | | |
71 | | already_AddRefed<Animation> |
72 | | CSSPseudoElement::Animate( |
73 | | JSContext* aContext, |
74 | | JS::Handle<JSObject*> aKeyframes, |
75 | | const UnrestrictedDoubleOrKeyframeAnimationOptions& aOptions, |
76 | | ErrorResult& aError) |
77 | 0 | { |
78 | 0 | Nullable<ElementOrCSSPseudoElement> target; |
79 | 0 | target.SetValue().SetAsCSSPseudoElement() = this; |
80 | 0 | return Element::Animate(target, aContext, aKeyframes, aOptions, aError); |
81 | 0 | } |
82 | | |
83 | | /* static */ already_AddRefed<CSSPseudoElement> |
84 | | CSSPseudoElement::GetCSSPseudoElement(Element* aElement, |
85 | | CSSPseudoElementType aType) |
86 | 0 | { |
87 | 0 | if (!aElement) { |
88 | 0 | return nullptr; |
89 | 0 | } |
90 | 0 | |
91 | 0 | nsAtom* propName = CSSPseudoElement::GetCSSPseudoElementPropertyAtom(aType); |
92 | 0 | RefPtr<CSSPseudoElement> pseudo = |
93 | 0 | static_cast<CSSPseudoElement*>(aElement->GetProperty(propName)); |
94 | 0 | if (pseudo) { |
95 | 0 | return pseudo.forget(); |
96 | 0 | } |
97 | 0 | |
98 | 0 | // CSSPseudoElement is a purely external interface created on-demand, and |
99 | 0 | // when all references from script to the pseudo are dropped, we can drop the |
100 | 0 | // CSSPseudoElement object, so use a non-owning reference from Element to |
101 | 0 | // CSSPseudoElement. |
102 | 0 | pseudo = new CSSPseudoElement(aElement, aType); |
103 | 0 | nsresult rv = aElement->SetProperty(propName, pseudo, nullptr, true); |
104 | 0 | if (NS_FAILED(rv)) { |
105 | 0 | NS_WARNING("SetProperty failed"); |
106 | 0 | return nullptr; |
107 | 0 | } |
108 | 0 | return pseudo.forget(); |
109 | 0 | } |
110 | | |
111 | | /* static */ nsAtom* |
112 | | CSSPseudoElement::GetCSSPseudoElementPropertyAtom(CSSPseudoElementType aType) |
113 | 0 | { |
114 | 0 | switch (aType) { |
115 | 0 | case CSSPseudoElementType::before: |
116 | 0 | return nsGkAtoms::cssPseudoElementBeforeProperty; |
117 | 0 |
|
118 | 0 | case CSSPseudoElementType::after: |
119 | 0 | return nsGkAtoms::cssPseudoElementAfterProperty; |
120 | 0 |
|
121 | 0 | default: |
122 | 0 | MOZ_ASSERT_UNREACHABLE("Should not try to get CSSPseudoElement " |
123 | 0 | "other than ::before or ::after"); |
124 | 0 | return nullptr; |
125 | 0 | } |
126 | 0 | } |
127 | | |
128 | | } // namespace dom |
129 | | } // namespace mozilla |