diff --git a/Cargo.lock b/Cargo.lock index f9ecdf2b..6803fc71 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -586,56 +586,57 @@ dependencies = [ [[package]] name = "cranelift-bforest" -version = "0.82.3" +version = "0.86.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38faa2a16616c8e78a18d37b4726b98bfd2de192f2fdc8a39ddf568a408a0f75" +checksum = "529ffacce2249ac60edba2941672dfedf3d96558b415d0d8083cd007456e0f55" dependencies = [ "cranelift-entity", ] [[package]] name = "cranelift-codegen" -version = "0.82.3" +version = "0.86.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26f192472a3ba23860afd07d2b0217dc628f21fcc72617aa1336d98e1671f33b" +checksum = "427d105f617efc8cb55f8d036a7fded2e227892d8780b4985e5551f8d27c4a92" dependencies = [ "cranelift-bforest", "cranelift-codegen-meta", "cranelift-codegen-shared", "cranelift-entity", + "cranelift-isle", "gimli", "log", - "regalloc", + "regalloc2", "smallvec", "target-lexicon", ] [[package]] name = "cranelift-codegen-meta" -version = "0.82.3" +version = "0.86.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f32ddb89e9b89d3d9b36a5b7d7ea3261c98235a76ac95ba46826b8ec40b1a24" +checksum = "551674bed85b838d45358e3eab4f0ffaa6790c70dc08184204b9a54b41cdb7d1" dependencies = [ "cranelift-codegen-shared", ] [[package]] name = "cranelift-codegen-shared" -version = "0.82.3" +version = "0.86.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01fd0d9f288cc1b42d9333b7a776b17e278fc888c28e6a0f09b5573d45a150bc" +checksum = "2b3a63ae57498c3eb495360944a33571754241e15e47e3bcae6082f40fec5866" [[package]] name = "cranelift-entity" -version = "0.82.3" +version = "0.86.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e3bfe172b83167604601faf9dc60453e0d0a93415b57a9c4d1a7ae6849185cf" +checksum = "11aa8aa624c72cc1c94ea3d0739fa61248260b5b14d3646f51593a88d67f3e6e" [[package]] name = "cranelift-frontend" -version = "0.82.3" +version = "0.86.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a006e3e32d80ce0e4ba7f1f9ddf66066d052a8c884a110b91d05404d6ce26dce" +checksum = "544ee8f4d1c9559c9aa6d46e7aaeac4a13856d620561094f35527356c7d21bd0" dependencies = [ "cranelift-codegen", "log", @@ -644,13 +645,10 @@ dependencies = [ ] [[package]] -name = "crc32fast" -version = "1.3.2" +name = "cranelift-isle" +version = "0.86.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" -dependencies = [ - "cfg-if 1.0.0", -] +checksum = "ed16b14363d929b8c37e3c557d0a7396791b383ecc302141643c054343170aad" [[package]] name = "crossbeam" @@ -1153,6 +1151,15 @@ dependencies = [ "thread_local", ] +[[package]] +name = "fxhash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" +dependencies = [ + "byteorder", +] + [[package]] name = "generational-arena" version = "0.2.8" @@ -1264,9 +1271,6 @@ name = "hashbrown" version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" -dependencies = [ - "ahash", -] [[package]] name = "hashbrown" @@ -1325,6 +1329,12 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" +[[package]] +name = "id-arena" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25a2bc672d1148e28034f176e01fffebb08b35768468cc954630da77a1449005" + [[package]] name = "ident_case" version = "1.0.1" @@ -1386,7 +1396,6 @@ checksum = "e6012d540c5baa3589337a98ce73408de9b5a25ec9fc2c6fd6be8f0d39e0ca5a" dependencies = [ "autocfg", "hashbrown 0.11.2", - "serde", ] [[package]] @@ -1514,9 +1523,9 @@ checksum = "112c678d4050afce233f4f2852bb2eb519230b3cf12f33585275537d7e41578d" [[package]] name = "js-sys" -version = "0.3.58" +version = "0.3.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3fac17f7123a73ca62df411b1bf727ccc805daa070338fda671c86dac1bdc27" +checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" dependencies = [ "wasm-bindgen", ] @@ -1591,16 +1600,6 @@ version = "0.2.140" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c" -[[package]] -name = "libloading" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" -dependencies = [ - "cfg-if 1.0.0", - "winapi", -] - [[package]] name = "libssh2-sys" version = "0.2.23" @@ -1692,27 +1691,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "loupe" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b6a72dfa44fe15b5e76b94307eeb2ff995a8c5b283b55008940c02e0c5b634d" -dependencies = [ - "indexmap", - "loupe-derive", - "rustversion", -] - -[[package]] -name = "loupe-derive" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0fbfc88337168279f2e9ae06e157cfed4efd3316e14dc96ed074d4f2e6c5952" -dependencies = [ - "quote", - "syn 1.0.96", -] - [[package]] name = "mach" version = "0.3.2" @@ -1997,17 +1975,14 @@ version = "0.28.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e42c982f2d955fac81dd7e1d0e1426a7d702acd9c98d19ab01083a6a0328c424" dependencies = [ - "crc32fast", - "hashbrown 0.11.2", - "indexmap", "memchr", ] [[package]] name = "once_cell" -version = "1.12.0" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7709cef83f0c1f58f666e746a08b21e0085f7440fa6a29cc194d68aac97a4225" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" [[package]] name = "opaque-debug" @@ -2451,6 +2426,17 @@ dependencies = [ "syn 1.0.96", ] +[[package]] +name = "pulldown-cmark" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffade02495f22453cd593159ea2f59827aae7f53fa8323f756799b670881dcf8" +dependencies = [ + "bitflags", + "memchr", + "unicase", +] + [[package]] name = "quote" version = "1.0.27" @@ -2586,13 +2572,14 @@ dependencies = [ ] [[package]] -name = "regalloc" -version = "0.0.34" +name = "regalloc2" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62446b1d3ebf980bdc68837700af1d77b37bc430e524bf95319c6eada2a4cc02" +checksum = "d43a209257d978ef079f3d446331d0f1794f5e0fc19b306a199983857833a779" dependencies = [ + "fxhash", "log", - "rustc-hash", + "slice-group-by", "smallvec", ] @@ -2651,6 +2638,7 @@ checksum = "cec2b3485b07d96ddfd3134767b8a447b45ea4eb91448d0a35180ec0ffd5ed15" dependencies = [ "bytecheck", "hashbrown 0.12.3", + "indexmap", "ptr_meta", "rend", "rkyv_derive", @@ -2696,12 +2684,6 @@ version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" -[[package]] -name = "rustc-hash" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" - [[package]] name = "rustc_version" version = "0.2.3" @@ -2734,12 +2716,6 @@ dependencies = [ "windows-sys 0.45.0", ] -[[package]] -name = "rustversion" -version = "1.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97477e48b4cf8603ad5f7aaf897467cf42ab4218a38ef76fb14c2d6773a6d6a8" - [[package]] name = "ryu" version = "1.0.10" @@ -2826,12 +2802,14 @@ dependencies = [ ] [[package]] -name = "serde_bytes" -version = "0.11.6" +name = "serde-wasm-bindgen" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "212e73464ebcde48d723aa02eb270ba62eff38a9b732df31f33f1b4e145f3a54" +checksum = "e3b4c031cd0d9014307d82b8abf653c0290fbdaeb4c02d00c63cf52f728628bf" dependencies = [ + "js-sys", "serde", + "wasm-bindgen", ] [[package]] @@ -3000,6 +2978,12 @@ version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eb703cfe953bccee95685111adeedb76fabe4e97549a58d16f03ea7b9367bb32" +[[package]] +name = "slice-group-by" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "826167069c09b99d56f31e9ae5c99049e932a98c9dc2dac47645b08dbbf76ba7" + [[package]] name = "smallvec" version = "1.8.0" @@ -3569,6 +3553,15 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c" +[[package]] +name = "unicase" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" +dependencies = [ + "version_check", +] + [[package]] name = "unicode-bidi" version = "0.3.8" @@ -3611,6 +3604,12 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" +[[package]] +name = "unicode-xid" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" + [[package]] name = "unsafe-any-ors" version = "1.0.0" @@ -3747,9 +3746,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.81" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c53b543413a17a202f4be280a7e5c62a1c69345f5de525ee64f8cfdbc954994" +checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" dependencies = [ "cfg-if 1.0.0", "wasm-bindgen-macro", @@ -3757,17 +3756,40 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.81" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5491a68ab4500fa6b4d726bd67408630c3dbe9c4fe7bda16d5c82a1fd8c7340a" +checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" dependencies = [ "bumpalo", - "lazy_static", "log", + "once_cell", + "proc-macro2", + "quote", + "syn 2.0.15", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-downcast" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dac026d43bcca6e7ce1c0956ba68f59edf6403e8e930a5d891be72c31a44340" +dependencies = [ + "js-sys", + "once_cell", + "wasm-bindgen", + "wasm-bindgen-downcast-macros", +] + +[[package]] +name = "wasm-bindgen-downcast-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5020cfa87c7cecefef118055d44e3c1fc122c7ec25701d528ee458a0b45f38f" +dependencies = [ "proc-macro2", "quote", "syn 1.0.96", - "wasm-bindgen-shared", ] [[package]] @@ -3784,9 +3806,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.81" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c441e177922bc58f1e12c022624b6216378e5febc2f0533e41ba443d505b80aa" +checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -3794,22 +3816,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.81" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d94ac45fcf608c1f45ef53e748d35660f168490c10b23704c7779ab8f5c3048" +checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ "proc-macro2", "quote", - "syn 1.0.96", + "syn 2.0.15", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.81" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a89911bd99e5f3659ec4acf9c4d93b0a90fe4a2a11f15328472058edc5261be" +checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" [[package]] name = "wasm-encoder" @@ -3822,74 +3844,65 @@ dependencies = [ [[package]] name = "wasmer" -version = "2.3.0" +version = "3.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea8d8361c9d006ea3d7797de7bd6b1492ffd0f91a22430cfda6c1658ad57bedf" +checksum = "840af6d21701220cb805dc7201af301cb99e9b4f646f48a41befbc1d949f0f90" dependencies = [ + "bytes", "cfg-if 1.0.0", "indexmap", "js-sys", - "loupe", "more-asserts", + "serde", + "serde-wasm-bindgen", "target-lexicon", "thiserror", "wasm-bindgen", - "wasmer-artifact", + "wasm-bindgen-downcast", "wasmer-compiler", "wasmer-compiler-cranelift", "wasmer-compiler-singlepass", "wasmer-derive", - "wasmer-engine", - "wasmer-engine-dylib", - "wasmer-engine-universal", "wasmer-types", "wasmer-vm", "wat", "winapi", ] -[[package]] -name = "wasmer-artifact" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7aaf9428c29c1d8ad2ac0e45889ba8a568a835e33fd058964e5e500f2f7ce325" -dependencies = [ - "enumset", - "loupe", - "thiserror", - "wasmer-compiler", - "wasmer-types", -] - [[package]] name = "wasmer-compiler" -version = "2.3.0" +version = "3.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e67a6cd866aed456656db2cfea96c18baabbd33f676578482b85c51e1ee19d2c" +checksum = "b86fab98beaaace77380cb04e681773739473860d1b8499ea6b14f920923e0c5" dependencies = [ + "backtrace", + "cfg-if 1.0.0", + "enum-iterator", "enumset", - "loupe", - "rkyv", - "serde", - "serde_bytes", + "lazy_static", + "leb128", + "memmap2", + "more-asserts", + "region", + "rustc-demangle", "smallvec", - "target-lexicon", "thiserror", "wasmer-types", + "wasmer-vm", "wasmparser", + "winapi", ] [[package]] name = "wasmer-compiler-cranelift" -version = "2.3.0" +version = "3.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48be2f9f6495f08649e4f8b946a2cbbe119faf5a654aa1457f9504a99d23dae0" +checksum = "015eef629fc84889540dc1686bd7fa524b93da9fd2d275b16c49dbe96268e58f" dependencies = [ "cranelift-codegen", "cranelift-entity", "cranelift-frontend", "gimli", - "loupe", "more-asserts", "rayon", "smallvec", @@ -3901,16 +3914,16 @@ dependencies = [ [[package]] name = "wasmer-compiler-singlepass" -version = "2.3.0" +version = "3.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29ca2a35204d8befa85062bc7aac259a8db8070b801b8a783770ba58231d729e" +checksum = "07e235ccc192d5f39147e8a430f48040dcfeebc1f1b0d979d2232ec1618d255c" dependencies = [ "byteorder", "dynasm", "dynasmrt", + "enumset", "gimli", "lazy_static", - "loupe", "more-asserts", "rayon", "smallvec", @@ -3920,9 +3933,9 @@ dependencies = [ [[package]] name = "wasmer-derive" -version = "2.3.0" +version = "3.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00e50405cc2a2f74ff574584710a5f2c1d5c93744acce2ca0866084739284b51" +checksum = "1ff577b7c1cfcd3d7c5b3a09fe1a499b73f7c17084845ff71225c8250a6a63a9" dependencies = [ "proc-macro-error", "proc-macro2", @@ -3931,123 +3944,35 @@ dependencies = [ ] [[package]] -name = "wasmer-engine" -version = "2.3.0" +name = "wasmer-types" +version = "3.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f98f010978c244db431b392aeab0661df7ea0822343334f8f2a920763548e45" +checksum = "8b9600f9da966abae3be0b0a4560e7d1f2c88415a2d01ce362ac06063cb1c473" dependencies = [ - "backtrace", + "enum-iterator", "enumset", - "lazy_static", - "loupe", - "memmap2", + "indexmap", "more-asserts", - "rustc-demangle", - "serde", - "serde_bytes", + "rkyv", "target-lexicon", "thiserror", - "wasmer-artifact", - "wasmer-compiler", - "wasmer-types", - "wasmer-vm", ] [[package]] -name = "wasmer-engine-dylib" -version = "2.3.0" +name = "wasmer-vbus" +version = "3.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad0358af9c154724587731175553805648d9acb8f6657880d165e378672b7e53" +checksum = "72b42f76b9f09c68084de3a35fdf4907609f4b5005ecf3767fa1839a669dcbdb" dependencies = [ - "cfg-if 1.0.0", - "enum-iterator", - "enumset", - "leb128", - "libloading", - "loupe", - "object", - "rkyv", - "serde", - "tempfile", - "tracing", - "wasmer-artifact", - "wasmer-compiler", - "wasmer-engine", - "wasmer-object", - "wasmer-types", - "wasmer-vm", - "which", -] - -[[package]] -name = "wasmer-engine-universal" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "440dc3d93c9ca47865a4f4edd037ea81bf983b5796b59b3d712d844b32dbef15" -dependencies = [ - "cfg-if 1.0.0", - "enumset", - "leb128", - "loupe", - "region", - "rkyv", - "wasmer-compiler", - "wasmer-engine", - "wasmer-engine-universal-artifact", - "wasmer-types", - "wasmer-vm", - "winapi", -] - -[[package]] -name = "wasmer-engine-universal-artifact" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68f1db3f54152657eb6e86c44b66525ff7801dad8328fe677da48dd06af9ad41" -dependencies = [ - "enum-iterator", - "enumset", - "loupe", - "rkyv", - "thiserror", - "wasmer-artifact", - "wasmer-compiler", - "wasmer-types", -] - -[[package]] -name = "wasmer-object" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d831335ff3a44ecf451303f6f891175c642488036b92ceceb24ac8623a8fa8b" -dependencies = [ - "object", - "thiserror", - "wasmer-compiler", - "wasmer-types", -] - -[[package]] -name = "wasmer-types" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39df01ea05dc0a9bab67e054c7cb01521e53b35a7bb90bd02eca564ed0b2667f" -dependencies = [ - "backtrace", - "enum-iterator", - "indexmap", - "loupe", - "more-asserts", - "rkyv", - "serde", "thiserror", + "wasmer-vfs", ] [[package]] name = "wasmer-vfs" -version = "2.3.0" +version = "3.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9302eae3edc53cb540c2d681e7f16d8274918c1ce207591f04fed351649e97c0" +checksum = "34bfbd243503d64aed4fc8a194657a561cae6c2d782dbcf649211d7f4db9e413" dependencies = [ "libc", "thiserror", @@ -4056,9 +3981,9 @@ dependencies = [ [[package]] name = "wasmer-vm" -version = "2.3.0" +version = "3.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30d965fa61f4dc4cdb35a54daaf7ecec3563fbb94154a6c35433f879466247dd" +checksum = "9fc68a7f0a003e6cb63845b7510065097d289553201d64afb9a5e1744da3c6a0" dependencies = [ "backtrace", "cc", @@ -4068,27 +3993,36 @@ dependencies = [ "indexmap", "lazy_static", "libc", - "loupe", "mach", "memoffset", "more-asserts", "region", - "rkyv", "scopeguard", - "serde", "thiserror", - "wasmer-artifact", "wasmer-types", "winapi", ] [[package]] -name = "wasmer-wasi" -version = "2.3.0" +name = "wasmer-vnet" +version = "3.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fadbe31e3c1b6f3e398ad172b169152ae1a743ae6efd5f9ffb34019983319d99" +checksum = "9bc4fe3b48ccc620901bdcdfac98d8a76ef3487412c221752814750c2e7db4c1" dependencies = [ + "bytes", + "thiserror", + "wasmer-vfs", +] + +[[package]] +name = "wasmer-wasi" +version = "3.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e893ecd57c63db83b17dacfaee90f660e1d7f5b26d2f9d88ea6aa2e8c4bc301d" +dependencies = [ + "bytes", "cfg-if 1.0.0", + "derivative", "generational-arena", "getrandom 0.2.7", "libc", @@ -4096,20 +4030,108 @@ dependencies = [ "tracing", "wasm-bindgen", "wasmer", + "wasmer-vbus", "wasmer-vfs", + "wasmer-vnet", + "wasmer-wasi-local-networking", "wasmer-wasi-types", "winapi", ] [[package]] -name = "wasmer-wasi-types" -version = "2.3.0" +name = "wasmer-wasi-local-networking" +version = "3.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22dc83aadbdf97388de3211cb6f105374f245a3cf2a5c65a16776e7a087a8468" +checksum = "bd65882d8cee793848776f26e979b7ff3e139d927947d87304c940c89527a730" +dependencies = [ + "bytes", + "tracing", + "wasmer-vfs", + "wasmer-vnet", +] + +[[package]] +name = "wasmer-wasi-types" +version = "3.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1afdec83c62d22bf7110b83d662a08f708332fd728a213399919a045a1061d4" dependencies = [ "byteorder", "time 0.2.27", + "wasmer", + "wasmer-derive", "wasmer-types", + "wasmer-wit-bindgen-gen-core", + "wasmer-wit-bindgen-gen-rust-wasm", + "wasmer-wit-bindgen-rust", + "wasmer-wit-parser", +] + +[[package]] +name = "wasmer-wit-bindgen-gen-core" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff8aa5be5ae5d61f5e151dc2c0e603093fe28395d2083b65ef7a3547844054fe" +dependencies = [ + "anyhow", + "wasmer-wit-parser", +] + +[[package]] +name = "wasmer-wit-bindgen-gen-rust" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "438bce7c4589842bf100cc9b312443a9b5fc6440e58ab0b8c114e460219c3c3b" +dependencies = [ + "heck 0.3.3", + "wasmer-wit-bindgen-gen-core", +] + +[[package]] +name = "wasmer-wit-bindgen-gen-rust-wasm" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "505f5168cfee591840e13e158a5c5e2f95d6df1df710839021564f36bee7bafc" +dependencies = [ + "heck 0.3.3", + "wasmer-wit-bindgen-gen-core", + "wasmer-wit-bindgen-gen-rust", +] + +[[package]] +name = "wasmer-wit-bindgen-rust" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "968747f1271f74aab9b70d9c5d4921db9bd13b4ec3ba5506506e6e7dc58c918c" +dependencies = [ + "async-trait", + "bitflags", + "wasmer-wit-bindgen-rust-impl", +] + +[[package]] +name = "wasmer-wit-bindgen-rust-impl" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd26fe00d08bd2119870b017d13413dfbd51e7750b6634d649fc7a7bbc057b85" +dependencies = [ + "proc-macro2", + "syn 1.0.96", + "wasmer-wit-bindgen-gen-core", + "wasmer-wit-bindgen-gen-rust-wasm", +] + +[[package]] +name = "wasmer-wit-parser" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f46c9a15086be8a2eb3790613902b9d3a9a687833b17cd021de263a20378585a" +dependencies = [ + "anyhow", + "id-arena", + "pulldown-cmark", + "unicode-normalization", + "unicode-xid", ] [[package]] diff --git a/zellij-server/Cargo.toml b/zellij-server/Cargo.toml index 0c2c1a1b..61890275 100644 --- a/zellij-server/Cargo.toml +++ b/zellij-server/Cargo.toml @@ -18,8 +18,8 @@ daemonize = "0.4.1" serde_json = "1.0" unicode-width = "0.1.8" url = "2.2.2" -wasmer = "2.3.0" -wasmer-wasi = "2.3.0" +wasmer = "3.1.1" +wasmer-wasi = "3.1.1" cassowary = "0.3.0" zellij-utils = { path = "../zellij-utils/", version = "0.39.0" } log = "0.4.17" @@ -36,7 +36,7 @@ semver = "0.11.0" [dev-dependencies] insta = "1.6.0" tempfile = "3.2.0" -wasmer = { version = "2.3.0", features = [ "singlepass" ] } +wasmer = { version = "3.1.1", features = ["singlepass"] } [features] singlepass = ["wasmer/singlepass"] diff --git a/zellij-server/src/lib.rs b/zellij-server/src/lib.rs index 0b5f2ea8..bfacbad7 100644 --- a/zellij-server/src/lib.rs +++ b/zellij-server/src/lib.rs @@ -911,11 +911,11 @@ fn init_session( #[cfg(not(feature = "singlepass"))] fn get_store() -> Store { log::info!("Compiling plugins using Cranelift"); - Store::new(&wasmer::Universal::new(wasmer::Cranelift::default()).engine()) + Store::new(wasmer::Cranelift::default()) } #[cfg(feature = "singlepass")] fn get_store() -> Store { log::info!("Compiling plugins using Singlepass"); - Store::new(&wasmer::Universal::new(wasmer::Singlepass::default()).engine()) + Store::new(wasmer::Singlepass::default()) } diff --git a/zellij-server/src/plugins/mod.rs b/zellij-server/src/plugins/mod.rs index deb368c1..cac902e7 100644 --- a/zellij-server/src/plugins/mod.rs +++ b/zellij-server/src/plugins/mod.rs @@ -9,6 +9,8 @@ use std::{ collections::{HashMap, HashSet}, fs, path::PathBuf, + sync::{Arc, Mutex}, + time::Duration, }; use wasmer::Store; @@ -19,6 +21,7 @@ use crate::{pty::PtyInstruction, thread_bus::Bus, ClientId, ServerInstruction}; use wasm_bridge::WasmBridge; use zellij_utils::{ + async_std::{channel, future::timeout, task}, data::{Event, EventType, PermissionStatus, PermissionType, PluginCapabilities}, errors::{prelude::*, ContextType, PluginContext}, input::{ @@ -142,6 +145,12 @@ pub(crate) fn plugin_thread_main( let plugin_dir = data_dir.join("plugins/"); let plugin_global_data_dir = plugin_dir.join("data"); + let store = Arc::new(Mutex::new(store)); + + // use this channel to ensure that tasks spawned from this thread terminate before exiting + // https://tokio.rs/tokio/topics/shutdown#waiting-for-things-to-finish-shutting-down + let (shutdown_send, shutdown_receive) = channel::bounded::<()>(1); + let mut wasm_bridge = WasmBridge::new( plugins, bus.senders.clone(), @@ -186,7 +195,7 @@ pub(crate) fn plugin_thread_main( }, }, PluginInstruction::Update(updates) => { - wasm_bridge.update_plugins(updates)?; + wasm_bridge.update_plugins(updates, shutdown_send.clone())?; }, PluginInstruction::Unload(pid) => { wasm_bridge.unload_plugin(pid)?; @@ -229,7 +238,7 @@ pub(crate) fn plugin_thread_main( } }, PluginInstruction::Resize(pid, new_columns, new_rows) => { - wasm_bridge.resize_plugin(pid, new_columns, new_rows)?; + wasm_bridge.resize_plugin(pid, new_columns, new_rows, shutdown_send.clone())?; }, PluginInstruction::AddClient(client_id) => { wasm_bridge.add_client(client_id)?; @@ -286,7 +295,7 @@ pub(crate) fn plugin_thread_main( ))); }, PluginInstruction::ApplyCachedEvents(plugin_id) => { - wasm_bridge.apply_cached_events(plugin_id)?; + wasm_bridge.apply_cached_events(plugin_id, shutdown_send.clone())?; }, PluginInstruction::ApplyCachedWorkerMessages(plugin_id) => { wasm_bridge.apply_cached_worker_messages(plugin_id)?; @@ -310,7 +319,7 @@ pub(crate) fn plugin_thread_main( Some(client_id), Event::CustomMessage(message, payload), )]; - wasm_bridge.update_plugins(updates)?; + wasm_bridge.update_plugins(updates, shutdown_send.clone())?; }, PluginInstruction::PluginSubscribedToEvents(_plugin_id, _client_id, events) => { for event in events { @@ -345,16 +354,28 @@ pub(crate) fn plugin_thread_main( client_id, Event::PermissionRequestResult(status), )]; - wasm_bridge.update_plugins(updates)?; + wasm_bridge.update_plugins(updates, shutdown_send.clone())?; }, PluginInstruction::Exit => { - wasm_bridge.cleanup(); break; }, } } info!("wasm main thread exits"); + // first drop our sender, then call recv. + // once all senders are dropped or the timeout is reached, recv will return an error, that we ignore + + drop(shutdown_send); + task::block_on(async { + let result = timeout(EXIT_TIMEOUT, shutdown_receive.recv()).await; + if let Err(err) = result { + log::error!("timeout waiting for plugin tasks to finish: {}", err); + } + }); + + wasm_bridge.cleanup(); + fs::remove_dir_all(&plugin_global_data_dir) .or_else(|err| { if err.kind() == std::io::ErrorKind::NotFound { @@ -367,6 +388,8 @@ pub(crate) fn plugin_thread_main( .context("failed to cleanup plugin data directory") } +const EXIT_TIMEOUT: Duration = Duration::from_secs(3); + #[path = "./unit/plugin_tests.rs"] #[cfg(test)] mod plugin_tests; diff --git a/zellij-server/src/plugins/plugin_loader.rs b/zellij-server/src/plugins/plugin_loader.rs index ea0c2b6a..3158610b 100644 --- a/zellij-server/src/plugins/plugin_loader.rs +++ b/zellij-server/src/plugins/plugin_loader.rs @@ -1,3 +1,4 @@ +use crate::get_store; use crate::plugins::plugin_map::{PluginEnv, PluginMap, RunningPlugin, Subscriptions}; use crate::plugins::plugin_worker::{plugin_worker, RunningWorker}; use crate::plugins::zellij_exports::{wasi_write_object, zellij_exports}; @@ -11,7 +12,7 @@ use std::{ sync::{Arc, Mutex}, }; use url::Url; -use wasmer::{ChainableNamedResolver, Instance, Module, Store}; +use wasmer::{AsStoreRef, Instance, Module, Store}; use wasmer_wasi::{Pipe, WasiState}; use zellij_utils::prost::Message; @@ -51,7 +52,7 @@ pub struct PluginLoader<'a> { senders: ThreadSenders, plugin_id: PluginId, client_id: ClientId, - store: Store, + store: Arc>, plugin: PluginConfig, plugin_dir: &'a PathBuf, tab_index: usize, @@ -72,7 +73,7 @@ impl<'a> PluginLoader<'a> { plugin_dir: PathBuf, plugin_cache: Arc>>, senders: ThreadSenders, - store: Store, + store: Arc>, plugin_map: Arc>, connected_clients: Arc>>, loading_indication: &mut LoadingIndication, @@ -98,7 +99,7 @@ impl<'a> PluginLoader<'a> { &senders, plugin_id, first_client_id, - &store, + store, &plugin_dir, path_to_default_shell, zellij_cwd, @@ -110,8 +111,9 @@ impl<'a> PluginLoader<'a> { plugin_loader .load_module_from_memory() .and_then(|module| plugin_loader.create_plugin_environment(module)) - .and_then(|(instance, plugin_env, subscriptions)| { + .and_then(|(store, instance, plugin_env, subscriptions)| { plugin_loader.load_plugin_instance( + store, &instance, &plugin_env, &plugin_map, @@ -134,7 +136,7 @@ impl<'a> PluginLoader<'a> { plugin_dir: PathBuf, plugin_cache: Arc>>, senders: ThreadSenders, - store: Store, + store: Arc>, plugin_map: Arc>, size: Size, connected_clients: Arc>>, @@ -153,7 +155,7 @@ impl<'a> PluginLoader<'a> { &senders, plugin_id, client_id, - &store, + store.clone(), plugin.clone(), &plugin_dir, tab_index, @@ -170,8 +172,9 @@ impl<'a> PluginLoader<'a> { .or_else(|_e| plugin_loader.load_module_from_hd_cache()) .or_else(|_e| plugin_loader.compile_module()) .and_then(|module| plugin_loader.create_plugin_environment(module)) - .and_then(|(instance, plugin_env, subscriptions)| { + .and_then(|(store, instance, plugin_env, subscriptions)| { plugin_loader.load_plugin_instance( + store, &instance, &plugin_env, &plugin_map, @@ -194,7 +197,7 @@ impl<'a> PluginLoader<'a> { plugin_dir: PathBuf, plugin_cache: Arc>>, senders: ThreadSenders, - store: Store, + store: Arc>, plugin_map: Arc>, connected_clients: Arc>>, loading_indication: &mut LoadingIndication, @@ -217,7 +220,7 @@ impl<'a> PluginLoader<'a> { &senders, plugin_id, existing_client_id, - &store, + store.clone(), &plugin_dir, path_to_default_shell.clone(), zellij_cwd.clone(), @@ -229,8 +232,9 @@ impl<'a> PluginLoader<'a> { plugin_loader .load_module_from_memory() .and_then(|module| plugin_loader.create_plugin_environment(module)) - .and_then(|(instance, plugin_env, subscriptions)| { + .and_then(|(store, instance, plugin_env, subscriptions)| { plugin_loader.load_plugin_instance( + store, &instance, &plugin_env, &plugin_map, @@ -247,7 +251,7 @@ impl<'a> PluginLoader<'a> { plugin_dir: PathBuf, plugin_cache: Arc>>, senders: ThreadSenders, - store: Store, + store: Arc>, plugin_map: Arc>, connected_clients: Arc>>, loading_indication: &mut LoadingIndication, @@ -274,7 +278,7 @@ impl<'a> PluginLoader<'a> { &senders, plugin_id, first_client_id, - &store, + store.clone(), &plugin_dir, path_to_default_shell, zellij_cwd, @@ -286,8 +290,9 @@ impl<'a> PluginLoader<'a> { plugin_loader .compile_module() .and_then(|module| plugin_loader.create_plugin_environment(module)) - .and_then(|(instance, plugin_env, subscriptions)| { + .and_then(|(store, instance, plugin_env, subscriptions)| { plugin_loader.load_plugin_instance( + store, &instance, &plugin_env, &plugin_map, @@ -307,7 +312,7 @@ impl<'a> PluginLoader<'a> { senders: &ThreadSenders, plugin_id: PluginId, client_id: ClientId, - store: &Store, + store: Arc>, plugin: PluginConfig, plugin_dir: &'a PathBuf, tab_index: usize, @@ -353,7 +358,7 @@ impl<'a> PluginLoader<'a> { senders: &ThreadSenders, plugin_id: PluginId, client_id: ClientId, - store: &Store, + store: Arc>, plugin_dir: &'a PathBuf, path_to_default_shell: PathBuf, zellij_cwd: PathBuf, @@ -403,7 +408,7 @@ impl<'a> PluginLoader<'a> { senders: &ThreadSenders, plugin_id: PluginId, client_id: ClientId, - store: &Store, + store: Arc>, plugin_dir: &'a PathBuf, path_to_default_shell: PathBuf, zellij_cwd: PathBuf, @@ -434,7 +439,7 @@ impl<'a> PluginLoader<'a> { senders, plugin_id, client_id, - store, + store.clone(), plugin_config, plugin_dir, tab_index, @@ -483,7 +488,9 @@ impl<'a> PluginLoader<'a> { ); let (_wasm_bytes, cached_path) = self.plugin_bytes_and_cache_path()?; let timer = std::time::Instant::now(); - let module = unsafe { Module::deserialize_from_file(&self.store, &cached_path)? }; + let module = unsafe { + Module::deserialize_from_file(&self.store.lock().unwrap().as_store_ref(), &cached_path)? + }; log::info!( "Loaded plugin '{}' from cache folder at '{}' in {:?}", self.plugin_path.display(), @@ -518,7 +525,8 @@ impl<'a> PluginLoader<'a> { .map_err(anyError::new) .and_then(|_| { // compile module - Module::new(&self.store, &wasm_bytes).map_err(anyError::new) + Module::new(&self.store.lock().unwrap().as_store_ref(), &wasm_bytes) + .map_err(anyError::new) }) .and_then(|m| { // serialize module to HD cache for faster loading in the future @@ -536,8 +544,8 @@ impl<'a> PluginLoader<'a> { pub fn create_plugin_environment( &mut self, module: Module, - ) -> Result<(Instance, PluginEnv, Arc>)> { - let (instance, plugin_env, subscriptions) = + ) -> Result<(Store, Instance, PluginEnv, Arc>)> { + let (store, instance, plugin_env, subscriptions) = self.create_plugin_instance_env_and_subscriptions(&module)?; // Only do an insert when everything went well! let cloned_plugin = self.plugin.clone(); @@ -545,11 +553,11 @@ impl<'a> PluginLoader<'a> { .lock() .unwrap() .insert(cloned_plugin.path, module); - Ok((instance, plugin_env, subscriptions)) + Ok((store, instance, plugin_env, subscriptions)) } pub fn create_plugin_instance_and_wasi_env_for_worker( &mut self, - ) -> Result<(Instance, PluginEnv)> { + ) -> Result<(Store, Instance, PluginEnv)> { let err_context = || { format!( "Failed to create instance and plugin env for worker {}", @@ -563,12 +571,13 @@ impl<'a> PluginLoader<'a> { .get(&self.plugin.path) .with_context(err_context)? .clone(); - let (instance, plugin_env, _subscriptions) = + let (store, instance, plugin_env, _subscriptions) = self.create_plugin_instance_env_and_subscriptions(&module)?; - Ok((instance, plugin_env)) + Ok((store, instance, plugin_env)) } pub fn load_plugin_instance( &mut self, + store: Store, instance: &Instance, plugin_env: &PluginEnv, plugin_map: &Arc>, @@ -595,7 +604,7 @@ impl<'a> PluginLoader<'a> { for (function_name, _exported_function) in instance.exports.iter().functions() { if function_name.ends_with("_worker") { let plugin_config = self.plugin.clone(); - let (instance, plugin_env) = + let (mut store, instance, plugin_env) = self.create_plugin_instance_and_wasi_env_for_worker()?; let start_function_for_worker = instance @@ -603,30 +612,35 @@ impl<'a> PluginLoader<'a> { .get_function("_start") .with_context(err_context)?; start_function_for_worker - .call(&[]) + .call(&mut store, &[]) .with_context(err_context)?; let worker = - RunningWorker::new(instance, &function_name, plugin_config, plugin_env); + RunningWorker::new(store, instance, &function_name, plugin_config, plugin_env); let worker_sender = plugin_worker(worker); workers.insert(function_name.into(), worker_sender); } } - start_function.call(&[]).with_context(err_context)?; + let plugin = Arc::new(Mutex::new(RunningPlugin::new( + store, + main_user_instance, + main_user_env, + self.size.rows, + self.size.cols, + ))); plugin_map.lock().unwrap().insert( self.plugin_id, self.client_id, - Arc::new(Mutex::new(RunningPlugin::new( - main_user_instance, - main_user_env, - self.size.rows, - self.size.cols, - ))), + plugin.clone(), subscriptions.clone(), workers, ); + start_function + .call(&mut plugin.lock().unwrap().store, &[]) + .with_context(err_context)?; + let protobuf_plugin_configuration: ProtobufPluginConfiguration = self .plugin .userspace_configuration @@ -640,7 +654,9 @@ impl<'a> PluginLoader<'a> { // &self.plugin.userspace_configuration.inner(), ) .with_context(err_context)?; - load_function.call(&[]).with_context(err_context)?; + load_function + .call(&mut plugin.lock().unwrap().store, &[]) + .with_context(err_context)?; display_loading_stage!( indicate_starting_plugin_success, @@ -660,6 +676,7 @@ impl<'a> PluginLoader<'a> { self.senders, self.plugin_id ); + Ok(()) } pub fn clone_instance_for_other_clients( @@ -687,7 +704,7 @@ impl<'a> PluginLoader<'a> { &self.senders.clone(), self.plugin_id, *client_id, - &self.store, + self.store.clone(), &self.plugin_dir, self.path_to_default_shell.clone(), self.zellij_cwd.clone(), @@ -699,8 +716,9 @@ impl<'a> PluginLoader<'a> { plugin_loader_for_client .load_module_from_memory() .and_then(|module| plugin_loader_for_client.create_plugin_environment(module)) - .and_then(|(instance, plugin_env, subscriptions)| { + .and_then(|(store, instance, plugin_env, subscriptions)| { plugin_loader_for_client.load_plugin_instance( + store, &instance, &plugin_env, plugin_map, @@ -743,13 +761,15 @@ impl<'a> PluginLoader<'a> { fn create_plugin_instance_env_and_subscriptions( &self, module: &Module, - ) -> Result<(Instance, PluginEnv, Arc>)> { + ) -> Result<(Store, Instance, PluginEnv, Arc>)> { let err_context = || { format!( "Failed to create instance, plugin env and subscriptions for plugin {}", self.plugin_id ) }; + let mut store = get_store(); + let store_mut = &mut store; let mut wasi_env = WasiState::new("Zellij") .env("CLICOLOR_FORCE", "1") .map_dir("/host", self.zellij_cwd.clone()) @@ -762,10 +782,12 @@ impl<'a> PluginLoader<'a> { &self.plugin.location.to_string(), self.plugin_id, ))) - .finalize() + .finalize(store_mut) }) .with_context(err_context)?; - let wasi = wasi_env.import_object(&module).with_context(err_context)?; + let wasi = wasi_env + .import_object(store_mut, &module) + .with_context(err_context)?; let mut mut_plugin = self.plugin.clone(); mut_plugin.set_tab_index(self.tab_index); let plugin_env = PluginEnv { @@ -774,7 +796,7 @@ impl<'a> PluginLoader<'a> { plugin: mut_plugin, permissions: Arc::new(Mutex::new(None)), senders: self.senders.clone(), - wasi_env, + wasi_env: wasi_env.data_mut(store_mut).clone(), plugin_own_data_dir: self.plugin_own_data_dir.clone(), tab_index: self.tab_index, path_to_default_shell: self.path_to_default_shell.clone(), @@ -785,10 +807,15 @@ impl<'a> PluginLoader<'a> { }; let subscriptions = Arc::new(Mutex::new(HashSet::new())); - let zellij = zellij_exports(&self.store, &plugin_env, &subscriptions); - let instance = - Instance::new(&module, &zellij.chain_back(wasi)).with_context(err_context)?; - Ok((instance, plugin_env, subscriptions)) + + let mut zellij = zellij_exports(store_mut, &plugin_env, &subscriptions); + zellij.extend(&wasi); + + let instance = Instance::new(store_mut, &module, &zellij).with_context(err_context)?; + + wasi_env.initialize(store_mut, &instance)?; + + Ok((store, instance, plugin_env, subscriptions)) } } diff --git a/zellij-server/src/plugins/plugin_map.rs b/zellij-server/src/plugins/plugin_map.rs index 0cf26943..c5f2ef20 100644 --- a/zellij-server/src/plugins/plugin_map.rs +++ b/zellij-server/src/plugins/plugin_map.rs @@ -5,7 +5,7 @@ use std::{ path::PathBuf, sync::{Arc, Mutex}, }; -use wasmer::Instance; +use wasmer::{Instance, Store}; use wasmer_wasi::WasiEnv; use crate::{thread_bus::ThreadSenders, ClientId}; @@ -228,6 +228,7 @@ pub enum AtomicEvent { } pub struct RunningPlugin { + pub store: Store, pub instance: Instance, pub plugin_env: PluginEnv, pub rows: usize, @@ -237,8 +238,15 @@ pub struct RunningPlugin { } impl RunningPlugin { - pub fn new(instance: Instance, plugin_env: PluginEnv, rows: usize, columns: usize) -> Self { + pub fn new( + store: Store, + instance: Instance, + plugin_env: PluginEnv, + rows: usize, + columns: usize, + ) -> Self { RunningPlugin { + store, instance, plugin_env, rows, diff --git a/zellij-server/src/plugins/plugin_worker.rs b/zellij-server/src/plugins/plugin_worker.rs index 9aae0bab..ec577102 100644 --- a/zellij-server/src/plugins/plugin_worker.rs +++ b/zellij-server/src/plugins/plugin_worker.rs @@ -1,6 +1,6 @@ use crate::plugins::plugin_map::PluginEnv; use crate::plugins::zellij_exports::wasi_write_object; -use wasmer::Instance; +use wasmer::{Instance, Store}; use zellij_utils::async_channel::{unbounded, Receiver, Sender}; use zellij_utils::async_std::task; @@ -14,23 +14,26 @@ pub struct RunningWorker { pub name: String, pub plugin_config: PluginConfig, pub plugin_env: PluginEnv, + store: Store, } impl RunningWorker { pub fn new( + store: Store, instance: Instance, name: &str, plugin_config: PluginConfig, plugin_env: PluginEnv, ) -> Self { RunningWorker { + store, instance, name: name.into(), plugin_config, plugin_env, } } - pub fn send_message(&self, message: String, payload: String) -> Result<()> { + pub fn send_message(&mut self, message: String, payload: String) -> Result<()> { let err_context = || format!("Failed to send message to worker"); let protobuf_message = ProtobufMessage { name: message, @@ -44,7 +47,9 @@ impl RunningWorker { .get_function(&self.name) .with_context(err_context)?; wasi_write_object(&self.plugin_env.wasi_env, &protobuf_bytes).with_context(err_context)?; - work_function.call(&[]).with_context(err_context)?; + work_function + .call(&mut self.store, &[]) + .with_context(err_context)?; Ok(()) } } @@ -54,7 +59,7 @@ pub enum MessageToWorker { Exit, } -pub fn plugin_worker(worker: RunningWorker) -> Sender { +pub fn plugin_worker(mut worker: RunningWorker) -> Sender { let (sender, receiver): (Sender, Receiver) = unbounded(); task::spawn({ async move { diff --git a/zellij-server/src/plugins/unit/plugin_tests.rs b/zellij-server/src/plugins/unit/plugin_tests.rs index 5c0600ca..652623cc 100644 --- a/zellij-server/src/plugins/unit/plugin_tests.rs +++ b/zellij-server/src/plugins/unit/plugin_tests.rs @@ -238,7 +238,7 @@ fn create_plugin_thread( ) -> ( SenderWithContext, Receiver<(ScreenInstruction, ErrorContext)>, - Box, + Box, ) { let zellij_cwd = zellij_cwd.unwrap_or_else(|| PathBuf::from(".")); let (to_server, _server_receiver): ChannelWithContext = @@ -272,13 +272,13 @@ fn create_plugin_thread( None, ) .should_silently_fail(); - let store = Store::new(&wasmer::Universal::new(wasmer::Singlepass::default()).engine()); + let store = Store::new(wasmer::Singlepass::default()); let data_dir = PathBuf::from(tempdir().unwrap().path()); let default_shell = PathBuf::from("."); let plugin_capabilities = PluginCapabilities::default(); let client_attributes = ClientAttributes::default(); let default_shell_action = None; // TODO: change me - let _plugin_thread = std::thread::Builder::new() + let plugin_thread = std::thread::Builder::new() .name("plugin_thread".to_string()) .spawn(move || { set_var("ZELLIJ_SESSION_NAME", "zellij-test"); @@ -305,10 +305,7 @@ fn create_plugin_thread( let _ = to_screen.send(ScreenInstruction::Exit); let _ = to_server.send(ServerInstruction::KillSession); let _ = to_plugin.send(PluginInstruction::Exit); - std::thread::sleep(std::time::Duration::from_millis(100)); // we need to do this - // otherwise there are race - // conditions with removing - // the plugin cache + let _ = plugin_thread.join(); } }; (to_plugin, screen_receiver, Box::new(teardown)) @@ -320,7 +317,7 @@ fn create_plugin_thread_with_server_receiver( SenderWithContext, Receiver<(ServerInstruction, ErrorContext)>, Receiver<(ScreenInstruction, ErrorContext)>, - Box, + Box, ) { let zellij_cwd = zellij_cwd.unwrap_or_else(|| PathBuf::from(".")); let (to_server, server_receiver): ChannelWithContext = channels::bounded(50); @@ -353,13 +350,13 @@ fn create_plugin_thread_with_server_receiver( None, ) .should_silently_fail(); - let store = Store::new(&wasmer::Universal::new(wasmer::Singlepass::default()).engine()); + let store = Store::new(wasmer::Singlepass::default()); let data_dir = PathBuf::from(tempdir().unwrap().path()); let default_shell = PathBuf::from("."); let plugin_capabilities = PluginCapabilities::default(); let client_attributes = ClientAttributes::default(); let default_shell_action = None; // TODO: change me - let _plugin_thread = std::thread::Builder::new() + let plugin_thread = std::thread::Builder::new() .name("plugin_thread".to_string()) .spawn(move || { set_var("ZELLIJ_SESSION_NAME", "zellij-test"); @@ -386,10 +383,7 @@ fn create_plugin_thread_with_server_receiver( let _ = to_screen.send(ScreenInstruction::Exit); let _ = to_server.send(ServerInstruction::KillSession); let _ = to_plugin.send(PluginInstruction::Exit); - std::thread::sleep(std::time::Duration::from_millis(100)); // we need to do this - // otherwise there are race - // conditions with removing - // the plugin cache + let _ = plugin_thread.join(); } }; ( @@ -406,7 +400,7 @@ fn create_plugin_thread_with_pty_receiver( SenderWithContext, Receiver<(PtyInstruction, ErrorContext)>, Receiver<(ScreenInstruction, ErrorContext)>, - Box, + Box, ) { let zellij_cwd = zellij_cwd.unwrap_or_else(|| PathBuf::from(".")); let (to_server, _server_receiver): ChannelWithContext = @@ -440,13 +434,13 @@ fn create_plugin_thread_with_pty_receiver( None, ) .should_silently_fail(); - let store = Store::new(&wasmer::Universal::new(wasmer::Singlepass::default()).engine()); + let store = Store::new(wasmer::Singlepass::default()); let data_dir = PathBuf::from(tempdir().unwrap().path()); let default_shell = PathBuf::from("."); let plugin_capabilities = PluginCapabilities::default(); let client_attributes = ClientAttributes::default(); let default_shell_action = None; // TODO: change me - let _plugin_thread = std::thread::Builder::new() + let plugin_thread = std::thread::Builder::new() .name("plugin_thread".to_string()) .spawn(move || { set_var("ZELLIJ_SESSION_NAME", "zellij-test"); @@ -473,10 +467,7 @@ fn create_plugin_thread_with_pty_receiver( let _ = to_screen.send(ScreenInstruction::Exit); let _ = to_server.send(ServerInstruction::KillSession); let _ = to_plugin.send(PluginInstruction::Exit); - std::thread::sleep(std::time::Duration::from_millis(100)); // we need to do this - // otherwise there are race - // conditions with removing - // the plugin cache + let _ = plugin_thread.join(); } }; (to_plugin, pty_receiver, screen_receiver, Box::new(teardown)) @@ -504,7 +495,7 @@ pub fn load_new_plugin_from_hd() { let temp_folder = tempdir().unwrap(); // placed explicitly in the test scope because its let plugin_host_folder = PathBuf::from(temp_folder.path()); let cache_path = plugin_host_folder.join("permissions_test.kdl"); - let (plugin_thread_sender, screen_receiver, mut teardown) = create_plugin_thread(None); + let (plugin_thread_sender, screen_receiver, teardown) = create_plugin_thread(None); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); let run_plugin = RunPlugin { @@ -572,7 +563,7 @@ pub fn load_new_plugin_from_hd() { pub fn plugin_workers() { let temp_folder = tempdir().unwrap(); // placed explicitly in the test scope because its // destructor removes the directory - let (plugin_thread_sender, screen_receiver, mut teardown) = create_plugin_thread(None); + let (plugin_thread_sender, screen_receiver, teardown) = create_plugin_thread(None); let plugin_should_float = Some(false); let plugin_host_folder = PathBuf::from(temp_folder.path()); let cache_path = plugin_host_folder.join("permissions_test.kdl"); @@ -611,6 +602,7 @@ pub fn plugin_workers() { client_id, size, )); + std::thread::sleep(std::time::Duration::from_millis(500)); // we send a SystemClipboardFailure to trigger the custom handler in the fixture plugin that // will send a message to the worker and in turn back to the plugin to be rendered, so we know // that this cycle is working @@ -645,7 +637,7 @@ pub fn plugin_workers() { pub fn plugin_workers_persist_state() { let temp_folder = tempdir().unwrap(); // placed explicitly in the test scope because its // destructor removes the directory - let (plugin_thread_sender, screen_receiver, mut teardown) = create_plugin_thread(None); + let (plugin_thread_sender, screen_receiver, teardown) = create_plugin_thread(None); let plugin_should_float = Some(false); let plugin_host_folder = PathBuf::from(temp_folder.path()); let cache_path = plugin_host_folder.join("permissions_test.kdl"); @@ -684,6 +676,7 @@ pub fn plugin_workers_persist_state() { client_id, size, )); + std::thread::sleep(std::time::Duration::from_millis(500)); // we send a SystemClipboardFailure to trigger the custom handler in the fixture plugin that // will send a message to the worker and in turn back to the plugin to be rendered, so we know // that this cycle is working @@ -727,7 +720,7 @@ pub fn can_subscribe_to_hd_events() { let temp_folder = tempdir().unwrap(); // placed explicitly in the test scope because its // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); - let (plugin_thread_sender, screen_receiver, mut teardown) = + let (plugin_thread_sender, screen_receiver, teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); @@ -795,7 +788,7 @@ pub fn switch_to_mode_plugin_command() { // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); let cache_path = plugin_host_folder.join("permissions_test.kdl"); - let (plugin_thread_sender, screen_receiver, mut teardown) = + let (plugin_thread_sender, screen_receiver, teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); @@ -840,7 +833,6 @@ pub fn switch_to_mode_plugin_command() { Event::Key(Key::Char('a')), // this triggers a SwitchToMode(Tab) command in the fixture // plugin )])); - std::thread::sleep(std::time::Duration::from_millis(100)); screen_thread.join().unwrap(); // this might take a while if the cache is cold teardown(); let switch_to_mode_event = received_screen_instructions @@ -865,7 +857,7 @@ pub fn switch_to_mode_plugin_command_permission_denied() { // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); let cache_path = plugin_host_folder.join("permissions_test.kdl"); - let (plugin_thread_sender, screen_receiver, mut teardown) = + let (plugin_thread_sender, screen_receiver, teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); @@ -910,7 +902,6 @@ pub fn switch_to_mode_plugin_command_permission_denied() { Event::Key(Key::Char('a')), // this triggers a SwitchToMode(Tab) command in the fixture // plugin )])); - std::thread::sleep(std::time::Duration::from_millis(100)); screen_thread.join().unwrap(); // this might take a while if the cache is cold teardown(); let switch_to_mode_event = received_screen_instructions @@ -935,7 +926,7 @@ pub fn new_tabs_with_layout_plugin_command() { // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); let cache_path = plugin_host_folder.join("permissions_test.kdl"); - let (plugin_thread_sender, screen_receiver, mut teardown) = + let (plugin_thread_sender, screen_receiver, teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); @@ -980,7 +971,6 @@ pub fn new_tabs_with_layout_plugin_command() { Event::Key(Key::Char('b')), // this triggers a new_tabs_with_layout command in the fixture // plugin )])); - std::thread::sleep(std::time::Duration::from_millis(100)); screen_thread.join().unwrap(); // this might take a while if the cache is cold teardown(); let first_new_tab_event = received_screen_instructions @@ -1019,7 +1009,7 @@ pub fn new_tab_plugin_command() { // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); let cache_path = plugin_host_folder.join("permissions_test.kdl"); - let (plugin_thread_sender, screen_receiver, mut teardown) = + let (plugin_thread_sender, screen_receiver, teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); @@ -1064,7 +1054,6 @@ pub fn new_tab_plugin_command() { Event::Key(Key::Char('c')), // this triggers a new_tab command in the fixture // plugin )])); - std::thread::sleep(std::time::Duration::from_millis(100)); screen_thread.join().unwrap(); // this might take a while if the cache is cold teardown(); let new_tab_event = received_screen_instructions @@ -1089,7 +1078,7 @@ pub fn go_to_next_tab_plugin_command() { // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); let cache_path = plugin_host_folder.join("permissions_test.kdl"); - let (plugin_thread_sender, screen_receiver, mut teardown) = + let (plugin_thread_sender, screen_receiver, teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); @@ -1133,7 +1122,6 @@ pub fn go_to_next_tab_plugin_command() { Some(client_id), Event::Key(Key::Char('d')), // this triggers the event in the fixture plugin )])); - std::thread::sleep(std::time::Duration::from_millis(100)); screen_thread.join().unwrap(); // this might take a while if the cache is cold teardown(); let new_tab_event = received_screen_instructions @@ -1158,7 +1146,7 @@ pub fn go_to_previous_tab_plugin_command() { // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); let cache_path = plugin_host_folder.join("permissions_test.kdl"); - let (plugin_thread_sender, screen_receiver, mut teardown) = + let (plugin_thread_sender, screen_receiver, teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); @@ -1202,7 +1190,6 @@ pub fn go_to_previous_tab_plugin_command() { Some(client_id), Event::Key(Key::Char('e')), // this triggers the event in the fixture plugin )])); - std::thread::sleep(std::time::Duration::from_millis(100)); screen_thread.join().unwrap(); // this might take a while if the cache is cold teardown(); let new_tab_event = received_screen_instructions @@ -1227,7 +1214,7 @@ pub fn resize_focused_pane_plugin_command() { // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); let cache_path = plugin_host_folder.join("permissions_test.kdl"); - let (plugin_thread_sender, screen_receiver, mut teardown) = + let (plugin_thread_sender, screen_receiver, teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); @@ -1271,7 +1258,6 @@ pub fn resize_focused_pane_plugin_command() { Some(client_id), Event::Key(Key::Char('f')), // this triggers the event in the fixture plugin )])); - std::thread::sleep(std::time::Duration::from_millis(100)); screen_thread.join().unwrap(); // this might take a while if the cache is cold teardown(); let new_tab_event = received_screen_instructions @@ -1296,7 +1282,7 @@ pub fn resize_focused_pane_with_direction_plugin_command() { // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); let cache_path = plugin_host_folder.join("permissions_test.kdl"); - let (plugin_thread_sender, screen_receiver, mut teardown) = + let (plugin_thread_sender, screen_receiver, teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); @@ -1340,7 +1326,6 @@ pub fn resize_focused_pane_with_direction_plugin_command() { Some(client_id), Event::Key(Key::Char('g')), // this triggers the enent in the fixture plugin )])); - std::thread::sleep(std::time::Duration::from_millis(100)); screen_thread.join().unwrap(); // this might take a while if the cache is cold teardown(); let new_tab_event = received_screen_instructions @@ -1365,7 +1350,7 @@ pub fn focus_next_pane_plugin_command() { // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); let cache_path = plugin_host_folder.join("permissions_test.kdl"); - let (plugin_thread_sender, screen_receiver, mut teardown) = + let (plugin_thread_sender, screen_receiver, teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); @@ -1409,7 +1394,6 @@ pub fn focus_next_pane_plugin_command() { Some(client_id), Event::Key(Key::Char('h')), // this triggers the enent in the fixture plugin )])); - std::thread::sleep(std::time::Duration::from_millis(100)); screen_thread.join().unwrap(); // this might take a while if the cache is cold teardown(); let new_tab_event = received_screen_instructions @@ -1434,7 +1418,7 @@ pub fn focus_previous_pane_plugin_command() { // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); let cache_path = plugin_host_folder.join("permissions_test.kdl"); - let (plugin_thread_sender, screen_receiver, mut teardown) = + let (plugin_thread_sender, screen_receiver, teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); @@ -1478,7 +1462,6 @@ pub fn focus_previous_pane_plugin_command() { Some(client_id), Event::Key(Key::Char('i')), // this triggers the enent in the fixture plugin )])); - std::thread::sleep(std::time::Duration::from_millis(100)); screen_thread.join().unwrap(); // this might take a while if the cache is cold teardown(); let new_tab_event = received_screen_instructions @@ -1503,7 +1486,7 @@ pub fn move_focus_plugin_command() { // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); let cache_path = plugin_host_folder.join("permissions_test.kdl"); - let (plugin_thread_sender, screen_receiver, mut teardown) = + let (plugin_thread_sender, screen_receiver, teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); @@ -1547,7 +1530,6 @@ pub fn move_focus_plugin_command() { Some(client_id), Event::Key(Key::Char('j')), // this triggers the enent in the fixture plugin )])); - std::thread::sleep(std::time::Duration::from_millis(100)); screen_thread.join().unwrap(); // this might take a while if the cache is cold teardown(); let new_tab_event = received_screen_instructions @@ -1572,7 +1554,7 @@ pub fn move_focus_or_tab_plugin_command() { // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); let cache_path = plugin_host_folder.join("permissions_test.kdl"); - let (plugin_thread_sender, screen_receiver, mut teardown) = + let (plugin_thread_sender, screen_receiver, teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); @@ -1616,7 +1598,6 @@ pub fn move_focus_or_tab_plugin_command() { Some(client_id), Event::Key(Key::Char('k')), // this triggers the enent in the fixture plugin )])); - std::thread::sleep(std::time::Duration::from_millis(100)); screen_thread.join().unwrap(); // this might take a while if the cache is cold teardown(); let new_tab_event = received_screen_instructions @@ -1641,7 +1622,7 @@ pub fn edit_scrollback_plugin_command() { // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); let cache_path = plugin_host_folder.join("permissions_test.kdl"); - let (plugin_thread_sender, screen_receiver, mut teardown) = + let (plugin_thread_sender, screen_receiver, teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); @@ -1685,7 +1666,6 @@ pub fn edit_scrollback_plugin_command() { Some(client_id), Event::Key(Key::Char('m')), // this triggers the enent in the fixture plugin )])); - std::thread::sleep(std::time::Duration::from_millis(100)); screen_thread.join().unwrap(); // this might take a while if the cache is cold teardown(); let new_tab_event = received_screen_instructions @@ -1710,7 +1690,7 @@ pub fn write_plugin_command() { // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); let cache_path = plugin_host_folder.join("permissions_test.kdl"); - let (plugin_thread_sender, screen_receiver, mut teardown) = + let (plugin_thread_sender, screen_receiver, teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); @@ -1754,7 +1734,6 @@ pub fn write_plugin_command() { Some(client_id), Event::Key(Key::Char('n')), // this triggers the enent in the fixture plugin )])); - std::thread::sleep(std::time::Duration::from_millis(100)); screen_thread.join().unwrap(); // this might take a while if the cache is cold teardown(); let new_tab_event = received_screen_instructions @@ -1779,7 +1758,7 @@ pub fn write_chars_plugin_command() { // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); let cache_path = plugin_host_folder.join("permissions_test.kdl"); - let (plugin_thread_sender, screen_receiver, mut teardown) = + let (plugin_thread_sender, screen_receiver, teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); @@ -1823,7 +1802,6 @@ pub fn write_chars_plugin_command() { Some(client_id), Event::Key(Key::Char('o')), // this triggers the enent in the fixture plugin )])); - std::thread::sleep(std::time::Duration::from_millis(100)); screen_thread.join().unwrap(); // this might take a while if the cache is cold teardown(); let new_tab_event = received_screen_instructions @@ -1848,7 +1826,7 @@ pub fn toggle_tab_plugin_command() { // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); let cache_path = plugin_host_folder.join("permissions_test.kdl"); - let (plugin_thread_sender, screen_receiver, mut teardown) = + let (plugin_thread_sender, screen_receiver, teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); @@ -1892,7 +1870,6 @@ pub fn toggle_tab_plugin_command() { Some(client_id), Event::Key(Key::Char('p')), // this triggers the enent in the fixture plugin )])); - std::thread::sleep(std::time::Duration::from_millis(100)); screen_thread.join().unwrap(); // this might take a while if the cache is cold teardown(); let new_tab_event = received_screen_instructions @@ -1917,7 +1894,7 @@ pub fn move_pane_plugin_command() { // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); let cache_path = plugin_host_folder.join("permissions_test.kdl"); - let (plugin_thread_sender, screen_receiver, mut teardown) = + let (plugin_thread_sender, screen_receiver, teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); @@ -1961,7 +1938,6 @@ pub fn move_pane_plugin_command() { Some(client_id), Event::Key(Key::Char('q')), // this triggers the enent in the fixture plugin )])); - std::thread::sleep(std::time::Duration::from_millis(100)); screen_thread.join().unwrap(); // this might take a while if the cache is cold teardown(); let new_tab_event = received_screen_instructions @@ -1986,7 +1962,7 @@ pub fn move_pane_with_direction_plugin_command() { // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); let cache_path = plugin_host_folder.join("permissions_test.kdl"); - let (plugin_thread_sender, screen_receiver, mut teardown) = + let (plugin_thread_sender, screen_receiver, teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); @@ -2030,7 +2006,6 @@ pub fn move_pane_with_direction_plugin_command() { Some(client_id), Event::Key(Key::Char('r')), // this triggers the enent in the fixture plugin )])); - std::thread::sleep(std::time::Duration::from_millis(100)); screen_thread.join().unwrap(); // this might take a while if the cache is cold teardown(); let new_tab_event = received_screen_instructions @@ -2055,7 +2030,7 @@ pub fn clear_screen_plugin_command() { // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); let cache_path = plugin_host_folder.join("permissions_test.kdl"); - let (plugin_thread_sender, screen_receiver, mut teardown) = + let (plugin_thread_sender, screen_receiver, teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); @@ -2100,7 +2075,6 @@ pub fn clear_screen_plugin_command() { Some(client_id), Event::Key(Key::Char('s')), // this triggers the enent in the fixture plugin )])); - std::thread::sleep(std::time::Duration::from_millis(100)); screen_thread.join().unwrap(); // this might take a while if the cache is cold teardown(); let new_tab_event = received_screen_instructions @@ -2125,7 +2099,7 @@ pub fn scroll_up_plugin_command() { // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); let cache_path = plugin_host_folder.join("permissions_test.kdl"); - let (plugin_thread_sender, screen_receiver, mut teardown) = + let (plugin_thread_sender, screen_receiver, teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); @@ -2170,7 +2144,6 @@ pub fn scroll_up_plugin_command() { Some(client_id), Event::Key(Key::Char('t')), // this triggers the enent in the fixture plugin )])); - std::thread::sleep(std::time::Duration::from_millis(100)); screen_thread.join().unwrap(); // this might take a while if the cache is cold teardown(); let new_tab_event = received_screen_instructions @@ -2195,7 +2168,7 @@ pub fn scroll_down_plugin_command() { // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); let cache_path = plugin_host_folder.join("permissions_test.kdl"); - let (plugin_thread_sender, screen_receiver, mut teardown) = + let (plugin_thread_sender, screen_receiver, teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); @@ -2239,7 +2212,6 @@ pub fn scroll_down_plugin_command() { Some(client_id), Event::Key(Key::Char('u')), // this triggers the enent in the fixture plugin )])); - std::thread::sleep(std::time::Duration::from_millis(100)); screen_thread.join().unwrap(); // this might take a while if the cache is cold teardown(); let new_tab_event = received_screen_instructions @@ -2264,7 +2236,7 @@ pub fn scroll_to_top_plugin_command() { // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); let cache_path = plugin_host_folder.join("permissions_test.kdl"); - let (plugin_thread_sender, screen_receiver, mut teardown) = + let (plugin_thread_sender, screen_receiver, teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); @@ -2308,7 +2280,6 @@ pub fn scroll_to_top_plugin_command() { Some(client_id), Event::Key(Key::Char('v')), // this triggers the enent in the fixture plugin )])); - std::thread::sleep(std::time::Duration::from_millis(100)); screen_thread.join().unwrap(); // this might take a while if the cache is cold teardown(); let new_tab_event = received_screen_instructions @@ -2333,7 +2304,7 @@ pub fn scroll_to_bottom_plugin_command() { // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); let cache_path = plugin_host_folder.join("permissions_test.kdl"); - let (plugin_thread_sender, screen_receiver, mut teardown) = + let (plugin_thread_sender, screen_receiver, teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); @@ -2377,7 +2348,6 @@ pub fn scroll_to_bottom_plugin_command() { Some(client_id), Event::Key(Key::Char('w')), // this triggers the enent in the fixture plugin )])); - std::thread::sleep(std::time::Duration::from_millis(100)); screen_thread.join().unwrap(); // this might take a while if the cache is cold teardown(); let new_tab_event = received_screen_instructions @@ -2402,7 +2372,7 @@ pub fn page_scroll_up_plugin_command() { // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); let cache_path = plugin_host_folder.join("permissions_test.kdl"); - let (plugin_thread_sender, screen_receiver, mut teardown) = + let (plugin_thread_sender, screen_receiver, teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); @@ -2446,7 +2416,6 @@ pub fn page_scroll_up_plugin_command() { Some(client_id), Event::Key(Key::Char('x')), // this triggers the enent in the fixture plugin )])); - std::thread::sleep(std::time::Duration::from_millis(100)); screen_thread.join().unwrap(); // this might take a while if the cache is cold teardown(); let new_tab_event = received_screen_instructions @@ -2471,7 +2440,7 @@ pub fn page_scroll_down_plugin_command() { // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); let cache_path = plugin_host_folder.join("permissions_test.kdl"); - let (plugin_thread_sender, screen_receiver, mut teardown) = + let (plugin_thread_sender, screen_receiver, teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); @@ -2515,7 +2484,6 @@ pub fn page_scroll_down_plugin_command() { Some(client_id), Event::Key(Key::Char('y')), // this triggers the enent in the fixture plugin )])); - std::thread::sleep(std::time::Duration::from_millis(100)); screen_thread.join().unwrap(); // this might take a while if the cache is cold teardown(); let new_tab_event = received_screen_instructions @@ -2540,7 +2508,7 @@ pub fn toggle_focus_fullscreen_plugin_command() { // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); let cache_path = plugin_host_folder.join("permissions_test.kdl"); - let (plugin_thread_sender, screen_receiver, mut teardown) = + let (plugin_thread_sender, screen_receiver, teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); @@ -2584,7 +2552,6 @@ pub fn toggle_focus_fullscreen_plugin_command() { Some(client_id), Event::Key(Key::Char('z')), // this triggers the enent in the fixture plugin )])); - std::thread::sleep(std::time::Duration::from_millis(100)); screen_thread.join().unwrap(); // this might take a while if the cache is cold teardown(); let new_tab_event = received_screen_instructions @@ -2609,7 +2576,7 @@ pub fn toggle_pane_frames_plugin_command() { // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); let cache_path = plugin_host_folder.join("permissions_test.kdl"); - let (plugin_thread_sender, screen_receiver, mut teardown) = + let (plugin_thread_sender, screen_receiver, teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); @@ -2653,7 +2620,6 @@ pub fn toggle_pane_frames_plugin_command() { Some(client_id), Event::Key(Key::Char('1')), // this triggers the enent in the fixture plugin )])); - std::thread::sleep(std::time::Duration::from_millis(100)); screen_thread.join().unwrap(); // this might take a while if the cache is cold teardown(); let new_tab_event = received_screen_instructions @@ -2678,7 +2644,7 @@ pub fn toggle_pane_embed_or_eject_plugin_command() { // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); let cache_path = plugin_host_folder.join("permissions_test.kdl"); - let (plugin_thread_sender, screen_receiver, mut teardown) = + let (plugin_thread_sender, screen_receiver, teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); @@ -2722,7 +2688,6 @@ pub fn toggle_pane_embed_or_eject_plugin_command() { Some(client_id), Event::Key(Key::Char('2')), // this triggers the enent in the fixture plugin )])); - std::thread::sleep(std::time::Duration::from_millis(100)); screen_thread.join().unwrap(); // this might take a while if the cache is cold teardown(); let new_tab_event = received_screen_instructions @@ -2747,7 +2712,7 @@ pub fn undo_rename_pane_plugin_command() { // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); let cache_path = plugin_host_folder.join("permissions_test.kdl"); - let (plugin_thread_sender, screen_receiver, mut teardown) = + let (plugin_thread_sender, screen_receiver, teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); @@ -2791,7 +2756,6 @@ pub fn undo_rename_pane_plugin_command() { Some(client_id), Event::Key(Key::Char('3')), // this triggers the enent in the fixture plugin )])); - std::thread::sleep(std::time::Duration::from_millis(100)); screen_thread.join().unwrap(); // this might take a while if the cache is cold teardown(); let new_tab_event = received_screen_instructions @@ -2816,7 +2780,7 @@ pub fn close_focus_plugin_command() { // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); let cache_path = plugin_host_folder.join("permissions_test.kdl"); - let (plugin_thread_sender, screen_receiver, mut teardown) = + let (plugin_thread_sender, screen_receiver, teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); @@ -2860,7 +2824,6 @@ pub fn close_focus_plugin_command() { Some(client_id), Event::Key(Key::Char('4')), // this triggers the enent in the fixture plugin )])); - std::thread::sleep(std::time::Duration::from_millis(100)); screen_thread.join().unwrap(); // this might take a while if the cache is cold teardown(); let new_tab_event = received_screen_instructions @@ -2885,7 +2848,7 @@ pub fn toggle_active_tab_sync_plugin_command() { // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); let cache_path = plugin_host_folder.join("permissions_test.kdl"); - let (plugin_thread_sender, screen_receiver, mut teardown) = + let (plugin_thread_sender, screen_receiver, teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); @@ -2929,7 +2892,6 @@ pub fn toggle_active_tab_sync_plugin_command() { Some(client_id), Event::Key(Key::Char('5')), // this triggers the enent in the fixture plugin )])); - std::thread::sleep(std::time::Duration::from_millis(100)); screen_thread.join().unwrap(); // this might take a while if the cache is cold teardown(); let new_tab_event = received_screen_instructions @@ -2954,7 +2916,7 @@ pub fn close_focused_tab_plugin_command() { // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); let cache_path = plugin_host_folder.join("permissions_test.kdl"); - let (plugin_thread_sender, screen_receiver, mut teardown) = + let (plugin_thread_sender, screen_receiver, teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); @@ -2998,7 +2960,6 @@ pub fn close_focused_tab_plugin_command() { Some(client_id), Event::Key(Key::Char('6')), // this triggers the enent in the fixture plugin )])); - std::thread::sleep(std::time::Duration::from_millis(100)); screen_thread.join().unwrap(); // this might take a while if the cache is cold teardown(); let new_tab_event = received_screen_instructions @@ -3023,7 +2984,7 @@ pub fn undo_rename_tab_plugin_command() { // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); let cache_path = plugin_host_folder.join("permissions_test.kdl"); - let (plugin_thread_sender, screen_receiver, mut teardown) = + let (plugin_thread_sender, screen_receiver, teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); @@ -3067,7 +3028,6 @@ pub fn undo_rename_tab_plugin_command() { Some(client_id), Event::Key(Key::Char('7')), // this triggers the enent in the fixture plugin )])); - std::thread::sleep(std::time::Duration::from_millis(100)); screen_thread.join().unwrap(); // this might take a while if the cache is cold teardown(); let new_tab_event = received_screen_instructions @@ -3092,7 +3052,7 @@ pub fn previous_swap_layout_plugin_command() { // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); let cache_path = plugin_host_folder.join("permissions_test.kdl"); - let (plugin_thread_sender, screen_receiver, mut teardown) = + let (plugin_thread_sender, screen_receiver, teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); @@ -3136,7 +3096,6 @@ pub fn previous_swap_layout_plugin_command() { Some(client_id), Event::Key(Key::Ctrl('a')), // this triggers the enent in the fixture plugin )])); - std::thread::sleep(std::time::Duration::from_millis(100)); screen_thread.join().unwrap(); // this might take a while if the cache is cold teardown(); let new_tab_event = received_screen_instructions @@ -3161,7 +3120,7 @@ pub fn next_swap_layout_plugin_command() { // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); let cache_path = plugin_host_folder.join("permissions_test.kdl"); - let (plugin_thread_sender, screen_receiver, mut teardown) = + let (plugin_thread_sender, screen_receiver, teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); @@ -3205,7 +3164,6 @@ pub fn next_swap_layout_plugin_command() { Some(client_id), Event::Key(Key::Ctrl('b')), // this triggers the enent in the fixture plugin )])); - std::thread::sleep(std::time::Duration::from_millis(100)); screen_thread.join().unwrap(); // this might take a while if the cache is cold teardown(); let new_tab_event = received_screen_instructions @@ -3230,7 +3188,7 @@ pub fn go_to_tab_name_plugin_command() { // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); let cache_path = plugin_host_folder.join("permissions_test.kdl"); - let (plugin_thread_sender, screen_receiver, mut teardown) = + let (plugin_thread_sender, screen_receiver, teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); @@ -3274,7 +3232,6 @@ pub fn go_to_tab_name_plugin_command() { Some(client_id), Event::Key(Key::Ctrl('c')), // this triggers the enent in the fixture plugin )])); - std::thread::sleep(std::time::Duration::from_millis(100)); screen_thread.join().unwrap(); // this might take a while if the cache is cold teardown(); let new_tab_event = received_screen_instructions @@ -3299,7 +3256,7 @@ pub fn focus_or_create_tab_plugin_command() { // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); let cache_path = plugin_host_folder.join("permissions_test.kdl"); - let (plugin_thread_sender, screen_receiver, mut teardown) = + let (plugin_thread_sender, screen_receiver, teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); @@ -3343,7 +3300,6 @@ pub fn focus_or_create_tab_plugin_command() { Some(client_id), Event::Key(Key::Ctrl('d')), // this triggers the enent in the fixture plugin )])); - std::thread::sleep(std::time::Duration::from_millis(100)); screen_thread.join().unwrap(); // this might take a while if the cache is cold teardown(); let new_tab_event = received_screen_instructions @@ -3368,7 +3324,7 @@ pub fn go_to_tab() { // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); let cache_path = plugin_host_folder.join("permissions_test.kdl"); - let (plugin_thread_sender, screen_receiver, mut teardown) = + let (plugin_thread_sender, screen_receiver, teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); @@ -3412,7 +3368,6 @@ pub fn go_to_tab() { Some(client_id), Event::Key(Key::Ctrl('e')), // this triggers the enent in the fixture plugin )])); - std::thread::sleep(std::time::Duration::from_millis(100)); screen_thread.join().unwrap(); // this might take a while if the cache is cold teardown(); let new_tab_event = received_screen_instructions @@ -3437,7 +3392,7 @@ pub fn start_or_reload_plugin() { // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); let cache_path = plugin_host_folder.join("permissions_test.kdl"); - let (plugin_thread_sender, screen_receiver, mut teardown) = + let (plugin_thread_sender, screen_receiver, teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); @@ -3481,7 +3436,6 @@ pub fn start_or_reload_plugin() { Some(client_id), Event::Key(Key::Ctrl('f')), // this triggers the enent in the fixture plugin )])); - std::thread::sleep(std::time::Duration::from_millis(100)); screen_thread.join().unwrap(); // this might take a while if the cache is cold teardown(); let new_tab_event = received_screen_instructions @@ -3506,7 +3460,7 @@ pub fn quit_zellij_plugin_command() { // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); let cache_path = plugin_host_folder.join("permissions_test.kdl"); - let (plugin_thread_sender, server_receiver, screen_receiver, mut teardown) = + let (plugin_thread_sender, server_receiver, screen_receiver, teardown) = create_plugin_thread_with_server_receiver(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); @@ -3557,7 +3511,6 @@ pub fn quit_zellij_plugin_command() { Some(client_id), Event::Key(Key::Char('8')), // this triggers the enent in the fixture plugin )])); - std::thread::sleep(std::time::Duration::from_millis(100)); server_thread.join().unwrap(); // this might take a while if the cache is cold teardown(); let new_tab_event = received_server_instruction @@ -3582,7 +3535,7 @@ pub fn detach_plugin_command() { // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); let cache_path = plugin_host_folder.join("permissions_test.kdl"); - let (plugin_thread_sender, server_receiver, screen_receiver, mut teardown) = + let (plugin_thread_sender, server_receiver, screen_receiver, teardown) = create_plugin_thread_with_server_receiver(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); @@ -3633,7 +3586,6 @@ pub fn detach_plugin_command() { Some(client_id), Event::Key(Key::Char('l')), // this triggers the enent in the fixture plugin )])); - std::thread::sleep(std::time::Duration::from_millis(100)); server_thread.join().unwrap(); // this might take a while if the cache is cold teardown(); let new_tab_event = received_server_instruction @@ -3658,7 +3610,7 @@ pub fn open_file_floating_plugin_command() { // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); let cache_path = plugin_host_folder.join("permissions_test.kdl"); - let (plugin_thread_sender, pty_receiver, screen_receiver, mut teardown) = + let (plugin_thread_sender, pty_receiver, screen_receiver, teardown) = create_plugin_thread_with_pty_receiver(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); @@ -3709,7 +3661,6 @@ pub fn open_file_floating_plugin_command() { Some(client_id), Event::Key(Key::Ctrl('h')), // this triggers the enent in the fixture plugin )])); - std::thread::sleep(std::time::Duration::from_millis(100)); pty_thread.join().unwrap(); // this might take a while if the cache is cold teardown(); let new_tab_event = received_pty_instructions @@ -3734,7 +3685,7 @@ pub fn open_file_plugin_command() { // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); let cache_path = plugin_host_folder.join("permissions_test.kdl"); - let (plugin_thread_sender, pty_receiver, screen_receiver, mut teardown) = + let (plugin_thread_sender, pty_receiver, screen_receiver, teardown) = create_plugin_thread_with_pty_receiver(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); @@ -3785,7 +3736,6 @@ pub fn open_file_plugin_command() { Some(client_id), Event::Key(Key::Ctrl('g')), // this triggers the enent in the fixture plugin )])); - std::thread::sleep(std::time::Duration::from_millis(100)); pty_thread.join().unwrap(); // this might take a while if the cache is cold teardown(); let new_tab_event = received_pty_instructions @@ -3810,7 +3760,7 @@ pub fn open_file_with_line_plugin_command() { // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); let cache_path = plugin_host_folder.join("permissions_test.kdl"); - let (plugin_thread_sender, pty_receiver, screen_receiver, mut teardown) = + let (plugin_thread_sender, pty_receiver, screen_receiver, teardown) = create_plugin_thread_with_pty_receiver(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); @@ -3862,7 +3812,6 @@ pub fn open_file_with_line_plugin_command() { Some(client_id), Event::Key(Key::Ctrl('i')), // this triggers the enent in the fixture plugin )])); - std::thread::sleep(std::time::Duration::from_millis(100)); pty_thread.join().unwrap(); // this might take a while if the cache is cold teardown(); let new_tab_event = received_pty_instructions @@ -3887,7 +3836,7 @@ pub fn open_file_with_line_floating_plugin_command() { // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); let cache_path = plugin_host_folder.join("permissions_test.kdl"); - let (plugin_thread_sender, pty_receiver, screen_receiver, mut teardown) = + let (plugin_thread_sender, pty_receiver, screen_receiver, teardown) = create_plugin_thread_with_pty_receiver(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); @@ -3938,7 +3887,6 @@ pub fn open_file_with_line_floating_plugin_command() { Some(client_id), Event::Key(Key::Ctrl('j')), // this triggers the enent in the fixture plugin )])); - std::thread::sleep(std::time::Duration::from_millis(100)); pty_thread.join().unwrap(); // this might take a while if the cache is cold teardown(); let new_tab_event = received_pty_instructions @@ -3963,7 +3911,7 @@ pub fn open_terminal_plugin_command() { // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); let cache_path = plugin_host_folder.join("permissions_test.kdl"); - let (plugin_thread_sender, pty_receiver, screen_receiver, mut teardown) = + let (plugin_thread_sender, pty_receiver, screen_receiver, teardown) = create_plugin_thread_with_pty_receiver(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); @@ -4014,7 +3962,6 @@ pub fn open_terminal_plugin_command() { Some(client_id), Event::Key(Key::Ctrl('k')), // this triggers the enent in the fixture plugin )])); - std::thread::sleep(std::time::Duration::from_millis(100)); pty_thread.join().unwrap(); // this might take a while if the cache is cold teardown(); let new_tab_event = received_pty_instructions @@ -4039,7 +3986,7 @@ pub fn open_terminal_floating_plugin_command() { // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); let cache_path = plugin_host_folder.join("permissions_test.kdl"); - let (plugin_thread_sender, pty_receiver, screen_receiver, mut teardown) = + let (plugin_thread_sender, pty_receiver, screen_receiver, teardown) = create_plugin_thread_with_pty_receiver(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); @@ -4090,7 +4037,6 @@ pub fn open_terminal_floating_plugin_command() { Some(client_id), Event::Key(Key::Ctrl('l')), // this triggers the enent in the fixture plugin )])); - std::thread::sleep(std::time::Duration::from_millis(100)); pty_thread.join().unwrap(); // this might take a while if the cache is cold teardown(); let new_tab_event = received_pty_instructions @@ -4115,7 +4061,7 @@ pub fn open_command_pane_plugin_command() { // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); let cache_path = plugin_host_folder.join("permissions_test.kdl"); - let (plugin_thread_sender, pty_receiver, screen_receiver, mut teardown) = + let (plugin_thread_sender, pty_receiver, screen_receiver, teardown) = create_plugin_thread_with_pty_receiver(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); @@ -4166,7 +4112,6 @@ pub fn open_command_pane_plugin_command() { Some(client_id), Event::Key(Key::Ctrl('m')), // this triggers the enent in the fixture plugin )])); - std::thread::sleep(std::time::Duration::from_millis(100)); pty_thread.join().unwrap(); // this might take a while if the cache is cold teardown(); let new_tab_event = received_pty_instructions @@ -4191,7 +4136,7 @@ pub fn open_command_pane_floating_plugin_command() { // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); let cache_path = plugin_host_folder.join("permissions_test.kdl"); - let (plugin_thread_sender, pty_receiver, screen_receiver, mut teardown) = + let (plugin_thread_sender, pty_receiver, screen_receiver, teardown) = create_plugin_thread_with_pty_receiver(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); @@ -4242,7 +4187,6 @@ pub fn open_command_pane_floating_plugin_command() { Some(client_id), Event::Key(Key::Ctrl('n')), // this triggers the enent in the fixture plugin )])); - std::thread::sleep(std::time::Duration::from_millis(100)); pty_thread.join().unwrap(); // this might take a while if the cache is cold teardown(); let new_tab_event = received_pty_instructions @@ -4267,7 +4211,7 @@ pub fn switch_to_tab_plugin_command() { // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); let cache_path = plugin_host_folder.join("permissions_test.kdl"); - let (plugin_thread_sender, screen_receiver, mut teardown) = + let (plugin_thread_sender, screen_receiver, teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); @@ -4311,7 +4255,6 @@ pub fn switch_to_tab_plugin_command() { Some(client_id), Event::Key(Key::Ctrl('o')), // this triggers the enent in the fixture plugin )])); - std::thread::sleep(std::time::Duration::from_millis(100)); screen_thread.join().unwrap(); // this might take a while if the cache is cold teardown(); let new_tab_event = received_screen_instructions @@ -4335,7 +4278,7 @@ pub fn hide_self_plugin_command() { let temp_folder = tempdir().unwrap(); // placed explicitly in the test scope because its // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); - let (plugin_thread_sender, screen_receiver, mut teardown) = + let (plugin_thread_sender, screen_receiver, teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); @@ -4375,7 +4318,6 @@ pub fn hide_self_plugin_command() { Some(client_id), Event::Key(Key::Ctrl('p')), // this triggers the enent in the fixture plugin )])); - std::thread::sleep(std::time::Duration::from_millis(100)); screen_thread.join().unwrap(); // this might take a while if the cache is cold teardown(); let new_tab_event = received_screen_instructions @@ -4399,7 +4341,7 @@ pub fn show_self_plugin_command() { let temp_folder = tempdir().unwrap(); // placed explicitly in the test scope because its // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); - let (plugin_thread_sender, screen_receiver, mut teardown) = + let (plugin_thread_sender, screen_receiver, teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); @@ -4439,7 +4381,6 @@ pub fn show_self_plugin_command() { Some(client_id), Event::Key(Key::Ctrl('q')), // this triggers the enent in the fixture plugin )])); - std::thread::sleep(std::time::Duration::from_millis(100)); screen_thread.join().unwrap(); // this might take a while if the cache is cold teardown(); let new_tab_event = received_screen_instructions @@ -4464,7 +4405,7 @@ pub fn close_terminal_pane_plugin_command() { // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); let cache_path = plugin_host_folder.join("permissions_test.kdl"); - let (plugin_thread_sender, screen_receiver, mut teardown) = + let (plugin_thread_sender, screen_receiver, teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); @@ -4508,7 +4449,6 @@ pub fn close_terminal_pane_plugin_command() { Some(client_id), Event::Key(Key::Ctrl('r')), // this triggers the enent in the fixture plugin )])); - std::thread::sleep(std::time::Duration::from_millis(100)); screen_thread.join().unwrap(); // this might take a while if the cache is cold teardown(); let new_tab_event = received_screen_instructions @@ -4533,7 +4473,7 @@ pub fn close_plugin_pane_plugin_command() { // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); let cache_path = plugin_host_folder.join("permissions_test.kdl"); - let (plugin_thread_sender, screen_receiver, mut teardown) = + let (plugin_thread_sender, screen_receiver, teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); @@ -4577,7 +4517,6 @@ pub fn close_plugin_pane_plugin_command() { Some(client_id), Event::Key(Key::Ctrl('s')), // this triggers the enent in the fixture plugin )])); - std::thread::sleep(std::time::Duration::from_millis(100)); screen_thread.join().unwrap(); // this might take a while if the cache is cold teardown(); let new_tab_event = received_screen_instructions @@ -4602,7 +4541,7 @@ pub fn focus_terminal_pane_plugin_command() { // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); let cache_path = plugin_host_folder.join("permissions_test.kdl"); - let (plugin_thread_sender, screen_receiver, mut teardown) = + let (plugin_thread_sender, screen_receiver, teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); @@ -4646,7 +4585,6 @@ pub fn focus_terminal_pane_plugin_command() { Some(client_id), Event::Key(Key::Ctrl('t')), // this triggers the enent in the fixture plugin )])); - std::thread::sleep(std::time::Duration::from_millis(100)); screen_thread.join().unwrap(); // this might take a while if the cache is cold teardown(); let new_tab_event = received_screen_instructions @@ -4671,7 +4609,7 @@ pub fn focus_plugin_pane_plugin_command() { // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); let cache_path = plugin_host_folder.join("permissions_test.kdl"); - let (plugin_thread_sender, screen_receiver, mut teardown) = + let (plugin_thread_sender, screen_receiver, teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); @@ -4715,7 +4653,6 @@ pub fn focus_plugin_pane_plugin_command() { Some(client_id), Event::Key(Key::Ctrl('u')), // this triggers the enent in the fixture plugin )])); - std::thread::sleep(std::time::Duration::from_millis(100)); screen_thread.join().unwrap(); // this might take a while if the cache is cold teardown(); let new_tab_event = received_screen_instructions @@ -4740,7 +4677,7 @@ pub fn rename_terminal_pane_plugin_command() { // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); let cache_path = plugin_host_folder.join("permissions_test.kdl"); - let (plugin_thread_sender, screen_receiver, mut teardown) = + let (plugin_thread_sender, screen_receiver, teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); @@ -4784,7 +4721,6 @@ pub fn rename_terminal_pane_plugin_command() { Some(client_id), Event::Key(Key::Ctrl('v')), // this triggers the enent in the fixture plugin )])); - std::thread::sleep(std::time::Duration::from_millis(100)); screen_thread.join().unwrap(); // this might take a while if the cache is cold teardown(); let new_tab_event = received_screen_instructions @@ -4809,7 +4745,7 @@ pub fn rename_plugin_pane_plugin_command() { // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); let cache_path = plugin_host_folder.join("permissions_test.kdl"); - let (plugin_thread_sender, screen_receiver, mut teardown) = + let (plugin_thread_sender, screen_receiver, teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); @@ -4853,7 +4789,6 @@ pub fn rename_plugin_pane_plugin_command() { Some(client_id), Event::Key(Key::Ctrl('w')), // this triggers the enent in the fixture plugin )])); - std::thread::sleep(std::time::Duration::from_millis(100)); screen_thread.join().unwrap(); // this might take a while if the cache is cold teardown(); let new_tab_event = received_screen_instructions @@ -4878,7 +4813,7 @@ pub fn rename_tab_plugin_command() { // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); let cache_path = plugin_host_folder.join("permissions_test.kdl"); - let (plugin_thread_sender, screen_receiver, mut teardown) = + let (plugin_thread_sender, screen_receiver, teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); @@ -4922,7 +4857,6 @@ pub fn rename_tab_plugin_command() { Some(client_id), Event::Key(Key::Ctrl('x')), // this triggers the enent in the fixture plugin )])); - std::thread::sleep(std::time::Duration::from_millis(100)); screen_thread.join().unwrap(); // this might take a while if the cache is cold teardown(); let new_tab_event = received_screen_instructions @@ -4947,7 +4881,7 @@ pub fn send_configuration_to_plugins() { // destructor removes the directory let plugin_host_folder = PathBuf::from(temp_folder.path()); let cache_path = plugin_host_folder.join("permissions_test.kdl"); - let (plugin_thread_sender, screen_receiver, mut teardown) = + let (plugin_thread_sender, screen_receiver, teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); @@ -5000,7 +4934,6 @@ pub fn send_configuration_to_plugins() { Some(client_id), Event::Key(Key::Ctrl('z')), // this triggers the enent in the fixture plugin )])); - std::thread::sleep(std::time::Duration::from_millis(100)); screen_thread.join().unwrap(); // this might take a while if the cache is cold teardown(); // here we make sure we received a rename_tab event with the title being the stringified @@ -5026,7 +4959,7 @@ pub fn send_configuration_to_plugins() { pub fn request_plugin_permissions() { let temp_folder = tempdir().unwrap(); let plugin_host_folder = PathBuf::from(temp_folder.path()); - let (plugin_thread_sender, screen_receiver, mut teardown) = + let (plugin_thread_sender, screen_receiver, teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); @@ -5066,7 +4999,6 @@ pub fn request_plugin_permissions() { Some(client_id), Event::Key(Key::Ctrl('1')), // this triggers the enent in the fixture plugin )])); - std::thread::sleep(std::time::Duration::from_millis(100)); screen_thread.join().unwrap(); // this might take a while if the cache is cold teardown(); let new_tab_event = received_screen_instructions @@ -5091,7 +5023,7 @@ pub fn granted_permission_request_result() { let plugin_host_folder = PathBuf::from(temp_folder.path()); let cache_path = plugin_host_folder.join("permissions_test.kdl"); - let (plugin_thread_sender, screen_receiver, mut teardown) = + let (plugin_thread_sender, screen_receiver, teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); @@ -5179,7 +5111,7 @@ pub fn denied_permission_request_result() { let plugin_host_folder = PathBuf::from(temp_folder.path()); let cache_path = plugin_host_folder.join("permissions_test.kdl"); - let (plugin_thread_sender, screen_receiver, mut teardown) = + let (plugin_thread_sender, screen_receiver, teardown) = create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); diff --git a/zellij-server/src/plugins/wasm_bridge.rs b/zellij-server/src/plugins/wasm_bridge.rs index 7e11d831..570d1bf7 100644 --- a/zellij-server/src/plugins/wasm_bridge.rs +++ b/zellij-server/src/plugins/wasm_bridge.rs @@ -11,7 +11,8 @@ use std::{ str::FromStr, sync::{Arc, Mutex}, }; -use wasmer::{Instance, Module, Store, Value}; +use wasmer::{Module, Store, Value}; +use zellij_utils::async_channel::Sender; use zellij_utils::async_std::task::{self, JoinHandle}; use zellij_utils::data::{PermissionStatus, PermissionType}; use zellij_utils::input::permission::PermissionCache; @@ -40,7 +41,7 @@ pub struct WasmBridge { connected_clients: Arc>>, plugins: PluginsConfig, senders: ThreadSenders, - store: Store, + store: Arc>, plugin_dir: PathBuf, plugin_cache: Arc>>, plugin_map: Arc>, @@ -66,7 +67,7 @@ impl WasmBridge { pub fn new( plugins: PluginsConfig, senders: ThreadSenders, - store: Store, + store: Arc>, plugin_dir: PathBuf, path_to_default_shell: PathBuf, zellij_cwd: PathBuf, @@ -342,6 +343,7 @@ impl WasmBridge { pid: PluginId, new_columns: usize, new_rows: usize, + shutdown_sender: Sender<()>, ) -> Result<()> { let err_context = move || format!("failed to resize plugin {pid}"); @@ -369,22 +371,29 @@ impl WasmBridge { let running_plugin = running_plugin.clone(); let plugin_id = plugin_id; let client_id = client_id; + let _s = shutdown_sender.clone(); async move { let mut running_plugin = running_plugin.lock().unwrap(); + let _s = _s; // guard to allow the task to complete before cleanup/shutdown if running_plugin.apply_event_id(AtomicEvent::Resize, event_id) { running_plugin.rows = new_rows; running_plugin.columns = new_columns; + let rendered_bytes = running_plugin .instance + .clone() .exports .get_function("render") .map_err(anyError::new) .and_then(|render| { render - .call(&[ - Value::I32(running_plugin.rows as i32), - Value::I32(running_plugin.columns as i32), - ]) + .call( + &mut running_plugin.store, + &[ + Value::I32(new_rows as i32), + Value::I32(new_columns as i32), + ], + ) .map_err(anyError::new) }) .and_then(|_| wasi_read_string(&running_plugin.plugin_env.wasi_env)) @@ -420,6 +429,7 @@ impl WasmBridge { pub fn update_plugins( &mut self, mut updates: Vec<(Option, Option, Event)>, + shutdown_sender: Sender<()>, ) -> Result<()> { let err_context = || "failed to update plugin state".to_string(); @@ -459,17 +469,16 @@ impl WasmBridge { let event = event.clone(); let plugin_id = *plugin_id; let client_id = *client_id; + let _s = shutdown_sender.clone(); async move { - let running_plugin = running_plugin.lock().unwrap(); + let mut running_plugin = running_plugin.lock().unwrap(); let mut plugin_bytes = vec![]; + let _s = _s; // guard to allow the task to complete before cleanup/shutdown match apply_event_to_plugin( plugin_id, client_id, - &running_plugin.instance, - &running_plugin.plugin_env, + &mut running_plugin, &event, - running_plugin.rows, - running_plugin.columns, &mut plugin_bytes, ) { Ok(()) => { @@ -503,10 +512,14 @@ impl WasmBridge { } Ok(()) } - pub fn apply_cached_events(&mut self, plugin_ids: Vec) -> Result<()> { + pub fn apply_cached_events( + &mut self, + plugin_ids: Vec, + shutdown_sender: Sender<()>, + ) -> Result<()> { let mut applied_plugin_paths = HashSet::new(); for plugin_id in plugin_ids { - self.apply_cached_events_and_resizes_for_plugin(plugin_id)?; + self.apply_cached_events_and_resizes_for_plugin(plugin_id, shutdown_sender.clone())?; if let Some(run_plugin) = self.run_plugin_of_plugin_id(plugin_id) { applied_plugin_paths.insert(run_plugin.clone()); } @@ -544,7 +557,11 @@ impl WasmBridge { .find(|((p_id, _run_plugin), _)| p_id == &plugin_id) .map(|((_p_id, run_plugin), _)| run_plugin) } - fn apply_cached_events_and_resizes_for_plugin(&mut self, plugin_id: PluginId) -> Result<()> { + fn apply_cached_events_and_resizes_for_plugin( + &mut self, + plugin_id: PluginId, + shutdown_sender: Sender<()>, + ) -> Result<()> { let err_context = || format!("Failed to apply cached events to plugin"); if let Some(events) = self.cached_events_for_pending_plugins.remove(&plugin_id) { let all_connected_clients: Vec = self @@ -572,17 +589,16 @@ impl WasmBridge { let senders = self.senders.clone(); let running_plugin = running_plugin.clone(); let client_id = *client_id; + let _s = shutdown_sender.clone(); async move { - let running_plugin = running_plugin.lock().unwrap(); + let mut running_plugin = running_plugin.lock().unwrap(); let mut plugin_bytes = vec![]; + let _s = _s; // guard to allow the task to complete before cleanup/shutdown match apply_event_to_plugin( plugin_id, client_id, - &running_plugin.instance, - &running_plugin.plugin_env, + &mut running_plugin, &event, - running_plugin.rows, - running_plugin.columns, &mut plugin_bytes, ) { Ok(()) => { @@ -601,7 +617,7 @@ impl WasmBridge { } } if let Some((rows, columns)) = self.cached_resizes_for_pending_plugins.remove(&plugin_id) { - self.resize_plugin(plugin_id, columns, rows)?; + self.resize_plugin(plugin_id, columns, rows, shutdown_sender.clone())?; } self.apply_cached_worker_messages(plugin_id)?; Ok(()) @@ -716,35 +732,34 @@ impl WasmBridge { status: PermissionStatus, cache_path: Option, ) -> Result<()> { - if let Some(running_plugin) = self + let err_context = || format!("Failed to write plugin permission {plugin_id}"); + + let running_plugin = self .plugin_map .lock() .unwrap() .get_running_plugin(plugin_id, client_id) - { - let err_context = || format!("Failed to write plugin permission {plugin_id}"); + .ok_or_else(|| anyhow!("Failed to get running plugin"))?; - let mut running_plugin = running_plugin.lock().unwrap(); - let permissions = if status == PermissionStatus::Granted { - permissions - } else { - vec![] - }; + let mut running_plugin = running_plugin.lock().unwrap(); - running_plugin - .plugin_env - .set_permissions(HashSet::from_iter(permissions.clone())); + let permissions = if status == PermissionStatus::Granted { + permissions + } else { + vec![] + }; - let mut permission_cache = PermissionCache::from_path_or_default(cache_path); - permission_cache.cache( - running_plugin.plugin_env.plugin.location.to_string(), - permissions, - ); + running_plugin + .plugin_env + .set_permissions(HashSet::from_iter(permissions.clone())); - permission_cache.write_to_file().with_context(err_context)?; - } + let mut permission_cache = PermissionCache::from_path_or_default(cache_path); + permission_cache.cache( + running_plugin.plugin_env.plugin.location.to_string(), + permissions, + ); - Ok(()) + permission_cache.write_to_file().with_context(err_context) } } @@ -801,13 +816,15 @@ fn check_event_permission( pub fn apply_event_to_plugin( plugin_id: PluginId, client_id: ClientId, - instance: &Instance, - plugin_env: &PluginEnv, + running_plugin: &mut RunningPlugin, event: &Event, - rows: usize, - columns: usize, plugin_bytes: &mut Vec<(PluginId, ClientId, Vec)>, ) -> Result<()> { + let instance = &running_plugin.instance; + let plugin_env = &running_plugin.plugin_env; + let rows = running_plugin.rows; + let columns = running_plugin.columns; + let err_context = || format!("Failed to apply event to plugin {plugin_id}"); match check_event_permission(plugin_env, event) { (PermissionStatus::Granted, _) => { @@ -821,7 +838,9 @@ pub fn apply_event_to_plugin( .with_context(err_context)?; wasi_write_object(&plugin_env.wasi_env, &protobuf_event.encode_to_vec()) .with_context(err_context)?; - let update_return = update.call(&[]).with_context(err_context)?; + let update_return = update + .call(&mut running_plugin.store, &[]) + .with_context(err_context)?; let mut should_render = match update_return.get(0) { Some(Value::I32(n)) => *n == 1, _ => false, @@ -838,7 +857,10 @@ pub fn apply_event_to_plugin( .map_err(anyError::new) .and_then(|render| { render - .call(&[Value::I32(rows as i32), Value::I32(columns as i32)]) + .call( + &mut running_plugin.store, + &[Value::I32(rows as i32), Value::I32(columns as i32)], + ) .map_err(anyError::new) }) .and_then(|_| wasi_read_string(&plugin_env.wasi_env)) diff --git a/zellij-server/src/plugins/zellij_exports.rs b/zellij-server/src/plugins/zellij_exports.rs index 901f66b2..1608df8f 100644 --- a/zellij-server/src/plugins/zellij_exports.rs +++ b/zellij-server/src/plugins/zellij_exports.rs @@ -14,7 +14,7 @@ use std::{ thread, time::{Duration, Instant}, }; -use wasmer::{imports, Function, ImportObject, Store, WasmerEnv}; +use wasmer::{imports, AsStoreMut, Function, FunctionEnv, FunctionEnvMut, Imports}; use wasmer_wasi::WasiEnv; use zellij_utils::data::{ CommandType, ConnectToSession, PermissionStatus, PermissionType, PluginPermission, @@ -64,20 +64,21 @@ macro_rules! apply_action { } pub fn zellij_exports( - store: &Store, + store: &mut impl AsStoreMut, plugin_env: &PluginEnv, subscriptions: &Arc>, -) -> ImportObject { +) -> Imports { + let function_env = FunctionEnv::new(store, ForeignFunctionEnv::new(plugin_env, subscriptions)); imports! { "zellij" => { "host_run_plugin_command" => { - Function::new_native_with_env(store, ForeignFunctionEnv::new(plugin_env, subscriptions), host_run_plugin_command) + Function::new_typed_with_env(store, &function_env, host_run_plugin_command) } } } } -#[derive(WasmerEnv, Clone)] +#[derive(Clone)] pub struct ForeignFunctionEnv { pub plugin_env: PluginEnv, pub subscriptions: Arc>, @@ -92,7 +93,8 @@ impl ForeignFunctionEnv { } } -fn host_run_plugin_command(env: &ForeignFunctionEnv) { +fn host_run_plugin_command(env: FunctionEnvMut) { + let env = env.data(); let err_context = || format!("failed to run plugin command {}", env.plugin_env.name()); wasi_read_bytes(&env.plugin_env.wasi_env) .and_then(|bytes| { @@ -1102,17 +1104,13 @@ pub fn wasi_read_string(wasi_env: &WasiEnv) -> Result { let mut buf = vec![]; wasi_env .state() - .fs - .stdout_mut() + .stdout() .map_err(anyError::new) - .and_then(|stdout| { - stdout - .as_mut() - .ok_or(anyhow!("failed to get mutable reference to stdout")) - }) - .and_then(|wasi_file| wasi_file.read_to_end(&mut buf).map_err(anyError::new)) + .and_then(|stdout| stdout.ok_or(anyhow!("failed to get mutable reference to stdout"))) + .and_then(|mut wasi_file| wasi_file.read_to_end(&mut buf).map_err(anyError::new)) .with_context(err_context)?; let buf = String::from_utf8_lossy(&buf); + // https://stackoverflow.com/questions/66450942/in-rust-is-there-a-way-to-make-literal-newlines-in-r-using-windows-c Ok(buf.replace("\n", "\n\r")) } @@ -1120,15 +1118,10 @@ pub fn wasi_read_string(wasi_env: &WasiEnv) -> Result { pub fn wasi_write_string(wasi_env: &WasiEnv, buf: &str) -> Result<()> { wasi_env .state() - .fs - .stdin_mut() + .stdin() .map_err(anyError::new) - .and_then(|stdin| { - stdin - .as_mut() - .ok_or(anyhow!("failed to get mutable reference to stdin")) - }) - .and_then(|stdin| writeln!(stdin, "{}\r", buf).map_err(anyError::new)) + .and_then(|stdin| stdin.ok_or(anyhow!("failed to get mutable reference to stdin"))) + .and_then(|mut stdin| writeln!(stdin, "{}\r", buf).map_err(anyError::new)) .with_context(|| format!("failed to write string to WASI env '{wasi_env:?}'")) }