├── .gitignore ├── rustfmt.toml ├── style ├── properties │ ├── Mako-1.1.2-py2.py3-none-any.whl │ ├── shorthands │ │ ├── page.mako.rs │ │ ├── xul.mako.rs │ │ ├── counters.mako.rs │ │ ├── effects.mako.rs │ │ ├── table.mako.rs │ │ ├── inherited_box.mako.rs │ │ ├── inherited_ui.mako.rs │ │ ├── inherited_table.mako.rs │ │ ├── inherited_svg.mako.rs │ │ ├── padding.mako.rs │ │ ├── margin.mako.rs │ │ └── outline.mako.rs │ ├── longhands │ │ ├── table.mako.rs │ │ ├── page.mako.rs │ │ ├── outline.mako.rs │ │ ├── inherited_table.mako.rs │ │ ├── padding.mako.rs │ │ ├── counters.mako.rs │ │ ├── margin.mako.rs │ │ ├── effects.mako.rs │ │ ├── xul.mako.rs │ │ ├── column.mako.rs │ │ ├── list.mako.rs │ │ └── text.mako.rs │ └── properties.html.mako ├── README.md ├── stylesheets │ ├── property_rule.rs │ ├── font_face_rule.rs │ ├── counter_style_rule.rs │ ├── loader.rs │ ├── namespace_rule.rs │ ├── nested_declarations_rule.rs │ ├── starting_style_rule.rs │ ├── position_try_rule.rs │ ├── media_rule.rs │ └── style_rule.rs ├── values │ ├── computed │ │ ├── outline.rs │ │ ├── table.rs │ │ ├── column.rs │ │ ├── rect.rs │ │ ├── list.rs │ │ ├── url.rs │ │ ├── background.rs │ │ ├── flex.rs │ │ ├── ui.rs │ │ ├── counters.rs │ │ ├── time.rs │ │ ├── effects.rs │ │ ├── resolution.rs │ │ ├── svg.rs │ │ ├── motion.rs │ │ ├── page.rs │ │ ├── angle.rs │ │ └── border.rs │ ├── specified │ │ ├── column.rs │ │ ├── rect.rs │ │ ├── url.rs │ │ ├── flex.rs │ │ ├── table.rs │ │ ├── ratio.rs │ │ └── outline.rs │ ├── generics │ │ ├── flex.rs │ │ ├── column.rs │ │ ├── url.rs │ │ ├── background.rs │ │ ├── ratio.rs │ │ └── size.rs │ ├── animated │ │ ├── effects.rs │ │ ├── font.rs │ │ └── svg.rs │ └── resolved │ │ ├── animation.rs │ │ ├── color.rs │ │ └── counters.rs ├── invalidation │ ├── mod.rs │ ├── element │ │ └── mod.rs │ └── viewport_units.rs ├── properties_and_values │ ├── mod.rs │ └── syntax │ │ └── ascii.rs ├── servo │ └── mod.rs ├── gecko_bindings │ ├── sugar │ │ ├── mod.rs │ │ ├── ns_com_ptr.rs │ │ ├── ns_compatibility.rs │ │ ├── origin_flags.rs │ │ └── ownership.rs │ └── mod.rs ├── media_queries │ └── mod.rs ├── gecko │ ├── mod.rs │ ├── values.rs │ ├── traversal.rs │ └── conversions.rs ├── queries │ ├── mod.rs │ └── values.rs ├── counter_style │ ├── update_predefined.py │ └── predefined.rs ├── simple_buckets_map.rs ├── rule_tree │ ├── source.rs │ └── unsafe_box.rs ├── macros.rs ├── font_metrics.rs ├── author_styles.rs ├── build.rs ├── gecko_string_cache │ └── namespace.rs ├── traversal_flags.rs └── thread_state.rs ├── selectors ├── CHANGES.md ├── relative_selector │ ├── mod.rs │ └── cache.rs ├── lib.rs ├── sink.rs ├── Cargo.toml ├── README.md └── build.rs ├── shell.nix ├── stylo_atoms ├── lib.rs ├── Cargo.toml ├── build.rs └── predefined_counter_styles.rs ├── style.paths ├── stylo_static_prefs ├── Cargo.toml └── src │ └── lib.rs ├── start-rebase.sh ├── Cargo.toml ├── stylo_config ├── Cargo.toml └── lib.rs ├── stylo_dom └── Cargo.toml ├── style_derive ├── Cargo.toml ├── to_animated_value.rs ├── to_resolved_value.rs ├── to_animated_zero.rs └── lib.rs ├── to_shmem_derive ├── lib.rs ├── Cargo.toml ├── util.rs └── to_shmem.rs ├── servo_arc ├── Cargo.toml └── LICENSE-MIT ├── .github └── workflows │ ├── sync-upstream.yml │ ├── mirror-to-release-branch.yml │ └── main.yml ├── commit-from-squashed.sh ├── malloc_size_of ├── Cargo.toml └── LICENSE-MIT ├── commit-from-merge.sh ├── style_traits ├── Cargo.toml ├── dom.rs └── owned_str.rs ├── to_shmem └── Cargo.toml ├── sync.sh └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | /_cache/ 2 | /_filtered/ 3 | /target/ 4 | /style/properties/__pycache__/ 5 | Cargo.lock 6 | -------------------------------------------------------------------------------- /rustfmt.toml: -------------------------------------------------------------------------------- 1 | match_block_trailing_comma = true 2 | binop_separator = "Back" 3 | reorder_imports = true 4 | -------------------------------------------------------------------------------- /style/properties/Mako-1.1.2-py2.py3-none-any.whl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DioxusLabs/stylo/main/style/properties/Mako-1.1.2-py2.py3-none-any.whl -------------------------------------------------------------------------------- /selectors/CHANGES.md: -------------------------------------------------------------------------------- 1 | - `parser.rs` no longer wraps values in quotes (`"..."`) but expects their `to_css` impl to already wrap it ([Gecko Bug 1854809](https://bugzilla.mozilla.org/show_bug.cgi?id=1854809)) 2 | -------------------------------------------------------------------------------- /shell.nix: -------------------------------------------------------------------------------- 1 | with import (builtins.fetchTarball { 2 | url = "https://github.com/NixOS/nixpkgs/archive/46ae0210ce163b3cba6c7da08840c1d63de9c701.tar.gz"; 3 | }) {}; 4 | stdenv.mkDerivation rec { 5 | name = "style-sync-shell"; 6 | } 7 | -------------------------------------------------------------------------------- /style/README.md: -------------------------------------------------------------------------------- 1 | servo-style 2 | =========== 3 | 4 | Style system for Servo, using [rust-cssparser](https://github.com/servo/rust-cssparser) for parsing. 5 | 6 | * [Documentation](https://book.servo.org/architecture/style.html). 7 | -------------------------------------------------------------------------------- /style/properties/shorthands/page.mako.rs: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /style/properties/shorthands/xul.mako.rs: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /style/properties/shorthands/counters.mako.rs: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /style/properties/shorthands/effects.mako.rs: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /style/properties/shorthands/table.mako.rs: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /style/properties/shorthands/inherited_box.mako.rs: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /style/properties/shorthands/inherited_ui.mako.rs: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /style/properties/shorthands/inherited_table.mako.rs: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /stylo_atoms/lib.rs: -------------------------------------------------------------------------------- 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 | include!(concat!(env!("OUT_DIR"), "/atom.rs")); 6 | -------------------------------------------------------------------------------- /selectors/relative_selector/mod.rs: -------------------------------------------------------------------------------- 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 | pub mod cache; 6 | pub mod filter; 7 | -------------------------------------------------------------------------------- /style/stylesheets/property_rule.rs: -------------------------------------------------------------------------------- 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 | pub use crate::properties_and_values::registry::PropertyRegistration as PropertyRule; 6 | -------------------------------------------------------------------------------- /style.paths: -------------------------------------------------------------------------------- 1 | # Filters and renames use git-filter-repo(1) --paths-from-file: 2 | # https://htmlpreview.github.io/?https://github.com/newren/git-filter-repo/blob/docs/html/git-filter-repo.html#_filtering_based_on_many_paths 3 | 4 | servo/components/ 5 | servo/rustfmt.toml 6 | 7 | regex:servo/components/(.+)==>\1 8 | servo/rustfmt.toml==>rustfmt.toml 9 | -------------------------------------------------------------------------------- /style/stylesheets/font_face_rule.rs: -------------------------------------------------------------------------------- 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(missing_docs)] 6 | 7 | pub use crate::font_face::FontFaceRuleData as FontFaceRule; 8 | -------------------------------------------------------------------------------- /style/values/computed/outline.rs: -------------------------------------------------------------------------------- 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 | //! Computed values for outline properties 6 | 7 | pub use crate::values::specified::OutlineStyle; 8 | -------------------------------------------------------------------------------- /style/values/computed/table.rs: -------------------------------------------------------------------------------- 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 | //! Computed types for CSS values related to tables. 6 | 7 | pub use super::specified::table::CaptionSide; 8 | -------------------------------------------------------------------------------- /style/stylesheets/counter_style_rule.rs: -------------------------------------------------------------------------------- 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(missing_docs)] 6 | 7 | pub use crate::counter_style::CounterStyleRuleData as CounterStyleRule; 8 | -------------------------------------------------------------------------------- /stylo_static_prefs/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "stylo_static_prefs" 3 | version = "0.1.0" 4 | authors = ["The Servo Project Developers"] 5 | documentation = "https://docs.rs/stylo_static_prefs/" 6 | description = "Static configuration for Stylo" 7 | repository = "https://github.com/servo/stylo" 8 | keywords = ["css", "style"] 9 | license = "MPL-2.0" 10 | edition = "2021" 11 | -------------------------------------------------------------------------------- /start-rebase.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Usage: start-rebase.sh [extra git-rebase(1) arguments ...] 3 | # Equivalent to git rebase --onto . 4 | set -eu 5 | 6 | new_base=$1; shift 7 | first_commit=$(git log --pretty=\%H --grep='Servo initial downstream commit') 8 | old_base=$first_commit~ 9 | 10 | git rebase --onto "$new_base" "$old_base" "$@" 11 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | resolver = "2" 3 | members = [ 4 | "stylo_atoms", 5 | "stylo_dom", 6 | "malloc_size_of", 7 | "rustfmt.toml", 8 | "selectors", 9 | "servo_arc", 10 | "style", 11 | "style_derive", 12 | "stylo_config", 13 | "stylo_static_prefs", 14 | "style_traits", 15 | "to_shmem", 16 | "to_shmem_derive", 17 | ] 18 | default-members = ["style"] 19 | -------------------------------------------------------------------------------- /style/invalidation/mod.rs: -------------------------------------------------------------------------------- 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 | //! Different bits of code related to invalidating style. 6 | 7 | pub mod element; 8 | pub mod media_queries; 9 | pub mod stylesheets; 10 | pub mod viewport_units; 11 | -------------------------------------------------------------------------------- /stylo_config/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "stylo_config" 3 | version = "0.1.0" 4 | authors = ["The Servo Project Developers"] 5 | documentation = "https://docs.rs/stylo_config/" 6 | description = "Runtime configuration for Stylo" 7 | repository = "https://github.com/servo/stylo" 8 | keywords = ["css", "style"] 9 | license = "MPL-2.0" 10 | edition = "2021" 11 | 12 | [lib] 13 | name = "stylo_config" 14 | path = "lib.rs" 15 | -------------------------------------------------------------------------------- /style/properties_and_values/mod.rs: -------------------------------------------------------------------------------- 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 | //! Properties and Values 6 | //! 7 | //! https://drafts.css-houdini.org/css-properties-values-api-1/ 8 | 9 | pub mod registry; 10 | pub mod rule; 11 | pub mod syntax; 12 | pub mod value; 13 | -------------------------------------------------------------------------------- /style/servo/mod.rs: -------------------------------------------------------------------------------- 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 | //! Servo-specific bits of the style system. 6 | //! 7 | //! These get compiled out on a Gecko build. 8 | 9 | pub mod media_queries; 10 | pub mod restyle_damage; 11 | pub mod selector_parser; 12 | pub mod url; 13 | -------------------------------------------------------------------------------- /style/gecko_bindings/sugar/mod.rs: -------------------------------------------------------------------------------- 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 | //! Rust sugar and convenience methods for Gecko types. 6 | 7 | mod ns_com_ptr; 8 | mod ns_compatibility; 9 | mod ns_style_auto_array; 10 | pub mod origin_flags; 11 | pub mod ownership; 12 | pub mod refptr; 13 | -------------------------------------------------------------------------------- /stylo_dom/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "stylo_dom" 3 | version = "0.1.0" 4 | authors = ["The Servo Project Developers"] 5 | documentation = "https://docs.rs/stylo_dom/" 6 | description = "DOM state types for Stylo" 7 | repository = "https://github.com/servo/stylo" 8 | keywords = ["css", "style"] 9 | license = "MPL-2.0" 10 | edition = "2021" 11 | 12 | [lib] 13 | path = "lib.rs" 14 | 15 | [dependencies] 16 | bitflags = "2" 17 | malloc_size_of = { path = "../malloc_size_of", package = "stylo_malloc_size_of" } 18 | -------------------------------------------------------------------------------- /stylo_atoms/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "stylo_atoms" 3 | version = "0.1.0" 4 | authors = ["The Servo Project Developers"] 5 | documentation = "https://docs.rs/stylo_atoms/" 6 | description = "Interned string type for the Servo and Stylo projects" 7 | repository = "https://github.com/servo/stylo" 8 | license = "MPL-2.0" 9 | edition = "2018" 10 | build = "build.rs" 11 | 12 | [lib] 13 | path = "lib.rs" 14 | 15 | [dependencies] 16 | string_cache = "0.8" 17 | 18 | [build-dependencies] 19 | string_cache_codegen = "0.5" 20 | -------------------------------------------------------------------------------- /style/gecko_bindings/sugar/ns_com_ptr.rs: -------------------------------------------------------------------------------- 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 | //! Little helpers for `nsCOMPtr`. 6 | 7 | use crate::gecko_bindings::structs::nsCOMPtr; 8 | 9 | impl nsCOMPtr { 10 | /// Get this pointer as a raw pointer. 11 | #[inline] 12 | pub fn raw(&self) -> *mut T { 13 | self.mRawPtr 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /style/invalidation/element/mod.rs: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ 4 | 5 | //! Invalidation of element styles due to attribute or style changes. 6 | 7 | pub mod document_state; 8 | pub mod element_wrapper; 9 | pub mod invalidation_map; 10 | pub mod invalidator; 11 | pub mod relative_selector; 12 | pub mod restyle_hints; 13 | pub mod state_and_attributes; 14 | -------------------------------------------------------------------------------- /style/values/computed/column.rs: -------------------------------------------------------------------------------- 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 | //! Computed types for the column properties. 6 | 7 | use crate::values::computed::PositiveInteger; 8 | use crate::values::generics::column::GenericColumnCount; 9 | 10 | /// A computed type for `column-count` values. 11 | pub type ColumnCount = GenericColumnCount; 12 | -------------------------------------------------------------------------------- /style/values/specified/column.rs: -------------------------------------------------------------------------------- 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 | //! Specified types for the column properties. 6 | 7 | use crate::values::generics::column::GenericColumnCount; 8 | use crate::values::specified::PositiveInteger; 9 | 10 | /// A specified type for `column-count` values. 11 | pub type ColumnCount = GenericColumnCount; 12 | -------------------------------------------------------------------------------- /style/values/computed/rect.rs: -------------------------------------------------------------------------------- 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 | //! Computed types for CSS borders. 6 | 7 | use crate::values::computed::length::NonNegativeLengthOrNumber; 8 | use crate::values::generics::rect::Rect; 9 | 10 | /// A specified rectangle made of four `` values. 11 | pub type NonNegativeLengthOrNumberRect = Rect; 12 | -------------------------------------------------------------------------------- /style_derive/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "stylo_derive" 3 | version = "0.0.1" 4 | authors = ["The Servo Project Developers"] 5 | license = "MPL-2.0" 6 | repository = "https://github.com/servo/stylo" 7 | edition = "2021" 8 | publish = false 9 | 10 | [lib] 11 | path = "lib.rs" 12 | proc-macro = true 13 | 14 | [dependencies] 15 | darling = { version = "0.20", default-features = false } 16 | proc-macro2 = "1" 17 | quote = "1" 18 | syn = { version = "2", default-features = false, features = ["clone-impls", "derive", "parsing"] } 19 | synstructure = "0.13" 20 | -------------------------------------------------------------------------------- /style/values/specified/rect.rs: -------------------------------------------------------------------------------- 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 | //! Specified types for CSS borders. 6 | 7 | use crate::values::generics::rect::Rect; 8 | use crate::values::specified::length::NonNegativeLengthOrNumber; 9 | 10 | /// A specified rectangle made of four `` values. 11 | pub type NonNegativeLengthOrNumberRect = Rect; 12 | -------------------------------------------------------------------------------- /to_shmem_derive/lib.rs: -------------------------------------------------------------------------------- 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 | #![recursion_limit = "128"] 6 | 7 | use proc_macro::TokenStream; 8 | 9 | mod to_shmem; 10 | mod util; 11 | 12 | #[proc_macro_derive(ToShmem, attributes(shmem))] 13 | pub fn derive_to_shmem(stream: TokenStream) -> TokenStream { 14 | let input = syn::parse(stream).unwrap(); 15 | to_shmem::derive(input).into() 16 | } 17 | -------------------------------------------------------------------------------- /to_shmem_derive/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "to_shmem_derive" 3 | version = "0.1.0" 4 | authors = ["The Servo Project Developers"] 5 | license = "MPL-2.0" 6 | repository = "https://github.com/servo/stylo" 7 | edition = "2021" 8 | description = "Allows deriving the to_shmem trait." 9 | 10 | [lib] 11 | path = "lib.rs" 12 | proc-macro = true 13 | 14 | [dependencies] 15 | darling = { version = "0.20", default-features = false } 16 | proc-macro2 = "1" 17 | quote = "1" 18 | syn = { version = "2", default-features = false, features = ["derive", "parsing"] } 19 | synstructure = "0.13" 20 | -------------------------------------------------------------------------------- /style/values/computed/list.rs: -------------------------------------------------------------------------------- 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 | //! `list` computed values. 6 | 7 | #[cfg(feature = "gecko")] 8 | pub use crate::values::specified::list::ListStyleType; 9 | pub use crate::values::specified::list::Quotes; 10 | 11 | impl Quotes { 12 | /// Initial value for `quotes`. 13 | #[inline] 14 | pub fn get_initial_value() -> Quotes { 15 | Quotes::Auto 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /servo_arc/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "servo_arc" 3 | version = "0.4.0" 4 | authors = ["The Servo Project Developers"] 5 | license = "MIT OR Apache-2.0" 6 | repository = "https://github.com/servo/stylo" 7 | description = "A fork of std::sync::Arc with some extra functionality and without weak references" 8 | edition = "2021" 9 | 10 | [lib] 11 | name = "servo_arc" 12 | path = "lib.rs" 13 | 14 | [features] 15 | gecko_refcount_logging = [] 16 | servo = ["serde", "track_alloc_size"] 17 | track_alloc_size = [] 18 | 19 | [dependencies] 20 | serde = { version = "1.0", optional = true } 21 | stable_deref_trait = "1.0.0" 22 | -------------------------------------------------------------------------------- /style/values/specified/url.rs: -------------------------------------------------------------------------------- 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 | //! Common handling for the specified value CSS url() values. 6 | 7 | use crate::values::generics::url::GenericUrlOrNone; 8 | 9 | #[cfg(feature = "gecko")] 10 | pub use crate::gecko::url::SpecifiedUrl; 11 | #[cfg(feature = "servo")] 12 | pub use crate::servo::url::SpecifiedUrl; 13 | 14 | /// Specified | 15 | pub type UrlOrNone = GenericUrlOrNone; 16 | -------------------------------------------------------------------------------- /.github/workflows/sync-upstream.yml: -------------------------------------------------------------------------------- 1 | name: Sync upstream with mozilla-central 2 | 3 | on: 4 | schedule: 5 | - cron: '0 13 * * *' 6 | workflow_dispatch: 7 | 8 | jobs: 9 | sync: 10 | name: Sync 11 | runs-on: ubuntu-22.04 12 | steps: 13 | - uses: actions/checkout@v3 14 | with: 15 | fetch-depth: 1 16 | - uses: actions/cache@v3 17 | with: 18 | path: _cache/upstream 19 | key: upstream 20 | - run: | 21 | ./sync.sh _filtered 22 | git fetch -f --progress ./_filtered master:upstream 23 | git push -fu --progress origin upstream 24 | -------------------------------------------------------------------------------- /style/values/computed/url.rs: -------------------------------------------------------------------------------- 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 | //! Common handling for the computed value CSS url() values. 6 | 7 | use crate::values::generics::url::UrlOrNone as GenericUrlOrNone; 8 | 9 | #[cfg(feature = "gecko")] 10 | pub use crate::gecko::url::ComputedUrl; 11 | #[cfg(feature = "servo")] 12 | pub use crate::servo::url::ComputedUrl; 13 | 14 | /// Computed | 15 | pub type UrlOrNone = GenericUrlOrNone; 16 | -------------------------------------------------------------------------------- /style/media_queries/mod.rs: -------------------------------------------------------------------------------- 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 | //! [Media queries][mq]. 6 | //! 7 | //! [mq]: https://drafts.csswg.org/mediaqueries/ 8 | 9 | mod media_list; 10 | mod media_query; 11 | 12 | pub use self::media_list::MediaList; 13 | pub use self::media_query::{MediaQuery, MediaQueryType, MediaType, Qualifier}; 14 | 15 | #[cfg(feature = "gecko")] 16 | pub use crate::gecko::media_queries::Device; 17 | #[cfg(feature = "servo")] 18 | pub use crate::servo::media_queries::Device; 19 | -------------------------------------------------------------------------------- /commit-from-squashed.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Usage: commit-from-squashed.sh [extra git-commit(1) arguments ...] 3 | # Given a squashed commit made by the GitHub merge queue, runs git-commit(1) with your local changes 4 | # while borrowing our author name/email from that commit, our author date from its committer date, 5 | # and our commit message from that commit. 6 | set -eu 7 | 8 | squashed_commit=$1; shift 9 | committer_date=$(git log -n1 --pretty='%cd' "$squashed_commit") 10 | 11 | # -c is equivalent to --author=$(...'%aN <%aE>') -m $(...'%B'), but allows editing 12 | set -- git commit -c "$squashed_commit" --date="$committer_date" "$@" 13 | echo "$@" 14 | "$@" 15 | -------------------------------------------------------------------------------- /style/gecko/mod.rs: -------------------------------------------------------------------------------- 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 | //! Gecko-specific style-system bits. 6 | 7 | #[macro_use] 8 | mod non_ts_pseudo_class_list; 9 | 10 | pub mod arc_types; 11 | pub mod conversions; 12 | pub mod data; 13 | pub mod media_features; 14 | pub mod media_queries; 15 | pub mod pseudo_element; 16 | pub mod restyle_damage; 17 | pub mod selector_parser; 18 | pub mod snapshot; 19 | pub mod snapshot_helpers; 20 | pub mod traversal; 21 | pub mod url; 22 | pub mod values; 23 | pub mod wrapper; 24 | -------------------------------------------------------------------------------- /style/values/computed/background.rs: -------------------------------------------------------------------------------- 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 | //! Computed types for CSS values related to backgrounds. 6 | 7 | use crate::values::computed::length::NonNegativeLengthPercentage; 8 | use crate::values::generics::background::BackgroundSize as GenericBackgroundSize; 9 | 10 | pub use crate::values::specified::background::BackgroundRepeat; 11 | 12 | /// A computed value for the `background-size` property. 13 | pub type BackgroundSize = GenericBackgroundSize; 14 | -------------------------------------------------------------------------------- /style/values/computed/flex.rs: -------------------------------------------------------------------------------- 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 | //! Computed types for CSS values related to flexbox. 6 | 7 | use crate::values::computed::Size; 8 | use crate::values::generics::flex::FlexBasis as GenericFlexBasis; 9 | 10 | /// A computed value for the `flex-basis` property. 11 | pub type FlexBasis = GenericFlexBasis; 12 | 13 | impl FlexBasis { 14 | /// `auto` 15 | #[inline] 16 | pub fn auto() -> Self { 17 | GenericFlexBasis::Size(Size::auto()) 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /malloc_size_of/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "stylo_malloc_size_of" 3 | version = "0.0.1" 4 | authors = ["The Servo Project Developers"] 5 | license = "MIT OR Apache-2.0" 6 | repository = "https://github.com/servo/stylo" 7 | publish = false 8 | 9 | [lib] 10 | path = "lib.rs" 11 | 12 | [features] 13 | gecko = ["thin-vec/gecko-ffi"] 14 | servo = ["string_cache"] 15 | 16 | [dependencies] 17 | app_units = "0.7" 18 | cssparser = "0.35" 19 | euclid = "0.22" 20 | selectors = { path = "../selectors" } 21 | servo_arc = { path = "../servo_arc" } 22 | smallbitvec = "2.3.0" 23 | smallvec = "1.13" 24 | string_cache = { version = "0.8", optional = true } 25 | thin-vec = { version = "0.2.13" } 26 | void = "1.0.2" 27 | -------------------------------------------------------------------------------- /commit-from-merge.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Usage: commit-from-merge.sh [extra git-commit(1) arguments ...] 3 | # Given a merge commit made by bors, runs git-commit(1) with your local changes 4 | # while borrowing the author name/email from the right-hand parent of the merge, 5 | # and the author date from the committer date of the merge. 6 | set -eu 7 | 8 | lookup_repo=$1; shift 9 | merge_commit=$1; shift 10 | author_name_email=$(git -C "$lookup_repo" log -n1 --pretty='%aN <%aE>' "$merge_commit"\^2) 11 | committer_date=$(git -C "$lookup_repo" log -n1 --pretty='%cd' "$merge_commit") 12 | 13 | set -- git commit --author="$author_name_email" --date="$committer_date" "$@" 14 | echo "$@" 15 | "$@" 16 | -------------------------------------------------------------------------------- /style/queries/mod.rs: -------------------------------------------------------------------------------- 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 | //! Code shared between [media queries][mq] and [container queries][cq]. 6 | //! 7 | //! [mq]: https://drafts.csswg.org/mediaqueries/ 8 | //! [cq]: https://drafts.csswg.org/css-contain-3/#container-rule 9 | 10 | pub mod condition; 11 | 12 | #[macro_use] 13 | pub mod feature; 14 | pub mod feature_expression; 15 | pub mod values; 16 | 17 | pub use self::condition::QueryCondition; 18 | pub use self::feature::FeatureFlags; 19 | pub use self::feature_expression::{FeatureType, QueryFeatureExpression}; 20 | -------------------------------------------------------------------------------- /selectors/lib.rs: -------------------------------------------------------------------------------- 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 | // Make |cargo bench| work. 6 | #![cfg_attr(feature = "bench", feature(test))] 7 | 8 | pub mod attr; 9 | pub mod bloom; 10 | mod builder; 11 | pub mod context; 12 | pub mod kleene_value; 13 | pub mod matching; 14 | mod nth_index_cache; 15 | pub mod parser; 16 | pub mod relative_selector; 17 | pub mod sink; 18 | mod tree; 19 | pub mod visitor; 20 | 21 | pub use crate::nth_index_cache::NthIndexCache; 22 | pub use crate::parser::{Parser, SelectorImpl, SelectorList}; 23 | pub use crate::tree::{Element, OpaqueElement}; 24 | -------------------------------------------------------------------------------- /style/values/specified/flex.rs: -------------------------------------------------------------------------------- 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 | //! Specified types for CSS values related to flexbox. 6 | 7 | use crate::values::generics::flex::FlexBasis as GenericFlexBasis; 8 | use crate::values::specified::Size; 9 | 10 | /// A specified value for the `flex-basis` property. 11 | pub type FlexBasis = GenericFlexBasis; 12 | 13 | impl FlexBasis { 14 | /// `auto` 15 | #[inline] 16 | pub fn auto() -> Self { 17 | GenericFlexBasis::Size(Size::auto()) 18 | } 19 | 20 | /// `0%` 21 | #[inline] 22 | pub fn zero_percent() -> Self { 23 | GenericFlexBasis::Size(Size::zero_percent()) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /style/gecko_bindings/sugar/ns_compatibility.rs: -------------------------------------------------------------------------------- 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 | //! Little helper for `nsCompatibility`. 6 | 7 | use crate::context::QuirksMode; 8 | use crate::gecko_bindings::structs::nsCompatibility; 9 | 10 | impl From for QuirksMode { 11 | #[inline] 12 | fn from(mode: nsCompatibility) -> QuirksMode { 13 | match mode { 14 | nsCompatibility::eCompatibility_FullStandards => QuirksMode::NoQuirks, 15 | nsCompatibility::eCompatibility_AlmostStandards => QuirksMode::LimitedQuirks, 16 | nsCompatibility::eCompatibility_NavQuirks => QuirksMode::Quirks, 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /.github/workflows/mirror-to-release-branch.yml: -------------------------------------------------------------------------------- 1 | name: 🪞 Mirror `main` 2 | on: 3 | push: 4 | branches: 5 | - main 6 | 7 | jobs: 8 | mirror: 9 | name: Mirror 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: actions/checkout@v4 13 | with: 14 | fetch-depth: 0 15 | - name: Get branch name 16 | id: branch-name 17 | run: | 18 | first_commit=$(git log --pretty=\%H --grep='Servo initial downstream commit') 19 | upstream_base="$first_commit~" 20 | echo BRANCH_NAME=$(git log -n1 --pretty='%as' $upstream_base) >> $GITHUB_OUTPUT 21 | - uses: google/mirror-branch-action@v1.0 22 | name: Mirror to ${{ steps.branch-name.outputs.BRANCH_NAME }} 23 | with: 24 | github-token: ${{ secrets.GITHUB_TOKEN }} 25 | source: main 26 | dest: ${{ steps.branch-name.outputs.BRANCH_NAME }} 27 | -------------------------------------------------------------------------------- /style/values/generics/flex.rs: -------------------------------------------------------------------------------- 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 | //! Generic types for CSS values related to flexbox. 6 | 7 | /// A generic value for the `flex-basis` property. 8 | #[derive( 9 | Animate, 10 | Clone, 11 | ComputeSquaredDistance, 12 | Copy, 13 | Debug, 14 | MallocSizeOf, 15 | Parse, 16 | PartialEq, 17 | SpecifiedValueInfo, 18 | ToAnimatedValue, 19 | ToAnimatedZero, 20 | ToComputedValue, 21 | ToCss, 22 | ToResolvedValue, 23 | ToShmem, 24 | )] 25 | #[repr(C)] 26 | pub enum GenericFlexBasis { 27 | /// `content` 28 | Content, 29 | /// `` 30 | Size(S), 31 | } 32 | 33 | pub use self::GenericFlexBasis as FlexBasis; 34 | -------------------------------------------------------------------------------- /style/properties/longhands/table.mako.rs: -------------------------------------------------------------------------------- 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 | <%namespace name="helpers" file="/helpers.mako.rs" /> 6 | 7 | ${helpers.single_keyword( 8 | "table-layout", 9 | "auto fixed", 10 | engines="gecko servo", 11 | gecko_ffi_name="mLayoutStrategy", 12 | animation_type="discrete", 13 | gecko_enum_prefix="StyleTableLayout", 14 | spec="https://drafts.csswg.org/css-tables/#propdef-table-layout", 15 | servo_restyle_damage="reflow", 16 | affects="layout", 17 | )} 18 | 19 | ${helpers.predefined_type( 20 | "-x-span", 21 | "Integer", 22 | "1", 23 | engines="gecko", 24 | spec="Internal-only (for `` pres attr)", 25 | animation_type="none", 26 | enabled_in="", 27 | affects="layout", 28 | )} 29 | -------------------------------------------------------------------------------- /style_traits/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "stylo_traits" 3 | version = "0.0.1" 4 | authors = ["The Servo Project Developers"] 5 | license = "MPL-2.0" 6 | repository = "https://github.com/servo/stylo" 7 | edition = "2021" 8 | publish = false 9 | 10 | [lib] 11 | name = "style_traits" 12 | path = "lib.rs" 13 | 14 | [features] 15 | servo = ["stylo_atoms", "cssparser/serde", "url", "euclid/serde"] 16 | gecko = [] 17 | 18 | [dependencies] 19 | app_units = "0.7" 20 | bitflags = "2" 21 | cssparser = "0.35" 22 | euclid = "0.22" 23 | malloc_size_of = { path = "../malloc_size_of", package = "stylo_malloc_size_of" } 24 | malloc_size_of_derive = "0.1" 25 | selectors = { path = "../selectors" } 26 | serde = "1.0" 27 | servo_arc = { path = "../servo_arc" } 28 | stylo_atoms = { path = "../stylo_atoms", optional = true } 29 | thin-vec = "0.2" 30 | to_shmem = { path = "../to_shmem" } 31 | to_shmem_derive = { path = "../to_shmem_derive" } 32 | url = { version = "2.5", optional = true } 33 | -------------------------------------------------------------------------------- /style/values/computed/ui.rs: -------------------------------------------------------------------------------- 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 | //! Computed values for UI properties 6 | 7 | use crate::values::computed::color::Color; 8 | use crate::values::computed::image::Image; 9 | use crate::values::computed::Number; 10 | use crate::values::generics::ui as generics; 11 | 12 | pub use crate::values::specified::ui::{ 13 | BoolInteger, CursorKind, Inert, MozTheme, PointerEvents, UserFocus, UserInput, UserSelect, 14 | }; 15 | 16 | /// A computed value for the `cursor` property. 17 | pub type Cursor = generics::GenericCursor; 18 | 19 | /// A computed value for item of `image cursors`. 20 | pub type CursorImage = generics::GenericCursorImage; 21 | 22 | /// A computed value for `scrollbar-color` property. 23 | pub type ScrollbarColor = generics::GenericScrollbarColor; 24 | -------------------------------------------------------------------------------- /style/gecko_bindings/mod.rs: -------------------------------------------------------------------------------- 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 | //! Gecko's C++ bindings, along with some rust helpers to ease its use. 6 | 7 | // FIXME: We allow `improper_ctypes` (for now), because the lint doesn't allow 8 | // foreign structs to have `PhantomData`. We should remove this once the lint 9 | // ignores this case. 10 | 11 | #[allow( 12 | dead_code, 13 | improper_ctypes, 14 | non_camel_case_types, 15 | non_snake_case, 16 | non_upper_case_globals, 17 | missing_docs 18 | )] 19 | // TODO: Remove this when updating bindgen, see 20 | // https://github.com/rust-lang/rust-bindgen/issues/1651 21 | #[cfg_attr(test, allow(deref_nullptr))] 22 | pub mod structs { 23 | include!(concat!(env!("OUT_DIR"), "/gecko/structs.rs")); 24 | } 25 | 26 | pub use self::structs as bindings; 27 | 28 | pub mod sugar; 29 | -------------------------------------------------------------------------------- /style/values/specified/table.rs: -------------------------------------------------------------------------------- 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 | //! Specified types for CSS values related to tables. 6 | 7 | /// Specified values for the `caption-side` property. 8 | /// 9 | /// Note that despite having "physical" names, these are actually interpreted 10 | /// according to the table's writing-mode: Top and Bottom are treated as 11 | /// block-start and -end respectively. 12 | /// 13 | /// https://drafts.csswg.org/css-tables/#propdef-caption-side 14 | #[allow(missing_docs)] 15 | #[derive( 16 | Clone, 17 | Copy, 18 | Debug, 19 | Eq, 20 | FromPrimitive, 21 | MallocSizeOf, 22 | Ord, 23 | Parse, 24 | PartialEq, 25 | PartialOrd, 26 | SpecifiedValueInfo, 27 | ToComputedValue, 28 | ToCss, 29 | ToResolvedValue, 30 | ToShmem, 31 | )] 32 | #[repr(u8)] 33 | pub enum CaptionSide { 34 | Top, 35 | Bottom, 36 | } 37 | -------------------------------------------------------------------------------- /selectors/sink.rs: -------------------------------------------------------------------------------- 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 | //! Small helpers to abstract over different containers. 6 | #![deny(missing_docs)] 7 | 8 | use smallvec::{Array, SmallVec}; 9 | 10 | /// A trait to abstract over a `push` method that may be implemented for 11 | /// different kind of types. 12 | /// 13 | /// Used to abstract over `Array`, `SmallVec` and `Vec`, and also to implement a 14 | /// type which `push` method does only tweak a byte when we only need to check 15 | /// for the presence of something. 16 | pub trait Push { 17 | /// Push a value into self. 18 | fn push(&mut self, value: T); 19 | } 20 | 21 | impl Push for Vec { 22 | fn push(&mut self, value: T) { 23 | Vec::push(self, value); 24 | } 25 | } 26 | 27 | impl Push for SmallVec { 28 | fn push(&mut self, value: A::Item) { 29 | SmallVec::push(self, value); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /servo_arc/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Permission is hereby granted, free of charge, to any 2 | person obtaining a copy of this software and associated 3 | documentation files (the "Software"), to deal in the 4 | Software without restriction, including without 5 | limitation the rights to use, copy, modify, merge, 6 | publish, distribute, sublicense, and/or sell copies of 7 | the Software, and to permit persons to whom the Software 8 | is furnished to do so, subject to the following 9 | conditions: 10 | 11 | The above copyright notice and this permission notice 12 | shall be included in all copies or substantial portions 13 | of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 16 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 17 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 18 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 19 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 20 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 22 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | DEALINGS IN THE SOFTWARE. 24 | -------------------------------------------------------------------------------- /malloc_size_of/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Permission is hereby granted, free of charge, to any 2 | person obtaining a copy of this software and associated 3 | documentation files (the "Software"), to deal in the 4 | Software without restriction, including without 5 | limitation the rights to use, copy, modify, merge, 6 | publish, distribute, sublicense, and/or sell copies of 7 | the Software, and to permit persons to whom the Software 8 | is furnished to do so, subject to the following 9 | conditions: 10 | 11 | The above copyright notice and this permission notice 12 | shall be included in all copies or substantial portions 13 | of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 16 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 17 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 18 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 19 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 20 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 22 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | DEALINGS IN THE SOFTWARE. 24 | -------------------------------------------------------------------------------- /stylo_atoms/build.rs: -------------------------------------------------------------------------------- 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 | use std::env; 6 | use std::fs::File; 7 | use std::io::{BufRead, BufReader}; 8 | use std::path::Path; 9 | 10 | fn main() { 11 | let static_atoms = 12 | Path::new(&env::var_os("CARGO_MANIFEST_DIR").unwrap()).join("static_atoms.txt"); 13 | let static_atoms = BufReader::new(File::open(&static_atoms).unwrap()); 14 | let mut atom_type = string_cache_codegen::AtomType::new("Atom", "atom!"); 15 | 16 | macro_rules! predefined { 17 | ($($name: expr,)+) => { 18 | { 19 | $( 20 | atom_type.atom($name); 21 | )+ 22 | } 23 | } 24 | } 25 | include!("./predefined_counter_styles.rs"); 26 | 27 | atom_type 28 | .atoms(static_atoms.lines().map(Result::unwrap)) 29 | .write_to_file(&Path::new(&env::var_os("OUT_DIR").unwrap()).join("atom.rs")) 30 | .unwrap(); 31 | } 32 | -------------------------------------------------------------------------------- /style/gecko_bindings/sugar/origin_flags.rs: -------------------------------------------------------------------------------- 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 | //! Helper to iterate over `OriginFlags` bits. 6 | 7 | use crate::gecko_bindings::structs::OriginFlags; 8 | use crate::stylesheets::OriginSet; 9 | 10 | /// Checks that the values for OriginFlags are the ones we expect. 11 | pub fn assert_flags_match() { 12 | use crate::stylesheets::origin::*; 13 | debug_assert_eq!( 14 | OriginFlags::UserAgent.0, 15 | OriginSet::ORIGIN_USER_AGENT.bits() 16 | ); 17 | debug_assert_eq!(OriginFlags::Author.0, OriginSet::ORIGIN_AUTHOR.bits()); 18 | debug_assert_eq!(OriginFlags::User.0, OriginSet::ORIGIN_USER.bits()); 19 | } 20 | 21 | impl From for OriginSet { 22 | fn from(flags: OriginFlags) -> Self { 23 | Self::from_bits_retain(flags.0) 24 | } 25 | } 26 | 27 | impl From for OriginFlags { 28 | fn from(set: OriginSet) -> Self { 29 | OriginFlags(set.bits()) 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /selectors/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "selectors" 3 | version = "0.26.0" 4 | authors = ["The Servo Project Developers"] 5 | documentation = "https://docs.rs/selectors/" 6 | description = "CSS Selectors matching for Rust" 7 | repository = "https://github.com/servo/stylo" 8 | readme = "README.md" 9 | keywords = ["css", "selectors"] 10 | license = "MPL-2.0" 11 | edition = "2021" 12 | build = "build.rs" 13 | 14 | [lib] 15 | name = "selectors" 16 | path = "lib.rs" 17 | 18 | [features] 19 | bench = [] 20 | to_shmem = ["dep:to_shmem", "dep:to_shmem_derive"] 21 | 22 | [dependencies] 23 | bitflags = "2" 24 | cssparser = "0.35" 25 | derive_more = { version = "0.99", default-features = false, features = ["add", "add_assign"] } 26 | fxhash = "0.2" 27 | log = "0.4" 28 | phf = "0.11" 29 | precomputed-hash = "0.1" 30 | servo_arc = { version = "0.4", path = "../servo_arc" } 31 | smallvec = "1.0" 32 | to_shmem = { version = "0.1", path = "../to_shmem", features = ["servo_arc"], optional = true } 33 | to_shmem_derive = { version = "0.1", path = "../to_shmem_derive", optional = true } 34 | new_debug_unreachable = "1" 35 | 36 | [build-dependencies] 37 | phf_codegen = "0.11" 38 | -------------------------------------------------------------------------------- /style/values/generics/column.rs: -------------------------------------------------------------------------------- 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 | //! Generic types for the column properties. 6 | 7 | /// A generic type for `column-count` values. 8 | #[derive( 9 | Animate, 10 | Clone, 11 | ComputeSquaredDistance, 12 | Copy, 13 | Debug, 14 | MallocSizeOf, 15 | Parse, 16 | PartialEq, 17 | SpecifiedValueInfo, 18 | ToAnimatedValue, 19 | ToAnimatedZero, 20 | ToComputedValue, 21 | ToCss, 22 | ToResolvedValue, 23 | ToShmem, 24 | )] 25 | #[repr(u8)] 26 | pub enum GenericColumnCount { 27 | /// A positive integer. 28 | Integer(PositiveInteger), 29 | /// The keyword `auto`. 30 | #[animation(error)] 31 | Auto, 32 | } 33 | 34 | pub use self::GenericColumnCount as ColumnCount; 35 | impl ColumnCount { 36 | /// Returns whether this value is `auto`. 37 | #[inline] 38 | pub fn is_auto(self) -> bool { 39 | matches!(self, ColumnCount::Auto) 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /style/properties/properties.html.mako: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Supported CSS properties in Servo 7 | 8 | 9 | 10 | 11 | 12 |
13 |

CSS properties currently supported in Servo

14 | % for kind, props in sorted(properties.items()): 15 |

${kind.capitalize()}

16 | 17 | 18 | 19 | 20 | 21 | % for name, data in sorted(props.items()): 22 | 23 | 24 | 25 | 26 | % endfor 27 |
NamePref
${name}${data['pref'] or ''}
28 | % endfor 29 |
30 | 31 | 32 | -------------------------------------------------------------------------------- /to_shmem/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "to_shmem" 3 | version = "0.1.0" 4 | authors = ["The Servo Project Developers"] 5 | license = "MPL-2.0" 6 | repository = "https://github.com/servo/stylo" 7 | edition = "2021" 8 | description = "Trait to write to a contiguous chunk of shared memory" 9 | 10 | [lib] 11 | name = "to_shmem" 12 | path = "lib.rs" 13 | 14 | [features] 15 | servo = ["cssparser/serde", "cssparser", "servo_arc", "smallbitvec", "smallvec", "string_cache", "thin-vec"] 16 | gecko = ["thin-vec/gecko-ffi", "cssparser", "servo_arc", "smallbitvec", "smallvec", "thin-vec"] 17 | 18 | cssparser = ["dep:cssparser"] 19 | servo_arc = ["dep:servo_arc"] 20 | smallbitvec = ["dep:smallbitvec"] 21 | smallvec = ["dep:smallvec"] 22 | string_cache = ["dep:string_cache"] 23 | thin-vec = ["dep:thin-vec"] 24 | 25 | [dependencies] 26 | cssparser = { version = "0.35", optional = true } 27 | servo_arc = { version = "0.4.0", path = "../servo_arc", optional = true } 28 | smallbitvec = { version = "2.3.0", optional = true } 29 | smallvec = { version = "1.13", optional = true } 30 | string_cache = { version = "0.8", optional = true } 31 | thin-vec = { version = "0.2.1", optional = true } 32 | -------------------------------------------------------------------------------- /style/values/specified/ratio.rs: -------------------------------------------------------------------------------- 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 | //! Specified types for . 6 | //! 7 | //! [ratio]: https://drafts.csswg.org/css-values/#ratios 8 | 9 | use crate::parser::{Parse, ParserContext}; 10 | use crate::values::generics::ratio::Ratio as GenericRatio; 11 | use crate::values::specified::NonNegativeNumber; 12 | use crate::One; 13 | use cssparser::Parser; 14 | use style_traits::ParseError; 15 | 16 | /// A specified value. 17 | pub type Ratio = GenericRatio; 18 | 19 | impl Parse for Ratio { 20 | fn parse<'i, 't>( 21 | context: &ParserContext, 22 | input: &mut Parser<'i, 't>, 23 | ) -> Result> { 24 | let a = NonNegativeNumber::parse(context, input)?; 25 | let b = match input.try_parse(|input| input.expect_delim('/')) { 26 | Ok(()) => NonNegativeNumber::parse(context, input)?, 27 | _ => One::one(), 28 | }; 29 | 30 | Ok(GenericRatio(a, b)) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /style/values/computed/counters.rs: -------------------------------------------------------------------------------- 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 | //! Computed values for counter properties 6 | 7 | use crate::values::computed::image::Image; 8 | use crate::values::generics::counters as generics; 9 | use crate::values::generics::counters::CounterIncrement as GenericCounterIncrement; 10 | use crate::values::generics::counters::CounterReset as GenericCounterReset; 11 | use crate::values::generics::counters::CounterSet as GenericCounterSet; 12 | 13 | /// A computed value for the `counter-increment` property. 14 | pub type CounterIncrement = GenericCounterIncrement; 15 | 16 | /// A computed value for the `counter-reset` property. 17 | pub type CounterReset = GenericCounterReset; 18 | 19 | /// A computed value for the `counter-set` property. 20 | pub type CounterSet = GenericCounterSet; 21 | 22 | /// A computed value for the `content` property. 23 | pub type Content = generics::GenericContent; 24 | 25 | /// A computed content item. 26 | pub type ContentItem = generics::GenericContentItem; 27 | -------------------------------------------------------------------------------- /stylo_static_prefs/src/lib.rs: -------------------------------------------------------------------------------- 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 | //! A list of static preferences exposed to the style crate. These should 6 | //! be kept sync with the preferences used by the style. 7 | #[macro_export] 8 | macro_rules! pref { 9 | ("layout.css.stylo-local-work-queue.in-main-thread") => { 10 | 32 11 | }; 12 | ("layout.css.stylo-work-unit-size") => { 13 | 16 14 | }; 15 | ("layout.css.stylo-local-work-queue.in-worker") => { 16 | 0 17 | }; 18 | ("layout.css.system-ui.enabled") => { 19 | true 20 | }; 21 | ("layout.css.basic-shape-rect.enabled") => { 22 | true 23 | }; 24 | ("layout.css.basic-shape-xywh.enabled") => { 25 | true 26 | }; 27 | ("layout.css.relative-color-syntax.enabled") => { 28 | true 29 | }; 30 | ("layout.css.stretch-size-keyword.enabled") => { 31 | true 32 | }; 33 | ("layout.css.transition-behavior.enabled") => { 34 | true 35 | }; 36 | ($string:literal) => { 37 | false 38 | }; 39 | } 40 | -------------------------------------------------------------------------------- /selectors/README.md: -------------------------------------------------------------------------------- 1 | rust-selectors 2 | ============== 3 | 4 | * [![Build Status](https://travis-ci.com/servo/rust-selectors.svg?branch=master)]( 5 | https://travis-ci.com/servo/rust-selectors) 6 | * [Documentation](https://docs.rs/selectors/) 7 | * [crates.io](https://crates.io/crates/selectors) 8 | 9 | CSS Selectors library for Rust. 10 | Includes parsing and serilization of selectors, 11 | as well as matching against a generic tree of elements. 12 | Pseudo-elements and most pseudo-classes are generic as well. 13 | 14 | **Warning:** breaking changes are made to this library fairly frequently 15 | (13 times in 2016, for example). 16 | However you can use this crate without updating it that often, 17 | old versions stay available on crates.io and Cargo will only automatically update 18 | to versions that are numbered as compatible. 19 | 20 | To see how to use this library with your own tree representation, 21 | see [Kuchiki’s `src/select.rs`](https://github.com/kuchiki-rs/kuchiki/blob/master/src/select.rs). 22 | (Note however that Kuchiki is not always up to date with the latest rust-selectors version, 23 | so that code may need to be tweaked.) 24 | If you don’t already have a tree data structure, 25 | consider using [Kuchiki](https://github.com/kuchiki-rs/kuchiki) itself. 26 | -------------------------------------------------------------------------------- /style/counter_style/update_predefined.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # This Source Code Form is subject to the terms of the Mozilla Public 4 | # License, v. 2.0. If a copy of the MPL was not distributed with this 5 | # file, You can obtain one at https://mozilla.org/MPL/2.0/. */ 6 | 7 | from os.path import join, dirname 8 | import re 9 | from urllib.request import urlopen 10 | 11 | 12 | def main(filename): 13 | names = [ 14 | re.search('>([^>]+)(|
3 | set -eu 4 | 5 | root=$(pwd) 6 | mkdir -p "$1" 7 | cd -- "$1" 8 | filtered=$(pwd) 9 | mkdir -p "$root/_cache" 10 | cd "$root/_cache" 11 | export PATH="$PWD:$PATH" 12 | 13 | step() { 14 | if [ "${TERM-}" != '' ]; then 15 | tput setaf 12 16 | fi 17 | >&2 printf '* %s\n' "$*" 18 | if [ "${TERM-}" != '' ]; then 19 | tput sgr0 20 | fi 21 | } 22 | 23 | step Downloading git-filter-repo if needed 24 | if ! git filter-repo --version 2> /dev/null; then 25 | curl -O https://raw.githubusercontent.com/newren/git-filter-repo/v2.38.0/git-filter-repo 26 | chmod +x git-filter-repo 27 | 28 | git filter-repo --version 29 | fi 30 | 31 | step Cloning upstream if needed 32 | if ! [ -e upstream ]; then 33 | git clone --bare --single-branch --progress https://github.com/mozilla/gecko-dev.git upstream 34 | fi 35 | 36 | step Updating upstream 37 | branch=$(git -C upstream rev-parse --abbrev-ref HEAD) 38 | git -C upstream fetch origin $branch:$branch 39 | 40 | step Filtering upstream 41 | # Cloning and filtering is much faster than git filter-repo --source --target. 42 | git clone --bare upstream -- "$filtered" 43 | git -C "$filtered" filter-repo --force --paths-from-file "$root/style.paths" 44 | -------------------------------------------------------------------------------- /style/values/generics/url.rs: -------------------------------------------------------------------------------- 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 | //! Generic types for url properties. 6 | 7 | /// An image url or none, used for example in list-style-image 8 | #[derive( 9 | Animate, 10 | Clone, 11 | ComputeSquaredDistance, 12 | Debug, 13 | MallocSizeOf, 14 | PartialEq, 15 | Parse, 16 | SpecifiedValueInfo, 17 | ToAnimatedValue, 18 | ToAnimatedZero, 19 | ToComputedValue, 20 | ToCss, 21 | ToResolvedValue, 22 | ToShmem, 23 | )] 24 | #[repr(C, u8)] 25 | pub enum GenericUrlOrNone { 26 | /// `none` 27 | None, 28 | /// A URL. 29 | Url(U), 30 | } 31 | 32 | pub use self::GenericUrlOrNone as UrlOrNone; 33 | 34 | impl UrlOrNone { 35 | /// Initial "none" value for properties such as `list-style-image` 36 | pub fn none() -> Self { 37 | UrlOrNone::None 38 | } 39 | 40 | /// Returns whether the value is `none`. 41 | pub fn is_none(&self) -> bool { 42 | match *self { 43 | UrlOrNone::None => true, 44 | UrlOrNone::Url(..) => false, 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /style/values/animated/effects.rs: -------------------------------------------------------------------------------- 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 | //! Animated types for CSS values related to effects. 6 | 7 | use crate::values::animated::color::Color; 8 | use crate::values::computed::length::Length; 9 | #[cfg(feature = "gecko")] 10 | use crate::values::computed::url::ComputedUrl; 11 | use crate::values::computed::{Angle, Number}; 12 | use crate::values::generics::effects::Filter as GenericFilter; 13 | use crate::values::generics::effects::SimpleShadow as GenericSimpleShadow; 14 | #[cfg(not(feature = "gecko"))] 15 | use crate::values::Impossible; 16 | 17 | /// An animated value for the `drop-shadow()` filter. 18 | pub type AnimatedSimpleShadow = GenericSimpleShadow; 19 | 20 | /// An animated value for a single `filter`. 21 | #[cfg(feature = "gecko")] 22 | pub type AnimatedFilter = 23 | GenericFilter; 24 | 25 | /// An animated value for a single `filter`. 26 | #[cfg(not(feature = "gecko"))] 27 | pub type AnimatedFilter = GenericFilter; 28 | -------------------------------------------------------------------------------- /style_traits/dom.rs: -------------------------------------------------------------------------------- 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 access the DOM from style calculation. 6 | 7 | /// An opaque handle to a node, which, unlike UnsafeNode, cannot be transformed 8 | /// back into a non-opaque representation. The only safe operation that can be 9 | /// performed on this node is to compare it to another opaque handle or to another 10 | /// OpaqueNode. 11 | /// 12 | /// Layout and Graphics use this to safely represent nodes for comparison purposes. 13 | /// Because the script task's GC does not trace layout, node data cannot be safely stored in layout 14 | /// data structures. Also, layout code tends to be faster when the DOM is not being accessed, for 15 | /// locality reasons. Using `OpaqueNode` enforces this invariant. 16 | #[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, PartialEq)] 17 | #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] 18 | pub struct OpaqueNode(pub usize); 19 | 20 | impl OpaqueNode { 21 | /// Returns the address of this node, for debugging purposes. 22 | #[inline] 23 | pub fn id(&self) -> usize { 24 | self.0 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /style/stylesheets/loader.rs: -------------------------------------------------------------------------------- 1 | /* This Source Code Form is subject to the terms of the Mozilla Public 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this 3 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ 4 | 5 | //! The stylesheet loader is the abstraction used to trigger network requests 6 | //! for `@import` rules. 7 | 8 | use crate::media_queries::MediaList; 9 | use crate::parser::ParserContext; 10 | use crate::shared_lock::{Locked, SharedRwLock}; 11 | use crate::stylesheets::import_rule::{ImportLayer, ImportRule, ImportSupportsCondition}; 12 | use crate::values::CssUrl; 13 | use cssparser::SourceLocation; 14 | use servo_arc::Arc; 15 | 16 | /// The stylesheet loader is the abstraction used to trigger network requests 17 | /// for `@import` rules. 18 | pub trait StylesheetLoader { 19 | /// Request a stylesheet after parsing a given `@import` rule, and return 20 | /// the constructed `@import` rule. 21 | fn request_stylesheet( 22 | &self, 23 | url: CssUrl, 24 | location: SourceLocation, 25 | context: &ParserContext, 26 | lock: &SharedRwLock, 27 | media: Arc>, 28 | supports: Option, 29 | layer: ImportLayer, 30 | ) -> Arc>; 31 | } 32 | -------------------------------------------------------------------------------- /style_derive/to_animated_value.rs: -------------------------------------------------------------------------------- 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 | use proc_macro2::TokenStream; 6 | use syn::DeriveInput; 7 | use synstructure::BindStyle; 8 | use crate::to_computed_value; 9 | 10 | pub fn derive(input: DeriveInput) -> TokenStream { 11 | let trait_impl = |from_body, to_body| { 12 | quote! { 13 | #[inline] 14 | fn from_animated_value(from: Self::AnimatedValue) -> Self { 15 | #from_body 16 | } 17 | 18 | #[inline] 19 | fn to_animated_value(self, context: &crate::values::animated::Context) -> Self::AnimatedValue { 20 | #to_body 21 | } 22 | } 23 | }; 24 | 25 | to_computed_value::derive_to_value( 26 | input, 27 | parse_quote!(crate::values::animated::ToAnimatedValue), 28 | parse_quote!(AnimatedValue), 29 | BindStyle::Move, 30 | |_| Default::default(), 31 | |binding| quote!(crate::values::animated::ToAnimatedValue::from_animated_value(#binding)), 32 | |binding| quote!(crate::values::animated::ToAnimatedValue::to_animated_value(#binding, context)), 33 | trait_impl, 34 | ) 35 | } 36 | -------------------------------------------------------------------------------- /style/values/resolved/animation.rs: -------------------------------------------------------------------------------- 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 | //! Resolved animation values. 6 | 7 | use super::{Context, ToResolvedValue}; 8 | 9 | use crate::values::computed::time::Time; 10 | use crate::values::computed::AnimationDuration; 11 | 12 | impl ToResolvedValue for AnimationDuration { 13 | type ResolvedValue = Self; 14 | 15 | fn to_resolved_value(self, context: &Context) -> Self::ResolvedValue { 16 | match self { 17 | // For backwards-compatibility with Level 1, when the computed value of 18 | // animation-timeline is auto (i.e. only one list value, and that value being auto), 19 | // the resolved value of auto for animation-duration is 0s whenever its used value 20 | // would also be 0s. 21 | // https://drafts.csswg.org/css-animations-2/#animation-duration 22 | Self::Auto if context.style.get_ui().has_initial_animation_timeline() => { 23 | Self::Time(Time::from_seconds(0.0f32)) 24 | }, 25 | _ => self, 26 | } 27 | } 28 | 29 | #[inline] 30 | fn from_resolved_value(value: Self::ResolvedValue) -> Self { 31 | value 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: ["main"] 6 | pull_request: 7 | workflow_dispatch: 8 | merge_group: 9 | types: [checks_requested] 10 | 11 | 12 | jobs: 13 | linux-debug: 14 | name: Linux (Debug) 15 | runs-on: ubuntu-latest 16 | steps: 17 | - uses: actions/checkout@v4 18 | - name: Install Rust 19 | uses: dtolnay/rust-toolchain@stable 20 | - name: Run Tests 21 | run: cargo build --features servo 22 | env: 23 | RUST_BACKTRACE: 1 24 | 25 | linux-release: 26 | name: Linux (Release) 27 | runs-on: ubuntu-latest 28 | steps: 29 | - uses: actions/checkout@v4 30 | - name: Install Rust 31 | uses: dtolnay/rust-toolchain@stable 32 | - name: Run Tests 33 | run: cargo build --release --features servo 34 | env: 35 | RUST_BACKTRACE: 1 36 | 37 | build-result: 38 | name: Result 39 | runs-on: ubuntu-latest 40 | if: ${{ always() }} 41 | needs: 42 | - linux-debug 43 | - linux-release 44 | steps: 45 | - name: Success 46 | if: ${{ !contains(needs.*.result, 'failure') && !contains(needs.*.result, 'cancelled') }} 47 | run: exit 0 48 | - name: Failure 49 | if: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }} 50 | run: exit 1 51 | 52 | -------------------------------------------------------------------------------- /style/gecko/values.rs: -------------------------------------------------------------------------------- 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 | //! Different kind of helpers to interact with Gecko values. 8 | 9 | use crate::color::{AbsoluteColor, ColorSpace}; 10 | 11 | /// Convert a color value to `nscolor`. 12 | pub fn convert_absolute_color_to_nscolor(color: &AbsoluteColor) -> u32 { 13 | let srgb = color.to_color_space(ColorSpace::Srgb); 14 | u32::from_le_bytes([ 15 | (srgb.components.0 * 255.0).round() as u8, 16 | (srgb.components.1 * 255.0).round() as u8, 17 | (srgb.components.2 * 255.0).round() as u8, 18 | (srgb.alpha * 255.0).round() as u8, 19 | ]) 20 | } 21 | 22 | /// Convert a given `nscolor` to a Servo AbsoluteColor value. 23 | pub fn convert_nscolor_to_absolute_color(color: u32) -> AbsoluteColor { 24 | let [r, g, b, a] = color.to_le_bytes(); 25 | AbsoluteColor::srgb_legacy(r, g, b, a as f32 / 255.0) 26 | } 27 | 28 | #[test] 29 | fn convert_ns_color_to_absolute_color_should_be_in_legacy_syntax() { 30 | use crate::color::ColorFlags; 31 | 32 | let result = convert_nscolor_to_absolute_color(0x336699CC); 33 | assert!(result.flags.contains(ColorFlags::IS_LEGACY_SRGB)); 34 | 35 | assert!(result.is_legacy_syntax()); 36 | } 37 | -------------------------------------------------------------------------------- /style/properties/shorthands/inherited_svg.mako.rs: -------------------------------------------------------------------------------- 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 | <%namespace name="helpers" file="/helpers.mako.rs" /> 6 | 7 | <%helpers:shorthand 8 | name="marker" 9 | engines="gecko" 10 | sub_properties="marker-start marker-end marker-mid" 11 | spec="https://svgwg.org/svg2-draft/painting.html#MarkerShorthand" 12 | > 13 | use crate::values::specified::url::UrlOrNone; 14 | 15 | pub fn parse_value<'i, 't>( 16 | context: &ParserContext, 17 | input: &mut Parser<'i, 't>, 18 | ) -> Result> { 19 | use crate::parser::Parse; 20 | let url = UrlOrNone::parse(context, input)?; 21 | 22 | Ok(expanded! { 23 | marker_start: url.clone(), 24 | marker_mid: url.clone(), 25 | marker_end: url, 26 | }) 27 | } 28 | 29 | impl<'a> ToCss for LonghandsToSerialize<'a> { 30 | fn to_css(&self, dest: &mut CssWriter) -> fmt::Result where W: fmt::Write { 31 | if self.marker_start == self.marker_mid && self.marker_mid == self.marker_end { 32 | self.marker_start.to_css(dest) 33 | } else { 34 | Ok(()) 35 | } 36 | } 37 | } 38 | 39 | -------------------------------------------------------------------------------- /style/values/computed/time.rs: -------------------------------------------------------------------------------- 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 | //! Computed time values. 6 | 7 | use crate::values::CSSFloat; 8 | use crate::Zero; 9 | use std::fmt::{self, Write}; 10 | use style_traits::{CssWriter, ToCss}; 11 | 12 | /// A computed `(input: &DeriveInput) -> A 12 | where 13 | A: FromDeriveInput, 14 | { 15 | match A::from_derive_input(input) { 16 | Ok(attrs) => attrs, 17 | Err(e) => panic!("failed to parse input attributes: {}", e), 18 | } 19 | } 20 | 21 | pub(crate) fn parse_field_attrs(field: &Field) -> A 22 | where 23 | A: FromField, 24 | { 25 | match A::from_field(field) { 26 | Ok(attrs) => attrs, 27 | Err(e) => panic!("failed to parse field attributes: {}", e), 28 | } 29 | } 30 | 31 | pub(crate) fn add_predicate(where_clause: &mut Option, pred: WherePredicate) { 32 | where_clause 33 | .get_or_insert(parse_quote!(where)) 34 | .predicates 35 | .push(pred); 36 | } 37 | 38 | pub(crate) fn fmap2_match( 39 | input: &DeriveInput, 40 | bind_style: BindStyle, 41 | mut f: F, 42 | mut g: G, 43 | ) -> TokenStream 44 | where 45 | F: FnMut(&BindingInfo) -> TokenStream, 46 | G: FnMut(&BindingInfo) -> Option, 47 | { 48 | let mut s = synstructure::Structure::new(input); 49 | s.variants_mut().iter_mut().for_each(|v| { 50 | v.bind_with(|_| bind_style); 51 | }); 52 | s.each_variant(|variant| { 53 | let (mapped, mapped_fields) = value(variant, "mapped"); 54 | let fields_pairs = variant.bindings().iter().zip(mapped_fields.iter()); 55 | let mut computations = quote!(); 56 | computations.append_all(fields_pairs.map(|(field, mapped_field)| { 57 | let expr = f(field); 58 | quote! { let #mapped_field = #expr; } 59 | })); 60 | computations.append_all( 61 | mapped_fields 62 | .iter() 63 | .map(|mapped_field| match g(mapped_field) { 64 | Some(expr) => quote! { let #mapped_field = #expr; }, 65 | None => quote!(), 66 | }), 67 | ); 68 | computations.append_all(mapped); 69 | Some(computations) 70 | }) 71 | } 72 | 73 | fn value<'a>(variant: &'a VariantInfo, prefix: &str) -> (TokenStream, Vec>) { 74 | let mut v = variant.clone(); 75 | v.bindings_mut().iter_mut().for_each(|b| { 76 | b.binding = Ident::new(&format!("{}_{}", b.binding, prefix), Span::call_site()) 77 | }); 78 | v.bind_with(|_| BindStyle::Move); 79 | (v.pat(), v.bindings().to_vec()) 80 | } 81 | -------------------------------------------------------------------------------- /style/properties/longhands/column.mako.rs: -------------------------------------------------------------------------------- 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 | <%namespace name="helpers" file="/helpers.mako.rs" /> 6 | 7 | ${helpers.predefined_type( 8 | "column-width", 9 | "length::NonNegativeLengthOrAuto", 10 | "computed::length::NonNegativeLengthOrAuto::auto()", 11 | engines="gecko servo", 12 | initial_specified_value="specified::length::NonNegativeLengthOrAuto::auto()", 13 | servo_pref="layout.columns.enabled", 14 | spec="https://drafts.csswg.org/css-multicol/#propdef-column-width", 15 | servo_restyle_damage="rebuild_and_reflow", 16 | affects="layout", 17 | )} 18 | 19 | ${helpers.predefined_type( 20 | "column-count", 21 | "ColumnCount", 22 | "computed::ColumnCount::Auto", 23 | engines="gecko servo", 24 | initial_specified_value="specified::ColumnCount::Auto", 25 | servo_pref="layout.columns.enabled", 26 | spec="https://drafts.csswg.org/css-multicol/#propdef-column-count", 27 | servo_restyle_damage="rebuild_and_reflow", 28 | affects="layout", 29 | )} 30 | 31 | ${helpers.single_keyword( 32 | "column-fill", 33 | "balance auto", 34 | engines="gecko", 35 | animation_type="discrete", 36 | gecko_enum_prefix="StyleColumnFill", 37 | spec="https://drafts.csswg.org/css-multicol/#propdef-column-fill", 38 | affects="layout", 39 | )} 40 | 41 | ${helpers.predefined_type( 42 | "column-rule-width", 43 | "BorderSideWidth", 44 | "app_units::Au::from_px(3)", 45 | engines="gecko", 46 | initial_specified_value="specified::BorderSideWidth::medium()", 47 | spec="https://drafts.csswg.org/css-multicol/#propdef-column-rule-width", 48 | affects="layout", 49 | )} 50 | 51 | // https://drafts.csswg.org/css-multicol-1/#crc 52 | ${helpers.predefined_type( 53 | "column-rule-color", 54 | "Color", 55 | "computed_value::T::currentcolor()", 56 | engines="gecko", 57 | initial_specified_value="specified::Color::currentcolor()", 58 | ignored_when_colors_disabled=True, 59 | spec="https://drafts.csswg.org/css-multicol/#propdef-column-rule-color", 60 | affects="paint", 61 | )} 62 | 63 | ${helpers.single_keyword( 64 | "column-span", 65 | "none all", 66 | engines="gecko servo", 67 | servo_pref="layout.columns.enabled", 68 | animation_type="discrete", 69 | gecko_enum_prefix="StyleColumnSpan", 70 | spec="https://drafts.csswg.org/css-multicol/#propdef-column-span", 71 | affects="layout", 72 | )} 73 | 74 | ${helpers.predefined_type( 75 | "column-rule-style", 76 | "BorderStyle", 77 | "computed::BorderStyle::None", 78 | engines="gecko", 79 | initial_specified_value="specified::BorderStyle::None", 80 | animation_type="discrete", 81 | spec="https://drafts.csswg.org/css-multicol/#propdef-column-rule-style", 82 | affects="paint", 83 | )} 84 | -------------------------------------------------------------------------------- /style/values/computed/page.rs: -------------------------------------------------------------------------------- 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 | //! Computed @page at-rule properties and named-page style properties 6 | 7 | use crate::values::computed::length::NonNegativeLength; 8 | use crate::values::computed::{Context, ToComputedValue}; 9 | use crate::values::generics; 10 | use crate::values::generics::size::Size2D; 11 | 12 | use crate::values::specified::page as specified; 13 | pub use generics::page::GenericPageSize; 14 | pub use generics::page::PageOrientation; 15 | pub use generics::page::PageSizeOrientation; 16 | pub use generics::page::PaperSize; 17 | pub use specified::PageName; 18 | 19 | /// Computed value of the @page size descriptor 20 | /// 21 | /// The spec says that the computed value should be the same as the specified 22 | /// value but with all absolute units, but it's not currently possibly observe 23 | /// the computed value of page-size. 24 | #[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToCss, ToResolvedValue, ToShmem)] 25 | #[repr(C, u8)] 26 | pub enum PageSize { 27 | /// Specified size, paper size, or paper size and orientation. 28 | Size(Size2D), 29 | /// `landscape` or `portrait` value, no specified size. 30 | Orientation(PageSizeOrientation), 31 | /// `auto` value 32 | Auto, 33 | } 34 | 35 | impl ToComputedValue for specified::PageSize { 36 | type ComputedValue = PageSize; 37 | 38 | fn to_computed_value(&self, ctx: &Context) -> Self::ComputedValue { 39 | match &*self { 40 | Self::Size(s) => PageSize::Size(s.to_computed_value(ctx)), 41 | Self::PaperSize(p, PageSizeOrientation::Landscape) => PageSize::Size(Size2D { 42 | width: p.long_edge().to_computed_value(ctx), 43 | height: p.short_edge().to_computed_value(ctx), 44 | }), 45 | Self::PaperSize(p, PageSizeOrientation::Portrait) => PageSize::Size(Size2D { 46 | width: p.short_edge().to_computed_value(ctx), 47 | height: p.long_edge().to_computed_value(ctx), 48 | }), 49 | Self::Orientation(o) => PageSize::Orientation(*o), 50 | Self::Auto => PageSize::Auto, 51 | } 52 | } 53 | 54 | fn from_computed_value(computed: &Self::ComputedValue) -> Self { 55 | match *computed { 56 | PageSize::Size(s) => Self::Size(ToComputedValue::from_computed_value(&s)), 57 | PageSize::Orientation(o) => Self::Orientation(o), 58 | PageSize::Auto => Self::Auto, 59 | } 60 | } 61 | } 62 | 63 | impl PageSize { 64 | /// `auto` value. 65 | #[inline] 66 | pub fn auto() -> Self { 67 | PageSize::Auto 68 | } 69 | 70 | /// Whether this is the `auto` value. 71 | #[inline] 72 | pub fn is_auto(&self) -> bool { 73 | matches!(*self, PageSize::Auto) 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /to_shmem_derive/to_shmem.rs: -------------------------------------------------------------------------------- 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 | use crate::util::{add_predicate, fmap2_match, parse_field_attrs, parse_input_attrs}; 6 | use darling::{FromDeriveInput, FromField}; 7 | use proc_macro2::TokenStream; 8 | use quote::quote; 9 | use syn::{self, parse_quote}; 10 | use synstructure::{BindStyle, Structure}; 11 | 12 | pub fn derive(mut input: syn::DeriveInput) -> TokenStream { 13 | let mut where_clause = input.generics.where_clause.take(); 14 | let attrs = parse_input_attrs::(&input); 15 | if !attrs.no_bounds { 16 | for param in input.generics.type_params() { 17 | add_predicate(&mut where_clause, parse_quote!(#param: ::to_shmem::ToShmem)); 18 | } 19 | } 20 | for variant in Structure::new(&input).variants() { 21 | for binding in variant.bindings() { 22 | let attrs = parse_field_attrs::(&binding.ast()); 23 | if attrs.field_bound { 24 | let ty = &binding.ast().ty; 25 | add_predicate(&mut where_clause, parse_quote!(#ty: ::to_shmem::ToShmem)) 26 | } 27 | } 28 | } 29 | 30 | input.generics.where_clause = where_clause; 31 | 32 | // Do all of the `to_shmem()?` calls before the `ManuallyDrop::into_inner()` 33 | // calls, so that we don't drop a value in the shared memory buffer if one 34 | // of the `to_shmem`s fails. 35 | let match_body = fmap2_match( 36 | &input, 37 | BindStyle::Ref, 38 | |binding| { 39 | quote! { 40 | ::to_shmem::ToShmem::to_shmem(#binding, builder)? 41 | } 42 | }, 43 | |binding| { 44 | Some(quote! { 45 | ::std::mem::ManuallyDrop::into_inner(#binding) 46 | }) 47 | }, 48 | ); 49 | 50 | let name = &input.ident; 51 | let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl(); 52 | 53 | quote! { 54 | impl #impl_generics ::to_shmem::ToShmem for #name #ty_generics #where_clause { 55 | #[allow(unused_variables, unreachable_code)] 56 | fn to_shmem( 57 | &self, 58 | builder: &mut ::to_shmem::SharedMemoryBuilder, 59 | ) -> ::to_shmem::Result { 60 | Ok(::std::mem::ManuallyDrop::new( 61 | match *self { 62 | #match_body 63 | } 64 | )) 65 | } 66 | } 67 | } 68 | } 69 | 70 | #[derive(Default, FromDeriveInput)] 71 | #[darling(attributes(shmem), default)] 72 | pub struct ShmemInputAttrs { 73 | pub no_bounds: bool, 74 | } 75 | 76 | #[derive(Default, FromField)] 77 | #[darling(attributes(shmem), default)] 78 | pub struct ShmemFieldAttrs { 79 | pub field_bound: bool, 80 | } 81 | -------------------------------------------------------------------------------- /style/gecko_string_cache/namespace.rs: -------------------------------------------------------------------------------- 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 | //! A type to represent a namespace. 6 | 7 | use crate::gecko_bindings::structs::nsAtom; 8 | use crate::string_cache::{Atom, WeakAtom}; 9 | use precomputed_hash::PrecomputedHash; 10 | use std::borrow::Borrow; 11 | use std::fmt; 12 | use std::ops::Deref; 13 | 14 | /// In Gecko namespaces are just regular atoms, so this is a simple macro to 15 | /// forward one macro to the other. 16 | #[macro_export] 17 | macro_rules! ns { 18 | () => { 19 | $crate::string_cache::Namespace(atom!("")) 20 | }; 21 | ($s:tt) => { 22 | $crate::string_cache::Namespace(atom!($s)) 23 | }; 24 | } 25 | 26 | /// A Gecko namespace is just a wrapped atom. 27 | #[derive( 28 | Clone, 29 | Debug, 30 | Default, 31 | Eq, 32 | Hash, 33 | MallocSizeOf, 34 | PartialEq, 35 | ToComputedValue, 36 | ToResolvedValue, 37 | ToShmem, 38 | )] 39 | #[repr(transparent)] 40 | pub struct Namespace(pub Atom); 41 | 42 | impl PrecomputedHash for Namespace { 43 | #[inline] 44 | fn precomputed_hash(&self) -> u32 { 45 | self.0.precomputed_hash() 46 | } 47 | } 48 | 49 | /// A Gecko WeakNamespace is a wrapped WeakAtom. 50 | #[derive(Deref, Hash)] 51 | pub struct WeakNamespace(WeakAtom); 52 | 53 | impl Deref for Namespace { 54 | type Target = WeakNamespace; 55 | 56 | #[inline] 57 | fn deref(&self) -> &WeakNamespace { 58 | let weak: *const WeakAtom = &*self.0; 59 | unsafe { &*(weak as *const WeakNamespace) } 60 | } 61 | } 62 | 63 | impl<'a> From<&'a str> for Namespace { 64 | fn from(s: &'a str) -> Self { 65 | Namespace(Atom::from(s)) 66 | } 67 | } 68 | 69 | impl fmt::Display for Namespace { 70 | fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result { 71 | self.0.fmt(w) 72 | } 73 | } 74 | 75 | impl Borrow for Namespace { 76 | #[inline] 77 | fn borrow(&self) -> &WeakNamespace { 78 | self 79 | } 80 | } 81 | 82 | impl WeakNamespace { 83 | /// Trivially construct a WeakNamespace. 84 | #[inline] 85 | pub unsafe fn new<'a>(atom: *mut nsAtom) -> &'a Self { 86 | &*(atom as *const WeakNamespace) 87 | } 88 | 89 | /// Clone this WeakNamespace to obtain a strong reference to the same 90 | /// underlying namespace. 91 | #[inline] 92 | pub fn clone(&self) -> Namespace { 93 | Namespace(self.0.clone()) 94 | } 95 | } 96 | 97 | impl Eq for WeakNamespace {} 98 | impl PartialEq for WeakNamespace { 99 | #[inline] 100 | fn eq(&self, other: &Self) -> bool { 101 | let weak: *const WeakNamespace = self; 102 | let other: *const WeakNamespace = other; 103 | weak == other 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /stylo_config/lib.rs: -------------------------------------------------------------------------------- 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 | use std::collections::HashMap; 6 | use std::sync::{LazyLock, RwLock}; 7 | 8 | static PREFS: LazyLock = LazyLock::new(Preferences::default); 9 | 10 | #[derive(Debug, Default)] 11 | pub struct Preferences { 12 | bool_prefs: RwLock>, 13 | i32_prefs: RwLock>, 14 | } 15 | 16 | impl Preferences { 17 | pub fn get_bool(&self, key: &str) -> bool { 18 | let prefs = self.bool_prefs.read().expect("RwLock is poisoned"); 19 | *prefs.get(key).unwrap_or(&false) 20 | } 21 | 22 | pub fn get_i32(&self, key: &str) -> i32 { 23 | let prefs = self.i32_prefs.read().expect("RwLock is poisoned"); 24 | *prefs.get(key).unwrap_or(&0) 25 | } 26 | 27 | pub fn set_bool(&self, key: &str, value: bool) { 28 | let mut prefs = self.bool_prefs.write().expect("RwLock is poisoned"); 29 | 30 | // Avoid cloning the key if it exists. 31 | if let Some(pref) = prefs.get_mut(key) { 32 | *pref = value; 33 | } else { 34 | prefs.insert(key.to_owned(), value); 35 | } 36 | } 37 | 38 | pub fn set_i32(&self, key: &str, value: i32) { 39 | let mut prefs = self.i32_prefs.write().expect("RwLock is poisoned"); 40 | 41 | // Avoid cloning the key if it exists. 42 | if let Some(pref) = prefs.get_mut(key) { 43 | *pref = value; 44 | } else { 45 | prefs.insert(key.to_owned(), value); 46 | } 47 | } 48 | } 49 | 50 | pub fn get_bool(key: &str) -> bool { 51 | PREFS.get_bool(key) 52 | } 53 | 54 | pub fn get_i32(key: &str) -> i32 { 55 | PREFS.get_i32(key) 56 | } 57 | 58 | pub fn set_bool(key: &str, value: bool) { 59 | PREFS.set_bool(key, value) 60 | } 61 | 62 | pub fn set_i32(key: &str, value: i32) { 63 | PREFS.set_i32(key, value) 64 | } 65 | 66 | #[test] 67 | fn test() { 68 | let prefs = Preferences::default(); 69 | 70 | // Prefs have default values when unset. 71 | assert_eq!(prefs.get_bool("foo"), false); 72 | assert_eq!(prefs.get_i32("bar"), 0); 73 | 74 | // Prefs can be set and retrieved. 75 | prefs.set_bool("foo", true); 76 | prefs.set_i32("bar", 1); 77 | assert_eq!(prefs.get_bool("foo"), true); 78 | assert_eq!(prefs.get_i32("bar"), 1); 79 | prefs.set_bool("foo", false); 80 | prefs.set_i32("bar", 2); 81 | assert_eq!(prefs.get_bool("foo"), false); 82 | assert_eq!(prefs.get_i32("bar"), 2); 83 | 84 | // Each value type currently has an independent namespace. 85 | prefs.set_i32("foo", 3); 86 | prefs.set_bool("bar", true); 87 | assert_eq!(prefs.get_i32("foo"), 3); 88 | assert_eq!(prefs.get_bool("foo"), false); 89 | assert_eq!(prefs.get_bool("bar"), true); 90 | assert_eq!(prefs.get_i32("bar"), 2); 91 | } 92 | -------------------------------------------------------------------------------- /style/properties/longhands/list.mako.rs: -------------------------------------------------------------------------------- 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 | <%namespace name="helpers" file="/helpers.mako.rs" /> 6 | 7 | ${helpers.single_keyword( 8 | "list-style-position", 9 | "outside inside", 10 | engines="gecko servo", 11 | gecko_enum_prefix="StyleListStylePosition", 12 | animation_type="discrete", 13 | spec="https://drafts.csswg.org/css-lists/#propdef-list-style-position", 14 | servo_restyle_damage="rebuild_and_reflow", 15 | affects="layout", 16 | )} 17 | 18 | // TODO(pcwalton): Implement the full set of counter styles per CSS-COUNTER-STYLES [1] 6.1: 19 | // 20 | // decimal-leading-zero, armenian, upper-armenian, lower-armenian, georgian, lower-roman, 21 | // upper-roman 22 | // 23 | // [1]: http://dev.w3.org/csswg/css-counter-styles/ 24 | % if engine == "servo": 25 | ${helpers.single_keyword( 26 | "list-style-type", 27 | """disc none circle square disclosure-open disclosure-closed 28 | decimal lower-alpha upper-alpha arabic-indic bengali cambodian cjk-decimal devanagari 29 | gujarati gurmukhi kannada khmer lao malayalam mongolian myanmar oriya persian telugu 30 | thai tibetan cjk-earthly-branch cjk-heavenly-stem lower-greek hiragana hiragana-iroha 31 | katakana katakana-iroha 32 | """, 33 | engines="servo", 34 | animation_type="discrete", 35 | spec="https://drafts.csswg.org/css-lists/#propdef-list-style-type", 36 | servo_restyle_damage="rebuild_and_reflow", 37 | affects="layout", 38 | )} 39 | % endif 40 | % if engine == "gecko": 41 | ${helpers.predefined_type( 42 | "list-style-type", 43 | "ListStyleType", 44 | "computed::ListStyleType::disc()", 45 | engines="gecko", 46 | initial_specified_value="specified::ListStyleType::disc()", 47 | animation_type="discrete", 48 | spec="https://drafts.csswg.org/css-lists/#propdef-list-style-type", 49 | servo_restyle_damage="rebuild_and_reflow", 50 | affects="layout", 51 | )} 52 | % endif 53 | 54 | ${helpers.predefined_type( 55 | "list-style-image", 56 | "Image", 57 | engines="gecko servo", 58 | initial_value="computed::Image::None", 59 | initial_specified_value="specified::Image::None", 60 | animation_type="discrete", 61 | spec="https://drafts.csswg.org/css-lists/#propdef-list-style-image", 62 | boxed=engine == "servo", 63 | servo_restyle_damage="rebuild_and_reflow", 64 | affects="layout", 65 | )} 66 | 67 | ${helpers.predefined_type( 68 | "quotes", 69 | "Quotes", 70 | "computed::Quotes::get_initial_value()", 71 | engines="gecko servo", 72 | animation_type="discrete", 73 | spec="https://drafts.csswg.org/css-content/#propdef-quotes", 74 | servo_restyle_damage="rebuild_and_reflow", 75 | affects="layout", 76 | )} 77 | -------------------------------------------------------------------------------- /selectors/relative_selector/cache.rs: -------------------------------------------------------------------------------- 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 | use fxhash::FxHashMap; 6 | /// Relative selector cache. This is useful for following cases. 7 | /// First case is non-subject relative selector: Imagine `.anchor:has(<..>) ~ .foo`, with DOM 8 | /// `.anchor + .foo + .. + .foo`. Each match on `.foo` triggers `:has()` traversal that 9 | /// yields the same result. This is simple enough, since we just need to store 10 | /// the exact match on that anchor pass/fail. 11 | /// Second case is `querySelectorAll`: Imagine `querySelectorAll(':has(.a)')`, with DOM 12 | /// `div > .. > div > .a`. When the we perform the traversal at the top div, 13 | /// we basically end up evaluating `:has(.a)` for all anchors, which could be reused. 14 | /// Also consider the sibling version: `querySelectorAll(':has(~ .a)')` with DOM 15 | /// `div + .. + div + .a`. 16 | /// TODO(dshin): Second case is not yet handled. That is tracked in Bug 1845291. 17 | use std::hash::Hash; 18 | 19 | use crate::parser::{RelativeSelector, SelectorKey}; 20 | use crate::{tree::OpaqueElement, SelectorImpl}; 21 | 22 | /// Match data for a given element and a selector. 23 | #[derive(Clone, Copy)] 24 | pub enum RelativeSelectorCachedMatch { 25 | /// This selector matches this element. 26 | Matched, 27 | /// This selector does not match this element. 28 | NotMatched, 29 | } 30 | 31 | impl RelativeSelectorCachedMatch { 32 | /// Is the cached result a match? 33 | pub fn matched(&self) -> bool { 34 | matches!(*self, Self::Matched) 35 | } 36 | } 37 | 38 | #[derive(Clone, Copy, Hash, Eq, PartialEq)] 39 | struct Key { 40 | element: OpaqueElement, 41 | selector: SelectorKey, 42 | } 43 | 44 | impl Key { 45 | pub fn new( 46 | element: OpaqueElement, 47 | selector: &RelativeSelector, 48 | ) -> Self { 49 | Key { 50 | element, 51 | selector: SelectorKey::new(&selector.selector), 52 | } 53 | } 54 | } 55 | 56 | /// Cache to speed up matching of relative selectors. 57 | #[derive(Default)] 58 | pub struct RelativeSelectorCache { 59 | cache: FxHashMap, 60 | } 61 | 62 | impl RelativeSelectorCache { 63 | /// Add a relative selector match into the cache. 64 | pub fn add( 65 | &mut self, 66 | anchor: OpaqueElement, 67 | selector: &RelativeSelector, 68 | matched: RelativeSelectorCachedMatch, 69 | ) { 70 | self.cache.insert(Key::new(anchor, selector), matched); 71 | } 72 | 73 | /// Check if we have a cache entry for the element. 74 | pub fn lookup( 75 | &mut self, 76 | element: OpaqueElement, 77 | selector: &RelativeSelector, 78 | ) -> Option { 79 | self.cache.get(&Key::new(element, selector)).copied() 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /style/values/computed/angle.rs: -------------------------------------------------------------------------------- 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 | //! Computed angles. 6 | 7 | use crate::values::distance::{ComputeSquaredDistance, SquaredDistance}; 8 | use crate::values::CSSFloat; 9 | use crate::Zero; 10 | use std::f64::consts::PI; 11 | use std::fmt::{self, Write}; 12 | use std::{f32, f64}; 13 | use style_traits::{CssWriter, ToCss}; 14 | 15 | /// A computed angle in degrees. 16 | #[derive( 17 | Add, 18 | Animate, 19 | Clone, 20 | Copy, 21 | Debug, 22 | Deserialize, 23 | MallocSizeOf, 24 | PartialEq, 25 | PartialOrd, 26 | Serialize, 27 | ToAnimatedZero, 28 | ToResolvedValue, 29 | )] 30 | #[repr(C)] 31 | pub struct Angle(CSSFloat); 32 | 33 | impl ToCss for Angle { 34 | fn to_css(&self, dest: &mut CssWriter) -> fmt::Result 35 | where 36 | W: Write, 37 | { 38 | self.degrees().to_css(dest)?; 39 | dest.write_str("deg") 40 | } 41 | } 42 | 43 | const RAD_PER_DEG: f64 = PI / 180.0; 44 | 45 | impl Angle { 46 | /// Creates a computed `Angle` value from a radian amount. 47 | pub fn from_radians(radians: CSSFloat) -> Self { 48 | Angle(radians / RAD_PER_DEG as f32) 49 | } 50 | 51 | /// Creates a computed `Angle` value from a degrees amount. 52 | #[inline] 53 | pub fn from_degrees(degrees: CSSFloat) -> Self { 54 | Angle(degrees) 55 | } 56 | 57 | /// Returns the amount of radians this angle represents. 58 | #[inline] 59 | pub fn radians(&self) -> CSSFloat { 60 | self.radians64().min(f32::MAX as f64).max(f32::MIN as f64) as f32 61 | } 62 | 63 | /// Returns the amount of radians this angle represents as a `f64`. 64 | /// 65 | /// Gecko stores angles as singles, but does this computation using doubles. 66 | /// 67 | /// This is significant enough to mess up rounding to the nearest 68 | /// quarter-turn for 225 degrees, for example. 69 | #[inline] 70 | pub fn radians64(&self) -> f64 { 71 | self.0 as f64 * RAD_PER_DEG 72 | } 73 | 74 | /// Return the value in degrees. 75 | #[inline] 76 | pub fn degrees(&self) -> CSSFloat { 77 | self.0 78 | } 79 | } 80 | 81 | impl Zero for Angle { 82 | #[inline] 83 | fn zero() -> Self { 84 | Angle(0.0) 85 | } 86 | 87 | #[inline] 88 | fn is_zero(&self) -> bool { 89 | self.0 == 0. 90 | } 91 | } 92 | 93 | impl ComputeSquaredDistance for Angle { 94 | #[inline] 95 | fn compute_squared_distance(&self, other: &Self) -> Result { 96 | // Use the formula for calculating the distance between angles defined in SVG: 97 | // https://www.w3.org/TR/SVG/animate.html#complexDistances 98 | self.radians64() 99 | .compute_squared_distance(&other.radians64()) 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /style/values/computed/border.rs: -------------------------------------------------------------------------------- 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 | //! Computed types for CSS values related to borders. 6 | 7 | use crate::values::computed::length::{NonNegativeLength, NonNegativeLengthPercentage}; 8 | use crate::values::computed::{NonNegativeNumber, NonNegativeNumberOrPercentage}; 9 | use crate::values::generics::border::{ 10 | GenericBorderCornerRadius, GenericBorderImageSideWidth, GenericBorderImageSlice, 11 | GenericBorderRadius, GenericBorderSpacing, 12 | }; 13 | use crate::values::generics::rect::Rect; 14 | use crate::values::generics::size::Size2D; 15 | use crate::values::generics::NonNegative; 16 | use crate::Zero; 17 | use app_units::Au; 18 | 19 | pub use crate::values::specified::border::BorderImageRepeat; 20 | 21 | /// A computed value for -webkit-text-stroke-width. 22 | pub type LineWidth = Au; 23 | 24 | /// A computed value for border-width (and the like). 25 | pub type BorderSideWidth = Au; 26 | 27 | /// A computed value for the `border-image-width` property. 28 | pub type BorderImageWidth = Rect; 29 | 30 | /// A computed value for a single side of a `border-image-width` property. 31 | pub type BorderImageSideWidth = 32 | GenericBorderImageSideWidth; 33 | 34 | /// A computed value for the `border-image-slice` property. 35 | pub type BorderImageSlice = GenericBorderImageSlice; 36 | 37 | /// A computed value for the `border-radius` property. 38 | pub type BorderRadius = GenericBorderRadius; 39 | 40 | /// A computed value for the `border-*-radius` longhand properties. 41 | pub type BorderCornerRadius = GenericBorderCornerRadius; 42 | 43 | /// A computed value for the `border-spacing` longhand property. 44 | pub type BorderSpacing = GenericBorderSpacing; 45 | 46 | impl BorderImageSideWidth { 47 | /// Returns `1`. 48 | #[inline] 49 | pub fn one() -> Self { 50 | GenericBorderImageSideWidth::Number(NonNegative(1.)) 51 | } 52 | } 53 | 54 | impl BorderImageSlice { 55 | /// Returns the `100%` value. 56 | #[inline] 57 | pub fn hundred_percent() -> Self { 58 | GenericBorderImageSlice { 59 | offsets: Rect::all(NonNegativeNumberOrPercentage::hundred_percent()), 60 | fill: false, 61 | } 62 | } 63 | } 64 | 65 | impl BorderSpacing { 66 | /// Returns `0 0`. 67 | pub fn zero() -> Self { 68 | GenericBorderSpacing(Size2D::new( 69 | NonNegativeLength::zero(), 70 | NonNegativeLength::zero(), 71 | )) 72 | } 73 | 74 | /// Returns the horizontal spacing. 75 | pub fn horizontal(&self) -> Au { 76 | Au::from(*self.0.width()) 77 | } 78 | 79 | /// Returns the vertical spacing. 80 | pub fn vertical(&self) -> Au { 81 | Au::from(*self.0.height()) 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /style/traversal_flags.rs: -------------------------------------------------------------------------------- 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 | //! Flags that control the traversal process. 6 | //! 7 | //! We CamelCase rather than UPPER_CASING so that we can grep for the same 8 | //! strings across gecko and servo. 9 | #![allow(non_upper_case_globals)] 10 | 11 | bitflags! { 12 | /// Flags that control the traversal process. 13 | #[derive(Clone, Copy, Debug, Eq, PartialEq)] 14 | pub struct TraversalFlags: u32 { 15 | /// Traverse only elements for animation restyles. 16 | const AnimationOnly = 1 << 0; 17 | /// Traverse and update all elements with CSS animations since 18 | /// @keyframes rules may have changed. Triggered by CSS rule changes. 19 | const ForCSSRuleChanges = 1 << 1; 20 | /// The final animation-only traversal, which shouldn't really care about other 21 | /// style changes anymore. 22 | const FinalAnimationTraversal = 1 << 2; 23 | /// Allows the traversal to run in parallel if there are sufficient cores on 24 | /// the machine. 25 | const ParallelTraversal = 1 << 7; 26 | /// Flush throttled animations. By default, we only update throttled animations 27 | /// when we have other non-throttled work to do. With this flag, we 28 | /// unconditionally tick and process them. 29 | const FlushThrottledAnimations = 1 << 8; 30 | 31 | } 32 | } 33 | 34 | /// Asserts that all TraversalFlags flags have a matching ServoTraversalFlags value in gecko. 35 | #[cfg(feature = "gecko")] 36 | #[inline] 37 | pub fn assert_traversal_flags_match() { 38 | use crate::gecko_bindings::structs; 39 | 40 | macro_rules! check_traversal_flags { 41 | ( $( $a:ident => $b:path ),*, ) => { 42 | if cfg!(debug_assertions) { 43 | let mut modes = TraversalFlags::all(); 44 | $( 45 | assert_eq!(structs::$a as usize, $b.bits() as usize, stringify!($b)); 46 | modes.remove($b); 47 | )* 48 | assert_eq!(modes, TraversalFlags::empty(), "all TraversalFlags bits should have an assertion"); 49 | } 50 | } 51 | } 52 | 53 | check_traversal_flags! { 54 | ServoTraversalFlags_AnimationOnly => TraversalFlags::AnimationOnly, 55 | ServoTraversalFlags_ForCSSRuleChanges => TraversalFlags::ForCSSRuleChanges, 56 | ServoTraversalFlags_FinalAnimationTraversal => TraversalFlags::FinalAnimationTraversal, 57 | ServoTraversalFlags_ParallelTraversal => TraversalFlags::ParallelTraversal, 58 | ServoTraversalFlags_FlushThrottledAnimations => TraversalFlags::FlushThrottledAnimations, 59 | } 60 | } 61 | 62 | impl TraversalFlags { 63 | /// Returns true if the traversal is for animation-only restyles. 64 | #[inline] 65 | pub fn for_animation_only(&self) -> bool { 66 | self.contains(TraversalFlags::AnimationOnly) 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /style/thread_state.rs: -------------------------------------------------------------------------------- 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 | //! Supports dynamic assertions in about what sort of thread is running and 6 | //! what state it's in. 7 | 8 | #![deny(missing_docs)] 9 | 10 | use std::cell::RefCell; 11 | 12 | bitflags! { 13 | /// A thread state flag, used for multiple assertions. 14 | #[derive(Clone, Copy, Debug, Eq, PartialEq)] 15 | pub struct ThreadState: u32 { 16 | /// Whether we're in a script thread. 17 | const SCRIPT = 0x01; 18 | /// Whether we're in a layout thread. 19 | const LAYOUT = 0x02; 20 | 21 | /// Whether we're in a script worker thread (actual web workers), or in 22 | /// a layout worker thread. 23 | const IN_WORKER = 0x0100; 24 | 25 | /// Whether the current thread is going through a GC. 26 | const IN_GC = 0x0200; 27 | } 28 | } 29 | 30 | macro_rules! thread_types ( ( $( $fun:ident = $flag:path ; )* ) => ( 31 | impl ThreadState { 32 | /// Whether the current thread is a worker thread. 33 | pub fn is_worker(self) -> bool { 34 | self.contains(ThreadState::IN_WORKER) 35 | } 36 | 37 | $( 38 | #[allow(missing_docs)] 39 | pub fn $fun(self) -> bool { 40 | self.contains($flag) 41 | } 42 | )* 43 | } 44 | )); 45 | 46 | thread_types! { 47 | is_script = ThreadState::SCRIPT; 48 | is_layout = ThreadState::LAYOUT; 49 | } 50 | 51 | thread_local!(static STATE: RefCell> = RefCell::new(None)); 52 | 53 | /// Initializes the current thread state. 54 | pub fn initialize(x: ThreadState) { 55 | STATE.with(|ref k| { 56 | if let Some(ref s) = *k.borrow() { 57 | if x != *s { 58 | panic!("Thread state already initialized as {:?}", s); 59 | } 60 | } 61 | *k.borrow_mut() = Some(x); 62 | }); 63 | } 64 | 65 | /// Initializes the current thread as a layout worker thread. 66 | pub fn initialize_layout_worker_thread() { 67 | initialize(ThreadState::LAYOUT | ThreadState::IN_WORKER); 68 | } 69 | 70 | /// Gets the current thread state. 71 | pub fn get() -> ThreadState { 72 | let state = STATE.with(|ref k| { 73 | match *k.borrow() { 74 | None => ThreadState::empty(), // Unknown thread. 75 | Some(s) => s, 76 | } 77 | }); 78 | 79 | state 80 | } 81 | 82 | /// Enters into a given temporary state. Panics if re-entring. 83 | pub fn enter(x: ThreadState) { 84 | let state = get(); 85 | debug_assert!(!state.intersects(x)); 86 | STATE.with(|ref k| { 87 | *k.borrow_mut() = Some(state | x); 88 | }) 89 | } 90 | 91 | /// Exits a given temporary state. 92 | pub fn exit(x: ThreadState) { 93 | let state = get(); 94 | debug_assert!(state.contains(x)); 95 | STATE.with(|ref k| { 96 | *k.borrow_mut() = Some(state & !x); 97 | }) 98 | } 99 | -------------------------------------------------------------------------------- /style/properties/longhands/text.mako.rs: -------------------------------------------------------------------------------- 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 | <%namespace name="helpers" file="/helpers.mako.rs" /> 6 | 7 | ${helpers.predefined_type( 8 | "text-overflow", 9 | "TextOverflow", 10 | "computed::TextOverflow::get_initial_value()", 11 | engines="gecko servo", 12 | servo_pref="layout.unimplemented", 13 | animation_type="discrete", 14 | boxed=True, 15 | spec="https://drafts.csswg.org/css-ui/#propdef-text-overflow", 16 | servo_restyle_damage="rebuild_and_reflow", 17 | affects="paint", 18 | )} 19 | 20 | ${helpers.single_keyword( 21 | "unicode-bidi", 22 | "normal embed isolate bidi-override isolate-override plaintext", 23 | engines="gecko servo", 24 | gecko_enum_prefix="StyleUnicodeBidi", 25 | animation_type="none", 26 | spec="https://drafts.csswg.org/css-writing-modes/#propdef-unicode-bidi", 27 | servo_restyle_damage="rebuild_and_reflow", 28 | affects="layout", 29 | )} 30 | 31 | ${helpers.predefined_type( 32 | "text-decoration-line", 33 | "TextDecorationLine", 34 | "specified::TextDecorationLine::none()", 35 | engines="gecko servo", 36 | initial_specified_value="specified::TextDecorationLine::none()", 37 | animation_type="discrete", 38 | spec="https://drafts.csswg.org/css-text-decor/#propdef-text-decoration-line", 39 | servo_restyle_damage="rebuild_and_reflow", 40 | affects="overflow", 41 | )} 42 | 43 | ${helpers.single_keyword( 44 | "text-decoration-style", 45 | "solid double dotted dashed wavy -moz-none", 46 | engines="gecko servo", 47 | gecko_enum_prefix="StyleTextDecorationStyle", 48 | animation_type="discrete", 49 | spec="https://drafts.csswg.org/css-text-decor/#propdef-text-decoration-style", 50 | affects="overflow", 51 | )} 52 | 53 | ${helpers.predefined_type( 54 | "text-decoration-color", 55 | "Color", 56 | "computed_value::T::currentcolor()", 57 | engines="gecko servo", 58 | initial_specified_value="specified::Color::currentcolor()", 59 | ignored_when_colors_disabled=True, 60 | spec="https://drafts.csswg.org/css-text-decor/#propdef-text-decoration-color", 61 | affects="paint", 62 | )} 63 | 64 | ${helpers.predefined_type( 65 | "initial-letter", 66 | "InitialLetter", 67 | "computed::InitialLetter::normal()", 68 | engines="gecko", 69 | initial_specified_value="specified::InitialLetter::normal()", 70 | animation_type="discrete", 71 | gecko_pref="layout.css.initial-letter.enabled", 72 | spec="https://drafts.csswg.org/css-inline/#sizing-drop-initials", 73 | affects="layout", 74 | )} 75 | 76 | ${helpers.predefined_type( 77 | "text-decoration-thickness", 78 | "TextDecorationLength", 79 | "generics::text::GenericTextDecorationLength::Auto", 80 | engines="gecko", 81 | initial_specified_value="generics::text::GenericTextDecorationLength::Auto", 82 | spec="https://drafts.csswg.org/css-text-decor-4/#text-decoration-width-property", 83 | affects="overflow", 84 | )} 85 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Stylo 2 | ===== 3 | 4 | This repo contains Servo’s downstream fork of [Stylo](https://searchfox.org/mozilla-central/source/servo). 5 | 6 | The branches are as follows: 7 | 8 | - [`upstream`](https://github.com/servo/style/tree/upstream) has upstream mozilla-central filtered to the paths we care about ([style.paths](style.paths)), but is otherwise unmodified 9 | - [`main`](https://github.com/servo/style/tree/ci) has our downstream patches, plus the scripts and workflows for syncing with mozilla-central, to be rebased onto `upstream` 10 | 11 | ## Building Servo against your local Stylo 12 | 13 | Assuming your local `servo` and `stylo` directories are siblings, you can build `servo` against `stylo` by adding the following to `servo/Cargo.toml`: 14 | 15 | ```toml 16 | [patch."https://github.com/servo/stylo"] 17 | selectors = { path = "../stylo/selectors" } 18 | servo_arc = { path = "../stylo/servo_arc" } 19 | stylo_atoms = { path = "../stylo/stylo_atoms" } 20 | stylo = { path = "../stylo/style" } 21 | stylo_config = { path = "../stylo/stylo_config" } 22 | stylo_dom = { path = "../stylo/stylo_dom" } 23 | stylo_malloc_size_of = { path = "../stylo/malloc_size_of" } 24 | stylo_traits = { path = "../stylo/style_traits" } 25 | ``` 26 | 27 | ## Syncing `upstream` with mozilla-central 28 | 29 | Start by generating a filtered copy of mozilla-central. This will cache the raw mozilla-central in `_cache/upstream`, storing the result in `_filtered`: 30 | 31 | ```sh 32 | $ ./sync.sh _filtered 33 | ``` 34 | 35 | If `_filtered` already exists, you will need to delete it and try again: 36 | 37 | ```sh 38 | $ rm -Rf _filtered 39 | ``` 40 | 41 | Now overwrite our `upstream` with those commits and push: 42 | 43 | ```sh 44 | $ git fetch -f --progress ./_filtered master:upstream 45 | $ git push -fu --progress origin upstream 46 | ``` 47 | 48 | ## Rebasing `main` onto `upstream` 49 | 50 | Start by fetching `upstream` into your local repo: 51 | 52 | ```sh 53 | $ git fetch -f origin upstream:upstream 54 | ``` 55 | 56 | In general, the filtering process is deterministic, yielding the same commit hashes each time, so we can rebase normally: 57 | 58 | ```sh 59 | $ git rebase upstream 60 | ``` 61 | 62 | But if the filtering config changes or Mozilla moves to GitHub, the commit hashes on `upstream` may change. In this case, we need to tell git where the old upstream ends and our own commits start (notice the `~`): 63 | 64 | ```sh 65 | $ git log --pretty=\%H --grep='Servo initial downstream commit' 66 | e62d7f0090941496e392e1dc91df103a38e3f488 67 | 68 | $ git rebase --onto upstream e62d7f0090941496e392e1dc91df103a38e3f488~ 69 | Successfully rebased and updated refs/heads/main. 70 | ``` 71 | 72 | `start-rebase.sh` takes care of this automatically, but you should still use `git rebase` for subsequent steps like `--continue` and `--abort`: 73 | 74 | ```sh 75 | $ ./start-rebase.sh upstream 76 | $ ./start-rebase.sh upstream -i # interactive 77 | $ git rebase --continue # not ./start-rebase.sh --continue 78 | $ git rebase --abort # not ./start-rebase.sh --abort 79 | ``` 80 | 81 | Or if we aren’t ready to rebase onto the tip of upstream: 82 | 83 | ```sh 84 | $ ./start-rebase.sh upstream~10 -i 85 | ``` 86 | -------------------------------------------------------------------------------- /style/stylesheets/style_rule.rs: -------------------------------------------------------------------------------- 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 | //! A style rule. 6 | 7 | use crate::properties::PropertyDeclarationBlock; 8 | use crate::selector_parser::SelectorImpl; 9 | use crate::shared_lock::{ 10 | DeepCloneWithLock, Locked, SharedRwLock, SharedRwLockReadGuard, ToCssWithGuard, 11 | }; 12 | use crate::str::CssStringWriter; 13 | use crate::stylesheets::{CssRules, style_or_page_rule_to_css}; 14 | use cssparser::SourceLocation; 15 | #[cfg(feature = "gecko")] 16 | use malloc_size_of::{ 17 | MallocSizeOf, MallocSizeOfOps, MallocUnconditionalShallowSizeOf, MallocUnconditionalSizeOf, 18 | }; 19 | use selectors::SelectorList; 20 | use servo_arc::Arc; 21 | use std::fmt::{self, Write}; 22 | 23 | /// A style rule, with selectors and declarations. 24 | #[derive(Debug, ToShmem)] 25 | pub struct StyleRule { 26 | /// The list of selectors in this rule. 27 | pub selectors: SelectorList, 28 | /// The declaration block with the properties it contains. 29 | pub block: Arc>, 30 | /// The nested rules to this style rule. Only non-`None` when nesting is enabled. 31 | pub rules: Option>>, 32 | /// The location in the sheet where it was found. 33 | pub source_location: SourceLocation, 34 | } 35 | 36 | impl DeepCloneWithLock for StyleRule { 37 | /// Deep clones this StyleRule. 38 | fn deep_clone_with_lock( 39 | &self, 40 | lock: &SharedRwLock, 41 | guard: &SharedRwLockReadGuard, 42 | ) -> StyleRule { 43 | StyleRule { 44 | selectors: self.selectors.clone(), 45 | block: Arc::new(lock.wrap(self.block.read_with(guard).clone())), 46 | rules: self.rules.as_ref().map(|rules| { 47 | let rules = rules.read_with(guard); 48 | Arc::new(lock.wrap(rules.deep_clone_with_lock(lock, guard))) 49 | }), 50 | source_location: self.source_location.clone(), 51 | } 52 | } 53 | } 54 | 55 | impl StyleRule { 56 | /// Measure heap usage. 57 | #[cfg(feature = "gecko")] 58 | pub fn size_of(&self, guard: &SharedRwLockReadGuard, ops: &mut MallocSizeOfOps) -> usize { 59 | let mut n = 0; 60 | n += self.selectors.unconditional_size_of(ops); 61 | n += self.block.unconditional_shallow_size_of(ops) + 62 | self.block.read_with(guard).size_of(ops); 63 | if let Some(ref rules) = self.rules { 64 | n += rules.unconditional_shallow_size_of(ops) + 65 | rules.read_with(guard).size_of(guard, ops) 66 | } 67 | n 68 | } 69 | } 70 | 71 | impl ToCssWithGuard for StyleRule { 72 | /// https://drafts.csswg.org/cssom/#serialize-a-css-rule CSSStyleRule 73 | fn to_css(&self, guard: &SharedRwLockReadGuard, dest: &mut CssStringWriter) -> fmt::Result { 74 | use cssparser::ToCss; 75 | self.selectors.to_css(dest)?; 76 | dest.write_char(' ')?; 77 | style_or_page_rule_to_css(self.rules.as_ref(), &self.block, guard, dest) 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /style/properties/shorthands/outline.mako.rs: -------------------------------------------------------------------------------- 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 | <%namespace name="helpers" file="/helpers.mako.rs" /> 6 | 7 | <%helpers:shorthand name="outline" 8 | engines="gecko servo" 9 | sub_properties="outline-color outline-style outline-width" 10 | spec="https://drafts.csswg.org/css-ui/#propdef-outline"> 11 | use crate::properties::longhands::{outline_color, outline_width, outline_style}; 12 | use crate::values::specified; 13 | use crate::parser::Parse; 14 | 15 | pub fn parse_value<'i, 't>( 16 | context: &ParserContext, 17 | input: &mut Parser<'i, 't>, 18 | ) -> Result> { 19 | let _unused = context; 20 | let mut color = None; 21 | let mut style = None; 22 | let mut width = None; 23 | let mut any = false; 24 | loop { 25 | if color.is_none() { 26 | if let Ok(value) = input.try_parse(|i| specified::Color::parse(context, i)) { 27 | color = Some(value); 28 | any = true; 29 | continue 30 | } 31 | } 32 | if style.is_none() { 33 | if let Ok(value) = input.try_parse(|input| outline_style::parse(context, input)) { 34 | style = Some(value); 35 | any = true; 36 | continue 37 | } 38 | } 39 | if width.is_none() { 40 | if let Ok(value) = input.try_parse(|input| outline_width::parse(context, input)) { 41 | width = Some(value); 42 | any = true; 43 | continue 44 | } 45 | } 46 | break 47 | } 48 | if any { 49 | Ok(expanded! { 50 | outline_color: unwrap_or_initial!(outline_color, color), 51 | outline_style: unwrap_or_initial!(outline_style, style), 52 | outline_width: unwrap_or_initial!(outline_width, width), 53 | }) 54 | } else { 55 | Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError)) 56 | } 57 | } 58 | 59 | impl<'a> ToCss for LonghandsToSerialize<'a> { 60 | fn to_css(&self, dest: &mut CssWriter) -> fmt::Result where W: fmt::Write { 61 | let mut wrote_value = false; 62 | 63 | % for name in "color style width".split(): 64 | if *self.outline_${name} != outline_${name}::get_initial_specified_value() { 65 | if wrote_value { 66 | dest.write_char(' ')?; 67 | } 68 | self.outline_${name}.to_css(dest)?; 69 | wrote_value = true; 70 | } 71 | % endfor 72 | 73 | if !wrote_value { 74 | self.outline_style.to_css(dest)?; 75 | } 76 | 77 | Ok(()) 78 | } 79 | } 80 | 81 | --------------------------------------------------------------------------------