mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 02:57:36 +00:00
LibWeb: Cache lowercased names in SimpleSelector
When matching selectors in HTML documents, we know that all the elements have lowercase local names already (the parser makes sure of this.) Style sheets still need to remember the original name strings, in case we want to match against non-HTML content like XML/SVG. To make the common HTML case faster, we now cache a lowercase version of the name with each type/class/id SimpleSelector. This makes tag type checks O(1) instead of O(n).
This commit is contained in:
parent
d9c64ee876
commit
1dd4e2dc87
4 changed files with 24 additions and 10 deletions
|
@ -695,7 +695,7 @@ Parser::ParseErrorOr<Optional<Selector::SimpleSelector>> Parser::parse_simple_se
|
||||||
}
|
}
|
||||||
return Selector::SimpleSelector {
|
return Selector::SimpleSelector {
|
||||||
.type = Selector::SimpleSelector::Type::Class,
|
.type = Selector::SimpleSelector::Type::Class,
|
||||||
.value = FlyString { class_name_value.token().ident() }
|
.value = Selector::SimpleSelector::Name { class_name_value.token().ident() }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
case '>':
|
case '>':
|
||||||
|
@ -719,13 +719,13 @@ Parser::ParseErrorOr<Optional<Selector::SimpleSelector>> Parser::parse_simple_se
|
||||||
}
|
}
|
||||||
return Selector::SimpleSelector {
|
return Selector::SimpleSelector {
|
||||||
.type = Selector::SimpleSelector::Type::Id,
|
.type = Selector::SimpleSelector::Type::Id,
|
||||||
.value = FlyString { first_value.token().hash_value() }
|
.value = Selector::SimpleSelector::Name { first_value.token().hash_value() }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if (first_value.is(Token::Type::Ident)) {
|
if (first_value.is(Token::Type::Ident)) {
|
||||||
return Selector::SimpleSelector {
|
return Selector::SimpleSelector {
|
||||||
.type = Selector::SimpleSelector::Type::TagName,
|
.type = Selector::SimpleSelector::Type::TagName,
|
||||||
.value = FlyString { first_value.token().ident() }
|
.value = Selector::SimpleSelector::Name { first_value.token().ident() }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if (first_value.is_block() && first_value.block().is_square())
|
if (first_value.is_block() && first_value.block().is_square())
|
||||||
|
|
|
@ -142,8 +142,19 @@ public:
|
||||||
CaseType case_type;
|
CaseType case_type;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Name {
|
||||||
|
Name(FlyString n)
|
||||||
|
: name(move(n))
|
||||||
|
, lowercase_name(name.to_lowercase())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
FlyString name;
|
||||||
|
FlyString lowercase_name;
|
||||||
|
};
|
||||||
|
|
||||||
Type type;
|
Type type;
|
||||||
Variant<Empty, Attribute, PseudoClass, PseudoElement, FlyString> value {};
|
Variant<Empty, Attribute, PseudoClass, PseudoElement, Name> value {};
|
||||||
|
|
||||||
Attribute const& attribute() const { return value.get<Attribute>(); }
|
Attribute const& attribute() const { return value.get<Attribute>(); }
|
||||||
Attribute& attribute() { return value.get<Attribute>(); }
|
Attribute& attribute() { return value.get<Attribute>(); }
|
||||||
|
@ -151,8 +162,11 @@ public:
|
||||||
PseudoClass& pseudo_class() { return value.get<PseudoClass>(); }
|
PseudoClass& pseudo_class() { return value.get<PseudoClass>(); }
|
||||||
PseudoElement const& pseudo_element() const { return value.get<PseudoElement>(); }
|
PseudoElement const& pseudo_element() const { return value.get<PseudoElement>(); }
|
||||||
PseudoElement& pseudo_element() { return value.get<PseudoElement>(); }
|
PseudoElement& pseudo_element() { return value.get<PseudoElement>(); }
|
||||||
FlyString const& name() const { return value.get<FlyString>(); }
|
|
||||||
FlyString& name() { return value.get<FlyString>(); }
|
FlyString const& name() const { return value.get<Name>().name; }
|
||||||
|
FlyString& name() { return value.get<Name>().name; }
|
||||||
|
FlyString const& lowercase_name() const { return value.get<Name>().lowercase_name; }
|
||||||
|
FlyString& lowercase_name() { return value.get<Name>().lowercase_name; }
|
||||||
|
|
||||||
String serialize() const;
|
String serialize() const;
|
||||||
};
|
};
|
||||||
|
|
|
@ -353,9 +353,9 @@ static inline bool matches(CSS::Selector::SimpleSelector const& component, DOM::
|
||||||
return element.has_class(component.name());
|
return element.has_class(component.name());
|
||||||
case CSS::Selector::SimpleSelector::Type::TagName:
|
case CSS::Selector::SimpleSelector::Type::TagName:
|
||||||
// See https://html.spec.whatwg.org/multipage/semantics-other.html#case-sensitivity-of-selectors
|
// See https://html.spec.whatwg.org/multipage/semantics-other.html#case-sensitivity-of-selectors
|
||||||
if (is<HTML::HTMLElement>(element) && element.document().document_type() != DOM::Document::Type::XML)
|
if (element.document().document_type() == DOM::Document::Type::HTML)
|
||||||
return component.name().equals_ignoring_case(element.local_name());
|
return component.lowercase_name() == element.local_name();
|
||||||
return component.name() == element.local_name();
|
return component.name().equals_ignoring_case(element.local_name());
|
||||||
case CSS::Selector::SimpleSelector::Type::Attribute:
|
case CSS::Selector::SimpleSelector::Type::Attribute:
|
||||||
return matches_attribute(component.attribute(), element);
|
return matches_attribute(component.attribute(), element);
|
||||||
case CSS::Selector::SimpleSelector::Type::PseudoClass:
|
case CSS::Selector::SimpleSelector::Type::PseudoClass:
|
||||||
|
|
|
@ -372,7 +372,7 @@ void dump_selector(StringBuilder& builder, CSS::Selector const& selector)
|
||||||
|
|
||||||
builder.appendff("{}:", type_description);
|
builder.appendff("{}:", type_description);
|
||||||
// FIXME: This is goofy
|
// FIXME: This is goofy
|
||||||
if (simple_selector.value.has<FlyString>())
|
if (simple_selector.value.has<CSS::Selector::SimpleSelector::Name>())
|
||||||
builder.append(simple_selector.name());
|
builder.append(simple_selector.name());
|
||||||
|
|
||||||
if (simple_selector.type == CSS::Selector::SimpleSelector::Type::PseudoClass) {
|
if (simple_selector.type == CSS::Selector::SimpleSelector::Type::PseudoClass) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue