api: Flatten and simplify Servo preferences (#34966)

Flatten and simplify Servo's preferences code. In addition, have both
preferences and options passed in as arguments to `Servo::new()` and
make sure not to use the globally set preferences in `servoshell` (as
much as possible now).

Instead of a complex procedural macro to generate preferences, just
expose a very simple derive macro that adds string based getters and
setters.

- All command-line parsing is moved to servoshell.
- There is no longer the concept of a missing preference.
- Preferences no longer have to be part of the resources bundle because
  they now have reasonable default values.
- servoshell specific preferences are no longer part of the preferences
  exposed by the Servo API.

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
This commit is contained in:
Martin Robinson 2025-01-14 14:54:06 +01:00 committed by GitHub
parent c4c85affb5
commit 0e616e0c5d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
316 changed files with 2088 additions and 3235 deletions

View file

@ -0,0 +1,19 @@
[package]
name = "servo_config_macro"
version.workspace = true
authors.workspace = true
license.workspace = true
edition.workspace = true
publish.workspace = true
rust-version.workspace = true
[lib]
name = "servo_config_macro"
proc-macro = true
path = "lib.rs"
[dependencies]
proc-macro2 = { workspace = true }
quote = { workspace = true }
syn = { workspace = true }
synstructure = { workspace = true }

View file

@ -0,0 +1,55 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* 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/. */
use proc_macro2::TokenStream;
use quote::quote;
use syn::{Data, Fields};
use synstructure::decl_derive;
decl_derive!([ServoPreferences] => servo_preferences_derive);
/// A derive macro that adds string-based getter and setter for each field of this struct
/// (enums and other types are not supported). Each field must be able to be convertable
/// (with `into()`) into a `PrefValue`.
fn servo_preferences_derive(input: synstructure::Structure) -> TokenStream {
let ast = input.ast();
let Data::Struct(ref data) = ast.data else {
unimplemented!();
};
let Fields::Named(ref named_fields) = data.fields else {
unimplemented!()
};
let mut get_match_cases = quote!();
for field in named_fields.named.iter() {
let name = field.ident.as_ref().unwrap();
get_match_cases.extend(quote!(stringify!(#name) => self.#name.clone().into(),))
}
let mut set_match_cases = quote!();
for field in named_fields.named.iter() {
let name = field.ident.as_ref().unwrap();
set_match_cases.extend(quote!(stringify!(#name) => self.#name = value.try_into().unwrap(),))
}
let structure_name = &ast.ident;
quote! {
impl #structure_name {
pub fn get_value(&self, name: &str) -> PrefValue {
match name {
#get_match_cases
_ => { panic!("Unknown preference: {:?}", name); }
}
}
pub fn set_value(&mut self, name: &str, value: PrefValue) {
match name {
#set_match_cases
_ => { panic!("Unknown preference: {:?}", name); }
}
}
}
}
}