diff --git a/dom/animation/Animation.cpp b/dom/animation/Animation.cpp index a693117ccf..e479be06ea 100644 --- a/dom/animation/Animation.cpp +++ b/dom/animation/Animation.cpp @@ -11,11 +11,13 @@ #include "mozilla/AutoRestore.h" #include "mozilla/AsyncEventDispatcher.h" // For AsyncEventDispatcher #include "mozilla/Maybe.h" // For Maybe +#include "nsAnimationManager.h" // For CSSAnimation #include "nsDOMMutationObserver.h" // For nsAutoAnimationMutationBatch #include "nsIDocument.h" // For nsIDocument #include "nsIPresShell.h" // For nsIPresShell #include "nsLayoutUtils.h" // For PostRestyleEvent (remove after bug 1073336) #include "nsThreadUtils.h" // For nsRunnableMethod and nsRevocableEventPtr +#include "nsTransitionManager.h" // For CSSTransition #include "PendingAnimationTracker.h" // For PendingAnimationTracker namespace mozilla { @@ -693,14 +695,58 @@ Animation::UpdateRelevance() bool Animation::HasLowerCompositeOrderThan(const Animation& aOther) const { - // Due to the way subclasses of this repurpose the mAnimationIndex to - // implement their own brand of composite ordering it is possible for - // two animations to have an identical mAnimationIndex member. - // However, these subclasses override this method so we shouldn't see - // identical animation indices here. - MOZ_ASSERT(mAnimationIndex != aOther.mAnimationIndex || &aOther == this, + // 0. Object-equality case + if (&aOther == this) { + return false; + } + + // 1. CSS Transitions sort lowest + { + auto asCSSTransitionForSorting = + [] (const Animation& anim) -> const CSSTransition* + { + const CSSTransition* transition = anim.AsCSSTransition(); + return transition && transition->IsTiedToMarkup() ? + transition : + nullptr; + }; + auto thisTransition = asCSSTransitionForSorting(*this); + auto otherTransition = asCSSTransitionForSorting(aOther); + if (thisTransition && otherTransition) { + return thisTransition->HasLowerCompositeOrderThan(*otherTransition); + } + if (thisTransition || otherTransition) { + return thisTransition; + } + } + + // 2. CSS Animations sort next + { + auto asCSSAnimationForSorting = + [] (const Animation& anim) -> const CSSAnimation* + { + const CSSAnimation* animation = anim.AsCSSAnimation(); + return animation && animation->IsTiedToMarkup() ? animation : nullptr; + }; + auto thisAnimation = asCSSAnimationForSorting(*this); + auto otherAnimation = asCSSAnimationForSorting(aOther); + if (thisAnimation && otherAnimation) { + return thisAnimation->HasLowerCompositeOrderThan(*otherAnimation); + } + if (thisAnimation || otherAnimation) { + return thisAnimation; + } + } + + // Subclasses of Animation repurpose mAnimationIndex to implement their + // own brand of composite ordering. However, by this point we should have + // handled any such custom composite ordering so we should now have unique + // animation indices. + MOZ_ASSERT(mAnimationIndex != aOther.mAnimationIndex, "Animation indices should be unique"); + // 3. Finally, generic animations sort by their position in the global + // animation array. return mAnimationIndex < aOther.mAnimationIndex; } @@ -750,7 +796,6 @@ Animation::ComposeStyle(RefPtr& aStyleRule, // immediately before updating the style rule and then restore it immediately // afterwards. This is purely to prevent visual flicker. Other behavior // such as dispatching events continues to rely on the regular timeline time. - bool updatedHoldTime = false; AnimationPlayState playState = PlayState(); { AutoRestore> restoreHoldTime(mHoldTime); @@ -767,20 +812,12 @@ Animation::ComposeStyle(RefPtr& aStyleRule, if (!timeToUse.IsNull()) { mHoldTime.SetValue((timeToUse.Value() - mStartTime.Value()) .MultDouble(mPlaybackRate)); - // Push the change down to the effect - UpdateEffect(); - updatedHoldTime = true; } } mEffect->ComposeStyle(aStyleRule, aSetProperties); } - // Now that the hold time has been restored, update the effect - if (updatedHoldTime) { - UpdateEffect(); - } - MOZ_ASSERT(playState == PlayState(), "Play state should not change during the course of compositing"); mFinishedAtLastComposeStyle = (playState == AnimationPlayState::Finished); @@ -1070,7 +1107,7 @@ Animation::PostUpdate() } Element* targetElement; - nsCSSPseudoElements::Type targetPseudoType; + CSSPseudoElementType targetPseudoType; mEffect->GetTarget(targetElement, targetPseudoType); if (!targetElement) { return; diff --git a/dom/animation/Animation.h b/dom/animation/Animation.h index 1852bc8c4e..d6877fc93f 100644 --- a/dom/animation/Animation.h +++ b/dom/animation/Animation.h @@ -288,7 +288,7 @@ public: /** * Returns true if this Animation has a lower composite order than aOther. */ - virtual bool HasLowerCompositeOrderThan(const Animation& aOther) const; + bool HasLowerCompositeOrderThan(const Animation& aOther) const; /** * Returns the level at which the effect(s) associated with this Animation diff --git a/dom/animation/AnimationEffectTiming.cpp b/dom/animation/AnimationEffectTiming.cpp new file mode 100644 index 0000000000..d483d989e5 --- /dev/null +++ b/dom/animation/AnimationEffectTiming.cpp @@ -0,0 +1,22 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et cindent: */ +/* 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/dom/AnimationEffectTiming.h" + +#include "mozilla/dom/AnimatableBinding.h" +#include "mozilla/dom/AnimationEffectTimingBinding.h" + +namespace mozilla { +namespace dom { + +JSObject* +AnimationEffectTiming::WrapObject(JSContext* aCx, JS::Handle aGivenProto) +{ + return AnimationEffectTimingBinding::Wrap(aCx, this, aGivenProto); +} + +} // namespace dom +} // namespace mozilla diff --git a/dom/animation/AnimationEffectTiming.h b/dom/animation/AnimationEffectTiming.h new file mode 100644 index 0000000000..94f7f1c387 --- /dev/null +++ b/dom/animation/AnimationEffectTiming.h @@ -0,0 +1,27 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et cindent: */ +/* 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_dom_AnimationEffectTiming_h +#define mozilla_dom_AnimationEffectTiming_h + +#include "mozilla/dom/AnimationEffectTimingReadOnly.h" + +namespace mozilla { +namespace dom { + +class AnimationEffectTiming : public AnimationEffectTimingReadOnly +{ +public: + explicit AnimationEffectTiming(const TimingParams& aTiming) + : AnimationEffectTimingReadOnly(aTiming) { } + + JSObject* WrapObject(JSContext* aCx, JS::Handle aGivenProto) override; +}; + +} // namespace dom +} // namespace mozilla + +#endif // mozilla_dom_AnimationEffectTiming_h diff --git a/dom/animation/CSSPseudoElement.cpp b/dom/animation/CSSPseudoElement.cpp index 6bad5d3447..791990f0ee 100644 --- a/dom/animation/CSSPseudoElement.cpp +++ b/dom/animation/CSSPseudoElement.cpp @@ -17,13 +17,13 @@ NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(CSSPseudoElement, AddRef) NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(CSSPseudoElement, Release) CSSPseudoElement::CSSPseudoElement(Element* aElement, - nsCSSPseudoElements::Type aType) + CSSPseudoElementType aType) : mParentElement(aElement) , mPseudoType(aType) { MOZ_ASSERT(aElement); - MOZ_ASSERT(aType == nsCSSPseudoElements::ePseudo_after || - aType == nsCSSPseudoElements::ePseudo_before, + MOZ_ASSERT(aType == CSSPseudoElementType::after || + aType == CSSPseudoElementType::before, "Unexpected Pseudo Type"); } @@ -63,7 +63,7 @@ CSSPseudoElement::Animate( /* static */ already_AddRefed CSSPseudoElement::GetCSSPseudoElement(Element* aElement, - nsCSSPseudoElements::Type aType) + CSSPseudoElementType aType) { if (!aElement) { return nullptr; @@ -90,14 +90,13 @@ CSSPseudoElement::GetCSSPseudoElement(Element* aElement, } /* static */ nsIAtom* -CSSPseudoElement::GetCSSPseudoElementPropertyAtom( - nsCSSPseudoElements::Type aType) +CSSPseudoElement::GetCSSPseudoElementPropertyAtom(CSSPseudoElementType aType) { switch (aType) { - case nsCSSPseudoElements::ePseudo_before: + case CSSPseudoElementType::before: return nsGkAtoms::cssPseudoElementBeforeProperty; - case nsCSSPseudoElements::ePseudo_after: + case CSSPseudoElementType::after: return nsGkAtoms::cssPseudoElementAfterProperty; default: diff --git a/dom/animation/CSSPseudoElement.h b/dom/animation/CSSPseudoElement.h index be8b2d993a..f5c2a05145 100644 --- a/dom/animation/CSSPseudoElement.h +++ b/dom/animation/CSSPseudoElement.h @@ -40,7 +40,7 @@ public: virtual JSObject* WrapObject(JSContext* aCx, JS::Handle aGivenProto) override; - nsCSSPseudoElements::Type GetType() const { return mPseudoType; } + CSSPseudoElementType GetType() const { return mPseudoType; } void GetType(nsString& aRetVal) const { MOZ_ASSERT(nsCSSPseudoElements::GetPseudoAtom(mPseudoType), @@ -66,20 +66,19 @@ public: // pseudo-type on element, a new CSSPseudoElement will be created and stored // on the element. static already_AddRefed - GetCSSPseudoElement(Element* aElement, nsCSSPseudoElements::Type aType); + GetCSSPseudoElement(Element* aElement, CSSPseudoElementType aType); private: // Only ::before and ::after are supported. - CSSPseudoElement(Element* aElement, nsCSSPseudoElements::Type aType); + CSSPseudoElement(Element* aElement, CSSPseudoElementType aType); - static nsIAtom* - GetCSSPseudoElementPropertyAtom(nsCSSPseudoElements::Type aType); + static nsIAtom* GetCSSPseudoElementPropertyAtom(CSSPseudoElementType aType); // mParentElement needs to be an owning reference since if script is holding // on to the pseudo-element, it needs to continue to be able to refer to // the parent element. RefPtr mParentElement; - nsCSSPseudoElements::Type mPseudoType; + CSSPseudoElementType mPseudoType; }; } // namespace dom diff --git a/dom/animation/EffectCompositor.cpp b/dom/animation/EffectCompositor.cpp index 9bedf4f81f..4dcad3ef2b 100644 --- a/dom/animation/EffectCompositor.cpp +++ b/dom/animation/EffectCompositor.cpp @@ -16,9 +16,11 @@ #include "nsComputedDOMStyle.h" // nsComputedDOMStyle::GetPresShellForContent #include "nsCSSPropertySet.h" #include "nsCSSProps.h" +#include "nsCSSPseudoElements.h" #include "nsIPresShell.h" #include "nsLayoutUtils.h" #include "nsRuleNode.h" // For nsRuleNode::ComputePropertiesOverridingAnimation +#include "nsRuleProcessorData.h" // For ElementRuleProcessorData etc. #include "nsTArray.h" #include "RestyleManager.h" @@ -79,7 +81,7 @@ FindAnimationsForCompositor(const nsIFrame* aFrame, // Those cases are probably not important but just to be safe, let's make // sure the cascade is up to date since if it *is* up to date, this is // basically a no-op. - Maybe> pseudoElement = + Maybe> pseudoElement = EffectCompositor::GetAnimationElementAndPseudoForFrame(aFrame); if (pseudoElement) { EffectCompositor::MaybeUpdateCascadeResults(pseudoElement->first(), @@ -130,7 +132,7 @@ FindAnimationsForCompositor(const nsIFrame* aFrame, void EffectCompositor::RequestRestyle(dom::Element* aElement, - nsCSSPseudoElements::Type aPseudoType, + CSSPseudoElementType aPseudoType, RestyleType aRestyleType, CascadeLevel aCascadeLevel) { @@ -142,9 +144,10 @@ EffectCompositor::RequestRestyle(dom::Element* aElement, auto& elementsToRestyle = mElementsToRestyle[aCascadeLevel]; PseudoElementHashKey key = { aElement, aPseudoType }; - if (aRestyleType == RestyleType::Throttled && - !elementsToRestyle.Contains(key)) { - elementsToRestyle.Put(key, false); + if (aRestyleType == RestyleType::Throttled) { + if (!elementsToRestyle.Contains(key)) { + elementsToRestyle.Put(key, false); + } mPresContext->Document()->SetNeedStyleFlush(); } else { // Get() returns 0 if the element is not found. It will also return @@ -169,7 +172,7 @@ EffectCompositor::RequestRestyle(dom::Element* aElement, void EffectCompositor::PostRestyleForAnimation(dom::Element* aElement, - nsCSSPseudoElements::Type aPseudoType, + CSSPseudoElementType aPseudoType, CascadeLevel aCascadeLevel) { if (!mPresContext) { @@ -210,8 +213,7 @@ EffectCompositor::PostRestyleForThrottledAnimations() void EffectCompositor::MaybeUpdateAnimationRule(dom::Element* aElement, - nsCSSPseudoElements::Type - aPseudoType, + CSSPseudoElementType aPseudoType, CascadeLevel aCascadeLevel) { // First update cascade results since that may cause some elements to @@ -233,33 +235,55 @@ EffectCompositor::MaybeUpdateAnimationRule(dom::Element* aElement, nsIStyleRule* EffectCompositor::GetAnimationRule(dom::Element* aElement, - nsCSSPseudoElements::Type aPseudoType, + CSSPseudoElementType aPseudoType, CascadeLevel aCascadeLevel) { + // NOTE: We need to be careful about early returns in this method where + // we *don't* update mElementsToRestyle. When we get a call to + // RequestRestyle that results in a call to PostRestyleForAnimation, we + // will set a bool flag in mElementsToRestyle indicating that we've + // called PostRestyleForAnimation so we don't need to call it again + // until that restyle happens. During that restyle, if we arrive here + // and *don't* update mElementsToRestyle we'll continue to skip calling + // PostRestyleForAnimation from RequestRestyle. + if (!mPresContext || !mPresContext->IsDynamic()) { // For print or print preview, ignore animations. return nullptr; } + if (mPresContext->RestyleManager()->SkipAnimationRules()) { + // We don't need to worry about updating mElementsToRestyle in this case + // since this is not the animation restyle we requested when we called + // PostRestyleForAnimation (see comment at start of this method). + return nullptr; + } + + MaybeUpdateAnimationRule(aElement, aPseudoType, aCascadeLevel); + +#ifdef DEBUG + { + auto& elementsToRestyle = mElementsToRestyle[aCascadeLevel]; + PseudoElementHashKey key = { aElement, aPseudoType }; + MOZ_ASSERT(!elementsToRestyle.Contains(key), + "Element should no longer require a restyle after its " + "animation rule has been updated"); + } +#endif + EffectSet* effectSet = EffectSet::GetEffectSet(aElement, aPseudoType); if (!effectSet) { return nullptr; } - if (mPresContext->RestyleManager()->SkipAnimationRules()) { - return nullptr; - } - - MaybeUpdateAnimationRule(aElement, aPseudoType, aCascadeLevel); - return effectSet->AnimationRule(aCascadeLevel); } /* static */ dom::Element* EffectCompositor::GetElementToRestyle(dom::Element* aElement, - nsCSSPseudoElements::Type aPseudoType) + CSSPseudoElementType aPseudoType) { - if (aPseudoType == nsCSSPseudoElements::ePseudo_NotPseudoElement) { + if (aPseudoType == CSSPseudoElementType::NotPseudo) { return aElement; } @@ -268,9 +292,9 @@ EffectCompositor::GetElementToRestyle(dom::Element* aElement, return nullptr; } nsIFrame* pseudoFrame; - if (aPseudoType == nsCSSPseudoElements::ePseudo_before) { + if (aPseudoType == CSSPseudoElementType::before) { pseudoFrame = nsLayoutUtils::GetBeforeFrame(primaryFrame); - } else if (aPseudoType == nsCSSPseudoElements::ePseudo_after) { + } else if (aPseudoType == CSSPseudoElementType::after) { pseudoFrame = nsLayoutUtils::GetAfterFrame(primaryFrame); } else { NS_NOTREACHED("Should not try to get the element to restyle for a pseudo " @@ -393,8 +417,7 @@ EffectCompositor::ClearIsRunningOnCompositor(const nsIFrame *aFrame, /* static */ void EffectCompositor::MaybeUpdateCascadeResults(Element* aElement, - nsCSSPseudoElements::Type - aPseudoType, + CSSPseudoElementType aPseudoType, nsStyleContext* aStyleContext) { EffectSet* effects = EffectSet::GetEffectSet(aElement, aPseudoType); @@ -409,8 +432,7 @@ EffectCompositor::MaybeUpdateCascadeResults(Element* aElement, /* static */ void EffectCompositor::MaybeUpdateCascadeResults(Element* aElement, - nsCSSPseudoElements::Type - aPseudoType) + CSSPseudoElementType aPseudoType) { nsStyleContext* styleContext = nullptr; { @@ -450,7 +472,7 @@ namespace { /* static */ void EffectCompositor::UpdateCascadeResults(Element* aElement, - nsCSSPseudoElements::Type aPseudoType, + CSSPseudoElementType aPseudoType, nsStyleContext* aStyleContext) { EffectSet* effects = EffectSet::GetEffectSet(aElement, aPseudoType); @@ -461,19 +483,18 @@ EffectCompositor::UpdateCascadeResults(Element* aElement, UpdateCascadeResults(*effects, aElement, aPseudoType, aStyleContext); } -/* static */ Maybe> +/* static */ Maybe> EffectCompositor::GetAnimationElementAndPseudoForFrame(const nsIFrame* aFrame) { // Always return the same object to benefit from return-value optimization. - Maybe> result; + Maybe> result; nsIContent* content = aFrame->GetContent(); if (!content) { return result; } - nsCSSPseudoElements::Type pseudoType = - nsCSSPseudoElements::ePseudo_NotPseudoElement; + CSSPseudoElementType pseudoType = CSSPseudoElementType::NotPseudo; if (aFrame->IsGeneratedContentFrame()) { nsIFrame* parent = aFrame->GetParent(); @@ -482,9 +503,9 @@ EffectCompositor::GetAnimationElementAndPseudoForFrame(const nsIFrame* aFrame) } nsIAtom* name = content->NodeInfo()->NameAtom(); if (name == nsGkAtoms::mozgeneratedcontentbefore) { - pseudoType = nsCSSPseudoElements::ePseudo_before; + pseudoType = CSSPseudoElementType::before; } else if (name == nsGkAtoms::mozgeneratedcontentafter) { - pseudoType = nsCSSPseudoElements::ePseudo_after; + pseudoType = CSSPseudoElementType::after; } else { return result; } @@ -492,6 +513,11 @@ EffectCompositor::GetAnimationElementAndPseudoForFrame(const nsIFrame* aFrame) if (!content) { return result; } + } else { + if (nsLayoutUtils::GetStyleFrame(content) != aFrame) { + // The effects associated with an element are for its primary frame. + return result; + } } if (!content->IsElement()) { @@ -505,7 +531,7 @@ EffectCompositor::GetAnimationElementAndPseudoForFrame(const nsIFrame* aFrame) /* static */ void EffectCompositor::ComposeAnimationRule(dom::Element* aElement, - nsCSSPseudoElements::Type aPseudoType, + CSSPseudoElementType aPseudoType, CascadeLevel aCascadeLevel, TimeStamp aRefreshTime) { @@ -542,6 +568,9 @@ EffectCompositor::ComposeAnimationRule(dom::Element* aElement, effect->GetAnimation()->ComposeStyle(animationRule, properties); } + MOZ_ASSERT(effects == EffectSet::GetEffectSet(aElement, aPseudoType), + "EffectSet should not change while composing style"); + effects->UpdateAnimationRuleRefreshTime(aCascadeLevel, aRefreshTime); } @@ -583,7 +612,7 @@ EffectCompositor::GetOverriddenProperties(nsStyleContext* aStyleContext, /* static */ void EffectCompositor::UpdateCascadeResults(EffectSet& aEffectSet, Element* aElement, - nsCSSPseudoElements::Type aPseudoType, + CSSPseudoElementType aPseudoType, nsStyleContext* aStyleContext) { MOZ_ASSERT(EffectSet::GetEffectSet(aElement, aPseudoType) == &aEffectSet, @@ -680,4 +709,110 @@ EffectCompositor::GetPresContext(Element* aElement) return shell->GetPresContext(); } +// --------------------------------------------------------- +// +// Nested class: AnimationStyleRuleProcessor +// +// --------------------------------------------------------- + +NS_IMPL_ISUPPORTS(EffectCompositor::AnimationStyleRuleProcessor, + nsIStyleRuleProcessor) + +nsRestyleHint +EffectCompositor::AnimationStyleRuleProcessor::HasStateDependentStyle( + StateRuleProcessorData* aData) +{ + return nsRestyleHint(0); +} + +nsRestyleHint +EffectCompositor::AnimationStyleRuleProcessor::HasStateDependentStyle( + PseudoElementStateRuleProcessorData* aData) +{ + return nsRestyleHint(0); +} + +bool +EffectCompositor::AnimationStyleRuleProcessor::HasDocumentStateDependentStyle( + StateRuleProcessorData* aData) +{ + return false; +} + +nsRestyleHint +EffectCompositor::AnimationStyleRuleProcessor::HasAttributeDependentStyle( + AttributeRuleProcessorData* aData, + RestyleHintData& aRestyleHintDataResult) +{ + return nsRestyleHint(0); +} + +bool +EffectCompositor::AnimationStyleRuleProcessor::MediumFeaturesChanged( + nsPresContext* aPresContext) +{ + return false; +} + +void +EffectCompositor::AnimationStyleRuleProcessor::RulesMatching( + ElementRuleProcessorData* aData) +{ + nsIStyleRule *rule = + mCompositor->GetAnimationRule(aData->mElement, + CSSPseudoElementType::NotPseudo, + mCascadeLevel); + if (rule) { + aData->mRuleWalker->Forward(rule); + aData->mRuleWalker->CurrentNode()->SetIsAnimationRule(); + } +} + +void +EffectCompositor::AnimationStyleRuleProcessor::RulesMatching( + PseudoElementRuleProcessorData* aData) +{ + if (aData->mPseudoType != CSSPseudoElementType::before && + aData->mPseudoType != CSSPseudoElementType::after) { + return; + } + + nsIStyleRule *rule = + mCompositor->GetAnimationRule(aData->mElement, + aData->mPseudoType, + mCascadeLevel); + if (rule) { + aData->mRuleWalker->Forward(rule); + aData->mRuleWalker->CurrentNode()->SetIsAnimationRule(); + } +} + +void +EffectCompositor::AnimationStyleRuleProcessor::RulesMatching( + AnonBoxRuleProcessorData* aData) +{ +} + +#ifdef MOZ_XUL +void +EffectCompositor::AnimationStyleRuleProcessor::RulesMatching( + XULTreeRuleProcessorData* aData) +{ +} +#endif + +size_t +EffectCompositor::AnimationStyleRuleProcessor::SizeOfExcludingThis( + MallocSizeOf aMallocSizeOf) const +{ + return 0; +} + +size_t +EffectCompositor::AnimationStyleRuleProcessor::SizeOfIncludingThis( + MallocSizeOf aMallocSizeOf) const +{ + return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf); +} + } // namespace mozilla diff --git a/dom/animation/EffectCompositor.h b/dom/animation/EffectCompositor.h index 46b90994ab..679fbf3374 100644 --- a/dom/animation/EffectCompositor.h +++ b/dom/animation/EffectCompositor.h @@ -9,13 +9,14 @@ #include "mozilla/EnumeratedArray.h" #include "mozilla/Maybe.h" +#include "mozilla/OwningNonNull.h" #include "mozilla/Pair.h" #include "mozilla/PseudoElementHashEntry.h" #include "mozilla/RefPtr.h" #include "nsCSSProperty.h" -#include "nsCSSPseudoElements.h" #include "nsCycleCollectionParticipant.h" #include "nsDataHashtable.h" +#include "nsIStyleRuleProcessor.h" #include "nsTArray.h" class nsCSSPropertySet; @@ -28,6 +29,7 @@ namespace mozilla { class EffectSet; class RestyleTracker; +enum class CSSPseudoElementType : uint8_t; namespace dom { class Animation; @@ -39,7 +41,13 @@ class EffectCompositor public: explicit EffectCompositor(nsPresContext* aPresContext) : mPresContext(aPresContext) - { } + { + for (size_t i = 0; i < kCascadeLevelCount; i++) { + CascadeLevel cascadeLevel = CascadeLevel(i); + mRuleProcessors[cascadeLevel] = + new AnimationStyleRuleProcessor(this, cascadeLevel); + } + } NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(EffectCompositor) NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(EffectCompositor) @@ -86,7 +94,7 @@ public: // The specified steps taken to update the animation rule depend on // |aRestyleType| whose values are described above. void RequestRestyle(dom::Element* aElement, - nsCSSPseudoElements::Type aPseudoType, + CSSPseudoElementType aPseudoType, RestyleType aRestyleType, CascadeLevel aCascadeLevel); @@ -95,7 +103,7 @@ public: // need to perform this step when triggering transitions *without* also // invalidating the animation style rule (which RequestRestyle would do). void PostRestyleForAnimation(dom::Element* aElement, - nsCSSPseudoElements::Type aPseudoType, + CSSPseudoElementType aPseudoType, CascadeLevel aCascadeLevel); // Posts an animation restyle for any elements whose animation style rule @@ -108,11 +116,11 @@ public: // If the animation rule is not marked as needing an update, // no work is done. void MaybeUpdateAnimationRule(dom::Element* aElement, - nsCSSPseudoElements::Type aPseudoType, + CSSPseudoElementType aPseudoType, CascadeLevel aCascadeLevel); nsIStyleRule* GetAnimationRule(dom::Element* aElement, - nsCSSPseudoElements::Type aPseudoType, + CSSPseudoElementType aPseudoType, CascadeLevel aCascadeLevel); bool HasPendingStyleUpdates() const; @@ -123,6 +131,11 @@ public: // elements. void AddStyleUpdatesTo(RestyleTracker& aTracker); + nsIStyleRuleProcessor* RuleProcessor(CascadeLevel aCascadeLevel) const + { + return mRuleProcessors[aCascadeLevel]; + } + static bool HasAnimationsForCompositor(const nsIFrame* aFrame, nsCSSProperty aProperty); @@ -142,14 +155,14 @@ public: // animation level of the cascade have changed. static void MaybeUpdateCascadeResults(dom::Element* aElement, - nsCSSPseudoElements::Type aPseudoType, + CSSPseudoElementType aPseudoType, nsStyleContext* aStyleContext); // An overload of MaybeUpdateCascadeResults that uses the style context // of the primary frame of the specified (pseudo-)element, when available. static void MaybeUpdateCascadeResults(dom::Element* aElement, - nsCSSPseudoElements::Type aPseudoType); + CSSPseudoElementType aPseudoType); // Update the mWinsInCascade member for each property in effects targetting // the specified (pseudo-)element. @@ -159,7 +172,7 @@ public: // other cases we should call MaybeUpdateCascadeResults. static void UpdateCascadeResults(dom::Element* aElement, - nsCSSPseudoElements::Type aPseudoType, + CSSPseudoElementType aPseudoType, nsStyleContext* aStyleContext); // Helper to fetch the corresponding element and pseudo-type from a frame. @@ -171,7 +184,7 @@ public: // Returns an empty result when a suitable element cannot be found including // when the frame represents a pseudo-element on which we do not support // animations. - static Maybe> + static Maybe> GetAnimationElementAndPseudoForFrame(const nsIFrame* aFrame); private: @@ -180,12 +193,12 @@ private: // Rebuilds the animation rule corresponding to |aCascadeLevel| on the // EffectSet associated with the specified (pseudo-)element. static void ComposeAnimationRule(dom::Element* aElement, - nsCSSPseudoElements::Type aPseudoType, + CSSPseudoElementType aPseudoType, CascadeLevel aCascadeLevel, TimeStamp aRefreshTime); static dom::Element* GetElementToRestyle(dom::Element* aElement, - nsCSSPseudoElements::Type + CSSPseudoElementType aPseudoType); // Get the properties in |aEffectSet| that we are able to animate on the @@ -199,7 +212,7 @@ private: static void UpdateCascadeResults(EffectSet& aEffectSet, dom::Element* aElement, - nsCSSPseudoElements::Type aPseudoType, + CSSPseudoElementType aPseudoType, nsStyleContext* aStyleContext); static nsPresContext* GetPresContext(dom::Element* aElement); @@ -214,6 +227,51 @@ private: EnumeratedArray> mElementsToRestyle; + + class AnimationStyleRuleProcessor final : public nsIStyleRuleProcessor + { + public: + AnimationStyleRuleProcessor(EffectCompositor* aCompositor, + CascadeLevel aCascadeLevel) + : mCompositor(aCompositor) + , mCascadeLevel(aCascadeLevel) + { + MOZ_ASSERT(aCompositor); + } + + NS_DECL_ISUPPORTS + + // nsIStyleRuleProcessor (parts) + nsRestyleHint HasStateDependentStyle( + StateRuleProcessorData* aData) override; + nsRestyleHint HasStateDependentStyle( + PseudoElementStateRuleProcessorData* aData) override; + bool HasDocumentStateDependentStyle(StateRuleProcessorData* aData) override; + nsRestyleHint HasAttributeDependentStyle( + AttributeRuleProcessorData* aData, + RestyleHintData& aRestyleHintDataResult) override; + bool MediumFeaturesChanged(nsPresContext* aPresContext) override; + void RulesMatching(ElementRuleProcessorData* aData) override; + void RulesMatching(PseudoElementRuleProcessorData* aData) override; + void RulesMatching(AnonBoxRuleProcessorData* aData) override; +#ifdef MOZ_XUL + void RulesMatching(XULTreeRuleProcessorData* aData) override; +#endif + size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) + const MOZ_MUST_OVERRIDE override; + size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) + const MOZ_MUST_OVERRIDE override; + + private: + ~AnimationStyleRuleProcessor() = default; + + EffectCompositor* mCompositor; + CascadeLevel mCascadeLevel; + }; + + EnumeratedArray> + mRuleProcessors; }; } // namespace mozilla diff --git a/dom/animation/EffectSet.cpp b/dom/animation/EffectSet.cpp index 254d8e3f61..04dbeba4ba 100644 --- a/dom/animation/EffectSet.cpp +++ b/dom/animation/EffectSet.cpp @@ -7,8 +7,10 @@ #include "EffectSet.h" #include "mozilla/dom/Element.h" // For Element #include "RestyleManager.h" +#include "nsCSSPseudoElements.h" // For CSSPseudoElementType #include "nsCycleCollectionNoteChild.h" // For CycleCollectionNoteChild #include "nsPresContext.h" +#include "nsLayoutUtils.h" namespace mozilla { @@ -37,7 +39,7 @@ EffectSet::Traverse(nsCycleCollectionTraversalCallback& aCallback) /* static */ EffectSet* EffectSet::GetEffectSet(dom::Element* aElement, - nsCSSPseudoElements::Type aPseudoType) + CSSPseudoElementType aPseudoType) { nsIAtom* propName = GetEffectSetPropertyAtom(aPseudoType); return static_cast(aElement->GetProperty(propName)); @@ -70,18 +72,23 @@ EffectSet::GetEffectSet(const nsIFrame* aFrame) return nullptr; } } else { - if (!content->MayHaveAnimations()) { + if (nsLayoutUtils::GetStyleFrame(content) != aFrame) { + // The effects associated with an element are for its primary frame. return nullptr; } propName = nsGkAtoms::animationEffectsProperty; } + if (!content->MayHaveAnimations()) { + return nullptr; + } + return static_cast(content->GetProperty(propName)); } /* static */ EffectSet* EffectSet::GetOrCreateEffectSet(dom::Element* aElement, - nsCSSPseudoElements::Type aPseudoType) + CSSPseudoElementType aPseudoType) { EffectSet* effectSet = GetEffectSet(aElement, aPseudoType); if (effectSet) { @@ -101,13 +108,29 @@ EffectSet::GetOrCreateEffectSet(dom::Element* aElement, return nullptr; } - if (aPseudoType == nsCSSPseudoElements::ePseudo_NotPseudoElement) { - aElement->SetMayHaveAnimations(); - } + aElement->SetMayHaveAnimations(); return effectSet; } +/* static */ void +EffectSet::DestroyEffectSet(dom::Element* aElement, + CSSPseudoElementType aPseudoType) +{ + nsIAtom* propName = GetEffectSetPropertyAtom(aPseudoType); + EffectSet* effectSet = + static_cast(aElement->GetProperty(propName)); + if (!effectSet) { + return; + } + + MOZ_ASSERT(!effectSet->IsBeingEnumerated(), + "Should not destroy an effect set while it is being enumerated"); + effectSet = nullptr; + + aElement->DeleteProperty(propName); +} + void EffectSet::UpdateAnimationGeneration(nsPresContext* aPresContext) { @@ -130,16 +153,16 @@ EffectSet::GetEffectSetPropertyAtoms() } /* static */ nsIAtom* -EffectSet::GetEffectSetPropertyAtom(nsCSSPseudoElements::Type aPseudoType) +EffectSet::GetEffectSetPropertyAtom(CSSPseudoElementType aPseudoType) { switch (aPseudoType) { - case nsCSSPseudoElements::ePseudo_NotPseudoElement: + case CSSPseudoElementType::NotPseudo: return nsGkAtoms::animationEffectsProperty; - case nsCSSPseudoElements::ePseudo_before: + case CSSPseudoElementType::before: return nsGkAtoms::animationEffectsForBeforeProperty; - case nsCSSPseudoElements::ePseudo_after: + case CSSPseudoElementType::after: return nsGkAtoms::animationEffectsForAfterProperty; default: diff --git a/dom/animation/EffectSet.h b/dom/animation/EffectSet.h index 9fc569ae28..4d1ecf8b16 100644 --- a/dom/animation/EffectSet.h +++ b/dom/animation/EffectSet.h @@ -8,10 +8,10 @@ #define mozilla_EffectSet_h #include "mozilla/AnimValuesStyleRule.h" +#include "mozilla/DebugOnly.h" #include "mozilla/EffectCompositor.h" #include "mozilla/EnumeratedArray.h" #include "mozilla/TimeStamp.h" -#include "nsCSSPseudoElements.h" // For nsCSSPseudoElements::Type #include "nsHashKeys.h" // For nsPtrHashKey #include "nsTHashtable.h" // For nsTHashtable @@ -24,6 +24,8 @@ class Element; class KeyframeEffectReadOnly; } // namespace dom +enum class CSSPseudoElementType : uint8_t; + // A wrapper around a hashset of AnimationEffect objects to handle // storing the set as a property of an element. class EffectSet @@ -32,6 +34,7 @@ public: EffectSet() : mCascadeNeedsUpdate(false) , mAnimationGeneration(0) + , mActiveIterators(0) #ifdef DEBUG , mCalledPropertyDtor(false) #endif @@ -43,6 +46,9 @@ public: { MOZ_ASSERT(mCalledPropertyDtor, "must call destructor through element property dtor"); + MOZ_ASSERT(mActiveIterators == 0, + "Effect set should not be destroyed while it is being " + "enumerated"); MOZ_COUNT_DTOR(EffectSet); } static void PropertyDtor(void* aObject, nsIAtom* aPropertyName, @@ -52,10 +58,12 @@ public: void Traverse(nsCycleCollectionTraversalCallback& aCallback); static EffectSet* GetEffectSet(dom::Element* aElement, - nsCSSPseudoElements::Type aPseudoType); + CSSPseudoElementType aPseudoType); static EffectSet* GetEffectSet(const nsIFrame* aFrame); static EffectSet* GetOrCreateEffectSet(dom::Element* aElement, - nsCSSPseudoElements::Type aPseudoType); + CSSPseudoElementType aPseudoType); + static void DestroyEffectSet(dom::Element* aElement, + CSSPseudoElementType aPseudoType); void AddEffect(dom::KeyframeEffectReadOnly& aEffect); void RemoveEffect(dom::KeyframeEffectReadOnly& aEffect); @@ -74,20 +82,35 @@ public: class Iterator { public: - explicit Iterator(OwningEffectSet::Iterator&& aHashIterator) - : mHashIterator(mozilla::Move(aHashIterator)) - , mIsEndIterator(false) { } - Iterator(Iterator&& aOther) - : mHashIterator(mozilla::Move(aOther.mHashIterator)) - , mIsEndIterator(aOther.mIsEndIterator) { } - - static Iterator EndIterator(OwningEffectSet::Iterator&& aHashIterator) + explicit Iterator(EffectSet& aEffectSet) + : mEffectSet(aEffectSet) + , mHashIterator(mozilla::Move(aEffectSet.mEffects.Iter())) + , mIsEndIterator(false) { - Iterator result(mozilla::Move(aHashIterator)); + mEffectSet.mActiveIterators++; + } + + Iterator(Iterator&& aOther) + : mEffectSet(aOther.mEffectSet) + , mHashIterator(mozilla::Move(aOther.mHashIterator)) + , mIsEndIterator(aOther.mIsEndIterator) + { + mEffectSet.mActiveIterators++; + } + + static Iterator EndIterator(EffectSet& aEffectSet) + { + Iterator result(aEffectSet); result.mIsEndIterator = true; return result; } + ~Iterator() + { + MOZ_ASSERT(mEffectSet.mActiveIterators > 0); + mEffectSet.mActiveIterators--; + } + bool operator!=(const Iterator& aOther) const { if (Done() || aOther.Done()) { return Done() != aOther.Done(); @@ -117,15 +140,19 @@ public: return mIsEndIterator || mHashIterator.Done(); } + EffectSet& mEffectSet; OwningEffectSet::Iterator mHashIterator; bool mIsEndIterator; }; - Iterator begin() { return Iterator(mEffects.Iter()); } - Iterator end() - { - return Iterator::EndIterator(mEffects.Iter()); - } + friend class Iterator; + + Iterator begin() { return Iterator(*this); } + Iterator end() { return Iterator::EndIterator(*this); } +#ifdef DEBUG + bool IsBeingEnumerated() const { return mActiveIterators != 0; } +#endif + bool IsEmpty() const { return mEffects.IsEmpty(); } RefPtr& AnimationRule(EffectCompositor::CascadeLevel @@ -156,8 +183,7 @@ public: static nsIAtom** GetEffectSetPropertyAtoms(); private: - static nsIAtom* GetEffectSetPropertyAtom(nsCSSPseudoElements::Type - aPseudoType); + static nsIAtom* GetEffectSetPropertyAtom(CSSPseudoElementType aPseudoType); OwningEffectSet mEffects; @@ -195,6 +221,10 @@ private: // the animation manager. uint64_t mAnimationGeneration; + // Track how many iterators are referencing this effect set when we are + // destroyed, we can assert that nothing is still pointing to us. + DebugOnly mActiveIterators; + #ifdef DEBUG bool mCalledPropertyDtor; #endif diff --git a/dom/animation/KeyframeEffect.cpp b/dom/animation/KeyframeEffect.cpp index 8562f8a5b7..53012700a3 100644 --- a/dom/animation/KeyframeEffect.cpp +++ b/dom/animation/KeyframeEffect.cpp @@ -17,6 +17,7 @@ #include "nsCSSParser.h" #include "nsCSSPropertySet.h" #include "nsCSSProps.h" // For nsCSSProps::PropHasFlags +#include "nsCSSPseudoElements.h" #include "nsCSSValue.h" #include "nsStyleUtil.h" #include // For std::max @@ -74,16 +75,26 @@ NS_IMPL_RELEASE_INHERITED(KeyframeEffectReadOnly, AnimationEffectReadOnly) KeyframeEffectReadOnly::KeyframeEffectReadOnly( nsIDocument* aDocument, Element* aTarget, - nsCSSPseudoElements::Type aPseudoType, + CSSPseudoElementType aPseudoType, const TimingParams& aTiming) + : KeyframeEffectReadOnly(aDocument, aTarget, aPseudoType, + new AnimationEffectTimingReadOnly(aTiming)) +{ +} + +KeyframeEffectReadOnly::KeyframeEffectReadOnly( + nsIDocument* aDocument, + Element* aTarget, + CSSPseudoElementType aPseudoType, + AnimationEffectTimingReadOnly* aTiming) : AnimationEffectReadOnly(aDocument) , mTarget(aTarget) + , mTiming(*aTiming) , mPseudoType(aPseudoType) , mInEffectOnLastAnimationTimingUpdate(false) { + MOZ_ASSERT(aTiming); MOZ_ASSERT(aTarget, "null animation target is not yet supported"); - - mTiming = new AnimationEffectTimingReadOnly(aTiming); } JSObject* @@ -180,6 +191,14 @@ KeyframeEffectReadOnly::NotifyAnimationTimingUpdated() RequestRestyle(mTarget, mPseudoType, restyleType, mAnimation->CascadeLevel()); } + + // If we're not relevant, we will have been removed from the EffectSet. + // As a result, when the restyle we requested above is fulfilled, our + // ComposeStyle will not get called and mProgressOnLastCompose will not + // be updated. Instead, we need to manually clear it. + if (!isRelevant) { + mProgressOnLastCompose.SetNull(); + } } } @@ -578,6 +597,71 @@ KeyframeEffectReadOnly::~KeyframeEffectReadOnly() { } +template +/* static */ already_AddRefed +KeyframeEffectReadOnly::ConstructKeyframeEffect(const GlobalObject& aGlobal, + const Nullable& aTarget, + JS::Handle aFrames, + const TimingParams& aTiming, + ErrorResult& aRv) +{ + if (aTarget.IsNull()) { + // We don't support null targets yet. + aRv.Throw(NS_ERROR_DOM_ANIM_NO_TARGET_ERR); + return nullptr; + } + + const ElementOrCSSPseudoElement& target = aTarget.Value(); + MOZ_ASSERT(target.IsElement() || target.IsCSSPseudoElement(), + "Uninitialized target"); + + RefPtr targetElement; + CSSPseudoElementType pseudoType = CSSPseudoElementType::NotPseudo; + if (target.IsElement()) { + targetElement = &target.GetAsElement(); + } else { + targetElement = target.GetAsCSSPseudoElement().ParentElement(); + pseudoType = target.GetAsCSSPseudoElement().GetType(); + } + + if (!targetElement->GetComposedDoc()) { + aRv.Throw(NS_ERROR_DOM_ANIM_TARGET_NOT_IN_DOC_ERR); + return nullptr; + } + + InfallibleTArray animationProperties; + BuildAnimationPropertyList(aGlobal.Context(), targetElement, pseudoType, + aFrames, animationProperties, aRv); + + if (aRv.Failed()) { + return nullptr; + } + + RefPtr effect = + new KeyframeEffectType(targetElement->OwnerDoc(), targetElement, + pseudoType, aTiming); + effect->mProperties = Move(animationProperties); + return effect.forget(); +} + +// Explicit instantiations to avoid linker errors. + +template +already_AddRefed +KeyframeEffectReadOnly::ConstructKeyframeEffect<>(const GlobalObject& aGlobal, + const Nullable& aTarget, + JS::Handle aFrames, + const TimingParams& aTiming, + ErrorResult& aRv); + +template +already_AddRefed +KeyframeEffectReadOnly::ConstructKeyframeEffect<>(const GlobalObject& aGlobal, + const Nullable& aTarget, + JS::Handle aFrames, + const TimingParams& aTiming, + ErrorResult& aRv); + void KeyframeEffectReadOnly::ResetIsRunningOnCompositor() { @@ -610,6 +694,9 @@ KeyframeEffectReadOnly::UpdateTargetRegistration() EffectSet* effectSet = EffectSet::GetEffectSet(mTarget, mPseudoType); if (effectSet) { effectSet->RemoveEffect(*this); + if (effectSet->IsEmpty()) { + EffectSet::DestroyEffectSet(mTarget, mPseudoType); + } } } } @@ -1134,7 +1221,7 @@ ApplyDistributeSpacing(nsTArray& aKeyframes) */ static void GenerateValueEntries(Element* aTarget, - nsCSSPseudoElements::Type aPseudoType, + CSSPseudoElementType aPseudoType, nsTArray& aKeyframes, nsTArray& aResult, ErrorResult& aRv) @@ -1338,7 +1425,7 @@ static void BuildAnimationPropertyListFromKeyframeSequence( JSContext* aCx, Element* aTarget, - nsCSSPseudoElements::Type aPseudoType, + CSSPseudoElementType aPseudoType, JS::ForOfIterator& aIterator, nsTArray& aResult, ErrorResult& aRv) @@ -1396,7 +1483,7 @@ static void BuildAnimationPropertyListFromPropertyIndexedKeyframes( JSContext* aCx, Element* aTarget, - nsCSSPseudoElements::Type aPseudoType, + CSSPseudoElementType aPseudoType, JS::Handle aValue, InfallibleTArray& aResult, ErrorResult& aRv) @@ -1571,7 +1658,7 @@ BuildAnimationPropertyListFromPropertyIndexedKeyframes( KeyframeEffectReadOnly::BuildAnimationPropertyList( JSContext* aCx, Element* aTarget, - nsCSSPseudoElements::Type aPseudoType, + CSSPseudoElementType aPseudoType, JS::Handle aFrames, InfallibleTArray& aResult, ErrorResult& aRv) @@ -1615,55 +1702,6 @@ KeyframeEffectReadOnly::BuildAnimationPropertyList( } } -/* static */ already_AddRefed -KeyframeEffectReadOnly::Constructor( - const GlobalObject& aGlobal, - const Nullable& aTarget, - JS::Handle aFrames, - const TimingParams& aTiming, - ErrorResult& aRv) -{ - if (aTarget.IsNull()) { - // We don't support null targets yet. - aRv.Throw(NS_ERROR_DOM_ANIM_NO_TARGET_ERR); - return nullptr; - } - - const ElementOrCSSPseudoElement& target = aTarget.Value(); - MOZ_ASSERT(target.IsElement() || target.IsCSSPseudoElement(), - "Uninitialized target"); - - RefPtr targetElement; - nsCSSPseudoElements::Type pseudoType = - nsCSSPseudoElements::ePseudo_NotPseudoElement; - if (target.IsElement()) { - targetElement = &target.GetAsElement(); - } else { - targetElement = target.GetAsCSSPseudoElement().ParentElement(); - pseudoType = target.GetAsCSSPseudoElement().GetType(); - } - - if (!targetElement->GetCurrentDoc()) { - // Bug 1245748: We don't support targets that are not in a document yet. - aRv.Throw(NS_ERROR_DOM_ANIM_TARGET_NOT_IN_DOC_ERR); - return nullptr; - } - - InfallibleTArray animationProperties; - BuildAnimationPropertyList(aGlobal.Context(), targetElement, pseudoType, - aFrames, animationProperties, aRv); - - if (aRv.Failed()) { - return nullptr; - } - - RefPtr effect = - new KeyframeEffectReadOnly(targetElement->OwnerDoc(), targetElement, - pseudoType, aTiming); - effect->mProperties = Move(animationProperties); - return effect.forget(); -} - void KeyframeEffectReadOnly::GetTarget( Nullable& aRv) const @@ -1674,13 +1712,13 @@ KeyframeEffectReadOnly::GetTarget( } switch (mPseudoType) { - case nsCSSPseudoElements::ePseudo_before: - case nsCSSPseudoElements::ePseudo_after: + case CSSPseudoElementType::before: + case CSSPseudoElementType::after: aRv.SetValue().SetAsCSSPseudoElement() = CSSPseudoElement::GetCSSPseudoElement(mTarget, mPseudoType); break; - case nsCSSPseudoElements::ePseudo_NotPseudoElement: + case CSSPseudoElementType::NotPseudo: aRv.SetValue().SetAsElement() = mTarget; break; @@ -1928,12 +1966,12 @@ KeyframeEffectReadOnly::GetAnimationFrame() const return nullptr; } - if (mPseudoType == nsCSSPseudoElements::ePseudo_before) { + if (mPseudoType == CSSPseudoElementType::before) { frame = nsLayoutUtils::GetBeforeFrame(frame); - } else if (mPseudoType == nsCSSPseudoElements::ePseudo_after) { + } else if (mPseudoType == CSSPseudoElementType::after) { frame = nsLayoutUtils::GetAfterFrame(frame); } else { - MOZ_ASSERT(mPseudoType == nsCSSPseudoElements::ePseudo_NotPseudoElement, + MOZ_ASSERT(mPseudoType == CSSPseudoElementType::NotPseudo, "unknown mPseudoType"); } if (!frame) { @@ -2063,6 +2101,21 @@ KeyframeEffectReadOnly::ShouldBlockCompositorAnimations(const nsIFrame* return false; } +//--------------------------------------------------------------------- +// +// KeyframeEffect +// +//--------------------------------------------------------------------- + +KeyframeEffect::KeyframeEffect(nsIDocument* aDocument, + Element* aTarget, + CSSPseudoElementType aPseudoType, + const TimingParams& aTiming) + : KeyframeEffectReadOnly(aDocument, aTarget, aPseudoType, + new AnimationEffectTiming(aTiming)) +{ +} + JSObject* KeyframeEffect::WrapObject(JSContext* aCx, JS::Handle aGivenProto) diff --git a/dom/animation/KeyframeEffect.h b/dom/animation/KeyframeEffect.h index 64a92b042a..f3b746b2cd 100644 --- a/dom/animation/KeyframeEffect.h +++ b/dom/animation/KeyframeEffect.h @@ -9,7 +9,6 @@ #include "nsAutoPtr.h" #include "nsCycleCollectionParticipant.h" -#include "nsCSSPseudoElements.h" #include "nsIDocument.h" #include "nsWrapperCache.h" #include "mozilla/Attributes.h" @@ -20,6 +19,7 @@ #include "mozilla/StyleAnimationValue.h" #include "mozilla/TimeStamp.h" #include "mozilla/dom/AnimationEffectReadOnly.h" +#include "mozilla/dom/AnimationEffectTiming.h" #include "mozilla/dom/AnimationEffectTimingReadOnly.h" // TimingParams #include "mozilla/dom/Element.h" #include "mozilla/dom/KeyframeBinding.h" @@ -37,6 +37,7 @@ namespace mozilla { struct AnimationCollection; class AnimValuesStyleRule; +enum class CSSPseudoElementType : uint8_t; namespace dom { class ElementOrCSSPseudoElement; @@ -171,7 +172,7 @@ class KeyframeEffectReadOnly : public AnimationEffectReadOnly public: KeyframeEffectReadOnly(nsIDocument* aDocument, Element* aTarget, - nsCSSPseudoElements::Type aPseudoType, + CSSPseudoElementType aPseudoType, const TimingParams& aTiming); NS_DECL_ISUPPORTS_INHERITED @@ -195,20 +196,11 @@ public: const UnrestrictedDoubleOrKeyframeEffectOptions& aOptions, ErrorResult& aRv) { - return Constructor(aGlobal, aTarget, aFrames, - TimingParams::FromOptionsUnion(aOptions, aTarget), - aRv); + return ConstructKeyframeEffect( + aGlobal, aTarget, aFrames, + TimingParams::FromOptionsUnion(aOptions, aTarget), aRv); } - // More generalized version for Animatable.animate. - // Not exposed to content. - static already_AddRefed - Constructor(const GlobalObject& aGlobal, - const Nullable& aTarget, - JS::Handle aFrames, - const TimingParams& aTiming, - ErrorResult& aRv); - void GetTarget(Nullable& aRv) const; void GetFrames(JSContext*& aCx, nsTArray& aResult, @@ -217,7 +209,7 @@ public: // Temporary workaround to return both the target element and pseudo-type // until we implement PseudoElement (bug 1174575). void GetTarget(Element*& aTarget, - nsCSSPseudoElements::Type& aPseudoType) const { + CSSPseudoElementType& aPseudoType) const { aTarget = mTarget; aPseudoType = mPseudoType; } @@ -328,7 +320,21 @@ public: inline AnimationCollection* GetCollection() const; protected: + KeyframeEffectReadOnly(nsIDocument* aDocument, + Element* aTarget, + CSSPseudoElementType aPseudoType, + AnimationEffectTimingReadOnly* aTiming); + virtual ~KeyframeEffectReadOnly(); + + template + static already_AddRefed + ConstructKeyframeEffect(const GlobalObject& aGlobal, + const Nullable& aTarget, + JS::Handle aFrames, + const TimingParams& aTiming, + ErrorResult& aRv); + void ResetIsRunningOnCompositor(); // This effect is registered with its target element so long as: @@ -345,7 +351,7 @@ protected: static void BuildAnimationPropertyList( JSContext* aCx, Element* aTarget, - nsCSSPseudoElements::Type aPseudoType, + CSSPseudoElementType aPseudoType, JS::Handle aFrames, InfallibleTArray& aResult, ErrorResult& aRv); @@ -354,7 +360,7 @@ protected: RefPtr mAnimation; OwningNonNull mTiming; - nsCSSPseudoElements::Type mPseudoType; + CSSPseudoElementType mPseudoType; InfallibleTArray mProperties; @@ -389,12 +395,36 @@ class KeyframeEffect : public KeyframeEffectReadOnly public: KeyframeEffect(nsIDocument* aDocument, Element* aTarget, - nsCSSPseudoElements::Type aPseudoType, - const TimingParams& aTiming) - : KeyframeEffectReadOnly(aDocument, aTarget, aPseudoType, aTiming) { } + CSSPseudoElementType aPseudoType, + const TimingParams& aTiming); JSObject* WrapObject(JSContext* aCx, JS::Handle aGivenProto) override; + + static already_AddRefed + Constructor(const GlobalObject& aGlobal, + const Nullable& aTarget, + JS::Handle aFrames, + const UnrestrictedDoubleOrKeyframeEffectOptions& aOptions, + ErrorResult& aRv) + { + return ConstructKeyframeEffect( + aGlobal, aTarget, aFrames, + TimingParams::FromOptionsUnion(aOptions, aTarget), aRv); + } + + // More generalized version for Animatable.animate. + // Not exposed to content. + static already_AddRefed + inline Constructor(const GlobalObject& aGlobal, + const Nullable& aTarget, + JS::Handle aFrames, + const TimingParams& aTiming, + ErrorResult& aRv) + { + return ConstructKeyframeEffect(aGlobal, aTarget, aFrames, + aTiming, aRv); + } }; } // namespace dom diff --git a/dom/animation/PseudoElementHashEntry.h b/dom/animation/PseudoElementHashEntry.h index 84aaf597ff..c1f90e670c 100644 --- a/dom/animation/PseudoElementHashEntry.h +++ b/dom/animation/PseudoElementHashEntry.h @@ -9,18 +9,19 @@ #include "mozilla/dom/Element.h" #include "mozilla/HashFunctions.h" -#include "nsCSSPseudoElements.h" #include "PLDHashTable.h" namespace mozilla { +enum class CSSPseudoElementType : uint8_t; + struct PseudoElementHashKey { dom::Element* mElement; - nsCSSPseudoElements::Type mPseudoType; + CSSPseudoElementType mPseudoType; }; -// A hash entry that uses a RefPtr, nsCSSPseudoElements::Type pair +// A hash entry that uses a RefPtr, CSSPseudoElementType pair class PseudoElementHashEntry : public PLDHashEntryHdr { public: @@ -47,12 +48,14 @@ public: if (!aKey) return 0; - return mozilla::HashGeneric(aKey->mElement, aKey->mPseudoType); + // Convert the scoped enum into an integer while adding it to hash. + return mozilla::HashGeneric(aKey->mElement, + static_cast(aKey->mPseudoType)); } enum { ALLOW_MEMMOVE = true }; RefPtr mElement; - nsCSSPseudoElements::Type mPseudoType; + CSSPseudoElementType mPseudoType; }; } // namespace mozilla diff --git a/dom/animation/moz.build b/dom/animation/moz.build index f5ae4a93b9..aa9aaba29c 100644 --- a/dom/animation/moz.build +++ b/dom/animation/moz.build @@ -10,6 +10,7 @@ MOCHITEST_CHROME_MANIFESTS += ['test/chrome.ini'] EXPORTS.mozilla.dom += [ 'Animation.h', 'AnimationEffectReadOnly.h', + 'AnimationEffectTiming.h', 'AnimationEffectTimingReadOnly.h', 'AnimationTimeline.h', 'CSSPseudoElement.h', @@ -31,6 +32,7 @@ EXPORTS.mozilla += [ UNIFIED_SOURCES += [ 'Animation.cpp', 'AnimationEffectReadOnly.cpp', + 'AnimationEffectTiming.cpp', 'AnimationEffectTimingReadOnly.cpp', 'AnimationTimeline.cpp', 'AnimationUtils.cpp', diff --git a/dom/base/Element.cpp b/dom/base/Element.cpp index 485a9186ed..3d73af9bb6 100644 --- a/dom/base/Element.cpp +++ b/dom/base/Element.cpp @@ -45,7 +45,6 @@ #include "nsNameSpaceManager.h" #include "nsContentList.h" #include "nsVariant.h" -#include "nsDOMSettableTokenList.h" #include "nsDOMTokenList.h" #include "nsXBLPrototypeBinding.h" #include "nsError.h" @@ -925,7 +924,7 @@ already_AddRefed Element::GetBoundingClientRect() { RefPtr rect = new DOMRect(this); - + nsIFrame* frame = GetPrimaryFrame(Flush_Layout); if (!frame) { // display:none, perhaps? Return the empty rect @@ -1497,7 +1496,7 @@ Element::BindToTree(nsIDocument* aDocument, nsIContent* aParent, if (xulElem) { xulElem->SetXULBindingParent(aBindingParent); } - else + else #endif { if (aBindingParent) { @@ -1557,7 +1556,7 @@ Element::BindToTree(nsIDocument* aDocument, nsIContent* aParent, // XXXbz ordering issues here? Probably not, since ChangeDocumentFor is // just pretty broken anyway.... Need to get it working. // XXXbz XBL doesn't handle this (asserts), and we don't really want - // to be doing this during parsing anyway... sort this out. + // to be doing this during parsing anyway... sort this out. // aDocument->BindingManager()->ChangeDocumentFor(this, nullptr, // aDocument); @@ -1882,7 +1881,7 @@ Element::UnbindFromTree(bool aDeep, bool aNullParent) } } - // This has to be here, rather than in nsGenericHTMLElement::UnbindFromTree, + // This has to be here, rather than in nsGenericHTMLElement::UnbindFromTree, // because it has to happen after unsetting the parent pointer, but before // recursively unbinding the kids. if (IsHTMLElement()) { @@ -2592,7 +2591,7 @@ Element::GetAttrInfo(int32_t aNamespaceID, nsIAtom* aName) const return nsAttrInfo(nullptr, nullptr); } - + bool Element::GetAttr(int32_t aNameSpaceID, nsIAtom* aName, @@ -2613,7 +2612,7 @@ Element::FindAttrValueIn(int32_t aNameSpaceID, NS_ASSERTION(aName, "Must have attr name"); NS_ASSERTION(aNameSpaceID != kNameSpaceID_Unknown, "Must have namespace"); NS_ASSERTION(aValues, "Null value array"); - + const nsAttrValue* val = mAttrsAndChildren.GetAttr(aName, aNameSpaceID); if (val) { for (int32_t i = 0; aValues[i]; ++i) { @@ -2817,7 +2816,7 @@ Element::List(FILE* out, int32_t aIndent, nsIContent* child = GetFirstChild(); if (child) { fputs("\n", out); - + for (; child; child = child->GetNextSibling()) { child->List(out, aIndent + 1); } @@ -2826,7 +2825,7 @@ Element::List(FILE* out, int32_t aIndent, } fputs(">\n", out); - + Element* nonConstThis = const_cast(this); // XXX sXBL/XBL2 issue! Owner or current document? @@ -3119,11 +3118,11 @@ Element::GetLinkTarget(nsAString& aTarget) } static void -nsDOMSettableTokenListPropertyDestructor(void *aObject, nsIAtom *aProperty, - void *aPropertyValue, void *aData) +nsDOMTokenListPropertyDestructor(void *aObject, nsIAtom *aProperty, + void *aPropertyValue, void *aData) { - nsDOMSettableTokenList* list = - static_cast(aPropertyValue); + nsDOMTokenList* list = + static_cast(aPropertyValue); NS_RELEASE(list); } @@ -3145,7 +3144,7 @@ Element::HTMLSVGPropertiesToTraverseAndUnlink() return sPropertiesToTraverseAndUnlink; } -nsDOMSettableTokenList* +nsDOMTokenList* Element::GetTokenList(nsIAtom* aAtom) { #ifdef DEBUG @@ -3161,14 +3160,14 @@ Element::GetTokenList(nsIAtom* aAtom) MOZ_ASSERT(found, "Trying to use an unknown tokenlist!"); #endif - nsDOMSettableTokenList* list = nullptr; + nsDOMTokenList* list = nullptr; if (HasProperties()) { - list = static_cast(GetProperty(aAtom)); + list = static_cast(GetProperty(aAtom)); } if (!list) { - list = new nsDOMSettableTokenList(this, aAtom); + list = new nsDOMTokenList(this, aAtom); NS_ADDREF(list); - SetProperty(aAtom, list, nsDOMSettableTokenListPropertyDestructor); + SetProperty(aAtom, list, nsDOMTokenListPropertyDestructor); } return list; } @@ -3185,7 +3184,7 @@ Element::GetTokenList(nsIAtom* aAtom, nsIVariant** aResult) nsresult Element::SetTokenList(nsIAtom* aAtom, nsIVariant* aValue) { - nsDOMSettableTokenList* itemType = GetTokenList(aAtom); + nsDOMTokenList* itemType = GetTokenList(aAtom); nsAutoString string; aValue->GetAsAString(string); ErrorResult rv; @@ -3402,9 +3401,8 @@ Element::Animate(JSContext* aContext, Nullable target; target.SetValue().SetAsElement() = this; - // Bug 1211783: Use KeyframeEffect here (instead of KeyframeEffectReadOnly) - RefPtr effect = - KeyframeEffectReadOnly::Constructor(global, target, frames, + RefPtr effect = + KeyframeEffect::Constructor(global, target, frames, TimingParams::FromOptionsUnion(aOptions, target), aError); if (aError.Failed()) { return nullptr; @@ -3444,7 +3442,7 @@ void Element::GetAnimationsUnsorted(nsTArray>& aAnimations) { EffectSet* effects = EffectSet::GetEffectSet(this, - nsCSSPseudoElements::ePseudo_NotPseudoElement); + CSSPseudoElementType::NotPseudo); if (!effects) { return; } @@ -3586,7 +3584,7 @@ Element::InsertAdjacentHTML(const nsAString& aPosition, const nsAString& aText, // Needed when insertAdjacentHTML is used in combination with contenteditable mozAutoDocUpdate updateBatch(doc, UPDATE_CONTENT_MODEL, true); nsAutoScriptLoaderDisabler sld(doc); - + // Batch possible DOMSubtreeModified events. mozAutoSubtreeModified subtree(doc, nullptr); diff --git a/dom/base/Element.h b/dom/base/Element.h index 536c953a4f..17a383a99c 100644 --- a/dom/base/Element.h +++ b/dom/base/Element.h @@ -45,7 +45,6 @@ class nsIURI; class nsIScrollableFrame; class nsAttrValueOrString; class nsContentList; -class nsDOMSettableTokenList; class nsDOMTokenList; struct nsRect; class nsFocusManager; @@ -1329,7 +1328,7 @@ protected: */ virtual void GetLinkTarget(nsAString& aTarget); - nsDOMSettableTokenList* GetTokenList(nsIAtom* aAtom); + nsDOMTokenList* GetTokenList(nsIAtom* aAtom); void GetTokenList(nsIAtom* aAtom, nsIVariant** aResult); nsresult SetTokenList(nsIAtom* aAtom, nsIVariant* aValue); diff --git a/dom/base/FragmentOrElement.cpp b/dom/base/FragmentOrElement.cpp index 23ca57b3ed..b01ebe2947 100644 --- a/dom/base/FragmentOrElement.cpp +++ b/dom/base/FragmentOrElement.cpp @@ -1355,10 +1355,11 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(FragmentOrElement) for (uint32_t i = 0; props[i]; ++i) { tmp->DeleteProperty(*props[i]); } - // Bug 1226091: Call MayHaveAnimations() first - nsIAtom** effectProps = EffectSet::GetEffectSetPropertyAtoms(); - for (uint32_t i = 0; effectProps[i]; ++i) { - tmp->DeleteProperty(effectProps[i]); + if (tmp->MayHaveAnimations()) { + nsIAtom** effectProps = EffectSet::GetEffectSetPropertyAtoms(); + for (uint32_t i = 0; effectProps[i]; ++i) { + tmp->DeleteProperty(effectProps[i]); + } } } } @@ -1900,6 +1901,14 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(FragmentOrElement) tmp->OwnerDoc()->BindingManager()->Traverse(tmp, cb); + // Check that whenever we have effect properties, MayHaveAnimations is set. +#ifdef DEBUG + nsIAtom** effectProps = EffectSet::GetEffectSetPropertyAtoms(); + for (uint32_t i = 0; effectProps[i]; ++i) { + MOZ_ASSERT_IF(tmp->GetProperty(effectProps[i]), tmp->MayHaveAnimations()); + } +#endif + if (tmp->HasProperties()) { if (tmp->IsHTMLElement() || tmp->IsSVGElement()) { nsIAtom*** props = Element::HTMLSVGPropertiesToTraverseAndUnlink(); @@ -1908,13 +1917,14 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(FragmentOrElement) static_cast(tmp->GetProperty(*props[i])); cb.NoteXPCOMChild(property); } - // Bug 1226091: Check MayHaveAnimations() first - nsIAtom** effectProps = EffectSet::GetEffectSetPropertyAtoms(); - for (uint32_t i = 0; effectProps[i]; ++i) { - EffectSet* effectSet = - static_cast(tmp->GetProperty(effectProps[i])); - if (effectSet) { - effectSet->Traverse(cb); + if (tmp->MayHaveAnimations()) { + nsIAtom** effectProps = EffectSet::GetEffectSetPropertyAtoms(); + for (uint32_t i = 0; effectProps[i]; ++i) { + EffectSet* effectSet = + static_cast(tmp->GetProperty(effectProps[i])); + if (effectSet) { + effectSet->Traverse(cb); + } } } } diff --git a/dom/base/moz.build b/dom/base/moz.build index 62b1e1c1bf..3206c8ff5b 100644 --- a/dom/base/moz.build +++ b/dom/base/moz.build @@ -278,7 +278,6 @@ UNIFIED_SOURCES += [ 'nsDOMNavigationTiming.cpp', 'nsDOMScriptObjectFactory.cpp', 'nsDOMSerializer.cpp', - 'nsDOMSettableTokenList.cpp', 'nsDOMTokenList.cpp', 'nsDOMWindowList.cpp', 'nsFocusManager.cpp', diff --git a/dom/base/nsDOMMutationObserver.cpp b/dom/base/nsDOMMutationObserver.cpp index 887ea274ac..670694417f 100644 --- a/dom/base/nsDOMMutationObserver.cpp +++ b/dom/base/nsDOMMutationObserver.cpp @@ -389,7 +389,7 @@ nsAnimationReceiver::RecordAnimationMutation(Animation* aAnimation, } mozilla::dom::Element* animationTarget; - nsCSSPseudoElements::Type pseudoType; + CSSPseudoElementType pseudoType; effect->GetTarget(animationTarget, pseudoType); if (!animationTarget) { return; diff --git a/dom/base/nsDOMSettableTokenList.cpp b/dom/base/nsDOMSettableTokenList.cpp deleted file mode 100644 index eea5a050e2..0000000000 --- a/dom/base/nsDOMSettableTokenList.cpp +++ /dev/null @@ -1,29 +0,0 @@ -/* -*- 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/. */ - -/* - * Implementation of DOMSettableTokenList specified by HTML5. - */ - -#include "nsDOMSettableTokenList.h" -#include "mozilla/dom/DOMSettableTokenListBinding.h" -#include "mozilla/dom/Element.h" - -void -nsDOMSettableTokenList::SetValue(const nsAString& aValue, mozilla::ErrorResult& rv) -{ - if (!mElement) { - return; - } - - rv = mElement->SetAttr(kNameSpaceID_None, mAttrAtom, aValue, true); -} - -JSObject* -nsDOMSettableTokenList::WrapObject(JSContext *cx, JS::Handle aGivenProto) -{ - return mozilla::dom::DOMSettableTokenListBinding::Wrap(cx, this, aGivenProto); -} diff --git a/dom/base/nsDOMSettableTokenList.h b/dom/base/nsDOMSettableTokenList.h deleted file mode 100644 index b004334ad9..0000000000 --- a/dom/base/nsDOMSettableTokenList.h +++ /dev/null @@ -1,35 +0,0 @@ -/* -*- 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/. */ - -/* - * Implementation of DOMSettableTokenList specified by HTML5. - */ - -#ifndef nsDOMSettableTokenList_h___ -#define nsDOMSettableTokenList_h___ - -#include "nsDOMTokenList.h" - -class nsIAtom; - -// nsISupports must be on the primary inheritance chain -// because nsDOMSettableTokenList is traversed by Element. -class nsDOMSettableTokenList final : public nsDOMTokenList -{ -public: - - nsDOMSettableTokenList(mozilla::dom::Element* aElement, nsIAtom* aAttrAtom) - : nsDOMTokenList(aElement, aAttrAtom) {} - - virtual JSObject* WrapObject(JSContext *cx, JS::Handle aGivenProto) override; - - // WebIDL - void GetValue(nsAString& aResult) { Stringify(aResult); } - void SetValue(const nsAString& aValue, mozilla::ErrorResult& rv); -}; - -#endif // nsDOMSettableTokenList_h___ - diff --git a/dom/base/nsDOMTokenList.cpp b/dom/base/nsDOMTokenList.cpp index 855b8e9c0e..63e0306135 100644 --- a/dom/base/nsDOMTokenList.cpp +++ b/dom/base/nsDOMTokenList.cpp @@ -9,7 +9,6 @@ */ #include "nsDOMTokenList.h" - #include "nsAttrValue.h" #include "nsContentUtils.h" #include "nsError.h" @@ -74,6 +73,16 @@ nsDOMTokenList::IndexedGetter(uint32_t aIndex, bool& aFound, nsAString& aResult) } } +void +nsDOMTokenList::SetValue(const nsAString& aValue, mozilla::ErrorResult& rv) +{ + if (!mElement) { + return; + } + + rv = mElement->SetAttr(kNameSpaceID_None, mAttrAtom, aValue, true); +} + nsresult nsDOMTokenList::CheckToken(const nsAString& aStr) { diff --git a/dom/base/nsDOMTokenList.h b/dom/base/nsDOMTokenList.h index 60fd596872..9f7a702014 100644 --- a/dom/base/nsDOMTokenList.h +++ b/dom/base/nsDOMTokenList.h @@ -26,7 +26,7 @@ class nsAttrValue; class nsIAtom; // nsISupports must be on the primary inheritance chain -// because nsDOMSettableTokenList is traversed by Element. + class nsDOMTokenList : public nsISupports, public nsWrapperCache { @@ -66,6 +66,9 @@ public: bool Toggle(const nsAString& aToken, const mozilla::dom::Optional& force, mozilla::ErrorResult& aError); + + void GetValue(nsAString& aResult) { Stringify(aResult); } + void SetValue(const nsAString& aValue, mozilla::ErrorResult& rv); void Stringify(nsAString& aResult); protected: diff --git a/dom/base/nsDOMWindowUtils.cpp b/dom/base/nsDOMWindowUtils.cpp index 9808086e83..7408c31b3b 100644 --- a/dom/base/nsDOMWindowUtils.cpp +++ b/dom/base/nsDOMWindowUtils.cpp @@ -102,6 +102,7 @@ #include "nsIStyleSheet.h" #include "nsIStyleSheetService.h" #include "nsContentPermissionHelper.h" +#include "nsCSSPseudoElements.h" // for CSSPseudoElementType #include "nsNetUtil.h" #include "nsDocument.h" #include "HTMLImageElement.h" @@ -2380,13 +2381,12 @@ ComputeAnimationValue(nsCSSProperty aProperty, StyleAnimationValue& aOutput) { - if (!StyleAnimationValue::ComputeValue( - aProperty, - aElement, - nsCSSPseudoElements::ePseudo_NotPseudoElement, - aInput, - false, - aOutput)) { + if (!StyleAnimationValue::ComputeValue(aProperty, + aElement, + CSSPseudoElementType::NotPseudo, + aInput, + false, + aOutput)) { return false; } diff --git a/dom/base/nsNodeUtils.cpp b/dom/base/nsNodeUtils.cpp index bb0e2d7cee..2ccb9f3d09 100644 --- a/dom/base/nsNodeUtils.cpp +++ b/dom/base/nsNodeUtils.cpp @@ -6,6 +6,7 @@ #include "nsNodeUtils.h" #include "nsContentUtils.h" +#include "nsCSSPseudoElements.h" #include "nsINode.h" #include "nsIContent.h" #include "mozilla/dom/Element.h" @@ -235,13 +236,13 @@ nsNodeUtils::GetTargetForAnimation(const Animation* aAnimation) } Element* target; - nsCSSPseudoElements::Type pseudoType; + CSSPseudoElementType pseudoType; effect->GetTarget(target, pseudoType); // If the animation targets a pseudo-element, we don't dispatch // notifications for it. (In the future we will have PseudoElement // objects we can use as the target of the notifications.) - if (pseudoType != nsCSSPseudoElements::ePseudo_NotPseudoElement) { + if (pseudoType != CSSPseudoElementType::NotPseudo) { return nullptr; } diff --git a/dom/base/test/test_bug346485.html b/dom/base/test/test_bug346485.html index b0543ced20..8db0fc67e2 100644 --- a/dom/base/test/test_bug346485.html +++ b/dom/base/test/test_bug346485.html @@ -22,7 +22,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=346485 /** Test for Bug 346485 **/ /** - * This test is testing DOMSettableTokenList used by the output element. + * This test is testing DOMTokenList used by the output element. */ function checkHtmlFor(htmlFor, list, msg) { diff --git a/dom/base/test/test_classList.html b/dom/base/test/test_classList.html index 3b659586be..648bde4a21 100644 --- a/dom/base/test/test_classList.html +++ b/dom/base/test/test_classList.html @@ -98,15 +98,20 @@ function assignToClassListStrict(e) { "use strict"; try { e.classList = "foo"; - ok(false, "assigning to classList didn't throw"); - } catch (e) { } + ok(true, "assigning to classList didn't throw"); + e.removeAttribute("class"); + } catch (e) { + ok(false, "assigning to classList threw"); + } } function assignToClassList(e) { try { var expect = e.classList; e.classList = "foo"; + ok(true, "assigning to classList didn't throw"); is(e.classList, expect, "classList should be unchanged after assignment"); + e.removeAttribute("class"); } catch (e) { ok(false, "assigning to classList threw"); } @@ -160,8 +165,6 @@ function testClassList(e) { ok(DOMTokenList.prototype.hasOwnProperty("toString"), "Should have own toString on DOMTokenList") - ok(!DOMSettableTokenList.prototype.hasOwnProperty("toString"), - "Should not have own toString on DOMSettableTokenList") e.removeAttribute("class"); is(e.classList.toString(), "", "wrong classList.toString() value"); diff --git a/dom/bindings/Bindings.conf b/dom/bindings/Bindings.conf index ded224765a..0aa12bb641 100644 --- a/dom/bindings/Bindings.conf +++ b/dom/bindings/Bindings.conf @@ -437,10 +437,6 @@ DOMInterfaces = { 'implicitJSContext': [ 'then' ], }, -'DOMSettableTokenList': { - 'nativeType': 'nsDOMSettableTokenList', -}, - 'DOMStringMap': { 'nativeType': 'nsDOMStringMap' }, diff --git a/dom/html/HTMLIFrameElement.h b/dom/html/HTMLIFrameElement.h index da8c0b2800..67fcc3662e 100644 --- a/dom/html/HTMLIFrameElement.h +++ b/dom/html/HTMLIFrameElement.h @@ -10,7 +10,7 @@ #include "mozilla/Attributes.h" #include "nsGenericHTMLFrameElement.h" #include "nsIDOMHTMLIFrameElement.h" -#include "nsDOMSettableTokenList.h" +#include "nsDOMTokenList.h" namespace mozilla { namespace dom { @@ -84,7 +84,7 @@ public: { SetHTMLAttr(nsGkAtoms::name, aName, aError); } - nsDOMSettableTokenList* Sandbox() + nsDOMTokenList* Sandbox() { return GetTokenList(nsGkAtoms::sandbox); } diff --git a/dom/html/HTMLLinkElement.h b/dom/html/HTMLLinkElement.h index 0411bcede7..44596bf1e2 100644 --- a/dom/html/HTMLLinkElement.h +++ b/dom/html/HTMLLinkElement.h @@ -119,7 +119,7 @@ public: { SetHTMLAttr(nsGkAtoms::hreflang, aHreflang, aRv); } - nsDOMSettableTokenList* Sizes() + nsDOMTokenList* Sizes() { return GetTokenList(nsGkAtoms::sizes); } diff --git a/dom/html/HTMLOutputElement.cpp b/dom/html/HTMLOutputElement.cpp index 79c30cc653..a5c5c9d2cf 100644 --- a/dom/html/HTMLOutputElement.cpp +++ b/dom/html/HTMLOutputElement.cpp @@ -11,7 +11,7 @@ #include "mozilla/dom/HTMLFormElement.h" #include "mozilla/dom/HTMLOutputElementBinding.h" #include "nsContentUtils.h" -#include "nsDOMSettableTokenList.h" +#include "nsDOMTokenList.h" #include "nsFormSubmission.h" NS_IMPL_NS_NEW_HTML_ELEMENT_CHECK_PARSER(Output) @@ -166,11 +166,11 @@ HTMLOutputElement::SetDefaultValue(const nsAString& aDefaultValue, ErrorResult& } } -nsDOMSettableTokenList* +nsDOMTokenList* HTMLOutputElement::HtmlFor() { if (!mTokenList) { - mTokenList = new nsDOMSettableTokenList(this, nsGkAtoms::_for); + mTokenList = new nsDOMTokenList(this, nsGkAtoms::_for); } return mTokenList; } diff --git a/dom/html/HTMLOutputElement.h b/dom/html/HTMLOutputElement.h index 0f57cabfac..b9e6ecd9c4 100644 --- a/dom/html/HTMLOutputElement.h +++ b/dom/html/HTMLOutputElement.h @@ -64,7 +64,7 @@ public: virtual JSObject* WrapNode(JSContext* aCx, JS::Handle aGivenProto) override; // WebIDL - nsDOMSettableTokenList* HtmlFor(); + nsDOMTokenList* HtmlFor(); // nsGenericHTMLFormElement::GetForm is fine. void GetName(nsAString& aName) { @@ -108,7 +108,7 @@ protected: ValueModeFlag mValueModeFlag; bool mIsDoneAddingChildren; nsString mDefaultValue; - RefPtr mTokenList; + RefPtr mTokenList; }; } // namespace dom diff --git a/dom/html/HTMLPropertiesCollection.cpp b/dom/html/HTMLPropertiesCollection.cpp index 252b89a22e..3eb340a9d0 100644 --- a/dom/html/HTMLPropertiesCollection.cpp +++ b/dom/html/HTMLPropertiesCollection.cpp @@ -9,7 +9,7 @@ #include "nsContentUtils.h" #include "nsGenericHTMLElement.h" #include "nsVariant.h" -#include "nsDOMSettableTokenList.h" +#include "nsDOMTokenList.h" #include "nsAttrValue.h" #include "nsWrapperCacheInlines.h" #include "mozilla/dom/HTMLPropertiesCollectionBinding.h" diff --git a/dom/html/HTMLTableCellElement.h b/dom/html/HTMLTableCellElement.h index 80f666617e..570747227e 100644 --- a/dom/html/HTMLTableCellElement.h +++ b/dom/html/HTMLTableCellElement.h @@ -47,7 +47,7 @@ public: { SetHTMLIntAttr(nsGkAtoms::rowspan, aRowSpan, aError); } - //already_AddRefed Headers() const; + //already_AddRefed Headers() const; void GetHeaders(DOMString& aHeaders) { GetHTMLAttr(nsGkAtoms::headers, aHeaders); diff --git a/dom/html/nsGenericHTMLElement.cpp b/dom/html/nsGenericHTMLElement.cpp index 35f2771f06..195ca20c15 100644 --- a/dom/html/nsGenericHTMLElement.cpp +++ b/dom/html/nsGenericHTMLElement.cpp @@ -96,7 +96,7 @@ #include "HTMLPropertiesCollection.h" #include "nsVariant.h" -#include "nsDOMSettableTokenList.h" +#include "nsDOMTokenList.h" #include "nsThreadUtils.h" #include "nsTextFragment.h" #include "mozilla/dom/BindingUtils.h" diff --git a/dom/html/nsGenericHTMLElement.h b/dom/html/nsGenericHTMLElement.h index 8612ef2df0..d720ce2174 100644 --- a/dom/html/nsGenericHTMLElement.h +++ b/dom/html/nsGenericHTMLElement.h @@ -20,7 +20,7 @@ #include "mozilla/dom/ValidityState.h" #include "mozilla/dom/ElementInlines.h" -class nsDOMSettableTokenList; +class nsDOMTokenList; class nsIDOMHTMLMenuElement; class nsIEditor; class nsIFormControlFrame; @@ -104,7 +104,7 @@ public: { SetHTMLBoolAttr(nsGkAtoms::itemscope, aItemScope, aError); } - nsDOMSettableTokenList* ItemType() + nsDOMTokenList* ItemType() { return GetTokenList(nsGkAtoms::itemtype); } @@ -116,11 +116,11 @@ public: { SetHTMLAttr(nsGkAtoms::itemid, aItemID, aError); } - nsDOMSettableTokenList* ItemRef() + nsDOMTokenList* ItemRef() { return GetTokenList(nsGkAtoms::itemref); } - nsDOMSettableTokenList* ItemProp() + nsDOMTokenList* ItemProp() { return GetTokenList(nsGkAtoms::itemprop); } diff --git a/dom/html/test/forms/test_output_element.html b/dom/html/test/forms/test_output_element.html index a8f0f61715..5b4097047f 100644 --- a/dom/html/test/forms/test_output_element.html +++ b/dom/html/test/forms/test_output_element.html @@ -109,7 +109,7 @@ function checkHtmlForIDLAttribute(element) is(String(element.htmlFor), 'a b', "htmlFor IDL attribute should reflect the for content attribute"); - // DOMSettableTokenList is tested in another bug so we just test assignation + // DOMTokenList is tested in another bug so we just test assignation element.htmlFor.value = 'a b c'; is(String(element.htmlFor), 'a b c', "htmlFor should have changed"); } diff --git a/dom/html/test/test_bug845057.html b/dom/html/test/test_bug845057.html index 39c176748f..631cd2b5cc 100644 --- a/dom/html/test/test_bug845057.html +++ b/dom/html/test/test_bug845057.html @@ -26,8 +26,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=845057 return ((a+'').split(" ").sort()+'') == ((b+'').split(" ").sort()+''); } - ok(attr instanceof DOMSettableTokenList, - "Iframe sandbox attribute is instace of DOMSettableTokenList"); + ok(attr instanceof DOMTokenList, + "Iframe sandbox attribute is instace of DOMTokenList"); ok(eq(attr, "allow-scripts") && eq(iframe.getAttribute("sandbox"), "allow-scripts"), "Stringyfied sandbox attribute is same as that of the DOM element"); diff --git a/dom/imptests/html/dom/test_interface-objects.html b/dom/imptests/html/dom/test_interface-objects.html index c0697b566c..0e2bf1acdd 100644 --- a/dom/imptests/html/dom/test_interface-objects.html +++ b/dom/imptests/html/dom/test_interface-objects.html @@ -33,8 +33,7 @@ var interfaces = [ "HTMLCollection", "DOMStringList", "DOMTokenList", - "DOMSettableTokenList" -]; + ]; test(function() { for (var p in window) { interfaces.forEach(function(i) { diff --git a/dom/imptests/html/dom/test_interfaces.html b/dom/imptests/html/dom/test_interfaces.html index 2bc96ed11b..84a23b314e 100644 --- a/dom/imptests/html/dom/test_interfaces.html +++ b/dom/imptests/html/dom/test_interfaces.html @@ -278,6 +278,7 @@ interface Element : Node { attribute DOMString id; attribute DOMString className; + [PutForwards=value] readonly attribute DOMTokenList classList; readonly attribute Attr[] attributes; @@ -443,10 +444,7 @@ interface DOMTokenList { void remove(DOMString... tokens); boolean toggle(DOMString token, optional boolean force); stringifier; -}; - -interface DOMSettableTokenList : DOMTokenList { - attribute DOMString value; + attribute DOMString value; }; + + diff --git a/layout/reftests/web-animations/green-box.html b/layout/reftests/web-animations/green-box.html new file mode 100644 index 0000000000..5f5b4d11fe --- /dev/null +++ b/layout/reftests/web-animations/green-box.html @@ -0,0 +1,17 @@ + + + + + Reference green box + + + +
+ + diff --git a/layout/reftests/web-animations/reftest.list b/layout/reftests/web-animations/reftest.list new file mode 100644 index 0000000000..f2befe2ba2 --- /dev/null +++ b/layout/reftests/web-animations/reftest.list @@ -0,0 +1 @@ +== 1246046-1.html green-box.html diff --git a/layout/style/AnimationCommon.cpp b/layout/style/AnimationCommon.cpp index cff8b5c810..330086493c 100644 --- a/layout/style/AnimationCommon.cpp +++ b/layout/style/AnimationCommon.cpp @@ -68,7 +68,7 @@ CommonAnimationManager::RemoveAllElementCollections() AnimationCollection* CommonAnimationManager::GetAnimationCollection(dom::Element *aElement, - nsCSSPseudoElements::Type + CSSPseudoElementType aPseudoType, bool aCreateIfNeeded) { @@ -78,11 +78,11 @@ CommonAnimationManager::GetAnimationCollection(dom::Element *aElement, } nsIAtom *propName; - if (aPseudoType == nsCSSPseudoElements::ePseudo_NotPseudoElement) { + if (aPseudoType == CSSPseudoElementType::NotPseudo) { propName = GetAnimationsAtom(); - } else if (aPseudoType == nsCSSPseudoElements::ePseudo_before) { + } else if (aPseudoType == CSSPseudoElementType::before) { propName = GetAnimationsBeforeAtom(); - } else if (aPseudoType == nsCSSPseudoElements::ePseudo_after) { + } else if (aPseudoType == CSSPseudoElementType::after) { propName = GetAnimationsAfterAtom(); } else { NS_ASSERTION(!aCreateIfNeeded, @@ -105,9 +105,8 @@ CommonAnimationManager::GetAnimationCollection(dom::Element *aElement, AnimationCollection::PropertyDtor(aElement, propName, collection, nullptr); return nullptr; } - if (aPseudoType == nsCSSPseudoElements::ePseudo_NotPseudoElement) { - aElement->SetMayHaveAnimations(); - } + + aElement->SetMayHaveAnimations(); AddElementCollection(collection); } @@ -118,15 +117,13 @@ CommonAnimationManager::GetAnimationCollection(dom::Element *aElement, AnimationCollection* CommonAnimationManager::GetAnimationCollection(const nsIFrame* aFrame) { - Maybe> pseudoElement = + Maybe> pseudoElement = EffectCompositor::GetAnimationElementAndPseudoForFrame(aFrame); if (!pseudoElement) { return nullptr; } - if (pseudoElement->second() == - nsCSSPseudoElements::ePseudo_NotPseudoElement && - !pseudoElement->first()->MayHaveAnimations()) { + if (!pseudoElement->first()->MayHaveAnimations()) { return nullptr; } @@ -135,121 +132,6 @@ CommonAnimationManager::GetAnimationCollection(const nsIFrame* aFrame) false /* aCreateIfNeeded */); } -nsRestyleHint -CommonAnimationManager::HasStateDependentStyle(StateRuleProcessorData* aData) -{ - return nsRestyleHint(0); -} - -nsRestyleHint -CommonAnimationManager::HasStateDependentStyle(PseudoElementStateRuleProcessorData* aData) -{ - return nsRestyleHint(0); -} - -bool -CommonAnimationManager::HasDocumentStateDependentStyle(StateRuleProcessorData* aData) -{ - return false; -} - -nsRestyleHint -CommonAnimationManager::HasAttributeDependentStyle( - AttributeRuleProcessorData* aData, - RestyleHintData& aRestyleHintDataResult) -{ - return nsRestyleHint(0); -} - -/* virtual */ bool -CommonAnimationManager::MediumFeaturesChanged(nsPresContext* aPresContext) -{ - return false; -} - -/* virtual */ void -CommonAnimationManager::RulesMatching(ElementRuleProcessorData* aData) -{ - MOZ_ASSERT(aData->mPresContext == mPresContext, - "pres context mismatch"); - - EffectCompositor::CascadeLevel cascadeLevel = - IsAnimationManager() ? - EffectCompositor::CascadeLevel::Animations : - EffectCompositor::CascadeLevel::Transitions; - nsCSSPseudoElements::Type pseudoType = - nsCSSPseudoElements::ePseudo_NotPseudoElement; - - nsIStyleRule *rule = - mPresContext->EffectCompositor()->GetAnimationRule(aData->mElement, - pseudoType, - cascadeLevel); - - if (rule) { - aData->mRuleWalker->Forward(rule); - aData->mRuleWalker->CurrentNode()->SetIsAnimationRule(); - } -} - -/* virtual */ void -CommonAnimationManager::RulesMatching(PseudoElementRuleProcessorData* aData) -{ - MOZ_ASSERT(aData->mPresContext == mPresContext, - "pres context mismatch"); - if (aData->mPseudoType != nsCSSPseudoElements::ePseudo_before && - aData->mPseudoType != nsCSSPseudoElements::ePseudo_after) { - return; - } - - // FIXME: Do we really want to be the only thing keeping a - // pseudo-element alive? I *think* the non-animation restyle should - // handle that, but should add a test. - - EffectCompositor::CascadeLevel cascadeLevel = - IsAnimationManager() ? - EffectCompositor::CascadeLevel::Animations : - EffectCompositor::CascadeLevel::Transitions; - nsIStyleRule *rule = - mPresContext->EffectCompositor()->GetAnimationRule(aData->mElement, - aData->mPseudoType, - cascadeLevel); - if (rule) { - aData->mRuleWalker->Forward(rule); - aData->mRuleWalker->CurrentNode()->SetIsAnimationRule(); - } -} - -/* virtual */ void -CommonAnimationManager::RulesMatching(AnonBoxRuleProcessorData* aData) -{ -} - -#ifdef MOZ_XUL -/* virtual */ void -CommonAnimationManager::RulesMatching(XULTreeRuleProcessorData* aData) -{ -} -#endif - -/* virtual */ size_t -CommonAnimationManager::SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const -{ - // Measurement of the following members may be added later if DMD finds it is - // worthwhile: - // - mElementCollections - // - // The following members are not measured - // - mPresContext, because it's non-owning - - return 0; -} - -/* virtual */ size_t -CommonAnimationManager::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const -{ - return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf); -} - /* static */ bool CommonAnimationManager::ExtractComputedValueForTransition( nsCSSProperty aProperty, @@ -270,15 +152,15 @@ CommonAnimationManager::ExtractComputedValueForTransition( } /*static*/ nsString -AnimationCollection::PseudoTypeAsString(nsCSSPseudoElements::Type aPseudoType) +AnimationCollection::PseudoTypeAsString(CSSPseudoElementType aPseudoType) { switch (aPseudoType) { - case nsCSSPseudoElements::ePseudo_before: + case CSSPseudoElementType::before: return NS_LITERAL_STRING("::before"); - case nsCSSPseudoElements::ePseudo_after: + case CSSPseudoElementType::after: return NS_LITERAL_STRING("::after"); default: - MOZ_ASSERT(aPseudoType == nsCSSPseudoElements::ePseudo_NotPseudoElement, + MOZ_ASSERT(aPseudoType == CSSPseudoElementType::NotPseudo, "Unexpected pseudo type"); return EmptyString(); } diff --git a/layout/style/AnimationCommon.h b/layout/style/AnimationCommon.h index c0ecb07eac..2b492827ee 100644 --- a/layout/style/AnimationCommon.h +++ b/layout/style/AnimationCommon.h @@ -7,7 +7,6 @@ #define mozilla_css_AnimationCommon_h #include // For -#include "nsIStyleRuleProcessor.h" #include "nsChangeHint.h" #include "nsCSSProperty.h" #include "nsDisplayList.h" // For nsDisplayItem::Type @@ -33,29 +32,10 @@ namespace mozilla { struct AnimationCollection; -class CommonAnimationManager : public nsIStyleRuleProcessor { +class CommonAnimationManager { public: explicit CommonAnimationManager(nsPresContext *aPresContext); - // nsIStyleRuleProcessor (parts) - virtual nsRestyleHint HasStateDependentStyle(StateRuleProcessorData* aData) override; - virtual nsRestyleHint HasStateDependentStyle(PseudoElementStateRuleProcessorData* aData) override; - virtual bool HasDocumentStateDependentStyle(StateRuleProcessorData* aData) override; - virtual nsRestyleHint - HasAttributeDependentStyle(AttributeRuleProcessorData* aData, - RestyleHintData& aRestyleHintDataResult) override; - virtual bool MediumFeaturesChanged(nsPresContext* aPresContext) override; - virtual void RulesMatching(ElementRuleProcessorData* aData) override; - virtual void RulesMatching(PseudoElementRuleProcessorData* aData) override; - virtual void RulesMatching(AnonBoxRuleProcessorData* aData) override; -#ifdef MOZ_XUL - virtual void RulesMatching(XULTreeRuleProcessorData* aData) override; -#endif - virtual size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) - const MOZ_MUST_OVERRIDE override; - virtual size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) - const MOZ_MUST_OVERRIDE override; - // NOTE: This can return null after Disconnect(). nsPresContext* PresContext() const { return mPresContext; } @@ -103,7 +83,7 @@ public: // by this class for the given |aElement| and |aPseudoType|. AnimationCollection* GetAnimationCollection(dom::Element *aElement, - nsCSSPseudoElements::Type aPseudoType, + CSSPseudoElementType aPseudoType, bool aCreateIfNeeded); // Given the frame |aFrame| with possibly animated content, finds its @@ -194,20 +174,20 @@ public: mElementProperty == nsGkAtoms::animationsOfAfterProperty; } - nsCSSPseudoElements::Type PseudoElementType() const + CSSPseudoElementType PseudoElementType() const { if (IsForElement()) { - return nsCSSPseudoElements::ePseudo_NotPseudoElement; + return CSSPseudoElementType::NotPseudo; } if (IsForBeforePseudo()) { - return nsCSSPseudoElements::ePseudo_before; + return CSSPseudoElementType::before; } MOZ_ASSERT(IsForAfterPseudo(), "::before & ::after should be the only pseudo-elements here"); - return nsCSSPseudoElements::ePseudo_after; + return CSSPseudoElementType::after; } - static nsString PseudoTypeAsString(nsCSSPseudoElements::Type aPseudoType); + static nsString PseudoTypeAsString(CSSPseudoElementType aPseudoType); dom::Element* GetElementToRestyle() const; @@ -255,11 +235,11 @@ class OwningElementRef final public: OwningElementRef() : mElement(nullptr) - , mPseudoType(nsCSSPseudoElements::ePseudo_NotPseudoElement) + , mPseudoType(CSSPseudoElementType::NotPseudo) { } OwningElementRef(dom::Element& aElement, - nsCSSPseudoElements::Type aPseudoType) + CSSPseudoElementType aPseudoType) : mElement(&aElement) , mPseudoType(aPseudoType) { } @@ -279,15 +259,15 @@ public: return nsContentUtils::PositionIsBefore(mElement, aOther.mElement); } - return mPseudoType == nsCSSPseudoElements::ePseudo_NotPseudoElement || - (mPseudoType == nsCSSPseudoElements::ePseudo_before && - aOther.mPseudoType == nsCSSPseudoElements::ePseudo_after); + return mPseudoType == CSSPseudoElementType::NotPseudo || + (mPseudoType == CSSPseudoElementType::before && + aOther.mPseudoType == CSSPseudoElementType::after); } bool IsSet() const { return !!mElement; } void GetElement(dom::Element*& aElement, - nsCSSPseudoElements::Type& aPseudoType) const { + CSSPseudoElementType& aPseudoType) const { aElement = mElement; aPseudoType = mPseudoType; } @@ -296,7 +276,7 @@ public: private: dom::Element* MOZ_NON_OWNING_REF mElement; - nsCSSPseudoElements::Type mPseudoType; + CSSPseudoElementType mPseudoType; }; template diff --git a/layout/style/Declaration.cpp b/layout/style/Declaration.cpp index 3ecdc67144..d2cb902f3b 100644 --- a/layout/style/Declaration.cpp +++ b/layout/style/Declaration.cpp @@ -1123,10 +1123,10 @@ Declaration::GetValue(nsCSSProperty aProperty, nsAString& aValue, AppendValueToString(eCSSProperty_grid_auto_flow, aValue, aSerialization); aValue.Append(char16_t(' ')); - AppendValueToString(eCSSProperty_grid_auto_columns, + AppendValueToString(eCSSProperty_grid_auto_rows, aValue, aSerialization); aValue.AppendLiteral(" / "); - AppendValueToString(eCSSProperty_grid_auto_rows, + AppendValueToString(eCSSProperty_grid_auto_columns, aValue, aSerialization); break; } else if (!(autoFlowValue.GetUnit() == eCSSUnit_Enumerated && @@ -1147,10 +1147,10 @@ Declaration::GetValue(nsCSSProperty aProperty, nsAString& aValue, const nsCSSValue& rowsValue = *data->ValueFor(eCSSProperty_grid_template_rows); if (areasValue.GetUnit() == eCSSUnit_None) { - AppendValueToString(eCSSProperty_grid_template_columns, + AppendValueToString(eCSSProperty_grid_template_rows, aValue, aSerialization); aValue.AppendLiteral(" / "); - AppendValueToString(eCSSProperty_grid_template_rows, + AppendValueToString(eCSSProperty_grid_template_columns, aValue, aSerialization); break; } @@ -1188,11 +1188,6 @@ Declaration::GetValue(nsCSSProperty aProperty, nsAString& aValue, // Not serializable, bail. return; } - if (columnsValue.GetUnit() != eCSSUnit_None) { - AppendValueToString(eCSSProperty_grid_template_columns, - aValue, aSerialization); - aValue.AppendLiteral(" / "); - } rowsItem = rowsValue.GetListValue(); uint32_t row = 0; for (;;) { @@ -1234,6 +1229,11 @@ Declaration::GetValue(nsCSSProperty aProperty, nsAString& aValue, aValue.Append(char16_t(' ')); } } + if (columnsValue.GetUnit() != eCSSUnit_None) { + aValue.AppendLiteral(" / "); + AppendValueToString(eCSSProperty_grid_template_columns, + aValue, aSerialization); + } break; } case eCSSProperty_grid_gap: { diff --git a/layout/style/StyleAnimationValue.cpp b/layout/style/StyleAnimationValue.cpp index 76f6b9f54f..0445f42635 100644 --- a/layout/style/StyleAnimationValue.cpp +++ b/layout/style/StyleAnimationValue.cpp @@ -19,6 +19,7 @@ #include "nsStyleSet.h" #include "nsComputedDOMStyle.h" #include "nsCSSParser.h" +#include "nsCSSPseudoElements.h" #include "mozilla/css/Declaration.h" #include "mozilla/dom/Element.h" #include "mozilla/FloatingPoint.h" @@ -2526,7 +2527,7 @@ BuildStyleRule(nsCSSProperty aProperty, inline already_AddRefed LookupStyleContext(dom::Element* aElement, - nsCSSPseudoElements::Type aPseudoType) + CSSPseudoElementType aPseudoType) { nsIDocument* doc = aElement->GetCurrentDoc(); nsIPresShell* shell = doc->GetShell(); @@ -2535,7 +2536,7 @@ LookupStyleContext(dom::Element* aElement, } nsIAtom* pseudo = - aPseudoType < nsCSSPseudoElements::ePseudo_PseudoElementCount ? + aPseudoType < CSSPseudoElementType::Count ? nsCSSPseudoElements::GetPseudoAtom(aPseudoType) : nullptr; return nsComputedDOMStyle::GetStyleContextForElement(aElement, pseudo, shell); } @@ -2543,7 +2544,7 @@ LookupStyleContext(dom::Element* aElement, /* static */ bool StyleAnimationValue::ComputeValue(nsCSSProperty aProperty, dom::Element* aTargetElement, - nsCSSPseudoElements::Type aPseudoType, + CSSPseudoElementType aPseudoType, const nsAString& aSpecifiedValue, bool aUseSVGMode, StyleAnimationValue& aComputedValue, @@ -2595,7 +2596,7 @@ StyleAnimationValue::ComputeValue(nsCSSProperty aProperty, StyleAnimationValue::ComputeValues(nsCSSProperty aProperty, nsCSSProps::EnabledState aEnabledState, dom::Element* aTargetElement, - nsCSSPseudoElements::Type aPseudoType, + CSSPseudoElementType aPseudoType, const nsAString& aSpecifiedValue, bool aUseSVGMode, nsTArray& aResult) @@ -2625,7 +2626,7 @@ StyleAnimationValue::ComputeValues( nsCSSProperty aProperty, nsCSSProps::EnabledState aEnabledState, dom::Element* aTargetElement, - nsCSSPseudoElements::Type aPseudoType, + CSSPseudoElementType aPseudoType, css::StyleRule* aStyleRule, nsTArray& aValues, bool* aIsContextSensitive) diff --git a/layout/style/StyleAnimationValue.h b/layout/style/StyleAnimationValue.h index 1af9a922c4..09798cd9a7 100644 --- a/layout/style/StyleAnimationValue.h +++ b/layout/style/StyleAnimationValue.h @@ -14,7 +14,6 @@ #include "nsCoord.h" #include "nsColor.h" #include "nsCSSProps.h" -#include "nsCSSPseudoElements.h" #include "nsCSSValue.h" class nsIFrame; @@ -31,6 +30,7 @@ namespace dom { class Element; } // namespace dom +enum class CSSPseudoElementType : uint8_t; struct PropertyStyleAnimationValuePair; /** @@ -156,7 +156,7 @@ public: */ static bool ComputeValue(nsCSSProperty aProperty, mozilla::dom::Element* aTargetElement, - nsCSSPseudoElements::Type aPseudoType, + CSSPseudoElementType aPseudoType, const nsAString& aSpecifiedValue, bool aUseSVGMode, StyleAnimationValue& aComputedValue, @@ -175,7 +175,7 @@ public: static bool ComputeValues(nsCSSProperty aProperty, nsCSSProps::EnabledState aEnabledState, mozilla::dom::Element* aTargetElement, - nsCSSPseudoElements::Type aPseudoType, + CSSPseudoElementType aPseudoType, const nsAString& aSpecifiedValue, bool aUseSVGMode, nsTArray& aResult); @@ -403,7 +403,7 @@ private: static bool ComputeValues(nsCSSProperty aProperty, nsCSSProps::EnabledState aEnabledState, mozilla::dom::Element* aTargetElement, - nsCSSPseudoElements::Type aPseudoType, + CSSPseudoElementType aPseudoType, mozilla::css::StyleRule* aStyleRule, nsTArray& aValues, bool* aIsContextSensitive); diff --git a/layout/style/StyleRule.cpp b/layout/style/StyleRule.cpp index 4b789a6d1d..d3f2c12ee4 100644 --- a/layout/style/StyleRule.cpp +++ b/layout/style/StyleRule.cpp @@ -23,7 +23,6 @@ #include "nsDOMCSSDeclaration.h" #include "nsNameSpaceManager.h" #include "nsXMLNameSpaceMap.h" -#include "nsCSSPseudoElements.h" #include "nsCSSPseudoClasses.h" #include "nsCSSAnonBoxes.h" #include "nsTArray.h" @@ -222,7 +221,8 @@ nsAttrSelector::nsAttrSelector(int32_t aNameSpace, const nsString& aAttr) mCasedAttr(nullptr), mNameSpace(aNameSpace), mFunction(NS_ATTR_FUNC_SET), - mCaseSensitive(1) + // mValueCaseSensitivity doesn't matter; we have no value. + mValueCaseSensitivity(ValueCaseSensitivity::CaseSensitive) { MOZ_COUNT_CTOR(nsAttrSelector); @@ -234,14 +234,15 @@ nsAttrSelector::nsAttrSelector(int32_t aNameSpace, const nsString& aAttr) } nsAttrSelector::nsAttrSelector(int32_t aNameSpace, const nsString& aAttr, uint8_t aFunction, - const nsString& aValue, bool aCaseSensitive) + const nsString& aValue, + ValueCaseSensitivity aValueCaseSensitivity) : mValue(aValue), mNext(nullptr), mLowercaseAttr(nullptr), mCasedAttr(nullptr), mNameSpace(aNameSpace), mFunction(aFunction), - mCaseSensitive(aCaseSensitive) + mValueCaseSensitivity(aValueCaseSensitivity) { MOZ_COUNT_CTOR(nsAttrSelector); @@ -254,14 +255,15 @@ nsAttrSelector::nsAttrSelector(int32_t aNameSpace, const nsString& aAttr, uint8_ nsAttrSelector::nsAttrSelector(int32_t aNameSpace, nsIAtom* aLowercaseAttr, nsIAtom* aCasedAttr, uint8_t aFunction, - const nsString& aValue, bool aCaseSensitive) + const nsString& aValue, + ValueCaseSensitivity aValueCaseSensitivity) : mValue(aValue), mNext(nullptr), mLowercaseAttr(aLowercaseAttr), mCasedAttr(aCasedAttr), mNameSpace(aNameSpace), mFunction(aFunction), - mCaseSensitive(aCaseSensitive) + mValueCaseSensitivity(aValueCaseSensitivity) { MOZ_COUNT_CTOR(nsAttrSelector); } @@ -271,7 +273,7 @@ nsAttrSelector::Clone(bool aDeep) const { nsAttrSelector *result = new nsAttrSelector(mNameSpace, mLowercaseAttr, mCasedAttr, - mFunction, mValue, mCaseSensitive); + mFunction, mValue, mValueCaseSensitivity); if (aDeep) NS_CSS_CLONE_LIST_MEMBER(nsAttrSelector, this, mNext, result, (false)); @@ -312,11 +314,11 @@ nsCSSSelector::nsCSSSelector(void) mNext(nullptr), mNameSpace(kNameSpaceID_Unknown), mOperator(0), - mPseudoType(nsCSSPseudoElements::ePseudo_NotPseudoElement) + mPseudoType(static_cast(CSSPseudoElementType::NotPseudo)) { MOZ_COUNT_CTOR(nsCSSSelector); - static_assert(nsCSSPseudoElements::ePseudo_MAX < INT16_MAX, - "nsCSSPseudoElements::Type values overflow mPseudoType"); + static_assert(static_cast(CSSPseudoElementType::MAX) < INT16_MAX, + "CSSPseudoElementType values overflow mPseudoType"); } nsCSSSelector* @@ -466,14 +468,15 @@ void nsCSSSelector::AddAttribute(int32_t aNameSpace, const nsString& aAttr) } void nsCSSSelector::AddAttribute(int32_t aNameSpace, const nsString& aAttr, uint8_t aFunc, - const nsString& aValue, bool aCaseSensitive) + const nsString& aValue, + nsAttrSelector::ValueCaseSensitivity aCaseSensitivity) { if (!aAttr.IsEmpty()) { nsAttrSelector** list = &mAttrList; while (nullptr != *list) { list = &((*list)->mNext); } - *list = new nsAttrSelector(aNameSpace, aAttr, aFunc, aValue, aCaseSensitive); + *list = new nsAttrSelector(aNameSpace, aAttr, aFunc, aValue, aCaseSensitivity); } } @@ -488,7 +491,7 @@ int32_t nsCSSSelector::CalcWeightWithoutNegations() const #ifdef MOZ_XUL MOZ_ASSERT(!(IsPseudoElement() && - PseudoType() != nsCSSPseudoElements::ePseudo_XULTree && + PseudoType() != CSSPseudoElementType::XULTree && mClassList), "If non-XUL-tree pseudo-elements can have class selectors " "after them, specificity calculation must be updated"); @@ -513,7 +516,7 @@ int32_t nsCSSSelector::CalcWeightWithoutNegations() const #ifdef MOZ_XUL // XUL tree pseudo-elements abuse mClassList to store some private // data; ignore that. - if (PseudoType() == nsCSSPseudoElements::ePseudo_XULTree) { + if (PseudoType() == CSSPseudoElementType::XULTree) { list = nullptr; } #endif @@ -865,6 +868,11 @@ nsCSSSelector::AppendToStringWithoutCombinatorsOrNegations // Append the value nsStyleUtil::AppendEscapedCSSString(list->mValue, aString); + + if (list->mValueCaseSensitivity == + nsAttrSelector::ValueCaseSensitivity::CaseInsensitive) { + aString.Append(NS_LITERAL_STRING(" i")); + } } aString.Append(char16_t(']')); diff --git a/layout/style/StyleRule.h b/layout/style/StyleRule.h index 5383854f0e..4fb1bf8e3d 100644 --- a/layout/style/StyleRule.h +++ b/layout/style/StyleRule.h @@ -17,8 +17,8 @@ #include "nsString.h" #include "nsCOMPtr.h" -#include "nsCSSPseudoElements.h" #include "nsCSSPseudoClasses.h" +#include "nsCSSPseudoElements.h" #include "nsIStyleRule.h" class nsIAtom; @@ -96,12 +96,20 @@ private: struct nsAttrSelector { public: + enum class ValueCaseSensitivity : uint8_t { + CaseSensitive, + CaseInsensitive, + CaseInsensitiveInHTML + }; + nsAttrSelector(int32_t aNameSpace, const nsString& aAttr); nsAttrSelector(int32_t aNameSpace, const nsString& aAttr, uint8_t aFunction, - const nsString& aValue, bool aCaseSensitive); + const nsString& aValue, + ValueCaseSensitivity aValueCaseSensitivity); nsAttrSelector(int32_t aNameSpace, nsIAtom* aLowercaseAttr, nsIAtom* aCasedAttr, uint8_t aFunction, - const nsString& aValue, bool aCaseSensitive); + const nsString& aValue, + ValueCaseSensitivity aValueCaseSensitivity); ~nsAttrSelector(void); /** Do a deep clone. Should be used only on the first in the linked list. */ @@ -109,14 +117,20 @@ public: size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const; + bool IsValueCaseSensitive(bool aInHTML) const { + return mValueCaseSensitivity == ValueCaseSensitivity::CaseSensitive || + (!aInHTML && + mValueCaseSensitivity == ValueCaseSensitivity::CaseInsensitiveInHTML); + } + nsString mValue; nsAttrSelector* mNext; nsCOMPtr mLowercaseAttr; nsCOMPtr mCasedAttr; int32_t mNameSpace; uint8_t mFunction; - bool mCaseSensitive; // If we are in an HTML document, - // is the value case sensitive? + ValueCaseSensitivity mValueCaseSensitivity; + private: nsAttrSelector* Clone(bool aDeep) const; @@ -145,7 +159,8 @@ public: nsCSSSelectorList* aSelectorList); void AddAttribute(int32_t aNameSpace, const nsString& aAttr); void AddAttribute(int32_t aNameSpace, const nsString& aAttr, uint8_t aFunc, - const nsString& aValue, bool aCaseSensitive); + const nsString& aValue, + nsAttrSelector::ValueCaseSensitivity aValueCaseSensitivity); void SetOperator(char16_t aOperator); inline bool HasTagSelector() const { @@ -163,7 +178,7 @@ public: bool aAppend = false) const; bool IsRestrictedSelector() const { - return PseudoType() == nsCSSPseudoElements::ePseudo_NotPseudoElement; + return PseudoType() == mozilla::CSSPseudoElementType::NotPseudo; } #ifdef DEBUG @@ -193,13 +208,10 @@ private: public: // Get and set the selector's pseudo type - nsCSSPseudoElements::Type PseudoType() const { - return static_cast(mPseudoType); + mozilla::CSSPseudoElementType PseudoType() const { + return static_cast(mPseudoType); } - void SetPseudoType(nsCSSPseudoElements::Type aType) { - NS_ASSERTION(static_cast(aType) >= INT16_MIN && - static_cast(aType) <= INT16_MAX, - "Out of bounds - this will overflow mPseudoType"); + void SetPseudoType(mozilla::CSSPseudoElementType aType) { mPseudoType = static_cast(aType); } diff --git a/layout/style/crashtests/1247865-1.html b/layout/style/crashtests/1247865-1.html new file mode 100644 index 0000000000..b7ec8ba60a --- /dev/null +++ b/layout/style/crashtests/1247865-1.html @@ -0,0 +1,19 @@ + + + + + + +
+ + + + diff --git a/layout/style/crashtests/crashtests.list b/layout/style/crashtests/crashtests.list index ac36df6f61..0fd1efed26 100644 --- a/layout/style/crashtests/crashtests.list +++ b/layout/style/crashtests/crashtests.list @@ -132,6 +132,7 @@ load 1230408-1.html load 1233135-1.html load 1233135-2.html load 1238660-1.html +load 1247865-1.html load border-image-visited-link.html load font-face-truncated-src.html load large_border_image_width.html diff --git a/layout/style/nsAnimationManager.cpp b/layout/style/nsAnimationManager.cpp index 643ccd5644..5225cb12bc 100644 --- a/layout/style/nsAnimationManager.cpp +++ b/layout/style/nsAnimationManager.cpp @@ -124,43 +124,24 @@ CSSAnimation::Tick() } bool -CSSAnimation::HasLowerCompositeOrderThan(const Animation& aOther) const +CSSAnimation::HasLowerCompositeOrderThan(const CSSAnimation& aOther) const { + MOZ_ASSERT(IsTiedToMarkup() && aOther.IsTiedToMarkup(), + "Should only be called for CSS animations that are sorted " + "as CSS animations (i.e. tied to CSS markup)"); + // 0. Object-equality case if (&aOther == this) { return false; } - // 1. Transitions sort lower - // - // FIXME: We need to differentiate between transitions and generic Animations. - // Generic animations don't exist yet (that's bug 1096773) so for now we're - // ok. - const CSSAnimation* otherAnimation = aOther.AsCSSAnimation(); - if (!otherAnimation) { - MOZ_ASSERT(aOther.AsCSSTransition(), - "Animation being compared is a CSS transition"); - return false; + // 1. Sort by document order + if (!mOwningElement.Equals(aOther.mOwningElement)) { + return mOwningElement.LessThan(aOther.mOwningElement); } - // 2. CSS animations that correspond to an animation-name property sort lower - // than other CSS animations (e.g. those created or kept-alive by script). - if (!IsTiedToMarkup()) { - return !otherAnimation->IsTiedToMarkup() ? - Animation::HasLowerCompositeOrderThan(aOther) : - false; - } - if (!otherAnimation->IsTiedToMarkup()) { - return true; - } - - // 3. Sort by document order - if (!mOwningElement.Equals(otherAnimation->mOwningElement)) { - return mOwningElement.LessThan(otherAnimation->mOwningElement); - } - - // 4. (Same element and pseudo): Sort by position in animation-name - return mAnimationIndex < otherAnimation->mAnimationIndex; + // 2. (Same element and pseudo): Sort by position in animation-name + return mAnimationIndex < aOther.mAnimationIndex; } void @@ -187,7 +168,7 @@ CSSAnimation::QueueEvents() } dom::Element* owningElement; - nsCSSPseudoElements::Type owningPseudoType; + CSSPseudoElementType owningPseudoType; mOwningElement.GetElement(owningElement, owningPseudoType); MOZ_ASSERT(owningElement, "Owning element should be set"); @@ -317,39 +298,18 @@ CSSAnimation::ElapsedTimeToTimeStamp(const StickyTimeDuration& NS_IMPL_CYCLE_COLLECTION(nsAnimationManager, mEventDispatcher) -NS_IMPL_CYCLE_COLLECTING_ADDREF(nsAnimationManager) -NS_IMPL_CYCLE_COLLECTING_RELEASE(nsAnimationManager) +NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(nsAnimationManager, AddRef) +NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(nsAnimationManager, Release) -NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsAnimationManager) - NS_INTERFACE_MAP_ENTRY(nsIStyleRuleProcessor) - NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIStyleRuleProcessor) -NS_INTERFACE_MAP_END - -/* virtual */ size_t -nsAnimationManager::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const +void +nsAnimationManager::UpdateAnimations(nsStyleContext* aStyleContext, + mozilla::dom::Element* aElement) { - return CommonAnimationManager::SizeOfExcludingThis(aMallocSizeOf); - - // Measurement of the following members may be added later if DMD finds it is - // worthwhile: - // - mEventDispatcher -} - -/* virtual */ size_t -nsAnimationManager::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const -{ - return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf); -} - -nsIStyleRule* -nsAnimationManager::CheckAnimationRule(nsStyleContext* aStyleContext, - mozilla::dom::Element* aElement) -{ - // Ignore animations for print or print preview, and for elements - // that are not attached to the document tree. - if (!mPresContext->IsDynamic() || !aElement->IsInComposedDoc()) { - return nullptr; - } + MOZ_ASSERT(mPresContext->IsDynamic(), + "Should not update animations for print or print preview"); + MOZ_ASSERT(aElement->IsInComposedDoc(), + "Should not update animations that are not attached to the " + "document tree"); // Everything that causes our animation data to change triggers a // style change, which in turn triggers a non-animation restyle. @@ -364,7 +324,7 @@ nsAnimationManager::CheckAnimationRule(nsStyleContext* aStyleContext, if (!collection && disp->mAnimationNameCount == 1 && disp->mAnimations[0].GetName().IsEmpty()) { - return nullptr; + return; } nsAutoAnimationMutationBatch mb(aElement->OwnerDoc()); @@ -380,7 +340,7 @@ nsAnimationManager::CheckAnimationRule(nsStyleContext* aStyleContext, if (collection) { collection->Destroy(); } - return nullptr; + return; } if (collection) { @@ -511,12 +471,10 @@ nsAnimationManager::CheckAnimationRule(nsStyleContext* aStyleContext, aStyleContext->GetPseudoType(), aStyleContext); - EffectCompositor::CascadeLevel cascadeLevel = - EffectCompositor::CascadeLevel::Animations; - mPresContext->EffectCompositor() - ->MaybeUpdateAnimationRule(aElement, - aStyleContext->GetPseudoType(), - cascadeLevel); + mPresContext->EffectCompositor()-> + MaybeUpdateAnimationRule(aElement, + aStyleContext->GetPseudoType(), + EffectCompositor::CascadeLevel::Animations); // We don't actually dispatch the pending events now. We'll either // dispatch them the next time we get a refresh driver notification @@ -525,17 +483,12 @@ nsAnimationManager::CheckAnimationRule(nsStyleContext* aStyleContext, if (mEventDispatcher.HasQueuedEvents()) { mPresContext->Document()->SetNeedStyleFlush(); } - - return mPresContext->EffectCompositor() - ->GetAnimationRule(aElement, - aStyleContext->GetPseudoType(), - cascadeLevel); } void nsAnimationManager::StopAnimationsForElement( mozilla::dom::Element* aElement, - nsCSSPseudoElements::Type aPseudoType) + mozilla::CSSPseudoElementType aPseudoType) { MOZ_ASSERT(aElement); AnimationCollection* collection = diff --git a/layout/style/nsAnimationManager.h b/layout/style/nsAnimationManager.h index 6aa1cd2731..7869e59074 100644 --- a/layout/style/nsAnimationManager.h +++ b/layout/style/nsAnimationManager.h @@ -9,7 +9,6 @@ #include "mozilla/ContentEvents.h" #include "mozilla/EventForwards.h" #include "AnimationCommon.h" -#include "nsCSSPseudoElements.h" #include "mozilla/dom/Animation.h" #include "mozilla/MemoryReporting.h" #include "mozilla/TimeStamp.h" @@ -26,6 +25,8 @@ class KeyframeEffectReadOnly; class Promise; } /* namespace dom */ +enum class CSSPseudoElementType : uint8_t; + struct AnimationEventInfo { RefPtr mElement; RefPtr mAnimation; @@ -33,7 +34,7 @@ struct AnimationEventInfo { TimeStamp mTimeStamp; AnimationEventInfo(dom::Element* aElement, - nsCSSPseudoElements::Type aPseudoType, + CSSPseudoElementType aPseudoType, EventMessage aMessage, const nsSubstring& aAnimationName, const StickyTimeDuration& aElapsedTime, @@ -130,7 +131,7 @@ public: bool IsStylePaused() const { return mIsStylePaused; } - bool HasLowerCompositeOrderThan(const Animation& aOther) const override; + bool HasLowerCompositeOrderThan(const CSSAnimation& aOther) const; void SetAnimationIndex(uint64_t aIndex) { @@ -280,28 +281,19 @@ public: { } - NS_DECL_CYCLE_COLLECTION_CLASS(nsAnimationManager) - NS_DECL_CYCLE_COLLECTING_ISUPPORTS - - // nsIStyleRuleProcessor (parts) - virtual size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) - const MOZ_MUST_OVERRIDE override; - virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) - const MOZ_MUST_OVERRIDE override; + NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(nsAnimationManager) + NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(nsAnimationManager) /** - * Return the style rule that RulesMatching should add for - * aStyleContext. This might be different from what RulesMatching - * actually added during aStyleContext's construction because the - * element's animation-name may have changed. (However, this does - * return null during the non-animation restyling phase, as - * RulesMatching does.) + * Update the set of animations on |aElement| based on |aStyleContext|. + * If necessary, this will notify the corresponding EffectCompositor so + * that it can update its animation rule. * * aStyleContext may be a style context for aElement or for its * :before or :after pseudo-element. */ - nsIStyleRule* CheckAnimationRule(nsStyleContext* aStyleContext, - mozilla::dom::Element* aElement); + void UpdateAnimations(nsStyleContext* aStyleContext, + mozilla::dom::Element* aElement); /** * Add a pending event. @@ -319,7 +311,11 @@ public: * accumulate animationstart events at other points when style * contexts are created. */ - void DispatchEvents() { mEventDispatcher.DispatchEvents(mPresContext); } + void DispatchEvents() + { + RefPtr kungFuDeathGrip(this); + mEventDispatcher.DispatchEvents(mPresContext); + } void SortEvents() { mEventDispatcher.SortEvents(); } void ClearEventQueue() { mEventDispatcher.ClearEventQueue(); } @@ -327,7 +323,7 @@ public: // rather than the element for the generated content for animations on // ::before and ::after. void StopAnimationsForElement(mozilla::dom::Element* aElement, - nsCSSPseudoElements::Type aPseudoType); + mozilla::CSSPseudoElementType aPseudoType); bool IsAnimationManager() override { return true; diff --git a/layout/style/nsCSSParser.cpp b/layout/style/nsCSSParser.cpp index 9a8348ab59..3e1ca34492 100644 --- a/layout/style/nsCSSParser.cpp +++ b/layout/style/nsCSSParser.cpp @@ -82,7 +82,7 @@ nsCSSProps::kParserVariantTable[eCSSProperty_COUNT_no_shorthands] = { }; // Maximum number of repetitions for the repeat() function -// in the grid-template-columns and grid-template-rows properties, +// in the grid-template-rows and grid-template-columns properties, // to limit high memory usage from small stylesheets. // Must be a positive integer. Should be large-ish. #define GRID_TEMPLATE_MAX_REPETITIONS 10000 @@ -753,7 +753,7 @@ protected: bool aIsNegated, nsIAtom** aPseudoElement, nsAtomList** aPseudoElementArgs, - nsCSSPseudoElements::Type* aPseudoElementType); + CSSPseudoElementType* aPseudoElementType); nsSelectorParsingStatus ParseAttributeSelector(int32_t& aDataMask, nsCSSSelector& aSelector); @@ -961,9 +961,9 @@ protected: // Assuming a [ ? ] has already been parsed, // parse the rest of a . // - // This exists because [ ? ] is ambiguous in the - // 'grid-template' shorthand: it can be either the start of a , - // or of the intertwined syntax that sets both + // This exists because [ ? ] is ambiguous in the 'grid-template' + // shorthand: it can be either the start of a (in + // a <'grid-template-rows'>) or of the intertwined syntax that sets both // grid-template-rows and grid-template-areas. // // On success, |aValue| will be a list of odd length >= 3, @@ -971,6 +971,8 @@ protected: // and alternating between that and . bool ParseGridTrackListWithFirstLineNames(nsCSSValue& aValue, const nsCSSValue& aFirstLineNames); + + bool ParseGridTrackList(nsCSSProperty aPropID); bool ParseGridTemplateColumnsRows(nsCSSProperty aPropID); // |aAreaIndices| is a lookup table to help us parse faster, @@ -980,7 +982,6 @@ protected: nsDataHashtable& aAreaIndices); bool ParseGridTemplateAreas(); bool ParseGridTemplate(); - bool ParseGridTemplateAfterSlash(bool aColumnsIsTrackList); bool ParseGridTemplateAfterString(const nsCSSValue& aFirstLineNames); bool ParseGrid(); bool ParseGridShorthandAutoProps(); @@ -5703,8 +5704,21 @@ CSSParserImpl::ParseAttributeSelector(int32_t& aDataMask, } if ((eCSSToken_Ident == mToken.mType) || (eCSSToken_String == mToken.mType)) { nsAutoString value(mToken.mIdent); + // Avoid duplicating the eof handling by just not checking for + // the 'i' annotation if we got eof. + typedef nsAttrSelector::ValueCaseSensitivity ValueCaseSensitivity; + ValueCaseSensitivity valueCaseSensitivity = + ValueCaseSensitivity::CaseSensitive; + bool eof = !GetToken(true); + if (!eof) { + if (eCSSToken_Ident == mToken.mType && + mToken.mIdent.LowerCaseEqualsLiteral("i")) { + valueCaseSensitivity = ValueCaseSensitivity::CaseInsensitive; + eof = !GetToken(true); + } + } bool gotClosingBracket; - if (! GetToken(true)) { // premature EOF + if (eof) { // premature EOF // Report a warning, but then treat it as a closing bracket. REPORT_UNEXPECTED_EOF(PEAttSelCloseEOF); gotClosingBracket = true; @@ -5712,14 +5726,13 @@ CSSParserImpl::ParseAttributeSelector(int32_t& aDataMask, gotClosingBracket = mToken.IsSymbol(']'); } if (gotClosingBracket) { - bool isCaseSensitive = true; - // For cases when this style sheet is applied to an HTML // element in an HTML document, and the attribute selector is // for a non-namespaced attribute, then check to see if it's // one of the known attributes whose VALUE is // case-insensitive. - if (nameSpaceID == kNameSpaceID_None) { + if (valueCaseSensitivity != ValueCaseSensitivity::CaseInsensitive && + nameSpaceID == kNameSpaceID_None) { static const char* caseInsensitiveHTMLAttribute[] = { // list based on http://www.w3.org/TR/html4/ "lang", @@ -5775,13 +5788,14 @@ CSSParserImpl::ParseAttributeSelector(int32_t& aDataMask, const char* htmlAttr; while ((htmlAttr = caseInsensitiveHTMLAttribute[i++])) { if (attr.LowerCaseEqualsASCII(htmlAttr)) { - isCaseSensitive = false; + valueCaseSensitivity = ValueCaseSensitivity::CaseInsensitiveInHTML; break; } } } aDataMask |= SEL_MASK_ATTRIB; - aSelector.AddAttribute(nameSpaceID, attr, func, value, isCaseSensitive); + aSelector.AddAttribute(nameSpaceID, attr, func, value, + valueCaseSensitivity); } else { REPORT_UNEXPECTED_TOKEN(PEAttSelNoClose); @@ -5813,7 +5827,7 @@ CSSParserImpl::ParsePseudoSelector(int32_t& aDataMask, bool aIsNegated, nsIAtom** aPseudoElement, nsAtomList** aPseudoElementArgs, - nsCSSPseudoElements::Type* aPseudoElementType) + CSSPseudoElementType* aPseudoElementType) { NS_ASSERTION(aIsNegated || (aPseudoElement && aPseudoElementArgs), "expected location to store pseudo element"); @@ -5853,7 +5867,7 @@ CSSParserImpl::ParsePseudoSelector(int32_t& aDataMask, // stash away some info about this pseudo so we only have to get it once. bool isTreePseudo = false; - nsCSSPseudoElements::Type pseudoElementType = + CSSPseudoElementType pseudoElementType = nsCSSPseudoElements::GetPseudoType(pseudo); nsCSSPseudoClasses::Type pseudoClassType = nsCSSPseudoClasses::GetPseudoType(pseudo); @@ -5861,7 +5875,7 @@ CSSParserImpl::ParsePseudoSelector(int32_t& aDataMask, nsCSSPseudoClasses::IsUserActionPseudoClass(pseudoClassType); if (!AgentRulesEnabled() && - ((pseudoElementType < nsCSSPseudoElements::ePseudo_PseudoElementCount && + ((pseudoElementType < CSSPseudoElementType::Count && nsCSSPseudoElements::PseudoElementIsUASheetOnly(pseudoElementType)) || (pseudoClassType != nsCSSPseudoClasses::ePseudoClass_NotPseudoClass && nsCSSPseudoClasses::PseudoClassIsUASheetOnly(pseudoClassType)))) { @@ -5873,17 +5887,17 @@ CSSParserImpl::ParsePseudoSelector(int32_t& aDataMask, // We currently allow :-moz-placeholder and ::-moz-placeholder. We have to // be a bit stricter regarding the pseudo-element parsing rules. - if (pseudoElementType == nsCSSPseudoElements::ePseudo_mozPlaceholder && + if (pseudoElementType == CSSPseudoElementType::mozPlaceholder && pseudoClassType == nsCSSPseudoClasses::ePseudoClass_mozPlaceholder) { if (parsingPseudoElement) { pseudoClassType = nsCSSPseudoClasses::ePseudoClass_NotPseudoClass; } else { - pseudoElementType = nsCSSPseudoElements::ePseudo_NotPseudoElement; + pseudoElementType = CSSPseudoElementType::NotPseudo; } } #ifdef MOZ_XUL - isTreePseudo = (pseudoElementType == nsCSSPseudoElements::ePseudo_XULTree); + isTreePseudo = (pseudoElementType == CSSPseudoElementType::XULTree); // If a tree pseudo-element is using the function syntax, it will // get isTree set here and will pass the check below that only // allows functions if they are in our list of things allowed to be @@ -5893,18 +5907,17 @@ CSSParserImpl::ParsePseudoSelector(int32_t& aDataMask, // desired. bool isTree = (eCSSToken_Function == mToken.mType) && isTreePseudo; #endif - bool isPseudoElement = - (pseudoElementType < nsCSSPseudoElements::ePseudo_PseudoElementCount); + bool isPseudoElement = (pseudoElementType < CSSPseudoElementType::Count); // anonymous boxes are only allowed if they're the tree boxes or we have // enabled agent rules bool isAnonBox = isTreePseudo || - (pseudoElementType == nsCSSPseudoElements::ePseudo_AnonBox && + (pseudoElementType == CSSPseudoElementType::AnonBox && AgentRulesEnabled()); bool isPseudoClass = (pseudoClassType != nsCSSPseudoClasses::ePseudoClass_NotPseudoClass); NS_ASSERTION(!isPseudoClass || - pseudoElementType == nsCSSPseudoElements::ePseudo_NotPseudoElement, + pseudoElementType == CSSPseudoElementType::NotPseudo, "Why is this atom both a pseudo-class and a pseudo-element?"); NS_ASSERTION(isPseudoClass + isPseudoElement + isAnonBox <= 1, "Shouldn't be more than one of these"); @@ -5943,7 +5956,7 @@ CSSParserImpl::ParsePseudoSelector(int32_t& aDataMask, } if (aSelector.IsPseudoElement()) { - nsCSSPseudoElements::Type type = aSelector.PseudoType(); + CSSPseudoElementType type = aSelector.PseudoType(); if (!nsCSSPseudoElements::PseudoElementSupportsUserActionState(type)) { // We only allow user action pseudo-classes on certain pseudo-elements. REPORT_UNEXPECTED_TOKEN(PEPseudoSelNoUserActionPC); @@ -6408,8 +6421,7 @@ CSSParserImpl::ParseSelector(nsCSSSelectorList* aList, nsCSSSelector* selector = aList->AddSelector(aPrevCombinator); nsCOMPtr pseudoElement; nsAutoPtr pseudoElementArgs; - nsCSSPseudoElements::Type pseudoElementType = - nsCSSPseudoElements::ePseudo_NotPseudoElement; + CSSPseudoElementType pseudoElementType = CSSPseudoElementType::NotPseudo; int32_t dataMask = 0; nsSelectorParsingStatus parsingStatus = @@ -6422,7 +6434,7 @@ CSSParserImpl::ParseSelector(nsCSSSelectorList* aList, getter_Transfers(pseudoElementArgs), &pseudoElementType); if (pseudoElement && - pseudoElementType != nsCSSPseudoElements::ePseudo_AnonBox) { + pseudoElementType != CSSPseudoElementType::AnonBox) { // Pseudo-elements other than anonymous boxes are represented with // a special ':' combinator. @@ -6481,7 +6493,7 @@ CSSParserImpl::ParseSelector(nsCSSSelectorList* aList, return false; } - if (pseudoElementType == nsCSSPseudoElements::ePseudo_AnonBox) { + if (pseudoElementType == CSSPseudoElementType::AnonBox) { // We got an anonymous box pseudo-element; it must be the only // thing in this selector group. if (selector->mNext || !IsUniversalSelector(*selector)) { @@ -8998,6 +9010,19 @@ CSSParserImpl::ParseGridTrackListRepeat(nsCSSValueList** aTailPtr) return true; } +bool +CSSParserImpl::ParseGridTrackList(nsCSSProperty aPropID) +{ + nsCSSValue value; + nsCSSValue firstLineNames; + if (ParseGridLineNames(firstLineNames) == CSSParseResult::Error || + !ParseGridTrackListWithFirstLineNames(value, firstLineNames)) { + return false; + } + AppendValue(aPropID, value); + return true; +} + bool CSSParserImpl::ParseGridTemplateColumnsRows(nsCSSProperty aPropID) { @@ -9023,13 +9048,7 @@ CSSParserImpl::ParseGridTemplateColumnsRows(nsCSSProperty aPropID) UngetToken(); } - nsCSSValue firstLineNames; - if (ParseGridLineNames(firstLineNames) == CSSParseResult::Error || - !ParseGridTrackListWithFirstLineNames(value, firstLineNames)) { - return false; - } - AppendValue(aPropID, value); - return true; + return ParseGridTrackList(aPropID); } bool @@ -9156,32 +9175,30 @@ CSSParserImpl::ParseGridTemplate() { // none | // subgrid | - // <'grid-template-columns'> / <'grid-template-rows'> | - // [ / ]? [ ? ? ? ]+ + // <'grid-template-rows'> / <'grid-template-columns'> | + // [ ? ? ? ]+ [ / ]? nsCSSValue value; if (ParseSingleTokenVariant(value, VARIANT_INHERIT, nullptr)) { AppendValue(eCSSProperty_grid_template_areas, value); - AppendValue(eCSSProperty_grid_template_columns, value); AppendValue(eCSSProperty_grid_template_rows, value); + AppendValue(eCSSProperty_grid_template_columns, value); return true; } - // TODO (bug 983175): add parsing for 'subgrid' by itself - // 'none' can appear either by itself, - // or as the beginning of <'grid-template-columns'> / <'grid-template-rows'> + // or as the beginning of <'grid-template-rows'> / <'grid-template-columns'> if (ParseSingleTokenVariant(value, VARIANT_NONE, nullptr)) { - AppendValue(eCSSProperty_grid_template_columns, value); - if (ExpectSymbol('/', true)) { - return ParseGridTemplateAfterSlash(/* aColumnsIsTrackList = */ false); - } - AppendValue(eCSSProperty_grid_template_areas, value); AppendValue(eCSSProperty_grid_template_rows, value); + AppendValue(eCSSProperty_grid_template_areas, value); + if (ExpectSymbol('/', true)) { + return ParseGridTemplateColumnsRows(eCSSProperty_grid_template_columns); + } + AppendValue(eCSSProperty_grid_template_columns, value); return true; } // 'subgrid' can appear either by itself, - // or as the beginning of <'grid-template-columns'> / <'grid-template-rows'> + // or as the beginning of <'grid-template-rows'> / <'grid-template-columns'> nsSubstring* ident = NextIdent(); if (ident) { if (ident->LowerCaseEqualsLiteral("subgrid")) { @@ -9192,28 +9209,26 @@ CSSParserImpl::ParseGridTemplate() if (!ParseOptionalLineNameListAfterSubgrid(value)) { return false; } - AppendValue(eCSSProperty_grid_template_columns, value); + AppendValue(eCSSProperty_grid_template_rows, value); + AppendValue(eCSSProperty_grid_template_areas, nsCSSValue(eCSSUnit_None)); if (ExpectSymbol('/', true)) { - return ParseGridTemplateAfterSlash(/* aColumnsIsTrackList = */ false); + return ParseGridTemplateColumnsRows(eCSSProperty_grid_template_columns); } if (value.GetListValue()->mNext) { // Non-empty after 'subgrid'. - // This is only valid as part of <'grid-template-columns'>, + // This is only valid as part of <'grid-template-rows'>, // which must be followed by a slash. return false; } - // 'subgrid' by itself sets both grid-template-columns - // and grid-template-rows. - AppendValue(eCSSProperty_grid_template_rows, value); - value.SetNoneValue(); - AppendValue(eCSSProperty_grid_template_areas, value); + // 'subgrid' by itself sets both grid-template-rows/columns. + AppendValue(eCSSProperty_grid_template_columns, value); return true; } UngetToken(); } // [ ? ] here is ambiguous: - // it can be either the start of a , + // it can be either the start of a (in a <'grid-template-rows'>), // or the start of [ ? ? ? ]+ nsCSSValue firstLineNames; if (ParseGridLineNames(firstLineNames) == CSSParseResult::Error || @@ -9221,83 +9236,30 @@ CSSParserImpl::ParseGridTemplate() return false; } if (mToken.mType == eCSSToken_String) { - // [ / ]? was omitted - // Parse [ ? ? ? ]+ - value.SetNoneValue(); + // It's the [ ? ? ? ]+ case. + if (!ParseGridTemplateAfterString(firstLineNames)) { + return false; + } + // Parse an optional [ / ] as the columns value. + if (ExpectSymbol('/', true)) { + return ParseGridTrackList(eCSSProperty_grid_template_columns); + } + value.SetNoneValue(); // absent means 'none' AppendValue(eCSSProperty_grid_template_columns, value); - return ParseGridTemplateAfterString(firstLineNames); - } - UngetToken(); - - if (!(ParseGridTrackListWithFirstLineNames(value, firstLineNames) && - ExpectSymbol('/', true))) { - return false; - } - AppendValue(eCSSProperty_grid_template_columns, value); - return ParseGridTemplateAfterSlash(/* aColumnsIsTrackList = */ true); -} - -// Helper for parsing the 'grid-template' shorthand -// -// NOTE: This parses the portion after the slash, for *one* of the -// following types of expressions: -// - <'grid-template-columns'> / <'grid-template-rows'> -// - / [ ? ? ? ]+ -// -// We don't know which type of expression we've got until we've parsed the -// second half, since the pre-slash part is ambiguous. The various return -// clauses below are labeled with the type of expression they're completing. -bool -CSSParserImpl::ParseGridTemplateAfterSlash(bool aColumnsIsTrackList) -{ - nsCSSValue rowsValue; - if (ParseSingleTokenVariant(rowsValue, VARIANT_NONE, nullptr)) { - // <'grid-template-columns'> / <'grid-template-rows'> - AppendValue(eCSSProperty_grid_template_rows, rowsValue); - nsCSSValue areasValue(eCSSUnit_None); // implied - AppendValue(eCSSProperty_grid_template_areas, areasValue); return true; } - - nsSubstring* ident = NextIdent(); - if (ident) { - if (ident->LowerCaseEqualsLiteral("subgrid")) { - if (!nsLayoutUtils::IsGridTemplateSubgridValueEnabled()) { - REPORT_UNEXPECTED(PESubgridNotSupported); - return false; - } - if (!ParseOptionalLineNameListAfterSubgrid(rowsValue)) { - return false; - } - // <'grid-template-columns'> / <'grid-template-rows'> - AppendValue(eCSSProperty_grid_template_rows, rowsValue); - nsCSSValue areasValue(eCSSUnit_None); // implied - AppendValue(eCSSProperty_grid_template_areas, areasValue); - return true; - } - UngetToken(); - } - - nsCSSValue firstLineNames; - if (ParseGridLineNames(firstLineNames) == CSSParseResult::Error || - !GetToken(true)) { - return false; - } - if (aColumnsIsTrackList && mToken.mType == eCSSToken_String) { - // [ / ]? [ ? ? ? ]+ - return ParseGridTemplateAfterString(firstLineNames); - } UngetToken(); - if (!ParseGridTrackListWithFirstLineNames(rowsValue, firstLineNames)) { + // Finish parsing <'grid-template-rows'> with the |firstLineNames| we have, + // and then parse a mandatory [ / <'grid-template-columns'> ]. + if (!ParseGridTrackListWithFirstLineNames(value, firstLineNames) || + !ExpectSymbol('/', true)) { return false; } - - // <'grid-template-columns'> / <'grid-template-rows'> - AppendValue(eCSSProperty_grid_template_rows, rowsValue); - nsCSSValue areasValue(eCSSUnit_None); // implied - AppendValue(eCSSProperty_grid_template_areas, areasValue); - return true; + AppendValue(eCSSProperty_grid_template_rows, value); + value.SetNoneValue(); + AppendValue(eCSSProperty_grid_template_areas, value); + return ParseGridTemplateColumnsRows(eCSSProperty_grid_template_columns); } // Helper for parsing the 'grid-template' shorthand: @@ -9375,7 +9337,7 @@ CSSParserImpl::ParseGridTemplateAfterString(const nsCSSValue& aFirstLineNames) } // <'grid-template'> | -// [ <'grid-auto-flow'> [ <'grid-auto-columns'> [ / <'grid-auto-rows'> ]? ]? ] +// [ <'grid-auto-flow'> [ <'grid-auto-rows'> [ / <'grid-auto-columns'> ]? ]? ] bool CSSParserImpl::ParseGrid() { @@ -9398,8 +9360,8 @@ CSSParserImpl::ParseGrid() // "Also, the gutter properties are reset by this shorthand, // even though they can't be set by it." value.SetFloatValue(0.0f, eCSSUnit_Pixel); - AppendValue(eCSSProperty_grid_column_gap, value); AppendValue(eCSSProperty_grid_row_gap, value); + AppendValue(eCSSProperty_grid_column_gap, value); // The values starts with a <'grid-auto-flow'> if and only if // it starts with a 'dense', 'column' or 'row' keyword. @@ -9419,12 +9381,12 @@ CSSParserImpl::ParseGrid() value.SetIntValue(NS_STYLE_GRID_AUTO_FLOW_ROW, eCSSUnit_Enumerated); AppendValue(eCSSProperty_grid_auto_flow, value); value.SetAutoValue(); - AppendValue(eCSSProperty_grid_auto_columns, value); AppendValue(eCSSProperty_grid_auto_rows, value); + AppendValue(eCSSProperty_grid_auto_columns, value); return ParseGridTemplate(); } -// Parse [ <'grid-auto-columns'> [ / <'grid-auto-rows'> ]? ]? +// Parse [ <'grid-auto-rows'> [ / <'grid-auto-columns'> ]? ]? // for the 'grid' shorthand. // Assumes that <'grid-auto-flow'> was already parsed by the caller. bool @@ -9432,26 +9394,26 @@ CSSParserImpl::ParseGridShorthandAutoProps() { nsCSSValue autoColumnsValue; nsCSSValue autoRowsValue; - CSSParseResult result = ParseGridTrackSize(autoColumnsValue); + CSSParseResult result = ParseGridTrackSize(autoRowsValue); if (result == CSSParseResult::Error) { return false; } if (result == CSSParseResult::NotFound) { - autoColumnsValue.SetAutoValue(); autoRowsValue.SetAutoValue(); + autoColumnsValue.SetAutoValue(); } else { if (!ExpectSymbol('/', true)) { - autoRowsValue.SetAutoValue(); - } else if (ParseGridTrackSize(autoRowsValue) != CSSParseResult::Ok) { + autoColumnsValue.SetAutoValue(); + } else if (ParseGridTrackSize(autoColumnsValue) != CSSParseResult::Ok) { return false; } } - AppendValue(eCSSProperty_grid_auto_columns, autoColumnsValue); AppendValue(eCSSProperty_grid_auto_rows, autoRowsValue); + AppendValue(eCSSProperty_grid_auto_columns, autoColumnsValue); nsCSSValue templateValue(eCSSUnit_None); // Initial values AppendValue(eCSSProperty_grid_template_areas, templateValue); - AppendValue(eCSSProperty_grid_template_columns, templateValue); AppendValue(eCSSProperty_grid_template_rows, templateValue); + AppendValue(eCSSProperty_grid_template_columns, templateValue); return true; } @@ -9671,8 +9633,8 @@ CSSParserImpl::ParseGridGap() { nsCSSValue first; if (ParseSingleTokenVariant(first, VARIANT_INHERIT, nullptr)) { - AppendValue(eCSSProperty_grid_column_gap, first); AppendValue(eCSSProperty_grid_row_gap, first); + AppendValue(eCSSProperty_grid_column_gap, first); return true; } if (ParseNonNegativeVariant(first, VARIANT_LCALC, nullptr) != @@ -9684,8 +9646,8 @@ CSSParserImpl::ParseGridGap() if (result == CSSParseResult::Error) { return false; } - AppendValue(eCSSProperty_grid_column_gap, first); - AppendValue(eCSSProperty_grid_row_gap, + AppendValue(eCSSProperty_grid_row_gap, first); + AppendValue(eCSSProperty_grid_column_gap, result == CSSParseResult::NotFound ? first : second); return true; } @@ -10497,9 +10459,12 @@ CSSParserImpl::ParseWebkitGradientColorStops(nsCSSValueGradient* aGradient) nsCSSValueGradientStop* stop1 = aGradient->mStops.AppendElement(); stop1->mColor.SetIntegerColorValue(NS_RGBA(0, 0, 0, 0), eCSSUnit_RGBAColor); + stop1->mLocation.SetPercentValue(0.0f); + nsCSSValueGradientStop* stop2 = aGradient->mStops.AppendElement(); stop2->mColor.SetIntegerColorValue(NS_RGBA(0, 0, 0, 0), eCSSUnit_RGBAColor); + stop2->mLocation.SetPercentValue(1.0f); } else if (aGradient->mStops.Length() == 1) { // Copy whatever the author provided in the first stop: nsCSSValueGradientStop* stop = aGradient->mStops.AppendElement(); @@ -14842,8 +14807,7 @@ CSSParserImpl::ParseTextEmphasis() } if (!(found & 1)) { // Provide default text-emphasis-style - values[0].SetIntValue(NS_STYLE_TEXT_EMPHASIS_STYLE_NONE, - eCSSUnit_Enumerated); + values[0].SetNoneValue(); } if (!(found & 2)) { // Provide default text-emphasis-color values[1].SetIntValue(NS_COLOR_CURRENTCOLOR, eCSSUnit_EnumColor); diff --git a/layout/style/nsCSSProps.cpp b/layout/style/nsCSSProps.cpp index 66adc731f5..4826599059 100644 --- a/layout/style/nsCSSProps.cpp +++ b/layout/style/nsCSSProps.cpp @@ -2775,20 +2775,20 @@ static const nsCSSProperty gFlexFlowSubpropTable[] = { static const nsCSSProperty gGridTemplateSubpropTable[] = { eCSSProperty_grid_template_areas, + eCSSProperty_grid_template_rows, eCSSProperty_grid_template_columns, - eCSSProperty_grid_template_rows, eCSSProperty_UNKNOWN }; static const nsCSSProperty gGridSubpropTable[] = { eCSSProperty_grid_template_areas, - eCSSProperty_grid_template_columns, eCSSProperty_grid_template_rows, + eCSSProperty_grid_template_columns, eCSSProperty_grid_auto_flow, - eCSSProperty_grid_auto_columns, eCSSProperty_grid_auto_rows, - eCSSProperty_grid_column_gap, // can only be reset, not get/set + eCSSProperty_grid_auto_columns, eCSSProperty_grid_row_gap, // can only be reset, not get/set + eCSSProperty_grid_column_gap, // can only be reset, not get/set eCSSProperty_UNKNOWN }; @@ -2813,8 +2813,8 @@ static const nsCSSProperty gGridAreaSubpropTable[] = { }; static const nsCSSProperty gGridGapSubpropTable[] = { - eCSSProperty_grid_column_gap, eCSSProperty_grid_row_gap, + eCSSProperty_grid_column_gap, eCSSProperty_UNKNOWN }; diff --git a/layout/style/nsCSSPseudoElements.cpp b/layout/style/nsCSSPseudoElements.cpp index fd140f75cd..7f5d85e39b 100644 --- a/layout/style/nsCSSPseudoElements.cpp +++ b/layout/style/nsCSSPseudoElements.cpp @@ -67,46 +67,45 @@ nsCSSPseudoElements::IsCSS2PseudoElement(nsIAtom *aAtom) aAtom == nsCSSPseudoElements::firstLetter || aAtom == nsCSSPseudoElements::firstLine; NS_ASSERTION(nsCSSAnonBoxes::IsAnonBox(aAtom) || - result == - PseudoElementHasFlags(GetPseudoType(aAtom), CSS_PSEUDO_ELEMENT_IS_CSS2), + result == PseudoElementHasFlags(GetPseudoType(aAtom), + CSS_PSEUDO_ELEMENT_IS_CSS2), "result doesn't match flags"); return result; } -/* static */ nsCSSPseudoElements::Type +/* static */ CSSPseudoElementType nsCSSPseudoElements::GetPseudoType(nsIAtom *aAtom) { - for (uint32_t i = 0; i < ArrayLength(CSSPseudoElements_info); ++i) { + for (uint8_t i = 0; i < ArrayLength(CSSPseudoElements_info); ++i) { if (*CSSPseudoElements_info[i].mAtom == aAtom) { - return Type(i); + return static_cast(i); } } if (nsCSSAnonBoxes::IsAnonBox(aAtom)) { #ifdef MOZ_XUL if (nsCSSAnonBoxes::IsTreePseudoElement(aAtom)) { - return ePseudo_XULTree; + return Type::XULTree; } #endif - return ePseudo_AnonBox; + return Type::AnonBox; } - return ePseudo_NotPseudoElement; + return Type::NotPseudo; } /* static */ nsIAtom* nsCSSPseudoElements::GetPseudoAtom(Type aType) { - NS_ASSERTION(aType < nsCSSPseudoElements::ePseudo_PseudoElementCount, - "Unexpected type"); - return *CSSPseudoElements_info[aType].mAtom; + NS_ASSERTION(aType < Type::Count, "Unexpected type"); + return *CSSPseudoElements_info[static_cast(aType)].mAtom; } /* static */ uint32_t nsCSSPseudoElements::FlagsForPseudoElement(const Type aType) { - size_t index = static_cast(aType); + uint8_t index = static_cast(aType); NS_ASSERTION(index < ArrayLength(CSSPseudoElements_flags), "argument must be a pseudo-element"); return CSSPseudoElements_flags[index]; diff --git a/layout/style/nsCSSPseudoElements.h b/layout/style/nsCSSPseudoElements.h index dc4b910c8c..8d7ec5c6cf 100644 --- a/layout/style/nsCSSPseudoElements.h +++ b/layout/style/nsCSSPseudoElements.h @@ -35,13 +35,37 @@ // Is content prevented from parsing selectors containing this pseudo-element? #define CSS_PSEUDO_ELEMENT_UA_SHEET_ONLY (1<<4) +namespace mozilla { + +// The total count of CSSPseudoElement is less than 256, +// so use uint8_t as its underlying type. +enum class CSSPseudoElementType : uint8_t { + // If the actual pseudo-elements stop being first here, change + // GetPseudoType. +#define CSS_PSEUDO_ELEMENT(_name, _value_, _flags) \ + _name, +#include "nsCSSPseudoElementList.h" +#undef CSS_PSEUDO_ELEMENT + Count, + AnonBox = Count, +#ifdef MOZ_XUL + XULTree, +#endif + NotPseudo, + MAX +}; + +} // namespace mozilla + // Empty class derived from nsIAtom so that function signatures can // require an atom from this atom list. class nsICSSPseudoElement : public nsIAtom {}; -class nsCSSPseudoElements { -public: +class nsCSSPseudoElements +{ + typedef mozilla::CSSPseudoElementType Type; +public: static void AddRefAtoms(); static bool IsPseudoElement(nsIAtom *aAtom); @@ -53,25 +77,9 @@ public: #include "nsCSSPseudoElementList.h" #undef CSS_PSEUDO_ELEMENT - enum Type { - // If the actual pseudo-elements stop being first here, change - // GetPseudoType. -#define CSS_PSEUDO_ELEMENT(_name, _value_, _flags) \ - ePseudo_##_name, -#include "nsCSSPseudoElementList.h" -#undef CSS_PSEUDO_ELEMENT - ePseudo_PseudoElementCount, - ePseudo_AnonBox = ePseudo_PseudoElementCount, -#ifdef MOZ_XUL - ePseudo_XULTree, -#endif - ePseudo_NotPseudoElement, - ePseudo_MAX - }; - static Type GetPseudoType(nsIAtom* aAtom); - // Get the atom for a given Type. aType must be < ePseudo_PseudoElementCount + // Get the atom for a given Type. aType must be < CSSPseudoElementType::Count static nsIAtom* GetPseudoAtom(Type aType); static bool PseudoElementContainsElements(const Type aType) { @@ -79,14 +87,15 @@ public: } static bool PseudoElementSupportsStyleAttribute(const Type aType) { - MOZ_ASSERT(aType < ePseudo_PseudoElementCount); - return PseudoElementHasFlags(aType, CSS_PSEUDO_ELEMENT_SUPPORTS_STYLE_ATTRIBUTE); + MOZ_ASSERT(aType < Type::Count); + return PseudoElementHasFlags(aType, + CSS_PSEUDO_ELEMENT_SUPPORTS_STYLE_ATTRIBUTE); } static bool PseudoElementSupportsUserActionState(const Type aType); static bool PseudoElementIsUASheetOnly(const Type aType) { - MOZ_ASSERT(aType < ePseudo_PseudoElementCount); + MOZ_ASSERT(aType < Type::Count); return PseudoElementHasFlags(aType, CSS_PSEUDO_ELEMENT_UA_SHEET_ONLY); } diff --git a/layout/style/nsCSSRuleProcessor.cpp b/layout/style/nsCSSRuleProcessor.cpp index c3e98f6f2a..c167e22b05 100644 --- a/layout/style/nsCSSRuleProcessor.cpp +++ b/layout/style/nsCSSRuleProcessor.cpp @@ -911,7 +911,7 @@ struct RuleCascadeData { RuleHash mRuleHash; RuleHash* - mPseudoElementRuleHashes[nsCSSPseudoElements::ePseudo_PseudoElementCount]; + mPseudoElementRuleHashes[static_cast(CSSPseudoElementType::Count)]; nsTArray mStateSelectors; EventStates mSelectorDocumentStates; PLDHashTable mClassSelectors; @@ -1493,7 +1493,7 @@ static bool AttrMatchesValue(const nsAttrSelector* aAttrSelector, const nsDefaultStringComparator defaultComparator; const nsASCIICaseInsensitiveStringComparator ciComparator; const nsStringComparator& comparator = - (aAttrSelector->mCaseSensitive || !isHTML) + aAttrSelector->IsValueCaseSensitive(isHTML) ? static_cast(defaultComparator) : static_cast(ciComparator); @@ -2294,8 +2294,8 @@ static bool SelectorMatches(Element* aElement, result = aElement-> AttrValueIs(attr->mNameSpace, matchAttribute, attr->mValue, - (!isHTML || attr->mCaseSensitive) ? eCaseMatters - : eIgnoreCase); + attr->IsValueCaseSensitive(isHTML) ? eCaseMatters + : eIgnoreCase); } else if (!aElement->HasAttr(attr->mNameSpace, matchAttribute)) { result = false; @@ -2645,7 +2645,9 @@ nsCSSRuleProcessor::RulesMatching(PseudoElementRuleProcessorData* aData) RuleCascadeData* cascade = GetRuleCascade(aData->mPresContext); if (cascade) { - RuleHash* ruleHash = cascade->mPseudoElementRuleHashes[aData->mPseudoType]; + RuleHash* ruleHash = + cascade->mPseudoElementRuleHashes[static_cast( + aData->mPseudoType)]; if (ruleHash) { NodeMatchContext nodeContext(EventStates(), nsCSSRuleProcessor::IsLink(aData->mElement)); @@ -2715,7 +2717,7 @@ static inline nsRestyleHint RestyleHintForOp(char16_t oper) nsRestyleHint nsCSSRuleProcessor::HasStateDependentStyle(ElementDependentRuleProcessorData* aData, Element* aStatefulElement, - nsCSSPseudoElements::Type aPseudoType, + CSSPseudoElementType aPseudoType, EventStates aStateMask) { MOZ_ASSERT(!aData->mTreeMatchContext.mForScopedStyle, @@ -2723,7 +2725,7 @@ nsCSSRuleProcessor::HasStateDependentStyle(ElementDependentRuleProcessorData* aD "SelectorMatchesTree call"); bool isPseudoElement = - aPseudoType != nsCSSPseudoElements::ePseudo_NotPseudoElement; + aPseudoType != CSSPseudoElementType::NotPseudo; RuleCascadeData* cascade = GetRuleCascade(aData->mPresContext); @@ -2807,7 +2809,7 @@ nsCSSRuleProcessor::HasStateDependentStyle(StateRuleProcessorData* aData) { return HasStateDependentStyle(aData, aData->mElement, - nsCSSPseudoElements::ePseudo_NotPseudoElement, + CSSPseudoElementType::NotPseudo, aData->mStateMask); } @@ -2889,7 +2891,7 @@ RestyleHintForSelectorWithAttributeChange(nsRestyleHint aCurrentHint, sel != aSelector; sel = sel->mNext) { MOZ_ASSERT(sel, "aSelector must be reachable from aRightmostSelector"); - if (sel->PseudoType() != nsCSSPseudoElements::ePseudo_NotPseudoElement) { + if (sel->PseudoType() != CSSPseudoElementType::NotPseudo) { return eRestyle_Subtree; } } @@ -3011,7 +3013,8 @@ nsCSSRuleProcessor::HasAttributeDependentStyle( EnumerateSelectors(cascade->mPossiblyNegatedIDSelectors, &data); } - if (aData->mAttribute == nsGkAtoms::_class) { + if (aData->mAttribute == nsGkAtoms::_class && + aData->mNameSpaceID == kNameSpaceID_None) { const nsAttrValue* otherClasses = aData->mOtherValue; NS_ASSERTION(otherClasses || aData->mModType == nsIDOMMutationEvent::REMOVAL, @@ -3409,11 +3412,12 @@ AddRule(RuleSelectorPair* aRuleInfo, RuleCascadeData* aCascade) RuleCascadeData * const cascade = aCascade; // Build the rule hash. - nsCSSPseudoElements::Type pseudoType = aRuleInfo->mSelector->PseudoType(); - if (MOZ_LIKELY(pseudoType == nsCSSPseudoElements::ePseudo_NotPseudoElement)) { + CSSPseudoElementType pseudoType = aRuleInfo->mSelector->PseudoType(); + if (MOZ_LIKELY(pseudoType == CSSPseudoElementType::NotPseudo)) { cascade->mRuleHash.AppendRule(*aRuleInfo); - } else if (pseudoType < nsCSSPseudoElements::ePseudo_PseudoElementCount) { - RuleHash*& ruleHash = cascade->mPseudoElementRuleHashes[pseudoType]; + } else if (pseudoType < CSSPseudoElementType::Count) { + RuleHash*& ruleHash = + cascade->mPseudoElementRuleHashes[static_cast(pseudoType)]; if (!ruleHash) { ruleHash = new RuleHash(cascade->mQuirksMode); if (!ruleHash) { @@ -3426,7 +3430,7 @@ AddRule(RuleSelectorPair* aRuleInfo, RuleCascadeData* aCascade) NS_ASSERTION(aRuleInfo->mSelector->mNext->mOperator == ':', "Unexpected mNext combinator"); ruleHash->AppendRule(*aRuleInfo); - } else if (pseudoType == nsCSSPseudoElements::ePseudo_AnonBox) { + } else if (pseudoType == CSSPseudoElementType::AnonBox) { NS_ASSERTION(!aRuleInfo->mSelector->mCasedTag && !aRuleInfo->mSelector->mIDList && !aRuleInfo->mSelector->mClassList && @@ -3444,7 +3448,7 @@ AddRule(RuleSelectorPair* aRuleInfo, RuleCascadeData* aCascade) RuleValue(*aRuleInfo, 0, aCascade->mQuirksMode)); } else { #ifdef MOZ_XUL - NS_ASSERTION(pseudoType == nsCSSPseudoElements::ePseudo_XULTree, + NS_ASSERTION(pseudoType == CSSPseudoElementType::XULTree, "Unexpected pseudo type"); // Index doesn't matter here, since we'll just be walking these // rules in order; just pass 0. @@ -3459,8 +3463,8 @@ AddRule(RuleSelectorPair* aRuleInfo, RuleCascadeData* aCascade) for (nsCSSSelector* selector = aRuleInfo->mSelector; selector; selector = selector->mNext) { if (selector->IsPseudoElement()) { - nsCSSPseudoElements::Type pseudo = selector->PseudoType(); - if (pseudo >= nsCSSPseudoElements::ePseudo_PseudoElementCount || + CSSPseudoElementType pseudo = selector->PseudoType(); + if (pseudo >= CSSPseudoElementType::Count || !nsCSSPseudoElements::PseudoElementSupportsUserActionState(pseudo)) { NS_ASSERTION(!selector->mNegations, "Shouldn't have negations"); // We do store selectors ending with pseudo-elements that allow :hover diff --git a/layout/style/nsCSSRuleProcessor.h b/layout/style/nsCSSRuleProcessor.h index 38b4094939..8dc1e21d1d 100644 --- a/layout/style/nsCSSRuleProcessor.h +++ b/layout/style/nsCSSRuleProcessor.h @@ -19,7 +19,6 @@ #include "mozilla/SheetType.h" #include "mozilla/UniquePtr.h" #include "nsAutoPtr.h" -#include "nsCSSPseudoElements.h" #include "nsExpirationTracker.h" #include "nsIMediaList.h" #include "nsIStyleRuleProcessor.h" @@ -40,6 +39,7 @@ class nsCSSCounterStyleRule; namespace mozilla { class CSSStyleSheet; +enum class CSSPseudoElementType : uint8_t; namespace css { class DocumentRule; } // namespace css @@ -234,7 +234,7 @@ private: nsRestyleHint HasStateDependentStyle(ElementDependentRuleProcessorData* aData, mozilla::dom::Element* aStatefulElement, - nsCSSPseudoElements::Type aPseudoType, + mozilla::CSSPseudoElementType aPseudoType, mozilla::EventStates aStateMask); void ClearSheets(); diff --git a/layout/style/nsComputedDOMStyle.cpp b/layout/style/nsComputedDOMStyle.cpp index 7e81b13139..f22f28ea9d 100644 --- a/layout/style/nsComputedDOMStyle.cpp +++ b/layout/style/nsComputedDOMStyle.cpp @@ -488,8 +488,8 @@ nsComputedDOMStyle::GetStyleContextForElementNoFlush(Element* aElement, RefPtr sc; if (aPseudo) { - nsCSSPseudoElements::Type type = nsCSSPseudoElements::GetPseudoType(aPseudo); - if (type >= nsCSSPseudoElements::ePseudo_PseudoElementCount) { + CSSPseudoElementType type = nsCSSPseudoElements::GetPseudoType(aPseudo); + if (type >= CSSPseudoElementType::Count) { return nullptr; } nsIFrame* frame = nsLayoutUtils::GetStyleFrame(aElement); @@ -701,8 +701,7 @@ nsComputedDOMStyle::UpdateCurrentStyleSources(bool aNeedsLayoutFlush) while (topWithPseudoElementData->GetParent()->HasPseudoElementData()) { topWithPseudoElementData = topWithPseudoElementData->GetParent(); } - nsCSSPseudoElements::Type pseudo = - topWithPseudoElementData->GetPseudoType(); + CSSPseudoElementType pseudo = topWithPseudoElementData->GetPseudoType(); nsIAtom* pseudoAtom = nsCSSPseudoElements::GetPseudoAtom(pseudo); nsAutoString assertMsg( NS_LITERAL_STRING("we should be in a pseudo-element that is expected to contain elements (")); diff --git a/layout/style/nsHTMLCSSStyleSheet.cpp b/layout/style/nsHTMLCSSStyleSheet.cpp index 51dd7db55f..f6b2ae5490 100644 --- a/layout/style/nsHTMLCSSStyleSheet.cpp +++ b/layout/style/nsHTMLCSSStyleSheet.cpp @@ -18,6 +18,7 @@ #include "mozilla/dom/Element.h" #include "nsAttrValue.h" #include "nsAttrValueInlines.h" +#include "nsCSSPseudoElements.h" #include "RestyleManager.h" using namespace mozilla; @@ -81,7 +82,7 @@ nsHTMLCSSStyleSheet::ElementRulesMatching(nsPresContext* aPresContext, void nsHTMLCSSStyleSheet::PseudoElementRulesMatching(Element* aPseudoElement, - nsCSSPseudoElements::Type + CSSPseudoElementType aPseudoType, nsRuleWalker* aRuleWalker) { diff --git a/layout/style/nsHTMLCSSStyleSheet.h b/layout/style/nsHTMLCSSStyleSheet.h index b8fdc4c813..2b7ea7ae83 100644 --- a/layout/style/nsHTMLCSSStyleSheet.h +++ b/layout/style/nsHTMLCSSStyleSheet.h @@ -13,7 +13,6 @@ #include "mozilla/Attributes.h" #include "mozilla/MemoryReporting.h" -#include "nsCSSPseudoElements.h" #include "nsDataHashtable.h" #include "nsIStyleRuleProcessor.h" @@ -21,6 +20,7 @@ class nsRuleWalker; struct MiscContainer; namespace mozilla { +enum class CSSPseudoElementType : uint8_t; namespace dom { class Element; } // namespace dom @@ -60,7 +60,7 @@ public: // aPseudoElement here is the content node for the pseudo-element, not // its corresponding real element. void PseudoElementRulesMatching(mozilla::dom::Element* aPseudoElement, - nsCSSPseudoElements::Type aPseudoType, + mozilla::CSSPseudoElementType aPseudoType, nsRuleWalker* aRuleWalker); void CacheStyleAttr(const nsAString& aSerialized, MiscContainer* aValue); diff --git a/layout/style/nsRuleProcessorData.h b/layout/style/nsRuleProcessorData.h index 3c31e1c3a7..3373cb9f1d 100644 --- a/layout/style/nsRuleProcessorData.h +++ b/layout/style/nsRuleProcessorData.h @@ -470,7 +470,7 @@ struct MOZ_STACK_CLASS PseudoElementRuleProcessorData : PseudoElementRuleProcessorData(nsPresContext* aPresContext, mozilla::dom::Element* aParentElement, nsRuleWalker* aRuleWalker, - nsCSSPseudoElements::Type aPseudoType, + mozilla::CSSPseudoElementType aPseudoType, TreeMatchContext& aTreeMatchContext, mozilla::dom::Element* aPseudoElement) : ElementDependentRuleProcessorData(aPresContext, aParentElement, aRuleWalker, @@ -478,14 +478,13 @@ struct MOZ_STACK_CLASS PseudoElementRuleProcessorData : mPseudoType(aPseudoType), mPseudoElement(aPseudoElement) { - NS_PRECONDITION(aPseudoType < - nsCSSPseudoElements::ePseudo_PseudoElementCount, + NS_PRECONDITION(aPseudoType < mozilla::CSSPseudoElementType::Count, "invalid aPseudoType value"); NS_PRECONDITION(aTreeMatchContext.mForStyling, "Styling here!"); NS_PRECONDITION(aRuleWalker, "Must have rule walker"); } - nsCSSPseudoElements::Type mPseudoType; + mozilla::CSSPseudoElementType mPseudoType; mozilla::dom::Element* const mPseudoElement; // weak ref }; @@ -550,7 +549,7 @@ struct MOZ_STACK_CLASS PseudoElementStateRuleProcessorData : PseudoElementStateRuleProcessorData(nsPresContext* aPresContext, mozilla::dom::Element* aElement, mozilla::EventStates aStateMask, - nsCSSPseudoElements::Type aPseudoType, + mozilla::CSSPseudoElementType aPseudoType, TreeMatchContext& aTreeMatchContext, mozilla::dom::Element* aPseudoElement) : StateRuleProcessorData(aPresContext, aElement, aStateMask, @@ -564,7 +563,7 @@ struct MOZ_STACK_CLASS PseudoElementStateRuleProcessorData : // We kind of want to inherit from both StateRuleProcessorData and // PseudoElementRuleProcessorData. Instead we've just copied those // members from PseudoElementRuleProcessorData to this struct. - nsCSSPseudoElements::Type mPseudoType; + mozilla::CSSPseudoElementType mPseudoType; mozilla::dom::Element* const mPseudoElement; // weak ref }; @@ -572,6 +571,7 @@ struct MOZ_STACK_CLASS AttributeRuleProcessorData : public ElementDependentRuleProcessorData { AttributeRuleProcessorData(nsPresContext* aPresContext, mozilla::dom::Element* aElement, + int32_t aNameSpaceID, nsIAtom* aAttribute, int32_t aModType, bool aAttrHasChanged, @@ -579,6 +579,7 @@ struct MOZ_STACK_CLASS AttributeRuleProcessorData : TreeMatchContext& aTreeMatchContext) : ElementDependentRuleProcessorData(aPresContext, aElement, nullptr, aTreeMatchContext), + mNameSpaceID(aNameSpaceID), mAttribute(aAttribute), mOtherValue(aOtherValue), mModType(aModType), @@ -586,6 +587,7 @@ struct MOZ_STACK_CLASS AttributeRuleProcessorData : { NS_PRECONDITION(!aTreeMatchContext.mForStyling, "Not styling here!"); } + int32_t mNameSpaceID; // Namespace of the attribute involved. nsIAtom* mAttribute; // |HasAttributeDependentStyle| for which attribute? // non-null if we have the value. const nsAttrValue* mOtherValue; diff --git a/layout/style/nsStyleContext.cpp b/layout/style/nsStyleContext.cpp index b61ae63276..32d842cba0 100644 --- a/layout/style/nsStyleContext.cpp +++ b/layout/style/nsStyleContext.cpp @@ -2,13 +2,14 @@ /* 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/. */ - + /* the interface (to internal code) for retrieving computed style data */ #include "CSSVariableImageTable.h" #include "mozilla/DebugOnly.h" #include "nsCSSAnonBoxes.h" +#include "nsCSSPseudoElements.h" #include "nsStyleConsts.h" #include "nsString.h" #include "nsPresContext.h" @@ -70,7 +71,7 @@ static bool sExpensiveStyleStructAssertionsEnabled; nsStyleContext::nsStyleContext(nsStyleContext* aParent, nsIAtom* aPseudoTag, - nsCSSPseudoElements::Type aPseudoType, + CSSPseudoElementType aPseudoType, nsRuleNode* aRuleNode, bool aSkipParentDisplayBasedStyleFixup) : mParent(aParent) @@ -89,7 +90,7 @@ nsStyleContext::nsStyleContext(nsStyleContext* aParent, // This check has to be done "backward", because if it were written the // more natural way it wouldn't fail even when it needed to. static_assert((UINT64_MAX >> NS_STYLE_CONTEXT_TYPE_SHIFT) >= - nsCSSPseudoElements::ePseudo_MAX, + static_cast(CSSPseudoElementType::MAX), "pseudo element bits no longer fit in a uint64_t"); MOZ_ASSERT(aRuleNode); @@ -526,7 +527,7 @@ ShouldSuppressLineBreak(const nsStyleContext* aContext, // some other frame with a ruby display value. Non-element pseudos // which represents text frames, as well as ruby pseudos are excluded // because we still want to set the flag for them. - if (aContext->GetPseudoType() == nsCSSPseudoElements::ePseudo_AnonBox && + if (aContext->GetPseudoType() == CSSPseudoElementType::AnonBox && aContext->GetPseudo() != nsCSSAnonBoxes::mozNonElement && !RubyUtils::IsRubyPseudo(aContext->GetPseudo())) { return false; @@ -1216,7 +1217,7 @@ nsStyleContext::Destroy() already_AddRefed NS_NewStyleContext(nsStyleContext* aParentContext, nsIAtom* aPseudoTag, - nsCSSPseudoElements::Type aPseudoType, + CSSPseudoElementType aPseudoType, nsRuleNode* aRuleNode, bool aSkipParentDisplayBasedStyleFixup) { diff --git a/layout/style/nsStyleContext.h b/layout/style/nsStyleContext.h index 7e0a1f1196..edd9e9518f 100644 --- a/layout/style/nsStyleContext.h +++ b/layout/style/nsStyleContext.h @@ -11,11 +11,14 @@ #include "mozilla/RestyleLogging.h" #include "mozilla/Assertions.h" #include "nsRuleNode.h" -#include "nsCSSPseudoElements.h" class nsIAtom; class nsPresContext; +namespace mozilla { +enum class CSSPseudoElementType : uint8_t; +} // namespace mozilla + /** * An nsStyleContext represents the computed style data for an element. * The computed style data are stored in a set of structs (see @@ -60,13 +63,13 @@ public: * matches. See |nsRuleNode| and |nsIStyleRule|. * @param aSkipParentDisplayBasedStyleFixup * If set, this flag indicates that we should skip - * the chunk of ApplyStyleFixups() that applies to - * special cases where a child element's style may - * need to be modified based on its parent's display + * the chunk of ApplyStyleFixups() that applies to + * special cases where a child element's style may + * need to be modified based on its parent's display * value. */ nsStyleContext(nsStyleContext* aParent, nsIAtom* aPseudoTag, - nsCSSPseudoElements::Type aPseudoType, + mozilla::CSSPseudoElementType aPseudoType, nsRuleNode* aRuleNode, bool aSkipParentDisplayBasedStyleFixup); @@ -137,9 +140,9 @@ public: nsStyleContext* GetParent() const { return mParent; } nsIAtom* GetPseudo() const { return mPseudoTag; } - nsCSSPseudoElements::Type GetPseudoType() const { - return static_cast(mBits >> - NS_STYLE_CONTEXT_TYPE_SHIFT); + mozilla::CSSPseudoElementType GetPseudoType() const { + return static_cast( + mBits >> NS_STYLE_CONTEXT_TYPE_SHIFT); } // Find, if it already exists *and is easily findable* (i.e., near the @@ -629,7 +632,7 @@ private: already_AddRefed NS_NewStyleContext(nsStyleContext* aParentContext, nsIAtom* aPseudoTag, - nsCSSPseudoElements::Type aPseudoType, + mozilla::CSSPseudoElementType aPseudoType, nsRuleNode* aRuleNode, bool aSkipParentDisplayBasedStyleFixup); #endif diff --git a/layout/style/nsStyleSet.cpp b/layout/style/nsStyleSet.cpp index 3ad4268249..9e3ee75dde 100644 --- a/layout/style/nsStyleSet.cpp +++ b/layout/style/nsStyleSet.cpp @@ -29,7 +29,6 @@ #include "nsIContent.h" #include "nsRuleData.h" #include "nsRuleProcessorData.h" -#include "nsTransitionManager.h" #include "nsAnimationManager.h" #include "nsStyleSheetService.h" #include "mozilla/dom/Element.h" @@ -455,11 +454,13 @@ nsStyleSet::GatherRuleProcessors(SheetType aType) // implement the style sheet interface. case SheetType::Animation: MOZ_ASSERT(mSheets[aType].IsEmpty()); - mRuleProcessors[aType] = PresContext()->AnimationManager(); + mRuleProcessors[aType] = PresContext()->EffectCompositor()-> + RuleProcessor(EffectCompositor::CascadeLevel::Animations); return NS_OK; case SheetType::Transition: MOZ_ASSERT(mSheets[aType].IsEmpty()); - mRuleProcessors[aType] = PresContext()->TransitionManager(); + mRuleProcessors[aType] = PresContext()->EffectCompositor()-> + RuleProcessor(EffectCompositor::CascadeLevel::Transitions); return NS_OK; case SheetType::StyleAttr: MOZ_ASSERT(mSheets[aType].IsEmpty()); @@ -724,7 +725,7 @@ nsStyleSet::DirtyRuleProcessors(SheetType aType) } bool -nsStyleSet::GetAuthorStyleDisabled() +nsStyleSet::GetAuthorStyleDisabled() const { return mAuthorStyleDisabled; } @@ -913,13 +914,13 @@ nsStyleSet::GetContext(nsStyleContext* aParentContext, // should be used.) nsRuleNode* aVisitedRuleNode, nsIAtom* aPseudoTag, - nsCSSPseudoElements::Type aPseudoType, + CSSPseudoElementType aPseudoType, Element* aElementForAnimation, uint32_t aFlags) { NS_PRECONDITION((!aPseudoTag && aPseudoType == - nsCSSPseudoElements::ePseudo_NotPseudoElement) || + CSSPseudoElementType::NotPseudo) || (aPseudoTag && nsCSSPseudoElements::GetPseudoType(aPseudoTag) == aPseudoType), @@ -998,13 +999,24 @@ nsStyleSet::GetContext(nsStyleContext* aParentContext, } if (aFlags & eDoAnimation) { - // Normally the animation manager has already added the correct - // style rule. However, if the animation-name just changed, it - // might have been wrong. So ask it to double-check based on the - // resulting style context. + nsIStyleRule *oldAnimRule = GetAnimationRule(aRuleNode); - nsIStyleRule *animRule = PresContext()->AnimationManager()-> - CheckAnimationRule(result, aElementForAnimation); + nsIStyleRule *animRule = nullptr; + + // Ignore animations for print or print preview, and for elements + // that are not attached to the document tree. + if (PresContext()->IsDynamic() && + aElementForAnimation->IsInComposedDoc()) { + // Update CSS animations in case the animation-name has just changed. + PresContext()->AnimationManager()->UpdateAnimations(result, + aElementForAnimation); + + animRule = PresContext()->EffectCompositor()-> + GetAnimationRule(aElementForAnimation, + result->GetPseudoType(), + EffectCompositor::CascadeLevel::Animations); + } + MOZ_ASSERT(result->RuleNode() == aRuleNode, "unexpected rule node"); MOZ_ASSERT(!result->GetStyleIfVisited() == !aVisitedRuleNode, @@ -1033,7 +1045,7 @@ nsStyleSet::GetContext(nsStyleContext* aParentContext, if (aElementForAnimation && aElementForAnimation->IsHTMLElement(nsGkAtoms::body) && - aPseudoType == nsCSSPseudoElements::ePseudo_NotPseudoElement && + aPseudoType == CSSPseudoElementType::NotPseudo && PresContext()->CompatibilityMode() == eCompatibility_NavQuirks) { nsIDocument* doc = aElementForAnimation->GetCurrentDoc(); if (doc && doc->GetBodyElement() == aElementForAnimation) { @@ -1412,7 +1424,7 @@ nsStyleSet::ResolveStyleFor(Element* aElement, } return GetContext(aParentContext, ruleNode, visitedRuleNode, - nullptr, nsCSSPseudoElements::ePseudo_NotPseudoElement, + nullptr, CSSPseudoElementType::NotPseudo, aElement, flags); } @@ -1431,7 +1443,7 @@ nsStyleSet::ResolveStyleForRules(nsStyleContext* aParentContext, } return GetContext(aParentContext, ruleWalker.CurrentNode(), nullptr, - nullptr, nsCSSPseudoElements::ePseudo_NotPseudoElement, + nullptr, CSSPseudoElementType::NotPseudo, nullptr, eNoFlags); } @@ -1521,13 +1533,13 @@ nsRuleNode* nsStyleSet::RuleNodeWithReplacement(Element* aElement, Element* aPseudoElement, nsRuleNode* aOldRuleNode, - nsCSSPseudoElements::Type aPseudoType, + CSSPseudoElementType aPseudoType, nsRestyleHint aReplacements) { NS_ASSERTION(mBatching == 0, "rule processors out of date"); MOZ_ASSERT(!aPseudoElement == - (aPseudoType >= nsCSSPseudoElements::ePseudo_PseudoElementCount || + (aPseudoType >= CSSPseudoElementType::Count || !(nsCSSPseudoElements::PseudoElementSupportsStyleAttribute(aPseudoType) || nsCSSPseudoElements::PseudoElementSupportsUserActionState(aPseudoType))), "should have aPseudoElement only for certain pseudo elements"); @@ -1582,9 +1594,9 @@ nsStyleSet::RuleNodeWithReplacement(Element* aElement, if (doReplace) { switch (level->mLevel) { case SheetType::Animation: { - if (aPseudoType == nsCSSPseudoElements::ePseudo_NotPseudoElement || - aPseudoType == nsCSSPseudoElements::ePseudo_before || - aPseudoType == nsCSSPseudoElements::ePseudo_after) { + if (aPseudoType == CSSPseudoElementType::NotPseudo || + aPseudoType == CSSPseudoElementType::before || + aPseudoType == CSSPseudoElementType::after) { nsIStyleRule* rule = PresContext()->EffectCompositor()-> GetAnimationRule(aElement, aPseudoType, EffectCompositor::CascadeLevel::Animations); @@ -1596,9 +1608,9 @@ nsStyleSet::RuleNodeWithReplacement(Element* aElement, break; } case SheetType::Transition: { - if (aPseudoType == nsCSSPseudoElements::ePseudo_NotPseudoElement || - aPseudoType == nsCSSPseudoElements::ePseudo_before || - aPseudoType == nsCSSPseudoElements::ePseudo_after) { + if (aPseudoType == CSSPseudoElementType::NotPseudo || + aPseudoType == CSSPseudoElementType::before || + aPseudoType == CSSPseudoElementType::after) { nsIStyleRule* rule = PresContext()->EffectCompositor()-> GetAnimationRule(aElement, aPseudoType, EffectCompositor::CascadeLevel::Transitions); @@ -1614,7 +1626,7 @@ nsStyleSet::RuleNodeWithReplacement(Element* aElement, static_cast( mRuleProcessors[SheetType::SVGAttrAnimation].get()); if (ruleProcessor && - aPseudoType == nsCSSPseudoElements::ePseudo_NotPseudoElement) { + aPseudoType == CSSPseudoElementType::NotPseudo) { ruleProcessor->ElementRulesMatching(aElement, &ruleWalker); } break; @@ -1628,12 +1640,12 @@ nsStyleSet::RuleNodeWithReplacement(Element* aElement, if (ruleProcessor) { lastScopedRN = ruleWalker.CurrentNode(); if (aPseudoType == - nsCSSPseudoElements::ePseudo_NotPseudoElement) { + CSSPseudoElementType::NotPseudo) { ruleProcessor->ElementRulesMatching(PresContext(), aElement, &ruleWalker); } else if (aPseudoType < - nsCSSPseudoElements::ePseudo_PseudoElementCount && + CSSPseudoElementType::Count && nsCSSPseudoElements:: PseudoElementSupportsStyleAttribute(aPseudoType)) { ruleProcessor->PseudoElementRulesMatching(aPseudoElement, @@ -1723,12 +1735,12 @@ nsStyleSet::ResolveStyleWithReplacement(Element* aElement, } } - nsCSSPseudoElements::Type pseudoType = aOldStyleContext->GetPseudoType(); + CSSPseudoElementType pseudoType = aOldStyleContext->GetPseudoType(); Element* elementForAnimation = nullptr; if (!(aFlags & eSkipStartingAnimations) && - (pseudoType == nsCSSPseudoElements::ePseudo_NotPseudoElement || - pseudoType == nsCSSPseudoElements::ePseudo_before || - pseudoType == nsCSSPseudoElements::ePseudo_after)) { + (pseudoType == CSSPseudoElementType::NotPseudo || + pseudoType == CSSPseudoElementType::before || + pseudoType == CSSPseudoElementType::after)) { // We want to compute a correct elementForAnimation to pass in // because at this point the parameter is more than just the element // for animation; it's also used for the SetBodyTextColor call when @@ -1742,12 +1754,16 @@ nsStyleSet::ResolveStyleWithReplacement(Element* aElement, flags |= eDoAnimation; } elementForAnimation = aElement; - NS_ASSERTION(pseudoType == nsCSSPseudoElements::ePseudo_NotPseudoElement || - !elementForAnimation->GetPrimaryFrame() || - elementForAnimation->GetPrimaryFrame()->StyleContext()-> - GetPseudoType() == - nsCSSPseudoElements::ePseudo_NotPseudoElement, - "aElement should be the element and not the pseudo-element"); +#ifdef DEBUG + { + nsIFrame* styleFrame = nsLayoutUtils::GetStyleFrame(elementForAnimation); + NS_ASSERTION(pseudoType == CSSPseudoElementType::NotPseudo || + !styleFrame || + styleFrame->StyleContext()->GetPseudoType() == + CSSPseudoElementType::NotPseudo, + "aElement should be the element and not the pseudo-element"); + } +#endif } if (aElement && aElement->IsRootOfAnonymousSubtree()) { @@ -1769,11 +1785,11 @@ nsStyleSet::ResolveStyleWithoutAnimation(dom::Element* aTarget, nsRestyleHint aWhichToRemove) { #ifdef DEBUG - nsCSSPseudoElements::Type pseudoType = aStyleContext->GetPseudoType(); + CSSPseudoElementType pseudoType = aStyleContext->GetPseudoType(); #endif - MOZ_ASSERT(pseudoType == nsCSSPseudoElements::ePseudo_NotPseudoElement || - pseudoType == nsCSSPseudoElements::ePseudo_before || - pseudoType == nsCSSPseudoElements::ePseudo_after, + MOZ_ASSERT(pseudoType == CSSPseudoElementType::NotPseudo || + pseudoType == CSSPseudoElementType::before || + pseudoType == CSSPseudoElementType::after, "unexpected type for animations"); RestyleManager* restyleManager = PresContext()->RestyleManager(); @@ -1795,21 +1811,21 @@ nsStyleSet::ResolveStyleForNonElement(nsStyleContext* aParentContext) { return GetContext(aParentContext, mRuleTree, nullptr, nsCSSAnonBoxes::mozNonElement, - nsCSSPseudoElements::ePseudo_AnonBox, nullptr, + CSSPseudoElementType::AnonBox, nullptr, eNoFlags); } void -nsStyleSet::WalkRestrictionRule(nsCSSPseudoElements::Type aPseudoType, +nsStyleSet::WalkRestrictionRule(CSSPseudoElementType aPseudoType, nsRuleWalker* aRuleWalker) { // This needs to match GetPseudoRestriction in nsRuleNode.cpp. aRuleWalker->SetLevel(SheetType::Agent, false, false); - if (aPseudoType == nsCSSPseudoElements::ePseudo_firstLetter) + if (aPseudoType == CSSPseudoElementType::firstLetter) aRuleWalker->Forward(mFirstLetterRule); - else if (aPseudoType == nsCSSPseudoElements::ePseudo_firstLine) + else if (aPseudoType == CSSPseudoElementType::firstLine) aRuleWalker->Forward(mFirstLineRule); - else if (aPseudoType == nsCSSPseudoElements::ePseudo_mozPlaceholder) + else if (aPseudoType == CSSPseudoElementType::mozPlaceholder) aRuleWalker->Forward(mPlaceholderRule); } @@ -1823,13 +1839,13 @@ nsStyleSet::WalkDisableTextZoomRule(Element* aElement, nsRuleWalker* aRuleWalker already_AddRefed nsStyleSet::ResolvePseudoElementStyle(Element* aParentElement, - nsCSSPseudoElements::Type aType, + CSSPseudoElementType aType, nsStyleContext* aParentContext, Element* aPseudoElement) { NS_ENSURE_FALSE(mInShutdown, nullptr); - NS_ASSERTION(aType < nsCSSPseudoElements::ePseudo_PseudoElementCount, + NS_ASSERTION(aType < CSSPseudoElementType::Count, "must have pseudo element type"); NS_ASSERTION(aParentElement, "Must have parent element"); @@ -1859,8 +1875,8 @@ nsStyleSet::ResolvePseudoElementStyle(Element* aParentElement, // For pseudos, |data.IsLink()| being true means that // our parent node is a link. uint32_t flags = eNoFlags; - if (aType == nsCSSPseudoElements::ePseudo_before || - aType == nsCSSPseudoElements::ePseudo_after) { + if (aType == CSSPseudoElementType::before || + aType == CSSPseudoElementType::after) { flags |= eDoAnimation; } else { // Flex and grid containers don't expect to have any pseudo-element children @@ -1877,7 +1893,7 @@ nsStyleSet::ResolvePseudoElementStyle(Element* aParentElement, already_AddRefed nsStyleSet::ProbePseudoElementStyle(Element* aParentElement, - nsCSSPseudoElements::Type aType, + CSSPseudoElementType aType, nsStyleContext* aParentContext) { TreeMatchContext treeContext(true, nsRuleWalker::eRelevantLinkUnvisited, @@ -1889,14 +1905,14 @@ nsStyleSet::ProbePseudoElementStyle(Element* aParentElement, already_AddRefed nsStyleSet::ProbePseudoElementStyle(Element* aParentElement, - nsCSSPseudoElements::Type aType, + CSSPseudoElementType aType, nsStyleContext* aParentContext, TreeMatchContext& aTreeMatchContext, Element* aPseudoElement) { NS_ENSURE_FALSE(mInShutdown, nullptr); - NS_ASSERTION(aType < nsCSSPseudoElements::ePseudo_PseudoElementCount, + NS_ASSERTION(aType < CSSPseudoElementType::Count, "must have pseudo element type"); NS_ASSERTION(aParentElement, "aParentElement must not be null"); @@ -1931,8 +1947,8 @@ nsStyleSet::ProbePseudoElementStyle(Element* aParentElement, // For pseudos, |data.IsLink()| being true means that // our parent node is a link. uint32_t flags = eNoFlags; - if (aType == nsCSSPseudoElements::ePseudo_before || - aType == nsCSSPseudoElements::ePseudo_after) { + if (aType == CSSPseudoElementType::before || + aType == CSSPseudoElementType::after) { flags |= eDoAnimation; } else { // Flex and grid containers don't expect to have any pseudo-element children @@ -1990,7 +2006,7 @@ nsStyleSet::ResolveAnonymousBoxStyle(nsIAtom* aPseudoTag, // Add any @page rules that are specified. nsTArray rules; nsTArray importantRules; - PresContext()->StyleSet()->AppendPageRules(rules); + AppendPageRules(rules); for (uint32_t i = 0, i_end = rules.Length(); i != i_end; ++i) { css::Declaration* declaration = rules[i]->Declaration(); declaration->SetImmutable(); @@ -2007,7 +2023,7 @@ nsStyleSet::ResolveAnonymousBoxStyle(nsIAtom* aPseudoTag, } return GetContext(aParentContext, ruleWalker.CurrentNode(), nullptr, - aPseudoTag, nsCSSPseudoElements::ePseudo_AnonBox, + aPseudoTag, CSSPseudoElementType::AnonBox, nullptr, aFlags); } @@ -2047,7 +2063,7 @@ nsStyleSet::ResolveXULTreePseudoStyle(Element* aParentElement, return GetContext(aParentContext, ruleNode, visitedRuleNode, // For pseudos, |data.IsLink()| being true means that // our parent node is a link. - aPseudoTag, nsCSSPseudoElements::ePseudo_XULTree, + aPseudoTag, CSSPseudoElementType::XULTree, nullptr, eNoFlags); } #endif @@ -2278,7 +2294,7 @@ nsStyleSet::ReparentStyleContext(nsStyleContext* aStyleContext, } nsIAtom* pseudoTag = aStyleContext->GetPseudo(); - nsCSSPseudoElements::Type pseudoType = aStyleContext->GetPseudoType(); + CSSPseudoElementType pseudoType = aStyleContext->GetPseudoType(); nsRuleNode* ruleNode = aStyleContext->RuleNode(); NS_ASSERTION(!PresContext()->RestyleManager()->SkipAnimationRules(), @@ -2306,9 +2322,9 @@ nsStyleSet::ReparentStyleContext(nsStyleContext* aStyleContext, } } - if (pseudoType == nsCSSPseudoElements::ePseudo_NotPseudoElement || - pseudoType == nsCSSPseudoElements::ePseudo_before || - pseudoType == nsCSSPseudoElements::ePseudo_after) { + if (pseudoType == CSSPseudoElementType::NotPseudo || + pseudoType == CSSPseudoElementType::before || + pseudoType == CSSPseudoElementType::after) { flags |= eDoAnimation; } @@ -2337,7 +2353,7 @@ struct MOZ_STACK_CLASS StatefulData : public StateRuleProcessorData { struct MOZ_STACK_CLASS StatefulPseudoElementData : public PseudoElementStateRuleProcessorData { StatefulPseudoElementData(nsPresContext* aPresContext, Element* aElement, - EventStates aStateMask, nsCSSPseudoElements::Type aPseudoType, + EventStates aStateMask, CSSPseudoElementType aPseudoType, TreeMatchContext& aTreeMatchContext, Element* aPseudoElement) : PseudoElementStateRuleProcessorData(aPresContext, aElement, aStateMask, aPseudoType, aTreeMatchContext, @@ -2408,7 +2424,7 @@ nsStyleSet::HasStateDependentStyle(Element* aElement, nsRestyleHint nsStyleSet::HasStateDependentStyle(Element* aElement, - nsCSSPseudoElements::Type aPseudoType, + CSSPseudoElementType aPseudoType, Element* aPseudoElement, EventStates aStateMask) { @@ -2422,12 +2438,13 @@ nsStyleSet::HasStateDependentStyle(Element* aElement, } struct MOZ_STACK_CLASS AttributeData : public AttributeRuleProcessorData { - AttributeData(nsPresContext* aPresContext, - Element* aElement, nsIAtom* aAttribute, int32_t aModType, + AttributeData(nsPresContext* aPresContext, Element* aElement, + int32_t aNameSpaceID, nsIAtom* aAttribute, int32_t aModType, bool aAttrHasChanged, const nsAttrValue* aOtherValue, TreeMatchContext& aTreeMatchContext) - : AttributeRuleProcessorData(aPresContext, aElement, aAttribute, aModType, - aAttrHasChanged, aOtherValue, aTreeMatchContext), + : AttributeRuleProcessorData(aPresContext, aElement, aNameSpaceID, + aAttribute, aModType, aAttrHasChanged, + aOtherValue, aTreeMatchContext), mHint(nsRestyleHint(0)) {} nsRestyleHint mHint; @@ -2447,6 +2464,7 @@ SheetHasAttributeStyle(nsIStyleRuleProcessor* aProcessor, void *aData) // Test if style is dependent on content state nsRestyleHint nsStyleSet::HasAttributeDependentStyle(Element* aElement, + int32_t aNameSpaceID, nsIAtom* aAttribute, int32_t aModType, bool aAttrHasChanged, @@ -2457,7 +2475,7 @@ nsStyleSet::HasAttributeDependentStyle(Element* aElement, TreeMatchContext treeContext(false, nsRuleWalker::eLinksVisitedOrUnvisited, aElement->OwnerDoc()); InitStyleScopes(treeContext, aElement); - AttributeData data(PresContext(), aElement, aAttribute, + AttributeData data(PresContext(), aElement, aNameSpaceID, aAttribute, aModType, aAttrHasChanged, aOtherValue, treeContext); WalkRuleProcessors(SheetHasAttributeStyle, &data, false); if (!(data.mHint & eRestyle_Subtree)) { diff --git a/layout/style/nsStyleSet.h b/layout/style/nsStyleSet.h index c96d536471..7c8f68e07d 100644 --- a/layout/style/nsStyleSet.h +++ b/layout/style/nsStyleSet.h @@ -25,7 +25,6 @@ #include "nsCOMArray.h" #include "nsAutoPtr.h" #include "nsIStyleRule.h" -#include "nsCSSPseudoElements.h" class gfxFontFeatureValueSet; class nsCSSKeyframesRule; @@ -40,6 +39,7 @@ struct TreeMatchContext; namespace mozilla { class EventStates; +enum class CSSPseudoElementType : uint8_t; } // namespace mozilla class nsEmptyStyleRule final : public nsIStyleRule @@ -171,13 +171,13 @@ class nsStyleSet final ResolveStyleForNonElement(nsStyleContext* aParentContext); // Get a style context for a pseudo-element. aParentElement must be - // non-null. aPseudoID is the nsCSSPseudoElements::Type for the + // non-null. aPseudoID is the CSSPseudoElementType for the // pseudo-element. aPseudoElement must be non-null if the pseudo-element // type is one that allows user action pseudo-classes after it or allows // style attributes; otherwise, it is ignored. already_AddRefed ResolvePseudoElementStyle(mozilla::dom::Element* aParentElement, - nsCSSPseudoElements::Type aType, + mozilla::CSSPseudoElementType aType, nsStyleContext* aParentContext, mozilla::dom::Element* aPseudoElement); @@ -186,11 +186,11 @@ class nsStyleSet final // pseudo element. already_AddRefed ProbePseudoElementStyle(mozilla::dom::Element* aParentElement, - nsCSSPseudoElements::Type aType, + mozilla::CSSPseudoElementType aType, nsStyleContext* aParentContext); already_AddRefed ProbePseudoElementStyle(mozilla::dom::Element* aParentElement, - nsCSSPseudoElements::Type aType, + mozilla::CSSPseudoElementType aType, nsStyleContext* aParentContext, TreeMatchContext& aTreeMatchContext, mozilla::dom::Element* aPseudoElement = nullptr); @@ -282,12 +282,13 @@ class nsStyleSet final nsRestyleHint HasStateDependentStyle(mozilla::dom::Element* aElement, mozilla::EventStates aStateMask); nsRestyleHint HasStateDependentStyle(mozilla::dom::Element* aElement, - nsCSSPseudoElements::Type aPseudoType, + mozilla::CSSPseudoElementType aPseudoType, mozilla::dom::Element* aPseudoElement, mozilla::EventStates aStateMask); // Test if style is dependent on the presence of an attribute. nsRestyleHint HasAttributeDependentStyle(mozilla::dom::Element* aElement, + int32_t aNameSpaceID, nsIAtom* aAttribute, int32_t aModType, bool aAttrHasChanged, @@ -321,7 +322,7 @@ class nsStyleSet final nsIStyleSheet *aReferenceSheet); // Enable/Disable entire author style level (Doc, ScopedDoc & PresHint levels) - bool GetAuthorStyleDisabled(); + bool GetAuthorStyleDisabled() const; nsresult SetAuthorStyleDisabled(bool aStyleDisabled); int32_t SheetCount(mozilla::SheetType aType) const { @@ -412,7 +413,7 @@ private: // Move aRuleWalker forward by the appropriate rule if we need to add // a rule due to property restrictions on pseudo-elements. - void WalkRestrictionRule(nsCSSPseudoElements::Type aPseudoType, + void WalkRestrictionRule(mozilla::CSSPseudoElementType aPseudoType, nsRuleWalker* aRuleWalker); void WalkDisableTextZoomRule(mozilla::dom::Element* aElement, @@ -453,7 +454,7 @@ private: nsRuleNode* RuleNodeWithReplacement(mozilla::dom::Element* aElement, mozilla::dom::Element* aPseudoElement, nsRuleNode* aOldRuleNode, - nsCSSPseudoElements::Type aPseudoType, + mozilla::CSSPseudoElementType aPseudoType, nsRestyleHint aReplacements); already_AddRefed @@ -461,7 +462,7 @@ private: nsRuleNode* aRuleNode, nsRuleNode* aVisitedRuleNode, nsIAtom* aPseudoTag, - nsCSSPseudoElements::Type aPseudoType, + mozilla::CSSPseudoElementType aPseudoType, mozilla::dom::Element* aElementForAnimation, uint32_t aFlags); diff --git a/layout/style/nsStyleStruct.h b/layout/style/nsStyleStruct.h index 4d469f3c63..f3a84dde7f 100644 --- a/layout/style/nsStyleStruct.h +++ b/layout/style/nsStyleStruct.h @@ -1579,7 +1579,8 @@ struct nsStyleText nsChangeHint CalcDifference(const nsStyleText& aOther) const; static nsChangeHint MaxDifference() { return NS_STYLE_HINT_FRAMECHANGE | - nsChangeHint_UpdateSubtreeOverflow; + nsChangeHint_UpdateSubtreeOverflow | + nsChangeHint_NeutralChange; } static nsChangeHint DifferenceAlwaysHandledForDescendants() { // CalcDifference never returns the reflow hints that are sometimes diff --git a/layout/style/nsTransitionManager.cpp b/layout/style/nsTransitionManager.cpp index ce131eee91..4ea84fbca7 100644 --- a/layout/style/nsTransitionManager.cpp +++ b/layout/style/nsTransitionManager.cpp @@ -28,6 +28,7 @@ #include "Layers.h" #include "FrameLayerBuilder.h" #include "nsCSSProps.h" +#include "nsCSSPseudoElements.h" #include "nsDisplayList.h" #include "nsStyleChangeList.h" #include "nsStyleSet.h" @@ -129,7 +130,7 @@ CSSTransition::QueueEvents() } dom::Element* owningElement; - nsCSSPseudoElements::Type owningPseudoType; + CSSPseudoElementType owningPseudoType; mOwningElement.GetElement(owningElement, owningPseudoType); MOZ_ASSERT(owningElement, "Owning element should be set"); @@ -177,56 +178,38 @@ CSSTransition::TransitionProperty() const } bool -CSSTransition::HasLowerCompositeOrderThan(const Animation& aOther) const +CSSTransition::HasLowerCompositeOrderThan(const CSSTransition& aOther) const { + MOZ_ASSERT(IsTiedToMarkup() && aOther.IsTiedToMarkup(), + "Should only be called for CSS transitions that are sorted " + "as CSS transitions (i.e. tied to CSS markup)"); + // 0. Object-equality case if (&aOther == this) { return false; } - // 1. Transitions sort lowest - const CSSTransition* otherTransition = aOther.AsCSSTransition(); - if (!otherTransition) { - return true; + // 1. Sort by document order + if (!mOwningElement.Equals(aOther.mOwningElement)) { + return mOwningElement.LessThan(aOther.mOwningElement); } - // 2. CSS transitions that correspond to a transition-property property sort - // lower than CSS transitions owned by script. - if (!IsTiedToMarkup()) { - return !otherTransition->IsTiedToMarkup() ? - Animation::HasLowerCompositeOrderThan(aOther) : - false; - } - if (!otherTransition->IsTiedToMarkup()) { - return true; + // 2. (Same element and pseudo): Sort by transition generation + if (mAnimationIndex != aOther.mAnimationIndex) { + return mAnimationIndex < aOther.mAnimationIndex; } - // 3. Sort by document order - if (!mOwningElement.Equals(otherTransition->mOwningElement)) { - return mOwningElement.LessThan(otherTransition->mOwningElement); - } - - // 4. (Same element and pseudo): Sort by transition generation - if (mAnimationIndex != otherTransition->mAnimationIndex) { - return mAnimationIndex < otherTransition->mAnimationIndex; - } - - // 5. (Same transition generation): Sort by transition property + // 3. (Same transition generation): Sort by transition property return nsCSSProps::GetStringValue(TransitionProperty()) < - nsCSSProps::GetStringValue(otherTransition->TransitionProperty()); + nsCSSProps::GetStringValue(aOther.TransitionProperty()); } ////////////////////////// nsTransitionManager //////////////////////////// NS_IMPL_CYCLE_COLLECTION(nsTransitionManager, mEventDispatcher) -NS_IMPL_CYCLE_COLLECTING_ADDREF(nsTransitionManager) -NS_IMPL_CYCLE_COLLECTING_RELEASE(nsTransitionManager) - -NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsTransitionManager) - NS_INTERFACE_MAP_ENTRY(nsIStyleRuleProcessor) - NS_INTERFACE_MAP_ENTRY(nsISupports) -NS_INTERFACE_MAP_END +NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(nsTransitionManager, AddRef) +NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(nsTransitionManager, Release) void nsTransitionManager::StyleContextChanged(dom::Element *aElement, @@ -279,16 +262,16 @@ nsTransitionManager::StyleContextChanged(dom::Element *aElement, // Return sooner (before the startedAny check below) for the most // common case: no transitions specified or running. const nsStyleDisplay *disp = newStyleContext->StyleDisplay(); - nsCSSPseudoElements::Type pseudoType = newStyleContext->GetPseudoType(); - if (pseudoType != nsCSSPseudoElements::ePseudo_NotPseudoElement) { - if (pseudoType != nsCSSPseudoElements::ePseudo_before && - pseudoType != nsCSSPseudoElements::ePseudo_after) { + CSSPseudoElementType pseudoType = newStyleContext->GetPseudoType(); + if (pseudoType != CSSPseudoElementType::NotPseudo) { + if (pseudoType != CSSPseudoElementType::before && + pseudoType != CSSPseudoElementType::after) { return; } - NS_ASSERTION((pseudoType == nsCSSPseudoElements::ePseudo_before && + NS_ASSERTION((pseudoType == CSSPseudoElementType::before && aElement->NodeInfo()->NameAtom() == nsGkAtoms::mozgeneratedcontentbefore) || - (pseudoType == nsCSSPseudoElements::ePseudo_after && + (pseudoType == CSSPseudoElementType::after && aElement->NodeInfo()->NameAtom() == nsGkAtoms::mozgeneratedcontentafter), "Unexpected aElement coming through"); @@ -676,9 +659,8 @@ nsTransitionManager::ConsiderStartingTransition( RefPtr pt = new ElementPropertyTransition(aElement->OwnerDoc(), aElement, - aNewStyleContext->GetPseudoType(), timing); - pt->mStartForReversingTest = startForReversingTest; - pt->mReversePortion = reversePortion; + aNewStyleContext->GetPseudoType(), timing, + startForReversingTest, reversePortion); AnimationProperty& prop = *pt->Properties().AppendElement(); prop.mProperty = aProperty; @@ -753,8 +735,7 @@ nsTransitionManager::ConsiderStartingTransition( void nsTransitionManager::PruneCompletedTransitions(mozilla::dom::Element* aElement, - nsCSSPseudoElements::Type - aPseudoType, + CSSPseudoElementType aPseudoType, nsStyleContext* aNewStyleContext) { AnimationCollection* collection = @@ -805,23 +786,3 @@ nsTransitionManager::PruneCompletedTransitions(mozilla::dom::Element* aElement, collection = nullptr; } } - -/* - * nsIStyleRuleProcessor implementation - */ - -/* virtual */ size_t -nsTransitionManager::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const -{ - return CommonAnimationManager::SizeOfExcludingThis(aMallocSizeOf); - - // Measurement of the following members may be added later if DMD finds it is - // worthwhile: - // - mEventDispatcher -} - -/* virtual */ size_t -nsTransitionManager::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const -{ - return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf); -} diff --git a/layout/style/nsTransitionManager.h b/layout/style/nsTransitionManager.h index 134a018983..a4c35f46b4 100644 --- a/layout/style/nsTransitionManager.h +++ b/layout/style/nsTransitionManager.h @@ -16,7 +16,6 @@ #include "mozilla/dom/KeyframeEffect.h" #include "AnimationCommon.h" #include "nsCSSProps.h" -#include "nsCSSPseudoElements.h" class nsIGlobalObject; class nsStyleContext; @@ -24,6 +23,7 @@ class nsPresContext; class nsCSSPropertySet; namespace mozilla { +enum class CSSPseudoElementType : uint8_t; struct StyleTransition; } // namespace mozilla @@ -37,9 +37,13 @@ struct ElementPropertyTransition : public dom::KeyframeEffectReadOnly { ElementPropertyTransition(nsIDocument* aDocument, dom::Element* aTarget, - nsCSSPseudoElements::Type aPseudoType, - const TimingParams &aTiming) + CSSPseudoElementType aPseudoType, + const TimingParams &aTiming, + StyleAnimationValue aStartForReversingTest, + double aReversePortion) : dom::KeyframeEffectReadOnly(aDocument, aTarget, aPseudoType, aTiming) + , mStartForReversingTest(aStartForReversingTest) + , mReversePortion(aReversePortion) { } ElementPropertyTransition* AsTransition() override { return this; } @@ -138,7 +142,7 @@ public: nsCSSProperty TransitionProperty() const; - bool HasLowerCompositeOrderThan(const Animation& aOther) const override; + bool HasLowerCompositeOrderThan(const CSSTransition& aOther) const; EffectCompositor::CascadeLevel CascadeLevel() const override { return IsTiedToMarkup() ? @@ -212,7 +216,7 @@ struct TransitionEventInfo { TimeStamp mTimeStamp; TransitionEventInfo(dom::Element* aElement, - nsCSSPseudoElements::Type aPseudoType, + CSSPseudoElementType aPseudoType, nsCSSProperty aProperty, StickyTimeDuration aDuration, const TimeStamp& aTimeStamp, @@ -253,8 +257,8 @@ public: { } - NS_DECL_CYCLE_COLLECTION_CLASS(nsTransitionManager) - NS_DECL_CYCLE_COLLECTING_ISUPPORTS + NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(nsTransitionManager) + NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(nsTransitionManager) typedef mozilla::AnimationCollection AnimationCollection; @@ -285,7 +289,7 @@ public: * new style. */ void PruneCompletedTransitions(mozilla::dom::Element* aElement, - nsCSSPseudoElements::Type aPseudoType, + mozilla::CSSPseudoElementType aPseudoType, nsStyleContext* aNewStyleContext); void SetInAnimationOnlyStyleUpdate(bool aInAnimationOnlyUpdate) { @@ -296,18 +300,17 @@ public: return mInAnimationOnlyStyleUpdate; } - virtual size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const - MOZ_MUST_OVERRIDE override; - virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const - MOZ_MUST_OVERRIDE override; - void QueueEvent(mozilla::TransitionEventInfo&& aEventInfo) { mEventDispatcher.QueueEvent( mozilla::Forward(aEventInfo)); } - void DispatchEvents() { mEventDispatcher.DispatchEvents(mPresContext); } + void DispatchEvents() + { + RefPtr kungFuDeathGrip(this); + mEventDispatcher.DispatchEvents(mPresContext); + } void SortEvents() { mEventDispatcher.SortEvents(); } void ClearEventQueue() { mEventDispatcher.ClearEventQueue(); } diff --git a/layout/style/test/property_database.js b/layout/style/test/property_database.js index 95ef9ee1b3..abc3d5ecdd 100644 --- a/layout/style/test/property_database.js +++ b/layout/style/test/property_database.js @@ -690,6 +690,7 @@ if (IsCSSPropertyPrefEnabled("layout.css.prefixes.webkit")) { // radial w/ no color stops (valid) and a several different radius values: "-webkit-gradient(radial, 1 2, 8, 3 4, 9)", + "-webkit-gradient(radial, 0 0, 10, 0 0, 5)", "-webkit-gradient(radial, 1 2, -1.5, center center, +99999.9999)", // radial w/ color stops @@ -7376,9 +7377,10 @@ if (IsCSSPropertyPrefEnabled("layout.css.text-emphasis.enabled")) { domProp: "textEmphasis", inherited: true, type: CSS_TYPE_TRUE_SHORTHAND, + prerequisites: { "color": "black" }, subproperties: [ "text-emphasis-style", "text-emphasis-color" ], - initial_values: [ "none currentColor", "currentColor none", "none", "currentColor" ], - other_values: [ "filled dot black", "#f00 circle open", "sesame filled rgba(0,0,255,0.5)", "red", "none black", "green none", "currentColor filled", "currentColor open" ], + initial_values: [ "none currentColor", "currentColor none", "none", "currentColor", "none black" ], + other_values: [ "filled dot black", "#f00 circle open", "sesame filled rgba(0,0,255,0.5)", "red", "green none", "currentColor filled", "currentColor open" ], invalid_values: [ "filled black dot", "filled filled red", "open open circle #000", "circle dot #f00", "rubbish" ] }; gCSSProperties["text-emphasis-color"] = { @@ -7386,7 +7388,7 @@ if (IsCSSPropertyPrefEnabled("layout.css.text-emphasis.enabled")) { inherited: true, type: CSS_TYPE_LONGHAND, prerequisites: { "color": "black" }, - initial_values: [ "currentColor", "-moz-use-text-color" ], + initial_values: [ "currentColor", "black", "rgb(0,0,0)" ], other_values: [ "red", "rgba(255,255,255,0.5)", "transparent" ], invalid_values: [ "#0", "#00", "#0000", "#00000", "#0000000", "#00000000", "#000000000", "000000", "ff00ff", "rgb(255,xxx,255)" ] }; diff --git a/layout/style/test/test_transitions_per_property.html b/layout/style/test/test_transitions_per_property.html index 0f0b81793e..af5d38458e 100644 --- a/layout/style/test/test_transitions_per_property.html +++ b/layout/style/test/test_transitions_per_property.html @@ -245,6 +245,8 @@ var supported_properties = { test_border_color_shorthand_transition ], "text-decoration-color": [ test_color_transition, test_border_color_transition ], + "text-emphasis-color": [ test_color_transition, + test_border_color_transition ], "text-indent": [ test_length_transition, test_percent_transition, test_length_percent_calc_transition, test_length_unclamped, test_percent_unclamped ], diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js index 5db13716d5..cd7ff80e2c 100644 --- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -2788,7 +2788,7 @@ pref("layout.css.control-characters.visible", true); #endif // Is support for text-emphasis enabled? -pref("layout.css.text-emphasis.enabled", false); +pref("layout.css.text-emphasis.enabled", true); // pref for which side vertical scrollbars should be on // 0 = end-side in UI direction diff --git a/netwerk/wifi/moz.build b/netwerk/wifi/moz.build index 1397b46ea4..69a42149a7 100644 --- a/netwerk/wifi/moz.build +++ b/netwerk/wifi/moz.build @@ -45,6 +45,7 @@ elif CONFIG['OS_ARCH'] == 'WINNT': 'nsWifiScannerWin.cpp', 'win_wifiScanner.cpp', 'win_wlanLibrary.cpp', + 'win_xp_wifiScanner.cpp' ] elif CONFIG['OS_ARCH'] == 'SunOS': CXXFLAGS += CONFIG['GLIB_CFLAGS'] diff --git a/netwerk/wifi/nsWifiMonitor.h b/netwerk/wifi/nsWifiMonitor.h index 665798efc3..3783d38bd3 100644 --- a/netwerk/wifi/nsWifiMonitor.h +++ b/netwerk/wifi/nsWifiMonitor.h @@ -76,7 +76,7 @@ class nsWifiMonitor final : nsIRunnable, nsIWifiMonitor, nsIObserver mozilla::ReentrantMonitor mReentrantMonitor; #ifdef XP_WIN - nsAutoPtr mWinWifiScanner; + nsAutoPtr mWinWifiScanner; #endif }; #else diff --git a/netwerk/wifi/nsWifiScannerWin.cpp b/netwerk/wifi/nsWifiScannerWin.cpp index 6089c45c6f..ef18706e47 100644 --- a/netwerk/wifi/nsWifiScannerWin.cpp +++ b/netwerk/wifi/nsWifiScannerWin.cpp @@ -12,6 +12,8 @@ #include "nsServiceManagerUtils.h" #include "nsWifiAccessPoint.h" #include "win_wifiScanner.h" +#include "win_xp_wifiScanner.h" +#include "mozilla/WindowsVersion.h" using namespace mozilla; @@ -29,7 +31,14 @@ nsresult nsWifiMonitor::DoScan() { if (!mWinWifiScanner) { - mWinWifiScanner = new WinWifiScanner(); + if (IsWin2003OrLater()) { + mWinWifiScanner = new WinWifiScanner(); + LOG(("Using Windows 2003+ wifi scanner.")); + } else { + mWinWifiScanner = new WinXPWifiScanner(); + LOG(("Using Windows XP wifi scanner.")); + } + if (!mWinWifiScanner) { // TODO: Probably return OOM error return NS_ERROR_FAILURE; diff --git a/netwerk/wifi/win_wifiScanner.h b/netwerk/wifi/win_wifiScanner.h index 671d8f1413..aff5da4cd9 100644 --- a/netwerk/wifi/win_wifiScanner.h +++ b/netwerk/wifi/win_wifiScanner.h @@ -11,10 +11,17 @@ class nsWifiAccessPoint; -class WinWifiScanner { +// This class allows the wifi monitor to use WinWifiScanner and WinXPWifiScanner interchangeably. +class WindowsWifiScannerInterface { +public: + virtual nsresult GetAccessPointsFromWLAN(nsCOMArray &accessPoints) = 0; +}; + + +class WinWifiScanner : public WindowsWifiScannerInterface { public: WinWifiScanner(); - ~WinWifiScanner(); + virtual ~WinWifiScanner(); /** * GetAccessPointsFromWLAN diff --git a/netwerk/wifi/win_xp_wifiScanner.cpp b/netwerk/wifi/win_xp_wifiScanner.cpp new file mode 100644 index 0000000000..1f7fcae7ca --- /dev/null +++ b/netwerk/wifi/win_xp_wifiScanner.cpp @@ -0,0 +1,399 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Windows Vista uses the Native Wifi (WLAN) API for accessing WiFi cards. See +// http://msdn.microsoft.com/en-us/library/ms705945(VS.85).aspx. Windows XP +// Service Pack 3 (and Windows XP Service Pack 2, if upgraded with a hot fix) +// also support a limited version of the WLAN API. See +// http://msdn.microsoft.com/en-us/library/bb204766.aspx. The WLAN API uses +// wlanapi.h, which is not part of the SDK used by Gears, so is replicated +// locally using data from the MSDN. +//\ +// Windows XP from Service Pack 2 onwards supports the Wireless Zero +// Configuration (WZC) programming interface. See +// http://msdn.microsoft.com/en-us/library/ms706587(VS.85).aspx. +// +// The MSDN recommends that one use the WLAN API where available, and WZC +// otherwise. +// +// However, it seems that WZC fails for some wireless cards. Also, WLAN seems +// not to work on XP SP3. So we use WLAN on Vista, and use NDIS directly +// otherwise. + +// MOZILLA NOTE: +// This code is ported from chromium: +// https://chromium.googlesource.com/chromium/src/+/master/content/browser/geolocation/wifi_data_provider_win.cc +// Based on changeset 42c5878 + +#include "win_xp_wifiScanner.h" +#include "nsWifiAccessPoint.h" +#include +#include +#include +#include +#include + +// Taken from ndis.h for WinCE. +#define NDIS_STATUS_INVALID_LENGTH ((NDIS_STATUS)0xC0010014L) +#define NDIS_STATUS_BUFFER_TOO_SHORT ((NDIS_STATUS)0xC0010016L) + +namespace { +// The limits on the size of the buffer used for the OID query. +const int kInitialBufferSize = 2 << 12; // Good for about 50 APs. +const int kMaximumBufferSize = 2 << 20; // 2MB + +// Length for generic string buffers passed to Win32 APIs. +const int kStringLength = 512; + +// WlanOpenHandle +typedef DWORD (WINAPI* WlanOpenHandleFunction)(DWORD dwClientVersion, + PVOID pReserved, + PDWORD pdwNegotiatedVersion, + PHANDLE phClientHandle); + +// WlanEnumInterfaces +typedef DWORD (WINAPI* WlanEnumInterfacesFunction)( + HANDLE hClientHandle, + PVOID pReserved, + PWLAN_INTERFACE_INFO_LIST* ppInterfaceList); + +// WlanGetNetworkBssList +typedef DWORD (WINAPI* WlanGetNetworkBssListFunction)( + HANDLE hClientHandle, + const GUID* pInterfaceGuid, + const PDOT11_SSID pDot11Ssid, + DOT11_BSS_TYPE dot11BssType, + BOOL bSecurityEnabled, + PVOID pReserved, + PWLAN_BSS_LIST* ppWlanBssList +); + +// WlanFreeMemory +typedef VOID (WINAPI* WlanFreeMemoryFunction)(PVOID pMemory); + +// WlanCloseHandle +typedef DWORD (WINAPI* WlanCloseHandleFunction)(HANDLE hClientHandle, + PVOID pReserved); + +// Extracts data for an access point and converts to Gears format. +bool UndefineDosDevice(const std::string& device_name); +bool DefineDosDeviceIfNotExists(const std::string& device_name); +HANDLE GetFileHandle(const std::string& device_name); +// Makes the OID query and returns a Win32 error code. +int PerformQuery(HANDLE adapter_handle, std::vector& buffer, DWORD* bytes_out); +bool ResizeBuffer(size_t requested_size, std::vector& buffer); +// Gets the system directory and appends a trailing slash if not already +// present. +bool GetSystemDirectory(std::string* path); + +bool ConvertToAccessPointData(const NDIS_WLAN_BSSID& data, nsWifiAccessPoint* access_point_data); +int GetDataFromBssIdList(const NDIS_802_11_BSSID_LIST& bss_id_list, + int list_size, + nsCOMArray& outData); +} // namespace + +class WindowsNdisApi +{ +public: + virtual ~WindowsNdisApi(); + static WindowsNdisApi* Create(); + virtual bool GetAccessPointData(nsCOMArray& outData); + +private: + static bool GetInterfacesNDIS(std::vector& interface_service_names_out); + // Swaps in content of the vector passed + explicit WindowsNdisApi(std::vector* interface_service_names); + bool GetInterfaceDataNDIS(HANDLE adapter_handle, nsCOMArray& outData); + // NDIS variables. + std::vector interface_service_names_; + std::vector _buffer; +}; + +// WindowsNdisApi +WindowsNdisApi::WindowsNdisApi( + std::vector* interface_service_names) + : _buffer(kInitialBufferSize) { + interface_service_names_.swap(*interface_service_names); +} + +WindowsNdisApi::~WindowsNdisApi() { +} + +WindowsNdisApi* WindowsNdisApi::Create() { + std::vector interface_service_names; + if (GetInterfacesNDIS(interface_service_names)) { + return new WindowsNdisApi(&interface_service_names); + } + return NULL; +} + +bool WindowsNdisApi::GetAccessPointData(nsCOMArray& outData) { + int interfaces_failed = 0; + int interfaces_succeeded = 0; + + for (int i = 0; i < static_cast(interface_service_names_.size()); ++i) { + // First, check that we have a DOS device for this adapter. + if (!DefineDosDeviceIfNotExists(interface_service_names_[i])) { + continue; + } + + // Get the handle to the device. This will fail if the named device is not + // valid. + HANDLE adapter_handle = GetFileHandle(interface_service_names_[i]); + if (adapter_handle == INVALID_HANDLE_VALUE) { + continue; + } + + // Get the data. + if (GetInterfaceDataNDIS(adapter_handle, outData)) { + ++interfaces_succeeded; + } else { + ++interfaces_failed; + } + + // Clean up. + CloseHandle(adapter_handle); + UndefineDosDevice(interface_service_names_[i]); + } + + // Return true if at least one interface succeeded, or at the very least none + // failed. + return interfaces_succeeded > 0 || interfaces_failed == 0; +} + +bool WindowsNdisApi::GetInterfacesNDIS(std::vector& interface_service_names_out) { + HKEY network_cards_key = NULL; + if (RegOpenKeyEx( + HKEY_LOCAL_MACHINE, + "Software\\Microsoft\\Windows NT\\CurrentVersion\\NetworkCards", + 0, + KEY_READ, + &network_cards_key) != ERROR_SUCCESS) { + return false; + } + if (!network_cards_key) { + return false; + } + + for (int i = 0; ; ++i) { + TCHAR name[kStringLength]; + DWORD name_size = kStringLength; + FILETIME time; + if (RegEnumKeyEx(network_cards_key, + i, + name, + &name_size, + NULL, + NULL, + NULL, + &time) != ERROR_SUCCESS) { + break; + } + HKEY hardware_key = NULL; + if (RegOpenKeyEx(network_cards_key, name, 0, KEY_READ, &hardware_key) != + ERROR_SUCCESS) { + break; + } + if (!hardware_key) { + return false; + } + + TCHAR service_name[kStringLength]; + DWORD service_name_size = kStringLength; + DWORD type = 0; + if (RegQueryValueEx(hardware_key, + "ServiceName", + NULL, + &type, + reinterpret_cast(service_name), + &service_name_size) == ERROR_SUCCESS) { + interface_service_names_out.push_back(service_name); + } + RegCloseKey(hardware_key); + } + + RegCloseKey(network_cards_key); + return true; +} + +bool WindowsNdisApi::GetInterfaceDataNDIS(HANDLE adapter_handle, + nsCOMArray& outData) { + DWORD bytes_out; + int result; + + while (true) { + bytes_out = 0; + result = PerformQuery(adapter_handle, _buffer, &bytes_out); + if (result == ERROR_GEN_FAILURE || // Returned by some Intel cards. + result == ERROR_INSUFFICIENT_BUFFER || + result == ERROR_MORE_DATA || + result == NDIS_STATUS_INVALID_LENGTH || + result == NDIS_STATUS_BUFFER_TOO_SHORT) { + // The buffer we supplied is too small, so increase it. bytes_out should + // provide the required buffer size, but this is not always the case. + size_t newSize; + if (bytes_out > static_cast(_buffer.size())) { + newSize = bytes_out; + } else { + newSize = _buffer.size() * 2; + } + if (!ResizeBuffer(newSize, _buffer)) { + return false; + } + } else { + // The buffer is not too small. + break; + } + } + + if (result == ERROR_SUCCESS) { + NDIS_802_11_BSSID_LIST* bssid_list = + reinterpret_cast(&_buffer[0]); + GetDataFromBssIdList(*bssid_list, _buffer.size(), outData); + } + + return true; +} + +namespace { +#define uint8 unsigned char + +bool ConvertToAccessPointData(const NDIS_WLAN_BSSID& data, nsWifiAccessPoint* access_point_data) +{ + access_point_data->setMac(data.MacAddress); + access_point_data->setSignal(data.Rssi); + // Note that _NDIS_802_11_SSID::Ssid::Ssid is not null-terminated. + const unsigned char* ssid = data.Ssid.Ssid; + size_t len = data.Ssid.SsidLength; + access_point_data->setSSID(reinterpret_cast(ssid), len); + return true; +} + +int GetDataFromBssIdList(const NDIS_802_11_BSSID_LIST& bss_id_list, + int list_size, + nsCOMArray& outData) +{ + // Walk through the BSS IDs. + int found = 0; + const uint8* iterator = reinterpret_cast(&bss_id_list.Bssid[0]); + const uint8* end_of_buffer = + reinterpret_cast(&bss_id_list) + list_size; + for (int i = 0; i < static_cast(bss_id_list.NumberOfItems); ++i) { + const NDIS_WLAN_BSSID *bss_id = + reinterpret_cast(iterator); + // Check that the length of this BSS ID is reasonable. + if (bss_id->Length < sizeof(NDIS_WLAN_BSSID) || + iterator + bss_id->Length > end_of_buffer) { + break; + } + nsWifiAccessPoint* ap = new nsWifiAccessPoint(); + if (ConvertToAccessPointData(*bss_id, ap)) { + outData.AppendObject(ap); + ++found; + } + // Move to the next BSS ID. + iterator += bss_id->Length; + } + return found; +} + + +bool UndefineDosDevice(const std::string& device_name) { + // We remove only the mapping we use, that is \Device\. + std::string target_path = "\\Device\\" + device_name; + return DefineDosDevice( + DDD_RAW_TARGET_PATH | DDD_REMOVE_DEFINITION | DDD_EXACT_MATCH_ON_REMOVE, + device_name.c_str(), + target_path.c_str()) == TRUE; +} + +bool DefineDosDeviceIfNotExists(const std::string& device_name) { + // We create a DOS device name for the device at \Device\. + std::string target_path = "\\Device\\" + device_name; + + TCHAR target[kStringLength]; + if (QueryDosDevice(device_name.c_str(), target, kStringLength) > 0 && + target_path.compare(target) == 0) { + // Device already exists. + return true; + } + + if (GetLastError() != ERROR_FILE_NOT_FOUND) { + return false; + } + + if (!DefineDosDevice(DDD_RAW_TARGET_PATH, + device_name.c_str(), + target_path.c_str())) { + return false; + } + + // Check that the device is really there. + return QueryDosDevice(device_name.c_str(), target, kStringLength) > 0 && + target_path.compare(target) == 0; +} + +HANDLE GetFileHandle(const std::string& device_name) { + // We access a device with DOS path \Device\ at + // \\.\. + std::string formatted_device_name = "\\\\.\\" + device_name; + + return CreateFile(formatted_device_name.c_str(), + GENERIC_READ, + FILE_SHARE_READ | FILE_SHARE_WRITE, // share mode + 0, // security attributes + OPEN_EXISTING, + 0, // flags and attributes + INVALID_HANDLE_VALUE); +} + +int PerformQuery(HANDLE adapter_handle, + std::vector& buffer, + DWORD* bytes_out) { + DWORD oid = OID_802_11_BSSID_LIST; + if (!DeviceIoControl(adapter_handle, + IOCTL_NDIS_QUERY_GLOBAL_STATS, + &oid, + sizeof(oid), + &buffer[0], + buffer.size(), + bytes_out, + NULL)) { + return GetLastError(); + } + return ERROR_SUCCESS; +} + +bool ResizeBuffer(size_t requested_size, std::vector& buffer) { + if (requested_size > kMaximumBufferSize) { + buffer.resize(kInitialBufferSize); + return false; + } + + buffer.resize(requested_size); + return true; +} + +} // namespace + + +nsresult +WinXPWifiScanner::GetAccessPointsFromWLAN(nsCOMArray &accessPoints) +{ + if (!mImplementation) { + mImplementation = WindowsNdisApi::Create(); + if (!mImplementation) { + return NS_ERROR_FAILURE; + } + } + + accessPoints.Clear(); + bool isOk = mImplementation->GetAccessPointData(accessPoints); + if (!isOk) { + mImplementation = 0; + return NS_ERROR_FAILURE; + } + + return NS_OK; +} diff --git a/netwerk/wifi/win_xp_wifiScanner.h b/netwerk/wifi/win_xp_wifiScanner.h new file mode 100644 index 0000000000..33ae4cae4e --- /dev/null +++ b/netwerk/wifi/win_xp_wifiScanner.h @@ -0,0 +1,25 @@ +/* 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 WINXPWIFISCANNER_H_ +#define WINXPWIFISCANNER_H_ + +#include "nsAutoPtr.h" +#include "nsCOMArray.h" +#include "win_wifiScanner.h" + +class nsWifiAccessPoint; +class WindowsNdisApi; + +// This class is wrapper into the Chromium WindowNdisApi class for scanning wifis +// on Windows XP. When Firefox drops XP support, this code can go. +class WinXPWifiScanner : public WindowsWifiScannerInterface { +public: + nsresult GetAccessPointsFromWLAN(nsCOMArray &accessPoints); + virtual ~WinXPWifiScanner() {} +private: + nsAutoPtr mImplementation; +}; + +#endif \ No newline at end of file diff --git a/testing/web-platform/meta/selectors/attribute-selectors/attribute-case/cssom.html.ini b/testing/web-platform/meta/selectors/attribute-selectors/attribute-case/cssom.html.ini index 91134afff5..38a58d96d4 100644 --- a/testing/web-platform/meta/selectors/attribute-selectors/attribute-case/cssom.html.ini +++ b/testing/web-platform/meta/selectors/attribute-selectors/attribute-case/cssom.html.ini @@ -12,93 +12,39 @@ [[foo="bar"\] /* sanity check */ setting CSSStyleRule#selectorText in @media] expected: FAIL - [[foo="bar" i\] insertRule] - expected: FAIL - - [[foo="bar" i\] getting CSSRule#cssText] - expected: FAIL - [[foo="bar" i\] setting CSSRule#cssText] expected: FAIL - [[foo="bar" i\] getting CSSStyleRule#selectorText] - expected: FAIL - [[foo="bar" i\] setting CSSStyleRule#selectorText] expected: FAIL - [[foo="bar" i\] insertRule in @media] - expected: FAIL - - [[foo="bar" i\] getting CSSRule#cssText in @media] - expected: FAIL - [[foo="bar" i\] setting CSSRule#cssText in @media] expected: FAIL - [[foo="bar" i\] getting CSSStyleRule#selectorText in @media] - expected: FAIL - [[foo="bar" i\] setting CSSStyleRule#selectorText in @media] expected: FAIL - [[foo="bar" /**/ i\] insertRule] - expected: FAIL - - [[foo="bar" /**/ i\] getting CSSRule#cssText] - expected: FAIL - [[foo="bar" /**/ i\] setting CSSRule#cssText] expected: FAIL - [[foo="bar" /**/ i\] getting CSSStyleRule#selectorText] - expected: FAIL - [[foo="bar" /**/ i\] setting CSSStyleRule#selectorText] expected: FAIL - [[foo="bar" /**/ i\] insertRule in @media] - expected: FAIL - - [[foo="bar" /**/ i\] getting CSSRule#cssText in @media] - expected: FAIL - [[foo="bar" /**/ i\] setting CSSRule#cssText in @media] expected: FAIL - [[foo="bar" /**/ i\] getting CSSStyleRule#selectorText in @media] - expected: FAIL - [[foo="bar" /**/ i\] setting CSSStyleRule#selectorText in @media] expected: FAIL - [[foo="bar"/**/i\] insertRule] - expected: FAIL - - [[foo="bar"/**/i\] getting CSSRule#cssText] - expected: FAIL - [[foo="bar"/**/i\] setting CSSRule#cssText] expected: FAIL - [[foo="bar"/**/i\] getting CSSStyleRule#selectorText] - expected: FAIL - [[foo="bar"/**/i\] setting CSSStyleRule#selectorText] expected: FAIL - [[foo="bar"/**/i\] insertRule in @media] - expected: FAIL - - [[foo="bar"/**/i\] getting CSSRule#cssText in @media] - expected: FAIL - [[foo="bar"/**/i\] setting CSSRule#cssText in @media] expected: FAIL - [[foo="bar"/**/i\] getting CSSStyleRule#selectorText in @media] - expected: FAIL - [[foo="bar"/**/i\] setting CSSStyleRule#selectorText in @media] expected: FAIL diff --git a/testing/web-platform/meta/selectors/attribute-selectors/attribute-case/semantics.html.ini b/testing/web-platform/meta/selectors/attribute-selectors/attribute-case/semantics.html.ini deleted file mode 100644 index 4508ca5f03..0000000000 --- a/testing/web-platform/meta/selectors/attribute-selectors/attribute-case/semantics.html.ini +++ /dev/null @@ -1,1019 +0,0 @@ -[semantics.html] - type: testharness - [[foo='bar' i\]
in standards mode] - expected: FAIL - - [[foo='bar' i\]
with querySelector in standards mode] - expected: FAIL - - [[foo='' i\]
in standards mode] - expected: FAIL - - [[foo='' i\]
with querySelector in standards mode] - expected: FAIL - - [[foo='ä' i\] /* COMBINING in both */
in standards mode] - expected: FAIL - - [[foo='ä' i\] /* COMBINING in both */
with querySelector in standards mode] - expected: FAIL - - [[foo='Ä' i\] /* COMBINING in both */
in standards mode] - expected: FAIL - - [[foo='Ä' i\] /* COMBINING in both */
with querySelector in standards mode] - expected: FAIL - - [[*|foo='bar' i\]
in standards mode] - expected: FAIL - - [[*|foo='bar' i\]
with querySelector in standards mode] - expected: FAIL - - [[*|foo='bar' i\]
in standards mode] - expected: FAIL - - [[*|foo='bar' i\]
with querySelector in standards mode] - expected: FAIL - - [[align='left' i\]
in standards mode] - expected: FAIL - - [[align='left' i\]
with querySelector in standards mode] - expected: FAIL - - [[align='LEFT' i\]
in standards mode] - expected: FAIL - - [[align='LEFT' i\]
with querySelector in standards mode] - expected: FAIL - - [[class='a' i\]
in standards mode] - expected: FAIL - - [[class='a' i\]
with querySelector in standards mode] - expected: FAIL - - [[class='A' i\]
in standards mode] - expected: FAIL - - [[class='A' i\]
with querySelector in standards mode] - expected: FAIL - - [[id='a' i\]
in standards mode] - expected: FAIL - - [[id='a' i\]
with querySelector in standards mode] - expected: FAIL - - [[id='A' i\]
in standards mode] - expected: FAIL - - [[id='A' i\]
with querySelector in standards mode] - expected: FAIL - - [[lang='a' i\]
in standards mode] - expected: FAIL - - [[lang='a' i\]
with querySelector in standards mode] - expected: FAIL - - [[lang='A' i\]
in standards mode] - expected: FAIL - - [[lang='A' i\]
with querySelector in standards mode] - expected: FAIL - - [[*|lang='a' i\]
in standards mode] - expected: FAIL - - [[*|lang='a' i\]
with querySelector in standards mode] - expected: FAIL - - [[*|lang='A' i\]
in standards mode] - expected: FAIL - - [[*|lang='A' i\]
with querySelector in standards mode] - expected: FAIL - - [@namespace x 'http://www.w3.org/XML/1998/namespace'; [x|lang='A' i\]
in standards mode] - expected: FAIL - - [[foo='bar' i\][foo='bar' i\]
in standards mode] - expected: FAIL - - [[foo='bar' i\][foo='bar' i\]
with querySelector in standards mode] - expected: FAIL - - [[foo='BAR'\][foo='bar' i\]
in standards mode] - expected: FAIL - - [[foo='BAR'\][foo='bar' i\]
with querySelector in standards mode] - expected: FAIL - - [[foo='bar' i\][foo='BAR'\]
in standards mode] - expected: FAIL - - [[foo='bar' i\][foo='BAR'\]
with querySelector in standards mode] - expected: FAIL - - [[foo='' i\]
in standards mode] - expected: FAIL - - [[foo='' i\]
with querySelector in standards mode] - expected: FAIL - - [[foo='\x00' i\] /* \\0 in selector */
in standards mode] - expected: FAIL - - [[foo='\x00' i\] /* \\0 in selector */
with querySelector in standards mode] - expected: FAIL - - [[foo='' i\] /* \\0 in attribute */
in standards mode] - expected: FAIL - - [[foo='' i\] /* \\0 in attribute */
with querySelector in standards mode] - expected: FAIL - - [[foo='ä' i\]
in standards mode] - expected: FAIL - - [[foo='ä' i\]
with querySelector in standards mode] - expected: FAIL - - [[foo='Ä' i\]
in standards mode] - expected: FAIL - - [[foo='Ä' i\]
with querySelector in standards mode] - expected: FAIL - - [[foo='ä' i\] /* COMBINING in selector */
in standards mode] - expected: FAIL - - [[foo='ä' i\] /* COMBINING in selector */
with querySelector in standards mode] - expected: FAIL - - [[foo='ä' i\] /* COMBINING in selector */
in standards mode] - expected: FAIL - - [[foo='ä' i\] /* COMBINING in selector */
with querySelector in standards mode] - expected: FAIL - - [[foo='Ä' i\] /* COMBINING in selector */
in standards mode] - expected: FAIL - - [[foo='Ä' i\] /* COMBINING in selector */
with querySelector in standards mode] - expected: FAIL - - [[foo='Ä' i\] /* COMBINING in selector */
in standards mode] - expected: FAIL - - [[foo='Ä' i\] /* COMBINING in selector */
with querySelector in standards mode] - expected: FAIL - - [[foo='ä' i\] /* COMBINING in attribute */
in standards mode] - expected: FAIL - - [[foo='ä' i\] /* COMBINING in attribute */
with querySelector in standards mode] - expected: FAIL - - [[foo='ä' i\] /* COMBINING in attribute */
in standards mode] - expected: FAIL - - [[foo='ä' i\] /* COMBINING in attribute */
with querySelector in standards mode] - expected: FAIL - - [[foo='Ä' i\] /* COMBINING in attribute */
in standards mode] - expected: FAIL - - [[foo='Ä' i\] /* COMBINING in attribute */
with querySelector in standards mode] - expected: FAIL - - [[foo='Ä' i\] /* COMBINING in attribute */
in standards mode] - expected: FAIL - - [[foo='Ä' i\] /* COMBINING in attribute */
with querySelector in standards mode] - expected: FAIL - - [[foo='ä' i\] /* COMBINING in selector */
in standards mode] - expected: FAIL - - [[foo='ä' i\] /* COMBINING in selector */
with querySelector in standards mode] - expected: FAIL - - [[foo='ä' i\] /* COMBINING in selector */
in standards mode] - expected: FAIL - - [[foo='ä' i\] /* COMBINING in selector */
with querySelector in standards mode] - expected: FAIL - - [[foo='Ä' i\] /* COMBINING in selector */
in standards mode] - expected: FAIL - - [[foo='Ä' i\] /* COMBINING in selector */
with querySelector in standards mode] - expected: FAIL - - [[foo='Ä' i\] /* COMBINING in selector */
in standards mode] - expected: FAIL - - [[foo='Ä' i\] /* COMBINING in selector */
with querySelector in standards mode] - expected: FAIL - - [[foo='a' i\] /* COMBINING in attribute */
in standards mode] - expected: FAIL - - [[foo='a' i\] /* COMBINING in attribute */
with querySelector in standards mode] - expected: FAIL - - [[foo='A' i\] /* COMBINING in attribute */
in standards mode] - expected: FAIL - - [[foo='A' i\] /* COMBINING in attribute */
with querySelector in standards mode] - expected: FAIL - - [[foo='a' i\] /* COMBINING in attribute */
in standards mode] - expected: FAIL - - [[foo='a' i\] /* COMBINING in attribute */
with querySelector in standards mode] - expected: FAIL - - [[foo='A' i\] /* COMBINING in attribute */
in standards mode] - expected: FAIL - - [[foo='A' i\] /* COMBINING in attribute */
with querySelector in standards mode] - expected: FAIL - - [[foo='i' i\]
in standards mode] - expected: FAIL - - [[foo='i' i\]
with querySelector in standards mode] - expected: FAIL - - [[foo='i' i\]
in standards mode] - expected: FAIL - - [[foo='i' i\]
with querySelector in standards mode] - expected: FAIL - - [[foo='I' i\]
in standards mode] - expected: FAIL - - [[foo='I' i\]
with querySelector in standards mode] - expected: FAIL - - [[foo='I' i\]
in standards mode] - expected: FAIL - - [[foo='I' i\]
with querySelector in standards mode] - expected: FAIL - - [[foo='İ' i\]
in standards mode] - expected: FAIL - - [[foo='İ' i\]
with querySelector in standards mode] - expected: FAIL - - [[foo='ı' i\]
in standards mode] - expected: FAIL - - [[foo='ı' i\]
with querySelector in standards mode] - expected: FAIL - - [[foo='İ' i\]
in standards mode] - expected: FAIL - - [[foo='İ' i\]
with querySelector in standards mode] - expected: FAIL - - [[foo='ı' i\]
in standards mode] - expected: FAIL - - [[foo='ı' i\]
with querySelector in standards mode] - expected: FAIL - - [[foo='bar' i\]
in standards mode] - expected: FAIL - - [[foo='bar' i\]
with querySelector in standards mode] - expected: FAIL - - [[|foo='bar' i\]
in standards mode] - expected: FAIL - - [[|foo='bar' i\]
with querySelector in standards mode] - expected: FAIL - - [[foo='bar' i\]
in standards mode] - expected: FAIL - - [[foo='bar' i\]
with querySelector in standards mode] - expected: FAIL - - [[foo='\t' i\] /* tab in selector */
in standards mode] - expected: FAIL - - [[foo='\t' i\] /* tab in selector */
with querySelector in standards mode] - expected: FAIL - - [[foo=' ' i\] /* tab in attribute */
in standards mode] - expected: FAIL - - [[foo=' ' i\] /* tab in attribute */
with querySelector in standards mode] - expected: FAIL - - [@namespace x 'a'; [x|foo='' i\]
in standards mode] - expected: FAIL - - [@namespace x 'A'; [x|foo='' i\]
in standards mode] - expected: FAIL - - [[foo='bar' i\][foo='bar'\]
in standards mode] - expected: FAIL - - [[foo='bar' i\][foo='bar'\]
with querySelector in standards mode] - expected: FAIL - - [[foo='bar' i\]
in standards mode] - expected: FAIL - - [[foo='bar' i\]
with querySelector in standards mode] - expected: FAIL - - [[foo='bar' i\]
in quirks mode] - expected: FAIL - - [[foo='bar' i\]
with querySelector in quirks mode] - expected: FAIL - - [[foo='' i\]
in quirks mode] - expected: FAIL - - [[foo='' i\]
with querySelector in quirks mode] - expected: FAIL - - [[foo='ä' i\] /* COMBINING in both */
in quirks mode] - expected: FAIL - - [[foo='ä' i\] /* COMBINING in both */
with querySelector in quirks mode] - expected: FAIL - - [[foo='Ä' i\] /* COMBINING in both */
in quirks mode] - expected: FAIL - - [[foo='Ä' i\] /* COMBINING in both */
with querySelector in quirks mode] - expected: FAIL - - [[*|foo='bar' i\]
in quirks mode] - expected: FAIL - - [[*|foo='bar' i\]
with querySelector in quirks mode] - expected: FAIL - - [[*|foo='bar' i\]
in quirks mode] - expected: FAIL - - [[*|foo='bar' i\]
with querySelector in quirks mode] - expected: FAIL - - [[align='left' i\]
in quirks mode] - expected: FAIL - - [[align='left' i\]
with querySelector in quirks mode] - expected: FAIL - - [[align='LEFT' i\]
in quirks mode] - expected: FAIL - - [[align='LEFT' i\]
with querySelector in quirks mode] - expected: FAIL - - [[class='a' i\]
in quirks mode] - expected: FAIL - - [[class='a' i\]
with querySelector in quirks mode] - expected: FAIL - - [[class='A' i\]
in quirks mode] - expected: FAIL - - [[class='A' i\]
with querySelector in quirks mode] - expected: FAIL - - [[id='a' i\]
in quirks mode] - expected: FAIL - - [[id='a' i\]
with querySelector in quirks mode] - expected: FAIL - - [[id='A' i\]
in quirks mode] - expected: FAIL - - [[id='A' i\]
with querySelector in quirks mode] - expected: FAIL - - [[lang='a' i\]
in quirks mode] - expected: FAIL - - [[lang='a' i\]
with querySelector in quirks mode] - expected: FAIL - - [[lang='A' i\]
in quirks mode] - expected: FAIL - - [[lang='A' i\]
with querySelector in quirks mode] - expected: FAIL - - [[*|lang='a' i\]
in quirks mode] - expected: FAIL - - [[*|lang='a' i\]
with querySelector in quirks mode] - expected: FAIL - - [[*|lang='A' i\]
in quirks mode] - expected: FAIL - - [[*|lang='A' i\]
with querySelector in quirks mode] - expected: FAIL - - [@namespace x 'http://www.w3.org/XML/1998/namespace'; [x|lang='A' i\]
in quirks mode] - expected: FAIL - - [[foo='bar' i\][foo='bar' i\]
in quirks mode] - expected: FAIL - - [[foo='bar' i\][foo='bar' i\]
with querySelector in quirks mode] - expected: FAIL - - [[foo='BAR'\][foo='bar' i\]
in quirks mode] - expected: FAIL - - [[foo='BAR'\][foo='bar' i\]
with querySelector in quirks mode] - expected: FAIL - - [[foo='bar' i\][foo='BAR'\]
in quirks mode] - expected: FAIL - - [[foo='bar' i\][foo='BAR'\]
with querySelector in quirks mode] - expected: FAIL - - [[foo='' i\]
in quirks mode] - expected: FAIL - - [[foo='' i\]
with querySelector in quirks mode] - expected: FAIL - - [[foo='\x00' i\] /* \\0 in selector */
in quirks mode] - expected: FAIL - - [[foo='\x00' i\] /* \\0 in selector */
with querySelector in quirks mode] - expected: FAIL - - [[foo='' i\] /* \\0 in attribute */
in quirks mode] - expected: FAIL - - [[foo='' i\] /* \\0 in attribute */
with querySelector in quirks mode] - expected: FAIL - - [[foo='ä' i\]
in quirks mode] - expected: FAIL - - [[foo='ä' i\]
with querySelector in quirks mode] - expected: FAIL - - [[foo='Ä' i\]
in quirks mode] - expected: FAIL - - [[foo='Ä' i\]
with querySelector in quirks mode] - expected: FAIL - - [[foo='ä' i\] /* COMBINING in selector */
in quirks mode] - expected: FAIL - - [[foo='ä' i\] /* COMBINING in selector */
with querySelector in quirks mode] - expected: FAIL - - [[foo='ä' i\] /* COMBINING in selector */
in quirks mode] - expected: FAIL - - [[foo='ä' i\] /* COMBINING in selector */
with querySelector in quirks mode] - expected: FAIL - - [[foo='Ä' i\] /* COMBINING in selector */
in quirks mode] - expected: FAIL - - [[foo='Ä' i\] /* COMBINING in selector */
with querySelector in quirks mode] - expected: FAIL - - [[foo='Ä' i\] /* COMBINING in selector */
in quirks mode] - expected: FAIL - - [[foo='Ä' i\] /* COMBINING in selector */
with querySelector in quirks mode] - expected: FAIL - - [[foo='ä' i\] /* COMBINING in attribute */
in quirks mode] - expected: FAIL - - [[foo='ä' i\] /* COMBINING in attribute */
with querySelector in quirks mode] - expected: FAIL - - [[foo='ä' i\] /* COMBINING in attribute */
in quirks mode] - expected: FAIL - - [[foo='ä' i\] /* COMBINING in attribute */
with querySelector in quirks mode] - expected: FAIL - - [[foo='Ä' i\] /* COMBINING in attribute */
in quirks mode] - expected: FAIL - - [[foo='Ä' i\] /* COMBINING in attribute */
with querySelector in quirks mode] - expected: FAIL - - [[foo='Ä' i\] /* COMBINING in attribute */
in quirks mode] - expected: FAIL - - [[foo='Ä' i\] /* COMBINING in attribute */
with querySelector in quirks mode] - expected: FAIL - - [[foo='ä' i\] /* COMBINING in selector */
in quirks mode] - expected: FAIL - - [[foo='ä' i\] /* COMBINING in selector */
with querySelector in quirks mode] - expected: FAIL - - [[foo='ä' i\] /* COMBINING in selector */
in quirks mode] - expected: FAIL - - [[foo='ä' i\] /* COMBINING in selector */
with querySelector in quirks mode] - expected: FAIL - - [[foo='Ä' i\] /* COMBINING in selector */
in quirks mode] - expected: FAIL - - [[foo='Ä' i\] /* COMBINING in selector */
with querySelector in quirks mode] - expected: FAIL - - [[foo='Ä' i\] /* COMBINING in selector */
in quirks mode] - expected: FAIL - - [[foo='Ä' i\] /* COMBINING in selector */
with querySelector in quirks mode] - expected: FAIL - - [[foo='a' i\] /* COMBINING in attribute */
in quirks mode] - expected: FAIL - - [[foo='a' i\] /* COMBINING in attribute */
with querySelector in quirks mode] - expected: FAIL - - [[foo='A' i\] /* COMBINING in attribute */
in quirks mode] - expected: FAIL - - [[foo='A' i\] /* COMBINING in attribute */
with querySelector in quirks mode] - expected: FAIL - - [[foo='a' i\] /* COMBINING in attribute */
in quirks mode] - expected: FAIL - - [[foo='a' i\] /* COMBINING in attribute */
with querySelector in quirks mode] - expected: FAIL - - [[foo='A' i\] /* COMBINING in attribute */
in quirks mode] - expected: FAIL - - [[foo='A' i\] /* COMBINING in attribute */
with querySelector in quirks mode] - expected: FAIL - - [[foo='i' i\]
in quirks mode] - expected: FAIL - - [[foo='i' i\]
with querySelector in quirks mode] - expected: FAIL - - [[foo='i' i\]
in quirks mode] - expected: FAIL - - [[foo='i' i\]
with querySelector in quirks mode] - expected: FAIL - - [[foo='I' i\]
in quirks mode] - expected: FAIL - - [[foo='I' i\]
with querySelector in quirks mode] - expected: FAIL - - [[foo='I' i\]
in quirks mode] - expected: FAIL - - [[foo='I' i\]
with querySelector in quirks mode] - expected: FAIL - - [[foo='İ' i\]
in quirks mode] - expected: FAIL - - [[foo='İ' i\]
with querySelector in quirks mode] - expected: FAIL - - [[foo='ı' i\]
in quirks mode] - expected: FAIL - - [[foo='ı' i\]
with querySelector in quirks mode] - expected: FAIL - - [[foo='İ' i\]
in quirks mode] - expected: FAIL - - [[foo='İ' i\]
with querySelector in quirks mode] - expected: FAIL - - [[foo='ı' i\]
in quirks mode] - expected: FAIL - - [[foo='ı' i\]
with querySelector in quirks mode] - expected: FAIL - - [[foo='bar' i\]
in quirks mode] - expected: FAIL - - [[foo='bar' i\]
with querySelector in quirks mode] - expected: FAIL - - [[|foo='bar' i\]
in quirks mode] - expected: FAIL - - [[|foo='bar' i\]
with querySelector in quirks mode] - expected: FAIL - - [[foo='bar' i\]
in quirks mode] - expected: FAIL - - [[foo='bar' i\]
with querySelector in quirks mode] - expected: FAIL - - [[foo='\t' i\] /* tab in selector */
in quirks mode] - expected: FAIL - - [[foo='\t' i\] /* tab in selector */
with querySelector in quirks mode] - expected: FAIL - - [[foo=' ' i\] /* tab in attribute */
in quirks mode] - expected: FAIL - - [[foo=' ' i\] /* tab in attribute */
with querySelector in quirks mode] - expected: FAIL - - [@namespace x 'a'; [x|foo='' i\]
in quirks mode] - expected: FAIL - - [@namespace x 'A'; [x|foo='' i\]
in quirks mode] - expected: FAIL - - [[foo='bar' i\][foo='bar'\]
in quirks mode] - expected: FAIL - - [[foo='bar' i\][foo='bar'\]
with querySelector in quirks mode] - expected: FAIL - - [[foo='bar' i\]
in quirks mode] - expected: FAIL - - [[foo='bar' i\]
with querySelector in quirks mode] - expected: FAIL - - [[foo='bar' i\]
in XML] - expected: FAIL - - [[foo='bar' i\]
with querySelector in XML] - expected: FAIL - - [[foo='' i\]
in XML] - expected: FAIL - - [[foo='' i\]
with querySelector in XML] - expected: FAIL - - [[foo='ä' i\] /* COMBINING in both */
in XML] - expected: FAIL - - [[foo='ä' i\] /* COMBINING in both */
with querySelector in XML] - expected: FAIL - - [[foo='Ä' i\] /* COMBINING in both */
in XML] - expected: FAIL - - [[foo='Ä' i\] /* COMBINING in both */
with querySelector in XML] - expected: FAIL - - [[*|foo='bar' i\]
in XML] - expected: FAIL - - [[*|foo='bar' i\]
with querySelector in XML] - expected: FAIL - - [[*|foo='bar' i\]
in XML] - expected: FAIL - - [[*|foo='bar' i\]
with querySelector in XML] - expected: FAIL - - [[align='left' i\]
in XML] - expected: FAIL - - [[align='left' i\]
with querySelector in XML] - expected: FAIL - - [[align='LEFT' i\]
in XML] - expected: FAIL - - [[align='LEFT' i\]
with querySelector in XML] - expected: FAIL - - [[class='a' i\]
in XML] - expected: FAIL - - [[class='a' i\]
with querySelector in XML] - expected: FAIL - - [[class='A' i\]
in XML] - expected: FAIL - - [[class='A' i\]
with querySelector in XML] - expected: FAIL - - [[id='a' i\]
in XML] - expected: FAIL - - [[id='a' i\]
with querySelector in XML] - expected: FAIL - - [[id='A' i\]
in XML] - expected: FAIL - - [[id='A' i\]
with querySelector in XML] - expected: FAIL - - [[lang='a' i\]
in XML] - expected: FAIL - - [[lang='a' i\]
with querySelector in XML] - expected: FAIL - - [[lang='A' i\]
in XML] - expected: FAIL - - [[lang='A' i\]
with querySelector in XML] - expected: FAIL - - [[*|lang='a' i\]
in XML] - expected: FAIL - - [[*|lang='a' i\]
with querySelector in XML] - expected: FAIL - - [[*|lang='A' i\]
in XML] - expected: FAIL - - [[*|lang='A' i\]
with querySelector in XML] - expected: FAIL - - [@namespace x 'http://www.w3.org/XML/1998/namespace'; [x|lang='A' i\]
in XML] - expected: FAIL - - [[foo='bar' i\][foo='bar' i\]
in XML] - expected: FAIL - - [[foo='bar' i\][foo='bar' i\]
with querySelector in XML] - expected: FAIL - - [[foo='BAR'\][foo='bar' i\]
in XML] - expected: FAIL - - [[foo='BAR'\][foo='bar' i\]
with querySelector in XML] - expected: FAIL - - [[foo='bar' i\][foo='BAR'\]
in XML] - expected: FAIL - - [[foo='bar' i\][foo='BAR'\]
with querySelector in XML] - expected: FAIL - - [[foo='' i\]
in XML] - expected: FAIL - - [[foo='' i\]
with querySelector in XML] - expected: FAIL - - [[foo='\x00' i\] /* \\0 in selector */
in XML] - expected: FAIL - - [[foo='\x00' i\] /* \\0 in selector */
with querySelector in XML] - expected: FAIL - - [[foo='' i\] /* \\0 in attribute */
in XML] - expected: FAIL - - [[foo='' i\] /* \\0 in attribute */
with querySelector in XML] - expected: FAIL - - [[foo='ä' i\]
in XML] - expected: FAIL - - [[foo='ä' i\]
with querySelector in XML] - expected: FAIL - - [[foo='Ä' i\]
in XML] - expected: FAIL - - [[foo='Ä' i\]
with querySelector in XML] - expected: FAIL - - [[foo='ä' i\] /* COMBINING in selector */
in XML] - expected: FAIL - - [[foo='ä' i\] /* COMBINING in selector */
with querySelector in XML] - expected: FAIL - - [[foo='ä' i\] /* COMBINING in selector */
in XML] - expected: FAIL - - [[foo='ä' i\] /* COMBINING in selector */
with querySelector in XML] - expected: FAIL - - [[foo='Ä' i\] /* COMBINING in selector */
in XML] - expected: FAIL - - [[foo='Ä' i\] /* COMBINING in selector */
with querySelector in XML] - expected: FAIL - - [[foo='Ä' i\] /* COMBINING in selector */
in XML] - expected: FAIL - - [[foo='Ä' i\] /* COMBINING in selector */
with querySelector in XML] - expected: FAIL - - [[foo='ä' i\] /* COMBINING in attribute */
in XML] - expected: FAIL - - [[foo='ä' i\] /* COMBINING in attribute */
with querySelector in XML] - expected: FAIL - - [[foo='ä' i\] /* COMBINING in attribute */
in XML] - expected: FAIL - - [[foo='ä' i\] /* COMBINING in attribute */
with querySelector in XML] - expected: FAIL - - [[foo='Ä' i\] /* COMBINING in attribute */
in XML] - expected: FAIL - - [[foo='Ä' i\] /* COMBINING in attribute */
with querySelector in XML] - expected: FAIL - - [[foo='Ä' i\] /* COMBINING in attribute */
in XML] - expected: FAIL - - [[foo='Ä' i\] /* COMBINING in attribute */
with querySelector in XML] - expected: FAIL - - [[foo='ä' i\] /* COMBINING in selector */
in XML] - expected: FAIL - - [[foo='ä' i\] /* COMBINING in selector */
with querySelector in XML] - expected: FAIL - - [[foo='ä' i\] /* COMBINING in selector */
in XML] - expected: FAIL - - [[foo='ä' i\] /* COMBINING in selector */
with querySelector in XML] - expected: FAIL - - [[foo='Ä' i\] /* COMBINING in selector */
in XML] - expected: FAIL - - [[foo='Ä' i\] /* COMBINING in selector */
with querySelector in XML] - expected: FAIL - - [[foo='Ä' i\] /* COMBINING in selector */
in XML] - expected: FAIL - - [[foo='Ä' i\] /* COMBINING in selector */
with querySelector in XML] - expected: FAIL - - [[foo='a' i\] /* COMBINING in attribute */
in XML] - expected: FAIL - - [[foo='a' i\] /* COMBINING in attribute */
with querySelector in XML] - expected: FAIL - - [[foo='A' i\] /* COMBINING in attribute */
in XML] - expected: FAIL - - [[foo='A' i\] /* COMBINING in attribute */
with querySelector in XML] - expected: FAIL - - [[foo='a' i\] /* COMBINING in attribute */
in XML] - expected: FAIL - - [[foo='a' i\] /* COMBINING in attribute */
with querySelector in XML] - expected: FAIL - - [[foo='A' i\] /* COMBINING in attribute */
in XML] - expected: FAIL - - [[foo='A' i\] /* COMBINING in attribute */
with querySelector in XML] - expected: FAIL - - [[foo='i' i\]
in XML] - expected: FAIL - - [[foo='i' i\]
with querySelector in XML] - expected: FAIL - - [[foo='i' i\]
in XML] - expected: FAIL - - [[foo='i' i\]
with querySelector in XML] - expected: FAIL - - [[foo='I' i\]
in XML] - expected: FAIL - - [[foo='I' i\]
with querySelector in XML] - expected: FAIL - - [[foo='I' i\]
in XML] - expected: FAIL - - [[foo='I' i\]
with querySelector in XML] - expected: FAIL - - [[foo='İ' i\]
in XML] - expected: FAIL - - [[foo='İ' i\]
with querySelector in XML] - expected: FAIL - - [[foo='ı' i\]
in XML] - expected: FAIL - - [[foo='ı' i\]
with querySelector in XML] - expected: FAIL - - [[foo='İ' i\]
in XML] - expected: FAIL - - [[foo='İ' i\]
with querySelector in XML] - expected: FAIL - - [[foo='ı' i\]
in XML] - expected: FAIL - - [[foo='ı' i\]
with querySelector in XML] - expected: FAIL - - [[foo='bar' i\]
in XML] - expected: FAIL - - [[foo='bar' i\]
with querySelector in XML] - expected: FAIL - - [[|foo='bar' i\]
in XML] - expected: FAIL - - [[|foo='bar' i\]
with querySelector in XML] - expected: FAIL - - [[foo='bar' i\]
in XML] - expected: FAIL - - [[foo='bar' i\]
with querySelector in XML] - expected: FAIL - - [[foo='\t' i\] /* tab in selector */
in XML] - expected: FAIL - - [[foo='\t' i\] /* tab in selector */
with querySelector in XML] - expected: FAIL - - [[foo=' ' i\] /* tab in attribute */
in XML] - expected: FAIL - - [[foo=' ' i\] /* tab in attribute */
with querySelector in XML] - expected: FAIL - - [@namespace x 'a'; [x|foo='' i\]
in XML] - expected: FAIL - - [@namespace x 'A'; [x|foo='' i\]
in XML] - expected: FAIL - - [[foo='bar' i\][foo='bar'\]
in XML] - expected: FAIL - - [[foo='bar' i\][foo='bar'\]
with querySelector in XML] - expected: FAIL - - [[foo='bar' i\]
in XML] - expected: FAIL - - [[foo='bar' i\]
with querySelector in XML] - expected: FAIL - diff --git a/testing/web-platform/meta/selectors/attribute-selectors/attribute-case/syntax.html.ini b/testing/web-platform/meta/selectors/attribute-selectors/attribute-case/syntax.html.ini deleted file mode 100644 index 4b45e9b304..0000000000 --- a/testing/web-platform/meta/selectors/attribute-selectors/attribute-case/syntax.html.ini +++ /dev/null @@ -1,374 +0,0 @@ -[syntax.html] - type: testharness - [[foo /* sanity check (invalid) */ with querySelector in standards mode] - expected: FAIL - - [[foo='bar' i\] in standards mode] - expected: FAIL - - [[foo='bar' i\] with querySelector in standards mode] - expected: FAIL - - [[foo=bar i\] in standards mode] - expected: FAIL - - [[foo=bar i\] with querySelector in standards mode] - expected: FAIL - - [[foo="bar" i\] in standards mode] - expected: FAIL - - [[foo="bar" i\] with querySelector in standards mode] - expected: FAIL - - [[foo='bar'i\] in standards mode] - expected: FAIL - - [[foo='bar'i\] with querySelector in standards mode] - expected: FAIL - - [[foo='bar'i \] in standards mode] - expected: FAIL - - [[foo='bar'i \] with querySelector in standards mode] - expected: FAIL - - [[foo='bar' i \] in standards mode] - expected: FAIL - - [[foo='bar' i \] with querySelector in standards mode] - expected: FAIL - - [[foo='bar' /**/ i\] in standards mode] - expected: FAIL - - [[foo='bar' /**/ i\] with querySelector in standards mode] - expected: FAIL - - [[foo='bar' i /**/ \] in standards mode] - expected: FAIL - - [[foo='bar' i /**/ \] with querySelector in standards mode] - expected: FAIL - - [[foo='bar'/**/i/**/\] in standards mode] - expected: FAIL - - [[foo='bar'/**/i/**/\] with querySelector in standards mode] - expected: FAIL - - [[foo=bar/**/i\] in standards mode] - expected: FAIL - - [[foo=bar/**/i\] with querySelector in standards mode] - expected: FAIL - - [[foo='bar'\ti\t\] /* \\t */ in standards mode] - expected: FAIL - - [[foo='bar'\ti\t\] /* \\t */ with querySelector in standards mode] - expected: FAIL - - [[foo='bar'\ni\n\] /* \\n */ in standards mode] - expected: FAIL - - [[foo='bar'\ni\n\] /* \\n */ with querySelector in standards mode] - expected: FAIL - - [[foo='bar'\ri\r\] /* \\r */ in standards mode] - expected: FAIL - - [[foo='bar'\ri\r\] /* \\r */ with querySelector in standards mode] - expected: FAIL - - [[foo='bar' \\i\] in standards mode] - expected: FAIL - - [[foo='bar' \\i\] with querySelector in standards mode] - expected: FAIL - - [[foo='bar' \\69\] in standards mode] - expected: FAIL - - [[foo='bar' \\69\] with querySelector in standards mode] - expected: FAIL - - [[foo~='bar' i\] in standards mode] - expected: FAIL - - [[foo~='bar' i\] with querySelector in standards mode] - expected: FAIL - - [[foo^='bar' i\] in standards mode] - expected: FAIL - - [[foo^='bar' i\] with querySelector in standards mode] - expected: FAIL - - [[foo$='bar' i\] in standards mode] - expected: FAIL - - [[foo$='bar' i\] with querySelector in standards mode] - expected: FAIL - - [[|foo='bar' i\] in standards mode] - expected: FAIL - - [[|foo='bar' i\] with querySelector in standards mode] - expected: FAIL - - [[*|foo='bar' i\] in standards mode] - expected: FAIL - - [[*|foo='bar' i\] with querySelector in standards mode] - expected: FAIL - - [[foo /* sanity check (invalid) */ with querySelector in standards mode] - expected: FAIL - - [[foo='bar' i\] in quirks mode] - expected: FAIL - - [[foo='bar' i\] with querySelector in quirks mode] - expected: FAIL - - [[foo=bar i\] in quirks mode] - expected: FAIL - - [[foo=bar i\] with querySelector in quirks mode] - expected: FAIL - - [[foo="bar" i\] in quirks mode] - expected: FAIL - - [[foo="bar" i\] with querySelector in quirks mode] - expected: FAIL - - [[foo='bar'i\] in quirks mode] - expected: FAIL - - [[foo='bar'i\] with querySelector in quirks mode] - expected: FAIL - - [[foo='bar'i \] in quirks mode] - expected: FAIL - - [[foo='bar'i \] with querySelector in quirks mode] - expected: FAIL - - [[foo='bar' i \] in quirks mode] - expected: FAIL - - [[foo='bar' i \] with querySelector in quirks mode] - expected: FAIL - - [[foo='bar' /**/ i\] in quirks mode] - expected: FAIL - - [[foo='bar' /**/ i\] with querySelector in quirks mode] - expected: FAIL - - [[foo='bar' i /**/ \] in quirks mode] - expected: FAIL - - [[foo='bar' i /**/ \] with querySelector in quirks mode] - expected: FAIL - - [[foo='bar'/**/i/**/\] in quirks mode] - expected: FAIL - - [[foo='bar'/**/i/**/\] with querySelector in quirks mode] - expected: FAIL - - [[foo=bar/**/i\] in quirks mode] - expected: FAIL - - [[foo=bar/**/i\] with querySelector in quirks mode] - expected: FAIL - - [[foo='bar'\ti\t\] /* \\t */ in quirks mode] - expected: FAIL - - [[foo='bar'\ti\t\] /* \\t */ with querySelector in quirks mode] - expected: FAIL - - [[foo='bar'\ni\n\] /* \\n */ in quirks mode] - expected: FAIL - - [[foo='bar'\ni\n\] /* \\n */ with querySelector in quirks mode] - expected: FAIL - - [[foo='bar'\ri\r\] /* \\r */ in quirks mode] - expected: FAIL - - [[foo='bar'\ri\r\] /* \\r */ with querySelector in quirks mode] - expected: FAIL - - [[foo='bar' \\i\] in quirks mode] - expected: FAIL - - [[foo='bar' \\i\] with querySelector in quirks mode] - expected: FAIL - - [[foo='bar' \\69\] in quirks mode] - expected: FAIL - - [[foo='bar' \\69\] with querySelector in quirks mode] - expected: FAIL - - [[foo~='bar' i\] in quirks mode] - expected: FAIL - - [[foo~='bar' i\] with querySelector in quirks mode] - expected: FAIL - - [[foo^='bar' i\] in quirks mode] - expected: FAIL - - [[foo^='bar' i\] with querySelector in quirks mode] - expected: FAIL - - [[foo$='bar' i\] in quirks mode] - expected: FAIL - - [[foo$='bar' i\] with querySelector in quirks mode] - expected: FAIL - - [[|foo='bar' i\] in quirks mode] - expected: FAIL - - [[|foo='bar' i\] with querySelector in quirks mode] - expected: FAIL - - [[*|foo='bar' i\] in quirks mode] - expected: FAIL - - [[*|foo='bar' i\] with querySelector in quirks mode] - expected: FAIL - - [[foo /* sanity check (invalid) */ with querySelector in quirks mode] - expected: FAIL - - [[foo='bar' i\] in XML] - expected: FAIL - - [[foo='bar' i\] with querySelector in XML] - expected: FAIL - - [[foo=bar i\] in XML] - expected: FAIL - - [[foo=bar i\] with querySelector in XML] - expected: FAIL - - [[foo="bar" i\] in XML] - expected: FAIL - - [[foo="bar" i\] with querySelector in XML] - expected: FAIL - - [[foo='bar'i\] in XML] - expected: FAIL - - [[foo='bar'i\] with querySelector in XML] - expected: FAIL - - [[foo='bar'i \] in XML] - expected: FAIL - - [[foo='bar'i \] with querySelector in XML] - expected: FAIL - - [[foo='bar' i \] in XML] - expected: FAIL - - [[foo='bar' i \] with querySelector in XML] - expected: FAIL - - [[foo='bar' /**/ i\] in XML] - expected: FAIL - - [[foo='bar' /**/ i\] with querySelector in XML] - expected: FAIL - - [[foo='bar' i /**/ \] in XML] - expected: FAIL - - [[foo='bar' i /**/ \] with querySelector in XML] - expected: FAIL - - [[foo='bar'/**/i/**/\] in XML] - expected: FAIL - - [[foo='bar'/**/i/**/\] with querySelector in XML] - expected: FAIL - - [[foo=bar/**/i\] in XML] - expected: FAIL - - [[foo=bar/**/i\] with querySelector in XML] - expected: FAIL - - [[foo='bar'\ti\t\] /* \\t */ in XML] - expected: FAIL - - [[foo='bar'\ti\t\] /* \\t */ with querySelector in XML] - expected: FAIL - - [[foo='bar'\ni\n\] /* \\n */ in XML] - expected: FAIL - - [[foo='bar'\ni\n\] /* \\n */ with querySelector in XML] - expected: FAIL - - [[foo='bar'\ri\r\] /* \\r */ in XML] - expected: FAIL - - [[foo='bar'\ri\r\] /* \\r */ with querySelector in XML] - expected: FAIL - - [[foo='bar' \\i\] in XML] - expected: FAIL - - [[foo='bar' \\i\] with querySelector in XML] - expected: FAIL - - [[foo='bar' \\69\] in XML] - expected: FAIL - - [[foo='bar' \\69\] with querySelector in XML] - expected: FAIL - - [[foo~='bar' i\] in XML] - expected: FAIL - - [[foo~='bar' i\] with querySelector in XML] - expected: FAIL - - [[foo^='bar' i\] in XML] - expected: FAIL - - [[foo^='bar' i\] with querySelector in XML] - expected: FAIL - - [[foo$='bar' i\] in XML] - expected: FAIL - - [[foo$='bar' i\] with querySelector in XML] - expected: FAIL - - [[|foo='bar' i\] in XML] - expected: FAIL - - [[|foo='bar' i\] with querySelector in XML] - expected: FAIL - - [[*|foo='bar' i\] in XML] - expected: FAIL - - [[*|foo='bar' i\] with querySelector in XML] - expected: FAIL - - [[foo /* sanity check (invalid) */ with querySelector in XML] - expected: FAIL - diff --git a/testing/web-platform/meta/web-animations/animatable/animate.html.ini b/testing/web-platform/meta/web-animations/animatable/animate.html.ini index cc950d3cf4..bb57bc344f 100644 --- a/testing/web-platform/meta/web-animations/animatable/animate.html.ini +++ b/testing/web-platform/meta/web-animations/animatable/animate.html.ini @@ -1,8 +1,5 @@ [animate.html] type: testharness - [Element.animate() creates an Animation object with a KeyframeEffect] - expected: FAIL - bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1211783 [Element.animate() accepts a single-valued keyframe specification] expected: FAIL bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1216844 diff --git a/testing/web-platform/tests/dom/interface-objects.html b/testing/web-platform/tests/dom/interface-objects.html index c0697b566c..422ae6f801 100644 --- a/testing/web-platform/tests/dom/interface-objects.html +++ b/testing/web-platform/tests/dom/interface-objects.html @@ -31,10 +31,8 @@ var interfaces = [ "NodeFilter", "NodeList", "HTMLCollection", - "DOMStringList", "DOMTokenList", - "DOMSettableTokenList" -]; + ]; test(function() { for (var p in window) { interfaces.forEach(function(i) { diff --git a/testing/web-platform/tests/dom/interfaces.html b/testing/web-platform/tests/dom/interfaces.html index 4db1a38667..f020d33a4b 100644 --- a/testing/web-platform/tests/dom/interfaces.html +++ b/testing/web-platform/tests/dom/interfaces.html @@ -282,7 +282,7 @@ interface Element : Node { attribute DOMString id; attribute DOMString className; - [SameObject] readonly attribute DOMTokenList classList; + [SameObject, PutForwards=value] readonly attribute DOMTokenList classList; boolean hasAttributes(); [SameObject] readonly attribute NamedNodeMap attributes; @@ -465,10 +465,6 @@ interface DOMTokenList { stringifier; // iterable; }; - -interface DOMSettableTokenList : DOMTokenList { - attribute DOMString value; -}; - diff --git a/testing/web-platform/tests/old-tests/submission/Microsoft/sandbox/sandbox_011.htm b/testing/web-platform/tests/old-tests/submission/Microsoft/sandbox/sandbox_011.htm index 0427ec0783..442500fbd3 100644 --- a/testing/web-platform/tests/old-tests/submission/Microsoft/sandbox/sandbox_011.htm +++ b/testing/web-platform/tests/old-tests/submission/Microsoft/sandbox/sandbox_011.htm @@ -1,11 +1,11 @@ - HTML5 Sandbox: iframe sandbox attribute value support DOMSettableTokenList interface. + HTML5 Sandbox: iframe sandbox attribute value support DOMTokenList interface. - + @@ -17,29 +17,29 @@ test(function() { var iframeEle = document.getElementById("iframe1"); assert_equals(iframeEle.sandbox.length, 3) - }, "DOMSettableTokenList length") + }, "DOMTokenList length") test(function() { var iframeEle = document.getElementById("iframe1"); assert_equals(iframeEle.sandbox.item(1), "allow-same-origin") - }, "DOMSettableTokenList item(index)") + }, "DOMTokenList item(index)") test(function() { var iframeEle = document.getElementById("iframe1"); assert_true(iframeEle.sandbox.contains("allow-forms")) - }, "DOMSettableTokenList contains(DomString)") + }, "DOMTokenList contains(DomString)") test(function() { var iframeEle = document.getElementById("iframe1"); iframeEle.sandbox.add("ALLOW-SANDBOX"); assert_true(iframeEle.sandbox.contains("ALLOW-SANDBOX")) - }, "DOMSettableTokenList add(DomString)") + }, "DOMTokenList add(DomString)") test(function() { var iframeEle = document.getElementById("iframe1"); iframeEle.sandbox.remove("ALLOW-SANDBOX"); assert_false(iframeEle.sandbox.contains("ALLOW-SANDBOX")) - }, "DOMSettableTokenList remove(DomString)") + }, "DOMTokenList remove(DomString)") test(function() { var iframeEle = document.getElementById("iframe1"); @@ -48,18 +48,18 @@ iframeEle.sandbox.toggle("allow-top-navigation") && iframeEle.sandbox.contains("allow-top-navigation") && !iframeEle.sandbox.toggle("allow-top-navigation") && !iframeEle.sandbox.contains("allow-top-navigation") ) - }, "DOMSettableTokenList toggle(DomString) - Returns true if token is now present (it was added); returns false if it is not (it was removed).") + }, "DOMTokenList toggle(DomString) - Returns true if token is now present (it was added); returns false if it is not (it was removed).") test(function() { var iframeEle = document.getElementById("iframe1"); assert_equals(iframeEle.sandbox.value, iframeEle.sandbox.toString()) - }, "DOMSettableTokenList sandbox.toString()") + }, "DOMTokenList sandbox.toString()") test(function() { var iframeEle = document.getElementById("iframe1"); iframeEle.sandbox.remove("ALLOW-SANDBOX"); assert_true(iframeEle.sandbox.contains("allow-scripts") != iframeEle.sandbox.contains("Allow-SCRIPTS")) - }, "DOMSettableTokenList case sensitivity") + }, "DOMTokenList case sensitivity") diff --git a/testing/web-platform/tests/web-animations/keyframe-effect/constructor.html b/testing/web-platform/tests/web-animations/keyframe-effect/constructor.html index 06af7b4626..1bcb4983b1 100644 --- a/testing/web-platform/tests/web-animations/keyframe-effect/constructor.html +++ b/testing/web-platform/tests/web-animations/keyframe-effect/constructor.html @@ -629,6 +629,23 @@ gKeyframeEffectOptionTests.forEach(function(stest) { }, "a KeyframeEffectReadOnly constructed by " + stest.desc); }); +test(function(t) { + var effect = new KeyframeEffect(target, + {left: ["10px", "20px"]}); + + assert_class_string(effect, "KeyframeEffect"); + assert_class_string(effect.timing, "AnimationEffectTiming"); +}, "KeyframeEffect constructor creates an AnimationEffectTiming timing object"); + +test(function(t) { + var test_error = { name: "test" }; + + assert_throws(test_error, function() { + new KeyframeEffect(target, { get left() { throw test_error }}) + }); +}, "KeyframeEffect constructor propagates exceptions generated by accessing" + + " the options object"); + done();