servo WebIDL Python codegen is incompatible with Nix hermetic sandbox.
Build weft-servo-shell and weft-app-shell without servo-embed feature
so the VM infrastructure compiles cleanly. The full servo-embed build
is performed separately via cargo on a Linux host.
Add oxalica/rust-overlay flake input; override rustPlatform in
weft-packages.nix with cargo/rustc from rust-bin.stable.1.93.0;
apply overlay in both devShell and nixosConfigurations.weft-vm.
Fixes build failure where nixos-25.05 Rust 1.86.0 was below the
rust-version requirement of wasmtime and other dependencies.
- weft-packages.nix: add weft-servo-shell and weft-app-shell with servo-embed
feature; real sha256 hashes for servo (8e7dc40) and stylo (dca3934) git deps
computed via nix-prefetch-git; add clang/cmake/python3 as native build inputs
for servo packages; set LIBCLANG_PATH; disable doCheck for VM builds
- configuration.nix: import virtualisation/qemu-vm.nix for system.build.vm;
replace hardware.opengl with hardware.graphics (NixOS 24.11); add
weft-servo-shell systemd user service; add servo-shell/app-shell/pack to
environment packages
- infra/vm/build.sh: switch to system.build.vm target (qcow2 attribute not
provided by default NixOS modules)
- infra/vm/run.sh: invoke the VM script produced by system.build.vm
- Replace Mesa-libEGL-devel and Mesa-libGLES-devel (do not exist on
openSUSE) with libglvnd-devel (Khronos EGL/GLES dispatch headers)
- Replace libseat-devel (does not exist on openSUSE) with seatd-devel
Package names confirmed via rpmfind.net against Tumbleweed and Leap
repositories.
In environments where XDG_RUNTIME_DIR/systemd/private exists but the
user systemd session is not functional, systemd_cgroup_available()
returns true and the test script is wrapped with systemd-run, which
fails immediately, causing ChildStdout to return EOF before READY.
Set WEFT_DISABLE_CGROUP=1 for the duration of the test and restore
it on exit.
- IoView/WasiView split: implement IoView for State, remove table()
from WasiView impl
- preopened_dir: new signature takes host path and guest path directly
- LinkerInstance::func_wrap returns Result in wasmtime 30; use a
variable for the clipboard LinkerInstance
- Set PR_SET_NO_NEW_PRIVS before applying the seccomp filter
- Unconditional syscall block uses empty Vec<SeccompRule>
- flake.nix, infra/nixos/: NixOS VM with Mesa, virtio-gpu, Wayland,
systemd user services for compositor and session supervisor
- infra/vm/: QEMU build and run scripts
- .github/workflows/ci.yml: add Linux job to type-check weft-servo-shell
and weft-app-shell with --features servo-embed
- docs/architecture.md, docs/security.md, docs/building.md: replace
stale pre-implementation design documents
- README.md: rewrite to reflect current codebase
- crates/weft-servo-shell/SERVO_PIN.md: update implementation status and add
SpiderMonkey process boundary statement
- examples/org.weft.demo.counter: stateless counter Wasm component
using weft:app/ipc for increment/decrement/reset; built for
wasm32-wasip2 with wit-bindgen 0.53; dark-themed HTML UI
- examples/org.weft.demo.notes: persistent notes Wasm component
using weft:app/ipc + WASI preopened /data dir (fs:rw:app-data);
save/load via newline-delimited IPC protocol; HTML textarea UI
- examples/keys/: committed demo Ed25519 keypair; both packages
signed with weft-pack sign
- workspace Cargo.toml: exclude examples from workspace members
(they target wasm32-wasip2, not the host toolchain)
- SERVO_PIN.md: update deps section and document shell-client display sharing resolved in
full description of connect_with_display implementation
- Add servo/winit/softbuffer as optional deps in weft-servo-shell and
weft-app-shell Cargo.toml, gated on servo-embed feature
- Replace ShellClient::connect() and connect_as_app() with
connect_with_display() and connect_as_app_with_display(), using
Backend::from_foreign_display to share the winit wl_display connection
- Move ShellClient construction into resumed() in both embedders after
winit window and wl_surface are available
- Pass actual wl_surface to create_window instead of None
- Fix pre-existing field name bug: wayland-scanner generates _type for
the reserved keyword arg name=type, not r#type
Add weft-app-shell binary: takes <app_id> <session_id> args, connects to
zweft_shell_manager_v1 as an application window, resolves the app UI URL,
and runs a single Servo WebView in an isolated process. Prints READY to
stdout after the window is initialised so weft-appd can track the session
lifecycle.
weft-appd runtime.rs: after weft-runtime emits READY, spawn weft-app-shell
(WEFT_APP_SHELL_BIN env var) alongside it. The app shell is killed when the
session ends via abort or natural runtime exit.
weft-servo-shell: remove in-process app WebView management. The shell now
manages the system UI WebView only; all app rendering happens in dedicated
weft-app-shell processes.
Wire ShellClient into App so its Wayland event queue is dispatched each
frame via about_to_wait. This ensures configure, focus_changed, and
window_closed events from the compositor are processed. window_closed
now triggers a clean Servo shutdown.
The EGL rendering path (WindowRenderingContext + surfman eglSwapBuffers)
produces frames transparently via Mesa DMA-BUF buffer sharing; no
explicit zwp_linux_dmabuf_v1 code is required in the shell.
Remaining: ZweftShellWindowV1 is created with surface=null; sharing the
winit wl_surface with the shell client connection is not currently
feasible without refactoring to a single shared Wayland connection.
backdrop-filter is fully implemented across two commits:
- marcoallegretti/stylo servo-weft f1ba496: enables backdrop-filter parsing
- marcoallegretti/servo servo-weft 8e7dc40: wires stacking context and display list
- CSS Grid is implemented via Taffy; backdrop-filter is the remaining unimplemented property
- Document the two-step implementation: stylo parsing enable + display list wiring
- Add Stylo fork section with patch template and step-by-step instructions
- Expand per-app process isolation section with clearer implementation detail
Fork: https://github.com/marcoallegretti/servo
Branch: servo-weft
Base rev: 04ca254f843ed650d3e5b14e5693ad51a60cc84b (upstream main 2026-03-11)
Update the Cargo snippet and update policy to match the fork-and-PR workflow.
The READY timeout branch killed the process and returned Ok(()) without
calling remove_abort_sender(), leaving a spent entry in abort_senders.
Add the call to keep it consistent with all other exit paths.
Path::starts_with is component-aware but does not resolve .., so
/allowed/../etc/passwd would pass the check. Add normalize_path() that
lexically resolves . and .. components without touching the filesystem
so the check works on non-existent paths too. Add regression test.
std::fs::write fails when the destination parent does not exist.
Add create_dir_all before the write so apps can store files in
nested paths (e.g. config/sub/settings.json) without pre-creating
directories. Add regression test for the nested-path case.
Previously the supervisor returned Ok(()) without updating the session
state, leaving it in Starting indefinitely. Now it sets state to
Stopped, removes the abort sender, and broadcasts AppState:stopped
before returning, consistent with every other early-exit path.
RUNNING_APPS response now produces a SyncSessions command instead of
individual Launch commands. The embedder retains only WebViews whose
session_id is in the active list (removes stale entries from sessions
that stopped during a disconnect), then creates WebViews for any
sessions not yet tracked. This is idempotent thanks to the existing
contains_key guard in create_app_webview.
When a runtime process exits naturally (not via TerminateApp) the
oneshot Sender remained in abort_senders until shutdown_all().
Add remove_abort_sender() and call it at the normal exit path in
supervise() to release the entry immediately.
App-level weftIpc messages from the system UI routinely fail Request
deserialization since they are not system commands. Using warn generates
log noise during normal operation.
check_package() now rejects any capabilities not in the known set:
fs:rw:app-data, fs:read:app-data,
fs:rw:xdg-documents, fs:read:xdg-documents
This keeps the manifest in sync with what resolve_preopens() in
weft-appd actually maps; unknown strings would otherwise silently
produce no preopens at runtime.
A broadcast LaunchAck can arrive in addition to any direct response,
causing create_app_webview to be called twice for the same session.
Without the guard the second call silently overwrites the existing
WebView entry without destroying it. Early-return if the session is
already tracked.
Previously LaunchAck was sent only as a direct response to the
requesting connection. The servo-shell appd_ws listener thread is a
separate WebSocket connection and would never receive LaunchAck for
UI-initiated launches, causing those sessions to have no WebView.
Now dispatch() broadcasts LaunchAck over the registry broadcast channel
immediately after returning the direct response, so all connected
WebSocket clients (including the shell listener) learn about every new
session regardless of which connection triggered the launch.
run_listener() now loops forever instead of returning on first failure.
Connect errors retry starting at 500ms, doubling up to 16s.
On disconnect the inner loop breaks and the outer loop reconnects
after the current backoff delay, then resets backoff to 500ms.
QUERY_RUNNING is sent again on each reconnect to re-sync session state.