Stream: git-wasmtime

Topic: wasmtime / PR #10511 Invoke wave enhancements


view this post on Zulip Wasmtime GitHub notifications bot (Apr 02 2025 at 07:19):

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 thedocs/cli-options.md file of this PR).

view this post on Zulip Wasmtime GitHub notifications bot (Apr 02 2025 at 07:19):

tpmccallum requested alexcrichton for a review on PR #10511.

view this post on Zulip Wasmtime GitHub notifications bot (Apr 02 2025 at 07:19):

tpmccallum requested wasmtime-core-reviewers for a review on PR #10511.

view this post on Zulip Wasmtime GitHub notifications bot (Apr 02 2025 at 07:19):

tpmccallum requested wasmtime-default-reviewers for a review on PR #10511.

view this post on Zulip Wasmtime GitHub notifications bot (Apr 02 2025 at 07:31):

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 your pch/invoke_wave branch; I'm not sure why pch/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 thedocs/cli-options.md file of this PR).

view this post on Zulip Wasmtime GitHub notifications bot (Apr 02 2025 at 08:38):

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 your pch/invoke_wave branch). I'm not sure why pch/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 thedocs/cli-options.md file of this PR).

view this post on Zulip Wasmtime GitHub notifications bot (Apr 02 2025 at 08:41):

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 your pch/invoke_wave branch). I'm not sure why pch/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 thedocs/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>;
}

lib.rs:

#[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]

view this post on Zulip Wasmtime GitHub notifications bot (Apr 02 2025 at 14:37):

pchickey requested wasmtime-fuzz-reviewers for a review on PR #10511.

view this post on Zulip Wasmtime GitHub notifications bot (Apr 02 2025 at 14:37):

pchickey requested wasmtime-compiler-reviewers for a review on PR #10511.

view this post on Zulip Wasmtime GitHub notifications bot (Apr 02 2025 at 14:37):

pchickey requested cfallin for a review on PR #10511.

view this post on Zulip Wasmtime GitHub notifications bot (Apr 02 2025 at 14:37):

pchickey edited PR #10511.

view this post on Zulip Wasmtime GitHub notifications bot (Apr 02 2025 at 14:44):

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.

view this post on Zulip Wasmtime GitHub notifications bot (Apr 02 2025 at 14:44):

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

view this post on Zulip Wasmtime GitHub notifications bot (Apr 02 2025 at 22:06):

tpmccallum submitted PR review.

view this post on Zulip Wasmtime GitHub notifications bot (Apr 02 2025 at 22:06):

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.

view this post on Zulip Wasmtime GitHub notifications bot (Apr 02 2025 at 22:32):

tpmccallum submitted PR review.

view this post on Zulip Wasmtime GitHub notifications bot (Apr 02 2025 at 22:32):

tpmccallum created PR review comment:

Ok, I did a cargo clean and cargo 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 ... :)

view this post on Zulip Wasmtime GitHub notifications bot (Apr 02 2025 at 23:39):

tpmccallum edited PR review comment.

view this post on Zulip Wasmtime GitHub notifications bot (Apr 02 2025 at 23:43):

tpmccallum edited PR review comment.

view this post on Zulip Wasmtime GitHub notifications bot (Apr 02 2025 at 23:49):

tpmccallum edited PR review comment.

view this post on Zulip Wasmtime GitHub notifications bot (Apr 03 2025 at 00:55):

tpmccallum submitted PR review.

view this post on Zulip Wasmtime GitHub notifications bot (Apr 03 2025 at 00:55):

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.

view this post on Zulip Wasmtime GitHub notifications bot (Apr 03 2025 at 01:03):

tpmccallum updated PR #10511.

view this post on Zulip Wasmtime GitHub notifications bot (Apr 03 2025 at 01:07):

tpmccallum updated PR #10511.

view this post on Zulip Wasmtime GitHub notifications bot (Apr 03 2025 at 04:07):

tpmccallum updated PR #10511.

view this post on Zulip Wasmtime GitHub notifications bot (Apr 03 2025 at 04:50):

tpmccallum updated PR #10511.

view this post on Zulip Wasmtime GitHub notifications bot (Apr 03 2025 at 05:42):

tpmccallum updated PR #10511.

view this post on Zulip Wasmtime GitHub notifications bot (Apr 03 2025 at 05:42):

tpmccallum commented on PR #10511:

Ok, signing off for the day.
cargo build --release and cargo 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 and ends_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.

view this post on Zulip Wasmtime GitHub notifications bot (Apr 03 2025 at 05:44):

tpmccallum edited a comment on PR #10511:

Ok, signing off for the day.
cargo build --release and cargo 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 and ends_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.

view this post on Zulip Wasmtime GitHub notifications bot (Apr 03 2025 at 05:45):

tpmccallum updated PR #10511.

view this post on Zulip Wasmtime GitHub notifications bot (Apr 03 2025 at 05:45):

tpmccallum edited a comment on PR #10511:

Ok, signing off for the day.
cargo build --release and cargo 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 and ends_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.

view this post on Zulip Wasmtime GitHub notifications bot (Apr 03 2025 at 05:47):

tpmccallum edited a comment on PR #10511:

Ok, signing off for the day.
cargo build --release and cargo 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 and ends_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.

view this post on Zulip Wasmtime GitHub notifications bot (Apr 03 2025 at 10:45):

tpmccallum requested pchickey for a review on PR #10511.

view this post on Zulip Wasmtime GitHub notifications bot (Apr 04 2025 at 15:58):

pchickey merged PR #10511.

view this post on Zulip Wasmtime GitHub notifications bot (Apr 05 2025 at 00:46):

tpmccallum edited a comment on PR #10511:

Ok, signing off for the day.
cargo build --release and cargo 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 and ends_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.

view this post on Zulip Wasmtime GitHub notifications bot (Apr 05 2025 at 01:51):

tpmccallum edited a comment on PR #10511:

Ok, signing off for the day.
cargo build --release and cargo 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 and ends_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 the format! 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.

view this post on Zulip Wasmtime GitHub notifications bot (Apr 05 2025 at 02:08):

tpmccallum edited a comment on PR #10511:

Ok, signing off for the day.
cargo build --release and cargo 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 and ends_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 the format! 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.

view this post on Zulip Wasmtime GitHub notifications bot (Apr 05 2025 at 02:10):

tpmccallum edited a comment on PR #10511:

Ok, signing off for the day.
cargo build --release and cargo 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 and ends_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 the format! 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