diff --git a/components/config/opts.rs b/components/config/opts.rs index 8432833eeb2..b14c3bd5ebc 100644 --- a/components/config/opts.rs +++ b/components/config/opts.rs @@ -7,7 +7,7 @@ use std::default::Default; use std::path::PathBuf; -use std::sync::{LazyLock, RwLock, RwLockReadGuard}; +use std::sync::OnceLock; use serde::{Deserialize, Serialize}; use servo_url::ServoUrl; @@ -209,13 +209,27 @@ impl Default for Opts { // Make Opts available globally. This saves having to clone and pass // opts everywhere it is used, which gets particularly cumbersome // when passing through the DOM structures. -static OPTIONS: LazyLock> = LazyLock::new(|| RwLock::new(Opts::default())); +static OPTIONS: OnceLock = OnceLock::new(); -pub fn set_options(opts: Opts) { - *OPTIONS.write().unwrap() = opts; +/// Initialize options. +/// +/// Should only be called once at process startup. +/// Must be called before the first call to [get]. +pub fn initialize_options(opts: Opts) { + OPTIONS.set(opts).expect("Already initialized"); } +/// Get the servo options +/// +/// If the servo options have not been initialized by calling [initialize_options], then the +/// options will be initialized to default values. Outside of tests the options should +/// be explicitly initialized. #[inline] -pub fn get() -> RwLockReadGuard<'static, Opts> { - OPTIONS.read().unwrap() +pub fn get() -> &'static Opts { + // In unit-tests using default options reduces boilerplate. + // We can't use `cfg(test)` since that only is enabled when this crate + // is compiled in test mode. + // We rely on the `expect` in `initialize_options` to inform us if refactoring + // causes a `get` call to move before `initialize_options`. + OPTIONS.get_or_init(Default::default) } diff --git a/components/servo/lib.rs b/components/servo/lib.rs index 7eb66c6deb5..37ce2019c7a 100644 --- a/components/servo/lib.rs +++ b/components/servo/lib.rs @@ -254,7 +254,7 @@ impl Servo { fn new(builder: ServoBuilder) -> Self { // Global configuration options, parsed from the command line. let opts = builder.opts.map(|opts| *opts); - opts::set_options(opts.unwrap_or_default()); + opts::initialize_options(opts.unwrap_or_default()); let opts = opts::get(); // Set the preferences globally. @@ -1244,7 +1244,7 @@ pub fn run_content_process(token: String) { .unwrap(); let unprivileged_content = unprivileged_content_receiver.recv().unwrap(); - opts::set_options(unprivileged_content.opts()); + opts::initialize_options(unprivileged_content.opts()); prefs::set(unprivileged_content.prefs().clone()); // Enter the sandbox if necessary.