--- a/layout/style/ServoStyleSet.cpp
+++ b/layout/style/ServoStyleSet.cpp
@@ -76,32 +76,32 @@ private:
// Sets up for one or more calls to Servo_TraverseSubtree.
class MOZ_RAII AutoPrepareTraversal
{
public:
explicit AutoPrepareTraversal(ServoStyleSet* aSet)
// For markers for animations, we have already set the markers in
// ServoRestyleManager::PostRestyleEventForAnimations so that we don't need
// to care about animation restyles here.
- : mTimelineMarker(aSet->mPresContext->GetDocShell(), false)
+ : mTimelineMarker(aSet->mDocument->GetDocShell(), false)
, mSetInServoTraversal(aSet)
{
MOZ_ASSERT(!aSet->StylistNeedsUpdate());
}
private:
AutoRestyleTimelineMarker mTimelineMarker;
AutoSetInServoTraversal mSetInServoTraversal;
};
} // namespace mozilla
ServoStyleSet::ServoStyleSet(Kind aKind)
: mKind(aKind)
- , mPresContext(nullptr)
+ , mDocument(nullptr)
, mAuthorStyleDisabled(false)
, mStylistState(StylistState::NotDirty)
, mUserFontSetUpdateGeneration(0)
, mUserFontCacheUpdateGeneration(0)
, mNeedsRestyleAfterEnsureUniqueInner(false)
{
}
@@ -126,34 +126,50 @@ ServoStyleSet::CreateXBLServoStyleSet(
// decide a particular SheetType to add them to style set. This type
// doesn't affect the place where we pull those rules from
// stylist::push_applicable_declarations_as_xbl_only_stylist().
set->ReplaceSheets(SheetType::Doc, aNewSheets);
// Update stylist immediately.
set->UpdateStylist();
- // The PresContext of the bound document could be destroyed anytime later,
- // which shouldn't be used for XBL styleset, so we clear it here to avoid
- // dangling pointer.
- set->mPresContext = nullptr;
+ // XBL resources are shared for a given URL, even across documents, so we
+ // can't safely keep this reference.
+ set->mDocument = nullptr;
return set;
}
+nsPresContext*
+ServoStyleSet::GetPresContext()
+{
+ if (!mDocument) {
+ return nullptr;
+ }
+
+ auto* shell = mDocument->GetShell();
+ if (!shell) {
+ return nullptr;
+ }
+
+ return shell->GetPresContext();
+}
+
void
ServoStyleSet::Init(nsPresContext* aPresContext, nsBindingManager* aBindingManager)
{
- mPresContext = aPresContext;
+ mDocument = aPresContext->Document();
+ MOZ_ASSERT(GetPresContext() == aPresContext);
+
mLastPresContextUsesXBLStyleSet = aPresContext;
mRawSet.reset(Servo_StyleSet_Init(aPresContext));
mBindingManager = aBindingManager;
- mPresContext->DeviceContext()->InitFontCache();
+ aPresContext->DeviceContext()->InitFontCache();
// Now that we have an mRawSet, go ahead and notify about whatever stylesheets
// we have so far.
for (auto& sheetArray : mSheets) {
for (auto& sheet : sheetArray) {
// There's no guarantee this will create a list on the servo side whose
// ordering matches the list that would have been created had all those
// sheets been appended/prepended/etc after we had mRawSet. That's okay
@@ -174,29 +190,25 @@ ServoStyleSet::Init(nsPresContext* aPres
void
ServoStyleSet::Shutdown()
{
// Make sure we drop our cached style contexts before the presshell arena
// starts going away.
ClearNonInheritingStyleContexts();
mRawSet = nullptr;
mStyleRuleMap = nullptr;
-
- // Also drop the reference to the pres context to avoid notifications from our
- // stylesheets to dereference a null restyle manager, see bug 1422634.
- //
- // We should really fix bug 154199...
- mPresContext = nullptr;
}
void
ServoStyleSet::InvalidateStyleForCSSRuleChanges()
{
MOZ_ASSERT(StylistNeedsUpdate());
- mPresContext->RestyleManager()->AsServo()->PostRestyleEventForCSSRuleChanges();
+ if (nsPresContext* pc = GetPresContext()) {
+ pc->RestyleManager()->AsServo()->PostRestyleEventForCSSRuleChanges();
+ }
}
bool
ServoStyleSet::SetPresContext(nsPresContext* aPresContext)
{
MOZ_ASSERT(IsForXBL(), "Only XBL styleset can set PresContext!");
mLastPresContextUsesXBLStyleSet = aPresContext;
@@ -213,20 +225,22 @@ ServoStyleSet::SetPresContext(nsPresCont
}
nsRestyleHint
ServoStyleSet::MediumFeaturesChanged(bool aViewportChanged)
{
bool viewportUnitsUsed = false;
bool rulesChanged = MediumFeaturesChangedRules(&viewportUnitsUsed);
- if (mBindingManager &&
- mBindingManager->MediumFeaturesChanged(mPresContext)) {
- SetStylistXBLStyleSheetsDirty();
- rulesChanged = true;
+ if (nsPresContext* pc = GetPresContext()) {
+ if (mDocument->BindingManager()->MediumFeaturesChanged(pc)) {
+ // TODO(emilio): We could technically just restyle the bound elements.
+ SetStylistXBLStyleSheetsDirty();
+ rulesChanged = true;
+ }
}
if (rulesChanged) {
return eRestyle_Subtree;
}
if (viewportUnitsUsed && aViewportChanged) {
return eRestyle_ForceDescendants;
@@ -291,17 +305,17 @@ ServoStyleSet::AddSizeOfIncludingThis(ns
}
// Measurement of the following members may be added later if DMD finds it is
// worthwhile:
// - mSheets
// - mNonInheritingStyleContexts
//
// The following members are not measured:
- // - mPresContext, because it a non-owning pointer
+ // - mDocument, because it a non-owning pointer
}
bool
ServoStyleSet::GetAuthorStyleDisabled() const
{
return mAuthorStyleDisabled;
}
@@ -341,48 +355,52 @@ ServoStyleSet::ResolveStyleFor(Element*
}
return ResolveServoStyle(aElement);
}
const ServoElementSnapshotTable&
ServoStyleSet::Snapshots()
{
- return mPresContext->RestyleManager()->AsServo()->Snapshots();
+ MOZ_ASSERT(GetPresContext(), "Styling a document without a shell?");
+ return GetPresContext()->RestyleManager()->AsServo()->Snapshots();
}
void
ServoStyleSet::ResolveMappedAttrDeclarationBlocks()
{
- if (nsHTMLStyleSheet* sheet = mPresContext->Document()->GetAttributeStyleSheet()) {
+ if (nsHTMLStyleSheet* sheet = mDocument->GetAttributeStyleSheet()) {
sheet->CalculateMappedServoDeclarations();
}
- mPresContext->Document()->ResolveScheduledSVGPresAttrs();
+ mDocument->ResolveScheduledSVGPresAttrs();
}
void
ServoStyleSet::PreTraverseSync()
{
// Get the Document's root element to ensure that the cache is valid before
// calling into the (potentially-parallel) Servo traversal, where a cache hit
// is necessary to avoid a data race when updating the cache.
- mozilla::Unused << mPresContext->Document()->GetRootElement();
+ mozilla::Unused << mDocument->GetRootElement();
ResolveMappedAttrDeclarationBlocks();
nsMediaFeatures::InitSystemMetrics();
LookAndFeel::NativeInit();
- if (gfxUserFontSet* userFontSet = mPresContext->Document()->GetUserFontSet()) {
+ nsPresContext* presContext = GetPresContext();
+ MOZ_ASSERT(presContext,
+ "For now, we don't call into here without a pres context");
+ if (gfxUserFontSet* userFontSet = mDocument->GetUserFontSet()) {
// Ensure that the @font-face data is not stale
uint64_t generation = userFontSet->GetGeneration();
if (generation != mUserFontSetUpdateGeneration) {
- mPresContext->DeviceContext()->UpdateFontCacheUserFonts(userFontSet);
+ presContext->DeviceContext()->UpdateFontCacheUserFonts(userFontSet);
mUserFontSetUpdateGeneration = generation;
}
// Ensure that the FontFaceSet's cached document principal is up to date.
FontFaceSet* fontFaceSet =
static_cast<FontFaceSet::UserFontSet*>(userFontSet)->GetFontFaceSet();
fontFaceSet->UpdateStandardFontLoadPrincipal();
bool principalChanged = fontFaceSet->HasStandardFontLoadPrincipalChanged();
@@ -395,39 +413,39 @@ ServoStyleSet::PreTraverseSync()
}
if (cacheGeneration != mUserFontCacheUpdateGeneration || principalChanged) {
gfxUserFontSet::UserFontCache::UpdateAllowedFontSets(userFontSet);
mUserFontCacheUpdateGeneration = cacheGeneration;
}
}
UpdateStylistIfNeeded();
- mPresContext->CacheAllLangs();
+ presContext->CacheAllLangs();
}
void
ServoStyleSet::PreTraverse(ServoTraversalFlags aFlags, Element* aRoot)
{
PreTraverseSync();
// Process animation stuff that we should avoid doing during the parallel
// traversal.
nsSMILAnimationController* smilController =
- mPresContext->Document()->HasAnimationController()
- ? mPresContext->Document()->GetAnimationController()
+ mDocument->HasAnimationController()
+ ? mDocument->GetAnimationController()
: nullptr;
+ MOZ_ASSERT(GetPresContext());
if (aRoot) {
- mPresContext->EffectCompositor()
- ->PreTraverseInSubtree(aFlags, aRoot);
+ GetPresContext()->EffectCompositor()->PreTraverseInSubtree(aFlags, aRoot);
if (smilController) {
smilController->PreTraverseInSubtree(aRoot);
}
} else {
- mPresContext->EffectCompositor()->PreTraverse(aFlags);
+ GetPresContext()->EffectCompositor()->PreTraverse(aFlags);
if (smilController) {
smilController->PreTraverse();
}
}
}
static inline already_AddRefed<ServoStyleContext>
ResolveStyleForTextOrFirstLetterContinuation(
@@ -916,60 +934,61 @@ ServoStyleSet::ProbePseudoElementStyle(E
}
return computedValues.forget();
}
bool
ServoStyleSet::StyleDocument(ServoTraversalFlags aFlags)
{
- nsIDocument* doc = mPresContext->Document();
- if (!doc->GetServoRestyleRoot()) {
+ MOZ_ASSERT(GetPresContext(), "Styling a document without a shell?");
+
+ if (!mDocument->GetServoRestyleRoot()) {
return false;
}
PreTraverse(aFlags);
AutoPrepareTraversal guard(this);
const SnapshotTable& snapshots = Snapshots();
// Restyle the document from the root element and each of the document level
// NAC subtree roots.
bool postTraversalRequired = false;
- Element* rootElement = doc->GetRootElement();
+ Element* rootElement = mDocument->GetRootElement();
MOZ_ASSERT_IF(rootElement, rootElement->HasServoData());
if (ShouldTraverseInParallel()) {
aFlags |= ServoTraversalFlags::ParallelTraversal;
}
// Do the first traversal.
- DocumentStyleRootIterator iter(doc->GetServoRestyleRoot());
+ DocumentStyleRootIterator iter(mDocument->GetServoRestyleRoot());
while (Element* root = iter.GetNextStyleRoot()) {
MOZ_ASSERT(MayTraverseFrom(root));
Element* parent = root->GetFlattenedTreeParentElementForStyle();
MOZ_ASSERT_IF(parent,
!parent->HasAnyOfFlags(Element::kAllServoDescendantBits));
postTraversalRequired |=
Servo_TraverseSubtree(root, mRawSet.get(), &snapshots, aFlags);
postTraversalRequired |=
root->HasAnyOfFlags(Element::kAllServoDescendantBits | NODE_NEEDS_FRAME);
if (parent) {
- MOZ_ASSERT(root == doc->GetServoRestyleRoot());
+ MOZ_ASSERT(root == mDocument->GetServoRestyleRoot());
if (parent->HasDirtyDescendantsForServo()) {
// If any style invalidation was triggered in our siblings, then we may
// need to post-traverse them, even if the root wasn't restyled after
// all.
- uint32_t existingBits = doc->GetServoRestyleRootDirtyBits();
+ uint32_t existingBits = mDocument->GetServoRestyleRootDirtyBits();
// We need to propagate the existing bits to the parent.
parent->SetFlags(existingBits);
- doc->SetServoRestyleRoot(
+ mDocument->SetServoRestyleRoot(
parent,
existingBits | ELEMENT_HAS_DIRTY_DESCENDANTS_FOR_SERVO);
postTraversalRequired = true;
}
}
}
// If there are still animation restyles needed, trigger a second traversal to
@@ -979,32 +998,33 @@ ServoStyleSet::StyleDocument(ServoTraver
// PreTraverse on the EffectCompositor might alter the style root. But we
// don't need to worry about NAC, since document-level NAC shouldn't have
// animations.
//
// We don't need to do this for SMIL since SMIL only updates its animation
// values once at the begin of a tick. As a result, even if the previous
// traversal caused, for example, the font-size to change, the SMIL style
// won't be updated until the next tick anyway.
- if (mPresContext->EffectCompositor()->PreTraverse(aFlags)) {
- nsINode* styleRoot = doc->GetServoRestyleRoot();
+ if (GetPresContext()->EffectCompositor()->PreTraverse(aFlags)) {
+ nsINode* styleRoot = mDocument->GetServoRestyleRoot();
Element* root = styleRoot->IsElement() ? styleRoot->AsElement() : rootElement;
postTraversalRequired |=
Servo_TraverseSubtree(root, mRawSet.get(), &snapshots, aFlags);
postTraversalRequired |=
root->HasAnyOfFlags(Element::kAllServoDescendantBits | NODE_NEEDS_FRAME);
}
return postTraversalRequired;
}
void
ServoStyleSet::StyleNewSubtree(Element* aRoot)
{
+ MOZ_ASSERT(GetPresContext());
MOZ_ASSERT(!aRoot->HasServoData());
PreTraverseSync();
AutoPrepareTraversal guard(this);
// Do the traversal. The snapshots will not be used.
const SnapshotTable& snapshots = Snapshots();
auto flags = ServoTraversalFlags::Empty;
if (ShouldTraverseInParallel()) {
@@ -1014,17 +1034,17 @@ ServoStyleSet::StyleNewSubtree(Element*
DebugOnly<bool> postTraversalRequired =
Servo_TraverseSubtree(aRoot, mRawSet.get(), &snapshots, flags);
MOZ_ASSERT(!postTraversalRequired);
// Annoyingly, the newly-styled content may have animations that need
// starting, which requires traversing them again. Mark the elements
// that need animation processing, then do a forgetful traversal to
// update the styles and clear the animation bits.
- if (mPresContext->EffectCompositor()->PreTraverseInSubtree(flags, aRoot)) {
+ if (GetPresContext()->EffectCompositor()->PreTraverseInSubtree(flags, aRoot)) {
postTraversalRequired =
Servo_TraverseSubtree(aRoot, mRawSet.get(), &snapshots,
ServoTraversalFlags::AnimationOnly |
ServoTraversalFlags::Forgetful |
ServoTraversalFlags::ClearAnimationOnlyDirtyDescendants);
MOZ_ASSERT(!postTraversalRequired);
}
}
@@ -1045,33 +1065,34 @@ ServoStyleSet::MarkOriginsDirty(OriginFl
void
ServoStyleSet::SetStylistStyleSheetsDirty()
{
mStylistState |= StylistState::StyleSheetsDirty;
// We need to invalidate cached style in getComputedStyle for undisplayed
// elements, since we don't know if any of the style sheet change that we
// do would affect undisplayed elements.
- if (mPresContext) {
- // XBL sheets don't have a pres context, but invalidating the restyle generation
- // in that case is handled by SetXBLStyleSheetsDirty in the "master" stylist.
- mPresContext->RestyleManager()->AsServo()->IncrementUndisplayedRestyleGeneration();
+ if (nsPresContext* presContext = GetPresContext()) {
+ // XBL sheets don't have a pres context, but invalidating the restyle
+ // generation in that case is handled by SetXBLStyleSheetsDirty in the
+ // "master" stylist.
+ presContext->RestyleManager()->AsServo()->IncrementUndisplayedRestyleGeneration();
}
}
void
ServoStyleSet::SetStylistXBLStyleSheetsDirty()
{
mStylistState |= StylistState::XBLStyleSheetsDirty;
// We need to invalidate cached style in getComputedStyle for undisplayed
// elements, since we don't know if any of the style sheet change that we
// do would affect undisplayed elements.
- MOZ_ASSERT(mPresContext);
- mPresContext->RestyleManager()->AsServo()->IncrementUndisplayedRestyleGeneration();
+ MOZ_ASSERT(GetPresContext());
+ GetPresContext()->RestyleManager()->AsServo()->IncrementUndisplayedRestyleGeneration();
}
void
ServoStyleSet::RuleAdded(ServoStyleSheet& aSheet, css::Rule& aRule)
{
if (mStyleRuleMap) {
mStyleRuleMap->RuleAdded(aSheet, aRule);
}
@@ -1097,17 +1118,17 @@ ServoStyleSet::RuleChanged(ServoStyleShe
// FIXME(emilio): Could be more granular based on aRule.
MarkOriginsDirty(aSheet.GetOrigin());
}
#ifdef DEBUG
void
ServoStyleSet::AssertTreeIsClean()
{
- DocumentStyleRootIterator iter(mPresContext->Document());
+ DocumentStyleRootIterator iter(mDocument);
while (Element* root = iter.GetNextStyleRoot()) {
Servo_AssertTreeIsClean(root);
}
}
#endif
bool
ServoStyleSet::GetKeyframesForName(nsAtom* aName,
@@ -1270,17 +1291,19 @@ ServoStyleSet::ClearNonInheritingStyleCo
}
}
already_AddRefed<ServoStyleContext>
ServoStyleSet::ResolveStyleLazilyInternal(Element* aElement,
CSSPseudoElementType aPseudoType,
StyleRuleInclusion aRuleInclusion)
{
- mPresContext->EffectCompositor()->PreTraverse(aElement, aPseudoType);
+ MOZ_ASSERT(GetPresContext(),
+ "For now, no style resolution without a pres context");
+ GetPresContext()->EffectCompositor()->PreTraverse(aElement, aPseudoType);
MOZ_ASSERT(!StylistNeedsUpdate());
AutoSetInServoTraversal guard(this);
/**
* NB: This is needed because we process animations and transitions on the
* pseudo-elements themselves, not on the parent's EagerPseudoStyles.
*
@@ -1308,27 +1331,27 @@ ServoStyleSet::ResolveStyleLazilyInterna
RefPtr<ServoStyleContext> computedValues =
Servo_ResolveStyleLazily(elementForStyleResolution,
pseudoTypeForStyleResolution,
aRuleInclusion,
&Snapshots(),
mRawSet.get(),
/* aIgnoreExistingStyles = */ false).Consume();
- if (mPresContext->EffectCompositor()->PreTraverse(aElement, aPseudoType)) {
+ if (GetPresContext()->EffectCompositor()->PreTraverse(aElement, aPseudoType)) {
computedValues =
Servo_ResolveStyleLazily(elementForStyleResolution,
pseudoTypeForStyleResolution,
aRuleInclusion,
&Snapshots(),
mRawSet.get(),
/* aIgnoreExistingStyles = */ false).Consume();
}
- MOZ_DIAGNOSTIC_ASSERT(computedValues->PresContext() == mPresContext ||
+ MOZ_DIAGNOSTIC_ASSERT(computedValues->PresContext() == GetPresContext() ||
aElement->OwnerDoc()->GetBFCacheEntry());
return computedValues.forget();
}
bool
ServoStyleSet::AppendFontFaceRules(nsTArray<nsFontFaceRuleContainer>& aArray)
{
@@ -1367,25 +1390,24 @@ void
ServoStyleSet::UpdateStylist()
{
MOZ_ASSERT(StylistNeedsUpdate());
if (mStylistState & StylistState::StyleSheetsDirty) {
// There's no need to compute invalidations and such for an XBL styleset,
// since they are loaded and unloaded synchronously, and they don't have to
// deal with dynamic content changes.
- Element* root =
- IsMaster() ? mPresContext->Document()->GetDocumentElement() : nullptr;
-
+ Element* root = IsMaster() ? mDocument->GetRootElement() : nullptr;
Servo_StyleSet_FlushStyleSheets(mRawSet.get(), root);
}
if (MOZ_UNLIKELY(mStylistState & StylistState::XBLStyleSheetsDirty)) {
MOZ_ASSERT(IsMaster(), "Only master styleset can mark XBL stylesets dirty!");
- mBindingManager->UpdateBoundContentBindingsForServo(mPresContext);
+ MOZ_ASSERT(GetPresContext(), "How did they get dirty?");
+ mDocument->BindingManager()->UpdateBoundContentBindingsForServo(GetPresContext());
}
mStylistState = StylistState::NotDirty;
}
void
ServoStyleSet::MaybeGCRuleTree()
{
@@ -1412,17 +1434,18 @@ ServoStyleSet::MayTraverseFrom(const Ele
}
return !Servo_Element_IsDisplayNone(parent->AsElement());
}
bool
ServoStyleSet::ShouldTraverseInParallel() const
{
- return mPresContext->PresShell()->IsActive();
+ MOZ_ASSERT(mDocument->GetShell(), "Styling a document without a shell?");
+ return mDocument->GetShell()->IsActive();
}
void
ServoStyleSet::PrependSheetOfType(SheetType aType,
ServoStyleSheet* aSheet)
{
aSheet->AddStyleSet(this);
mSheets[aType].InsertElementAt(0, aSheet);