Clone in a terminal:
Commit 2145271
Johan Mattsson - 2026-07-10T21:51:04+00:00
2145271d93a297c7525a9516295e256e64f99ba7johan.mattsson.m@gmail.com

Remove thread pool and provide a single function for spawning new threads

Changed files (27)

Diff

diff --git a/examples/raytrace-parallel/Cargo.lock b/examples/raytrace-parallel/Cargo.lockdeleted file mode 100644index adc78bd..0000000--- a/examples/raytrace-parallel/Cargo.lock+++ /dev/null@@ -1,950 +0,0 @@-# This file is automatically @generated by Cargo.-# It is not intended for manual editing.-version = 4--[[package]]-name = "async-channel"-version = "2.5.0"-source = "registry+https://github.com/rust-lang/crates.io-index"-checksum = "924ed96dd52d1b75e9c1a3e6275715fd320f5f9439fb5a4a11fa51f4221158d2"-dependencies = [- "concurrent-queue",- "event-listener-strategy",- "futures-core",- "pin-project-lite",-]--[[package]]-name = "bincode"-version = "1.3.3"-source = "registry+https://github.com/rust-lang/crates.io-index"-checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad"-dependencies = [- "serde",-]--[[package]]-name = "bumpalo"-version = "3.20.3"-source = "registry+https://github.com/rust-lang/crates.io-index"-checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649"--[[package]]-name = "bytes"-version = "1.12.1"-source = "registry+https://github.com/rust-lang/crates.io-index"-checksum = "fc652a48c352aef3ea3aed32080501cf3ef6ed5da78602a020c991775b0aff04"--[[package]]-name = "cfg-if"-version = "1.0.4"-source = "registry+https://github.com/rust-lang/crates.io-index"-checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"--[[package]]-name = "concurrent-queue"-version = "2.5.0"-source = "registry+https://github.com/rust-lang/crates.io-index"-checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973"-dependencies = [- "crossbeam-utils",-]--[[package]]-name = "console_error_panic_hook"-version = "0.1.7"-source = "registry+https://github.com/rust-lang/crates.io-index"-checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc"-dependencies = [- "cfg-if",- "wasm-bindgen",-]--[[package]]-name = "crossbeam-utils"-version = "0.8.22"-source = "registry+https://github.com/rust-lang/crates.io-index"-checksum = "61803da095bee82a81bb1a452ecc25d3b2f1416d1897eb86430c6159ef717c17"--[[package]]-name = "equivalent"-version = "1.0.2"-source = "registry+https://github.com/rust-lang/crates.io-index"-checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"--[[package]]-name = "event-listener"-version = "5.4.1"-source = "registry+https://github.com/rust-lang/crates.io-index"-checksum = "e13b66accf52311f30a0db42147dadea9850cb48cd070028831ae5f5d4b856ab"-dependencies = [- "concurrent-queue",- "parking",- "pin-project-lite",-]--[[package]]-name = "event-listener-strategy"-version = "0.5.4"-source = "registry+https://github.com/rust-lang/crates.io-index"-checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93"-dependencies = [- "event-listener",- "pin-project-lite",-]--[[package]]-name = "form_urlencoded"-version = "1.2.2"-source = "registry+https://github.com/rust-lang/crates.io-index"-checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf"-dependencies = [- "percent-encoding",-]--[[package]]-name = "futures"-version = "0.3.32"-source = "registry+https://github.com/rust-lang/crates.io-index"-checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d"-dependencies = [- "futures-channel",- "futures-core",- "futures-io",- "futures-sink",- "futures-task",- "futures-util",-]--[[package]]-name = "futures-channel"-version = "0.3.32"-source = "registry+https://github.com/rust-lang/crates.io-index"-checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d"-dependencies = [- "futures-core",- "futures-sink",-]--[[package]]-name = "futures-channel-preview"-version = "0.3.0-alpha.19"-source = "registry+https://github.com/rust-lang/crates.io-index"-checksum = "d5e5f4df964fa9c1c2f8bddeb5c3611631cacd93baf810fc8bb2fb4b495c263a"-dependencies = [- "futures-core-preview",-]--[[package]]-name = "futures-core"-version = "0.3.32"-source = "registry+https://github.com/rust-lang/crates.io-index"-checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d"--[[package]]-name = "futures-core-preview"-version = "0.3.0-alpha.19"-source = "registry+https://github.com/rust-lang/crates.io-index"-checksum = "b35b6263fb1ef523c3056565fa67b1d16f0a8604ff12b11b08c25f28a734c60a"--[[package]]-name = "futures-io"-version = "0.3.32"-source = "registry+https://github.com/rust-lang/crates.io-index"-checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718"--[[package]]-name = "futures-macro"-version = "0.3.32"-source = "registry+https://github.com/rust-lang/crates.io-index"-checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b"-dependencies = [- "proc-macro2",- "quote",- "syn 2.0.118",-]--[[package]]-name = "futures-sink"-version = "0.3.32"-source = "registry+https://github.com/rust-lang/crates.io-index"-checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893"--[[package]]-name = "futures-task"-version = "0.3.32"-source = "registry+https://github.com/rust-lang/crates.io-index"-checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393"--[[package]]-name = "futures-util"-version = "0.3.32"-source = "registry+https://github.com/rust-lang/crates.io-index"-checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6"-dependencies = [- "futures-channel",- "futures-core",- "futures-io",- "futures-macro",- "futures-sink",- "futures-task",- "memchr",- "pin-project-lite",- "slab",-]--[[package]]-name = "getrandom"-version = "0.2.17"-source = "registry+https://github.com/rust-lang/crates.io-index"-checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0"-dependencies = [- "cfg-if",- "js-sys",- "libc",- "wasi",- "wasm-bindgen",-]--[[package]]-name = "getrandom"-version = "0.4.3"-source = "registry+https://github.com/rust-lang/crates.io-index"-checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099"-dependencies = [- "cfg-if",- "libc",- "r-efi",-]--[[package]]-name = "gloo"-version = "0.12.0"-source = "registry+https://github.com/rust-lang/crates.io-index"-checksum = "dc13cc21c3835347855fd83900414d94716adc1e332f09f7fba56f21be127214"-dependencies = [- "gloo-console",- "gloo-dialogs",- "gloo-events",- "gloo-file",- "gloo-history",- "gloo-net",- "gloo-render",- "gloo-storage",- "gloo-timers",- "gloo-utils 0.3.0",- "gloo-worker",-]--[[package]]-name = "gloo-console"-version = "0.4.0"-source = "registry+https://github.com/rust-lang/crates.io-index"-checksum = "9f1d5cec0b97edb53f21221f799c659cef3764ad5a00eca52950eb9b902028ba"-dependencies = [- "gloo-utils 0.3.0",- "js-sys",- "serde",- "wasm-bindgen",- "web-sys",-]--[[package]]-name = "gloo-dialogs"-version = "0.3.0"-source = "registry+https://github.com/rust-lang/crates.io-index"-checksum = "45618929b7022bb49903b958b5b7af1d4fb58fbd99712926d91641fe582f3d55"-dependencies = [- "wasm-bindgen",- "web-sys",-]--[[package]]-name = "gloo-events"-version = "0.3.0"-source = "registry+https://github.com/rust-lang/crates.io-index"-checksum = "8c6a94fa8cd88bea0babf8a27fe9abbcdece831fd1c3c84dd5c231fab4685ec7"-dependencies = [- "wasm-bindgen",- "web-sys",-]--[[package]]-name = "gloo-file"-version = "0.4.0"-source = "registry+https://github.com/rust-lang/crates.io-index"-checksum = "544a15ff6a3d5976bebc97380c8471ae14283bc71f4bb198d6c8cae64f411ab7"-dependencies = [- "futures-channel",- "gloo-events",- "js-sys",- "wasm-bindgen",- "web-sys",-]--[[package]]-name = "gloo-history"-version = "0.3.0"-source = "registry+https://github.com/rust-lang/crates.io-index"-checksum = "f07f3d446931414cc92f4a1b6e631dfa233db2f96c887d5f72beeecd1b5db39c"-dependencies = [- "getrandom 0.2.17",- "gloo-events",- "gloo-utils 0.3.0",- "serde",- "serde-wasm-bindgen 0.6.5",- "serde_urlencoded",- "thiserror 2.0.18",- "wasm-bindgen",- "web-sys",-]--[[package]]-name = "gloo-net"-version = "0.7.0"-source = "registry+https://github.com/rust-lang/crates.io-index"-checksum = "a6420f887c48417e9e86c6cf61274eb231830cccc100e49613f7952e269a1fe1"-dependencies = [- "futures-channel",- "futures-core",- "futures-sink",- "gloo-utils 0.3.0",- "http",- "js-sys",- "pin-project",- "serde",- "serde_json",- "thiserror 2.0.18",- "wasm-bindgen",- "wasm-bindgen-futures",- "web-sys",-]--[[package]]-name = "gloo-render"-version = "0.3.0"-source = "registry+https://github.com/rust-lang/crates.io-index"-checksum = "3f609333b9e38e43e74224410d6616e3ad773ed6fe14f53cd8a006d1bb25e108"-dependencies = [- "wasm-bindgen",- "web-sys",-]--[[package]]-name = "gloo-storage"-version = "0.4.0"-source = "registry+https://github.com/rust-lang/crates.io-index"-checksum = "e82ce7d41c6d821640a43726f6ff33c924795cc151b62e5a84d0c988c151c980"-dependencies = [- "gloo-utils 0.3.0",- "js-sys",- "serde",- "serde_json",- "thiserror 2.0.18",- "wasm-bindgen",- "web-sys",-]--[[package]]-name = "gloo-timers"-version = "0.4.0"-source = "registry+https://github.com/rust-lang/crates.io-index"-checksum = "482ce8a491a501da4cd806bd190275363d674f2845005c6ddbd5d3e1dd54495d"-dependencies = [- "futures-channel",- "futures-core",- "js-sys",- "wasm-bindgen",-]--[[package]]-name = "gloo-utils"-version = "0.2.0"-source = "registry+https://github.com/rust-lang/crates.io-index"-checksum = "0b5555354113b18c547c1d3a98fbf7fb32a9ff4f6fa112ce823a21641a0ba3aa"-dependencies = [- "js-sys",- "serde",- "serde_json",- "wasm-bindgen",- "web-sys",-]--[[package]]-name = "gloo-utils"-version = "0.3.0"-source = "registry+https://github.com/rust-lang/crates.io-index"-checksum = "4202275d95a142fa209a1e35e91c250a710c5600731372cd3464a39ed01573d6"-dependencies = [- "js-sys",- "serde",- "serde_json",- "wasm-bindgen",- "web-sys",-]--[[package]]-name = "gloo-worker"-version = "0.6.0"-source = "registry+https://github.com/rust-lang/crates.io-index"-checksum = "142478655c5d764e5168d3019510ea0c0885687a72ba74e90548bd74ae160a41"-dependencies = [- "bincode",- "futures",- "gloo-utils 0.2.0",- "gloo-worker-macros",- "js-sys",- "pinned",- "serde",- "thiserror 2.0.18",- "wasm-bindgen",- "wasm-bindgen-futures",- "web-sys",-]--[[package]]-name = "gloo-worker-macros"-version = "0.2.0"-source = "registry+https://github.com/rust-lang/crates.io-index"-checksum = "f3bf5ede96b06406bd74351a026f708ae196b7dc262077aee56e6ad7223e7466"-dependencies = [- "proc-macro-crate",- "proc-macro2",- "quote",- "syn 2.0.118",-]--[[package]]-name = "hashbrown"-version = "0.17.1"-source = "registry+https://github.com/rust-lang/crates.io-index"-checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a"--[[package]]-name = "http"-version = "1.4.2"-source = "registry+https://github.com/rust-lang/crates.io-index"-checksum = "6970f50e31d6fc17d3fa27329444bfa74e196cf62e95052a3f6fee181dba6425"-dependencies = [- "bytes",- "itoa",-]--[[package]]-name = "indexmap"-version = "2.14.0"-source = "registry+https://github.com/rust-lang/crates.io-index"-checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9"-dependencies = [- "equivalent",- "hashbrown",-]--[[package]]-name = "inventory"-version = "0.3.24"-source = "registry+https://github.com/rust-lang/crates.io-index"-checksum = "a4f0c30c76f2f4ccee3fe55a2435f691ca00c0e4bd87abe4f4a851b1d4dac39b"-dependencies = [- "rustversion",-]--[[package]]-name = "itoa"-version = "1.0.18"-source = "registry+https://github.com/rust-lang/crates.io-index"-checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"--[[package]]-name = "js-sys"-version = "0.3.103"-source = "registry+https://github.com/rust-lang/crates.io-index"-checksum = "53b44bfcdb3f8d5837a46dae1ca9660a837176eee74a28b229bc626816589102"-dependencies = [- "cfg-if",- "futures-util",- "wasm-bindgen",-]--[[package]]-name = "kaja-callback-macro"-version = "1.0.0"-dependencies = [- "gloo",- "proc-macro2",- "quote",- "syn 2.0.118",-]--[[package]]-name = "kaja-html-macro"-version = "1.0.5"-source = "registry+https://github.com/rust-lang/crates.io-index"-checksum = "a5c37d76721e795460d8ba194309f8c989a64a66dc79118de9dccc083e5fe9db"-dependencies = [- "proc-macro-error",- "proc-macro2",- "quote",- "syn 2.0.118",-]--[[package]]-name = "kaja-web"-version = "1.0.2"-dependencies = [- "gloo",- "gloo-console",- "inventory",- "js-sys",- "kaja-callback-macro",- "kaja-html-macro",- "kaja-web-component",- "serde",- "serde-wasm-bindgen 0.5.0",- "wasm-bindgen",- "wasm-bindgen-futures",- "web-sys",-]--[[package]]-name = "kaja-web-component"-version = "0.1.0"-dependencies = [- "gloo",- "inventory",- "js-sys",- "proc-macro2",- "quote",- "syn 2.0.118",- "wasm-bindgen",- "web-sys",-]--[[package]]-name = "libc"-version = "0.2.186"-source = "registry+https://github.com/rust-lang/crates.io-index"-checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66"--[[package]]-name = "memchr"-version = "2.8.3"-source = "registry+https://github.com/rust-lang/crates.io-index"-checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98"--[[package]]-name = "once_cell"-version = "1.21.4"-source = "registry+https://github.com/rust-lang/crates.io-index"-checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"--[[package]]-name = "parking"-version = "2.2.1"-source = "registry+https://github.com/rust-lang/crates.io-index"-checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba"--[[package]]-name = "percent-encoding"-version = "2.3.2"-source = "registry+https://github.com/rust-lang/crates.io-index"-checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220"--[[package]]-name = "pin-project"-version = "1.1.13"-source = "registry+https://github.com/rust-lang/crates.io-index"-checksum = "2466b2336ed02bcdca6b294417127b90ec92038d1d5c4fbeac971a922e0e0924"-dependencies = [- "pin-project-internal",-]--[[package]]-name = "pin-project-internal"-version = "1.1.13"-source = "registry+https://github.com/rust-lang/crates.io-index"-checksum = "c96395f0a926bc13b1c17622aaddda1ecb55d49c8f1bf9777e4d877800a43f8b"-dependencies = [- "proc-macro2",- "quote",- "syn 2.0.118",-]--[[package]]-name = "pin-project-lite"-version = "0.2.17"-source = "registry+https://github.com/rust-lang/crates.io-index"-checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd"--[[package]]-name = "pinned"-version = "0.1.0"-source = "registry+https://github.com/rust-lang/crates.io-index"-checksum = "a829027bd95e54cfe13e3e258a1ae7b645960553fb82b75ff852c29688ee595b"-dependencies = [- "futures",- "rustversion",- "thiserror 1.0.69",-]--[[package]]-name = "proc-macro-crate"-version = "3.3.0"-source = "registry+https://github.com/rust-lang/crates.io-index"-checksum = "edce586971a4dfaa28950c6f18ed55e0406c1ab88bbce2c6f6293a7aaba73d35"-dependencies = [- "toml_edit",-]--[[package]]-name = "proc-macro-error"-version = "1.0.4"-source = "registry+https://github.com/rust-lang/crates.io-index"-checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"-dependencies = [- "proc-macro-error-attr",- "proc-macro2",- "quote",- "syn 1.0.109",- "version_check",-]--[[package]]-name = "proc-macro-error-attr"-version = "1.0.4"-source = "registry+https://github.com/rust-lang/crates.io-index"-checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"-dependencies = [- "proc-macro2",- "quote",- "version_check",-]--[[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.46"-source = "registry+https://github.com/rust-lang/crates.io-index"-checksum = "dfbc457d0c7a0759a614551b11a6409e5951f6c7537be1f1b7682b9ae9230368"-dependencies = [- "proc-macro2",-]--[[package]]-name = "r-efi"-version = "6.0.0"-source = "registry+https://github.com/rust-lang/crates.io-index"-checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf"--[[package]]-name = "raytrace-parallel"-version = "0.0.0"-dependencies = [- "async-channel",- "console_error_panic_hook",- "futures-channel-preview",- "gloo",- "gloo-timers",- "inventory",- "js-sys",- "kaja-html-macro",- "kaja-web",- "kaja-web-component",- "serde",- "serde-wasm-bindgen 0.6.5",- "serde_json",- "uuid",- "wasm-bindgen",- "wasm-bindgen-futures",- "web-sys",-]--[[package]]-name = "rustversion"-version = "1.0.23"-source = "registry+https://github.com/rust-lang/crates.io-index"-checksum = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f"--[[package]]-name = "ryu"-version = "1.0.23"-source = "registry+https://github.com/rust-lang/crates.io-index"-checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f"--[[package]]-name = "serde"-version = "1.0.228"-source = "registry+https://github.com/rust-lang/crates.io-index"-checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"-dependencies = [- "serde_core",- "serde_derive",-]--[[package]]-name = "serde-wasm-bindgen"-version = "0.5.0"-source = "registry+https://github.com/rust-lang/crates.io-index"-checksum = "f3b143e2833c57ab9ad3ea280d21fd34e285a42837aeb0ee301f4f41890fa00e"-dependencies = [- "js-sys",- "serde",- "wasm-bindgen",-]--[[package]]-name = "serde-wasm-bindgen"-version = "0.6.5"-source = "registry+https://github.com/rust-lang/crates.io-index"-checksum = "8302e169f0eddcc139c70f139d19d6467353af16f9fce27e8c30158036a1e16b"-dependencies = [- "js-sys",- "serde",- "wasm-bindgen",-]--[[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 2.0.118",-]--[[package]]-name = "serde_json"-version = "1.0.150"-source = "registry+https://github.com/rust-lang/crates.io-index"-checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9"-dependencies = [- "itoa",- "memchr",- "serde",- "serde_core",- "zmij",-]--[[package]]-name = "serde_urlencoded"-version = "0.7.1"-source = "registry+https://github.com/rust-lang/crates.io-index"-checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd"-dependencies = [- "form_urlencoded",- "itoa",- "ryu",- "serde",-]--[[package]]-name = "slab"-version = "0.4.12"-source = "registry+https://github.com/rust-lang/crates.io-index"-checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5"--[[package]]-name = "syn"-version = "1.0.109"-source = "registry+https://github.com/rust-lang/crates.io-index"-checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"-dependencies = [- "proc-macro2",- "unicode-ident",-]--[[package]]-name = "syn"-version = "2.0.118"-source = "registry+https://github.com/rust-lang/crates.io-index"-checksum = "1b9ae57f904213ebb649ce6895b8a66c66f0203b9319718f69a5612a065b1422"-dependencies = [- "proc-macro2",- "quote",- "unicode-ident",-]--[[package]]-name = "thiserror"-version = "1.0.69"-source = "registry+https://github.com/rust-lang/crates.io-index"-checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"-dependencies = [- "thiserror-impl 1.0.69",-]--[[package]]-name = "thiserror"-version = "2.0.18"-source = "registry+https://github.com/rust-lang/crates.io-index"-checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4"-dependencies = [- "thiserror-impl 2.0.18",-]--[[package]]-name = "thiserror-impl"-version = "1.0.69"-source = "registry+https://github.com/rust-lang/crates.io-index"-checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"-dependencies = [- "proc-macro2",- "quote",- "syn 2.0.118",-]--[[package]]-name = "thiserror-impl"-version = "2.0.18"-source = "registry+https://github.com/rust-lang/crates.io-index"-checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5"-dependencies = [- "proc-macro2",- "quote",- "syn 2.0.118",-]--[[package]]-name = "toml_datetime"-version = "0.6.11"-source = "registry+https://github.com/rust-lang/crates.io-index"-checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c"--[[package]]-name = "toml_edit"-version = "0.22.27"-source = "registry+https://github.com/rust-lang/crates.io-index"-checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a"-dependencies = [- "indexmap",- "toml_datetime",- "winnow",-]--[[package]]-name = "unicode-ident"-version = "1.0.24"-source = "registry+https://github.com/rust-lang/crates.io-index"-checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"--[[package]]-name = "uuid"-version = "1.23.4"-source = "registry+https://github.com/rust-lang/crates.io-index"-checksum = "bf80a72845275afea99e7f2b434723d3bc7e38470fcd1c7ed39a599c73319a53"-dependencies = [- "getrandom 0.4.3",- "js-sys",- "wasm-bindgen",-]--[[package]]-name = "version_check"-version = "0.9.5"-source = "registry+https://github.com/rust-lang/crates.io-index"-checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"--[[package]]-name = "wasi"-version = "0.11.1+wasi-snapshot-preview1"-source = "registry+https://github.com/rust-lang/crates.io-index"-checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"--[[package]]-name = "wasm-bindgen"-version = "0.2.126"-source = "registry+https://github.com/rust-lang/crates.io-index"-checksum = "4b067c0c11094aef6b7a801c1e34a26affafdf3d051dba08456b868789aaf9a4"-dependencies = [- "cfg-if",- "once_cell",- "rustversion",- "wasm-bindgen-macro",- "wasm-bindgen-shared",-]--[[package]]-name = "wasm-bindgen-futures"-version = "0.4.76"-source = "registry+https://github.com/rust-lang/crates.io-index"-checksum = "c62df1340f32221cb9c54d6a27b030e3dba64361d4a95bed55f9aacb44da291d"-dependencies = [- "js-sys",- "wasm-bindgen",-]--[[package]]-name = "wasm-bindgen-macro"-version = "0.2.126"-source = "registry+https://github.com/rust-lang/crates.io-index"-checksum = "167ce5e579f6bcf889c4f7175a8a5a585de84e8ff93976ce393efa5f2837aab1"-dependencies = [- "quote",- "wasm-bindgen-macro-support",-]--[[package]]-name = "wasm-bindgen-macro-support"-version = "0.2.126"-source = "registry+https://github.com/rust-lang/crates.io-index"-checksum = "f3997c7839262f4ef12cf90b818d6340c18e80f263f1a94bf157d0ec4420380e"-dependencies = [- "bumpalo",- "proc-macro2",- "quote",- "syn 2.0.118",- "wasm-bindgen-shared",-]--[[package]]-name = "wasm-bindgen-shared"-version = "0.2.126"-source = "registry+https://github.com/rust-lang/crates.io-index"-checksum = "dc1b4cb0cc549fcf58d7dfc081778139b3d283a081644e833e84682ad71cea24"-dependencies = [- "unicode-ident",-]--[[package]]-name = "web-sys"-version = "0.3.103"-source = "registry+https://github.com/rust-lang/crates.io-index"-checksum = "8622dcb61c0bcc9fffa6938bed81210af2da9a7e4a1a834b2e37a59b6dfb6141"-dependencies = [- "js-sys",- "wasm-bindgen",-]--[[package]]-name = "winnow"-version = "0.7.15"-source = "registry+https://github.com/rust-lang/crates.io-index"-checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945"-dependencies = [- "memchr",-]--[[package]]-name = "zmij"-version = "1.0.21"-source = "registry+https://github.com/rust-lang/crates.io-index"-checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa"diff --git a/examples/raytrace-parallel/Cargo.toml b/examples/raytrace-parallel/Cargo.tomldeleted file mode 100644index d16447f..0000000--- a/examples/raytrace-parallel/Cargo.toml+++ /dev/null@@ -1,43 +0,0 @@-[package]-authors = ["The wasm-bindgen Developers"]-edition = "2021"-name = "raytrace-parallel"-publish = false-version = "0.0.0"--[lib]-crate-type = ["cdylib"]--[dependencies]-console_error_panic_hook = "0.1"-futures-channel-preview = "0.3.0-alpha.18"-js-sys = "0.3.103"-serde-wasm-bindgen = "0.6"-wasm-bindgen = "0.2.126"-wasm-bindgen-futures = "0.4.76"--web-sys = { version = "0.3.103", features = [-  "ErrorEvent",-  "Event",-  "Navigator",-  "Window",-  "Worker",-  "DedicatedWorkerGlobalScope",-  "MessageEvent",-  "Element",-  "HtmlElement",-  "NodeList",-  "CustomElementRegistry",-  "ElementDefinitionOptions"-] }--kaja-web = { path = "../.." }-kaja-web-component = { path = "../../../kaja-web-component" }-gloo = { version = "0.12", features = ["futures"] }-kaja-html-macro = "1.0.4"-serde = { version = "1.0.228", features = ["derive"] }-serde_json = "1.0.150"-uuid = { version = "1.23.2", features = ["js", "v4"] }-inventory = "0.3.24"-gloo-timers = { version = "0.4.0", features = ["futures"] }-async-channel = "2"diff --git a/examples/raytrace-parallel/LICENSE-APACHE b/examples/raytrace-parallel/LICENSE-APACHEdeleted file mode 100644index 16fe87b..0000000--- a/examples/raytrace-parallel/LICENSE-APACHE+++ /dev/null@@ -1,201 +0,0 @@-                              Apache License-                        Version 2.0, January 2004-                     http://www.apache.org/licenses/--TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION--1. Definitions.--   "License" shall mean the terms and conditions for use, reproduction,-   and distribution as defined by Sections 1 through 9 of this document.--   "Licensor" shall mean the copyright owner or entity authorized by-   the copyright owner that is granting the License.--   "Legal Entity" shall mean the union of the acting entity and all-   other entities that control, are controlled by, or are under common-   control with that entity. For the purposes of this definition,-   "control" means (i) the power, direct or indirect, to cause the-   direction or management of such entity, whether by contract or-   otherwise, or (ii) ownership of fifty percent (50%) or more of the-   outstanding shares, or (iii) beneficial ownership of such entity.--   "You" (or "Your") shall mean an individual or Legal Entity-   exercising permissions granted by this License.--   "Source" form shall mean the preferred form for making modifications,-   including but not limited to software source code, documentation-   source, and configuration files.--   "Object" form shall mean any form resulting from mechanical-   transformation or translation of a Source form, including but-   not limited to compiled object code, generated documentation,-   and conversions to other media types.--   "Work" shall mean the work of authorship, whether in Source or-   Object form, made available under the License, as indicated by a-   copyright notice that is included in or attached to the work-   (an example is provided in the Appendix below).--   "Derivative Works" shall mean any work, whether in Source or Object-   form, that is based on (or derived from) the Work and for which the-   editorial revisions, annotations, elaborations, or other modifications-   represent, as a whole, an original work of authorship. For the purposes-   of this License, Derivative Works shall not include works that remain-   separable from, or merely link (or bind by name) to the interfaces of,-   the Work and Derivative Works thereof.--   "Contribution" shall mean any work of authorship, including-   the original version of the Work and any modifications or additions-   to that Work or Derivative Works thereof, that is intentionally-   submitted to Licensor for inclusion in the Work by the copyright owner-   or by an individual or Legal Entity authorized to submit on behalf of-   the copyright owner. For the purposes of this definition, "submitted"-   means any form of electronic, verbal, or written communication sent-   to the Licensor or its representatives, including but not limited to-   communication on electronic mailing lists, source code control systems,-   and issue tracking systems that are managed by, or on behalf of, the-   Licensor for the purpose of discussing and improving the Work, but-   excluding communication that is conspicuously marked or otherwise-   designated in writing by the copyright owner as "Not a Contribution."--   "Contributor" shall mean Licensor and any individual or Legal Entity-   on behalf of whom a Contribution has been received by Licensor and-   subsequently incorporated within the Work.--2. Grant of Copyright License. Subject to the terms and conditions of-   this License, each Contributor hereby grants to You a perpetual,-   worldwide, non-exclusive, no-charge, royalty-free, irrevocable-   copyright license to reproduce, prepare Derivative Works of,-   publicly display, publicly perform, sublicense, and distribute the-   Work and such Derivative Works in Source or Object form.--3. Grant of Patent License. Subject to the terms and conditions of-   this License, each Contributor hereby grants to You a perpetual,-   worldwide, non-exclusive, no-charge, royalty-free, irrevocable-   (except as stated in this section) patent license to make, have made,-   use, offer to sell, sell, import, and otherwise transfer the Work,-   where such license applies only to those patent claims licensable-   by such Contributor that are necessarily infringed by their-   Contribution(s) alone or by combination of their Contribution(s)-   with the Work to which such Contribution(s) was submitted. If You-   institute patent litigation against any entity (including a-   cross-claim or counterclaim in a lawsuit) alleging that the Work-   or a Contribution incorporated within the Work constitutes direct-   or contributory patent infringement, then any patent licenses-   granted to You under this License for that Work shall terminate-   as of the date such litigation is filed.--4. Redistribution. You may reproduce and distribute copies of the-   Work or Derivative Works thereof in any medium, with or without-   modifications, and in Source or Object form, provided that You-   meet the following conditions:--   (a) You must give any other recipients of the Work or-       Derivative Works a copy of this License; and--   (b) You must cause any modified files to carry prominent notices-       stating that You changed the files; and--   (c) You must retain, in the Source form of any Derivative Works-       that You distribute, all copyright, patent, trademark, and-       attribution notices from the Source form of the Work,-       excluding those notices that do not pertain to any part of-       the Derivative Works; and--   (d) If the Work includes a "NOTICE" text file as part of its-       distribution, then any Derivative Works that You distribute must-       include a readable copy of the attribution notices contained-       within such NOTICE file, excluding those notices that do not-       pertain to any part of the Derivative Works, in at least one-       of the following places: within a NOTICE text file distributed-       as part of the Derivative Works; within the Source form or-       documentation, if provided along with the Derivative Works; or,-       within a display generated by the Derivative Works, if and-       wherever such third-party notices normally appear. The contents-       of the NOTICE file are for informational purposes only and-       do not modify the License. You may add Your own attribution-       notices within Derivative Works that You distribute, alongside-       or as an addendum to the NOTICE text from the Work, provided-       that such additional attribution notices cannot be construed-       as modifying the License.--   You may add Your own copyright statement to Your modifications and-   may provide additional or different license terms and conditions-   for use, reproduction, or distribution of Your modifications, or-   for any such Derivative Works as a whole, provided Your use,-   reproduction, and distribution of the Work otherwise complies with-   the conditions stated in this License.--5. Submission of Contributions. Unless You explicitly state otherwise,-   any Contribution intentionally submitted for inclusion in the Work-   by You to the Licensor shall be under the terms and conditions of-   this License, without any additional terms or conditions.-   Notwithstanding the above, nothing herein shall supersede or modify-   the terms of any separate license agreement you may have executed-   with Licensor regarding such Contributions.--6. Trademarks. This License does not grant permission to use the trade-   names, trademarks, service marks, or product names of the Licensor,-   except as required for reasonable and customary use in describing the-   origin of the Work and reproducing the content of the NOTICE file.--7. Disclaimer of Warranty. Unless required by applicable law or-   agreed to in writing, Licensor provides the Work (and each-   Contributor provides its Contributions) on an "AS IS" BASIS,-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or-   implied, including, without limitation, any warranties or conditions-   of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A-   PARTICULAR PURPOSE. You are solely responsible for determining the-   appropriateness of using or redistributing the Work and assume any-   risks associated with Your exercise of permissions under this License.--8. Limitation of Liability. In no event and under no legal theory,-   whether in tort (including negligence), contract, or otherwise,-   unless required by applicable law (such as deliberate and grossly-   negligent acts) or agreed to in writing, shall any Contributor be-   liable to You for damages, including any direct, indirect, special,-   incidental, or consequential damages of any character arising as a-   result of this License or out of the use or inability to use the-   Work (including but not limited to damages for loss of goodwill,-   work stoppage, computer failure or malfunction, or any and all-   other commercial damages or losses), even if such Contributor-   has been advised of the possibility of such damages.--9. Accepting Warranty or Additional Liability. While redistributing-   the Work or Derivative Works thereof, You may choose to offer,-   and charge a fee for, acceptance of support, warranty, indemnity,-   or other liability obligations and/or rights consistent with this-   License. However, in accepting such obligations, You may act only-   on Your own behalf and on Your sole responsibility, not on behalf-   of any other Contributor, and only if You agree to indemnify,-   defend, and hold each Contributor harmless for any liability-   incurred by, or claims asserted against, such Contributor by reason-   of your accepting any such warranty or additional liability.--END OF TERMS AND CONDITIONS--APPENDIX: How to apply the Apache License to your work.--   To apply the Apache License to your work, attach the following-   boilerplate notice, with the fields enclosed by brackets "[]"-   replaced with your own identifying information. (Don't include-   the brackets!)  The text should be enclosed in the appropriate-   comment syntax for the file format. We also recommend that a-   file or class name and description of purpose be included on the-   same "printed page" as the copyright notice for easier-   identification within third-party archives.--Copyright [yyyy] [name of copyright owner]--Licensed under the Apache License, Version 2.0 (the "License");-you may not use this file except in compliance with the License.-You may obtain a copy of the License at--	http://www.apache.org/licenses/LICENSE-2.0--Unless required by applicable law or agreed to in writing, software-distributed under the License is distributed on an "AS IS" BASIS,-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.-See the License for the specific language governing permissions and-limitations under the License.diff --git a/examples/raytrace-parallel/README.md b/examples/raytrace-parallel/README.mddeleted file mode 100644index 62ce4b1..0000000--- a/examples/raytrace-parallel/README.md+++ /dev/null@@ -1,7 +0,0 @@-# Example--Run build.sh to build the example.--This example requires the nightly version of Rust. See rust-toolchain.toml--The code is based on the raytrace example in the wasm-bindgen crate. License: Apache-2.0. Original author: Alex Crichton et. al.diff --git a/examples/raytrace-parallel/build.sh b/examples/raytrace-parallel/build.shdeleted file mode 100755index 98860d4..0000000--- a/examples/raytrace-parallel/build.sh+++ /dev/null@@ -1,13 +0,0 @@-#!/bin/sh-set -eu--mkdir -p pkg--CARGO_TARGET_WASM32_UNKNOWN_UNKNOWN_RUSTFLAGS="-Ctarget-feature=+atomics -Clink-args=--shared-memory -Clink-args=--max-memory=1073741824 -Clink-args=--import-memory -Clink-args=--export=__heap_base -Clink-args=--export=__wasm_init_tls -Clink-args=--export=__tls_size -Clink-args=--export=__tls_align -Clink-args=--export=__tls_base" cargo +nightly build -Zbuild-std=std,panic_abort --target wasm32-unknown-unknown-wasm-bindgen target/wasm32-unknown-unknown/debug/raytrace_parallel.wasm --target no-modules --out-dir ./pkg--cp static/index.html ./pkg/-cp static/worker.js ./pkg/-cp static/index.js ./pkg/--python3 server.pydiff --git a/examples/raytrace-parallel/rust-toolchain.toml b/examples/raytrace-parallel/rust-toolchain.tomldeleted file mode 100644index 2dc8cf0..0000000--- a/examples/raytrace-parallel/rust-toolchain.toml+++ /dev/null@@ -1,5 +0,0 @@-[toolchain]-channel = "nightly"-components = ["rust-src"]-profile = "minimal"-targets = ["wasm32-unknown-unknown"]diff --git a/examples/raytrace-parallel/server.py b/examples/raytrace-parallel/server.pydeleted file mode 100755index 8805579..0000000--- a/examples/raytrace-parallel/server.py+++ /dev/null@@ -1,20 +0,0 @@-#!/usr/bin/env python3-from http.server import HTTPServer, SimpleHTTPRequestHandler, test-from pathlib import Path-import sys--PKG_DIR = Path(__file__).resolve().parent / 'pkg'--class RequestHandler(SimpleHTTPRequestHandler):-    def __init__(self, *args, **kwargs):-        super().__init__(*args, directory=str(PKG_DIR), **kwargs)--    def end_headers(self):-        self.send_header('Cross-Origin-Opener-Policy', 'same-origin')-        self.send_header('Cross-Origin-Embedder-Policy', 'require-corp')-        SimpleHTTPRequestHandler.end_headers(self)--if __name__ == '__main__':-    port=int(sys.argv[1]) if len(sys.argv) > 1 else 8000-    print(f"Serving {PKG_DIR} at http://localhost:{port}/")-    test(RequestHandler, HTTPServer, port=port, bind='127.0.0.1')diff --git a/examples/raytrace-parallel/src/lib.rs b/examples/raytrace-parallel/src/lib.rsdeleted file mode 100644index 3fbd702..0000000--- a/examples/raytrace-parallel/src/lib.rs+++ /dev/null@@ -1,29 +0,0 @@-use kaja_web::prelude::*;-use wasm_bindgen::{JsValue, prelude::wasm_bindgen};--macro_rules! console_log {-    ($($t:tt)*) => (crate::log(&format_args!($($t)*).to_string()))-}--#[wasm_bindgen]-extern "C" {-    #[wasm_bindgen(js_namespace = console)]-    pub(crate) fn log(s: &str);-    #[wasm_bindgen(js_namespace = console, js_name = log)]-    pub(crate) fn logv(x: &JsValue);-}--mod main_component;-mod pool;--#[wasm_bindgen(start)]-pub fn init() {-    log!("Starting");--    std::panic::set_hook(Box::new(console_error_panic_hook::hook));-    console_error_panic_hook::set_once();--    log!("Init callbacks");-    init_callbacks();-    log!("Init complete");-}diff --git a/examples/raytrace-parallel/src/main_component.rs b/examples/raytrace-parallel/src/main_component.rsdeleted file mode 100644index 1677cc3..0000000--- a/examples/raytrace-parallel/src/main_component.rs+++ /dev/null@@ -1,81 +0,0 @@-use kaja_web::prelude::*;-use std::time::Duration;--thread_local! {-    static BACKGROUND_POOL: std::cell::RefCell<Option<crate::pool::WorkerPool>> =-        const { std::cell::RefCell::new(None) };-}--#[component("main-component")]-struct Main {-    test: bool,-}--impl Component for Main {-    fn connected(id: &str) {-        start_background_thread(&id);-    }--    fn update(id: &str) {-        log!(-            "Update from background thread, running on the UI thread:",-            id-        );--        let Some(handle) = Self::get_component(id) else {-            error!("Main component not found:", id);-            return;-        };--        let Some(element) = get_element_by_id(id) else {-            error!("Element not found:", id);-            return;-        };--        let mut component = handle.lock().unwrap();-        component.test = !component.test;-        component.render(&element);-    }-}--impl Main {-    fn render(&self, element: &HtmlElement) {-        element.set_inner_text(&self.test.to_string());-    }-}--fn start_background_thread(id: &str) {-    let component_id = id.to_string();--    BACKGROUND_POOL.with(|pool_slot| {-        if pool_slot.borrow().is_none() {-            match crate::pool::WorkerPool::new(1) {-                Ok(pool) => {-                    *pool_slot.borrow_mut() = Some(pool);-                }-                Err(err) => {-                    error!("Failed to create worker pool for background thread");-                    crate::logv(&err);-                    return;-                }-            }-        }--        let pool_ref = pool_slot.borrow();-        let pool = pool_ref.as_ref().unwrap();--        if let Err(err) = pool.run(move || {-            loop {-                Main::post_ui_thread_update(component_id.as_str());-                std::thread::sleep(Duration::from_millis(1000));--                // this a background thread, so:-                // try_inner_html("#test", "<b>INNER_HTML</b>");-                // will not update the DOM. Only the UI thread can do that.-            }-        }) {-            error!("Failed to spawn background worker task");-            crate::logv(&err);-        }-    });-}diff --git a/examples/raytrace-parallel/src/pool.rs b/examples/raytrace-parallel/src/pool.rsdeleted file mode 100644index 6a0470d..0000000--- a/examples/raytrace-parallel/src/pool.rs+++ /dev/null@@ -1,219 +0,0 @@-// Silences warnings from the compiler about Work.func and child_entry_point-// being unused when the target is not wasm.-#![cfg_attr(not(target_arch = "wasm32"), allow(dead_code))]--//! A small module that's intended to provide an example of creating a pool of-//! web workers which can be used to execute `rayon`-style work.--use std::cell::RefCell;-use std::rc::Rc;-use wasm_bindgen::prelude::*;-use web_sys::{DedicatedWorkerGlobalScope, MessageEvent};-use web_sys::{ErrorEvent, Event, Worker};--#[wasm_bindgen]-pub struct WorkerPool {-    state: Rc<PoolState>,-}--struct PoolState {-    workers: RefCell<Vec<Worker>>,-    callback: Closure<dyn FnMut(Event)>,-}--struct Work {-    func: Box<dyn FnOnce() + Send>,-}--#[wasm_bindgen]-impl WorkerPool {-    /// Creates a new `WorkerPool` which immediately creates `initial` workers.-    ///-    /// The pool created here can be used over a long period of time, and it-    /// will be initially primed with `initial` workers. Currently workers are-    /// never released or gc'd until the whole pool is destroyed.-    ///-    /// # Errors-    ///-    /// Returns any error that may happen while a JS web worker is created and a-    /// message is sent to it.-    #[wasm_bindgen(constructor)]-    pub fn new(initial: usize) -> Result<WorkerPool, JsValue> {-        let pool = WorkerPool {-            state: Rc::new(PoolState {-                workers: RefCell::new(Vec::with_capacity(initial)),-                callback: Closure::new(|event: Event| {-                    console_log!("unhandled event: {}", event.type_());-                    crate::logv(&event);-                }),-            }),-        };-        for _ in 0..initial {-            let worker = pool.spawn()?;-            pool.state.push(worker);-        }--        Ok(pool)-    }--    /// Unconditionally spawns a new worker-    ///-    /// The worker isn't registered with this `WorkerPool` but is capable of-    /// executing work for this Wasm module.-    ///-    /// # Errors-    ///-    /// Returns any error that may happen while a JS web worker is created and a-    /// message is sent to it.-    fn spawn(&self) -> Result<Worker, JsValue> {-        console_log!("spawning new worker");-        // TODO: what to do about `./worker.js`:-        //-        // * the path is only known by the bundler. How can we, as a-        //   library, know what's going on?-        // * How do we not fetch a script N times? It internally then-        //   causes another script to get fetched N times...-        let worker = Worker::new("./worker.js")?;--        // With a worker spun up send it the module/memory so it can start-        // instantiating the Wasm module. Later it might receive further-        // messages about code to run on the Wasm module.-        let array = js_sys::Array::new();-        array.push(&wasm_bindgen::module());-        array.push(&wasm_bindgen::memory());-        worker.post_message(&array)?;--        Ok(worker)-    }--    /// Fetches a worker from this pool, spawning one if necessary.-    ///-    /// This will attempt to pull an already-spawned web worker from our cache-    /// if one is available, otherwise it will spawn a new worker and return the-    /// newly spawned worker.-    ///-    /// # Errors-    ///-    /// Returns any error that may happen while a JS web worker is created and a-    /// message is sent to it.-    fn worker(&self) -> Result<Worker, JsValue> {-        match self.state.workers.borrow_mut().pop() {-            Some(worker) => Ok(worker),-            None => self.spawn(),-        }-    }--    /// Executes the work `f` in a web worker, spawning a web worker if-    /// necessary.-    ///-    /// This will acquire a web worker and then send the closure `f` to the-    /// worker to execute. The worker won't be usable for anything else while-    /// `f` is executing, and no callbacks are registered for when the worker-    /// finishes.-    ///-    /// # Errors-    ///-    /// Returns any error that may happen while a JS web worker is created and a-    /// message is sent to it.-    fn execute(&self, f: impl FnOnce() + Send + 'static) -> Result<Worker, JsValue> {-        let worker = self.worker()?;-        let work = Box::new(Work { func: Box::new(f) });-        let ptr = Box::into_raw(work);-        match worker.post_message(&JsValue::from(ptr as u32)) {-            Ok(()) => Ok(worker),-            Err(e) => {-                unsafe {-                    drop(Box::from_raw(ptr));-                }-                Err(e)-            }-        }-    }--    /// Configures an `onmessage` callback for the `worker` specified for the-    /// web worker to be reclaimed and re-inserted into this pool when a message-    /// is received.-    ///-    /// Currently this `WorkerPool` abstraction is intended to execute one-off-    /// style work where the work itself doesn't send any notifications and-    /// whatn it's done the worker is ready to execute more work. This method is-    /// used for all spawned workers to ensure that when the work is finished-    /// the worker is reclaimed back into this pool.-    fn reclaim_on_message(&self, worker: Worker) {-        let state = Rc::downgrade(&self.state);-        let worker2 = worker.clone();-        let reclaim_slot = Rc::new(RefCell::new(None));-        let slot2 = reclaim_slot.clone();-        let reclaim = Closure::<dyn FnMut(_)>::new(move |event: Event| {-            if let Some(error) = event.dyn_ref::<ErrorEvent>() {-                console_log!("error in worker: {}", error.message());-                // TODO: this probably leaks memory somehow? It's sort of-                // unclear what to do about errors in workers right now.-                return;-            }--            // If this is a completion event then can deallocate our own-            // callback by clearing out `slot2` which contains our own closure.-            if let Some(_msg) = event.dyn_ref::<MessageEvent>() {-                if let Some(state) = state.upgrade() {-                    state.push(worker2.clone());-                }-                *slot2.borrow_mut() = None;-                return;-            }--            console_log!("unhandled event: {}", event.type_());-            crate::logv(&event);-            // TODO: like above, maybe a memory leak here?-        });-        worker.set_onmessage(Some(reclaim.as_ref().unchecked_ref()));-        *reclaim_slot.borrow_mut() = Some(reclaim);-    }-}--impl WorkerPool {-    /// Executes `f` in a web worker.-    ///-    /// This pool manages a set of web workers to draw from, and `f` will be-    /// spawned quickly into one if the worker is idle. If no idle workers are-    /// available then a new web worker will be spawned.-    ///-    /// Once `f` returns the worker assigned to `f` is automatically reclaimed-    /// by this `WorkerPool`. This method provides no method of learning when-    /// `f` completes, and for that you'll need to use `run_notify`.-    ///-    /// # Errors-    ///-    /// If an error happens while spawning a web worker or sending a message to-    /// a web worker, that error is returned.-    pub fn run(&self, f: impl FnOnce() + Send + 'static) -> Result<(), JsValue> {-        let worker = self.execute(f)?;-        self.reclaim_on_message(worker);-        Ok(())-    }-}--impl PoolState {-    fn push(&self, worker: Worker) {-        worker.set_onmessage(Some(self.callback.as_ref().unchecked_ref()));-        worker.set_onerror(Some(self.callback.as_ref().unchecked_ref()));-        let mut workers = self.workers.borrow_mut();-        for prev in workers.iter() {-            let prev: &JsValue = prev;-            let worker: &JsValue = &worker;-            assert!(prev != worker);-        }-        workers.push(worker);-    }-}--/// Entry point invoked by `worker.js`, a bit of a hack but see the "TODO" above-/// about `worker.js` in general.-#[wasm_bindgen]-pub fn child_entry_point(ptr: u32) -> Result<(), JsValue> {-    let ptr = unsafe { Box::from_raw(ptr as *mut Work) };-    let global = js_sys::global().unchecked_into::<DedicatedWorkerGlobalScope>();-    (ptr.func)();-    global.post_message(&JsValue::undefined())?;-    Ok(())-}diff --git a/examples/raytrace-parallel/static/index.html b/examples/raytrace-parallel/static/index.htmldeleted file mode 100644index c7385de..0000000--- a/examples/raytrace-parallel/static/index.html+++ /dev/null@@ -1,10 +0,0 @@-<html>-  <head>-      <title>Wasm Threads</title>-  </head>-  <body>-    Known: <main-component></main-component>-    <script src='raytrace_parallel.js'></script>-    <script src='index.js'></script>-  </body>-</html>diff --git a/examples/raytrace-parallel/static/index.js b/examples/raytrace-parallel/static/index.jsdeleted file mode 100644index 6ecf9b8..0000000--- a/examples/raytrace-parallel/static/index.js+++ /dev/null@@ -1,19 +0,0 @@-function loadWasm() {-  if (typeof SharedArrayBuffer !== 'function') {-    console.error('this browser does not have SharedArrayBuffer support enabled' + '\n\n' + msg);-    return-  }-  // Test for bulk memory operations with passive data segments-  //  (module (memory 1) (data passive ""))-  const buf = new Uint8Array([0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00,-    0x05, 0x03, 0x01, 0x00, 0x01, 0x0b, 0x03, 0x01, 0x01, 0x00]);-  if (!WebAssembly.validate(buf)) {-    console.error('This browser does not support passive Wasm memory, Background threads will not work' + '\n\n' + msg);-    return-  }--  wasm_bindgen()-    .catch(console.error);-}--loadWasm();diff --git a/examples/raytrace-parallel/static/worker.js b/examples/raytrace-parallel/static/worker.jsdeleted file mode 100644index 26d40c6..0000000--- a/examples/raytrace-parallel/static/worker.js+++ /dev/null@@ -1,25 +0,0 @@-// synchronously, using the browser, import out shim JS scripts-importScripts('raytrace_parallel.js');--// Wait for the main thread to send us the shared module/memory. Once we've got-// it, initialize it all with the `wasm_bindgen` global we imported via-// `importScripts`.-//-// After our first message all subsequent messages are an entry point to run,-// so we just do that.-self.onmessage = event => {-  let initialised = wasm_bindgen(...event.data).catch(err => {-    // Propagate to main `onerror`:-    setTimeout(() => {-      throw err;-    });-    // Rethrow to keep promise rejected and prevent execution of further commands:-    throw err;-  });--  self.onmessage = async event => {-    // This will queue further commands up until the module is fully initialised:-    await initialised;-    wasm_bindgen.child_entry_point(event.data);-  };-};diff --git a/examples/threads/Cargo.lock b/examples/threads/Cargo.locknew file mode 100644index 0000000..adc78bd--- /dev/null+++ b/examples/threads/Cargo.lock@@ -0,0 +1,950 @@+# This file is automatically @generated by Cargo.+# It is not intended for manual editing.+version = 4++[[package]]+name = "async-channel"+version = "2.5.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "924ed96dd52d1b75e9c1a3e6275715fd320f5f9439fb5a4a11fa51f4221158d2"+dependencies = [+ "concurrent-queue",+ "event-listener-strategy",+ "futures-core",+ "pin-project-lite",+]++[[package]]+name = "bincode"+version = "1.3.3"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad"+dependencies = [+ "serde",+]++[[package]]+name = "bumpalo"+version = "3.20.3"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649"++[[package]]+name = "bytes"+version = "1.12.1"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "fc652a48c352aef3ea3aed32080501cf3ef6ed5da78602a020c991775b0aff04"++[[package]]+name = "cfg-if"+version = "1.0.4"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"++[[package]]+name = "concurrent-queue"+version = "2.5.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973"+dependencies = [+ "crossbeam-utils",+]++[[package]]+name = "console_error_panic_hook"+version = "0.1.7"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc"+dependencies = [+ "cfg-if",+ "wasm-bindgen",+]++[[package]]+name = "crossbeam-utils"+version = "0.8.22"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "61803da095bee82a81bb1a452ecc25d3b2f1416d1897eb86430c6159ef717c17"++[[package]]+name = "equivalent"+version = "1.0.2"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"++[[package]]+name = "event-listener"+version = "5.4.1"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "e13b66accf52311f30a0db42147dadea9850cb48cd070028831ae5f5d4b856ab"+dependencies = [+ "concurrent-queue",+ "parking",+ "pin-project-lite",+]++[[package]]+name = "event-listener-strategy"+version = "0.5.4"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93"+dependencies = [+ "event-listener",+ "pin-project-lite",+]++[[package]]+name = "form_urlencoded"+version = "1.2.2"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf"+dependencies = [+ "percent-encoding",+]++[[package]]+name = "futures"+version = "0.3.32"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d"+dependencies = [+ "futures-channel",+ "futures-core",+ "futures-io",+ "futures-sink",+ "futures-task",+ "futures-util",+]++[[package]]+name = "futures-channel"+version = "0.3.32"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d"+dependencies = [+ "futures-core",+ "futures-sink",+]++[[package]]+name = "futures-channel-preview"+version = "0.3.0-alpha.19"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "d5e5f4df964fa9c1c2f8bddeb5c3611631cacd93baf810fc8bb2fb4b495c263a"+dependencies = [+ "futures-core-preview",+]++[[package]]+name = "futures-core"+version = "0.3.32"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d"++[[package]]+name = "futures-core-preview"+version = "0.3.0-alpha.19"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "b35b6263fb1ef523c3056565fa67b1d16f0a8604ff12b11b08c25f28a734c60a"++[[package]]+name = "futures-io"+version = "0.3.32"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718"++[[package]]+name = "futures-macro"+version = "0.3.32"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b"+dependencies = [+ "proc-macro2",+ "quote",+ "syn 2.0.118",+]++[[package]]+name = "futures-sink"+version = "0.3.32"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893"++[[package]]+name = "futures-task"+version = "0.3.32"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393"++[[package]]+name = "futures-util"+version = "0.3.32"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6"+dependencies = [+ "futures-channel",+ "futures-core",+ "futures-io",+ "futures-macro",+ "futures-sink",+ "futures-task",+ "memchr",+ "pin-project-lite",+ "slab",+]++[[package]]+name = "getrandom"+version = "0.2.17"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0"+dependencies = [+ "cfg-if",+ "js-sys",+ "libc",+ "wasi",+ "wasm-bindgen",+]++[[package]]+name = "getrandom"+version = "0.4.3"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099"+dependencies = [+ "cfg-if",+ "libc",+ "r-efi",+]++[[package]]+name = "gloo"+version = "0.12.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "dc13cc21c3835347855fd83900414d94716adc1e332f09f7fba56f21be127214"+dependencies = [+ "gloo-console",+ "gloo-dialogs",+ "gloo-events",+ "gloo-file",+ "gloo-history",+ "gloo-net",+ "gloo-render",+ "gloo-storage",+ "gloo-timers",+ "gloo-utils 0.3.0",+ "gloo-worker",+]++[[package]]+name = "gloo-console"+version = "0.4.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "9f1d5cec0b97edb53f21221f799c659cef3764ad5a00eca52950eb9b902028ba"+dependencies = [+ "gloo-utils 0.3.0",+ "js-sys",+ "serde",+ "wasm-bindgen",+ "web-sys",+]++[[package]]+name = "gloo-dialogs"+version = "0.3.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "45618929b7022bb49903b958b5b7af1d4fb58fbd99712926d91641fe582f3d55"+dependencies = [+ "wasm-bindgen",+ "web-sys",+]++[[package]]+name = "gloo-events"+version = "0.3.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "8c6a94fa8cd88bea0babf8a27fe9abbcdece831fd1c3c84dd5c231fab4685ec7"+dependencies = [+ "wasm-bindgen",+ "web-sys",+]++[[package]]+name = "gloo-file"+version = "0.4.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "544a15ff6a3d5976bebc97380c8471ae14283bc71f4bb198d6c8cae64f411ab7"+dependencies = [+ "futures-channel",+ "gloo-events",+ "js-sys",+ "wasm-bindgen",+ "web-sys",+]++[[package]]+name = "gloo-history"+version = "0.3.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "f07f3d446931414cc92f4a1b6e631dfa233db2f96c887d5f72beeecd1b5db39c"+dependencies = [+ "getrandom 0.2.17",+ "gloo-events",+ "gloo-utils 0.3.0",+ "serde",+ "serde-wasm-bindgen 0.6.5",+ "serde_urlencoded",+ "thiserror 2.0.18",+ "wasm-bindgen",+ "web-sys",+]++[[package]]+name = "gloo-net"+version = "0.7.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "a6420f887c48417e9e86c6cf61274eb231830cccc100e49613f7952e269a1fe1"+dependencies = [+ "futures-channel",+ "futures-core",+ "futures-sink",+ "gloo-utils 0.3.0",+ "http",+ "js-sys",+ "pin-project",+ "serde",+ "serde_json",+ "thiserror 2.0.18",+ "wasm-bindgen",+ "wasm-bindgen-futures",+ "web-sys",+]++[[package]]+name = "gloo-render"+version = "0.3.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "3f609333b9e38e43e74224410d6616e3ad773ed6fe14f53cd8a006d1bb25e108"+dependencies = [+ "wasm-bindgen",+ "web-sys",+]++[[package]]+name = "gloo-storage"+version = "0.4.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "e82ce7d41c6d821640a43726f6ff33c924795cc151b62e5a84d0c988c151c980"+dependencies = [+ "gloo-utils 0.3.0",+ "js-sys",+ "serde",+ "serde_json",+ "thiserror 2.0.18",+ "wasm-bindgen",+ "web-sys",+]++[[package]]+name = "gloo-timers"+version = "0.4.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "482ce8a491a501da4cd806bd190275363d674f2845005c6ddbd5d3e1dd54495d"+dependencies = [+ "futures-channel",+ "futures-core",+ "js-sys",+ "wasm-bindgen",+]++[[package]]+name = "gloo-utils"+version = "0.2.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "0b5555354113b18c547c1d3a98fbf7fb32a9ff4f6fa112ce823a21641a0ba3aa"+dependencies = [+ "js-sys",+ "serde",+ "serde_json",+ "wasm-bindgen",+ "web-sys",+]++[[package]]+name = "gloo-utils"+version = "0.3.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "4202275d95a142fa209a1e35e91c250a710c5600731372cd3464a39ed01573d6"+dependencies = [+ "js-sys",+ "serde",+ "serde_json",+ "wasm-bindgen",+ "web-sys",+]++[[package]]+name = "gloo-worker"+version = "0.6.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "142478655c5d764e5168d3019510ea0c0885687a72ba74e90548bd74ae160a41"+dependencies = [+ "bincode",+ "futures",+ "gloo-utils 0.2.0",+ "gloo-worker-macros",+ "js-sys",+ "pinned",+ "serde",+ "thiserror 2.0.18",+ "wasm-bindgen",+ "wasm-bindgen-futures",+ "web-sys",+]++[[package]]+name = "gloo-worker-macros"+version = "0.2.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "f3bf5ede96b06406bd74351a026f708ae196b7dc262077aee56e6ad7223e7466"+dependencies = [+ "proc-macro-crate",+ "proc-macro2",+ "quote",+ "syn 2.0.118",+]++[[package]]+name = "hashbrown"+version = "0.17.1"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a"++[[package]]+name = "http"+version = "1.4.2"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "6970f50e31d6fc17d3fa27329444bfa74e196cf62e95052a3f6fee181dba6425"+dependencies = [+ "bytes",+ "itoa",+]++[[package]]+name = "indexmap"+version = "2.14.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9"+dependencies = [+ "equivalent",+ "hashbrown",+]++[[package]]+name = "inventory"+version = "0.3.24"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "a4f0c30c76f2f4ccee3fe55a2435f691ca00c0e4bd87abe4f4a851b1d4dac39b"+dependencies = [+ "rustversion",+]++[[package]]+name = "itoa"+version = "1.0.18"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"++[[package]]+name = "js-sys"+version = "0.3.103"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "53b44bfcdb3f8d5837a46dae1ca9660a837176eee74a28b229bc626816589102"+dependencies = [+ "cfg-if",+ "futures-util",+ "wasm-bindgen",+]++[[package]]+name = "kaja-callback-macro"+version = "1.0.0"+dependencies = [+ "gloo",+ "proc-macro2",+ "quote",+ "syn 2.0.118",+]++[[package]]+name = "kaja-html-macro"+version = "1.0.5"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "a5c37d76721e795460d8ba194309f8c989a64a66dc79118de9dccc083e5fe9db"+dependencies = [+ "proc-macro-error",+ "proc-macro2",+ "quote",+ "syn 2.0.118",+]++[[package]]+name = "kaja-web"+version = "1.0.2"+dependencies = [+ "gloo",+ "gloo-console",+ "inventory",+ "js-sys",+ "kaja-callback-macro",+ "kaja-html-macro",+ "kaja-web-component",+ "serde",+ "serde-wasm-bindgen 0.5.0",+ "wasm-bindgen",+ "wasm-bindgen-futures",+ "web-sys",+]++[[package]]+name = "kaja-web-component"+version = "0.1.0"+dependencies = [+ "gloo",+ "inventory",+ "js-sys",+ "proc-macro2",+ "quote",+ "syn 2.0.118",+ "wasm-bindgen",+ "web-sys",+]++[[package]]+name = "libc"+version = "0.2.186"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66"++[[package]]+name = "memchr"+version = "2.8.3"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98"++[[package]]+name = "once_cell"+version = "1.21.4"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"++[[package]]+name = "parking"+version = "2.2.1"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba"++[[package]]+name = "percent-encoding"+version = "2.3.2"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220"++[[package]]+name = "pin-project"+version = "1.1.13"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "2466b2336ed02bcdca6b294417127b90ec92038d1d5c4fbeac971a922e0e0924"+dependencies = [+ "pin-project-internal",+]++[[package]]+name = "pin-project-internal"+version = "1.1.13"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "c96395f0a926bc13b1c17622aaddda1ecb55d49c8f1bf9777e4d877800a43f8b"+dependencies = [+ "proc-macro2",+ "quote",+ "syn 2.0.118",+]++[[package]]+name = "pin-project-lite"+version = "0.2.17"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd"++[[package]]+name = "pinned"+version = "0.1.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "a829027bd95e54cfe13e3e258a1ae7b645960553fb82b75ff852c29688ee595b"+dependencies = [+ "futures",+ "rustversion",+ "thiserror 1.0.69",+]++[[package]]+name = "proc-macro-crate"+version = "3.3.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "edce586971a4dfaa28950c6f18ed55e0406c1ab88bbce2c6f6293a7aaba73d35"+dependencies = [+ "toml_edit",+]++[[package]]+name = "proc-macro-error"+version = "1.0.4"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"+dependencies = [+ "proc-macro-error-attr",+ "proc-macro2",+ "quote",+ "syn 1.0.109",+ "version_check",+]++[[package]]+name = "proc-macro-error-attr"+version = "1.0.4"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"+dependencies = [+ "proc-macro2",+ "quote",+ "version_check",+]++[[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.46"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "dfbc457d0c7a0759a614551b11a6409e5951f6c7537be1f1b7682b9ae9230368"+dependencies = [+ "proc-macro2",+]++[[package]]+name = "r-efi"+version = "6.0.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf"++[[package]]+name = "raytrace-parallel"+version = "0.0.0"+dependencies = [+ "async-channel",+ "console_error_panic_hook",+ "futures-channel-preview",+ "gloo",+ "gloo-timers",+ "inventory",+ "js-sys",+ "kaja-html-macro",+ "kaja-web",+ "kaja-web-component",+ "serde",+ "serde-wasm-bindgen 0.6.5",+ "serde_json",+ "uuid",+ "wasm-bindgen",+ "wasm-bindgen-futures",+ "web-sys",+]++[[package]]+name = "rustversion"+version = "1.0.23"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f"++[[package]]+name = "ryu"+version = "1.0.23"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f"++[[package]]+name = "serde"+version = "1.0.228"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"+dependencies = [+ "serde_core",+ "serde_derive",+]++[[package]]+name = "serde-wasm-bindgen"+version = "0.5.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "f3b143e2833c57ab9ad3ea280d21fd34e285a42837aeb0ee301f4f41890fa00e"+dependencies = [+ "js-sys",+ "serde",+ "wasm-bindgen",+]++[[package]]+name = "serde-wasm-bindgen"+version = "0.6.5"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "8302e169f0eddcc139c70f139d19d6467353af16f9fce27e8c30158036a1e16b"+dependencies = [+ "js-sys",+ "serde",+ "wasm-bindgen",+]++[[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 2.0.118",+]++[[package]]+name = "serde_json"+version = "1.0.150"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9"+dependencies = [+ "itoa",+ "memchr",+ "serde",+ "serde_core",+ "zmij",+]++[[package]]+name = "serde_urlencoded"+version = "0.7.1"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd"+dependencies = [+ "form_urlencoded",+ "itoa",+ "ryu",+ "serde",+]++[[package]]+name = "slab"+version = "0.4.12"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5"++[[package]]+name = "syn"+version = "1.0.109"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"+dependencies = [+ "proc-macro2",+ "unicode-ident",+]++[[package]]+name = "syn"+version = "2.0.118"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "1b9ae57f904213ebb649ce6895b8a66c66f0203b9319718f69a5612a065b1422"+dependencies = [+ "proc-macro2",+ "quote",+ "unicode-ident",+]++[[package]]+name = "thiserror"+version = "1.0.69"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"+dependencies = [+ "thiserror-impl 1.0.69",+]++[[package]]+name = "thiserror"+version = "2.0.18"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4"+dependencies = [+ "thiserror-impl 2.0.18",+]++[[package]]+name = "thiserror-impl"+version = "1.0.69"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"+dependencies = [+ "proc-macro2",+ "quote",+ "syn 2.0.118",+]++[[package]]+name = "thiserror-impl"+version = "2.0.18"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5"+dependencies = [+ "proc-macro2",+ "quote",+ "syn 2.0.118",+]++[[package]]+name = "toml_datetime"+version = "0.6.11"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c"++[[package]]+name = "toml_edit"+version = "0.22.27"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a"+dependencies = [+ "indexmap",+ "toml_datetime",+ "winnow",+]++[[package]]+name = "unicode-ident"+version = "1.0.24"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"++[[package]]+name = "uuid"+version = "1.23.4"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "bf80a72845275afea99e7f2b434723d3bc7e38470fcd1c7ed39a599c73319a53"+dependencies = [+ "getrandom 0.4.3",+ "js-sys",+ "wasm-bindgen",+]++[[package]]+name = "version_check"+version = "0.9.5"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"++[[package]]+name = "wasi"+version = "0.11.1+wasi-snapshot-preview1"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"++[[package]]+name = "wasm-bindgen"+version = "0.2.126"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "4b067c0c11094aef6b7a801c1e34a26affafdf3d051dba08456b868789aaf9a4"+dependencies = [+ "cfg-if",+ "once_cell",+ "rustversion",+ "wasm-bindgen-macro",+ "wasm-bindgen-shared",+]++[[package]]+name = "wasm-bindgen-futures"+version = "0.4.76"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "c62df1340f32221cb9c54d6a27b030e3dba64361d4a95bed55f9aacb44da291d"+dependencies = [+ "js-sys",+ "wasm-bindgen",+]++[[package]]+name = "wasm-bindgen-macro"+version = "0.2.126"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "167ce5e579f6bcf889c4f7175a8a5a585de84e8ff93976ce393efa5f2837aab1"+dependencies = [+ "quote",+ "wasm-bindgen-macro-support",+]++[[package]]+name = "wasm-bindgen-macro-support"+version = "0.2.126"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "f3997c7839262f4ef12cf90b818d6340c18e80f263f1a94bf157d0ec4420380e"+dependencies = [+ "bumpalo",+ "proc-macro2",+ "quote",+ "syn 2.0.118",+ "wasm-bindgen-shared",+]++[[package]]+name = "wasm-bindgen-shared"+version = "0.2.126"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "dc1b4cb0cc549fcf58d7dfc081778139b3d283a081644e833e84682ad71cea24"+dependencies = [+ "unicode-ident",+]++[[package]]+name = "web-sys"+version = "0.3.103"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "8622dcb61c0bcc9fffa6938bed81210af2da9a7e4a1a834b2e37a59b6dfb6141"+dependencies = [+ "js-sys",+ "wasm-bindgen",+]++[[package]]+name = "winnow"+version = "0.7.15"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945"+dependencies = [+ "memchr",+]++[[package]]+name = "zmij"+version = "1.0.21"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa"diff --git a/examples/threads/Cargo.toml b/examples/threads/Cargo.tomlnew file mode 100644index 0000000..d16447f--- /dev/null+++ b/examples/threads/Cargo.toml@@ -0,0 +1,43 @@+[package]+authors = ["The wasm-bindgen Developers"]+edition = "2021"+name = "raytrace-parallel"+publish = false+version = "0.0.0"++[lib]+crate-type = ["cdylib"]++[dependencies]+console_error_panic_hook = "0.1"+futures-channel-preview = "0.3.0-alpha.18"+js-sys = "0.3.103"+serde-wasm-bindgen = "0.6"+wasm-bindgen = "0.2.126"+wasm-bindgen-futures = "0.4.76"++web-sys = { version = "0.3.103", features = [+  "ErrorEvent",+  "Event",+  "Navigator",+  "Window",+  "Worker",+  "DedicatedWorkerGlobalScope",+  "MessageEvent",+  "Element",+  "HtmlElement",+  "NodeList",+  "CustomElementRegistry",+  "ElementDefinitionOptions"+] }++kaja-web = { path = "../.." }+kaja-web-component = { path = "../../../kaja-web-component" }+gloo = { version = "0.12", features = ["futures"] }+kaja-html-macro = "1.0.4"+serde = { version = "1.0.228", features = ["derive"] }+serde_json = "1.0.150"+uuid = { version = "1.23.2", features = ["js", "v4"] }+inventory = "0.3.24"+gloo-timers = { version = "0.4.0", features = ["futures"] }+async-channel = "2"diff --git a/examples/threads/LICENSE-APACHE b/examples/threads/LICENSE-APACHEnew file mode 100644index 0000000..16fe87b--- /dev/null+++ b/examples/threads/LICENSE-APACHE@@ -0,0 +1,201 @@+                              Apache License+                        Version 2.0, January 2004+                     http://www.apache.org/licenses/++TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION++1. Definitions.++   "License" shall mean the terms and conditions for use, reproduction,+   and distribution as defined by Sections 1 through 9 of this document.++   "Licensor" shall mean the copyright owner or entity authorized by+   the copyright owner that is granting the License.++   "Legal Entity" shall mean the union of the acting entity and all+   other entities that control, are controlled by, or are under common+   control with that entity. For the purposes of this definition,+   "control" means (i) the power, direct or indirect, to cause the+   direction or management of such entity, whether by contract or+   otherwise, or (ii) ownership of fifty percent (50%) or more of the+   outstanding shares, or (iii) beneficial ownership of such entity.++   "You" (or "Your") shall mean an individual or Legal Entity+   exercising permissions granted by this License.++   "Source" form shall mean the preferred form for making modifications,+   including but not limited to software source code, documentation+   source, and configuration files.++   "Object" form shall mean any form resulting from mechanical+   transformation or translation of a Source form, including but+   not limited to compiled object code, generated documentation,+   and conversions to other media types.++   "Work" shall mean the work of authorship, whether in Source or+   Object form, made available under the License, as indicated by a+   copyright notice that is included in or attached to the work+   (an example is provided in the Appendix below).++   "Derivative Works" shall mean any work, whether in Source or Object+   form, that is based on (or derived from) the Work and for which the+   editorial revisions, annotations, elaborations, or other modifications+   represent, as a whole, an original work of authorship. For the purposes+   of this License, Derivative Works shall not include works that remain+   separable from, or merely link (or bind by name) to the interfaces of,+   the Work and Derivative Works thereof.++   "Contribution" shall mean any work of authorship, including+   the original version of the Work and any modifications or additions+   to that Work or Derivative Works thereof, that is intentionally+   submitted to Licensor for inclusion in the Work by the copyright owner+   or by an individual or Legal Entity authorized to submit on behalf of+   the copyright owner. For the purposes of this definition, "submitted"+   means any form of electronic, verbal, or written communication sent+   to the Licensor or its representatives, including but not limited to+   communication on electronic mailing lists, source code control systems,+   and issue tracking systems that are managed by, or on behalf of, the+   Licensor for the purpose of discussing and improving the Work, but+   excluding communication that is conspicuously marked or otherwise+   designated in writing by the copyright owner as "Not a Contribution."++   "Contributor" shall mean Licensor and any individual or Legal Entity+   on behalf of whom a Contribution has been received by Licensor and+   subsequently incorporated within the Work.++2. Grant of Copyright License. Subject to the terms and conditions of+   this License, each Contributor hereby grants to You a perpetual,+   worldwide, non-exclusive, no-charge, royalty-free, irrevocable+   copyright license to reproduce, prepare Derivative Works of,+   publicly display, publicly perform, sublicense, and distribute the+   Work and such Derivative Works in Source or Object form.++3. Grant of Patent License. Subject to the terms and conditions of+   this License, each Contributor hereby grants to You a perpetual,+   worldwide, non-exclusive, no-charge, royalty-free, irrevocable+   (except as stated in this section) patent license to make, have made,+   use, offer to sell, sell, import, and otherwise transfer the Work,+   where such license applies only to those patent claims licensable+   by such Contributor that are necessarily infringed by their+   Contribution(s) alone or by combination of their Contribution(s)+   with the Work to which such Contribution(s) was submitted. If You+   institute patent litigation against any entity (including a+   cross-claim or counterclaim in a lawsuit) alleging that the Work+   or a Contribution incorporated within the Work constitutes direct+   or contributory patent infringement, then any patent licenses+   granted to You under this License for that Work shall terminate+   as of the date such litigation is filed.++4. Redistribution. You may reproduce and distribute copies of the+   Work or Derivative Works thereof in any medium, with or without+   modifications, and in Source or Object form, provided that You+   meet the following conditions:++   (a) You must give any other recipients of the Work or+       Derivative Works a copy of this License; and++   (b) You must cause any modified files to carry prominent notices+       stating that You changed the files; and++   (c) You must retain, in the Source form of any Derivative Works+       that You distribute, all copyright, patent, trademark, and+       attribution notices from the Source form of the Work,+       excluding those notices that do not pertain to any part of+       the Derivative Works; and++   (d) If the Work includes a "NOTICE" text file as part of its+       distribution, then any Derivative Works that You distribute must+       include a readable copy of the attribution notices contained+       within such NOTICE file, excluding those notices that do not+       pertain to any part of the Derivative Works, in at least one+       of the following places: within a NOTICE text file distributed+       as part of the Derivative Works; within the Source form or+       documentation, if provided along with the Derivative Works; or,+       within a display generated by the Derivative Works, if and+       wherever such third-party notices normally appear. The contents+       of the NOTICE file are for informational purposes only and+       do not modify the License. You may add Your own attribution+       notices within Derivative Works that You distribute, alongside+       or as an addendum to the NOTICE text from the Work, provided+       that such additional attribution notices cannot be construed+       as modifying the License.++   You may add Your own copyright statement to Your modifications and+   may provide additional or different license terms and conditions+   for use, reproduction, or distribution of Your modifications, or+   for any such Derivative Works as a whole, provided Your use,+   reproduction, and distribution of the Work otherwise complies with+   the conditions stated in this License.++5. Submission of Contributions. Unless You explicitly state otherwise,+   any Contribution intentionally submitted for inclusion in the Work+   by You to the Licensor shall be under the terms and conditions of+   this License, without any additional terms or conditions.+   Notwithstanding the above, nothing herein shall supersede or modify+   the terms of any separate license agreement you may have executed+   with Licensor regarding such Contributions.++6. Trademarks. This License does not grant permission to use the trade+   names, trademarks, service marks, or product names of the Licensor,+   except as required for reasonable and customary use in describing the+   origin of the Work and reproducing the content of the NOTICE file.++7. Disclaimer of Warranty. Unless required by applicable law or+   agreed to in writing, Licensor provides the Work (and each+   Contributor provides its Contributions) on an "AS IS" BASIS,+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or+   implied, including, without limitation, any warranties or conditions+   of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A+   PARTICULAR PURPOSE. You are solely responsible for determining the+   appropriateness of using or redistributing the Work and assume any+   risks associated with Your exercise of permissions under this License.++8. Limitation of Liability. In no event and under no legal theory,+   whether in tort (including negligence), contract, or otherwise,+   unless required by applicable law (such as deliberate and grossly+   negligent acts) or agreed to in writing, shall any Contributor be+   liable to You for damages, including any direct, indirect, special,+   incidental, or consequential damages of any character arising as a+   result of this License or out of the use or inability to use the+   Work (including but not limited to damages for loss of goodwill,+   work stoppage, computer failure or malfunction, or any and all+   other commercial damages or losses), even if such Contributor+   has been advised of the possibility of such damages.++9. Accepting Warranty or Additional Liability. While redistributing+   the Work or Derivative Works thereof, You may choose to offer,+   and charge a fee for, acceptance of support, warranty, indemnity,+   or other liability obligations and/or rights consistent with this+   License. However, in accepting such obligations, You may act only+   on Your own behalf and on Your sole responsibility, not on behalf+   of any other Contributor, and only if You agree to indemnify,+   defend, and hold each Contributor harmless for any liability+   incurred by, or claims asserted against, such Contributor by reason+   of your accepting any such warranty or additional liability.++END OF TERMS AND CONDITIONS++APPENDIX: How to apply the Apache License to your work.++   To apply the Apache License to your work, attach the following+   boilerplate notice, with the fields enclosed by brackets "[]"+   replaced with your own identifying information. (Don't include+   the brackets!)  The text should be enclosed in the appropriate+   comment syntax for the file format. We also recommend that a+   file or class name and description of purpose be included on the+   same "printed page" as the copyright notice for easier+   identification within third-party archives.++Copyright [yyyy] [name of copyright owner]++Licensed under the Apache License, Version 2.0 (the "License");+you may not use this file except in compliance with the License.+You may obtain a copy of the License at++	http://www.apache.org/licenses/LICENSE-2.0++Unless required by applicable law or agreed to in writing, software+distributed under the License is distributed on an "AS IS" BASIS,+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.+See the License for the specific language governing permissions and+limitations under the License.diff --git a/examples/threads/README.md b/examples/threads/README.mdnew file mode 100644index 0000000..69bc2bf--- /dev/null+++ b/examples/threads/README.md@@ -0,0 +1,20 @@+# Example++Run build.sh to build the example.++This example requires the nightly version of Rust. See rust-toolchain.toml++The more common way to do parallel work in the browser is to use async/await+style code with++```+use wasm_bindgen_futures::spawn_local;++spawn_local(async {+    // your async work here+});+```++See the async example.++The code is based on the raytrace example in the wasm-bindgen crate. License: Apache-2.0. Original author: Alex Crichton et. al.diff --git a/examples/threads/build.sh b/examples/threads/build.shnew file mode 100755index 0000000..d67df3c--- /dev/null+++ b/examples/threads/build.sh@@ -0,0 +1,11 @@+#!/bin/sh+set -eu++mkdir -p pkg++CARGO_TARGET_WASM32_UNKNOWN_UNKNOWN_RUSTFLAGS="-Ctarget-feature=+atomics -Clink-args=--shared-memory -Clink-args=--max-memory=1073741824 -Clink-args=--import-memory -Clink-args=--export=__heap_base -Clink-args=--export=__wasm_init_tls -Clink-args=--export=__tls_size -Clink-args=--export=__tls_align -Clink-args=--export=__tls_base" cargo +nightly build -Zbuild-std=std,panic_abort --target wasm32-unknown-unknown+wasm-bindgen target/wasm32-unknown-unknown/debug/raytrace_parallel.wasm --target no-modules --out-dir ./pkg++cp static/index.html ./pkg/+cp static/worker.js ./pkg/+cp static/index.js ./pkg/diff --git a/examples/threads/run.sh b/examples/threads/run.shnew file mode 100755index 0000000..0d29c05--- /dev/null+++ b/examples/threads/run.sh@@ -0,0 +1,6 @@+#!/bin/sh+set -eu++./build.sh++python3 server.pydiff --git a/examples/threads/rust-toolchain.toml b/examples/threads/rust-toolchain.tomlnew file mode 100644index 0000000..2dc8cf0--- /dev/null+++ b/examples/threads/rust-toolchain.toml@@ -0,0 +1,5 @@+[toolchain]+channel = "nightly"+components = ["rust-src"]+profile = "minimal"+targets = ["wasm32-unknown-unknown"]diff --git a/examples/threads/server.py b/examples/threads/server.pynew file mode 100755index 0000000..8805579--- /dev/null+++ b/examples/threads/server.py@@ -0,0 +1,20 @@+#!/usr/bin/env python3+from http.server import HTTPServer, SimpleHTTPRequestHandler, test+from pathlib import Path+import sys++PKG_DIR = Path(__file__).resolve().parent / 'pkg'++class RequestHandler(SimpleHTTPRequestHandler):+    def __init__(self, *args, **kwargs):+        super().__init__(*args, directory=str(PKG_DIR), **kwargs)++    def end_headers(self):+        self.send_header('Cross-Origin-Opener-Policy', 'same-origin')+        self.send_header('Cross-Origin-Embedder-Policy', 'require-corp')+        SimpleHTTPRequestHandler.end_headers(self)++if __name__ == '__main__':+    port=int(sys.argv[1]) if len(sys.argv) > 1 else 8000+    print(f"Serving {PKG_DIR} at http://localhost:{port}/")+    test(RequestHandler, HTTPServer, port=port, bind='127.0.0.1')diff --git a/examples/threads/src/lib.rs b/examples/threads/src/lib.rsnew file mode 100644index 0000000..3fbd702--- /dev/null+++ b/examples/threads/src/lib.rs@@ -0,0 +1,29 @@+use kaja_web::prelude::*;+use wasm_bindgen::{JsValue, prelude::wasm_bindgen};++macro_rules! console_log {+    ($($t:tt)*) => (crate::log(&format_args!($($t)*).to_string()))+}++#[wasm_bindgen]+extern "C" {+    #[wasm_bindgen(js_namespace = console)]+    pub(crate) fn log(s: &str);+    #[wasm_bindgen(js_namespace = console, js_name = log)]+    pub(crate) fn logv(x: &JsValue);+}++mod main_component;+mod pool;++#[wasm_bindgen(start)]+pub fn init() {+    log!("Starting");++    std::panic::set_hook(Box::new(console_error_panic_hook::hook));+    console_error_panic_hook::set_once();++    log!("Init callbacks");+    init_callbacks();+    log!("Init complete");+}diff --git a/examples/threads/src/main_component.rs b/examples/threads/src/main_component.rsnew file mode 100644index 0000000..596271c--- /dev/null+++ b/examples/threads/src/main_component.rs@@ -0,0 +1,55 @@+use kaja_web::prelude::*;+use std::time::Duration;++#[component("main-component")]+struct Main {+    test: bool,+}++impl Component for Main {+    fn connected(id: &str) {+        start_background_thread(&id);+    }++    fn update(id: &str) {+        log!(+            "Update from background thread, running on the UI thread:",+            id+        );++        let Some(handle) = Self::get_component(id) else {+            error!("Main component not found:", id);+            return;+        };++        let Some(element) = get_element_by_id(id) else {+            error!("Element not found:", id);+            return;+        };++        let mut component = handle.lock().unwrap();+        component.test = !component.test;+        component.render(&element);+    }+}++impl Main {+    fn render(&self, element: &HtmlElement) {+        element.set_inner_text(&self.test.to_string());+    }+}++fn start_background_thread(id: &str) {+    let component_id = id.to_string();++    c   rate::thread::spawn(move || {+        loop {+            Main::post_ui_thread_update(component_id.as_str());+            std::thread::sleep(Duration::from_millis(1000));++            // this a background thread, so:+            // try_inner_html("#test", "<b>INNER_HTML</b>");+            // will not update the DOM. Only the UI thread can do that.+        }+    });+}diff --git a/examples/threads/src/thread.rs b/examples/threads/src/thread.rsnew file mode 100644index 0000000..f703b3b--- /dev/null+++ b/examples/threads/src/thread.rs@@ -0,0 +1,81 @@+// Silences warnings from the compiler about Work.func and child_entry_point+// being unused when the target is not wasm.+#![cfg_attr(not(target_arch = "wasm32"), allow(dead_code))]++use std::cell::RefCell;+use std::rc::Rc;+use wasm_bindgen::prelude::*;+use web_sys::{DedicatedWorkerGlobalScope, MessageEvent};+use web_sys::{ErrorEvent, Event, Worker};++struct Work {+    func: Box<dyn FnOnce() + Send>,+}++fn spawn_worker() -> Result<Worker, JsValue> {+    let worker = Worker::new("./worker.js")?;++    // With a worker spun up send it the module/memory so it can start+    // instantiating the Wasm module. Later it might receive further+    // messages about code to run on the Wasm module.+    let array = js_sys::Array::new();+    array.push(&wasm_bindgen::module());+    array.push(&wasm_bindgen::memory());+    worker.post_message(&array)?;++    Ok(worker)+}++/// Spawns a single standalone worker and runs `f` on it.+pub fn spawn(f: impl FnOnce() + Send + 'static) -> Result<(), JsValue> {+    let worker = spawn_worker()?;++    let worker2 = worker.clone();+    let completion_slot = Rc::new(RefCell::new(None));+    let slot2 = completion_slot.clone();++    let completion = Closure::<dyn FnMut(_)>::new(move |event: Event| {+        if let Some(error) = event.dyn_ref::<ErrorEvent>() {+            console_log!("error in standalone worker: {}", error.message());+        } else if event.dyn_ref::<MessageEvent>().is_none() {+            console_log!("unhandled event: {}", event.type_());+            crate::logv(&event);+        }++        worker2.terminate();+        worker2.set_onmessage(None);+        worker2.set_onerror(None);+        *slot2.borrow_mut() = None;+    });++    worker.set_onmessage(Some(completion.as_ref().unchecked_ref()));+    worker.set_onerror(Some(completion.as_ref().unchecked_ref()));+    *completion_slot.borrow_mut() = Some(completion);++    let work = Box::new(Work { func: Box::new(f) });+    let ptr = Box::into_raw(work);++    match worker.post_message(&JsValue::from(ptr as u32)) {+        Ok(()) => Ok(()),+        Err(e) => {+            unsafe {+                drop(Box::from_raw(ptr));+            }+            worker.terminate();+            worker.set_onmessage(None);+            worker.set_onerror(None);+            *completion_slot.borrow_mut() = None;+            Err(e)+        }+    }+}++/// Entry point invoked by `worker.js`+#[wasm_bindgen]+pub fn child_entry_point(ptr: u32) -> Result<(), JsValue> {+    let ptr = unsafe { Box::from_raw(ptr as *mut Work) };+    let global = js_sys::global().unchecked_into::<DedicatedWorkerGlobalScope>();+    (ptr.func)();+    global.post_message(&JsValue::undefined())?;+    Ok(())+}diff --git a/examples/threads/static/index.html b/examples/threads/static/index.htmlnew file mode 100644index 0000000..c7385de--- /dev/null+++ b/examples/threads/static/index.html@@ -0,0 +1,10 @@+<html>+  <head>+      <title>Wasm Threads</title>+  </head>+  <body>+    Known: <main-component></main-component>+    <script src='raytrace_parallel.js'></script>+    <script src='index.js'></script>+  </body>+</html>diff --git a/examples/threads/static/index.js b/examples/threads/static/index.jsnew file mode 100644index 0000000..6ecf9b8--- /dev/null+++ b/examples/threads/static/index.js@@ -0,0 +1,19 @@+function loadWasm() {+  if (typeof SharedArrayBuffer !== 'function') {+    console.error('this browser does not have SharedArrayBuffer support enabled' + '\n\n' + msg);+    return+  }+  // Test for bulk memory operations with passive data segments+  //  (module (memory 1) (data passive ""))+  const buf = new Uint8Array([0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00,+    0x05, 0x03, 0x01, 0x00, 0x01, 0x0b, 0x03, 0x01, 0x01, 0x00]);+  if (!WebAssembly.validate(buf)) {+    console.error('This browser does not support passive Wasm memory, Background threads will not work' + '\n\n' + msg);+    return+  }++  wasm_bindgen()+    .catch(console.error);+}++loadWasm();diff --git a/examples/threads/static/worker.js b/examples/threads/static/worker.jsnew file mode 100644index 0000000..26d40c6--- /dev/null+++ b/examples/threads/static/worker.js@@ -0,0 +1,25 @@+// synchronously, using the browser, import out shim JS scripts+importScripts('raytrace_parallel.js');++// Wait for the main thread to send us the shared module/memory. Once we've got+// it, initialize it all with the `wasm_bindgen` global we imported via+// `importScripts`.+//+// After our first message all subsequent messages are an entry point to run,+// so we just do that.+self.onmessage = event => {+  let initialised = wasm_bindgen(...event.data).catch(err => {+    // Propagate to main `onerror`:+    setTimeout(() => {+      throw err;+    });+    // Rethrow to keep promise rejected and prevent execution of further commands:+    throw err;+  });++  self.onmessage = async event => {+    // This will queue further commands up until the module is fully initialised:+    await initialised;+    wasm_bindgen.child_entry_point(event.data);+  };+};

Contact

Email: johan.mattsson.m@gmail.com
Mastodon: typo.social/@birdfont
GitHub: johanmattssonm
LinkedIn: johan-mattsson-2ab324112