makepad/platform/script/census/tests/census.rs
Admin 62d4f31b1e script: Splash VM heaps, isolates and lazy system modules
Every heap ref carries its heap tag, generation checks always on, rooted
async values. Splash isolates get a domain table and curated minimal
preludes; system modules under `mod` expand lazily on first touch. No
wall-clock script caps: isolation and force-stop instead.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-13 12:26:21 +02:00

84 lines
3.7 KiB
Rust

//! The module census keeps every module whose definitions a used module
//! names, so a web build cut by it still registers all it evaluates.
use makepad_script::*;
fn test_vm() -> ScriptVm<'static> {
let host = Box::leak(Box::new(ScriptVmHost::new(0i32, ())));
ScriptVm {
host: host.host_context(),
bx: Box::new(ScriptVmBase::new()),
}
}
fn script(module_path: &str, file: &str, code: &str) -> ScriptMod {
ScriptMod::new("", &module_path, &file, 0, 0, &code, &[])
}
fn register(vm: &mut ScriptVm, module_path: &'static str, code: &str) {
vm.census_begin(module_path);
vm.eval(script(module_path, module_path, code));
vm.census_end();
}
#[test]
fn a_spread_definition_is_used_by_the_module_that_spreads_it() {
let vm = &mut test_vm();
vm.new_module(id!(cz));
makepad_script_census::census_record(vm);
// `vector` is only ever spread by `svg` (its fields are copied at
// registration: no heap edge leads to it); `unused` nobody names.
register(vm, "t::vector", "mod.cz.Vector = {fill: 1}");
register(vm, "t::svg", "mod.cz.Svg = {stroke: 2, ..mod.cz.Vector}");
register(vm, "t::unused", "mod.cz.Unused = {x: 3}");
// The app holds an Svg.
let app = vm.eval(script("app", "app", "let held = mod.cz.Svg{stroke: 4}\nheld"));
if let Some(obj) = app.as_object() {
std::mem::forget(vm.bx.heap.new_object_ref(obj));
}
let used = makepad_script_census::census_used(vm).expect("recording");
assert!(used.used.contains_key("t::svg"), "{used:?}");
assert!(used.used.contains_key("t::vector"), "a spread definition must stay: {used:?}");
assert!(!used.used.contains_key("t::unused"), "{used:?}");
}
#[test]
fn the_app_crate_is_a_root_with_everything_it_names() {
let vm = &mut test_vm();
vm.new_module(id!(cz));
makepad_script_census::census_record(vm);
register(vm, "lib::window", "mod.cz.Window = {title: 1}");
register(vm, "lib::unused", "mod.cz.Unused = {x: 3}");
// The app registers its UI inside its own script_mod, and Rust holds it
// from there on: no walk from the app's objects starts at it.
vm.census_begin("app");
let ui = vm.eval(script("app", "app", "mod.cz.Ui = mod.cz.Window{title: 2}\nmod.cz.Ui"));
if let Some(obj) = ui.as_object() {
std::mem::forget(vm.bx.heap.new_object_ref(obj));
}
vm.census_end();
let used = makepad_script_census::census_used_from(vm, &["app"]).expect("recording");
assert!(used.used.contains_key("app"), "{used:?}");
assert!(used.used.contains_key("lib::window"), "what the app names is used: {used:?}");
assert!(!used.used.contains_key("lib::unused"), "{used:?}");
}
#[test]
fn a_registration_that_patches_a_used_definition_is_used() {
let vm = &mut test_vm();
vm.new_module(id!(cz));
makepad_script_census::census_record(vm);
// `hardware` sets no name of its own: it replaces a field of `sampling`'s
// definition (render's hardware shadow sampling), and `shader` spreads it.
register(vm, "t::sampling", "mod.cz.Sampling = {map: {kind: 1}}");
register(vm, "t::hardware", "mod.cz.Sampling.map = {kind: 2}");
register(vm, "t::shader", "mod.cz.Shader = {..mod.cz.Sampling}");
register(vm, "t::unused", "mod.cz.Unused = {x: 3}");
let app = vm.eval(script("app", "app", "let held = mod.cz.Shader{}\nheld"));
if let Some(obj) = app.as_object() {
std::mem::forget(vm.bx.heap.new_object_ref(obj));
}
let used = makepad_script_census::census_used(vm).expect("recording");
assert!(used.used.contains_key("t::sampling"), "{used:?}");
assert!(used.used.contains_key("t::hardware"), "a patch of a used definition must stay: {used:?}");
assert!(!used.used.contains_key("t::unused"), "{used:?}");
}