2
0
Эх сурвалжийг харах

Remove pseudo class properties from element definition. This simplifies the code a whole lot, and makes fetching a new definition a lot faster. This means that we have to fetch new definitions more often (specifically, now also when we set a pseudo class), but despite this, the net performance gains are substantial. We could introduce flags to avoid this later.

Michael Ragazzon 6 жил өмнө
parent
commit
23e356ae4c

+ 0 - 2
Include/Rocket/Core/Element.h

@@ -630,7 +630,6 @@ private:
 	void DirtyStackingContext();
 
 	void DirtyStructure();
-	void DirtyParentStructure();
 	void UpdateStructure();
 
 	void DirtyTransformState(bool perspective_changed, bool transform_changed, bool parent_transform_changed);
@@ -722,7 +721,6 @@ private:
 	bool stacking_context_dirty;
 
 	bool structure_dirty;
-	bool parent_structure_dirty;
 
 	bool computed_values_are_default_initialized;
 	bool box_dirty;

+ 0 - 2
Include/Rocket/Core/StyleSheet.h

@@ -133,8 +133,6 @@ private:
 	NodeIndex complete_node_index;
 
 	typedef UnorderedMap< size_t, ElementDefinition* > ElementDefinitionCache;
-	// Index of element addresses to element definitions.
-	mutable ElementDefinitionCache address_cache;
 	// Index of node sets to element definitions.
 	mutable ElementDefinitionCache node_cache;
 };

+ 5 - 21
Source/Core/Element.cpp

@@ -148,7 +148,6 @@ transform_state(), transform_state_perspective_dirty(true), transform_state_tran
 	stacking_context_dirty = false;
 
 	structure_dirty = false;
-	parent_structure_dirty = false;
 
 	computed_values_are_default_initialized = true;
 	box_dirty = false;
@@ -1802,6 +1801,7 @@ void Element::OnPropertyChange(const PropertyNameList& changed_properties)
 		if (all_dirty || 
 			changed_properties.find(PropertyId::Display) != changed_properties.end())
 		{
+			// TODO: Is this really necessary. It has problems, because any change to definitions as a result of this will only be reflected on the next frame.
 			if (parent != NULL)
 				parent->DirtyStructure();
 		}
@@ -2292,33 +2292,17 @@ void Element::DirtyStackingContext()
 
 void Element::DirtyStructure()
 {
-	// Clear the cached owner document
 	structure_dirty = true;
 }
 
-void Element::DirtyParentStructure()
-{
-	parent_structure_dirty = true;
-}
-
 void Element::UpdateStructure()
 {
-	if (parent_structure_dirty)
+	if (structure_dirty)
 	{
-		// If children depend on structured selectors, they may need to be updated
-		const ElementDefinition* element_definition = GetStyle()->GetDefinition();
-		if (element_definition != NULL && element_definition->IsStructurallyVolatile())
-		{
-			GetStyle()->DirtyDefinition();
-		}
-	}
-	if (structure_dirty || parent_structure_dirty)
-	{
-		for (size_t i = 0; i < children.size(); ++i)
-			children[i]->DirtyParentStructure();
-
 		structure_dirty = false;
-		parent_structure_dirty = false;
+
+		// If this element or its children depend on structured selectors, they may need to be updated.
+		GetStyle()->DirtyDefinition();
 	}
 }
 

+ 3 - 170
Source/Core/ElementDefinition.cpp

@@ -35,7 +35,6 @@ namespace Core {
 
 ElementDefinition::ElementDefinition()
 {
-	structurally_volatile = false;
 }
 
 ElementDefinition::~ElementDefinition()
@@ -43,182 +42,24 @@ ElementDefinition::~ElementDefinition()
 }
 
 // Initialises the element definition from a list of style sheet nodes.
-void ElementDefinition::Initialise(const std::vector< const StyleSheetNode* >& style_sheet_nodes, const PseudoClassList& volatile_pseudo_classes, bool _structurally_volatile)
+void ElementDefinition::Initialise(const std::vector< const StyleSheetNode* >& style_sheet_nodes)
 {
-	// Set the volatile structure flag.
-	structurally_volatile = _structurally_volatile;
-
-	// Mark all the volatile pseudo-classes as structurally volatile.
-	for (const String& pseudo_name : volatile_pseudo_classes)
-		pseudo_class_volatility[pseudo_name] = STRUCTURE_VOLATILE;
-
-
 	// Merge the default (non-pseudo-class) properties.
 	for (size_t i = 0; i < style_sheet_nodes.size(); ++i)
 		properties.Merge(style_sheet_nodes[i]->GetProperties());
-
-
-	// Merge the pseudo-class properties.
-	for (size_t i = 0; i < style_sheet_nodes.size(); ++i)
-	{
-		PseudoClassPropertyMap pseudo_properties_map;
-		style_sheet_nodes[i]->GetPseudoClassProperties(pseudo_properties_map);
-		for (auto& pseudo_properties_pair : pseudo_properties_map)
-		{
-			const PseudoClassList& pseudo_classes = pseudo_properties_pair.first;
-			PropertyDictionary& pseudo_properties = pseudo_properties_pair.second;
-
-			// Search through all entries in this dictionary; we'll insert each one into our optimised list of
-			// pseudo-class properties.
-			for (auto& property_pair : pseudo_properties.GetProperties())
-			{
-				PropertyId property_id = property_pair.first;
-				const Property& property = property_pair.second;
-
-				// Skip this property if its specificity is lower than the base property's, as in
-				// this case it will never be used.
-				const Property* default_property = properties.GetProperty(property_id);
-				if (default_property && (default_property->specificity >= property.specificity))
-					continue;
-
-				auto it = pseudo_class_properties.find(property_id);
-				if (it == pseudo_class_properties.end())
-					pseudo_class_properties[property_id] = PseudoClassPropertyList(1, PseudoClassProperty(pseudo_classes, property));
-				else
-				{
-					PseudoClassPropertyList& pseudo_property_list = it->second;
-
-					// Find the location to insert this entry in the map, based on property priorities.
-					int index = 0;
-					while (index < (int)pseudo_property_list.size() && pseudo_property_list[index].second.specificity > property.specificity)
-						index++;
-
-					pseudo_property_list.insert(pseudo_property_list.begin() + index, PseudoClassProperty(pseudo_classes, property));
-				}
-			}
-		}
-	}
 }
 
 // Returns a specific property from the element definition's base properties.
-const Property* ElementDefinition::GetProperty(PropertyId id, const PseudoClassList& pseudo_classes) const
+const Property* ElementDefinition::GetProperty(PropertyId id) const
 {
-	// Find a pseudo-class override for this property.
-	if(pseudo_class_properties.size() > 0 && pseudo_classes.size() > 0)
-	{
-		PseudoClassPropertyDictionary::const_iterator property_iterator = pseudo_class_properties.find(id);
-		if (property_iterator != pseudo_class_properties.end())
-		{
-			const PseudoClassPropertyList& property_list = (*property_iterator).second;
-			for (size_t i = 0; i < property_list.size(); ++i)
-			{
-				if (!IsPseudoClassRuleApplicable(property_list[i].first, pseudo_classes))
-					continue;
-
-				return &property_list[i].second;
-			}
-		}
-	}
-
 	return properties.GetProperty(id);
 }
 
 // Returns the list of properties this element definition defines for an element with the given set of pseudo-classes.
-void ElementDefinition::GetDefinedProperties(PropertyNameList& property_names, const PseudoClassList& pseudo_classes) const
+void ElementDefinition::GetDefinedProperties(PropertyNameList& property_names) const
 {
 	for (PropertyMap::const_iterator i = properties.GetProperties().begin(); i != properties.GetProperties().end(); ++i)
 		property_names.insert((*i).first);
-
-	for (const auto& pseudo_class_properties_pair : pseudo_class_properties)
-	{
-		PropertyId property_id = pseudo_class_properties_pair.first;
-
-		// If this property is already in the default dictionary, don't bother checking for it here.
-		if (property_names.find(property_id) != property_names.end())
-			continue;
-
-		const PseudoClassPropertyList& property_list = pseudo_class_properties_pair.second;
-
-		// Search through all the pseudo-class combinations that have a definition for this property; if the calling
-		// element matches at least one of them, then add it to the list.
-		bool property_defined = false;
-		for (size_t j = 0; j < property_list.size(); ++j)
-		{
-			if (IsPseudoClassRuleApplicable(property_list[j].first, pseudo_classes))
-			{
-				property_defined = true;
-				break;
-			}
-		}
-
-		if (property_defined)
-			property_names.insert(property_id);
-	}
-}
-
-// Returns the list of properties this element definition has explicit definitions for involving the given
-// pseudo-class.
-void ElementDefinition::GetDefinedProperties(PropertyNameList& property_names, const PseudoClassList& pseudo_classes, const String& pseudo_class) const
-{
-	for (const auto& pseudo_class_properties_pair : pseudo_class_properties)
-	{
-		PropertyId property_id = pseudo_class_properties_pair.first;
-
-		// If this property has already been found, don't bother checking for it again.
-		if (property_names.find(property_id) != property_names.end())
-			continue;
-
-		const PseudoClassPropertyList& property_list = pseudo_class_properties_pair.second;
-
-		bool property_defined = false;
-		for (size_t j = 0; j < property_list.size(); ++j)
-		{
-			bool rule_valid = true;
-			bool found_toggled_pseudo_class = false;
-
-			const PseudoClassList& rule_pseudo_classes = property_list[j].first;
-			for (const String& rule_pseudo_class : rule_pseudo_classes)
-			{
-				if (rule_pseudo_class == pseudo_class)
-				{
-					found_toggled_pseudo_class = true;
-					continue;
-				}
-
-				if (pseudo_classes.count(rule_pseudo_class) == 0)
-				{			
-					rule_valid = false;
-					break;
-				}
-			}
-
-			if (rule_valid &&
-				found_toggled_pseudo_class)
-			{
-				property_defined = true;
-				break;
-			}
-		}
-
-		if (property_defined)
-			property_names.insert(property_id);
-	}
-}
-
-// Returns the volatility of a pseudo-class.
-ElementDefinition::PseudoClassVolatility ElementDefinition::GetPseudoClassVolatility(const String& pseudo_class) const
-{
-	PseudoClassVolatilityMap::const_iterator i = pseudo_class_volatility.find(pseudo_class);
-	if (i == pseudo_class_volatility.end())
-		return STABLE;
-	else
-		return i->second;
-}
-
-// Returns true if this definition is built from nodes using structural selectors.
-bool ElementDefinition::IsStructurallyVolatile() const
-{
-	return structurally_volatile;
 }
 
 // Destroys the definition.
@@ -227,14 +68,6 @@ void ElementDefinition::OnReferenceDeactivate()
 	delete this;
 }
 
-// Returns true if the pseudo-class requirement of a rule is met by a list of an element's pseudo-classes.
-bool ElementDefinition::IsPseudoClassRuleApplicable(const PseudoClassList& rule_pseudo_classes, const PseudoClassList& element_pseudo_classes)
-{
-	// The rule pseudo classes must be a subset of the element pseudo classes
-	// Note, requires PseudoClassList to be an @ordered container.
-	bool result = std::includes(element_pseudo_classes.begin(), element_pseudo_classes.end(), rule_pseudo_classes.begin(), rule_pseudo_classes.end());
-	return result;
-}
 
 }
 }

+ 3 - 33
Source/Core/ElementDefinition.h

@@ -55,59 +55,29 @@ public:
 	virtual ~ElementDefinition();
 
 	/// Initialises the element definition from a list of style sheet nodes.
-	void Initialise(const std::vector< const StyleSheetNode* >& style_sheet_nodes, const PseudoClassList& volatile_pseudo_classes, bool structurally_volatile);
+	void Initialise(const std::vector< const StyleSheetNode* >& style_sheet_nodes);
 
 	/// Returns a specific property from the element definition's base properties.
 	/// @param[in] name The name of the property to return.
 	/// @param[in] pseudo_classes The pseudo-classes currently active on the calling element.
 	/// @return The property defined against the give name, or NULL if no such property was found.
-	const Property* GetProperty(PropertyId id, const PseudoClassList& pseudo_classes) const;
+	const Property* GetProperty(PropertyId id) const;
 
 	/// Returns the list of properties this element definition defines for an element with the given set of
 	/// pseudo-classes.
 	/// @param[out] property_names The list to store the defined properties in.
 	/// @param[in] pseudo_classes The pseudo-classes defined on the querying element.
-	void GetDefinedProperties(PropertyNameList& property_names, const PseudoClassList& pseudo_classes) const;
-	/// Returns the list of properties this element definition has explicit definitions for involving the given
-	/// pseudo-class.
-	/// @param[out] property_names The list of store the newly defined / undefined properties in.
-	/// @param[in] pseudo_classes The list of pseudo-classes currently set on the element (post-change).
-	/// @param[in] pseudo_class The pseudo-class that was just activated or deactivated.
-	void GetDefinedProperties(PropertyNameList& property_names, const PseudoClassList& pseudo_classes, const String& pseudo_class) const;
-
-	/// Returns the volatility of a pseudo-class.
-	/// @param[in] pseudo_class The name of the pseudo-class to check for volatility.
-	/// @return The volatility of the pseudo-class.
-	PseudoClassVolatility GetPseudoClassVolatility(const String& pseudo_class) const;
-
-	/// Returns true if this definition is built from nodes using structural selectors, and therefore is reliant on
-	/// siblings remaining stable.
-	/// @return True if this definition is structurally volatile.
-	bool IsStructurallyVolatile() const;
+	void GetDefinedProperties(PropertyNameList& property_names) const;
 
 	const PropertyDictionary& GetProperties() const { return properties; }
-	const PseudoClassPropertyDictionary& GetPseudoClassProperties() const { return pseudo_class_properties; }
-
-	/// Returns true if the pseudo-class requirement of a rule is met by a list of an element's pseudo-classes.
-	static bool IsPseudoClassRuleApplicable(const PseudoClassList& rule_pseudo_classes, const PseudoClassList& element_pseudo_classes);
 
 protected:
 	/// Destroys the definition.
 	void OnReferenceDeactivate();
 
 private:
-	typedef SmallUnorderedMap< String, PseudoClassVolatility > PseudoClassVolatilityMap;
-
 	// The attributes for the default state of the element, with no pseudo-classes.
 	PropertyDictionary properties;
-	// The overridden attributes for the element's pseudo-classes.
-	PseudoClassPropertyDictionary pseudo_class_properties;
-
-	// The list of volatile pseudo-classes in this definition, and how volatile they are.
-	PseudoClassVolatilityMap pseudo_class_volatility;
-
-	// True if this definition has the potential to change as sibling elements are added or removed.
-	bool structurally_volatile;
 };
 
 }

+ 18 - 40
Source/Core/ElementStyle.cpp

@@ -71,7 +71,7 @@ const ElementDefinition* ElementStyle::GetDefinition() const
 }
 
 // Returns one of this element's properties.
-const Property* ElementStyle::GetLocalProperty(PropertyId id, const PropertyDictionary& local_properties, const ElementDefinition* definition, const PseudoClassList& pseudo_classes)
+const Property* ElementStyle::GetLocalProperty(PropertyId id, const PropertyDictionary& local_properties, const ElementDefinition* definition)
 {
 	// Check for overriding local properties.
 	const Property* property = local_properties.GetProperty(id);
@@ -80,15 +80,15 @@ const Property* ElementStyle::GetLocalProperty(PropertyId id, const PropertyDict
 
 	// Check for a property defined in an RCSS rule.
 	if (definition)
-		return definition->GetProperty(id, pseudo_classes);
+		return definition->GetProperty(id);
 
 	return nullptr;
 }
 
 // Returns one of this element's properties.
-const Property* ElementStyle::GetProperty(PropertyId id, const Element* element, const PropertyDictionary& local_properties, const ElementDefinition* definition, const PseudoClassList& pseudo_classes)
+const Property* ElementStyle::GetProperty(PropertyId id, const Element* element, const PropertyDictionary& local_properties, const ElementDefinition* definition)
 {
-	const Property* local_property = GetLocalProperty(id, local_properties, definition, pseudo_classes);
+	const Property* local_property = GetLocalProperty(id, local_properties, definition);
 	if (local_property)
 		return local_property;
 
@@ -117,14 +117,13 @@ const Property* ElementStyle::GetProperty(PropertyId id, const Element* element,
 
 // Apply transition to relevant properties if a transition is defined on element.
 // Properties that are part of a transition are removed from the properties list.
-void ElementStyle::TransitionPropertyChanges(Element* element, PropertyNameList& properties, const PropertyDictionary& local_properties, const ElementDefinition* old_definition, const ElementDefinition* new_definition,
-	const PseudoClassList& pseudo_classes_before, const PseudoClassList& pseudo_classes_after)
+void ElementStyle::TransitionPropertyChanges(Element* element, PropertyNameList& properties, const PropertyDictionary& local_properties, const ElementDefinition* old_definition, const ElementDefinition* new_definition)
 {
 	ROCKET_ASSERT(element);
 	if (!old_definition || !new_definition || properties.empty())
 		return;
 
-	if (const Property* transition_property = GetLocalProperty(PropertyId::Transition, local_properties, new_definition, pseudo_classes_after))
+	if (const Property* transition_property = GetLocalProperty(PropertyId::Transition, local_properties, new_definition))
 	{
 		auto transition_list = transition_property->Get<TransitionList>();
 
@@ -134,8 +133,8 @@ void ElementStyle::TransitionPropertyChanges(Element* element, PropertyNameList&
 
 			auto add_transition = [&](const Transition& transition) {
 				bool transition_added = false;
-				const Property* start_value = GetProperty(transition.id, element, local_properties, old_definition, pseudo_classes_before);
-				const Property* target_value = GetProperty(transition.id, element, empty_properties, new_definition, pseudo_classes_after);
+				const Property* start_value = GetProperty(transition.id, element, local_properties, old_definition);
+				const Property* target_value = GetProperty(transition.id, element, empty_properties, new_definition);
 				if (start_value && target_value && (*start_value != *target_value))
 					transition_added = element->StartTransition(transition, *start_value, *target_value);
 				return transition_added;
@@ -199,12 +198,12 @@ void ElementStyle::UpdateDefinition()
 			PropertyNameList properties;
 			
 			if (definition)
-				definition->GetDefinedProperties(properties, pseudo_classes);
+				definition->GetDefinedProperties(properties);
 
 			if (new_definition)
-				new_definition->GetDefinedProperties(properties, pseudo_classes);
+				new_definition->GetDefinedProperties(properties);
 
-			TransitionPropertyChanges(element, properties, local_properties, definition, new_definition, pseudo_classes, pseudo_classes);
+			TransitionPropertyChanges(element, properties, local_properties, definition, new_definition);
 
 			if (definition)
 				definition->RemoveReference();
@@ -220,8 +219,9 @@ void ElementStyle::UpdateDefinition()
 			new_definition->RemoveReference();
 		}
 
-		if (definition_changed)
-			DirtyChildDefinitions();
+		// Even if the definition was not changed, the child definitions may have changed as a result of anything that
+		// could change the definition of this element, such as a new pseudo class.
+		DirtyChildDefinitions();
 	}
 }
 
@@ -241,29 +241,7 @@ void ElementStyle::SetPseudoClass(const String& pseudo_class, bool activate)
 
 	if (changed)
 	{
-		if (definition)
-		{
-			PropertyNameList properties;
-			definition->GetDefinedProperties(properties, pseudo_classes, pseudo_class);
-
-			TransitionPropertyChanges(element, properties, local_properties, definition, definition, pseudo_classes_before, pseudo_classes);
-
-			DirtyProperties(properties);
-
-			switch (definition->GetPseudoClassVolatility(pseudo_class))
-			{
-				case ElementDefinition::FONT_VOLATILE:
-					element->DirtyFont();
-					break;
-
-				case ElementDefinition::STRUCTURE_VOLATILE:
-					DirtyChildDefinitions();
-					break;
-
-				default:
-					break;
-			}
-		}
+		DirtyDefinition();
 	}
 }
 
@@ -361,13 +339,13 @@ void ElementStyle::RemoveProperty(PropertyId id)
 // Returns one of this element's properties.
 const Property* ElementStyle::GetProperty(PropertyId id) const
 {
-	return GetProperty(id, element, local_properties, definition, pseudo_classes);
+	return GetProperty(id, element, local_properties, definition);
 }
 
 // Returns one of this element's properties.
 const Property* ElementStyle::GetLocalProperty(PropertyId id) const
 {
-	return GetLocalProperty(id, local_properties, definition, pseudo_classes);
+	return GetLocalProperty(id, local_properties, definition);
 }
 
 const PropertyMap& ElementStyle::GetLocalStyleProperties() const
@@ -511,7 +489,7 @@ PropertiesIterator ElementStyle::Iterate() const {
 	PropertyMap::const_iterator it_base{}, it_base_end{};
 	if (definition)
 	{
-		const PseudoClassPropertyDictionary& pseudo = definition->GetPseudoClassProperties();
+		static const PseudoClassPropertyDictionary pseudo;
 		const PropertyMap& base = definition->GetProperties().GetProperties();
 		it_pseudo = pseudo.begin();
 		it_pseudo_end = pseudo.end();

+ 3 - 4
Source/Core/ElementStyle.h

@@ -142,10 +142,9 @@ private:
 	// Sets a list of our potentially inherited properties as dirtied by an ancestor.
 	void DirtyInheritedProperties(const PropertyNameList& properties);
 
-	static const Property* GetLocalProperty(PropertyId id, const PropertyDictionary & local_properties, const ElementDefinition * definition, const PseudoClassList & pseudo_classes);
-	static const Property* GetProperty(PropertyId id, const Element * element, const PropertyDictionary & local_properties, const ElementDefinition * definition, const PseudoClassList & pseudo_classes);
-	static void TransitionPropertyChanges(Element * element, PropertyNameList & properties, const PropertyDictionary & local_properties, const ElementDefinition * old_definition, const ElementDefinition * new_definition,
-		const PseudoClassList & pseudo_classes_before, const PseudoClassList & pseudo_classes_after);
+	static const Property* GetLocalProperty(PropertyId id, const PropertyDictionary & local_properties, const ElementDefinition * definition);
+	static const Property* GetProperty(PropertyId id, const Element * element, const PropertyDictionary & local_properties, const ElementDefinition * definition);
+	static void TransitionPropertyChanges(Element * element, PropertyNameList & properties, const PropertyDictionary & local_properties, const ElementDefinition * old_definition, const ElementDefinition * new_definition);
 
 	// Element these properties belong to
 	Element* element;

+ 0 - 10
Source/Core/PropertiesIterator.h

@@ -117,16 +117,6 @@ private:
 		// Iterate over all the pseudo classes and match the applicable rules
 		for (; it_pseudo != it_pseudo_end; ++it_pseudo)
 		{
-			const PseudoClassPropertyList& pseudo_list = it_pseudo->second;
-			for (; i_pseudo_class < pseudo_list.size(); ++i_pseudo_class)
-			{
-				if (ElementDefinition::IsPseudoClassRuleApplicable(pseudo_list[i_pseudo_class].first, *element_pseudo_classes))
-				{
-					if (IsDirtyRemove(it_pseudo->first))
-						return;
-				}
-			}
-			i_pseudo_class = 0;
 		}
 
 		for (; it_base != it_base_end; ++it_base)

+ 3 - 41
Source/Core/StyleSheet.cpp

@@ -62,10 +62,6 @@ StyleSheet::~StyleSheet()
 {
 	delete root;
 
-	// Release our reference count on the cached element definitions.
-	for (ElementDefinitionCache::iterator cache_iterator = address_cache.begin(); cache_iterator != address_cache.end(); ++cache_iterator)
-		(*cache_iterator).second->RemoveReference();
-
 	for (ElementDefinitionCache::iterator cache_iterator = node_cache.begin(); cache_iterator != node_cache.end(); ++cache_iterator)
 		(*cache_iterator).second->RemoveReference();
 }
@@ -257,38 +253,8 @@ ElementDefinition* StyleSheet::GetElementDefinition(const Element* element) cons
 
 	std::sort(applicable_nodes.begin(), applicable_nodes.end(), StyleSheetNodeSort);
 
-	// Compile the list of volatile pseudo-classes for this element definition.
-	PseudoClassList volatile_pseudo_classes;
-	bool structurally_volatile = false;
-
-	for (int i = 0; i < 2; ++i)
-	{
-		auto it_nodes = complete_node_index.find(tags[i]);
-		if (it_nodes != complete_node_index.end())
-		{
-			const NodeList& nodes = it_nodes->second;
-
-			// See if we satisfy all of the parenting requirements for each of these nodes (as in the previous loop).
-			for (StyleSheetNode* node : nodes)
-			{
-				structurally_volatile |= node->IsStructurallyVolatile();
-
-				if (node->IsApplicable(element))
-				{
-					std::vector< const StyleSheetNode* > volatile_nodes;
-					node->GetApplicableDescendants(volatile_nodes, element);
-
-					for (size_t i = 0; i < volatile_nodes.size(); ++i)
-						volatile_nodes[i]->GetVolatilePseudoClasses(volatile_pseudo_classes);
-				}
-			}
-		}
-	}
-
 	// If this element definition won't actually store any information, don't bother with it.
-	if (applicable_nodes.empty() &&
-		volatile_pseudo_classes.empty() &&
-		!structurally_volatile)
+	if (applicable_nodes.empty())
 		return NULL;
 
 	// Check if this puppy has already been cached in the node index; it may be that it has already been created by an
@@ -296,8 +262,6 @@ ElementDefinition* StyleSheet::GetElementDefinition(const Element* element) cons
 	size_t seed = 0;
 	for (const auto* node : applicable_nodes)
 		hash_combine(seed, node);
-	for (const String& str : volatile_pseudo_classes)
-		hash_combine(seed, str);
 
 	auto cache_iterator = node_cache.find(seed);
 	if (cache_iterator != node_cache.end())
@@ -311,11 +275,9 @@ ElementDefinition* StyleSheet::GetElementDefinition(const Element* element) cons
 	// Create the new definition and add it to our cache. One reference count is added, bringing the total to two; one
 	// for the element that requested it, and one for the cache.
 	ElementDefinition* new_definition = new ElementDefinition();
-	new_definition->Initialise(applicable_nodes, volatile_pseudo_classes, structurally_volatile);
+	new_definition->Initialise(applicable_nodes);
+
 
-	// Add to the address cache.
-//	address_cache[element_address] = new_definition;
-//	new_definition->AddReference();
 
 	// Add to the node cache.
 	node_cache[seed] = new_definition;

+ 3 - 8
Source/Core/StyleSheetNode.cpp

@@ -486,18 +486,13 @@ void StyleSheetNode::GetApplicableDescendants(std::vector< const StyleSheetNode*
 		break;
 	}
 
-	if (properties.GetNumProperties() > 0 ||
-		!children[PSEUDO_CLASS].empty())
+	if (properties.GetNumProperties() > 0)
 		applicable_nodes.push_back(this);
 
 	for (int i = CLASS; i < NUM_NODE_TYPES; i++)
 	{
-		// Don't recurse into pseudo-classes; they can't be built into the root definition.
-		if (i == PSEUDO_CLASS)
-			continue;
-
-		for (NodeMap::const_iterator j = children[i].begin(); j != children[i].end(); ++j)
-			(*j).second->GetApplicableDescendants(applicable_nodes, element);
+		for (auto& child_tag_node : children[i])
+			child_tag_node.second->GetApplicableDescendants(applicable_nodes, element);
 	}
 }