Line data Source code
1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* vim:set ts=2 sw=2 sts=2 et cindent: */
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/AnimationComparator.h"
11 :
12 : namespace mozilla {
13 : namespace dom {
14 :
15 0 : NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(CSSPseudoElement, mParentElement)
16 :
17 0 : NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(CSSPseudoElement, AddRef)
18 0 : NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(CSSPseudoElement, Release)
19 :
20 0 : CSSPseudoElement::CSSPseudoElement(Element* aElement,
21 0 : CSSPseudoElementType aType)
22 : : mParentElement(aElement)
23 0 : , mPseudoType(aType)
24 : {
25 0 : MOZ_ASSERT(aElement);
26 0 : MOZ_ASSERT(aType == CSSPseudoElementType::after ||
27 : aType == CSSPseudoElementType::before,
28 : "Unexpected Pseudo Type");
29 0 : }
30 :
31 0 : CSSPseudoElement::~CSSPseudoElement()
32 : {
33 : // Element might have been unlinked already, so we have to do null check.
34 0 : if (mParentElement) {
35 0 : mParentElement->DeleteProperty(
36 0 : GetCSSPseudoElementPropertyAtom(mPseudoType));
37 : }
38 0 : }
39 :
40 : ParentObject
41 0 : CSSPseudoElement::GetParentObject() const
42 : {
43 0 : return mParentElement->GetParentObject();
44 : }
45 :
46 : JSObject*
47 0 : CSSPseudoElement::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
48 : {
49 0 : return CSSPseudoElementBinding::Wrap(aCx, this, aGivenProto);
50 : }
51 :
52 : void
53 0 : CSSPseudoElement::GetAnimations(const AnimationFilter& filter,
54 : nsTArray<RefPtr<Animation>>& aRetVal)
55 : {
56 0 : nsIDocument* doc = mParentElement->GetComposedDoc();
57 0 : if (doc) {
58 0 : doc->FlushPendingNotifications(FlushType::Style);
59 : }
60 :
61 0 : Element::GetAnimationsUnsorted(mParentElement, mPseudoType, aRetVal);
62 0 : aRetVal.Sort(AnimationPtrComparator<RefPtr<Animation>>());
63 0 : }
64 :
65 : already_AddRefed<Animation>
66 0 : CSSPseudoElement::Animate(
67 : JSContext* aContext,
68 : JS::Handle<JSObject*> aKeyframes,
69 : const UnrestrictedDoubleOrKeyframeAnimationOptions& aOptions,
70 : ErrorResult& aError)
71 : {
72 0 : Nullable<ElementOrCSSPseudoElement> target;
73 0 : target.SetValue().SetAsCSSPseudoElement() = this;
74 0 : return Element::Animate(target, aContext, aKeyframes, aOptions, aError);
75 : }
76 :
77 : /* static */ already_AddRefed<CSSPseudoElement>
78 0 : CSSPseudoElement::GetCSSPseudoElement(Element* aElement,
79 : CSSPseudoElementType aType)
80 : {
81 0 : if (!aElement) {
82 0 : return nullptr;
83 : }
84 :
85 0 : nsIAtom* propName = CSSPseudoElement::GetCSSPseudoElementPropertyAtom(aType);
86 : RefPtr<CSSPseudoElement> pseudo =
87 0 : static_cast<CSSPseudoElement*>(aElement->GetProperty(propName));
88 0 : if (pseudo) {
89 0 : return pseudo.forget();
90 : }
91 :
92 : // CSSPseudoElement is a purely external interface created on-demand, and
93 : // when all references from script to the pseudo are dropped, we can drop the
94 : // CSSPseudoElement object, so use a non-owning reference from Element to
95 : // CSSPseudoElement.
96 0 : pseudo = new CSSPseudoElement(aElement, aType);
97 0 : nsresult rv = aElement->SetProperty(propName, pseudo, nullptr, true);
98 0 : if (NS_FAILED(rv)) {
99 0 : NS_WARNING("SetProperty failed");
100 0 : return nullptr;
101 : }
102 0 : return pseudo.forget();
103 : }
104 :
105 : /* static */ nsIAtom*
106 0 : CSSPseudoElement::GetCSSPseudoElementPropertyAtom(CSSPseudoElementType aType)
107 : {
108 0 : switch (aType) {
109 : case CSSPseudoElementType::before:
110 0 : return nsGkAtoms::cssPseudoElementBeforeProperty;
111 :
112 : case CSSPseudoElementType::after:
113 0 : return nsGkAtoms::cssPseudoElementAfterProperty;
114 :
115 : default:
116 0 : NS_NOTREACHED("Should not try to get CSSPseudoElement "
117 : "other than ::before or ::after");
118 0 : return nullptr;
119 : }
120 : }
121 :
122 : } // namespace dom
123 : } // namespace mozilla
|