Stream: git-wasmtime

Topic: wasmtime / issue #6074 wasmtime report import `streams` h...


view this post on Zulip Wasmtime GitHub notifications bot (Mar 21 2023 at 09:42):

Sherlock-Holo opened issue #6074:

Thanks for filing a bug report! Please fill out the TODOs below.

Note: if you want to report a security issue, please read our security policy!

Test Case

wit file

default world http {
    import get: func(url: string) -> result<string, string>
    export run: func(url: string) -> result<string, string>
}

rust wasm code

wit_bindgen::generate!("world");

struct Runner;

impl Http for Runner {
    fn run(url: String) -> Result<String, String> {
        let resp = get(&url)?;

        Ok(format!("wasm response: {resp}"))
        // Ok("wasm response: ".to_string() + &resp)
        // Ok(resp)
    }
}

export_http!(Runner);

rust normal codes

use async_trait::async_trait;
use wasmtime::component::{bindgen, Component, Linker};
use wasmtime::{Config, Engine, Store};

bindgen!({
    path: "../wit",
    async: true,
});

struct Function;

impl Function {
    async fn inner_get(&mut self, url: &str) -> Result<String, String> {
        let resp = reqwest::get(url).await.map_err(|err| err.to_string())?;

        Ok(resp.status().to_string())
    }
}

#[async_trait]
impl HttpImports for Function {
    async fn get(&mut self, url: String) -> wasmtime::Result<Result<String, String>> {
        Ok(self.inner_get(&url).await)
    }
}

#[tokio::main(flavor = "current_thread")]
async fn main() {
    let mut config = Config::new();
    config.wasm_component_model(true).async_support(true);
    let engine = Engine::new(&config).unwrap();
    let component = Component::from_file(&engine, "../target/component.wasm").unwrap();
    let mut linker = Linker::new(&engine);
    Http::add_to_linker(&mut linker, |state: &mut Function| state).unwrap();
    let mut store = Store::new(&engine, Function);

    let (http, _instance) = Http::instantiate_async(&mut store, &component, &linker)
        .await
        .unwrap();

    let result = http
        .call_run(&mut store, "http://www.example.com")
        .await
        .unwrap();
    println!("{:?}", result);
}

Steps to Reproduce

I build the rust wasm codes with cargo b -r, the target is set on .cargo/config.toml

[build]
target = "wasm32-wasi"

then I download the https://github.com/bytecodealliance/preview2-prototyping/releases/download/latest/wasi_snapshot_preview1.reactor.wasm and rename it to wasi_snapshot_preview1.wasm

then run wasm-tools component new ../target/wasm32-wasi/release/wasm.wasm -o ../target/component.wasm --adapt ../wasi_snapshot_preview1.wasm to compile the wasm file, no error

then I run the normal codes, it report error

thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: import `streams` has the wrong type

Caused by:
    0: instance export `drop-input-stream` has the wrong type
    1: expected func found nothing', runtime/src/main.rs:39:10
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

I run wasm-tools component wit ../target/component.wasm to dump the wit file, it shows

interface streams {
  type input-stream = u32

  type output-stream = u32

  record stream-error {
  }

  drop-input-stream: func(this: input-stream)

  write: func(this: output-stream, buf: list<u8>) -> result<u64, stream-error>

  drop-output-stream: func(this: output-stream)
}

interface filesystem {
  use self.streams.{output-stream}

  type descriptor = u32

  type filesize = u64

  write-via-stream: func(this: descriptor, offset: filesize) -> output-stream

  append-via-stream: func(this: descriptor) -> output-stream

  drop-descriptor: func(this: descriptor)
}

interface environment {
  get-environment: func() -> list<tuple<string, string>>
}

interface exit {
  exit: func(status: result)
}

interface stderr {
  print: func(message: string)
}

default world component {
  import streams: self.streams
  import filesystem: self.filesystem
  import environment: self.environment
  import exit: self.exit
  import stderr: self.stderr
  import get: func(url: string) -> result<string, string>
  export run: func(url: string) -> result<string, string>
}

a lot of things, but if I remove the Ok(format!("wasm response: {resp}")) in the rust wasm codes, replace with Ok(resp), dump again and it will shows

default world component {
  import get: func(url: string) -> result<string, string>
  export run: func(url: string) -> result<string, string>
}

it looks like normal

Expected Results

works well

Versions and Environment

Wasmtime version or commit: wasmtime crate 7.0.0

Operating system: Archlinux

Architecture: x64

view this post on Zulip Wasmtime GitHub notifications bot (Mar 21 2023 at 09:42):

Sherlock-Holo labeled issue #6074:

Thanks for filing a bug report! Please fill out the TODOs below.

Note: if you want to report a security issue, please read our security policy!

Test Case

wit file

default world http {
    import get: func(url: string) -> result<string, string>
    export run: func(url: string) -> result<string, string>
}

rust wasm code

wit_bindgen::generate!("world");

struct Runner;

impl Http for Runner {
    fn run(url: String) -> Result<String, String> {
        let resp = get(&url)?;

        Ok(format!("wasm response: {resp}"))
        // Ok("wasm response: ".to_string() + &resp)
        // Ok(resp)
    }
}

export_http!(Runner);

rust normal codes

use async_trait::async_trait;
use wasmtime::component::{bindgen, Component, Linker};
use wasmtime::{Config, Engine, Store};

bindgen!({
    path: "../wit",
    async: true,
});

struct Function;

impl Function {
    async fn inner_get(&mut self, url: &str) -> Result<String, String> {
        let resp = reqwest::get(url).await.map_err(|err| err.to_string())?;

        Ok(resp.status().to_string())
    }
}

#[async_trait]
impl HttpImports for Function {
    async fn get(&mut self, url: String) -> wasmtime::Result<Result<String, String>> {
        Ok(self.inner_get(&url).await)
    }
}

#[tokio::main(flavor = "current_thread")]
async fn main() {
    let mut config = Config::new();
    config.wasm_component_model(true).async_support(true);
    let engine = Engine::new(&config).unwrap();
    let component = Component::from_file(&engine, "../target/component.wasm").unwrap();
    let mut linker = Linker::new(&engine);
    Http::add_to_linker(&mut linker, |state: &mut Function| state).unwrap();
    let mut store = Store::new(&engine, Function);

    let (http, _instance) = Http::instantiate_async(&mut store, &component, &linker)
        .await
        .unwrap();

    let result = http
        .call_run(&mut store, "http://www.example.com")
        .await
        .unwrap();
    println!("{:?}", result);
}

Steps to Reproduce

I build the rust wasm codes with cargo b -r, the target is set on .cargo/config.toml

[build]
target = "wasm32-wasi"

then I download the https://github.com/bytecodealliance/preview2-prototyping/releases/download/latest/wasi_snapshot_preview1.reactor.wasm and rename it to wasi_snapshot_preview1.wasm

then run wasm-tools component new ../target/wasm32-wasi/release/wasm.wasm -o ../target/component.wasm --adapt ../wasi_snapshot_preview1.wasm to compile the wasm file, no error

then I run the normal codes, it report error

thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: import `streams` has the wrong type

Caused by:
    0: instance export `drop-input-stream` has the wrong type
    1: expected func found nothing', runtime/src/main.rs:39:10
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

I run wasm-tools component wit ../target/component.wasm to dump the wit file, it shows

interface streams {
  type input-stream = u32

  type output-stream = u32

  record stream-error {
  }

  drop-input-stream: func(this: input-stream)

  write: func(this: output-stream, buf: list<u8>) -> result<u64, stream-error>

  drop-output-stream: func(this: output-stream)
}

interface filesystem {
  use self.streams.{output-stream}

  type descriptor = u32

  type filesize = u64

  write-via-stream: func(this: descriptor, offset: filesize) -> output-stream

  append-via-stream: func(this: descriptor) -> output-stream

  drop-descriptor: func(this: descriptor)
}

interface environment {
  get-environment: func() -> list<tuple<string, string>>
}

interface exit {
  exit: func(status: result)
}

interface stderr {
  print: func(message: string)
}

default world component {
  import streams: self.streams
  import filesystem: self.filesystem
  import environment: self.environment
  import exit: self.exit
  import stderr: self.stderr
  import get: func(url: string) -> result<string, string>
  export run: func(url: string) -> result<string, string>
}

a lot of things, but if I remove the Ok(format!("wasm response: {resp}")) in the rust wasm codes, replace with Ok(resp), dump again and it will shows

default world component {
  import get: func(url: string) -> result<string, string>
  export run: func(url: string) -> result<string, string>
}

it looks like normal

Expected Results

works well

Versions and Environment

Wasmtime version or commit: wasmtime crate 7.0.0

Operating system: Archlinux

Architecture: x64

view this post on Zulip Wasmtime GitHub notifications bot (Mar 21 2023 at 10:03):

bjorn3 commented on issue #6074:

I think if you use wasi_snapshot_preview1.wasm you will need to provide an implementation of wasi_snapshot_preview2 on the host side. Wasmtime doesn't have an implementation of this yet afaik.

view this post on Zulip Wasmtime GitHub notifications bot (Mar 21 2023 at 11:20):

Sherlock-Holo commented on issue #6074:

@bjorn3 could you tell me how to add the

implementation of wasi_snapshot_preview2

I try to use the wasmtime::Linker

let mut linker = Linker::new(&engine);
let wasi_ctx = WasiCtxBuilder::new()
        .inherit_stdio()
        .inherit_args()
        .unwrap()
        .inherit_env()
        .unwrap()
        .build();
wasmtime_wasi::add_to_linker(&mut linker, |state: &mut Function| &mut state.wasi_ctx).unwrap();

but run still report same error

view this post on Zulip Wasmtime GitHub notifications bot (Mar 21 2023 at 12:22):

bjorn3 commented on issue #6074:

wasmtime_wasi is an implementation of wasi_snapshot_preview1, not the wasi_snapshot_preview2 you need.

view this post on Zulip Wasmtime GitHub notifications bot (Mar 21 2023 at 12:24):

Sherlock-Holo commented on issue #6074:

so i can't use the component model feature to write normal rust wasm codes, until wasmtime support preview2 ?

view this post on Zulip Wasmtime GitHub notifications bot (Mar 21 2023 at 12:27):

Sherlock-Holo commented on issue #6074:

but why if i return the resp directly, ot can works on wasmtime?

view this post on Zulip Wasmtime GitHub notifications bot (Mar 21 2023 at 12:34):

bjorn3 commented on issue #6074:

so i can't use the component model feature to write normal rust wasm codes, until wasmtime support preview2 ?

Yeah, using wasi with wasm components requires wasi preview2. I just found that https://github.com/bytecodealliance/preview2-prototyping has host support for wasi preview2 in the host/ directory. Be aware that it depends on a specific commit of wasmtime, so you will need to specify the exact same version of wasmtime: https://github.com/bytecodealliance/preview2-prototyping/blob/b4eb2043b165971820e60f077076c9484de283ed/host/Cargo.toml#L14

but why if i return the resp directly, ot can works on wasmtime?

The wasi_snapshot_preview1.wasm adapter probably got skipped due to the inner wasm module not needing any of the wasi methods when directly returning the response. Printing the response requires wasi and thus the wasi_snapshot_preview1 -> wasi_snapshot_preview2 adapter and in turn means the final wasm component needs wasi_snapshot_preview2.

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

Sherlock-Holo commented on issue #6074:

I change to
wasmtime = { git = "https://github.com/bytecodealliance/wasmtime", rev = "5ae8575296d5b524cde42ad10badf8c89945105a", features = ["component-model"] }
but still report error

thread 'main' panicked at 'called Result::unwrap() on an Err value: import streams has the wrong type

Caused by:
0: instance export drop-input-stream has the wrong type
1: expected func found nothing', runtime/src/main.rs:42:10
note: run with RUST_BACKTRACE=1 environment variable to display a backtrace

anything I miss?

view this post on Zulip Wasmtime GitHub notifications bot (Mar 22 2023 at 04:17):

pchickey commented on issue #6074:

are you using the preview1.wasm adapter and host crate from the same revision of preview2-prototyping? use the host crate's command::add_to_linker on your wasmtime::component::Linker in order to provide the drop-import-stream export func that is reported missing there

view this post on Zulip Wasmtime GitHub notifications bot (Mar 22 2023 at 07:16):

Sherlock-Holo commented on issue #6074:

I change the Cargo.toml to

[package]
name = "runtime"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
clap = { version = "4", features = ["derive"] }
tokio = { version = "1", features = ["rt", "macros", "time"] }
reqwest = "0.11"
wasmtime = { version = "7", features = ["component-model"] }
#wasmtime = { git = "https://github.com/bytecodealliance/wasmtime", rev = "5ae8575296d5b524cde42ad10badf8c89945105a", features = ["component-model"] }
#wasmtime = { git = "https://github.com/bytecodealliance/wasmtime", branch = "main", features = ["component-model"] }
host = { git = "https://github.com/bytecodealliance/preview2-prototyping", branch = "main" }
wasi-cap-std-sync = { git = "https://github.com/bytecodealliance/preview2-prototyping", branch = "main" }
async-trait = "0.1"

and add command::add_to_linker(&mut linker, |state: &mut Function| &mut state.wasi_ctx).unwrap();, it works!

thanks for your help~

view this post on Zulip Wasmtime GitHub notifications bot (Mar 22 2023 at 08:12):

Sherlock-Holo closed issue #6074:

Thanks for filing a bug report! Please fill out the TODOs below.

Note: if you want to report a security issue, please read our security policy!

Test Case

wit file

default world http {
    import get: func(url: string) -> result<string, string>
    export run: func(url: string) -> result<string, string>
}

rust wasm code

wit_bindgen::generate!("world");

struct Runner;

impl Http for Runner {
    fn run(url: String) -> Result<String, String> {
        let resp = get(&url)?;

        Ok(format!("wasm response: {resp}"))
        // Ok("wasm response: ".to_string() + &resp)
        // Ok(resp)
    }
}

export_http!(Runner);

rust normal codes

use async_trait::async_trait;
use wasmtime::component::{bindgen, Component, Linker};
use wasmtime::{Config, Engine, Store};

bindgen!({
    path: "../wit",
    async: true,
});

struct Function;

impl Function {
    async fn inner_get(&mut self, url: &str) -> Result<String, String> {
        let resp = reqwest::get(url).await.map_err(|err| err.to_string())?;

        Ok(resp.status().to_string())
    }
}

#[async_trait]
impl HttpImports for Function {
    async fn get(&mut self, url: String) -> wasmtime::Result<Result<String, String>> {
        Ok(self.inner_get(&url).await)
    }
}

#[tokio::main(flavor = "current_thread")]
async fn main() {
    let mut config = Config::new();
    config.wasm_component_model(true).async_support(true);
    let engine = Engine::new(&config).unwrap();
    let component = Component::from_file(&engine, "../target/component.wasm").unwrap();
    let mut linker = Linker::new(&engine);
    Http::add_to_linker(&mut linker, |state: &mut Function| state).unwrap();
    let mut store = Store::new(&engine, Function);

    let (http, _instance) = Http::instantiate_async(&mut store, &component, &linker)
        .await
        .unwrap();

    let result = http
        .call_run(&mut store, "http://www.example.com")
        .await
        .unwrap();
    println!("{:?}", result);
}

Steps to Reproduce

I build the rust wasm codes with cargo b -r, the target is set on .cargo/config.toml

[build]
target = "wasm32-wasi"

then I download the https://github.com/bytecodealliance/preview2-prototyping/releases/download/latest/wasi_snapshot_preview1.reactor.wasm and rename it to wasi_snapshot_preview1.wasm

then run wasm-tools component new ../target/wasm32-wasi/release/wasm.wasm -o ../target/component.wasm --adapt ../wasi_snapshot_preview1.wasm to compile the wasm file, no error

then I run the normal codes, it report error

thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: import `streams` has the wrong type

Caused by:
    0: instance export `drop-input-stream` has the wrong type
    1: expected func found nothing', runtime/src/main.rs:39:10
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

I run wasm-tools component wit ../target/component.wasm to dump the wit file, it shows

interface streams {
  type input-stream = u32

  type output-stream = u32

  record stream-error {
  }

  drop-input-stream: func(this: input-stream)

  write: func(this: output-stream, buf: list<u8>) -> result<u64, stream-error>

  drop-output-stream: func(this: output-stream)
}

interface filesystem {
  use self.streams.{output-stream}

  type descriptor = u32

  type filesize = u64

  write-via-stream: func(this: descriptor, offset: filesize) -> output-stream

  append-via-stream: func(this: descriptor) -> output-stream

  drop-descriptor: func(this: descriptor)
}

interface environment {
  get-environment: func() -> list<tuple<string, string>>
}

interface exit {
  exit: func(status: result)
}

interface stderr {
  print: func(message: string)
}

default world component {
  import streams: self.streams
  import filesystem: self.filesystem
  import environment: self.environment
  import exit: self.exit
  import stderr: self.stderr
  import get: func(url: string) -> result<string, string>
  export run: func(url: string) -> result<string, string>
}

a lot of things, but if I remove the Ok(format!("wasm response: {resp}")) in the rust wasm codes, replace with Ok(resp), dump again and it will shows

default world component {
  import get: func(url: string) -> result<string, string>
  export run: func(url: string) -> result<string, string>
}

it looks like normal

Expected Results

works well

Versions and Environment

Wasmtime version or commit: wasmtime crate 7.0.0

Operating system: Archlinux

Architecture: x64

view this post on Zulip Wasmtime GitHub notifications bot (Jun 07 2023 at 19:45):

DougAnderson444 commented on issue #6074:

I am still seeing this error, noting that a few things have changed since March

Error: import `wasi:io/streams` has the wrong type

Caused by:
    0: instance export `drop-input-stream` has the wrong type
    1: expected func found nothing

1) First I used --adapt as per the instructions

2) Next I also see that preview2-prototyping moved to crates/wasi-preview1-component-adapter so I also tried

# Cargo.toml
[dev-dependencies]
wasi-preview1-component-adapter = { git = "https://github.com/bytecodealliance/wasmtime", default-features = false, features = [
    "command",
] }

...in order to use the command::add_to_linker move, but the feature selection doesn't seem to be working as command isn't available?


Last updated: Dec 23 2024 at 12:05 UTC