diff --git a/CHANGELOG.md b/CHANGELOG.md index 4bf51f638..6549c4ab4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,238 +6,288 @@ Looking for changes that affect our C API? See the [C API Changelog](lib/c-api/CHANGELOG.md). - + ## **Unreleased** +## 3.1.0 - 12/12/2022 + +## Added + + - [#3403](https://github.com/wasmerio/wasmer/pull/3403) Add wasm_importtype_copy to C API + +## Changed + + - [#3416](https://github.com/wasmerio/wasmer/pull/3416) Download and install packages via .tar.gz URLs and improve installation error message + - [#3402](https://github.com/wasmerio/wasmer/pull/3402) Do not run first command of wapm file and print all commands instead + - [#3400](https://github.com/wasmerio/wasmer/pull/3400) Use the wasm_bindgen_downcast crate for downcasting JsValues + - [#3363](https://github.com/wasmerio/wasmer/pull/3363) Store Used CpuFeature in Artifact instead of Present CpuFeatures for Singlepass + - [#3378](https://github.com/wasmerio/wasmer/pull/3378) Introduced EngineRef and AsEngineRef trait + - [#3386](https://github.com/wasmerio/wasmer/pull/3386) Restore Support For All Wasi Clock Types + - [#3153](https://github.com/wasmerio/wasmer/pull/3153) SharedMemory & Atomics + +## Fixed + + - [#3415](https://github.com/wasmerio/wasmer/pull/3415) Fix singlepass for Aarch64 + - [#3395](https://github.com/wasmerio/wasmer/pull/3395) Fix create-exe to be able to cross-compile on Windows + - [#3396](https://github.com/wasmerio/wasmer/pull/3396) Fix build doc and minimum-sys build + ## 3.0.2 - 25/11/2022 ## Added - [#3364](https://github.com/wasmerio/wasmer/pull/3364) Added the actual LZCNT / TZCNT implementation - - [#3361](https://github.com/wasmerio/wasmer/pull/3361) Give users feedback when they are running "wasmer add ..." ## Changed + - [#3365](https://github.com/wasmerio/wasmer/pull/3365) Improve FreeBSD support - [#3368](https://github.com/wasmerio/wasmer/pull/3368) Remove wasi conditional compilation from wasmer-registry - [#3367](https://github.com/wasmerio/wasmer/pull/3367) Change LLVM detection in Makefile - - [#3365](https://github.com/wasmerio/wasmer/pull/3365) Improve FreeBSD support - - [#3360](https://github.com/wasmerio/wasmer/pull/3360) Introduce a "wasmer_registry::queries" module with all GraphQL queries ## Fixed - - [#3371](https://github.com/wasmerio/wasmer/pull/3371) Fix cargo binstall - [#3370](https://github.com/wasmerio/wasmer/pull/3370) Fix wasmer run not interpreting URLs correctly + display fixes + - [#3371](https://github.com/wasmerio/wasmer/pull/3371) Fix cargo binstall ## 3.0.1 - 23/11/2022 ## Added + - [#3361](https://github.com/wasmerio/wasmer/pull/3361) Give users feedback when they are running "wasmer add ..." ## Changed + - [#3360](https://github.com/wasmerio/wasmer/pull/3360) Introduce a "wasmer_registry::queries" module with all GraphQL queries + - [#3355](https://github.com/wasmerio/wasmer/pull/3355) Fetch the pirita download URL - [#3344](https://github.com/wasmerio/wasmer/pull/3344) Revert #3145 + - [#3302](https://github.com/wasmerio/wasmer/pull/3302) Some Refactor of Singlepass compiler to have better error and cpu features handling + - [#3296](https://github.com/wasmerio/wasmer/pull/3296) Use the right collection when parsing type section + - [#3292](https://github.com/wasmerio/wasmer/pull/3292) Precompute offsets in VMOffsets + - [#3290](https://github.com/wasmerio/wasmer/pull/3290) Limit the use of clone when handling Compilation object + - [#3316](https://github.com/wasmerio/wasmer/pull/3316) Implement wasmer whoami - [#3341](https://github.com/wasmerio/wasmer/pull/3341) Update CHANGELOG.md ## Fixed - [#3342](https://github.com/wasmerio/wasmer/pull/3342) Fixes for 3.0.0 release - - ## 3.0.0 - 20/11/2022 ## Added - - [#3338](https://github.com/wasmerio/wasmer/3338) Re-add codecov to get coverage reports - - [#3337](https://github.com/wasmerio/wasmer/3337) Add automation script to automate deploying releases on GitHub + - [#3339](https://github.com/wasmerio/wasmer/pull/3339) Fixes for wasmer login / wasmer add + - [#3337](https://github.com/wasmerio/wasmer/pull/3337) Add automation script to automate deploying releases on GitHub + - [#3338](https://github.com/wasmerio/wasmer/pull/3338) Re-add codecov to get coverage reports ## Changed + - [#3295](https://github.com/wasmerio/wasmer/pull/3295) Implement wasmer run {url} ## Fixed - - [#3339](https://github.com/wasmerio/wasmer/3339) Fixes for wasmer login / wasmer add - ## 3.0.0-rc.3 - 2022/11/18 ## Added -- [#3314](https://github.com/wasmerio/wasmer/pull/3314) Add windows-gnu workflow -- [#3317](https://github.com/wasmerio/wasmer/pull/3317) Add a `wasmer add` command for adding bindings to a WAPM package -- [#3297](https://github.com/wasmerio/wasmer/pull/3297) Implement wasmer login -- [#3311](https://github.com/wasmerio/wasmer/pull/3311) Export `Module::IoCompileError` + - [#3314](https://github.com/wasmerio/wasmer/pull/3314) Add windows-gnu workflow ## Changed -- [#3319](https://github.com/wasmerio/wasmer/pull/3319) Disable 'Test integration CLI' on CI for the Windows platform as it's not working at all -- [#3318](https://github.com/wasmerio/wasmer/pull/3318) Bump the MSRV to 1.63 -- [#3293](https://github.com/wasmerio/wasmer/pull/3293) Removed call to to_vec() on assembler.finalise() -- [#3288](https://github.com/wasmerio/wasmer/pull/3288) Rollback all the TARGET_DIR changes -- [#3284](https://github.com/wasmerio/wasmer/pull/3284) Makefile now handle TARGET_DIR env. var. for build too -- [#3276](https://github.com/wasmerio/wasmer/pull/3276) Remove unnecessary checks to test internet connection -- [#3275](https://github.com/wasmerio/wasmer/pull/3275) Disable printing "local package ... not found" in release mode -- [#3273](https://github.com/wasmerio/wasmer/pull/3273) Undo Makefile commit + - [#3317](https://github.com/wasmerio/wasmer/pull/3317) Port "wapm install" to Wasmer + - [#3318](https://github.com/wasmerio/wasmer/pull/3318) Bump the MSRV to 1.63 + - [#3319](https://github.com/wasmerio/wasmer/pull/3319) Disable 'Test integration CLI' on CI for the Windows platform as it's not working at all + - [#3297](https://github.com/wasmerio/wasmer/pull/3297) Implement wasmer login + - [#3311](https://github.com/wasmerio/wasmer/pull/3311) Export Module::IoCompileError as it's an error returned by an exported function + - [#2800](https://github.com/wasmerio/wasmer/pull/2800) RISC-V support + - [#3293](https://github.com/wasmerio/wasmer/pull/3293) Removed call to to_vec() on assembler.finalise() + - [#3288](https://github.com/wasmerio/wasmer/pull/3288) Rollback all the TARGET_DIR changes + - [#3284](https://github.com/wasmerio/wasmer/pull/3284) Makefile now handle TARGET_DIR env. var. for build too + - [#3276](https://github.com/wasmerio/wasmer/pull/3276) Remove unnecessary checks to test internet connection + - [#3266](https://github.com/wasmerio/wasmer/pull/3266) Return ENotCapable error when accessing unknown files on root (for #3263 and #3264) + - [#3275](https://github.com/wasmerio/wasmer/pull/3275) Disable printing "local package ... not found" in release mode + - [#3273](https://github.com/wasmerio/wasmer/pull/3273) Undo Makefile commit ## Fixed -- [#3299](https://github.com/wasmerio/wasmer/pull/3299) Fix "create-exe" for windows-x86_64 target -- [#3294](https://github.com/wasmerio/wasmer/pull/3294) Fix test sys yaml syntax -- [#3287](https://github.com/wasmerio/wasmer/pull/3287) Fix Makefile with TARGET_DIR end with release folder, removing it -- [#3286](https://github.com/wasmerio/wasmer/pull/3286) Fix Makefile with TARGET_DIR end with release folder -- [#3285](https://github.com/wasmerio/wasmer/pull/3285) Fix CI to setup TARGET_DIR to target/release directly -- [#3277](https://github.com/wasmerio/wasmer/pull/3277) Fix red CI on master + - [#3299](https://github.com/wasmerio/wasmer/pull/3299) Fix "create-exe" for windows-x86_64 target + - [#3294](https://github.com/wasmerio/wasmer/pull/3294) Fix test sys yaml syntax + - [#3287](https://github.com/wasmerio/wasmer/pull/3287) Fix Makefile with TARGET_DIR end with release folder, removing it + - [#3286](https://github.com/wasmerio/wasmer/pull/3286) Fix Makefile with TARGET_DIR end with release folder + - [#3285](https://github.com/wasmerio/wasmer/pull/3285) Fix CI to setup TARGET_DIR to target/release directly + - [#3277](https://github.com/wasmerio/wasmer/pull/3277) Fix red CI on master + ## 3.0.0-rc.2 - 2022/11/02 +## Added + + +## Changed + + - [#3258](https://github.com/wasmerio/wasmer/pull/3258) Migrate pirita / native executables feature from wasmer-private + ## Fixed -- [#3268](https://github.com/wasmerio/wasmer/pulls/3268) Fix fd_right nightly test to avoid foo.txt file leftover -- [#3260](https://github.com/wasmerio/wasmer/pulls/3260) Fix bug in wasmer run -- [#3257](https://github.com/wasmerio/wasmer/pulls/3257) Fix linux-aarch64 build + + - [#3268](https://github.com/wasmerio/wasmer/pull/3268) Fix fd_right nightly test to avoid foo.txt file leftover + - [#3260](https://github.com/wasmerio/wasmer/pull/3260) Fix bug in wasmer run + - [#3257](https://github.com/wasmerio/wasmer/pull/3257) Fix linux-aarch64 build + ## 3.0.0-rc.1 - 2022/10/25 ## Added -- [#3215](https://github.com/wasmerio/wasmer/pull/3215) Update wasmer --version logic, integrate wapm-cli -- [#3218](https://github.com/wasmerio/wasmer/pull/3218) Seal `HostFunctionKind` -- [#3222](https://github.com/wasmerio/wasmer/pull/3222) Add function to retrieve function name from wasm_frame_t + - [#3222](https://github.com/wasmerio/wasmer/pull/3222) Add function to retrieve function name from wasm_frame_t + - [#3240](https://github.com/wasmerio/wasmer/pull/3240) Fix filesystem rights on WASI, add integration test for file permissions + - [#3238](https://github.com/wasmerio/wasmer/pull/3238) Fixed main README ocaml homepage link and added ocaml in other language README + - [#3145](https://github.com/wasmerio/wasmer/pull/3145) C-API: add functions to overwrite stdin / stdout / stderr handlers ## Changed -- [#3248](https://github.com/wasmerio/wasmer/pull/3248) Move loupe CHANGELOG entry from 2.3.0 to 3.x -- [#3230](https://github.com/wasmerio/wasmer/pull/3230) Remove test if dest file exist on path_rename wasi syscall (for #3228) -- [#3223](https://github.com/wasmerio/wasmer/pull/3223) Delete lib/wasi-types-generated directory + - [#3215](https://github.com/wasmerio/wasmer/pull/3215) Update wasmer --version logic, integrate wapm-cli + - [#3248](https://github.com/wasmerio/wasmer/pull/3248) Move loupe CHANGELOG entry from 2.3.0 to 3.x + - [#3230](https://github.com/wasmerio/wasmer/pull/3230) Remove test if dest file exist on path_rename wasi syscall (for #3228) + - [#3061](https://github.com/wasmerio/wasmer/pull/3061) Removed trailing zero in WASI::fd_prestat_dir_name name return (for #3025) + - [#3223](https://github.com/wasmerio/wasmer/pull/3223) Delete lib/wasi-types-generated directory + - [#3178](https://github.com/wasmerio/wasmer/pull/3178) Feat enhanced tinytunable test + - [#3177](https://github.com/wasmerio/wasmer/pull/3177) Auto-generate wasi-types from .wit files + - [#3218](https://github.com/wasmerio/wasmer/pull/3218) Seal `HostFunctionKind` ## Fixed -- [#3145](https://github.com/wasmerio/wasmer/pull/3145) C-API: add functions to overwrite stdin / stdout / stderr handlers -- [#3240](https://github.com/wasmerio/wasmer/pull/3240) Fix filesystem rights on WASI, add integration test for file permissions -- [#3238](https://github.com/wasmerio/wasmer/pull/3238) Fixed main README ocaml homepage link and added ocaml in other language README -- [#3229](https://github.com/wasmerio/wasmer/pull/3229) Fixed version to nightly-2022-10-09 for the CI build Minimal Wasmer Headless again -- [#3227](https://github.com/wasmerio/wasmer/pull/3227) Fixed version to nightly-2022-10-09 for the CI build Minimal Wasmer Headless -- [#3226](https://github.com/wasmerio/wasmer/pull/3226) Fixed version to nightly-2002-10-09 for the CI build Minimal Wasmer Headless -- [#3221](https://github.com/wasmerio/wasmer/pull/3221) Fix #3197 -- [#3211](https://github.com/wasmerio/wasmer/pull/3211) Fix popcnt for aarch64 -- [#3204](https://github.com/wasmerio/wasmer/pull/3204) Fixed a typo in README -- [#3199](https://github.com/wasmerio/wasmer/pull/3199) Release fixes + - [#3221](https://github.com/wasmerio/wasmer/pull/3221) Fix #3197 + - [#3229](https://github.com/wasmerio/wasmer/pull/3229) Fixed version to nightly-2022-10-09 for the CI build Minimal Wasmer Headless again + - [#3227](https://github.com/wasmerio/wasmer/pull/3227) Fixed version to nightly-2022-10-09 for the CI build Minimal Wasmer Headless + - [#3226](https://github.com/wasmerio/wasmer/pull/3226) Fixed version to nightly-2002-10-09 for the CI build Minimal Wasmer Headless + - [#3211](https://github.com/wasmerio/wasmer/pull/3211) fix popcnt for aarch64 + - [#3204](https://github.com/wasmerio/wasmer/pull/3204) Fixed a typo in README + ## 3.0.0-beta.2 - 2022/09/26 ## Added -- [#3176](https://github.com/wasmerio/wasmer/pull/3176) Add support for `cargo-binstall` -- [#3117](https://github.com/wasmerio/wasmer/pull/3117) Add tests for wasmer-cli create-{exe,obj} commands -- [#3116](https://github.com/wasmerio/wasmer/pull/3116) Multithreading, full networking and RPC for WebAssembly -- [#3101](https://github.com/wasmerio/wasmer/pull/3101) CI/build.yaml: add libwasmer headless in default distribution -- [#3090](https://github.com/wasmerio/wasmer/pull/3090) Added version to the wasmer cli -- [#3089](https://github.com/wasmerio/wasmer/pull/3089) Add wasi_* C-API function changes in migration guide for 3.0.0 + - [#3176](https://github.com/wasmerio/wasmer/pull/3176) Add support for `cargo-binstall` + - [#3141](https://github.com/wasmerio/wasmer/pull/3141) The API breaking changes from future WASIX/Network/Threading addition + - [#3119](https://github.com/wasmerio/wasmer/pull/3119) Added LinearMemory trait + - [#3117](https://github.com/wasmerio/wasmer/pull/3117) Add tests for wasmer-cli create-{exe,obj} commands + - [#3101](https://github.com/wasmerio/wasmer/pull/3101) CI/build.yaml: add libwasmer headless in default distribution + - [#3090](https://github.com/wasmerio/wasmer/pull/3090) Added version to the wasmer cli + - [#3089](https://github.com/wasmerio/wasmer/pull/3089) Add wasi_* C-API function changes in migration guide for 3.0.0 + - [#3076](https://github.com/wasmerio/wasmer/pull/3076) Add support for cross-compiling in create-exe with zig cc WIP + - [#3072](https://github.com/wasmerio/wasmer/pull/3072) Add back `Function::*_with_env(…)` + - [#3048](https://github.com/wasmerio/wasmer/pull/3048) Add cloudcompiler.yaml + - [#3068](https://github.com/wasmerio/wasmer/pull/3068) create-{exe,obj}: add documentations and header file generation for create-obj + - [#3065](https://github.com/wasmerio/wasmer/pull/3065) Added '.' and '..' special folder t WASI fd_readdir return (for #3033) ## Changed -- [#3165](https://github.com/wasmerio/wasmer/pull/3165) Initial port of make test-js-core (port wasmer API to core) -- [#3164](https://github.com/wasmerio/wasmer/pull/3164) Synchronize between -sys and -js tests -- [#3142](https://github.com/wasmerio/wasmer/pull/3142) Bump rust toolchain -- [#3141](https://github.com/wasmerio/wasmer/pull/3141) The API breaking changes from future WASIX/Network/Threading addition -- [#3138](https://github.com/wasmerio/wasmer/pull/3138) Js imports revamp -- [#3134](https://github.com/wasmerio/wasmer/pull/3134) Bring libwasmer-headless.a from 22MiB to 7.2MiB (on my machine) -- [#3132](https://github.com/wasmerio/wasmer/pull/3132) Revert "Lower libwasmer headless size" -- [#3131](https://github.com/wasmerio/wasmer/pull/3131) Update for migration-to-3.0.0 for MemoryView changes -- [#3130](https://github.com/wasmerio/wasmer/pull/3130) Remove panics from Artifact::deserialize -- [#3128](https://github.com/wasmerio/wasmer/pull/3128) scripts/publish.py: validate crates version before publishing -- [#3126](https://github.com/wasmerio/wasmer/pull/3126) scripts/publish.py: replace toposort dependency with python std graphlib module -- [#3123](https://github.com/wasmerio/wasmer/pull/3123) Lower libwasmer headless size -- [#3122](https://github.com/wasmerio/wasmer/pull/3122) Update Cargo.lock dependencies -- [#3119](https://github.com/wasmerio/wasmer/pull/3119) Added LinearMemory trait -- [#3118](https://github.com/wasmerio/wasmer/pull/3118) Refactor Artifact enum into a struct -- [#3114](https://github.com/wasmerio/wasmer/pull/3114) Implemented shared memory for Wasmer in preparation for multithreading -- [#3104](https://github.com/wasmerio/wasmer/pull/3104) Re-enabled ExternRef tests -- [#3103](https://github.com/wasmerio/wasmer/pull/3103) create-exe: prefer libwasmer headless when cross-compiling -- [#3097](https://github.com/wasmerio/wasmer/pull/3097) MemoryView lifetime tied to memory and not StoreRef -- [#3096](https://github.com/wasmerio/wasmer/pull/3096) create-exe: use cached wasmer tarballs for network fetches -- [#3095](https://github.com/wasmerio/wasmer/pull/3095) create-exe: list supported cross-compilation target triples in help … -- [#3083](https://github.com/wasmerio/wasmer/pull/3083) Disable wasm build in build CI + - [#3184](https://github.com/wasmerio/wasmer/pull/3184) Test libwasmer.dll on Windows + - [#3164](https://github.com/wasmerio/wasmer/pull/3164) Synchronize between -sys and -js tests + - [#3165](https://github.com/wasmerio/wasmer/pull/3165) Initial port of make test-js-core (port wasmer API to core) + - [#3138](https://github.com/wasmerio/wasmer/pull/3138) Js imports revamp + - [#3142](https://github.com/wasmerio/wasmer/pull/3142) Bump rust toolchain + - [#3116](https://github.com/wasmerio/wasmer/pull/3116) Multithreading, full networking and RPC for WebAssembly + - [#3130](https://github.com/wasmerio/wasmer/pull/3130) Remove panics from Artifact::deserialize + - [#3134](https://github.com/wasmerio/wasmer/pull/3134) Bring libwasmer-headless.a from 22MiB to 7.2MiB (on my machine) + - [#3131](https://github.com/wasmerio/wasmer/pull/3131) Update for migration-to-3.0.0 for MemoryView changes + - [#3123](https://github.com/wasmerio/wasmer/pull/3123) Lower libwasmer headless size + - [#3132](https://github.com/wasmerio/wasmer/pull/3132) Revert "Lower libwasmer headless size" + - [#3128](https://github.com/wasmerio/wasmer/pull/3128) scripts/publish.py: validate crates version before publishing + - [#3126](https://github.com/wasmerio/wasmer/pull/3126) scripts/publish.py: replace toposort dependency with python std graphlib module + - [#3122](https://github.com/wasmerio/wasmer/pull/3122) Update Cargo.lock dependencies + - [#3118](https://github.com/wasmerio/wasmer/pull/3118) Refactor Artifact enum into a struct + - [#3114](https://github.com/wasmerio/wasmer/pull/3114) Implemented shared memory for Wasmer in preparation for multithreading + - [#3104](https://github.com/wasmerio/wasmer/pull/3104) Re-enabled ExternRef tests + - [#3103](https://github.com/wasmerio/wasmer/pull/3103) create-exe: prefer libwasmer headless when cross-compiling + - [#3097](https://github.com/wasmerio/wasmer/pull/3097) MemoryView lifetime tied to memory and not StoreRef + - [#3095](https://github.com/wasmerio/wasmer/pull/3095) create-exe: list supported cross-compilation target triples in help … + - [#3096](https://github.com/wasmerio/wasmer/pull/3096) create-exe: use cached wasmer tarballs for network fetches + - [#3083](https://github.com/wasmerio/wasmer/pull/3083) Disable wasm build in build CI + - [#3081](https://github.com/wasmerio/wasmer/pull/3081) 3.0.0-beta release + - [#3079](https://github.com/wasmerio/wasmer/pull/3079) Migrate to clap from structopt + - [#3075](https://github.com/wasmerio/wasmer/pull/3075) Remove __wbindgen_thread_id + - [#3074](https://github.com/wasmerio/wasmer/pull/3074) Update chrono to 0.4.20, avoiding RUSTSEC-2020-0159 + - [#3070](https://github.com/wasmerio/wasmer/pull/3070) wasmer-cli: Allow create-exe to receive a static object as input + - [#3069](https://github.com/wasmerio/wasmer/pull/3069) Remove native feature entry from docs.rs metadata + - [#3057](https://github.com/wasmerio/wasmer/pull/3057) wasmer-cli: create-obj command + - [#3060](https://github.com/wasmerio/wasmer/pull/3060) CI: Unset rustup override after usage instead of setting it to stable ## Fixed -- [#3185](https://github.com/wasmerio/wasmer/pull/3185) Fix `wasmer compile` command for non-x86 target -- [#3184](https://github.com/wasmerio/wasmer/pull/3184) Fix windows build -- [#3137](https://github.com/wasmerio/wasmer/pull/3137) Fix cache path not being present during installation of cross-tarball -- [#3129](https://github.com/wasmerio/wasmer/pull/3129) Fix differences between -sys and -js API -- [#3115](https://github.com/wasmerio/wasmer/pull/3115) Fix static object signature deserialization -- [#3093](https://github.com/wasmerio/wasmer/pull/3093) Fixed a potential issue when renaming a file -- [#3088](https://github.com/wasmerio/wasmer/pull/3088) Fixed an issue when renaming a file from a preopened dir directly (for 3084) + - [#3192](https://github.com/wasmerio/wasmer/pull/3192) fix the typos + - [#3185](https://github.com/wasmerio/wasmer/pull/3185) Fix `wasmer compile` command for non-x86 target + - [#3129](https://github.com/wasmerio/wasmer/pull/3129) Fix differences between -sys and -js API + - [#3137](https://github.com/wasmerio/wasmer/pull/3137) Fix cache path not being present during installation of cross-tarball + - [#3115](https://github.com/wasmerio/wasmer/pull/3115) Fix static object signature deserialization + - [#3093](https://github.com/wasmerio/wasmer/pull/3093) Fixed a potential issue when renaming a file + - [#3088](https://github.com/wasmerio/wasmer/pull/3088) Fixed an issue when renaming a file from a preopened dir directly (for 3084) + - [#3078](https://github.com/wasmerio/wasmer/pull/3078) Fix errors from "make lint" + - [#3052](https://github.com/wasmerio/wasmer/pull/3052) Fixed a memory corruption issue with JS memory operations that were r… + - [#3058](https://github.com/wasmerio/wasmer/pull/3058) Fix trap tracking -## 3.0.0-beta - 2022/08/08 - -### Added -- [#3076](https://github.com/wasmerio/wasmer/pull/3076) Add support for cross-compiling in create-exe with zig cc - -### Changed -- [#3079](https://github.com/wasmerio/wasmer/pull/3079) Migrate CLI tools to `clap` from `structopt` -- [#3048](https://github.com/wasmerio/wasmer/pull/3048) Automatically publish wasmer as "cloudcompiler" package to wapm.dev on every release -- [#3075](https://github.com/wasmerio/wasmer/pull/3075) Remove __wbindgen_thread_id -- [#3072](https://github.com/wasmerio/wasmer/pull/3072) Add back `Function::*_with_env(…)` functions - -### Fixed ## 3.0.0-alpha.4 - 2022/07/28 -### Added -- [#3035](https://github.com/wasmerio/wasmer/pull/3035) Added a simple "divide by zero" wast test, for #1899, as the trap information are correctly tracked on singlepass now -- [#3021](https://github.com/wasmerio/wasmer/pull/3021) Add back missing Aarch64 relocations (needed for llvm compiler) -- [#3008](https://github.com/wasmerio/wasmer/pull/3008) Add a new cargo public-api CI check -- [#2941](https://github.com/wasmerio/wasmer/pull/2941) Implementation of WASIX and a fully networking for Web Assembly -- [#2952](https://github.com/wasmerio/wasmer/pull/2952) CI: add make build-wasmer-wasm test -- [#2982](https://github.com/wasmerio/wasmer/pull/2982) Add a rustfmt.toml file to the repository +## Added -### Changed -- [#3047](https://github.com/wasmerio/wasmer/pull/3047) `Store::new` now takes an `impl Into`. -- [#3046](https://github.com/wasmerio/wasmer/pull/3046) Merge Backend into EngineBuilder and refactor feature flags -- [#3039](https://github.com/wasmerio/wasmer/pull/3039) Improved hashing/ids of function envs -- [#3031](https://github.com/wasmerio/wasmer/pull/3031) Update docs/migration_to_3.0.0.md -- [#3030](https://github.com/wasmerio/wasmer/pull/3030) Remove cranelift dependency from wasmer-wasi -- [#3029](https://github.com/wasmerio/wasmer/pull/3029) Removed Artifact, Engine traits. Renamed UniversalArtifact to Artifact, and UniversalEngine to Engine. -- [#3028](https://github.com/wasmerio/wasmer/pull/3028) Rename old variable names from ctx to env (in case of FunctionEnv usage) and from ctx to store in case of store usage -- [#3023](https://github.com/wasmerio/wasmer/pull/3023) Changed CI "rust install" action to dtolnay one -- [#3013](https://github.com/wasmerio/wasmer/pull/3013) Refactor Context API -- [#3003](https://github.com/wasmerio/wasmer/pull/3003) Remove RuntimeError::raise from public API -- [#3000](https://github.com/wasmerio/wasmer/pull/3001) Allow debugging of EXC_BAD_INSTRUCTION on macOS -- [#2999](https://github.com/wasmerio/wasmer/pull/2999) Allow `--invoke` CLI option for Emscripten files without a `main` function -- [#2996](https://github.com/wasmerio/wasmer/pull/2996) Migrated all examples to new Context API -- [#2946](https://github.com/wasmerio/wasmer/pull/2946) Remove dylib,staticlib engines in favor of a single Universal engine -- [#2949](https://github.com/wasmerio/wasmer/pull/2949) Switch back to using custom LLVM builds on CI -- [#2892](https://github.com/wasmerio/wasmer/pull/2892) Renamed `get_native_function` to `get_typed_function`, marked former as deprecated. -- [#2976](https://github.com/wasmerio/wasmer/pull/2976) Upgrade enumset minimum version to one that compiles -- [#2974](https://github.com/wasmerio/wasmer/pull/2974) Context api tests -- [#2973](https://github.com/wasmerio/wasmer/pull/2973) Port C API to new Context API -- [#2969](https://github.com/wasmerio/wasmer/pull/2969) Port JS API to new Context API -- [#2966](https://github.com/wasmerio/wasmer/pull/2966) Singlepass nopanic #2966 -- [#2957](https://github.com/wasmerio/wasmer/pull/2957) Enable multi-value handling in Singlepass compiler -- [#2954](https://github.com/wasmerio/wasmer/pull/2954) Some fixes to x86_64 Singlepass compiler, when using atomics -- [#2953](https://github.com/wasmerio/wasmer/pull/2953) Makefile: add check target -- [#2950](https://github.com/wasmerio/wasmer/pull/2950) compiler-cranelift: Fix typo in enum variant -- [#2947](https://github.com/wasmerio/wasmer/pull/2947) Converted the WASI js test into a generic stdio test that works for both sys and js versions of wasmer -- [#2940](https://github.com/wasmerio/wasmer/pull/2940) Merge wasmer3 back to master branch -- [#2939](https://github.com/wasmerio/wasmer/pull/2939) Rename NativeFunc to TypedFunction -- [#2868](https://github.com/wasmerio/wasmer/pull/2868) Removed loupe crate dependency + - [#3035](https://github.com/wasmerio/wasmer/pull/3035) Added a simple divide by zero trap wast test (for #1899) + - [#3008](https://github.com/wasmerio/wasmer/pull/3008) Add check-public-api.yaml workflow + - [#3021](https://github.com/wasmerio/wasmer/pull/3021) Added back some needed relocation for arm64 llvm compiler + - [#2982](https://github.com/wasmerio/wasmer/pull/2982) Add a `rustfmt.toml` file to the repository + - [#2953](https://github.com/wasmerio/wasmer/pull/2953) Makefile: add `check` target + - [#2952](https://github.com/wasmerio/wasmer/pull/2952) CI: add make build-wasmer-wasm test -### Fixed -- [#3045](https://github.com/wasmerio/wasmer/pull/3045) Fixed WASI fd_read syscall when reading multiple iovs and read is partial (for #2904) -- [#3027](https://github.com/wasmerio/wasmer/pull/3027) Fixed some residual doc issues that prevented make package-docs to build -- [#3026](https://github.com/wasmerio/wasmer/pull/3026) test-js.yaml: fix typo -- [#3017](https://github.com/wasmerio/wasmer/pull/3017) Fix typo in README.md -- [#3001](https://github.com/wasmerio/wasmer/pull/3001) Fix context capi ci errors -- [#2997](https://github.com/wasmerio/wasmer/pull/2997) Fix "run --invoke [function]" to behave the same as "run" -- [#2963](https://github.com/wasmerio/wasmer/pull/2963) Remove accidental dependency on libwayland and libxcb in ClI -- [#2942](https://github.com/wasmerio/wasmer/pull/2942) Fix clippy lints. -- [#2943](https://github.com/wasmerio/wasmer/pull/2943) Fix build error on some archs by using c_char instead of i8 -- [#2976](https://github.com/wasmerio/wasmer/pull/2976) Upgrade minimum enumset to one that compiles -- [#2988](https://github.com/wasmerio/wasmer/pull/2988) Have make targets install-capi-lib,install-pkgconfig work without building the wasmer binary -- [#2967](https://github.com/wasmerio/wasmer/pull/2967) Fix singlepass on arm64 that was trying to emit a sub opcode with a constant as destination (for #2959) -- [#2948](https://github.com/wasmerio/wasmer/pull/2948) Fix regression on gen_import_call_trampoline_arm64() -- [#2944](https://github.com/wasmerio/wasmer/pull/2944) Fix duplicate entries in the CHANGELOG +## Changed + + - [#3051](https://github.com/wasmerio/wasmer/pull/3051) Updated Crenelift to v0.86.1 + - [#3038](https://github.com/wasmerio/wasmer/pull/3038) Re-introduce create-exe to wasmer-cli v3.0 + - [#3049](https://github.com/wasmerio/wasmer/pull/3049) Disable traps::trap_display_multi_module test for Windows+singlepass + - [#3047](https://github.com/wasmerio/wasmer/pull/3047) Improved EngineBuilder API + - [#3046](https://github.com/wasmerio/wasmer/pull/3046) Merge Backend into EngineBuilder and refactor feature flags + - [#3039](https://github.com/wasmerio/wasmer/pull/3039) Improved hashing/ids of function envs + - [#3029](https://github.com/wasmerio/wasmer/pull/3029) Remove Engine, Artifact traits, merge all Engines into one, make everything rkyv serialazable + - [#2892](https://github.com/wasmerio/wasmer/pull/2892) Implement new Context API for Wasmer 3.0 + - [#3031](https://github.com/wasmerio/wasmer/pull/3031) Update docs/migration_to_3.0.0.md + - [#3030](https://github.com/wasmerio/wasmer/pull/3030) Remove cranelift dependency from wasmer-wasi + - [#3028](https://github.com/wasmerio/wasmer/pull/3028) Ctx store rename + - [#3023](https://github.com/wasmerio/wasmer/pull/3023) Changed CI rust install action to dtolnay one + - [#3013](https://github.com/wasmerio/wasmer/pull/3013) Context api refactor + - [#2999](https://github.com/wasmerio/wasmer/pull/2999) Support --invoke option for emscripten files without _start function + - [#3003](https://github.com/wasmerio/wasmer/pull/3003) Remove RuntimeError::raise from public API + - [#3000](https://github.com/wasmerio/wasmer/pull/3000) Allow debugging of EXC_BAD_INSTRUCTION on macOS + - [#2946](https://github.com/wasmerio/wasmer/pull/2946) Removing dylib and staticlib engines in favor of a single Universal Engine + - [#2996](https://github.com/wasmerio/wasmer/pull/2996) Migrated al examples to new Context API + - [#2973](https://github.com/wasmerio/wasmer/pull/2973) Port C API to new Context API + - [#2974](https://github.com/wasmerio/wasmer/pull/2974) Context api tests + - [#2988](https://github.com/wasmerio/wasmer/pull/2988) Have make targets install-capi-lib,install-pkgconfig work without building the wasmer binary + - [#2976](https://github.com/wasmerio/wasmer/pull/2976) Upgrade enumset minimum version to one that compiles + - [#2969](https://github.com/wasmerio/wasmer/pull/2969) Port JS API to new Context API + - [#2966](https://github.com/wasmerio/wasmer/pull/2966) Singlepass nopanic + - [#2949](https://github.com/wasmerio/wasmer/pull/2949) Switch back to using custom LLVM builds on CI + - [#2963](https://github.com/wasmerio/wasmer/pull/2963) Remove libxcb and libwayland dependencies from wasmer-cli release build + - [#2957](https://github.com/wasmerio/wasmer/pull/2957) Enable multi-value handling in Singlepass compiler + - [#2941](https://github.com/wasmerio/wasmer/pull/2941) Implementation of WASIX and a fully networking for Web Assembly + - [#2947](https://github.com/wasmerio/wasmer/pull/2947) - Converted the WASI js test into a generic stdio test that works for… + - [#2940](https://github.com/wasmerio/wasmer/pull/2940) Merge `wasmer3` back to `master` branch + - [#2939](https://github.com/wasmerio/wasmer/pull/2939) Rename NativeFunc to TypedFunction + +## Fixed + + - [#3045](https://github.com/wasmerio/wasmer/pull/3045) Fixed WASI fd_read syscall when reading multiple iovs and read is partial (for #2904) + - [#2997](https://github.com/wasmerio/wasmer/pull/2997) Fix "run --invoke [function]" to behave the same as "run" + - [#3027](https://github.com/wasmerio/wasmer/pull/3027) Fixed residual package-doc issues + - [#3026](https://github.com/wasmerio/wasmer/pull/3026) test-js.yaml: fix typo + - [#3017](https://github.com/wasmerio/wasmer/pull/3017) Fixed translation in README.md + - [#3001](https://github.com/wasmerio/wasmer/pull/3001) Fix context capi ci errors + - [#2967](https://github.com/wasmerio/wasmer/pull/2967) Fix singlepass on arm64 that was trying to emit a sub opcode with a constant as destination (for #2959) + - [#2954](https://github.com/wasmerio/wasmer/pull/2954) Some fixes to x86_64 Singlepass compiler, when using atomics + - [#2950](https://github.com/wasmerio/wasmer/pull/2950) compiler-cranelift: Fix typo in enum variant + - [#2948](https://github.com/wasmerio/wasmer/pull/2948) Fix regression on gen_import_call_trampoline_arm64() + - [#2943](https://github.com/wasmerio/wasmer/pull/2943) Fix build error on some archs by using c_char instead of i8 + - [#2944](https://github.com/wasmerio/wasmer/pull/2944) Fix duplicate entries in the CHANGELOG + - [#2942](https://github.com/wasmerio/wasmer/pull/2942) Fix clippy lints ## 2.3.0 - 2022/06/06 diff --git a/Cargo.lock b/Cargo.lock index 8a45be372..e9b721ebb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1101,9 +1101,9 @@ dependencies = [ [[package]] name = "filetime" -version = "0.2.18" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b9663d381d07ae25dc88dbdf27df458faa83a9b25336bcac83d5e452b5fc9d3" +checksum = "4e884668cd0c7480504233e951174ddc3b382f7c2666e3b7310b5c4e7b0c37f9" dependencies = [ "cfg-if 1.0.0", "libc", @@ -1899,7 +1899,7 @@ dependencies = [ [[package]] name = "macro-wasmer-universal-test" -version = "3.0.2" +version = "3.1.0" dependencies = [ "proc-macro2", "proc-quote", @@ -4076,7 +4076,7 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasi-test-generator" -version = "3.0.2" +version = "3.1.0" dependencies = [ "glob", "gumdrop", @@ -4120,6 +4120,29 @@ dependencies = [ "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", +] + [[package]] name = "wasm-bindgen-futures" version = "0.4.33" @@ -4217,7 +4240,7 @@ dependencies = [ [[package]] name = "wasmer" -version = "3.0.2" +version = "3.1.0" dependencies = [ "anyhow", "bytes", @@ -4235,6 +4258,7 @@ dependencies = [ "thiserror", "tracing", "wasm-bindgen", + "wasm-bindgen-downcast", "wasm-bindgen-test", "wasmer-compiler", "wasmer-compiler-cranelift", @@ -4266,7 +4290,7 @@ dependencies = [ [[package]] name = "wasmer-c-api" -version = "3.0.2" +version = "3.1.0" dependencies = [ "cbindgen", "cfg-if 1.0.0", @@ -4294,7 +4318,7 @@ dependencies = [ [[package]] name = "wasmer-c-api-test-runner" -version = "3.0.2" +version = "3.1.0" dependencies = [ "cc", "regex", @@ -4304,7 +4328,7 @@ dependencies = [ [[package]] name = "wasmer-cache" -version = "3.0.2" +version = "3.1.0" dependencies = [ "blake3", "criterion", @@ -4318,7 +4342,7 @@ dependencies = [ [[package]] name = "wasmer-capi-examples-runner" -version = "3.0.2" +version = "3.1.0" dependencies = [ "cc", "regex", @@ -4328,7 +4352,7 @@ dependencies = [ [[package]] name = "wasmer-cli" -version = "3.0.2" +version = "3.1.0" dependencies = [ "anyhow", "atty", @@ -4341,6 +4365,7 @@ dependencies = [ "dirs", "distance", "fern", + "hex", "http_req", "isatty", "libc", @@ -4381,7 +4406,7 @@ dependencies = [ [[package]] name = "wasmer-compiler" -version = "3.0.2" +version = "3.1.0" dependencies = [ "backtrace", "cfg-if 1.0.0", @@ -4407,7 +4432,7 @@ dependencies = [ [[package]] name = "wasmer-compiler-cli" -version = "3.0.2" +version = "3.1.0" dependencies = [ "anyhow", "atty", @@ -4429,7 +4454,7 @@ dependencies = [ [[package]] name = "wasmer-compiler-cranelift" -version = "3.0.2" +version = "3.1.0" dependencies = [ "cranelift-codegen", "cranelift-entity", @@ -4448,7 +4473,7 @@ dependencies = [ [[package]] name = "wasmer-compiler-llvm" -version = "3.0.2" +version = "3.1.0" dependencies = [ "byteorder", "cc", @@ -4470,7 +4495,7 @@ dependencies = [ [[package]] name = "wasmer-compiler-singlepass" -version = "3.0.2" +version = "3.1.0" dependencies = [ "byteorder", "dynasm", @@ -4489,7 +4514,7 @@ dependencies = [ [[package]] name = "wasmer-derive" -version = "3.0.2" +version = "3.1.0" dependencies = [ "compiletest_rs", "proc-macro-error", @@ -4501,7 +4526,7 @@ dependencies = [ [[package]] name = "wasmer-emscripten" -version = "3.0.2" +version = "3.1.0" dependencies = [ "byteorder", "getrandom", @@ -4543,7 +4568,7 @@ dependencies = [ [[package]] name = "wasmer-integration-tests-cli" -version = "3.0.2" +version = "3.1.0" dependencies = [ "anyhow", "flate2", @@ -4559,11 +4584,11 @@ dependencies = [ [[package]] name = "wasmer-integration-tests-ios" -version = "3.0.2" +version = "3.1.0" [[package]] name = "wasmer-middlewares" -version = "3.0.2" +version = "3.1.0" dependencies = [ "wasmer", "wasmer-types", @@ -4572,7 +4597,7 @@ dependencies = [ [[package]] name = "wasmer-object" -version = "3.0.2" +version = "3.1.0" dependencies = [ "object 0.28.4", "thiserror", @@ -4581,17 +4606,20 @@ dependencies = [ [[package]] name = "wasmer-registry" -version = "3.0.2" +version = "3.1.0" dependencies = [ "anyhow", "dirs", + "filetime", "flate2", + "fs_extra", "futures-util", "graphql_client", "hex", "log", "lzma-rs", "rand 0.8.5", + "regex", "reqwest", "semver 1.0.14", "serde", @@ -4599,6 +4627,7 @@ dependencies = [ "tar", "tempdir", "thiserror", + "tldextract", "tokio", "toml", "url", @@ -4609,7 +4638,7 @@ dependencies = [ [[package]] name = "wasmer-types" -version = "3.0.2" +version = "3.1.0" dependencies = [ "enum-iterator", "enumset", @@ -4625,7 +4654,7 @@ dependencies = [ [[package]] name = "wasmer-vbus" -version = "3.0.2" +version = "3.1.0" dependencies = [ "libc", "slab", @@ -4639,7 +4668,7 @@ dependencies = [ [[package]] name = "wasmer-vfs" -version = "3.0.2" +version = "3.1.0" dependencies = [ "anyhow", "async-trait", @@ -4662,7 +4691,7 @@ dependencies = [ [[package]] name = "wasmer-vm" -version = "3.0.2" +version = "3.1.0" dependencies = [ "backtrace", "cc", @@ -4687,7 +4716,7 @@ dependencies = [ [[package]] name = "wasmer-vnet" -version = "3.0.2" +version = "3.1.0" dependencies = [ "async-trait", "bytes", @@ -4697,7 +4726,7 @@ dependencies = [ [[package]] name = "wasmer-wasi" -version = "3.0.2" +version = "3.1.0" dependencies = [ "anyhow", "async-trait", @@ -4756,7 +4785,7 @@ dependencies = [ [[package]] name = "wasmer-wasi-experimental-io-devices" -version = "3.0.2" +version = "3.1.0" dependencies = [ "minifb", "nix 0.25.0", @@ -4769,7 +4798,7 @@ dependencies = [ [[package]] name = "wasmer-wasi-local-networking" -version = "3.0.2" +version = "3.1.0" dependencies = [ "async-trait", "bytes", @@ -4781,7 +4810,7 @@ dependencies = [ [[package]] name = "wasmer-wasi-types" -version = "3.0.2" +version = "3.1.0" dependencies = [ "anyhow", "bitflags", @@ -4803,7 +4832,7 @@ dependencies = [ [[package]] name = "wasmer-wast" -version = "3.0.2" +version = "3.1.0" dependencies = [ "anyhow", "serde", @@ -4818,7 +4847,7 @@ dependencies = [ [[package]] name = "wasmer-workspace" -version = "3.0.2" +version = "3.1.0" dependencies = [ "anyhow", "build-deps", diff --git a/Cargo.toml b/Cargo.toml index 0c7985713..899e9a777 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer-workspace" -version = "3.0.2" +version = "3.1.0" description = "Wasmer workspace" authors = ["Wasmer Engineering Team "] repository = "https://github.com/wasmerio/wasmer" @@ -10,18 +10,18 @@ publish = false autoexamples = false [dependencies] -wasmer = { version = "=3.0.2", path = "lib/api", default-features = false } -wasmer-compiler = { version = "=3.0.2", path = "lib/compiler", features = ["compiler"] } -wasmer-compiler-cranelift = { version = "=3.0.2", path = "lib/compiler-cranelift", optional = true } -wasmer-compiler-singlepass = { version = "=3.0.2", path = "lib/compiler-singlepass", optional = true } -wasmer-compiler-llvm = { version = "=3.0.2", path = "lib/compiler-llvm", optional = true } -wasmer-emscripten = { version = "=3.0.2", path = "lib/emscripten", optional = true } -wasmer-wasi = { version = "=3.0.2", path = "lib/wasi", optional = true } -wasmer-wast = { version = "=3.0.2", path = "tests/lib/wast", optional = true } -wasi-test-generator = { version = "=3.0.2", path = "tests/wasi-wast", optional = true } -wasmer-cache = { version = "=3.0.2", path = "lib/cache", optional = true } -wasmer-types = { version = "=3.0.2", path = "lib/types" } -wasmer-middlewares = { version = "=3.0.2", path = "lib/middlewares", optional = true } +wasmer = { version = "=3.1.0", path = "lib/api", default-features = false } +wasmer-compiler = { version = "=3.1.0", path = "lib/compiler", features = ["compiler"] } +wasmer-compiler-cranelift = { version = "=3.1.0", path = "lib/compiler-cranelift", optional = true } +wasmer-compiler-singlepass = { version = "=3.1.0", path = "lib/compiler-singlepass", optional = true } +wasmer-compiler-llvm = { version = "=3.1.0", path = "lib/compiler-llvm", optional = true } +wasmer-emscripten = { version = "=3.1.0", path = "lib/emscripten", optional = true } +wasmer-wasi = { version = "=3.1.0", path = "lib/wasi", optional = true } +wasmer-wast = { version = "=3.1.0", path = "tests/lib/wast", optional = true } +wasi-test-generator = { version = "=3.1.0", path = "tests/wasi-wast", optional = true } +wasmer-cache = { version = "=3.1.0", path = "lib/cache", optional = true } +wasmer-types = { version = "=3.1.0", path = "lib/types" } +wasmer-middlewares = { version = "=3.1.0", path = "lib/middlewares", optional = true } cfg-if = "1.0" [workspace] @@ -70,7 +70,7 @@ glob = "0.3" rustc_version = "0.4" [dev-dependencies] -wasmer = { version = "=3.0.2", path = "lib/api", default-features = false, features = ["cranelift"] } +wasmer = { version = "=3.1.0", path = "lib/api", default-features = false, features = ["cranelift"] } anyhow = "1.0" criterion = "0.3" lazy_static = "1.4" diff --git a/Makefile b/Makefile index f1d4e5078..dfa31f9f1 100644 --- a/Makefile +++ b/Makefile @@ -550,7 +550,7 @@ test-examples: $(CARGO_BINARY) test $(CARGO_TARGET) --release $(compiler_features) --features wasi --examples test-integration-cli: - $(CARGO_BINARY) test $(CARGO_TARGET) --features webc_runner --no-fail-fast -p wasmer-integration-tests-cli -- --nocapture + $(CARGO_BINARY) test $(CARGO_TARGET) --features webc_runner --no-fail-fast -p wasmer-integration-tests-cli -- --nocapture --test-threads=1 test-integration-ios: $(CARGO_BINARY) test $(CARGO_TARGET) --features webc_runner -p wasmer-integration-tests-ios diff --git a/lib/api/Cargo.toml b/lib/api/Cargo.toml index 07b0dd5a9..c6b700301 100644 --- a/lib/api/Cargo.toml +++ b/lib/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer" -version = "3.0.2" +version = "3.1.0" description = "High-performance WebAssembly runtime" categories = ["wasm"] keywords = ["wasm", "webassembly", "runtime", "vm"] @@ -35,15 +35,15 @@ tracing = { version = "0.1", optional = true } # Dependencies and Development Dependencies for `sys`. [target.'cfg(not(target_arch = "wasm32"))'.dependencies] # - Mandatory dependencies for `sys`. -wasmer-vm = { path = "../vm", version = "=3.0.2" } -wasmer-compiler = { path = "../compiler", version = "=3.0.2" } -wasmer-derive = { path = "../derive", version = "=3.0.2" } -wasmer-types = { path = "../types", version = "=3.0.2" } +wasmer-vm = { path = "../vm", version = "=3.1.0" } +wasmer-compiler = { path = "../compiler", version = "=3.1.0" } +wasmer-derive = { path = "../derive", version = "=3.1.0" } +wasmer-types = { path = "../types", version = "=3.1.0" } target-lexicon = { version = "0.12.2", default-features = false } # - Optional dependencies for `sys`. -wasmer-compiler-singlepass = { path = "../compiler-singlepass", version = "=3.0.2", optional = true } -wasmer-compiler-cranelift = { path = "../compiler-cranelift", version = "=3.0.2", optional = true } -wasmer-compiler-llvm = { path = "../compiler-llvm", version = "=3.0.2", optional = true } +wasmer-compiler-singlepass = { path = "../compiler-singlepass", version = "=3.1.0", optional = true } +wasmer-compiler-cranelift = { path = "../compiler-cranelift", version = "=3.1.0", optional = true } +wasmer-compiler-llvm = { path = "../compiler-llvm", version = "=3.1.0", optional = true } wasm-bindgen = { version = "0.2.74", optional = true } js-sys = { version = "0.3.51", optional = true } @@ -56,16 +56,17 @@ winapi = "0.3" wat = "1.0" tempfile = "3.1" anyhow = "1.0" -macro-wasmer-universal-test = { version = "3.0.2", path = "./macro-wasmer-universal-test" } +macro-wasmer-universal-test = { version = "3.1.0", path = "./macro-wasmer-universal-test" } # Dependencies and Develoment Dependencies for `js`. [target.'cfg(target_arch = "wasm32")'.dependencies] # - Mandatory dependencies for `js`. -wasmer-types = { path = "../types", version = "=3.0.2", default-features = false, features = ["std"] } +wasmer-types = { path = "../types", version = "=3.1.0", default-features = false, features = ["std"] } wasm-bindgen = "0.2.74" +wasm-bindgen-downcast = { version = "0.1.1" } js-sys = "0.3.51" #web-sys = { version = "0.3.51", features = [ "console" ] } -wasmer-derive = { path = "../derive", version = "=3.0.2" } +wasmer-derive = { path = "../derive", version = "=3.1.0" } # - Optional dependencies for `js`. wasmparser = { version = "0.83", default-features = false, optional = true } hashbrown = { version = "0.11", optional = true } @@ -77,7 +78,7 @@ serde = { version = "1.0", features = ["derive"] } wat = "1.0" anyhow = "1.0" wasm-bindgen-test = "0.3.0" -macro-wasmer-universal-test = { version = "3.0.2", path = "./macro-wasmer-universal-test" } +macro-wasmer-universal-test = { version = "3.1.0", path = "./macro-wasmer-universal-test" } # Specific to `js`. # diff --git a/lib/api/macro-wasmer-universal-test/Cargo.toml b/lib/api/macro-wasmer-universal-test/Cargo.toml index c87166daf..dc8601ced 100644 --- a/lib/api/macro-wasmer-universal-test/Cargo.toml +++ b/lib/api/macro-wasmer-universal-test/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "macro-wasmer-universal-test" -version = "3.0.2" +version = "3.1.0" edition = "2021" license = "MIT" description = "Universal test macro for wasmer-test" diff --git a/lib/api/src/js/trap.rs b/lib/api/src/js/trap.rs index 4c1e2658a..5ba0dd5bf 100644 --- a/lib/api/src/js/trap.rs +++ b/lib/api/src/js/trap.rs @@ -5,6 +5,7 @@ use std::sync::Arc; use wasm_bindgen::convert::FromWasmAbi; use wasm_bindgen::prelude::*; use wasm_bindgen::JsValue; +use wasm_bindgen_downcast::DowncastJS; pub trait CoreError: fmt::Debug + fmt::Display { fn source(&self) -> Option<&(dyn CoreError + 'static)> { @@ -97,7 +98,7 @@ impl dyn CoreError { /// A struct representing an aborted instruction execution, with a message /// indicating the cause. #[wasm_bindgen] -#[derive(Clone)] +#[derive(Clone, DowncastJS)] pub struct WasmerRuntimeError { inner: Arc, } @@ -285,7 +286,7 @@ impl From for RuntimeError { // We try to downcast the error and see if it's // an instance of RuntimeError instead, so we don't need // to re-wrap it. - generic_of_jsval(original, "WasmerRuntimeError").unwrap_or_else(|js| RuntimeError { + WasmerRuntimeError::downcast_js(original).unwrap_or_else(|js| RuntimeError { inner: Arc::new(RuntimeErrorSource::Js(js)), }) } diff --git a/lib/c-api/Cargo.toml b/lib/c-api/Cargo.toml index a180b5051..d3fa6617c 100644 --- a/lib/c-api/Cargo.toml +++ b/lib/c-api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer-c-api" -version = "3.0.2" +version = "3.1.0" description = "Wasmer C API library" categories = ["wasm", "api-bindings"] keywords = ["wasm", "webassembly", "runtime"] @@ -22,16 +22,16 @@ crate-type = ["staticlib", "cdylib"] #"cdylib", "rlib", "staticlib"] [dependencies] # We rename `wasmer` to `wasmer-api` to avoid the conflict with this # library name (see `[lib]`). -wasmer-api = { version = "=3.0.2", path = "../api", default-features = false, features = ["sys"], package = "wasmer" } -wasmer-compiler-cranelift = { version = "=3.0.2", path = "../compiler-cranelift", optional = true } -wasmer-compiler-singlepass = { version = "=3.0.2", path = "../compiler-singlepass", optional = true } -wasmer-compiler-llvm = { version = "=3.0.2", path = "../compiler-llvm", optional = true } -wasmer-emscripten = { version = "=3.0.2", path = "../emscripten", optional = true } -wasmer-compiler = { version = "=3.0.2", path = "../compiler" } -wasmer-middlewares = { version = "=3.0.2", path = "../middlewares", optional = true } -wasmer-wasi = { version = "=3.0.2", path = "../wasi", default-features = false, features = ["host-fs", "sys"], optional = true } -wasmer-types = { version = "=3.0.2", path = "../types" } -wasmer-vfs = { version = "=3.0.2", path = "../vfs", optional = true, default-features = false, features = ["static-fs"] } +wasmer-api = { version = "=3.1.0", path = "../api", default-features = false, features = ["sys"], package = "wasmer" } +wasmer-compiler-cranelift = { version = "=3.1.0", path = "../compiler-cranelift", optional = true } +wasmer-compiler-singlepass = { version = "=3.1.0", path = "../compiler-singlepass", optional = true } +wasmer-compiler-llvm = { version = "=3.1.0", path = "../compiler-llvm", optional = true } +wasmer-emscripten = { version = "=3.1.0", path = "../emscripten", optional = true } +wasmer-compiler = { version = "=3.1.0", path = "../compiler" } +wasmer-middlewares = { version = "=3.1.0", path = "../middlewares", optional = true } +wasmer-wasi = { version = "=3.1.0", path = "../wasi", default-features = false, features = ["host-fs", "sys"], optional = true } +wasmer-types = { version = "=3.1.0", path = "../types" } +wasmer-vfs = { version = "=3.1.0", path = "../vfs", optional = true, default-features = false, features = ["static-fs"] } webc = { version = "3.0.1", optional = true } enumset = "1.0.2" cfg-if = "1.0" diff --git a/lib/c-api/examples/wasmer-capi-examples-runner/Cargo.toml b/lib/c-api/examples/wasmer-capi-examples-runner/Cargo.toml index d7300cf99..7eedc2ee4 100644 --- a/lib/c-api/examples/wasmer-capi-examples-runner/Cargo.toml +++ b/lib/c-api/examples/wasmer-capi-examples-runner/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer-capi-examples-runner" -version = "3.0.2" +version = "3.1.0" edition = "2021" license = "MIT" description = "wasmer-capi-examples-runner" diff --git a/lib/c-api/src/wasm_c_api/types/import.rs b/lib/c-api/src/wasm_c_api/types/import.rs index dc2e891d7..8be6b99c1 100644 --- a/lib/c-api/src/wasm_c_api/types/import.rs +++ b/lib/c-api/src/wasm_c_api/types/import.rs @@ -11,6 +11,7 @@ pub struct wasm_importtype_t { } wasm_declare_boxed_vec!(importtype); +wasm_impl_copy!(importtype); #[no_mangle] pub extern "C" fn wasm_importtype_new( diff --git a/lib/c-api/tests/wasmer-c-api-test-runner/Cargo.toml b/lib/c-api/tests/wasmer-c-api-test-runner/Cargo.toml index 2d6fb4a91..dad6642e4 100644 --- a/lib/c-api/tests/wasmer-c-api-test-runner/Cargo.toml +++ b/lib/c-api/tests/wasmer-c-api-test-runner/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer-c-api-test-runner" -version = "3.0.2" +version = "3.1.0" edition = "2021" license = "MIT" description = "wasmer-c-api-test-runner" diff --git a/lib/cache/Cargo.toml b/lib/cache/Cargo.toml index 71eb844b5..ef8e1d6f3 100644 --- a/lib/cache/Cargo.toml +++ b/lib/cache/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer-cache" -version = "3.0.2" +version = "3.1.0" description = "Cache system for Wasmer WebAssembly runtime" categories = ["wasm", "caching"] keywords = ["wasm", "webassembly", "cache"] @@ -11,7 +11,7 @@ readme = "README.md" edition = "2018" [dependencies] -wasmer = { path = "../api", version = "=3.0.2", default-features = false, features = ["sys"] } +wasmer = { path = "../api", version = "=3.1.0", default-features = false, features = ["sys"] } hex = "0.4" thiserror = "1" blake3 = "1.0" @@ -20,7 +20,7 @@ blake3 = "1.0" criterion = "0.3" tempfile = "3" rand = "0.8.3" -wasmer-compiler-singlepass = { path = "../compiler-singlepass", version = "=3.0.2" } +wasmer-compiler-singlepass = { path = "../compiler-singlepass", version = "=3.1.0" } [features] default = ["wasmer/js-serializable-module", "wasmer/compiler", "filesystem"] diff --git a/lib/cli-compiler/Cargo.toml b/lib/cli-compiler/Cargo.toml index 63158131c..3a1daf42d 100644 --- a/lib/cli-compiler/Cargo.toml +++ b/lib/cli-compiler/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer-compiler-cli" -version = "3.0.2" +version = "3.1.0" description = "Wasmer Compiler CLI" categories = ["wasm", "command-line-interface"] keywords = ["wasm", "webassembly", "cli"] @@ -18,8 +18,8 @@ path = "src/bin/wasmer_compiler.rs" doc = false [dependencies] -wasmer-compiler = { version = "=3.0.2", path = "../compiler", features = ["compiler"] } -wasmer-types = { version = "=3.0.2", path = "../types" } +wasmer-compiler = { version = "=3.1.0", path = "../compiler", features = ["compiler"] } +wasmer-types = { version = "=3.1.0", path = "../types" } atty = "0.2" colored = "2.0" anyhow = "1.0" @@ -36,12 +36,12 @@ target-lexicon = { version = "0.12", features = ["std"] } tempfile = "3" [target.'cfg(not(target_arch = "wasm32"))'.dependencies] -wasmer-compiler-singlepass = { version = "=3.0.2", path = "../compiler-singlepass", optional = true } -wasmer-compiler-cranelift = { version = "=3.0.2", path = "../compiler-cranelift", optional = true } +wasmer-compiler-singlepass = { version = "=3.1.0", path = "../compiler-singlepass", optional = true } +wasmer-compiler-cranelift = { version = "=3.1.0", path = "../compiler-cranelift", optional = true } [target.'cfg(target_arch = "wasm32")'.dependencies] -wasmer-compiler-singlepass = { version = "=3.0.2", path = "../compiler-singlepass", optional = true, default-features = false, features = ["wasm"] } -wasmer-compiler-cranelift = { version = "=3.0.2", path = "../compiler-cranelift", optional = true, default-features = false, features = ["wasm"] } +wasmer-compiler-singlepass = { version = "=3.1.0", path = "../compiler-singlepass", optional = true, default-features = false, features = ["wasm"] } +wasmer-compiler-cranelift = { version = "=3.1.0", path = "../compiler-cranelift", optional = true, default-features = false, features = ["wasm"] } [target.'cfg(target_os = "linux")'.dependencies] unix_mode = "0.1.3" diff --git a/lib/cli/Cargo.toml b/lib/cli/Cargo.toml index 7f2502af0..8e74131fc 100644 --- a/lib/cli/Cargo.toml +++ b/lib/cli/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer-cli" -version = "3.0.2" +version = "3.1.0" description = "Wasmer CLI" categories = ["wasm", "command-line-interface"] keywords = ["wasm", "webassembly", "cli"] @@ -25,21 +25,21 @@ doc = false required-features = ["headless"] [dependencies] -wasmer = { version = "=3.0.2", path = "../api", default-features = false } -wasmer-compiler = { version = "=3.0.2", path = "../compiler", features = ["compiler", ] } -wasmer-compiler-cranelift = { version = "=3.0.2", path = "../compiler-cranelift", optional = true } -wasmer-compiler-singlepass = { version = "=3.0.2", path = "../compiler-singlepass", optional = true } -wasmer-compiler-llvm = { version = "=3.0.2", path = "../compiler-llvm", optional = true } -wasmer-emscripten = { version = "=3.0.2", path = "../emscripten", optional = true } -wasmer-vm = { version = "=3.0.2", path = "../vm", features = ["tracing"] } -wasmer-wasi = { version = "=3.0.2", path = "../wasi", optional = true, features = ["host-vnet"] } -wasmer-wasi-experimental-io-devices = { version = "=3.0.2", path = "../wasi-experimental-io-devices", optional = true, features = ["link_external_libs"] } -wasmer-wast = { version = "=3.0.2", path = "../../tests/lib/wast", optional = true } -wasmer-cache = { version = "=3.0.2", path = "../cache", optional = true } -wasmer-types = { version = "=3.0.2", path = "../types" } -wasmer-registry = { version = "=3.0.2", path = "../registry" } -wasmer-object = { version = "=3.0.2", path = "../object", optional = true } -wasmer-vfs = { version = "=3.0.2", path = "../vfs", default-features = false, features = ["host-fs"] } +wasmer = { version = "=3.1.0", path = "../api", default-features = false } +wasmer-compiler = { version = "=3.1.0", path = "../compiler", features = ["compiler", ] } +wasmer-compiler-cranelift = { version = "=3.1.0", path = "../compiler-cranelift", optional = true } +wasmer-compiler-singlepass = { version = "=3.1.0", path = "../compiler-singlepass", optional = true } +wasmer-compiler-llvm = { version = "=3.1.0", path = "../compiler-llvm", optional = true } +wasmer-emscripten = { version = "=3.1.0", path = "../emscripten", optional = true } +wasmer-vm = { version = "=3.1.0", path = "../vm" } +wasmer-wasi = { version = "=3.1.0", path = "../wasi", optional = true } +wasmer-wasi-experimental-io-devices = { version = "=3.1.0", path = "../wasi-experimental-io-devices", optional = true, features = ["link_external_libs"] } +wasmer-wast = { version = "=3.1.0", path = "../../tests/lib/wast", optional = true } +wasmer-cache = { version = "=3.1.0", path = "../cache", optional = true } +wasmer-types = { version = "=3.1.0", path = "../types" } +wasmer-registry = { version = "=3.1.0", path = "../registry" } +wasmer-object = { version = "=3.1.0", path = "../object", optional = true } +wasmer-vfs = { version = "=3.1.0", path = "../vfs", default-features = false, features = ["host-fs"] } atty = "0.2" colored = "2.0" anyhow = "1.0" @@ -55,11 +55,11 @@ fern = { version = "0.6", features = ["colored"], optional = true } log = { version = "0.4", optional = true } tempfile = "3" tempdir = "0.3.7" -http_req = { version="^0.8", default-features = false, features = ["rust-tls"], optional = true } -reqwest = { version = "^0.11", default-features = false, features = ["rustls-tls", "json", "multipart"], optional = true } -serde = { version = "1.0.147", features = ["derive"], optional = true } -dirs = { version = "4.0", optional = true } -serde_json = { version = "1.0", optional = true } +http_req = { version="^0.8", default-features = false, features = ["rust-tls"] } +reqwest = { version = "^0.11", default-features = false, features = ["rustls-tls", "json", "multipart"] } +serde = { version = "1.0.147", features = ["derive"] } +dirs = { version = "4.0" } +serde_json = { version = "1.0" } target-lexicon = { version = "0.12", features = ["std"] } prettytable-rs = "0.9.0" wapm-toml = "0.2.0" @@ -73,6 +73,7 @@ webc = { version = "3.0.1", optional = true } isatty = "0.1.9" dialoguer = "0.10.2" tldextract = "0.6.0" +hex = "0.4.3" [build-dependencies] chrono = { version = "^0.4", default-features = false, features = [ "std", "clock" ] } @@ -86,7 +87,6 @@ unix_mode = "0.1.3" default = [ "wat", "wast", - "http", "cache", "wasi", "emscripten", @@ -160,14 +160,6 @@ enable-serde = [ "wasmer-wasi/enable-serde", ] -http = [ - "http_req", - "reqwest", - "dirs", - "serde_json", - "serde", -] - [target.'cfg(target_os = "windows")'.dependencies] colored = "2.0.0" diff --git a/lib/cli/src/cli.rs b/lib/cli/src/cli.rs index 5829fb16c..3b9b8cea6 100644 --- a/lib/cli/src/cli.rs +++ b/lib/cli/src/cli.rs @@ -15,7 +15,6 @@ use crate::commands::{ }; use crate::error::PrettyError; use clap::{CommandFactory, ErrorKind, Parser}; -use std::{fmt, str::FromStr}; #[derive(Parser, Debug)] #[cfg_attr( @@ -243,218 +242,9 @@ fn wasmer_main_inner() -> Result<(), anyhow::Error> { } }; - // Check if the file is a package name - if let WasmerCLIOptions::Run(r) = &options { - #[cfg(not(feature = "debug"))] - let debug = false; - #[cfg(feature = "debug")] - let debug = r.options.debug; - return crate::commands::try_run_package_or_file(&args, r, debug); - } - options.execute() } -#[derive(Debug, Clone, PartialEq, Default)] -pub(crate) struct SplitVersion { - pub(crate) original: String, - pub(crate) registry: Option, - pub(crate) package: String, - pub(crate) version: Option, - pub(crate) command: Option, -} - -impl fmt::Display for SplitVersion { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let version = self.version.as_deref().unwrap_or("latest"); - let command = self - .command - .as_ref() - .map(|s| format!(":{s}")) - .unwrap_or_default(); - write!(f, "{}@{version}{command}", self.package) - } -} - -#[test] -fn test_split_version() { - assert_eq!( - SplitVersion::parse("registry.wapm.io/graphql/python/python").unwrap(), - SplitVersion { - original: "registry.wapm.io/graphql/python/python".to_string(), - registry: Some("https://registry.wapm.io/graphql".to_string()), - package: "python/python".to_string(), - version: None, - command: None, - } - ); - assert_eq!( - SplitVersion::parse("registry.wapm.io/python/python").unwrap(), - SplitVersion { - original: "registry.wapm.io/python/python".to_string(), - registry: Some("https://registry.wapm.io/graphql".to_string()), - package: "python/python".to_string(), - version: None, - command: None, - } - ); - assert_eq!( - SplitVersion::parse("namespace/name@version:command").unwrap(), - SplitVersion { - original: "namespace/name@version:command".to_string(), - registry: None, - package: "namespace/name".to_string(), - version: Some("version".to_string()), - command: Some("command".to_string()), - } - ); - assert_eq!( - SplitVersion::parse("namespace/name@version").unwrap(), - SplitVersion { - original: "namespace/name@version".to_string(), - registry: None, - package: "namespace/name".to_string(), - version: Some("version".to_string()), - command: None, - } - ); - assert_eq!( - SplitVersion::parse("namespace/name").unwrap(), - SplitVersion { - original: "namespace/name".to_string(), - registry: None, - package: "namespace/name".to_string(), - version: None, - command: None, - } - ); - assert_eq!( - SplitVersion::parse("registry.wapm.io/namespace/name").unwrap(), - SplitVersion { - original: "registry.wapm.io/namespace/name".to_string(), - registry: Some("https://registry.wapm.io/graphql".to_string()), - package: "namespace/name".to_string(), - version: None, - command: None, - } - ); - assert_eq!( - format!("{}", SplitVersion::parse("namespace").unwrap_err()), - "Invalid package version: \"namespace\"".to_string(), - ); -} - -impl SplitVersion { - pub fn parse(s: &str) -> Result { - s.parse() - } -} - -impl FromStr for SplitVersion { - type Err = anyhow::Error; - - fn from_str(s: &str) -> Result { - let command = WasmerCLIOptions::command(); - let mut prohibited_package_names = command.get_subcommands().map(|s| s.get_name()); - - let re1 = regex::Regex::new(r#"(.*)/(.*)@(.*):(.*)"#).unwrap(); - let re2 = regex::Regex::new(r#"(.*)/(.*)@(.*)"#).unwrap(); - let re3 = regex::Regex::new(r#"(.*)/(.*)"#).unwrap(); - let re4 = regex::Regex::new(r#"(.*)/(.*):(.*)"#).unwrap(); - - let mut no_version = false; - - let captures = if re1.is_match(s) { - re1.captures(s) - .map(|c| { - c.iter() - .flatten() - .map(|m| m.as_str().to_owned()) - .collect::>() - }) - .unwrap_or_default() - } else if re2.is_match(s) { - re2.captures(s) - .map(|c| { - c.iter() - .flatten() - .map(|m| m.as_str().to_owned()) - .collect::>() - }) - .unwrap_or_default() - } else if re4.is_match(s) { - no_version = true; - re4.captures(s) - .map(|c| { - c.iter() - .flatten() - .map(|m| m.as_str().to_owned()) - .collect::>() - }) - .unwrap_or_default() - } else if re3.is_match(s) { - re3.captures(s) - .map(|c| { - c.iter() - .flatten() - .map(|m| m.as_str().to_owned()) - .collect::>() - }) - .unwrap_or_default() - } else { - return Err(anyhow::anyhow!("Invalid package version: {s:?}")); - }; - - let mut namespace = match captures.get(1).cloned() { - Some(s) => s, - None => { - return Err(anyhow::anyhow!( - "Invalid package version: {s:?}: no namespace" - )) - } - }; - - let name = match captures.get(2).cloned() { - Some(s) => s, - None => return Err(anyhow::anyhow!("Invalid package version: {s:?}: no name")), - }; - - let mut registry = None; - if namespace.contains('/') { - let (r, n) = namespace.rsplit_once('/').unwrap(); - let mut real_registry = r.to_string(); - if !real_registry.ends_with("graphql") { - real_registry = format!("{real_registry}/graphql"); - } - if !real_registry.contains("://") { - real_registry = format!("https://{real_registry}"); - } - registry = Some(real_registry); - namespace = n.to_string(); - } - - let sv = SplitVersion { - original: s.to_string(), - registry, - package: format!("{namespace}/{name}"), - version: if no_version { - None - } else { - captures.get(3).cloned() - }, - command: captures.get(if no_version { 3 } else { 4 }).cloned(), - }; - - let svp = sv.package.clone(); - anyhow::ensure!( - !prohibited_package_names.any(|s| s == sv.package.trim()), - "Invalid package name {svp:?}" - ); - - Ok(sv) - } -} - fn print_help(verbose: bool) -> Result<(), anyhow::Error> { let mut cmd = WasmerCLIOptions::command(); if verbose { diff --git a/lib/cli/src/commands/add.rs b/lib/cli/src/commands/add.rs index f52964936..fc1395c5c 100644 --- a/lib/cli/src/commands/add.rs +++ b/lib/cli/src/commands/add.rs @@ -4,8 +4,6 @@ use anyhow::{Context, Error}; use clap::Parser; use wasmer_registry::{Bindings, PartialWapmConfig, ProgrammingLanguage}; -use crate::cli::SplitVersion; - /// Add a WAPM package's bindings to your application. #[derive(Debug, Parser)] pub struct Add { @@ -26,7 +24,7 @@ pub struct Add { pip: bool, /// The packages to add (e.g. "wasmer/wasmer-pack@0.5.0" or "python/python") #[clap(parse(try_from_str))] - packages: Vec, + packages: Vec, } impl Add { @@ -103,11 +101,11 @@ impl Add { fn lookup_bindings_for_package( registry: &str, - pkg: &SplitVersion, + pkg: &wasmer_registry::Package, language: &ProgrammingLanguage, ) -> Result { let all_bindings = - wasmer_registry::list_bindings(registry, &pkg.package, pkg.version.as_deref())?; + wasmer_registry::list_bindings(registry, &pkg.package(), pkg.version.as_deref())?; match all_bindings.iter().find(|b| b.language == *language) { Some(b) => { diff --git a/lib/cli/src/commands/create_exe.rs b/lib/cli/src/commands/create_exe.rs index c13a38d11..c8f326ba6 100644 --- a/lib/cli/src/commands/create_exe.rs +++ b/lib/cli/src/commands/create_exe.rs @@ -402,52 +402,34 @@ impl CreateExe { let library = if let Some(v) = cross_subc.library_path.clone() { v.canonicalize().unwrap_or(v) } else { - { - let libwasmer_path = "lib/libwasmer.a"; - let tarball_dir; - let filename = if let Some(local_tarball) = cross_subc.tarball.as_ref() { - let target_file_path = local_tarball - .parent() - .and_then(|parent| Some(parent.join(local_tarball.file_stem()?))) - .unwrap_or_else(|| local_tarball.clone()); - - let target_file_path = target_file_path - .parent() - .and_then(|parent| Some(parent.join(target_file_path.file_stem()?))) - .unwrap_or_else(|| target_file_path.clone()); - - let _ = std::fs::create_dir_all(&target_file_path); - let files = untar(local_tarball.clone(), target_file_path.clone())?; - tarball_dir = target_file_path.canonicalize().unwrap_or(target_file_path); - files.iter().find(|f| f.contains(libwasmer_path)).cloned().ok_or_else(|| { - anyhow!("Could not find libwasmer for {} target in the provided tarball path (files = {files:#?}, libwasmer_path = {libwasmer_path:?})", target)})? + let (filename, tarball_dir) = + if let Some(local_tarball) = cross_subc.tarball.as_ref() { + Self::find_filename(local_tarball, &target) } else { - #[cfg(feature = "http")] - { + // check if the tarball for the target already exists locally + let local_tarball = std::fs::read_dir(get_libwasmer_cache_path()?)? + .filter_map(|e| e.ok()) + .filter_map(|e| { + let path = format!("{}", e.path().display()); + if path.ends_with(".tar.gz") { + Some(e.path()) + } else { + None + } + }) + .filter_map(|p| Self::filter_tarballs(&p, &target)) + .next(); + + if let Some(local_tarball) = local_tarball.as_ref() { + Self::find_filename(local_tarball, &target) + } else { let release = http_fetch::get_latest_release()?; let tarball = http_fetch::download_release(release, target.clone())?; - let target_file_path = tarball - .parent() - .and_then(|parent| Some(parent.join(tarball.file_stem()?))) - .unwrap_or_else(|| tarball.clone()); - - let target_file_path = target_file_path - .parent() - .and_then(|parent| Some(parent.join(target_file_path.file_stem()?))) - .unwrap_or_else(|| target_file_path.clone()); - - tarball_dir = target_file_path - .canonicalize() - .unwrap_or_else(|_| target_file_path.clone()); - let files = untar(tarball, target_file_path)?; - files.into_iter().find(|f| f.contains(libwasmer_path)).ok_or_else(|| { - anyhow!("Could not find libwasmer for {} target in the fetched release from Github: you can download it manually and specify its path with the --cross-compilation-library-path LIBRARY_PATH flag.", target)})? + Self::find_filename(&tarball, &target) } - #[cfg(not(feature = "http"))] - return Err(anyhow!("This wasmer binary isn't compiled with an HTTP request library (feature flag `http`). To cross-compile, specify the path of the non-native libwasmer or release tarball with the --library-path LIBRARY_PATH or --tarball TARBALL_PATH flag.")); - }; - tarball_dir.join(&filename) - } + }?; + + tarball_dir.join(&filename) }; let ccs = CrossCompileSetup { target, @@ -460,6 +442,72 @@ impl CreateExe { } } + fn find_filename( + local_tarball: &Path, + target: &Triple, + ) -> Result<(String, PathBuf), anyhow::Error> { + let target_file_path = local_tarball + .parent() + .and_then(|parent| Some(parent.join(local_tarball.file_stem()?))) + .unwrap_or_else(|| local_tarball.to_path_buf()); + + let target_file_path = target_file_path + .parent() + .and_then(|parent| Some(parent.join(target_file_path.file_stem()?))) + .unwrap_or_else(|| target_file_path.clone()); + + std::fs::create_dir_all(&target_file_path) + .map_err(|e| anyhow::anyhow!("{e}")) + .context(anyhow::anyhow!("{}", target_file_path.display()))?; + let files = untar(local_tarball.to_path_buf(), target_file_path.clone())?; + let tarball_dir = target_file_path.canonicalize().unwrap_or(target_file_path); + + let file = files + .iter() + .find(|f| f.ends_with("libwasmer.a")).cloned() + .ok_or_else(|| { + anyhow!("Could not find libwasmer.a for {} target in the provided tarball path (files = {files:#?})", target) + })?; + + Ok((file, tarball_dir)) + } + + fn filter_tarballs(p: &Path, target: &Triple) -> Option { + if let Architecture::Aarch64(_) = target.architecture { + if !p.file_name()?.to_str()?.contains("aarch64") { + return None; + } + } + + if let Architecture::X86_64 = target.architecture { + if !p.file_name()?.to_str()?.contains("x86_64") { + return None; + } + } + + if let OperatingSystem::Windows = target.operating_system { + if !p.file_name()?.to_str()?.contains("windows") { + return None; + } + } + + if let OperatingSystem::Darwin = target.operating_system { + if !(p.file_name()?.to_str()?.contains("apple") + || p.file_name()?.to_str()?.contains("darwin")) + { + return None; + } + } + + if let OperatingSystem::Linux = target.operating_system { + if !p.file_name()?.to_str()?.contains("linux") { + return None; + } + } + + Some(p.to_path_buf()) + } + fn compile_c( &self, wasm_object_path: PathBuf, @@ -573,9 +621,6 @@ impl CreateExe { } cmd.arg("-lunwind"); cmd.arg("-OReleaseSafe"); - cmd.arg("-fstrip"); - cmd.arg("-dead_strip"); - cmd.arg("-dead_strip_dylibs"); cmd.arg("-fno-compiler-rt"); cmd.arg(&format!("-femit-bin={}", output_path.display())); @@ -1329,7 +1374,6 @@ impl LinkCode { } } -#[cfg(feature = "http")] mod http_fetch { use anyhow::{anyhow, Context, Result}; use http_req::{request::Request, response::StatusCode, uri::Uri}; @@ -1379,7 +1423,7 @@ mod http_fetch { } Err(anyhow!( - "Could not get expected Github API response.\n\nReason: response format is not recognized:\n{:#?}", "" + "Could not get expected Github API response.\n\nReason: response format is not recognized:\n{response:#?}", )) } diff --git a/lib/cli/src/commands/list.rs b/lib/cli/src/commands/list.rs index 0851d9947..36d5d6f84 100644 --- a/lib/cli/src/commands/list.rs +++ b/lib/cli/src/commands/list.rs @@ -9,10 +9,10 @@ impl List { pub fn execute(&self) -> Result<(), anyhow::Error> { use prettytable::{format, row, Table}; - let rows = wasmer_registry::get_all_local_packages(None) + let rows = wasmer_registry::get_all_local_packages() .into_iter() .filter_map(|pkg| { - let package_root_path = pkg.get_path().ok()?; + let package_root_path = pkg.path; let (manifest, _) = wasmer_registry::get_executable_file_from_path(&package_root_path, None) .ok()?; diff --git a/lib/cli/src/commands/run.rs b/lib/cli/src/commands/run.rs index e5d329108..527bbd196 100644 --- a/lib/cli/src/commands/run.rs +++ b/lib/cli/src/commands/run.rs @@ -1,7 +1,7 @@ -use crate::cli::SplitVersion; use crate::common::get_cache_dir; #[cfg(feature = "debug")] use crate::logging; +use crate::package_source::PackageSource; use crate::store::{CompilerType, StoreOptions}; use crate::suggestions::suggest_function_exports; use crate::warning; @@ -11,12 +11,10 @@ use std::collections::HashMap; use std::ops::Deref; use std::path::PathBuf; use std::str::FromStr; -use url::Url; use wasmer::FunctionEnv; use wasmer::*; #[cfg(feature = "cache")] use wasmer_cache::{Cache, FileSystemCache, Hash}; -use wasmer_registry::PackageDownloadInfo; use wasmer_types::Type as ValueType; #[cfg(feature = "webc_runner")] use wasmer_wasi::runners::{Runner, WapmContainer}; @@ -27,6 +25,17 @@ mod wasi; #[cfg(feature = "wasi")] use wasi::Wasi; +/// The options for the `wasmer run` subcommand, runs either a package, URL or a file +#[derive(Debug, Parser, Clone, Default)] +pub struct Run { + /// File to run + #[clap(name = "SOURCE", parse(try_from_str))] + pub(crate) path: PackageSource, + /// Options to run the file / package / URL with + #[clap(flatten)] + pub(crate) options: RunWithoutFile, +} + /// Same as `wasmer run`, but without the required `path` argument (injected previously) #[derive(Debug, Parser, Clone, Default)] pub struct RunWithoutFile { @@ -83,103 +92,65 @@ pub struct RunWithoutFile { pub(crate) args: Vec, } -#[allow(dead_code)] -fn is_dir(e: &walkdir::DirEntry) -> bool { - let meta = match e.metadata() { - Ok(o) => o, - Err(_) => return false, - }; - meta.is_dir() -} - -impl RunWithoutFile { - /// Given a local path, returns the `Run` command (overriding the `--path` argument). - pub fn into_run_args( - mut self, - package_root_dir: PathBuf, // <- package dir - command: Option<&str>, - _debug_output_allowed: bool, - ) -> Result { - let (manifest, pathbuf) = - wasmer_registry::get_executable_file_from_path(&package_root_dir, command)?; - - #[cfg(feature = "wasi")] - { - let default = HashMap::default(); - let fs = manifest.fs.as_ref().unwrap_or(&default); - for (alias, real_dir) in fs.iter() { - let real_dir = package_root_dir.join(&real_dir); - if !real_dir.exists() { - if _debug_output_allowed { - println!( - "warning: cannot map {alias:?} to {}: directory does not exist", - real_dir.display() - ); - } - continue; - } - - self.wasi.map_dir(alias, real_dir.clone()); - } - } - - Ok(Run { - path: pathbuf, - options: RunWithoutFile { - force_install: self.force_install, - #[cfg(feature = "cache")] - disable_cache: self.disable_cache, - invoke: self.invoke, - // If the RunWithoutFile was constructed via a package name, - // the correct syntax is "package:command-name" (--command-name would be - // interpreted as a CLI argument for the .wasm file) - command_name: None, - #[cfg(feature = "cache")] - cache_key: self.cache_key, - store: self.store, - #[cfg(feature = "wasi")] - wasi: self.wasi, - #[cfg(feature = "io-devices")] - enable_experimental_io_devices: self.enable_experimental_io_devices, - #[cfg(feature = "debug")] - debug: self.debug, - #[cfg(feature = "debug")] - verbose: self.verbose, - args: self.args, - }, - }) - } -} - -#[derive(Debug, Parser, Clone, Default)] -/// The options for the `wasmer run` subcommand -pub struct Run { +/// Same as `Run`, but uses a resolved local file path. +#[derive(Debug, Clone, Default)] +pub struct RunWithPathBuf { /// File to run - #[clap(name = "FILE", parse(from_os_str))] pub(crate) path: PathBuf, - - #[clap(flatten)] + /// Options for running the file pub(crate) options: RunWithoutFile, } -impl Deref for Run { +impl Deref for RunWithPathBuf { type Target = RunWithoutFile; fn deref(&self) -> &Self::Target { &self.options } } -impl Run { +impl RunWithPathBuf { /// Execute the run command pub fn execute(&self) -> Result<()> { + let mut self_clone = self.clone(); + + if self_clone.path.is_dir() { + let (manifest, pathbuf) = wasmer_registry::get_executable_file_from_path( + &self_clone.path, + self_clone.command_name.as_deref(), + )?; + + #[cfg(feature = "wasi")] + { + let default = HashMap::default(); + let fs = manifest.fs.as_ref().unwrap_or(&default); + for (alias, real_dir) in fs.iter() { + let real_dir = self_clone.path.join(&real_dir); + if !real_dir.exists() { + #[cfg(feature = "debug")] + if self_clone.debug { + println!( + "warning: cannot map {alias:?} to {}: directory does not exist", + real_dir.display() + ); + } + continue; + } + + self_clone.options.wasi.map_dir(alias, real_dir.clone()); + } + } + + self_clone.path = pathbuf; + } + #[cfg(feature = "debug")] if self.debug { - logging::set_up_logging(self.verbose.unwrap_or(0)).unwrap(); + logging::set_up_logging(self_clone.verbose.unwrap_or(0)).unwrap(); } - self.inner_execute().with_context(|| { + self_clone.inner_execute().with_context(|| { format!( "failed to run `{}`{}", - self.path.display(), + self_clone.path.display(), if CompilerType::enabled().is_empty() { " (no compilers enabled)" } else { @@ -589,6 +560,19 @@ impl Run { .collect::>>()?; Ok(func.call(ctx, &invoke_args)?) } +} + +impl Run { + /// Executes the `wasmer run` command + pub fn execute(&self) -> Result<(), anyhow::Error> { + // downloads and installs the package if necessary + let path_to_run = self.path.download_and_get_filepath()?; + RunWithPathBuf { + path: path_to_run, + options: self.options.clone(), + } + .execute() + } /// Create Run instance for arguments/env, /// assuming we're being run from a CFP binfmt interpreter. @@ -602,364 +586,30 @@ impl Run { #[cfg(target_os = "linux")] fn from_binfmt_args_fallible() -> Result { - let argv = std::env::args_os().collect::>(); + let argv = std::env::args().collect::>(); let (_interpreter, executable, original_executable, args) = match &argv[..] { [a, b, c, d @ ..] => (a, b, c, d), _ => { bail!("Wasmer binfmt interpreter needs at least three arguments (including $0) - must be registered as binfmt interpreter with the CFP flags. (Got arguments: {:?})", argv); } }; - // TODO: Optimally, args and env would be passed as an UTF-8 Vec. - // (Can be pulled out of std::os::unix::ffi::OsStrExt) - // But I don't want to duplicate or rewrite run.rs today. - let args = args - .iter() - .enumerate() - .map(|(i, s)| { - s.clone().into_string().map_err(|s| { - anyhow!( - "Cannot convert argument {} ({:?}) to UTF-8 string", - i + 1, - s - ) - }) - }) - .collect::>>()?; - let original_executable = original_executable - .clone() - .into_string() - .map_err(|s| anyhow!("Cannot convert executable name {:?} to UTF-8 string", s))?; let store = StoreOptions::default(); // TODO: store.compiler.features.all = true; ? Ok(Self { - path: executable.into(), + // unwrap is safe, since parsing never fails + path: PackageSource::parse(executable).unwrap(), options: RunWithoutFile { - args, - command_name: Some(original_executable), + args: args.to_vec(), + command_name: Some(original_executable.to_string()), store, wasi: Wasi::for_binfmt_interpreter()?, ..Default::default() }, }) } + #[cfg(not(target_os = "linux"))] fn from_binfmt_args_fallible() -> Result { bail!("binfmt_misc is only available on linux.") } } - -fn start_spinner(msg: String) -> Option { - if !isatty::stdout_isatty() { - return None; - } - #[cfg(target_os = "windows")] - { - use colored::control; - let _ = control::set_virtual_terminal(true); - } - Some(spinoff::Spinner::new( - spinoff::Spinners::Dots, - msg, - spinoff::Color::White, - )) -} - -/// Before looking up a command from the registry, try to see if we have -/// the command already installed -fn try_run_local_command( - args: &[String], - sv: &SplitVersion, - debug_msgs_allowed: bool, -) -> Result<(), ExecuteLocalPackageError> { - let result = wasmer_registry::try_finding_local_command(&sv.original).ok_or_else(|| { - ExecuteLocalPackageError::BeforeExec(anyhow::anyhow!( - "could not find command {} locally", - sv.original - )) - })?; - let package_dir = result - .get_path() - .map_err(|e| ExecuteLocalPackageError::BeforeExec(anyhow::anyhow!("{e}")))?; - - // Try auto-installing the remote package - let args_without_package = fixup_args(args, &sv.original); - let mut run_args = RunWithoutFile::try_parse_from(args_without_package.iter()) - .map_err(|e| ExecuteLocalPackageError::DuringExec(e.into()))?; - run_args.command_name = sv.command.clone(); - - run_args - .into_run_args(package_dir, sv.command.as_deref(), debug_msgs_allowed) - .map_err(ExecuteLocalPackageError::DuringExec)? - .execute() - .map_err(ExecuteLocalPackageError::DuringExec) -} - -pub(crate) fn try_autoinstall_package( - args: &[String], - sv: &SplitVersion, - package: Option, - force_install: bool, -) -> Result<(), anyhow::Error> { - use std::io::Write; - let mut sp = start_spinner(format!("Installing package {} ...", sv.package)); - let debug_msgs_allowed = sp.is_some(); - let v = sv.version.as_deref(); - let result = wasmer_registry::install_package( - sv.registry.as_deref(), - &sv.package, - v, - package, - force_install, - ); - if let Some(sp) = sp.take() { - sp.clear(); - } - let _ = std::io::stdout().flush(); - let (_, package_dir) = match result { - Ok(o) => o, - Err(e) => { - return Err(anyhow::anyhow!("{e}")); - } - }; - - // Try auto-installing the remote package - let args_without_package = fixup_args(args, &sv.original); - let mut run_args = RunWithoutFile::try_parse_from(args_without_package.iter())?; - run_args.command_name = sv.command.clone(); - - run_args - .into_run_args(package_dir, sv.command.as_deref(), debug_msgs_allowed)? - .execute() -} - -// We need to distinguish between errors that happen -// before vs. during execution -enum ExecuteLocalPackageError { - BeforeExec(anyhow::Error), - DuringExec(anyhow::Error), -} - -fn try_execute_local_package( - args: &[String], - sv: &SplitVersion, - debug_msgs_allowed: bool, -) -> Result<(), ExecuteLocalPackageError> { - let package = wasmer_registry::get_local_package(None, &sv.package, sv.version.as_deref()) - .ok_or_else(|| { - ExecuteLocalPackageError::BeforeExec(anyhow::anyhow!("no local package {sv:?} found")) - })?; - - let package_dir = package - .get_path() - .map_err(|e| ExecuteLocalPackageError::BeforeExec(anyhow::anyhow!("{e}")))?; - - // Try finding the local package - let args_without_package = fixup_args(args, &sv.original); - - RunWithoutFile::try_parse_from(args_without_package.iter()) - .map_err(|e| ExecuteLocalPackageError::DuringExec(e.into()))? - .into_run_args(package_dir, sv.command.as_deref(), debug_msgs_allowed) - .map_err(ExecuteLocalPackageError::DuringExec)? - .execute() - .map_err(|e| ExecuteLocalPackageError::DuringExec(e.context(anyhow::anyhow!("{}", sv)))) -} - -fn try_lookup_command(sv: &mut SplitVersion) -> Result { - use std::io::Write; - let mut sp = start_spinner(format!("Looking up command {} ...", sv.package)); - - for registry in wasmer_registry::get_all_available_registries().unwrap_or_default() { - let result = wasmer_registry::query_command_from_registry(®istry, &sv.package); - if let Some(s) = sp.take() { - s.clear(); - } - let _ = std::io::stdout().flush(); - let command = sv.package.clone(); - if let Ok(o) = result { - sv.package = o.package.clone(); - sv.version = Some(o.version.clone()); - sv.command = Some(command); - return Ok(o); - } - } - - if let Some(sp) = sp.take() { - sp.clear(); - } - let _ = std::io::stdout().flush(); - Err(anyhow::anyhow!("command {sv} not found")) -} - -/// Removes the difference between "wasmer run {file} arg1 arg2" and "wasmer {file} arg1 arg2" -fn fixup_args(args: &[String], command: &str) -> Vec { - let mut args_without_package = args.to_vec(); - if args_without_package.get(1).map(|s| s.as_str()) == Some(command) { - let _ = args_without_package.remove(1); - } else if args_without_package.get(2).map(|s| s.as_str()) == Some(command) { - let _ = args_without_package.remove(1); - let _ = args_without_package.remove(1); - } - args_without_package -} - -#[test] -fn test_fixup_args() { - let first_args = vec![ - format!("wasmer"), - format!("run"), - format!("python/python"), - format!("--arg1"), - format!("--arg2"), - ]; - - let second_args = vec![ - format!("wasmer"), // no "run" - format!("python/python"), - format!("--arg1"), - format!("--arg2"), - ]; - - let arg1_transformed = fixup_args(&first_args, "python/python"); - let arg2_transformed = fixup_args(&second_args, "python/python"); - - assert_eq!(arg1_transformed, arg2_transformed); -} - -pub(crate) fn try_run_package_or_file( - args: &[String], - r: &Run, - debug: bool, -) -> Result<(), anyhow::Error> { - let debug_msgs_allowed = isatty::stdout_isatty(); - - // Check "r.path" is a file or a package / command name - if r.path.exists() { - if r.path.is_dir() && r.path.join("wapm.toml").exists() { - let args_without_package = fixup_args(args, &format!("{}", r.path.display())); - return RunWithoutFile::try_parse_from(args_without_package.iter())? - .into_run_args( - r.path.clone(), - r.command_name.as_deref(), - debug_msgs_allowed, - )? - .execute(); - } - return r.execute(); - } - - // c:// might be parsed as a URL on Windows - let url_string = format!("{}", r.path.display()); - if let Ok(url) = url::Url::parse(&url_string) { - if url.scheme() == "http" || url.scheme() == "https" { - match try_run_url(&url, args, r, debug) { - Err(ExecuteLocalPackageError::BeforeExec(_)) => {} - Err(ExecuteLocalPackageError::DuringExec(e)) => return Err(e), - Ok(o) => return Ok(o), - } - } - } - - let package = format!("{}", r.path.display()); - - let mut is_fake_sv = false; - let mut sv = match SplitVersion::parse(&package) { - Ok(o) => o, - Err(_) => { - let mut fake_sv = SplitVersion { - original: package.to_string(), - registry: None, - package: package.to_string(), - version: None, - command: None, - }; - is_fake_sv = true; - match try_run_local_command(args, &fake_sv, debug) { - Ok(()) => return Ok(()), - Err(ExecuteLocalPackageError::DuringExec(e)) => return Err(e), - _ => {} - } - match try_lookup_command(&mut fake_sv) { - Ok(o) => SplitVersion { - original: package.to_string(), - registry: None, - package: o.package, - version: Some(o.version), - command: r.command_name.clone(), - }, - Err(e) => { - return Err( - anyhow::anyhow!("No package for command {package:?} found, file {package:?} not found either") - .context(e) - .context(anyhow::anyhow!("{}", r.path.display())) - ); - } - } - } - }; - - if sv.command.is_none() { - sv.command = r.command_name.clone(); - } - - if sv.command.is_none() && is_fake_sv { - sv.command = Some(package); - } - - let mut package_download_info = None; - if !sv.package.contains('/') { - if let Ok(o) = try_lookup_command(&mut sv) { - package_download_info = Some(o); - } - } - - match try_execute_local_package(args, &sv, debug_msgs_allowed) { - Ok(o) => return Ok(o), - Err(ExecuteLocalPackageError::DuringExec(e)) => return Err(e), - _ => {} - } - - if debug && isatty::stdout_isatty() { - eprintln!("finding local package {} failed", sv); - } - - // else: local package not found - try to download and install package - try_autoinstall_package(args, &sv, package_download_info, r.force_install) -} - -fn try_run_url( - url: &Url, - _args: &[String], - r: &Run, - _debug: bool, -) -> Result<(), ExecuteLocalPackageError> { - let checksum = wasmer_registry::get_remote_webc_checksum(url).map_err(|e| { - ExecuteLocalPackageError::BeforeExec(anyhow::anyhow!("error fetching {url}: {e}")) - })?; - - let packages = wasmer_registry::get_all_installed_webc_packages(); - - if !packages.iter().any(|p| p.checksum == checksum) { - let sp = start_spinner(format!("Installing {}", url)); - - let result = wasmer_registry::install_webc_package(url, &checksum); - - result.map_err(|e| { - ExecuteLocalPackageError::BeforeExec(anyhow::anyhow!("error fetching {url}: {e}")) - })?; - - if let Some(sp) = sp { - sp.clear(); - } - } - - let webc_dir = wasmer_registry::get_webc_dir(); - - let webc_install_path = webc_dir - .context("Error installing package: no webc dir") - .map_err(ExecuteLocalPackageError::BeforeExec)? - .join(checksum); - - let mut r = r.clone(); - r.path = webc_install_path; - r.execute().map_err(ExecuteLocalPackageError::DuringExec) -} diff --git a/lib/cli/src/lib.rs b/lib/cli/src/lib.rs index 7a80b9fae..5129d48be 100644 --- a/lib/cli/src/lib.rs +++ b/lib/cli/src/lib.rs @@ -24,6 +24,7 @@ pub mod c_gen; pub mod cli; #[cfg(feature = "debug")] pub mod logging; +pub mod package_source; pub mod store; pub mod suggestions; pub mod utils; diff --git a/lib/cli/src/package_source.rs b/lib/cli/src/package_source.rs new file mode 100644 index 000000000..6bb7cdbcd --- /dev/null +++ b/lib/cli/src/package_source.rs @@ -0,0 +1,191 @@ +//! Module for parsing and installing packages + +use anyhow::Context; +use std::path::{Path, PathBuf}; +use std::str::FromStr; +use url::Url; + +/// Source of a package +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] +pub enum PackageSource { + /// Download from a URL + Url(Url), + /// Run a local file + File(String), + /// Download from a package + Package(wasmer_registry::Package), +} + +impl Default for PackageSource { + fn default() -> Self { + PackageSource::File(String::new()) + } +} + +impl FromStr for PackageSource { + type Err = String; + + fn from_str(s: &str) -> Result { + Self::parse(s) + } +} + +impl PackageSource { + /// Parses a package source and transforms it to a URL or a File + pub fn parse(s: &str) -> Result { + // If the file is a http:// URL, run the URL + if let Ok(url) = url::Url::parse(s) { + if url.scheme() == "http" || url.scheme() == "https" { + return Ok(Self::Url(url)); + } + } + + Ok(match wasmer_registry::Package::from_str(s) { + Ok(o) => Self::Package(o), + Err(_) => Self::File(s.to_string()), + }) + } + + /// Downloads the package (if any) to the installation directory, returns the path + /// of the package directory (containing the wapm.toml) + pub fn download_and_get_filepath(&self) -> Result { + let url = match self { + Self::File(f) => { + let path = Path::new(&f).to_path_buf(); + return if path.exists() { + Ok(path) + } else { + Err(anyhow::anyhow!( + "invalid package name, could not find file {f}" + )) + }; + } + Self::Url(u) => { + if let Some(path) = wasmer_registry::Package::is_url_already_installed(u) { + return Ok(path); + } else { + u.clone() + } + } + Self::Package(p) => { + let package_path = Path::new(&p.file()).to_path_buf(); + if package_path.exists() { + return Ok(package_path); + } else if let Some(path) = p.already_installed() { + return Ok(path); + } else { + p.url()? + } + } + }; + + let extra = if let Self::Package(p) = self { + format!(", file {} does not exist either", p.file()) + } else { + String::new() + }; + + let mut sp = start_spinner(format!("Installing package {url} ...")); + let opt_path = wasmer_registry::install_package(&url); + if let Some(sp) = sp.take() { + use std::io::Write; + sp.clear(); + let _ = std::io::stdout().flush(); + } + + let path = opt_path + .with_context(|| anyhow::anyhow!("could not install package from URL {url}{extra}"))?; + + Ok(path) + } +} + +fn start_spinner(msg: String) -> Option { + if !isatty::stdout_isatty() { + return None; + } + #[cfg(target_os = "windows")] + { + use colored::control; + let _ = control::set_virtual_terminal(true); + } + Some(spinoff::Spinner::new( + spinoff::Spinners::Dots, + msg, + spinoff::Color::White, + )) +} + +#[test] +fn test_package_source() { + assert_eq!( + PackageSource::parse("registry.wapm.io/graphql/python/python").unwrap(), + PackageSource::File("registry.wapm.io/graphql/python/python".to_string()), + ); + + assert_eq!( + PackageSource::parse("/absolute/path/test.wasm").unwrap(), + PackageSource::File("/absolute/path/test.wasm".to_string()), + ); + + assert_eq!( + PackageSource::parse("C://absolute/path/test.wasm").unwrap(), + PackageSource::File("C://absolute/path/test.wasm".to_string()), + ); + + assert_eq!( + PackageSource::parse("namespace/name@latest").unwrap(), + PackageSource::Package(wasmer_registry::Package { + namespace: "namespace".to_string(), + name: "name".to_string(), + version: Some("latest".to_string()), + }) + ); + + assert_eq!( + PackageSource::parse("namespace/name@latest:command").unwrap(), + PackageSource::File("namespace/name@latest:command".to_string()), + ); + + assert_eq!( + PackageSource::parse("namespace/name@1.0.2").unwrap(), + PackageSource::Package(wasmer_registry::Package { + namespace: "namespace".to_string(), + name: "name".to_string(), + version: Some("1.0.2".to_string()), + }) + ); + + assert_eq!( + PackageSource::parse("namespace/name@1.0.2-rc.2").unwrap(), + PackageSource::Package(wasmer_registry::Package { + namespace: "namespace".to_string(), + name: "name".to_string(), + version: Some("1.0.2-rc.2".to_string()), + }) + ); + + assert_eq!( + PackageSource::parse("namespace/name").unwrap(), + PackageSource::Package(wasmer_registry::Package { + namespace: "namespace".to_string(), + name: "name".to_string(), + version: None, + }) + ); + + assert_eq!( + PackageSource::parse("https://wapm.io/syrusakbary/python").unwrap(), + PackageSource::Url(url::Url::parse("https://wapm.io/syrusakbary/python").unwrap()), + ); + + assert_eq!( + PackageSource::parse("command").unwrap(), + PackageSource::File("command".to_string()), + ); + + assert_eq!( + PackageSource::parse("python@latest").unwrap(), + PackageSource::File("python@latest".to_string()), + ); +} diff --git a/lib/compiler-cranelift/Cargo.toml b/lib/compiler-cranelift/Cargo.toml index 2968e65e0..425bc3873 100644 --- a/lib/compiler-cranelift/Cargo.toml +++ b/lib/compiler-cranelift/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer-compiler-cranelift" -version = "3.0.2" +version = "3.1.0" description = "Cranelift compiler for Wasmer WebAssembly runtime" categories = ["wasm"] keywords = ["wasm", "webassembly", "compiler", "cranelift"] @@ -12,8 +12,8 @@ readme = "README.md" edition = "2018" [dependencies] -wasmer-compiler = { path = "../compiler", version = "=3.0.2", features = ["translator", "compiler"], default-features = false } -wasmer-types = { path = "../types", version = "=3.0.2", default-features = false, features = ["std"] } +wasmer-compiler = { path = "../compiler", version = "=3.1.0", features = ["translator", "compiler"], default-features = false } +wasmer-types = { path = "../types", version = "=3.1.0", default-features = false, features = ["std"] } cranelift-entity = { version = "0.86.1", default-features = false } cranelift-codegen = { version = "0.86.1", default-features = false, features = ["x86", "arm64"] } cranelift-frontend = { version = "0.86.1", default-features = false } diff --git a/lib/compiler-llvm/Cargo.toml b/lib/compiler-llvm/Cargo.toml index 87a827559..1f0330c0f 100644 --- a/lib/compiler-llvm/Cargo.toml +++ b/lib/compiler-llvm/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer-compiler-llvm" -version = "3.0.2" +version = "3.1.0" description = "LLVM compiler for Wasmer WebAssembly runtime" categories = ["wasm"] keywords = ["wasm", "webassembly", "compiler", "llvm"] @@ -12,11 +12,11 @@ readme = "README.md" edition = "2018" [dependencies] -wasmer-compiler = { path = "../compiler", version = "=3.0.2", features = [ +wasmer-compiler = { path = "../compiler", version = "=3.1.0", features = [ "translator", "compiler" ] } -wasmer-vm = { path = "../vm", version = "=3.0.2" } -wasmer-types = { path = "../types", version = "=3.0.2" } +wasmer-vm = { path = "../vm", version = "=3.1.0" } +wasmer-types = { path = "../types", version = "=3.1.0" } target-lexicon = { version = "0.12.2", default-features = false } smallvec = "1.6" object = { version = "0.28.3", default-features = false, features = ["read"] } diff --git a/lib/compiler-singlepass/Cargo.toml b/lib/compiler-singlepass/Cargo.toml index 9362235ca..7f146863f 100644 --- a/lib/compiler-singlepass/Cargo.toml +++ b/lib/compiler-singlepass/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer-compiler-singlepass" -version = "3.0.2" +version = "3.1.0" description = "Singlepass compiler for Wasmer WebAssembly runtime" categories = ["wasm"] keywords = ["wasm", "webassembly", "compiler", "singlepass"] @@ -12,8 +12,8 @@ readme = "README.md" edition = "2018" [dependencies] -wasmer-compiler = { path = "../compiler", version = "=3.0.2", features = ["translator", "compiler"], default-features = false } -wasmer-types = { path = "../types", version = "=3.0.2", default-features = false, features = ["std"] } +wasmer-compiler = { path = "../compiler", version = "=3.1.0", features = ["translator", "compiler"], default-features = false } +wasmer-types = { path = "../types", version = "=3.1.0", default-features = false, features = ["std"] } hashbrown = { version = "0.11", optional = true } gimli = { version = "0.26", optional = true } enumset = "1.0.2" diff --git a/lib/compiler-singlepass/src/emitter_arm64.rs b/lib/compiler-singlepass/src/emitter_arm64.rs index 074ae0acd..948fe793c 100644 --- a/lib/compiler-singlepass/src/emitter_arm64.rs +++ b/lib/compiler-singlepass/src/emitter_arm64.rs @@ -1303,6 +1303,12 @@ impl EmitterARM64 for Assembler { let masked = 0xffff & (val >> offset); if (masked << offset) == val { dynasm!(self ; movz X(dst), masked as u32, LSL offset); + } else if val >> 16 == 0xffff_ffff_ffff { + let val: u16 = !((val & 0xffff) as u16); + dynasm!(self ; movn X(dst), val as u32); + } else if val >> 16 == 0xffff { + let val: u16 = !((val & 0xffff) as u16); + dynasm!(self ; movn W(dst), val as u32); } else { dynasm!(self ; movz W(dst), (val&0xffff) as u32); let val = val >> 16; @@ -1336,13 +1342,13 @@ impl EmitterARM64 for Assembler { let src1 = src1.into_index() as u32; let src2 = src2.into_index() as u32; let dst = dst.into_index() as u32; - dynasm!(self ; add X(dst), X(src1), X(src2)); + dynasm!(self ; add X(dst), X(src1), X(src2), UXTX); } (Size::S32, Location::GPR(src1), Location::GPR(src2), Location::GPR(dst)) => { let src1 = src1.into_index() as u32; let src2 = src2.into_index() as u32; let dst = dst.into_index() as u32; - dynasm!(self ; add W(dst), W(src1), W(src2)); + dynasm!(self ; add W(dst), W(src1), W(src2), UXTX); } (Size::S64, Location::GPR(src1), Location::Imm8(imm), Location::GPR(dst)) | (Size::S64, Location::Imm8(imm), Location::GPR(src1), Location::GPR(dst)) => { @@ -1406,13 +1412,13 @@ impl EmitterARM64 for Assembler { let src1 = src1.into_index() as u32; let src2 = src2.into_index() as u32; let dst = dst.into_index() as u32; - dynasm!(self ; sub X(dst), X(src1), X(src2)); + dynasm!(self ; sub X(dst), X(src1), X(src2), UXTX); } (Size::S32, Location::GPR(src1), Location::GPR(src2), Location::GPR(dst)) => { let src1 = src1.into_index() as u32; let src2 = src2.into_index() as u32; let dst = dst.into_index() as u32; - dynasm!(self ; sub W(dst), W(src1), W(src2)); + dynasm!(self ; sub W(dst), W(src1), W(src2), UXTX); } (Size::S64, Location::GPR(src1), Location::Imm8(imm), Location::GPR(dst)) => { let src1 = src1.into_index() as u32; @@ -3257,24 +3263,17 @@ pub fn gen_std_trampoline_arm64( #[allow(clippy::single_match)] match calling_convention { CallingConvention::AppleAarch64 => { - match sz { - Size::S8 => (), - Size::S16 => { - if caller_stack_offset & 1 != 0 { - caller_stack_offset = (caller_stack_offset + 1) & !1; - } - } - Size::S32 => { - if caller_stack_offset & 3 != 0 { - caller_stack_offset = (caller_stack_offset + 3) & !3; - } - } - Size::S64 => { - if caller_stack_offset & 7 != 0 { - caller_stack_offset = (caller_stack_offset + 7) & !7; - } - } - }; + let sz = 1 + << match sz { + Size::S8 => 0, + Size::S16 => 1, + Size::S32 => 2, + Size::S64 => 3, + }; + // align first + if sz > 1 && caller_stack_offset & (sz - 1) != 0 { + caller_stack_offset = (caller_stack_offset + (sz - 1)) & !(sz - 1); + } } _ => (), }; @@ -3291,12 +3290,13 @@ pub fn gen_std_trampoline_arm64( )?; match calling_convention { CallingConvention::AppleAarch64 => { - caller_stack_offset += match sz { - Size::S8 => 1, - Size::S16 => 2, - Size::S32 => 4, - Size::S64 => 8, - }; + caller_stack_offset += 1 + << match sz { + Size::S8 => 0, + Size::S16 => 1, + Size::S32 => 2, + Size::S64 => 3, + }; } _ => { caller_stack_offset += 8; diff --git a/lib/compiler-singlepass/src/machine_arm64.rs b/lib/compiler-singlepass/src/machine_arm64.rs index 1f0c5b95f..b07e0f46e 100644 --- a/lib/compiler-singlepass/src/machine_arm64.rs +++ b/lib/compiler-singlepass/src/machine_arm64.rs @@ -1760,16 +1760,26 @@ impl Machine for MachineARM64 { .emit_stur(Size::S64, location, GPR::X29, -stack_offset)?; } else { let tmp = GPR::X17; - self.assembler - .emit_mov_imm(Location::GPR(tmp), (stack_offset as i64) as u64)?; - self.assembler.emit_sub( - Size::S64, - Location::GPR(GPR::X29), - Location::GPR(tmp), - Location::GPR(tmp), - )?; - self.assembler - .emit_str(Size::S64, location, Location::GPR(tmp))?; + if stack_offset < 0x1_0000 { + self.assembler + .emit_mov_imm(Location::GPR(tmp), (-stack_offset as i64) as u64)?; + self.assembler.emit_str( + Size::S64, + location, + Location::Memory2(GPR::X29, tmp, Multiplier::One, 0), + )?; + } else { + self.assembler + .emit_mov_imm(Location::GPR(tmp), (stack_offset as i64) as u64)?; + self.assembler.emit_sub( + Size::S64, + Location::GPR(GPR::X29), + Location::GPR(tmp), + Location::GPR(tmp), + )?; + self.assembler + .emit_str(Size::S64, location, Location::GPR(tmp))?; + } } match location { Location::GPR(x) => self.emit_unwind_op(UnwindOps::SaveRegister { @@ -1809,18 +1819,19 @@ impl Machine for MachineARM64 { 6 => Location::GPR(GPR::X6), 7 => Location::GPR(GPR::X7), _ => { - let sz = match sz { - Size::S8 => 0, - Size::S16 => 1, - Size::S32 => 2, - Size::S64 => 3, - }; + let sz = 1 + << match sz { + Size::S8 => 0, + Size::S16 => 1, + Size::S32 => 2, + Size::S64 => 3, + }; // align first - if sz > 1 && *stack_args & !((1 << sz) - 1) != 0 { - *stack_args = (*stack_args + ((1 << sz) - 1)) & !((1 << sz) - 1); + if sz > 1 && *stack_args & (sz - 1) != 0 { + *stack_args = (*stack_args + (sz - 1)) & !(sz - 1); } let loc = Location::Memory(GPR::XzrSp, *stack_args as i32); - *stack_args += 1 << sz; + *stack_args += sz; loc } }, @@ -1860,18 +1871,19 @@ impl Machine for MachineARM64 { 6 => Location::GPR(GPR::X6), 7 => Location::GPR(GPR::X7), _ => { - let sz = match sz { - Size::S8 => 0, - Size::S16 => 1, - Size::S32 => 2, - Size::S64 => 3, - }; + let sz = 1 + << match sz { + Size::S8 => 0, + Size::S16 => 1, + Size::S32 => 2, + Size::S64 => 3, + }; // align first - if sz > 1 && *stack_args & !((1 << sz) - 1) != 0 { - *stack_args = (*stack_args + ((1 << sz) - 1)) & !((1 << sz) - 1); + if sz > 1 && *stack_args & (sz - 1) != 0 { + *stack_args = (*stack_args + (sz - 1)) & !(sz - 1); } let loc = Location::Memory(GPR::X29, 16 * 2 + *stack_args as i32); - *stack_args += 1 << sz; + *stack_args += sz; loc } }, diff --git a/lib/compiler-singlepass/src/machine_x64.rs b/lib/compiler-singlepass/src/machine_x64.rs index dad625c69..22dba2357 100644 --- a/lib/compiler-singlepass/src/machine_x64.rs +++ b/lib/compiler-singlepass/src/machine_x64.rs @@ -45,7 +45,7 @@ impl AssemblerX64 { Some(CpuFeature::SSE42) } else { return Err(CompileError::UnsupportedTarget( - "x86_64 without AVX or SSE 4.2".to_string(), + "x86_64 without AVX or SSE 4.2, use -m avx to enable".to_string(), )); } }; diff --git a/lib/compiler/Cargo.toml b/lib/compiler/Cargo.toml index 68096ee13..a528eaa75 100644 --- a/lib/compiler/Cargo.toml +++ b/lib/compiler/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer-compiler" -version = "3.0.2" +version = "3.1.0" description = "Base compiler abstraction for Wasmer WebAssembly runtime" categories = ["wasm", "no-std"] keywords = ["wasm", "webassembly", "compiler"] @@ -11,8 +11,8 @@ readme = "README.md" edition = "2018" [dependencies] -wasmer-types = { path = "../types", version = "=3.0.2", default-features = false } -wasmer-object = { path = "../object", version = "=3.0.2", optional = true } +wasmer-types = { path = "../types", version = "=3.1.0", default-features = false } +wasmer-object = { path = "../object", version = "=3.1.0", optional = true } wasmparser = { version = "0.83", optional = true, default-features = false } enumset = "1.0.2" hashbrown = { version = "0.11", optional = true } @@ -32,7 +32,7 @@ leb128 = "0.2" enum-iterator = "0.7.0" [target.'cfg(not(target_arch = "wasm32"))'.dependencies] -wasmer-vm = { path = "../vm", version = "=3.0.2" } +wasmer-vm = { path = "../vm", version = "=3.1.0" } region = { version = "3.0" } [target.'cfg(target_os = "windows")'.dependencies] diff --git a/lib/derive/Cargo.toml b/lib/derive/Cargo.toml index 2a697ef80..d13ffc9aa 100644 --- a/lib/derive/Cargo.toml +++ b/lib/derive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer-derive" -version = "3.0.2" +version = "3.1.0" description = "Wasmer derive macros" authors = ["Wasmer Engineering Team "] repository = "https://github.com/wasmerio/wasmer" diff --git a/lib/emscripten/Cargo.toml b/lib/emscripten/Cargo.toml index 6c0446f27..08e9994cb 100644 --- a/lib/emscripten/Cargo.toml +++ b/lib/emscripten/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer-emscripten" -version = "3.0.2" +version = "3.1.0" description = "Emscripten implementation library for Wasmer WebAssembly runtime" categories = ["wasm", "os"] keywords = ["wasm", "webassembly", "abi", "emscripten", "posix"] @@ -16,8 +16,8 @@ lazy_static = "1.4" libc = "^0.2" log = "0.4" time = { version = "0.2", features = ["std"] } -wasmer = { path = "../api", version = "=3.0.2", default-features = false, features = ["sys", "compiler"] } -wasmer-types = { path = "../types", version = "=3.0.2" } +wasmer = { path = "../api", version = "=3.1.0", default-features = false, features = ["sys", "compiler"] } +wasmer-types = { path = "../types", version = "=3.1.0" } [target.'cfg(windows)'.dependencies] getrandom = "0.2" diff --git a/lib/middlewares/Cargo.toml b/lib/middlewares/Cargo.toml index 5dadce3b5..727447f8e 100644 --- a/lib/middlewares/Cargo.toml +++ b/lib/middlewares/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer-middlewares" -version = "3.0.2" +version = "3.1.0" authors = ["Wasmer Engineering Team "] description = "A collection of various useful middlewares" license = "MIT OR Apache-2.0 WITH LLVM-exception" @@ -11,12 +11,12 @@ readme = "README.md" edition = "2018" [dependencies] -wasmer = { path = "../api", version = "=3.0.2", default-features = false, features = ["compiler"] } -wasmer-types = { path = "../types", version = "=3.0.2" } -wasmer-vm = { path = "../vm", version = "=3.0.2" } +wasmer = { path = "../api", version = "=3.1.0", default-features = false, features = ["compiler"] } +wasmer-types = { path = "../types", version = "=3.1.0" } +wasmer-vm = { path = "../vm", version = "=3.1.0" } [dev-dependencies] -wasmer = { path = "../api", version = "=3.0.2", features = ["compiler"] } +wasmer = { path = "../api", version = "=3.1.0", features = ["compiler"] } [badges] maintenance = { status = "actively-developed" } diff --git a/lib/object/Cargo.toml b/lib/object/Cargo.toml index 2a7ca2a1d..74a5a2b58 100644 --- a/lib/object/Cargo.toml +++ b/lib/object/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer-object" -version = "3.0.2" +version = "3.1.0" description = "Wasmer Native Object generator" categories = ["wasm"] keywords = ["wasm", "webassembly"] @@ -11,6 +11,6 @@ readme = "README.md" edition = "2018" [dependencies] -wasmer-types = { path = "../types", version = "=3.0.2" } +wasmer-types = { path = "../types", version = "=3.1.0" } object = { version = "0.28.3", default-features = false, features = ["write"] } thiserror = "1.0" diff --git a/lib/registry/Cargo.toml b/lib/registry/Cargo.toml index aa1204a93..9985e6902 100644 --- a/lib/registry/Cargo.toml +++ b/lib/registry/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer-registry" -version = "3.0.2" +version = "3.1.0" edition = "2021" license = "MIT" description = "Crate to interact with the wasmer registry (wapm.io), download packages, etc." @@ -30,3 +30,7 @@ hex = "0.4.3" tokio = "1.21.2" tempdir = "0.3.7" log = "0.4.17" +regex = "1.7.0" +fs_extra = "1.2.0" +filetime = "0.2.19" +tldextract = "0.6.0" diff --git a/lib/registry/src/lib.rs b/lib/registry/src/lib.rs index 5d2798671..4a7c18a2f 100644 --- a/lib/registry/src/lib.rs +++ b/lib/registry/src/lib.rs @@ -13,23 +13,21 @@ use anyhow::Context; use core::ops::Range; use reqwest::header::{ACCEPT, RANGE}; use std::fmt; -use std::io::Write; +use std::io::{Read, Write}; use std::path::{Path, PathBuf}; use std::time::Duration; -use std::{ - collections::BTreeMap, - fmt::{Display, Formatter}, -}; use url::Url; pub mod config; pub mod graphql; pub mod login; +pub mod package; pub mod queries; pub mod utils; pub use crate::{ config::{format_graphql, PartialWapmConfig}, + package::Package, queries::get_bindings_query::ProgrammingLanguage, }; @@ -49,31 +47,23 @@ pub struct PackageDownloadInfo { pub fn get_package_local_dir( #[cfg(test)] test_name: &str, - registry_host: &str, - name: &str, + url: &str, version: &str, -) -> Result { - if !name.contains('/') { - return Err(format!( - "package name has to be in the format namespace/package: {name:?}" - )); - } - let (namespace, name) = name - .split_once('/') - .ok_or_else(|| format!("missing namespace / name for {name:?}"))?; +) -> Option { #[cfg(test)] - let global_install_dir = get_global_install_dir(test_name, registry_host); + let checkouts_dir = get_checkouts_dir(test_name)?; #[cfg(not(test))] - let global_install_dir = get_global_install_dir(registry_host); - let install_dir = global_install_dir.ok_or_else(|| format!("no install dir for {name:?}"))?; - Ok(install_dir.join(namespace).join(name).join(version)) + let checkouts_dir = get_checkouts_dir()?; + let url_hash = Package::hash_url(url); + let dir = checkouts_dir.join(format!("{url_hash}@{version}")); + Some(dir) } pub fn try_finding_local_command(#[cfg(test)] test_name: &str, cmd: &str) -> Option { #[cfg(test)] - let local_packages = get_all_local_packages(test_name, None); + let local_packages = get_all_local_packages(test_name); #[cfg(not(test))] - let local_packages = get_all_local_packages(None); + let local_packages = get_all_local_packages(); for p in local_packages { #[cfg(not(test))] let commands = p.get_commands(); @@ -92,24 +82,12 @@ pub struct LocalPackage { pub registry: String, pub name: String, pub version: String, + pub path: PathBuf, } impl LocalPackage { pub fn get_path(&self, #[cfg(test)] test_name: &str) -> Result { - let host = url::Url::parse(&self.registry) - .ok() - .and_then(|o| o.host_str().map(|s| s.to_string())) - .unwrap_or_else(|| self.registry.clone()); - - #[cfg(test)] - { - get_package_local_dir(test_name, &host, &self.name, &self.version) - } - - #[cfg(not(test))] - { - get_package_local_dir(&host, &self.name, &self.version) - } + Ok(self.path.clone()) } pub fn get_commands(&self, #[cfg(test)] test_name: &str) -> Result, String> { #[cfg(not(test))] @@ -149,9 +127,20 @@ pub fn get_executable_file_from_path( Some(s) => commands.iter().find(|c| c.get_name() == s).ok_or_else(|| { anyhow::anyhow!("Cannot run {name}@{version}: package has no command {s:?}") })?, - None => commands.first().ok_or_else(|| { - anyhow::anyhow!("Cannot run {name}@{version}: package has no commands") - })?, + None => { + if commands.is_empty() { + Err(anyhow::anyhow!( + "Cannot run {name}@{version}: package has no commands" + )) + } else if commands.len() == 1 { + Ok(&commands[0]) + } else { + Err(anyhow::anyhow!(" -> wasmer run {name}@{version} --command-name={0}", commands.first().map(|f| f.get_name()).unwrap())) + .context(anyhow::anyhow!("{}", commands.iter().map(|c| format!("`{}`", c.get_name())).collect::>().join(", "))) + .context(anyhow::anyhow!("You can run any of those by using the --command-name=COMMAND flag")) + .context(anyhow::anyhow!("The `{name}@{version}` package doesn't have a default entrypoint, but has multiple available commands:")) + }? + } }; let module_name = entrypoint_module.get_module(); @@ -196,72 +185,44 @@ fn get_all_names_in_dir(dir: &PathBuf) -> Vec<(PathBuf, String)> { } /// Returns a list of all locally installed packages -pub fn get_all_local_packages( - #[cfg(test)] test_name: &str, - registry: Option<&str>, -) -> Vec { +pub fn get_all_local_packages(#[cfg(test)] test_name: &str) -> Vec { let mut packages = Vec::new(); - let registries = match registry { - Some(s) => vec![s.to_string()], - None => { - #[cfg(test)] - { - get_all_available_registries(test_name).unwrap_or_default() - } - #[cfg(not(test))] - { - get_all_available_registries().unwrap_or_default() - } - } - }; - - let mut registry_hosts = registries - .into_iter() - .filter_map(|s| url::Url::parse(&s).ok()?.host_str().map(|s| s.to_string())) - .collect::>(); #[cfg(not(test))] let checkouts_dir = get_checkouts_dir(); #[cfg(test)] let checkouts_dir = get_checkouts_dir(test_name); - let mut registries_in_root_dir = checkouts_dir - .as_ref() - .map(get_all_names_in_dir) - .unwrap_or_default() - .into_iter() - .filter_map(|(path, p)| if path.is_dir() { Some(p) } else { None }) - .collect(); + let checkouts_dir = match checkouts_dir { + Some(s) => s, + None => return packages, + }; - registry_hosts.append(&mut registries_in_root_dir); - registry_hosts.sort(); - registry_hosts.dedup(); - - for host in registry_hosts { - #[cfg(not(test))] - let global_install_dir = get_global_install_dir(&host); - #[cfg(test)] - let global_install_dir = get_global_install_dir(test_name, &host); - let root_dir = match global_install_dir { - Some(o) => o, + for (path, url_hash_with_version) in get_all_names_in_dir(&checkouts_dir) { + let s = match std::fs::read_to_string(path.join("wapm.toml")) { + Ok(o) => o, + Err(_) => continue, + }; + let manifest = match wapm_toml::Manifest::parse(&s) { + Ok(o) => o, + Err(_) => continue, + }; + let url_hash = match url_hash_with_version.split('@').next() { + Some(s) => s, None => continue, }; - - for (username_path, user_name) in get_all_names_in_dir(&root_dir) { - for (package_path, package_name) in get_all_names_in_dir(&username_path) { - for (version_path, package_version) in get_all_names_in_dir(&package_path) { - let _ = match std::fs::read_to_string(version_path.join("wapm.toml")) { - Ok(o) => o, - Err(_) => continue, - }; - packages.push(LocalPackage { - registry: host.clone(), - name: format!("{user_name}/{package_name}"), - version: package_version, - }); - } - } - } + let package = + Url::parse(&Package::unhash_url(url_hash)).map(|s| s.origin().ascii_serialization()); + let host = match package { + Ok(s) => s, + Err(_) => continue, + }; + packages.push(LocalPackage { + registry: host, + name: manifest.package.name, + version: manifest.package.version.to_string(), + path, + }); } packages @@ -269,14 +230,13 @@ pub fn get_all_local_packages( pub fn get_local_package( #[cfg(test)] test_name: &str, - registry: Option<&str>, name: &str, version: Option<&str>, ) -> Option { #[cfg(not(test))] - let local_packages = get_all_local_packages(registry); + let local_packages = get_all_local_packages(); #[cfg(test)] - let local_packages = get_all_local_packages(test_name, registry); + let local_packages = get_all_local_packages(test_name); local_packages .iter() @@ -309,7 +269,7 @@ pub fn query_command_from_registry( }); let response: get_package_by_command_query::ResponseData = execute_query(registry_url, "", &q) - .map_err(|e| format!("Error sending GetPackageByCommandQuery:  {e}"))?; + .map_err(|e| format!("Error sending GetPackageByCommandQuery: {e}"))?; let command = response .get_command @@ -342,7 +302,7 @@ pub enum QueryPackageError { } impl fmt::Display for QueryPackageError { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { QueryPackageError::ErrorSendingQuery(q) => write!(f, "error sending query: {q}"), QueryPackageError::NoPackageFound { name, version } => { @@ -380,194 +340,6 @@ pub enum GetIfPackageHasNewVersionResult { }, } -#[test] -fn test_get_if_package_has_new_version() { - const TEST_NAME: &str = "test_get_if_package_has_new_version"; - let fake_registry = "https://h0.com"; - let fake_name = "namespace0/project1"; - let fake_version = "1.0.0"; - - let package_path = get_package_local_dir(TEST_NAME, "h0.com", fake_name, fake_version).unwrap(); - let _ = std::fs::remove_file(&package_path.join("wapm.toml")); - let _ = std::fs::remove_file(&package_path.join("wapm.toml")); - - let r1 = get_if_package_has_new_version( - TEST_NAME, - fake_registry, - "namespace0/project1", - Some(fake_version.to_string()), - Duration::from_secs(5 * 60), - ); - - assert_eq!( - r1.unwrap(), - GetIfPackageHasNewVersionResult::PackageNotInstalledYet { - registry_url: fake_registry.to_string(), - namespace: "namespace0".to_string(), - name: "project1".to_string(), - version: Some(fake_version.to_string()), - } - ); - - let package_path = get_package_local_dir(TEST_NAME, "h0.com", fake_name, fake_version).unwrap(); - std::fs::create_dir_all(&package_path).unwrap(); - std::fs::write(&package_path.join("wapm.toml"), b"").unwrap(); - - let r1 = get_if_package_has_new_version( - TEST_NAME, - fake_registry, - "namespace0/project1", - Some(fake_version.to_string()), - Duration::from_secs(5 * 60), - ); - - assert_eq!( - r1.unwrap(), - GetIfPackageHasNewVersionResult::UseLocalAlreadyInstalled { - registry_host: "h0.com".to_string(), - namespace: "namespace0".to_string(), - name: "project1".to_string(), - version: fake_version.to_string(), - path: package_path, - } - ); -} - -/// Returns true if a package has a newer version -/// -/// Also returns true if the package is not installed yet. -pub fn get_if_package_has_new_version( - #[cfg(test)] test_name: &str, - registry_url: &str, - name: &str, - version: Option, - max_timeout: Duration, -) -> Result { - let host = match url::Url::parse(registry_url) { - Ok(o) => match o.host_str().map(|s| s.to_string()) { - Some(s) => s, - None => return Err(format!("invalid host: {registry_url}")), - }, - Err(_) => return Err(format!("invalid host: {registry_url}")), - }; - - let (namespace, name) = name - .split_once('/') - .ok_or_else(|| format!("missing namespace / name for {name:?}"))?; - - #[cfg(not(test))] - let global_install_dir = get_global_install_dir(&host); - #[cfg(test)] - let global_install_dir = get_global_install_dir(test_name, &host); - - let package_dir = global_install_dir.map(|path| path.join(namespace).join(name)); - - let package_dir = match package_dir { - Some(s) => s, - None => { - return Ok(GetIfPackageHasNewVersionResult::PackageNotInstalledYet { - registry_url: registry_url.to_string(), - namespace: namespace.to_string(), - name: name.to_string(), - version, - }) - } - }; - - // if version is specified: look if that specific version exists - if let Some(s) = version.as_ref() { - let installed_path = package_dir.join(s).join("wapm.toml"); - if installed_path.exists() { - return Ok(GetIfPackageHasNewVersionResult::UseLocalAlreadyInstalled { - registry_host: host, - namespace: namespace.to_string(), - name: name.to_string(), - version: s.clone(), - path: package_dir.join(s), - }); - } else { - return Ok(GetIfPackageHasNewVersionResult::PackageNotInstalledYet { - registry_url: registry_url.to_string(), - namespace: namespace.to_string(), - name: name.to_string(), - version: Some(s.clone()), - }); - } - } - - // version has not been explicitly specified: check if any package < duration exists - let read_dir = match std::fs::read_dir(&package_dir) { - Ok(o) => o, - Err(_) => { - return Ok(GetIfPackageHasNewVersionResult::PackageNotInstalledYet { - registry_url: registry_url.to_string(), - namespace: namespace.to_string(), - name: name.to_string(), - version, - }); - } - }; - - // all installed versions of this package - let all_installed_versions = read_dir - .filter_map(|entry| { - let entry = entry.ok()?; - let version = semver::Version::parse(entry.file_name().to_str()?).ok()?; - let modified = entry.metadata().ok()?.modified().ok()?; - let older_than_timeout = modified.elapsed().ok()? > max_timeout; - Some((version, older_than_timeout)) - }) - .collect::>(); - - if all_installed_versions.is_empty() { - // package not installed yet - Ok(GetIfPackageHasNewVersionResult::PackageNotInstalledYet { - registry_url: registry_url.to_string(), - namespace: namespace.to_string(), - name: name.to_string(), - version, - }) - } else if all_installed_versions - .iter() - .all(|(_, older_than_timeout)| *older_than_timeout) - { - // all packages are older than the timeout: there might be a new package available - return Ok(GetIfPackageHasNewVersionResult::LocalVersionMayBeOutdated { - registry_host: registry_url.to_string(), - namespace: namespace.to_string(), - name: name.to_string(), - installed_versions: all_installed_versions - .iter() - .map(|(key, old)| (format!("{key}"), *old)) - .collect::>(), - }); - } else { - // return the package that was younger than timeout - let younger_than_timeout_version = all_installed_versions - .iter() - .find(|(_, older_than_timeout)| !older_than_timeout) - .unwrap(); - let version = format!("{}", younger_than_timeout_version.0); - let installed_path = package_dir.join(&version).join("wapm.toml"); - if installed_path.exists() { - Ok(GetIfPackageHasNewVersionResult::UseLocalAlreadyInstalled { - registry_host: host, - namespace: namespace.to_string(), - name: name.to_string(), - version: version.clone(), - path: package_dir.join(&version), - }) - } else { - Ok(GetIfPackageHasNewVersionResult::PackageNotInstalledYet { - registry_url: registry_url.to_string(), - namespace: namespace.to_string(), - name: name.to_string(), - version: None, - }) - } - } -} - /// Returns the download info of the packages, on error returns all the available packages /// i.e. (("foo/python", "wapm.io"), ("bar/python" "wapm.io"))) pub fn query_package_from_registry( @@ -592,9 +364,7 @@ pub fn query_package_from_registry( })?; let v = response.package_version.as_ref().ok_or_else(|| { - QueryPackageError::ErrorSendingQuery(format!( - "Invalid response for crate {name:?}: no package version: {response:#?}" - )) + QueryPackageError::ErrorSendingQuery(format!("no package version for {name:?}")) })?; let manifest = toml::from_str::(&v.manifest).map_err(|e| { @@ -766,139 +536,67 @@ where Ok(()) } -/// Given a triple of [registry, name, version], downloads and installs the -/// .tar.gz if it doesn't yet exist, returns the (package dir, entrypoint .wasm file path) -pub fn install_package( - #[cfg(test)] test_name: &str, - registry: Option<&str>, - name: &str, - version: Option<&str>, - package_download_info: Option, - force_install: bool, -) -> Result<(LocalPackage, PathBuf), String> { - let package_info = match package_download_info { - Some(s) => s, - None => { - let registries = match registry { - Some(s) => vec![s.to_string()], - None => { - #[cfg(test)] - { - get_all_available_registries(test_name)? - } - #[cfg(not(test))] - { - get_all_available_registries()? - } - } - }; - let mut url_of_package = None; +/// Installs the .tar.gz if it doesn't yet exist, returns the +/// (package dir, entrypoint .wasm file path) +pub fn install_package(#[cfg(test)] test_name: &str, url: &Url) -> Result { + use fs_extra::dir::copy; - let version_str = match version { - None => name.to_string(), - Some(v) => format!("{name}@{v}"), - }; + let tempdir = tempdir::TempDir::new("download") + .map_err(|e| anyhow::anyhow!("could not create download temp dir: {e}"))?; - let registries_searched = registries - .iter() - .filter_map(|s| url::Url::parse(s).ok()) - .filter_map(|s| Some(s.host_str()?.to_string())) - .collect::>(); + let target_targz_path = tempdir.path().join("package.tar.gz"); + let unpacked_targz_path = tempdir.path().join("package"); + std::fs::create_dir_all(&unpacked_targz_path).map_err(|e| { + anyhow::anyhow!( + "could not create dir {}: {e}", + unpacked_targz_path.display() + ) + })?; - let mut errors = BTreeMap::new(); + get_targz_bytes(url, None, Some(target_targz_path.clone())) + .map_err(|e| anyhow::anyhow!("failed to download {url}: {e}"))?; - for r in registries.iter() { - if !force_install { - #[cfg(not(test))] - let package_has_new_version = get_if_package_has_new_version( - r, - name, - version.map(|s| s.to_string()), - Duration::from_secs(60 * 5), - )?; - #[cfg(test)] - let package_has_new_version = get_if_package_has_new_version( - test_name, - r, - name, - version.map(|s| s.to_string()), - Duration::from_secs(60 * 5), - )?; - if let GetIfPackageHasNewVersionResult::UseLocalAlreadyInstalled { - registry_host, - namespace, - name, - version, - path, - } = package_has_new_version - { - return Ok(( - LocalPackage { - registry: registry_host, - name: format!("{namespace}/{name}"), - version, - }, - path, - )); - } - } + try_unpack_targz( + target_targz_path.as_path(), + unpacked_targz_path.as_path(), + false, + ) + .with_context(|| anyhow::anyhow!("Could not unpack file downloaded from {url}"))?; - match query_package_from_registry(r, name, version) { - Ok(o) => { - url_of_package = Some((r, o)); - break; - } - Err(e) => { - errors.insert(r.clone(), e); - } - } - } + // read {unpacked}/wapm.toml to get the name + version number + let toml_path = unpacked_targz_path.join("wapm.toml"); + let toml = std::fs::read_to_string(&toml_path) + .map_err(|e| anyhow::anyhow!("error reading {}: {e}", toml_path.display()))?; + let toml_parsed = toml::from_str::(&toml) + .map_err(|e| anyhow::anyhow!("error parsing {}: {e}", toml_path.display()))?; - let errors = errors - .into_iter() - .map(|(registry, e)| format!(" {registry}: {e}")) - .collect::>() - .join("\r\n"); - - let (_, package_info) = url_of_package.ok_or_else(|| { - format!("Package {version_str} not found in registries {registries_searched:?}.\r\n\r\nErrors:\r\n\r\n{errors}") - })?; - - package_info - } - }; - - let host = url::Url::parse(&package_info.registry) - .map_err(|e| format!("invalid url: {}: {e}", package_info.registry))? - .host_str() - .ok_or_else(|| format!("invalid url: {}", package_info.registry))? - .to_string(); + let version = toml_parsed.package.version.to_string(); #[cfg(test)] - let dir = get_package_local_dir( - test_name, - &host, - &package_info.package, - &package_info.version, - )?; + let checkouts_dir = crate::get_checkouts_dir(test_name); #[cfg(not(test))] - let dir = get_package_local_dir(&host, &package_info.package, &package_info.version)?; + let checkouts_dir = crate::get_checkouts_dir(); - let version = package_info.version; - let name = package_info.package; + let checkouts_dir = checkouts_dir.ok_or_else(|| anyhow::anyhow!("no checkouts dir"))?; - if !dir.join("wapm.toml").exists() || force_install { - download_and_unpack_targz(&package_info.url, &dir, false).map_err(|e| format!("{e}"))?; - } + let installation_path = + checkouts_dir.join(format!("{}@{version}", Package::hash_url(url.as_ref()))); - Ok(( - LocalPackage { - registry: package_info.registry, - name, - version, - }, - dir, - )) + std::fs::create_dir_all(&installation_path) + .map_err(|e| anyhow::anyhow!("could not create installation path for {url}: {e}"))?; + + let mut options = fs_extra::dir::CopyOptions::new(); + options.content_only = true; + options.overwrite = true; + copy(&unpacked_targz_path, &installation_path, &options)?; + + #[cfg(not(target_os = "wasi"))] + let _ = filetime::set_file_mtime( + installation_path.join("wapm.toml"), + filetime::FileTime::now(), + ); + + Ok(installation_path) } pub fn whoami( @@ -1032,6 +730,7 @@ async fn install_webc_package_inner( let builder = reqwest::Client::builder(); let builder = crate::graphql::proxy::maybe_set_up_proxy(builder)?; builder + .redirect(reqwest::redirect::Policy::limited(10)) .build() .map_err(|e| anyhow::anyhow!("{e}")) .context("install_webc_package: failed to build reqwest Client")? @@ -1129,18 +828,18 @@ pub fn get_checksum_hash(bytes: &[u8]) -> String { while checksum.last().copied() == Some(0) { checksum.pop(); } - hex::encode(&checksum) + hex::encode(&checksum).chars().take(64).collect() } /// Returns the checksum of the .webc file, so that we can check whether the /// file is already installed before downloading it pub fn get_remote_webc_checksum(url: &Url) -> Result { let request_max_bytes = webc::WebC::get_signature_offset_start() + 4 + 1024 + 8 + 8; - let data = get_webc_bytes(url, Some(0..request_max_bytes)) - .with_context(|| format!("get_webc_bytes failed on {url}"))?; + let data = get_webc_bytes(url, Some(0..request_max_bytes), None) + .with_context(|| anyhow::anyhow!("note: use --registry to change the registry URL"))? + .unwrap(); let checksum = webc::WebC::get_checksum_bytes(&data) - .map_err(|e| anyhow::anyhow!("{e}")) - .context("get_checksum_bytes failed")? + .map_err(|e| anyhow::anyhow!("{e}"))? .to_vec(); Ok(get_checksum_hash(&checksum)) } @@ -1150,7 +849,7 @@ pub fn get_remote_webc_checksum(url: &Url) -> Result { pub fn get_remote_webc_manifest(url: &Url) -> Result { // Request up unti manifest size / manifest len let request_max_bytes = webc::WebC::get_signature_offset_start() + 4 + 1024 + 8 + 8; - let data = get_webc_bytes(url, Some(0..request_max_bytes))?; + let data = get_webc_bytes(url, Some(0..request_max_bytes), None)?.unwrap(); let checksum = webc::WebC::get_checksum_bytes(&data) .map_err(|e| anyhow::anyhow!("{e}")) .context("WebC::get_checksum_bytes failed")? @@ -1160,7 +859,8 @@ pub fn get_remote_webc_manifest(url: &Url) -> Result Result Result { +fn setup_client( + url: &Url, + application_type: &'static str, +) -> Result { let client = { let builder = reqwest::blocking::Client::builder(); let builder = crate::graphql::proxy::maybe_set_up_proxy_blocking(builder) .context("setup_webc_client")?; builder + .redirect(reqwest::redirect::Policy::limited(10)) .build() .map_err(|e| anyhow::anyhow!("{e}")) .context("setup_webc_client: builder.build() failed")? }; - Ok(client.get(url.clone()).header(ACCEPT, "application/webc")) + Ok(client.get(url.clone()).header(ACCEPT, application_type)) } -fn get_webc_bytes(url: &Url, range: Option>) -> Result, anyhow::Error> { +fn get_webc_bytes( + url: &Url, + range: Option>, + stream_response_into: Option, +) -> Result>, anyhow::Error> { + get_bytes(url, range, "application/webc", stream_response_into) +} + +fn get_targz_bytes( + url: &Url, + range: Option>, + stream_response_into: Option, +) -> Result>, anyhow::Error> { + get_bytes(url, range, "application/tar+gzip", stream_response_into) +} + +fn get_bytes( + url: &Url, + range: Option>, + application_type: &'static str, + stream_response_into: Option, +) -> Result>, anyhow::Error> { // curl -r 0-500 -L https://wapm.dev/syrusakbary/python -H "Accept: application/webc" --output python.webc - let mut res = setup_webc_client(url)?; + let mut res = setup_client(url, application_type)?; if let Some(range) = range.as_ref() { res = res.header(RANGE, format!("bytes={}-{}", range.start, range.end)); } - let res = res + let mut res = res .send() .map_err(|e| anyhow::anyhow!("{e}")) .context("send() failed")?; - let bytes = res - .bytes() - .map_err(|e| anyhow::anyhow!("{e}")) - .context("bytes() failed")?; - Ok(bytes.to_vec()) + if res.status().is_redirection() { + return Err(anyhow::anyhow!("redirect: {:?}", res.status())); + } + + if res.status().is_server_error() { + return Err(anyhow::anyhow!("server error: {:?}", res.status())); + } + + if res.status().is_client_error() { + return Err(anyhow::anyhow!("client error: {:?}", res.status())); + } + + if let Some(path) = stream_response_into.as_ref() { + let mut file = std::fs::File::create(&path).map_err(|e| { + anyhow::anyhow!("failed to download {url} into {}: {e}", path.display()) + })?; + + res.copy_to(&mut file) + .map_err(|e| anyhow::anyhow!("{e}")) + .map_err(|e| { + anyhow::anyhow!("failed to download {url} into {}: {e}", path.display()) + })?; + + if application_type == "application/webc" { + let mut buf = vec![0; 100]; + file.read_exact(&mut buf) + .map_err(|e| anyhow::anyhow!("invalid webc downloaded from {url}: {e}"))?; + if buf[0..webc::MAGIC.len()] != webc::MAGIC[..] { + let first_100_bytes = String::from_utf8_lossy(&buf); + return Err(anyhow::anyhow!("invalid webc bytes: {first_100_bytes:?}")); + } + } + + Ok(None) + } else { + let bytes = res + .bytes() + .map_err(|e| anyhow::anyhow!("{e}")) + .context("bytes() failed")?; + + if application_type == "application/webc" + && (range.is_none() || range.unwrap().start == 0) + && bytes[0..webc::MAGIC.len()] != webc::MAGIC[..] + { + let bytes = bytes.iter().copied().take(100).collect::>(); + let first_100_bytes = String::from_utf8_lossy(&bytes); + return Err(anyhow::anyhow!("invalid webc bytes: {first_100_bytes:?}")); + } + + // else if "application/tar+gzip" - we would need to uncompress the response here + // since failure responses are very small, this will fail during unpacking instead + + Ok(Some(bytes.to_vec())) + } } // TODO: this test is segfaulting only on linux-musl, no other OS @@ -1235,39 +1009,25 @@ fn test_install_package() { "https://registry-cdn.wapm.io/packages/wasmer/wabt/wabt-1.0.29.tar.gz".to_string() ); - let (package, _) = install_package( - TEST_NAME, - Some(registry), - "wasmer/wabt", - Some("1.0.29"), - None, - true, - ) - .unwrap(); + let path = install_package(TEST_NAME, &url::Url::parse(&wabt.url).unwrap()).unwrap(); - println!("package installed: {package:#?}"); + println!("package installed: {path:?}"); assert_eq!( - package.get_path(TEST_NAME).unwrap(), - get_global_install_dir(TEST_NAME, "registry.wapm.io") + path, + get_checkouts_dir(TEST_NAME) .unwrap() - .join("wasmer") - .join("wabt") - .join("1.0.29") + .join(&format!("{}@1.0.29", Package::hash_url(&wabt.url))) ); - let all_installed_packages = get_all_local_packages(TEST_NAME, Some(registry)); - - println!("all_installed_packages: {all_installed_packages:#?}"); + let all_installed_packages = get_all_local_packages(TEST_NAME); let is_installed = all_installed_packages .iter() .any(|p| p.name == "wasmer/wabt" && p.version == "1.0.29"); - println!("is_installed: {is_installed:#?}"); - if !is_installed { - let panic_str = get_all_local_packages(TEST_NAME, Some(registry)) + let panic_str = get_all_local_packages(TEST_NAME) .iter() .map(|p| format!("{} {} {}", p.registry, p.name, p.version)) .collect::>() @@ -1305,8 +1065,8 @@ pub struct BindingsGenerator { pub command: String, } -impl Display for BindingsGenerator { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { +impl fmt::Display for BindingsGenerator { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let BindingsGenerator { package_name, version, diff --git a/lib/registry/src/package.rs b/lib/registry/src/package.rs new file mode 100644 index 000000000..d73007bed --- /dev/null +++ b/lib/registry/src/package.rs @@ -0,0 +1,214 @@ +use crate::PartialWapmConfig; +use std::path::PathBuf; +use std::{fmt, str::FromStr}; +use url::Url; + +#[derive(Debug, Default, Clone, PartialEq, Eq, PartialOrd, Ord)] +pub struct Package { + pub namespace: String, + pub name: String, + pub version: Option, +} + +impl fmt::Display for Package { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.file()) + } +} + +impl Package { + /// Checks whether the package is already installed, if yes, returns the path to the root dir + pub fn already_installed(&self, #[cfg(test)] test_name: &str) -> Option { + #[cfg(not(test))] + let checkouts_dir = crate::get_checkouts_dir()?; + #[cfg(test)] + let checkouts_dir = crate::get_checkouts_dir(test_name)?; + + #[cfg(not(test))] + let hash = self.get_hash(); + #[cfg(test)] + let hash = self.get_hash(test_name); + + let found = std::fs::read_dir(&checkouts_dir) + .ok()? + .filter_map(|e| Some(e.ok()?.file_name().to_str()?.to_string())) + .find(|s| match self.version.as_ref() { + None => s.contains(&hash), + Some(v) => s.contains(&hash) && s.ends_with(v), + })?; + Some(checkouts_dir.join(found)) + } + + /// Checks if the URL is already installed, note that `{url}@{version}` + /// and `{url}` are treated the same + pub fn is_url_already_installed(url: &Url, #[cfg(test)] test_name: &str) -> Option { + #[cfg(not(test))] + let checkouts_dir = crate::get_checkouts_dir()?; + #[cfg(test)] + let checkouts_dir = crate::get_checkouts_dir(test_name)?; + + let url_string = url.to_string(); + let (url, version) = match url_string.split('@').collect::>()[..] { + [url, version] => (url.to_string(), Some(version)), + _ => (url_string, None), + }; + let hash = Self::hash_url(&url); + let found = std::fs::read_dir(&checkouts_dir) + .ok()? + .filter_map(|e| Some(e.ok()?.file_name().to_str()?.to_string())) + .find(|s| match version.as_ref() { + None => s.contains(&hash), + Some(v) => s.contains(&hash) && s.ends_with(v), + })?; + Some(checkouts_dir.join(found)) + } + + /// Returns the hash of the URL with a maximum of 128 bytes length + /// (necessary for not erroring on filesystem limitations) + pub fn hash_url(url: &str) -> String { + hex::encode(url).chars().take(128).collect() + } + + /// Returns the hash of the URL with a maximum of 64 bytes length + pub fn unhash_url(hashed: &str) -> String { + String::from_utf8_lossy(&hex::decode(hashed).unwrap_or_default()).to_string() + } + + /// Returns the hash of the package URL without the version + /// (because the version is encoded as @version and isn't part of the hash itself) + pub fn get_hash(&self, #[cfg(test)] test_name: &str) -> String { + #[cfg(test)] + let url = self.get_url_without_version(test_name); + #[cfg(not(test))] + let url = self.get_url_without_version(); + Self::hash_url(&url.unwrap_or_default()) + } + + fn get_url_without_version( + &self, + #[cfg(test)] test_name: &str, + ) -> Result { + #[cfg(test)] + let url = self.url(test_name); + #[cfg(not(test))] + let url = self.url(); + Ok(format!( + "{}/{}/{}", + url?.origin().ascii_serialization(), + self.namespace, + self.name + )) + } + + /// Returns the filename for this package + pub fn file(&self) -> String { + let version = self + .version + .as_ref() + .map(|f| format!("@{f}")) + .unwrap_or_default(); + format!("{}/{}{version}", self.namespace, self.name) + } + + /// Returns the {namespace}/{name} package name + pub fn package(&self) -> String { + format!("{}/{}", self.namespace, self.name) + } + + /// Returns the full URL including the version for this package + pub fn url(&self, #[cfg(test)] test_name: &str) -> Result { + #[cfg(test)] + let config = PartialWapmConfig::from_file(test_name) + .map_err(|e| anyhow::anyhow!("could not read wapm config: {e}"))?; + #[cfg(not(test))] + let config = PartialWapmConfig::from_file() + .map_err(|e| anyhow::anyhow!("could not read wapm config: {e}"))?; + let registry = config.registry.get_current_registry(); + let registry_tld = tldextract::TldExtractor::new(tldextract::TldOption::default()) + .extract(®istry) + .map_err(|e| anyhow::anyhow!("Invalid registry: {}: {e}", registry))?; + + let registry_tld = format!( + "{}.{}", + registry_tld.domain.as_deref().unwrap_or(""), + registry_tld.suffix.as_deref().unwrap_or(""), + ); + + let version = self + .version + .as_ref() + .map(|f| format!("@{f}")) + .unwrap_or_default(); + let url = format!( + "https://{registry_tld}/{}/{}{version}", + self.namespace, self.name + ); + url::Url::parse(&url).map_err(|e| anyhow::anyhow!("error parsing {url}: {e}")) + } + + /// Returns the path to the installation directory. + /// Does not check whether the installation directory already exists. + pub fn get_path(&self, #[cfg(test)] test_name: &str) -> Result { + #[cfg(test)] + let checkouts_dir = crate::get_checkouts_dir(test_name); + #[cfg(not(test))] + let checkouts_dir = crate::get_checkouts_dir(); + + let checkouts_dir = checkouts_dir.ok_or_else(|| anyhow::anyhow!("no checkouts dir"))?; + + #[cfg(not(test))] + let hash = self.get_hash(); + #[cfg(test)] + let hash = self.get_hash(test_name); + + match self.version.as_ref() { + Some(v) => Ok(checkouts_dir.join(format!("{}@{}", hash, v))), + None => Ok(checkouts_dir.join(&hash)), + } + } +} + +impl FromStr for Package { + type Err = anyhow::Error; + + fn from_str(s: &str) -> Result { + let regex = + regex::Regex::new(r#"^([a-zA-Z0-9\-_]+)/([a-zA-Z0-9\-_]+)(@([a-zA-Z0-9\.\-_]+*))?$"#) + .unwrap(); + + let captures = regex + .captures(s.trim()) + .map(|c| { + c.iter() + .flatten() + .map(|m| m.as_str().to_owned()) + .collect::>() + }) + .unwrap_or_default(); + + match captures.len() { + // namespace/package + 3 => { + let namespace = captures[1].to_string(); + let name = captures[2].to_string(); + Ok(Package { + namespace, + name, + version: None, + }) + } + // namespace/package@version + 5 => { + let namespace = captures[1].to_string(); + let name = captures[2].to_string(); + let version = captures[4].to_string(); + Ok(Package { + namespace, + name, + version: Some(version), + }) + } + other => Err(anyhow::anyhow!("invalid package {other}")), + } + } +} diff --git a/lib/types/Cargo.toml b/lib/types/Cargo.toml index 0ff6382ad..74a64c6b6 100644 --- a/lib/types/Cargo.toml +++ b/lib/types/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer-types" -version = "3.0.2" +version = "3.1.0" description = "Wasmer Common Types" categories = ["wasm", "no-std", "data-structures"] keywords = ["wasm", "webassembly", "types"] diff --git a/lib/vbus/Cargo.toml b/lib/vbus/Cargo.toml index e3f175b29..05693120f 100644 --- a/lib/vbus/Cargo.toml +++ b/lib/vbus/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer-vbus" -version = "3.0.2" +version = "3.1.0" description = "Wasmer Virtual Bus" authors = ["Wasmer Engineering Team "] license = "MIT" @@ -13,9 +13,9 @@ thiserror = "1" tracing = { version = "0.1" } typetag = { version = "0.1", optional = true } slab = { version = "0.4", optional = true } -wasmer = { path = "../api", version = "=3.0.2", default-features = false } -wasmer-vfs = { path = "../vfs", version = "=3.0.2", default-features = false } -wasmer-wasi-types = { path = "../wasi-types/", version = "3.0.2" } +wasmer = { path = "../api", version = "=3.1.0", default-features = false } +wasmer-vfs = { path = "../vfs", version = "=3.1.0", default-features = false } +wasmer-wasi-types = { path = "../wasi-types/", version = "3.1.0" } [features] default = [] diff --git a/lib/vfs/Cargo.toml b/lib/vfs/Cargo.toml index 3cd08beb2..84666355e 100644 --- a/lib/vfs/Cargo.toml +++ b/lib/vfs/Cargo.toml @@ -1,14 +1,14 @@ [package] name = "wasmer-vfs" -version = "3.0.2" +version = "3.1.0" description = "Wasmer Virtual FileSystem" authors = ["Wasmer Engineering Team "] license = "MIT" edition = "2018" [dependencies] -wasmer-types = { path = "../types", version = "3.0.2", default_features = false } -wasmer-wasi-types = { path = "../wasi-types", version = "3.0.2", default_features = false } +wasmer-types = { path = "../types", version = "3.1.0", default_features = false } +wasmer-wasi-types = { path = "../wasi-types", version = "3.1.0", default_features = false } libc = { version = "^0.2", default-features = false, optional = true } thiserror = "1" diff --git a/lib/vm/Cargo.toml b/lib/vm/Cargo.toml index 729fba3f6..7a03b76cb 100644 --- a/lib/vm/Cargo.toml +++ b/lib/vm/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer-vm" -version = "3.0.2" +version = "3.1.0" description = "Runtime library support for Wasmer" categories = ["wasm"] keywords = ["wasm", "webassembly"] @@ -11,7 +11,7 @@ readme = "README.md" edition = "2018" [dependencies] -wasmer-types = { path = "../types", version = "=3.0.2" } +wasmer-types = { path = "../types", version = "=3.1.0" } libc = { version = "^0.2", default-features = false } memoffset = "0.6" indexmap = { version = "1.6" } diff --git a/lib/vnet/Cargo.toml b/lib/vnet/Cargo.toml index a5dd2c9da..f665a7cc2 100644 --- a/lib/vnet/Cargo.toml +++ b/lib/vnet/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer-vnet" -version = "3.0.2" +version = "3.1.0" description = "Wasmer Virtual Networking" authors = ["Wasmer Engineering Team "] license = "MIT" @@ -8,7 +8,7 @@ edition = "2018" [dependencies] thiserror = "1" -wasmer-vfs = { path = "../vfs", version = "=3.0.2", default-features = false } +wasmer-vfs = { path = "../vfs", version = "=3.1.0", default-features = false } bytes = "1" async-trait = { version = "^0.1" } diff --git a/lib/wai-bindgen-wasmer/Cargo.toml b/lib/wai-bindgen-wasmer/Cargo.toml index 3acc6d369..59d937b74 100644 --- a/lib/wai-bindgen-wasmer/Cargo.toml +++ b/lib/wai-bindgen-wasmer/Cargo.toml @@ -18,7 +18,7 @@ once_cell = "1.13" thiserror = "1.0" tracing-lib = { version = "0.1.26", optional = true, package = "tracing" } wai-bindgen-wasmer-impl = { version = "0.2.2" } -wasmer = { version = "3.0.2", path = "../api", default-features = false } +wasmer = { version = "3.1.0", path = "../api", default-features = false } [features] # Enables generated code to emit events via the `tracing` crate whenever wasm is diff --git a/lib/wasi-experimental-io-devices/Cargo.toml b/lib/wasi-experimental-io-devices/Cargo.toml index 556ff0add..2d867fe0f 100644 --- a/lib/wasi-experimental-io-devices/Cargo.toml +++ b/lib/wasi-experimental-io-devices/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer-wasi-experimental-io-devices" -version = "3.0.2" +version = "3.1.0" description = "An experimental non-standard WASI extension for graphics" categories = ["wasm"] keywords = ["wasm", "webassembly", "types"] @@ -14,7 +14,7 @@ edition = "2018" maintenance = { status = "experimental" } [dependencies] -wasmer-wasi = { version = "=3.0.2", path = "../wasi", default-features=false } +wasmer-wasi = { version = "=3.1.0", path = "../wasi", default-features=false } tracing = "0.1" minifb = { version = "0.23", optional = true } nix = "0.25.0" diff --git a/lib/wasi-local-networking/Cargo.toml b/lib/wasi-local-networking/Cargo.toml index 9d204382f..e430864f7 100644 --- a/lib/wasi-local-networking/Cargo.toml +++ b/lib/wasi-local-networking/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer-wasi-local-networking" -version = "3.0.2" +version = "3.1.0" description = "An WASIX extension for local networking" categories = ["wasm"] keywords = ["wasm", "webassembly", "types"] @@ -14,8 +14,8 @@ edition = "2018" maintenance = { status = "experimental" } [dependencies] -wasmer-vnet = { version = "=3.0.2", path = "../vnet", default-features = false } -wasmer-vfs = { path = "../vfs", version = "=3.0.2", default-features = false } +wasmer-vnet = { version = "=3.1.0", path = "../vnet", default-features = false } +wasmer-vfs = { path = "../vfs", version = "=3.1.0", default-features = false } tracing = "0.1" bytes = "1.1" tokio = { version = "1", features = [ "sync", "macros", "io-util", "signal" ], default_features = false } diff --git a/lib/wasi-types/Cargo.toml b/lib/wasi-types/Cargo.toml index 82d1d97f8..dc896df0b 100644 --- a/lib/wasi-types/Cargo.toml +++ b/lib/wasi-types/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer-wasi-types" -version = "3.0.2" +version = "3.1.0" description = "WASI types for Wasmer WebAssembly runtime" categories = ["wasm", "os"] keywords = ["wasm", "webassembly", "wasi", "sandbox", "ABI"] @@ -14,8 +14,8 @@ edition = "2018" [dependencies] wasmer = { default-features = false, path = "../api", version = "3.0.0-beta" } -wasmer-types = { path = "../types", version = "=3.0.2" } -wasmer-derive = { path = "../derive", version = "=3.0.2" } +wasmer-types = { path = "../types", version = "=3.1.0" } +wasmer-derive = { path = "../derive", version = "=3.1.0" } wai-bindgen-gen-rust = "0.2.1" wai-bindgen-rust = { version = "0.2.1", default-features = false, features = ["macros"] } diff --git a/lib/wasi/Cargo.toml b/lib/wasi/Cargo.toml index eaf90824a..437cb46b4 100644 --- a/lib/wasi/Cargo.toml +++ b/lib/wasi/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer-wasi" -version = "3.0.2" +version = "3.1.0" description = "WASI implementation library for Wasmer WebAssembly runtime" categories = ["wasm", "os"] keywords = ["wasm", "webassembly", "wasi", "sandbox", "ABI"] @@ -16,13 +16,14 @@ thiserror = "1" generational-arena = { version = "0.2" } tracing = "0.1" getrandom = "0.2" -wasmer-wasi-types = { path = "../wasi-types", version = "=3.0.2" } -wasmer-types = { path = "../types", version = "=3.0.2", default-features = false } -wasmer = { path = "../api", version = "=3.0.2", default-features = false, features = ["wat", "js-serializable-module"] } -wasmer-vfs = { path = "../vfs", version = "=3.0.2", default-features = false, features = ["webc-fs"] } -wasmer-vbus = { path = "../vbus", version = "=3.0.2", default-features = false } -wasmer-vnet = { path = "../vnet", version = "=3.0.2", default-features = false } -wasmer-wasi-local-networking = { path = "../wasi-local-networking", version = "=3.0.2", default-features = false, optional = true } +wasmer-wasi-types = { path = "../wasi-types", version = "=3.1.0" } +wasmer-types = { path = "../types", version = "=3.1.0", default-features = false } +wasmer = { path = "../api", version = "=3.1.0", default-features = false, features = ["wat", "js-serializable-module"] } +wasmer-vfs = { path = "../vfs", version = "=3.1.0", default-features = false, features = ["webc-fs"] } +wasmer-vbus = { path = "../vbus", version = "=3.1.0", default-features = false } +wasmer-vnet = { path = "../vnet", version = "=3.1.0", default-features = false } +wasmer-wasi-local-networking = { path = "../wasi-local-networking", version = "=3.1.0", default-features = false, optional = true } +wasmer-emscripten = { path = "../emscripten", version = "=3.1.0", optional = true } typetag = { version = "0.1", optional = true } serde = { version = "1.0", default-features = false, features = ["derive"] } bincode = { version = "1.3", optional = true } @@ -32,7 +33,6 @@ bytes = "1" webc = { version = "3.0.1", default-features = false, features = ["std", "mmap"] } serde_cbor = { version = "0.11.2", optional = true } anyhow = { version = "1.0.66" } -wasmer-emscripten = { path = "../emscripten", version = "=3.0.2", optional = true } lazy_static = "1.4" sha2 = { version = "0.10" } waker-fn = { version = "1.1" } diff --git a/scripts/make-release.py b/scripts/make-release.py index c246b91a5..a9ea65e33 100644 --- a/scripts/make-release.py +++ b/scripts/make-release.py @@ -63,7 +63,7 @@ def make_release(version): raise Exception("could not clone github repo") # generate changelog - proc = subprocess.Popen(['gh', "search", "prs", "--repo", "wasmerio/wasmer", "--merged", "--limit", "100"], stdout = subprocess.PIPE, cwd = temp_dir.name) + proc = subprocess.Popen(['gh', "search", "prs", "--repo", "wasmerio/wasmer", "--merged", "--limit", "100", "--sort", "updated"], stdout = subprocess.PIPE, cwd = temp_dir.name) proc.wait() if proc.returncode != 0: print(proc.stdout) @@ -120,7 +120,7 @@ def make_release(version): for l in changelog: print(" " + l) - proc = subprocess.Popen(['gh','search', "prs", "--repo", "wasmerio/wasmer", "--merged"], stdout = subprocess.PIPE, cwd = temp_dir.name) + proc = subprocess.Popen(['gh','search', "prs", "--repo", "wasmerio/wasmer", "--merged", "--sort", "updated"], stdout = subprocess.PIPE, cwd = temp_dir.name) proc.wait() already_released_str = "" @@ -170,7 +170,7 @@ def make_release(version): print(line.rstrip()) raise Exception("could not run git checkout -b release-" + RELEASE_VERSION) - replace(temp_dir.name + "/CHANGELOG.md", "## **Unreleased**", "\r\n".join(changelog)) + replace(temp_dir.name + "/CHANGELOG.md", "## **Unreleased**", "\n".join(changelog)) proc = subprocess.Popen(['git','commit', "-am", "Update CHANGELOG"], stdout = subprocess.PIPE, cwd = temp_dir.name) proc.wait() @@ -338,7 +338,7 @@ def make_release(version): print(line.rstrip()) raise Exception("could not pull origin ") - proc = subprocess.Popen(['gh','search', "prs", "--repo", "wasmerio/wasmer", "--merged"], stdout = subprocess.PIPE, cwd = temp_dir.name) + proc = subprocess.Popen(['gh','search', "prs", "--repo", "wasmerio/wasmer", "--merged", "--sort", "updated"], stdout = subprocess.PIPE, cwd = temp_dir.name) proc.wait() github_link_line = "" diff --git a/scripts/update-version.py b/scripts/update-version.py index dcba7c62f..73d2961b6 100644 --- a/scripts/update-version.py +++ b/scripts/update-version.py @@ -1,7 +1,7 @@ #!/usr/bin/python -PREVIOUS_VERSION='3.0.1' -NEXT_VERSION='3.0.2' +PREVIOUS_VERSION='3.0.2' +NEXT_VERSION='3.1.0' import os import re diff --git a/scripts/windows-installer/wasmer.iss b/scripts/windows-installer/wasmer.iss index 0c0286a80..5330188e2 100644 --- a/scripts/windows-installer/wasmer.iss +++ b/scripts/windows-installer/wasmer.iss @@ -1,6 +1,6 @@ [Setup] AppName=Wasmer -AppVersion=3.0.2 +AppVersion=3.1.0 DefaultDirName={pf}\Wasmer DefaultGroupName=Wasmer Compression=lzma2 diff --git a/tests/compilers/issues.rs b/tests/compilers/issues.rs index 42e50c102..4e1a64481 100644 --- a/tests/compilers/issues.rs +++ b/tests/compilers/issues.rs @@ -317,3 +317,108 @@ fn test_popcnt(mut config: crate::Config) -> Result<()> { Ok(()) } + +/// Create a large number of local (more than 0x1_0000 bytes, thats 32*16 i64 + 1) +/// to trigger an issue in the arm64 singlepass compiler +/// sequence +/// mov x17, #0x1010 +/// sub xsp, xsp, x17 +/// will tranform to +/// mov x17, #0x1010 +/// sub xzr, xzr, x17 +/// and the locals +/// on stack can get corrupted by subsequent calls if they also have locals on stack +#[compiler_test(issues)] +fn large_number_local(mut config: crate::Config) -> Result<()> { + let mut store = config.store(); + let wat = r#" + (module + (func (;0;) + (local i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64) + i64.const 0 + i64.const 5555 + i64.add + local.set 8 + i64.const 0 + i64.const 5555 + i64.add + local.set 9 + i64.const 0 + i64.const 5555 + i64.add + local.set 10 + ) + (func $large_local (export "large_local") (result i64) + (local + i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 + i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 + i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 + i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 + i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 + i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 + i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 + i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 + i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 + i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 + i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 + i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 + i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 + i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 + i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 + i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 + i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 + i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 + i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 + i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 + i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 + i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 + i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 + i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 + i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 + i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 + i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 + i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 + i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 + i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 + i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 + i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 + i64 + ) + (local.set 15 (i64.const 1)) + (call 0) + local.get 6 + local.get 7 + i64.add + local.get 8 + i64.add + local.get 9 + i64.add + local.get 10 + i64.add + local.get 11 + i64.add + local.get 12 + i64.add + local.get 13 + i64.add + local.get 14 + i64.add + local.get 15 + i64.add + local.get 16 + i64.add + ) + ) + "#; + let mut env = FunctionEnv::new(&mut store, ()); + let module = Module::new(&store, wat)?; + let imports: Imports = imports! {}; + let instance = Instance::new(&mut store, &module, &imports)?; + let result = instance + .exports + .get_function("large_local")? + .call(&mut store, &[]) + .unwrap(); + assert_eq!(&Value::I64(1 as i64), result.get(0).unwrap()); + Ok(()) +} diff --git a/tests/integration/cli/Cargo.toml b/tests/integration/cli/Cargo.toml index 1d1cd81cd..15156ef84 100644 --- a/tests/integration/cli/Cargo.toml +++ b/tests/integration/cli/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer-integration-tests-cli" -version = "3.0.2" +version = "3.1.0" authors = ["Wasmer Engineering Team "] description = "CLI integration tests" repository = "https://github.com/wasmerio/wasmer" diff --git a/tests/integration/cli/tests/run.rs b/tests/integration/cli/tests/run.rs index 8146e5578..bcd1cbec0 100644 --- a/tests/integration/cli/tests/run.rs +++ b/tests/integration/cli/tests/run.rs @@ -21,7 +21,6 @@ fn test_no_start_wat_path() -> PathBuf { Path::new(ASSET_PATH).join("no_start.wat") } -#[cfg(any(target_os = "linux", target_os = "macos"))] #[test] fn test_cross_compile_python_windows() -> anyhow::Result<()> { let temp_dir = tempfile::TempDir::new()?; @@ -34,41 +33,70 @@ fn test_cross_compile_python_windows() -> anyhow::Result<()> { "x86_64-windows-gnu", ]; + // MUSL has no support for LLVM in C-API + #[cfg(target_env = "musl")] + let compilers = &["cranelift", "singlepass"]; + #[cfg(not(target_env = "musl"))] + let compilers = &["cranelift", "singlepass", "llvm"]; + + // llvm-objdump --disassemble-all --demangle ./objects/wasmer_vm-50cb118b098c15db.wasmer_vm.60425a0a-cgu.12.rcgu.o + // llvm-objdump --macho --exports-trie ~/.wasmer/cache/wasmer-darwin-arm64/lib/libwasmer.dylib + let excluded_combinations = &[ + ("aarch64-darwin", "llvm"), // LLVM: aarch64 not supported relocation Arm64MovwG0 not supported + ("aarch64-linux-gnu", "llvm"), // LLVM: aarch64 not supported relocation Arm64MovwG0 not supported + // https://github.com/ziglang/zig/issues/13729 + ("x86_64-darwin", "llvm"), // undefined reference to symbol 'wasmer_vm_raise_trap' kind Unknown + ("x86_64-windows-gnu", "llvm"), // unimplemented symbol `wasmer_vm_raise_trap` kind Unknown + ]; + for t in targets { - let python_wasmer_path = temp_dir.path().join(format!("{t}-python")); + for c in compilers { + if excluded_combinations.contains(&(t, c)) { + continue; + } + println!("{t} target {c}"); + let python_wasmer_path = temp_dir.path().join(format!("{t}-python")); - let mut output = Command::new(get_wasmer_path()); + let mut output = Command::new(get_wasmer_path()); - output.arg("create-exe"); - output.arg(wasi_test_python_path()); - output.arg("--target"); - output.arg(t); - output.arg("-o"); - output.arg(python_wasmer_path.clone()); - let output = output.output()?; + output.arg("create-exe"); + output.arg(wasi_test_python_path()); + output.arg("--target"); + output.arg(t); + output.arg("-o"); + output.arg(python_wasmer_path.clone()); + output.arg(format!("--{c}")); - let stdout = std::str::from_utf8(&output.stdout) - .expect("stdout is not utf8! need to handle arbitrary bytes"); + if t.contains("x86_64") && *c == "singlepass" { + output.arg("-m"); + output.arg("avx"); + } - let stderr = std::str::from_utf8(&output.stderr) - .expect("stderr is not utf8! need to handle arbitrary bytes"); + let output = output.output()?; - if !output.status.success() { - bail!("linking failed with: stdout: {stdout}\n\nstderr: {stderr}"); - } + let stdout = std::str::from_utf8(&output.stdout) + .expect("stdout is not utf8! need to handle arbitrary bytes"); - println!("stdout: {stdout}"); - println!("stderr: {stderr}"); + let stderr = std::str::from_utf8(&output.stderr) + .expect("stderr is not utf8! need to handle arbitrary bytes"); - if !python_wasmer_path.exists() { - let p = std::fs::read_dir(temp_dir.path()) - .unwrap() - .filter_map(|e| Some(e.ok()?.path())) - .collect::>(); - panic!( - "target {t} was not compiled correctly {stdout} {stderr}, tempdir: {:#?}", - p - ); + if !output.status.success() { + bail!("linking failed with: stdout: {stdout}\n\nstderr: {stderr}"); + } + + println!("stdout: {stdout}"); + println!("stderr: {stderr}"); + + if !python_wasmer_path.exists() { + let p = std::fs::read_dir(temp_dir.path()) + .unwrap() + .filter_map(|e| Some(e.ok()?.path())) + .collect::>(); + panic!( + "target {t} was not compiled correctly {stdout} {stderr}, tempdir: {:#?}", + p + ); + } } } @@ -380,7 +408,7 @@ fn test_wasmer_run_works_with_dir() -> anyhow::Result<()> { #[test] fn test_wasmer_run_works() -> anyhow::Result<()> { let output = Command::new(get_wasmer_path()) - .arg("registry.wapm.io/python/python") + .arg("https://wapm.io/python/python") .arg(format!("--mapdir=.:{}", ASSET_PATH)) .arg("test.py") .output()?; @@ -400,7 +428,7 @@ fn test_wasmer_run_works() -> anyhow::Result<()> { // same test again, but this time with "wasmer run ..." let output = Command::new(get_wasmer_path()) .arg("run") - .arg("registry.wapm.io/python/python") + .arg("https://wapm.io/python/python") .arg(format!("--mapdir=.:{}", ASSET_PATH)) .arg("test.py") .output()?; @@ -417,6 +445,15 @@ fn test_wasmer_run_works() -> anyhow::Result<()> { ); } + // set wapm.io as the current registry + let _ = Command::new(get_wasmer_path()) + .arg("login") + .arg("--registry") + .arg("wapm.io") + // will fail, but set wapm.io as the current registry regardless + .arg("öladkfjasöldfkjasdölfkj") + .output()?; + // same test again, but this time without specifying the registry let output = Command::new(get_wasmer_path()) .arg("run") @@ -440,7 +477,7 @@ fn test_wasmer_run_works() -> anyhow::Result<()> { // same test again, but this time with only the command "python" (should be looked up locally) let output = Command::new(get_wasmer_path()) .arg("run") - .arg("python") + .arg("_/python") .arg(format!("--mapdir=.:{}", ASSET_PATH)) .arg("test.py") .output()?; @@ -480,6 +517,133 @@ fn run_no_imports_wasm_works() -> anyhow::Result<()> { Ok(()) } +#[test] +fn run_wasi_works_non_existent() -> anyhow::Result<()> { + let output = Command::new(get_wasmer_path()) + .arg("run") + .arg("does/not/exist") + .output()?; + + let stderr = std::str::from_utf8(&output.stderr).unwrap(); + + let stderr_lines = stderr.lines().map(|s| s.to_string()).collect::>(); + + assert_eq!( + stderr_lines, + vec!["error: invalid package name, could not find file does/not/exist".to_string()] + ); + + Ok(()) +} + +#[test] +fn run_test_caching_works_for_packages() -> anyhow::Result<()> { + // set wapm.io as the current registry + let _ = Command::new(get_wasmer_path()) + .arg("login") + .arg("--registry") + .arg("wapm.io") + // will fail, but set wapm.io as the current registry regardless + .arg("öladkfjasöldfkjasdölfkj") + .output()?; + + let output = Command::new(get_wasmer_path()) + .arg("python/python") + .arg(format!("--mapdir=.:{}", ASSET_PATH)) + .arg("test.py") + .output()?; + + if output.stdout != b"hello\n".to_vec() { + panic!("failed to run https://wapm.io/python/python for the first time"); + } + + let time = std::time::Instant::now(); + + let output = Command::new(get_wasmer_path()) + .arg("python/python") + .arg(format!("--mapdir=.:{}", ASSET_PATH)) + .arg("test.py") + .output()?; + + if output.stdout != b"hello\n".to_vec() { + panic!("failed to run https://wapm.io/python/python for the second time"); + } + + // package should be cached + assert!(std::time::Instant::now() - time < std::time::Duration::from_secs(1)); + + Ok(()) +} + +#[test] +fn run_test_caching_works_for_packages_with_versions() -> anyhow::Result<()> { + // set wapm.io as the current registry + let _ = Command::new(get_wasmer_path()) + .arg("login") + .arg("--registry") + .arg("wapm.io") + // will fail, but set wapm.io as the current registry regardless + .arg("öladkfjasöldfkjasdölfkj") + .output()?; + + let output = Command::new(get_wasmer_path()) + .arg("python/python@0.1.0") + .arg(format!("--mapdir=.:{}", ASSET_PATH)) + .arg("test.py") + .output()?; + + if output.stdout != b"hello\n".to_vec() { + panic!("failed to run https://wapm.io/python/python for the first time"); + } + + let time = std::time::Instant::now(); + + let output = Command::new(get_wasmer_path()) + .arg("python/python@0.1.0") + .arg(format!("--mapdir=.:{}", ASSET_PATH)) + .arg("test.py") + .output()?; + + if output.stdout != b"hello\n".to_vec() { + panic!("failed to run https://wapm.io/python/python for the second time"); + } + + // package should be cached + assert!(std::time::Instant::now() - time < std::time::Duration::from_secs(1)); + + Ok(()) +} + +#[test] +fn run_test_caching_works_for_urls() -> anyhow::Result<()> { + let output = Command::new(get_wasmer_path()) + .arg("https://wapm.io/python/python") + .arg(format!("--mapdir=.:{}", ASSET_PATH)) + .arg("test.py") + .output()?; + + if output.stdout != b"hello\n".to_vec() { + panic!("failed to run https://wapm.io/python/python for the first time"); + } + + let time = std::time::Instant::now(); + + let output = Command::new(get_wasmer_path()) + .arg("https://wapm.io/python/python") + .arg(format!("--mapdir=.:{}", ASSET_PATH)) + .arg("test.py") + .output()?; + + if output.stdout != b"hello\n".to_vec() { + panic!("failed to run https://wapm.io/python/python for the second time"); + } + + // package should be cached + assert!(std::time::Instant::now() - time < std::time::Duration::from_secs(1)); + + Ok(()) +} + // This test verifies that "wasmer run --invoke _start module.wat" // works the same as "wasmer run module.wat" (without --invoke). #[test] diff --git a/tests/integration/ios/Cargo.toml b/tests/integration/ios/Cargo.toml index 3841cb519..2debdee51 100644 --- a/tests/integration/ios/Cargo.toml +++ b/tests/integration/ios/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer-integration-tests-ios" -version = "3.0.2" +version = "3.1.0" authors = ["Wasmer Engineering Team "] description = "iOS integration tests" repository = "https://github.com/wasmerio/wasmer" diff --git a/tests/lib/wast/Cargo.toml b/tests/lib/wast/Cargo.toml index 019c94017..f6596e061 100644 --- a/tests/lib/wast/Cargo.toml +++ b/tests/lib/wast/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasmer-wast" -version = "3.0.2" +version = "3.1.0" authors = ["Wasmer Engineering Team "] description = "wast testing support for wasmer" license = "MIT OR Apache-2.0 WITH LLVM-exception" @@ -12,9 +12,9 @@ edition = "2018" [dependencies] anyhow = "1.0" -wasmer = { path = "../../../lib/api", version = "=3.0.2", default-features = false } -wasmer-wasi = { path = "../../../lib/wasi", version = "=3.0.2" } -wasmer-vfs = { path = "../../../lib/vfs", version = "=3.0.2" } +wasmer = { path = "../../../lib/api", version = "=3.1.0", default-features = false } +wasmer-wasi = { path = "../../../lib/wasi", version = "=3.1.0" } +wasmer-vfs = { path = "../../../lib/vfs", version = "=3.1.0" } wast = "38.0" serde = "1" tempfile = "3" diff --git a/tests/wasi-wast/Cargo.toml b/tests/wasi-wast/Cargo.toml index 349eba41d..dab510eab 100644 --- a/tests/wasi-wast/Cargo.toml +++ b/tests/wasi-wast/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasi-test-generator" -version = "3.0.2" +version = "3.1.0" description = "Tests for our WASI implementation" license = "MIT" authors = ["Wasmer Engineering Team "]