1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-16 20:05:07 +00:00

LibWeb: Add naive support for document.querySelectorAll()

This currently returns a JS::Array of elements matching a selector.
The more correct behavior would be to return a static NodeList, but as
we don't have NodeLists right now, that'll be a task for the future.
This commit is contained in:
Andreas Kling 2020-03-29 22:24:23 +02:00
parent c56acba75e
commit 0f7bcd4111
11 changed files with 182 additions and 78 deletions

View file

@ -170,78 +170,83 @@ void dump_tree(const LayoutNode& layout_node)
--indent;
}
void dump_selector(const Selector& selector)
{
dbgprintf(" Selector:\n");
for (auto& complex_selector : selector.complex_selectors()) {
dbgprintf(" ");
const char* relation_description = "";
switch (complex_selector.relation) {
case Selector::ComplexSelector::Relation::None:
break;
case Selector::ComplexSelector::Relation::ImmediateChild:
relation_description = "ImmediateChild";
break;
case Selector::ComplexSelector::Relation::Descendant:
relation_description = "Descendant";
break;
case Selector::ComplexSelector::Relation::AdjacentSibling:
relation_description = "AdjacentSibling";
break;
case Selector::ComplexSelector::Relation::GeneralSibling:
relation_description = "GeneralSibling";
break;
}
if (*relation_description)
dbgprintf("{%s} ", relation_description);
for (size_t i = 0; i < complex_selector.compound_selector.size(); ++i) {
auto& simple_selector = complex_selector.compound_selector[i];
const char* type_description = "Unknown";
switch (simple_selector.type) {
case Selector::SimpleSelector::Type::Invalid:
type_description = "Invalid";
break;
case Selector::SimpleSelector::Type::Universal:
type_description = "Universal";
break;
case Selector::SimpleSelector::Type::Id:
type_description = "Id";
break;
case Selector::SimpleSelector::Type::Class:
type_description = "Class";
break;
case Selector::SimpleSelector::Type::TagName:
type_description = "TagName";
break;
}
const char* attribute_match_type_description = "";
switch (simple_selector.attribute_match_type) {
case Selector::SimpleSelector::AttributeMatchType::None:
break;
case Selector::SimpleSelector::AttributeMatchType::HasAttribute:
attribute_match_type_description = "HasAttribute";
break;
case Selector::SimpleSelector::AttributeMatchType::ExactValueMatch:
attribute_match_type_description = "ExactValueMatch";
break;
}
dbgprintf("%s:%s", type_description, simple_selector.value.characters());
if (simple_selector.attribute_match_type != Selector::SimpleSelector::AttributeMatchType::None) {
dbgprintf(" [%s, name='%s', value='%s']", attribute_match_type_description, simple_selector.attribute_name.characters(), simple_selector.attribute_value.characters());
}
if (i != complex_selector.compound_selector.size() - 1)
dbgprintf(", ");
}
dbgprintf("\n");
}
}
void dump_rule(const StyleRule& rule)
{
dbgprintf("Rule:\n");
for (auto& selector : rule.selectors()) {
dbgprintf(" Selector:\n");
for (auto& complex_selector : selector.complex_selectors()) {
dbgprintf(" ");
const char* relation_description = "";
switch (complex_selector.relation) {
case Selector::ComplexSelector::Relation::None:
break;
case Selector::ComplexSelector::Relation::ImmediateChild:
relation_description = "ImmediateChild";
break;
case Selector::ComplexSelector::Relation::Descendant:
relation_description = "Descendant";
break;
case Selector::ComplexSelector::Relation::AdjacentSibling:
relation_description = "AdjacentSibling";
break;
case Selector::ComplexSelector::Relation::GeneralSibling:
relation_description = "GeneralSibling";
break;
}
if (*relation_description)
dbgprintf("{%s} ", relation_description);
for (size_t i = 0; i < complex_selector.compound_selector.size(); ++i) {
auto& simple_selector = complex_selector.compound_selector[i];
const char* type_description = "Unknown";
switch (simple_selector.type) {
case Selector::SimpleSelector::Type::Invalid:
type_description = "Invalid";
break;
case Selector::SimpleSelector::Type::Universal:
type_description = "Universal";
break;
case Selector::SimpleSelector::Type::Id:
type_description = "Id";
break;
case Selector::SimpleSelector::Type::Class:
type_description = "Class";
break;
case Selector::SimpleSelector::Type::TagName:
type_description = "TagName";
break;
}
const char* attribute_match_type_description = "";
switch (simple_selector.attribute_match_type) {
case Selector::SimpleSelector::AttributeMatchType::None:
break;
case Selector::SimpleSelector::AttributeMatchType::HasAttribute:
attribute_match_type_description = "HasAttribute";
break;
case Selector::SimpleSelector::AttributeMatchType::ExactValueMatch:
attribute_match_type_description = "ExactValueMatch";
break;
}
dbgprintf("%s:%s", type_description, simple_selector.value.characters());
if (simple_selector.attribute_match_type != Selector::SimpleSelector::AttributeMatchType::None) {
dbgprintf(" [%s, name='%s', value='%s']", attribute_match_type_description, simple_selector.attribute_name.characters(), simple_selector.attribute_value.characters());
}
if (i != complex_selector.compound_selector.size() - 1)
dbgprintf(", ");
}
dbgprintf("\n");
}
dump_selector(selector);
}
dbgprintf(" Declarations:\n");
for (auto& property : rule.declaration().properties()) {