mirror of
https://github.com/marcoallegretti/WEFT_OS.git
synced 2026-03-26 17:03:09 +00:00
feat(examples): add counter and notes demo apps
- 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
This commit is contained in:
parent
34359acf3f
commit
794f6c2225
24 changed files with 1227 additions and 17 deletions
|
|
@ -11,6 +11,10 @@ members = [
|
||||||
"crates/weft-runtime",
|
"crates/weft-runtime",
|
||||||
"crates/weft-servo-shell",
|
"crates/weft-servo-shell",
|
||||||
]
|
]
|
||||||
|
exclude = [
|
||||||
|
"examples/org.weft.demo.counter",
|
||||||
|
"examples/org.weft.demo.notes",
|
||||||
|
]
|
||||||
resolver = "2"
|
resolver = "2"
|
||||||
|
|
||||||
[workspace.package]
|
[workspace.package]
|
||||||
|
|
|
||||||
|
|
@ -10,12 +10,14 @@
|
||||||
| Crate | `servo` (package name as of 2026-03-11; previously `libservo`) |
|
| Crate | `servo` (package name as of 2026-03-11; previously `libservo`) |
|
||||||
| Feature | `servo-embed` (optional; off by default) |
|
| Feature | `servo-embed` (optional; off by default) |
|
||||||
|
|
||||||
## Adding the Cargo dependencies
|
## Cargo dependencies
|
||||||
|
|
||||||
The Servo deps are **not** in `Cargo.toml` by default to avoid pulling the
|
The Servo deps are wired in `crates/weft-servo-shell/Cargo.toml` and
|
||||||
Servo monorepo (~1 GB) into every `cargo check` cycle. To activate, add the
|
`crates/weft-app-shell/Cargo.toml` under the `servo-embed` optional feature.
|
||||||
following to `crates/weft-servo-shell/Cargo.toml` and change the `servo-embed`
|
They are off by default to avoid pulling the Servo monorepo (~1 GB) into every
|
||||||
feature line to declare `dep:servo`, `dep:winit`, and `dep:softbuffer`:
|
`cargo check` cycle.
|
||||||
|
|
||||||
|
Current `Cargo.toml` block (already committed):
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
[features]
|
[features]
|
||||||
|
|
@ -37,7 +39,7 @@ version = "0.4"
|
||||||
optional = true
|
optional = true
|
||||||
```
|
```
|
||||||
|
|
||||||
Then build:
|
To build:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
cargo build -p weft-servo-shell --features servo-embed
|
cargo build -p weft-servo-shell --features servo-embed
|
||||||
|
|
@ -75,17 +77,15 @@ DMA-BUF buffer sharing with the compositor transparently.
|
||||||
|
|
||||||
- **GAP-1**: ~~Wayland input events not forwarded to Servo~~ **Resolved** — keyboard and
|
- **GAP-1**: ~~Wayland input events not forwarded to Servo~~ **Resolved** — keyboard and
|
||||||
mouse events forwarded via `webview.notify_input_event`; key mapping in `keyutils.rs`.
|
mouse events forwarded via `webview.notify_input_event`; key mapping in `keyutils.rs`.
|
||||||
- **GAP-2**: EGL `WindowRenderingContext` path scaffolded (`WEFT_EGL_RENDERING=1`).
|
- **GAP-2**: ~~`ZweftShellWindowV1` created with `surface = null`~~ **Resolved** —
|
||||||
When EGL is active, Servo presents frames via surfman's `eglSwapBuffers`; Mesa handles
|
`ShellClient::connect_with_display(display_ptr, surface_ptr)` uses
|
||||||
DMA-BUF buffer sharing with the compositor transparently — no explicit
|
`Backend::from_foreign_display` to share winit's `wl_display` connection; the winit
|
||||||
`zwp_linux_dmabuf_v1` code is needed in the shell for basic rendering.
|
`wl_surface` pointer is passed directly to `create_window`, associating the compositor
|
||||||
The `zweft_shell_manager_v1` event queue is now dispatched each frame so `configure`,
|
shell slot with the actual rendered surface. `ShellClient` is now constructed inside
|
||||||
`focus_changed`, and `window_closed` events are processed; `window_closed` triggers a
|
`resumed()` after the winit window exists, not before the event loop. EGL path and
|
||||||
clean Servo shutdown.
|
per-frame event dispatch are unchanged.
|
||||||
Remaining gap: the `ZweftShellWindowV1` is created with `surface = null`; the winit
|
Protocol note: `wayland-scanner 0.31` generates `_type` (not `r#type`) for the
|
||||||
`wl_surface` is not yet associated with the shell window slot (requires sharing a single
|
`navigation_gesture` event arg named `type`.
|
||||||
Wayland connection between winit and the shell client, which is not currently feasible
|
|
||||||
without significant refactoring).
|
|
||||||
- **GAP-3**: WebGPU adapter on Mesa may fail CTS — validation task, requires Mesa GPU hardware.
|
- **GAP-3**: WebGPU adapter on Mesa may fail CTS — validation task, requires Mesa GPU hardware.
|
||||||
- **GAP-4**: ~~CSS Grid~~ **Grid resolved** (Taffy-backed, fully wired).
|
- **GAP-4**: ~~CSS Grid~~ **Grid resolved** (Taffy-backed, fully wired).
|
||||||
~~CSS `backdrop-filter` unimplemented~~ **`backdrop-filter` resolved** (servo/servo issue
|
~~CSS `backdrop-filter` unimplemented~~ **`backdrop-filter` resolved** (servo/servo issue
|
||||||
|
|
|
||||||
1
examples/keys/weft-sign.key
Normal file
1
examples/keys/weft-sign.key
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
6322e10dadbbe0f0d95fa113278392eac87768826167dd1cfcb3cc1cb7e43312
|
||||||
1
examples/keys/weft-sign.pub
Normal file
1
examples/keys/weft-sign.pub
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
470490314923b5f51d96196a6dee67e831f0b758119b8558d83cf415088fe062
|
||||||
2
examples/org.weft.demo.counter/.cargo/config.toml
Normal file
2
examples/org.weft.demo.counter/.cargo/config.toml
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
[build]
|
||||||
|
target = "wasm32-wasip2"
|
||||||
321
examples/org.weft.demo.counter/Cargo.lock
generated
Normal file
321
examples/org.weft.demo.counter/Cargo.lock
generated
Normal file
|
|
@ -0,0 +1,321 @@
|
||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 4
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anyhow"
|
||||||
|
version = "1.0.102"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bitflags"
|
||||||
|
version = "2.11.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "equivalent"
|
||||||
|
version = "1.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "foldhash"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hashbrown"
|
||||||
|
version = "0.16.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100"
|
||||||
|
dependencies = [
|
||||||
|
"foldhash",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "heck"
|
||||||
|
version = "0.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "id-arena"
|
||||||
|
version = "2.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "indexmap"
|
||||||
|
version = "2.13.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017"
|
||||||
|
dependencies = [
|
||||||
|
"equivalent",
|
||||||
|
"hashbrown",
|
||||||
|
"serde",
|
||||||
|
"serde_core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "itoa"
|
||||||
|
version = "1.0.17"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "leb128fmt"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "log"
|
||||||
|
version = "0.4.29"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memchr"
|
||||||
|
version = "2.8.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "org-weft-demo-counter"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"serde_json",
|
||||||
|
"wit-bindgen",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "prettyplease"
|
||||||
|
version = "0.2.37"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro2"
|
||||||
|
version = "1.0.106"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quote"
|
||||||
|
version = "1.0.45"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "semver"
|
||||||
|
version = "1.0.27"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde"
|
||||||
|
version = "1.0.228"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
|
||||||
|
dependencies = [
|
||||||
|
"serde_core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_core"
|
||||||
|
version = "1.0.228"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
|
||||||
|
dependencies = [
|
||||||
|
"serde_derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_derive"
|
||||||
|
version = "1.0.228"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_json"
|
||||||
|
version = "1.0.149"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86"
|
||||||
|
dependencies = [
|
||||||
|
"itoa",
|
||||||
|
"memchr",
|
||||||
|
"serde",
|
||||||
|
"serde_core",
|
||||||
|
"zmij",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "2.0.117"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-ident"
|
||||||
|
version = "1.0.24"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-xid"
|
||||||
|
version = "0.2.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-encoder"
|
||||||
|
version = "0.245.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3f9dca005e69bf015e45577e415b9af8c67e8ee3c0e38b5b0add5aa92581ed5c"
|
||||||
|
dependencies = [
|
||||||
|
"leb128fmt",
|
||||||
|
"wasmparser",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-metadata"
|
||||||
|
version = "0.245.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "da55e60097e8b37b475a0fa35c3420dd71d9eb7bd66109978ab55faf56a57efb"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"indexmap",
|
||||||
|
"wasm-encoder",
|
||||||
|
"wasmparser",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasmparser"
|
||||||
|
version = "0.245.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4f08c9adee0428b7bddf3890fc27e015ac4b761cc608c822667102b8bfd6995e"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
"hashbrown",
|
||||||
|
"indexmap",
|
||||||
|
"semver",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wit-bindgen"
|
||||||
|
version = "0.53.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6e915216dde3e818093168df8380a64fba25df468d626c80dd5d6a184c87e7c7"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
"wit-bindgen-rust-macro",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wit-bindgen-core"
|
||||||
|
version = "0.53.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3deda4b7e9f522d994906f6e6e0fc67965ea8660306940a776b76732be8f3933"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"heck",
|
||||||
|
"wit-parser",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wit-bindgen-rust"
|
||||||
|
version = "0.53.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "863a7ab3c4dfee58db196811caeb0718b88412a0aef3d1c2b02fcbae1e37c688"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"heck",
|
||||||
|
"indexmap",
|
||||||
|
"prettyplease",
|
||||||
|
"syn",
|
||||||
|
"wasm-metadata",
|
||||||
|
"wit-bindgen-core",
|
||||||
|
"wit-component",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wit-bindgen-rust-macro"
|
||||||
|
version = "0.53.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d14f3a9bfa3804bb0e9ab7f66da047f210eded6a1297ae3ba5805b384d64797f"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"prettyplease",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
"wit-bindgen-core",
|
||||||
|
"wit-bindgen-rust",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wit-component"
|
||||||
|
version = "0.245.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4894f10d2d5cbc17c77e91f86a1e48e191a788da4425293b55c98b44ba3fcac9"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"bitflags",
|
||||||
|
"indexmap",
|
||||||
|
"log",
|
||||||
|
"serde",
|
||||||
|
"serde_derive",
|
||||||
|
"serde_json",
|
||||||
|
"wasm-encoder",
|
||||||
|
"wasm-metadata",
|
||||||
|
"wasmparser",
|
||||||
|
"wit-parser",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wit-parser"
|
||||||
|
version = "0.245.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "330698718e82983499419494dd1e3d7811a457a9bf9f69734e8c5f07a2547929"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"hashbrown",
|
||||||
|
"id-arena",
|
||||||
|
"indexmap",
|
||||||
|
"log",
|
||||||
|
"semver",
|
||||||
|
"serde",
|
||||||
|
"serde_derive",
|
||||||
|
"serde_json",
|
||||||
|
"unicode-xid",
|
||||||
|
"wasmparser",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zmij"
|
||||||
|
version = "1.0.21"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa"
|
||||||
17
examples/org.weft.demo.counter/Cargo.toml
Normal file
17
examples/org.weft.demo.counter/Cargo.toml
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
[package]
|
||||||
|
name = "org-weft-demo-counter"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "app"
|
||||||
|
path = "src/main.rs"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
wit-bindgen = "0.53"
|
||||||
|
serde_json = "1"
|
||||||
|
|
||||||
|
[profile.release]
|
||||||
|
opt-level = "z"
|
||||||
|
strip = true
|
||||||
|
lto = true
|
||||||
BIN
examples/org.weft.demo.counter/app.wasm
Normal file
BIN
examples/org.weft.demo.counter/app.wasm
Normal file
Binary file not shown.
1
examples/org.weft.demo.counter/signature.sig
Normal file
1
examples/org.weft.demo.counter/signature.sig
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
4d26abef46af41b1992c0592313ea6aeb39b21eb4a31b978c13ed7c46b444f4d3469819eec1e9d3a00ef40898b77cc3391edfac55fcc50e13817a9eaf126ec0a
|
||||||
42
examples/org.weft.demo.counter/src/main.rs
Normal file
42
examples/org.weft.demo.counter/src/main.rs
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
wit_bindgen::generate!({
|
||||||
|
path: "wit",
|
||||||
|
world: "app",
|
||||||
|
with: {
|
||||||
|
"weft:app/notify@0.1.0": generate,
|
||||||
|
"weft:app/ipc@0.1.0": generate,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
use weft::app::{ipc, notify};
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
notify::ready();
|
||||||
|
|
||||||
|
let mut count: i32 = 0;
|
||||||
|
|
||||||
|
loop {
|
||||||
|
if let Some(raw) = ipc::recv() {
|
||||||
|
let reply = match raw.trim() {
|
||||||
|
"increment" => {
|
||||||
|
count += 1;
|
||||||
|
format!("{{\"count\":{count}}}")
|
||||||
|
}
|
||||||
|
"decrement" => {
|
||||||
|
count -= 1;
|
||||||
|
format!("{{\"count\":{count}}}")
|
||||||
|
}
|
||||||
|
"reset" => {
|
||||||
|
count = 0;
|
||||||
|
format!("{{\"count\":{count}}}")
|
||||||
|
}
|
||||||
|
"get" => {
|
||||||
|
format!("{{\"count\":{count}}}")
|
||||||
|
}
|
||||||
|
_ => continue,
|
||||||
|
};
|
||||||
|
let _ = ipc::send(&reply);
|
||||||
|
} else {
|
||||||
|
std::thread::sleep(std::time::Duration::from_millis(10));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
144
examples/org.weft.demo.counter/ui/index.html
Normal file
144
examples/org.weft.demo.counter/ui/index.html
Normal file
|
|
@ -0,0 +1,144 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<title>Counter</title>
|
||||||
|
<style>
|
||||||
|
* { box-sizing: border-box; margin: 0; padding: 0; }
|
||||||
|
body {
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
||||||
|
background: #0f0f0f;
|
||||||
|
color: #e8e8e8;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
.card {
|
||||||
|
background: #1a1a1a;
|
||||||
|
border: 1px solid #2a2a2a;
|
||||||
|
border-radius: 16px;
|
||||||
|
padding: 48px 64px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 32px;
|
||||||
|
min-width: 320px;
|
||||||
|
}
|
||||||
|
h1 {
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
|
letter-spacing: 0.12em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
#count {
|
||||||
|
font-size: 96px;
|
||||||
|
font-weight: 700;
|
||||||
|
font-variant-numeric: tabular-nums;
|
||||||
|
line-height: 1;
|
||||||
|
min-width: 3ch;
|
||||||
|
text-align: center;
|
||||||
|
transition: color 0.15s;
|
||||||
|
}
|
||||||
|
#count.negative { color: #e05252; }
|
||||||
|
#count.positive { color: #e8e8e8; }
|
||||||
|
.controls {
|
||||||
|
display: flex;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
button {
|
||||||
|
width: 56px;
|
||||||
|
height: 56px;
|
||||||
|
border-radius: 12px;
|
||||||
|
border: 1px solid #333;
|
||||||
|
background: #222;
|
||||||
|
color: #e8e8e8;
|
||||||
|
font-size: 24px;
|
||||||
|
font-weight: 300;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background 0.1s, transform 0.08s;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
button:hover { background: #2e2e2e; }
|
||||||
|
button:active { transform: scale(0.94); }
|
||||||
|
#reset {
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 500;
|
||||||
|
letter-spacing: 0.04em;
|
||||||
|
width: auto;
|
||||||
|
padding: 0 20px;
|
||||||
|
color: #888;
|
||||||
|
border-color: #2a2a2a;
|
||||||
|
}
|
||||||
|
#status {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #444;
|
||||||
|
min-height: 16px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="card">
|
||||||
|
<h1>Counter</h1>
|
||||||
|
<div id="count" class="positive">0</div>
|
||||||
|
<div class="controls">
|
||||||
|
<button id="dec" aria-label="Decrement">−</button>
|
||||||
|
<button id="reset">Reset</button>
|
||||||
|
<button id="inc" aria-label="Increment">+</button>
|
||||||
|
</div>
|
||||||
|
<div id="status">connecting…</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
(function () {
|
||||||
|
var countEl = document.getElementById('count');
|
||||||
|
var statusEl = document.getElementById('status');
|
||||||
|
|
||||||
|
function applyCount(n) {
|
||||||
|
countEl.textContent = n;
|
||||||
|
countEl.className = n < 0 ? 'negative' : 'positive';
|
||||||
|
}
|
||||||
|
|
||||||
|
function send(action) {
|
||||||
|
if (window.weftIpc) {
|
||||||
|
window.weftIpc.send(action);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
document.getElementById('inc').addEventListener('click', function () { send('increment'); });
|
||||||
|
document.getElementById('dec').addEventListener('click', function () { send('decrement'); });
|
||||||
|
document.getElementById('reset').addEventListener('click', function () { send('reset'); });
|
||||||
|
|
||||||
|
document.addEventListener('keydown', function (e) {
|
||||||
|
if (e.key === 'ArrowUp' || e.key === '+') send('increment');
|
||||||
|
if (e.key === 'ArrowDown' || e.key === '-') send('decrement');
|
||||||
|
if (e.key === 'r' || e.key === 'R') send('reset');
|
||||||
|
});
|
||||||
|
|
||||||
|
function setupIpc() {
|
||||||
|
if (!window.weftIpc) {
|
||||||
|
setTimeout(setupIpc, 50);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
statusEl.textContent = '';
|
||||||
|
send('get');
|
||||||
|
window.weftIpc.onmessage = function (raw) {
|
||||||
|
try {
|
||||||
|
var msg = typeof raw === 'string' ? JSON.parse(raw) : raw;
|
||||||
|
if (typeof msg.count === 'number') {
|
||||||
|
applyCount(msg.count);
|
||||||
|
}
|
||||||
|
} catch (_) {}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
setupIpc();
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
12
examples/org.weft.demo.counter/wapp.toml
Normal file
12
examples/org.weft.demo.counter/wapp.toml
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
[package]
|
||||||
|
id = "org.weft.demo.counter"
|
||||||
|
name = "Counter"
|
||||||
|
version = "0.1.0"
|
||||||
|
description = "Stateless counter demonstrating weft:app/ipc"
|
||||||
|
author = "WEFT OS"
|
||||||
|
|
||||||
|
[runtime]
|
||||||
|
module = "app.wasm"
|
||||||
|
|
||||||
|
[ui]
|
||||||
|
entry = "ui/index.html"
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
package weft:app@0.1.0;
|
||||||
|
|
||||||
|
interface notify {
|
||||||
|
ready: func();
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ipc {
|
||||||
|
send: func(payload: string) -> result<_, string>;
|
||||||
|
recv: func() -> option<string>;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface fetch {
|
||||||
|
record response {
|
||||||
|
status: u16,
|
||||||
|
content-type: string,
|
||||||
|
body: list<u8>,
|
||||||
|
}
|
||||||
|
|
||||||
|
fetch: func(
|
||||||
|
url: string,
|
||||||
|
method: string,
|
||||||
|
headers: list<tuple<string, string>>,
|
||||||
|
body: option<list<u8>>,
|
||||||
|
) -> result<response, string>;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface notifications {
|
||||||
|
notify: func(
|
||||||
|
title: string,
|
||||||
|
body: string,
|
||||||
|
icon: option<string>,
|
||||||
|
) -> result<_, string>;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface clipboard {
|
||||||
|
read: func() -> result<string, string>;
|
||||||
|
write: func(text: string) -> result<_, string>;
|
||||||
|
}
|
||||||
6
examples/org.weft.demo.counter/wit/world.wit
Normal file
6
examples/org.weft.demo.counter/wit/world.wit
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
package org:weft-demo-counter@0.1.0;
|
||||||
|
|
||||||
|
world app {
|
||||||
|
import weft:app/notify@0.1.0;
|
||||||
|
import weft:app/ipc@0.1.0;
|
||||||
|
}
|
||||||
2
examples/org.weft.demo.notes/.cargo/config.toml
Normal file
2
examples/org.weft.demo.notes/.cargo/config.toml
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
[build]
|
||||||
|
target = "wasm32-wasip2"
|
||||||
321
examples/org.weft.demo.notes/Cargo.lock
generated
Normal file
321
examples/org.weft.demo.notes/Cargo.lock
generated
Normal file
|
|
@ -0,0 +1,321 @@
|
||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 4
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anyhow"
|
||||||
|
version = "1.0.102"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bitflags"
|
||||||
|
version = "2.11.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "equivalent"
|
||||||
|
version = "1.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "foldhash"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hashbrown"
|
||||||
|
version = "0.16.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100"
|
||||||
|
dependencies = [
|
||||||
|
"foldhash",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "heck"
|
||||||
|
version = "0.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "id-arena"
|
||||||
|
version = "2.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "indexmap"
|
||||||
|
version = "2.13.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017"
|
||||||
|
dependencies = [
|
||||||
|
"equivalent",
|
||||||
|
"hashbrown",
|
||||||
|
"serde",
|
||||||
|
"serde_core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "itoa"
|
||||||
|
version = "1.0.17"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "leb128fmt"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "log"
|
||||||
|
version = "0.4.29"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memchr"
|
||||||
|
version = "2.8.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "org-weft-demo-notes"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"serde_json",
|
||||||
|
"wit-bindgen",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "prettyplease"
|
||||||
|
version = "0.2.37"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro2"
|
||||||
|
version = "1.0.106"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quote"
|
||||||
|
version = "1.0.45"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "semver"
|
||||||
|
version = "1.0.27"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde"
|
||||||
|
version = "1.0.228"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
|
||||||
|
dependencies = [
|
||||||
|
"serde_core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_core"
|
||||||
|
version = "1.0.228"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
|
||||||
|
dependencies = [
|
||||||
|
"serde_derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_derive"
|
||||||
|
version = "1.0.228"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_json"
|
||||||
|
version = "1.0.149"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86"
|
||||||
|
dependencies = [
|
||||||
|
"itoa",
|
||||||
|
"memchr",
|
||||||
|
"serde",
|
||||||
|
"serde_core",
|
||||||
|
"zmij",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "2.0.117"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-ident"
|
||||||
|
version = "1.0.24"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-xid"
|
||||||
|
version = "0.2.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-encoder"
|
||||||
|
version = "0.245.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3f9dca005e69bf015e45577e415b9af8c67e8ee3c0e38b5b0add5aa92581ed5c"
|
||||||
|
dependencies = [
|
||||||
|
"leb128fmt",
|
||||||
|
"wasmparser",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-metadata"
|
||||||
|
version = "0.245.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "da55e60097e8b37b475a0fa35c3420dd71d9eb7bd66109978ab55faf56a57efb"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"indexmap",
|
||||||
|
"wasm-encoder",
|
||||||
|
"wasmparser",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasmparser"
|
||||||
|
version = "0.245.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4f08c9adee0428b7bddf3890fc27e015ac4b761cc608c822667102b8bfd6995e"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
"hashbrown",
|
||||||
|
"indexmap",
|
||||||
|
"semver",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wit-bindgen"
|
||||||
|
version = "0.53.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6e915216dde3e818093168df8380a64fba25df468d626c80dd5d6a184c87e7c7"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
"wit-bindgen-rust-macro",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wit-bindgen-core"
|
||||||
|
version = "0.53.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3deda4b7e9f522d994906f6e6e0fc67965ea8660306940a776b76732be8f3933"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"heck",
|
||||||
|
"wit-parser",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wit-bindgen-rust"
|
||||||
|
version = "0.53.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "863a7ab3c4dfee58db196811caeb0718b88412a0aef3d1c2b02fcbae1e37c688"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"heck",
|
||||||
|
"indexmap",
|
||||||
|
"prettyplease",
|
||||||
|
"syn",
|
||||||
|
"wasm-metadata",
|
||||||
|
"wit-bindgen-core",
|
||||||
|
"wit-component",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wit-bindgen-rust-macro"
|
||||||
|
version = "0.53.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d14f3a9bfa3804bb0e9ab7f66da047f210eded6a1297ae3ba5805b384d64797f"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"prettyplease",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
"wit-bindgen-core",
|
||||||
|
"wit-bindgen-rust",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wit-component"
|
||||||
|
version = "0.245.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4894f10d2d5cbc17c77e91f86a1e48e191a788da4425293b55c98b44ba3fcac9"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"bitflags",
|
||||||
|
"indexmap",
|
||||||
|
"log",
|
||||||
|
"serde",
|
||||||
|
"serde_derive",
|
||||||
|
"serde_json",
|
||||||
|
"wasm-encoder",
|
||||||
|
"wasm-metadata",
|
||||||
|
"wasmparser",
|
||||||
|
"wit-parser",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wit-parser"
|
||||||
|
version = "0.245.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "330698718e82983499419494dd1e3d7811a457a9bf9f69734e8c5f07a2547929"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"hashbrown",
|
||||||
|
"id-arena",
|
||||||
|
"indexmap",
|
||||||
|
"log",
|
||||||
|
"semver",
|
||||||
|
"serde",
|
||||||
|
"serde_derive",
|
||||||
|
"serde_json",
|
||||||
|
"unicode-xid",
|
||||||
|
"wasmparser",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zmij"
|
||||||
|
version = "1.0.21"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa"
|
||||||
17
examples/org.weft.demo.notes/Cargo.toml
Normal file
17
examples/org.weft.demo.notes/Cargo.toml
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
[package]
|
||||||
|
name = "org-weft-demo-notes"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "app"
|
||||||
|
path = "src/main.rs"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
wit-bindgen = "0.53"
|
||||||
|
serde_json = "1"
|
||||||
|
|
||||||
|
[profile.release]
|
||||||
|
opt-level = "z"
|
||||||
|
strip = true
|
||||||
|
lto = true
|
||||||
BIN
examples/org.weft.demo.notes/app.wasm
Normal file
BIN
examples/org.weft.demo.notes/app.wasm
Normal file
Binary file not shown.
1
examples/org.weft.demo.notes/signature.sig
Normal file
1
examples/org.weft.demo.notes/signature.sig
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
e781544104eee4538e17f953ea3223903e2b2a46a78705cd1ffa8d6946a62d0385c76eab2cc1c2533eecbeff7600e76a4205abc66915be8851fe2e71316ebc0d
|
||||||
59
examples/org.weft.demo.notes/src/main.rs
Normal file
59
examples/org.weft.demo.notes/src/main.rs
Normal file
|
|
@ -0,0 +1,59 @@
|
||||||
|
wit_bindgen::generate!({
|
||||||
|
path: "wit",
|
||||||
|
world: "app",
|
||||||
|
with: {
|
||||||
|
"weft:app/notify@0.1.0": generate,
|
||||||
|
"weft:app/ipc@0.1.0": generate,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
use weft::app::{ipc, notify};
|
||||||
|
|
||||||
|
const NOTES_PATH: &str = "/data/notes.txt";
|
||||||
|
|
||||||
|
fn load_notes() -> String {
|
||||||
|
std::fs::read_to_string(NOTES_PATH).unwrap_or_default()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn save_notes(text: &str) -> Result<(), String> {
|
||||||
|
std::fs::write(NOTES_PATH, text).map_err(|e| e.to_string())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn json_text(text: &str) -> String {
|
||||||
|
let escaped = text
|
||||||
|
.replace('\\', "\\\\")
|
||||||
|
.replace('"', "\\\"")
|
||||||
|
.replace('\n', "\\n")
|
||||||
|
.replace('\r', "\\r")
|
||||||
|
.replace('\t', "\\t");
|
||||||
|
format!("{{\"text\":\"{escaped}\"}}")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn json_error(msg: &str) -> String {
|
||||||
|
let escaped = msg.replace('"', "\\\"");
|
||||||
|
format!("{{\"error\":\"{escaped}\"}}")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
notify::ready();
|
||||||
|
|
||||||
|
loop {
|
||||||
|
if let Some(raw) = ipc::recv() {
|
||||||
|
let raw = raw.trim().to_owned();
|
||||||
|
let reply = if raw == "load" {
|
||||||
|
json_text(&load_notes())
|
||||||
|
} else if let Some(rest) = raw.strip_prefix("save:") {
|
||||||
|
let text = rest.replace("\\n", "\n");
|
||||||
|
match save_notes(&text) {
|
||||||
|
Ok(()) => json_text(&text),
|
||||||
|
Err(e) => json_error(&e),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
let _ = ipc::send(&reply);
|
||||||
|
} else {
|
||||||
|
std::thread::sleep(std::time::Duration::from_millis(10));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
164
examples/org.weft.demo.notes/ui/index.html
Normal file
164
examples/org.weft.demo.notes/ui/index.html
Normal file
|
|
@ -0,0 +1,164 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<title>Notes</title>
|
||||||
|
<style>
|
||||||
|
* { box-sizing: border-box; margin: 0; padding: 0; }
|
||||||
|
body {
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
||||||
|
background: #0f0f0f;
|
||||||
|
color: #e8e8e8;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
height: 100vh;
|
||||||
|
padding: 24px;
|
||||||
|
gap: 16px;
|
||||||
|
}
|
||||||
|
header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
h1 {
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
|
letter-spacing: 0.12em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
.actions {
|
||||||
|
display: flex;
|
||||||
|
gap: 8px;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
button {
|
||||||
|
height: 32px;
|
||||||
|
padding: 0 16px;
|
||||||
|
border-radius: 8px;
|
||||||
|
border: 1px solid #2a2a2a;
|
||||||
|
background: #1a1a1a;
|
||||||
|
color: #e8e8e8;
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 500;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background 0.1s;
|
||||||
|
}
|
||||||
|
button:hover { background: #222; }
|
||||||
|
button:active { background: #2a2a2a; }
|
||||||
|
button.primary {
|
||||||
|
background: #2a2a2a;
|
||||||
|
border-color: #444;
|
||||||
|
}
|
||||||
|
button.primary:hover { background: #333; }
|
||||||
|
textarea {
|
||||||
|
flex: 1;
|
||||||
|
background: #1a1a1a;
|
||||||
|
border: 1px solid #2a2a2a;
|
||||||
|
border-radius: 12px;
|
||||||
|
color: #e8e8e8;
|
||||||
|
font-family: inherit;
|
||||||
|
font-size: 15px;
|
||||||
|
line-height: 1.6;
|
||||||
|
padding: 20px;
|
||||||
|
resize: none;
|
||||||
|
outline: none;
|
||||||
|
transition: border-color 0.15s;
|
||||||
|
}
|
||||||
|
textarea:focus { border-color: #444; }
|
||||||
|
textarea::placeholder { color: #444; }
|
||||||
|
footer {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
flex-shrink: 0;
|
||||||
|
height: 20px;
|
||||||
|
}
|
||||||
|
#status {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #444;
|
||||||
|
}
|
||||||
|
#charcount {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #444;
|
||||||
|
font-variant-numeric: tabular-nums;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<header>
|
||||||
|
<h1>Notes</h1>
|
||||||
|
<div class="actions">
|
||||||
|
<button id="discard">Discard</button>
|
||||||
|
<button class="primary" id="save">Save</button>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
<textarea id="editor" placeholder="Start typing…" spellcheck="false"></textarea>
|
||||||
|
<footer>
|
||||||
|
<span id="status">connecting…</span>
|
||||||
|
<span id="charcount">0 chars</span>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
(function () {
|
||||||
|
var editor = document.getElementById('editor');
|
||||||
|
var statusEl = document.getElementById('status');
|
||||||
|
var charEl = document.getElementById('charcount');
|
||||||
|
var saved = '';
|
||||||
|
|
||||||
|
function setStatus(msg) { statusEl.textContent = msg; }
|
||||||
|
|
||||||
|
editor.addEventListener('input', function () {
|
||||||
|
charEl.textContent = editor.value.length + ' chars';
|
||||||
|
});
|
||||||
|
|
||||||
|
document.getElementById('save').addEventListener('click', function () {
|
||||||
|
if (!window.weftIpc) return;
|
||||||
|
var text = editor.value.replace(/\n/g, '\\n');
|
||||||
|
window.weftIpc.send('save:' + text);
|
||||||
|
setStatus('saving…');
|
||||||
|
});
|
||||||
|
|
||||||
|
document.getElementById('discard').addEventListener('click', function () {
|
||||||
|
editor.value = saved;
|
||||||
|
charEl.textContent = saved.length + ' chars';
|
||||||
|
setStatus('discarded');
|
||||||
|
setTimeout(function () { setStatus(''); }, 1500);
|
||||||
|
});
|
||||||
|
|
||||||
|
document.addEventListener('keydown', function (e) {
|
||||||
|
if ((e.ctrlKey || e.metaKey) && e.key === 's') {
|
||||||
|
e.preventDefault();
|
||||||
|
document.getElementById('save').click();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function setupIpc() {
|
||||||
|
if (!window.weftIpc) { setTimeout(setupIpc, 50); return; }
|
||||||
|
window.weftIpc.onmessage = function (raw) {
|
||||||
|
try {
|
||||||
|
var msg = typeof raw === 'string' ? JSON.parse(raw) : raw;
|
||||||
|
if (typeof msg.error === 'string') {
|
||||||
|
setStatus('error: ' + msg.error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (typeof msg.text === 'string') {
|
||||||
|
var text = msg.text.replace(/\\n/g, '\n');
|
||||||
|
editor.value = text;
|
||||||
|
saved = text;
|
||||||
|
charEl.textContent = text.length + ' chars';
|
||||||
|
setStatus('');
|
||||||
|
}
|
||||||
|
} catch (_) {}
|
||||||
|
};
|
||||||
|
setStatus('');
|
||||||
|
window.weftIpc.send('load');
|
||||||
|
}
|
||||||
|
|
||||||
|
setupIpc();
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
13
examples/org.weft.demo.notes/wapp.toml
Normal file
13
examples/org.weft.demo.notes/wapp.toml
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
[package]
|
||||||
|
id = "org.weft.demo.notes"
|
||||||
|
name = "Notes"
|
||||||
|
version = "0.1.0"
|
||||||
|
description = "Persistent notes demonstrating fs:rw:app-data via weft:app/ipc"
|
||||||
|
author = "WEFT OS"
|
||||||
|
capabilities = ["fs:rw:app-data"]
|
||||||
|
|
||||||
|
[runtime]
|
||||||
|
module = "app.wasm"
|
||||||
|
|
||||||
|
[ui]
|
||||||
|
entry = "ui/index.html"
|
||||||
38
examples/org.weft.demo.notes/wit/deps/weft-app/weft-app.wit
Normal file
38
examples/org.weft.demo.notes/wit/deps/weft-app/weft-app.wit
Normal file
|
|
@ -0,0 +1,38 @@
|
||||||
|
package weft:app@0.1.0;
|
||||||
|
|
||||||
|
interface notify {
|
||||||
|
ready: func();
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ipc {
|
||||||
|
send: func(payload: string) -> result<_, string>;
|
||||||
|
recv: func() -> option<string>;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface fetch {
|
||||||
|
record response {
|
||||||
|
status: u16,
|
||||||
|
content-type: string,
|
||||||
|
body: list<u8>,
|
||||||
|
}
|
||||||
|
|
||||||
|
fetch: func(
|
||||||
|
url: string,
|
||||||
|
method: string,
|
||||||
|
headers: list<tuple<string, string>>,
|
||||||
|
body: option<list<u8>>,
|
||||||
|
) -> result<response, string>;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface notifications {
|
||||||
|
notify: func(
|
||||||
|
title: string,
|
||||||
|
body: string,
|
||||||
|
icon: option<string>,
|
||||||
|
) -> result<_, string>;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface clipboard {
|
||||||
|
read: func() -> result<string, string>;
|
||||||
|
write: func(text: string) -> result<_, string>;
|
||||||
|
}
|
||||||
6
examples/org.weft.demo.notes/wit/world.wit
Normal file
6
examples/org.weft.demo.notes/wit/world.wit
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
package org:weft-demo-notes@0.1.0;
|
||||||
|
|
||||||
|
world app {
|
||||||
|
import weft:app/notify@0.1.0;
|
||||||
|
import weft:app/ipc@0.1.0;
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue