tpmccallum opened PR #10511 from tpmccallum:invoke_wave_enhancements
to bytecodealliance:main
:
This PR is in relation to the Zulip conversation at #wasmtime > wasmtime-cli: support run --invoke for components using wave.
This PR includes @pchickey's existing PR 10054.
There is an open issue relating to this work.
Along with the changes, the documentation has also been updated accordingly (the changes in the
docs/cli-options.md
file of this PR).
tpmccallum requested alexcrichton for a review on PR #10511.
tpmccallum requested wasmtime-core-reviewers for a review on PR #10511.
tpmccallum requested wasmtime-default-reviewers for a review on PR #10511.
tpmccallum edited PR #10511:
This PR is in relation to the Zulip conversation at #wasmtime > wasmtime-cli: support run --invoke for components using wave.
This PR includes @pchickey's existing PR 10054. (Apologies @pchickey I could not see the
pch/invoke_wave
in the dropdown when trying to create a PR that would target yourpch/invoke_wave
branch; I'm not sure whypch/invoke_wave
does not show up. When I pushed it generated this new 10511 PR and included all of your previous changes, so I hope we are still on the right path to getting this--invoke
feature implemented.There is an open issue relating to this work.
Along with the changes, the documentation has also been updated accordingly (the changes in the
docs/cli-options.md
file of this PR).
tpmccallum edited PR #10511:
This PR is in relation to the Zulip conversation at #wasmtime > wasmtime-cli: support run --invoke for components using wave.
This PR includes @pchickey's existing PR 10054. (Apologies @pchickey I could not see the
pch/invoke_wave
in the dropdown when trying to create a PR that would target yourpch/invoke_wave
branch). I'm not sure whypch/invoke_wave
does not show up. When I pushed it generated this new 10511 PR and included all of your previous changes, so I hope we are still on the right path to getting this--invoke
feature implemented.There is an open issue relating to this work.
Along with the changes, the documentation has also been updated accordingly (the changes in the
docs/cli-options.md
file of this PR).
tpmccallum edited PR #10511:
This PR is in relation to the Zulip conversation at #wasmtime > wasmtime-cli: support run --invoke for components using wave.
This PR includes @pchickey's existing PR 10054. (Apologies @pchickey I could not see the
pch/invoke_wave
in the dropdown when trying to create a PR that would target yourpch/invoke_wave
branch). I'm not sure whypch/invoke_wave
does not show up. When I pushed it generated this new 10511 PR and included all of your previous changes, so I hope we are still on the right path to getting this--invoke
feature implemented.There is an open issue relating to this work.
Along with the changes, the documentation has also been updated accordingly (the changes in the
docs/cli-options.md
file of this PR).Functionality
The invoke function works great:
Compress WIT:
package example:component; world compress { export compress: func(input: string) -> list<u8>; }
#[allow(warnings)] mod bindings; use bindings::Guest; use zstd::stream::encode_all; use std::io::Cursor; struct Component; impl Guest for Component { fn compress(input: String) -> Vec<u8> { encode_all(Cursor::new(input.as_bytes()), 5).unwrap() } } bindings::export!(Component with_types_in bindings);
Cargo.toml:
[package] name = "compress" version = "0.1.0" edition = "2021" [dependencies] zstd = "0.13" wit-bindgen-rt = { version = "0.39.0", features = ["bitflags"] } [lib] crate-type = ["cdylib"] [package.metadata.component] target = { path = "wit/compress.wit" }
CLI:
/Users/tpmccallum/wasmtime/target/release/wasmtime run --invoke "compress(\"hello\")" /Users/tpmccallum/testing_components/compress/target/wasm32-wasip1/debug/compress.wasm [40, 181, 47, 253, 0, 88, 41, 0, 0, 104, 101, 108, 108, 111]
pchickey requested wasmtime-fuzz-reviewers for a review on PR #10511.
pchickey requested wasmtime-compiler-reviewers for a review on PR #10511.
pchickey requested cfallin for a review on PR #10511.
pchickey edited PR #10511.
pchickey submitted PR review:
Thanks for working on this.
I rebased my branch on main, and changed the base branch for this PR to be my branch.
I think if you drop the change to wave core i128, we can merge this to my branch, and then I'll have alex review my PR.
pchickey created PR review comment:
The original code is correct here - this is making a pair of i64 out of the bits in a i128, so we want those operations to discard the extra bits and not panic when they are present
tpmccallum submitted PR review.
tpmccallum created PR review comment:
Thanks, Pat.
Sure thing. The reason I updated this code is that there was a value truncation error in the cargo clippy CI, which read:error: casting `u128` to `i64` may truncate the value help: if this is intentional, allow the lint with `#[allow(clippy::cast_possible_truncation)]` or use `try_from` and handle the error accordingly let low = i64::try_from(v);
I will change it back and run clippy locally to ensure it truncates silently and suppresses the warning/error.
Will report back here soon.
tpmccallum submitted PR review.
tpmccallum created PR review comment:
Ok, I did a
cargo clean
andcargo build --release
and then also performed the CI locally i.e.:export CARGO_INCREMENTAL=0 export CARGO_PROFILE_DEV_DEBUG=0 export CARGO_PROFILE_TEST_DEBUG=0 export RUSTFLAGS="-D warnings" export WIT_REQUIRE_SEMICOLONS=1 cargo clippy --workspace --all-targets
The following error occurred:
Checking wiggle v32.0.0 (/Users/tpmccallum/wasmtime/crates/wiggle) error: casting `u128` to `i64` may truncate the value --> crates/wasmtime/src/runtime/wave/core.rs:103:19 | 103 | let low = v as i64; | ^^^^^^^^ | = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ... = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#cast_possible_truncation = note: `-D clippy::cast-possible-truncation` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::cast_possible_truncation)]` help: ... or use `try_from` and handle the error accordingly | 103 - let low = v as i64; 103 + let low = i64::try_from(v); | error: could not compile `wasmtime` (lib) due to 1 previous error warning: build failed, waiting for other jobs to finish...
I will try that same original code again, but this time with the following:
#![allow(clippy::cast_possible_truncation)]
Report back soon ... :)
tpmccallum edited PR review comment.
tpmccallum edited PR review comment.
tpmccallum edited PR review comment.
tpmccallum submitted PR review.
tpmccallum created PR review comment:
Ok, so that attribute (
#[allow(clippy::cast_possible_truncation)]
at the function level) seemed to do the trick.Build:
$ cargo build --release Compiling proc-macro2 v1.0.92 Compiling unicode-ident v1.0.8 -- snip -- Compiling wasmtime-wasi-tls v32.0.0 (/Users/tpmccallum/wasmtime/crates/wasi-tls) Finished `release` profile [optimized] target(s) in 10m 59s
Clippy:
$ export CARGO_INCREMENTAL=0 $ export CARGO_PROFILE_DEV_DEBUG=0 $ export CARGO_PROFILE_TEST_DEBUG=0 $ export RUSTFLAGS="-D warnings" $ export WIT_REQUIRE_SEMICOLONS=1 $ cargo clippy --workspace --all-targets Compiling proc-macro2 v1.0.92 Compiling unicode-ident v1.0.8 Compiling serde v1.0.215 --snip-- Checking wasmtime-c-api v32.0.0 (/Users/tpmccallum/wasmtime/crates/c-api/artifact) Finished `dev` profile [unoptimized] target(s) in 4m 34s
I will commit the changes now.
tpmccallum updated PR #10511.
tpmccallum updated PR #10511.
tpmccallum updated PR #10511.
tpmccallum updated PR #10511.
tpmccallum updated PR #10511.
tpmccallum commented on PR #10511:
Ok, signing off for the day.
cargo build --release
andcargo clippy
are :check:The absence of parentheses will give a helpful result:
$ wasmtime run --invoke "compress" compress.wasm
Error: failed to run main module `compress.wasm` Caused by: 0: Failed to parse invoke 'compress': function calls must be enveloped in double quotes and must include parentheses (e.g., "compress()"). String arguments must be enveloped in escaped double quotes (e.g., "compress(\"hello\")"). 1: unexpected end of input at 8..8
Interestingly, the absence of outer double quotes is a little trickier. The Rust code I added attempts to test for double quotes via
starts_with
andends_with
, but this does not work. For example:let s = "compress(\"hello\")"; println!("starts_with: {}, ends_with: {}", s.starts_with("\""), s.ends_with("\""));
One would assume the result to be
starts_with: true, ends_with: true
but in reality the result is actually:starts_with: false, ends_with: false
Alas, this is not a good enough validator of whether the exported function being invoked by
--invoke
is surrounded in double quotes. I did try (and succeeded) to see the outer double quotes when they existed. For example:// This `invoke` that Rust sees here does not show the outer double quotes. Only the following `func()` or `func(42)`. let invoke: &String = self.invoke.as_ref().unwrap(); // However, I can get the raw data and see double quotes if/when they exist. For example `"func()"` or `"func(42)"`. let raw_invoke = format!("{:?}", invoke);
The overarching issue is ... if a user does not surround the exported function in double quotes it fails in the shell log before the Rust even sees it. And the result is something along these lines:
$ wasmtime run --invoke compress(\"hello\") compress.wasm
zsh: unknown file attribute: "
I am stumped in finding a way to enforce outer double quotes in the
wasmtime run
CLI. For this reason, I ended up being a bit verbose on the documentation on this PR:## `run` This is the `wasmtime` CLI's main subcommand, and it's also the default if no other subcommand is provided. The `run` command will execute a WebAssembly module. This means that the module will be compiled to native code, instantiated, and then optionally have an export executed. The `wasmtime` CLI will automatically hook up any WASI-related imported functionality, but at this time, if your module imports anything else, it will fail instantiation. The `run` command takes one positional argument, which is the name of the module to run: ```sh $ wasmtime run foo.wasm $ wasmtime foo.wasm ``` Note that the `wasmtime` CLI can take both a binary WebAssembly file (`*.wasm`) as well as the text format for WebAssembly (`*.wat`): ```sh $ wasmtime foo.wat ``` The `run` command accepts an optional `--invoke` argument, which is the name of an exported function of the module to run. ```sh $ wasmtime run --invoke "initialize()" foo.wasm ``` The exported function's name and exported function's parentheses must both be enclosed in one set of double quotes, i.e. `"initialize()"`. This treats the exported function as a single argument and prevents issues with shell interpretation. The presence of the parenthesis `()` signifies function invocation, as apposed to the function name just being referenced. This convention helps to distinguish function calls from other kinds of string arguments. **Note:** If your function takes a string argument, ensure that you use escaped double quotes inside the parentheses. For example: ```sh $ wasmtime run --invoke "initialize(\"hello\")" foo.wasm ``` Each individual argument within the parentheses must be separated by a comma: ```sh $ wasmtime run --invoke "initialize(\"Pi\", 3.14)" $ wasmtime run --invoke "add(1, 2)" ```
Hope all of that makes sense. Happy to do more - happy reviewing.
tpmccallum edited a comment on PR #10511:
Ok, signing off for the day.
cargo build --release
andcargo clippy
are :check:The absence of parentheses will give a helpful result:
$ wasmtime run --invoke "compress" compress.wasm
Error: failed to run main module `compress.wasm` Caused by: 0: Failed to parse invoke 'compress': function calls must be enveloped in double quotes and must include parentheses (e.g., "compress()"). String arguments must be enveloped in escaped double quotes (e.g., "compress(\"hello\")"). 1: unexpected end of input at 8..8
Interestingly, the absence of outer double quotes is a little trickier. The Rust code I added attempts to test for double quotes via
starts_with
andends_with
, but this does not work. For example:let s = "compress(\"hello\")"; println!("starts_with: {}, ends_with: {}", s.starts_with("\""), s.ends_with("\""));
One would assume the result to be
starts_with: true, ends_with: true
but in reality the result is actually:starts_with: false, ends_with: false
Alas, this is not a good enough validator of whether the exported function being invoked by
--invoke
is surrounded in double quotes. I did try (and succeeded) to see the outer double quotes when they existed. For example:// This `invoke` that Rust sees here does not show the outer double quotes. Only the following `func()` or `func(42)`. let invoke: &String = self.invoke.as_ref().unwrap(); // However, I can get the raw data and see double quotes if/when they exist. For example `"func()"` or `"func(42)"`. let raw_invoke = format!("{:?}", invoke);
The overarching issue is ... if a user does not surround the exported function in double quotes it fails in the shell long before the Rust even sees it. And the result is something along these lines:
$ wasmtime run --invoke compress(\"hello\") compress.wasm
zsh: unknown file attribute: "
I am stumped in finding a way to enforce outer double quotes in the
wasmtime run
CLI. For this reason, I ended up being a bit verbose on the documentation on this PR:## `run` This is the `wasmtime` CLI's main subcommand, and it's also the default if no other subcommand is provided. The `run` command will execute a WebAssembly module. This means that the module will be compiled to native code, instantiated, and then optionally have an export executed. The `wasmtime` CLI will automatically hook up any WASI-related imported functionality, but at this time, if your module imports anything else, it will fail instantiation. The `run` command takes one positional argument, which is the name of the module to run: ```sh $ wasmtime run foo.wasm $ wasmtime foo.wasm ``` Note that the `wasmtime` CLI can take both a binary WebAssembly file (`*.wasm`) as well as the text format for WebAssembly (`*.wat`): ```sh $ wasmtime foo.wat ``` The `run` command accepts an optional `--invoke` argument, which is the name of an exported function of the module to run. ```sh $ wasmtime run --invoke "initialize()" foo.wasm ``` The exported function's name and exported function's parentheses must both be enclosed in one set of double quotes, i.e. `"initialize()"`. This treats the exported function as a single argument and prevents issues with shell interpretation. The presence of the parenthesis `()` signifies function invocation, as apposed to the function name just being referenced. This convention helps to distinguish function calls from other kinds of string arguments. **Note:** If your function takes a string argument, ensure that you use escaped double quotes inside the parentheses. For example: ```sh $ wasmtime run --invoke "initialize(\"hello\")" foo.wasm ``` Each individual argument within the parentheses must be separated by a comma: ```sh $ wasmtime run --invoke "initialize(\"Pi\", 3.14)" $ wasmtime run --invoke "add(1, 2)" ```
Hope all of that makes sense. Happy to do more - happy reviewing.
tpmccallum updated PR #10511.
tpmccallum edited a comment on PR #10511:
Ok, signing off for the day.
cargo build --release
andcargo clippy
are :check:The absence of parentheses will give a helpful result:
$ wasmtime run --invoke "compress" compress.wasm
Error: failed to run main module `compress.wasm` Caused by: 0: Failed to parse invoke 'compress': function calls must be enveloped in double quotes and must include parentheses (e.g., "compress()"). String arguments must be enveloped in escaped double quotes (e.g., "compress(\"hello\")"). 1: unexpected end of input at 8..8
Interestingly, the absence of outer double quotes is a little trickier. The Rust code I added attempts to test for double quotes via
starts_with
andends_with
, but this does not work. For example:let s = "compress(\"hello\")"; println!("starts_with: {}, ends_with: {}", s.starts_with("\""), s.ends_with("\""));
One would assume the result to be
starts_with: true, ends_with: true
but in reality the result is actually:starts_with: false, ends_with: false
Alas, this is not a good enough validator of whether the exported function being invoked by
--invoke
is surrounded in double quotes. I did try (and succeeded) to see the outer double quotes when they existed. For example:// This `invoke` that Rust sees here does not show the outer double quotes. Only the following `func()` or `func(42)`. let invoke: &String = self.invoke.as_ref().unwrap(); // However, I can get the raw data and see double quotes if/when they exist. For example `"func()"` or `"func(42)"`. let raw_invoke = format!("{:?}", invoke);
The overarching issue is ... if a user does not surround the exported function in double quotes it fails in the shell long before the Rust even sees it. And the result is something along these lines:
$ wasmtime run --invoke compress(\"hello\") compress.wasm
zsh: unknown file attribute: "
I am stumped in finding a way to enforce outer double quotes in the
wasmtime run
CLI. For this reason, I ended up being a bit verbose on the documentation on this PR:## `run` This is the `wasmtime` CLI's main subcommand, and it's also the default if no other subcommand is provided. The `run` command will execute a WebAssembly module. This means that the module will be compiled to native code, instantiated, and then optionally have an export executed. The `wasmtime` CLI will automatically hook up any WASI-related imported functionality, but at this time, if your module imports anything else, it will fail instantiation. The `run` command takes one positional argument, which is the name of the module to run: ```sh $ wasmtime run foo.wasm $ wasmtime foo.wasm ``` Note that the `wasmtime` CLI can take both a binary WebAssembly file (`*.wasm`) as well as the text format for WebAssembly (`*.wat`): ```sh $ wasmtime foo.wat ``` The `run` command accepts an optional `--invoke` argument, which is the name of an exported function of the module to run. ```sh $ wasmtime run --invoke "initialize()" foo.wasm ``` The exported function's name and exported function's parentheses must both be enclosed in one set of double quotes, i.e. `"initialize()"`. This treats the exported function as a single argument and prevents issues with shell interpretation. The presence of the parenthesis `()` signifies function invocation, as apposed to the function name just being referenced. This convention helps to distinguish function calls from other kinds of string arguments. **Note:** If your function takes a string argument, ensure that you use escaped double quotes inside the parentheses. For example: ```sh $ wasmtime run --invoke "initialize(\"hello\")" foo.wasm ``` Each individual argument within the parentheses must be separated by a comma: ```sh $ wasmtime run --invoke "initialize(\"Pi\", 3.14)" foo.wasm $ wasmtime run --invoke "add(1, 2)" foo.wasm ```
Hope all of that makes sense. Happy to do more - happy reviewing.
tpmccallum edited a comment on PR #10511:
Ok, signing off for the day.
cargo build --release
andcargo clippy
are :check:The absence of parentheses will give a helpful result:
$ wasmtime run --invoke "compress" compress.wasm
Error: failed to run main module `compress.wasm` Caused by: 0: Failed to parse invoke 'compress': function calls must be enveloped in double quotes and must include parentheses (e.g., "compress()"). String arguments must be enveloped in escaped double quotes (e.g., "compress(\"hello\")"). 1: unexpected end of input at 8..8
Interestingly, the absence of outer double quotes is a little trickier. The Rust code I added attempts to test for double quotes via
starts_with
andends_with
, but this does not work. For example:let s = "compress(\"hello\")"; println!("starts_with: {}, ends_with: {}", s.starts_with("\""), s.ends_with("\""));
One would assume the result to be
starts_with: true, ends_with: true
but in reality the result is actually:starts_with: false, ends_with: false
Alas, this is not a good enough validator of whether the exported function being invoked by
--invoke
is surrounded in double quotes. I did try (and succeeded) to see the outer double quotes when they existed. For example:// This `invoke` that Rust sees here does not show the outer double quotes. Only the following `func()` or `func(42)`. let invoke: &String = self.invoke.as_ref().unwrap(); // However, I can get the raw data and see double quotes if/when they exist. For example `"func()"` or `"func(42)"`. let raw_invoke = format!("{:?}", invoke);
The overarching issue is ... if a user does not surround the exported function in double quotes it fails in the shell long before the Rust even sees it. And the result is something along these lines:
$ wasmtime run --invoke compress(\"hello\") compress.wasm
zsh: unknown file attribute: "
I am stumped in finding a way to enforce outer double quotes in the
wasmtime run
CLI.(I am convinced that even something built into wasm-wave would not catch the missing outer double quotes in time anyway.)
For this reason, I ended up being a bit verbose on the documentation on this PR:
## `run` This is the `wasmtime` CLI's main subcommand, and it's also the default if no other subcommand is provided. The `run` command will execute a WebAssembly module. This means that the module will be compiled to native code, instantiated, and then optionally have an export executed. The `wasmtime` CLI will automatically hook up any WASI-related imported functionality, but at this time, if your module imports anything else, it will fail instantiation. The `run` command takes one positional argument, which is the name of the module to run: ```sh $ wasmtime run foo.wasm $ wasmtime foo.wasm ``` Note that the `wasmtime` CLI can take both a binary WebAssembly file (`*.wasm`) as well as the text format for WebAssembly (`*.wat`): ```sh $ wasmtime foo.wat ``` The `run` command accepts an optional `--invoke` argument, which is the name of an exported function of the module to run. ```sh $ wasmtime run --invoke "initialize()" foo.wasm ``` The exported function's name and exported function's parentheses must both be enclosed in one set of double quotes, i.e. `"initialize()"`. This treats the exported function as a single argument and prevents issues with shell interpretation. The presence of the parenthesis `()` signifies function invocation, as apposed to the function name just being referenced. This convention helps to distinguish function calls from other kinds of string arguments. **Note:** If your function takes a string argument, ensure that you use escaped double quotes inside the parentheses. For example: ```sh $ wasmtime run --invoke "initialize(\"hello\")" foo.wasm ``` Each individual argument within the parentheses must be separated by a comma: ```sh $ wasmtime run --invoke "initialize(\"Pi\", 3.14)" foo.wasm $ wasmtime run --invoke "add(1, 2)" foo.wasm ```
Hope all of that makes sense. Happy to do more - happy reviewing.
tpmccallum requested pchickey for a review on PR #10511.
pchickey merged PR #10511.
tpmccallum edited a comment on PR #10511:
Ok, signing off for the day.
cargo build --release
andcargo clippy
are :check:The absence of parentheses will give a helpful result:
$ wasmtime run --invoke "compress" compress.wasm
Error: failed to run main module `compress.wasm` Caused by: 0: Failed to parse invoke 'compress': function calls must be enveloped in double quotes and must include parentheses (e.g., "compress()"). String arguments must be enveloped in escaped double quotes (e.g., "compress(\"hello\")"). 1: unexpected end of input at 8..8
Detecting Quotes In Rust
Interestingly, the absence of outer double quotes is a little trickier. The Rust code I added attempts to test for double quotes via
starts_with
andends_with
, but this does not work. For example:let s = "compress(\"hello\")"; println!("starts_with: {}, ends_with: {}", s.starts_with("\""), s.ends_with("\""));
One would assume the result to be
starts_with: true, ends_with: true
but in reality the result is actually:starts_with: false, ends_with: false
Alas, this is not a validator that is good enough to know whether the exported function being invoked by
--invoke
is surrounded by double quotes. I did try (and succeeded) to see the outer double quotes when they actually do existed. For example:// This `invoke` that Rust sees here does not show the outer double quotes. Only the following `func()` or `func(42)`. let invoke: &String = self.invoke.as_ref().unwrap(); // However, I can get the raw data and see double quotes if/when they exist. For example `"func()"` or `"func(42)"`. let raw_invoke = format!("{:?}", invoke);
The overarching issue is that if a user does not surround the exported function in quotes, it fails in the shell long before the Rust even sees it. And the result is something along these lines:
$ wasmtime run --invoke compress(\"hello\") compress.wasm
zsh: unknown file attribute: "
I am stumped in finding a way to enforce outer double quotes in the
wasmtime run
CLI.(I am convinced that even something built into wasm-wave would not catch the missing outer double quotes in time anyway.)
For this reason, I ended up being a bit verbose on the documentation on this PR:
## `run` This is the `wasmtime` CLI's main subcommand, and it's also the default if no other subcommand is provided. The `run` command will execute a WebAssembly module. This means that the module will be compiled to native code, instantiated, and then optionally have an export executed. The `wasmtime` CLI will automatically hook up any WASI-related imported functionality, but at this time, if your module imports anything else, it will fail instantiation. The `run` command takes one positional argument, which is the name of the module to run: ```sh $ wasmtime run foo.wasm $ wasmtime foo.wasm ``` Note that the `wasmtime` CLI can take both a binary WebAssembly file (`*.wasm`) as well as the text format for WebAssembly (`*.wat`): ```sh $ wasmtime foo.wat ``` The `run` command accepts an optional `--invoke` argument, which is the name of an exported function of the module to run. ```sh $ wasmtime run --invoke "initialize()" foo.wasm ``` The exported function's name and exported function's parentheses must both be enclosed in one set of double quotes, i.e. `"initialize()"`. This treats the exported function as a single argument and prevents issues with shell interpretation. The presence of the parenthesis `()` signifies function invocation, as apposed to the function name just being referenced. This convention helps to distinguish function calls from other kinds of string arguments. **Note:** If your function takes a string argument, ensure that you use escaped double quotes inside the parentheses. For example: ```sh $ wasmtime run --invoke "initialize(\"hello\")" foo.wasm ``` Each individual argument within the parentheses must be separated by a comma: ```sh $ wasmtime run --invoke "initialize(\"Pi\", 3.14)" foo.wasm $ wasmtime run --invoke "add(1, 2)" foo.wasm ```
Hope all of that makes sense. Happy to do more - happy reviewing.
tpmccallum edited a comment on PR #10511:
Ok, signing off for the day.
cargo build --release
andcargo clippy
are :check:The absence of parentheses will give a helpful result:
$ wasmtime run --invoke "compress" compress.wasm
Error: failed to run main module `compress.wasm` Caused by: 0: Failed to parse invoke 'compress': function calls must be enveloped in double quotes and must include parentheses (e.g., "compress()"). String arguments must be enveloped in escaped double quotes (e.g., "compress(\"hello\")"). 1: unexpected end of input at 8..8
Detecting Quotes In Rust
Interestingly, the absence of outer double quotes is a little trickier. The Rust code I added attempts to test for double quotes via
starts_with
andends_with
, but this does not work. For example:let s = "compress(\"hello\")"; println!("starts_with: {}, ends_with: {}", s.starts_with("\""), s.ends_with("\""));
One would assume the result to be
starts_with: true, ends_with: true
but in reality the result is actually:starts_with: false, ends_with: false
Alas, this is not a validator that is good enough to know whether the exported function being invoked by
--invoke
is surrounded by double quotes. I did try (and succeeded using theformat!
macro) to see the outer double quotes when they actually do existed. For example:// This `invoke` that Rust sees here does not show the outer double quotes. Only the following `func()` or `func(42)`. let invoke: &String = self.invoke.as_ref().unwrap(); // However, I can get the raw data and see double quotes if/when they exist. For example `"func()"` or `"func(42)"`. let raw_invoke = format!("{:?}", invoke);
The overarching issue is that if a user does not surround the exported function in quotes, it fails in the shell long before the Rust even sees it. And the result is something along these lines:
$ wasmtime run --invoke compress(\"hello\") compress.wasm
zsh: unknown file attribute: "
I am stumped in finding a way to enforce outer double quotes in the
wasmtime run
CLI.(I am convinced that even something built into wasm-wave would not catch the missing outer double quotes in time anyway.)
For this reason, I ended up being a bit verbose on the documentation on this PR:
## `run` This is the `wasmtime` CLI's main subcommand, and it's also the default if no other subcommand is provided. The `run` command will execute a WebAssembly module. This means that the module will be compiled to native code, instantiated, and then optionally have an export executed. The `wasmtime` CLI will automatically hook up any WASI-related imported functionality, but at this time, if your module imports anything else, it will fail instantiation. The `run` command takes one positional argument, which is the name of the module to run: ```sh $ wasmtime run foo.wasm $ wasmtime foo.wasm ``` Note that the `wasmtime` CLI can take both a binary WebAssembly file (`*.wasm`) as well as the text format for WebAssembly (`*.wat`): ```sh $ wasmtime foo.wat ``` The `run` command accepts an optional `--invoke` argument, which is the name of an exported function of the module to run. ```sh $ wasmtime run --invoke "initialize()" foo.wasm ``` The exported function's name and exported function's parentheses must both be enclosed in one set of double quotes, i.e. `"initialize()"`. This treats the exported function as a single argument and prevents issues with shell interpretation. The presence of the parenthesis `()` signifies function invocation, as apposed to the function name just being referenced. This convention helps to distinguish function calls from other kinds of string arguments. **Note:** If your function takes a string argument, ensure that you use escaped double quotes inside the parentheses. For example: ```sh $ wasmtime run --invoke "initialize(\"hello\")" foo.wasm ``` Each individual argument within the parentheses must be separated by a comma: ```sh $ wasmtime run --invoke "initialize(\"Pi\", 3.14)" foo.wasm $ wasmtime run --invoke "add(1, 2)" foo.wasm ```
Hope all of that makes sense. Happy to do more - happy reviewing.
tpmccallum edited a comment on PR #10511:
Ok, signing off for the day.
cargo build --release
andcargo clippy
are :check:The absence of parentheses will give a helpful result:
$ wasmtime run --invoke "compress" compress.wasm
Error: failed to run main module `compress.wasm` Caused by: 0: Failed to parse invoke 'compress': function calls must be enveloped in double quotes and must include parentheses (e.g., "compress()"). String arguments must be enveloped in escaped double quotes (e.g., "compress(\"hello\")"). 1: unexpected end of input at 8..8
Detecting Quotes In Rust
Interestingly, the absence of outer double quotes is a little trickier. The Rust code I added attempts to test for double quotes via
starts_with
andends_with
, but this does not work. For example:let s = "compress(\"hello\")"; println!("starts_with: {}, ends_with: {}", s.starts_with("\""), s.ends_with("\""));
One would assume the result to be
starts_with: true, ends_with: true
but in reality the result is actually:starts_with: false, ends_with: false
Alas, this is not a validator that is good enough to know whether the exported function being invoked by
--invoke
is surrounded by double quotes. I did try (and succeeded using theformat!
macro) to see the outer double quotes when they actually do existed. For example:// This `invoke` that Rust sees here does not show the outer double quotes. Only the following `func()` or `func(42)`. let invoke: &String = self.invoke.as_ref().unwrap(); // However, I can get the raw data and see double quotes if/when they exist. For example `"func()"` or `"func(42)"`. let raw_invoke = format!("{:?}", invoke);
The overarching issue is that if a user does not surround the exported function in quotes, it fails in the shell long before the Rust even sees it. And the result is something along these lines:
$ wasmtime run --invoke compress(\"hello\") compress.wasm zsh: unknown file attribute: "
wasmtime run --invoke compress("hello") compress.wasm zsh: unknown file attribute: h
The following quoting examples do work, which is great.
$ wasmtime run --invoke "compress(\"hello\")" compress.wasm [40, 181, 47, 253, 0, 88, 41, 0, 0, 104, 101, 108, 108, 111]
$ wasmtime run --invoke 'compress("hello")' compress.wasm [40, 181, 47, 253, 0, 88, 41, 0, 0, 104, 101, 108, 108, 111]
Assist
I am stumped in finding a way to enforce outer double or single quotes in the
wasmtime run
CLI.(I am convinced that even something built into wasm-wave would not catch the missing outer double quotes in time either. The errors with no outer quotes are stopped in their tracks in the CLI)
For this reason, I ended up being a bit verbose on the documentation on this PR
Hope all of that makes sense. Happy to do more - happy reviewing.
tpmccallum edited a comment on PR #10511:
Ok, signing off for the day.
cargo build --release
andcargo clippy
are :check:The absence of parentheses will give a helpful result:
$ wasmtime run --invoke "compress" compress.wasm
Error: failed to run main module `compress.wasm` Caused by: 0: Failed to parse invoke 'compress': function calls must be enveloped in double quotes and must include parentheses (e.g., "compress()"). String arguments must be enveloped in escaped double quotes (e.g., "compress(\"hello\")"). 1: unexpected end of input at 8..8
Detecting Quotes In Rust
Interestingly, the absence of outer double quotes is a little trickier. The Rust code I added attempts to test for double quotes via
starts_with
andends_with
, but this does not work. For example:let s = "compress(\"hello\")"; println!("starts_with: {}, ends_with: {}", s.starts_with("\""), s.ends_with("\""));
One would assume the result to be
starts_with: true, ends_with: true
but in reality the result is actually:starts_with: false, ends_with: false
Alas, this is not a validator that is good enough to know whether the exported function being invoked by
--invoke
is surrounded by double quotes. I did try (and succeeded using theformat!
macro) to see the outer double quotes when they actually do existed. For example:// This `invoke` that Rust sees here does not show the outer double quotes. Only the following `func()` or `func(42)`. let invoke: &String = self.invoke.as_ref().unwrap(); // However, I can get the raw data and see double quotes if/when they exist. For example `"func()"` or `"func(42)"`. let raw_invoke = format!("{:?}", invoke);
The overarching issue is that if a user does not surround the exported function in quotes, it fails in the shell long before the Rust even sees it. And the result is something along these lines:
$ wasmtime run --invoke compress(\"hello\") compress.wasm zsh: unknown file attribute: "
wasmtime run --invoke compress("hello") compress.wasm zsh: unknown file attribute: h
The following quoting examples do work, which is great.
$ wasmtime run --invoke "compress(\"hello\")" compress.wasm [40, 181, 47, 253, 0, 88, 41, 0, 0, 104, 101, 108, 108, 111]
$ wasmtime run --invoke 'compress("hello")' compress.wasm [40, 181, 47, 253, 0, 88, 41, 0, 0, 104, 101, 108, 108, 111]
Assist
I am stumped in finding a way to enforce outer double or single quotes in the
wasmtime run
CLI.(I am convinced that even something built into wasm-wave would not catch the missing outer double quotes in time either. The errors with no outer quotes are stopped in their tracks in the CLI)
For this reason, I ended up being a bit verbose on the documentation on this PR
Hope all of that makes sense. Happy to do more - happy reviewing.
Last updated: Apr 17 2025 at 04:04 UTC