1 #![cfg(not(miri))]
2 
3 use super::engine;
4 use wasmtime::Result;
5 use wasmtime::{
6     Config, Engine, Store,
7     component::{Component, Linker},
8 };
9 
10 mod ownership;
11 mod results;
12 
13 mod no_imports {
14     use super::*;
15     use std::rc::Rc;
16 
17     wasmtime::component::bindgen!({
18         inline: "
19             package foo:foo;
20 
21             world no-imports {
22                 export foo: interface {
23                     foo: func();
24                 }
25 
26                 export bar: func();
27             }
28         ",
29     });
30 
31     #[test]
run() -> Result<()>32     fn run() -> Result<()> {
33         let engine = engine();
34 
35         let component = Component::new(
36             &engine,
37             r#"
38                 (component
39                     (core module $m
40                         (func (export ""))
41                     )
42                     (core instance $i (instantiate $m))
43 
44                     (func $f (export "bar") (canon lift (core func $i "")))
45 
46                     (instance $i (export "foo" (func $f)))
47                     (export "foo" (instance $i))
48                 )
49             "#,
50         )?;
51 
52         let linker = Linker::new(&engine);
53         let mut store = Store::new(&engine, ());
54         let no_imports = NoImports::instantiate(&mut store, &component, &linker)?;
55         no_imports.call_bar(&mut store)?;
56         no_imports.foo().call_foo(&mut store)?;
57 
58         let linker = Linker::new(&engine);
59         let mut non_send_store = Store::new(&engine, Rc::new(()));
60         let no_imports = NoImports::instantiate(&mut non_send_store, &component, &linker)?;
61         no_imports.call_bar(&mut non_send_store)?;
62         no_imports.foo().call_foo(&mut non_send_store)?;
63         Ok(())
64     }
65 }
66 
67 mod no_imports_concurrent {
68     use super::*;
69     use futures::{
70         FutureExt,
71         stream::{FuturesUnordered, TryStreamExt},
72     };
73 
74     wasmtime::component::bindgen!({
75         inline: "
76             package foo:foo;
77 
78             world no-imports {
79                 export foo: interface {
80                     foo: async func();
81                 }
82 
83                 export bar: async func();
84             }
85         ",
86     });
87 
88     #[tokio::test]
run() -> Result<()>89     async fn run() -> Result<()> {
90         let mut config = Config::new();
91         config.wasm_component_model_async(true);
92         let engine = &Engine::new(&config)?;
93 
94         let component = Component::new(
95             &engine,
96             r#"
97                 (component
98                     (core module $m
99                         (import "" "task.return" (func $task-return))
100                         (func (export "bar") (result i32)
101                             call $task-return
102                             i32.const 0
103                         )
104                         (func (export "callback") (param i32 i32 i32) (result i32) unreachable)
105                     )
106                     (core func $task-return (canon task.return))
107                     (core instance $i (instantiate $m
108                         (with "" (instance (export "task.return" (func $task-return))))
109                     ))
110 
111                     (func $f (export "bar")
112                         (canon lift (core func $i "bar") async (callback (func $i "callback")))
113                     )
114 
115                     (instance $i (export "foo" (func $f)))
116                     (export "foo" (instance $i))
117                 )
118             "#,
119         )?;
120 
121         let linker = Linker::new(&engine);
122         let mut store = Store::new(&engine, ());
123         let no_imports = NoImports::instantiate_async(&mut store, &component, &linker).await?;
124         store
125             .run_concurrent(async move |accessor| {
126                 let mut futures = FuturesUnordered::new();
127                 futures.push(no_imports.call_bar(accessor).boxed());
128                 futures.push(no_imports.foo().call_foo(accessor).boxed());
129                 assert!(futures.try_next().await?.is_some());
130                 assert!(futures.try_next().await?.is_some());
131                 Ok(())
132             })
133             .await?
134     }
135 }
136 
137 mod one_import {
138     use super::*;
139     use wasmtime::component::HasSelf;
140 
141     wasmtime::component::bindgen!({
142         inline: "
143             package foo:foo;
144 
145             world one-import {
146                 import foo: interface {
147                     foo: func();
148                 }
149 
150                 export bar: func();
151             }
152         ",
153     });
154 
155     #[test]
run() -> Result<()>156     fn run() -> Result<()> {
157         let engine = engine();
158 
159         let component = Component::new(
160             &engine,
161             r#"
162                 (component
163                     (import "foo" (instance $i
164                         (export "foo" (func))
165                     ))
166                     (core module $m
167                         (import "" "" (func))
168                         (export "" (func 0))
169                     )
170                     (core func $f (canon lower (func $i "foo")))
171                     (core instance $i (instantiate $m
172                         (with "" (instance (export "" (func $f))))
173                     ))
174 
175                     (func $f (export "bar") (canon lift (core func $i "")))
176                 )
177             "#,
178         )?;
179 
180         #[derive(Default)]
181         struct MyImports {
182             hit: bool,
183         }
184 
185         impl foo::Host for MyImports {
186             fn foo(&mut self) {
187                 self.hit = true;
188             }
189         }
190 
191         let mut linker = Linker::new(&engine);
192         foo::add_to_linker::<_, HasSelf<_>>(&mut linker, |f| f)?;
193         let mut store = Store::new(&engine, MyImports::default());
194         let one_import = OneImport::instantiate(&mut store, &component, &linker)?;
195         one_import.call_bar(&mut store)?;
196         assert!(store.data().hit);
197         Ok(())
198     }
199 }
200 
201 mod one_import_concurrent {
202     use super::*;
203     use wasmtime::component::{Accessor, HasData};
204 
205     wasmtime::component::bindgen!({
206         inline: "
207             package foo:foo;
208 
209             world no-imports {
210                 import foo: interface {
211                     foo: async func();
212                 }
213 
214                 export bar: async func();
215             }
216         "
217     });
218 
219     #[tokio::test]
run() -> Result<()>220     async fn run() -> Result<()> {
221         let mut config = Config::new();
222         config.wasm_component_model_async(true);
223         let engine = &Engine::new(&config)?;
224 
225         let component = Component::new(
226             &engine,
227             r#"
228                 (component
229                     (import "foo" (instance $foo-instance
230                         (export "foo" (func async))
231                     ))
232                     (core module $libc
233                         (memory (export "memory") 1)
234                     )
235                     (core instance $libc-instance (instantiate $libc))
236                     (core module $m
237                         (import "" "foo" (func $foo (param) (result i32)))
238                         (import "" "task.return" (func $task-return))
239                         (func (export "bar") (result i32)
240                             call $foo
241                             drop
242                             call $task-return
243                             i32.const 0
244                         )
245                         (func (export "callback") (param i32 i32 i32) (result i32) unreachable)
246                     )
247                     (core func $foo (canon lower (func $foo-instance "foo") async (memory $libc-instance "memory")))
248                     (core func $task-return (canon task.return))
249                     (core instance $i (instantiate $m
250                         (with "" (instance
251                             (export "task.return" (func $task-return))
252                             (export "foo" (func $foo))
253                         ))
254                     ))
255 
256                     (func $f (export "bar") async
257                         (canon lift (core func $i "bar") async (callback (func $i "callback")))
258                     )
259 
260                     (instance $i (export "foo" (func $f)))
261                     (export "foo" (instance $i))
262                 )
263             "#,
264         )?;
265 
266         #[derive(Default)]
267         struct MyImports {
268             hit: bool,
269         }
270 
271         impl HasData for MyImports {
272             type Data<'a> = &'a mut MyImports;
273         }
274 
275         impl foo::HostWithStore for MyImports {
276             async fn foo<T>(accessor: &Accessor<T, Self>) {
277                 accessor.with(|mut view| view.get().hit = true);
278             }
279         }
280 
281         impl foo::Host for MyImports {}
282 
283         let mut linker = Linker::new(&engine);
284         foo::add_to_linker::<_, MyImports>(&mut linker, |x| x)?;
285         let mut store = Store::new(&engine, MyImports::default());
286         let no_imports = NoImports::instantiate_async(&mut store, &component, &linker).await?;
287         store
288             .run_concurrent(async move |accessor| no_imports.call_bar(accessor).await)
289             .await??;
290         assert!(store.data().hit);
291         Ok(())
292     }
293 }
294 
295 mod resources_at_world_level {
296     use super::*;
297     use wasmtime::component::{HasSelf, Resource};
298 
299     wasmtime::component::bindgen!({
300         inline: "
301             package foo:foo;
302 
303             world resources {
304                 resource x {
305                     constructor();
306                 }
307 
308                 export y: func(x: x);
309             }
310         ",
311     });
312 
313     #[test]
run() -> Result<()>314     fn run() -> Result<()> {
315         let engine = engine();
316 
317         let component = Component::new(
318             &engine,
319             r#"
320                 (component
321                     (import "x" (type $x (sub resource)))
322                     (import "[constructor]x" (func $ctor (result (own $x))))
323 
324                     (core func $dtor (canon resource.drop $x))
325                     (core func $ctor (canon lower (func $ctor)))
326 
327                     (core module $m
328                         (import "" "ctor" (func $ctor (result i32)))
329                         (import "" "dtor" (func $dtor (param i32)))
330 
331                         (func (export "x") (param i32)
332                             (call $dtor (local.get 0))
333                             (call $dtor (call $ctor))
334                         )
335                     )
336                     (core instance $i (instantiate $m
337                         (with "" (instance
338                             (export "ctor" (func $ctor))
339                             (export "dtor" (func $dtor))
340                         ))
341                     ))
342                     (func (export "y") (param "x" (own $x))
343                         (canon lift (core func $i "x")))
344                 )
345             "#,
346         )?;
347 
348         #[derive(Default)]
349         struct MyImports {
350             ctor_hit: bool,
351             drops: usize,
352         }
353 
354         impl HostX for MyImports {
355             fn new(&mut self) -> Resource<X> {
356                 self.ctor_hit = true;
357                 Resource::new_own(80)
358             }
359 
360             fn drop(&mut self, val: Resource<X>) -> Result<()> {
361                 match self.drops {
362                     0 => assert_eq!(val.rep(), 40),
363                     1 => assert_eq!(val.rep(), 80),
364                     _ => unreachable!(),
365                 }
366                 self.drops += 1;
367                 Ok(())
368             }
369         }
370 
371         impl ResourcesImports for MyImports {}
372 
373         let mut linker = Linker::new(&engine);
374         Resources::add_to_linker::<_, HasSelf<_>>(&mut linker, |f| f)?;
375         let mut store = Store::new(&engine, MyImports::default());
376         let one_import = Resources::instantiate(&mut store, &component, &linker)?;
377         one_import.call_y(&mut store, Resource::new_own(40))?;
378         assert!(store.data().ctor_hit);
379         assert_eq!(store.data().drops, 2);
380         Ok(())
381     }
382 }
383 
384 mod resources_at_interface_level {
385     use super::*;
386     use wasmtime::component::{HasSelf, Resource};
387 
388     wasmtime::component::bindgen!({
389         inline: "
390             package foo:foo;
391 
392             interface def {
393                 resource x {
394                     constructor();
395                 }
396             }
397 
398             interface user {
399                 use def.{x};
400 
401                 y: func(x: x);
402             }
403 
404             world resources {
405                 export user;
406             }
407         ",
408     });
409 
410     #[test]
run() -> Result<()>411     fn run() -> Result<()> {
412         let engine = engine();
413 
414         let component = Component::new(
415             &engine,
416             r#"
417                 (component
418                     (import (interface "foo:foo/def") (instance $i
419                         (export "x" (type $x (sub resource)))
420                         (export "[constructor]x" (func (result (own $x))))
421                     ))
422                     (alias export $i "x" (type $x))
423                     (core func $dtor (canon resource.drop $x))
424                     (core func $ctor (canon lower (func $i "[constructor]x")))
425 
426                     (core module $m
427                         (import "" "ctor" (func $ctor (result i32)))
428                         (import "" "dtor" (func $dtor (param i32)))
429 
430                         (func (export "x") (param i32)
431                             (call $dtor (local.get 0))
432                             (call $dtor (call $ctor))
433                         )
434                     )
435                     (core instance $i (instantiate $m
436                         (with "" (instance
437                             (export "ctor" (func $ctor))
438                             (export "dtor" (func $dtor))
439                         ))
440                     ))
441                     (func $y (param "x" (own $x))
442                         (canon lift (core func $i "x")))
443 
444                     (instance (export (interface "foo:foo/user"))
445                         (export "y" (func $y))
446                     )
447                 )
448             "#,
449         )?;
450 
451         #[derive(Default)]
452         struct MyImports {
453             ctor_hit: bool,
454             drops: usize,
455         }
456 
457         use foo::foo::def::X;
458 
459         impl foo::foo::def::HostX for MyImports {
460             fn new(&mut self) -> Resource<X> {
461                 self.ctor_hit = true;
462                 Resource::new_own(80)
463             }
464 
465             fn drop(&mut self, val: Resource<X>) -> Result<()> {
466                 match self.drops {
467                     0 => assert_eq!(val.rep(), 40),
468                     1 => assert_eq!(val.rep(), 80),
469                     _ => unreachable!(),
470                 }
471                 self.drops += 1;
472                 Ok(())
473             }
474         }
475 
476         impl foo::foo::def::Host for MyImports {}
477 
478         let mut linker = Linker::new(&engine);
479         Resources::add_to_linker::<_, HasSelf<_>>(&mut linker, |f| f)?;
480         let mut store = Store::new(&engine, MyImports::default());
481         let one_import = Resources::instantiate(&mut store, &component, &linker)?;
482         one_import
483             .foo_foo_user()
484             .call_y(&mut store, Resource::new_own(40))?;
485         assert!(store.data().ctor_hit);
486         assert_eq!(store.data().drops, 2);
487         Ok(())
488     }
489 }
490 
491 mod async_config {
492     use super::*;
493 
494     wasmtime::component::bindgen!({
495         inline: "
496             package foo:foo;
497 
498             world t1 {
499                 import foo: interface {
500                     foo: func();
501                 }
502                 import x: func();
503                 import y: func();
504                 export z: func();
505             }
506         ",
507         imports: { default: async },
508         exports: { default: async },
509     });
510 
511     #[expect(dead_code, reason = "just here for bindings")]
512     struct T;
513 
514     impl T1Imports for T {
x(&mut self)515         async fn x(&mut self) {}
516 
y(&mut self)517         async fn y(&mut self) {}
518     }
519 
_test_t1(t1: &T1, store: &mut Store<()>)520     async fn _test_t1(t1: &T1, store: &mut Store<()>) {
521         let _ = t1.call_z(&mut *store).await;
522     }
523 
524     wasmtime::component::bindgen!({
525         inline: "
526             package foo:foo;
527 
528             world t2 {
529                 import x: func();
530                 import y: func();
531                 export z: func();
532             }
533         ",
534         imports: {
535             "x": tracing,
536             default: async,
537         },
538         exports: { default: async },
539     });
540 
541     impl T2Imports for T {
x(&mut self)542         fn x(&mut self) {}
543 
y(&mut self)544         async fn y(&mut self) {}
545     }
546 
_test_t2(t2: &T2, store: &mut Store<()>)547     async fn _test_t2(t2: &T2, store: &mut Store<()>) {
548         let _ = t2.call_z(&mut *store).await;
549     }
550 
551     wasmtime::component::bindgen!({
552         inline: "
553             package foo:foo;
554 
555             world t3 {
556                 import x: func();
557                 import y: func();
558                 export z: func();
559             }
560         ",
561         imports: { "x": async },
562         exports: { default: async },
563     });
564 
565     impl T3Imports for T {
x(&mut self)566         async fn x(&mut self) {}
567 
y(&mut self)568         fn y(&mut self) {}
569     }
570 
_test_t3(t3: &T3, store: &mut Store<()>)571     async fn _test_t3(t3: &T3, store: &mut Store<()>) {
572         let _ = t3.call_z(&mut *store).await;
573     }
574 }
575 
576 mod exported_resources {
577     use super::*;
578     use std::mem;
579     use wasmtime::component::{HasSelf, Resource};
580 
581     wasmtime::component::bindgen!({
582         inline: "
583             package foo:foo;
584 
585             interface a {
586                 resource x {
587                     constructor();
588                 }
589             }
590 
591             world resources {
592                 export b: interface {
593                     use a.{x as y};
594 
595                     resource x {
596                         constructor(y: y);
597                         foo: func() -> u32;
598                     }
599                 }
600 
601                 resource x;
602 
603                 export f: func(x1: x, x2: x) -> x;
604             }
605         ",
606     });
607 
608     #[derive(Default)]
609     struct MyImports {
610         hostcalls: Vec<Hostcall>,
611         next_a_x: u32,
612     }
613 
614     #[derive(PartialEq, Debug)]
615     enum Hostcall {
616         DropRootX(u32),
617         DropAX(u32),
618         NewA,
619     }
620 
621     use foo::foo::a;
622 
623     impl ResourcesImports for MyImports {}
624 
625     impl HostX for MyImports {
drop(&mut self, val: Resource<X>) -> Result<()>626         fn drop(&mut self, val: Resource<X>) -> Result<()> {
627             self.hostcalls.push(Hostcall::DropRootX(val.rep()));
628             Ok(())
629         }
630     }
631 
632     impl a::HostX for MyImports {
new(&mut self) -> Resource<a::X>633         fn new(&mut self) -> Resource<a::X> {
634             let rep = self.next_a_x;
635             self.next_a_x += 1;
636             self.hostcalls.push(Hostcall::NewA);
637             Resource::new_own(rep)
638         }
639 
drop(&mut self, val: Resource<a::X>) -> Result<()>640         fn drop(&mut self, val: Resource<a::X>) -> Result<()> {
641             self.hostcalls.push(Hostcall::DropAX(val.rep()));
642             Ok(())
643         }
644     }
645 
646     impl foo::foo::a::Host for MyImports {}
647 
648     #[test]
run() -> Result<()>649     fn run() -> Result<()> {
650         let engine = engine();
651 
652         let component = Component::new(
653             &engine,
654             r#"
655 (component
656   ;; setup the `foo:foo/a` import
657   (import (interface "foo:foo/a") (instance $a
658     (export "x" (type $x (sub resource)))
659     (export "[constructor]x" (func (result (own $x))))
660   ))
661   (alias export $a "x" (type $a-x))
662   (core func $a-x-drop (canon resource.drop $a-x))
663   (core func $a-x-ctor (canon lower (func $a "[constructor]x")))
664 
665   ;; setup the root import of the `x` resource
666   (import "x" (type $x (sub resource)))
667   (core func $root-x-dtor (canon resource.drop $x))
668 
669   ;; setup and declare the `x` resource for the `b` export.
670   (core module $indirect-dtor
671     (func (export "b-x-dtor") (param i32)
672       local.get 0
673       i32.const 0
674       call_indirect (param i32)
675     )
676     (table (export "$imports") 1 1 funcref)
677   )
678   (core instance $indirect-dtor (instantiate $indirect-dtor))
679   (type $b-x (resource (rep i32) (dtor (func $indirect-dtor "b-x-dtor"))))
680   (core func $b-x-drop (canon resource.drop $b-x))
681   (core func $b-x-rep (canon resource.rep $b-x))
682   (core func $b-x-new (canon resource.new $b-x))
683 
684   ;; main module implementation
685   (core module $main
686     (import "foo:foo/a" "[constructor]x" (func $a-x-ctor (result i32)))
687     (import "foo:foo/a" "[resource-drop]x" (func $a-x-dtor (param i32)))
688     (import "$root" "[resource-drop]x" (func $x-dtor (param i32)))
689     (import "[export]b" "[resource-drop]x" (func $b-x-dtor (param i32)))
690     (import "[export]b" "[resource-new]x" (func $b-x-new (param i32) (result i32)))
691     (import "[export]b" "[resource-rep]x" (func $b-x-rep (param i32) (result i32)))
692     (func (export "b#[constructor]x") (param i32) (result i32)
693       (call $a-x-dtor (local.get 0))
694       (call $b-x-new (call $a-x-ctor))
695     )
696     (func (export "b#[method]x.foo") (param i32) (result i32)
697       local.get 0)
698     (func (export "b#[dtor]x") (param i32)
699       (call $a-x-dtor (local.get 0))
700     )
701     (func (export "f") (param i32 i32) (result i32)
702       (call $x-dtor (local.get 0))
703       local.get 1
704     )
705   )
706   (core instance $main (instantiate $main
707     (with "foo:foo/a" (instance
708       (export "[resource-drop]x" (func $a-x-drop))
709       (export "[constructor]x" (func $a-x-ctor))
710     ))
711     (with "$root" (instance
712       (export "[resource-drop]x" (func $root-x-dtor))
713     ))
714     (with "[export]b" (instance
715       (export "[resource-drop]x" (func $b-x-drop))
716       (export "[resource-rep]x" (func $b-x-rep))
717       (export "[resource-new]x" (func $b-x-new))
718     ))
719   ))
720 
721   ;; fill in `$indirect-dtor`'s table with the actual destructor definition
722   ;; now that it's available.
723   (core module $fixup
724     (import "" "b-x-dtor" (func $b-x-dtor (param i32)))
725     (import "" "$imports" (table 1 1 funcref))
726     (elem (i32.const 0) func $b-x-dtor)
727   )
728   (core instance (instantiate $fixup
729     (with "" (instance
730       (export "$imports" (table 0 "$imports"))
731       (export "b-x-dtor" (func $main "b#[dtor]x"))
732     ))
733   ))
734 
735   ;; Create the `b` export through a subcomponent instantiation.
736   (func $b-x-ctor (param "y" (own $a-x)) (result (own $b-x))
737     (canon lift (core func $main "b#[constructor]x")))
738   (func $b-x-foo (param "self" (borrow $b-x)) (result u32)
739     (canon lift (core func $main "b#[method]x.foo")))
740   (component $b
741     (import "a-x" (type $y (sub resource)))
742     (import "b-x" (type $x' (sub resource)))
743     (import "ctor" (func $ctor (param "y" (own $y)) (result (own $x'))))
744     (import "foo" (func $foo (param "self" (borrow $x')) (result u32)))
745     (export $x "x" (type $x'))
746     (export "[constructor]x"
747       (func $ctor)
748       (func (param "y" (own $y)) (result (own $x))))
749     (export "[method]x.foo"
750       (func $foo)
751       (func (param "self" (borrow $x)) (result u32)))
752   )
753   (instance (export "b") (instantiate $b
754     (with "ctor" (func $b-x-ctor))
755     (with "foo" (func $b-x-foo))
756     (with "a-x" (type 0 "x"))
757     (with "b-x" (type $b-x))
758   ))
759 
760   ;; Create the `f` export which is a bare function
761   (func (export "f") (param "x1" (own $x)) (param "x2" (own $x)) (result (own $x))
762     (canon lift (core func $main "f")))
763 )
764             "#,
765         )?;
766 
767         let mut linker = Linker::new(&engine);
768         Resources::add_to_linker::<_, HasSelf<_>>(&mut linker, |f| f)?;
769         let mut store = Store::new(&engine, MyImports::default());
770         let i = Resources::instantiate(&mut store, &component, &linker)?;
771 
772         // call the root export `f` twice
773         let ret = i.call_f(&mut store, Resource::new_own(1), Resource::new_own(2))?;
774         assert_eq!(ret.rep(), 2);
775         assert_eq!(
776             mem::take(&mut store.data_mut().hostcalls),
777             [Hostcall::DropRootX(1)]
778         );
779         let ret = i.call_f(&mut store, Resource::new_own(3), Resource::new_own(4))?;
780         assert_eq!(ret.rep(), 4);
781         assert_eq!(
782             mem::take(&mut store.data_mut().hostcalls),
783             [Hostcall::DropRootX(3)]
784         );
785 
786         // interact with the `b` export
787         let b = i.b();
788         let b_x = b.x().call_constructor(&mut store, Resource::new_own(5))?;
789         assert_eq!(
790             mem::take(&mut store.data_mut().hostcalls),
791             [Hostcall::DropAX(5), Hostcall::NewA]
792         );
793         b.x().call_foo(&mut store, b_x)?;
794         assert_eq!(mem::take(&mut store.data_mut().hostcalls), []);
795         b_x.resource_drop(&mut store)?;
796         assert_eq!(
797             mem::take(&mut store.data_mut().hostcalls),
798             [Hostcall::DropAX(0)],
799         );
800         Ok(())
801     }
802 }
803 
804 mod unstable_import {
805     use super::*;
806     use wasmtime::component::HasSelf;
807 
808     wasmtime::component::bindgen!({
809         inline: "
810             package foo:foo;
811 
812             @unstable(feature = experimental-interface)
813             interface my-interface {
814                 @unstable(feature = experimental-function)
815                 my-function: func();
816             }
817 
818             world my-world {
819                 @unstable(feature = experimental-import)
820                 import my-interface;
821 
822                 export bar: func();
823             }
824         ",
825     });
826 
827     #[test]
run() -> Result<()>828     fn run() -> Result<()> {
829         // In the example above, all features are required for `my-function` to be imported:
830         assert_success(
831             LinkOptions::default()
832                 .experimental_interface(true)
833                 .experimental_import(true)
834                 .experimental_function(true),
835         );
836 
837         // And every other incomplete combination should fail:
838         assert_failure(&LinkOptions::default());
839         assert_failure(LinkOptions::default().experimental_function(true));
840         assert_failure(LinkOptions::default().experimental_interface(true));
841         assert_failure(
842             LinkOptions::default()
843                 .experimental_interface(true)
844                 .experimental_function(true),
845         );
846         assert_failure(
847             LinkOptions::default()
848                 .experimental_interface(true)
849                 .experimental_import(true),
850         );
851         assert_failure(LinkOptions::default().experimental_import(true));
852         assert_failure(
853             LinkOptions::default()
854                 .experimental_import(true)
855                 .experimental_function(true),
856         );
857 
858         Ok(())
859     }
860 
assert_success(link_options: &LinkOptions)861     fn assert_success(link_options: &LinkOptions) {
862         run_with_options(link_options).unwrap();
863     }
assert_failure(link_options: &LinkOptions)864     fn assert_failure(link_options: &LinkOptions) {
865         let err = run_with_options(link_options).unwrap_err().to_string();
866         assert_eq!(
867             err,
868             "component imports instance `foo:foo/my-interface`, but a matching implementation was not found in the linker"
869         );
870     }
871 
run_with_options(link_options: &LinkOptions) -> Result<()>872     fn run_with_options(link_options: &LinkOptions) -> Result<()> {
873         let engine = engine();
874 
875         let component = Component::new(
876             &engine,
877             r#"
878                 (component
879                     (import "foo:foo/my-interface" (instance $i
880                         (export "my-function" (func))
881                     ))
882                     (core module $m
883                         (import "" "" (func))
884                         (export "" (func 0))
885                     )
886                     (core func $f (canon lower (func $i "my-function")))
887                     (core instance $r (instantiate $m
888                         (with "" (instance (export "" (func $f))))
889                     ))
890 
891                     (func $f (export "bar") (canon lift (core func $r "")))
892                 )
893             "#,
894         )?;
895 
896         #[derive(Default)]
897         struct MyHost;
898 
899         impl foo::foo::my_interface::Host for MyHost {
900             fn my_function(&mut self) {}
901         }
902 
903         let mut linker = Linker::new(&engine);
904         MyWorld::add_to_linker::<_, HasSelf<_>>(&mut linker, link_options, |h| h)?;
905         let mut store = Store::new(&engine, MyHost::default());
906         let one_import = MyWorld::instantiate(&mut store, &component, &linker)?;
907         one_import.call_bar(&mut store)?;
908         Ok(())
909     }
910 }
911 
912 mod anyhow_errors {
913     use super::*;
914     use crate::ErrorExt;
915     use wasmtime::component::HasSelf;
916     use wasmtime::error::Context as _;
917 
918     wasmtime::component::bindgen!({
919         anyhow: true,
920         imports: { default: trappable },
921         inline: "
922             package foo:foo;
923 
924             interface my-interface {
925                 ok: func() -> u32;
926                 trap: func() -> u32;
927             }
928 
929             world my-world {
930                 import my-interface;
931                 export ok: func() -> u32;
932                 export trap: func() -> u32;
933             }
934         ",
935     });
936 
937     #[test]
run() -> Result<()>938     fn run() -> Result<()> {
939         let engine = engine();
940 
941         let component = Component::new(
942             &engine,
943             r#"
944                 (component
945                     (import "foo:foo/my-interface" (instance $i
946                         (export "ok" (func (result u32)))
947                         (export "trap" (func (result u32)))
948                     ))
949 
950                     (core module $m
951                         (import "" "ok" (func (result i32)))
952                         (import "" "trap" (func (result i32)))
953                         (export "ok" (func 0))
954                         (export "trap" (func 1))
955                     )
956 
957                     (core func $ok (canon lower (func $i "ok")))
958                     (core func $trap (canon lower (func $i "trap")))
959 
960                     (core instance $r (instantiate $m
961                         (with "" (instance (export "ok" (func $ok))
962                                            (export "trap" (func $trap))))
963                     ))
964 
965                     (func (export "ok") (result u32) (canon lift (core func $r "ok")))
966                     (func (export "trap") (result u32) (canon lift (core func $r "trap")))
967                 )
968             "#,
969         )?;
970 
971         #[derive(Default)]
972         struct MyHost;
973 
974         impl foo::foo::my_interface::Host for MyHost {
975             // NB: these must return an `anyhow::Result` since we `bindgen!`ed
976             // with `anyhow: true`.
977             fn ok(&mut self) -> anyhow_for_testing::Result<u32> {
978                 Ok(42)
979             }
980             fn trap(&mut self) -> anyhow_for_testing::Result<u32> {
981                 anyhow_for_testing::bail!("anyhow error")
982             }
983         }
984 
985         let mut linker = Linker::new(&engine);
986         MyWorld::add_to_linker::<_, HasSelf<_>>(&mut linker, |h| h)
987             .context("failed to add to linker")?;
988         let mut store = Store::new(&engine, MyHost::default());
989         let instance = MyWorld::instantiate(&mut store, &component, &linker)
990             .context("failed to instantiate")?;
991 
992         let x = instance
993             .call_ok(&mut store)
994             .context("failed to call `ok` function")?;
995         assert_eq!(x, 42);
996 
997         let result = instance.call_trap(&mut store);
998         let error = result.unwrap_err();
999         error.assert_contains("anyhow error");
1000 
1001         Ok(())
1002     }
1003 }
1004