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,427 @@
|
|
|
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
|
+
#![deny(unsafe_code)]
|
|
6
|
+
|
|
7
|
+
//! The rule tree.
|
|
8
|
+
|
|
9
|
+
use crate::applicable_declarations::{ApplicableDeclarationList, CascadePriority};
|
|
10
|
+
use crate::properties::{LonghandIdSet, PropertyDeclarationBlock};
|
|
11
|
+
use crate::shared_lock::{Locked, StylesheetGuards};
|
|
12
|
+
use crate::stylesheets::layer_rule::LayerOrder;
|
|
13
|
+
use servo_arc::ArcBorrow;
|
|
14
|
+
use smallvec::SmallVec;
|
|
15
|
+
use std::io::{self, Write};
|
|
16
|
+
|
|
17
|
+
mod core;
|
|
18
|
+
pub mod level;
|
|
19
|
+
mod map;
|
|
20
|
+
mod source;
|
|
21
|
+
mod unsafe_box;
|
|
22
|
+
|
|
23
|
+
pub use self::core::{RuleTree, StrongRuleNode};
|
|
24
|
+
pub use self::level::{CascadeLevel, CascadeOrigin, ShadowCascadeOrder};
|
|
25
|
+
pub use self::source::StyleSource;
|
|
26
|
+
|
|
27
|
+
bitflags! {
|
|
28
|
+
/// Flags that are part of the cascade priority, and that we use to track
|
|
29
|
+
/// information about where the rule came from.
|
|
30
|
+
#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
|
|
31
|
+
pub struct RuleCascadeFlags: u8 {
|
|
32
|
+
/// Whether the rule is inside a @starting-style block.
|
|
33
|
+
const STARTING_STYLE = 1 << 0;
|
|
34
|
+
/// Whether the rule is inside an @appearance-base block.
|
|
35
|
+
const APPEARANCE_BASE = 1 << 1;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
malloc_size_of::malloc_size_of_is_0!(RuleCascadeFlags);
|
|
40
|
+
|
|
41
|
+
impl RuleTree {
|
|
42
|
+
fn dump<W: Write>(&self, guards: &StylesheetGuards, writer: &mut W) {
|
|
43
|
+
let _ = writeln!(writer, " + RuleTree");
|
|
44
|
+
self.root().dump(guards, writer, 0);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/// Dump the rule tree to stdout.
|
|
48
|
+
pub fn dump_stdout(&self, guards: &StylesheetGuards) {
|
|
49
|
+
let mut stdout = io::stdout();
|
|
50
|
+
self.dump(guards, &mut stdout);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/// Inserts the given rules, that must be in proper order by specifity, and
|
|
54
|
+
/// returns the corresponding rule node representing the last inserted one.
|
|
55
|
+
///
|
|
56
|
+
/// !important rules are detected and inserted into the appropriate position
|
|
57
|
+
/// in the rule tree. This allows selector matching to ignore importance,
|
|
58
|
+
/// while still maintaining the appropriate cascade order in the rule tree.
|
|
59
|
+
pub fn insert_ordered_rules_with_important<'a, I>(
|
|
60
|
+
&self,
|
|
61
|
+
iter: I,
|
|
62
|
+
guards: &StylesheetGuards,
|
|
63
|
+
) -> StrongRuleNode
|
|
64
|
+
where
|
|
65
|
+
I: Iterator<Item = (StyleSource, CascadePriority)>,
|
|
66
|
+
{
|
|
67
|
+
let mut current = self.root().clone();
|
|
68
|
+
|
|
69
|
+
let mut found_important = false;
|
|
70
|
+
|
|
71
|
+
let mut important_author = SmallVec::<[(StyleSource, CascadePriority); 4]>::new();
|
|
72
|
+
let mut important_user = SmallVec::<[(StyleSource, CascadePriority); 4]>::new();
|
|
73
|
+
let mut important_ua = SmallVec::<[(StyleSource, CascadePriority); 4]>::new();
|
|
74
|
+
let mut transition = None;
|
|
75
|
+
|
|
76
|
+
for (source, priority) in iter {
|
|
77
|
+
let level = priority.cascade_level();
|
|
78
|
+
debug_assert!(!level.is_important(), "Important levels handled internally");
|
|
79
|
+
|
|
80
|
+
let any_important = {
|
|
81
|
+
let pdb = source.read(level.guard(guards));
|
|
82
|
+
pdb.any_important()
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
if any_important {
|
|
86
|
+
found_important = true;
|
|
87
|
+
match level.origin() {
|
|
88
|
+
CascadeOrigin::Author => {
|
|
89
|
+
important_author.push((source.clone(), priority.important()))
|
|
90
|
+
},
|
|
91
|
+
CascadeOrigin::UA => important_ua.push((source.clone(), priority.important())),
|
|
92
|
+
CascadeOrigin::User => {
|
|
93
|
+
important_user.push((source.clone(), priority.important()))
|
|
94
|
+
},
|
|
95
|
+
_ => {},
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// We don't optimize out empty rules, even though we could.
|
|
100
|
+
//
|
|
101
|
+
// Inspector relies on every rule being inserted in the normal level
|
|
102
|
+
// at least once, in order to return the rules with the correct
|
|
103
|
+
// specificity order.
|
|
104
|
+
//
|
|
105
|
+
// TODO(emilio): If we want to apply these optimizations without
|
|
106
|
+
// breaking inspector's expectations, we'd need to run
|
|
107
|
+
// selector-matching again at the inspector's request. That may or
|
|
108
|
+
// may not be a better trade-off.
|
|
109
|
+
if level.origin() == CascadeOrigin::Transitions && found_important {
|
|
110
|
+
// There can be at most one transition, and it will come at
|
|
111
|
+
// the end of the iterator. Stash it and apply it after
|
|
112
|
+
// !important rules.
|
|
113
|
+
debug_assert!(transition.is_none());
|
|
114
|
+
transition = Some(source);
|
|
115
|
+
} else {
|
|
116
|
+
current = current.ensure_child(self.root(), source, priority);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Early-return in the common case of no !important declarations.
|
|
121
|
+
if !found_important {
|
|
122
|
+
return current;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Insert important declarations, in order of increasing importance,
|
|
126
|
+
// followed by any transition rule.
|
|
127
|
+
//
|
|
128
|
+
// Important rules are sorted differently from unimportant ones by
|
|
129
|
+
// shadow order and cascade order.
|
|
130
|
+
if !important_author.is_empty()
|
|
131
|
+
&& important_author.first().unwrap().1 != important_author.last().unwrap().1
|
|
132
|
+
{
|
|
133
|
+
// We only need to sort if the important rules come from
|
|
134
|
+
// different trees, but we need this sort to be stable.
|
|
135
|
+
//
|
|
136
|
+
// FIXME(emilio): This could maybe be smarter, probably by chunking
|
|
137
|
+
// the important rules while inserting, and iterating the outer
|
|
138
|
+
// chunks in reverse order.
|
|
139
|
+
//
|
|
140
|
+
// That is, if we have rules with levels like: -1 -1 -1 0 0 0 1 1 1,
|
|
141
|
+
// we're really only sorting the chunks, while keeping elements
|
|
142
|
+
// inside the same chunk already sorted. Seems like we could try to
|
|
143
|
+
// keep a SmallVec-of-SmallVecs with the chunks and just iterate the
|
|
144
|
+
// outer in reverse.
|
|
145
|
+
important_author.sort_by_key(|&(_, priority)| priority);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
for (source, priority) in important_author.drain(..) {
|
|
149
|
+
current = current.ensure_child(self.root(), source, priority);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
for (source, priority) in important_user.drain(..) {
|
|
153
|
+
current = current.ensure_child(self.root(), source, priority);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
for (source, priority) in important_ua.drain(..) {
|
|
157
|
+
current = current.ensure_child(self.root(), source, priority);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
if let Some(source) = transition {
|
|
161
|
+
current = current.ensure_child(
|
|
162
|
+
self.root(),
|
|
163
|
+
source,
|
|
164
|
+
CascadePriority::new(
|
|
165
|
+
CascadeLevel::new(CascadeOrigin::Transitions),
|
|
166
|
+
LayerOrder::root(),
|
|
167
|
+
RuleCascadeFlags::empty(),
|
|
168
|
+
),
|
|
169
|
+
);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
current
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/// Given a list of applicable declarations, insert the rules and return the
|
|
176
|
+
/// corresponding rule node.
|
|
177
|
+
pub fn compute_rule_node(
|
|
178
|
+
&self,
|
|
179
|
+
applicable_declarations: &mut ApplicableDeclarationList,
|
|
180
|
+
guards: &StylesheetGuards,
|
|
181
|
+
) -> StrongRuleNode {
|
|
182
|
+
self.insert_ordered_rules_with_important(
|
|
183
|
+
applicable_declarations.drain(..).map(|d| d.for_rule_tree()),
|
|
184
|
+
guards,
|
|
185
|
+
)
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/// Insert the given rules, that must be in proper order by specifity, and
|
|
189
|
+
/// return the corresponding rule node representing the last inserted one.
|
|
190
|
+
pub fn insert_ordered_rules<'a, I>(&self, iter: I) -> StrongRuleNode
|
|
191
|
+
where
|
|
192
|
+
I: Iterator<Item = (StyleSource, CascadePriority)>,
|
|
193
|
+
{
|
|
194
|
+
self.insert_ordered_rules_from(self.root().clone(), iter)
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
fn insert_ordered_rules_from<'a, I>(&self, from: StrongRuleNode, iter: I) -> StrongRuleNode
|
|
198
|
+
where
|
|
199
|
+
I: Iterator<Item = (StyleSource, CascadePriority)>,
|
|
200
|
+
{
|
|
201
|
+
let mut current = from;
|
|
202
|
+
for (source, priority) in iter {
|
|
203
|
+
current = current.ensure_child(self.root(), source, priority);
|
|
204
|
+
}
|
|
205
|
+
current
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/// Replaces a rule in a given level (if present) for another rule.
|
|
209
|
+
///
|
|
210
|
+
/// Returns the resulting node that represents the new path, or None if
|
|
211
|
+
/// the old path is still valid.
|
|
212
|
+
pub fn update_rule_at_level(
|
|
213
|
+
&self,
|
|
214
|
+
level: CascadeLevel,
|
|
215
|
+
layer_order: LayerOrder,
|
|
216
|
+
pdb: Option<ArcBorrow<Locked<PropertyDeclarationBlock>>>,
|
|
217
|
+
path: &StrongRuleNode,
|
|
218
|
+
guards: &StylesheetGuards,
|
|
219
|
+
important_rules_changed: &mut bool,
|
|
220
|
+
) -> Option<StrongRuleNode> {
|
|
221
|
+
// TODO(emilio): Being smarter with lifetimes we could avoid a bit of
|
|
222
|
+
// the refcount churn.
|
|
223
|
+
let mut current = path.clone();
|
|
224
|
+
*important_rules_changed = false;
|
|
225
|
+
|
|
226
|
+
// First walk up until the first less-or-equally specific rule.
|
|
227
|
+
let mut children = SmallVec::<[_; 10]>::new();
|
|
228
|
+
while current.cascade_priority().cascade_level() > level {
|
|
229
|
+
children.push((
|
|
230
|
+
current.style_source().unwrap().clone(),
|
|
231
|
+
current.cascade_priority(),
|
|
232
|
+
));
|
|
233
|
+
current = current.parent().unwrap().clone();
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
let cascade_priority = CascadePriority::new(level, layer_order, RuleCascadeFlags::empty());
|
|
237
|
+
|
|
238
|
+
// Then remove the one at the level we want to replace, if any.
|
|
239
|
+
//
|
|
240
|
+
// NOTE: Here we assume that only one rule can be at the level + priority we're replacing,
|
|
241
|
+
// which holds because we only use this for HTML style attribute, animations and transition
|
|
242
|
+
// rules.
|
|
243
|
+
//
|
|
244
|
+
// This is certainly true for HTML style attribute rules, animations, transitions, and
|
|
245
|
+
// SMIL.
|
|
246
|
+
if current.cascade_priority() == cascade_priority {
|
|
247
|
+
*important_rules_changed |= level.is_important();
|
|
248
|
+
|
|
249
|
+
let current_decls = current.style_source().unwrap().get();
|
|
250
|
+
|
|
251
|
+
// If the only rule at the level we're replacing is exactly the
|
|
252
|
+
// same as `pdb`, we're done, and `path` is still valid.
|
|
253
|
+
if let Some(ref pdb) = pdb {
|
|
254
|
+
// If the only rule at the level we're replacing is exactly the
|
|
255
|
+
// same as `pdb`, we're done, and `path` is still valid.
|
|
256
|
+
//
|
|
257
|
+
// TODO(emilio): Another potential optimization is the one where
|
|
258
|
+
// we can just replace the rule at that level for `pdb`, and
|
|
259
|
+
// then we don't need to re-create the children, and `path` is
|
|
260
|
+
// also equally valid. This is less likely, and would require an
|
|
261
|
+
// in-place mutation of the source, which is, at best, fiddly,
|
|
262
|
+
// so let's skip it for now.
|
|
263
|
+
let is_here_already = ArcBorrow::ptr_eq(pdb, ¤t_decls.borrow_arc());
|
|
264
|
+
if is_here_already {
|
|
265
|
+
debug!("Picking the fast path in rule replacement");
|
|
266
|
+
return None;
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
current = current.parent().unwrap().clone();
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// Insert the rule if it's relevant at this level in the cascade.
|
|
274
|
+
//
|
|
275
|
+
// These optimizations are likely to be important, because the levels where replacements
|
|
276
|
+
// apply (style and animations) tend to trigger pretty bad styling cases already.
|
|
277
|
+
if let Some(pdb) = pdb {
|
|
278
|
+
if level.is_important() {
|
|
279
|
+
if pdb.read_with(level.guard(guards)).any_important() {
|
|
280
|
+
current = current.ensure_child(
|
|
281
|
+
self.root(),
|
|
282
|
+
StyleSource::from_declarations(pdb.clone_arc()),
|
|
283
|
+
cascade_priority,
|
|
284
|
+
);
|
|
285
|
+
*important_rules_changed = true;
|
|
286
|
+
}
|
|
287
|
+
} else if pdb.read_with(level.guard(guards)).any_normal() {
|
|
288
|
+
current = current.ensure_child(
|
|
289
|
+
self.root(),
|
|
290
|
+
StyleSource::from_declarations(pdb.clone_arc()),
|
|
291
|
+
cascade_priority,
|
|
292
|
+
);
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
// Now the rule is in the relevant place, push the children as
|
|
297
|
+
// necessary.
|
|
298
|
+
let rule = self.insert_ordered_rules_from(current, children.drain(..).rev());
|
|
299
|
+
Some(rule)
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
/// Returns whether this rule node has any @starting-style rule.
|
|
303
|
+
pub fn has_starting_style(path: &StrongRuleNode) -> bool {
|
|
304
|
+
path.self_and_ancestors().any(|node| {
|
|
305
|
+
node.cascade_priority()
|
|
306
|
+
.flags()
|
|
307
|
+
.intersects(RuleCascadeFlags::STARTING_STYLE)
|
|
308
|
+
})
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
/// Returns new rule nodes without Transitions level rule.
|
|
312
|
+
pub fn remove_transition_rule_if_applicable(path: &StrongRuleNode) -> StrongRuleNode {
|
|
313
|
+
// Return a clone if there is no transition level.
|
|
314
|
+
if path.cascade_level().origin() != CascadeOrigin::Transitions {
|
|
315
|
+
return path.clone();
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
path.parent().unwrap().clone()
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
/// Returns new rule node without rules from declarative animations.
|
|
322
|
+
pub fn remove_animation_rules(&self, path: &StrongRuleNode) -> StrongRuleNode {
|
|
323
|
+
// Return a clone if there are no animation rules.
|
|
324
|
+
if !path.has_animation_or_transition_rules() {
|
|
325
|
+
return path.clone();
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
let iter = path.self_and_ancestors().take_while(|node| {
|
|
329
|
+
node.cascade_level() >= CascadeLevel::new(CascadeOrigin::SMILOverride)
|
|
330
|
+
});
|
|
331
|
+
let mut last = path;
|
|
332
|
+
let mut children = SmallVec::<[_; 10]>::new();
|
|
333
|
+
for node in iter {
|
|
334
|
+
if !node.cascade_level().is_animation() {
|
|
335
|
+
children.push((
|
|
336
|
+
node.style_source().unwrap().clone(),
|
|
337
|
+
node.cascade_priority(),
|
|
338
|
+
));
|
|
339
|
+
}
|
|
340
|
+
last = node;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
let rule = self
|
|
344
|
+
.insert_ordered_rules_from(last.parent().unwrap().clone(), children.drain(..).rev());
|
|
345
|
+
rule
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
impl StrongRuleNode {
|
|
350
|
+
/// Get an iterator for this rule node and its ancestors.
|
|
351
|
+
pub fn self_and_ancestors(&self) -> SelfAndAncestors<'_> {
|
|
352
|
+
SelfAndAncestors {
|
|
353
|
+
current: Some(self),
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
/// Returns true if there is either animation or transition level rule.
|
|
358
|
+
pub fn has_animation_or_transition_rules(&self) -> bool {
|
|
359
|
+
self.self_and_ancestors()
|
|
360
|
+
.take_while(|node| {
|
|
361
|
+
node.cascade_level() >= CascadeLevel::new(CascadeOrigin::SMILOverride)
|
|
362
|
+
})
|
|
363
|
+
.any(|node| node.cascade_level().is_animation())
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
/// Get a set of properties whose CascadeLevel are higher than Animations
|
|
367
|
+
/// but not equal to Transitions.
|
|
368
|
+
///
|
|
369
|
+
/// If there are any custom properties, we set the boolean value of the
|
|
370
|
+
/// returned tuple to true.
|
|
371
|
+
pub fn get_properties_overriding_animations(
|
|
372
|
+
&self,
|
|
373
|
+
guards: &StylesheetGuards,
|
|
374
|
+
) -> (LonghandIdSet, bool) {
|
|
375
|
+
use crate::properties::PropertyDeclarationId;
|
|
376
|
+
|
|
377
|
+
// We want to iterate over cascade levels that override the animations
|
|
378
|
+
// level, i.e. !important levels and the transitions level.
|
|
379
|
+
//
|
|
380
|
+
// However, we actually want to skip the transitions level because
|
|
381
|
+
// although it is higher in the cascade than animations, when both
|
|
382
|
+
// transitions and animations are present for a given element and
|
|
383
|
+
// property, transitions are suppressed so that they don't actually
|
|
384
|
+
// override animations.
|
|
385
|
+
let iter = self
|
|
386
|
+
.self_and_ancestors()
|
|
387
|
+
.skip_while(|node| node.cascade_level().origin() == CascadeOrigin::Transitions)
|
|
388
|
+
.take_while(|node| node.cascade_level() > CascadeLevel::new(CascadeOrigin::Animations));
|
|
389
|
+
let mut result = (LonghandIdSet::new(), false);
|
|
390
|
+
for node in iter {
|
|
391
|
+
let style = node.style_source().unwrap();
|
|
392
|
+
for (decl, important) in style
|
|
393
|
+
.read(node.cascade_level().guard(guards))
|
|
394
|
+
.declaration_importance_iter()
|
|
395
|
+
{
|
|
396
|
+
// Although we are only iterating over cascade levels that
|
|
397
|
+
// override animations, in a given property declaration block we
|
|
398
|
+
// can have a mixture of !important and non-!important
|
|
399
|
+
// declarations but only the !important declarations actually
|
|
400
|
+
// override animations.
|
|
401
|
+
if important.important() {
|
|
402
|
+
match decl.id() {
|
|
403
|
+
PropertyDeclarationId::Longhand(id) => result.0.insert(id),
|
|
404
|
+
PropertyDeclarationId::Custom(_) => result.1 = true,
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
result
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
/// An iterator over a rule node and its ancestors.
|
|
414
|
+
#[derive(Clone)]
|
|
415
|
+
pub struct SelfAndAncestors<'a> {
|
|
416
|
+
current: Option<&'a StrongRuleNode>,
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
impl<'a> Iterator for SelfAndAncestors<'a> {
|
|
420
|
+
type Item = &'a StrongRuleNode;
|
|
421
|
+
|
|
422
|
+
fn next(&mut self) -> Option<Self::Item> {
|
|
423
|
+
self.current.inspect(|node| {
|
|
424
|
+
self.current = node.parent();
|
|
425
|
+
})
|
|
426
|
+
}
|
|
427
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
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
|
+
#![deny(unsafe_code)]
|
|
6
|
+
|
|
7
|
+
use crate::properties::PropertyDeclarationBlock;
|
|
8
|
+
use crate::shared_lock::{Locked, SharedRwLockReadGuard};
|
|
9
|
+
use servo_arc::Arc;
|
|
10
|
+
use std::io::Write;
|
|
11
|
+
use std::ptr;
|
|
12
|
+
|
|
13
|
+
/// A style source for the rule node. It is a declaration block that may come from either a style
|
|
14
|
+
/// rule or a standalone block like animations / transitions / smil / preshints / style attr...
|
|
15
|
+
///
|
|
16
|
+
/// Keeping the style rule around would provide more debugability, but also causes more
|
|
17
|
+
/// pointer-chasing in the common code-path, which is undesired. If needed, we could keep it around
|
|
18
|
+
/// in debug builds or something along those lines.
|
|
19
|
+
#[derive(Clone, Debug)]
|
|
20
|
+
pub struct StyleSource(Arc<Locked<PropertyDeclarationBlock>>);
|
|
21
|
+
|
|
22
|
+
impl PartialEq for StyleSource {
|
|
23
|
+
fn eq(&self, other: &Self) -> bool {
|
|
24
|
+
Arc::ptr_eq(&self.0, &other.0)
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
impl StyleSource {
|
|
29
|
+
#[inline]
|
|
30
|
+
pub(super) fn key(&self) -> ptr::NonNull<()> {
|
|
31
|
+
self.0.raw_ptr()
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/// Creates a StyleSource from a PropertyDeclarationBlock.
|
|
35
|
+
#[inline]
|
|
36
|
+
pub fn from_declarations(decls: Arc<Locked<PropertyDeclarationBlock>>) -> Self {
|
|
37
|
+
Self(decls)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
pub(super) fn dump<W: Write>(&self, guard: &SharedRwLockReadGuard, writer: &mut W) {
|
|
41
|
+
let _ = write!(writer, " -> {:?}", self.read(guard).declarations());
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/// Read the style source guard, and obtain thus read access to the
|
|
45
|
+
/// underlying property declaration block.
|
|
46
|
+
#[inline]
|
|
47
|
+
pub fn read<'a>(&'a self, guard: &'a SharedRwLockReadGuard) -> &'a PropertyDeclarationBlock {
|
|
48
|
+
self.0.read_with(guard)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/// Returns the declaration block if applicable, otherwise None.
|
|
52
|
+
#[inline]
|
|
53
|
+
pub fn get(&self) -> &Arc<Locked<PropertyDeclarationBlock>> {
|
|
54
|
+
&self.0
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/// Marks this block as part of the rule tree.
|
|
58
|
+
#[inline]
|
|
59
|
+
pub fn mark_in_rule_tree(&self) {
|
|
60
|
+
use std::sync::atomic::Ordering;
|
|
61
|
+
if self.0.is_static() {
|
|
62
|
+
// For static pointers, it doesn't matter whether we might be in the rule tree or not,
|
|
63
|
+
// because those are not mutable.
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
// SAFETY: We're only accessing a relaxed atomic inside the locked object, which we know
|
|
67
|
+
// is alive. In theory, we could/should track that boolean outside of the
|
|
68
|
+
// Locked<PropertyDeclarationBlock>, but that is kind of a PITA.
|
|
69
|
+
#[allow(unsafe_code)]
|
|
70
|
+
unsafe {
|
|
71
|
+
// Load before storing: the flag is never cleared, so after the first mark every
|
|
72
|
+
// store is redundant, and an unconditional store would still take the cache line
|
|
73
|
+
// exclusive and invalidate it for every other thread reading this block.
|
|
74
|
+
let immutable = &self.0.read_unchecked().immutable;
|
|
75
|
+
if !immutable.load(Ordering::Relaxed) {
|
|
76
|
+
immutable.store(true, Ordering::Relaxed);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
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
|
+
use std::mem::ManuallyDrop;
|
|
8
|
+
use std::ops::Deref;
|
|
9
|
+
use std::ptr;
|
|
10
|
+
|
|
11
|
+
/// An unsafe box, derefs to `T`.
|
|
12
|
+
pub(super) struct UnsafeBox<T> {
|
|
13
|
+
inner: ManuallyDrop<Box<T>>,
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
impl<T> UnsafeBox<T> {
|
|
17
|
+
/// Creates a new unsafe box.
|
|
18
|
+
pub(super) fn from_box(value: Box<T>) -> Self {
|
|
19
|
+
Self {
|
|
20
|
+
inner: ManuallyDrop::new(value),
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/// Creates a new box from a pointer.
|
|
25
|
+
///
|
|
26
|
+
/// # Safety
|
|
27
|
+
///
|
|
28
|
+
/// The input should point to a valid `T`.
|
|
29
|
+
pub(super) unsafe fn from_raw(ptr: *mut T) -> Self {
|
|
30
|
+
unsafe {
|
|
31
|
+
Self {
|
|
32
|
+
inner: ManuallyDrop::new(Box::from_raw(ptr)),
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/// Creates a new unsafe box from an existing one.
|
|
38
|
+
///
|
|
39
|
+
/// # Safety
|
|
40
|
+
///
|
|
41
|
+
/// There is no refcounting or whatever else in an unsafe box, so this
|
|
42
|
+
/// operation can lead to double frees.
|
|
43
|
+
pub(super) unsafe fn clone(this: &Self) -> Self {
|
|
44
|
+
unsafe {
|
|
45
|
+
Self {
|
|
46
|
+
inner: ptr::read(&this.inner),
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/// Returns a mutable reference to the inner value of this unsafe box.
|
|
52
|
+
///
|
|
53
|
+
/// # Safety
|
|
54
|
+
///
|
|
55
|
+
/// Given `Self::clone`, nothing prevents anyone from creating
|
|
56
|
+
/// multiple mutable references to the inner value, which is completely UB.
|
|
57
|
+
pub(crate) unsafe fn deref_mut(this: &mut Self) -> &mut T {
|
|
58
|
+
&mut this.inner
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/// Drops the inner value of this unsafe box.
|
|
62
|
+
///
|
|
63
|
+
/// # Safety
|
|
64
|
+
///
|
|
65
|
+
/// Given this doesn't consume the unsafe box itself, this has the same
|
|
66
|
+
/// safety caveats as `ManuallyDrop::drop`.
|
|
67
|
+
pub(super) unsafe fn drop(this: &mut Self) {
|
|
68
|
+
unsafe { ManuallyDrop::drop(&mut this.inner) }
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
impl<T> Deref for UnsafeBox<T> {
|
|
73
|
+
type Target = T;
|
|
74
|
+
|
|
75
|
+
fn deref(&self) -> &Self::Target {
|
|
76
|
+
&self.inner
|
|
77
|
+
}
|
|
78
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
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
|
+
//! Stack-scoped thread-local storage for rayon thread pools.
|
|
6
|
+
|
|
7
|
+
#![allow(unsafe_code)]
|
|
8
|
+
#![deny(missing_docs)]
|
|
9
|
+
|
|
10
|
+
use crate::global_style_data::STYLO_MAX_THREADS;
|
|
11
|
+
use std::cell::{Ref, RefCell, RefMut};
|
|
12
|
+
use std::ops::DerefMut;
|
|
13
|
+
|
|
14
|
+
/// A scoped TLS set, that is alive during the `'scope` lifetime.
|
|
15
|
+
///
|
|
16
|
+
/// We use this on Servo to construct thread-local contexts, but clear them once
|
|
17
|
+
/// we're done with restyling.
|
|
18
|
+
///
|
|
19
|
+
/// Note that the cleanup is done on the thread that owns the scoped TLS, thus
|
|
20
|
+
/// the Send bound.
|
|
21
|
+
pub struct ScopedTLS<'scope, T: Send> {
|
|
22
|
+
pool: Option<&'scope rayon::ThreadPool>,
|
|
23
|
+
slots: [RefCell<Option<T>>; STYLO_MAX_THREADS],
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/// The scoped TLS is `Sync` because no more than one worker thread can access a
|
|
27
|
+
/// given slot.
|
|
28
|
+
unsafe impl<'scope, T: Send> Sync for ScopedTLS<'scope, T> {}
|
|
29
|
+
|
|
30
|
+
impl<'scope, T: Send> ScopedTLS<'scope, T> {
|
|
31
|
+
/// Create a new scoped TLS that will last as long as this rayon threadpool
|
|
32
|
+
/// reference.
|
|
33
|
+
pub fn new(pool: Option<&'scope rayon::ThreadPool>) -> Self {
|
|
34
|
+
debug_assert!(pool.is_none_or(|p| p.current_num_threads() <= STYLO_MAX_THREADS));
|
|
35
|
+
ScopedTLS {
|
|
36
|
+
pool,
|
|
37
|
+
slots: Default::default(),
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/// Returns the index corresponding to the calling thread in the thread pool.
|
|
42
|
+
#[inline]
|
|
43
|
+
pub fn current_thread_index(&self) -> usize {
|
|
44
|
+
self.pool.map_or(0, |p| p.current_thread_index().unwrap())
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/// Return an immutable reference to the `Option<T>` that this thread owns.
|
|
48
|
+
pub fn borrow(&self) -> Ref<'_, Option<T>> {
|
|
49
|
+
let idx = self.current_thread_index();
|
|
50
|
+
self.slots[idx].borrow()
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/// Return a mutable reference to the `Option<T>` that this thread owns.
|
|
54
|
+
pub fn borrow_mut(&self) -> RefMut<'_, Option<T>> {
|
|
55
|
+
let idx = self.current_thread_index();
|
|
56
|
+
self.slots[idx].borrow_mut()
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/// Ensure that the current data this thread owns is initialized, or
|
|
60
|
+
/// initialize it using `f`. We want ensure() to be fast and inline, and we
|
|
61
|
+
/// want to inline the memmove that initializes the Option<T>. But we don't
|
|
62
|
+
/// want to inline space for the entire large T struct in our stack frame.
|
|
63
|
+
/// That's why we hand `f` a mutable borrow to write to instead of just
|
|
64
|
+
/// having it return a T.
|
|
65
|
+
#[inline(always)]
|
|
66
|
+
pub fn ensure<F: FnOnce(&mut Option<T>)>(&self, f: F) -> RefMut<'_, T> {
|
|
67
|
+
let mut opt = self.borrow_mut();
|
|
68
|
+
if opt.is_none() {
|
|
69
|
+
f(opt.deref_mut());
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
RefMut::map(opt, |x| x.as_mut().unwrap())
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/// Returns the slots. Safe because if we have a mut reference the tls can't be referenced by
|
|
76
|
+
/// any other thread.
|
|
77
|
+
pub fn slots(&mut self) -> &mut [RefCell<Option<T>>] {
|
|
78
|
+
&mut self.slots
|
|
79
|
+
}
|
|
80
|
+
}
|