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.
- package/LICENSE +21 -0
- package/README.md +355 -2
- package/THIRD_PARTY_NOTICES.md +25 -0
- package/assets/icon.svg +4 -0
- package/dist/api.d.ts +7 -0
- package/dist/api.d.ts.map +1 -0
- package/dist/api.js +46 -0
- package/dist/api.js.map +1 -0
- package/dist/assets.d.ts +7 -0
- package/dist/assets.d.ts.map +1 -0
- package/dist/assets.js +52 -0
- package/dist/assets.js.map +1 -0
- package/dist/browser.d.ts +3 -0
- package/dist/browser.d.ts.map +1 -0
- package/dist/browser.js +3 -0
- package/dist/browser.js.map +1 -0
- package/dist/node.d.ts +3 -0
- package/dist/node.d.ts.map +1 -0
- package/dist/node.js +10 -0
- package/dist/node.js.map +1 -0
- package/dist/options.d.ts +24 -0
- package/dist/options.d.ts.map +1 -0
- package/dist/options.js +135 -0
- package/dist/options.js.map +1 -0
- package/dist/types.d.ts +51 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/examples/bun.ts +8 -0
- package/examples/german-invoice/README.md +70 -0
- package/examples/german-invoice/data.mjs +83 -0
- package/examples/german-invoice/invoice.css +59 -0
- package/examples/german-invoice/template.mjs +49 -0
- package/examples/german-invoice.mjs +20 -0
- package/examples/invoice.html +29 -0
- package/examples/node.mjs +8 -0
- package/examples/pagination.html +40 -0
- package/examples/pagination.mjs +8 -0
- package/licenses/DejaVu.txt +187 -0
- package/licenses/RUST_DEPENDENCIES.txt +11577 -0
- package/package.json +89 -4
- package/src/api.ts +44 -0
- package/src/assets.ts +43 -0
- package/src/browser.ts +6 -0
- package/src/node.ts +12 -0
- package/src/options.ts +101 -0
- package/src/types.ts +49 -0
- package/vendor/README.md +17 -0
- package/vendor/stylo/.cargo-ok +1 -0
- package/vendor/stylo/.cargo_vcs_info.json +6 -0
- package/vendor/stylo/Cargo.lock +1485 -0
- package/vendor/stylo/Cargo.toml +274 -0
- package/vendor/stylo/LICENSE +373 -0
- package/vendor/stylo/README.md +6 -0
- package/vendor/stylo/applicable_declarations.rs +328 -0
- package/vendor/stylo/author_styles.rs +79 -0
- package/vendor/stylo/bezier.rs +176 -0
- package/vendor/stylo/bloom.rs +414 -0
- package/vendor/stylo/build.rs +91 -0
- package/vendor/stylo/build_gecko.rs +393 -0
- package/vendor/stylo/color/color_function.rs +601 -0
- package/vendor/stylo/color/component.rs +207 -0
- package/vendor/stylo/color/convert.rs +935 -0
- package/vendor/stylo/color/gamut/raytrace.rs +265 -0
- package/vendor/stylo/color/gamut.rs +227 -0
- package/vendor/stylo/color/mix.rs +645 -0
- package/vendor/stylo/color/mod.rs +750 -0
- package/vendor/stylo/color/parsing.rs +770 -0
- package/vendor/stylo/color/to_css.rs +297 -0
- package/vendor/stylo/context.rs +716 -0
- package/vendor/stylo/counter_style/mod.rs +754 -0
- package/vendor/stylo/counter_style/predefined.rs +61 -0
- package/vendor/stylo/counter_style/update_predefined.py +35 -0
- package/vendor/stylo/custom_properties.rs +2023 -0
- package/vendor/stylo/custom_properties_map.rs +220 -0
- package/vendor/stylo/data.rs +693 -0
- package/vendor/stylo/device/gecko.rs +486 -0
- package/vendor/stylo/device/mod.rs +304 -0
- package/vendor/stylo/device/servo.rs +507 -0
- package/vendor/stylo/dom.rs +1164 -0
- package/vendor/stylo/dom_apis.rs +937 -0
- package/vendor/stylo/driver.rs +172 -0
- package/vendor/stylo/error_reporting.rs +484 -0
- package/vendor/stylo/font_face.rs +558 -0
- package/vendor/stylo/font_metrics.rs +124 -0
- package/vendor/stylo/gecko/anon_boxes.toml +113 -0
- package/vendor/stylo/gecko/arc_types.rs +211 -0
- package/vendor/stylo/gecko/conversions.rs +59 -0
- package/vendor/stylo/gecko/data.rs +222 -0
- package/vendor/stylo/gecko/media_features.rs +971 -0
- package/vendor/stylo/gecko/mod.rs +20 -0
- package/vendor/stylo/gecko/non_ts_pseudo_class_list.rs +119 -0
- package/vendor/stylo/gecko/pseudo_element.rs +640 -0
- package/vendor/stylo/gecko/pseudo_element_definition.mako.rs +298 -0
- package/vendor/stylo/gecko/pseudo_elements.py +137 -0
- package/vendor/stylo/gecko/pseudo_elements.toml +197 -0
- package/vendor/stylo/gecko/regen_pseudo_elements.py +33 -0
- package/vendor/stylo/gecko/restyle_damage.rs +127 -0
- package/vendor/stylo/gecko/selector_parser.rs +627 -0
- package/vendor/stylo/gecko/snapshot.rs +202 -0
- package/vendor/stylo/gecko/snapshot_helpers.rs +334 -0
- package/vendor/stylo/gecko/traversal.rs +52 -0
- package/vendor/stylo/gecko/wrapper.rs +2258 -0
- package/vendor/stylo/gecko_bindings/mod.rs +34 -0
- package/vendor/stylo/gecko_bindings/sugar/mod.rs +12 -0
- package/vendor/stylo/gecko_bindings/sugar/ns_com_ptr.rs +15 -0
- package/vendor/stylo/gecko_bindings/sugar/ns_compatibility.rs +19 -0
- package/vendor/stylo/gecko_bindings/sugar/ns_style_auto_array.rs +111 -0
- package/vendor/stylo/gecko_bindings/sugar/origin_flags.rs +31 -0
- package/vendor/stylo/gecko_bindings/sugar/ownership.rs +70 -0
- package/vendor/stylo/gecko_bindings/sugar/refptr.rs +299 -0
- package/vendor/stylo/gecko_string_cache/mod.rs +543 -0
- package/vendor/stylo/gecko_string_cache/namespace.rs +106 -0
- package/vendor/stylo/global_style_data.rs +224 -0
- package/vendor/stylo/invalidation/element/document_state.rs +156 -0
- package/vendor/stylo/invalidation/element/element_wrapper.rs +432 -0
- package/vendor/stylo/invalidation/element/invalidation_map.rs +1631 -0
- package/vendor/stylo/invalidation/element/invalidator.rs +1470 -0
- package/vendor/stylo/invalidation/element/mod.rs +13 -0
- package/vendor/stylo/invalidation/element/relative_selector.rs +1399 -0
- package/vendor/stylo/invalidation/element/restyle_hints.rs +226 -0
- package/vendor/stylo/invalidation/element/state_and_attributes.rs +756 -0
- package/vendor/stylo/invalidation/media_queries.rs +144 -0
- package/vendor/stylo/invalidation/mod.rs +10 -0
- package/vendor/stylo/invalidation/stylesheets.rs +745 -0
- package/vendor/stylo/invalidation/viewport_units.rs +71 -0
- package/vendor/stylo/lib.rs +336 -0
- package/vendor/stylo/logical_geometry.rs +1684 -0
- package/vendor/stylo/macros.rs +70 -0
- package/vendor/stylo/matching.rs +1226 -0
- package/vendor/stylo/media_queries/media_list.rs +168 -0
- package/vendor/stylo/media_queries/media_query.rs +190 -0
- package/vendor/stylo/media_queries/mod.rs +13 -0
- package/vendor/stylo/parallel.rs +205 -0
- package/vendor/stylo/parser.rs +276 -0
- package/vendor/stylo/piecewise_linear.rs +282 -0
- package/vendor/stylo/prefs.rs +33 -0
- package/vendor/stylo/properties/build.py +119 -0
- package/vendor/stylo/properties/cascade.rs +2704 -0
- package/vendor/stylo/properties/computed_value_flags.rs +206 -0
- package/vendor/stylo/properties/counted_unknown_properties.py +104 -0
- package/vendor/stylo/properties/counter_style_descriptors.toml +45 -0
- package/vendor/stylo/properties/data.py +1375 -0
- package/vendor/stylo/properties/declaration_block.rs +1788 -0
- package/vendor/stylo/properties/font_face_descriptors.toml +50 -0
- package/vendor/stylo/properties/gecko.mako.rs +1555 -0
- package/vendor/stylo/properties/helpers/animated_properties.mako.rs +800 -0
- package/vendor/stylo/properties/helpers.mako.rs +812 -0
- package/vendor/stylo/properties/longhands.toml +4305 -0
- package/vendor/stylo/properties/mod.rs +1857 -0
- package/vendor/stylo/properties/properties.html.mako +31 -0
- package/vendor/stylo/properties/properties.mako.rs +3103 -0
- package/vendor/stylo/properties/property_descriptors.toml +18 -0
- package/vendor/stylo/properties/shorthands.rs +4241 -0
- package/vendor/stylo/properties/shorthands.toml +575 -0
- package/vendor/stylo/properties/vendored_python/mako-1.3.10-py3-none-any.whl +0 -0
- package/vendor/stylo/properties/vendored_python/markupsafe/LICENSE.txt +28 -0
- package/vendor/stylo/properties/vendored_python/markupsafe/__init__.py +384 -0
- package/vendor/stylo/properties/vendored_python/toml-0.10.2-py2.py3-none-any.whl +0 -0
- package/vendor/stylo/properties/view_transition_descriptors.toml +11 -0
- package/vendor/stylo/properties_and_values/mod.rs +12 -0
- package/vendor/stylo/properties_and_values/registry.rs +65 -0
- package/vendor/stylo/properties_and_values/rule.rs +331 -0
- package/vendor/stylo/properties_and_values/syntax/ascii.rs +60 -0
- package/vendor/stylo/properties_and_values/syntax/data_type.rs +146 -0
- package/vendor/stylo/properties_and_values/syntax/mod.rs +437 -0
- package/vendor/stylo/properties_and_values/value.rs +758 -0
- package/vendor/stylo/queries/condition.rs +996 -0
- package/vendor/stylo/queries/feature.rs +199 -0
- package/vendor/stylo/queries/feature_expression.rs +1170 -0
- package/vendor/stylo/queries/mod.rs +19 -0
- package/vendor/stylo/queries/values.rs +46 -0
- package/vendor/stylo/rule_cache.rs +267 -0
- package/vendor/stylo/rule_collector.rs +554 -0
- package/vendor/stylo/rule_tree/core.rs +787 -0
- package/vendor/stylo/rule_tree/level.rs +396 -0
- package/vendor/stylo/rule_tree/map.rs +201 -0
- package/vendor/stylo/rule_tree/mod.rs +427 -0
- package/vendor/stylo/rule_tree/source.rs +80 -0
- package/vendor/stylo/rule_tree/unsafe_box.rs +78 -0
- package/vendor/stylo/scoped_tls.rs +80 -0
- package/vendor/stylo/selector_map.rs +1050 -0
- package/vendor/stylo/selector_parser.rs +305 -0
- package/vendor/stylo/servo/animation.rs +1922 -0
- package/vendor/stylo/servo/attr.rs +714 -0
- package/vendor/stylo/servo/encoding_support.rs +81 -0
- package/vendor/stylo/servo/media_features.rs +254 -0
- package/vendor/stylo/servo/mod.rs +16 -0
- package/vendor/stylo/servo/restyle_damage.rs +215 -0
- package/vendor/stylo/servo/selector_parser.rs +1036 -0
- package/vendor/stylo/servo/shadow_parts.rs +207 -0
- package/vendor/stylo/shared_lock.rs +271 -0
- package/vendor/stylo/sharing/checks.rs +281 -0
- package/vendor/stylo/sharing/mod.rs +1000 -0
- package/vendor/stylo/simple_buckets_map.rs +52 -0
- package/vendor/stylo/str.rs +168 -0
- package/vendor/stylo/style_adjuster.rs +1086 -0
- package/vendor/stylo/style_resolver.rs +658 -0
- package/vendor/stylo/stylesheet_set.rs +658 -0
- package/vendor/stylo/stylesheets/appearance_base_rule.rs +51 -0
- package/vendor/stylo/stylesheets/container_rule.rs +769 -0
- package/vendor/stylo/stylesheets/counter_style_rule.rs +7 -0
- package/vendor/stylo/stylesheets/document_rule.rs +272 -0
- package/vendor/stylo/stylesheets/font_face_rule.rs +7 -0
- package/vendor/stylo/stylesheets/font_feature_values_rule.rs +481 -0
- package/vendor/stylo/stylesheets/font_palette_values_rule.rs +304 -0
- package/vendor/stylo/stylesheets/import_rule.rs +259 -0
- package/vendor/stylo/stylesheets/keyframes_rule.rs +733 -0
- package/vendor/stylo/stylesheets/layer_rule.rs +221 -0
- package/vendor/stylo/stylesheets/loader.rs +29 -0
- package/vendor/stylo/stylesheets/margin_rule.rs +190 -0
- package/vendor/stylo/stylesheets/media_rule.rs +191 -0
- package/vendor/stylo/stylesheets/mod.rs +918 -0
- package/vendor/stylo/stylesheets/namespace_rule.rs +43 -0
- package/vendor/stylo/stylesheets/nested_declarations_rule.rs +51 -0
- package/vendor/stylo/stylesheets/origin.rs +249 -0
- package/vendor/stylo/stylesheets/page_rule.rs +354 -0
- package/vendor/stylo/stylesheets/position_try_rule.rs +68 -0
- package/vendor/stylo/stylesheets/property_rule.rs +5 -0
- package/vendor/stylo/stylesheets/rule_list.rs +167 -0
- package/vendor/stylo/stylesheets/rule_parser.rs +1189 -0
- package/vendor/stylo/stylesheets/rules_iterator.rs +397 -0
- package/vendor/stylo/stylesheets/scope_rule.rs +511 -0
- package/vendor/stylo/stylesheets/starting_style_rule.rs +54 -0
- package/vendor/stylo/stylesheets/style_rule.rs +80 -0
- package/vendor/stylo/stylesheets/stylesheet.rs +570 -0
- package/vendor/stylo/stylesheets/supports_rule.rs +486 -0
- package/vendor/stylo/stylesheets/view_transition_rule.rs +81 -0
- package/vendor/stylo/stylist.rs +5076 -0
- package/vendor/stylo/thread_state.rs +87 -0
- package/vendor/stylo/traversal.rs +765 -0
- package/vendor/stylo/traversal_flags.rs +68 -0
- package/vendor/stylo/typed_om/mod.rs +981 -0
- package/vendor/stylo/typed_om/numeric.rs +128 -0
- package/vendor/stylo/typed_om/numeric_declaration.rs +93 -0
- package/vendor/stylo/typed_om/numeric_type.rs +640 -0
- package/vendor/stylo/typed_om/sum_value.rs +426 -0
- package/vendor/stylo/url/gecko.rs +367 -0
- package/vendor/stylo/url/mod.rs +71 -0
- package/vendor/stylo/url/servo.rs +239 -0
- package/vendor/stylo/use_counters/mod.rs +137 -0
- package/vendor/stylo/values/animated/color.rs +103 -0
- package/vendor/stylo/values/animated/effects.rs +26 -0
- package/vendor/stylo/values/animated/font.rs +37 -0
- package/vendor/stylo/values/animated/grid.rs +161 -0
- package/vendor/stylo/values/animated/lists.rs +141 -0
- package/vendor/stylo/values/animated/mod.rs +550 -0
- package/vendor/stylo/values/animated/svg.rs +46 -0
- package/vendor/stylo/values/animated/text.rs +58 -0
- package/vendor/stylo/values/animated/transform.rs +1592 -0
- package/vendor/stylo/values/computed/align.rs +90 -0
- package/vendor/stylo/values/computed/angle.rs +130 -0
- package/vendor/stylo/values/computed/animation.rs +124 -0
- package/vendor/stylo/values/computed/background.rs +13 -0
- package/vendor/stylo/values/computed/basic_shape.rs +267 -0
- package/vendor/stylo/values/computed/border.rs +163 -0
- package/vendor/stylo/values/computed/box.rs +267 -0
- package/vendor/stylo/values/computed/calc.rs +334 -0
- package/vendor/stylo/values/computed/color.rs +161 -0
- package/vendor/stylo/values/computed/column.rs +11 -0
- package/vendor/stylo/values/computed/corner_shape.rs +155 -0
- package/vendor/stylo/values/computed/counters.rs +26 -0
- package/vendor/stylo/values/computed/easing.rs +109 -0
- package/vendor/stylo/values/computed/effects.rs +30 -0
- package/vendor/stylo/values/computed/flex.rs +19 -0
- package/vendor/stylo/values/computed/font.rs +1517 -0
- package/vendor/stylo/values/computed/image.rs +273 -0
- package/vendor/stylo/values/computed/length.rs +576 -0
- package/vendor/stylo/values/computed/length_percentage.rs +1055 -0
- package/vendor/stylo/values/computed/list.rs +16 -0
- package/vendor/stylo/values/computed/mod.rs +1141 -0
- package/vendor/stylo/values/computed/motion.rs +73 -0
- package/vendor/stylo/values/computed/outline.rs +7 -0
- package/vendor/stylo/values/computed/page.rs +77 -0
- package/vendor/stylo/values/computed/param.rs +9 -0
- package/vendor/stylo/values/computed/percentage.rs +143 -0
- package/vendor/stylo/values/computed/position.rs +273 -0
- package/vendor/stylo/values/computed/ratio.rs +88 -0
- package/vendor/stylo/values/computed/rect.rs +19 -0
- package/vendor/stylo/values/computed/resolution.rs +76 -0
- package/vendor/stylo/values/computed/svg.rs +66 -0
- package/vendor/stylo/values/computed/table.rs +7 -0
- package/vendor/stylo/values/computed/text.rs +199 -0
- package/vendor/stylo/values/computed/time.rs +83 -0
- package/vendor/stylo/values/computed/transform.rs +559 -0
- package/vendor/stylo/values/computed/tree_counting.rs +30 -0
- package/vendor/stylo/values/computed/ui.rs +23 -0
- package/vendor/stylo/values/computed/url.rs +12 -0
- package/vendor/stylo/values/distance.rs +139 -0
- package/vendor/stylo/values/generics/animation.rs +363 -0
- package/vendor/stylo/values/generics/background.rs +65 -0
- package/vendor/stylo/values/generics/basic_shape.rs +1389 -0
- package/vendor/stylo/values/generics/border.rs +303 -0
- package/vendor/stylo/values/generics/box.rs +552 -0
- package/vendor/stylo/values/generics/calc.rs +2986 -0
- package/vendor/stylo/values/generics/color.rs +318 -0
- package/vendor/stylo/values/generics/column.rs +44 -0
- package/vendor/stylo/values/generics/counters.rs +320 -0
- package/vendor/stylo/values/generics/easing.rs +132 -0
- package/vendor/stylo/values/generics/effects.rs +131 -0
- package/vendor/stylo/values/generics/flex.rs +34 -0
- package/vendor/stylo/values/generics/font.rs +376 -0
- package/vendor/stylo/values/generics/grid.rs +962 -0
- package/vendor/stylo/values/generics/image.rs +653 -0
- package/vendor/stylo/values/generics/length.rs +656 -0
- package/vendor/stylo/values/generics/mod.rs +303 -0
- package/vendor/stylo/values/generics/motion.rs +274 -0
- package/vendor/stylo/values/generics/page.rs +167 -0
- package/vendor/stylo/values/generics/position.rs +669 -0
- package/vendor/stylo/values/generics/ratio.rs +88 -0
- package/vendor/stylo/values/generics/rect.rs +147 -0
- package/vendor/stylo/values/generics/size.rs +102 -0
- package/vendor/stylo/values/generics/svg.rs +226 -0
- package/vendor/stylo/values/generics/text.rs +268 -0
- package/vendor/stylo/values/generics/transform.rs +1157 -0
- package/vendor/stylo/values/generics/ui.rs +147 -0
- package/vendor/stylo/values/generics/url.rs +51 -0
- package/vendor/stylo/values/mod.rs +820 -0
- package/vendor/stylo/values/resolved/animation.rs +33 -0
- package/vendor/stylo/values/resolved/color.rs +53 -0
- package/vendor/stylo/values/resolved/counters.rs +45 -0
- package/vendor/stylo/values/resolved/mod.rs +316 -0
- package/vendor/stylo/values/specified/align.rs +711 -0
- package/vendor/stylo/values/specified/angle.rs +407 -0
- package/vendor/stylo/values/specified/animation.rs +921 -0
- package/vendor/stylo/values/specified/background.rs +270 -0
- package/vendor/stylo/values/specified/basic_shape.rs +986 -0
- package/vendor/stylo/values/specified/border.rs +430 -0
- package/vendor/stylo/values/specified/box.rs +2231 -0
- package/vendor/stylo/values/specified/calc.rs +1657 -0
- package/vendor/stylo/values/specified/color.rs +1210 -0
- package/vendor/stylo/values/specified/column.rs +11 -0
- package/vendor/stylo/values/specified/corner_shape.rs +152 -0
- package/vendor/stylo/values/specified/counters.rs +242 -0
- package/vendor/stylo/values/specified/easing.rs +225 -0
- package/vendor/stylo/values/specified/effects.rs +421 -0
- package/vendor/stylo/values/specified/flex.rs +42 -0
- package/vendor/stylo/values/specified/font.rs +2103 -0
- package/vendor/stylo/values/specified/frequency.rs +39 -0
- package/vendor/stylo/values/specified/grid.rs +407 -0
- package/vendor/stylo/values/specified/image.rs +1385 -0
- package/vendor/stylo/values/specified/intersection_observer.rs +80 -0
- package/vendor/stylo/values/specified/length.rs +2024 -0
- package/vendor/stylo/values/specified/list.rs +190 -0
- package/vendor/stylo/values/specified/mod.rs +531 -0
- package/vendor/stylo/values/specified/motion.rs +316 -0
- package/vendor/stylo/values/specified/number.rs +603 -0
- package/vendor/stylo/values/specified/outline.rs +69 -0
- package/vendor/stylo/values/specified/page.rs +94 -0
- package/vendor/stylo/values/specified/param.rs +121 -0
- package/vendor/stylo/values/specified/percentage.rs +364 -0
- package/vendor/stylo/values/specified/position.rs +2247 -0
- package/vendor/stylo/values/specified/ratio.rs +29 -0
- package/vendor/stylo/values/specified/rect.rs +28 -0
- package/vendor/stylo/values/specified/resolution.rs +237 -0
- package/vendor/stylo/values/specified/source_size_list.rs +135 -0
- package/vendor/stylo/values/specified/svg.rs +427 -0
- package/vendor/stylo/values/specified/svg_path.rs +1115 -0
- package/vendor/stylo/values/specified/table.rs +38 -0
- package/vendor/stylo/values/specified/text.rs +1561 -0
- package/vendor/stylo/values/specified/time.rs +313 -0
- package/vendor/stylo/values/specified/transform.rs +599 -0
- package/vendor/stylo/values/specified/tree_counting.rs +32 -0
- package/vendor/stylo/values/specified/ui.rs +344 -0
- package/vendor/stylo/values/specified/url.rs +12 -0
- package/vendor/stylo/values/tagged_numeric.rs +253 -0
- package/wasm/blitz_pdf.d.ts +67 -0
- package/wasm/blitz_pdf.js +699 -0
- package/wasm/blitz_pdf_bg.wasm +0 -0
- package/wasm/blitz_pdf_bg.wasm.d.ts +20 -0
|
@@ -0,0 +1,172 @@
|
|
|
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
|
+
//! Implements traversal over the DOM tree. The traversal starts in sequential
|
|
6
|
+
//! mode, and optionally parallelizes as it discovers work.
|
|
7
|
+
|
|
8
|
+
#![deny(missing_docs)]
|
|
9
|
+
|
|
10
|
+
use crate::context::{PerThreadTraversalStatistics, StyleContext};
|
|
11
|
+
use crate::context::{ThreadLocalStyleContext, TraversalStatistics};
|
|
12
|
+
use crate::dom::{SendNode, TElement, TNode};
|
|
13
|
+
use crate::parallel;
|
|
14
|
+
use crate::scoped_tls::ScopedTLS;
|
|
15
|
+
use crate::traversal::{DomTraversal, PreTraverseToken};
|
|
16
|
+
use std::collections::VecDeque;
|
|
17
|
+
use std::time::Instant;
|
|
18
|
+
|
|
19
|
+
#[cfg(feature = "servo")]
|
|
20
|
+
fn should_report_statistics() -> bool {
|
|
21
|
+
false
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
#[cfg(feature = "gecko")]
|
|
25
|
+
fn should_report_statistics() -> bool {
|
|
26
|
+
unsafe { !crate::gecko_bindings::structs::ServoTraversalStatistics_sSingleton.is_null() }
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
#[cfg(feature = "servo")]
|
|
30
|
+
fn report_statistics(_stats: &PerThreadTraversalStatistics) {
|
|
31
|
+
unreachable!("Servo never report stats");
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
#[cfg(feature = "gecko")]
|
|
35
|
+
fn report_statistics(stats: &PerThreadTraversalStatistics) {
|
|
36
|
+
// This should only be called in the main thread, or it may be racy
|
|
37
|
+
// to update the statistics in a global variable.
|
|
38
|
+
unsafe {
|
|
39
|
+
debug_assert!(crate::gecko_bindings::bindings::Gecko_IsMainThread());
|
|
40
|
+
let gecko_stats = crate::gecko_bindings::structs::ServoTraversalStatistics_sSingleton;
|
|
41
|
+
(*gecko_stats).mElementsTraversed += stats.elements_traversed;
|
|
42
|
+
(*gecko_stats).mElementsStyled += stats.elements_styled;
|
|
43
|
+
(*gecko_stats).mElementsMatched += stats.elements_matched;
|
|
44
|
+
(*gecko_stats).mStylesShared += stats.styles_shared;
|
|
45
|
+
(*gecko_stats).mStylesReused += stats.styles_reused;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
fn with_pool_in_place_scope<'scope>(
|
|
50
|
+
work_unit_max: usize,
|
|
51
|
+
pool: Option<&rayon::ThreadPool>,
|
|
52
|
+
closure: impl FnOnce(Option<&rayon::ScopeFifo<'scope>>) + Send + 'scope,
|
|
53
|
+
) {
|
|
54
|
+
if work_unit_max == 0 || pool.is_none() {
|
|
55
|
+
closure(None);
|
|
56
|
+
} else {
|
|
57
|
+
let pool = pool.unwrap();
|
|
58
|
+
pool.in_place_scope_fifo(|scope| {
|
|
59
|
+
#[cfg(feature = "gecko")]
|
|
60
|
+
debug_assert_eq!(
|
|
61
|
+
pool.current_thread_index(),
|
|
62
|
+
Some(0),
|
|
63
|
+
"Main thread should be the first thread"
|
|
64
|
+
);
|
|
65
|
+
if cfg!(feature = "gecko") || pool.current_thread_index().is_some() {
|
|
66
|
+
closure(Some(scope));
|
|
67
|
+
} else {
|
|
68
|
+
scope.spawn_fifo(|scope| closure(Some(scope)));
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/// See documentation of the pref for performance characteristics.
|
|
75
|
+
fn work_unit_max() -> usize {
|
|
76
|
+
crate::pref!("layout.css.stylo-work-unit-size") as usize
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/// Do a DOM traversal for top-down and (optionally) bottom-up processing, generic over `D`.
|
|
80
|
+
///
|
|
81
|
+
/// We use an adaptive traversal strategy. We start out with simple sequential processing, until we
|
|
82
|
+
/// arrive at a wide enough level in the DOM that the parallel traversal would parallelize it.
|
|
83
|
+
/// If a thread pool is provided, we then transfer control over to the parallel traversal.
|
|
84
|
+
///
|
|
85
|
+
/// Returns true if the traversal was parallel, and also returns the statistics object containing
|
|
86
|
+
/// information on nodes traversed (on nightly only). Not all of its fields will be initialized
|
|
87
|
+
/// since we don't call finish().
|
|
88
|
+
pub fn traverse_dom<E, D>(
|
|
89
|
+
traversal: &D,
|
|
90
|
+
token: PreTraverseToken<E>,
|
|
91
|
+
pool: Option<&rayon::ThreadPool>,
|
|
92
|
+
) -> E
|
|
93
|
+
where
|
|
94
|
+
E: TElement,
|
|
95
|
+
D: DomTraversal<E>,
|
|
96
|
+
{
|
|
97
|
+
let root = token
|
|
98
|
+
.traversal_root()
|
|
99
|
+
.expect("Should've ensured we needed to traverse");
|
|
100
|
+
|
|
101
|
+
let report_stats = should_report_statistics();
|
|
102
|
+
let dump_stats = traversal.shared_context().options.dump_style_statistics;
|
|
103
|
+
let start_time = if dump_stats {
|
|
104
|
+
Some(Instant::now())
|
|
105
|
+
} else {
|
|
106
|
+
None
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
// Declare the main-thread context, as well as the worker-thread contexts,
|
|
110
|
+
// which we may or may not instantiate. It's important to declare the worker-
|
|
111
|
+
// thread contexts first, so that they get dropped second. This matters because:
|
|
112
|
+
// * ThreadLocalContexts borrow AtomicRefCells in TLS.
|
|
113
|
+
// * Dropping a ThreadLocalContext can run SequentialTasks.
|
|
114
|
+
// * Sequential tasks may call into functions like
|
|
115
|
+
// Servo_StyleSet_GetBaseComputedValuesForElement, which instantiate a
|
|
116
|
+
// ThreadLocalStyleContext on the main thread. If the main thread
|
|
117
|
+
// ThreadLocalStyleContext has not released its TLS borrow by that point,
|
|
118
|
+
// we'll panic on double-borrow.
|
|
119
|
+
let mut scoped_tls = ScopedTLS::<ThreadLocalStyleContext<E>>::new(pool);
|
|
120
|
+
// Process the nodes breadth-first. This helps keep similar traversal characteristics for the
|
|
121
|
+
// style sharing cache.
|
|
122
|
+
let work_unit_max = work_unit_max();
|
|
123
|
+
|
|
124
|
+
let send_root = unsafe { SendNode::new(root.as_node()) };
|
|
125
|
+
with_pool_in_place_scope(work_unit_max, pool, |maybe_scope| {
|
|
126
|
+
let mut tlc = scoped_tls.ensure(parallel::create_thread_local_context);
|
|
127
|
+
tlc.current_dom_depth = send_root.depth();
|
|
128
|
+
|
|
129
|
+
let mut context = StyleContext {
|
|
130
|
+
shared: traversal.shared_context(),
|
|
131
|
+
thread_local: &mut tlc,
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
let mut discovered = VecDeque::with_capacity(work_unit_max * 2);
|
|
135
|
+
let opaque_root = send_root.opaque();
|
|
136
|
+
discovered.push_back(send_root);
|
|
137
|
+
parallel::style_trees(
|
|
138
|
+
&mut context,
|
|
139
|
+
discovered,
|
|
140
|
+
opaque_root,
|
|
141
|
+
work_unit_max,
|
|
142
|
+
maybe_scope,
|
|
143
|
+
traversal,
|
|
144
|
+
&scoped_tls,
|
|
145
|
+
);
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
// Collect statistics from thread-locals if requested.
|
|
149
|
+
if dump_stats || report_stats {
|
|
150
|
+
let mut aggregate = PerThreadTraversalStatistics::default();
|
|
151
|
+
for slot in scoped_tls.slots() {
|
|
152
|
+
if let Some(cx) = slot.get_mut() {
|
|
153
|
+
aggregate += cx.statistics.clone();
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
if report_stats {
|
|
158
|
+
report_statistics(&aggregate);
|
|
159
|
+
}
|
|
160
|
+
// dump statistics to stdout if requested
|
|
161
|
+
if dump_stats {
|
|
162
|
+
let parallel = pool.is_some();
|
|
163
|
+
let stats =
|
|
164
|
+
TraversalStatistics::new(aggregate, traversal, parallel, start_time.unwrap());
|
|
165
|
+
if stats.is_large {
|
|
166
|
+
println!("{}", stats);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
root
|
|
172
|
+
}
|
|
@@ -0,0 +1,484 @@
|
|
|
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
|
+
//! Types used to report parsing errors.
|
|
6
|
+
|
|
7
|
+
#![deny(missing_docs)]
|
|
8
|
+
|
|
9
|
+
use crate::selector_parser::SelectorImpl;
|
|
10
|
+
use crate::stylesheets::UrlExtraData;
|
|
11
|
+
use cssparser::{BasicParseErrorKind, ParseErrorKind, SourceLocation};
|
|
12
|
+
use selectors::SelectorList;
|
|
13
|
+
use selectors::parser::{Combinator, Component, RelativeSelector, Selector};
|
|
14
|
+
use selectors::visitor::{SelectorListKind, SelectorVisitor};
|
|
15
|
+
use std::fmt;
|
|
16
|
+
use style_traits::ParseError;
|
|
17
|
+
|
|
18
|
+
/// Errors that can be encountered while parsing CSS.
|
|
19
|
+
#[derive(Debug)]
|
|
20
|
+
pub enum ContextualParseError<'a> {
|
|
21
|
+
/// A property declaration was not recognized.
|
|
22
|
+
UnsupportedPropertyDeclaration(&'a str, ParseError, &'a [SelectorList<SelectorImpl>]),
|
|
23
|
+
/// A property descriptor was not recognized.
|
|
24
|
+
UnsupportedPropertyDescriptor(&'a str, ParseError),
|
|
25
|
+
/// A font face descriptor was not recognized.
|
|
26
|
+
UnsupportedFontFaceDescriptor(&'a str, ParseError),
|
|
27
|
+
/// A font feature values descriptor was not recognized.
|
|
28
|
+
UnsupportedFontFeatureValuesDescriptor(&'a str, ParseError),
|
|
29
|
+
/// A font palette values descriptor was not recognized.
|
|
30
|
+
UnsupportedFontPaletteValuesDescriptor(&'a str, ParseError),
|
|
31
|
+
/// A keyframe rule was not valid.
|
|
32
|
+
InvalidKeyframeRule(&'a str, ParseError),
|
|
33
|
+
/// A font feature values rule was not valid.
|
|
34
|
+
InvalidFontFeatureValuesRule(&'a str, ParseError),
|
|
35
|
+
/// A rule was invalid for some reason.
|
|
36
|
+
InvalidRule(&'a str, ParseError),
|
|
37
|
+
/// A rule was not recognized.
|
|
38
|
+
UnsupportedRule(&'a str, ParseError),
|
|
39
|
+
/// A viewport descriptor declaration was not recognized.
|
|
40
|
+
UnsupportedViewportDescriptorDeclaration(&'a str, ParseError),
|
|
41
|
+
/// A counter style descriptor declaration was not recognized.
|
|
42
|
+
UnsupportedCounterStyleDescriptorDeclaration(&'a str, ParseError),
|
|
43
|
+
/// A counter style rule had no symbols.
|
|
44
|
+
InvalidCounterStyleWithoutSymbols(String),
|
|
45
|
+
/// A counter style rule had less than two symbols.
|
|
46
|
+
InvalidCounterStyleNotEnoughSymbols(String),
|
|
47
|
+
/// A counter style rule did not have additive-symbols.
|
|
48
|
+
InvalidCounterStyleWithoutAdditiveSymbols,
|
|
49
|
+
/// A counter style rule had extends with symbols.
|
|
50
|
+
InvalidCounterStyleExtendsWithSymbols,
|
|
51
|
+
/// A counter style rule had extends with additive-symbols.
|
|
52
|
+
InvalidCounterStyleExtendsWithAdditiveSymbols,
|
|
53
|
+
/// A media rule was invalid for some reason.
|
|
54
|
+
InvalidMediaRule(&'a str, ParseError),
|
|
55
|
+
/// A value was not recognized.
|
|
56
|
+
UnsupportedValue(&'a str, ParseError),
|
|
57
|
+
/// A never-matching `:host` selector was found.
|
|
58
|
+
NeverMatchingHostSelector(String),
|
|
59
|
+
/// A view-transition declaration was not recognized.
|
|
60
|
+
UnsupportedViewTransitionDescriptor(&'a str, ParseError),
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
impl<'a> fmt::Display for ContextualParseError<'a> {
|
|
64
|
+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
65
|
+
fn parse_error_to_str(err: &ParseError, f: &mut fmt::Formatter) -> fmt::Result {
|
|
66
|
+
match err.kind {
|
|
67
|
+
ParseErrorKind::Basic(BasicParseErrorKind::UnexpectedToken) => {
|
|
68
|
+
write!(f, "found unexpected token")
|
|
69
|
+
},
|
|
70
|
+
ParseErrorKind::Basic(BasicParseErrorKind::TooManyNestedBlocks) => {
|
|
71
|
+
write!(f, "too many nested blocks")
|
|
72
|
+
},
|
|
73
|
+
ParseErrorKind::Basic(BasicParseErrorKind::EndOfInput) => {
|
|
74
|
+
write!(f, "unexpected end of input")
|
|
75
|
+
},
|
|
76
|
+
ParseErrorKind::Basic(BasicParseErrorKind::AtRuleInvalid) => {
|
|
77
|
+
write!(f, "@ rule invalid")
|
|
78
|
+
},
|
|
79
|
+
ParseErrorKind::Basic(BasicParseErrorKind::AtRuleBodyInvalid) => {
|
|
80
|
+
write!(f, "@ rule invalid")
|
|
81
|
+
},
|
|
82
|
+
ParseErrorKind::Basic(BasicParseErrorKind::QualifiedRuleInvalid) => {
|
|
83
|
+
write!(f, "qualified rule invalid")
|
|
84
|
+
},
|
|
85
|
+
ParseErrorKind::Custom(ref err) => write!(f, "{:?}", err),
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
match *self {
|
|
90
|
+
ContextualParseError::UnsupportedPropertyDeclaration(decl, ref err, _selectors) => {
|
|
91
|
+
write!(f, "Unsupported property declaration: '{}', ", decl)?;
|
|
92
|
+
parse_error_to_str(err, f)
|
|
93
|
+
},
|
|
94
|
+
ContextualParseError::UnsupportedPropertyDescriptor(decl, ref err) => {
|
|
95
|
+
write!(
|
|
96
|
+
f,
|
|
97
|
+
"Unsupported @property descriptor declaration: '{}', ",
|
|
98
|
+
decl
|
|
99
|
+
)?;
|
|
100
|
+
parse_error_to_str(err, f)
|
|
101
|
+
},
|
|
102
|
+
ContextualParseError::UnsupportedFontFaceDescriptor(decl, ref err) => {
|
|
103
|
+
write!(
|
|
104
|
+
f,
|
|
105
|
+
"Unsupported @font-face descriptor declaration: '{}', ",
|
|
106
|
+
decl
|
|
107
|
+
)?;
|
|
108
|
+
parse_error_to_str(err, f)
|
|
109
|
+
},
|
|
110
|
+
ContextualParseError::UnsupportedFontFeatureValuesDescriptor(decl, ref err) => {
|
|
111
|
+
write!(
|
|
112
|
+
f,
|
|
113
|
+
"Unsupported @font-feature-values descriptor declaration: '{}', ",
|
|
114
|
+
decl
|
|
115
|
+
)?;
|
|
116
|
+
parse_error_to_str(err, f)
|
|
117
|
+
},
|
|
118
|
+
ContextualParseError::UnsupportedFontPaletteValuesDescriptor(decl, ref err) => {
|
|
119
|
+
write!(
|
|
120
|
+
f,
|
|
121
|
+
"Unsupported @font-palette-values descriptor declaration: '{}', ",
|
|
122
|
+
decl
|
|
123
|
+
)?;
|
|
124
|
+
parse_error_to_str(err, f)
|
|
125
|
+
},
|
|
126
|
+
ContextualParseError::InvalidKeyframeRule(rule, ref err) => {
|
|
127
|
+
write!(f, "Invalid keyframe rule: '{}', ", rule)?;
|
|
128
|
+
parse_error_to_str(err, f)
|
|
129
|
+
},
|
|
130
|
+
ContextualParseError::InvalidFontFeatureValuesRule(rule, ref err) => {
|
|
131
|
+
write!(f, "Invalid font feature value rule: '{}', ", rule)?;
|
|
132
|
+
parse_error_to_str(err, f)
|
|
133
|
+
},
|
|
134
|
+
ContextualParseError::InvalidRule(rule, ref err) => {
|
|
135
|
+
write!(f, "Invalid rule: '{}', ", rule)?;
|
|
136
|
+
parse_error_to_str(err, f)
|
|
137
|
+
},
|
|
138
|
+
ContextualParseError::UnsupportedRule(rule, ref err) => {
|
|
139
|
+
write!(f, "Unsupported rule: '{}', ", rule)?;
|
|
140
|
+
parse_error_to_str(err, f)
|
|
141
|
+
},
|
|
142
|
+
ContextualParseError::UnsupportedViewportDescriptorDeclaration(decl, ref err) => {
|
|
143
|
+
write!(
|
|
144
|
+
f,
|
|
145
|
+
"Unsupported @viewport descriptor declaration: '{}', ",
|
|
146
|
+
decl
|
|
147
|
+
)?;
|
|
148
|
+
parse_error_to_str(err, f)
|
|
149
|
+
},
|
|
150
|
+
ContextualParseError::UnsupportedCounterStyleDescriptorDeclaration(decl, ref err) => {
|
|
151
|
+
write!(
|
|
152
|
+
f,
|
|
153
|
+
"Unsupported @counter-style descriptor declaration: '{}', ",
|
|
154
|
+
decl
|
|
155
|
+
)?;
|
|
156
|
+
parse_error_to_str(err, f)
|
|
157
|
+
},
|
|
158
|
+
ContextualParseError::InvalidCounterStyleWithoutSymbols(ref system) => write!(
|
|
159
|
+
f,
|
|
160
|
+
"Invalid @counter-style rule: 'system: {}' without 'symbols'",
|
|
161
|
+
system
|
|
162
|
+
),
|
|
163
|
+
ContextualParseError::InvalidCounterStyleNotEnoughSymbols(ref system) => write!(
|
|
164
|
+
f,
|
|
165
|
+
"Invalid @counter-style rule: 'system: {}' less than two 'symbols'",
|
|
166
|
+
system
|
|
167
|
+
),
|
|
168
|
+
ContextualParseError::InvalidCounterStyleWithoutAdditiveSymbols => write!(
|
|
169
|
+
f,
|
|
170
|
+
"Invalid @counter-style rule: 'system: additive' without 'additive-symbols'"
|
|
171
|
+
),
|
|
172
|
+
ContextualParseError::InvalidCounterStyleExtendsWithSymbols => write!(
|
|
173
|
+
f,
|
|
174
|
+
"Invalid @counter-style rule: 'system: extends …' with 'symbols'"
|
|
175
|
+
),
|
|
176
|
+
ContextualParseError::InvalidCounterStyleExtendsWithAdditiveSymbols => write!(
|
|
177
|
+
f,
|
|
178
|
+
"Invalid @counter-style rule: 'system: extends …' with 'additive-symbols'"
|
|
179
|
+
),
|
|
180
|
+
ContextualParseError::InvalidMediaRule(media_rule, ref err) => {
|
|
181
|
+
write!(f, "Invalid media rule: {}, ", media_rule)?;
|
|
182
|
+
parse_error_to_str(err, f)
|
|
183
|
+
},
|
|
184
|
+
ContextualParseError::UnsupportedValue(_value, ref err) => parse_error_to_str(err, f),
|
|
185
|
+
ContextualParseError::NeverMatchingHostSelector(ref selector) => {
|
|
186
|
+
write!(f, ":host selector is not featureless: {}", selector)
|
|
187
|
+
},
|
|
188
|
+
ContextualParseError::UnsupportedViewTransitionDescriptor(decl, ref err) => {
|
|
189
|
+
write!(
|
|
190
|
+
f,
|
|
191
|
+
"Unsupported @view-transition descriptor declaration: '{}', ",
|
|
192
|
+
decl
|
|
193
|
+
)?;
|
|
194
|
+
parse_error_to_str(err, f)
|
|
195
|
+
},
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/// A generic trait for an error reporter.
|
|
201
|
+
pub trait ParseErrorReporter {
|
|
202
|
+
/// Called when the style engine detects an error.
|
|
203
|
+
///
|
|
204
|
+
/// Returns the current input being parsed, an approximate source location
|
|
205
|
+
/// for the error, and a message.
|
|
206
|
+
fn report_error(
|
|
207
|
+
&self,
|
|
208
|
+
url: &UrlExtraData,
|
|
209
|
+
location: SourceLocation,
|
|
210
|
+
error: ContextualParseError,
|
|
211
|
+
);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/// An error reporter that uses [the `log` crate](https://github.com/rust-lang-nursery/log)
|
|
215
|
+
/// at `info` level.
|
|
216
|
+
///
|
|
217
|
+
/// This logging is silent by default, and can be enabled with a `RUST_LOG=style=info`
|
|
218
|
+
/// environment variable.
|
|
219
|
+
/// (See [`env_logger`](https://rust-lang-nursery.github.io/log/env_logger/).)
|
|
220
|
+
#[cfg(feature = "servo")]
|
|
221
|
+
pub struct RustLogReporter;
|
|
222
|
+
|
|
223
|
+
#[cfg(feature = "servo")]
|
|
224
|
+
impl ParseErrorReporter for RustLogReporter {
|
|
225
|
+
fn report_error(
|
|
226
|
+
&self,
|
|
227
|
+
url: &UrlExtraData,
|
|
228
|
+
location: SourceLocation,
|
|
229
|
+
error: ContextualParseError,
|
|
230
|
+
) {
|
|
231
|
+
if log_enabled!(log::Level::Info) {
|
|
232
|
+
info!(
|
|
233
|
+
"Url:\t{}\n{}:{} {}",
|
|
234
|
+
url.as_str(),
|
|
235
|
+
location.line,
|
|
236
|
+
location.column,
|
|
237
|
+
error
|
|
238
|
+
)
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/// Any warning a selector may generate.
|
|
244
|
+
/// TODO(dshin): Bug 1860634 - Merge with never matching host selector warning, which is part of the rule parser.
|
|
245
|
+
#[repr(u8)]
|
|
246
|
+
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
|
|
247
|
+
pub enum SelectorWarningKind {
|
|
248
|
+
/// Relative Selector with not enough constraint, either outside or inside the selector. e.g. `*:has(.a)`, `.a:has(*)`.
|
|
249
|
+
/// May cause expensive invalidations for every element inserted and/or removed.
|
|
250
|
+
UnconstraintedRelativeSelector,
|
|
251
|
+
/// `:scope` can have 3 meanings, but in all cases, the relationship is defined strictly by an ancestor-descendant
|
|
252
|
+
/// relationship. This means that any presence of sibling selectors to its right would make it never match.
|
|
253
|
+
SiblingCombinatorAfterScopeSelector,
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
impl SelectorWarningKind {
|
|
257
|
+
/// Get all warnings for this selector.
|
|
258
|
+
pub fn from_selector(selector: &Selector<SelectorImpl>) -> Vec<Self> {
|
|
259
|
+
let mut result = vec![];
|
|
260
|
+
if UnconstrainedRelativeSelectorVisitor::has_warning(selector, 0, false) {
|
|
261
|
+
result.push(SelectorWarningKind::UnconstraintedRelativeSelector);
|
|
262
|
+
}
|
|
263
|
+
if SiblingCombinatorAfterScopeSelectorVisitor::has_warning(selector) {
|
|
264
|
+
result.push(SelectorWarningKind::SiblingCombinatorAfterScopeSelector);
|
|
265
|
+
}
|
|
266
|
+
result
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/// Per-compound state for finding unconstrained relative selectors.
|
|
271
|
+
struct PerCompoundState {
|
|
272
|
+
/// Is there a relative selector in this compound?
|
|
273
|
+
relative_selector_found: bool,
|
|
274
|
+
/// Is this compound constrained in any way?
|
|
275
|
+
constrained: bool,
|
|
276
|
+
/// Nested below, or inside relative selector?
|
|
277
|
+
in_relative_selector: bool,
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
impl PerCompoundState {
|
|
281
|
+
fn new(in_relative_selector: bool) -> Self {
|
|
282
|
+
Self {
|
|
283
|
+
relative_selector_found: false,
|
|
284
|
+
constrained: false,
|
|
285
|
+
in_relative_selector,
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/// Visitor to check if there's any unconstrained relative selector.
|
|
291
|
+
struct UnconstrainedRelativeSelectorVisitor {
|
|
292
|
+
compound_state: PerCompoundState,
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
impl UnconstrainedRelativeSelectorVisitor {
|
|
296
|
+
fn new(in_relative_selector: bool) -> Self {
|
|
297
|
+
Self {
|
|
298
|
+
compound_state: PerCompoundState::new(in_relative_selector),
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
fn has_warning(
|
|
303
|
+
selector: &Selector<SelectorImpl>,
|
|
304
|
+
offset: usize,
|
|
305
|
+
in_relative_selector: bool,
|
|
306
|
+
) -> bool {
|
|
307
|
+
let relative_selector = matches!(
|
|
308
|
+
selector.iter_raw_parse_order_from(0).next().unwrap(),
|
|
309
|
+
Component::RelativeSelectorAnchor
|
|
310
|
+
);
|
|
311
|
+
debug_assert!(
|
|
312
|
+
!relative_selector || offset == 0,
|
|
313
|
+
"Checking relative selector from non-rightmost?"
|
|
314
|
+
);
|
|
315
|
+
let mut visitor = Self::new(in_relative_selector);
|
|
316
|
+
let mut iter = if relative_selector {
|
|
317
|
+
selector.iter_skip_relative_selector_anchor()
|
|
318
|
+
} else {
|
|
319
|
+
selector.iter_from(offset)
|
|
320
|
+
};
|
|
321
|
+
loop {
|
|
322
|
+
visitor.compound_state = PerCompoundState::new(in_relative_selector);
|
|
323
|
+
|
|
324
|
+
for s in &mut iter {
|
|
325
|
+
s.visit(&mut visitor);
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
if (visitor.compound_state.relative_selector_found
|
|
329
|
+
|| visitor.compound_state.in_relative_selector)
|
|
330
|
+
&& !visitor.compound_state.constrained
|
|
331
|
+
{
|
|
332
|
+
return true;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
if iter.next_sequence().is_none() {
|
|
336
|
+
break;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
false
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
impl SelectorVisitor for UnconstrainedRelativeSelectorVisitor {
|
|
344
|
+
type Impl = SelectorImpl;
|
|
345
|
+
|
|
346
|
+
fn visit_simple_selector(&mut self, c: &Component<Self::Impl>) -> bool {
|
|
347
|
+
match c {
|
|
348
|
+
// Deferred to visit_selector_list
|
|
349
|
+
Component::Is(..)
|
|
350
|
+
| Component::Where(..)
|
|
351
|
+
| Component::Negation(..)
|
|
352
|
+
| Component::Has(..) => (),
|
|
353
|
+
Component::ExplicitUniversalType => (),
|
|
354
|
+
_ => self.compound_state.constrained |= true,
|
|
355
|
+
};
|
|
356
|
+
true
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
fn visit_selector_list(
|
|
360
|
+
&mut self,
|
|
361
|
+
_list_kind: SelectorListKind,
|
|
362
|
+
list: &[Selector<Self::Impl>],
|
|
363
|
+
) -> bool {
|
|
364
|
+
let mut all_constrained = true;
|
|
365
|
+
for s in list {
|
|
366
|
+
let mut offset = 0;
|
|
367
|
+
// First, check the rightmost compound for constraint at this level.
|
|
368
|
+
if !self.compound_state.in_relative_selector {
|
|
369
|
+
let mut nested = Self::new(false);
|
|
370
|
+
let mut iter = s.iter();
|
|
371
|
+
loop {
|
|
372
|
+
for c in &mut iter {
|
|
373
|
+
c.visit(&mut nested);
|
|
374
|
+
offset += 1;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
let c = iter.next_sequence();
|
|
378
|
+
offset += 1;
|
|
379
|
+
if c.is_none_or(|c| !c.is_pseudo_element()) {
|
|
380
|
+
break;
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
// Every single selector in the list must be constrained.
|
|
384
|
+
all_constrained &= nested.compound_state.constrained;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
if offset >= s.len() {
|
|
388
|
+
continue;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
// Then, recurse in to check at the deeper level.
|
|
392
|
+
if Self::has_warning(s, offset, self.compound_state.in_relative_selector) {
|
|
393
|
+
self.compound_state.constrained = false;
|
|
394
|
+
if !self.compound_state.in_relative_selector {
|
|
395
|
+
self.compound_state.relative_selector_found = true;
|
|
396
|
+
}
|
|
397
|
+
return false;
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
self.compound_state.constrained |= all_constrained;
|
|
401
|
+
true
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
fn visit_relative_selector_list(&mut self, list: &[RelativeSelector<Self::Impl>]) -> bool {
|
|
405
|
+
debug_assert!(
|
|
406
|
+
!self.compound_state.in_relative_selector,
|
|
407
|
+
"Nested relative selector"
|
|
408
|
+
);
|
|
409
|
+
self.compound_state.relative_selector_found = true;
|
|
410
|
+
|
|
411
|
+
for rs in list {
|
|
412
|
+
// If the inside is unconstrained, we are unconstrained no matter what.
|
|
413
|
+
if Self::has_warning(&rs.selector, 0, true) {
|
|
414
|
+
self.compound_state.constrained = false;
|
|
415
|
+
return false;
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
true
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
struct SiblingCombinatorAfterScopeSelectorVisitor {
|
|
423
|
+
right_combinator_is_sibling: bool,
|
|
424
|
+
found: bool,
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
impl SiblingCombinatorAfterScopeSelectorVisitor {
|
|
428
|
+
fn new(right_combinator_is_sibling: bool) -> Self {
|
|
429
|
+
Self {
|
|
430
|
+
right_combinator_is_sibling,
|
|
431
|
+
found: false,
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
fn has_warning(selector: &Selector<SelectorImpl>) -> bool {
|
|
435
|
+
if !selector.has_scope_selector() {
|
|
436
|
+
return false;
|
|
437
|
+
}
|
|
438
|
+
let visitor = SiblingCombinatorAfterScopeSelectorVisitor::new(false);
|
|
439
|
+
visitor.find_never_matching_scope_selector(selector)
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
fn find_never_matching_scope_selector(mut self, selector: &Selector<SelectorImpl>) -> bool {
|
|
443
|
+
selector.visit(&mut self);
|
|
444
|
+
self.found
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
impl SelectorVisitor for SiblingCombinatorAfterScopeSelectorVisitor {
|
|
449
|
+
type Impl = SelectorImpl;
|
|
450
|
+
|
|
451
|
+
fn visit_simple_selector(&mut self, c: &Component<Self::Impl>) -> bool {
|
|
452
|
+
if !matches!(c, Component::Scope | Component::ImplicitScope) {
|
|
453
|
+
return true;
|
|
454
|
+
}
|
|
455
|
+
// e.g. `:scope ~ .a` will never match.
|
|
456
|
+
if self.right_combinator_is_sibling {
|
|
457
|
+
self.found = true;
|
|
458
|
+
}
|
|
459
|
+
true
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
fn visit_selector_list(
|
|
463
|
+
&mut self,
|
|
464
|
+
_list_kind: SelectorListKind,
|
|
465
|
+
list: &[Selector<Self::Impl>],
|
|
466
|
+
) -> bool {
|
|
467
|
+
for s in list {
|
|
468
|
+
let list_visitor = Self::new(self.right_combinator_is_sibling);
|
|
469
|
+
self.found |= list_visitor.find_never_matching_scope_selector(s);
|
|
470
|
+
}
|
|
471
|
+
true
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
fn visit_complex_selector(&mut self, combinator_to_right: Option<Combinator>) -> bool {
|
|
475
|
+
if let Some(c) = combinator_to_right {
|
|
476
|
+
// Subject compounds' state is determined by the outer visitor. e.g: When there's `:is(.a .b) ~ .c`,
|
|
477
|
+
// the inner visitor is assumed to be constructed with right_combinator_is_sibling == true.
|
|
478
|
+
self.right_combinator_is_sibling = c.is_sibling();
|
|
479
|
+
}
|
|
480
|
+
true
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
// It's harder to discern if use of :scope <sibling-combinator> is invalid - at least for now, defer.
|
|
484
|
+
}
|