blitz-pdf 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (370) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +355 -2
  3. package/THIRD_PARTY_NOTICES.md +25 -0
  4. package/assets/icon.svg +4 -0
  5. package/dist/api.d.ts +7 -0
  6. package/dist/api.d.ts.map +1 -0
  7. package/dist/api.js +46 -0
  8. package/dist/api.js.map +1 -0
  9. package/dist/assets.d.ts +7 -0
  10. package/dist/assets.d.ts.map +1 -0
  11. package/dist/assets.js +52 -0
  12. package/dist/assets.js.map +1 -0
  13. package/dist/browser.d.ts +3 -0
  14. package/dist/browser.d.ts.map +1 -0
  15. package/dist/browser.js +3 -0
  16. package/dist/browser.js.map +1 -0
  17. package/dist/node.d.ts +3 -0
  18. package/dist/node.d.ts.map +1 -0
  19. package/dist/node.js +10 -0
  20. package/dist/node.js.map +1 -0
  21. package/dist/options.d.ts +24 -0
  22. package/dist/options.d.ts.map +1 -0
  23. package/dist/options.js +135 -0
  24. package/dist/options.js.map +1 -0
  25. package/dist/types.d.ts +51 -0
  26. package/dist/types.d.ts.map +1 -0
  27. package/dist/types.js +2 -0
  28. package/dist/types.js.map +1 -0
  29. package/examples/bun.ts +8 -0
  30. package/examples/german-invoice/README.md +70 -0
  31. package/examples/german-invoice/data.mjs +83 -0
  32. package/examples/german-invoice/invoice.css +59 -0
  33. package/examples/german-invoice/template.mjs +49 -0
  34. package/examples/german-invoice.mjs +20 -0
  35. package/examples/invoice.html +29 -0
  36. package/examples/node.mjs +8 -0
  37. package/examples/pagination.html +40 -0
  38. package/examples/pagination.mjs +8 -0
  39. package/licenses/DejaVu.txt +187 -0
  40. package/licenses/RUST_DEPENDENCIES.txt +11577 -0
  41. package/package.json +89 -4
  42. package/src/api.ts +44 -0
  43. package/src/assets.ts +43 -0
  44. package/src/browser.ts +6 -0
  45. package/src/node.ts +12 -0
  46. package/src/options.ts +101 -0
  47. package/src/types.ts +49 -0
  48. package/vendor/README.md +17 -0
  49. package/vendor/stylo/.cargo-ok +1 -0
  50. package/vendor/stylo/.cargo_vcs_info.json +6 -0
  51. package/vendor/stylo/Cargo.lock +1485 -0
  52. package/vendor/stylo/Cargo.toml +274 -0
  53. package/vendor/stylo/LICENSE +373 -0
  54. package/vendor/stylo/README.md +6 -0
  55. package/vendor/stylo/applicable_declarations.rs +328 -0
  56. package/vendor/stylo/author_styles.rs +79 -0
  57. package/vendor/stylo/bezier.rs +176 -0
  58. package/vendor/stylo/bloom.rs +414 -0
  59. package/vendor/stylo/build.rs +91 -0
  60. package/vendor/stylo/build_gecko.rs +393 -0
  61. package/vendor/stylo/color/color_function.rs +601 -0
  62. package/vendor/stylo/color/component.rs +207 -0
  63. package/vendor/stylo/color/convert.rs +935 -0
  64. package/vendor/stylo/color/gamut/raytrace.rs +265 -0
  65. package/vendor/stylo/color/gamut.rs +227 -0
  66. package/vendor/stylo/color/mix.rs +645 -0
  67. package/vendor/stylo/color/mod.rs +750 -0
  68. package/vendor/stylo/color/parsing.rs +770 -0
  69. package/vendor/stylo/color/to_css.rs +297 -0
  70. package/vendor/stylo/context.rs +716 -0
  71. package/vendor/stylo/counter_style/mod.rs +754 -0
  72. package/vendor/stylo/counter_style/predefined.rs +61 -0
  73. package/vendor/stylo/counter_style/update_predefined.py +35 -0
  74. package/vendor/stylo/custom_properties.rs +2023 -0
  75. package/vendor/stylo/custom_properties_map.rs +220 -0
  76. package/vendor/stylo/data.rs +693 -0
  77. package/vendor/stylo/device/gecko.rs +486 -0
  78. package/vendor/stylo/device/mod.rs +304 -0
  79. package/vendor/stylo/device/servo.rs +507 -0
  80. package/vendor/stylo/dom.rs +1164 -0
  81. package/vendor/stylo/dom_apis.rs +937 -0
  82. package/vendor/stylo/driver.rs +172 -0
  83. package/vendor/stylo/error_reporting.rs +484 -0
  84. package/vendor/stylo/font_face.rs +558 -0
  85. package/vendor/stylo/font_metrics.rs +124 -0
  86. package/vendor/stylo/gecko/anon_boxes.toml +113 -0
  87. package/vendor/stylo/gecko/arc_types.rs +211 -0
  88. package/vendor/stylo/gecko/conversions.rs +59 -0
  89. package/vendor/stylo/gecko/data.rs +222 -0
  90. package/vendor/stylo/gecko/media_features.rs +971 -0
  91. package/vendor/stylo/gecko/mod.rs +20 -0
  92. package/vendor/stylo/gecko/non_ts_pseudo_class_list.rs +119 -0
  93. package/vendor/stylo/gecko/pseudo_element.rs +640 -0
  94. package/vendor/stylo/gecko/pseudo_element_definition.mako.rs +298 -0
  95. package/vendor/stylo/gecko/pseudo_elements.py +137 -0
  96. package/vendor/stylo/gecko/pseudo_elements.toml +197 -0
  97. package/vendor/stylo/gecko/regen_pseudo_elements.py +33 -0
  98. package/vendor/stylo/gecko/restyle_damage.rs +127 -0
  99. package/vendor/stylo/gecko/selector_parser.rs +627 -0
  100. package/vendor/stylo/gecko/snapshot.rs +202 -0
  101. package/vendor/stylo/gecko/snapshot_helpers.rs +334 -0
  102. package/vendor/stylo/gecko/traversal.rs +52 -0
  103. package/vendor/stylo/gecko/wrapper.rs +2258 -0
  104. package/vendor/stylo/gecko_bindings/mod.rs +34 -0
  105. package/vendor/stylo/gecko_bindings/sugar/mod.rs +12 -0
  106. package/vendor/stylo/gecko_bindings/sugar/ns_com_ptr.rs +15 -0
  107. package/vendor/stylo/gecko_bindings/sugar/ns_compatibility.rs +19 -0
  108. package/vendor/stylo/gecko_bindings/sugar/ns_style_auto_array.rs +111 -0
  109. package/vendor/stylo/gecko_bindings/sugar/origin_flags.rs +31 -0
  110. package/vendor/stylo/gecko_bindings/sugar/ownership.rs +70 -0
  111. package/vendor/stylo/gecko_bindings/sugar/refptr.rs +299 -0
  112. package/vendor/stylo/gecko_string_cache/mod.rs +543 -0
  113. package/vendor/stylo/gecko_string_cache/namespace.rs +106 -0
  114. package/vendor/stylo/global_style_data.rs +224 -0
  115. package/vendor/stylo/invalidation/element/document_state.rs +156 -0
  116. package/vendor/stylo/invalidation/element/element_wrapper.rs +432 -0
  117. package/vendor/stylo/invalidation/element/invalidation_map.rs +1631 -0
  118. package/vendor/stylo/invalidation/element/invalidator.rs +1470 -0
  119. package/vendor/stylo/invalidation/element/mod.rs +13 -0
  120. package/vendor/stylo/invalidation/element/relative_selector.rs +1399 -0
  121. package/vendor/stylo/invalidation/element/restyle_hints.rs +226 -0
  122. package/vendor/stylo/invalidation/element/state_and_attributes.rs +756 -0
  123. package/vendor/stylo/invalidation/media_queries.rs +144 -0
  124. package/vendor/stylo/invalidation/mod.rs +10 -0
  125. package/vendor/stylo/invalidation/stylesheets.rs +745 -0
  126. package/vendor/stylo/invalidation/viewport_units.rs +71 -0
  127. package/vendor/stylo/lib.rs +336 -0
  128. package/vendor/stylo/logical_geometry.rs +1684 -0
  129. package/vendor/stylo/macros.rs +70 -0
  130. package/vendor/stylo/matching.rs +1226 -0
  131. package/vendor/stylo/media_queries/media_list.rs +168 -0
  132. package/vendor/stylo/media_queries/media_query.rs +190 -0
  133. package/vendor/stylo/media_queries/mod.rs +13 -0
  134. package/vendor/stylo/parallel.rs +205 -0
  135. package/vendor/stylo/parser.rs +276 -0
  136. package/vendor/stylo/piecewise_linear.rs +282 -0
  137. package/vendor/stylo/prefs.rs +33 -0
  138. package/vendor/stylo/properties/build.py +119 -0
  139. package/vendor/stylo/properties/cascade.rs +2704 -0
  140. package/vendor/stylo/properties/computed_value_flags.rs +206 -0
  141. package/vendor/stylo/properties/counted_unknown_properties.py +104 -0
  142. package/vendor/stylo/properties/counter_style_descriptors.toml +45 -0
  143. package/vendor/stylo/properties/data.py +1375 -0
  144. package/vendor/stylo/properties/declaration_block.rs +1788 -0
  145. package/vendor/stylo/properties/font_face_descriptors.toml +50 -0
  146. package/vendor/stylo/properties/gecko.mako.rs +1555 -0
  147. package/vendor/stylo/properties/helpers/animated_properties.mako.rs +800 -0
  148. package/vendor/stylo/properties/helpers.mako.rs +812 -0
  149. package/vendor/stylo/properties/longhands.toml +4305 -0
  150. package/vendor/stylo/properties/mod.rs +1857 -0
  151. package/vendor/stylo/properties/properties.html.mako +31 -0
  152. package/vendor/stylo/properties/properties.mako.rs +3103 -0
  153. package/vendor/stylo/properties/property_descriptors.toml +18 -0
  154. package/vendor/stylo/properties/shorthands.rs +4241 -0
  155. package/vendor/stylo/properties/shorthands.toml +575 -0
  156. package/vendor/stylo/properties/vendored_python/mako-1.3.10-py3-none-any.whl +0 -0
  157. package/vendor/stylo/properties/vendored_python/markupsafe/LICENSE.txt +28 -0
  158. package/vendor/stylo/properties/vendored_python/markupsafe/__init__.py +384 -0
  159. package/vendor/stylo/properties/vendored_python/toml-0.10.2-py2.py3-none-any.whl +0 -0
  160. package/vendor/stylo/properties/view_transition_descriptors.toml +11 -0
  161. package/vendor/stylo/properties_and_values/mod.rs +12 -0
  162. package/vendor/stylo/properties_and_values/registry.rs +65 -0
  163. package/vendor/stylo/properties_and_values/rule.rs +331 -0
  164. package/vendor/stylo/properties_and_values/syntax/ascii.rs +60 -0
  165. package/vendor/stylo/properties_and_values/syntax/data_type.rs +146 -0
  166. package/vendor/stylo/properties_and_values/syntax/mod.rs +437 -0
  167. package/vendor/stylo/properties_and_values/value.rs +758 -0
  168. package/vendor/stylo/queries/condition.rs +996 -0
  169. package/vendor/stylo/queries/feature.rs +199 -0
  170. package/vendor/stylo/queries/feature_expression.rs +1170 -0
  171. package/vendor/stylo/queries/mod.rs +19 -0
  172. package/vendor/stylo/queries/values.rs +46 -0
  173. package/vendor/stylo/rule_cache.rs +267 -0
  174. package/vendor/stylo/rule_collector.rs +554 -0
  175. package/vendor/stylo/rule_tree/core.rs +787 -0
  176. package/vendor/stylo/rule_tree/level.rs +396 -0
  177. package/vendor/stylo/rule_tree/map.rs +201 -0
  178. package/vendor/stylo/rule_tree/mod.rs +427 -0
  179. package/vendor/stylo/rule_tree/source.rs +80 -0
  180. package/vendor/stylo/rule_tree/unsafe_box.rs +78 -0
  181. package/vendor/stylo/scoped_tls.rs +80 -0
  182. package/vendor/stylo/selector_map.rs +1050 -0
  183. package/vendor/stylo/selector_parser.rs +305 -0
  184. package/vendor/stylo/servo/animation.rs +1922 -0
  185. package/vendor/stylo/servo/attr.rs +714 -0
  186. package/vendor/stylo/servo/encoding_support.rs +81 -0
  187. package/vendor/stylo/servo/media_features.rs +254 -0
  188. package/vendor/stylo/servo/mod.rs +16 -0
  189. package/vendor/stylo/servo/restyle_damage.rs +215 -0
  190. package/vendor/stylo/servo/selector_parser.rs +1036 -0
  191. package/vendor/stylo/servo/shadow_parts.rs +207 -0
  192. package/vendor/stylo/shared_lock.rs +271 -0
  193. package/vendor/stylo/sharing/checks.rs +281 -0
  194. package/vendor/stylo/sharing/mod.rs +1000 -0
  195. package/vendor/stylo/simple_buckets_map.rs +52 -0
  196. package/vendor/stylo/str.rs +168 -0
  197. package/vendor/stylo/style_adjuster.rs +1086 -0
  198. package/vendor/stylo/style_resolver.rs +658 -0
  199. package/vendor/stylo/stylesheet_set.rs +658 -0
  200. package/vendor/stylo/stylesheets/appearance_base_rule.rs +51 -0
  201. package/vendor/stylo/stylesheets/container_rule.rs +769 -0
  202. package/vendor/stylo/stylesheets/counter_style_rule.rs +7 -0
  203. package/vendor/stylo/stylesheets/document_rule.rs +272 -0
  204. package/vendor/stylo/stylesheets/font_face_rule.rs +7 -0
  205. package/vendor/stylo/stylesheets/font_feature_values_rule.rs +481 -0
  206. package/vendor/stylo/stylesheets/font_palette_values_rule.rs +304 -0
  207. package/vendor/stylo/stylesheets/import_rule.rs +259 -0
  208. package/vendor/stylo/stylesheets/keyframes_rule.rs +733 -0
  209. package/vendor/stylo/stylesheets/layer_rule.rs +221 -0
  210. package/vendor/stylo/stylesheets/loader.rs +29 -0
  211. package/vendor/stylo/stylesheets/margin_rule.rs +190 -0
  212. package/vendor/stylo/stylesheets/media_rule.rs +191 -0
  213. package/vendor/stylo/stylesheets/mod.rs +918 -0
  214. package/vendor/stylo/stylesheets/namespace_rule.rs +43 -0
  215. package/vendor/stylo/stylesheets/nested_declarations_rule.rs +51 -0
  216. package/vendor/stylo/stylesheets/origin.rs +249 -0
  217. package/vendor/stylo/stylesheets/page_rule.rs +354 -0
  218. package/vendor/stylo/stylesheets/position_try_rule.rs +68 -0
  219. package/vendor/stylo/stylesheets/property_rule.rs +5 -0
  220. package/vendor/stylo/stylesheets/rule_list.rs +167 -0
  221. package/vendor/stylo/stylesheets/rule_parser.rs +1189 -0
  222. package/vendor/stylo/stylesheets/rules_iterator.rs +397 -0
  223. package/vendor/stylo/stylesheets/scope_rule.rs +511 -0
  224. package/vendor/stylo/stylesheets/starting_style_rule.rs +54 -0
  225. package/vendor/stylo/stylesheets/style_rule.rs +80 -0
  226. package/vendor/stylo/stylesheets/stylesheet.rs +570 -0
  227. package/vendor/stylo/stylesheets/supports_rule.rs +486 -0
  228. package/vendor/stylo/stylesheets/view_transition_rule.rs +81 -0
  229. package/vendor/stylo/stylist.rs +5076 -0
  230. package/vendor/stylo/thread_state.rs +87 -0
  231. package/vendor/stylo/traversal.rs +765 -0
  232. package/vendor/stylo/traversal_flags.rs +68 -0
  233. package/vendor/stylo/typed_om/mod.rs +981 -0
  234. package/vendor/stylo/typed_om/numeric.rs +128 -0
  235. package/vendor/stylo/typed_om/numeric_declaration.rs +93 -0
  236. package/vendor/stylo/typed_om/numeric_type.rs +640 -0
  237. package/vendor/stylo/typed_om/sum_value.rs +426 -0
  238. package/vendor/stylo/url/gecko.rs +367 -0
  239. package/vendor/stylo/url/mod.rs +71 -0
  240. package/vendor/stylo/url/servo.rs +239 -0
  241. package/vendor/stylo/use_counters/mod.rs +137 -0
  242. package/vendor/stylo/values/animated/color.rs +103 -0
  243. package/vendor/stylo/values/animated/effects.rs +26 -0
  244. package/vendor/stylo/values/animated/font.rs +37 -0
  245. package/vendor/stylo/values/animated/grid.rs +161 -0
  246. package/vendor/stylo/values/animated/lists.rs +141 -0
  247. package/vendor/stylo/values/animated/mod.rs +550 -0
  248. package/vendor/stylo/values/animated/svg.rs +46 -0
  249. package/vendor/stylo/values/animated/text.rs +58 -0
  250. package/vendor/stylo/values/animated/transform.rs +1592 -0
  251. package/vendor/stylo/values/computed/align.rs +90 -0
  252. package/vendor/stylo/values/computed/angle.rs +130 -0
  253. package/vendor/stylo/values/computed/animation.rs +124 -0
  254. package/vendor/stylo/values/computed/background.rs +13 -0
  255. package/vendor/stylo/values/computed/basic_shape.rs +267 -0
  256. package/vendor/stylo/values/computed/border.rs +163 -0
  257. package/vendor/stylo/values/computed/box.rs +267 -0
  258. package/vendor/stylo/values/computed/calc.rs +334 -0
  259. package/vendor/stylo/values/computed/color.rs +161 -0
  260. package/vendor/stylo/values/computed/column.rs +11 -0
  261. package/vendor/stylo/values/computed/corner_shape.rs +155 -0
  262. package/vendor/stylo/values/computed/counters.rs +26 -0
  263. package/vendor/stylo/values/computed/easing.rs +109 -0
  264. package/vendor/stylo/values/computed/effects.rs +30 -0
  265. package/vendor/stylo/values/computed/flex.rs +19 -0
  266. package/vendor/stylo/values/computed/font.rs +1517 -0
  267. package/vendor/stylo/values/computed/image.rs +273 -0
  268. package/vendor/stylo/values/computed/length.rs +576 -0
  269. package/vendor/stylo/values/computed/length_percentage.rs +1055 -0
  270. package/vendor/stylo/values/computed/list.rs +16 -0
  271. package/vendor/stylo/values/computed/mod.rs +1141 -0
  272. package/vendor/stylo/values/computed/motion.rs +73 -0
  273. package/vendor/stylo/values/computed/outline.rs +7 -0
  274. package/vendor/stylo/values/computed/page.rs +77 -0
  275. package/vendor/stylo/values/computed/param.rs +9 -0
  276. package/vendor/stylo/values/computed/percentage.rs +143 -0
  277. package/vendor/stylo/values/computed/position.rs +273 -0
  278. package/vendor/stylo/values/computed/ratio.rs +88 -0
  279. package/vendor/stylo/values/computed/rect.rs +19 -0
  280. package/vendor/stylo/values/computed/resolution.rs +76 -0
  281. package/vendor/stylo/values/computed/svg.rs +66 -0
  282. package/vendor/stylo/values/computed/table.rs +7 -0
  283. package/vendor/stylo/values/computed/text.rs +199 -0
  284. package/vendor/stylo/values/computed/time.rs +83 -0
  285. package/vendor/stylo/values/computed/transform.rs +559 -0
  286. package/vendor/stylo/values/computed/tree_counting.rs +30 -0
  287. package/vendor/stylo/values/computed/ui.rs +23 -0
  288. package/vendor/stylo/values/computed/url.rs +12 -0
  289. package/vendor/stylo/values/distance.rs +139 -0
  290. package/vendor/stylo/values/generics/animation.rs +363 -0
  291. package/vendor/stylo/values/generics/background.rs +65 -0
  292. package/vendor/stylo/values/generics/basic_shape.rs +1389 -0
  293. package/vendor/stylo/values/generics/border.rs +303 -0
  294. package/vendor/stylo/values/generics/box.rs +552 -0
  295. package/vendor/stylo/values/generics/calc.rs +2986 -0
  296. package/vendor/stylo/values/generics/color.rs +318 -0
  297. package/vendor/stylo/values/generics/column.rs +44 -0
  298. package/vendor/stylo/values/generics/counters.rs +320 -0
  299. package/vendor/stylo/values/generics/easing.rs +132 -0
  300. package/vendor/stylo/values/generics/effects.rs +131 -0
  301. package/vendor/stylo/values/generics/flex.rs +34 -0
  302. package/vendor/stylo/values/generics/font.rs +376 -0
  303. package/vendor/stylo/values/generics/grid.rs +962 -0
  304. package/vendor/stylo/values/generics/image.rs +653 -0
  305. package/vendor/stylo/values/generics/length.rs +656 -0
  306. package/vendor/stylo/values/generics/mod.rs +303 -0
  307. package/vendor/stylo/values/generics/motion.rs +274 -0
  308. package/vendor/stylo/values/generics/page.rs +167 -0
  309. package/vendor/stylo/values/generics/position.rs +669 -0
  310. package/vendor/stylo/values/generics/ratio.rs +88 -0
  311. package/vendor/stylo/values/generics/rect.rs +147 -0
  312. package/vendor/stylo/values/generics/size.rs +102 -0
  313. package/vendor/stylo/values/generics/svg.rs +226 -0
  314. package/vendor/stylo/values/generics/text.rs +268 -0
  315. package/vendor/stylo/values/generics/transform.rs +1157 -0
  316. package/vendor/stylo/values/generics/ui.rs +147 -0
  317. package/vendor/stylo/values/generics/url.rs +51 -0
  318. package/vendor/stylo/values/mod.rs +820 -0
  319. package/vendor/stylo/values/resolved/animation.rs +33 -0
  320. package/vendor/stylo/values/resolved/color.rs +53 -0
  321. package/vendor/stylo/values/resolved/counters.rs +45 -0
  322. package/vendor/stylo/values/resolved/mod.rs +316 -0
  323. package/vendor/stylo/values/specified/align.rs +711 -0
  324. package/vendor/stylo/values/specified/angle.rs +407 -0
  325. package/vendor/stylo/values/specified/animation.rs +921 -0
  326. package/vendor/stylo/values/specified/background.rs +270 -0
  327. package/vendor/stylo/values/specified/basic_shape.rs +986 -0
  328. package/vendor/stylo/values/specified/border.rs +430 -0
  329. package/vendor/stylo/values/specified/box.rs +2231 -0
  330. package/vendor/stylo/values/specified/calc.rs +1657 -0
  331. package/vendor/stylo/values/specified/color.rs +1210 -0
  332. package/vendor/stylo/values/specified/column.rs +11 -0
  333. package/vendor/stylo/values/specified/corner_shape.rs +152 -0
  334. package/vendor/stylo/values/specified/counters.rs +242 -0
  335. package/vendor/stylo/values/specified/easing.rs +225 -0
  336. package/vendor/stylo/values/specified/effects.rs +421 -0
  337. package/vendor/stylo/values/specified/flex.rs +42 -0
  338. package/vendor/stylo/values/specified/font.rs +2103 -0
  339. package/vendor/stylo/values/specified/frequency.rs +39 -0
  340. package/vendor/stylo/values/specified/grid.rs +407 -0
  341. package/vendor/stylo/values/specified/image.rs +1385 -0
  342. package/vendor/stylo/values/specified/intersection_observer.rs +80 -0
  343. package/vendor/stylo/values/specified/length.rs +2024 -0
  344. package/vendor/stylo/values/specified/list.rs +190 -0
  345. package/vendor/stylo/values/specified/mod.rs +531 -0
  346. package/vendor/stylo/values/specified/motion.rs +316 -0
  347. package/vendor/stylo/values/specified/number.rs +603 -0
  348. package/vendor/stylo/values/specified/outline.rs +69 -0
  349. package/vendor/stylo/values/specified/page.rs +94 -0
  350. package/vendor/stylo/values/specified/param.rs +121 -0
  351. package/vendor/stylo/values/specified/percentage.rs +364 -0
  352. package/vendor/stylo/values/specified/position.rs +2247 -0
  353. package/vendor/stylo/values/specified/ratio.rs +29 -0
  354. package/vendor/stylo/values/specified/rect.rs +28 -0
  355. package/vendor/stylo/values/specified/resolution.rs +237 -0
  356. package/vendor/stylo/values/specified/source_size_list.rs +135 -0
  357. package/vendor/stylo/values/specified/svg.rs +427 -0
  358. package/vendor/stylo/values/specified/svg_path.rs +1115 -0
  359. package/vendor/stylo/values/specified/table.rs +38 -0
  360. package/vendor/stylo/values/specified/text.rs +1561 -0
  361. package/vendor/stylo/values/specified/time.rs +313 -0
  362. package/vendor/stylo/values/specified/transform.rs +599 -0
  363. package/vendor/stylo/values/specified/tree_counting.rs +32 -0
  364. package/vendor/stylo/values/specified/ui.rs +344 -0
  365. package/vendor/stylo/values/specified/url.rs +12 -0
  366. package/vendor/stylo/values/tagged_numeric.rs +253 -0
  367. package/wasm/blitz_pdf.d.ts +67 -0
  368. package/wasm/blitz_pdf.js +699 -0
  369. package/wasm/blitz_pdf_bg.wasm +0 -0
  370. package/wasm/blitz_pdf_bg.wasm.d.ts +20 -0
@@ -0,0 +1,1399 @@
1
+ /* This Source Code Form is subject to the terms of the Mozilla Public
2
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
+
5
+ //! Invalidation of element styles relative selectors.
6
+
7
+ use crate::data::ElementData;
8
+ use crate::dom::{TElement, TNode};
9
+ #[cfg(feature = "gecko")]
10
+ use crate::gecko_bindings::structs::ServoElementSnapshotTable;
11
+ use crate::invalidation::element::element_wrapper::ElementWrapper;
12
+ use crate::invalidation::element::invalidation_map::{
13
+ AdditionalRelativeSelectorInvalidationMap, Dependency, DependencyInvalidationKind,
14
+ InvalidationMap, NormalDependencyInvalidationKind, RelativeDependencyInvalidationKind,
15
+ ScopeDependencyInvalidationKind, TSStateForInvalidation,
16
+ };
17
+ use crate::invalidation::element::invalidator::{
18
+ note_scope_dependency_force_at_subject, DescendantInvalidationLists, Invalidation,
19
+ InvalidationProcessor, InvalidationResult, InvalidationVector, SiblingTraversalMap,
20
+ TreeStyleInvalidator,
21
+ };
22
+ use crate::invalidation::element::restyle_hints::RestyleHint;
23
+ use crate::invalidation::element::state_and_attributes::{
24
+ check_dependency, dependency_may_be_relevant, invalidated_descendants, invalidated_self,
25
+ invalidated_sibling, push_invalidation, should_process_descendants,
26
+ };
27
+ #[cfg(feature = "servo")]
28
+ use crate::selector_parser::SnapshotMap as ServoElementSnapshotTable;
29
+ use crate::stylist::{CascadeData, Stylist};
30
+ use dom::ElementState;
31
+ use rustc_hash::FxHashMap;
32
+ use selectors::matching::{
33
+ early_reject_by_local_name, matches_selector, ElementSelectorFlags, MatchingContext,
34
+ MatchingForInvalidation, MatchingMode, NeedsSelectorFlags, QuirksMode, SelectorCaches,
35
+ VisitedHandlingMode,
36
+ };
37
+ use selectors::parser::SelectorKey;
38
+ use selectors::OpaqueElement;
39
+ use smallvec::{smallvec, SmallVec};
40
+ use std::ops::DerefMut;
41
+
42
+ /// Kind of DOM mutation this relative selector invalidation is being carried out in.
43
+ #[derive(Clone, Copy)]
44
+ pub enum DomMutationOperation {
45
+ /// Insertion operation, can cause side effect, but presumed already happened.
46
+ Insert,
47
+ /// Append operation, cannot cause side effect.
48
+ Append,
49
+ /// Removal operation, can cause side effect, but presumed already happened. Sibling relationships are destroyed.
50
+ Remove,
51
+ /// Invalidating for side effect of a DOM operation, for the previous sibling.
52
+ SideEffectPrevSibling,
53
+ /// Invalidating for side effect of a DOM operation, for the next sibling.
54
+ SideEffectNextSibling,
55
+ }
56
+
57
+ impl DomMutationOperation {
58
+ fn accept<E: TElement>(&self, d: &Dependency, e: E) -> bool {
59
+ match self {
60
+ Self::Insert | Self::Append | Self::Remove => {
61
+ !e.relative_selector_search_direction().is_empty()
62
+ },
63
+ // `:has(+ .a + .b)` with `.anchor + .a + .remove + .b` - `.a` would be present
64
+ // in the search path.
65
+ Self::SideEffectPrevSibling => {
66
+ !e.relative_selector_search_direction().is_empty()
67
+ && d.right_combinator_is_next_sibling()
68
+ },
69
+ // If an element is being removed and would cause next-sibling match to happen,
70
+ // e.g. `:has(+ .a)` with `.anchor + .remove + .a`, `.a` isn't yet searched
71
+ // for relative selector matching.
72
+ Self::SideEffectNextSibling => d.dependency_is_relative_with_single_next_sibling(),
73
+ }
74
+ }
75
+
76
+ fn is_side_effect(&self) -> bool {
77
+ match self {
78
+ Self::Insert | Self::Append | Self::Remove => false,
79
+ Self::SideEffectPrevSibling | Self::SideEffectNextSibling => true,
80
+ }
81
+ }
82
+ }
83
+
84
+ /// Context required to try and optimize away relative dependencies.
85
+ struct OptimizationContext<'a, E: TElement> {
86
+ sibling_traversal_map: &'a SiblingTraversalMap<E>,
87
+ quirks_mode: QuirksMode,
88
+ operation: DomMutationOperation,
89
+ }
90
+
91
+ impl<'a, E: TElement> OptimizationContext<'a, E> {
92
+ fn can_be_ignored(
93
+ &self,
94
+ is_subtree: bool,
95
+ element: E,
96
+ host: Option<OpaqueElement>,
97
+ dependency: &Dependency,
98
+ leftmost_collapse_offset: usize,
99
+ ) -> bool {
100
+ if is_subtree {
101
+ // Subtree elements don't have unaffected sibling to look at.
102
+ return false;
103
+ }
104
+ debug_assert!(
105
+ matches!(
106
+ dependency.invalidation_kind(),
107
+ DependencyInvalidationKind::Relative(..)
108
+ ),
109
+ "Non-relative selector being evaluated for optimization"
110
+ );
111
+ // This optimization predecates on the fact that there may be a sibling that can readily
112
+ // "take over" this element.
113
+ let sibling = match self.sibling_traversal_map.prev_sibling_for(&element) {
114
+ None => {
115
+ if matches!(self.operation, DomMutationOperation::Append) {
116
+ return false;
117
+ }
118
+ match self.sibling_traversal_map.next_sibling_for(&element) {
119
+ Some(s) => s,
120
+ None => return false,
121
+ }
122
+ },
123
+ Some(s) => s,
124
+ };
125
+ {
126
+ // Run through the affected compund.
127
+ let iter = dependency.selector.iter_from(dependency.selector_offset);
128
+ for c in iter {
129
+ if c.has_indexed_selector_in_subject() {
130
+ // We do not calculate indices during invalidation as they're wasteful - as a side effect,
131
+ // such selectors always return true, breaking this optimization. Note that we only check
132
+ // this compound only because the check to skip compares against this element's sibling.
133
+ // i.e. Given `:has(:nth-child(2) .foo)`, we'd try to find `.foo`'s sibling, which
134
+ // shares `:nth-child` up the selector.
135
+ return false;
136
+ }
137
+ }
138
+ }
139
+ let dependency_is_rightmost = dependency.selector_offset == 0;
140
+ if !dependency_is_rightmost {
141
+ let combinator = dependency
142
+ .selector
143
+ .combinator_at_match_order(dependency.selector_offset - 1);
144
+ if combinator.is_ancestor() {
145
+ // We can safely ignore these, since we're about to traverse the
146
+ // rest of the affected tree anyway to find the rightmost invalidated element.
147
+ return true;
148
+ }
149
+ if combinator.is_sibling() && matches!(self.operation, DomMutationOperation::Append) {
150
+ // If we're at the top of the DOM tree being mutated, we can ignore it if the
151
+ // operation is append - we know we'll cover all the later siblings and their descendants.
152
+ return true;
153
+ }
154
+ }
155
+
156
+ // We have a situation like `:has(.item .item + .item + .item)`, where the first element in the sibling
157
+ // chain position (i.e. The element matched by the second `.item` from the left) mutates. By the time we
158
+ // get here, we've collapsed the 4 dependencies for each of `.item` position into one at the rightmost
159
+ // position. Before we look for a standin, we need to find which `.item` this element matches - Doing
160
+ // that would generate more work than it saves.
161
+ if dependency_is_rightmost
162
+ && leftmost_collapse_offset != dependency.selector_offset
163
+ && self
164
+ .sibling_traversal_map
165
+ .next_sibling_for(&element)
166
+ .is_some()
167
+ {
168
+ return false;
169
+ }
170
+
171
+ let mut caches = SelectorCaches::default();
172
+ let mut matching_context = MatchingContext::new(
173
+ MatchingMode::Normal,
174
+ None,
175
+ &mut caches,
176
+ self.quirks_mode,
177
+ NeedsSelectorFlags::No,
178
+ MatchingForInvalidation::Yes,
179
+ );
180
+ matching_context.current_host = host;
181
+ let sibling_matches = matches_selector(
182
+ &dependency.selector,
183
+ dependency.selector_offset,
184
+ None,
185
+ &sibling,
186
+ &mut matching_context,
187
+ );
188
+ if sibling_matches {
189
+ // Remember that at this point, we know that the combinator to the right of this
190
+ // compound is a sibling combinator. Effectively, we've found a standin for the
191
+ // element we're mutating.
192
+ // e.g. Given `:has(... .a ~ .b ...)`, we're the mutating element matching `... .a`,
193
+ // if we find a sibling that matches the `... .a`, it can stand in for us.
194
+ debug_assert!(
195
+ dependency.next.is_some(),
196
+ "No relative selector outer dependency?"
197
+ );
198
+ return dependency.next.as_ref().is_some_and(|deps| {
199
+ // ... However, if the standin sibling can be the anchor, we can't skip it, since
200
+ // that sibling should be invlidated to become the anchor.
201
+ let next = &deps.as_ref().slice()[0];
202
+ !matches_selector(
203
+ &next.selector,
204
+ next.selector_offset,
205
+ None,
206
+ &sibling,
207
+ &mut matching_context,
208
+ )
209
+ });
210
+ }
211
+ // Ok, there's no standin element - but would this element have matched the upstream
212
+ // selector anyway? If we don't, either the match exists somewhere far from us
213
+ // (In which case our mutation doesn't really matter), or it doesn't exist at all,
214
+ // so we can just skip the invalidation.
215
+ let (combinator, prev_offset) = {
216
+ let mut iter = dependency.selector.iter_from(dependency.selector_offset);
217
+ let mut o = dependency.selector_offset;
218
+ while iter.next().is_some() {
219
+ o += 1;
220
+ }
221
+ let combinator = iter.next_sequence();
222
+ o += 1;
223
+ debug_assert!(
224
+ combinator.is_some(),
225
+ "Should at least see a relative combinator"
226
+ );
227
+ (combinator.unwrap(), o)
228
+ };
229
+ if combinator.is_sibling() && prev_offset >= dependency.selector.len() - 1 {
230
+ // Hit the relative combinator - we don't have enough information to
231
+ // see if there's going to be a downstream match.
232
+ return false;
233
+ }
234
+ !matches_selector(
235
+ &dependency.selector,
236
+ dependency.selector_offset,
237
+ None,
238
+ &element,
239
+ &mut matching_context,
240
+ )
241
+ }
242
+ }
243
+
244
+ /// Overall invalidator for handling relative selector invalidations.
245
+ pub struct RelativeSelectorInvalidator<'a, 'b, E>
246
+ where
247
+ E: TElement + 'a,
248
+ {
249
+ /// Element triggering the invalidation.
250
+ pub element: E,
251
+ /// Quirks mode of the current invalidation.
252
+ pub quirks_mode: QuirksMode,
253
+ /// Snapshot containing changes to invalidate against.
254
+ /// Can be None if it's a DOM mutation.
255
+ pub snapshot_table: Option<&'b ServoElementSnapshotTable>,
256
+ /// Callback to trigger when the subject element is invalidated.
257
+ pub invalidated: fn(E, &InvalidationResult),
258
+ /// The traversal map that should be used to process invalidations.
259
+ pub sibling_traversal_map: SiblingTraversalMap<E>,
260
+ /// Marker for 'a lifetime.
261
+ pub _marker: ::std::marker::PhantomData<&'a ()>,
262
+ }
263
+
264
+ struct RelativeSelectorInvalidation<'a> {
265
+ host: Option<OpaqueElement>,
266
+ kind: RelativeDependencyInvalidationKind,
267
+ dependency: &'a Dependency,
268
+ }
269
+
270
+ type ElementDependencies<'a> = SmallVec<[(Option<OpaqueElement>, &'a Dependency); 1]>;
271
+ type Dependencies<'a, E> = SmallVec<[(E, ElementDependencies<'a>); 1]>;
272
+ type AlreadyInvalidated<'a, E> = SmallVec<[AlreadyInvalidatedEntry<'a, E>; 2]>;
273
+
274
+ struct AlreadyInvalidatedEntry<'a, E>
275
+ where
276
+ E: TElement + 'a,
277
+ {
278
+ /// Element where the invalidation will begin.
279
+ element: E,
280
+ /// The current shadow host.
281
+ host: Option<OpaqueElement>,
282
+ /// Dependency chain for this invalidation.
283
+ dependency: &'a Dependency,
284
+ /// The offset, of the leftmost dependencies that this
285
+ /// invalidation collapsed. See the `update()` function
286
+ /// for more information.
287
+ leftmost_collapse_offset: usize,
288
+ }
289
+
290
+ impl<'a, E> AlreadyInvalidatedEntry<'a, E>
291
+ where
292
+ E: TElement + 'a,
293
+ {
294
+ fn new(element: E, host: Option<OpaqueElement>, dependency: &'a Dependency) -> Self {
295
+ Self {
296
+ element,
297
+ host,
298
+ dependency,
299
+ leftmost_collapse_offset: dependency.selector_offset,
300
+ }
301
+ }
302
+
303
+ /// Update this invalidation with a new invalidation that may collapse with it.
304
+ fn update(&mut self, element: E, host: Option<OpaqueElement>, dependency: &'a Dependency) {
305
+ // This dependency should invalidate the same way - Collapse the invalidation
306
+ // to a more general case so we don't do duplicate work.
307
+ // e.g. For `:has(.item .item + .item + .item)`, since the anchor would be located
308
+ // in the ancestor chain for any invalidation triggered by any `.item` compound,
309
+ // 4 entries can collapse into one - but keep track of the leftmost offset.
310
+ if self.dependency.selector_offset > dependency.selector_offset {
311
+ *self = Self {
312
+ element,
313
+ host,
314
+ dependency,
315
+ leftmost_collapse_offset: self.leftmost_collapse_offset,
316
+ };
317
+ } else if self.leftmost_collapse_offset < dependency.selector_offset {
318
+ self.leftmost_collapse_offset = dependency.selector_offset;
319
+ }
320
+ }
321
+ }
322
+
323
+ /// Interface for collecting relative selector dependencies.
324
+ pub struct RelativeSelectorDependencyCollector<'a, E>
325
+ where
326
+ E: TElement,
327
+ {
328
+ /// Dependencies that need to run through the normal invalidation that may generate
329
+ /// a relative selector invalidation.
330
+ dependencies: FxHashMap<E, ElementDependencies<'a>>,
331
+ /// Dependencies that created an invalidation right away.
332
+ invalidations: AlreadyInvalidated<'a, E>,
333
+ /// The top element in the subtree being invalidated.
334
+ top: E,
335
+ /// Optional context that will be used to try and skip invalidations
336
+ /// by running selector matches.
337
+ optimization_context: Option<OptimizationContext<'a, E>>,
338
+ }
339
+
340
+ type Invalidations<'a> = SmallVec<[RelativeSelectorInvalidation<'a>; 1]>;
341
+ type InnerInvalidations<'a, E> = SmallVec<[(E, RelativeSelectorInvalidation<'a>); 1]>;
342
+
343
+ struct ToInvalidate<'a, E: TElement + 'a> {
344
+ /// Dependencies to run through normal invalidator.
345
+ dependencies: Dependencies<'a, E>,
346
+ /// Dependencies already invalidated.
347
+ invalidations: Invalidations<'a>,
348
+ }
349
+
350
+ impl<'a, E: TElement + 'a> Default for ToInvalidate<'a, E> {
351
+ fn default() -> Self {
352
+ Self {
353
+ dependencies: Dependencies::default(),
354
+ invalidations: Invalidations::default(),
355
+ }
356
+ }
357
+ }
358
+
359
+ fn invalidation_can_collapse(
360
+ a: &Dependency,
361
+ b: &Dependency,
362
+ allow_indexed_selectors: bool,
363
+ ) -> bool {
364
+ // We want to detect identical dependencies that occur at different
365
+ // compounds but has the identical compound in the same selector,
366
+ // e.g. :has(.item .item).
367
+
368
+ // If they trigger different invalidations, they shouldn't be collapsed.
369
+ if a.relative_invalidation_kind() != b.relative_invalidation_kind() {
370
+ return false;
371
+ }
372
+
373
+ // Not in the same selector, trivially skipped.
374
+ if SelectorKey::new(&a.selector) != SelectorKey::new(&b.selector) {
375
+ return false;
376
+ }
377
+
378
+ // Check that this is in the same nesting.
379
+ // TODO(dshin): @scope probably brings more subtleties...
380
+ let mut a_next = a.next.as_ref();
381
+ let mut b_next = b.next.as_ref();
382
+ while let (Some(a_deps), Some(b_deps)) = (a_next, b_next) {
383
+ // This is a bit subtle - but we don't need to do the checks we do at higher levels.
384
+ // Cases like `:is(.item .foo) :is(.item .foo)` where `.item` invalidates would
385
+ // point to different dependencies, pointing to the same outer selector, but
386
+ // differing in selector offset.
387
+ let a_nexts = a_deps.as_ref().slice();
388
+ let b_nexts = b_deps.as_ref().slice();
389
+ if a_nexts.is_empty() || b_nexts.is_empty() {
390
+ // Can happen when we get out to empty @scope() rules.
391
+ // If they're both empty, we can just do nothing for both.
392
+ return a_nexts.is_empty() == b_nexts.is_empty();
393
+ }
394
+ let a_n = &a_nexts[0];
395
+ let b_n = &b_nexts[0];
396
+ if SelectorKey::new(&a_n.selector) != SelectorKey::new(&b_n.selector) {
397
+ return false;
398
+ }
399
+ a_next = a_n.next.as_ref();
400
+ b_next = b_n.next.as_ref();
401
+ }
402
+ if a_next.is_some() || b_next.is_some() {
403
+ return false;
404
+ }
405
+
406
+ // Ok, now, do the compounds actually match?
407
+ // This can get expensive quickly, but we're assuming that:
408
+ //
409
+ // * In most cases, authors don't generally duplicate compounds in a selector, so
410
+ // this fails quickly
411
+ // * In cases where compounds are duplicated, reducing the number of invalidations
412
+ // has a payoff that offsets the comparison cost
413
+ //
414
+ // Note, `.a.b` != `.b.a` - doesn't affect correctness, though.
415
+ // TODO(dshin): Caching this may be worth it as well?
416
+ let mut a_iter = a.selector.iter_from(a.selector_offset);
417
+ let mut b_iter = b.selector.iter_from(b.selector_offset);
418
+ loop {
419
+ let a_component = a_iter.next();
420
+ let b_component = b_iter.next();
421
+
422
+ if a_component != b_component {
423
+ return false;
424
+ }
425
+ let Some(component) = a_component else {
426
+ return true;
427
+ };
428
+ if !allow_indexed_selectors && component.has_indexed_selector_in_subject() {
429
+ // The element's positioning matters, so can't collapse.
430
+ return false;
431
+ }
432
+ }
433
+ }
434
+
435
+ impl<'a, E> RelativeSelectorDependencyCollector<'a, E>
436
+ where
437
+ E: TElement,
438
+ {
439
+ fn new(top: E, optimization_context: Option<OptimizationContext<'a, E>>) -> Self {
440
+ Self {
441
+ dependencies: FxHashMap::default(),
442
+ invalidations: AlreadyInvalidated::default(),
443
+ top,
444
+ optimization_context,
445
+ }
446
+ }
447
+
448
+ fn insert_invalidation(
449
+ &mut self,
450
+ element: E,
451
+ dependency: &'a Dependency,
452
+ host: Option<OpaqueElement>,
453
+ ) {
454
+ let in_subtree = element != self.top;
455
+ if let Some(entry) = self.invalidations.iter_mut().find(|entry| {
456
+ // If we're in the subtree of DOM manipulation - worrying the about positioning of this element
457
+ // is irrelevant, because the DOM structure is either completely new or about to go away.
458
+ let both_in_subtree = in_subtree && entry.element != self.top;
459
+ // If we're considering the same element for invalidation, their evaluation of the indexed selector
460
+ // is identical by definition.
461
+ let same_element = element == entry.element;
462
+ invalidation_can_collapse(
463
+ dependency,
464
+ entry.dependency,
465
+ both_in_subtree || same_element,
466
+ )
467
+ }) {
468
+ entry.update(element, host, dependency)
469
+ } else {
470
+ self.invalidations
471
+ .push(AlreadyInvalidatedEntry::new(element, host, dependency));
472
+ }
473
+ }
474
+
475
+ /// Add this dependency, if it is unique (i.e. Different outer dependency or same outer dependency
476
+ /// but requires a different invalidation traversal).
477
+ pub fn add_dependency(
478
+ &mut self,
479
+ dependency: &'a Dependency,
480
+ element: E,
481
+ host: Option<OpaqueElement>,
482
+ ) {
483
+ match dependency.invalidation_kind() {
484
+ DependencyInvalidationKind::FullSelector => unreachable!(),
485
+ DependencyInvalidationKind::Normal(..) | DependencyInvalidationKind::Scope(..) => {
486
+ self.dependencies
487
+ .entry(element)
488
+ .or_default()
489
+ .push((host, dependency));
490
+ },
491
+ DependencyInvalidationKind::Relative(kind) => {
492
+ debug_assert!(
493
+ dependency.next.is_some(),
494
+ "Orphaned inner relative selector?"
495
+ );
496
+ if element != self.top
497
+ && matches!(
498
+ kind,
499
+ RelativeDependencyInvalidationKind::Parent
500
+ | RelativeDependencyInvalidationKind::PrevSibling
501
+ | RelativeDependencyInvalidationKind::EarlierSibling
502
+ )
503
+ {
504
+ return;
505
+ }
506
+ if early_reject_by_local_name(
507
+ &dependency.selector,
508
+ dependency.selector_offset,
509
+ &element,
510
+ ) {
511
+ return;
512
+ }
513
+ self.insert_invalidation(element, dependency, host);
514
+ },
515
+ };
516
+ }
517
+
518
+ /// Get the dependencies in a list format.
519
+ fn get(self) -> ToInvalidate<'a, E> {
520
+ let mut result = ToInvalidate::default();
521
+ for invalidation in self.invalidations {
522
+ match invalidation.dependency.invalidation_kind() {
523
+ DependencyInvalidationKind::FullSelector => unreachable!(),
524
+ DependencyInvalidationKind::Normal(_) | DependencyInvalidationKind::Scope(_) => {
525
+ unreachable!("Inner selector in invalidation?")
526
+ },
527
+ DependencyInvalidationKind::Relative(kind) => {
528
+ if let Some(context) = self.optimization_context.as_ref() {
529
+ if context.can_be_ignored(
530
+ invalidation.element != self.top,
531
+ invalidation.element,
532
+ invalidation.host,
533
+ invalidation.dependency,
534
+ invalidation.leftmost_collapse_offset,
535
+ ) {
536
+ continue;
537
+ }
538
+ }
539
+ let dependency = &invalidation.dependency.next.as_ref().unwrap().slice()[0];
540
+ result.invalidations.push(RelativeSelectorInvalidation {
541
+ kind,
542
+ host: invalidation.host,
543
+ dependency,
544
+ });
545
+ // We move the invalidation up to the top of the subtree to avoid unnecessary traveral, but
546
+ // this means that we need to take ancestor-earlier sibling invalidations into account, as
547
+ // they'd look into earlier siblings of the top of the subtree as well.
548
+ if invalidation.element != self.top
549
+ && matches!(
550
+ kind,
551
+ RelativeDependencyInvalidationKind::AncestorEarlierSibling
552
+ | RelativeDependencyInvalidationKind::AncestorPrevSibling
553
+ )
554
+ {
555
+ result.invalidations.push(RelativeSelectorInvalidation {
556
+ kind: if matches!(
557
+ kind,
558
+ RelativeDependencyInvalidationKind::AncestorPrevSibling
559
+ ) {
560
+ RelativeDependencyInvalidationKind::PrevSibling
561
+ } else {
562
+ RelativeDependencyInvalidationKind::EarlierSibling
563
+ },
564
+ host: invalidation.host,
565
+ dependency,
566
+ });
567
+ }
568
+ },
569
+ };
570
+ }
571
+ for (key, element_dependencies) in self.dependencies {
572
+ // At least for now, we don't try to optimize away dependencies emitted from nested selectors.
573
+ result.dependencies.push((key, element_dependencies));
574
+ }
575
+ result
576
+ }
577
+
578
+ fn collect_all_dependencies_for_element(
579
+ &mut self,
580
+ element: E,
581
+ scope: Option<OpaqueElement>,
582
+ quirks_mode: QuirksMode,
583
+ map: &'a InvalidationMap,
584
+ additional_relative_selector_invalidation_map: &'a AdditionalRelativeSelectorInvalidationMap,
585
+ operation: DomMutationOperation,
586
+ ) {
587
+ element.id().map(|v| {
588
+ if let Some(v) = map.id_to_selector.get(v, quirks_mode) {
589
+ for dependency in v {
590
+ if !operation.accept(dependency, element) {
591
+ continue;
592
+ }
593
+ self.add_dependency(dependency, element, scope);
594
+ }
595
+ }
596
+ });
597
+ element.each_class(|v| {
598
+ if let Some(v) = map.class_to_selector.get(v, quirks_mode) {
599
+ for dependency in v {
600
+ if !operation.accept(dependency, element) {
601
+ continue;
602
+ }
603
+ self.add_dependency(dependency, element, scope);
604
+ }
605
+ }
606
+ });
607
+ element.each_custom_state(|v| {
608
+ if let Some(v) = map.custom_state_affecting_selectors.get(v) {
609
+ for dependency in v {
610
+ if !operation.accept(dependency, element) {
611
+ continue;
612
+ }
613
+ self.add_dependency(dependency, element, scope);
614
+ }
615
+ }
616
+ });
617
+ element.each_attr_name(|v| {
618
+ if let Some(v) = map.other_attribute_affecting_selectors.get(v) {
619
+ for dependency in v {
620
+ if !operation.accept(dependency, element) {
621
+ continue;
622
+ }
623
+ self.add_dependency(dependency, element, scope);
624
+ }
625
+ }
626
+ });
627
+ let state = element.state();
628
+ map.state_affecting_selectors.lookup_with_additional(
629
+ element,
630
+ quirks_mode,
631
+ None,
632
+ &[],
633
+ ElementState::empty(),
634
+ |dependency| {
635
+ if !dependency.state.intersects(state) {
636
+ return true;
637
+ }
638
+ if !operation.accept(&dependency.dep, element) {
639
+ return true;
640
+ }
641
+ self.add_dependency(&dependency.dep, element, scope);
642
+ true
643
+ },
644
+ );
645
+
646
+ additional_relative_selector_invalidation_map
647
+ .ts_state_to_selector
648
+ .lookup_with_additional(
649
+ element,
650
+ quirks_mode,
651
+ None,
652
+ &[],
653
+ ElementState::empty(),
654
+ |dependency| {
655
+ if !operation.accept(&dependency.dep, element) {
656
+ return true;
657
+ }
658
+ // This section contain potential optimization for not running full invalidation -
659
+ // consult documentation in `TSStateForInvalidation`.
660
+ if dependency.state.may_be_optimized() {
661
+ if operation.is_side_effect() {
662
+ // Side effect operations act on element not being mutated, so they can't
663
+ // change the match outcome of these optimizable pseudoclasses.
664
+ return true;
665
+ }
666
+ debug_assert!(
667
+ self.optimization_context.is_some(),
668
+ "Optimization context not available for DOM mutation?"
669
+ );
670
+ if dependency.state.contains(TSStateForInvalidation::EMPTY)
671
+ && element.first_element_child().is_some()
672
+ {
673
+ return true;
674
+ }
675
+
676
+ let sibling_traversal_map = self
677
+ .optimization_context
678
+ .as_ref()
679
+ .unwrap()
680
+ .sibling_traversal_map;
681
+ if dependency
682
+ .state
683
+ .contains(TSStateForInvalidation::NTH_EDGE_FIRST)
684
+ && sibling_traversal_map.prev_sibling_for(&element).is_some()
685
+ {
686
+ return true;
687
+ }
688
+
689
+ if dependency
690
+ .state
691
+ .contains(TSStateForInvalidation::NTH_EDGE_LAST)
692
+ && sibling_traversal_map.next_sibling_for(&element).is_some()
693
+ {
694
+ return true;
695
+ }
696
+ }
697
+ self.add_dependency(&dependency.dep, element, scope);
698
+ true
699
+ },
700
+ );
701
+
702
+ if let Some(v) = additional_relative_selector_invalidation_map
703
+ .type_to_selector
704
+ .get(element.local_name())
705
+ {
706
+ for dependency in v {
707
+ if !operation.accept(dependency, element) {
708
+ continue;
709
+ }
710
+ self.add_dependency(dependency, element, scope);
711
+ }
712
+ }
713
+
714
+ for dependency in &additional_relative_selector_invalidation_map.any_to_selector {
715
+ if !operation.accept(dependency, element) {
716
+ continue;
717
+ }
718
+ self.add_dependency(dependency, element, scope);
719
+ }
720
+ }
721
+
722
+ fn is_empty(&self) -> bool {
723
+ self.invalidations.is_empty() && self.dependencies.is_empty()
724
+ }
725
+ }
726
+
727
+ impl<'a, 'b, E> RelativeSelectorInvalidator<'a, 'b, E>
728
+ where
729
+ E: TElement + 'a,
730
+ {
731
+ /// Gather relative selector dependencies for the given element, and invalidate as necessary.
732
+ #[inline(never)]
733
+ pub fn invalidate_relative_selectors_for_this<F>(
734
+ self,
735
+ stylist: &'a Stylist,
736
+ mut gather_dependencies: F,
737
+ ) where
738
+ F: FnMut(
739
+ &E,
740
+ Option<OpaqueElement>,
741
+ &'a CascadeData,
742
+ QuirksMode,
743
+ &mut RelativeSelectorDependencyCollector<'a, E>,
744
+ ),
745
+ {
746
+ let mut collector = RelativeSelectorDependencyCollector::new(self.element, None);
747
+ stylist.for_each_cascade_data_with_scope(self.element, |data, scope| {
748
+ let map = data.relative_invalidation_map_attributes();
749
+ if !map.used {
750
+ return;
751
+ }
752
+ gather_dependencies(
753
+ &self.element,
754
+ scope.map(|e| e.opaque()),
755
+ data,
756
+ self.quirks_mode,
757
+ &mut collector,
758
+ );
759
+ });
760
+ if collector.is_empty() {
761
+ return;
762
+ }
763
+ self.invalidate_from_dependencies(collector.get());
764
+ }
765
+
766
+ /// Gather relative selector dependencies for the given element (And its subtree) that mutated, and invalidate as necessary.
767
+ #[inline(never)]
768
+ pub fn invalidate_relative_selectors_for_dom_mutation(
769
+ self,
770
+ subtree: bool,
771
+ stylist: &'a Stylist,
772
+ inherited_search_path: ElementSelectorFlags,
773
+ operation: DomMutationOperation,
774
+ ) {
775
+ let mut collector = RelativeSelectorDependencyCollector::new(
776
+ self.element,
777
+ if operation.is_side_effect() {
778
+ None
779
+ } else {
780
+ Some(OptimizationContext {
781
+ sibling_traversal_map: &self.sibling_traversal_map,
782
+ quirks_mode: self.quirks_mode,
783
+ operation,
784
+ })
785
+ },
786
+ );
787
+ let mut traverse_subtree = false;
788
+ self.element.apply_selector_flags(inherited_search_path);
789
+ stylist.for_each_cascade_data_with_scope(self.element, |data, scope| {
790
+ let map_attributes = data.relative_invalidation_map_attributes();
791
+ if !map_attributes.used {
792
+ return;
793
+ }
794
+ let map = data.relative_selector_invalidation_map();
795
+ traverse_subtree |= map_attributes.needs_ancestors_traversal;
796
+ collector.collect_all_dependencies_for_element(
797
+ self.element,
798
+ scope.map(|e| e.opaque()),
799
+ self.quirks_mode,
800
+ map,
801
+ map_attributes,
802
+ operation,
803
+ );
804
+ });
805
+
806
+ if subtree && traverse_subtree {
807
+ for node in self.element.as_node().dom_descendants() {
808
+ let descendant = match node.as_element() {
809
+ Some(e) => e,
810
+ None => continue,
811
+ };
812
+ descendant.apply_selector_flags(inherited_search_path);
813
+ stylist.for_each_cascade_data_with_scope(descendant, |data, scope| {
814
+ let map_attributes = data.relative_invalidation_map_attributes();
815
+ if !map_attributes.used {
816
+ return;
817
+ }
818
+ let map = data.relative_selector_invalidation_map();
819
+ collector.collect_all_dependencies_for_element(
820
+ descendant,
821
+ scope.map(|e| e.opaque()),
822
+ self.quirks_mode,
823
+ map,
824
+ map_attributes,
825
+ operation,
826
+ );
827
+ });
828
+ }
829
+ }
830
+ if collector.is_empty() {
831
+ return;
832
+ }
833
+ self.invalidate_from_dependencies(collector.get());
834
+ }
835
+
836
+ /// Carry out complete invalidation triggered by a relative selector invalidation.
837
+ fn invalidate_from_dependencies(&self, to_invalidate: ToInvalidate<'a, E>) {
838
+ for (element, dependencies) in to_invalidate.dependencies {
839
+ let mut selector_caches = SelectorCaches::default();
840
+ let mut processor = RelativeSelectorInnerInvalidationProcessor::new(
841
+ self.quirks_mode,
842
+ self.snapshot_table,
843
+ &dependencies,
844
+ &mut selector_caches,
845
+ &self.sibling_traversal_map,
846
+ );
847
+ TreeStyleInvalidator::new(element, None, &mut processor).invalidate();
848
+ for (element, invalidation) in processor.take_invalidations() {
849
+ self.invalidate_upwards(element, &invalidation);
850
+ }
851
+ }
852
+ for invalidation in to_invalidate.invalidations {
853
+ self.invalidate_upwards(self.element, &invalidation);
854
+ }
855
+ }
856
+
857
+ fn invalidate_upwards(&self, element: E, invalidation: &RelativeSelectorInvalidation<'a>) {
858
+ // This contains the main reason for why relative selector invalidation is handled
859
+ // separately - It travels ancestor and/or earlier sibling direction.
860
+ match invalidation.kind {
861
+ RelativeDependencyInvalidationKind::Parent => {
862
+ element.parent_element().map(|e| {
863
+ if !Self::in_search_direction(
864
+ &e,
865
+ ElementSelectorFlags::RELATIVE_SELECTOR_SEARCH_DIRECTION_ANCESTOR,
866
+ ) {
867
+ return;
868
+ }
869
+ self.handle_anchor(e, invalidation.dependency, invalidation.host);
870
+ });
871
+ },
872
+ RelativeDependencyInvalidationKind::Ancestors => {
873
+ let mut parent = element.parent_element();
874
+ while let Some(par) = parent {
875
+ if !Self::in_search_direction(
876
+ &par,
877
+ ElementSelectorFlags::RELATIVE_SELECTOR_SEARCH_DIRECTION_ANCESTOR,
878
+ ) {
879
+ return;
880
+ }
881
+ self.handle_anchor(par, invalidation.dependency, invalidation.host);
882
+ parent = par.parent_element();
883
+ }
884
+ },
885
+ RelativeDependencyInvalidationKind::PrevSibling => {
886
+ self.sibling_traversal_map
887
+ .prev_sibling_for(&element)
888
+ .map(|e| {
889
+ if !Self::in_search_direction(
890
+ &e,
891
+ ElementSelectorFlags::RELATIVE_SELECTOR_SEARCH_DIRECTION_SIBLING,
892
+ ) {
893
+ return;
894
+ }
895
+ self.handle_anchor(e, invalidation.dependency, invalidation.host);
896
+ });
897
+ },
898
+ RelativeDependencyInvalidationKind::AncestorPrevSibling => {
899
+ let mut parent = element.parent_element();
900
+ while let Some(par) = parent {
901
+ if !Self::in_search_direction(
902
+ &par,
903
+ ElementSelectorFlags::RELATIVE_SELECTOR_SEARCH_DIRECTION_ANCESTOR,
904
+ ) {
905
+ return;
906
+ }
907
+ par.prev_sibling_element().map(|e| {
908
+ if !Self::in_search_direction(
909
+ &e,
910
+ ElementSelectorFlags::RELATIVE_SELECTOR_SEARCH_DIRECTION_SIBLING,
911
+ ) {
912
+ return;
913
+ }
914
+ self.handle_anchor(e, invalidation.dependency, invalidation.host);
915
+ });
916
+ parent = par.parent_element();
917
+ }
918
+ },
919
+ RelativeDependencyInvalidationKind::EarlierSibling => {
920
+ let mut sibling = self.sibling_traversal_map.prev_sibling_for(&element);
921
+ while let Some(sib) = sibling {
922
+ if !Self::in_search_direction(
923
+ &sib,
924
+ ElementSelectorFlags::RELATIVE_SELECTOR_SEARCH_DIRECTION_SIBLING,
925
+ ) {
926
+ return;
927
+ }
928
+ self.handle_anchor(sib, invalidation.dependency, invalidation.host);
929
+ sibling = sib.prev_sibling_element();
930
+ }
931
+ },
932
+ RelativeDependencyInvalidationKind::AncestorEarlierSibling => {
933
+ let mut parent = element.parent_element();
934
+ while let Some(par) = parent {
935
+ if !Self::in_search_direction(
936
+ &par,
937
+ ElementSelectorFlags::RELATIVE_SELECTOR_SEARCH_DIRECTION_ANCESTOR,
938
+ ) {
939
+ return;
940
+ }
941
+ let mut sibling = par.prev_sibling_element();
942
+ while let Some(sib) = sibling {
943
+ if !Self::in_search_direction(
944
+ &sib,
945
+ ElementSelectorFlags::RELATIVE_SELECTOR_SEARCH_DIRECTION_SIBLING,
946
+ ) {
947
+ return;
948
+ }
949
+ self.handle_anchor(sib, invalidation.dependency, invalidation.host);
950
+ sibling = sib.prev_sibling_element();
951
+ }
952
+ parent = par.parent_element();
953
+ }
954
+ },
955
+ }
956
+ }
957
+
958
+ /// Is this element in the direction of the given relative selector search path?
959
+ fn in_search_direction(element: &E, desired: ElementSelectorFlags) -> bool {
960
+ element
961
+ .relative_selector_search_direction()
962
+ .intersects(desired)
963
+ }
964
+
965
+ /// Handle a potential relative selector anchor.
966
+ fn handle_anchor(
967
+ &self,
968
+ element: E,
969
+ outer_dependency: &Dependency,
970
+ host: Option<OpaqueElement>,
971
+ ) {
972
+ let is_rightmost = Self::is_subject(outer_dependency);
973
+ if (is_rightmost
974
+ && !element.has_selector_flags(ElementSelectorFlags::ANCHORS_RELATIVE_SELECTOR))
975
+ || (!is_rightmost
976
+ && !element.has_selector_flags(
977
+ ElementSelectorFlags::ANCHORS_RELATIVE_SELECTOR_NON_SUBJECT,
978
+ ))
979
+ {
980
+ // If it was never a relative selector anchor, don't bother.
981
+ return;
982
+ }
983
+ let mut selector_caches = SelectorCaches::default();
984
+ let matching_context = MatchingContext::<'_, E::Impl>::new_for_visited(
985
+ MatchingMode::Normal,
986
+ None,
987
+ &mut selector_caches,
988
+ VisitedHandlingMode::AllLinksVisitedAndUnvisited,
989
+ self.quirks_mode,
990
+ NeedsSelectorFlags::No,
991
+ MatchingForInvalidation::Yes,
992
+ );
993
+ let mut data = match element.mutate_data() {
994
+ Some(data) => data,
995
+ None => return,
996
+ };
997
+ let mut processor = RelativeSelectorOuterInvalidationProcessor {
998
+ element,
999
+ host,
1000
+ data: data.deref_mut(),
1001
+ dependency: outer_dependency,
1002
+ matching_context,
1003
+ traversal_map: &self.sibling_traversal_map,
1004
+ };
1005
+ let result = TreeStyleInvalidator::new(element, None, &mut processor).invalidate();
1006
+ (self.invalidated)(element, &result);
1007
+ }
1008
+
1009
+ /// Does this relative selector dependency have its relative selector in the subject position?
1010
+ fn is_subject(outer_dependency: &Dependency) -> bool {
1011
+ debug_assert!(
1012
+ matches!(
1013
+ outer_dependency.invalidation_kind(),
1014
+ DependencyInvalidationKind::Normal(_) | DependencyInvalidationKind::Scope(_)
1015
+ ),
1016
+ "Outer selector of relative selector is relative?"
1017
+ );
1018
+
1019
+ if let Some(x) = outer_dependency.next.as_ref() {
1020
+ // We only care to ensure that we're the subject in the outermost selector of the current
1021
+ // selector - Crossing over a scope invalidation would mean moving into a selector inside
1022
+ // the current scope block
1023
+ if matches!(
1024
+ outer_dependency.invalidation_kind(),
1025
+ DependencyInvalidationKind::Normal(..)
1026
+ ) && !Self::is_subject(&x.as_ref().slice()[0])
1027
+ {
1028
+ // Not subject in outer selector.
1029
+ return false;
1030
+ }
1031
+ }
1032
+ outer_dependency
1033
+ .selector
1034
+ .is_rightmost(outer_dependency.selector_offset)
1035
+ }
1036
+ }
1037
+
1038
+ /// Blindly invalidate everything outside of a relative selector.
1039
+ /// Consider `:is(.a :has(.b) .c ~ .d) ~ .e .f`, where .b gets deleted.
1040
+ /// Since the tree mutated, we cannot rely on snapshots.
1041
+ pub struct RelativeSelectorOuterInvalidationProcessor<'a, 'b, E: TElement> {
1042
+ /// Element being invalidated.
1043
+ pub element: E,
1044
+ /// The current shadow host, if any.
1045
+ pub host: Option<OpaqueElement>,
1046
+ /// Data for the element being invalidated.
1047
+ pub data: &'a mut ElementData,
1048
+ /// Dependency to be processed.
1049
+ pub dependency: &'b Dependency,
1050
+ /// Matching context to use for invalidation.
1051
+ pub matching_context: MatchingContext<'a, E::Impl>,
1052
+ /// Traversal map for this invalidation.
1053
+ pub traversal_map: &'a SiblingTraversalMap<E>,
1054
+ }
1055
+
1056
+ impl<'a, 'b: 'a, E: 'a> InvalidationProcessor<'b, 'a, E>
1057
+ for RelativeSelectorOuterInvalidationProcessor<'a, 'b, E>
1058
+ where
1059
+ E: TElement,
1060
+ {
1061
+ fn invalidates_on_pseudo_element(&self) -> bool {
1062
+ true
1063
+ }
1064
+
1065
+ fn check_outer_dependency(
1066
+ &mut self,
1067
+ _dependency: &Dependency,
1068
+ _element: E,
1069
+ _: Option<OpaqueElement>,
1070
+ ) -> bool {
1071
+ // At this point, we know a relative selector invalidated, and are ignoring them.
1072
+ true
1073
+ }
1074
+
1075
+ fn matching_context(&mut self) -> &mut MatchingContext<'a, E::Impl> {
1076
+ &mut self.matching_context
1077
+ }
1078
+
1079
+ fn sibling_traversal_map(&self) -> &SiblingTraversalMap<E> {
1080
+ self.traversal_map
1081
+ }
1082
+
1083
+ fn collect_invalidations(
1084
+ &mut self,
1085
+ element: E,
1086
+ _self_invalidations: &mut InvalidationVector<'b>,
1087
+ descendant_invalidations: &mut DescendantInvalidationLists<'b>,
1088
+ sibling_invalidations: &mut InvalidationVector<'b>,
1089
+ ) -> bool {
1090
+ debug_assert_eq!(element, self.element);
1091
+ debug_assert!(
1092
+ self.matching_context.matching_for_invalidation(),
1093
+ "Not matching for invalidation?"
1094
+ );
1095
+
1096
+ // Ok, this element can potentially an anchor to the given dependency.
1097
+ // Before we do the potentially-costly ancestor/earlier sibling traversal,
1098
+ // See if it can actuall be an anchor by trying to match the "rest" of the selector
1099
+ // outside and to the left of `:has` in question.
1100
+ // e.g. Element under consideration can only be the anchor to `:has` in
1101
+ // `.foo .bar ~ .baz:has()`, iff it matches `.foo .bar ~ .baz`.
1102
+ let invalidated_self = {
1103
+ let mut invalidated = false;
1104
+ let mut dependencies_to_invalidate: SmallVec<[&Dependency; 1]> =
1105
+ smallvec![self.dependency];
1106
+ while let Some(d) = dependencies_to_invalidate.pop() {
1107
+ debug_assert!(
1108
+ matches!(
1109
+ d.invalidation_kind(),
1110
+ DependencyInvalidationKind::Normal(_)
1111
+ | DependencyInvalidationKind::Scope(_)
1112
+ ),
1113
+ "Unexpected dependency kind"
1114
+ );
1115
+ if !dependency_may_be_relevant(d, &element, false) {
1116
+ continue;
1117
+ }
1118
+ if !matches_selector(
1119
+ &d.selector,
1120
+ d.selector_offset,
1121
+ None,
1122
+ &element,
1123
+ self.matching_context(),
1124
+ ) {
1125
+ continue;
1126
+ }
1127
+
1128
+ let invalidation_kind = d.invalidation_kind();
1129
+
1130
+ if let DependencyInvalidationKind::Scope(scope_kind) = invalidation_kind {
1131
+ if d.selector.is_rightmost(d.selector_offset) {
1132
+ if scope_kind == ScopeDependencyInvalidationKind::ScopeEnd {
1133
+ let invalidations = note_scope_dependency_force_at_subject(
1134
+ d,
1135
+ self.matching_context.current_host,
1136
+ self.matching_context.scope_element,
1137
+ false,
1138
+ );
1139
+ descendant_invalidations
1140
+ .dom_descendants
1141
+ .extend(invalidations);
1142
+
1143
+ invalidated |= true;
1144
+ } else if let Some(ref next) = d.next {
1145
+ dependencies_to_invalidate.extend(next.as_ref().slice());
1146
+ }
1147
+ continue;
1148
+ }
1149
+ }
1150
+
1151
+ if matches!(
1152
+ invalidation_kind,
1153
+ DependencyInvalidationKind::Normal(NormalDependencyInvalidationKind::Element)
1154
+ ) {
1155
+ if let Some(ref deps) = d.next {
1156
+ // Normal dependencies should only have one next
1157
+ dependencies_to_invalidate.push(&deps.as_ref().slice()[0]);
1158
+ continue;
1159
+ }
1160
+ invalidated |= true;
1161
+ continue;
1162
+ }
1163
+ debug_assert_ne!(d.selector_offset, 0);
1164
+ debug_assert_ne!(d.selector_offset, d.selector.len());
1165
+ let invalidation = Invalidation::new(d, self.host, None);
1166
+ invalidated |= push_invalidation(
1167
+ invalidation,
1168
+ d.invalidation_kind(),
1169
+ descendant_invalidations,
1170
+ sibling_invalidations,
1171
+ );
1172
+ }
1173
+ invalidated
1174
+ };
1175
+
1176
+ if invalidated_self {
1177
+ self.data.hint.insert(RestyleHint::RESTYLE_SELF);
1178
+ }
1179
+ invalidated_self
1180
+ }
1181
+
1182
+ fn should_process_descendants(&mut self, element: E) -> bool {
1183
+ if element == self.element {
1184
+ return should_process_descendants(self.data);
1185
+ }
1186
+
1187
+ match element.borrow_data() {
1188
+ Some(d) => should_process_descendants(&d),
1189
+ None => false,
1190
+ }
1191
+ }
1192
+
1193
+ fn recursion_limit_exceeded(&mut self, _element: E) {
1194
+ unreachable!("Unexpected recursion limit");
1195
+ }
1196
+
1197
+ fn invalidated_descendants(&mut self, element: E, child: E) {
1198
+ invalidated_descendants(element, child)
1199
+ }
1200
+
1201
+ fn invalidated_self(&mut self, element: E) {
1202
+ debug_assert_ne!(element, self.element);
1203
+ invalidated_self(element);
1204
+ }
1205
+
1206
+ fn invalidated_sibling(&mut self, element: E, of: E) {
1207
+ debug_assert_ne!(element, self.element);
1208
+ invalidated_sibling(element, of);
1209
+ }
1210
+ }
1211
+
1212
+ /// Invalidation for the selector(s) inside a relative selector.
1213
+ pub struct RelativeSelectorInnerInvalidationProcessor<'a, 'b, 'c, E>
1214
+ where
1215
+ E: TElement + 'a,
1216
+ {
1217
+ /// Matching context to be used.
1218
+ matching_context: MatchingContext<'b, E::Impl>,
1219
+ /// Table of snapshots.
1220
+ snapshot_table: Option<&'c ServoElementSnapshotTable>,
1221
+ /// Incoming dependencies to be processed.
1222
+ dependencies: &'c ElementDependencies<'a>,
1223
+ /// Generated invalidations.
1224
+ invalidations: InnerInvalidations<'a, E>,
1225
+ /// Traversal map for this invalidation.
1226
+ traversal_map: &'b SiblingTraversalMap<E>,
1227
+ }
1228
+
1229
+ impl<'a, 'b, 'c, E> RelativeSelectorInnerInvalidationProcessor<'a, 'b, 'c, E>
1230
+ where
1231
+ E: TElement + 'a,
1232
+ {
1233
+ fn new(
1234
+ quirks_mode: QuirksMode,
1235
+ snapshot_table: Option<&'c ServoElementSnapshotTable>,
1236
+ dependencies: &'c ElementDependencies<'a>,
1237
+ selector_caches: &'b mut SelectorCaches,
1238
+ traversal_map: &'b SiblingTraversalMap<E>,
1239
+ ) -> Self {
1240
+ let matching_context = MatchingContext::new_for_visited(
1241
+ MatchingMode::Normal,
1242
+ None,
1243
+ selector_caches,
1244
+ VisitedHandlingMode::AllLinksVisitedAndUnvisited,
1245
+ quirks_mode,
1246
+ NeedsSelectorFlags::No,
1247
+ MatchingForInvalidation::Yes,
1248
+ );
1249
+ Self {
1250
+ matching_context,
1251
+ snapshot_table,
1252
+ dependencies,
1253
+ invalidations: InnerInvalidations::default(),
1254
+ traversal_map,
1255
+ }
1256
+ }
1257
+
1258
+ fn note_dependency(
1259
+ &mut self,
1260
+ element: E,
1261
+ host: Option<OpaqueElement>,
1262
+ dependency: &'a Dependency,
1263
+ descendant_invalidations: &mut DescendantInvalidationLists<'a>,
1264
+ sibling_invalidations: &mut InvalidationVector<'a>,
1265
+ ) {
1266
+ match dependency.invalidation_kind() {
1267
+ DependencyInvalidationKind::FullSelector => unreachable!(),
1268
+ DependencyInvalidationKind::Normal(_) | DependencyInvalidationKind::Scope(_) => (),
1269
+ DependencyInvalidationKind::Relative(kind) => {
1270
+ self.found_relative_selector_invalidation(element, kind, dependency);
1271
+ return;
1272
+ },
1273
+ }
1274
+ if matches!(
1275
+ dependency.normal_invalidation_kind(),
1276
+ NormalDependencyInvalidationKind::Element
1277
+ ) {
1278
+ // Ok, keep heading outwards.
1279
+ debug_assert!(
1280
+ dependency.next.is_some(),
1281
+ "Orphaned inner selector dependency?"
1282
+ );
1283
+ if let Some(next) = dependency.next.as_ref() {
1284
+ self.note_dependency(
1285
+ element,
1286
+ host,
1287
+ &next.as_ref().slice()[0],
1288
+ descendant_invalidations,
1289
+ sibling_invalidations,
1290
+ );
1291
+ }
1292
+ return;
1293
+ }
1294
+ let invalidation = Invalidation::new(dependency, None, None);
1295
+ match dependency.normal_invalidation_kind() {
1296
+ NormalDependencyInvalidationKind::Descendants => {
1297
+ // Descendant invalidations are simplified due to pseudo-elements not being available within the relative selector.
1298
+ descendant_invalidations.dom_descendants.push(invalidation)
1299
+ },
1300
+ NormalDependencyInvalidationKind::Siblings => sibling_invalidations.push(invalidation),
1301
+ // Note(dshin, bug 1940212): Nesting can enabling stuffing pseudo-elements into :has, like `::marker { :has(&) }`.
1302
+ // Ideally, we can just not insert the dependency into the invalidation map, but the necessary selector information
1303
+ // for this (i.e. `HAS_PSEUDO`) is filtered out in `replace_parent_selector` through
1304
+ // `SelectorFlags::forbidden_for_nesting`, so just ignoring such dependencies here is the best we can do.
1305
+ _ => (),
1306
+ }
1307
+ }
1308
+
1309
+ /// Take the generated invalidations.
1310
+ fn take_invalidations(self) -> InnerInvalidations<'a, E> {
1311
+ self.invalidations
1312
+ }
1313
+ }
1314
+
1315
+ impl<'a, 'b, 'c, E> InvalidationProcessor<'a, 'b, E>
1316
+ for RelativeSelectorInnerInvalidationProcessor<'a, 'b, 'c, E>
1317
+ where
1318
+ E: TElement + 'a,
1319
+ {
1320
+ fn check_outer_dependency(
1321
+ &mut self,
1322
+ dependency: &Dependency,
1323
+ element: E,
1324
+ _: Option<OpaqueElement>,
1325
+ ) -> bool {
1326
+ if let Some(snapshot_table) = self.snapshot_table {
1327
+ let wrapper = ElementWrapper::new(element, snapshot_table);
1328
+ return check_dependency(
1329
+ dependency,
1330
+ &element,
1331
+ &wrapper,
1332
+ &mut self.matching_context,
1333
+ None,
1334
+ );
1335
+ }
1336
+ // Just invalidate if we don't have a snapshot.
1337
+ true
1338
+ }
1339
+
1340
+ fn matching_context(&mut self) -> &mut MatchingContext<'b, E::Impl> {
1341
+ &mut self.matching_context
1342
+ }
1343
+
1344
+ fn collect_invalidations(
1345
+ &mut self,
1346
+ element: E,
1347
+ _self_invalidations: &mut InvalidationVector<'a>,
1348
+ descendant_invalidations: &mut DescendantInvalidationLists<'a>,
1349
+ sibling_invalidations: &mut InvalidationVector<'a>,
1350
+ ) -> bool {
1351
+ for (scope, dependency) in self.dependencies {
1352
+ self.note_dependency(
1353
+ element,
1354
+ *scope,
1355
+ dependency,
1356
+ descendant_invalidations,
1357
+ sibling_invalidations,
1358
+ )
1359
+ }
1360
+ false
1361
+ }
1362
+
1363
+ fn should_process_descendants(&mut self, _element: E) -> bool {
1364
+ true
1365
+ }
1366
+
1367
+ fn recursion_limit_exceeded(&mut self, _element: E) {
1368
+ unreachable!("Unexpected recursion limit");
1369
+ }
1370
+
1371
+ // Don't do anything for normal invalidations.
1372
+ fn invalidated_self(&mut self, _element: E) {}
1373
+ fn invalidated_sibling(&mut self, _sibling: E, _of: E) {}
1374
+ fn invalidated_descendants(&mut self, _element: E, _child: E) {}
1375
+
1376
+ fn found_relative_selector_invalidation(
1377
+ &mut self,
1378
+ element: E,
1379
+ kind: RelativeDependencyInvalidationKind,
1380
+ dep: &'a Dependency,
1381
+ ) {
1382
+ debug_assert!(dep.next.is_some(), "Orphaned inners selector?");
1383
+ if element.relative_selector_search_direction().is_empty() {
1384
+ return;
1385
+ }
1386
+ self.invalidations.push((
1387
+ element,
1388
+ RelativeSelectorInvalidation {
1389
+ host: self.matching_context.current_host,
1390
+ kind,
1391
+ dependency: &dep.next.as_ref().unwrap().as_ref().slice()[0],
1392
+ },
1393
+ ));
1394
+ }
1395
+
1396
+ fn sibling_traversal_map(&self) -> &SiblingTraversalMap<E> {
1397
+ self.traversal_map
1398
+ }
1399
+ }