xtask: the wasm check compiles the web app; the web's SVG depth cap follows from its stack

`cargo xtask wasm` (part of `cargo xtask ci`) checked the wasm-safe crates but not
apps/vectorcraft-web, so web-only code was never compiled before a merge. It now runs
`cargo check --target wasm32-unknown-unknown -p vectorcraft-web` too (no Trunk, no network).

The SVG importer's cap on the web was 48, sized from native measurements. rustc links the web
build with a 1 MiB stack (`-z stack-size=1048576`; the app passes no linker arguments of its
own) and usvg uses about 15 kB a level: half the stack at that cost gives 34, set in one place
with the arithmetic.
This commit is contained in:
bflatastic committed 2026-10-14 10:13:45 +07:00
1 parent f1fd8e85e8
commit f774968b20
2 files changed
+20 -6

No files matched your search

+16 -2
View File
@@ -20,8 +20,22 @@ use super::css::{Styles, XNode, parse_decls};
/// that hold one object aren't kept, and what is still deeper is merged into the group around
/// it). usvg uses about 15 kB of stack for each level: the importer runs on a thread with 16 MB
/// ([`vectorcraft_doc::depth::with_deep_stack`]), except on the web, where there is the one
/// 1 MB stack.
pub const MAX_ELEMENT_DEPTH: usize = if cfg!(target_arch = "wasm32") { 48 } else { 256 };
/// stack: [`WEB_DEPTH`] there.
pub const MAX_ELEMENT_DEPTH: usize = if cfg!(target_arch = "wasm32") { WEB_DEPTH } else { 256 };
/// The stack of the web build: rustc links `wasm32-unknown-unknown` with
/// `-z stack-size=1048576` (`rustc --print link-args` shows it), and the web app gives the linker
/// no arguments of its own (`apps/vectorcraft-web`: `Trunk.toml`, `index.html`, no rustflags).
const WEB_STACK: usize = 1 << 20;
/// The stack usvg uses for each level of elements: about 70 levels overflowed the 1 MB main
/// thread of Windows. Measured natively, never in a browser.
const LEVEL_STACK: usize = 15 << 10;
/// The deepest elements may nest on the web: half its stack at usvg's cost a level, the other
/// half left for what is on the stack when a file is opened and for the cost being a native
/// measure. 1,048,576 / (2 × 15,360) = 34.
const WEB_DEPTH: usize = WEB_STACK / (2 * LEVEL_STACK);
/// Properties whose value an element's descendants use too: the paint server they name is
/// converted at each descendant, under everything between.
+4 -4
View File
@@ -25,7 +25,7 @@ commands:
assets check that every icon/image/font/asset is attributed in ASSETS.md
brands check that user-visible text (labels, params docs, MCP, docs, packaging) names no other vendor's products
layers enforce the crate dependency layering (plan/architecture.md §3)
wasm cargo check --target wasm32-unknown-unknown for the wasm-safe crates
wasm cargo check --target wasm32-unknown-unknown for the wasm-safe crates and the web app
ci fmt --check, clippy -D warnings, test, assets, brands, layers, wasm (stops at first failure)
corpus [--download] [--affinity]
show where test corpora live; --download fetches PngSuite into corpus/pngsuite,
@@ -141,8 +141,8 @@ fn cmd_layers() -> Result<(), String> {
}
}
/// Workspace packages that must build for wasm32: all L0–L5 crates plus
/// the egui shell.
/// Workspace packages that must build for wasm32: all L0–L5 crates, the egui
/// shell, and the web app (its wasm-only code is compiled by nothing else).
fn wasm_set() -> Result<Vec<String>, String> {
let crates = layers::from_metadata(&metadata()?)?;
Ok(crates
@@ -150,7 +150,7 @@ fn wasm_set() -> Result<Vec<String>, String> {
.filter(|c| match layers::classify(&c.name) {
Some(layers::Class::Layer(l)) => l <= 5 || layers::short_name(&c.name) == "ui-egui",
Some(layers::Class::Standalone) => true,
_ => false,
_ => layers::short_name(&c.name) == "web",
})
.map(|c| c.name)
.collect())