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,1470 @@
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
+ //! The struct that takes care of encapsulating all the logic on where and how
6
+ //! element styles need to be invalidated.
7
+
8
+ use crate::context::StackLimitChecker;
9
+ use crate::dom::{TElement, TNode, TShadowRoot};
10
+ use crate::invalidation::element::invalidation_map::{
11
+ Dependency, DependencyInvalidationKind, NormalDependencyInvalidationKind,
12
+ RelativeDependencyInvalidationKind, ScopeDependencyInvalidationKind,
13
+ };
14
+ use selectors::matching::matches_compound_selector_from;
15
+ use selectors::matching::{CompoundSelectorMatchingResult, MatchingContext};
16
+ use selectors::parser::{Combinator, Component, Selector, SelectorVisitor};
17
+ use selectors::{OpaqueElement, SelectorImpl};
18
+ use smallvec::{smallvec, SmallVec};
19
+ use std::fmt;
20
+ use std::fmt::Write;
21
+
22
+ struct SiblingInfo<E>
23
+ where
24
+ E: TElement,
25
+ {
26
+ affected: E,
27
+ prev_sibling: Option<E>,
28
+ next_sibling: Option<E>,
29
+ }
30
+
31
+ /// Traversal mapping for elements under consideration. It acts like a snapshot map,
32
+ /// though this only "maps" one element at most.
33
+ /// For general invalidations, this has no effect, especially since when
34
+ /// DOM mutates, the mutation's effect should not escape the subtree being mutated.
35
+ /// This is not the case for relative selectors, unfortunately, so we may end up
36
+ /// traversing a portion of the DOM tree that mutated. In case the mutation is removal,
37
+ /// its sibling relation is severed by the time the invalidation happens. This structure
38
+ /// recovers that relation. Note - it assumes that there is only one element under this
39
+ /// effect.
40
+ pub struct SiblingTraversalMap<E>
41
+ where
42
+ E: TElement,
43
+ {
44
+ info: Option<SiblingInfo<E>>,
45
+ }
46
+
47
+ impl<E> Default for SiblingTraversalMap<E>
48
+ where
49
+ E: TElement,
50
+ {
51
+ fn default() -> Self {
52
+ Self { info: None }
53
+ }
54
+ }
55
+
56
+ impl<E> SiblingTraversalMap<E>
57
+ where
58
+ E: TElement,
59
+ {
60
+ /// Create a new traversal map with the affected element.
61
+ pub fn new(affected: E, prev_sibling: Option<E>, next_sibling: Option<E>) -> Self {
62
+ Self {
63
+ info: Some(SiblingInfo {
64
+ affected,
65
+ prev_sibling,
66
+ next_sibling,
67
+ }),
68
+ }
69
+ }
70
+
71
+ /// Get the element's previous sibling element.
72
+ pub fn next_sibling_for(&self, element: &E) -> Option<E> {
73
+ if let Some(ref info) = self.info {
74
+ if *element == info.affected {
75
+ return info.next_sibling;
76
+ }
77
+ }
78
+ element.next_sibling_element()
79
+ }
80
+
81
+ /// Get the element's previous sibling element.
82
+ pub fn prev_sibling_for(&self, element: &E) -> Option<E> {
83
+ if let Some(ref info) = self.info {
84
+ if *element == info.affected {
85
+ return info.prev_sibling;
86
+ }
87
+ }
88
+ element.prev_sibling_element()
89
+ }
90
+ }
91
+
92
+ /// A trait to abstract the collection of invalidations for a given pass.
93
+ pub trait InvalidationProcessor<'a, 'b, E>
94
+ where
95
+ E: TElement,
96
+ {
97
+ /// Whether an invalidation that contains only a pseudo-element selector
98
+ /// like ::before or ::after triggers invalidation of the element that would
99
+ /// originate it.
100
+ fn invalidates_on_pseudo_element(&self) -> bool {
101
+ false
102
+ }
103
+
104
+ /// Whether the invalidation processor only cares about light-tree
105
+ /// descendants of a given element, that is, doesn't invalidate
106
+ /// pseudo-elements, NAC, shadow dom...
107
+ fn light_tree_only(&self) -> bool {
108
+ false
109
+ }
110
+
111
+ /// When a dependency from a :where or :is selector matches, it may still be
112
+ /// the case that we don't need to invalidate the full style. Consider the
113
+ /// case of:
114
+ ///
115
+ /// div .foo:where(.bar *, .baz) .qux
116
+ ///
117
+ /// We can get to the `*` part after a .bar class change, but you only need
118
+ /// to restyle the element if it also matches .foo.
119
+ ///
120
+ /// Similarly, you only need to restyle .baz if the whole result of matching
121
+ /// the selector changes.
122
+ ///
123
+ /// This function is called to check the result of matching the "outer"
124
+ /// dependency that we generate for the parent of the `:where` selector,
125
+ /// that is, in the case above it should match
126
+ /// `div .foo:where(.bar *, .baz)`.
127
+ ///
128
+ /// `scope` is set to `Some()` if this dependency follows a scope invalidation
129
+ /// Matching context should be adjusted accordingly with `nest_for_scope`.
130
+ ///
131
+ /// Returning true unconditionally here is over-optimistic and may
132
+ /// over-invalidate.
133
+ fn check_outer_dependency(
134
+ &mut self,
135
+ dependency: &Dependency,
136
+ element: E,
137
+ scope: Option<OpaqueElement>,
138
+ ) -> bool;
139
+
140
+ /// The matching context that should be used to process invalidations.
141
+ fn matching_context(&mut self) -> &mut MatchingContext<'b, E::Impl>;
142
+
143
+ /// The traversal map that should be used to process invalidations.
144
+ fn sibling_traversal_map(&self) -> &SiblingTraversalMap<E>;
145
+
146
+ /// Collect invalidations for a given element's descendants and siblings.
147
+ ///
148
+ /// Returns whether the element itself was invalidated.
149
+ fn collect_invalidations(
150
+ &mut self,
151
+ element: E,
152
+ self_invalidations: &mut InvalidationVector<'a>,
153
+ descendant_invalidations: &mut DescendantInvalidationLists<'a>,
154
+ sibling_invalidations: &mut InvalidationVector<'a>,
155
+ ) -> bool;
156
+
157
+ /// Returns whether the invalidation process should process the descendants
158
+ /// of the given element.
159
+ fn should_process_descendants(&mut self, element: E) -> bool;
160
+
161
+ /// Executes an arbitrary action when the recursion limit is exceded (if
162
+ /// any).
163
+ fn recursion_limit_exceeded(&mut self, element: E);
164
+
165
+ /// Executes an action when `Self` is invalidated.
166
+ fn invalidated_self(&mut self, element: E);
167
+
168
+ /// Executes an action when `sibling` is invalidated as a sibling of
169
+ /// `of`.
170
+ fn invalidated_sibling(&mut self, sibling: E, of: E);
171
+
172
+ /// Called when a highlight pseudo-element (::selection, ::highlight,
173
+ /// ::target-text) style is invalidated. These pseudos have their styles
174
+ /// resolved lazily during painting rather than during the restyle traversal,
175
+ /// so style changes don't automatically trigger repaints.
176
+ fn invalidated_highlight_pseudo(&mut self, _element: E) {}
177
+
178
+ /// Executes an action when any descendant of `Self` is invalidated.
179
+ fn invalidated_descendants(&mut self, element: E, child: E);
180
+
181
+ /// Executes an action when an element in a relative selector is reached.
182
+ /// Lets the dependency to be borrowed for further processing out of the
183
+ /// invalidation traversal.
184
+ fn found_relative_selector_invalidation(
185
+ &mut self,
186
+ _element: E,
187
+ _kind: RelativeDependencyInvalidationKind,
188
+ _relative_dependency: &'a Dependency,
189
+ ) {
190
+ debug_assert!(false, "Reached relative selector dependency");
191
+ }
192
+ }
193
+
194
+ /// Different invalidation lists for descendants.
195
+ #[derive(Debug, Default)]
196
+ pub struct DescendantInvalidationLists<'a> {
197
+ /// Invalidations for normal DOM children and pseudo-elements.
198
+ ///
199
+ /// TODO(emilio): Having a list of invalidations just for pseudo-elements
200
+ /// may save some work here and there.
201
+ pub dom_descendants: InvalidationVector<'a>,
202
+ /// Invalidations for slotted children of an element.
203
+ pub slotted_descendants: InvalidationVector<'a>,
204
+ /// Invalidations for ::part()s of an element.
205
+ pub parts: InvalidationVector<'a>,
206
+ }
207
+
208
+ impl<'a> DescendantInvalidationLists<'a> {
209
+ fn is_empty(&self) -> bool {
210
+ self.dom_descendants.is_empty()
211
+ && self.slotted_descendants.is_empty()
212
+ && self.parts.is_empty()
213
+ }
214
+ }
215
+
216
+ /// The struct that takes care of encapsulating all the logic on where and how
217
+ /// element styles need to be invalidated.
218
+ pub struct TreeStyleInvalidator<'a, 'b, 'c, E, P: 'a>
219
+ where
220
+ 'b: 'a,
221
+ E: TElement,
222
+ P: InvalidationProcessor<'b, 'c, E>,
223
+ {
224
+ element: E,
225
+ stack_limit_checker: Option<&'a StackLimitChecker>,
226
+ processor: &'a mut P,
227
+ _marker: std::marker::PhantomData<(&'b (), &'c ())>,
228
+ }
229
+
230
+ /// A vector of invalidations, optimized for small invalidation sets.
231
+ pub type InvalidationVector<'a> = SmallVec<[Invalidation<'a>; 10]>;
232
+
233
+ /// The kind of descendant invalidation we're processing.
234
+ #[derive(Clone, Copy, Debug, Eq, PartialEq)]
235
+ enum DescendantInvalidationKind {
236
+ /// A DOM descendant invalidation.
237
+ Dom,
238
+ /// A ::slotted() descendant invalidation.
239
+ Slotted,
240
+ /// A ::part() descendant invalidation.
241
+ Part,
242
+ }
243
+
244
+ /// The kind of invalidation we're processing.
245
+ ///
246
+ /// We can use this to avoid pushing invalidations of the same kind to our
247
+ /// descendants or siblings.
248
+ #[derive(Clone, Copy, Debug, Eq, PartialEq)]
249
+ enum InvalidationKind {
250
+ Descendant(DescendantInvalidationKind),
251
+ Sibling,
252
+ }
253
+
254
+ /// The kind of traversal an invalidation requires.
255
+ pub enum InvalidationAddOverride {
256
+ /// This invalidation should be added to descendant invalidation
257
+ Descendant,
258
+ /// This invalidation should be added to sibling invalidations
259
+ Sibling,
260
+ }
261
+
262
+ /// An `Invalidation` is a complex selector that describes which elements,
263
+ /// relative to a current element we are processing, must be restyled.
264
+ #[derive(Clone)]
265
+ pub struct Invalidation<'a> {
266
+ /// The dependency that generated this invalidation.
267
+ ///
268
+ /// Note that the offset inside the dependency is not really useful after
269
+ /// construction.
270
+ dependency: &'a Dependency,
271
+ /// The right shadow host from where the rule came from, if any.
272
+ ///
273
+ /// This is needed to ensure that we match the selector with the right
274
+ /// state, as whether some selectors like :host and ::part() match depends
275
+ /// on it.
276
+ host: Option<OpaqueElement>,
277
+ /// The scope element from which this rule comes from, if any.
278
+ scope: Option<OpaqueElement>,
279
+ /// The offset of the selector pointing to a compound selector.
280
+ ///
281
+ /// This order is a "parse order" offset, that is, zero is the leftmost part
282
+ /// of the selector written as parsed / serialized.
283
+ ///
284
+ /// It is initialized from the offset from `dependency`.
285
+ offset: usize,
286
+ /// Whether the invalidation was already matched by any previous sibling or
287
+ /// ancestor.
288
+ ///
289
+ /// If this is the case, we can avoid pushing invalidations generated by
290
+ /// this one if the generated invalidation is effective for all the siblings
291
+ /// or descendants after us.
292
+ matched_by_any_previous: bool,
293
+ /// Whether this incalidation should always be pushed to next invalidations.
294
+ ///
295
+ /// This is useful for overriding invalidations we would otherwise skip.
296
+ /// e.g @scope(.a){:not(:scope)} where we would need the :not(:scope)
297
+ /// invalidation to traverse down for all children of the scope root
298
+ always_effective_for_next_descendant: bool,
299
+ }
300
+
301
+ impl<'a> Invalidation<'a> {
302
+ /// Create a new invalidation for matching a dependency.
303
+ pub fn new(
304
+ dependency: &'a Dependency,
305
+ host: Option<OpaqueElement>,
306
+ scope: Option<OpaqueElement>,
307
+ ) -> Self {
308
+ debug_assert!(
309
+ dependency.selector_offset == dependency.selector.len() + 1
310
+ || dependency.invalidation_kind()
311
+ != DependencyInvalidationKind::Normal(
312
+ NormalDependencyInvalidationKind::Element
313
+ ),
314
+ "No point to this, if the dependency matched the element we should just invalidate it"
315
+ );
316
+ Self {
317
+ dependency,
318
+ host,
319
+ scope,
320
+ // + 1 to go past the combinator.
321
+ offset: dependency.selector.len() + 1 - dependency.selector_offset,
322
+ matched_by_any_previous: false,
323
+ always_effective_for_next_descendant: false,
324
+ }
325
+ }
326
+
327
+ /// Create a new invalidation for matching a dependency from the selector's subject.
328
+ /// Using this should be avoided whenever possible as it overinvalidates.
329
+ /// Only use it when it's not possible to match the selector in order due to
330
+ /// invalidations that don't necessarily start at the pointed compound, such as
331
+ /// what happens in note_scope_dependency_force_at_subject.
332
+ pub fn new_subject_invalidation(
333
+ dependency: &'a Dependency,
334
+ host: Option<OpaqueElement>,
335
+ scope: Option<OpaqueElement>,
336
+ ) -> Self {
337
+ let mut compound_offset = 0;
338
+ for s in dependency.selector.iter_raw_match_order() {
339
+ if s.is_combinator() {
340
+ break;
341
+ }
342
+ compound_offset += 1;
343
+ }
344
+
345
+ Self {
346
+ dependency,
347
+ host,
348
+ scope,
349
+ offset: dependency.selector.len() - compound_offset,
350
+ matched_by_any_previous: false,
351
+ always_effective_for_next_descendant: true,
352
+ }
353
+ }
354
+
355
+ /// Create a new invalidation for matching a dependency that should always check
356
+ /// its next descendants. It tends to overinvalidate less than new_subject_invalidation
357
+ /// but it should also be avoided whenever possible. Specifically used when crossing
358
+ /// into implicit scope invalidation.
359
+ pub fn new_always_effective_for_next_descendant(
360
+ dependency: &'a Dependency,
361
+ host: Option<OpaqueElement>,
362
+ scope: Option<OpaqueElement>,
363
+ ) -> Self {
364
+ if dependency.selector.is_rightmost(dependency.selector_offset) {
365
+ return Self::new_subject_invalidation(dependency, host, scope);
366
+ }
367
+
368
+ Self {
369
+ dependency,
370
+ host,
371
+ scope,
372
+ // + 1 to go past the combinator.
373
+ offset: dependency.selector.len() + 1 - dependency.selector_offset,
374
+ matched_by_any_previous: false,
375
+ always_effective_for_next_descendant: true,
376
+ }
377
+ }
378
+
379
+ /// Return the combinator to the right of the currently invalidating compound
380
+ /// Useful for determining whether this invalidation should be pushed to
381
+ /// sibling or descendant invalidations.
382
+ pub fn combinator_to_right(&self) -> Combinator {
383
+ debug_assert_ne!(self.dependency.selector_offset, 0);
384
+ self.dependency
385
+ .selector
386
+ .combinator_at_match_order(self.dependency.selector.len() - self.offset)
387
+ }
388
+
389
+ /// Whether this invalidation is effective for the next sibling or
390
+ /// descendant after us.
391
+ fn effective_for_next(&self) -> bool {
392
+ if self.offset == 0 || self.always_effective_for_next_descendant {
393
+ return true;
394
+ }
395
+
396
+ // TODO(emilio): For pseudo-elements this should be mostly false, except
397
+ // for the weird pseudos in <input type="number">.
398
+ //
399
+ // We should be able to do better here!
400
+ match self
401
+ .dependency
402
+ .selector
403
+ .combinator_at_parse_order(self.offset - 1)
404
+ {
405
+ Combinator::Descendant | Combinator::LaterSibling | Combinator::PseudoElement => true,
406
+ Combinator::Part
407
+ | Combinator::SlotAssignment
408
+ | Combinator::NextSibling
409
+ | Combinator::Child => false,
410
+ }
411
+ }
412
+
413
+ fn kind(&self) -> InvalidationKind {
414
+ if self.offset == 0 {
415
+ return InvalidationKind::Descendant(DescendantInvalidationKind::Dom);
416
+ }
417
+
418
+ match self
419
+ .dependency
420
+ .selector
421
+ .combinator_at_parse_order(self.offset - 1)
422
+ {
423
+ Combinator::Child | Combinator::Descendant | Combinator::PseudoElement => {
424
+ InvalidationKind::Descendant(DescendantInvalidationKind::Dom)
425
+ },
426
+ Combinator::Part => InvalidationKind::Descendant(DescendantInvalidationKind::Part),
427
+ Combinator::SlotAssignment => {
428
+ InvalidationKind::Descendant(DescendantInvalidationKind::Slotted)
429
+ },
430
+ Combinator::NextSibling | Combinator::LaterSibling => InvalidationKind::Sibling,
431
+ }
432
+ }
433
+ }
434
+
435
+ /// A struct that visits a selector and determines if there is a `:scope`
436
+ /// component nested withing a negation. eg. :not(:scope)
437
+ struct NegationScopeVisitor {
438
+ /// Have we found a negation list yet
439
+ in_negation: bool,
440
+ /// Have we found a :scope inside a negation yet
441
+ found_scope_in_negation: bool,
442
+ }
443
+
444
+ impl NegationScopeVisitor {
445
+ /// Create a new NegationScopeVisitor
446
+ fn new() -> Self {
447
+ Self {
448
+ in_negation: false,
449
+ found_scope_in_negation: false,
450
+ }
451
+ }
452
+
453
+ fn traverse_selector(
454
+ mut self,
455
+ selector: &Selector<<NegationScopeVisitor as SelectorVisitor>::Impl>,
456
+ ) -> bool {
457
+ selector.visit(&mut self);
458
+ self.found_scope_in_negation
459
+ }
460
+
461
+ /// Traverse all the next dependencies in an outer dependency until we reach
462
+ /// 1. :not(* :scope *)
463
+ /// 2. a scope or relative dependency
464
+ /// 3. the end of the chain of dependencies
465
+ /// Return whether or not we encountered :not(* :scope *)
466
+ fn traverse_dependency(mut self, dependency: &Dependency) -> bool {
467
+ if dependency.next.is_none()
468
+ || !matches!(
469
+ dependency.invalidation_kind(),
470
+ DependencyInvalidationKind::Normal(..)
471
+ )
472
+ {
473
+ dependency.selector.visit(&mut self);
474
+ return self.found_scope_in_negation;
475
+ }
476
+
477
+ let nested_visitor = Self {
478
+ in_negation: self.in_negation,
479
+ found_scope_in_negation: false,
480
+ };
481
+ dependency.selector.visit(&mut self);
482
+ // Has to be normal dependency and next.is_some()
483
+ nested_visitor.traverse_dependency(&dependency.next.as_ref().unwrap().slice()[0])
484
+ }
485
+ }
486
+
487
+ impl SelectorVisitor for NegationScopeVisitor {
488
+ type Impl = crate::selector_parser::SelectorImpl;
489
+
490
+ fn visit_attribute_selector(
491
+ &mut self,
492
+ _namespace: &selectors::attr::NamespaceConstraint<
493
+ &<Self::Impl as SelectorImpl>::NamespaceUrl,
494
+ >,
495
+ _local_name: &<Self::Impl as SelectorImpl>::LocalName,
496
+ _local_name_lower: &<Self::Impl as SelectorImpl>::LocalName,
497
+ ) -> bool {
498
+ true
499
+ }
500
+
501
+ fn visit_simple_selector(&mut self, component: &Component<Self::Impl>) -> bool {
502
+ if self.in_negation && component == &Component::Scope {
503
+ self.found_scope_in_negation = true;
504
+ }
505
+ true
506
+ }
507
+
508
+ fn visit_relative_selector_list(
509
+ &mut self,
510
+ _list: &[selectors::parser::RelativeSelector<Self::Impl>],
511
+ ) -> bool {
512
+ true
513
+ }
514
+
515
+ fn visit_selector_list(
516
+ &mut self,
517
+ list_kind: selectors::visitor::SelectorListKind,
518
+ list: &[selectors::parser::Selector<Self::Impl>],
519
+ ) -> bool {
520
+ for nested in list {
521
+ let nested_visitor = Self {
522
+ in_negation: list_kind.in_negation(),
523
+ found_scope_in_negation: false,
524
+ };
525
+
526
+ self.found_scope_in_negation |= nested_visitor.traverse_selector(nested);
527
+ }
528
+ true
529
+ }
530
+
531
+ fn visit_complex_selector(&mut self, _combinator_to_right: Option<Combinator>) -> bool {
532
+ true
533
+ }
534
+ }
535
+
536
+ /// Determines if we can find a selector in the form of :not(:scope)
537
+ /// anywhere down the chain of dependencies.
538
+ pub fn any_next_has_scope_in_negation(dependency: &Dependency) -> bool {
539
+ let next = match dependency.next.as_ref() {
540
+ None => return false,
541
+ Some(l) => l,
542
+ };
543
+
544
+ next.slice().iter().any(|dep| {
545
+ let visitor = NegationScopeVisitor::new();
546
+ visitor.traverse_dependency(dep)
547
+ })
548
+ }
549
+
550
+ impl<'a> fmt::Debug for Invalidation<'a> {
551
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
552
+ use cssparser::ToCss;
553
+
554
+ f.write_str("Invalidation(")?;
555
+ for component in self
556
+ .dependency
557
+ .selector
558
+ .iter_raw_parse_order_from(self.offset)
559
+ {
560
+ if matches!(*component, Component::Combinator(..)) {
561
+ break;
562
+ }
563
+ component.to_css(f)?;
564
+ }
565
+ f.write_char(')')
566
+ }
567
+ }
568
+
569
+ /// The result of processing a single invalidation for a given element.
570
+ struct ProcessInvalidationResult {
571
+ /// Whether the element itself was invalidated.
572
+ invalidated_self: bool,
573
+ /// Whether the invalidation matched, either invalidating the element or
574
+ /// generating another invalidation.
575
+ matched: bool,
576
+ }
577
+
578
+ /// The result of a whole invalidation process for a given element.
579
+ pub struct InvalidationResult {
580
+ /// Whether the element itself was invalidated.
581
+ invalidated_self: bool,
582
+ /// Whether the element's descendants were invalidated.
583
+ invalidated_descendants: bool,
584
+ /// Whether the element's siblings were invalidated.
585
+ invalidated_siblings: bool,
586
+ }
587
+
588
+ impl InvalidationResult {
589
+ /// Create an emtpy result.
590
+ pub fn empty() -> Self {
591
+ Self {
592
+ invalidated_self: false,
593
+ invalidated_descendants: false,
594
+ invalidated_siblings: false,
595
+ }
596
+ }
597
+
598
+ /// Whether the invalidation has invalidate the element itself.
599
+ pub fn has_invalidated_self(&self) -> bool {
600
+ self.invalidated_self
601
+ }
602
+
603
+ /// Whether the invalidation has invalidate desendants.
604
+ pub fn has_invalidated_descendants(&self) -> bool {
605
+ self.invalidated_descendants
606
+ }
607
+
608
+ /// Whether the invalidation has invalidate siblings.
609
+ pub fn has_invalidated_siblings(&self) -> bool {
610
+ self.invalidated_siblings
611
+ }
612
+ }
613
+
614
+ impl<'a, 'b, 'c, E, P: 'a> TreeStyleInvalidator<'a, 'b, 'c, E, P>
615
+ where
616
+ 'b: 'a,
617
+ E: TElement,
618
+ P: InvalidationProcessor<'b, 'c, E>,
619
+ {
620
+ /// Trivially constructs a new `TreeStyleInvalidator`.
621
+ pub fn new(
622
+ element: E,
623
+ stack_limit_checker: Option<&'a StackLimitChecker>,
624
+ processor: &'a mut P,
625
+ ) -> Self {
626
+ Self {
627
+ element,
628
+ stack_limit_checker,
629
+ processor,
630
+ _marker: std::marker::PhantomData,
631
+ }
632
+ }
633
+
634
+ /// Perform the invalidation pass.
635
+ pub fn invalidate(mut self) -> InvalidationResult {
636
+ debug!("StyleTreeInvalidator::invalidate({:?})", self.element);
637
+
638
+ let mut self_invalidations = InvalidationVector::new();
639
+ let mut descendant_invalidations = DescendantInvalidationLists::default();
640
+ let mut sibling_invalidations = InvalidationVector::new();
641
+
642
+ let mut invalidated_self = self.processor.collect_invalidations(
643
+ self.element,
644
+ &mut self_invalidations,
645
+ &mut descendant_invalidations,
646
+ &mut sibling_invalidations,
647
+ );
648
+
649
+ debug!("Collected invalidations (self: {}): ", invalidated_self);
650
+ debug!(
651
+ " > self: {}, {:?}",
652
+ self_invalidations.len(),
653
+ self_invalidations
654
+ );
655
+ debug!(" > descendants: {:?}", descendant_invalidations);
656
+ debug!(
657
+ " > siblings: {}, {:?}",
658
+ sibling_invalidations.len(),
659
+ sibling_invalidations
660
+ );
661
+
662
+ let invalidated_self_from_collection = invalidated_self;
663
+
664
+ invalidated_self |= self.process_descendant_invalidations(
665
+ &self_invalidations,
666
+ &mut descendant_invalidations,
667
+ &mut sibling_invalidations,
668
+ DescendantInvalidationKind::Dom,
669
+ );
670
+
671
+ if invalidated_self && !invalidated_self_from_collection {
672
+ self.processor.invalidated_self(self.element);
673
+ }
674
+
675
+ let invalidated_descendants = self.invalidate_descendants(&descendant_invalidations);
676
+ let invalidated_siblings = self.invalidate_siblings(&mut sibling_invalidations);
677
+
678
+ InvalidationResult {
679
+ invalidated_self,
680
+ invalidated_descendants,
681
+ invalidated_siblings,
682
+ }
683
+ }
684
+
685
+ /// Go through later DOM siblings, invalidating style as needed using the
686
+ /// `sibling_invalidations` list.
687
+ ///
688
+ /// Returns whether any sibling's style or any sibling descendant's style
689
+ /// was invalidated.
690
+ fn invalidate_siblings(&mut self, sibling_invalidations: &mut InvalidationVector<'b>) -> bool {
691
+ if sibling_invalidations.is_empty() {
692
+ return false;
693
+ }
694
+
695
+ let mut current = self
696
+ .processor
697
+ .sibling_traversal_map()
698
+ .next_sibling_for(&self.element);
699
+ let mut any_invalidated = false;
700
+
701
+ while let Some(sibling) = current {
702
+ let mut sibling_invalidator =
703
+ TreeStyleInvalidator::new(sibling, self.stack_limit_checker, self.processor);
704
+
705
+ let mut invalidations_for_descendants = DescendantInvalidationLists::default();
706
+ let invalidated_sibling = sibling_invalidator.process_sibling_invalidations(
707
+ &mut invalidations_for_descendants,
708
+ sibling_invalidations,
709
+ );
710
+
711
+ if invalidated_sibling {
712
+ sibling_invalidator
713
+ .processor
714
+ .invalidated_sibling(sibling, self.element);
715
+ }
716
+
717
+ any_invalidated |= invalidated_sibling;
718
+
719
+ any_invalidated |=
720
+ sibling_invalidator.invalidate_descendants(&invalidations_for_descendants);
721
+
722
+ if sibling_invalidations.is_empty() {
723
+ break;
724
+ }
725
+
726
+ current = self
727
+ .processor
728
+ .sibling_traversal_map()
729
+ .next_sibling_for(&sibling);
730
+ }
731
+
732
+ any_invalidated
733
+ }
734
+
735
+ fn invalidate_pseudo_element_or_nac(
736
+ &mut self,
737
+ child: E,
738
+ invalidations: &[Invalidation<'b>],
739
+ ) -> bool {
740
+ let mut sibling_invalidations = InvalidationVector::new();
741
+
742
+ // Roots of NAC subtrees can indeed generate sibling invalidations, but
743
+ // they can be just ignored, since they have no siblings.
744
+ //
745
+ // Note that we can end up testing selectors that wouldn't end up
746
+ // matching due to this being NAC, like those coming from document
747
+ // rules, but we overinvalidate instead of checking this.
748
+
749
+ self.invalidate_child(
750
+ child,
751
+ invalidations,
752
+ &mut sibling_invalidations,
753
+ DescendantInvalidationKind::Dom,
754
+ )
755
+ }
756
+
757
+ /// Invalidate a child and recurse down invalidating its descendants if
758
+ /// needed.
759
+ fn invalidate_child(
760
+ &mut self,
761
+ child: E,
762
+ invalidations: &[Invalidation<'b>],
763
+ sibling_invalidations: &mut InvalidationVector<'b>,
764
+ descendant_invalidation_kind: DescendantInvalidationKind,
765
+ ) -> bool {
766
+ let mut invalidations_for_descendants = DescendantInvalidationLists::default();
767
+
768
+ let mut invalidated_child = false;
769
+ let invalidated_descendants = {
770
+ let mut child_invalidator =
771
+ TreeStyleInvalidator::new(child, self.stack_limit_checker, self.processor);
772
+
773
+ if !sibling_invalidations.is_empty() {
774
+ invalidated_child |= child_invalidator.process_sibling_invalidations(
775
+ &mut invalidations_for_descendants,
776
+ sibling_invalidations,
777
+ );
778
+ }
779
+
780
+ invalidated_child |= child_invalidator.process_descendant_invalidations(
781
+ invalidations,
782
+ &mut invalidations_for_descendants,
783
+ sibling_invalidations,
784
+ descendant_invalidation_kind,
785
+ );
786
+
787
+ if invalidated_child {
788
+ child_invalidator.processor.invalidated_self(child);
789
+ }
790
+
791
+ child_invalidator.invalidate_descendants(&invalidations_for_descendants)
792
+ };
793
+
794
+ // The child may not be a flattened tree child of the current element,
795
+ // but may be arbitrarily deep.
796
+ //
797
+ // Since we keep the traversal flags in terms of the flattened tree,
798
+ // we need to propagate it as appropriate.
799
+ if invalidated_child || invalidated_descendants {
800
+ self.processor.invalidated_descendants(self.element, child);
801
+ }
802
+
803
+ invalidated_child || invalidated_descendants
804
+ }
805
+
806
+ fn invalidate_nac(&mut self, invalidations: &[Invalidation<'b>]) -> bool {
807
+ let mut any_nac_root = false;
808
+
809
+ let element = self.element;
810
+ element.each_anonymous_content_child(|nac| {
811
+ any_nac_root |= self.invalidate_pseudo_element_or_nac(nac, invalidations);
812
+ });
813
+
814
+ any_nac_root
815
+ }
816
+
817
+ // NB: It's important that this operates on DOM children, which is what
818
+ // selector-matching operates on.
819
+ fn invalidate_dom_descendants_of(
820
+ &mut self,
821
+ parent: E::ConcreteNode,
822
+ invalidations: &[Invalidation<'b>],
823
+ ) -> bool {
824
+ let mut any_descendant = false;
825
+
826
+ let mut sibling_invalidations = InvalidationVector::new();
827
+ for child in parent.dom_children() {
828
+ let child = match child.as_element() {
829
+ Some(e) => e,
830
+ None => continue,
831
+ };
832
+
833
+ any_descendant |= self.invalidate_child(
834
+ child,
835
+ invalidations,
836
+ &mut sibling_invalidations,
837
+ DescendantInvalidationKind::Dom,
838
+ );
839
+ }
840
+
841
+ any_descendant
842
+ }
843
+
844
+ fn invalidate_parts_in_shadow_tree(
845
+ &mut self,
846
+ shadow: <E::ConcreteNode as TNode>::ConcreteShadowRoot,
847
+ invalidations: &[Invalidation<'b>],
848
+ ) -> bool {
849
+ debug_assert!(!invalidations.is_empty());
850
+
851
+ let mut any = false;
852
+ let mut sibling_invalidations = InvalidationVector::new();
853
+
854
+ for node in shadow.as_node().dom_descendants() {
855
+ let element = match node.as_element() {
856
+ Some(e) => e,
857
+ None => continue,
858
+ };
859
+
860
+ if element.has_part_attr() {
861
+ any |= self.invalidate_child(
862
+ element,
863
+ invalidations,
864
+ &mut sibling_invalidations,
865
+ DescendantInvalidationKind::Part,
866
+ );
867
+ debug_assert!(
868
+ sibling_invalidations.is_empty(),
869
+ "::part() shouldn't have sibling combinators to the right, \
870
+ this makes no sense! {:?}",
871
+ sibling_invalidations
872
+ );
873
+ }
874
+
875
+ if let Some(shadow) = element.shadow_root() {
876
+ if element.exports_any_part() {
877
+ any |= self.invalidate_parts_in_shadow_tree(shadow, invalidations)
878
+ }
879
+ }
880
+ }
881
+
882
+ any
883
+ }
884
+
885
+ fn invalidate_parts(&mut self, invalidations: &[Invalidation<'b>]) -> bool {
886
+ if invalidations.is_empty() {
887
+ return false;
888
+ }
889
+
890
+ let shadow = match self.element.shadow_root() {
891
+ Some(s) => s,
892
+ None => return false,
893
+ };
894
+
895
+ self.invalidate_parts_in_shadow_tree(shadow, invalidations)
896
+ }
897
+
898
+ fn invalidate_slotted_elements(&mut self, invalidations: &[Invalidation<'b>]) -> bool {
899
+ if invalidations.is_empty() {
900
+ return false;
901
+ }
902
+
903
+ let slot = self.element;
904
+ self.invalidate_slotted_elements_in_slot(slot, invalidations)
905
+ }
906
+
907
+ fn invalidate_slotted_elements_in_slot(
908
+ &mut self,
909
+ slot: E,
910
+ invalidations: &[Invalidation<'b>],
911
+ ) -> bool {
912
+ let mut any = false;
913
+
914
+ let mut sibling_invalidations = InvalidationVector::new();
915
+ for node in slot.slotted_nodes() {
916
+ let element = match node.as_element() {
917
+ Some(e) => e,
918
+ None => continue,
919
+ };
920
+
921
+ if element.is_html_slot_element() {
922
+ any |= self.invalidate_slotted_elements_in_slot(element, invalidations);
923
+ } else {
924
+ any |= self.invalidate_child(
925
+ element,
926
+ invalidations,
927
+ &mut sibling_invalidations,
928
+ DescendantInvalidationKind::Slotted,
929
+ );
930
+ }
931
+
932
+ debug_assert!(
933
+ sibling_invalidations.is_empty(),
934
+ "::slotted() shouldn't have sibling combinators to the right, \
935
+ this makes no sense! {:?}",
936
+ sibling_invalidations
937
+ );
938
+ }
939
+
940
+ any
941
+ }
942
+
943
+ fn invalidate_non_slotted_descendants(&mut self, invalidations: &[Invalidation<'b>]) -> bool {
944
+ if invalidations.is_empty() {
945
+ return false;
946
+ }
947
+
948
+ if self.processor.light_tree_only() {
949
+ let node = self.element.as_node();
950
+ return self.invalidate_dom_descendants_of(node, invalidations);
951
+ }
952
+
953
+ let mut any_descendant = false;
954
+
955
+ // NOTE(emilio): This is only needed for Shadow DOM to invalidate
956
+ // correctly on :host(..) changes. Instead of doing this, we could add
957
+ // a third kind of invalidation list that walks shadow root children,
958
+ // but it's not clear it's worth it.
959
+ //
960
+ // Also, it's needed as of right now for document state invalidation,
961
+ // where we rely on iterating every element that ends up in the composed
962
+ // doc, but we could fix that invalidating per subtree.
963
+ if let Some(root) = self.element.shadow_root() {
964
+ any_descendant |= self.invalidate_dom_descendants_of(root.as_node(), invalidations);
965
+ }
966
+
967
+ any_descendant |= self.invalidate_dom_descendants_of(self.element.as_node(), invalidations);
968
+
969
+ any_descendant |= self.invalidate_nac(invalidations);
970
+
971
+ any_descendant
972
+ }
973
+
974
+ /// Given the descendant invalidation lists, go through the current
975
+ /// element's descendants, and invalidate style on them.
976
+ fn invalidate_descendants(&mut self, invalidations: &DescendantInvalidationLists<'b>) -> bool {
977
+ if invalidations.is_empty() {
978
+ return false;
979
+ }
980
+
981
+ debug!(
982
+ "StyleTreeInvalidator::invalidate_descendants({:?})",
983
+ self.element
984
+ );
985
+ debug!(" > {:?}", invalidations);
986
+
987
+ let should_process = self.processor.should_process_descendants(self.element);
988
+
989
+ if !should_process {
990
+ return false;
991
+ }
992
+
993
+ if let Some(checker) = self.stack_limit_checker {
994
+ if checker.limit_exceeded() {
995
+ self.processor.recursion_limit_exceeded(self.element);
996
+ return true;
997
+ }
998
+ }
999
+
1000
+ let mut any_descendant = false;
1001
+
1002
+ any_descendant |= self.invalidate_non_slotted_descendants(&invalidations.dom_descendants);
1003
+ any_descendant |= self.invalidate_slotted_elements(&invalidations.slotted_descendants);
1004
+ any_descendant |= self.invalidate_parts(&invalidations.parts);
1005
+
1006
+ any_descendant
1007
+ }
1008
+
1009
+ /// Process the given sibling invalidations coming from our previous
1010
+ /// sibling.
1011
+ ///
1012
+ /// The sibling invalidations are somewhat special because they can be
1013
+ /// modified on the fly. New invalidations may be added and removed.
1014
+ ///
1015
+ /// In particular, all descendants get the same set of invalidations from
1016
+ /// the parent, but the invalidations from a given sibling depend on the
1017
+ /// ones we got from the previous one.
1018
+ ///
1019
+ /// Returns whether invalidated the current element's style.
1020
+ ///
1021
+ /// Callers should skip this when `sibling_invalidations` is empty, as it
1022
+ /// builds and drains a `SmallVec` to do nothing.
1023
+ fn process_sibling_invalidations(
1024
+ &mut self,
1025
+ descendant_invalidations: &mut DescendantInvalidationLists<'b>,
1026
+ sibling_invalidations: &mut InvalidationVector<'b>,
1027
+ ) -> bool {
1028
+ let mut i = 0;
1029
+ let mut new_sibling_invalidations = InvalidationVector::new();
1030
+ let mut invalidated_self = false;
1031
+
1032
+ while i < sibling_invalidations.len() {
1033
+ let result = self.process_invalidation(
1034
+ &sibling_invalidations[i],
1035
+ descendant_invalidations,
1036
+ &mut new_sibling_invalidations,
1037
+ InvalidationKind::Sibling,
1038
+ );
1039
+
1040
+ invalidated_self |= result.invalidated_self;
1041
+ sibling_invalidations[i].matched_by_any_previous |= result.matched;
1042
+ if sibling_invalidations[i].effective_for_next() {
1043
+ i += 1;
1044
+ } else {
1045
+ sibling_invalidations.remove(i);
1046
+ }
1047
+ }
1048
+
1049
+ sibling_invalidations.extend(new_sibling_invalidations.drain(..));
1050
+ invalidated_self
1051
+ }
1052
+
1053
+ /// Process a given invalidation list coming from our parent,
1054
+ /// adding to `descendant_invalidations` and `sibling_invalidations` as
1055
+ /// needed.
1056
+ ///
1057
+ /// Returns whether our style was invalidated as a result.
1058
+ fn process_descendant_invalidations(
1059
+ &mut self,
1060
+ invalidations: &[Invalidation<'b>],
1061
+ descendant_invalidations: &mut DescendantInvalidationLists<'b>,
1062
+ sibling_invalidations: &mut InvalidationVector<'b>,
1063
+ descendant_invalidation_kind: DescendantInvalidationKind,
1064
+ ) -> bool {
1065
+ let mut invalidated = false;
1066
+
1067
+ for invalidation in invalidations {
1068
+ let result = self.process_invalidation(
1069
+ invalidation,
1070
+ descendant_invalidations,
1071
+ sibling_invalidations,
1072
+ InvalidationKind::Descendant(descendant_invalidation_kind),
1073
+ );
1074
+
1075
+ invalidated |= result.invalidated_self;
1076
+ if invalidation.effective_for_next() {
1077
+ let mut invalidation = invalidation.clone();
1078
+ invalidation.matched_by_any_previous |= result.matched;
1079
+ debug_assert_eq!(
1080
+ descendant_invalidation_kind,
1081
+ DescendantInvalidationKind::Dom,
1082
+ "Slotted or part invalidations don't propagate."
1083
+ );
1084
+ descendant_invalidations.dom_descendants.push(invalidation);
1085
+ }
1086
+ }
1087
+
1088
+ invalidated
1089
+ }
1090
+
1091
+ #[inline(always)]
1092
+ fn handle_fully_matched(
1093
+ &mut self,
1094
+ invalidation: &Invalidation<'b>,
1095
+ ) -> (ProcessInvalidationResult, SmallVec<[Invalidation<'b>; 1]>) {
1096
+ debug!(" > Invalidation matched completely");
1097
+ // We matched completely. If we're an inner selector now we need
1098
+ // to go outside our selector and carry on invalidating.
1099
+ let mut to_process: SmallVec<[&Dependency; 1]> = SmallVec::from([invalidation.dependency]);
1100
+ let mut next_invalidations: SmallVec<[Invalidation; 1]> = SmallVec::new();
1101
+ let mut result = ProcessInvalidationResult {
1102
+ invalidated_self: false,
1103
+ matched: false,
1104
+ };
1105
+
1106
+ while !to_process.is_empty() {
1107
+ let mut next_dependencies: SmallVec<[&Dependency; 1]> = SmallVec::new();
1108
+
1109
+ while let Some(dependency) = to_process.pop() {
1110
+ if let DependencyInvalidationKind::Scope(scope_kind) =
1111
+ dependency.invalidation_kind()
1112
+ {
1113
+ if scope_kind == ScopeDependencyInvalidationKind::ImplicitScope {
1114
+ if let Some(ref deps) = dependency.next {
1115
+ for dep in deps.as_ref().slice() {
1116
+ let invalidation =
1117
+ Invalidation::new_always_effective_for_next_descendant(
1118
+ dep,
1119
+ invalidation.host,
1120
+ invalidation.scope,
1121
+ );
1122
+ next_invalidations.push(invalidation);
1123
+ }
1124
+ }
1125
+ continue;
1126
+ }
1127
+
1128
+ let force_add = any_next_has_scope_in_negation(dependency);
1129
+ if scope_kind == ScopeDependencyInvalidationKind::ScopeEnd || force_add {
1130
+ let invalidations = note_scope_dependency_force_at_subject(
1131
+ dependency,
1132
+ invalidation.host,
1133
+ invalidation.scope,
1134
+ force_add,
1135
+ );
1136
+
1137
+ next_invalidations.extend(invalidations);
1138
+
1139
+ continue;
1140
+ }
1141
+ }
1142
+
1143
+ match dependency.next {
1144
+ None => {
1145
+ result.invalidated_self = true;
1146
+ result.matched = true;
1147
+ },
1148
+ Some(ref deps) => {
1149
+ for n in deps.as_ref().slice() {
1150
+ let invalidation_kind = n.invalidation_kind();
1151
+ match invalidation_kind {
1152
+ DependencyInvalidationKind::FullSelector => unreachable!(),
1153
+ DependencyInvalidationKind::Normal(_) => next_dependencies.push(n),
1154
+ //TODO(descalente, bug 1934061): Add specific handling for implicit scopes.
1155
+ DependencyInvalidationKind::Scope(_) => {
1156
+ next_dependencies.push(n);
1157
+ },
1158
+ DependencyInvalidationKind::Relative(kind) => {
1159
+ self.processor.found_relative_selector_invalidation(
1160
+ self.element,
1161
+ kind,
1162
+ n,
1163
+ );
1164
+ result.matched = true;
1165
+ },
1166
+ }
1167
+ }
1168
+ },
1169
+ };
1170
+ }
1171
+
1172
+ for cur_dependency in next_dependencies.as_ref() {
1173
+ let scope = matches!(
1174
+ invalidation.dependency.invalidation_kind(),
1175
+ DependencyInvalidationKind::Scope(_)
1176
+ )
1177
+ .then(|| self.element.opaque());
1178
+ debug!(" > Checking outer dependency {:?}", cur_dependency);
1179
+
1180
+ // The inner selector changed, now check if the full
1181
+ // previous part of the selector did, before keeping
1182
+ // checking for descendants.
1183
+ if !self
1184
+ .processor
1185
+ .check_outer_dependency(cur_dependency, self.element, scope)
1186
+ {
1187
+ // Dependency is not relevant, do not note it down
1188
+ continue;
1189
+ }
1190
+
1191
+ let invalidation_kind = cur_dependency.invalidation_kind();
1192
+ if matches!(
1193
+ invalidation_kind,
1194
+ DependencyInvalidationKind::Normal(NormalDependencyInvalidationKind::Element)
1195
+ ) || (matches!(invalidation_kind, DependencyInvalidationKind::Scope(_))
1196
+ && cur_dependency
1197
+ .selector
1198
+ .is_rightmost(cur_dependency.selector_offset))
1199
+ {
1200
+ // Add to dependency stack to process its next dependencies.
1201
+ to_process.push(cur_dependency);
1202
+ continue;
1203
+ }
1204
+
1205
+ debug!(" > Generating invalidation");
1206
+ next_invalidations.push(Invalidation::new(
1207
+ cur_dependency,
1208
+ invalidation.host,
1209
+ scope,
1210
+ ));
1211
+ }
1212
+ }
1213
+ (result, next_invalidations)
1214
+ }
1215
+
1216
+ /// Processes a given invalidation, potentially invalidating the style of
1217
+ /// the current element.
1218
+ ///
1219
+ /// Returns whether invalidated the style of the element, and whether the
1220
+ /// invalidation should be effective to subsequent siblings or descendants
1221
+ /// down in the tree.
1222
+ fn process_invalidation(
1223
+ &mut self,
1224
+ invalidation: &Invalidation<'b>,
1225
+ descendant_invalidations: &mut DescendantInvalidationLists<'b>,
1226
+ sibling_invalidations: &mut InvalidationVector<'b>,
1227
+ invalidation_kind: InvalidationKind,
1228
+ ) -> ProcessInvalidationResult {
1229
+ debug!(
1230
+ "TreeStyleInvalidator::process_invalidation({:?}, {:?}, {:?})",
1231
+ self.element, invalidation, invalidation_kind
1232
+ );
1233
+
1234
+ let matching_result = {
1235
+ let context = self.processor.matching_context();
1236
+ context.current_host = invalidation.host;
1237
+
1238
+ context.nest_for_scope_condition(invalidation.scope, |ctx| {
1239
+ matches_compound_selector_from(
1240
+ &invalidation.dependency.selector,
1241
+ invalidation.offset,
1242
+ ctx,
1243
+ &self.element,
1244
+ )
1245
+ })
1246
+ };
1247
+
1248
+ let (mut result, next_invalidations) = match matching_result {
1249
+ CompoundSelectorMatchingResult::NotMatched => {
1250
+ return ProcessInvalidationResult {
1251
+ invalidated_self: false,
1252
+ matched: false,
1253
+ }
1254
+ },
1255
+ CompoundSelectorMatchingResult::FullyMatched => self.handle_fully_matched(invalidation),
1256
+ CompoundSelectorMatchingResult::Matched {
1257
+ next_combinator_offset,
1258
+ } => (
1259
+ ProcessInvalidationResult {
1260
+ invalidated_self: false,
1261
+ matched: true,
1262
+ },
1263
+ smallvec![Invalidation {
1264
+ dependency: invalidation.dependency,
1265
+ host: invalidation.host,
1266
+ scope: invalidation.scope,
1267
+ offset: next_combinator_offset + 1,
1268
+ matched_by_any_previous: false,
1269
+ always_effective_for_next_descendant: invalidation
1270
+ .always_effective_for_next_descendant,
1271
+ }],
1272
+ ),
1273
+ };
1274
+
1275
+ for next_invalidation in next_invalidations {
1276
+ let next_invalidation_kind = if next_invalidation.always_effective_for_next_descendant {
1277
+ InvalidationKind::Descendant(DescendantInvalidationKind::Dom)
1278
+ } else {
1279
+ debug_assert_ne!(
1280
+ next_invalidation.offset, 0,
1281
+ "Rightmost selectors shouldn't generate more invalidations",
1282
+ );
1283
+
1284
+ let next_combinator = next_invalidation
1285
+ .dependency
1286
+ .selector
1287
+ .combinator_at_parse_order(next_invalidation.offset - 1);
1288
+
1289
+ if matches!(next_combinator, Combinator::PseudoElement)
1290
+ && self.processor.invalidates_on_pseudo_element()
1291
+ {
1292
+ // We need to invalidate the element whenever pseudos change, for
1293
+ // two reasons:
1294
+ //
1295
+ // * Eager pseudo styles are stored as part of the originating
1296
+ // element's computed style.
1297
+ //
1298
+ // * Lazy pseudo-styles might be cached on the originating
1299
+ // element's pseudo-style cache.
1300
+ //
1301
+ // This could be more fine-grained (perhaps with a RESTYLE_PSEUDOS
1302
+ // hint?).
1303
+ //
1304
+ // Note that we'll also restyle the pseudo-element because it would
1305
+ // match this invalidation.
1306
+ result.invalidated_self = true;
1307
+
1308
+ // For highlight pseudos (::selection, ::highlight, ::target-text),
1309
+ // we also need to trigger a repaint since their styles are resolved
1310
+ // lazily during painting.
1311
+ if next_invalidation
1312
+ .dependency
1313
+ .selector
1314
+ .pseudo_element()
1315
+ .is_some_and(|p| p.is_lazy_painted_highlight_pseudo())
1316
+ {
1317
+ self.processor.invalidated_highlight_pseudo(self.element);
1318
+ }
1319
+ }
1320
+
1321
+ debug!(
1322
+ " > Invalidation matched, next: {:?}, ({:?})",
1323
+ next_invalidation, next_combinator
1324
+ );
1325
+
1326
+ next_invalidation.kind()
1327
+ };
1328
+
1329
+ // We can skip pushing under some circumstances, and we should
1330
+ // because otherwise the invalidation list could grow
1331
+ // exponentially.
1332
+ //
1333
+ // * First of all, both invalidations need to be of the same
1334
+ // kind. This is because of how we propagate them going to
1335
+ // the right of the tree for sibling invalidations and going
1336
+ // down the tree for children invalidations. A sibling
1337
+ // invalidation that ends up generating a children
1338
+ // invalidation ends up (correctly) in five different lists,
1339
+ // not in the same list five different times.
1340
+ //
1341
+ // * Then, the invalidation needs to be matched by a previous
1342
+ // ancestor/sibling, in order to know that this invalidation
1343
+ // has been generated already.
1344
+ //
1345
+ // * Finally, the new invalidation needs to be
1346
+ // `effective_for_next()`, in order for us to know that it is
1347
+ // still in the list, since we remove the dependencies that
1348
+ // aren't from the lists for our children / siblings.
1349
+ //
1350
+ // To go through an example, let's imagine we are processing a
1351
+ // dom subtree like:
1352
+ //
1353
+ // <div><address><div><div/></div></address></div>
1354
+ //
1355
+ // And an invalidation list with a single invalidation like:
1356
+ //
1357
+ // [div div div]
1358
+ //
1359
+ // When we process the invalidation list for the outer div, we
1360
+ // match it, and generate a `div div` invalidation, so for the
1361
+ // <address> child we have:
1362
+ //
1363
+ // [div div div, div div]
1364
+ //
1365
+ // With the first of them marked as `matched`.
1366
+ //
1367
+ // When we process the <address> child, we don't match any of
1368
+ // them, so both invalidations go untouched to our children.
1369
+ //
1370
+ // When we process the second <div>, we match _both_
1371
+ // invalidations.
1372
+ //
1373
+ // However, when matching the first, we can tell it's been
1374
+ // matched, and not push the corresponding `div div`
1375
+ // invalidation, since we know it's necessarily already on the
1376
+ // list.
1377
+ //
1378
+ // Thus, without skipping the push, we'll arrive to the
1379
+ // innermost <div> with:
1380
+ //
1381
+ // [div div div, div div, div div, div]
1382
+ //
1383
+ // While skipping it, we won't arrive here with duplicating
1384
+ // dependencies:
1385
+ //
1386
+ // [div div div, div div, div]
1387
+ //
1388
+ let can_skip_pushing = next_invalidation_kind == invalidation_kind
1389
+ && invalidation.matched_by_any_previous
1390
+ && next_invalidation.effective_for_next();
1391
+
1392
+ if can_skip_pushing {
1393
+ debug!(
1394
+ " > Can avoid push, since the invalidation had \
1395
+ already been matched before"
1396
+ );
1397
+ } else {
1398
+ match next_invalidation_kind {
1399
+ InvalidationKind::Descendant(DescendantInvalidationKind::Dom) => {
1400
+ descendant_invalidations
1401
+ .dom_descendants
1402
+ .push(next_invalidation);
1403
+ },
1404
+ InvalidationKind::Descendant(DescendantInvalidationKind::Part) => {
1405
+ descendant_invalidations.parts.push(next_invalidation);
1406
+ },
1407
+ InvalidationKind::Descendant(DescendantInvalidationKind::Slotted) => {
1408
+ descendant_invalidations
1409
+ .slotted_descendants
1410
+ .push(next_invalidation);
1411
+ },
1412
+ InvalidationKind::Sibling => {
1413
+ sibling_invalidations.push(next_invalidation);
1414
+ },
1415
+ }
1416
+ }
1417
+ }
1418
+
1419
+ result
1420
+ }
1421
+ }
1422
+
1423
+ /// Note the child dependencies of a scope end selector
1424
+ /// This is necessary because the scope end selector is not bound to :scope
1425
+ ///
1426
+ /// e.g @scope to (.b) {:scope .a .c {...}}
1427
+ /// in the case of the following:
1428
+ /// <div class=a><div id=x class=b><div class=c></div></div></div>
1429
+ ///
1430
+ /// If we toggle class "b" in x, we would have to go up to find .a
1431
+ /// if we wanted to invalidate correctly. However, this is costly.
1432
+ /// Instead we just invalidate to the subject of the selector .c
1433
+ pub fn note_scope_dependency_force_at_subject<'selectors>(
1434
+ dependency: &'selectors Dependency,
1435
+ current_host: Option<OpaqueElement>,
1436
+ scope: Option<OpaqueElement>,
1437
+ traversed_non_subject: bool,
1438
+ ) -> Vec<Invalidation<'selectors>> {
1439
+ let mut invalidations: Vec<Invalidation> = Vec::new();
1440
+ if let Some(next) = dependency.next.as_ref() {
1441
+ for dep in next.slice() {
1442
+ if dep.selector.is_rightmost(dep.selector_offset) && !traversed_non_subject {
1443
+ continue;
1444
+ }
1445
+
1446
+ // Follow the normal dependencies as far as we can, leaving
1447
+ // other kinds to their own invalidation mechanisms elsewhere
1448
+ if dep.next.is_some()
1449
+ && matches!(
1450
+ dep.invalidation_kind(),
1451
+ DependencyInvalidationKind::Normal(_)
1452
+ )
1453
+ {
1454
+ invalidations.extend(note_scope_dependency_force_at_subject(
1455
+ dep,
1456
+ current_host,
1457
+ scope,
1458
+ // Force add from now on because we
1459
+ // passed through a non-subject compound
1460
+ true,
1461
+ ));
1462
+ } else {
1463
+ let invalidation = Invalidation::new_subject_invalidation(dep, current_host, scope);
1464
+
1465
+ invalidations.push(invalidation);
1466
+ }
1467
+ }
1468
+ }
1469
+ invalidations
1470
+ }