void
ServoRestyleManager::ContentInserted(nsINode* aContainer, nsIContent* aChild)
{
  if (aContainer == aContainer->OwnerDoc()) {
    // If we're getting this notification for the insertion of a root element,
    // that means either:
    //   (a) We initialized the PresShell before the root element existed, or
    //   (b) The root element was removed and it or another root is being
    //       inserted.
    //
    // Either way the whole tree is dirty, so we should style the document.
    MOZ_ASSERT(aChild == aChild->OwnerDoc()->GetRootElement());
    MOZ_ASSERT(aChild->IsDirtyForServo());
    StyleSet()->StyleDocument(/* aLeaveDirtyBits = */ false);
    return;
  }

  if (!aContainer->HasServoData()) {
    // This can happen with display:none. Bug 1297249 tracks more investigation
    // and assertions here.
    return;
  }

  // Style the new subtree because we will most likely need it during subsequent
  // frame construction. Bug 1298281 tracks deferring this work in the lazy
  // frame construction case.
  StyleSet()->StyleNewSubtree(aChild);

  RestyleForInsertOrChange(aContainer, aChild);
}
void
ServoRestyleManager::ContentAppended(nsIContent* aContainer,
                                     nsIContent* aFirstNewContent)
{
  if (!aContainer->HasServoData()) {
    // This can happen with display:none. Bug 1297249 tracks more investigation
    // and assertions here.
    return;
  }

  // Style the new subtree because we will most likely need it during subsequent
  // frame construction. Bug 1298281 tracks deferring this work in the lazy
  // frame construction case.
  if (aFirstNewContent->GetNextSibling()) {
    aContainer->SetHasDirtyDescendantsForServo();
    StyleSet()->StyleNewChildren(aContainer);
  } else {
    StyleSet()->StyleNewSubtree(aFirstNewContent);
  }

  RestyleForAppend(aContainer, aFirstNewContent);
}
void
ServoRestyleManager::PostRebuildAllStyleDataEvent(nsChangeHint aExtraHint,
                                                  nsRestyleHint aRestyleHint)
{
  StyleSet()->ClearDataAndMarkDeviceDirty();

  if (Element* root = mPresContext->Document()->GetRootElement()) {
    PostRestyleEvent(root, aRestyleHint, aExtraHint);
  }

  // TODO(emilio, bz): Extensions can add/remove stylesheets that can affect
  // non-inheriting anon boxes. It's not clear if we want to support that, but
  // if we do, we need to re-selector-match them here.
}
Exemple #4
0
void
ServoRestyleManager::RebuildAllStyleData(nsChangeHint aExtraHint,
                                         nsRestyleHint aRestyleHint)
{
  NS_WARNING("stylo: ServoRestyleManager::RebuildAllStyleData not implemented");
  // That said, we do know that rebuilding all style data in Gecko would get rid
  // of the old ruletree, and hence of the cached-on-the-root default computed
  // styles.  So we know we need to clear them here.  I think this is the only
  // way they could get cleared, in fact, though not _all_ calls that come
  // through here may need to clear them in practice.
  //
  // We probably need to do some actual restyling here too, though.  And figure
  // out whether it actually matters that we may be recomputing the default
  // styles in too many cases.  For one thing, we do a bunch of eager work here,
  // whereas we should really just set a bit that says to recompute the default
  // computed styles before the next time we restyle anything!
  StyleSet()->RecomputeDefaultComputedStyles();
}
void
ServoRestyleManager::ProcessPendingRestyles()
{
  MOZ_ASSERT(PresContext()->Document(), "No document?  Pshaw!");
  MOZ_ASSERT(!nsContentUtils::IsSafeToRunScript(), "Missing a script blocker!");
  MOZ_ASSERT(!mInStyleRefresh, "Reentrant call?");

  if (MOZ_UNLIKELY(!PresContext()->PresShell()->DidInitialize())) {
    // PresShell::FlushPendingNotifications doesn't early-return in the case
    // where the PreShell hasn't yet been initialized (and therefore we haven't
    // yet done the initial style traversal of the DOM tree). We should arguably
    // fix up the callers and assert against this case, but we just detect and
    // handle it for now.
    return;
  }

  // Create a AnimationsWithDestroyedFrame during restyling process to
  // stop animations and transitions on elements that have no frame at the end
  // of the restyling process.
  AnimationsWithDestroyedFrame animationsWithDestroyedFrame(this);

  ServoStyleSet* styleSet = StyleSet();
  nsIDocument* doc = PresContext()->Document();

  // Ensure the refresh driver is active during traversal to avoid mutating
  // mActiveTimer and mMostRecentRefresh time.
  PresContext()->RefreshDriver()->MostRecentRefresh();


  // Perform the Servo traversal, and the post-traversal if required. We do this
  // in a loop because certain rare paths in the frame constructor (like
  // uninstalling XBL bindings) can trigger additional style validations.
  mInStyleRefresh = true;
  if (mHaveNonAnimationRestyles) {
    ++mAnimationGeneration;
  }

  while (styleSet->StyleDocument()) {
    ClearSnapshots();

    // Recreate style contexts, and queue up change hints (which also handle
    // lazy frame construction).
    nsStyleChangeList currentChanges(StyleBackendType::Servo);
    DocumentStyleRootIterator iter(doc);
    while (Element* root = iter.GetNextStyleRoot()) {
      ProcessPostTraversal(root, nullptr, styleSet, currentChanges);
    }

    // Process the change hints.
    //
    // Unfortunately, the frame constructor can generate new change hints while
    // processing existing ones. We redirect those into a secondary queue and
    // iterate until there's nothing left.
    ReentrantChangeList newChanges;
    mReentrantChanges = &newChanges;
    while (!currentChanges.IsEmpty()) {
      ProcessRestyledFrames(currentChanges);
      MOZ_ASSERT(currentChanges.IsEmpty());
      for (ReentrantChange& change: newChanges)  {
        currentChanges.AppendChange(change.mContent->GetPrimaryFrame(),
                                    change.mContent, change.mHint);
      }
      newChanges.Clear();
    }
    mReentrantChanges = nullptr;

    IncrementRestyleGeneration();
  }

  ClearSnapshots();
  FlushOverflowChangedTracker();

  mHaveNonAnimationRestyles = false;
  mInStyleRefresh = false;
  styleSet->AssertTreeIsClean();

  // Note: We are in the scope of |animationsWithDestroyedFrame|, so
  //       |mAnimationsWithDestroyedFrame| is still valid.
  MOZ_ASSERT(mAnimationsWithDestroyedFrame);
  mAnimationsWithDestroyedFrame->StopAnimationsForElementsWithoutFrames();
}
void
ServoRestyleManager::ProcessPendingRestyles()
{
  MOZ_ASSERT(PresContext()->Document(), "No document?  Pshaw!");
  MOZ_ASSERT(!nsContentUtils::IsSafeToRunScript(), "Missing a script blocker!");

  if (MOZ_UNLIKELY(!PresContext()->PresShell()->DidInitialize())) {
    // PresShell::FlushPendingNotifications doesn't early-return in the case
    // where the PreShell hasn't yet been initialized (and therefore we haven't
    // yet done the initial style traversal of the DOM tree). We should arguably
    // fix up the callers and assert against this case, but we just detect and
    // handle it for now.
    return;
  }

  if (!HasPendingRestyles()) {
    return;
  }

  ServoStyleSet* styleSet = StyleSet();
  nsIDocument* doc = PresContext()->Document();
  Element* root = doc->GetRootElement();
  if (root) {
    for (auto iter = mModifiedElements.Iter(); !iter.Done(); iter.Next()) {
      ServoElementSnapshot* snapshot = iter.UserData();
      Element* element = iter.Key();

      // TODO: avoid the ComputeRestyleHint call if we already have the highest
      // explicit restyle hint?
      nsRestyleHint hint = styleSet->ComputeRestyleHint(element, snapshot);
      hint |= snapshot->ExplicitRestyleHint();

      if (hint) {
        NoteRestyleHint(element, hint);
      }
    }

    if (root->IsDirtyForServo() || root->HasDirtyDescendantsForServo()) {
      mInStyleRefresh = true;
      styleSet->StyleDocument(/* aLeaveDirtyBits = */ true);

      // First do any queued-up frame creation. (see bugs 827239 and 997506).
      //
      // XXXEmilio I'm calling this to avoid random behavior changes, since we
      // delay frame construction after styling we should re-check once our
      // model is more stable whether we can skip this call.
      //
      // Note this has to be *after* restyling, because otherwise frame
      // construction will find unstyled nodes, and that's not funny.
      PresContext()->FrameConstructor()->CreateNeededFrames();

      nsStyleChangeList changeList;
      RecreateStyleContexts(root, nullptr, styleSet, changeList);
      ProcessRestyledFrames(changeList);

      mInStyleRefresh = false;
    }
  }

  MOZ_ASSERT(!doc->IsDirtyForServo());
  doc->UnsetHasDirtyDescendantsForServo();

  mModifiedElements.Clear();

  IncrementRestyleGeneration();
}
Exemple #7
0
void
ServoRestyleManager::ProcessPendingRestyles()
{
  MOZ_ASSERT(PresContext()->Document(), "No document?  Pshaw!");
  MOZ_ASSERT(!nsContentUtils::IsSafeToRunScript(), "Missing a script blocker!");

  if (MOZ_UNLIKELY(!PresContext()->PresShell()->DidInitialize())) {
    // PresShell::FlushPendingNotifications doesn't early-return in the case
    // where the PreShell hasn't yet been initialized (and therefore we haven't
    // yet done the initial style traversal of the DOM tree). We should arguably
    // fix up the callers and assert against this case, but we just detect and
    // handle it for now.
    return;
  }

  if (!HasPendingRestyles()) {
    return;
  }

  ServoStyleSet* styleSet = StyleSet();
  nsIDocument* doc = PresContext()->Document();

  // XXXbholley: Should this be while() per bug 1316247?
  if (HasPendingRestyles()) {
    mInStyleRefresh = true;
    styleSet->StyleDocument();

    // First do any queued-up frame creation. (see bugs 827239 and 997506).
    //
    // XXXEmilio I'm calling this to avoid random behavior changes, since we
    // delay frame construction after styling we should re-check once our
    // model is more stable whether we can skip this call.
    //
    // Note this has to be *after* restyling, because otherwise frame
    // construction will find unstyled nodes, and that's not funny.
    PresContext()->FrameConstructor()->CreateNeededFrames();

    // Recreate style contexts and queue up change hints.
    nsStyleChangeList currentChanges;
    DocumentStyleRootIterator iter(doc);
    while (Element* root = iter.GetNextStyleRoot()) {
      RecreateStyleContexts(root, nullptr, styleSet, currentChanges);
    }

    // Process the change hints.
    //
    // Unfortunately, the frame constructor can generate new change hints while
    // processing existing ones. We redirect those into a secondary queue and
    // iterate until there's nothing left.
    ReentrantChangeList newChanges;
    mReentrantChanges = &newChanges;
    while (!currentChanges.IsEmpty()) {
      ProcessRestyledFrames(currentChanges);
      MOZ_ASSERT(currentChanges.IsEmpty());
      for (ReentrantChange& change: newChanges)  {
        currentChanges.AppendChange(change.mContent->GetPrimaryFrame(),
                                    change.mContent, change.mHint);
      }
      newChanges.Clear();
    }
    mReentrantChanges = nullptr;

    styleSet->AssertTreeIsClean();
    mInStyleRefresh = false;
  }

  IncrementRestyleGeneration();
}