| Index: third_party/WebKit/Source/core/dom/TreeScopeStyleSheetCollection.cpp
|
| diff --git a/third_party/WebKit/Source/core/dom/TreeScopeStyleSheetCollection.cpp b/third_party/WebKit/Source/core/dom/TreeScopeStyleSheetCollection.cpp
|
| index 918824798ed10537f1849443e14cd12541843d22..a64330698a590fa62ffe8da209d914a5272f575c 100644
|
| --- a/third_party/WebKit/Source/core/dom/TreeScopeStyleSheetCollection.cpp
|
| +++ b/third_party/WebKit/Source/core/dom/TreeScopeStyleSheetCollection.cpp
|
| @@ -28,10 +28,10 @@
|
|
|
| #include "core/dom/TreeScopeStyleSheetCollection.h"
|
|
|
| -#include "core/css/ActiveStyleSheets.h"
|
| #include "core/css/CSSStyleSheet.h"
|
| #include "core/css/StyleRuleImport.h"
|
| #include "core/css/StyleSheetContents.h"
|
| +#include "core/css/invalidation/StyleSheetInvalidationAnalysis.h"
|
| #include "core/css/resolver/StyleResolver.h"
|
| #include "core/dom/Element.h"
|
| #include "core/dom/StyleEngine.h"
|
| @@ -42,31 +42,139 @@
|
|
|
| TreeScopeStyleSheetCollection::TreeScopeStyleSheetCollection(
|
| TreeScope& treeScope)
|
| - : m_treeScope(treeScope) {}
|
| + : m_treeScope(treeScope), m_hadActiveLoadingStylesheet(false) {}
|
|
|
| void TreeScopeStyleSheetCollection::addStyleSheetCandidateNode(Node& node) {
|
| - if (node.isConnected())
|
| - m_styleSheetCandidateNodes.add(&node);
|
| + if (!node.isConnected())
|
| + return;
|
| +
|
| + m_styleSheetCandidateNodes.add(&node);
|
| }
|
|
|
| -bool TreeScopeStyleSheetCollection::mediaQueryAffectingValueChanged() {
|
| - bool needsActiveStyleUpdate = false;
|
| - for (const auto& activeSheet : m_activeAuthorStyleSheets) {
|
| - if (activeSheet.first->mediaQueries())
|
| - needsActiveStyleUpdate = true;
|
| - StyleSheetContents* contents = activeSheet.first->contents();
|
| +TreeScopeStyleSheetCollection::StyleResolverUpdateType
|
| +TreeScopeStyleSheetCollection::compareStyleSheets(
|
| + const HeapVector<Member<CSSStyleSheet>>& oldStyleSheets,
|
| + const HeapVector<Member<CSSStyleSheet>>& newStylesheets,
|
| + HeapVector<Member<StyleSheetContents>>& addedSheets) {
|
| + unsigned newStyleSheetCount = newStylesheets.size();
|
| + unsigned oldStyleSheetCount = oldStyleSheets.size();
|
| + DCHECK_GE(newStyleSheetCount, oldStyleSheetCount);
|
| +
|
| + if (!newStyleSheetCount)
|
| + return Reconstruct;
|
| +
|
| + unsigned newIndex = 0;
|
| + for (unsigned oldIndex = 0; oldIndex < oldStyleSheetCount; ++oldIndex) {
|
| + while (oldStyleSheets[oldIndex] != newStylesheets[newIndex]) {
|
| + addedSheets.append(newStylesheets[newIndex]->contents());
|
| + if (++newIndex == newStyleSheetCount)
|
| + return Reconstruct;
|
| + }
|
| + if (++newIndex == newStyleSheetCount)
|
| + return Reconstruct;
|
| + }
|
| + bool hasInsertions = !addedSheets.isEmpty();
|
| + while (newIndex < newStyleSheetCount) {
|
| + addedSheets.append(newStylesheets[newIndex]->contents());
|
| + ++newIndex;
|
| + }
|
| + // If all new sheets were added at the end of the list we can just add them to
|
| + // existing StyleResolver. If there were insertions we need to re-add all the
|
| + // stylesheets so rules are ordered correctly.
|
| + return hasInsertions ? Reset : Additive;
|
| +}
|
| +
|
| +bool TreeScopeStyleSheetCollection::activeLoadingStyleSheetLoaded(
|
| + const HeapVector<Member<CSSStyleSheet>>& newStyleSheets) {
|
| + // StyleSheets of <style> elements that @import stylesheets are active but
|
| + // loading. We need to trigger a full recalc when such loads are done.
|
| + bool hasActiveLoadingStylesheet = false;
|
| + for (const auto& sheet : newStyleSheets) {
|
| + if (sheet->isLoading())
|
| + hasActiveLoadingStylesheet = true;
|
| + }
|
| + if (m_hadActiveLoadingStylesheet && !hasActiveLoadingStylesheet) {
|
| + m_hadActiveLoadingStylesheet = false;
|
| + return true;
|
| + }
|
| + m_hadActiveLoadingStylesheet = hasActiveLoadingStylesheet;
|
| + return false;
|
| +}
|
| +
|
| +static bool findFontFaceRulesFromStyleSheetContents(
|
| + const HeapVector<Member<StyleSheetContents>>& sheets,
|
| + HeapVector<Member<const StyleRuleFontFace>>& fontFaceRules) {
|
| + bool hasFontFaceRule = false;
|
| +
|
| + for (const auto& sheet : sheets) {
|
| + DCHECK(sheet);
|
| + if (sheet->hasFontFaceRule()) {
|
| + // FIXME: We don't need this for styles in shadow tree.
|
| + sheet->findFontFaceRules(fontFaceRules);
|
| + hasFontFaceRule = true;
|
| + }
|
| + }
|
| + return hasFontFaceRule;
|
| +}
|
| +
|
| +void TreeScopeStyleSheetCollection::analyzeStyleSheetChange(
|
| + StyleResolverUpdateMode updateMode,
|
| + const HeapVector<Member<CSSStyleSheet>>& newActiveAuthorStyleSheets,
|
| + StyleSheetChange& change) {
|
| + if (activeLoadingStyleSheetLoaded(newActiveAuthorStyleSheets))
|
| + return;
|
| +
|
| + if (updateMode != AnalyzedStyleUpdate)
|
| + return;
|
| +
|
| + // Find out which stylesheets are new.
|
| + HeapVector<Member<StyleSheetContents>> addedSheets;
|
| + if (m_activeAuthorStyleSheets.size() <= newActiveAuthorStyleSheets.size()) {
|
| + change.styleResolverUpdateType = compareStyleSheets(
|
| + m_activeAuthorStyleSheets, newActiveAuthorStyleSheets, addedSheets);
|
| + } else {
|
| + StyleResolverUpdateType updateType = compareStyleSheets(
|
| + newActiveAuthorStyleSheets, m_activeAuthorStyleSheets, addedSheets);
|
| + if (updateType != Additive) {
|
| + change.styleResolverUpdateType = updateType;
|
| + } else {
|
| + change.styleResolverUpdateType = Reset;
|
| + // If @font-face is removed, needs full style recalc.
|
| + if (findFontFaceRulesFromStyleSheetContents(addedSheets,
|
| + change.fontFaceRulesToRemove))
|
| + return;
|
| + }
|
| + }
|
| +
|
| + // FIXME: If styleResolverUpdateType is Reconstruct, we should return early
|
| + // here since we need to recalc the whole document. It's wrong to use
|
| + // StyleSheetInvalidationAnalysis since it only looks at the addedSheets.
|
| +
|
| + // No point in doing the analysis work if we're just going to recalc the whole
|
| + // document anyways. This needs to be done after the compareStyleSheets calls
|
| + // above to ensure we don't throw away the StyleResolver if we don't need to.
|
| + if (document().hasPendingForcedStyleRecalc())
|
| + return;
|
| +
|
| + // If we are already parsing the body and so may have significant amount of
|
| + // elements, put some effort into trying to avoid style recalcs.
|
| + if (!document().body() || document().hasNodesWithPlaceholderStyle())
|
| + return;
|
| + StyleSheetInvalidationAnalysis invalidationAnalysis(*m_treeScope,
|
| + addedSheets);
|
| + if (invalidationAnalysis.dirtiesAllStyle())
|
| + return;
|
| + invalidationAnalysis.invalidateStyle();
|
| + change.requiresFullStyleRecalc = false;
|
| + return;
|
| +}
|
| +
|
| +void TreeScopeStyleSheetCollection::clearMediaQueryRuleSetStyleSheets() {
|
| + for (const auto& sheet : m_activeAuthorStyleSheets) {
|
| + StyleSheetContents* contents = sheet->contents();
|
| if (contents->hasMediaQueries())
|
| contents->clearRuleSet();
|
| }
|
| - return needsActiveStyleUpdate;
|
| -}
|
| -
|
| -void TreeScopeStyleSheetCollection::applyActiveStyleSheetChanges(
|
| - StyleSheetCollection& newCollection) {
|
| - document().styleEngine().applyRuleSetChanges(
|
| - treeScope(), activeAuthorStyleSheets(),
|
| - newCollection.activeAuthorStyleSheets());
|
| - newCollection.swap(*this);
|
| }
|
|
|
| DEFINE_TRACE(TreeScopeStyleSheetCollection) {
|
|
|