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,2258 @@
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
+ #![allow(unsafe_code)]
6
+
7
+ //! Wrapper definitions on top of Gecko types in order to be used in the style
8
+ //! system.
9
+ //!
10
+ //! This really follows the Servo pattern in
11
+ //! `components/script/layout_wrapper.rs`.
12
+ //!
13
+ //! This theoretically should live in its own crate, but now it lives in the
14
+ //! style system it's kind of pointless in the Stylo case, and only Servo forces
15
+ //! the separation between the style system implementation and everything else.
16
+
17
+ use crate::applicable_declarations::ApplicableDeclarationBlock;
18
+ use crate::bloom::each_relevant_element_hash;
19
+ use crate::context::{QuirksMode, SharedStyleContext, UpdateAnimationsTasks};
20
+ use crate::data::{ElementDataMut, ElementDataRef, ElementDataWrapper};
21
+ use crate::device::Device;
22
+ use crate::dom::{LayoutIterator, NodeInfo, OpaqueNode, TDocument, TElement, TNode, TShadowRoot};
23
+ use crate::gecko::selector_parser::{NonTSPseudoClass, PseudoElement, SelectorImpl};
24
+ use crate::gecko::snapshot_helpers;
25
+ use crate::gecko_bindings::bindings;
26
+ use crate::gecko_bindings::bindings::Gecko_ElementHasAnimations;
27
+ use crate::gecko_bindings::bindings::Gecko_ElementHasCSSAnimations;
28
+ use crate::gecko_bindings::bindings::Gecko_ElementHasCSSTransitions;
29
+ use crate::gecko_bindings::bindings::Gecko_ElementState;
30
+ use crate::gecko_bindings::bindings::Gecko_GetActiveLinkAttrDeclarationBlock;
31
+ use crate::gecko_bindings::bindings::Gecko_GetAnimationEffectCount;
32
+ use crate::gecko_bindings::bindings::Gecko_GetAnimationRule;
33
+ use crate::gecko_bindings::bindings::Gecko_GetExtraContentStyleDeclarations;
34
+ use crate::gecko_bindings::bindings::Gecko_GetStyleAttrDeclarationBlock;
35
+ use crate::gecko_bindings::bindings::Gecko_GetUnvisitedLinkAttrDeclarationBlock;
36
+ use crate::gecko_bindings::bindings::Gecko_GetVisitedLinkAttrDeclarationBlock;
37
+ use crate::gecko_bindings::bindings::Gecko_IsSignificantChild;
38
+ use crate::gecko_bindings::bindings::Gecko_MatchLang;
39
+ use crate::gecko_bindings::bindings::Gecko_UpdateAnimations;
40
+ use crate::gecko_bindings::structs;
41
+ use crate::gecko_bindings::structs::nsChangeHint;
42
+ use crate::gecko_bindings::structs::EffectCompositor_CascadeLevel as CascadeLevel;
43
+ use crate::gecko_bindings::structs::ELEMENT_HANDLED_SNAPSHOT;
44
+ use crate::gecko_bindings::structs::ELEMENT_HAS_ANIMATION_ONLY_DIRTY_DESCENDANTS_FOR_SERVO;
45
+ use crate::gecko_bindings::structs::ELEMENT_HAS_DIRTY_DESCENDANTS_FOR_SERVO;
46
+ use crate::gecko_bindings::structs::ELEMENT_HAS_SNAPSHOT;
47
+ use crate::gecko_bindings::structs::NODE_DESCENDANTS_NEED_FRAMES;
48
+ use crate::gecko_bindings::structs::NODE_NEEDS_FRAME;
49
+ use crate::gecko_bindings::structs::{nsAtom, nsIContent, nsINode_BooleanFlag};
50
+ use crate::gecko_bindings::structs::{nsINode as RawGeckoNode, Element as RawGeckoElement};
51
+ use crate::global_style_data::GLOBAL_STYLE_DATA;
52
+ use crate::invalidation::element::restyle_hints::RestyleHint;
53
+ use crate::properties::{
54
+ animated_properties::{AnimationValue, AnimationValueMap},
55
+ ComputedValues, Importance, OwnedPropertyDeclarationId, PropertyDeclaration,
56
+ PropertyDeclarationBlock, PropertyDeclarationId, PropertyDeclarationIdSet,
57
+ };
58
+ use crate::rule_tree::CascadeLevel as ServoCascadeLevel;
59
+ use crate::rule_tree::CascadeOrigin as ServoCascadeOrigin;
60
+ use crate::selector_parser::{AttrValue, Lang};
61
+ use crate::shared_lock::{Locked, SharedRwLock};
62
+ use crate::string_cache::{Atom, Namespace, WeakAtom, WeakNamespace};
63
+ use crate::stylesheets::scope_rule::ImplicitScopeRoot;
64
+ use crate::stylist::CascadeData;
65
+ use crate::values::computed::Display;
66
+ use crate::values::{AtomIdent, AtomString};
67
+ use crate::CaseSensitivityExt;
68
+ use crate::LocalName;
69
+ use app_units::Au;
70
+ use dom::{DocumentState, ElementState};
71
+ use euclid::default::Size2D;
72
+ use nsstring::nsString;
73
+ use rustc_hash::FxHashMap;
74
+ use selectors::attr::{AttrSelectorOperation, CaseSensitivity, NamespaceConstraint};
75
+ use selectors::bloom::{BloomFilter, BLOOM_HASH_MASK};
76
+ use selectors::matching::VisitedHandlingMode;
77
+ use selectors::matching::{ElementSelectorFlags, MatchingContext};
78
+ use selectors::sink::Push;
79
+ use selectors::{Element, OpaqueElement};
80
+ use servo_arc::{Arc, ArcBorrow};
81
+ use std::cell::Cell;
82
+ use std::hash::{Hash, Hasher};
83
+ use std::sync::atomic::{AtomicU32, Ordering};
84
+ use std::{fmt, mem, ptr};
85
+
86
+ #[inline]
87
+ fn elements_with_id<'a, 'le>(
88
+ array: structs::RustSpan<*const RawGeckoElement>,
89
+ ) -> &'a [GeckoElement<'le>] {
90
+ unsafe {
91
+ let elements: &[*const RawGeckoElement] =
92
+ std::slice::from_raw_parts(array.begin, array.length);
93
+
94
+ // NOTE(emilio): We rely on the in-memory representation of
95
+ // GeckoElement<'ld> and *const RawGeckoElement being the same.
96
+ #[allow(dead_code)]
97
+ unsafe fn static_assert() {
98
+ unsafe {
99
+ mem::transmute::<*mut RawGeckoElement, GeckoElement<'static>>(0xbadc0de as *mut _);
100
+ }
101
+ }
102
+
103
+ mem::transmute(elements)
104
+ }
105
+ }
106
+
107
+ /// A simple wrapper over `Document`.
108
+ #[derive(Clone, Copy)]
109
+ pub struct GeckoDocument<'ld>(pub &'ld structs::Document);
110
+
111
+ impl<'ld> TDocument for GeckoDocument<'ld> {
112
+ type ConcreteNode = GeckoNode<'ld>;
113
+
114
+ #[inline]
115
+ fn as_node(&self) -> Self::ConcreteNode {
116
+ GeckoNode(&self.0._base)
117
+ }
118
+
119
+ #[inline]
120
+ fn is_html_document(&self) -> bool {
121
+ self.0.mType == structs::Document_Type::eHTML
122
+ }
123
+
124
+ #[inline]
125
+ fn quirks_mode(&self) -> QuirksMode {
126
+ self.0.mCompatMode.into()
127
+ }
128
+
129
+ #[inline]
130
+ fn elements_with_id<'a>(&self, id: &AtomIdent) -> Result<&'a [GeckoElement<'ld>], ()>
131
+ where
132
+ Self: 'a,
133
+ {
134
+ Ok(elements_with_id(unsafe {
135
+ bindings::Gecko_Document_GetElementsWithId(self.0, id.as_ptr())
136
+ }))
137
+ }
138
+
139
+ fn shared_lock(&self) -> &SharedRwLock {
140
+ &GLOBAL_STYLE_DATA.shared_lock
141
+ }
142
+ }
143
+
144
+ /// A simple wrapper over `ShadowRoot`.
145
+ #[derive(Clone, Copy)]
146
+ pub struct GeckoShadowRoot<'lr>(pub &'lr structs::ShadowRoot);
147
+
148
+ impl<'ln> fmt::Debug for GeckoShadowRoot<'ln> {
149
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
150
+ // TODO(emilio): Maybe print the host or something?
151
+ write!(f, "<shadow-root> ({:#x})", self.as_node().opaque().0)
152
+ }
153
+ }
154
+
155
+ impl<'lr> PartialEq for GeckoShadowRoot<'lr> {
156
+ #[inline]
157
+ fn eq(&self, other: &Self) -> bool {
158
+ std::ptr::eq(self.0, other.0)
159
+ }
160
+ }
161
+
162
+ impl<'lr> TShadowRoot for GeckoShadowRoot<'lr> {
163
+ type ConcreteNode = GeckoNode<'lr>;
164
+
165
+ #[inline]
166
+ fn as_node(&self) -> Self::ConcreteNode {
167
+ GeckoNode(&self.0._base._base._base._base)
168
+ }
169
+
170
+ #[inline]
171
+ fn host(&self) -> GeckoElement<'lr> {
172
+ GeckoElement(unsafe { &*self.0._base.mHost.mRawPtr })
173
+ }
174
+
175
+ #[inline]
176
+ fn style_data<'a>(&self) -> Option<&'a CascadeData>
177
+ where
178
+ Self: 'a,
179
+ {
180
+ let author_styles = unsafe { self.0.mServoStyles.mPtr.as_ref()? };
181
+ Some(&author_styles.data)
182
+ }
183
+
184
+ #[inline]
185
+ fn elements_with_id<'a>(&self, id: &AtomIdent) -> Result<&'a [GeckoElement<'lr>], ()>
186
+ where
187
+ Self: 'a,
188
+ {
189
+ Ok(elements_with_id(unsafe {
190
+ bindings::Gecko_ShadowRoot_GetElementsWithId(self.0, id.as_ptr())
191
+ }))
192
+ }
193
+
194
+ #[inline]
195
+ fn parts<'a>(&self) -> &[<Self::ConcreteNode as TNode>::ConcreteElement]
196
+ where
197
+ Self: 'a,
198
+ {
199
+ let slice: &[*const RawGeckoElement] = &self.0.mParts;
200
+
201
+ #[allow(dead_code)]
202
+ unsafe fn static_assert() {
203
+ unsafe {
204
+ mem::transmute::<*const RawGeckoElement, GeckoElement<'static>>(
205
+ 0xbadc0de as *const _,
206
+ );
207
+ }
208
+ }
209
+
210
+ unsafe { mem::transmute(slice) }
211
+ }
212
+
213
+ #[inline]
214
+ fn implicit_scope_for_sheet(&self, sheet_index: usize) -> Option<ImplicitScopeRoot> {
215
+ use crate::stylesheets::StylesheetInDocument;
216
+
217
+ let author_styles = unsafe { self.0.mServoStyles.mPtr.as_ref()? };
218
+ let sheet = author_styles.stylesheets.get(sheet_index)?;
219
+ sheet.implicit_scope_root()
220
+ }
221
+ }
222
+
223
+ /// A simple wrapper over a non-null Gecko node (`nsINode`) pointer.
224
+ ///
225
+ /// Important: We don't currently refcount the DOM, because the wrapper lifetime
226
+ /// magic guarantees that our LayoutFoo references won't outlive the root, and
227
+ /// we don't mutate any of the references on the Gecko side during restyle.
228
+ ///
229
+ /// We could implement refcounting if need be (at a potentially non-trivial
230
+ /// performance cost) by implementing Drop and making LayoutFoo non-Copy.
231
+ #[derive(Clone, Copy)]
232
+ pub struct GeckoNode<'ln>(pub &'ln RawGeckoNode);
233
+
234
+ impl<'ln> PartialEq for GeckoNode<'ln> {
235
+ #[inline]
236
+ fn eq(&self, other: &Self) -> bool {
237
+ std::ptr::eq(self.0, other.0)
238
+ }
239
+ }
240
+
241
+ impl<'ln> fmt::Debug for GeckoNode<'ln> {
242
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
243
+ if let Some(el) = self.as_element() {
244
+ return el.fmt(f);
245
+ }
246
+
247
+ if self.is_text_node() {
248
+ return write!(f, "<text node> ({:#x})", self.opaque().0);
249
+ }
250
+
251
+ if self.is_document() {
252
+ return write!(f, "<document> ({:#x})", self.opaque().0);
253
+ }
254
+
255
+ if let Some(sr) = self.as_shadow_root() {
256
+ return sr.fmt(f);
257
+ }
258
+
259
+ write!(f, "<non-text node> ({:#x})", self.opaque().0)
260
+ }
261
+ }
262
+
263
+ impl<'ln> GeckoNode<'ln> {
264
+ #[inline]
265
+ fn is_document(&self) -> bool {
266
+ // This is a DOM constant that isn't going to change.
267
+ const DOCUMENT_NODE: u16 = 9;
268
+ self.node_info().mInner.mNodeType == DOCUMENT_NODE
269
+ }
270
+
271
+ #[inline]
272
+ fn is_shadow_root(&self) -> bool {
273
+ self.is_in_shadow_tree() && self.parent_node().is_none()
274
+ }
275
+
276
+ #[inline]
277
+ fn from_content(content: &'ln nsIContent) -> Self {
278
+ GeckoNode(&content._base)
279
+ }
280
+
281
+ #[inline]
282
+ fn set_flags(&self, flags: u32) {
283
+ self.flags_atomic().fetch_or(flags, Ordering::Relaxed);
284
+ }
285
+
286
+ fn flags_atomic_for(flags: &Cell<u32>) -> &AtomicU32 {
287
+ const_assert!(mem::size_of::<Cell<u32>>() == mem::size_of::<AtomicU32>());
288
+ const_assert!(mem::align_of::<Cell<u32>>() == mem::align_of::<AtomicU32>());
289
+
290
+ // Rust doesn't provide standalone atomic functions like GCC/clang do
291
+ // (via the atomic intrinsics) or via std::atomic_ref, but it guarantees
292
+ // that the memory representation of u32 and AtomicU32 matches:
293
+ // https://doc.rust-lang.org/std/sync/atomic/struct.AtomicU32.html
294
+ unsafe { mem::transmute::<&Cell<u32>, &AtomicU32>(flags) }
295
+ }
296
+
297
+ #[inline]
298
+ fn flags_atomic(&self) -> &AtomicU32 {
299
+ Self::flags_atomic_for(&self.0._base._base_1.mFlags)
300
+ }
301
+
302
+ #[inline]
303
+ fn flags(&self) -> u32 {
304
+ self.flags_atomic().load(Ordering::Relaxed)
305
+ }
306
+
307
+ #[inline]
308
+ fn may_have_element_children(&self) -> bool {
309
+ self.flags() & structs::NODE_MAY_HAVE_ELEMENT_CHILDREN != 0
310
+ }
311
+
312
+ #[inline]
313
+ fn selector_flags_atomic(&self) -> &AtomicU32 {
314
+ Self::flags_atomic_for(&self.0.mSelectorFlags)
315
+ }
316
+
317
+ #[inline]
318
+ fn selector_flags(&self) -> u32 {
319
+ self.selector_flags_atomic().load(Ordering::Relaxed)
320
+ }
321
+
322
+ #[inline]
323
+ fn set_selector_flags(&self, flags: u32) {
324
+ self.selector_flags_atomic()
325
+ .fetch_or(flags, Ordering::Relaxed);
326
+ }
327
+
328
+ #[inline]
329
+ fn node_info(&self) -> &structs::NodeInfo {
330
+ debug_assert!(!self.0.mNodeInfo.mRawPtr.is_null());
331
+ unsafe { &*self.0.mNodeInfo.mRawPtr }
332
+ }
333
+
334
+ // These live in different locations depending on processor architecture.
335
+ #[cfg(target_pointer_width = "64")]
336
+ #[inline]
337
+ fn bool_flags(&self) -> u32 {
338
+ (self.0)._base._base_1.mBoolFlags
339
+ }
340
+
341
+ #[cfg(target_pointer_width = "32")]
342
+ #[inline]
343
+ fn bool_flags(&self) -> u32 {
344
+ (self.0).mBoolFlags
345
+ }
346
+
347
+ #[inline]
348
+ fn get_bool_flag(&self, flag: nsINode_BooleanFlag) -> bool {
349
+ self.bool_flags() & (1u32 << flag as u32) != 0
350
+ }
351
+
352
+ /// This logic is duplicate in Gecko's nsINode::IsInShadowTree().
353
+ #[inline]
354
+ fn is_in_shadow_tree(&self) -> bool {
355
+ use crate::gecko_bindings::structs::NODE_IS_IN_SHADOW_TREE;
356
+ self.flags() & NODE_IS_IN_SHADOW_TREE != 0
357
+ }
358
+
359
+ /// Returns true if we know for sure that `flattened_tree_parent` and `parent_node` return the
360
+ /// same thing.
361
+ ///
362
+ /// TODO(emilio): Measure and consider not doing this fast-path, it's only a function call and
363
+ /// from profiles it seems that keeping this fast path makes the compiler not inline
364
+ /// `flattened_tree_parent` as a whole, so we're not gaining much either.
365
+ #[inline]
366
+ fn flattened_tree_parent_is_parent(&self) -> bool {
367
+ use crate::gecko_bindings::structs::*;
368
+ let flags = self.flags();
369
+
370
+ let parent = match self.parent_node() {
371
+ Some(p) => p,
372
+ None => return true,
373
+ };
374
+
375
+ if parent.is_shadow_root() {
376
+ return false;
377
+ }
378
+
379
+ if let Some(parent) = parent.as_element() {
380
+ if flags & NODE_IS_NATIVE_ANONYMOUS_ROOT != 0 && parent.is_root() {
381
+ return false;
382
+ }
383
+ if parent.shadow_root().is_some() || parent.is_html_slot_element() {
384
+ return false;
385
+ }
386
+ }
387
+
388
+ true
389
+ }
390
+
391
+ #[inline]
392
+ fn flattened_tree_parent(&self) -> Option<Self> {
393
+ if self.flattened_tree_parent_is_parent() {
394
+ debug_assert_eq!(
395
+ unsafe {
396
+ bindings::Gecko_GetFlattenedTreeParentNode(self.0)
397
+ .as_ref()
398
+ .map(GeckoNode)
399
+ },
400
+ self.parent_node(),
401
+ "Fast path stopped holding!"
402
+ );
403
+ return self.parent_node();
404
+ }
405
+
406
+ // NOTE(emilio): If this call is too expensive, we could manually inline more aggressively.
407
+ unsafe {
408
+ bindings::Gecko_GetFlattenedTreeParentNode(self.0)
409
+ .as_ref()
410
+ .map(GeckoNode)
411
+ }
412
+ }
413
+
414
+ #[inline]
415
+ fn contains_non_whitespace_content(&self) -> bool {
416
+ unsafe { Gecko_IsSignificantChild(self.0, false) }
417
+ }
418
+
419
+ /// Returns the previous sibling of this node that is an element.
420
+ #[inline]
421
+ pub fn prev_sibling_element(&self) -> Option<GeckoElement<'ln>> {
422
+ if !self.parent_node()?.may_have_element_children() {
423
+ return None;
424
+ }
425
+ let mut prev = self.prev_sibling();
426
+ while let Some(p) = prev {
427
+ if let Some(e) = p.as_element() {
428
+ return Some(e);
429
+ }
430
+ prev = p.prev_sibling();
431
+ }
432
+ None
433
+ }
434
+
435
+ /// Returns the next sibling of this node that is an element.
436
+ #[inline]
437
+ pub fn next_sibling_element(&self) -> Option<GeckoElement<'ln>> {
438
+ if !self.parent_node()?.may_have_element_children() {
439
+ return None;
440
+ }
441
+ let mut next = self.next_sibling();
442
+ while let Some(n) = next {
443
+ if let Some(e) = n.as_element() {
444
+ return Some(e);
445
+ }
446
+ next = n.next_sibling();
447
+ }
448
+ None
449
+ }
450
+
451
+ /// Returns last child sibling of this node that is an element.
452
+ #[inline]
453
+ pub fn last_child_element(&self) -> Option<GeckoElement<'ln>> {
454
+ let last = self.last_child()?;
455
+ if let Some(e) = last.as_element() {
456
+ return Some(e);
457
+ }
458
+ None
459
+ }
460
+ }
461
+
462
+ impl<'ln> NodeInfo for GeckoNode<'ln> {
463
+ #[inline]
464
+ fn is_element(&self) -> bool {
465
+ self.get_bool_flag(nsINode_BooleanFlag::NodeIsElement)
466
+ }
467
+
468
+ fn is_text_node(&self) -> bool {
469
+ // This is a DOM constant that isn't going to change.
470
+ const TEXT_NODE: u16 = 3;
471
+ self.node_info().mInner.mNodeType == TEXT_NODE
472
+ }
473
+ }
474
+
475
+ impl<'ln> TNode for GeckoNode<'ln> {
476
+ type ConcreteDocument = GeckoDocument<'ln>;
477
+ type ConcreteShadowRoot = GeckoShadowRoot<'ln>;
478
+ type ConcreteElement = GeckoElement<'ln>;
479
+
480
+ #[inline]
481
+ fn parent_node(&self) -> Option<Self> {
482
+ unsafe { self.0.mParent.as_ref().map(GeckoNode) }
483
+ }
484
+
485
+ #[inline]
486
+ fn first_child(&self) -> Option<Self> {
487
+ unsafe {
488
+ self.0
489
+ .mFirstChild
490
+ .raw()
491
+ .as_ref()
492
+ .map(GeckoNode::from_content)
493
+ }
494
+ }
495
+
496
+ #[inline]
497
+ fn last_child(&self) -> Option<Self> {
498
+ unsafe { bindings::Gecko_GetLastChild(self.0).as_ref().map(GeckoNode) }
499
+ }
500
+
501
+ #[inline]
502
+ fn prev_sibling(&self) -> Option<Self> {
503
+ unsafe {
504
+ let prev_or_last = GeckoNode::from_content(self.0.mPreviousOrLastSibling.as_ref()?);
505
+ if prev_or_last.0.mNextSibling.raw().is_null() {
506
+ return None;
507
+ }
508
+ Some(prev_or_last)
509
+ }
510
+ }
511
+
512
+ #[inline]
513
+ fn next_sibling(&self) -> Option<Self> {
514
+ unsafe {
515
+ self.0
516
+ .mNextSibling
517
+ .raw()
518
+ .as_ref()
519
+ .map(GeckoNode::from_content)
520
+ }
521
+ }
522
+
523
+ #[inline]
524
+ fn owner_doc(&self) -> Self::ConcreteDocument {
525
+ debug_assert!(!self.node_info().mDocument.is_null());
526
+ GeckoDocument(unsafe { &*self.node_info().mDocument })
527
+ }
528
+
529
+ #[inline]
530
+ fn is_in_document(&self) -> bool {
531
+ self.get_bool_flag(nsINode_BooleanFlag::IsInDocument)
532
+ }
533
+
534
+ fn traversal_parent(&self) -> Option<GeckoElement<'ln>> {
535
+ self.flattened_tree_parent().and_then(|n| n.as_element())
536
+ }
537
+
538
+ #[inline]
539
+ fn opaque(&self) -> OpaqueNode {
540
+ let ptr: usize = self.0 as *const _ as usize;
541
+ OpaqueNode(ptr)
542
+ }
543
+
544
+ fn debug_id(self) -> usize {
545
+ unimplemented!()
546
+ }
547
+
548
+ #[inline]
549
+ fn as_element(&self) -> Option<GeckoElement<'ln>> {
550
+ if !self.is_element() {
551
+ return None;
552
+ }
553
+
554
+ Some(GeckoElement(unsafe {
555
+ &*(self.0 as *const _ as *const RawGeckoElement)
556
+ }))
557
+ }
558
+
559
+ #[inline]
560
+ fn as_document(&self) -> Option<Self::ConcreteDocument> {
561
+ if !self.is_document() {
562
+ return None;
563
+ }
564
+
565
+ debug_assert_eq!(self.owner_doc().as_node(), *self, "How?");
566
+ Some(self.owner_doc())
567
+ }
568
+
569
+ #[inline]
570
+ fn as_shadow_root(&self) -> Option<Self::ConcreteShadowRoot> {
571
+ if !self.is_shadow_root() {
572
+ return None;
573
+ }
574
+
575
+ Some(GeckoShadowRoot(unsafe {
576
+ &*(self.0 as *const _ as *const structs::ShadowRoot)
577
+ }))
578
+ }
579
+ }
580
+
581
+ /// A wrapper on top of two kind of iterators, depending on the parent being
582
+ /// iterated.
583
+ ///
584
+ /// We generally iterate children by traversing the light-tree siblings of the
585
+ /// first child like Servo does.
586
+ ///
587
+ /// However, for nodes with anonymous children, we use a custom (heavier-weight)
588
+ /// Gecko-implemented iterator.
589
+ ///
590
+ /// FIXME(emilio): If we take into account shadow DOM, we're going to need the
591
+ /// flat tree pretty much always. We can try to optimize the case where there's
592
+ /// no shadow root sibling, probably.
593
+ pub enum GeckoChildrenIterator<'a> {
594
+ /// A simple iterator that tracks the current node being iterated and
595
+ /// replaces it with the next sibling when requested.
596
+ Current(Option<GeckoNode<'a>>),
597
+ /// A Gecko-implemented iterator we need to drop appropriately.
598
+ GeckoIterator(mem::ManuallyDrop<structs::StyleChildrenIterator>),
599
+ }
600
+
601
+ impl<'a> Drop for GeckoChildrenIterator<'a> {
602
+ fn drop(&mut self) {
603
+ if let GeckoChildrenIterator::GeckoIterator(ref mut it) = *self {
604
+ unsafe {
605
+ bindings::Gecko_DestroyStyleChildrenIterator(&mut **it);
606
+ }
607
+ }
608
+ }
609
+ }
610
+
611
+ impl<'a> Iterator for GeckoChildrenIterator<'a> {
612
+ type Item = GeckoNode<'a>;
613
+ fn next(&mut self) -> Option<GeckoNode<'a>> {
614
+ match *self {
615
+ GeckoChildrenIterator::Current(curr) => {
616
+ let next = curr.and_then(|node| node.next_sibling());
617
+ *self = GeckoChildrenIterator::Current(next);
618
+ curr
619
+ },
620
+ GeckoChildrenIterator::GeckoIterator(ref mut it) => unsafe {
621
+ // We do this unsafe lengthening of the lifetime here because
622
+ // structs::StyleChildrenIterator is actually StyleChildrenIterator<'a>,
623
+ // however we can't express this easily with bindgen, and it would
624
+ // introduce functions with two input lifetimes into bindgen,
625
+ // which would be out of scope for elision.
626
+ bindings::Gecko_GetNextStyleChild(&mut **it)
627
+ .as_ref()
628
+ .map(GeckoNode)
629
+ },
630
+ }
631
+ }
632
+ }
633
+
634
+ /// A simple wrapper over a non-null Gecko `Element` pointer.
635
+ #[derive(Clone, Copy)]
636
+ pub struct GeckoElement<'le>(pub &'le RawGeckoElement);
637
+
638
+ impl<'le> fmt::Debug for GeckoElement<'le> {
639
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
640
+ use nsstring::nsCString;
641
+
642
+ write!(f, "<{}", self.local_name())?;
643
+
644
+ let mut attrs = nsCString::new();
645
+ unsafe {
646
+ bindings::Gecko_Element_DebugListAttributes(self.0, &mut attrs);
647
+ }
648
+ write!(f, "{}", attrs)?;
649
+ write!(f, "> ({:#x})", self.as_node().opaque().0)
650
+ }
651
+ }
652
+
653
+ impl<'le> GeckoElement<'le> {
654
+ /// Gets the raw `ElementDataWrapper` for the element.
655
+ #[inline(always)]
656
+ pub fn get_data(&self) -> Option<&ElementDataWrapper> {
657
+ unsafe { self.0.mServoData.get().as_ref() }
658
+ }
659
+
660
+ /// Returns whether any animation applies to this element.
661
+ #[inline]
662
+ pub fn has_any_animation(&self) -> bool {
663
+ self.may_have_animations() && unsafe { Gecko_ElementHasAnimations(self.0) }
664
+ }
665
+
666
+ /// Check if mImpl contains a real pointer (not a bloom filter).
667
+ #[inline(always)]
668
+ fn has_attr_impl(&self) -> bool {
669
+ let ptr = self.0.mAttrs.mImpl.mPtr as usize;
670
+ ptr != 0 && (ptr & 1) == 0
671
+ }
672
+
673
+ #[inline(always)]
674
+ fn attrs(&self) -> &[structs::AttrArray_InternalAttr] {
675
+ unsafe {
676
+ if !self.has_attr_impl() {
677
+ return &[];
678
+ }
679
+ match self.0.mAttrs.mImpl.mPtr.as_ref() {
680
+ Some(attrs) => attrs.mBuffer.as_slice(attrs.mAttrCount as usize),
681
+ None => &[],
682
+ }
683
+ }
684
+ }
685
+
686
+ #[inline(always)]
687
+ fn get_part_attr(&self) -> Option<&structs::nsAttrValue> {
688
+ if !self.has_part_attr() {
689
+ return None;
690
+ }
691
+ snapshot_helpers::find_attr(self.attrs(), &atom!("part"))
692
+ }
693
+
694
+ #[inline(always)]
695
+ fn get_class_attr(&self) -> Option<&structs::nsAttrValue> {
696
+ if !self.may_have_class() {
697
+ return None;
698
+ }
699
+
700
+ if self.is_svg_element() {
701
+ let svg_class = unsafe { bindings::Gecko_GetSVGAnimatedClass(self.0).as_ref() };
702
+ if let Some(c) = svg_class {
703
+ return Some(c);
704
+ }
705
+ }
706
+
707
+ snapshot_helpers::find_attr(self.attrs(), &atom!("class"))
708
+ }
709
+
710
+ #[inline]
711
+ fn may_have_anonymous_children(&self) -> bool {
712
+ self.as_node()
713
+ .get_bool_flag(nsINode_BooleanFlag::ElementMayHaveAnonymousChildren)
714
+ }
715
+
716
+ #[inline]
717
+ fn flags(&self) -> u32 {
718
+ self.as_node().flags()
719
+ }
720
+
721
+ #[inline]
722
+ fn set_flags(&self, flags: u32) {
723
+ self.as_node().set_flags(flags);
724
+ }
725
+
726
+ #[inline]
727
+ unsafe fn unset_flags(&self, flags: u32) {
728
+ self.as_node()
729
+ .flags_atomic()
730
+ .fetch_and(!flags, Ordering::Relaxed);
731
+ }
732
+
733
+ /// Returns true if this element has descendants for lazy frame construction.
734
+ #[inline]
735
+ pub fn descendants_need_frames(&self) -> bool {
736
+ self.flags() & NODE_DESCENDANTS_NEED_FRAMES != 0
737
+ }
738
+
739
+ /// Returns true if this element needs lazy frame construction.
740
+ #[inline]
741
+ pub fn needs_frame(&self) -> bool {
742
+ self.flags() & NODE_NEEDS_FRAME != 0
743
+ }
744
+
745
+ /// Returns a reference to the DOM slots for this Element, if they exist.
746
+ #[inline]
747
+ fn dom_slots(&self) -> Option<&structs::FragmentOrElement_nsDOMSlots> {
748
+ // For the bit usage, see nsINode::mSlotsOrListenerManager.
749
+ let slots_or_elm = self.as_node().0.mSlotsOrListenerManager;
750
+ if slots_or_elm & structs::nsINode_kListenerManagerBit != 0 {
751
+ return None;
752
+ }
753
+ let slots = slots_or_elm as *const structs::FragmentOrElement_nsDOMSlots;
754
+ unsafe { slots.as_ref() }
755
+ }
756
+
757
+ /// Returns a reference to the extended DOM slots for this Element.
758
+ #[inline]
759
+ fn extended_slots(&self) -> Option<&structs::FragmentOrElement_nsExtendedDOMSlots> {
760
+ self.dom_slots().and_then(|s| unsafe {
761
+ // For the bit usage, see nsContentSlots::GetExtendedSlots.
762
+ let e_slots = s._base.mExtendedSlots
763
+ & !structs::nsIContent_nsContentSlots_sNonOwningExtendedSlotsFlag;
764
+ (e_slots as *const structs::FragmentOrElement_nsExtendedDOMSlots).as_ref()
765
+ })
766
+ }
767
+
768
+ #[inline]
769
+ fn namespace_id(&self) -> i32 {
770
+ self.as_node().node_info().mInner.mNamespaceID
771
+ }
772
+
773
+ #[inline]
774
+ fn has_id(&self) -> bool {
775
+ self.as_node()
776
+ .get_bool_flag(nsINode_BooleanFlag::ElementHasID)
777
+ }
778
+
779
+ #[inline]
780
+ fn state_internal(&self) -> u64 {
781
+ if !self
782
+ .as_node()
783
+ .get_bool_flag(nsINode_BooleanFlag::ElementHasLockedStyleStates)
784
+ {
785
+ return self.0.mState.bits;
786
+ }
787
+ unsafe { Gecko_ElementState(self.0) }
788
+ }
789
+
790
+ #[inline]
791
+ fn document_state(&self) -> DocumentState {
792
+ DocumentState::from_bits_retain(self.as_node().owner_doc().0.mState.bits)
793
+ }
794
+
795
+ #[inline]
796
+ fn may_have_class(&self) -> bool {
797
+ self.as_node()
798
+ .get_bool_flag(nsINode_BooleanFlag::ElementMayHaveClass)
799
+ }
800
+
801
+ #[inline]
802
+ fn has_properties(&self) -> bool {
803
+ use crate::gecko_bindings::structs::NODE_HAS_PROPERTIES;
804
+
805
+ self.flags() & NODE_HAS_PROPERTIES != 0
806
+ }
807
+
808
+ #[inline]
809
+ fn may_have_style_attribute(&self) -> bool {
810
+ self.as_node()
811
+ .get_bool_flag(nsINode_BooleanFlag::ElementMayHaveStyle)
812
+ }
813
+
814
+ /// Only safe to call on the main thread, with exclusive access to the
815
+ /// element and its ancestors.
816
+ ///
817
+ /// This function is also called after display property changed for SMIL
818
+ /// animation.
819
+ ///
820
+ /// Also this function schedules style flush.
821
+ pub unsafe fn note_explicit_hints(&self, restyle_hint: RestyleHint, change_hint: nsChangeHint) {
822
+ use crate::gecko::restyle_damage::GeckoRestyleDamage;
823
+
824
+ let damage = GeckoRestyleDamage::new(change_hint);
825
+ debug!(
826
+ "note_explicit_hints: {:?}, restyle_hint={:?}, change_hint={:?}",
827
+ self, restyle_hint, change_hint
828
+ );
829
+ debug_assert!(unsafe { bindings::Gecko_IsMainThread() });
830
+ debug_assert!(
831
+ !(restyle_hint.has_animation_hint() && restyle_hint.has_non_animation_hint()),
832
+ "Animation restyle hints should not appear with non-animation restyle hints"
833
+ );
834
+
835
+ let Some(mut data) = self.mutate_data() else {
836
+ debug!("(Element not styled, discarding hints)");
837
+ return;
838
+ };
839
+
840
+ // Propagate the bit up the chain.
841
+ unsafe {
842
+ if restyle_hint.has_animation_hint() {
843
+ bindings::Gecko_NoteAnimationOnlyDirtyElement(self.0);
844
+ } else {
845
+ bindings::Gecko_NoteDirtyElement(self.0);
846
+ }
847
+ }
848
+
849
+ data.hint.insert(restyle_hint);
850
+ data.damage |= damage;
851
+ }
852
+
853
+ /// This logic is duplicated in Gecko's nsIContent::IsRootOfNativeAnonymousSubtree.
854
+ #[inline]
855
+ fn is_root_of_native_anonymous_subtree(&self) -> bool {
856
+ self.flags() & structs::NODE_IS_NATIVE_ANONYMOUS_ROOT != 0
857
+ }
858
+
859
+ /// Whether the element is in an anonymous subtree. Note that this includes UA widgets!
860
+ #[inline]
861
+ fn in_native_anonymous_subtree(&self) -> bool {
862
+ (self.flags() & structs::NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE) != 0
863
+ }
864
+
865
+ /// Whether the element has been in a UA widget
866
+ #[inline]
867
+ fn in_ua_widget(&self) -> bool {
868
+ (self.flags() & structs::NODE_HAS_BEEN_IN_UA_WIDGET) != 0
869
+ }
870
+
871
+ fn css_transitions_info(&self) -> FxHashMap<OwnedPropertyDeclarationId, Arc<AnimationValue>> {
872
+ use crate::gecko_bindings::bindings::Gecko_ElementTransitions_EndValueAt;
873
+ use crate::gecko_bindings::bindings::Gecko_ElementTransitions_Length;
874
+
875
+ let collection_length = unsafe { Gecko_ElementTransitions_Length(self.0) } as usize;
876
+ let mut map = FxHashMap::with_capacity_and_hasher(collection_length, Default::default());
877
+
878
+ for i in 0..collection_length {
879
+ let end_value =
880
+ unsafe { Arc::from_raw_addrefed(Gecko_ElementTransitions_EndValueAt(self.0, i)) };
881
+ let property = end_value.id();
882
+ debug_assert!(!property.is_logical());
883
+ map.insert(property.to_owned(), end_value);
884
+ }
885
+ map
886
+ }
887
+
888
+ fn needs_transitions_update_per_property(
889
+ &self,
890
+ property_declaration_id: PropertyDeclarationId,
891
+ combined_duration_seconds: f32,
892
+ before_change_style: &ComputedValues,
893
+ after_change_style: &ComputedValues,
894
+ existing_transitions: &FxHashMap<OwnedPropertyDeclarationId, Arc<AnimationValue>>,
895
+ ) -> bool {
896
+ debug_assert!(!property_declaration_id.is_logical());
897
+
898
+ // If there is an existing transition, update only if the end value
899
+ // differs.
900
+ //
901
+ // If the end value has not changed, we should leave the currently
902
+ // running transition as-is since we don't want to interrupt its timing
903
+ // function.
904
+ if let Some(existing) = existing_transitions.get(&property_declaration_id.to_owned()) {
905
+ let after_value =
906
+ AnimationValue::from_computed_values(property_declaration_id, after_change_style);
907
+ debug_assert!(
908
+ after_value.is_some()
909
+ || matches!(property_declaration_id, PropertyDeclarationId::Custom(..))
910
+ );
911
+ return after_value.is_none() || **existing != after_value.unwrap();
912
+ }
913
+
914
+ if combined_duration_seconds <= 0.0f32 {
915
+ return false;
916
+ }
917
+
918
+ AnimationValue::is_different_for(
919
+ property_declaration_id,
920
+ before_change_style,
921
+ after_change_style,
922
+ )
923
+ }
924
+
925
+ /// Get slow selector flags required for nth-of invalidation.
926
+ pub fn slow_selector_flags(&self) -> ElementSelectorFlags {
927
+ slow_selector_flags_from_node_selector_flags(self.as_node().selector_flags())
928
+ }
929
+ }
930
+
931
+ /// Convert slow selector flags from the raw `NodeSelectorFlags`.
932
+ pub fn slow_selector_flags_from_node_selector_flags(flags: u32) -> ElementSelectorFlags {
933
+ use crate::gecko_bindings::structs::NodeSelectorFlags;
934
+ let mut result = ElementSelectorFlags::empty();
935
+ if flags & NodeSelectorFlags::HasSlowSelector.0 != 0 {
936
+ result.insert(ElementSelectorFlags::HAS_SLOW_SELECTOR);
937
+ }
938
+ if flags & NodeSelectorFlags::HasSlowSelectorLaterSiblings.0 != 0 {
939
+ result.insert(ElementSelectorFlags::HAS_SLOW_SELECTOR_LATER_SIBLINGS);
940
+ }
941
+ result
942
+ }
943
+
944
+ /// Converts flags from the layout used by rust-selectors to the layout used
945
+ /// by Gecko. We could align these and then do this without conditionals, but
946
+ /// it's probably not worth the trouble.
947
+ fn selector_flags_to_node_flags(flags: ElementSelectorFlags) -> u32 {
948
+ use crate::gecko_bindings::structs::NodeSelectorFlags;
949
+ let mut gecko_flags = 0u32;
950
+ if flags.contains(ElementSelectorFlags::HAS_SLOW_SELECTOR) {
951
+ gecko_flags |= NodeSelectorFlags::HasSlowSelector.0;
952
+ }
953
+ if flags.contains(ElementSelectorFlags::HAS_SLOW_SELECTOR_LATER_SIBLINGS) {
954
+ gecko_flags |= NodeSelectorFlags::HasSlowSelectorLaterSiblings.0;
955
+ }
956
+ if flags.contains(ElementSelectorFlags::HAS_SLOW_SELECTOR_NTH) {
957
+ gecko_flags |= NodeSelectorFlags::HasSlowSelectorNth.0;
958
+ }
959
+ if flags.contains(ElementSelectorFlags::HAS_SLOW_SELECTOR_NTH_OF) {
960
+ gecko_flags |= NodeSelectorFlags::HasSlowSelectorNthOf.0;
961
+ }
962
+ if flags.contains(ElementSelectorFlags::HAS_EDGE_CHILD_SELECTOR) {
963
+ gecko_flags |= NodeSelectorFlags::HasEdgeChildSelector.0;
964
+ }
965
+ if flags.contains(ElementSelectorFlags::HAS_EMPTY_SELECTOR) {
966
+ gecko_flags |= NodeSelectorFlags::HasEmptySelector.0;
967
+ }
968
+ if flags.contains(ElementSelectorFlags::ANCHORS_RELATIVE_SELECTOR) {
969
+ gecko_flags |= NodeSelectorFlags::RelativeSelectorAnchor.0;
970
+ }
971
+ if flags.contains(ElementSelectorFlags::ANCHORS_RELATIVE_SELECTOR_NON_SUBJECT) {
972
+ gecko_flags |= NodeSelectorFlags::RelativeSelectorAnchorNonSubject.0;
973
+ }
974
+ if flags.contains(ElementSelectorFlags::RELATIVE_SELECTOR_SEARCH_DIRECTION_ANCESTOR) {
975
+ gecko_flags |= NodeSelectorFlags::RelativeSelectorSearchDirectionAncestor.0;
976
+ }
977
+ if flags.contains(ElementSelectorFlags::RELATIVE_SELECTOR_SEARCH_DIRECTION_SIBLING) {
978
+ gecko_flags |= NodeSelectorFlags::RelativeSelectorSearchDirectionSibling.0;
979
+ }
980
+ if flags.contains(ElementSelectorFlags::MAY_HAVE_TREE_COUNTING_FUNCTION) {
981
+ gecko_flags |= NodeSelectorFlags::MayHaveTreeCountingFunction.0;
982
+ }
983
+
984
+ gecko_flags
985
+ }
986
+
987
+ fn get_animation_rule(
988
+ element: &GeckoElement,
989
+ cascade_level: CascadeLevel,
990
+ ) -> Option<Arc<Locked<PropertyDeclarationBlock>>> {
991
+ // There's a very rough correlation between the number of effects
992
+ // (animations) on an element and the number of properties it is likely to
993
+ // animate, so we use that as an initial guess for the size of the
994
+ // AnimationValueMap in order to reduce the number of re-allocations needed.
995
+ let effect_count = unsafe { Gecko_GetAnimationEffectCount(element.0) };
996
+ // Also, we should try to reuse the PDB, to avoid creating extra rule nodes.
997
+ let mut animation_values = AnimationValueMap::with_capacity_and_hasher(
998
+ effect_count.min(crate::properties::property_counts::ANIMATABLE),
999
+ Default::default(),
1000
+ );
1001
+ if unsafe { Gecko_GetAnimationRule(element.0, cascade_level, &mut animation_values) } {
1002
+ let shared_lock = &GLOBAL_STYLE_DATA.shared_lock;
1003
+ Some(Arc::new(shared_lock.wrap(
1004
+ PropertyDeclarationBlock::from_animation_value_map(&animation_values),
1005
+ )))
1006
+ } else {
1007
+ None
1008
+ }
1009
+ }
1010
+
1011
+ /// Turns a gecko namespace id into an atom. Might panic if you pass any random thing that isn't a
1012
+ /// namespace id.
1013
+ #[inline(always)]
1014
+ pub unsafe fn namespace_id_to_atom(id: i32) -> *mut nsAtom {
1015
+ unsafe {
1016
+ let namespace_manager = structs::nsNameSpaceManager_sInstance.mRawPtr;
1017
+ (&(*namespace_manager).mURIArray)[id as usize].mRawPtr
1018
+ }
1019
+ }
1020
+
1021
+ impl<'le> TElement for GeckoElement<'le> {
1022
+ type ConcreteNode = GeckoNode<'le>;
1023
+ type TraversalChildrenIterator = GeckoChildrenIterator<'le>;
1024
+
1025
+ fn implicit_scope_for_sheet_in_shadow_root(
1026
+ opaque_host: OpaqueElement,
1027
+ sheet_index: usize,
1028
+ ) -> Option<ImplicitScopeRoot> {
1029
+ // As long as this "unopaqued" element does not escape this function, we're not leaking
1030
+ // potentially-mutable elements from opaque elements.
1031
+ let e = unsafe {
1032
+ Self(
1033
+ opaque_host
1034
+ .as_const_ptr::<RawGeckoElement>()
1035
+ .as_ref()
1036
+ .unwrap(),
1037
+ )
1038
+ };
1039
+ let shadow_root = e.shadow_root()?;
1040
+ shadow_root.implicit_scope_for_sheet(sheet_index)
1041
+ }
1042
+
1043
+ fn inheritance_parent(&self) -> Option<Self> {
1044
+ if let Some(pseudo) = self.implemented_pseudo_element() {
1045
+ if !pseudo.is_element_backed() {
1046
+ return self.pseudo_element_originating_element();
1047
+ }
1048
+ }
1049
+
1050
+ self.as_node()
1051
+ .flattened_tree_parent()
1052
+ .and_then(|n| n.as_element())
1053
+ }
1054
+
1055
+ fn traversal_children(&self) -> LayoutIterator<GeckoChildrenIterator<'le>> {
1056
+ // This condition is similar to the check that
1057
+ // StyleChildrenIterator::IsNeeded does, except that it might return
1058
+ // true if we used to (but no longer) have anonymous content from
1059
+ // ::before/::after, or nsIAnonymousContentCreators.
1060
+ if self.is_html_slot_element()
1061
+ || self.shadow_root().is_some()
1062
+ || self.may_have_anonymous_children()
1063
+ {
1064
+ unsafe {
1065
+ let mut iter = mem::MaybeUninit::<structs::StyleChildrenIterator>::uninit();
1066
+ bindings::Gecko_ConstructStyleChildrenIterator(self.0, iter.as_mut_ptr());
1067
+ return LayoutIterator(GeckoChildrenIterator::GeckoIterator(
1068
+ mem::ManuallyDrop::new(iter.assume_init()),
1069
+ ));
1070
+ }
1071
+ }
1072
+
1073
+ LayoutIterator(GeckoChildrenIterator::Current(self.as_node().first_child()))
1074
+ }
1075
+
1076
+ #[inline]
1077
+ fn is_html_element(&self) -> bool {
1078
+ self.namespace_id() == structs::kNameSpaceID_XHTML as i32
1079
+ }
1080
+
1081
+ #[inline]
1082
+ fn is_mathml_element(&self) -> bool {
1083
+ self.namespace_id() == structs::kNameSpaceID_MathML as i32
1084
+ }
1085
+
1086
+ #[inline]
1087
+ fn is_svg_element(&self) -> bool {
1088
+ self.namespace_id() == structs::kNameSpaceID_SVG as i32
1089
+ }
1090
+
1091
+ #[inline]
1092
+ fn is_xul_element(&self) -> bool {
1093
+ self.namespace_id() == structs::root::kNameSpaceID_XUL as i32
1094
+ }
1095
+
1096
+ #[inline]
1097
+ fn is_html_media_element(&self) -> bool {
1098
+ self.is_html_element()
1099
+ && (self.local_name().as_ptr() == local_name!("video").as_ptr()
1100
+ || self.local_name().as_ptr() == local_name!("audio").as_ptr())
1101
+ }
1102
+
1103
+ #[inline]
1104
+ fn subtree_bloom_filter(&self) -> u64 {
1105
+ unsafe { bindings::Gecko_Element_GetSubtreeBloomFilter(self.0) }
1106
+ }
1107
+
1108
+ #[inline]
1109
+ fn local_name(&self) -> &WeakAtom {
1110
+ unsafe { WeakAtom::new(self.as_node().node_info().mInner.mName) }
1111
+ }
1112
+
1113
+ #[inline]
1114
+ fn namespace(&self) -> &WeakNamespace {
1115
+ unsafe { WeakNamespace::new(namespace_id_to_atom(self.namespace_id())) }
1116
+ }
1117
+
1118
+ #[inline]
1119
+ fn query_container_size(&self, display: &Display) -> Size2D<Option<Au>> {
1120
+ // If an element gets 'display: contents' and its nsIFrame has not been removed yet,
1121
+ // Gecko_GetQueryContainerSize will not notice that it can't have size containment.
1122
+ // Other cases like 'display: inline' will be handled once the new nsIFrame is created.
1123
+ if display.is_contents() {
1124
+ return Size2D::new(None, None);
1125
+ }
1126
+
1127
+ let mut width = -1;
1128
+ let mut height = -1;
1129
+ unsafe {
1130
+ bindings::Gecko_GetQueryContainerSize(self.0, &mut width, &mut height);
1131
+ }
1132
+ Size2D::new(
1133
+ if width >= 0 { Some(Au(width)) } else { None },
1134
+ if height >= 0 { Some(Au(height)) } else { None },
1135
+ )
1136
+ }
1137
+
1138
+ /// Return the list of slotted nodes of this node.
1139
+ #[inline]
1140
+ fn slotted_nodes(&self) -> &[Self::ConcreteNode] {
1141
+ if !self.is_html_slot_element() || !self.as_node().is_in_shadow_tree() {
1142
+ return &[];
1143
+ }
1144
+ if cfg!(debug_assertions) {
1145
+ let slot: &structs::HTMLSlotElement = unsafe { mem::transmute(self.0) };
1146
+ let base: &RawGeckoElement = &slot._base._base._base;
1147
+ assert_eq!(base as *const _, self.0 as *const _, "Bad cast");
1148
+ }
1149
+ unsafe {
1150
+ let nodes = bindings::Gecko_GetAssignedNodes(self.0);
1151
+ let nodes: &[*const RawGeckoNode] =
1152
+ std::slice::from_raw_parts(nodes.begin, nodes.length);
1153
+ // NOTE(emilio): We rely on the in-memory representation of
1154
+ // GeckoNode<'ld> and *const RawGeckoNode being the same.
1155
+ #[allow(dead_code)]
1156
+ unsafe fn static_assert() {
1157
+ unsafe {
1158
+ mem::transmute::<*mut RawGeckoNode, GeckoNode<'static>>(0xbadc0de as *mut _);
1159
+ }
1160
+ }
1161
+ mem::transmute(nodes)
1162
+ }
1163
+ }
1164
+
1165
+ #[inline]
1166
+ fn shadow_root(&self) -> Option<GeckoShadowRoot<'le>> {
1167
+ let slots = self.extended_slots()?;
1168
+ unsafe { slots.mShadowRoot.mRawPtr.as_ref().map(GeckoShadowRoot) }
1169
+ }
1170
+
1171
+ fn note_highlight_pseudo_style_invalidated(&self) {
1172
+ let doc = self.as_node().owner_doc().0;
1173
+ unsafe {
1174
+ bindings::Gecko_NoteHighlightPseudoStyleInvalidated(doc);
1175
+ }
1176
+ }
1177
+
1178
+ #[inline]
1179
+ fn containing_shadow(&self) -> Option<GeckoShadowRoot<'le>> {
1180
+ if !self.as_node().is_in_shadow_tree() {
1181
+ return None;
1182
+ }
1183
+ let sr = self.as_node().0.mSubtreeRoot as *const structs::ShadowRoot;
1184
+ Some(GeckoShadowRoot(unsafe { &*sr }))
1185
+ }
1186
+
1187
+ fn each_anonymous_content_child<F>(&self, mut f: F)
1188
+ where
1189
+ F: FnMut(Self),
1190
+ {
1191
+ if !self.may_have_anonymous_children() {
1192
+ return;
1193
+ }
1194
+
1195
+ thin_vec::auto_thin_vec!(let array: [*mut nsIContent; 8]);
1196
+ unsafe {
1197
+ bindings::Gecko_GetAnonymousContentForElement(self.0, array.as_mut().as_mut_ptr())
1198
+ };
1199
+ for content in array.iter() {
1200
+ let node = GeckoNode::from_content(unsafe { &**content });
1201
+ let element = match node.as_element() {
1202
+ Some(e) => e,
1203
+ None => continue,
1204
+ };
1205
+ f(element);
1206
+ }
1207
+ }
1208
+
1209
+ #[inline]
1210
+ fn as_node(&self) -> Self::ConcreteNode {
1211
+ unsafe { GeckoNode(&*(self.0 as *const _ as *const RawGeckoNode)) }
1212
+ }
1213
+
1214
+ fn owner_doc_matches_for_testing(&self, device: &Device) -> bool {
1215
+ std::ptr::eq(self.as_node().owner_doc().0, device.document())
1216
+ }
1217
+
1218
+ fn style_attribute(&self) -> Option<ArcBorrow<'_, Locked<PropertyDeclarationBlock>>> {
1219
+ if !self.may_have_style_attribute() {
1220
+ return None;
1221
+ }
1222
+
1223
+ unsafe {
1224
+ let declarations = Gecko_GetStyleAttrDeclarationBlock(self.0).as_ref()?;
1225
+ Some(ArcBorrow::from_ref(declarations))
1226
+ }
1227
+ }
1228
+
1229
+ fn smil_override(&self) -> Option<ArcBorrow<'_, Locked<PropertyDeclarationBlock>>> {
1230
+ unsafe {
1231
+ let slots = self.extended_slots()?;
1232
+ let raw: &structs::StyleLockedDeclarationBlock =
1233
+ slots.mSMILOverrideStyleDeclaration.mRawPtr.as_ref()?;
1234
+ Some(ArcBorrow::from_ref(raw))
1235
+ }
1236
+ }
1237
+
1238
+ fn animation_rule(
1239
+ &self,
1240
+ _: &SharedStyleContext,
1241
+ ) -> Option<Arc<Locked<PropertyDeclarationBlock>>> {
1242
+ get_animation_rule(self, CascadeLevel::Animations)
1243
+ }
1244
+
1245
+ fn transition_rule(
1246
+ &self,
1247
+ _: &SharedStyleContext,
1248
+ ) -> Option<Arc<Locked<PropertyDeclarationBlock>>> {
1249
+ get_animation_rule(self, CascadeLevel::Transitions)
1250
+ }
1251
+
1252
+ #[inline]
1253
+ fn state(&self) -> ElementState {
1254
+ ElementState::from_bits_retain(self.state_internal())
1255
+ }
1256
+
1257
+ #[inline]
1258
+ fn has_part_attr(&self) -> bool {
1259
+ self.as_node()
1260
+ .get_bool_flag(nsINode_BooleanFlag::ElementHasPart)
1261
+ }
1262
+
1263
+ #[inline]
1264
+ fn exports_any_part(&self) -> bool {
1265
+ snapshot_helpers::find_attr(self.attrs(), &atom!("exportparts")).is_some()
1266
+ }
1267
+
1268
+ // FIXME(emilio): we should probably just return a reference to the Atom.
1269
+ #[inline]
1270
+ fn id(&self) -> Option<&WeakAtom> {
1271
+ if !self.has_id() {
1272
+ return None;
1273
+ }
1274
+ snapshot_helpers::get_id(self.attrs())
1275
+ }
1276
+
1277
+ fn each_attr_name<F>(&self, mut callback: F)
1278
+ where
1279
+ F: FnMut(&AtomIdent),
1280
+ {
1281
+ for attr in self.attrs() {
1282
+ unsafe { AtomIdent::with(attr.mName.name(), |a| callback(a)) }
1283
+ }
1284
+ }
1285
+
1286
+ fn each_class<F>(&self, callback: F)
1287
+ where
1288
+ F: FnMut(&AtomIdent),
1289
+ {
1290
+ let attr = match self.get_class_attr() {
1291
+ Some(c) => c,
1292
+ None => return,
1293
+ };
1294
+
1295
+ snapshot_helpers::each_class_or_part(attr, callback)
1296
+ }
1297
+
1298
+ #[inline]
1299
+ fn each_custom_state<F>(&self, mut callback: F)
1300
+ where
1301
+ F: FnMut(&AtomIdent),
1302
+ {
1303
+ if let Some(slots) = self.extended_slots() {
1304
+ unsafe {
1305
+ for atom in slots.mCustomStates.iter() {
1306
+ AtomIdent::with(atom.mRawPtr, &mut callback)
1307
+ }
1308
+ }
1309
+ }
1310
+ }
1311
+
1312
+ #[inline]
1313
+ fn each_exported_part<F>(&self, name: &AtomIdent, callback: F)
1314
+ where
1315
+ F: FnMut(&AtomIdent),
1316
+ {
1317
+ snapshot_helpers::each_exported_part(self.attrs(), name, callback)
1318
+ }
1319
+
1320
+ fn each_part<F>(&self, callback: F)
1321
+ where
1322
+ F: FnMut(&AtomIdent),
1323
+ {
1324
+ let attr = match self.get_part_attr() {
1325
+ Some(c) => c,
1326
+ None => return,
1327
+ };
1328
+
1329
+ snapshot_helpers::each_class_or_part(attr, callback)
1330
+ }
1331
+
1332
+ #[inline]
1333
+ fn has_snapshot(&self) -> bool {
1334
+ self.flags() & ELEMENT_HAS_SNAPSHOT != 0
1335
+ }
1336
+
1337
+ #[inline]
1338
+ fn handled_snapshot(&self) -> bool {
1339
+ self.flags() & ELEMENT_HANDLED_SNAPSHOT != 0
1340
+ }
1341
+
1342
+ unsafe fn set_handled_snapshot(&self) {
1343
+ debug_assert!(self.has_data());
1344
+ self.set_flags(ELEMENT_HANDLED_SNAPSHOT)
1345
+ }
1346
+
1347
+ #[inline]
1348
+ fn has_dirty_descendants(&self) -> bool {
1349
+ self.flags() & ELEMENT_HAS_DIRTY_DESCENDANTS_FOR_SERVO != 0
1350
+ }
1351
+
1352
+ unsafe fn set_dirty_descendants(&self) {
1353
+ debug_assert!(self.has_data());
1354
+ debug!("Setting dirty descendants: {:?}", self);
1355
+ self.set_flags(ELEMENT_HAS_DIRTY_DESCENDANTS_FOR_SERVO)
1356
+ }
1357
+
1358
+ unsafe fn unset_dirty_descendants(&self) {
1359
+ unsafe { self.unset_flags(ELEMENT_HAS_DIRTY_DESCENDANTS_FOR_SERVO) }
1360
+ }
1361
+
1362
+ #[inline]
1363
+ fn has_animation_only_dirty_descendants(&self) -> bool {
1364
+ self.flags() & ELEMENT_HAS_ANIMATION_ONLY_DIRTY_DESCENDANTS_FOR_SERVO != 0
1365
+ }
1366
+
1367
+ unsafe fn set_animation_only_dirty_descendants(&self) {
1368
+ self.set_flags(ELEMENT_HAS_ANIMATION_ONLY_DIRTY_DESCENDANTS_FOR_SERVO)
1369
+ }
1370
+
1371
+ unsafe fn unset_animation_only_dirty_descendants(&self) {
1372
+ unsafe { self.unset_flags(ELEMENT_HAS_ANIMATION_ONLY_DIRTY_DESCENDANTS_FOR_SERVO) }
1373
+ }
1374
+
1375
+ unsafe fn clear_descendant_bits(&self) {
1376
+ unsafe {
1377
+ self.unset_flags(
1378
+ ELEMENT_HAS_DIRTY_DESCENDANTS_FOR_SERVO
1379
+ | ELEMENT_HAS_ANIMATION_ONLY_DIRTY_DESCENDANTS_FOR_SERVO
1380
+ | NODE_DESCENDANTS_NEED_FRAMES,
1381
+ )
1382
+ }
1383
+ }
1384
+
1385
+ fn is_visited_link(&self) -> bool {
1386
+ self.state().intersects(ElementState::VISITED)
1387
+ }
1388
+
1389
+ /// We want to match rules from the same tree in all cases, except for native anonymous content
1390
+ /// that _isn't_ part directly of a UA widget (e.g., such generated by form controls, or
1391
+ /// pseudo-elements).
1392
+ #[inline]
1393
+ fn matches_user_and_content_rules(&self) -> bool {
1394
+ !self.in_native_anonymous_subtree() || self.in_ua_widget()
1395
+ }
1396
+
1397
+ #[inline]
1398
+ fn implemented_pseudo_element(&self) -> Option<PseudoElement> {
1399
+ if !self.in_native_anonymous_subtree() {
1400
+ return None;
1401
+ }
1402
+
1403
+ if !self.has_properties() {
1404
+ return None;
1405
+ }
1406
+
1407
+ let name = unsafe { bindings::Gecko_GetImplementedPseudoIdentifier(self.0) };
1408
+ PseudoElement::from_pseudo_type(
1409
+ unsafe { bindings::Gecko_GetImplementedPseudoType(self.0) },
1410
+ if name.is_null() {
1411
+ None
1412
+ } else {
1413
+ Some(AtomIdent::new(unsafe { Atom::from_raw(name) }))
1414
+ },
1415
+ )
1416
+ }
1417
+
1418
+ #[inline]
1419
+ fn store_children_to_process(&self, _: isize) {
1420
+ // This is only used for bottom-up traversal, and is thus a no-op for Gecko.
1421
+ }
1422
+
1423
+ fn did_process_child(&self) -> isize {
1424
+ panic!("Atomic child count not implemented in Gecko");
1425
+ }
1426
+
1427
+ unsafe fn ensure_data(&self) -> ElementDataMut<'_> {
1428
+ if !self.has_data() {
1429
+ debug!("Creating ElementData for {:?}", self);
1430
+ let ptr = Box::into_raw(Box::new(ElementDataWrapper::default()));
1431
+ self.0.mServoData.set(ptr);
1432
+ }
1433
+ self.mutate_data().unwrap()
1434
+ }
1435
+
1436
+ unsafe fn clear_data(&self) {
1437
+ #[cfg(debug_assertions)]
1438
+ {
1439
+ // Perform a mutable borrow of the data in debug builds. This serves as an assertion
1440
+ // that there are no outstanding borrows when we destroy the data.
1441
+ let _ = self.mutate_data();
1442
+ }
1443
+ let ptr = self.0.mServoData.get();
1444
+ unsafe {
1445
+ self.unset_flags(
1446
+ ELEMENT_HAS_SNAPSHOT
1447
+ | ELEMENT_HANDLED_SNAPSHOT
1448
+ | structs::Element_kAllServoDescendantBits
1449
+ | NODE_NEEDS_FRAME,
1450
+ );
1451
+ if !ptr.is_null() {
1452
+ debug!("Dropping ElementData for {:?}", self);
1453
+ let _data = Box::from_raw(self.0.mServoData.get());
1454
+ self.0.mServoData.set(ptr::null_mut());
1455
+ }
1456
+ }
1457
+ }
1458
+
1459
+ #[inline]
1460
+ fn skip_item_display_fixup(&self) -> bool {
1461
+ debug_assert!(
1462
+ !self.is_pseudo_element(),
1463
+ "Just don't call me if I'm a pseudo, you should know the answer already"
1464
+ );
1465
+ self.is_root_of_native_anonymous_subtree()
1466
+ }
1467
+
1468
+ #[inline]
1469
+ fn may_have_animations(&self) -> bool {
1470
+ if let Some(pseudo) = self.implemented_pseudo_element() {
1471
+ if pseudo.animations_stored_in_parent() {
1472
+ // FIXME(emilio): When would the parent of a ::before / ::after
1473
+ // pseudo-element be null?
1474
+ return self.parent_element().is_some_and(|p| {
1475
+ p.as_node()
1476
+ .get_bool_flag(nsINode_BooleanFlag::ElementHasAnimations)
1477
+ });
1478
+ }
1479
+ }
1480
+ self.as_node()
1481
+ .get_bool_flag(nsINode_BooleanFlag::ElementHasAnimations)
1482
+ }
1483
+
1484
+ /// Update various animation-related state on a given (pseudo-)element as
1485
+ /// results of normal restyle.
1486
+ fn update_animations(
1487
+ &self,
1488
+ before_change_style: Option<Arc<ComputedValues>>,
1489
+ tasks: UpdateAnimationsTasks,
1490
+ ) {
1491
+ // We have to update animations even if the element has no computed
1492
+ // style since it means the element is in a display:none subtree, we
1493
+ // should destroy all CSS animations in display:none subtree.
1494
+ let computed_data = self.borrow_data();
1495
+ let computed_values = computed_data.as_ref().map(|d| d.styles.primary());
1496
+ let before_change_values = before_change_style
1497
+ .as_ref()
1498
+ .map_or(ptr::null(), |x| x.as_gecko_computed_style());
1499
+ let computed_values_opt = computed_values
1500
+ .as_ref()
1501
+ .map_or(ptr::null(), |x| x.as_gecko_computed_style());
1502
+ unsafe {
1503
+ Gecko_UpdateAnimations(
1504
+ self.0,
1505
+ before_change_values,
1506
+ computed_values_opt,
1507
+ tasks.bits(),
1508
+ );
1509
+ }
1510
+ }
1511
+
1512
+ #[inline]
1513
+ fn has_animations(&self, _: &SharedStyleContext) -> bool {
1514
+ self.has_any_animation()
1515
+ }
1516
+
1517
+ fn has_css_animations(&self, _: &SharedStyleContext, _: Option<PseudoElement>) -> bool {
1518
+ self.may_have_animations() && unsafe { Gecko_ElementHasCSSAnimations(self.0) }
1519
+ }
1520
+
1521
+ fn has_css_transitions(&self, _: &SharedStyleContext, _: Option<PseudoElement>) -> bool {
1522
+ self.may_have_animations() && unsafe { Gecko_ElementHasCSSTransitions(self.0) }
1523
+ }
1524
+
1525
+ // Detect if there are any changes that require us to update transitions.
1526
+ //
1527
+ // This is used as a more thoroughgoing check than the cheaper
1528
+ // might_need_transitions_update check.
1529
+ //
1530
+ // The following logic shadows the logic used on the Gecko side
1531
+ // (nsTransitionManager::DoUpdateTransitions) where we actually perform the
1532
+ // update.
1533
+ //
1534
+ // https://drafts.csswg.org/css-transitions/#starting
1535
+ fn needs_transitions_update(
1536
+ &self,
1537
+ before_change_style: &ComputedValues,
1538
+ after_change_style: &ComputedValues,
1539
+ ) -> bool {
1540
+ let after_change_ui_style = after_change_style.get_ui();
1541
+ let existing_transitions = self.css_transitions_info();
1542
+
1543
+ if after_change_style.get_box().clone_display().is_none()
1544
+ && !crate::pref!("layout.css.display-animations.enabled")
1545
+ {
1546
+ // We need to cancel existing transitions.
1547
+ return !existing_transitions.is_empty();
1548
+ }
1549
+
1550
+ let mut transitions_to_keep = PropertyDeclarationIdSet::default();
1551
+ for transition_property in after_change_style.transition_properties() {
1552
+ let physical_property = transition_property
1553
+ .property
1554
+ .as_borrowed()
1555
+ .to_physical(after_change_style.writing_mode);
1556
+ transitions_to_keep.insert(physical_property);
1557
+ if self.needs_transitions_update_per_property(
1558
+ physical_property,
1559
+ after_change_ui_style
1560
+ .transition_combined_duration_at(transition_property.index)
1561
+ .seconds(),
1562
+ before_change_style,
1563
+ after_change_style,
1564
+ &existing_transitions,
1565
+ ) {
1566
+ return true;
1567
+ }
1568
+ }
1569
+
1570
+ // Check if we have to cancel the running transition because this is not
1571
+ // a matching transition-property value.
1572
+ existing_transitions
1573
+ .keys()
1574
+ .any(|property| !transitions_to_keep.contains(property.as_borrowed()))
1575
+ }
1576
+
1577
+ /// Whether there is an ElementData container.
1578
+ #[inline]
1579
+ fn has_data(&self) -> bool {
1580
+ self.get_data().is_some()
1581
+ }
1582
+
1583
+ /// Immutably borrows the ElementData.
1584
+ fn borrow_data(&self) -> Option<ElementDataRef<'_>> {
1585
+ self.get_data().map(|d| d.borrow())
1586
+ }
1587
+
1588
+ /// Mutably borrows the ElementData.
1589
+ fn mutate_data(&self) -> Option<ElementDataMut<'_>> {
1590
+ self.get_data().map(|d| d.borrow_mut())
1591
+ }
1592
+
1593
+ #[inline]
1594
+ fn lang_attr(&self) -> Option<AttrValue> {
1595
+ let ptr = unsafe { bindings::Gecko_LangValue(self.0) };
1596
+ if ptr.is_null() {
1597
+ None
1598
+ } else {
1599
+ Some(AtomString(unsafe { Atom::from_addrefed(ptr) }))
1600
+ }
1601
+ }
1602
+
1603
+ fn match_element_lang(&self, override_lang: Option<Option<AttrValue>>, value: &Lang) -> bool {
1604
+ // Gecko supports :lang() from CSS Selectors 4, which accepts a list
1605
+ // of language tags, and does BCP47-style range matching.
1606
+ let override_lang_ptr = match override_lang {
1607
+ Some(Some(ref atom)) => atom.as_ptr(),
1608
+ _ => ptr::null_mut(),
1609
+ };
1610
+ value.0.iter().any(|lang| unsafe {
1611
+ Gecko_MatchLang(
1612
+ self.0,
1613
+ override_lang_ptr,
1614
+ override_lang.is_some(),
1615
+ lang.as_slice().as_ptr(),
1616
+ )
1617
+ })
1618
+ }
1619
+
1620
+ fn is_html_document_body_element(&self) -> bool {
1621
+ if self.local_name() != &**local_name!("body") {
1622
+ return false;
1623
+ }
1624
+
1625
+ if !self.is_html_element() {
1626
+ return false;
1627
+ }
1628
+
1629
+ unsafe { bindings::Gecko_IsDocumentBody(self.0) }
1630
+ }
1631
+
1632
+ fn synthesize_view_transition_dynamic_rules<V>(&self, rules: &mut V)
1633
+ where
1634
+ V: Push<ApplicableDeclarationBlock>,
1635
+ {
1636
+ use crate::stylesheets::layer_rule::LayerOrder;
1637
+ let declarations = unsafe { bindings::Gecko_GetViewTransitionDynamicRule(self.0).as_ref() };
1638
+ if let Some(decl) = declarations {
1639
+ rules.push(ApplicableDeclarationBlock::from_declarations(
1640
+ unsafe { Arc::from_raw_addrefed(decl) },
1641
+ ServoCascadeLevel::new(ServoCascadeOrigin::UA),
1642
+ LayerOrder::root(),
1643
+ ));
1644
+ }
1645
+ }
1646
+
1647
+ fn synthesize_presentational_hints_for_legacy_attributes<V>(
1648
+ &self,
1649
+ visited_handling: VisitedHandlingMode,
1650
+ hints: &mut V,
1651
+ ) where
1652
+ V: Push<ApplicableDeclarationBlock>,
1653
+ {
1654
+ use crate::properties::longhands::_x_lang::SpecifiedValue as SpecifiedLang;
1655
+ use crate::properties::longhands::color::SpecifiedValue as SpecifiedColor;
1656
+ use crate::stylesheets::layer_rule::LayerOrder;
1657
+ use crate::values::specified::{color::Color, font::XTextScale};
1658
+ use std::sync::LazyLock;
1659
+
1660
+ static TABLE_COLOR_RULE: LazyLock<ApplicableDeclarationBlock> = LazyLock::new(|| {
1661
+ let global_style_data = &*GLOBAL_STYLE_DATA;
1662
+ let pdb = PropertyDeclarationBlock::with_one(
1663
+ PropertyDeclaration::Color(SpecifiedColor(Color::InheritFromBodyQuirk)),
1664
+ Importance::Normal,
1665
+ );
1666
+ let arc = Arc::new_leaked(global_style_data.shared_lock.wrap(pdb));
1667
+ ApplicableDeclarationBlock::from_declarations(
1668
+ arc,
1669
+ ServoCascadeLevel::new(ServoCascadeOrigin::PresHints),
1670
+ LayerOrder::root(),
1671
+ )
1672
+ });
1673
+ static MATHML_LANG_RULE: LazyLock<ApplicableDeclarationBlock> = LazyLock::new(|| {
1674
+ let global_style_data = &*GLOBAL_STYLE_DATA;
1675
+ let pdb = PropertyDeclarationBlock::with_one(
1676
+ PropertyDeclaration::XLang(SpecifiedLang(atom!("x-math"))),
1677
+ Importance::Normal,
1678
+ );
1679
+ let arc = Arc::new_leaked(global_style_data.shared_lock.wrap(pdb));
1680
+ ApplicableDeclarationBlock::from_declarations(
1681
+ arc,
1682
+ ServoCascadeLevel::new(ServoCascadeOrigin::PresHints),
1683
+ LayerOrder::root(),
1684
+ )
1685
+ });
1686
+ static SVG_TEXT_DISABLE_SCALE_RULE: LazyLock<ApplicableDeclarationBlock> =
1687
+ LazyLock::new(|| {
1688
+ let global_style_data = &*GLOBAL_STYLE_DATA;
1689
+ let pdb = PropertyDeclarationBlock::with_one(
1690
+ PropertyDeclaration::XTextScale(XTextScale::None),
1691
+ Importance::Normal,
1692
+ );
1693
+ let arc = Arc::new_leaked(global_style_data.shared_lock.wrap(pdb));
1694
+ ApplicableDeclarationBlock::from_declarations(
1695
+ arc,
1696
+ ServoCascadeLevel::new(ServoCascadeOrigin::PresHints),
1697
+ LayerOrder::root(),
1698
+ )
1699
+ });
1700
+
1701
+ let ns = self.namespace_id();
1702
+ // <th> elements get a default MozCenterOrInherit which may get overridden
1703
+ if ns == structs::kNameSpaceID_XHTML as i32
1704
+ && self.local_name().as_ptr() == atom!("table").as_ptr()
1705
+ && self.as_node().owner_doc().quirks_mode() == QuirksMode::Quirks
1706
+ {
1707
+ hints.push(TABLE_COLOR_RULE.clone());
1708
+ }
1709
+ if ns == structs::kNameSpaceID_SVG as i32
1710
+ && self.local_name().as_ptr() == atom!("text").as_ptr()
1711
+ {
1712
+ hints.push(SVG_TEXT_DISABLE_SCALE_RULE.clone());
1713
+ }
1714
+ let declarations =
1715
+ unsafe { bindings::Gecko_GetMappedAttributeDeclarations(self.0).as_ref() };
1716
+ if let Some(decl) = declarations {
1717
+ hints.push(ApplicableDeclarationBlock::from_declarations(
1718
+ unsafe { Arc::from_raw_addrefed(decl) },
1719
+ ServoCascadeLevel::new(ServoCascadeOrigin::PresHints),
1720
+ LayerOrder::root(),
1721
+ ));
1722
+ }
1723
+ let declarations = unsafe { Gecko_GetExtraContentStyleDeclarations(self.0).as_ref() };
1724
+ if let Some(decl) = declarations {
1725
+ hints.push(ApplicableDeclarationBlock::from_declarations(
1726
+ unsafe { Arc::from_raw_addrefed(decl) },
1727
+ ServoCascadeLevel::new(ServoCascadeOrigin::PresHints),
1728
+ LayerOrder::root(),
1729
+ ));
1730
+ }
1731
+
1732
+ // Support for link, vlink, and alink presentation hints on <body>
1733
+ if self.is_link() {
1734
+ // Unvisited vs. visited styles are computed up-front based on the
1735
+ // visited mode (not the element's actual state).
1736
+ let declarations = match visited_handling {
1737
+ VisitedHandlingMode::AllLinksVisitedAndUnvisited => {
1738
+ unreachable!(
1739
+ "We should never try to selector match with \
1740
+ AllLinksVisitedAndUnvisited"
1741
+ );
1742
+ },
1743
+ VisitedHandlingMode::AllLinksUnvisited => unsafe {
1744
+ Gecko_GetUnvisitedLinkAttrDeclarationBlock(self.0).as_ref()
1745
+ },
1746
+ VisitedHandlingMode::RelevantLinkVisited => unsafe {
1747
+ Gecko_GetVisitedLinkAttrDeclarationBlock(self.0).as_ref()
1748
+ },
1749
+ };
1750
+ if let Some(decl) = declarations {
1751
+ hints.push(ApplicableDeclarationBlock::from_declarations(
1752
+ unsafe { Arc::from_raw_addrefed(decl) },
1753
+ ServoCascadeLevel::new(ServoCascadeOrigin::PresHints),
1754
+ LayerOrder::root(),
1755
+ ));
1756
+ }
1757
+
1758
+ let active = self
1759
+ .state()
1760
+ .intersects(NonTSPseudoClass::Active.state_flag());
1761
+ if active {
1762
+ let declarations =
1763
+ unsafe { Gecko_GetActiveLinkAttrDeclarationBlock(self.0).as_ref() };
1764
+ if let Some(decl) = declarations {
1765
+ hints.push(ApplicableDeclarationBlock::from_declarations(
1766
+ unsafe { Arc::from_raw_addrefed(decl) },
1767
+ ServoCascadeLevel::new(ServoCascadeOrigin::PresHints),
1768
+ LayerOrder::root(),
1769
+ ));
1770
+ }
1771
+ }
1772
+ }
1773
+
1774
+ // MathML's default lang has precedence over both `lang` and `xml:lang`
1775
+ if !crate::pref!("mathml.font_family_math.enabled")
1776
+ && ns == structs::kNameSpaceID_MathML as i32
1777
+ && self.local_name().as_ptr() == atom!("math").as_ptr()
1778
+ {
1779
+ hints.push(MATHML_LANG_RULE.clone());
1780
+ }
1781
+ }
1782
+
1783
+ fn has_selector_flags(&self, flags: ElementSelectorFlags) -> bool {
1784
+ let node_flags = selector_flags_to_node_flags(flags);
1785
+ self.as_node().selector_flags() & node_flags == node_flags
1786
+ }
1787
+
1788
+ fn relative_selector_search_direction(&self) -> ElementSelectorFlags {
1789
+ use crate::gecko_bindings::structs::NodeSelectorFlags;
1790
+ let flags = self.as_node().selector_flags();
1791
+ if (flags & NodeSelectorFlags::RelativeSelectorSearchDirectionAncestorSibling.0) != 0 {
1792
+ ElementSelectorFlags::RELATIVE_SELECTOR_SEARCH_DIRECTION_ANCESTOR_SIBLING
1793
+ } else if (flags & NodeSelectorFlags::RelativeSelectorSearchDirectionAncestor.0) != 0 {
1794
+ ElementSelectorFlags::RELATIVE_SELECTOR_SEARCH_DIRECTION_ANCESTOR
1795
+ } else if (flags & NodeSelectorFlags::RelativeSelectorSearchDirectionSibling.0) != 0 {
1796
+ ElementSelectorFlags::RELATIVE_SELECTOR_SEARCH_DIRECTION_SIBLING
1797
+ } else {
1798
+ ElementSelectorFlags::empty()
1799
+ }
1800
+ }
1801
+
1802
+ fn get_attr(&self, attr: &LocalName, namespace: &Namespace) -> Option<String> {
1803
+ //TODO(bug 2003334): Avoid unnecessary string copies/conversions here.
1804
+ let mut result = nsString::new();
1805
+ if unsafe {
1806
+ bindings::Gecko_LookupAttrValue(
1807
+ self.0,
1808
+ namespace.as_ptr(),
1809
+ attr.0.as_ptr(),
1810
+ &mut *result,
1811
+ )
1812
+ } {
1813
+ Some(result.to_string())
1814
+ } else {
1815
+ None
1816
+ }
1817
+ }
1818
+ }
1819
+
1820
+ impl<'le> PartialEq for GeckoElement<'le> {
1821
+ #[inline]
1822
+ fn eq(&self, other: &Self) -> bool {
1823
+ std::ptr::eq(self.0, other.0)
1824
+ }
1825
+ }
1826
+
1827
+ impl<'le> Eq for GeckoElement<'le> {}
1828
+
1829
+ impl<'le> Hash for GeckoElement<'le> {
1830
+ #[inline]
1831
+ fn hash<H: Hasher>(&self, state: &mut H) {
1832
+ (self.0 as *const RawGeckoElement).hash(state);
1833
+ }
1834
+ }
1835
+
1836
+ impl<'le> ::selectors::Element for GeckoElement<'le> {
1837
+ type Impl = SelectorImpl;
1838
+
1839
+ #[inline]
1840
+ fn opaque(&self) -> OpaqueElement {
1841
+ OpaqueElement::new(self.0)
1842
+ }
1843
+
1844
+ #[inline]
1845
+ fn parent_element(&self) -> Option<Self> {
1846
+ let parent_node = self.as_node().parent_node();
1847
+ parent_node.and_then(|n| n.as_element())
1848
+ }
1849
+
1850
+ #[inline]
1851
+ fn parent_node_is_shadow_root(&self) -> bool {
1852
+ self.as_node()
1853
+ .parent_node()
1854
+ .is_some_and(|p| p.is_shadow_root())
1855
+ }
1856
+
1857
+ #[inline]
1858
+ fn containing_shadow_host(&self) -> Option<Self> {
1859
+ let shadow = self.containing_shadow()?;
1860
+ Some(shadow.host())
1861
+ }
1862
+
1863
+ #[inline]
1864
+ fn is_pseudo_element(&self) -> bool {
1865
+ self.implemented_pseudo_element().is_some()
1866
+ }
1867
+
1868
+ #[inline]
1869
+ fn pseudo_element_originating_element(&self) -> Option<Self> {
1870
+ debug_assert!(self.is_pseudo_element());
1871
+ debug_assert!(self.in_native_anonymous_subtree());
1872
+ if self.in_ua_widget() {
1873
+ return self.containing_shadow_host();
1874
+ }
1875
+ let mut current = *self;
1876
+ loop {
1877
+ let anon_root = current.is_root_of_native_anonymous_subtree();
1878
+ current = current.traversal_parent()?;
1879
+ if anon_root {
1880
+ return Some(current);
1881
+ }
1882
+ }
1883
+ }
1884
+
1885
+ #[inline]
1886
+ fn assigned_slot(&self) -> Option<Self> {
1887
+ let slot = self.extended_slots()?._base.mAssignedSlot.mRawPtr;
1888
+
1889
+ unsafe { Some(GeckoElement(&slot.as_ref()?._base._base._base)) }
1890
+ }
1891
+
1892
+ #[inline]
1893
+ fn prev_sibling_element(&self) -> Option<Self> {
1894
+ let mut sibling = self.as_node().prev_sibling();
1895
+ while let Some(sibling_node) = sibling {
1896
+ if let Some(el) = sibling_node.as_element() {
1897
+ return Some(el);
1898
+ }
1899
+ sibling = sibling_node.prev_sibling();
1900
+ }
1901
+ None
1902
+ }
1903
+
1904
+ #[inline]
1905
+ fn next_sibling_element(&self) -> Option<Self> {
1906
+ let mut sibling = self.as_node().next_sibling();
1907
+ while let Some(sibling_node) = sibling {
1908
+ if let Some(el) = sibling_node.as_element() {
1909
+ return Some(el);
1910
+ }
1911
+ sibling = sibling_node.next_sibling();
1912
+ }
1913
+ None
1914
+ }
1915
+
1916
+ #[inline]
1917
+ fn first_element_child(&self) -> Option<Self> {
1918
+ let mut child = self.as_node().first_child();
1919
+ while let Some(child_node) = child {
1920
+ if let Some(el) = child_node.as_element() {
1921
+ return Some(el);
1922
+ }
1923
+ child = child_node.next_sibling();
1924
+ }
1925
+ None
1926
+ }
1927
+
1928
+ fn apply_selector_flags(&self, flags: ElementSelectorFlags) {
1929
+ // Handle flags that apply to the element.
1930
+ let self_flags = flags.for_self();
1931
+ if !self_flags.is_empty() {
1932
+ self.as_node()
1933
+ .set_selector_flags(selector_flags_to_node_flags(self_flags))
1934
+ }
1935
+
1936
+ // Handle flags that apply to the parent.
1937
+ let parent_flags = flags.for_parent();
1938
+ if !parent_flags.is_empty() {
1939
+ if let Some(p) = self.as_node().parent_node() {
1940
+ if p.is_element() || p.is_shadow_root() {
1941
+ p.set_selector_flags(selector_flags_to_node_flags(parent_flags));
1942
+ }
1943
+ }
1944
+ }
1945
+ }
1946
+
1947
+ fn has_attr_in_no_namespace(&self, local_name: &LocalName) -> bool {
1948
+ for attr in self.attrs() {
1949
+ if attr.mName.mBits == local_name.as_ptr() as usize {
1950
+ return true;
1951
+ }
1952
+ }
1953
+ false
1954
+ }
1955
+
1956
+ fn attr_matches(
1957
+ &self,
1958
+ ns: &NamespaceConstraint<&Namespace>,
1959
+ local_name: &LocalName,
1960
+ operation: &AttrSelectorOperation<&AttrValue>,
1961
+ ) -> bool {
1962
+ snapshot_helpers::attr_matches(self.attrs(), ns, local_name, operation)
1963
+ }
1964
+
1965
+ #[inline]
1966
+ fn is_root(&self) -> bool {
1967
+ if self
1968
+ .as_node()
1969
+ .get_bool_flag(nsINode_BooleanFlag::ParentIsContent)
1970
+ {
1971
+ return false;
1972
+ }
1973
+
1974
+ if !self.as_node().is_in_document() {
1975
+ return false;
1976
+ }
1977
+
1978
+ debug_assert!(self
1979
+ .as_node()
1980
+ .parent_node()
1981
+ .is_some_and(|p| p.is_document()));
1982
+ // XXX this should always return true at this point, shouldn't it?
1983
+ unsafe { bindings::Gecko_IsRootElement(self.0) }
1984
+ }
1985
+
1986
+ fn is_empty(&self) -> bool {
1987
+ !self
1988
+ .as_node()
1989
+ .dom_children()
1990
+ .any(|child| unsafe { Gecko_IsSignificantChild(child.0, true) })
1991
+ }
1992
+
1993
+ #[inline]
1994
+ fn has_local_name(&self, name: &WeakAtom) -> bool {
1995
+ self.local_name() == name
1996
+ }
1997
+
1998
+ #[inline]
1999
+ fn has_namespace(&self, ns: &WeakNamespace) -> bool {
2000
+ self.namespace() == ns
2001
+ }
2002
+
2003
+ #[inline]
2004
+ fn is_same_type(&self, other: &Self) -> bool {
2005
+ self.local_name() == other.local_name() && self.namespace() == other.namespace()
2006
+ }
2007
+
2008
+ fn match_non_ts_pseudo_class(
2009
+ &self,
2010
+ pseudo_class: &NonTSPseudoClass,
2011
+ context: &mut MatchingContext<Self::Impl>,
2012
+ ) -> bool {
2013
+ use selectors::matching::*;
2014
+ match *pseudo_class {
2015
+ NonTSPseudoClass::Autofill
2016
+ | NonTSPseudoClass::Defined
2017
+ | NonTSPseudoClass::Focus
2018
+ | NonTSPseudoClass::Enabled
2019
+ | NonTSPseudoClass::Disabled
2020
+ | NonTSPseudoClass::Checked
2021
+ | NonTSPseudoClass::Fullscreen
2022
+ | NonTSPseudoClass::Indeterminate
2023
+ | NonTSPseudoClass::MozInert
2024
+ | NonTSPseudoClass::PopoverOpen
2025
+ | NonTSPseudoClass::PlaceholderShown
2026
+ | NonTSPseudoClass::Target
2027
+ | NonTSPseudoClass::Valid
2028
+ | NonTSPseudoClass::Invalid
2029
+ | NonTSPseudoClass::MozBroken
2030
+ | NonTSPseudoClass::Required
2031
+ | NonTSPseudoClass::Optional
2032
+ | NonTSPseudoClass::ReadOnly
2033
+ | NonTSPseudoClass::ReadWrite
2034
+ | NonTSPseudoClass::FocusWithin
2035
+ | NonTSPseudoClass::FocusVisible
2036
+ | NonTSPseudoClass::MozDragOver
2037
+ | NonTSPseudoClass::MozDevtoolsHighlighted
2038
+ | NonTSPseudoClass::MozStyleeditorTransitioning
2039
+ | NonTSPseudoClass::MozMathIncrementScriptLevel
2040
+ | NonTSPseudoClass::InRange
2041
+ | NonTSPseudoClass::OutOfRange
2042
+ | NonTSPseudoClass::Default
2043
+ | NonTSPseudoClass::UserValid
2044
+ | NonTSPseudoClass::UserInvalid
2045
+ | NonTSPseudoClass::MozMeterOptimum
2046
+ | NonTSPseudoClass::MozMeterSubOptimum
2047
+ | NonTSPseudoClass::MozMeterSubSubOptimum
2048
+ | NonTSPseudoClass::MozHasDirAttr
2049
+ | NonTSPseudoClass::MozDirAttrLTR
2050
+ | NonTSPseudoClass::MozDirAttrRTL
2051
+ | NonTSPseudoClass::MozDirAttrLikeAuto
2052
+ | NonTSPseudoClass::Modal
2053
+ | NonTSPseudoClass::MozTopmostModal
2054
+ | NonTSPseudoClass::Open
2055
+ | NonTSPseudoClass::Active
2056
+ | NonTSPseudoClass::Hover
2057
+ | NonTSPseudoClass::HasSlotted
2058
+ | NonTSPseudoClass::MozAutofillPreview
2059
+ | NonTSPseudoClass::MozRevealed
2060
+ | NonTSPseudoClass::ActiveViewTransition
2061
+ | NonTSPseudoClass::MozValueEmpty
2062
+ | NonTSPseudoClass::MozSuppressForPrintSelection
2063
+ | NonTSPseudoClass::Seeking
2064
+ | NonTSPseudoClass::Buffering
2065
+ | NonTSPseudoClass::Stalled
2066
+ | NonTSPseudoClass::PictureInPicture
2067
+ | NonTSPseudoClass::Muted => self.state().intersects(pseudo_class.state_flag()),
2068
+ NonTSPseudoClass::Paused => {
2069
+ self.is_html_media_element() && self.state().intersects(ElementState::PAUSED)
2070
+ },
2071
+ NonTSPseudoClass::Playing => {
2072
+ self.is_html_media_element() && !self.state().intersects(ElementState::PAUSED)
2073
+ },
2074
+ NonTSPseudoClass::VolumeLocked => false, // Bug 2013371
2075
+ NonTSPseudoClass::Dir(ref dir) => self.state().intersects(dir.element_state()),
2076
+ NonTSPseudoClass::ActiveViewTransitionType(ref types) => {
2077
+ self.state().intersects(pseudo_class.state_flag())
2078
+ && unsafe {
2079
+ bindings::Gecko_HasActiveViewTransitionTypes(
2080
+ self.as_node().owner_doc().0,
2081
+ types,
2082
+ )
2083
+ }
2084
+ },
2085
+ NonTSPseudoClass::AnyLink => self.is_link(),
2086
+ NonTSPseudoClass::Link => {
2087
+ self.is_link() && context.visited_handling().matches_unvisited()
2088
+ },
2089
+ NonTSPseudoClass::CustomState(ref state) => self.has_custom_state(&state.0),
2090
+ NonTSPseudoClass::Visited => {
2091
+ self.is_link() && context.visited_handling().matches_visited()
2092
+ },
2093
+ NonTSPseudoClass::MozFirstNode => {
2094
+ if context.needs_selector_flags() {
2095
+ self.apply_selector_flags(ElementSelectorFlags::HAS_EDGE_CHILD_SELECTOR);
2096
+ }
2097
+ let mut elem = self.as_node();
2098
+ while let Some(prev) = elem.prev_sibling() {
2099
+ if prev.contains_non_whitespace_content() {
2100
+ return false;
2101
+ }
2102
+ elem = prev;
2103
+ }
2104
+ true
2105
+ },
2106
+ NonTSPseudoClass::MozLastNode => {
2107
+ if context.needs_selector_flags() {
2108
+ self.apply_selector_flags(ElementSelectorFlags::HAS_EDGE_CHILD_SELECTOR);
2109
+ }
2110
+ let mut elem = self.as_node();
2111
+ while let Some(next) = elem.next_sibling() {
2112
+ if next.contains_non_whitespace_content() {
2113
+ return false;
2114
+ }
2115
+ elem = next;
2116
+ }
2117
+ true
2118
+ },
2119
+ NonTSPseudoClass::MozOnlyWhitespace => {
2120
+ if context.needs_selector_flags() {
2121
+ self.apply_selector_flags(ElementSelectorFlags::HAS_EMPTY_SELECTOR);
2122
+ }
2123
+ if self
2124
+ .as_node()
2125
+ .dom_children()
2126
+ .any(|c| c.contains_non_whitespace_content())
2127
+ {
2128
+ return false;
2129
+ }
2130
+ true
2131
+ },
2132
+ NonTSPseudoClass::MozNativeAnonymous => !self.matches_user_and_content_rules(),
2133
+ NonTSPseudoClass::MozTableBorderNonzero => unsafe {
2134
+ bindings::Gecko_IsTableBorderNonzero(self.0)
2135
+ },
2136
+ NonTSPseudoClass::MozSelectListBox => unsafe {
2137
+ bindings::Gecko_IsSelectListBox(self.0)
2138
+ },
2139
+ NonTSPseudoClass::MozIsHTML => self.as_node().owner_doc().is_html_document(),
2140
+ NonTSPseudoClass::MozLocaleDir(..) | NonTSPseudoClass::MozWindowInactive => {
2141
+ let state_bit = pseudo_class.document_state_flag();
2142
+ if state_bit.is_empty() {
2143
+ debug_assert!(
2144
+ matches!(pseudo_class, NonTSPseudoClass::MozLocaleDir(..)),
2145
+ "Only moz-locale-dir should ever return an empty state"
2146
+ );
2147
+ return false;
2148
+ }
2149
+ if context
2150
+ .extra_data
2151
+ .invalidation_data
2152
+ .document_state
2153
+ .intersects(state_bit)
2154
+ {
2155
+ return !context.in_negation();
2156
+ }
2157
+ self.document_state().contains(state_bit)
2158
+ },
2159
+ NonTSPseudoClass::MozPlaceholder => false,
2160
+ NonTSPseudoClass::Lang(ref lang_arg) => self.match_element_lang(None, lang_arg),
2161
+ NonTSPseudoClass::Heading(ref levels) => levels.matches_state(self.state()),
2162
+ }
2163
+ }
2164
+
2165
+ fn match_pseudo_element(
2166
+ &self,
2167
+ pseudo_selector: &PseudoElement,
2168
+ _context: &mut MatchingContext<Self::Impl>,
2169
+ ) -> bool {
2170
+ // TODO(emilio): I believe we could assert we are a pseudo-element and
2171
+ // match the proper pseudo-element, given how we rulehash the stuff
2172
+ // based on the pseudo.
2173
+ let pseudo = match self.implemented_pseudo_element() {
2174
+ Some(pseudo) => pseudo,
2175
+ None => return false,
2176
+ };
2177
+
2178
+ pseudo.matches(pseudo_selector, self)
2179
+ }
2180
+
2181
+ #[inline]
2182
+ fn is_link(&self) -> bool {
2183
+ self.state().intersects(ElementState::VISITED_OR_UNVISITED)
2184
+ }
2185
+
2186
+ #[inline]
2187
+ fn has_id(&self, id: &AtomIdent, case_sensitivity: CaseSensitivity) -> bool {
2188
+ if !self.has_id() {
2189
+ return false;
2190
+ }
2191
+
2192
+ let element_id = match snapshot_helpers::get_id(self.attrs()) {
2193
+ Some(id) => id,
2194
+ None => return false,
2195
+ };
2196
+
2197
+ case_sensitivity.eq_atom(element_id, id)
2198
+ }
2199
+
2200
+ #[inline]
2201
+ fn is_part(&self, name: &AtomIdent) -> bool {
2202
+ let attr = match self.get_part_attr() {
2203
+ Some(c) => c,
2204
+ None => return false,
2205
+ };
2206
+
2207
+ snapshot_helpers::has_class_or_part(name, CaseSensitivity::CaseSensitive, attr)
2208
+ }
2209
+
2210
+ #[inline]
2211
+ fn imported_part(&self, name: &AtomIdent) -> Option<AtomIdent> {
2212
+ snapshot_helpers::imported_part(self.attrs(), name)
2213
+ }
2214
+
2215
+ #[inline(always)]
2216
+ fn has_class(&self, name: &AtomIdent, case_sensitivity: CaseSensitivity) -> bool {
2217
+ let attr = match self.get_class_attr() {
2218
+ Some(c) => c,
2219
+ None => return false,
2220
+ };
2221
+
2222
+ snapshot_helpers::has_class_or_part(name, case_sensitivity, attr)
2223
+ }
2224
+
2225
+ #[inline]
2226
+ fn has_custom_state(&self, state: &AtomIdent) -> bool {
2227
+ if !self.is_html_element() {
2228
+ return false;
2229
+ }
2230
+ let check_state_ptr: *const nsAtom = state.as_ptr();
2231
+ self.extended_slots().is_some_and(|slot| {
2232
+ slot.mCustomStates.iter().any(|setstate| {
2233
+ let setstate_ptr: *const nsAtom = setstate.mRawPtr;
2234
+ setstate_ptr == check_state_ptr
2235
+ })
2236
+ })
2237
+ }
2238
+
2239
+ #[inline]
2240
+ fn is_html_element_in_html_document(&self) -> bool {
2241
+ self.is_html_element() && self.as_node().owner_doc().is_html_document()
2242
+ }
2243
+
2244
+ #[inline]
2245
+ fn is_html_slot_element(&self) -> bool {
2246
+ self.is_html_element() && self.local_name().as_ptr() == local_name!("slot").as_ptr()
2247
+ }
2248
+
2249
+ #[inline]
2250
+ fn ignores_nth_child_selectors(&self) -> bool {
2251
+ self.is_root_of_native_anonymous_subtree()
2252
+ }
2253
+
2254
+ fn add_element_unique_hashes(&self, filter: &mut BloomFilter) -> bool {
2255
+ each_relevant_element_hash(*self, |hash| filter.insert_hash(hash & BLOOM_HASH_MASK));
2256
+ true
2257
+ }
2258
+ }