1 #![cfg(not(miri))] // not testing unsafe code
2 
3 use wasmtime::component::{Component, Func, Linker, ResourceAny};
4 use wasmtime::{Config, Engine, Result, Store};
5 
async_store() -> Store<()>6 fn async_store() -> Store<()> {
7     let engine = Engine::default();
8     let mut store = Store::new(&engine, ());
9     wasmtime::Func::wrap_async(&mut store, |_, ()| Box::new(async {}));
10     return store;
11 }
12 
func_in_store(store: &mut Store<()>) -> Result<Func>13 async fn func_in_store(store: &mut Store<()>) -> Result<Func> {
14     let component = Component::new(
15         store.engine(),
16         r#"
17             (component
18                 (core module $a
19                     (func (export "hi") )
20                 )
21                 (core instance $i (instantiate $a))
22                 (func (export "hi") (canon lift (core func $i "hi")))
23             )
24         "#,
25     )?;
26     let instance = Linker::new(store.engine())
27         .instantiate_async(&mut *store, &component)
28         .await?;
29     let func = instance.get_func(&mut *store, "hi").unwrap();
30     Ok(func)
31 }
32 
assert_requires_async<T>(store: &mut Store<T>)33 fn assert_requires_async<T>(store: &mut Store<T>) {
34     let module = wasmtime::Module::new(store.engine(), "(module)").unwrap();
35     assert!(wasmtime::Instance::new(&mut *store, &module, &[]).is_err());
36 }
37 
38 #[tokio::test]
async_disallows_func_call() -> Result<()>39 async fn async_disallows_func_call() -> Result<()> {
40     let mut store = async_store();
41     let func = func_in_store(&mut store).await?;
42     assert!(func.call(&mut store, &[], &mut []).is_err());
43     func.call_async(&mut store, &[], &mut []).await?;
44     Ok(())
45 }
46 
47 #[tokio::test]
async_disallows_typed_func_call() -> Result<()>48 async fn async_disallows_typed_func_call() -> Result<()> {
49     let mut store = async_store();
50     let func = func_in_store(&mut store).await?;
51     let func = func.typed::<(), ()>(&store)?;
52     assert!(func.call(&mut store, ()).is_err());
53     func.call_async(&mut store, ()).await?;
54     Ok(())
55 }
56 
57 #[tokio::test]
async_disallows_instantiate() -> Result<()>58 async fn async_disallows_instantiate() -> Result<()> {
59     let mut store = async_store();
60     let component = Component::new(store.engine(), "(component)")?;
61     let linker = Linker::new(store.engine());
62     assert!(linker.instantiate(&mut store, &component).is_err());
63     linker.instantiate_async(&mut store, &component).await?;
64     Ok(())
65 }
66 
67 #[tokio::test]
require_async_after_linker_with_func_wrap_async() -> Result<()>68 async fn require_async_after_linker_with_func_wrap_async() -> Result<()> {
69     let engine = Engine::default();
70     let mut store = Store::new(&engine, ());
71     let mut linker = Linker::new(store.engine());
72     linker
73         .root()
74         .func_wrap_async("hi", |_, ()| Box::new(async { Ok(()) }))?;
75     let module = Component::new(
76         store.engine(),
77         r#"
78             (component
79                 (import "hi" (func))
80                 (core func (canon lower (func 0)))
81             )
82         "#,
83     )?;
84     linker.instantiate_async(&mut store, &module).await?;
85     assert_requires_async(&mut store);
86     Ok(())
87 }
88 
89 #[tokio::test]
require_async_after_linker_with_func_wrap_concurrent() -> Result<()>90 async fn require_async_after_linker_with_func_wrap_concurrent() -> Result<()> {
91     let mut config = Config::new();
92     config.wasm_component_model_async(true);
93     let engine = Engine::new(&config)?;
94     let mut store = Store::new(&engine, ());
95     let mut linker = Linker::new(store.engine());
96     linker
97         .root()
98         .func_wrap_concurrent("hi", |_, ()| Box::pin(async { Ok(()) }))?;
99     let module = Component::new(
100         store.engine(),
101         r#"
102             (component
103                 (import "hi" (func async))
104                 (core func (canon lower (func 0)))
105             )
106         "#,
107     )?;
108     linker.instantiate_async(&mut store, &module).await?;
109     assert_requires_async(&mut store);
110     Ok(())
111 }
112 
113 #[tokio::test]
require_async_after_linker_with_func_new_async() -> Result<()>114 async fn require_async_after_linker_with_func_new_async() -> Result<()> {
115     let engine = Engine::default();
116     let mut store = Store::new(&engine, ());
117     let mut linker = Linker::new(store.engine());
118     linker
119         .root()
120         .func_new_async("hi", |_, _, _, _| Box::new(async { Ok(()) }))?;
121     let module = Component::new(
122         store.engine(),
123         r#"
124             (component
125                 (import "hi" (func))
126                 (core func (canon lower (func 0)))
127             )
128         "#,
129     )?;
130     linker.instantiate_async(&mut store, &module).await?;
131     assert_requires_async(&mut store);
132     Ok(())
133 }
134 
135 #[tokio::test]
require_async_after_linker_with_func_new_concurrent() -> Result<()>136 async fn require_async_after_linker_with_func_new_concurrent() -> Result<()> {
137     let mut config = Config::new();
138     config.wasm_component_model_async(true);
139     let engine = Engine::new(&config)?;
140     let mut store = Store::new(&engine, ());
141     let mut linker = Linker::new(store.engine());
142     linker
143         .root()
144         .func_new_concurrent("hi", |_, _, _, _| Box::pin(async { Ok(()) }))?;
145     let module = Component::new(
146         store.engine(),
147         r#"
148             (component
149                 (import "hi" (func async))
150                 (core func (canon lower (func 0)))
151             )
152         "#,
153     )?;
154     linker.instantiate_async(&mut store, &module).await?;
155     assert_requires_async(&mut store);
156     Ok(())
157 }
158 
159 #[tokio::test]
async_disallows_resource_any_drop() -> Result<()>160 async fn async_disallows_resource_any_drop() -> Result<()> {
161     let mut store = async_store();
162     let component = Component::new(
163         store.engine(),
164         r#"
165             (component
166                 (type $t' (resource (rep i32)))
167                 (export $t "t" (type $t'))
168 
169                 (core func $new (canon resource.new $t))
170                 (func (export "mk") (param "r" u32) (result (own $t))
171                     (canon lift (core func $new))
172                 )
173             )
174         "#,
175     )?;
176     let instance = Linker::new(store.engine())
177         .instantiate_async(&mut store, &component)
178         .await?;
179     let func = instance.get_typed_func::<(u32,), (ResourceAny,)>(&mut store, "mk")?;
180     let (resource,) = func.call_async(&mut store, (42,)).await?;
181 
182     assert!(resource.resource_drop(&mut store).is_err());
183     resource.resource_drop_async(&mut store).await?;
184 
185     Ok(())
186 }
187