Bug 1415940 Part 1: Expand StyleSheet dirty flag into a bitfield, to allow more types of dirtiness.
MozReview-Commit-ID: 7IasNqj85il
--- a/dom/base/nsTreeSanitizer.cpp
+++ b/dom/base/nsTreeSanitizer.cpp
@@ -1107,18 +1107,18 @@ nsTreeSanitizer::SanitizeStyleSheet(cons
} else {
// Create the CSS parser, and parse the CSS text.
nsCSSParser parser(nullptr, sheet->AsGecko());
rv = parser.ParseSheet(aOriginal, aDocument->GetDocumentURI(), aBaseURI,
aDocument->NodePrincipal(), 0);
}
NS_ENSURE_SUCCESS(rv, true);
// Mark the sheet as complete.
- MOZ_ASSERT(!sheet->IsModified(),
- "should not get marked modified during parsing");
+ MOZ_ASSERT(!sheet->HasForcedUniqueInner(),
+ "should not get a forced unique inner during parsing");
sheet->SetComplete();
// Loop through all the rules found in the CSS text
ErrorResult err;
RefPtr<dom::CSSRuleList> rules =
sheet->GetCssRules(*nsContentUtils::GetSystemPrincipal(), err);
err.SuppressException();
if (!rules) {
return true;
--- a/layout/style/CSSStyleSheet.cpp
+++ b/layout/style/CSSStyleSheet.cpp
@@ -348,17 +348,17 @@ CSSStyleSheet::CSSStyleSheet(const CSSSt
aParentToUse,
aOwnerRuleToUse,
aDocumentToUse,
aOwningNodeToUse)
, mInRuleProcessorCache(false)
, mScopeElement(nullptr)
, mRuleProcessors(nullptr)
{
- if (mDirty) { // CSSOM's been there, force full copy now
+ if (HasForcedUniqueInner()) { // CSSOM's been there, force full copy now
NS_ASSERTION(mInner->mComplete,
"Why have rules been accessed on an incomplete sheet?");
// FIXME: handle failure?
//
// NOTE: It's important to call this from the subclass, since it could
// access uninitialized members otherwise.
EnsureUniqueInner();
}
@@ -605,17 +605,17 @@ CSSStyleSheet::ClearRuleCascades()
if (mParent) {
static_cast<CSSStyleSheet*>(mParent)->ClearRuleCascades();
}
}
void
CSSStyleSheet::DidDirty()
{
- MOZ_ASSERT(!mInner->mComplete || mDirty,
+ MOZ_ASSERT(!mInner->mComplete || HasForcedUniqueInner(),
"caller must have called WillDirty()");
ClearRuleCascades();
}
nsresult
CSSStyleSheet::RegisterNamespaceRule(css::Rule* aRule)
{
if (!Inner()->mNameSpaceMap) {
--- a/layout/style/Loader.cpp
+++ b/layout/style/Loader.cpp
@@ -998,19 +998,22 @@ Loader::CreateSheet(nsIURI* aURI,
}
if (sheet) {
// This sheet came from the XUL cache or our per-document hashtable; it
// better be a complete sheet.
NS_ASSERTION(sheet->IsComplete(),
"Sheet thinks it's not complete while we think it is");
- // Make sure it hasn't been modified; if it has, we can't use it
- if (sheet->IsModified()) {
- LOG((" Not cloning completed sheet %p because it's been modified",
+ // Make sure it hasn't been forced to have a unique inner;
+ // that is an indication that its rules have been exposed to
+ // CSSOM and so we can't use it.
+ if (sheet->HasForcedUniqueInner()) {
+ LOG((" Not cloning completed sheet %p because it has a "
+ "forced unique inner",
sheet.get()));
sheet = nullptr;
fromCompleteSheets = false;
}
}
// Then loading sheets
if (!sheet && !aSyncLoad) {
@@ -1051,20 +1054,21 @@ Loader::CreateSheet(nsIURI* aURI,
&debugEqual)) && debugEqual),
"Principals should be the same");
#endif
}
}
}
if (sheet) {
- // The sheet we have now should be either incomplete or unmodified
- NS_ASSERTION(!sheet->IsModified() ||
+ // The sheet we have now should be either incomplete or without
+ // a forced unique inner.
+ NS_ASSERTION(!sheet->HasForcedUniqueInner() ||
!sheet->IsComplete(),
- "Unexpected modified complete sheet");
+ "Unexpected complete sheet with forced unique inner");
NS_ASSERTION(sheet->IsComplete() ||
aSheetState != eSheetComplete,
"Sheet thinks it's not complete while we think it is");
RefPtr<StyleSheet> clonedSheet =
sheet->Clone(nullptr, nullptr, nullptr, nullptr);
*aSheet = Move(clonedSheet);
if (*aSheet && fromCompleteSheets &&
@@ -1807,18 +1811,18 @@ Loader::DoSheetComplete(SheetLoadData* a
// Go through and deal with the whole linked list.
SheetLoadData* data = aLoadData;
while (data) {
if (!data->mSheetAlreadyComplete) {
// If mSheetAlreadyComplete, then the sheet could well be modified between
// when we posted the async call to SheetComplete and now, since the sheet
// was page-accessible during that whole time.
- MOZ_ASSERT(!data->mSheet->IsModified(),
- "should not get marked modified during parsing");
+ MOZ_ASSERT(!data->mSheet->HasForcedUniqueInner(),
+ "should not get a forced unique inner during parsing");
data->mSheet->SetComplete();
data->ScheduleLoadEventIfNeeded(aStatus);
}
if (data->mMustNotify && (data->mObserver || !mObservers.IsEmpty())) {
// Don't notify here so we don't trigger script. Remember the
// info we need to notify, then do it later when it's safe.
aDatasToNotify.AppendElement(data);
--- a/layout/style/ServoStyleSheet.cpp
+++ b/layout/style/ServoStyleSheet.cpp
@@ -144,17 +144,17 @@ ServoStyleSheet::ServoStyleSheet(const S
nsIDocument* aDocumentToUse,
nsINode* aOwningNodeToUse)
: StyleSheet(aCopy,
aParentToUse,
aOwnerRuleToUse,
aDocumentToUse,
aOwningNodeToUse)
{
- if (mDirty) { // CSSOM's been there, force full copy now
+ if (HasForcedUniqueInner()) { // CSSOM's been there, force full copy now
NS_ASSERTION(mInner->mComplete,
"Why have rules been accessed on an incomplete sheet?");
// FIXME: handle failure?
//
// NOTE: It's important to call this from the subclass, since this could
// access uninitialized members otherwise.
EnsureUniqueInner();
}
--- a/layout/style/StyleSheet.cpp
+++ b/layout/style/StyleSheet.cpp
@@ -23,17 +23,17 @@ namespace mozilla {
StyleSheet::StyleSheet(StyleBackendType aType, css::SheetParsingMode aParsingMode)
: mParent(nullptr)
, mDocument(nullptr)
, mOwningNode(nullptr)
, mOwnerRule(nullptr)
, mParsingMode(aParsingMode)
, mType(aType)
, mDisabled(false)
- , mDirty(false)
+ , mDirtyFlags(0)
, mDocumentAssociationMode(NotOwnedByDocument)
, mInner(nullptr)
{
}
StyleSheet::StyleSheet(const StyleSheet& aCopy,
StyleSheet* aParentToUse,
dom::CSSImportRule* aOwnerRuleToUse,
@@ -42,17 +42,17 @@ StyleSheet::StyleSheet(const StyleSheet&
: mParent(aParentToUse)
, mTitle(aCopy.mTitle)
, mDocument(aDocumentToUse)
, mOwningNode(aOwningNodeToUse)
, mOwnerRule(aOwnerRuleToUse)
, mParsingMode(aCopy.mParsingMode)
, mType(aCopy.mType)
, mDisabled(aCopy.mDisabled)
- , mDirty(aCopy.mDirty)
+ , mDirtyFlags(aCopy.mDirtyFlags)
// We only use this constructor during cloning. It's the cloner's
// responsibility to notify us if we end up being owned by a document.
, mDocumentAssociationMode(NotOwnedByDocument)
, mInner(aCopy.mInner) // Shallow copy, but concrete subclasses will fix up.
{
MOZ_ASSERT(mInner, "Should only copy StyleSheets with an mInner.");
mInner->AddSheet(this);
@@ -191,17 +191,19 @@ bool
StyleSheet::IsComplete() const
{
return SheetInfo().mComplete;
}
void
StyleSheet::SetComplete()
{
- NS_ASSERTION(!mDirty, "Can't set a dirty sheet complete!");
+ NS_ASSERTION(!HasForcedUniqueInner(),
+ "Can't complete a sheet that's already been forced "
+ "unique.");
SheetInfo().mComplete = true;
if (mDocument && !mDisabled) {
// Let the document know
mDocument->BeginUpdate(UPDATE_STYLE);
mDocument->SetStyleSheetApplicableState(this, true);
mDocument->EndUpdate(UPDATE_STYLE);
}
@@ -372,17 +374,17 @@ StyleSheet::DropStyleSet(const StyleSetH
NS_ASSERTION(found, "didn't find style set");
}
void
StyleSheet::EnsureUniqueInner()
{
MOZ_ASSERT(mInner->mSheets.Length() != 0,
"unexpected number of outers");
- mDirty = true;
+ mDirtyFlags |= FORCED_UNIQUE_INNER;
if (HasUniqueInner()) {
// already unique
return;
}
// If this stylesheet is for XBL with Servo, don't bother cloning
// it, as it may break ServoStyleRuleMap. XBL stylesheets are not
--- a/layout/style/StyleSheet.h
+++ b/layout/style/StyleSheet.h
@@ -127,17 +127,18 @@ public:
inline bool IsApplicable() const;
inline bool HasRules() const;
virtual already_AddRefed<StyleSheet> Clone(StyleSheet* aCloneParent,
dom::CSSImportRule* aCloneOwnerRule,
nsIDocument* aCloneDocument,
nsINode* aCloneOwningNode) const = 0;
- bool IsModified() const { return mDirty; }
+ bool HasForcedUniqueInner() const { return mDirtyFlags &
+ FORCED_UNIQUE_INNER; }
inline bool HasUniqueInner() const;
void EnsureUniqueInner();
// Append all of this sheet's child sheets to aArray.
void AppendAllChildSheets(nsTArray<StyleSheet*>& aArray);
// style sheet owner info
@@ -333,17 +334,20 @@ protected:
// mParsingMode controls access to nonstandard style constructs that
// are not safe for use on the public Web but necessary in UA sheets
// and/or useful in user sheets.
css::SheetParsingMode mParsingMode;
const StyleBackendType mType;
bool mDisabled;
- bool mDirty; // has been modified
+ enum dirtyFlagAttributes {
+ FORCED_UNIQUE_INNER = 0x1,
+ };
+ uint8_t mDirtyFlags; // has been modified
// mDocumentAssociationMode determines whether mDocument directly owns us (in
// the sense that if it's known-live then we're known-live). Always
// NotOwnedByDocument when mDocument is null.
DocumentAssociationMode mDocumentAssociationMode;
// Core information we get from parsed sheets, which are shared amongst
// StyleSheet clones.