script: Move code generation and webidl files to new script_bindings crate. (#35157)

Signed-off-by: Josh Matthews <josh@joshmatthews.net>
This commit is contained in:
Josh Matthews 2025-01-24 15:47:43 -05:00 committed by GitHub
parent a88b59534f
commit af8d7c2de7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
469 changed files with 187 additions and 137 deletions

13
Cargo.lock generated
View file

@ -6176,14 +6176,13 @@ dependencies = [
"parking_lot",
"percent-encoding",
"phf",
"phf_codegen",
"phf_shared 0.11.2",
"pixels",
"profile_traits",
"range",
"ref_filter_map",
"regex",
"ring",
"script_bindings",
"script_layout_interface",
"script_traits",
"selectors",
@ -6220,6 +6219,16 @@ dependencies = [
"xml5ever",
]
[[package]]
name = "script_bindings"
version = "0.0.1"
dependencies = [
"phf_codegen",
"phf_shared 0.11.2",
"serde_json",
"style",
]
[[package]]
name = "script_layout_interface"
version = "0.0.1"

View file

@ -21,17 +21,12 @@ tracing = ["dep:tracing"]
webgl_backtrace = ["canvas_traits/webgl_backtrace"]
js_backtrace = []
refcell_backtrace = ["accountable-refcell"]
webxr = ["webxr-api"]
webgpu = []
webxr = ["webxr-api", "script_bindings/webxr"]
webgpu = ["script_bindings/webgpu"]
[lints.rust]
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(crown)'] }
[build-dependencies]
phf_codegen = "0.11"
phf_shared = "0.11"
serde_json = { workspace = true }
[dependencies]
aes = { workspace = true }
aes-kw = { workspace = true }
@ -99,6 +94,7 @@ range = { path = "../range" }
ref_filter_map = "1.0.1"
regex = { workspace = true }
ring = { workspace = true }
script_bindings = { path = "../script_bindings" }
script_layout_interface = { workspace = true }
script_traits = { workspace = true }
selectors = { workspace = true }

View file

@ -2,121 +2,11 @@
* 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 std::fs::File;
use std::io::Write;
use std::path::PathBuf;
use std::process::Command;
use std::time::Instant;
use std::{env, fmt};
use phf_shared::{self, FmtConst};
use serde_json::{self, Value};
use std::env;
fn main() {
let start = Instant::now();
let style_out_dir = PathBuf::from(env::var_os("DEP_SERVO_STYLE_CRATE_OUT_DIR").unwrap());
let css_properties_json = style_out_dir.join("css-properties.json");
let out_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap());
println!("cargo::rerun-if-changed=dom/webidls");
println!("cargo::rerun-if-changed=dom/bindings/codegen");
println!("cargo::rerun-if-changed={}", css_properties_json.display());
println!("cargo::rerun-if-changed=../../third_party/WebIDL/WebIDL.py");
// NB: We aren't handling changes in `third_party/ply` here.
let status = Command::new(find_python())
.arg("dom/bindings/codegen/run.py")
.arg(&css_properties_json)
.arg(&out_dir)
.status()
.unwrap();
if !status.success() {
std::process::exit(1)
}
println!("Binding generation completed in {:?}", start.elapsed());
let json = out_dir.join("InterfaceObjectMapData.json");
let json: Value = serde_json::from_reader(File::open(json).unwrap()).unwrap();
let mut map = phf_codegen::Map::new();
for (key, value) in json.as_object().unwrap() {
map.entry(Bytes(key), value.as_str().unwrap());
}
let phf = PathBuf::from(env::var_os("OUT_DIR").unwrap()).join("InterfaceObjectMapPhf.rs");
let mut phf = File::create(phf).unwrap();
writeln!(
&mut phf,
"pub(crate) static MAP: phf::Map<&'static [u8], fn(JSContext, HandleObject)> = {};",
map.build(),
)
.unwrap();
}
#[derive(Eq, Hash, PartialEq)]
struct Bytes<'a>(&'a str);
impl FmtConst for Bytes<'_> {
fn fmt_const(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "b\"{}\"", self.0)
}
}
impl phf_shared::PhfHash for Bytes<'_> {
fn phf_hash<H: std::hash::Hasher>(&self, hasher: &mut H) {
self.0.as_bytes().phf_hash(hasher)
}
}
/// Tries to find a suitable python
///
/// Algorithm
/// 1. Trying to find python3/python in $VIRTUAL_ENV (this should be from Servo's venv)
/// 2. Checking PYTHON3 (set by mach)
/// 3. Falling back to the system installation.
///
/// Note: This function should be kept in sync with the version in `components/servo/build.rs`
fn find_python() -> PathBuf {
let mut candidates = vec![];
if let Some(venv) = env::var_os("VIRTUAL_ENV") {
let bin_directory = PathBuf::from(venv).join("bin");
let python3 = bin_directory.join("python3");
if python3.exists() {
candidates.push(python3);
}
let python = bin_directory.join("python");
if python.exists() {
candidates.push(python);
}
};
if let Some(python3) = env::var_os("PYTHON3") {
let python3 = PathBuf::from(python3);
if python3.exists() {
candidates.push(python3);
}
}
let system_python = ["python3", "python"].map(PathBuf::from);
candidates.extend_from_slice(&system_python);
for name in &candidates {
// Command::new() allows us to omit the `.exe` suffix on windows
if Command::new(name)
.arg("--version")
.output()
.is_ok_and(|out| out.status.success())
{
return name.to_owned();
}
}
let candidates = candidates
.into_iter()
.map(|c| c.into_os_string())
.collect::<Vec<_>>();
panic!(
"Can't find python (tried {:?})! Try enabling Servo's Python venv, \
setting the PYTHON3 env var or adding python3 to PATH.",
candidates.join(", ".as_ref())
)
println!(
"cargo:rustc-env=BINDINGS_OUT_DIR={}",
env::var("DEP_SCRIPT_BINDINGS_CRATE_OUT_DIR").unwrap(),
);
}

View file

@ -174,28 +174,28 @@ pub(crate) mod xmlname;
#[allow(missing_docs, non_snake_case)]
pub(crate) mod codegen {
pub(crate) mod DomTypeHolder {
include!(concat!(env!("OUT_DIR"), "/DomTypeHolder.rs"));
include!(concat!(env!("BINDINGS_OUT_DIR"), "/DomTypeHolder.rs"));
}
pub(crate) mod DomTypes {
include!(concat!(env!("OUT_DIR"), "/DomTypes.rs"));
include!(concat!(env!("BINDINGS_OUT_DIR"), "/DomTypes.rs"));
}
#[allow(dead_code)]
pub(crate) mod Bindings {
include!(concat!(env!("OUT_DIR"), "/Bindings/mod.rs"));
include!(concat!(env!("BINDINGS_OUT_DIR"), "/Bindings/mod.rs"));
}
pub(crate) mod InterfaceObjectMap {
include!(concat!(env!("OUT_DIR"), "/InterfaceObjectMap.rs"));
include!(concat!(env!("BINDINGS_OUT_DIR"), "/InterfaceObjectMap.rs"));
}
#[allow(dead_code, unused_imports, clippy::enum_variant_names)]
pub(crate) mod InheritTypes {
include!(concat!(env!("OUT_DIR"), "/InheritTypes.rs"));
include!(concat!(env!("BINDINGS_OUT_DIR"), "/InheritTypes.rs"));
}
#[allow(clippy::upper_case_acronyms)]
pub(crate) mod PrototypeList {
include!(concat!(env!("OUT_DIR"), "/PrototypeList.rs"));
include!(concat!(env!("BINDINGS_OUT_DIR"), "/PrototypeList.rs"));
}
pub(crate) mod RegisterBindings {
include!(concat!(env!("OUT_DIR"), "/RegisterBindings.rs"));
include!(concat!(env!("BINDINGS_OUT_DIR"), "/RegisterBindings.rs"));
}
#[allow(
non_camel_case_types,
@ -206,6 +206,6 @@ pub(crate) mod codegen {
clippy::enum_variant_names
)]
pub(crate) mod UnionTypes {
include!(concat!(env!("OUT_DIR"), "/UnionTypes.rs"));
include!(concat!(env!("BINDINGS_OUT_DIR"), "/UnionTypes.rs"));
}
}

View file

@ -206,7 +206,7 @@
pub(crate) mod macros;
pub(crate) mod types {
include!(concat!(env!("OUT_DIR"), "/InterfaceTypes.rs"));
include!(concat!(env!("BINDINGS_OUT_DIR"), "/InterfaceTypes.rs"));
}
pub(crate) mod abortcontroller;

View file

@ -0,0 +1,28 @@
[package]
name = "script_bindings"
build = "build.rs"
version.workspace = true
authors.workspace = true
license.workspace = true
edition.workspace = true
publish.workspace = true
rust-version.workspace = true
# https://github.com/rust-lang/cargo/issues/3544
links = "script_bindings_crate"
[lib]
name = "script_bindings"
path = "lib.rs"
[build-dependencies]
phf_codegen = "0.11"
phf_shared = "0.11"
serde_json = { workspace = true }
[dependencies]
style = { workspace = true }
[features]
webgpu = []
webxr = []

View file

@ -0,0 +1,124 @@
/* 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 std::fs::File;
use std::io::Write;
use std::path::PathBuf;
use std::process::Command;
use std::time::Instant;
use std::{env, fmt};
use phf_shared::{self, FmtConst};
use serde_json::{self, Value};
fn main() {
let start = Instant::now();
let style_out_dir = PathBuf::from(env::var_os("DEP_SERVO_STYLE_CRATE_OUT_DIR").unwrap());
let css_properties_json = style_out_dir.join("css-properties.json");
let out_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap());
println!("cargo:out_dir={}", out_dir.display());
println!("cargo::rerun-if-changed=webidls");
println!("cargo::rerun-if-changed=codegen");
println!("cargo::rerun-if-changed={}", css_properties_json.display());
println!("cargo::rerun-if-changed=../../third_party/WebIDL/WebIDL.py");
// NB: We aren't handling changes in `third_party/ply` here.
let status = Command::new(find_python())
.arg("codegen/run.py")
.arg(&css_properties_json)
.arg(&out_dir)
.status()
.unwrap();
if !status.success() {
std::process::exit(1)
}
println!("Binding generation completed in {:?}", start.elapsed());
let json = out_dir.join("InterfaceObjectMapData.json");
let json: Value = serde_json::from_reader(File::open(json).unwrap()).unwrap();
let mut map = phf_codegen::Map::new();
for (key, value) in json.as_object().unwrap() {
map.entry(Bytes(key), value.as_str().unwrap());
}
let phf = PathBuf::from(env::var_os("OUT_DIR").unwrap()).join("InterfaceObjectMapPhf.rs");
let mut phf = File::create(phf).unwrap();
writeln!(
&mut phf,
"pub(crate) static MAP: phf::Map<&'static [u8], fn(JSContext, HandleObject)> = {};",
map.build(),
)
.unwrap();
}
#[derive(Eq, Hash, PartialEq)]
struct Bytes<'a>(&'a str);
impl FmtConst for Bytes<'_> {
fn fmt_const(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "b\"{}\"", self.0)
}
}
impl phf_shared::PhfHash for Bytes<'_> {
fn phf_hash<H: std::hash::Hasher>(&self, hasher: &mut H) {
self.0.as_bytes().phf_hash(hasher)
}
}
/// Tries to find a suitable python
///
/// Algorithm
/// 1. Trying to find python3/python in $VIRTUAL_ENV (this should be from Servo's venv)
/// 2. Checking PYTHON3 (set by mach)
/// 3. Falling back to the system installation.
///
/// Note: This function should be kept in sync with the version in `components/servo/build.rs`
fn find_python() -> PathBuf {
let mut candidates = vec![];
if let Some(venv) = env::var_os("VIRTUAL_ENV") {
let bin_directory = PathBuf::from(venv).join("bin");
let python3 = bin_directory.join("python3");
if python3.exists() {
candidates.push(python3);
}
let python = bin_directory.join("python");
if python.exists() {
candidates.push(python);
}
};
if let Some(python3) = env::var_os("PYTHON3") {
let python3 = PathBuf::from(python3);
if python3.exists() {
candidates.push(python3);
}
}
let system_python = ["python3", "python"].map(PathBuf::from);
candidates.extend_from_slice(&system_python);
for name in &candidates {
// Command::new() allows us to omit the `.exe` suffix on windows
if Command::new(name)
.arg("--version")
.output()
.is_ok_and(|out| out.status.success())
{
return name.to_owned();
}
}
let candidates = candidates
.into_iter()
.map(|c| c.into_os_string())
.collect::<Vec<_>>();
panic!(
"Can't find python (tried {:?})! Try enabling Servo's Python venv, \
setting the PYTHON3 env var or adding python3 to PATH.",
candidates.join(", ".as_ref())
)
}

View file

@ -8229,7 +8229,7 @@ class GlobalGenRoots():
], "\n")), pre="#[derive(Clone, Copy)]\npub(crate) struct Globals: u8 {\n", post="\n}")
globals_ = CGWrapper(CGIndenter(global_flags), pre="bitflags::bitflags! {\n", post="\n}")
phf = CGGeneric("include!(concat!(env!(\"OUT_DIR\"), \"/InterfaceObjectMapPhf.rs\"));")
phf = CGGeneric("include!(concat!(env!(\"BINDINGS_OUT_DIR\"), \"/InterfaceObjectMapPhf.rs\"));")
return CGList([
CGGeneric(AUTOGENERATED_WARNING_COMMENT),

View file

@ -8,7 +8,7 @@ import json
import re
SCRIPT_PATH = os.path.abspath(os.path.dirname(__file__))
SERVO_ROOT = os.path.abspath(os.path.join(SCRIPT_PATH, "..", "..", "..", "..", ".."))
SERVO_ROOT = os.path.abspath(os.path.join(SCRIPT_PATH, "..", "..", ".."))
FILTER_PATTERN = re.compile("// skip-unless ([A-Z_]+)\n")
@ -23,7 +23,7 @@ def main():
# Do not ascend above the target dir, because it may not be called target
# or even have a parent (see CARGO_TARGET_DIR).
doc_servo = os.path.join(out_dir, "..", "..", "..", "..", "doc")
webidls_dir = os.path.join(SCRIPT_PATH, "..", "..", "webidls")
webidls_dir = os.path.join(SCRIPT_PATH, "..", "webidls")
config_file = "Bindings.conf"
import WebIDL

View file

@ -0,0 +1,3 @@
/* 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/. */

Some files were not shown because too many files have changed in this diff Show more