コード例 #1
0
void
ServoRestyleManager::PostRestyleEvent(Element* aElement,
                                      nsRestyleHint aRestyleHint,
                                      nsChangeHint aMinChangeHint)
{
  if (MOZ_UNLIKELY(IsDisconnected()) ||
      MOZ_UNLIKELY(PresContext()->PresShell()->IsDestroying())) {
    return;
  }

  if (aRestyleHint == 0 && !aMinChangeHint && !HasPendingRestyles()) {
    return; // Nothing to do.
  }

  // XXX This is a temporary hack to make style attribute change works.
  //     In the future, we should be able to use this hint directly.
  if (aRestyleHint & eRestyle_StyleAttribute) {
    aRestyleHint |= eRestyle_Subtree;
  }

  // Note that unlike in Servo, we don't mark elements as dirty until we process
  // the restyle hints in ProcessPendingRestyles.
  if (aRestyleHint || aMinChangeHint) {
    ServoElementSnapshot* snapshot = SnapshotForElement(aElement);
    snapshot->AddExplicitRestyleHint(aRestyleHint);
    snapshot->AddExplicitChangeHint(aMinChangeHint);
  }

  PostRestyleEventInternal(false);
}
コード例 #2
0
void
ServoRestyleManager::PostRestyleEvent(Element* aElement,
                                      nsRestyleHint aRestyleHint,
                                      nsChangeHint aMinChangeHint)
{
  if (MOZ_UNLIKELY(IsDisconnected()) ||
      MOZ_UNLIKELY(PresContext()->PresShell()->IsDestroying())) {
    return;
  }

  if (aRestyleHint == 0 && !aMinChangeHint && !HasPendingRestyles()) {
    return; // Nothing to do.
  }

  // We allow posting change hints during restyling, but not restyle hints
  // themselves, since those would require us to re-traverse the tree.
  MOZ_ASSERT_IF(mInStyleRefresh, aRestyleHint == 0);

  // Processing change hints sometimes causes new change hints to be generated.
  // Doing this after the gecko post-traversal is problematic, so instead we just
  // queue them up for special handling.
  if (mReentrantChanges) {
    MOZ_ASSERT(aRestyleHint == 0);
    mReentrantChanges->AppendElement(ReentrantChange { aElement, aMinChangeHint });
    return;
  }

  // XXX This is a temporary hack to make style attribute change works.
  //     In the future, we should be able to use this hint directly.
  if (aRestyleHint & eRestyle_StyleAttribute) {
    aRestyleHint &= ~eRestyle_StyleAttribute;
    aRestyleHint |= eRestyle_Self | eRestyle_Subtree;
  }

  // XXX For now, convert eRestyle_Subtree into (eRestyle_Self |
  // eRestyle_SomeDescendants), which Servo will interpret as
  // RESTYLE_SELF | RESTYLE_DESCENDANTS, since this is a commonly
  // posted restyle hint that doesn't yet align with RestyleHint's
  // bits.
  if (aRestyleHint & eRestyle_Subtree) {
    aRestyleHint &= ~eRestyle_Subtree;
    aRestyleHint |= eRestyle_Self | eRestyle_SomeDescendants;
  }

  if (aRestyleHint || aMinChangeHint) {
    Servo_NoteExplicitHints(aElement, aRestyleHint, aMinChangeHint);
  }

  PostRestyleEventInternal(false);
}
コード例 #3
0
void
ServoRestyleManager::PostRestyleEvent(Element* aElement,
                                      nsRestyleHint aRestyleHint,
                                      nsChangeHint aMinChangeHint)
{
  if (MOZ_UNLIKELY(IsDisconnected()) ||
      MOZ_UNLIKELY(PresContext()->PresShell()->IsDestroying())) {
    return;
  }

  if (aRestyleHint == 0 && !aMinChangeHint && !HasPendingRestyles()) {
    return; // Nothing to do.
  }

  // Note that unlike in Servo, we don't mark elements as dirty until we process
  // the restyle hints in ProcessPendingRestyles.
  if (aRestyleHint || aMinChangeHint) {
    ServoElementSnapshot* snapshot = SnapshotForElement(aElement);
    snapshot->AddExplicitRestyleHint(aRestyleHint);
    snapshot->AddExplicitChangeHint(aMinChangeHint);
  }

  PostRestyleEventInternal(false);
}
コード例 #4
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();
  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();
}
コード例 #5
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();
}