Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions apps/chuzz/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,10 @@ tauri.workspace = true
tauri-runtime-blitz.workspace = true

[dev-dependencies]
# `flavor = "multi_thread"` in the script-fetch test: the blocking fetch takes
# the `block_in_place` path, which only the multi-threaded runtime has, and
# that is the path the capture actually uses.
tokio = { workspace = true, features = ["macros", "rt", "rt-multi-thread", "sync", "time"] }
# Assembles `fixtures/panel.wat` into a module in-process, so the capture test
# owns its guest instead of borrowing blitz-wasm's demo, and so it needs no
# wasm32 target and no nested cargo build. See the header of that file.
Expand Down
38 changes: 23 additions & 15 deletions apps/chuzz/frontend/bun.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions apps/chuzz/frontend/local-ui/bundle/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@
"**/*"
],
"peerDependencies": {
"@pathscale/ui": "^2.5.0",
"solid-js": "^1.9.5",
"solid-layouts": "^0.1.3"
"@pathscale/ui": "^2.11.9",
"solid-js": ">=2.0.0-rc.0",
"solid-layouts": "^0.2.1"
},
"solidLayouts": "./layouts.manifest.json"
}
6 changes: 3 additions & 3 deletions apps/chuzz/frontend/local-ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
"**/*.css"
],
"peerDependencies": {
"@pathscale/ui": "^2.5.0",
"solid-js": "^1.9.5",
"solid-layouts": "^0.1.3"
"@pathscale/ui": "^2.11.9",
"solid-js": ">=2.0.0-rc.0",
"solid-layouts": "^0.2.1"
}
}
12 changes: 7 additions & 5 deletions apps/chuzz/frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,25 +29,27 @@
"dependencies": {
"@chuzz/ui": "workspace:*",
"@iconify/tailwind4": "^1.0.6",
"@pathscale/ui": "2.7.4",
"@solidjs/web": "2.0.0-rc.0",
"@pathscale/ui": "^2.11.10",
"@solidjs/web": "2.0.0-rc.4",
"@tauri-apps/api": "^2.1.1",
"clsx": "^2.1.1",
"popmotion": "^11.0.5",
"solid-js": "2.0.0-rc.0",
"solid-js": "2.0.0-rc.4",
"solid-layouts": "^0.2.1",
"tailwind-merge": "^3.6.0"
},
"devDependencies": {
"@biomejs/biome": "^2.4.15",
"@iconify-json/lucide": "^1.2.127",
"@iconify-json/mdi": "^1.2.3",
"@rsbuild/core": "^1.3.20",
"@rsbuild/plugin-babel": "^1.0.5",
"@rsbuild/plugin-solid": "^1.0.5",
"@solidjs/testing-library": "1.0.0-beta.2",
"@tailwindcss/postcss": "^4.1.7",
"@testing-library/jest-dom": "^7.0.0",
"@types/node": "^22.15.17",
"babel-preset-solid": "2.0.0-rc.0",
"babel-preset-solid": "^2.0.0-rc.2",
"fork-ts-checker-webpack-plugin": "^9.1.0",
"jsdom": "^30.0.0",
"rsbuild-plugin-solid-layouts": "^0.2.1",
Expand All @@ -58,6 +60,6 @@
"vitest": "^4.1.10"
},
"overrides": {
"babel-preset-solid": "2.0.0-rc.0"
"babel-preset-solid": "^2.0.0-rc.2"
}
}
6 changes: 3 additions & 3 deletions apps/chuzz/frontend/src/styles/theme.css
Original file line number Diff line number Diff line change
Expand Up @@ -598,9 +598,9 @@
}

/*
* `@theme` emits the app-specific variables outside the DaisyUI theme layer.
* Keep their light counterparts outside that layer too, or the unlayered dark
* values win the cascade even when the root carries `data-color-mode=light`.
* `@theme` emits the app-specific variables outside the theme layer. Keep their
* light counterparts outside that layer too, or the unlayered dark values win
* the cascade even when the root carries `data-color-mode=light`.
*/
[data-theme="24x-dark"][data-color-mode="light"] {
/* Tailwind's `white/N` utilities are translucent interface surfaces in this app. */
Expand Down
40 changes: 24 additions & 16 deletions apps/chuzz/src/browser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,20 @@ struct WasmPage {
module: std::path::PathBuf,
}

/// How long the window waits for a script the page asked for while running.
///
/// Shorter than the capture's, and the reason is worth stating plainly:
/// `ScriptFetcher::fetch` is synchronous and the page's scripts run on the UI
/// thread, so this blocks the whole window, other tabs included, for as long
/// as it waits. The alternative is what happened before, which was to drop the
/// script and render a page missing whatever it was going to build. A short
/// stall is the better of the two, but only a short one; a page cannot be
/// allowed to freeze the browser because one of its servers went quiet.
///
/// The real answer is an asynchronous script-loading path in the engine, which
/// would not need to choose.
const WINDOW_SCRIPT_DEADLINE: std::time::Duration = std::time::Duration::from_secs(5);

struct BrowserInner {
state: Mutex<BrowserState>,
log: Mutex<DebugLog>,
Expand Down Expand Up @@ -556,7 +570,11 @@ impl Browser {
// certain the document is exactly what the page said.
let mut page =
blitz_script::ScriptDocument::from_html(&html, make_config())
.with_fetcher(PrefetchedScripts { scripts });
.with_fetcher(crate::script_fetch::PageScripts::new(
scripts,
Arc::clone(&self.0.net),
WINDOW_SCRIPT_DEADLINE,
));
page.eval(WEB_API_SHIM);
page.execute_scripts();
let title = page
Expand All @@ -573,7 +591,11 @@ impl Browser {
wasm: None,
} => {
let mut page = blitz_script::ScriptDocument::from_html(&html, make_config())
.with_fetcher(PrefetchedScripts { scripts });
.with_fetcher(crate::script_fetch::PageScripts::new(
scripts,
Arc::clone(&self.0.net),
WINDOW_SCRIPT_DEADLINE,
));
page.eval(WEB_API_SHIM);
page.execute_scripts();
let title = page
Expand Down Expand Up @@ -653,20 +675,6 @@ impl NavigationProvider for PageNavigation {
}
}

struct PrefetchedScripts {
scripts: HashMap<Url, String>,
}

impl blitz_script::ScriptFetcher for PrefetchedScripts {
fn fetch(&self, url: &Url) -> Result<String, blitz_script::FetchError> {
self.scripts
.get(url)
.cloned()
.map(Ok)
.unwrap_or_else(|| blitz_script::DefaultScriptFetcher.fetch(url))
}
}

/// Build a page document by letting a WebAssembly guest construct it.
///
/// The config is the page config the HTML path uses, so the guest's document
Expand Down
23 changes: 23 additions & 0 deletions apps/chuzz/src/capture.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,29 @@ fn capture_scale() -> f32 {
.unwrap_or(1.0)
}

/// CSS pixel size to lay the page out at. Defaults to 1440 by 960.
///
/// A capture is only comparable against a reference browser when both laid the
/// page out at the same width: every responsive breakpoint, every percentage
/// width and every centred box moves with it. These were exported by
/// `scripts/render-check.sh` and read by nothing, so a run at another size
/// silently produced the default and the resulting diff was all viewport and
/// no signal.
pub fn capture_viewport() -> (u32, u32) {
fn dimension(name: &str, fallback: u32) -> u32 {
std::env::var(name)
.ok()
.and_then(|value| value.parse().ok())
.filter(|pixels: &u32| *pixels > 0)
.unwrap_or(fallback)
}

(
dimension("CHUZZ_CAPTURE_WIDTH", 1440),
dimension("CHUZZ_CAPTURE_HEIGHT", 960),
)
}

/// Which colour scheme to render at. Defaults to dark.
///
/// A site that respects `prefers-color-scheme` is a different page in each, so
Expand Down
Loading
Loading