nsStyleContext*
nsTransitionManager::UpdateThrottledStyle(dom::Element* aElement,
                                          nsStyleContext* aParentStyle)
{
  NS_ASSERTION(GetElementTransitions(aElement,
                                     nsCSSPseudoElements::ePseudo_NotPseudoElement,
                                     false), "element not transitioning");

  nsIFrame* primaryFrame = aElement->GetPrimaryFrame();
  if (!primaryFrame) {
    return nullptr;
  }

  nsStyleContext* oldStyle = primaryFrame->GetStyleContext();
  nsRuleNode* ruleNode = oldStyle->GetRuleNode();
  nsTArray<nsStyleSet::RuleAndLevel> rules;
  do {
    if (ruleNode->IsRoot()) {
      break;
    }

    nsStyleSet::RuleAndLevel* curRule = rules.AppendElement();
    curRule->mLevel = ruleNode->GetLevel();

    if (curRule->mLevel == nsStyleSet::eAnimationSheet) {
      ElementAnimations* ea = 
        mPresContext->AnimationManager()->GetElementAnimations(aElement,
                                                               oldStyle->GetPseudoType(),
                                                               false);
      NS_ASSERTION(ea, "Rule has level eAnimationSheet without animation on manager");

      mPresContext->AnimationManager()->EnsureStyleRuleFor(ea);
      curRule->mRule = ea->mStyleRule;

      ForceLayerRerendering(primaryFrame, ea);
    } else if (curRule->mLevel == nsStyleSet::eTransitionSheet) {
      ElementTransitions *et =
        GetElementTransitions(aElement, oldStyle->GetPseudoType(), false);
      NS_ASSERTION(et, "Rule has level eTransitionSheet without transition on manager");
      
      et->EnsureStyleRuleFor(mPresContext->RefreshDriver()->MostRecentRefresh());
      curRule->mRule = et->mStyleRule;

      ForceLayerRerendering(primaryFrame, et);
    } else {
      curRule->mRule = ruleNode->GetRule();
    }
  } while ((ruleNode = ruleNode->GetParent()));

  nsRefPtr<nsStyleContext> newStyle = mPresContext->PresShell()->StyleSet()->
    ResolveStyleForRules(aParentStyle, oldStyle, rules);
  primaryFrame->SetStyleContextWithoutNotification(newStyle);

  ReparentBeforeAndAfter(aElement, primaryFrame, newStyle, mPresContext->PresShell()->StyleSet());

  return newStyle;
}
nsStyleContext*
CommonAnimationManager::UpdateThrottledStyle(dom::Element* aElement,
                                             nsStyleContext* aParentStyle,
                                             nsStyleChangeList& aChangeList)
{
  NS_ASSERTION(mPresContext->TransitionManager()->GetElementTransitions(
                 aElement,
                 nsCSSPseudoElements::ePseudo_NotPseudoElement,
                 false) ||
               mPresContext->AnimationManager()->GetElementAnimations(
                 aElement,
                 nsCSSPseudoElements::ePseudo_NotPseudoElement,
                 false), "element not animated");

  nsIFrame* primaryFrame = nsLayoutUtils::GetStyleFrame(aElement);
  if (!primaryFrame) {
    return nullptr;
  }

  nsStyleContext* oldStyle = primaryFrame->StyleContext();
  nsRuleNode* ruleNode = oldStyle->RuleNode();
  nsTArray<nsStyleSet::RuleAndLevel> rules;
  do {
    if (ruleNode->IsRoot()) {
      break;
    }

    nsStyleSet::RuleAndLevel curRule;
    curRule.mLevel = ruleNode->GetLevel();

    if (curRule.mLevel == nsStyleSet::eAnimationSheet) {
      ElementAnimations* ea =
        mPresContext->AnimationManager()->GetElementAnimations(
          aElement,
          oldStyle->GetPseudoType(),
          false);
      NS_ASSERTION(ea,
        "Rule has level eAnimationSheet without animation on manager");

      mPresContext->AnimationManager()->EnsureStyleRuleFor(ea);
      curRule.mRule = ea->mStyleRule;
    } else if (curRule.mLevel == nsStyleSet::eTransitionSheet) {
      ElementTransitions *et =
        mPresContext->TransitionManager()->GetElementTransitions(
          aElement,
          oldStyle->GetPseudoType(),
          false);
      NS_ASSERTION(et,
        "Rule has level eTransitionSheet without transition on manager");

      et->EnsureStyleRuleFor(mPresContext->RefreshDriver()->MostRecentRefresh());
      curRule.mRule = et->mStyleRule;
    } else {
      curRule.mRule = ruleNode->GetRule();
    }

    if (curRule.mRule) {
      rules.AppendElement(curRule);
    }
  } while ((ruleNode = ruleNode->GetParent()));

  nsRefPtr<nsStyleContext> newStyle = mPresContext->PresShell()->StyleSet()->
    ResolveStyleForRules(aParentStyle, oldStyle, rules);

  // We absolutely must call CalcStyleDifference in order to ensure the
  // new context has all the structs cached that the old context had.
  // We also need it for processing of the changes.
  nsChangeHint styleChange =
    oldStyle->CalcStyleDifference(newStyle, nsChangeHint(0));
  aChangeList.AppendChange(primaryFrame, primaryFrame->GetContent(),
                           styleChange);

  primaryFrame->SetStyleContext(newStyle);

  ReparentBeforeAndAfter(aElement, primaryFrame, newStyle,
                         mPresContext->PresShell()->StyleSet());

  return newStyle;
}
nsStyleContext*
nsTransitionManager::UpdateThrottledStyle(dom::Element* aElement,
                                          nsStyleContext* aParentStyle,
                                          nsStyleChangeList& aChangeList)
{
  NS_ASSERTION(GetElementTransitions(aElement,
                                     nsCSSPseudoElements::ePseudo_NotPseudoElement,
                                     false), "element not transitioning");

  nsIFrame* primaryFrame = aElement->GetPrimaryFrame();
  if (!primaryFrame) {
    return nullptr;
  }

  nsStyleContext* oldStyle = primaryFrame->GetStyleContext();
  nsRuleNode* ruleNode = oldStyle->GetRuleNode();
  nsTArray<nsStyleSet::RuleAndLevel> rules;
  do {
    if (ruleNode->IsRoot()) {
      break;
    }

    nsStyleSet::RuleAndLevel curRule;
    curRule.mLevel = ruleNode->GetLevel();

    if (curRule.mLevel == nsStyleSet::eAnimationSheet) {
      ElementAnimations* ea = 
        mPresContext->AnimationManager()->GetElementAnimations(aElement,
                                                               oldStyle->GetPseudoType(),
                                                               false);
      NS_ASSERTION(ea, "Rule has level eAnimationSheet without animation on manager");

      mPresContext->AnimationManager()->EnsureStyleRuleFor(ea);
      curRule.mRule = ea->mStyleRule;

      // FIXME: maybe not needed anymore:
      ForceLayerRerendering(primaryFrame, ea);
    } else if (curRule.mLevel == nsStyleSet::eTransitionSheet) {
      ElementTransitions *et =
        GetElementTransitions(aElement, oldStyle->GetPseudoType(), false);
      NS_ASSERTION(et, "Rule has level eTransitionSheet without transition on manager");
      
      et->EnsureStyleRuleFor(mPresContext->RefreshDriver()->MostRecentRefresh());
      curRule.mRule = et->mStyleRule;

      // FIXME: maybe not needed anymore:
      ForceLayerRerendering(primaryFrame, et);
    } else {
      curRule.mRule = ruleNode->GetRule();
    }

    if (curRule.mRule) {
      rules.AppendElement(curRule);
    }
  } while ((ruleNode = ruleNode->GetParent()));

  nsRefPtr<nsStyleContext> newStyle = mPresContext->PresShell()->StyleSet()->
    ResolveStyleForRules(aParentStyle, oldStyle, rules);

  // We absolutely must call CalcStyleDifference in order to ensure the
  // new context has all the structs cached that the old context had.
  // We also need it for processing of the changes.
  nsChangeHint styleChange =
    oldStyle->CalcStyleDifference(newStyle, nsChangeHint(0));
  // This isn't particularly dangerous, but I want to catch if it happens:
  NS_ABORT_IF_FALSE(NS_IsHintSubset(styleChange,
                                    NS_CombineHint(nsChangeHint_UpdateOpacityLayer,
                                      NS_CombineHint(nsChangeHint_UpdateTransformLayer,
                                                     nsChangeHint_UpdateOverflow))),
                    "unexpected change hint");
  aChangeList.AppendChange(primaryFrame, primaryFrame->GetContent(),
                           styleChange);

  primaryFrame->SetStyleContextWithoutNotification(newStyle);

  ReparentBeforeAndAfter(aElement, primaryFrame, newStyle, mPresContext->PresShell()->StyleSet());

  return newStyle;
}