Selector.cpp 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712
  1. /*
  2. * Copyright (c) 2018-2020, Andreas Kling <andreas@ladybird.org>
  3. * Copyright (c) 2021-2024, Sam Atkins <sam@ladybird.org>
  4. *
  5. * SPDX-License-Identifier: BSD-2-Clause
  6. */
  7. #include "Selector.h"
  8. #include <AK/GenericShorthands.h>
  9. #include <LibWeb/CSS/Serialize.h>
  10. namespace Web::CSS {
  11. static bool component_value_contains_nesting_selector(Parser::ComponentValue const& component_value)
  12. {
  13. if (component_value.is_delim('&'))
  14. return true;
  15. if (component_value.is_block()) {
  16. for (auto const& child_value : component_value.block().value) {
  17. if (component_value_contains_nesting_selector(child_value))
  18. return true;
  19. }
  20. }
  21. if (component_value.is_function()) {
  22. for (auto const& child_value : component_value.function().value) {
  23. if (component_value_contains_nesting_selector(child_value))
  24. return true;
  25. }
  26. }
  27. return false;
  28. }
  29. Selector::Selector(Vector<CompoundSelector>&& compound_selectors)
  30. : m_compound_selectors(move(compound_selectors))
  31. {
  32. // FIXME: This assumes that only one pseudo-element is allowed in a selector, and that it appears at the end.
  33. // This is not true in Selectors-4!
  34. if (!m_compound_selectors.is_empty()) {
  35. for (auto const& simple_selector : m_compound_selectors.last().simple_selectors) {
  36. if (simple_selector.type == SimpleSelector::Type::PseudoElement) {
  37. m_pseudo_element = simple_selector.pseudo_element();
  38. break;
  39. }
  40. }
  41. }
  42. // https://drafts.csswg.org/css-nesting-1/#contain-the-nesting-selector
  43. // "A selector is said to contain the nesting selector if, when it was parsed as any type of selector,
  44. // a <delim-token> with the value "&" (U+0026 AMPERSAND) was encountered."
  45. for (auto const& compound_selector : m_compound_selectors) {
  46. for (auto const& simple_selector : compound_selector.simple_selectors) {
  47. if (simple_selector.type == SimpleSelector::Type::Nesting) {
  48. m_contains_the_nesting_selector = true;
  49. break;
  50. }
  51. if (simple_selector.type == SimpleSelector::Type::PseudoClass) {
  52. for (auto const& child_selector : simple_selector.pseudo_class().argument_selector_list) {
  53. if (child_selector->contains_the_nesting_selector()) {
  54. m_contains_the_nesting_selector = true;
  55. break;
  56. }
  57. }
  58. if (m_contains_the_nesting_selector)
  59. break;
  60. }
  61. if (simple_selector.type == SimpleSelector::Type::Invalid) {
  62. auto& invalid = simple_selector.value.get<SimpleSelector::Invalid>();
  63. for (auto& item : invalid.component_values) {
  64. if (component_value_contains_nesting_selector(item)) {
  65. m_contains_the_nesting_selector = true;
  66. break;
  67. }
  68. }
  69. if (m_contains_the_nesting_selector)
  70. break;
  71. }
  72. }
  73. if (m_contains_the_nesting_selector)
  74. break;
  75. }
  76. collect_ancestor_hashes();
  77. }
  78. void Selector::collect_ancestor_hashes()
  79. {
  80. size_t next_hash_index = 0;
  81. auto append_unique_hash = [&](u32 hash) -> bool {
  82. if (next_hash_index >= m_ancestor_hashes.size())
  83. return true;
  84. for (size_t i = 0; i < next_hash_index; ++i) {
  85. if (m_ancestor_hashes[i] == hash)
  86. return false;
  87. }
  88. m_ancestor_hashes[next_hash_index++] = hash;
  89. return false;
  90. };
  91. auto last_combinator = m_compound_selectors.last().combinator;
  92. for (ssize_t compound_selector_index = static_cast<ssize_t>(m_compound_selectors.size()) - 2; compound_selector_index >= 0; --compound_selector_index) {
  93. auto const& compound_selector = m_compound_selectors[compound_selector_index];
  94. if (last_combinator == Combinator::Descendant || last_combinator == Combinator::ImmediateChild) {
  95. for (auto const& simple_selector : compound_selector.simple_selectors) {
  96. switch (simple_selector.type) {
  97. case SimpleSelector::Type::Id:
  98. case SimpleSelector::Type::Class:
  99. if (append_unique_hash(simple_selector.name().hash()))
  100. return;
  101. break;
  102. case SimpleSelector::Type::TagName:
  103. if (append_unique_hash(simple_selector.qualified_name().name.name.hash()))
  104. return;
  105. break;
  106. case SimpleSelector::Type::Attribute:
  107. if (append_unique_hash(simple_selector.attribute().qualified_name.name.name.hash()))
  108. return;
  109. break;
  110. default:
  111. break;
  112. }
  113. }
  114. }
  115. last_combinator = compound_selector.combinator;
  116. }
  117. for (size_t i = next_hash_index; i < m_ancestor_hashes.size(); ++i)
  118. m_ancestor_hashes[i] = 0;
  119. }
  120. // https://www.w3.org/TR/selectors-4/#specificity-rules
  121. u32 Selector::specificity() const
  122. {
  123. if (m_specificity.has_value())
  124. return *m_specificity;
  125. constexpr u32 ids_shift = 16;
  126. constexpr u32 classes_shift = 8;
  127. constexpr u32 tag_names_shift = 0;
  128. constexpr u32 ids_mask = 0xff << ids_shift;
  129. constexpr u32 classes_mask = 0xff << classes_shift;
  130. constexpr u32 tag_names_mask = 0xff << tag_names_shift;
  131. u32 ids = 0;
  132. u32 classes = 0;
  133. u32 tag_names = 0;
  134. auto count_specificity_of_most_complex_selector = [&](auto& selector_list) {
  135. u32 max_selector_list_argument_specificity = 0;
  136. for (auto const& complex_selector : selector_list) {
  137. max_selector_list_argument_specificity = max(max_selector_list_argument_specificity, complex_selector->specificity());
  138. }
  139. u32 child_ids = (max_selector_list_argument_specificity & ids_mask) >> ids_shift;
  140. u32 child_classes = (max_selector_list_argument_specificity & classes_mask) >> classes_shift;
  141. u32 child_tag_names = (max_selector_list_argument_specificity & tag_names_mask) >> tag_names_shift;
  142. ids += child_ids;
  143. classes += child_classes;
  144. tag_names += child_tag_names;
  145. };
  146. for (auto& list : m_compound_selectors) {
  147. for (auto& simple_selector : list.simple_selectors) {
  148. switch (simple_selector.type) {
  149. case SimpleSelector::Type::Id:
  150. // count the number of ID selectors in the selector (= A)
  151. ++ids;
  152. break;
  153. case SimpleSelector::Type::Class:
  154. case SimpleSelector::Type::Attribute:
  155. // count the number of class selectors, attributes selectors, and pseudo-classes in the selector (= B)
  156. ++classes;
  157. break;
  158. case SimpleSelector::Type::PseudoClass: {
  159. auto& pseudo_class = simple_selector.pseudo_class();
  160. switch (pseudo_class.type) {
  161. case PseudoClass::Has:
  162. case PseudoClass::Is:
  163. case PseudoClass::Not: {
  164. // The specificity of an :is(), :not(), or :has() pseudo-class is replaced by the
  165. // specificity of the most specific complex selector in its selector list argument.
  166. count_specificity_of_most_complex_selector(pseudo_class.argument_selector_list);
  167. break;
  168. }
  169. case PseudoClass::NthChild:
  170. case PseudoClass::NthLastChild: {
  171. // Analogously, the specificity of an :nth-child() or :nth-last-child() selector
  172. // is the specificity of the pseudo class itself (counting as one pseudo-class selector)
  173. // plus the specificity of the most specific complex selector in its selector list argument (if any).
  174. ++classes;
  175. count_specificity_of_most_complex_selector(pseudo_class.argument_selector_list);
  176. break;
  177. }
  178. case PseudoClass::Where:
  179. // The specificity of a :where() pseudo-class is replaced by zero.
  180. break;
  181. default:
  182. ++classes;
  183. break;
  184. }
  185. break;
  186. }
  187. case SimpleSelector::Type::TagName:
  188. case SimpleSelector::Type::PseudoElement:
  189. // count the number of type selectors and pseudo-elements in the selector (= C)
  190. ++tag_names;
  191. break;
  192. case SimpleSelector::Type::Universal:
  193. // ignore the universal selector
  194. break;
  195. case SimpleSelector::Type::Nesting:
  196. // "The specificity of the nesting selector is equal to the largest specificity among the complex selectors in the parent style rule’s selector list (identical to the behavior of :is()), or zero if no such selector list exists."
  197. // - https://drafts.csswg.org/css-nesting/#ref-for-specificity
  198. // The parented case is handled by replacing & with :is().
  199. // So if we got here, the specificity is 0.
  200. break;
  201. case SimpleSelector::Type::Invalid:
  202. // Ignore invalid selectors
  203. break;
  204. }
  205. }
  206. }
  207. // Due to storage limitations, implementations may have limitations on the size of A, B, or C.
  208. // If so, values higher than the limit must be clamped to that limit, and not overflow.
  209. m_specificity = (min(ids, 0xff) << ids_shift)
  210. + (min(classes, 0xff) << classes_shift)
  211. + (min(tag_names, 0xff) << tag_names_shift);
  212. return *m_specificity;
  213. }
  214. // https://www.w3.org/TR/cssom/#serialize-a-simple-selector
  215. String Selector::SimpleSelector::serialize() const
  216. {
  217. StringBuilder s;
  218. switch (type) {
  219. case Selector::SimpleSelector::Type::TagName:
  220. case Selector::SimpleSelector::Type::Universal: {
  221. auto qualified_name = this->qualified_name();
  222. // 1. If the namespace prefix maps to a namespace that is not the default namespace and is not the null
  223. // namespace (not in a namespace) append the serialization of the namespace prefix as an identifier,
  224. // followed by a "|" (U+007C) to s.
  225. if (qualified_name.namespace_type == QualifiedName::NamespaceType::Named) {
  226. serialize_an_identifier(s, qualified_name.namespace_);
  227. s.append('|');
  228. }
  229. // 2. If the namespace prefix maps to a namespace that is the null namespace (not in a namespace)
  230. // append "|" (U+007C) to s.
  231. if (qualified_name.namespace_type == QualifiedName::NamespaceType::None)
  232. s.append('|');
  233. // 3. If this is a type selector append the serialization of the element name as an identifier to s.
  234. if (type == Selector::SimpleSelector::Type::TagName)
  235. serialize_an_identifier(s, qualified_name.name.name);
  236. // 4. If this is a universal selector append "*" (U+002A) to s.
  237. if (type == Selector::SimpleSelector::Type::Universal)
  238. s.append('*');
  239. break;
  240. }
  241. case Selector::SimpleSelector::Type::Attribute: {
  242. auto& attribute = this->attribute();
  243. // 1. Append "[" (U+005B) to s.
  244. s.append('[');
  245. // 2. If the namespace prefix maps to a namespace that is not the null namespace (not in a namespace)
  246. // append the serialization of the namespace prefix as an identifier, followed by a "|" (U+007C) to s.
  247. if (attribute.qualified_name.namespace_type == QualifiedName::NamespaceType::Named) {
  248. serialize_an_identifier(s, attribute.qualified_name.namespace_);
  249. s.append('|');
  250. }
  251. // 3. Append the serialization of the attribute name as an identifier to s.
  252. serialize_an_identifier(s, attribute.qualified_name.name.name);
  253. // 4. If there is an attribute value specified, append "=", "~=", "|=", "^=", "$=", or "*=" as appropriate (depending on the type of attribute selector),
  254. // followed by the serialization of the attribute value as a string, to s.
  255. if (!attribute.value.is_empty()) {
  256. switch (attribute.match_type) {
  257. case Selector::SimpleSelector::Attribute::MatchType::ExactValueMatch:
  258. s.append("="sv);
  259. break;
  260. case Selector::SimpleSelector::Attribute::MatchType::ContainsWord:
  261. s.append("~="sv);
  262. break;
  263. case Selector::SimpleSelector::Attribute::MatchType::ContainsString:
  264. s.append("*="sv);
  265. break;
  266. case Selector::SimpleSelector::Attribute::MatchType::StartsWithSegment:
  267. s.append("|="sv);
  268. break;
  269. case Selector::SimpleSelector::Attribute::MatchType::StartsWithString:
  270. s.append("^="sv);
  271. break;
  272. case Selector::SimpleSelector::Attribute::MatchType::EndsWithString:
  273. s.append("$="sv);
  274. break;
  275. default:
  276. break;
  277. }
  278. serialize_a_string(s, attribute.value);
  279. }
  280. // 5. If the attribute selector has the case-insensitivity flag present, append " i" (U+0020 U+0069) to s.
  281. // If the attribute selector has the case-insensitivity flag present, append " s" (U+0020 U+0073) to s.
  282. // (the line just above is an addition to CSS OM to match Selectors Level 4 last draft)
  283. switch (attribute.case_type) {
  284. case Selector::SimpleSelector::Attribute::CaseType::CaseInsensitiveMatch:
  285. s.append(" i"sv);
  286. break;
  287. case Selector::SimpleSelector::Attribute::CaseType::CaseSensitiveMatch:
  288. s.append(" s"sv);
  289. break;
  290. default:
  291. break;
  292. }
  293. // 6. Append "]" (U+005D) to s.
  294. s.append(']');
  295. break;
  296. }
  297. case Selector::SimpleSelector::Type::Class:
  298. // Append a "." (U+002E), followed by the serialization of the class name as an identifier to s.
  299. s.append('.');
  300. serialize_an_identifier(s, name());
  301. break;
  302. case Selector::SimpleSelector::Type::Id:
  303. // Append a "#" (U+0023), followed by the serialization of the ID as an identifier to s.
  304. s.append('#');
  305. serialize_an_identifier(s, name());
  306. break;
  307. case Selector::SimpleSelector::Type::PseudoClass: {
  308. auto& pseudo_class = this->pseudo_class();
  309. auto metadata = pseudo_class_metadata(pseudo_class.type);
  310. // HACK: `:host()` has both a function and a non-function form, so handle that first.
  311. // It's also not in the spec.
  312. if (pseudo_class.type == PseudoClass::Host) {
  313. if (pseudo_class.argument_selector_list.is_empty()) {
  314. s.append(':');
  315. s.append(pseudo_class_name(pseudo_class.type));
  316. } else {
  317. s.append(':');
  318. s.append(pseudo_class_name(pseudo_class.type));
  319. s.append('(');
  320. s.append(serialize_a_group_of_selectors(pseudo_class.argument_selector_list));
  321. s.append(')');
  322. }
  323. }
  324. // If the pseudo-class does not accept arguments append ":" (U+003A), followed by the name of the pseudo-class, to s.
  325. else if (metadata.is_valid_as_identifier) {
  326. s.append(':');
  327. s.append(pseudo_class_name(pseudo_class.type));
  328. }
  329. // Otherwise, append ":" (U+003A), followed by the name of the pseudo-class, followed by "(" (U+0028),
  330. // followed by the value of the pseudo-class argument(s) determined as per below, followed by ")" (U+0029), to s.
  331. else {
  332. s.append(':');
  333. s.append(pseudo_class_name(pseudo_class.type));
  334. s.append('(');
  335. if (pseudo_class.type == PseudoClass::NthChild
  336. || pseudo_class.type == PseudoClass::NthLastChild
  337. || pseudo_class.type == PseudoClass::NthOfType
  338. || pseudo_class.type == PseudoClass::NthLastOfType) {
  339. // The result of serializing the value using the rules to serialize an <an+b> value.
  340. s.append(pseudo_class.nth_child_pattern.serialize());
  341. } else if (pseudo_class.type == PseudoClass::Not
  342. || pseudo_class.type == PseudoClass::Is
  343. || pseudo_class.type == PseudoClass::Where) {
  344. // The result of serializing the value using the rules for serializing a group of selectors.
  345. // NOTE: `:is()` and `:where()` aren't in the spec for this yet, but it should be!
  346. s.append(serialize_a_group_of_selectors(pseudo_class.argument_selector_list));
  347. } else if (pseudo_class.type == PseudoClass::Lang) {
  348. // The serialization of a comma-separated list of each argument’s serialization as a string, preserving relative order.
  349. s.join(", "sv, pseudo_class.languages);
  350. }
  351. s.append(')');
  352. }
  353. break;
  354. }
  355. case Selector::SimpleSelector::Type::PseudoElement:
  356. // Note: Pseudo-elements are dealt with in Selector::serialize()
  357. break;
  358. case Type::Nesting:
  359. // AD-HOC: Not in spec yet.
  360. s.append('&');
  361. break;
  362. case Type::Invalid:
  363. // AD-HOC: We're not told how to do these. Just serialize their component values.
  364. auto invalid = value.get<Invalid>();
  365. for (auto const& component_value : invalid.component_values)
  366. s.append(component_value.to_string());
  367. break;
  368. }
  369. return MUST(s.to_string());
  370. }
  371. // https://www.w3.org/TR/cssom/#serialize-a-selector
  372. String Selector::serialize() const
  373. {
  374. StringBuilder s;
  375. // To serialize a selector let s be the empty string, run the steps below for each part of the chain of the selector, and finally return s:
  376. for (size_t i = 0; i < compound_selectors().size(); ++i) {
  377. auto const& compound_selector = compound_selectors()[i];
  378. // 1. If there is only one simple selector in the compound selectors which is a universal selector, append the result of serializing the universal selector to s.
  379. if (compound_selector.simple_selectors.size() == 1
  380. && compound_selector.simple_selectors.first().type == Selector::SimpleSelector::Type::Universal) {
  381. s.append(compound_selector.simple_selectors.first().serialize());
  382. }
  383. // 2. Otherwise, for each simple selector in the compound selectors that is not a universal selector
  384. // of which the namespace prefix maps to a namespace that is not the default namespace
  385. // serialize the simple selector and append the result to s.
  386. else {
  387. for (auto& simple_selector : compound_selector.simple_selectors) {
  388. if (simple_selector.type == SimpleSelector::Type::Universal) {
  389. auto qualified_name = simple_selector.qualified_name();
  390. if (qualified_name.namespace_type == SimpleSelector::QualifiedName::NamespaceType::Default)
  391. continue;
  392. // FIXME: I *think* if we have a namespace prefix that happens to equal the same as the default namespace,
  393. // we also should skip it. But we don't have access to that here. eg:
  394. // <style>
  395. // @namespace "http://example";
  396. // @namespace foo "http://example";
  397. // foo|*.bar { } /* This would skip the `foo|*` when serializing. */
  398. // </style>
  399. }
  400. s.append(simple_selector.serialize());
  401. }
  402. }
  403. // 3. If this is not the last part of the chain of the selector append a single SPACE (U+0020),
  404. // followed by the combinator ">", "+", "~", ">>", "||", as appropriate, followed by another
  405. // single SPACE (U+0020) if the combinator was not whitespace, to s.
  406. if (i != compound_selectors().size() - 1) {
  407. s.append(' ');
  408. // Note: The combinator that appears between parts `i` and `i+1` appears with the `i+1` selector,
  409. // so we have to check that one.
  410. switch (compound_selectors()[i + 1].combinator) {
  411. case Selector::Combinator::ImmediateChild:
  412. s.append("> "sv);
  413. break;
  414. case Selector::Combinator::NextSibling:
  415. s.append("+ "sv);
  416. break;
  417. case Selector::Combinator::SubsequentSibling:
  418. s.append("~ "sv);
  419. break;
  420. case Selector::Combinator::Column:
  421. s.append("|| "sv);
  422. break;
  423. default:
  424. break;
  425. }
  426. } else {
  427. // 4. If this is the last part of the chain of the selector and there is a pseudo-element,
  428. // append "::" followed by the name of the pseudo-element, to s.
  429. if (compound_selector.simple_selectors.last().type == Selector::SimpleSelector::Type::PseudoElement) {
  430. s.append("::"sv);
  431. s.append(compound_selector.simple_selectors.last().pseudo_element().name());
  432. }
  433. }
  434. }
  435. return MUST(s.to_string());
  436. }
  437. // https://www.w3.org/TR/cssom/#serialize-a-group-of-selectors
  438. String serialize_a_group_of_selectors(SelectorList const& selectors)
  439. {
  440. // To serialize a group of selectors serialize each selector in the group of selectors and then serialize a comma-separated list of these serializations.
  441. return MUST(String::join(", "sv, selectors));
  442. }
  443. StringView Selector::PseudoElement::name(Selector::PseudoElement::Type pseudo_element)
  444. {
  445. switch (pseudo_element) {
  446. case Selector::PseudoElement::Type::Before:
  447. return "before"sv;
  448. case Selector::PseudoElement::Type::After:
  449. return "after"sv;
  450. case Selector::PseudoElement::Type::FirstLine:
  451. return "first-line"sv;
  452. case Selector::PseudoElement::Type::FirstLetter:
  453. return "first-letter"sv;
  454. case Selector::PseudoElement::Type::Marker:
  455. return "marker"sv;
  456. case Selector::PseudoElement::Type::MeterBar:
  457. return "-webkit-meter-bar"sv;
  458. case Selector::PseudoElement::Type::MeterEvenLessGoodValue:
  459. return "-webkit-meter-even-less-good-value"sv;
  460. case Selector::PseudoElement::Type::MeterOptimumValue:
  461. return "-webkit-meter-optimum-value"sv;
  462. case Selector::PseudoElement::Type::MeterSuboptimumValue:
  463. return "-webkit-meter-suboptimum-value"sv;
  464. case Selector::PseudoElement::Type::ProgressBar:
  465. return "-webkit-progress-bar"sv;
  466. case Selector::PseudoElement::Type::ProgressValue:
  467. return "-webkit-progress-value"sv;
  468. case Selector::PseudoElement::Type::Placeholder:
  469. return "placeholder"sv;
  470. case Selector::PseudoElement::Type::Selection:
  471. return "selection"sv;
  472. case Selector::PseudoElement::Type::SliderRunnableTrack:
  473. return "-webkit-slider-runnable-track"sv;
  474. case Selector::PseudoElement::Type::SliderThumb:
  475. return "-webkit-slider-thumb"sv;
  476. case Selector::PseudoElement::Type::Backdrop:
  477. return "backdrop"sv;
  478. case Selector::PseudoElement::Type::KnownPseudoElementCount:
  479. break;
  480. case Selector::PseudoElement::Type::UnknownWebKit:
  481. VERIFY_NOT_REACHED();
  482. }
  483. VERIFY_NOT_REACHED();
  484. }
  485. Optional<Selector::PseudoElement> Selector::PseudoElement::from_string(FlyString const& name)
  486. {
  487. if (name.equals_ignoring_ascii_case("after"sv)) {
  488. return Selector::PseudoElement { Selector::PseudoElement::Type::After };
  489. } else if (name.equals_ignoring_ascii_case("before"sv)) {
  490. return Selector::PseudoElement { Selector::PseudoElement::Type::Before };
  491. } else if (name.equals_ignoring_ascii_case("first-letter"sv)) {
  492. return Selector::PseudoElement { Selector::PseudoElement::Type::FirstLetter };
  493. } else if (name.equals_ignoring_ascii_case("first-line"sv)) {
  494. return Selector::PseudoElement { Selector::PseudoElement::Type::FirstLine };
  495. } else if (name.equals_ignoring_ascii_case("marker"sv)) {
  496. return Selector::PseudoElement { Selector::PseudoElement::Type::Marker };
  497. } else if (name.equals_ignoring_ascii_case("-webkit-meter-bar"sv)) {
  498. return Selector::PseudoElement { Selector::PseudoElement::Type::MeterBar };
  499. } else if (name.equals_ignoring_ascii_case("-webkit-meter-even-less-good-value"sv)) {
  500. return Selector::PseudoElement { Selector::PseudoElement::Type::MeterEvenLessGoodValue };
  501. } else if (name.equals_ignoring_ascii_case("-webkit-meter-optimum-value"sv)) {
  502. return Selector::PseudoElement { Selector::PseudoElement::Type::MeterOptimumValue };
  503. } else if (name.equals_ignoring_ascii_case("-webkit-meter-suboptimum-value"sv)) {
  504. return Selector::PseudoElement { Selector::PseudoElement::Type::MeterSuboptimumValue };
  505. } else if (name.equals_ignoring_ascii_case("-webkit-progress-bar"sv)) {
  506. return Selector::PseudoElement { Selector::PseudoElement::Type::ProgressBar };
  507. } else if (name.equals_ignoring_ascii_case("-webkit-progress-value"sv)) {
  508. return Selector::PseudoElement { Selector::PseudoElement::Type::ProgressValue };
  509. } else if (name.equals_ignoring_ascii_case("placeholder"sv)) {
  510. return Selector::PseudoElement { Selector::PseudoElement::Type::Placeholder };
  511. } else if (name.equals_ignoring_ascii_case("selection"sv)) {
  512. return Selector::PseudoElement { Selector::PseudoElement::Type::Selection };
  513. } else if (name.equals_ignoring_ascii_case("backdrop"sv)) {
  514. return Selector::PseudoElement { Selector::PseudoElement::Type::Backdrop };
  515. } else if (name.equals_ignoring_ascii_case("-webkit-slider-runnable-track"sv)) {
  516. return Selector::PseudoElement { Selector::PseudoElement::Type::SliderRunnableTrack };
  517. } else if (name.equals_ignoring_ascii_case("-webkit-slider-thumb"sv)) {
  518. return Selector::PseudoElement { Selector::PseudoElement::Type::SliderThumb };
  519. }
  520. return {};
  521. }
  522. NonnullRefPtr<Selector> Selector::relative_to(SimpleSelector const& parent) const
  523. {
  524. // To make us relative to the parent, prepend it to the list of compound selectors,
  525. // and ensure the next compound selector starts with a combinator.
  526. Vector<CompoundSelector> copied_compound_selectors;
  527. copied_compound_selectors.ensure_capacity(compound_selectors().size() + 1);
  528. copied_compound_selectors.empend(CompoundSelector { .simple_selectors = { parent } });
  529. bool first = true;
  530. for (auto compound_selector : compound_selectors()) {
  531. if (first) {
  532. if (compound_selector.combinator == Combinator::None)
  533. compound_selector.combinator = Combinator::Descendant;
  534. first = false;
  535. }
  536. copied_compound_selectors.append(move(compound_selector));
  537. }
  538. return Selector::create(move(copied_compound_selectors));
  539. }
  540. RefPtr<Selector> Selector::absolutized(Selector::SimpleSelector const& selector_for_nesting) const
  541. {
  542. if (!contains_the_nesting_selector())
  543. return *this;
  544. Vector<CompoundSelector> absolutized_compound_selectors;
  545. absolutized_compound_selectors.ensure_capacity(m_compound_selectors.size());
  546. for (auto const& compound_selector : m_compound_selectors) {
  547. if (auto absolutized = compound_selector.absolutized(selector_for_nesting); absolutized.has_value()) {
  548. absolutized_compound_selectors.append(absolutized.release_value());
  549. } else {
  550. return nullptr;
  551. }
  552. }
  553. return Selector::create(move(absolutized_compound_selectors));
  554. }
  555. Optional<Selector::CompoundSelector> Selector::CompoundSelector::absolutized(Selector::SimpleSelector const& selector_for_nesting) const
  556. {
  557. // TODO: Cache if it contains the nesting selector?
  558. Vector<SimpleSelector> absolutized_simple_selectors;
  559. absolutized_simple_selectors.ensure_capacity(simple_selectors.size());
  560. for (auto const& simple_selector : simple_selectors) {
  561. if (auto absolutized = simple_selector.absolutized(selector_for_nesting); absolutized.has_value()) {
  562. absolutized_simple_selectors.append(absolutized.release_value());
  563. } else {
  564. return {};
  565. }
  566. }
  567. return CompoundSelector {
  568. .combinator = this->combinator,
  569. .simple_selectors = absolutized_simple_selectors,
  570. };
  571. }
  572. Optional<Selector::SimpleSelector> Selector::SimpleSelector::absolutized(Selector::SimpleSelector const& selector_for_nesting) const
  573. {
  574. switch (type) {
  575. case Type::Nesting:
  576. // Nesting selectors get replaced directly.
  577. return selector_for_nesting;
  578. case Type::PseudoClass: {
  579. // Pseudo-classes may contain other selectors, so we need to absolutize them.
  580. // Copy the PseudoClassSelector, and then replace its argument selector list.
  581. auto pseudo_class = this->pseudo_class();
  582. if (!pseudo_class.argument_selector_list.is_empty()) {
  583. SelectorList new_selector_list;
  584. new_selector_list.ensure_capacity(pseudo_class.argument_selector_list.size());
  585. for (auto const& argument_selector : pseudo_class.argument_selector_list) {
  586. if (auto absolutized = argument_selector->absolutized(selector_for_nesting)) {
  587. new_selector_list.append(absolutized.release_nonnull());
  588. } else if (!pseudo_class.is_forgiving) {
  589. return {};
  590. }
  591. }
  592. pseudo_class.argument_selector_list = move(new_selector_list);
  593. }
  594. return SimpleSelector {
  595. .type = Type::PseudoClass,
  596. .value = move(pseudo_class),
  597. };
  598. }
  599. case Type::Universal:
  600. case Type::TagName:
  601. case Type::Id:
  602. case Type::Class:
  603. case Type::Attribute:
  604. case Type::PseudoElement:
  605. case Type::Invalid:
  606. // Everything else isn't affected
  607. return *this;
  608. }
  609. VERIFY_NOT_REACHED();
  610. }
  611. SelectorList adapt_nested_relative_selector_list(SelectorList const& selectors)
  612. {
  613. // "Nested style rules differ from non-nested rules in the following ways:
  614. // - A nested style rule accepts a <relative-selector-list> as its prelude (rather than just a <selector-list>).
  615. // Any relative selectors are relative to the elements represented by the nesting selector.
  616. // - If a selector in the <relative-selector-list> does not start with a combinator but does contain the nesting
  617. // selector, it is interpreted as a non-relative selector."
  618. // https://drafts.csswg.org/css-nesting-1/#syntax
  619. // NOTE: We already parsed the selectors as a <relative-selector-list>
  620. // Nested relative selectors get a `&` inserted at the beginning.
  621. // This is, handily, how the spec wants them serialized:
  622. // "When serializing a relative selector in a nested style rule, the selector must be absolutized,
  623. // with the implied nesting selector inserted."
  624. // - https://drafts.csswg.org/css-nesting-1/#cssom
  625. CSS::SelectorList new_list;
  626. new_list.ensure_capacity(selectors.size());
  627. for (auto const& selector : selectors) {
  628. auto first_combinator = selector->compound_selectors().first().combinator;
  629. if (!first_is_one_of(first_combinator, CSS::Selector::Combinator::None, CSS::Selector::Combinator::Descendant)
  630. || !selector->contains_the_nesting_selector()) {
  631. new_list.append(selector->relative_to(CSS::Selector::SimpleSelector { .type = CSS::Selector::SimpleSelector::Type::Nesting }));
  632. } else if (first_combinator == CSS::Selector::Combinator::Descendant) {
  633. // Replace leading descendant combinator (whitespace) with none, because we're not actually relative.
  634. auto copied_compound_selectors = selector->compound_selectors();
  635. copied_compound_selectors.first().combinator = CSS::Selector::Combinator::None;
  636. new_list.append(CSS::Selector::create(move(copied_compound_selectors)));
  637. } else {
  638. new_list.append(selector);
  639. }
  640. }
  641. return new_list;
  642. }
  643. // https://drafts.csswg.org/selectors/#has-allowed-pseudo-element
  644. bool is_has_allowed_pseudo_element(Selector::PseudoElement::Type)
  645. {
  646. // No spec currently defines any pseudo-elements that are allowed in :has()
  647. return false;
  648. }
  649. }