blob: d3bcfed5a5b7ac0f1e6f23f1961564d03e185622 [file] [log] [blame]
/*
* Copyright (C) 1999 Lars Knoll (knoll@kde.org)
* Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc.
* All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*
*/
#ifndef RuleFeatureSet_h
#define RuleFeatureSet_h
#include "base/macros.h"
#include "core/CoreExport.h"
#include "core/css/CSSSelector.h"
#include "core/css/MediaQueryEvaluator.h"
#include "core/css/invalidation/InvalidationSet.h"
#include "platform/heap/Handle.h"
#include "platform/wtf/Forward.h"
#include "platform/wtf/HashSet.h"
#include "platform/wtf/text/AtomicStringHash.h"
namespace blink {
class ContainerNode;
struct InvalidationLists;
class QualifiedName;
class RuleData;
class CORE_EXPORT RuleFeatureSet {
DISALLOW_NEW();
public:
RuleFeatureSet();
~RuleFeatureSet();
void Add(const RuleFeatureSet&);
void Clear();
enum SelectorPreMatch { kSelectorNeverMatches, kSelectorMayMatch };
SelectorPreMatch CollectFeaturesFromRuleData(const RuleData&);
bool UsesFirstLineRules() const { return metadata_.uses_first_line_rules; }
bool UsesWindowInactiveSelector() const {
return metadata_.uses_window_inactive_selector;
}
bool NeedsFullRecalcForRuleSetInvalidation() const {
return metadata_.needs_full_recalc_for_rule_set_invalidation;
}
unsigned MaxDirectAdjacentSelectors() const {
return metadata_.max_direct_adjacent_selectors;
}
bool HasSelectorForAttribute(const AtomicString& attribute_name) const {
DCHECK(!attribute_name.IsEmpty());
return attribute_invalidation_sets_.Contains(attribute_name);
}
bool HasSelectorForClass(const AtomicString& class_value) const {
DCHECK(!class_value.IsEmpty());
return class_invalidation_sets_.Contains(class_value);
}
bool HasSelectorForId(const AtomicString& id_value) const {
return id_invalidation_sets_.Contains(id_value);
}
const MediaQueryResultList& ViewportDependentMediaQueryResults() const {
return viewport_dependent_media_query_results_;
}
const MediaQueryResultList& DeviceDependentMediaQueryResults() const {
return device_dependent_media_query_results_;
}
MediaQueryResultList& ViewportDependentMediaQueryResults() {
return viewport_dependent_media_query_results_;
}
MediaQueryResultList& DeviceDependentMediaQueryResults() {
return device_dependent_media_query_results_;
}
// Collect descendant and sibling invalidation sets.
void CollectInvalidationSetsForClass(InvalidationLists&,
Element&,
const AtomicString& class_name) const;
void CollectInvalidationSetsForId(InvalidationLists&,
Element&,
const AtomicString& id) const;
void CollectInvalidationSetsForAttribute(
InvalidationLists&,
Element&,
const QualifiedName& attribute_name) const;
void CollectInvalidationSetsForPseudoClass(InvalidationLists&,
Element&,
CSSSelector::PseudoType) const;
void CollectSiblingInvalidationSetForClass(
InvalidationLists&,
Element&,
const AtomicString& class_name,
unsigned min_direct_adjacent) const;
void CollectSiblingInvalidationSetForId(InvalidationLists&,
Element&,
const AtomicString& id,
unsigned min_direct_adjacent) const;
void CollectSiblingInvalidationSetForAttribute(
InvalidationLists&,
Element&,
const QualifiedName& attribute_name,
unsigned min_direct_adjacent) const;
void CollectUniversalSiblingInvalidationSet(
InvalidationLists&,
unsigned min_direct_adjacent) const;
void CollectNthInvalidationSet(InvalidationLists&) const;
void CollectTypeRuleInvalidationSet(InvalidationLists&, ContainerNode&) const;
bool HasIdsInSelectors() const { return id_invalidation_sets_.size() > 0; }
bool IsAlive() const { return is_alive_; }
protected:
enum PositionType { kSubject, kAncestor };
InvalidationSet* InvalidationSetForSimpleSelector(const CSSSelector&,
InvalidationType,
PositionType);
private:
// Each map entry is either a DescendantInvalidationSet or
// SiblingInvalidationSet.
// When both are needed, we store the SiblingInvalidationSet, and use it to
// hold the DescendantInvalidationSet.
using InvalidationSetMap =
HashMap<AtomicString, scoped_refptr<InvalidationSet>>;
using PseudoTypeInvalidationSetMap =
HashMap<CSSSelector::PseudoType,
scoped_refptr<InvalidationSet>,
WTF::IntHash<unsigned>,
WTF::UnsignedWithZeroKeyHashTraits<unsigned>>;
struct FeatureMetadata {
DISALLOW_NEW();
void Add(const FeatureMetadata& other);
void Clear();
bool uses_first_line_rules = false;
bool uses_window_inactive_selector = false;
bool found_insertion_point_crossing = false;
bool needs_full_recalc_for_rule_set_invalidation = false;
unsigned max_direct_adjacent_selectors = 0;
};
SelectorPreMatch CollectFeaturesFromSelector(const CSSSelector&,
FeatureMetadata&);
InvalidationSet& EnsureClassInvalidationSet(const AtomicString& class_name,
InvalidationType,
PositionType);
InvalidationSet& EnsureAttributeInvalidationSet(
const AtomicString& attribute_name,
InvalidationType,
PositionType);
InvalidationSet& EnsureIdInvalidationSet(const AtomicString& id,
InvalidationType,
PositionType);
InvalidationSet& EnsurePseudoInvalidationSet(CSSSelector::PseudoType,
InvalidationType,
PositionType);
SiblingInvalidationSet& EnsureUniversalSiblingInvalidationSet();
DescendantInvalidationSet& EnsureNthInvalidationSet();
DescendantInvalidationSet& EnsureTypeRuleInvalidationSet();
void UpdateInvalidationSets(const RuleData&);
void UpdateInvalidationSetsForContentAttribute(const RuleData&);
struct InvalidationSetFeatures {
DISALLOW_NEW();
void Add(const InvalidationSetFeatures& other);
bool HasFeatures() const;
bool HasIdClassOrAttribute() const;
Vector<AtomicString> classes;
Vector<AtomicString> attributes;
Vector<AtomicString> ids;
Vector<AtomicString> tag_names;
unsigned max_direct_adjacent_selectors = 0;
bool custom_pseudo_element = false;
bool has_before_or_after = false;
bool tree_boundary_crossing = false;
bool insertion_point_crossing = false;
bool force_subtree = false;
bool content_pseudo_crossing = false;
bool invalidates_slotted = false;
bool has_nth_pseudo = false;
bool has_features_for_rule_set_invalidation = false;
};
static void ExtractInvalidationSetFeature(const CSSSelector&,
InvalidationSetFeatures&);
enum FeatureInvalidationType {
kNormalInvalidation,
kRequiresSubtreeInvalidation
};
void ExtractInvalidationSetFeaturesFromSimpleSelector(
const CSSSelector&,
InvalidationSetFeatures&);
const CSSSelector* ExtractInvalidationSetFeaturesFromCompound(
const CSSSelector&,
InvalidationSetFeatures&,
PositionType,
CSSSelector::PseudoType = CSSSelector::kPseudoUnknown);
FeatureInvalidationType ExtractInvalidationSetFeaturesFromSelectorList(
const CSSSelector&,
InvalidationSetFeatures&,
PositionType);
void UpdateFeaturesFromCombinator(
const CSSSelector&,
const CSSSelector* last_compound_selector_in_adjacent_chain,
InvalidationSetFeatures& last_compound_in_adjacent_chain_features,
InvalidationSetFeatures*& sibling_features,
InvalidationSetFeatures& descendant_features);
void AddFeaturesToInvalidationSet(InvalidationSet&,
const InvalidationSetFeatures&);
void AddFeaturesToInvalidationSets(
const CSSSelector&,
InvalidationSetFeatures* sibling_features,
InvalidationSetFeatures& descendant_features);
const CSSSelector* AddFeaturesToInvalidationSetsForCompoundSelector(
const CSSSelector&,
InvalidationSetFeatures* sibling_features,
InvalidationSetFeatures& descendant_features);
void AddFeaturesToInvalidationSetsForSimpleSelector(
const CSSSelector&,
InvalidationSetFeatures* sibling_features,
InvalidationSetFeatures& descendant_features);
void AddFeaturesToInvalidationSetsForSelectorList(
const CSSSelector&,
InvalidationSetFeatures* sibling_features,
InvalidationSetFeatures& descendant_features);
void AddFeaturesToUniversalSiblingInvalidationSet(
const InvalidationSetFeatures& sibling_features,
const InvalidationSetFeatures& descendant_features);
void UpdateRuleSetInvalidation(const InvalidationSetFeatures&);
static InvalidationSet& StoredInvalidationSet(scoped_refptr<InvalidationSet>&,
InvalidationType,
PositionType);
static InvalidationSet& EnsureInvalidationSet(
HashMap<AtomicString, scoped_refptr<InvalidationSet>>&,
const AtomicString& key,
InvalidationType,
PositionType);
static InvalidationSet& EnsureInvalidationSet(
HashMap<CSSSelector::PseudoType,
scoped_refptr<InvalidationSet>,
WTF::IntHash<unsigned>,
WTF::UnsignedWithZeroKeyHashTraits<unsigned>>&,
CSSSelector::PseudoType key,
InvalidationType,
PositionType);
FeatureMetadata metadata_;
InvalidationSetMap class_invalidation_sets_;
InvalidationSetMap attribute_invalidation_sets_;
InvalidationSetMap id_invalidation_sets_;
PseudoTypeInvalidationSetMap pseudo_invalidation_sets_;
scoped_refptr<SiblingInvalidationSet> universal_sibling_invalidation_set_;
scoped_refptr<DescendantInvalidationSet> nth_invalidation_set_;
scoped_refptr<DescendantInvalidationSet> type_rule_invalidation_set_;
MediaQueryResultList viewport_dependent_media_query_results_;
MediaQueryResultList device_dependent_media_query_results_;
// If true, the RuleFeatureSet is alive and can be used.
unsigned is_alive_ : 1;
friend class RuleFeatureSetTest;
DISALLOW_COPY_AND_ASSIGN(RuleFeatureSet);
};
} // namespace blink
#endif // RuleFeatureSet_h