commit bbeecfb159fb6174ffa7a912ba114c41af5fd762
parent 70a4e7824b0453fc89c09638173c525bf4956644
Author: Nico Burns <nico@nicoburns.com>
Date: Mon, 15 Dec 2025 19:03:58 +0000
Bug 2005254: Stylo: Use std::sync::LazyLock instead of lazy_static crate (r=firefox-style-system-reviewers,dshin)
Differential Revision: https://phabricator.services.mozilla.com/D275846
Diffstat:
14 files changed, 180 insertions(+), 200 deletions(-)
diff --git a/Cargo.lock b/Cargo.lock
@@ -6691,7 +6691,6 @@ dependencies = [
"indexmap",
"itertools",
"itoa",
- "lazy_static",
"log",
"malloc_size_of",
"malloc_size_of_derive",
diff --git a/servo/components/style/Cargo.toml b/servo/components/style/Cargo.toml
@@ -66,7 +66,6 @@ icu_segmenter = { version = "2.0", default-features = false, features = ["auto",
indexmap = {version = "2", features = ["std"]}
itertools = "0.14"
itoa = "1.0"
-lazy_static = "1"
log = "0.4"
malloc_size_of = { path = "../malloc_size_of" }
malloc_size_of_derive = { path = "../../../xpcom/rust/malloc_size_of_derive" }
@@ -102,7 +101,6 @@ gecko-profiler = { path = "../../../tools/profiler/rust-api" }
url = { version = "2.5", optional = true, features = ["serde"] }
[build-dependencies]
-lazy_static = "1"
log = { version = "0.4", features = ["std"] }
bindgen = {version = "0.69", optional = true, default-features = false}
regex = {version = "1.0", optional = true, default-features = false, features = ["perf", "std"]}
diff --git a/servo/components/style/author_styles.rs b/servo/components/style/author_styles.rs
@@ -13,6 +13,7 @@ use crate::stylesheets::StylesheetInDocument;
use crate::stylist::CascadeData;
use crate::stylist::Stylist;
use servo_arc::Arc;
+use std::sync::LazyLock;
/// A set of author stylesheets and their computed representation, such as the
/// ones used for ShadowRoot.
@@ -31,9 +32,8 @@ where
pub use self::GenericAuthorStyles as AuthorStyles;
-lazy_static! {
- static ref EMPTY_CASCADE_DATA: Arc<CascadeData> = Arc::new_leaked(CascadeData::new());
-}
+static EMPTY_CASCADE_DATA: LazyLock<Arc<CascadeData>> =
+ LazyLock::new(|| Arc::new_leaked(CascadeData::new()));
impl<S> GenericAuthorStyles<S>
where
diff --git a/servo/components/style/build.rs b/servo/components/style/build.rs
@@ -2,12 +2,10 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
-#[macro_use]
-extern crate lazy_static;
-
use std::env;
use std::path::Path;
use std::process::{exit, Command};
+use std::sync::LazyLock;
use walkdir::WalkDir;
#[cfg(feature = "gecko")]
@@ -18,8 +16,8 @@ mod build_gecko {
pub fn generate() {}
}
-lazy_static! {
- pub static ref PYTHON: String = env::var("PYTHON3").ok().unwrap_or_else(|| {
+pub static PYTHON: LazyLock<String> = LazyLock::new(|| {
+ env::var("PYTHON3").ok().unwrap_or_else(|| {
let candidates = if cfg!(windows) {
["python3.exe"]
} else {
@@ -39,8 +37,8 @@ lazy_static! {
"Can't find python (tried {})! Try fixing PATH or setting the PYTHON3 env var",
candidates.join(", ")
)
- });
-}
+ })
+});
fn generate_properties(engine: &str) {
for entry in WalkDir::new("properties") {
diff --git a/servo/components/style/build_gecko.rs b/servo/components/style/build_gecko.rs
@@ -13,14 +13,14 @@ use std::io::{Read, Write};
use std::path::{Path, PathBuf};
use std::process::{exit, Command};
use std::slice;
+use std::sync::LazyLock;
use std::sync::Mutex;
use std::time::SystemTime;
use toml;
use toml::value::Table;
-lazy_static! {
- static ref OUTDIR_PATH: PathBuf = PathBuf::from(env::var_os("OUT_DIR").unwrap()).join("gecko");
-}
+static OUTDIR_PATH: LazyLock<PathBuf> =
+ LazyLock::new(|| PathBuf::from(env::var_os("OUT_DIR").unwrap()).join("gecko"));
const STRUCTS_FILE: &'static str = "structs.rs";
@@ -39,32 +39,36 @@ fn read_config(path: &PathBuf) -> Table {
}
}
-lazy_static! {
- static ref CONFIG: Table = {
- // Load Gecko's binding generator config from the source tree.
- let path = mozbuild::TOPSRCDIR.join("layout/style/ServoBindings.toml");
- read_config(&path)
- };
- static ref BINDGEN_FLAGS: Vec<String> = {
- mozbuild::config::BINDGEN_SYSTEM_FLAGS
- .iter()
- .chain(&mozbuild::config::NSPR_CFLAGS)
- .chain(&mozbuild::config::MOZ_PIXMAN_CFLAGS)
- .chain(&mozbuild::config::MOZ_ICU_CFLAGS)
- .map(|s| s.to_string())
- .collect()
- };
- static ref INCLUDE_RE: Regex = Regex::new(r#"#include\s*"(.+?)""#).unwrap();
- static ref DISTDIR_PATH: PathBuf = mozbuild::TOPOBJDIR.join("dist");
- static ref SEARCH_PATHS: Vec<PathBuf> = vec![
+static CONFIG: LazyLock<Table> = LazyLock::new(|| {
+ // Load Gecko's binding generator config from the source tree.
+ let path = mozbuild::TOPSRCDIR.join("layout/style/ServoBindings.toml");
+ read_config(&path)
+});
+static BINDGEN_FLAGS: LazyLock<Vec<String>> = LazyLock::new(|| {
+ mozbuild::config::BINDGEN_SYSTEM_FLAGS
+ .iter()
+ .chain(&mozbuild::config::NSPR_CFLAGS)
+ .chain(&mozbuild::config::MOZ_PIXMAN_CFLAGS)
+ .chain(&mozbuild::config::MOZ_ICU_CFLAGS)
+ .map(|s| s.to_string())
+ .collect()
+});
+static INCLUDE_RE: LazyLock<Regex> = LazyLock::new(|| Regex::new(r#"#include\s*"(.+?)""#).unwrap());
+static DISTDIR_PATH: LazyLock<PathBuf> = LazyLock::new(|| mozbuild::TOPOBJDIR.join("dist"));
+static SEARCH_PATHS: LazyLock<Vec<PathBuf>> = LazyLock::new(|| {
+ vec![
DISTDIR_PATH.join("include"),
DISTDIR_PATH.join("include/nspr"),
- ];
- static ref ADDED_PATHS: Mutex<HashSet<PathBuf>> = Mutex::new(HashSet::new());
- static ref LAST_MODIFIED: Mutex<SystemTime> =
- Mutex::new(get_modified_time(&env::current_exe().unwrap())
- .expect("Failed to get modified time of executable"));
-}
+ ]
+});
+static ADDED_PATHS: LazyLock<Mutex<HashSet<PathBuf>>> =
+ LazyLock::new(|| Mutex::new(HashSet::new()));
+static LAST_MODIFIED: LazyLock<Mutex<SystemTime>> = LazyLock::new(|| {
+ Mutex::new(
+ get_modified_time(&env::current_exe().unwrap())
+ .expect("Failed to get modified time of executable"),
+ )
+});
fn get_modified_time(file: &Path) -> Option<SystemTime> {
file.metadata().and_then(|m| m.modified()).ok()
diff --git a/servo/components/style/custom_properties_map.rs b/servo/components/style/custom_properties_map.rs
@@ -10,6 +10,7 @@ use crate::selector_map::PrecomputedHasher;
use indexmap::IndexMap;
use servo_arc::Arc;
use std::hash::BuildHasherDefault;
+use std::sync::LazyLock;
/// A map for a set of custom properties, which implements copy-on-write behavior on insertion with
/// cheap copying.
@@ -26,16 +27,14 @@ impl Default for CustomPropertiesMap {
type OwnMap =
IndexMap<Name, Option<ComputedRegisteredValue>, BuildHasherDefault<PrecomputedHasher>>;
-lazy_static! {
- static ref EMPTY: Arc<Inner> = {
- Arc::new_leaked(Inner {
- own_properties: Default::default(),
- parent: None,
- len: 0,
- ancestor_count: 0,
- })
- };
-}
+static EMPTY: LazyLock<Arc<Inner>> = LazyLock::new(|| {
+ Arc::new_leaked(Inner {
+ own_properties: Default::default(),
+ parent: None,
+ len: 0,
+ ancestor_count: 0,
+ })
+});
#[derive(Debug, Clone)]
struct Inner {
diff --git a/servo/components/style/gecko/url.rs b/servo/components/style/gecko/url.rs
@@ -17,7 +17,7 @@ use servo_arc::Arc;
use std::collections::HashMap;
use std::fmt::{self, Write};
use std::mem::ManuallyDrop;
-use std::sync::RwLock;
+use std::sync::{LazyLock, RwLock};
use style_traits::{CssWriter, ParseError, ToCss};
use to_shmem::{SharedMemoryBuilder, ToShmem};
@@ -382,10 +382,7 @@ impl ToCss for ComputedUrl {
}
}
-lazy_static! {
- /// A table mapping CssUrlData objects to their lazily created LoadData
- /// objects.
- static ref LOAD_DATA_TABLE: RwLock<HashMap<LoadDataKey, Box<LoadData>>> = {
- Default::default()
- };
-}
+/// A table mapping CssUrlData objects to their lazily created LoadData
+/// objects.
+static LOAD_DATA_TABLE: LazyLock<RwLock<HashMap<LoadDataKey, Box<LoadData>>>> =
+ LazyLock::new(|| Default::default());
diff --git a/servo/components/style/gecko/wrapper.rs b/servo/components/style/gecko/wrapper.rs
@@ -1674,34 +1674,36 @@ impl<'le> TElement for GeckoElement<'le> {
use crate::properties::longhands::color::SpecifiedValue as SpecifiedColor;
use crate::stylesheets::layer_rule::LayerOrder;
use crate::values::specified::{color::Color, font::XTextScale};
- lazy_static! {
- static ref TABLE_COLOR_RULE: ApplicableDeclarationBlock = {
- let global_style_data = &*GLOBAL_STYLE_DATA;
- let pdb = PropertyDeclarationBlock::with_one(
- PropertyDeclaration::Color(SpecifiedColor(Color::InheritFromBodyQuirk.into())),
- Importance::Normal,
- );
- let arc = Arc::new_leaked(global_style_data.shared_lock.wrap(pdb));
- ApplicableDeclarationBlock::from_declarations(
- arc,
- ServoCascadeLevel::PresHints,
- LayerOrder::root(),
- )
- };
- static ref MATHML_LANG_RULE: ApplicableDeclarationBlock = {
- let global_style_data = &*GLOBAL_STYLE_DATA;
- let pdb = PropertyDeclarationBlock::with_one(
- PropertyDeclaration::XLang(SpecifiedLang(atom!("x-math"))),
- Importance::Normal,
- );
- let arc = Arc::new_leaked(global_style_data.shared_lock.wrap(pdb));
- ApplicableDeclarationBlock::from_declarations(
- arc,
- ServoCascadeLevel::PresHints,
- LayerOrder::root(),
- )
- };
- static ref SVG_TEXT_DISABLE_SCALE_RULE: ApplicableDeclarationBlock = {
+ use std::sync::LazyLock;
+
+ static TABLE_COLOR_RULE: LazyLock<ApplicableDeclarationBlock> = LazyLock::new(|| {
+ let global_style_data = &*GLOBAL_STYLE_DATA;
+ let pdb = PropertyDeclarationBlock::with_one(
+ PropertyDeclaration::Color(SpecifiedColor(Color::InheritFromBodyQuirk.into())),
+ Importance::Normal,
+ );
+ let arc = Arc::new_leaked(global_style_data.shared_lock.wrap(pdb));
+ ApplicableDeclarationBlock::from_declarations(
+ arc,
+ ServoCascadeLevel::PresHints,
+ LayerOrder::root(),
+ )
+ });
+ static MATHML_LANG_RULE: LazyLock<ApplicableDeclarationBlock> = LazyLock::new(|| {
+ let global_style_data = &*GLOBAL_STYLE_DATA;
+ let pdb = PropertyDeclarationBlock::with_one(
+ PropertyDeclaration::XLang(SpecifiedLang(atom!("x-math"))),
+ Importance::Normal,
+ );
+ let arc = Arc::new_leaked(global_style_data.shared_lock.wrap(pdb));
+ ApplicableDeclarationBlock::from_declarations(
+ arc,
+ ServoCascadeLevel::PresHints,
+ LayerOrder::root(),
+ )
+ });
+ static SVG_TEXT_DISABLE_SCALE_RULE: LazyLock<ApplicableDeclarationBlock> =
+ LazyLock::new(|| {
let global_style_data = &*GLOBAL_STYLE_DATA;
let pdb = PropertyDeclarationBlock::with_one(
PropertyDeclaration::XTextScale(XTextScale::None),
@@ -1713,8 +1715,7 @@ impl<'le> TElement for GeckoElement<'le> {
ServoCascadeLevel::PresHints,
LayerOrder::root(),
)
- };
- };
+ });
let ns = self.namespace_id();
// <th> elements get a default MozCenterOrInherit which may get overridden
diff --git a/servo/components/style/global_style_data.rs b/servo/components/style/global_style_data.rs
@@ -15,7 +15,7 @@ use parking_lot::{Mutex, RwLock, RwLockReadGuard};
use std::os::unix::thread::{JoinHandleExt, RawPthread};
#[cfg(windows)]
use std::os::windows::{io::AsRawHandle, prelude::RawHandle};
-use std::{io, thread};
+use std::{io, sync::LazyLock, thread};
use thin_vec::ThinVec;
/// Platform-specific handle to a thread.
@@ -65,17 +65,14 @@ fn thread_name(index: usize) -> String {
format!("StyleThread#{}", index)
}
-lazy_static! {
- /// JoinHandles for spawned style threads. These will be joined during
- /// StyleThreadPool::shutdown() after exiting the thread pool.
- ///
- /// This would be quite inefficient if rayon destroyed and re-created
- /// threads regularly during threadpool operation in response to demand,
- /// however rayon actually never destroys its threads until the entire
- /// thread pool is shut-down, so the size of this list is bounded.
- static ref STYLE_THREAD_JOIN_HANDLES: Mutex<Vec<thread::JoinHandle<()>>> =
- Mutex::new(Vec::new());
-}
+/// JoinHandles for spawned style threads. These will be joined during
+/// StyleThreadPool::shutdown() after exiting the thread pool.
+///
+/// This would be quite inefficient if rayon destroyed and re-created
+/// threads regularly during threadpool operation in response to demand,
+/// however rayon actually never destroys its threads until the entire
+/// thread pool is shut-down, so the size of this list is bounded.
+static STYLE_THREAD_JOIN_HANDLES: Mutex<Vec<thread::JoinHandle<()>>> = Mutex::new(Vec::new());
fn thread_spawn(options: rayon::ThreadBuilder) -> io::Result<()> {
let mut b = thread::Builder::new();
@@ -139,7 +136,7 @@ impl StyleThreadPool {
pub fn get_thread_handles(handles: &mut ThinVec<PlatformThreadHandle>) {
// Force the lazy initialization of STYLE_THREAD_POOL so that the threads get spawned and
// their join handles are added to STYLE_THREAD_JOIN_HANDLES.
- lazy_static::initialize(&STYLE_THREAD_POOL);
+ LazyLock::force(&STYLE_THREAD_POOL);
for join_handle in STYLE_THREAD_JOIN_HANDLES.lock().iter() {
#[cfg(unix)]
@@ -171,59 +168,57 @@ fn stylo_threads_pref() -> i32 {
/// there on many-core machines (see bug 1431285 comment 14).
pub(crate) const STYLO_MAX_THREADS: usize = 6;
-lazy_static! {
- /// Global thread pool
- pub static ref STYLE_THREAD_POOL: StyleThreadPool = {
- use std::cmp;
- // We always set this pref on startup, before layout or script have had a chance of
- // accessing (and thus creating) the thread-pool.
- let threads_pref: i32 = stylo_threads_pref();
- let num_threads = if threads_pref >= 0 {
- threads_pref as usize
+/// Global thread pool
+pub static STYLE_THREAD_POOL: LazyLock<StyleThreadPool> = LazyLock::new(|| {
+ use std::cmp;
+ // We always set this pref on startup, before layout or script have had a chance of
+ // accessing (and thus creating) the thread-pool.
+ let threads_pref: i32 = stylo_threads_pref();
+ let num_threads = if threads_pref >= 0 {
+ threads_pref as usize
+ } else {
+ // Gecko may wish to override the default number of threads, for example on
+ // systems with heterogeneous CPUs.
+ #[cfg(feature = "gecko")]
+ let num_threads = unsafe { bindings::Gecko_GetNumStyleThreads() };
+ #[cfg(not(feature = "gecko"))]
+ let num_threads = -1;
+
+ if num_threads >= 0 {
+ num_threads as usize
} else {
- // Gecko may wish to override the default number of threads, for example on
- // systems with heterogeneous CPUs.
- #[cfg(feature = "gecko")]
- let num_threads = unsafe { bindings::Gecko_GetNumStyleThreads() };
- #[cfg(not(feature = "gecko"))]
- let num_threads = -1;
-
- if num_threads >= 0 {
- num_threads as usize
- } else {
- // The default heuristic is num_virtual_cores * .75. This gives us three threads on a
- // hyper-threaded dual core, and six threads on a hyper-threaded quad core.
- cmp::max(num_cpus::get() * 3 / 4, 1)
- }
- };
-
- let num_threads = cmp::min(num_threads, STYLO_MAX_THREADS);
- // Since the main-thread is also part of the pool, having one thread or less doesn't make
- // sense.
- let (pool, num_threads) = if num_threads <= 1 {
- (None, None)
- } else {
- let workers = rayon::ThreadPoolBuilder::new()
- .spawn_handler(thread_spawn)
- .use_current_thread()
- .num_threads(num_threads)
- .thread_name(thread_name)
- .start_handler(thread_startup)
- .exit_handler(thread_shutdown)
- .stack_size(STYLE_THREAD_STACK_SIZE_KB * 1024)
- .build();
- (workers.ok(), Some(num_threads))
- };
-
- StyleThreadPool {
- num_threads,
- style_thread_pool: RwLock::new(pool),
+ // The default heuristic is num_virtual_cores * .75. This gives us three threads on a
+ // hyper-threaded dual core, and six threads on a hyper-threaded quad core.
+ cmp::max(num_cpus::get() * 3 / 4, 1)
}
};
- /// Global style data
- pub static ref GLOBAL_STYLE_DATA: GlobalStyleData = GlobalStyleData {
- shared_lock: SharedRwLock::new_leaked(),
- options: StyleSystemOptions::default(),
+ let num_threads = cmp::min(num_threads, STYLO_MAX_THREADS);
+ // Since the main-thread is also part of the pool, having one thread or less doesn't make
+ // sense.
+ let (pool, num_threads) = if num_threads <= 1 {
+ (None, None)
+ } else {
+ let workers = rayon::ThreadPoolBuilder::new()
+ .spawn_handler(thread_spawn)
+ .use_current_thread()
+ .num_threads(num_threads)
+ .thread_name(thread_name)
+ .start_handler(thread_startup)
+ .exit_handler(thread_shutdown)
+ .stack_size(STYLE_THREAD_STACK_SIZE_KB * 1024)
+ .build();
+ (workers.ok(), Some(num_threads))
};
-}
+
+ StyleThreadPool {
+ num_threads,
+ style_thread_pool: RwLock::new(pool),
+ }
+});
+
+/// Global style data
+pub static GLOBAL_STYLE_DATA: LazyLock<GlobalStyleData> = LazyLock::new(|| GlobalStyleData {
+ shared_lock: SharedRwLock::new_leaked(),
+ options: StyleSystemOptions::default(),
+});
diff --git a/servo/components/style/lib.rs b/servo/components/style/lib.rs
@@ -36,8 +36,6 @@ extern crate gecko_profiler;
#[macro_use]
pub mod gecko_string_cache;
#[macro_use]
-extern crate lazy_static;
-#[macro_use]
extern crate log;
#[allow(unused_extern_crates)]
#[macro_use]
diff --git a/servo/components/style/properties/gecko.mako.rs b/servo/components/style/properties/gecko.mako.rs
@@ -444,18 +444,16 @@ impl ${style_struct.gecko_struct_name} {
UniqueArc::assume_init(result).shareable()
}
% else:
- lazy_static! {
- static ref DEFAULT: Arc<${style_struct.gecko_struct_name}> = unsafe {
- let mut result = UniqueArc::<${style_struct.gecko_struct_name}>::new_uninit();
- Gecko_Construct_Default_${style_struct.gecko_ffi_name}(
- result.as_mut_ptr() as *mut _,
- std::ptr::null(),
- );
- let arc = UniqueArc::assume_init(result).shareable();
- arc.mark_as_intentionally_leaked();
- arc
- };
- };
+ static DEFAULT: std::sync::LazyLock<Arc<${style_struct.gecko_struct_name}>> = std::sync::LazyLock::new(|| unsafe {
+ let mut result = UniqueArc::<${style_struct.gecko_struct_name}>::new_uninit();
+ Gecko_Construct_Default_${style_struct.gecko_ffi_name}(
+ result.as_mut_ptr() as *mut _,
+ std::ptr::null(),
+ );
+ let arc = UniqueArc::assume_init(result).shareable();
+ arc.mark_as_intentionally_leaked();
+ arc
+ });
DEFAULT.clone()
% endif
}
diff --git a/servo/components/style/stylist.rs b/servo/components/style/stylist.rs
@@ -85,7 +85,7 @@ use servo_arc::{Arc, ArcBorrow, ThinArc};
use smallvec::SmallVec;
use std::cmp::Ordering;
use std::hash::{Hash, Hasher};
-use std::sync::Mutex;
+use std::sync::{LazyLock, Mutex};
use std::{mem, ops};
/// The type of the stylesheets that the stylist contains.
@@ -277,11 +277,9 @@ pub fn add_size_of_ua_cache(ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSet
.add_size_of(ops, sizes);
}
-lazy_static! {
- /// A cache of computed user-agent data, to be shared across documents.
- static ref UA_CASCADE_DATA_CACHE: Mutex<UserAgentCascadeDataCache> =
- Mutex::new(UserAgentCascadeDataCache::new());
-}
+/// A cache of computed user-agent data, to be shared across documents.
+static UA_CASCADE_DATA_CACHE: LazyLock<Mutex<UserAgentCascadeDataCache>> =
+ LazyLock::new(|| Mutex::new(UserAgentCascadeDataCache::new()));
impl CascadeDataCacheEntry for UserAgentCascadeData {
fn rebuild<S>(
@@ -343,14 +341,12 @@ struct UserAgentCascadeData {
precomputed_pseudo_element_decls: PrecomputedPseudoElementDeclarations,
}
-lazy_static! {
- /// The empty UA cascade data for un-filled stylists.
- static ref EMPTY_UA_CASCADE_DATA: Arc<UserAgentCascadeData> = {
- let arc = Arc::new(UserAgentCascadeData::default());
- arc.mark_as_intentionally_leaked();
- arc
- };
-}
+/// The empty UA cascade data for un-filled stylists.
+static EMPTY_UA_CASCADE_DATA: LazyLock<Arc<UserAgentCascadeData>> = LazyLock::new(|| {
+ let arc = Arc::new(UserAgentCascadeData::default());
+ arc.mark_as_intentionally_leaked();
+ arc
+});
/// All the computed information for all the stylesheets that apply to the
/// document.
@@ -3182,16 +3178,14 @@ pub struct CascadeData {
num_declarations: usize,
}
-lazy_static! {
- static ref IMPLICIT_SCOPE: SelectorList<SelectorImpl> = {
- // Implicit scope, as per https://github.com/w3c/csswg-drafts/issues/10196
- // Also, `&` is `:where(:scope)`, as per https://github.com/w3c/csswg-drafts/issues/9740
- // ``:where(:scope)` effectively behaves the same as the implicit scope.
- let list = SelectorList::implicit_scope();
- list.mark_as_intentionally_leaked();
- list
- };
-}
+static IMPLICIT_SCOPE: LazyLock<SelectorList<SelectorImpl>> = LazyLock::new(|| {
+ // Implicit scope, as per https://github.com/w3c/csswg-drafts/issues/10196
+ // Also, `&` is `:where(:scope)`, as per https://github.com/w3c/csswg-drafts/issues/9740
+ // ``:where(:scope)` effectively behaves the same as the implicit scope.
+ let list = SelectorList::implicit_scope();
+ list.mark_as_intentionally_leaked();
+ list
+});
fn scope_start_matches_shadow_host(start: &SelectorList<SelectorImpl>) -> bool {
// TODO(emilio): Should we carry a MatchesFeaturelessHost rather than a bool around?
diff --git a/servo/components/style/values/computed/font.rs b/servo/components/style/values/computed/font.rs
@@ -362,15 +362,13 @@ pub struct FontFamily {
macro_rules! static_font_family {
($ident:ident, $family:expr) => {
- lazy_static! {
- static ref $ident: FontFamily = FontFamily {
- families: FontFamilyList {
- list: crate::ArcSlice::from_iter_leaked(std::iter::once($family)),
- },
- is_system_font: false,
- is_initial: false,
- };
- }
+ static $ident: std::sync::LazyLock<FontFamily> = std::sync::LazyLock::new(|| FontFamily {
+ families: FontFamilyList {
+ list: crate::ArcSlice::from_iter_leaked(std::iter::once($family)),
+ },
+ is_system_font: false,
+ is_initial: false,
+ });
};
}
diff --git a/servo/ports/geckolib/glue.rs b/servo/ports/geckolib/glue.rs
@@ -25,6 +25,7 @@ use std::fmt::Write;
use std::iter;
use std::os::raw::c_void;
use std::ptr;
+use std::sync::LazyLock;
use style::color::mix::ColorInterpolationMethod;
use style::color::{AbsoluteColor, ColorComponents, ColorSpace};
use style::computed_value_flags::ComputedValueFlags;
@@ -226,7 +227,7 @@ pub unsafe extern "C" fn Servo_Initialize(
thread_state::initialize(thread_state::ThreadState::LAYOUT);
debug_assert!(is_main_thread());
- lazy_static::initialize(&STYLE_THREAD_POOL);
+ LazyLock::force(&STYLE_THREAD_POOL);
// Perform some debug-only runtime assertions.
origin_flags::assert_flags_match();