AuthorStyleSheets shouldn't trigger synchronous style resolutions
https://bugs.webkit.org/show_bug.cgi?id=162532
Reviewed by Darin Adler.
Source/WebCore:
AuthorStyleSheets::didChange() took four different enum values, two of which triggered
a synchronous style resolution. This is almost always unnecessary as any subsequent
call that requires up-to-date style or layout will perform it. In the few cases where
it is actually needed the client can just do it manually.
The patch also replaces the remaining two enum values with functions:
void didChangeCandidatesForActiveSet();
void didChangeContentsOrInterpretation();
The first indicates that the set of active stylesheets might have changed and needs to be recomputed.
The seconds one indicates that either the content of some stylesheet has changed or that the environment
where we interpret the sheets has somehow changed.
The existing "AsNeeded" values map to didChangeCandidatesForActiveSet() and the rest map to
didChangeContentsOrInterpretation(). This also makes it obvious that some call sites use the wrong value.
The patch doesn't address these cases.
* css/CSSStyleSheet.cpp:
(WebCore::CSSStyleSheet::didMutateRules):
(WebCore::CSSStyleSheet::didMutate):
(WebCore::CSSStyleSheet::clearOwnerNode):
* dom/AuthorStyleSheets.cpp:
(WebCore::AuthorStyleSheets::AuthorStyleSheets):
(WebCore::AuthorStyleSheets::analyzeStyleSheetChange):
(WebCore::AuthorStyleSheets::updateActiveStyleSheets):
(WebCore::AuthorStyleSheets::flushPendingChanges):
(WebCore::AuthorStyleSheets::scheduleActiveSetChange):
(WebCore::AuthorStyleSheets::didChange):
(WebCore::AuthorStyleSheets::pendingChangeTimerFired):
(WebCore::AuthorStyleSheets::flushPendingUpdates): Deleted.
(WebCore::AuthorStyleSheets::scheduleOptimizedUpdate): Deleted.
(WebCore::AuthorStyleSheets::optimizedUpdateTimerFired): Deleted.
* dom/AuthorStyleSheets.h:
(WebCore::AuthorStyleSheets::hasPendingUpdate):
* dom/Document.cpp:
(WebCore::Document::setContentLanguage):
(WebCore::Document::recalcStyle):
(WebCore::Document::updateStyleIfNeeded):
(WebCore::Document::updateLayoutIgnorePendingStylesheets):
(WebCore::Document::didRemoveAllPendingStylesheet):
(WebCore::Document::usesStyleBasedEditability):
(WebCore::Document::processHttpEquiv):
(WebCore::Document::setSelectedStylesheetSet):
* dom/ExtensionStyleSheets.cpp:
(WebCore::ExtensionStyleSheets::clearPageUserSheet):
(WebCore::ExtensionStyleSheets::updatePageUserSheet):
(WebCore::ExtensionStyleSheets::invalidateInjectedStyleSheetCache):
(WebCore::ExtensionStyleSheets::addUserStyleSheet):
(WebCore::ExtensionStyleSheets::addAuthorStyleSheetForTesting):
(WebCore::ExtensionStyleSheets::styleResolverChangedTimerFired):
* dom/InlineStyleSheetOwner.cpp:
(WebCore::InlineStyleSheetOwner::removedFromDocument):
* dom/ProcessingInstruction.cpp:
(WebCore::ProcessingInstruction::removedFrom):
* dom/ShadowRoot.cpp:
(WebCore::ShadowRoot::updateStyle):
* html/HTMLLinkElement.cpp:
(WebCore::HTMLLinkElement::setDisabledState):
(WebCore::HTMLLinkElement::parseAttribute):
(WebCore::HTMLLinkElement::process):
(WebCore::HTMLLinkElement::removedFrom):
(WebCore::HTMLLinkElement::removePendingSheet):
* html/HTMLStyleElement.cpp:
(WebCore::HTMLStyleElement::parseAttribute):
* inspector/InspectorCSSAgent.cpp:
(WebCore::InspectorCSSAgent::forcePseudoState):
(WebCore::InspectorCSSAgent::resetPseudoStates):
* inspector/InspectorPageAgent.cpp:
(WebCore::InspectorPageAgent::setEmulatedMedia):
* page/Frame.cpp:
(WebCore::Frame::setPrinting):
* page/FrameView.cpp:
(WebCore::FrameView::layout):
(WebCore::FrameView::setPagination):
(WebCore::FrameView::setViewportSizeForCSSViewportUnits):
* page/Page.cpp:
(WebCore::Page::setViewMode):
(WebCore::Page::setNeedsRecalcStyleInAllFrames):
(WebCore::Page::invalidateInjectedStyleSheetCacheInAllFrames):
* svg/SVGFontFaceElement.cpp:
(WebCore::SVGFontFaceElement::rebuildFontFace):
(WebCore::SVGFontFaceElement::removedFrom):
* xml/XMLTreeViewer.cpp:
(WebCore::XMLTreeViewer::transformDocumentToTreeView):
* xml/parser/XMLDocumentParser.cpp:
(WebCore::XMLDocumentParser::end):
* xml/parser/XMLDocumentParserLibxml2.cpp:
(WebCore::XMLDocumentParser::doEnd):
Source/WebKit/mac:
* WebView/WebHTMLView.mm:
(-[WebHTMLView reapplyStyles]):
(-[WebHTMLView _setPrinting:minimumPageLogicalWidth:logicalHeight:originalPageWidth:originalPageHeight:maximumShrinkRatio:adjustViewSize:paginateScreenContent:]):
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@206361 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/WebCore/dom/AuthorStyleSheets.cpp b/Source/WebCore/dom/AuthorStyleSheets.cpp
index 3e0ef14..79cb201 100644
--- a/Source/WebCore/dom/AuthorStyleSheets.cpp
+++ b/Source/WebCore/dom/AuthorStyleSheets.cpp
@@ -57,14 +57,14 @@
AuthorStyleSheets::AuthorStyleSheets(Document& document)
: m_document(document)
- , m_optimizedUpdateTimer(*this, &AuthorStyleSheets::optimizedUpdateTimerFired)
+ , m_pendingUpdateTimer(*this, &AuthorStyleSheets::pendingUpdateTimerFired)
{
}
AuthorStyleSheets::AuthorStyleSheets(ShadowRoot& shadowRoot)
: m_document(shadowRoot.documentScope())
, m_shadowRoot(&shadowRoot)
- , m_optimizedUpdateTimer(*this, &AuthorStyleSheets::optimizedUpdateTimerFired)
+ , m_pendingUpdateTimer(*this, &AuthorStyleSheets::pendingUpdateTimerFired)
{
}
@@ -213,14 +213,12 @@
}
}
-AuthorStyleSheets::StyleResolverUpdateType AuthorStyleSheets::analyzeStyleSheetChange(UpdateFlag updateFlag, const Vector<RefPtr<CSSStyleSheet>>& newStylesheets, bool& requiresFullStyleRecalc)
+AuthorStyleSheets::StyleResolverUpdateType AuthorStyleSheets::analyzeStyleSheetChange(const Vector<RefPtr<CSSStyleSheet>>& newStylesheets, bool& requiresFullStyleRecalc)
{
requiresFullStyleRecalc = true;
unsigned newStylesheetCount = newStylesheets.size();
- if (updateFlag != OptimizedUpdate)
- return Reconstruct;
if (!m_document.styleResolverIfExists())
return Reconstruct;
@@ -282,19 +280,32 @@
}
}
-bool AuthorStyleSheets::updateActiveStyleSheets(UpdateFlag updateFlag)
+void AuthorStyleSheets::updateActiveStyleSheets(UpdateType updateType)
{
+ ASSERT(!m_pendingUpdateType);
+
if (m_document.inStyleRecalc() || m_document.inRenderTreeUpdate()) {
// Protect against deleting style resolver in the middle of a style resolution.
- // Crash stacks indicate we can get here when z resource load fails synchronously (for example due to content blocking).
+ // Crash stacks indicate we can get here when a resource load fails synchronously (for example due to content blocking).
// FIXME: These kind of cases should be eliminated and this path replaced by an assert.
- m_pendingUpdateType = FullUpdate;
+ m_pendingUpdateType = UpdateType::ContentsOrInterpretation;
m_document.scheduleForcedStyleRecalc();
- return false;
-
+ return;
}
- if (!m_document.hasLivingRenderTree())
- return false;
+
+ if (!m_document.hasLivingRenderTree()) {
+ m_document.clearStyleResolver();
+ return;
+ }
+
+ // Don't bother updating, since we haven't loaded all our style info yet
+ // and haven't calculated the style resolver for the first time.
+ if (!m_shadowRoot && !m_didUpdateActiveStyleSheets && m_pendingStyleSheetCount) {
+ m_document.clearStyleResolver();
+ return;
+ }
+
+ m_didUpdateActiveStyleSheets = true;
Vector<RefPtr<StyleSheet>> activeStyleSheets;
collectActiveStyleSheets(activeStyleSheets);
@@ -304,8 +315,10 @@
activeCSSStyleSheets.appendVector(m_document.extensionStyleSheets().authorStyleSheetsForTesting());
filterEnabledNonemptyCSSStyleSheets(activeCSSStyleSheets, activeStyleSheets);
- bool requiresFullStyleRecalc;
- auto styleResolverUpdateType = analyzeStyleSheetChange(updateFlag, activeCSSStyleSheets, requiresFullStyleRecalc);
+ bool requiresFullStyleRecalc = true;
+ StyleResolverUpdateType styleResolverUpdateType = Reconstruct;
+ if (updateType == UpdateType::ActiveSet)
+ styleResolverUpdateType = analyzeStyleSheetChange(activeCSSStyleSheets, requiresFullStyleRecalc);
updateStyleResolver(activeCSSStyleSheets, styleResolverUpdateType);
@@ -321,9 +334,13 @@
if (sheet->contents().usesStyleBasedEditability())
m_usesStyleBasedEditability = true;
}
- m_pendingUpdateType = NoUpdate;
- return requiresFullStyleRecalc;
+ if (requiresFullStyleRecalc) {
+ if (m_shadowRoot)
+ m_shadowRoot->setNeedsStyleRecalc();
+ else
+ m_document.scheduleForcedStyleRecalc();
+ }
}
void AuthorStyleSheets::updateStyleResolver(Vector<RefPtr<CSSStyleSheet>>& activeStyleSheets, StyleResolverUpdateType updateType)
@@ -386,64 +403,48 @@
return m_weakCopyOfActiveStyleSheetListForFastLookup->contains(sheet);
}
-void AuthorStyleSheets::flushPendingUpdates()
+void AuthorStyleSheets::flushPendingUpdate()
{
- if (m_pendingUpdateType == NoUpdate)
+ if (!m_pendingUpdateType)
return;
- updateActiveStyleSheets(m_pendingUpdateType);
+ auto updateType = *m_pendingUpdateType;
+
+ clearPendingUpdate();
+
+ updateActiveStyleSheets(updateType);
}
-void AuthorStyleSheets::scheduleOptimizedUpdate()
+void AuthorStyleSheets::clearPendingUpdate()
{
- if (m_optimizedUpdateTimer.isActive())
- return;
- if (m_pendingUpdateType == NoUpdate)
- m_pendingUpdateType = OptimizedUpdate;
- m_optimizedUpdateTimer.startOneShot(0);
+ m_pendingUpdateTimer.stop();
+ m_pendingUpdateType = { };
}
-void AuthorStyleSheets::didChange(StyleResolverUpdateFlag updateFlag)
+void AuthorStyleSheets::scheduleActiveSetUpdate()
{
- m_optimizedUpdateTimer.stop();
-
- // Don't bother updating, since we haven't loaded all our style info yet
- // and haven't calculated the style resolver for the first time.
- if (!m_document.hasLivingRenderTree() || (!m_shadowRoot && !m_didCalculateStyleResolver && m_pendingStyleSheetCount)) {
- m_document.clearStyleResolver();
+ if (m_pendingUpdateTimer.isActive())
return;
- }
- m_didCalculateStyleResolver = true;
-
- auto styleSheetUpdate = (updateFlag == RecalcStyleIfNeeded || updateFlag == DeferRecalcStyleIfNeeded)
- ? AuthorStyleSheets::OptimizedUpdate
- : AuthorStyleSheets::FullUpdate;
- bool stylesheetChangeRequiresStyleRecalc = updateActiveStyleSheets(styleSheetUpdate);
-
- auto scheduleStyleRecalc = [&] {
- if (m_shadowRoot)
- m_shadowRoot->setNeedsStyleRecalc();
- else
- m_document.scheduleForcedStyleRecalc();
- };
-
- if (updateFlag == DeferRecalcStyle) {
- scheduleStyleRecalc();
- return;
- }
-
- if (updateFlag == DeferRecalcStyleIfNeeded) {
- if (stylesheetChangeRequiresStyleRecalc)
- scheduleStyleRecalc();
- return;
- }
-
- if (stylesheetChangeRequiresStyleRecalc)
- m_document.recalcStyle(Style::Force);
+ if (!m_pendingUpdateType)
+ m_pendingUpdateType = UpdateType::ActiveSet;
+ m_pendingUpdateTimer.startOneShot(0);
}
-void AuthorStyleSheets::optimizedUpdateTimerFired()
+void AuthorStyleSheets::didChangeCandidatesForActiveSet()
{
- didChange(RecalcStyleIfNeeded);
+ auto updateType = m_pendingUpdateType.valueOr(UpdateType::ActiveSet);
+ clearPendingUpdate();
+ updateActiveStyleSheets(updateType);
+}
+
+void AuthorStyleSheets::didChangeContentsOrInterpretation()
+{
+ clearPendingUpdate();
+ updateActiveStyleSheets(UpdateType::ContentsOrInterpretation);
+}
+
+void AuthorStyleSheets::pendingUpdateTimerFired()
+{
+ flushPendingUpdate();
}
}