dom/base/ElementInlines.h
author Emilio Cobos Álvarez <emilio@crisal.io>
Sun, 07 May 2017 16:36:47 +0200
changeset 357707 2150351429b5c9515589facd9f2aefb1e4640842
parent 350741 6df7d7fb8b7e48e4d9e73e183fe1c3ceb0f19dae
child 363887 2694abedc65ad9723004aac9a54631fb03046610
permissions -rw-r--r--
Bug 1355343: Take all the snapshots into account. r=bholley I've chosen this approach mainly because there's no other good way to guarantee the model is correct than holding the snapshots alive until a style refresh. What I tried before this (storing them in a sort of "immutable element data") is a pain, since we call into style from the frame constructor and other content notifications, which makes keeping track of which snapshots should be cleared an which shouldn't an insane task. Ideally we'd have a single entry-point for style, but that's not the case right now, and changing that requires pretty non-trivial changes to the frame constructor. MozReview-Commit-ID: FF1KWZv2iBM

/* -*- 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/. */

#ifndef mozilla_dom_ElementInlines_h
#define mozilla_dom_ElementInlines_h

#include "mozilla/dom/Element.h"
#include "mozilla/ServoBindings.h"
#include "nsIContentInlines.h"
#include "nsIDocument.h"
#include "nsIPresShell.h"
#include "nsIPresShellInlines.h"

namespace mozilla {
namespace dom {

inline void
Element::RegisterActivityObserver()
{
  OwnerDoc()->RegisterActivityObserver(this);
}

inline void
Element::UnregisterActivityObserver()
{
  OwnerDoc()->UnregisterActivityObserver(this);
}

inline Element*
Element::GetFlattenedTreeParentElement() const
{
  nsINode* parentNode = GetFlattenedTreeParentNode();
  if MOZ_LIKELY(parentNode && parentNode->IsElement()) {
    return parentNode->AsElement();
  }

  return nullptr;
}

inline Element*
Element::GetFlattenedTreeParentElementForStyle() const
{
  nsINode* parentNode = GetFlattenedTreeParentNodeForStyle();
  if MOZ_LIKELY(parentNode && parentNode->IsElement()) {
    return parentNode->AsElement();
  }

  return nullptr;
}

inline void
Element::NoteDirtyDescendantsForServo()
{
  if (!HasServoData()) {
    // The dirty descendants bit only applies to styled elements.
    return;
  }

  Element* curr = this;
  while (curr && !curr->HasDirtyDescendantsForServo()) {
    curr->SetHasDirtyDescendantsForServo();
    curr = curr->GetFlattenedTreeParentElementForStyle();
  }

  if (nsIPresShell* shell = OwnerDoc()->GetShell()) {
    shell->EnsureStyleFlush();
  }

  MOZ_ASSERT(DirtyDescendantsBitIsPropagatedForServo());
}

#ifdef DEBUG
inline bool
Element::DirtyDescendantsBitIsPropagatedForServo()
{
  Element* curr = this;
  while (curr) {
    if (!curr->HasDirtyDescendantsForServo()) {
      return false;
    }
    nsINode* parentNode = curr->GetParentNode();
    curr = curr->GetFlattenedTreeParentElementForStyle();
    MOZ_ASSERT_IF(!curr,
                  parentNode == OwnerDoc() ||
                  parentNode == parentNode->OwnerDoc()->GetRootElement());
  }
  return true;
}
#endif

} // namespace dom
} // namespace mozilla

#endif // mozilla_dom_ElementInlines_h