diff --git a/dom/base/Document.cpp b/dom/base/Document.cpp index 5f193f732ac3..6138aec8cb1b 100644 --- a/dom/base/Document.cpp +++ b/dom/base/Document.cpp @@ -45,6 +45,7 @@ #include "nsIObserver.h" #include "nsIBaseWindow.h" #include "nsILayoutHistoryState.h" +#include "nsLayoutStylesheetCache.h" #include "mozilla/css/Loader.h" #include "mozilla/css/ImageLoader.h" #include "nsDocShell.h" @@ -1220,6 +1221,7 @@ Document::Document(const char* aContentType) mInXBLUpdate(false), mNeedsReleaseAfterStackRefCntRelease(false), mStyleSetFilled(false), + mQuirkSheetAdded(false), mSSApplicableStateNotificationPending(false), mMayHaveTitleElement(false), mDOMLoadingSet(false), @@ -1649,10 +1651,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(Document) cb.NoteXPCOMChild(ToSupports(tmp)); } - for (auto iter = tmp->mIdentifierMap.ConstIter(); !iter.Done(); iter.Next()) { - iter.Get()->Traverse(&cb); - } - tmp->mExternalResourceMap.Traverse(&cb); // Traverse all Document pointer members. @@ -1666,7 +1664,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(Document) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParser) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mScriptGlobalObject) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mListenerManager) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDOMStyleSheets) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mStyleSheetSetList) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mScriptLoader) @@ -1708,7 +1705,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(Document) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPrototypeDocument) // Traverse all our nsCOMArrays. - NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mStyleSheets) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPreloadingImages) for (uint32_t i = 0; i < tmp->mFrameRequestCallbacks.Length(); ++i) { @@ -1814,8 +1810,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Document) tmp->mListenerManager = nullptr; } - NS_IMPL_CYCLE_COLLECTION_UNLINK(mDOMStyleSheets) - if (tmp->mStyleSheetSetList) { tmp->mStyleSheetSetList->Disconnect(); tmp->mStyleSheetSetList = nullptr; @@ -1835,7 +1829,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Document) // assume that *most* cycles you actually want to break somewhere // else, and not unlink an awful lot here. - tmp->mIdentifierMap.Clear(); tmp->mExpandoAndGeneration.OwnerUnlinked(); if (tmp->mAnimationController) { @@ -1913,6 +1906,8 @@ nsresult Document::Init() { mFeaturePolicy = new FeaturePolicy(this); mFeaturePolicy->SetDefaultOrigin(NodePrincipal()); + mStyleSet = MakeUnique(*this); + mozilla::HoldJSObjects(this); return NS_OK; @@ -2205,15 +2200,12 @@ already_AddRefed Document::MaybeDowngradePrincipal( } void Document::RemoveDocStyleSheetsFromStyleSets() { + MOZ_ASSERT(mStyleSetFilled); // The stylesheets should forget us for (StyleSheet* sheet : Reversed(mStyleSheets)) { sheet->ClearAssociatedDocumentOrShadowRoot(); - if (sheet->IsApplicable()) { - RefPtr presShell = GetPresShell(); - if (presShell) { - presShell->StyleSet()->RemoveDocStyleSheet(sheet); - } + mStyleSet->RemoveDocStyleSheet(sheet); } // XXX Tell observers? } @@ -2224,12 +2216,8 @@ void Document::RemoveStyleSheetsFromStyleSets( // The stylesheets should forget us for (StyleSheet* sheet : Reversed(aSheets)) { sheet->ClearAssociatedDocumentOrShadowRoot(); - - if (sheet->IsApplicable()) { - RefPtr presShell = GetPresShell(); - if (presShell) { - presShell->StyleSet()->RemoveStyleSheet(aType, sheet); - } + if (mStyleSetFilled && sheet->IsApplicable()) { + mStyleSet->RemoveStyleSheet(aType, sheet); } // XXX Tell observers? } @@ -2255,8 +2243,6 @@ void Document::ResetStylesheetsToURI(nsIURI* aURI) { RemoveStyleSheetsFromStyleSets(*sheetService->AuthorStyleSheets(), SheetType::Doc); } - - mStyleSetFilled = false; } // Release all the sheets @@ -2281,11 +2267,13 @@ void Document::ResetStylesheetsToURI(nsIURI* aURI) { mStyleAttrStyleSheet = new nsHTMLCSSStyleSheet(); } - // Now set up our style sets - if (PresShell* presShell = GetPresShell()) { - FillStyleSet(presShell->StyleSet()); - if (presShell->StyleSet()->StyleSheetsHaveChanged()) { - presShell->ApplicableStylesChanged(); + if (mStyleSetFilled) { + FillStyleSetDocumentSheets(); + + if (mStyleSet->StyleSheetsHaveChanged()) { + if (PresShell* presShell = GetPresShell()) { + presShell->ApplicableStylesChanged(); + } } } } @@ -2298,34 +2286,126 @@ static void AppendSheetsToStyleSet(ServoStyleSet* aStyleSet, } } -void Document::FillStyleSet(ServoStyleSet* aStyleSet) { - MOZ_ASSERT(aStyleSet, "Must have a style set"); - MOZ_ASSERT(aStyleSet->SheetCount(SheetType::Doc) == 0, - "Style set already has document sheets?"); +void Document::FillStyleSetUserAndUASheets() { + // Make sure this does the same thing as PresShell::Add{User,Agent}Sheet wrt + // ordering. + // The document will fill in the document sheets when we create the presshell + auto cache = nsLayoutStylesheetCache::Singleton(); + + nsStyleSheetService* sheetService = nsStyleSheetService::GetInstance(); + MOZ_ASSERT(sheetService, + "should never be creating a StyleSet after the style sheet " + "service has gone"); + + for (StyleSheet* sheet : *sheetService->UserStyleSheets()) { + mStyleSet->AppendStyleSheet(SheetType::User, sheet); + } + + StyleSheet* sheet = IsInChromeDocShell() ? cache->GetUserChromeSheet() + : cache->GetUserContentSheet(); + if (sheet) { + mStyleSet->AppendStyleSheet(SheetType::User, sheet); + } + + mStyleSet->AppendStyleSheet(SheetType::Agent, cache->UASheet()); + + if (MOZ_LIKELY(NodeInfoManager()->MathMLEnabled())) { + mStyleSet->AppendStyleSheet(SheetType::Agent, cache->MathMLSheet()); + } + + if (MOZ_LIKELY(NodeInfoManager()->SVGEnabled())) { + mStyleSet->AppendStyleSheet(SheetType::Agent, cache->SVGSheet()); + } + + mStyleSet->AppendStyleSheet(SheetType::Agent, cache->HTMLSheet()); + + if (nsLayoutUtils::ShouldUseNoFramesSheet(this)) { + mStyleSet->AppendStyleSheet(SheetType::Agent, cache->NoFramesSheet()); + } + + if (nsLayoutUtils::ShouldUseNoScriptSheet(this)) { + mStyleSet->AppendStyleSheet(SheetType::Agent, cache->NoScriptSheet()); + } + + mStyleSet->AppendStyleSheet(SheetType::Agent, cache->CounterStylesSheet()); + + // Load the minimal XUL rules for scrollbars and a few other XUL things + // that non-XUL (typically HTML) documents commonly use. + mStyleSet->AppendStyleSheet(SheetType::Agent, cache->MinimalXULSheet()); + + // Only load the full XUL sheet if we'll need it. + if (LoadsFullXULStyleSheetUpFront()) { + mStyleSet->AppendStyleSheet(SheetType::Agent, cache->XULSheet()); + } + + MOZ_ASSERT(!mQuirkSheetAdded); + if (mCompatMode == eCompatibility_NavQuirks) { + mStyleSet->AppendStyleSheet(SheetType::Agent, cache->QuirkSheet()); + mQuirkSheetAdded = true; + } + + mStyleSet->AppendStyleSheet(SheetType::Agent, cache->FormsSheet()); + mStyleSet->AppendStyleSheet(SheetType::Agent, cache->ScrollbarsSheet()); + mStyleSet->AppendStyleSheet(SheetType::Agent, cache->PluginProblemSheet()); + + for (StyleSheet* sheet : *sheetService->AgentStyleSheets()) { + mStyleSet->AppendStyleSheet(SheetType::Agent, sheet); + } +} + +void Document::FillStyleSet() { MOZ_ASSERT(!mStyleSetFilled); + FillStyleSetUserAndUASheets(); + FillStyleSetDocumentSheets(); + mStyleSetFilled = true; +} + +void Document::FillStyleSetDocumentSheets() { + MOZ_ASSERT(mStyleSet->SheetCount(SheetType::Doc) == 0, + "Style set already has document sheets?"); for (StyleSheet* sheet : Reversed(mStyleSheets)) { if (sheet->IsApplicable()) { - aStyleSet->AddDocStyleSheet(sheet, this); + mStyleSet->AddDocStyleSheet(sheet, this); } } - if (nsStyleSheetService* sheetService = nsStyleSheetService::GetInstance()) { - nsTArray>& sheets = *sheetService->AuthorStyleSheets(); - for (StyleSheet* sheet : sheets) { - aStyleSet->AppendStyleSheet(SheetType::Doc, sheet); - } + nsStyleSheetService* sheetService = nsStyleSheetService::GetInstance(); + for (StyleSheet* sheet : *sheetService->AuthorStyleSheets()) { + mStyleSet->AppendStyleSheet(SheetType::Doc, sheet); } - AppendSheetsToStyleSet(aStyleSet, mAdditionalSheets[eAgentSheet], + AppendSheetsToStyleSet(mStyleSet.get(), mAdditionalSheets[eAgentSheet], SheetType::Agent); - AppendSheetsToStyleSet(aStyleSet, mAdditionalSheets[eUserSheet], + AppendSheetsToStyleSet(mStyleSet.get(), mAdditionalSheets[eUserSheet], SheetType::User); - AppendSheetsToStyleSet(aStyleSet, mAdditionalSheets[eAuthorSheet], + AppendSheetsToStyleSet(mStyleSet.get(), mAdditionalSheets[eAuthorSheet], SheetType::Doc); +} - mStyleSetFilled = true; +void Document::CompatibilityModeChanged() { + MOZ_ASSERT(IsHTMLOrXHTML()); + CSSLoader()->SetCompatibilityMode(mCompatMode); + mStyleSet->CompatibilityModeChanged(); + if (!mStyleSetFilled) { + MOZ_ASSERT(!mQuirkSheetAdded); + return; + } + if (mQuirkSheetAdded == NeedsQuirksSheet()) { + return; + } + auto cache = nsLayoutStylesheetCache::Singleton(); + StyleSheet* sheet = cache->QuirkSheet(); + if (mQuirkSheetAdded) { + mStyleSet->RemoveStyleSheet(SheetType::Agent, sheet); + } else { + mStyleSet->AppendStyleSheet(SheetType::Agent, sheet); + } + mQuirkSheetAdded = !mQuirkSheetAdded; + if (PresShell* presShell = GetPresShell()) { + presShell->ApplicableStylesChanged(); + } } static void WarnIfSandboxIneffective(nsIDocShell* aDocShell, @@ -3590,19 +3670,29 @@ static inline void AssertNoStaleServoDataIn(nsINode& aSubtreeRoot) { } already_AddRefed Document::CreatePresShell( - nsPresContext* aContext, nsViewManager* aViewManager, - UniquePtr aStyleSet) { - NS_ASSERTION(!mPresShell, "We have a presshell already!"); + nsPresContext* aContext, nsViewManager* aViewManager) { + MOZ_ASSERT(!mPresShell, "We have a presshell already!"); NS_ENSURE_FALSE(GetBFCacheEntry(), nullptr); - FillStyleSet(aStyleSet.get()); AssertNoStaleServoDataIn(*this); RefPtr presShell = new PresShell; // Note: we don't hold a ref to the shell (it holds a ref to us) mPresShell = presShell; - presShell->Init(this, aContext, aViewManager, std::move(aStyleSet)); + + bool hadStyleSheets = mStyleSetFilled; + if (!hadStyleSheets) { + FillStyleSet(); + } + + presShell->Init(this, aContext, aViewManager); + + if (hadStyleSheets) { + // Gaining a shell causes changes in how media queries are evaluated, so + // invalidate that. + aContext->MediaFeatureValuesChanged({MediaFeatureChange::kAllChanges}); + } // Make sure to never paint if we belong to an invisible DocShell. nsCOMPtr docShell(mDocumentContainer); @@ -3705,6 +3795,8 @@ void Document::DeletePresShell() { presContext->RefreshDriver()->CancelPendingFullscreenEvents(this); } + mStyleSet->ShellDetachedFromDocument(); + // When our shell goes away, request that all our images be immediately // discarded, so we don't carry around decoded image data for a document we // no longer intend to paint. @@ -3719,7 +3811,6 @@ void Document::DeletePresShell() { PresShell* oldPresShell = mPresShell; mPresShell = nullptr; UpdateFrameRequestCallbackSchedulingState(oldPresShell); - mStyleSetFilled = false; ClearStaleServoData(); AssertNoStaleServoDataIn(*this); @@ -3913,9 +4004,11 @@ void Document::RemoveChildNode(nsIContent* aKid, bool aNotify) { } void Document::AddStyleSheetToStyleSets(StyleSheet* aSheet) { - if (PresShell* presShell = GetPresShell()) { - presShell->StyleSet()->AddDocStyleSheet(aSheet, this); - presShell->ApplicableStylesChanged(); + if (mStyleSetFilled) { + mStyleSet->AddDocStyleSheet(aSheet, this); + if (PresShell* presShell = GetPresShell()) { + presShell->ApplicableStylesChanged(); + } } } @@ -3953,9 +4046,11 @@ void Document::NotifyStyleSheetRemoved(StyleSheet* aSheet, } void Document::RemoveStyleSheetFromStyleSets(StyleSheet* aSheet) { - if (PresShell* presShell = GetPresShell()) { - presShell->StyleSet()->RemoveDocStyleSheet(aSheet); - presShell->ApplicableStylesChanged(); + if (mStyleSetFilled) { + mStyleSet->RemoveDocStyleSheet(aSheet); + if (PresShell* presShell = GetPresShell()) { + presShell->ApplicableStylesChanged(); + } } } @@ -4135,10 +4230,12 @@ nsresult Document::AddAdditionalStyleSheet(additionalSheetType aType, mAdditionalSheets[aType].AppendElement(aSheet); - if (PresShell* presShell = GetPresShell()) { + if (mStyleSetFilled) { SheetType type = ConvertAdditionalSheetType(aType); - presShell->StyleSet()->AppendStyleSheet(type, aSheet); - presShell->ApplicableStylesChanged(); + mStyleSet->AppendStyleSheet(type, aSheet); + if (PresShell* presShell = GetPresShell()) { + presShell->ApplicableStylesChanged(); + } } // Passing false, so documet.styleSheets.length will not be affected by @@ -4160,10 +4257,12 @@ void Document::RemoveAdditionalStyleSheet(additionalSheetType aType, if (!mIsGoingAway) { MOZ_ASSERT(sheetRef->IsApplicable()); - if (PresShell* presShell = GetPresShell()) { + if (mStyleSetFilled) { SheetType type = ConvertAdditionalSheetType(aType); - presShell->StyleSet()->RemoveStyleSheet(type, sheetRef); - presShell->ApplicableStylesChanged(); + mStyleSet->RemoveStyleSheet(type, sheetRef); + if (PresShell* presShell = GetPresShell()) { + presShell->ApplicableStylesChanged(); + } } } @@ -11668,8 +11767,7 @@ void Document::FlushUserFontSet() { if (gfxPlatform::GetPlatform()->DownloadableFontsEnabled()) { nsTArray rules; - PresShell* presShell = GetPresShell(); - if (presShell && !presShell->StyleSet()->AppendFontFaceRules(rules)) { + if (mStyleSetFilled && !mStyleSet->AppendFontFaceRules(rules)) { return; } @@ -11687,6 +11785,7 @@ void Document::FlushUserFontSet() { // reflect that we're modifying @font-face rules. (However, // without a reflow, nothing will happen to start any downloads // that are needed.) + PresShell* presShell = GetPresShell(); if (changed && presShell) { if (nsPresContext* presContext = presShell->GetPresContext()) { presContext->UserFontSetUpdated(); diff --git a/dom/base/Document.h b/dom/base/Document.h index 65a790f363b8..385b288d3f3b 100644 --- a/dom/base/Document.h +++ b/dom/base/Document.h @@ -1244,9 +1244,8 @@ class Document : public nsINode, * method is responsible for calling BeginObservingDocument() on the * presshell if the presshell should observe document mutations. */ - already_AddRefed CreatePresShell( - nsPresContext* aContext, nsViewManager* aViewManager, - UniquePtr aStyleSet); + already_AddRefed CreatePresShell(nsPresContext* aContext, + nsViewManager* aViewManager); void DeletePresShell(); PresShell* GetPresShell() const { @@ -1631,6 +1630,14 @@ class Document : public nsINode, // Get the "head" element in the sense of document.head. HTMLSharedElement* GetHead(); + ServoStyleSet* StyleSetForPresShellOrMediaQueryEvaluation() const { + return mStyleSet.get(); + } + + // Whether we filled the style set with any style sheet. Only meant to be used + // from DocumentOrShadowRoot::Traverse. + bool StyleSetFilled() const { return mStyleSetFilled; } + /** * Accessors to the collection of stylesheets owned by this document. * Style sheets are ordered, most significant last. @@ -3784,7 +3791,14 @@ class Document : public nsINode, void RemoveStyleSheetsFromStyleSets( const nsTArray>& aSheets, SheetType aType); void ResetStylesheetsToURI(nsIURI* aURI); - void FillStyleSet(ServoStyleSet* aStyleSet); + void FillStyleSet(); + void FillStyleSetUserAndUASheets(); + void FillStyleSetDocumentSheets(); + void CompatibilityModeChanged(); + bool NeedsQuirksSheet() const { + // SVG documents never load quirk.css. + return mCompatMode == eCompatibility_NavQuirks && !IsSVGDocument(); + } void AddStyleSheetToStyleSets(StyleSheet* aSheet); void RemoveStyleSheetFromStyleSets(StyleSheet* aSheet); void NotifyStyleSheetAdded(StyleSheet* aSheet, bool aDocumentSheet); @@ -3808,6 +3822,7 @@ class Document : public nsINode, // Lazy-initialization to have mDocGroup initialized in prior to the // SelectorCaches. UniquePtr mSelectorCache; + UniquePtr mStyleSet; protected: friend class nsDocumentOnStack; @@ -4165,10 +4180,12 @@ class Document : public nsINode, bool mNeedsReleaseAfterStackRefCntRelease : 1; - // Whether we have filled our pres shell's style set with the document's - // additional sheets and sheets from the nsStyleSheetService. + // Whether we have filled our style set with all the stylesheets. bool mStyleSetFilled : 1; + // Whether we have a quirks mode stylesheet in the style set. + bool mQuirkSheetAdded : 1; + // Keeps track of whether we have a pending // 'style-sheet-applicable-state-changed' notification. bool mSSApplicableStateNotificationPending : 1; diff --git a/dom/base/DocumentOrShadowRoot.cpp b/dom/base/DocumentOrShadowRoot.cpp index 1770f6689ca7..0f005740c112 100644 --- a/dom/base/DocumentOrShadowRoot.cpp +++ b/dom/base/DocumentOrShadowRoot.cpp @@ -588,6 +588,29 @@ nsRadioGroupStruct* DocumentOrShadowRoot::GetOrCreateRadioGroup( void DocumentOrShadowRoot::Traverse(DocumentOrShadowRoot* tmp, nsCycleCollectionTraversalCallback& cb) { + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mStyleSheets) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDOMStyleSheets) + for (StyleSheet* sheet : tmp->mStyleSheets) { + if (!sheet->IsApplicable()) { + continue; + } + // The style set or mServoStyles keep more references to it if the sheet is + // applicable. + if (tmp->mKind == Kind::ShadowRoot) { + NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mServoStyles->sheets[i]"); + cb.NoteXPCOMChild(sheet); + } else if (tmp->AsNode().AsDocument()->StyleSetFilled()) { + NS_CYCLE_COLLECTION_NOTE_EDGE_NAME( + cb, "mStyleSet->mStyleSheets[SheetType::Author][i]"); + cb.NoteXPCOMChild(sheet); + NS_CYCLE_COLLECTION_NOTE_EDGE_NAME( + cb, "mStyleSet->mRawSet.stylist.stylesheets.author[i]"); + cb.NoteXPCOMChild(sheet); + } + } + for (auto iter = tmp->mIdentifierMap.ConstIter(); !iter.Done(); iter.Next()) { + iter.Get()->Traverse(&cb); + } for (auto iter = tmp->mRadioGroups.Iter(); !iter.Done(); iter.Next()) { nsRadioGroupStruct* radioGroup = iter.UserData(); NS_CYCLE_COLLECTION_NOTE_EDGE_NAME( @@ -604,6 +627,8 @@ void DocumentOrShadowRoot::Traverse(DocumentOrShadowRoot* tmp, } void DocumentOrShadowRoot::Unlink(DocumentOrShadowRoot* tmp) { + NS_IMPL_CYCLE_COLLECTION_UNLINK(mDOMStyleSheets) + tmp->mIdentifierMap.Clear(); tmp->mRadioGroups.Clear(); } diff --git a/dom/base/ShadowRoot.cpp b/dom/base/ShadowRoot.cpp index 51d751c735c6..ab778ebdef62 100644 --- a/dom/base/ShadowRoot.cpp +++ b/dom/base/ShadowRoot.cpp @@ -30,19 +30,6 @@ using namespace mozilla::dom; NS_IMPL_CYCLE_COLLECTION_CLASS(ShadowRoot) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(ShadowRoot, DocumentFragment) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mStyleSheets) - for (StyleSheet* sheet : tmp->mStyleSheets) { - // mServoStyles keeps another reference to it if applicable. - if (sheet->IsApplicable()) { - MOZ_ASSERT(tmp->mServoStyles); - NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mServoStyles->sheets[i]"); - cb.NoteXPCOMChild(sheet); - } - } - NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDOMStyleSheets) - for (auto iter = tmp->mIdentifierMap.ConstIter(); !iter.Done(); iter.Next()) { - iter.Get()->Traverse(&cb); - } DocumentOrShadowRoot::Traverse(tmp, cb); NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END @@ -50,8 +37,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ShadowRoot) if (tmp->GetHost()) { tmp->GetHost()->RemoveMutationObserver(tmp); } - NS_IMPL_CYCLE_COLLECTION_UNLINK(mDOMStyleSheets) - tmp->mIdentifierMap.Clear(); DocumentOrShadowRoot::Unlink(tmp); NS_IMPL_CYCLE_COLLECTION_UNLINK_END_INHERITED(DocumentFragment) diff --git a/dom/canvas/CanvasRenderingContext2D.cpp b/dom/canvas/CanvasRenderingContext2D.cpp index e5b7dc50e1c9..4431843aef65 100644 --- a/dom/canvas/CanvasRenderingContext2D.cpp +++ b/dom/canvas/CanvasRenderingContext2D.cpp @@ -20,6 +20,7 @@ #include "SVGObserverUtils.h" #include "nsPresContext.h" #include "nsIPresShell.h" +#include "nsIPresShellInlines.h" #include "nsIInterfaceRequestorUtils.h" #include "nsIFrame.h" diff --git a/dom/html/nsHTMLDocument.cpp b/dom/html/nsHTMLDocument.cpp index e8e9694d7145..2cdbab0233c8 100644 --- a/dom/html/nsHTMLDocument.cpp +++ b/dom/html/nsHTMLDocument.cpp @@ -509,7 +509,7 @@ nsresult nsHTMLDocument::StartDocumentLoad(const char* aCommand, if (!viewSource && xhtml) { // We're parsing XHTML as XML, remember that. mType = eXHTML; - mCompatMode = eCompatibility_FullStandards; + SetCompatibilityMode(eCompatibility_FullStandards); loadAsHtml5 = false; } @@ -528,8 +528,6 @@ nsresult nsHTMLDocument::StartDocumentLoad(const char* aCommand, } } - CSSLoader()->SetCompatibilityMode(mCompatMode); - nsresult rv = Document::StartDocumentLoad(aCommand, aChannel, aLoadGroup, aContainer, aDocListener, aReset); if (NS_FAILED(rv)) { @@ -782,10 +780,7 @@ void nsHTMLDocument::SetCompatibilityMode(nsCompatibility aMode) { return; } mCompatMode = aMode; - CSSLoader()->SetCompatibilityMode(mCompatMode); - if (nsPresContext* pc = GetPresContext()) { - pc->CompatibilityModeChanged(); - } + CompatibilityModeChanged(); } bool nsHTMLDocument::UseWidthDeviceWidthFallbackViewport() const { diff --git a/editor/libeditor/HTMLAnonymousNodeEditor.cpp b/editor/libeditor/HTMLAnonymousNodeEditor.cpp index cebd6638daa0..e74fa15ef4e9 100644 --- a/editor/libeditor/HTMLAnonymousNodeEditor.cpp +++ b/editor/libeditor/HTMLAnonymousNodeEditor.cpp @@ -27,6 +27,7 @@ #include "nsIHTMLObjectResizer.h" #include "nsStubMutationObserver.h" #include "nsINode.h" +#include "nsIPresShellInlines.h" #include "nsISupportsImpl.h" #include "nsISupportsUtils.h" #include "nsLiteralString.h" diff --git a/layout/base/PresShell.cpp b/layout/base/PresShell.cpp index a6dcc33ce2d6..c35d2ef8370c 100644 --- a/layout/base/PresShell.cpp +++ b/layout/base/PresShell.cpp @@ -897,7 +897,6 @@ PresShell::~PresShell() { MOZ_ASSERT(mAllocatedPointers.IsEmpty(), "Some pres arena objects were not freed"); - mStyleSet = nullptr; mFrameManager = nullptr; mFrameConstructor = nullptr; @@ -911,8 +910,7 @@ PresShell::~PresShell() { * calls AddRef() on us. */ void PresShell::Init(Document* aDocument, nsPresContext* aPresContext, - nsViewManager* aViewManager, - UniquePtr aStyleSet) { + nsViewManager* aViewManager) { MOZ_ASSERT(aDocument, "null ptr"); MOZ_ASSERT(aPresContext, "null ptr"); MOZ_ASSERT(aViewManager, "null ptr"); @@ -944,16 +942,7 @@ void PresShell::Init(Document* aDocument, nsPresContext* aPresContext, mPresContext = aPresContext; mPresContext->AttachShell(this); - // Now we can initialize the style set. Make sure to set the member before - // calling Init, since various subroutines need to find the style set off - // the PresContext during initialization. - mStyleSet = std::move(aStyleSet); - mStyleSet->Init(aPresContext); - - // Notify our prescontext that it now has a compatibility mode. Note that - // this MUST happen after we set up our style set but before we create any - // frames. - mPresContext->CompatibilityModeChanged(); + mPresContext->DeviceContext()->InitFontCache(); // Add the preference style sheet. UpdatePreferenceStyles(); @@ -1276,8 +1265,7 @@ void PresShell::Destroy() { // release our pref style sheet, if we have one still // - // FIXME(emilio): Why do we need to do this? The stylist is getting nixed with - // us anyway. + // TODO(emilio): Should we move the preference sheet tracking to the Document? RemovePreferenceStyles(); mIsDestroying = true; @@ -1310,7 +1298,6 @@ void PresShell::Destroy() { mViewManager = nullptr; } - mStyleSet->BeginShutdown(); nsRefreshDriver* rd = GetPresContext()->RefreshDriver(); // This shell must be removed from the document before the frame @@ -1361,9 +1348,6 @@ void PresShell::Destroy() { weakFrame->Clear(this); } - // Let the style set do its cleanup. - mStyleSet->Shutdown(); - if (mPresContext) { // We hold a reference to the pres context, and it holds a weak link back // to us. To avoid the pres context having a dangling reference, set its @@ -1410,8 +1394,8 @@ nsRefreshDriver* nsIPresShell::GetRefreshDriver() const { } void nsIPresShell::SetAuthorStyleDisabled(bool aStyleDisabled) { - if (aStyleDisabled != mStyleSet->GetAuthorStyleDisabled()) { - mStyleSet->SetAuthorStyleDisabled(aStyleDisabled); + if (aStyleDisabled != StyleSet()->GetAuthorStyleDisabled()) { + StyleSet()->SetAuthorStyleDisabled(aStyleDisabled); ApplicableStylesChanged(); nsCOMPtr observerService = @@ -1424,7 +1408,7 @@ void nsIPresShell::SetAuthorStyleDisabled(bool aStyleDisabled) { } bool nsIPresShell::GetAuthorStyleDisabled() const { - return mStyleSet->GetAuthorStyleDisabled(); + return StyleSet()->GetAuthorStyleDisabled(); } void nsIPresShell::UpdatePreferenceStyles() { @@ -1463,13 +1447,13 @@ void nsIPresShell::UpdatePreferenceStyles() { // it to be modifiable from devtools and similar, see bugs 1239336 and // 1436782. I think it conceptually should be a user sheet, and could be // without too much trouble I'd think. - mStyleSet->AppendStyleSheet(SheetType::Agent, newPrefSheet); + StyleSet()->AppendStyleSheet(SheetType::Agent, newPrefSheet); mPrefStyleSheet = newPrefSheet; } void nsIPresShell::RemovePreferenceStyles() { if (mPrefStyleSheet) { - mStyleSet->RemoveStyleSheet(SheetType::Agent, mPrefStyleSheet); + StyleSet()->RemoveStyleSheet(SheetType::Agent, mPrefStyleSheet); mPrefStyleSheet = nullptr; } } @@ -1496,14 +1480,14 @@ void nsIPresShell::AddUserSheet(StyleSheet* aSheet) { // Assert that all of userSheets (except for the last, new element) matches up // with what's in the style set. for (size_t i = 0; i < index; ++i) { - MOZ_ASSERT(mStyleSet->StyleSheetAt(SheetType::User, i) == userSheets[i]); + MOZ_ASSERT(StyleSet()->StyleSheetAt(SheetType::User, i) == userSheets[i]); } - if (index == static_cast(mStyleSet->SheetCount(SheetType::User))) { - mStyleSet->AppendStyleSheet(SheetType::User, aSheet); + if (index == static_cast(StyleSet()->SheetCount(SheetType::User))) { + StyleSet()->AppendStyleSheet(SheetType::User, aSheet); } else { - StyleSheet* ref = mStyleSet->StyleSheetAt(SheetType::User, index); - mStyleSet->InsertStyleSheetBefore(SheetType::User, aSheet, ref); + StyleSheet* ref = StyleSet()->StyleSheetAt(SheetType::User, index); + StyleSet()->InsertStyleSheetBefore(SheetType::User, aSheet, ref); } ApplicableStylesChanged(); @@ -1512,7 +1496,7 @@ void nsIPresShell::AddUserSheet(StyleSheet* aSheet) { void nsIPresShell::AddAgentSheet(StyleSheet* aSheet) { // Make sure this does what nsDocumentViewer::CreateStyleSet does // wrt ordering. - mStyleSet->AppendStyleSheet(SheetType::Agent, aSheet); + StyleSet()->AppendStyleSheet(SheetType::Agent, aSheet); ApplicableStylesChanged(); } @@ -1521,16 +1505,17 @@ void nsIPresShell::AddAuthorSheet(StyleSheet* aSheet) { // ones added with the StyleSheetService. StyleSheet* firstAuthorSheet = mDocument->GetFirstAdditionalAuthorSheet(); if (firstAuthorSheet) { - mStyleSet->InsertStyleSheetBefore(SheetType::Doc, aSheet, firstAuthorSheet); + StyleSet()->InsertStyleSheetBefore(SheetType::Doc, aSheet, + firstAuthorSheet); } else { - mStyleSet->AppendStyleSheet(SheetType::Doc, aSheet); + StyleSet()->AppendStyleSheet(SheetType::Doc, aSheet); } ApplicableStylesChanged(); } void nsIPresShell::RemoveSheet(SheetType aType, StyleSheet* aSheet) { - mStyleSet->RemoveStyleSheet(aType, aSheet); + StyleSet()->RemoveStyleSheet(aType, aSheet); ApplicableStylesChanged(); } @@ -4089,7 +4074,7 @@ void PresShell::DoFlushPendingNotifications(mozilla::ChangesToFlush aFlush) { if (MOZ_LIKELY(!mIsDestroying)) { // Now that we have flushed media queries, update the rules before looking // up @font-face / @counter-style / @font-feature-values rules. - mStyleSet->UpdateStylistIfNeeded(); + StyleSet()->UpdateStylistIfNeeded(); // Flush any pending update of the user font set, since that could // cause style changes (for updating ex/ch units, and to cause a @@ -4234,7 +4219,7 @@ void PresShell::DocumentStatesChanged(Document* aDocument, MOZ_ASSERT(!aStateMask.IsEmpty()); if (mDidInitialize) { - mStyleSet->InvalidateStyleForDocumentStateChanges(aStateMask); + StyleSet()->InvalidateStyleForDocumentStateChanges(aStateMask); } if (aStateMask.HasState(NS_DOCUMENT_STATE_WINDOW_INACTIVE)) { @@ -5904,7 +5889,7 @@ class nsAutoNotifyDidPaint { }; void nsIPresShell::RecordShadowStyleChange(ShadowRoot& aShadowRoot) { - mStyleSet->RecordShadowStyleChange(aShadowRoot); + StyleSet()->RecordShadowStyleChange(aShadowRoot); ApplicableStylesChanged(); } @@ -8798,14 +8783,14 @@ bool PresShell::IsDisplayportSuppressed() { nsresult PresShell::GetAgentStyleSheets(nsTArray>& aSheets) { aSheets.Clear(); - int32_t sheetCount = mStyleSet->SheetCount(SheetType::Agent); + int32_t sheetCount = StyleSet()->SheetCount(SheetType::Agent); if (!aSheets.SetCapacity(sheetCount, fallible)) { return NS_ERROR_OUT_OF_MEMORY; } for (int32_t i = 0; i < sheetCount; ++i) { - StyleSheet* sheet = mStyleSet->StyleSheetAt(SheetType::Agent, i); + StyleSheet* sheet = StyleSet()->StyleSheetAt(SheetType::Agent, i); aSheets.AppendElement(sheet); } @@ -8814,15 +8799,15 @@ nsresult PresShell::GetAgentStyleSheets(nsTArray>& aSheets) { nsresult PresShell::SetAgentStyleSheets( const nsTArray>& aSheets) { - return mStyleSet->ReplaceSheets(SheetType::Agent, aSheets); + return StyleSet()->ReplaceSheets(SheetType::Agent, aSheets); } nsresult PresShell::AddOverrideStyleSheet(StyleSheet* aSheet) { - return mStyleSet->AppendStyleSheet(SheetType::Override, aSheet); + return StyleSet()->AppendStyleSheet(SheetType::Override, aSheet); } nsresult PresShell::RemoveOverrideStyleSheet(StyleSheet* aSheet) { - return mStyleSet->RemoveStyleSheet(SheetType::Override, aSheet); + return StyleSet()->RemoveStyleSheet(SheetType::Override, aSheet); } static void FreezeElement(nsISupports* aSupports, void* /* unused */) { @@ -9835,42 +9820,6 @@ FindTopFrame(nsIFrame* aRoot) #ifdef DEBUG -static void CopySheetsIntoClone(ServoStyleSet* aSet, ServoStyleSet* aClone) { - int32_t i, n = aSet->SheetCount(SheetType::Override); - for (i = 0; i < n; i++) { - StyleSheet* ss = aSet->StyleSheetAt(SheetType::Override, i); - if (ss) aClone->AppendStyleSheet(SheetType::Override, ss); - } - - // The document expects to insert document stylesheets itself -# if 0 - n = aSet->SheetCount(SheetType::Doc); - for (i = 0; i < n; i++) { - StyleSheet* ss = aSet->StyleSheetAt(SheetType::Doc, i); - if (ss) - aClone->AddDocStyleSheet(ss, mDocument); - } -# endif - - n = aSet->SheetCount(SheetType::User); - for (i = 0; i < n; i++) { - StyleSheet* ss = aSet->StyleSheetAt(SheetType::User, i); - if (ss) aClone->AppendStyleSheet(SheetType::User, ss); - } - - n = aSet->SheetCount(SheetType::Agent); - for (i = 0; i < n; i++) { - StyleSheet* ss = aSet->StyleSheetAt(SheetType::Agent, i); - if (ss) aClone->AppendStyleSheet(SheetType::Agent, ss); - } -} - -UniquePtr nsIPresShell::CloneStyleSet(ServoStyleSet* aSet) { - auto clone = MakeUnique(); - CopySheetsIntoClone(aSet, clone.get()); - return clone; -} - // After an incremental reflow, we verify the correctness by doing a // full reflow into a fresh frame tree. bool nsIPresShell::VerifyIncrementalReflow() { @@ -9917,13 +9866,9 @@ bool nsIPresShell::VerifyIncrementalReflow() { // presentation context. cx->SetVisibleArea(mPresContext->GetVisibleArea()); - // Create a new presentation shell to view the document. Use the - // exact same style information that this document has. - UniquePtr newSet = CloneStyleSet(StyleSet()); - - RefPtr presShell = - mDocument->CreatePresShell(cx, vm, std::move(newSet)); + RefPtr presShell = mDocument->CreatePresShell(cx, vm); NS_ENSURE_TRUE(presShell, false); + // Note that after we create the shell, we must make sure to destroy it presShell->SetVerifyReflowEnable( false); // turn off verify reflow while we're @@ -10003,9 +9948,9 @@ void PresShell::ListComputedStyles(FILE* out, int32_t aIndent) { } void PresShell::ListStyleSheets(FILE* out, int32_t aIndent) { - int32_t sheetCount = mStyleSet->SheetCount(SheetType::Doc); + int32_t sheetCount = StyleSet()->SheetCount(SheetType::Doc); for (int32_t i = 0; i < sheetCount; ++i) { - mStyleSet->StyleSheetAt(SheetType::Doc, i)->List(out, aIndent); + StyleSet()->StyleSheetAt(SheetType::Doc, i)->List(out, aIndent); fputs("\n", out); } } @@ -10909,10 +10854,6 @@ nsresult nsIPresShell::HasRuleProcessorUsedByMultipleStyleSets( void nsIPresShell::NotifyStyleSheetServiceSheetAdded(StyleSheet* aSheet, uint32_t aSheetType) { - if (!mStyleSet) { - return; - } - switch (aSheetType) { case nsIStyleSheetService::AGENT_SHEET: AddAgentSheet(aSheet); @@ -10931,10 +10872,6 @@ void nsIPresShell::NotifyStyleSheetServiceSheetAdded(StyleSheet* aSheet, void nsIPresShell::NotifyStyleSheetServiceSheetRemoved(StyleSheet* aSheet, uint32_t aSheetType) { - if (!mStyleSet) { - return; - } - RemoveSheet(ToSheetType(aSheetType), aSheet); } diff --git a/layout/base/PresShell.h b/layout/base/PresShell.h index 9addba1a7ea7..ddaffa530620 100644 --- a/layout/base/PresShell.h +++ b/layout/base/PresShell.h @@ -64,6 +64,7 @@ class PresShell final : public nsIPresShell, public nsIObserver, public nsSupportsWeakReference { typedef layers::FocusTarget FocusTarget; + typedef dom::Element Element; public: PresShell(); @@ -73,8 +74,7 @@ class PresShell final : public nsIPresShell, static bool AccessibleCaretEnabled(nsIDocShell* aDocShell); - void Init(Document* aDocument, nsPresContext* aPresContext, - nsViewManager* aViewManager, UniquePtr aStyleSet); + void Init(Document*, nsPresContext*, nsViewManager*); void Destroy() override; NS_IMETHOD GetSelectionFromScript(RawSelectionType aRawSelectionType, diff --git a/layout/base/nsDocumentViewer.cpp b/layout/base/nsDocumentViewer.cpp index 72bb0b274c45..a41e38f0b4fb 100644 --- a/layout/base/nsDocumentViewer.cpp +++ b/layout/base/nsDocumentViewer.cpp @@ -726,12 +726,8 @@ nsresult nsDocumentViewer::InitPresentationStuff(bool aDoInitialReflow) { NS_ASSERTION(!mPresShell, "Someone should have destroyed the presshell!"); - // Create the style set... - UniquePtr styleSet = CreateStyleSet(mDocument); - // Now make the shell for the document - mPresShell = mDocument->CreatePresShell(mPresContext, mViewManager, - std::move(styleSet)); + mPresShell = mDocument->CreatePresShell(mPresContext, mViewManager); if (!mPresShell) { return NS_ERROR_FAILURE; } @@ -2291,81 +2287,6 @@ nsDocumentViewer::RequestWindowClose(bool* aCanClose) { return NS_OK; } -UniquePtr nsDocumentViewer::CreateStyleSet(Document* aDocument) { - // Make sure this does the same thing as PresShell::Add{User,Agent}Sheet wrt - // ordering. - - // The document will fill in the document sheets when we create the presshell - auto cache = nsLayoutStylesheetCache::Singleton(); - nsStyleSheetService* sheetService = nsStyleSheetService::GetInstance(); - - MOZ_ASSERT(sheetService, - "should never be creating a StyleSet after the style sheet " - "service has gone"); - - auto styleSet = MakeUnique(); - - // User sheets - - for (StyleSheet* sheet : *sheetService->UserStyleSheets()) { - styleSet->AppendStyleSheet(SheetType::User, sheet); - } - - StyleSheet* sheet = nsContentUtils::IsInChromeDocshell(aDocument) - ? cache->GetUserChromeSheet() - : cache->GetUserContentSheet(); - - if (sheet) { - styleSet->AppendStyleSheet(SheetType::User, sheet); - } - - // Agent sheets - - styleSet->AppendStyleSheet(SheetType::Agent, cache->UASheet()); - - if (MOZ_LIKELY(mDocument->NodeInfoManager()->MathMLEnabled())) { - styleSet->AppendStyleSheet(SheetType::Agent, cache->MathMLSheet()); - } - - if (MOZ_LIKELY(mDocument->NodeInfoManager()->SVGEnabled())) { - styleSet->AppendStyleSheet(SheetType::Agent, cache->SVGSheet()); - } - - styleSet->AppendStyleSheet(SheetType::Agent, cache->HTMLSheet()); - - // We don't add quirk.css here; nsPresContext::CompatibilityModeChanged will - // append it if needed. - - if (nsLayoutUtils::ShouldUseNoFramesSheet(aDocument)) { - styleSet->AppendStyleSheet(SheetType::Agent, cache->NoFramesSheet()); - } - - if (nsLayoutUtils::ShouldUseNoScriptSheet(aDocument)) { - styleSet->AppendStyleSheet(SheetType::Agent, cache->NoScriptSheet()); - } - - styleSet->AppendStyleSheet(SheetType::Agent, cache->CounterStylesSheet()); - - // Load the minimal XUL rules for scrollbars and a few other XUL things - // that non-XUL (typically HTML) documents commonly use. - styleSet->AppendStyleSheet(SheetType::Agent, cache->MinimalXULSheet()); - - // Only load the full XUL sheet if we'll need it. - if (aDocument->LoadsFullXULStyleSheetUpFront()) { - styleSet->AppendStyleSheet(SheetType::Agent, cache->XULSheet()); - } - - styleSet->AppendStyleSheet(SheetType::Agent, cache->FormsSheet()); - styleSet->AppendStyleSheet(SheetType::Agent, cache->ScrollbarsSheet()); - styleSet->AppendStyleSheet(SheetType::Agent, cache->PluginProblemSheet()); - - for (StyleSheet* sheet : *sheetService->AgentStyleSheets()) { - styleSet->AppendStyleSheet(SheetType::Agent, sheet); - } - - return styleSet; -} - NS_IMETHODIMP nsDocumentViewer::ClearHistoryEntry() { if (mDocument) { diff --git a/layout/base/nsIDocumentViewerPrint.h b/layout/base/nsIDocumentViewerPrint.h index 1e8b369bc7e0..5a36f1f02694 100644 --- a/layout/base/nsIDocumentViewerPrint.h +++ b/layout/base/nsIDocumentViewerPrint.h @@ -39,12 +39,6 @@ class nsIDocumentViewerPrint : public nsISupports { virtual void SetIsPrintPreview(bool aIsPrintPreview) = 0; virtual bool GetIsPrintPreview() = 0; - // The style set returned by CreateStyleSet is in the middle of an - // update batch so that the caller can add sheets to it if needed. - // Callers should call EndUpdate() on it when ready to use. - virtual mozilla::UniquePtr CreateStyleSet( - mozilla::dom::Document* aDocument) = 0; - /** * This is used by nsPagePrintTimer to make nsDocumentViewer::Destroy() * a no-op until printing is finished. That prevents the nsDocumentViewer @@ -82,8 +76,6 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsIDocumentViewerPrint, bool GetIsPrinting() override; \ void SetIsPrintPreview(bool aIsPrintPreview) override; \ bool GetIsPrintPreview() override; \ - mozilla::UniquePtr CreateStyleSet( \ - mozilla::dom::Document* aDocument) override; \ void IncrementDestroyBlockedCount() override; \ void DecrementDestroyBlockedCount() override; \ void OnDonePrinting() override; \ diff --git a/layout/base/nsIPresShell.h b/layout/base/nsIPresShell.h index 78c4cf70b037..12401184c50d 100644 --- a/layout/base/nsIPresShell.h +++ b/layout/base/nsIPresShell.h @@ -272,7 +272,7 @@ class nsIPresShell : public nsStubDocumentObserver { } #endif - mozilla::ServoStyleSet* StyleSet() const { return mStyleSet.get(); } + inline mozilla::ServoStyleSet* StyleSet() const; nsCSSFrameConstructor* FrameConstructor() const { return mFrameConstructor.get(); @@ -1778,8 +1778,6 @@ class nsIPresShell : public nsStubDocumentObserver { FrameMetrics::ScrollOffsetUpdateType aUpdateType); #ifdef DEBUG - mozilla::UniquePtr CloneStyleSet( - mozilla::ServoStyleSet*); bool VerifyIncrementalReflow(); void DoVerifyReflow(); void VerifyHasDirtyRootAncestor(nsIFrame* aFrame); @@ -1857,9 +1855,8 @@ class nsIPresShell : public nsStubDocumentObserver { // we must share ownership. RefPtr mDocument; RefPtr mPresContext; - // mStyleSet owns it but we maintain a ref, may be null + // The document's style set owns it but we maintain a ref, may be null. RefPtr mPrefStyleSheet; - mozilla::UniquePtr mStyleSet; mozilla::UniquePtr mFrameConstructor; nsViewManager* mViewManager; // [WEAK] docViewer owns it so I don't have to nsPresArena<8192> mFrameArena; diff --git a/layout/base/nsIPresShellInlines.h b/layout/base/nsIPresShellInlines.h index 355780518a57..8857a7b05a65 100644 --- a/layout/base/nsIPresShellInlines.h +++ b/layout/base/nsIPresShellInlines.h @@ -9,6 +9,7 @@ #include "mozilla/PresShell.h" #include "mozilla/dom/Document.h" +#include "mozilla/dom/Element.h" void nsIPresShell::SetNeedLayoutFlush() { mNeedLayoutFlush = true; @@ -54,6 +55,10 @@ void nsIPresShell::SetNeedThrottledAnimationFlush() { } } +mozilla::ServoStyleSet* nsIPresShell::StyleSet() const { + return mDocument->StyleSetForPresShellOrMediaQueryEvaluation(); +} + namespace mozilla { /* static */ diff --git a/layout/base/nsPresContext.cpp b/layout/base/nsPresContext.cpp index 8f96cee5d3d2..ff9d853f5136 100644 --- a/layout/base/nsPresContext.cpp +++ b/layout/base/nsPresContext.cpp @@ -847,44 +847,6 @@ nsRootPresContext* nsPresContext::GetRootPresContext() { return pc->IsRoot() ? static_cast(pc) : nullptr; } -void nsPresContext::CompatibilityModeChanged() { - if (!mShell) { - return; - } - - ServoStyleSet* styleSet = mShell->StyleSet(); - styleSet->CompatibilityModeChanged(); - - mShell->EnsureStyleFlush(); - - if (mDocument->IsSVGDocument()) { - // SVG documents never load quirk.css. - return; - } - - bool needsQuirkSheet = CompatibilityMode() == eCompatibility_NavQuirks; - if (mQuirkSheetAdded == needsQuirkSheet) { - return; - } - - auto cache = nsLayoutStylesheetCache::Singleton(); - StyleSheet* sheet = cache->QuirkSheet(); - - if (needsQuirkSheet) { - // quirk.css needs to come after html.css; we just keep it at the end. - DebugOnly rv = - styleSet->AppendStyleSheet(SheetType::Agent, sheet); - NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "failed to insert quirk.css"); - } else { - DebugOnly rv = - styleSet->RemoveStyleSheet(SheetType::Agent, sheet); - NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "failed to remove quirk.css"); - } - - mQuirkSheetAdded = needsQuirkSheet; - mShell->ApplicableStylesChanged(); -} - // Helper function for setting Anim Mode on image static void SetImgAnimModeOnImgReq(imgIRequest* aImgReq, uint16_t aMode) { if (aImgReq) { diff --git a/layout/base/nsPresContext.h b/layout/base/nsPresContext.h index 1e0a854f9343..9a92e22c9ab4 100644 --- a/layout/base/nsPresContext.h +++ b/layout/base/nsPresContext.h @@ -294,11 +294,6 @@ class nsPresContext : public nsISupports, */ nsCompatibility CompatibilityMode() const; - /** - * Notify the context that the document's compatibility mode has changed - */ - void CompatibilityModeChanged(); - /** * Access the image animation mode for this context */ diff --git a/layout/base/nsPresContextInlines.h b/layout/base/nsPresContextInlines.h index 83acb145461e..ed6c696d6ca8 100644 --- a/layout/base/nsPresContextInlines.h +++ b/layout/base/nsPresContextInlines.h @@ -4,18 +4,18 @@ * 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 nsIPresContextInlines_h -#define nsIPresContextInlines_h +#ifndef nsPresContextInlines_h +#define nsPresContextInlines_h #include "mozilla/PresShell.h" #include "nsCSSFrameConstructor.h" inline mozilla::ServoStyleSet* nsPresContext::StyleSet() const { - return GetPresShell()->StyleSet(); + return mDocument->StyleSetForPresShellOrMediaQueryEvaluation(); } inline nsCSSFrameConstructor* nsPresContext::FrameConstructor() { return PresShell()->FrameConstructor(); } -#endif // #ifndef nsIPresContextInlines_h +#endif // #ifndef nsPresContextInlines_h diff --git a/layout/base/nsStyleSheetService.cpp b/layout/base/nsStyleSheetService.cpp index 61fea4d63d16..f9108761996d 100644 --- a/layout/base/nsStyleSheetService.cpp +++ b/layout/base/nsStyleSheetService.cpp @@ -24,6 +24,7 @@ #include "nsNetUtil.h" #include "nsIConsoleService.h" #include "nsIObserverService.h" +#include "nsIPresShellInlines.h" #include "nsLayoutStatics.h" #include "nsLayoutUtils.h" diff --git a/layout/inspector/InspectorUtils.cpp b/layout/inspector/InspectorUtils.cpp index 1224bad89790..6393a31ace32 100644 --- a/layout/inspector/InspectorUtils.cpp +++ b/layout/inspector/InspectorUtils.cpp @@ -18,6 +18,7 @@ #include "nsIContentInlines.h" #include "mozilla/dom/Document.h" #include "nsIDOMWindow.h" +#include "nsIPresShellInlines.h" #include "nsXBLBinding.h" #include "nsXBLPrototypeBinding.h" #include "nsIMutableArray.h" diff --git a/layout/printing/nsPrintJob.cpp b/layout/printing/nsPrintJob.cpp index d9f6d11e46d7..326c62c14999 100644 --- a/layout/printing/nsPrintJob.cpp +++ b/layout/printing/nsPrintJob.cpp @@ -2235,11 +2235,8 @@ nsresult nsPrintJob::ReflowPrintObject(const UniquePtr& aPO) { rv = aPO->mViewManager->Init(printData->mPrintDC); NS_ENSURE_SUCCESS(rv, rv); - UniquePtr styleSet = - mDocViewerPrint->CreateStyleSet(aPO->mDocument); - - aPO->mPresShell = aPO->mDocument->CreatePresShell( - aPO->mPresContext, aPO->mViewManager, std::move(styleSet)); + aPO->mPresShell = + aPO->mDocument->CreatePresShell(aPO->mPresContext, aPO->mViewManager); if (!aPO->mPresShell) { return NS_ERROR_FAILURE; } diff --git a/layout/style/Loader.cpp b/layout/style/Loader.cpp index 0771a336a582..07fcb56f9810 100644 --- a/layout/style/Loader.cpp +++ b/layout/style/Loader.cpp @@ -369,8 +369,9 @@ Loader::Loader() Loader::Loader(DocGroup* aDocGroup) : Loader() { mDocGroup = aDocGroup; } Loader::Loader(Document* aDocument) : Loader() { + MOZ_ASSERT(aDocument, "We should get a valid document from the caller!"); mDocument = aDocument; - MOZ_ASSERT(mDocument, "We should get a valid document from the caller!"); + mCompatMode = aDocument->GetCompatibilityMode(); } Loader::~Loader() { diff --git a/layout/style/MediaFeatureChange.h b/layout/style/MediaFeatureChange.h index 7e091316394b..1ec8324a7f26 100644 --- a/layout/style/MediaFeatureChange.h +++ b/layout/style/MediaFeatureChange.h @@ -44,6 +44,8 @@ enum class MediaFeatureChangeReason { MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(MediaFeatureChangeReason) struct MediaFeatureChange { + static const auto kAllChanges = static_cast(~0); + RestyleHint mRestyleHint; nsChangeHint mChangeHint; MediaFeatureChangeReason mReason; diff --git a/layout/style/ServoStyleSet.cpp b/layout/style/ServoStyleSet.cpp index 4f4157a6f4b4..44e5a2d7b0ba 100644 --- a/layout/style/ServoStyleSet.cpp +++ b/layout/style/ServoStyleSet.cpp @@ -92,12 +92,15 @@ class MOZ_RAII AutoPrepareTraversal { } // namespace mozilla -ServoStyleSet::ServoStyleSet() - : mDocument(nullptr), +ServoStyleSet::ServoStyleSet(Document& aDocument) + : mDocument(&aDocument), mAuthorStyleDisabled(false), mStylistState(StylistState::NotDirty), mUserFontSetUpdateGeneration(0), - mNeedsRestyleAfterEnsureUniqueInner(false) {} + mNeedsRestyleAfterEnsureUniqueInner(false) { + PreferenceSheet::EnsureInitialized(); + mRawSet.reset(Servo_StyleSet_Init(&aDocument)); +} ServoStyleSet::~ServoStyleSet() { for (auto& sheetArray : mSheets) { @@ -108,41 +111,10 @@ ServoStyleSet::~ServoStyleSet() { } nsPresContext* ServoStyleSet::GetPresContext() { - if (!mDocument) { - return nullptr; - } - return mDocument->GetPresContext(); } -void ServoStyleSet::Init(nsPresContext* aPresContext) { - mDocument = aPresContext->Document(); - MOZ_ASSERT(GetPresContext() == aPresContext); - - mRawSet.reset(Servo_StyleSet_Init(aPresContext)); - - 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 - // because Servo only needs to maintain relative ordering within a sheet - // type, which this preserves. - - MOZ_ASSERT(sheet->RawContents(), - "We should only append non-null raw sheets."); - Servo_StyleSet_AppendStyleSheet(mRawSet.get(), sheet); - } - } - - // We added prefilled stylesheets into mRawSet, so the stylist is dirty. - // The Stylist should be updated later when necessary. - SetStylistStyleSheetsDirty(); - +void ServoStyleSet::ShellAttachedToDocument() { // We may have Shadow DOM style changes that we weren't notified about because // the document didn't have a shell, if the ShadowRoot was created in a // display: none iframe. @@ -165,11 +137,10 @@ void EnumerateShadowRoots(const Document& aDoc, const Functor& aCb) { } } -void ServoStyleSet::Shutdown() { +void ServoStyleSet::ShellDetachedFromDocument() { // Make sure we drop our cached styles before the presshell arena starts going // away. ClearNonInheritingComputedStyles(); - mRawSet = nullptr; mStyleRuleMap = nullptr; } @@ -630,13 +601,11 @@ nsresult ServoStyleSet::AppendStyleSheet(SheetType aType, StyleSheet* aSheet) { RemoveSheetOfType(aType, aSheet); AppendSheetOfType(aType, aSheet); - if (mRawSet) { - // Maintain a mirrored list of sheets on the servo side. - // Servo will remove aSheet from its original position as part of the call - // to Servo_StyleSet_AppendStyleSheet. - Servo_StyleSet_AppendStyleSheet(mRawSet.get(), aSheet); - SetStylistStyleSheetsDirty(); - } + // Maintain a mirrored list of sheets on the servo side. + // Servo will remove aSheet from its original position as part of the call + // to Servo_StyleSet_AppendStyleSheet. + Servo_StyleSet_AppendStyleSheet(mRawSet.get(), aSheet); + SetStylistStyleSheetsDirty(); if (mStyleRuleMap) { mStyleRuleMap->SheetAdded(*aSheet); @@ -650,11 +619,10 @@ nsresult ServoStyleSet::RemoveStyleSheet(SheetType aType, StyleSheet* aSheet) { MOZ_ASSERT(IsCSSSheetType(aType)); RemoveSheetOfType(aType, aSheet); - if (mRawSet) { - // Maintain a mirrored list of sheets on the servo side. - Servo_StyleSet_RemoveStyleSheet(mRawSet.get(), aSheet); - SetStylistStyleSheetsDirty(); - } + + // Maintain a mirrored list of sheets on the servo side. + Servo_StyleSet_RemoveStyleSheet(mRawSet.get(), aSheet); + SetStylistStyleSheetsDirty(); if (mStyleRuleMap) { mStyleRuleMap->SheetRemoved(*aSheet); @@ -675,20 +643,16 @@ nsresult ServoStyleSet::ReplaceSheets( // Remove all the existing sheets first. for (const auto& sheet : mSheets[aType]) { sheet->DropStyleSet(this); - if (mRawSet) { - Servo_StyleSet_RemoveStyleSheet(mRawSet.get(), sheet); - } + Servo_StyleSet_RemoveStyleSheet(mRawSet.get(), sheet); } mSheets[aType].Clear(); // Add in all the new sheets. for (auto& sheet : aNewSheets) { AppendSheetOfType(aType, sheet); - if (mRawSet) { - MOZ_ASSERT(sheet->RawContents(), - "Raw sheet should be in place before replacement."); - Servo_StyleSet_AppendStyleSheet(mRawSet.get(), sheet); - } + MOZ_ASSERT(sheet->RawContents(), + "Raw sheet should be in place before replacement."); + Servo_StyleSet_AppendStyleSheet(mRawSet.get(), sheet); } // Just don't bother calling SheetRemoved / SheetAdded, and recreate the rule @@ -714,12 +678,10 @@ nsresult ServoStyleSet::InsertStyleSheetBefore(SheetType aType, RemoveSheetOfType(aType, aNewSheet); InsertSheetOfType(aType, aNewSheet, aReferenceSheet); - if (mRawSet) { - // Maintain a mirrored list of sheets on the servo side. - Servo_StyleSet_InsertStyleSheetBefore(mRawSet.get(), aNewSheet, - aReferenceSheet); - SetStylistStyleSheetsDirty(); - } + // Maintain a mirrored list of sheets on the servo side. + Servo_StyleSet_InsertStyleSheetBefore(mRawSet.get(), aNewSheet, + aReferenceSheet); + SetStylistStyleSheetsDirty(); if (mStyleRuleMap) { mStyleRuleMap->SheetAdded(*aNewSheet); @@ -772,20 +734,16 @@ nsresult ServoStyleSet::AddDocStyleSheet(StyleSheet* aSheet, StyleSheet* beforeSheet = mSheets[SheetType::Doc][index]; InsertSheetOfType(SheetType::Doc, aSheet, beforeSheet); - if (mRawSet) { - // Maintain a mirrored list of sheets on the servo side. - Servo_StyleSet_InsertStyleSheetBefore(mRawSet.get(), aSheet, beforeSheet); - SetStylistStyleSheetsDirty(); - } + // Maintain a mirrored list of sheets on the servo side. + Servo_StyleSet_InsertStyleSheetBefore(mRawSet.get(), aSheet, beforeSheet); + SetStylistStyleSheetsDirty(); } else { // This case is append. AppendSheetOfType(SheetType::Doc, aSheet); - if (mRawSet) { - // Maintain a mirrored list of sheets on the servo side. - Servo_StyleSet_AppendStyleSheet(mRawSet.get(), aSheet); - SetStylistStyleSheetsDirty(); - } + // Maintain a mirrored list of sheets on the servo side. + Servo_StyleSet_AppendStyleSheet(mRawSet.get(), aSheet); + SetStylistStyleSheetsDirty(); } if (mStyleRuleMap) { @@ -970,10 +928,6 @@ void ServoStyleSet::StyleNewSubtree(Element* aRoot) { } void ServoStyleSet::MarkOriginsDirty(OriginFlags aChangedOrigins) { - if (MOZ_UNLIKELY(!mRawSet)) { - return; - } - SetStylistStyleSheetsDirty(); Servo_StyleSet_NoteStyleSheetsChanged(mRawSet.get(), aChangedOrigins); } diff --git a/layout/style/ServoStyleSet.h b/layout/style/ServoStyleSet.h index 206d44f52254..ead9343c5643 100644 --- a/layout/style/ServoStyleSet.h +++ b/layout/style/ServoStyleSet.h @@ -95,12 +95,11 @@ class ServoStyleSet { static ServoStyleSet* Current() { return sInServoTraversal; } - ServoStyleSet(); + explicit ServoStyleSet(dom::Document&); ~ServoStyleSet(); - void Init(nsPresContext* aPresContext); - void BeginShutdown() {} - void Shutdown(); + void ShellAttachedToDocument(); + void ShellDetachedFromDocument(); // Called when a rules in a stylesheet in this set, or a child sheet of that, // are mutated from CSSOM. @@ -505,10 +504,8 @@ class ServoStyleSet { void RemoveSheetOfType(SheetType aType, StyleSheet* aSheet); - // The owner document of this style set. Null if this is an XBL style set. - // - // TODO(emilio): This should become a DocumentOrShadowRoot, and be owned by it - // directly instead of the shell, eventually. + // The owner document of this style set. Never null, and always outlives the + // StyleSet. dom::Document* mDocument; const nsPresContext* GetPresContext() const { diff --git a/servo/ports/geckolib/glue.rs b/servo/ports/geckolib/glue.rs index 337fb32df7fa..053ca429f5fd 100644 --- a/servo/ports/geckolib/glue.rs +++ b/servo/ports/geckolib/glue.rs @@ -3517,14 +3517,8 @@ pub extern "C" fn Servo_ComputedValues_GetStyleRuleList( })) } -/// See the comment in `Device` to see why it's ok to pass an owned reference to -/// the pres context (hint: the context outlives the StyleSet, that holds the -/// device alive). #[no_mangle] -pub extern "C" fn Servo_StyleSet_Init( - pres_context: &structs::nsPresContext, -) -> *mut RawServoStyleSet { - let doc = pres_context.mDocument.mRawPtr; +pub extern "C" fn Servo_StyleSet_Init(doc: &structs::Document) -> *mut RawServoStyleSet { let data = Box::new(PerDocumentStyleData::new(doc)); Box::into_raw(data) as *mut RawServoStyleSet }