1 #![allow(dead_code)]
2 #![expect(clippy::allow_attributes_without_reason, reason = "crate not migrated")]
3 
4 macro_rules! gentest {
5     ($id:ident $name:tt $path:tt) => {
6         mod $id {
7             mod sugar {
8                 wasmtime::component::bindgen!(in $path);
9             }
10             mod async_ {
11                 wasmtime::component::bindgen!({
12                     path: $path,
13                     async: true,
14                 });
15             }
16             mod tracing {
17                 wasmtime::component::bindgen!({
18                     path: $path,
19                     tracing: true,
20                     verbose_tracing: true,
21                     ownership: Borrowing {
22                         duplicate_if_necessary: true
23                     }
24                 });
25             }
26         }
27     };
28 }
29 
30 component_macro_test_helpers::foreach!(gentest);
31 
32 mod with_key_and_resources {
33     use anyhow::Result;
34     use wasmtime::component::Resource;
35 
36     wasmtime::component::bindgen!({
37         inline: "
38             package demo:pkg;
39 
40             interface bar {
41                 resource a;
42                 resource b;
43             }
44 
45             world foo {
46                 resource a;
47                 resource b;
48 
49                 import foo: interface {
50                     resource a;
51                     resource b;
52                 }
53 
54                 import bar;
55             }
56         ",
57         with: {
58             "a": MyA,
59             "b": MyA,
60             "foo/a": MyA,
61             "foo/b": MyA,
62             "demo:pkg/bar/a": MyA,
63             "demo:pkg/bar/b": MyA,
64         },
65     });
66 
67     pub struct MyA;
68 
69     struct MyComponent;
70 
71     impl FooImports for MyComponent {}
72 
73     impl HostA for MyComponent {
74         fn drop(&mut self, _: Resource<MyA>) -> Result<()> {
75             loop {}
76         }
77     }
78 
79     impl HostB for MyComponent {
80         fn drop(&mut self, _: Resource<MyA>) -> Result<()> {
81             loop {}
82         }
83     }
84 
85     impl foo::Host for MyComponent {}
86 
87     impl foo::HostA for MyComponent {
88         fn drop(&mut self, _: Resource<MyA>) -> Result<()> {
89             loop {}
90         }
91     }
92 
93     impl foo::HostB for MyComponent {
94         fn drop(&mut self, _: Resource<MyA>) -> Result<()> {
95             loop {}
96         }
97     }
98 
99     impl demo::pkg::bar::Host for MyComponent {}
100 
101     impl demo::pkg::bar::HostA for MyComponent {
102         fn drop(&mut self, _: Resource<MyA>) -> Result<()> {
103             loop {}
104         }
105     }
106 
107     impl demo::pkg::bar::HostB for MyComponent {
108         fn drop(&mut self, _: Resource<MyA>) -> Result<()> {
109             loop {}
110         }
111     }
112 }
113 
114 mod trappable_errors_with_versioned_and_unversioned_packages {
115     wasmtime::component::bindgen!({
116         world: "foo:foo/nope",
117         inline: "
118             package foo:[email protected];
119 
120             interface a {
121                 variant error {
122                     other(string),
123                 }
124 
125                 f: func() -> result<_, error>;
126             }
127 
128             world foo {
129                 import a;
130             }
131         ",
132         path: "tests/codegen/unversioned-foo.wit",
133         trappable_error_type: {
134             "foo:foo/[email protected]/error" => MyX,
135         },
136     });
137 
138     #[allow(dead_code)]
139     type MyX = u64;
140 }
141 
142 mod trappable_errors {
143     wasmtime::component::bindgen!({
144         inline: "
145             package demo:pkg;
146 
147             interface a {
148                 type b = u64;
149 
150                 z1: func() -> result<_, b>;
151                 z2: func() -> result<_, b>;
152             }
153 
154             interface b {
155                 use a.{b};
156                 z: func() -> result<_, b>;
157             }
158 
159             interface c {
160                 type b = u64;
161             }
162 
163             interface d {
164                 use c.{b};
165                 z: func() -> result<_, b>;
166             }
167 
168             world foo {
169                 import a;
170                 import b;
171                 import d;
172             }
173         ",
174         trappable_error_type: {
175             "demo:pkg/a/b" => MyX,
176             "demo:pkg/c/b" => MyX,
177         },
178     });
179 
180     #[allow(dead_code)]
181     type MyX = u32;
182 }
183 
184 mod interface_name_with_rust_keyword {
185     wasmtime::component::bindgen!({
186         inline: "
187             package foo:foo;
188 
189             interface crate { }
190 
191             world foo {
192                 export crate;
193             }
194         "
195     });
196 }
197 
198 mod with_works_with_hierarchy {
199     mod bindings {
200         wasmtime::component::bindgen!({
201             inline: "
202                 package foo:foo;
203 
204                 interface a {
205                     record t {
206                         x: u32,
207                     }
208                     x: func() -> t;
209                 }
210 
211                 interface b {
212                     use a.{t};
213                     x: func() -> t;
214                 }
215 
216                 interface c {
217                     use b.{t};
218                     x: func() -> t;
219                 }
220 
221                 world foo {
222                     import c;
223                 }
224             "
225         });
226     }
227 
228     mod with_just_one_interface {
229         wasmtime::component::bindgen!({
230             inline: "
231                 package foo:foo;
232 
233                 interface a {
234                     record t {
235                         x: u32,
236                     }
237                     x: func() -> t;
238                 }
239 
240                 interface b {
241                     use a.{t};
242                     x: func() -> t;
243                 }
244 
245                 interface c {
246                     use b.{t};
247                     x: func() -> t;
248                 }
249 
250                 world foo {
251                     use c.{t};
252 
253                     import x: func() -> t;
254                 }
255             ",
256             with: { "foo:foo/a": super::bindings::foo::foo::a }
257         });
258 
259         struct X;
260 
261         impl FooImports for X {
262             fn x(&mut self) -> super::bindings::foo::foo::a::T {
263                 loop {}
264             }
265         }
266     }
267 
268     mod with_whole_package {
269         wasmtime::component::bindgen!({
270             inline: "
271                 package foo:foo;
272 
273                 interface a {
274                     record t {
275                         x: u32,
276                     }
277                     x: func() -> t;
278                 }
279 
280                 interface b {
281                     use a.{t};
282                     x: func() -> t;
283                 }
284 
285                 interface c {
286                     use b.{t};
287                     x: func() -> t;
288                 }
289 
290                 world foo {
291                     use c.{t};
292 
293                     import x: func() -> t;
294                 }
295             ",
296             with: { "foo:foo": super::bindings::foo::foo }
297         });
298 
299         struct X;
300 
301         impl FooImports for X {
302             fn x(&mut self) -> super::bindings::foo::foo::a::T {
303                 loop {}
304             }
305         }
306     }
307 
308     mod with_whole_namespace {
309         wasmtime::component::bindgen!({
310             inline: "
311                 package foo:foo;
312 
313                 interface a {
314                     record t {
315                         x: u32,
316                     }
317                     x: func() -> t;
318                 }
319 
320                 interface b {
321                     use a.{t};
322                     x: func() -> t;
323                 }
324 
325                 interface c {
326                     use b.{t};
327                     x: func() -> t;
328                 }
329 
330                 world foo {
331                     use c.{t};
332 
333                     import x: func() -> t;
334                 }
335             ",
336             with: { "foo": super::bindings::foo }
337         });
338 
339         struct X;
340 
341         impl FooImports for X {
342             fn x(&mut self) -> super::bindings::foo::foo::a::T {
343                 loop {}
344             }
345         }
346     }
347 }
348 
349 mod trappable_imports {
350     mod none {
351         wasmtime::component::bindgen!({
352             inline: "
353                 package foo:foo;
354 
355                 world foo {
356                     import foo: func();
357                 }
358             ",
359             trappable_imports: false,
360         });
361         struct X;
362 
363         impl FooImports for X {
364             fn foo(&mut self) {}
365         }
366     }
367 
368     mod all {
369         wasmtime::component::bindgen!({
370             inline: "
371                 package foo:foo;
372 
373                 world foo {
374                     import foo: func();
375                 }
376             ",
377             trappable_imports: true,
378         });
379         struct X;
380 
381         impl FooImports for X {
382             fn foo(&mut self) -> wasmtime::Result<()> {
383                 Ok(())
384             }
385         }
386     }
387 
388     mod some {
389         wasmtime::component::bindgen!({
390             inline: "
391                 package foo:foo;
392 
393                 world foo {
394                     import foo: func();
395                     import bar: func();
396                 }
397             ",
398             trappable_imports: ["foo"],
399         });
400         struct X;
401 
402         impl FooImports for X {
403             fn foo(&mut self) -> wasmtime::Result<()> {
404                 Ok(())
405             }
406             fn bar(&mut self) {}
407         }
408     }
409 
410     mod across_interfaces {
411         use wasmtime::component::Resource;
412 
413         wasmtime::component::bindgen!({
414             inline: "
415                 package foo:foo;
416 
417                 interface a {
418                     foo: func();
419                     bar: func();
420 
421                     resource r {
422                         constructor();
423                         foo: func();
424                         bar: static func();
425                     }
426                 }
427 
428                 world foo {
429                     import a;
430                     import foo: func();
431                     import bar: func();
432                     import i: interface {
433                         foo: func();
434                         bar: func();
435                     }
436 
437                 }
438             ",
439             trappable_imports: ["foo"],
440             with: { "foo:foo/a/r": R },
441         });
442 
443         struct X;
444         pub struct R;
445 
446         impl FooImports for X {
447             fn foo(&mut self) -> wasmtime::Result<()> {
448                 Ok(())
449             }
450             fn bar(&mut self) {}
451         }
452 
453         impl i::Host for X {
454             fn foo(&mut self) -> wasmtime::Result<()> {
455                 Ok(())
456             }
457             fn bar(&mut self) {}
458         }
459 
460         impl foo::foo::a::Host for X {
461             fn foo(&mut self) -> wasmtime::Result<()> {
462                 Ok(())
463             }
464             fn bar(&mut self) {}
465         }
466 
467         impl foo::foo::a::HostR for X {
468             fn new(&mut self) -> Resource<R> {
469                 loop {}
470             }
471             fn foo(&mut self, _: Resource<R>) {}
472             fn bar(&mut self) {}
473             fn drop(&mut self, _: Resource<R>) -> wasmtime::Result<()> {
474                 Ok(())
475             }
476         }
477     }
478 
479     mod resources {
480         use wasmtime::component::Resource;
481 
482         wasmtime::component::bindgen!({
483             inline: "
484                 package foo:foo;
485 
486                 interface a {
487                     resource r {
488                         constructor();
489                         foo: func();
490                         bar: static func();
491                     }
492                 }
493 
494                 world foo {
495                     import a;
496 
497                 }
498             ",
499             trappable_imports: [
500                 "[constructor]r",
501                 "[method]r.foo",
502                 "[static]r.bar",
503             ],
504             with: { "foo:foo/a/r": R },
505         });
506 
507         struct X;
508         pub struct R;
509 
510         impl foo::foo::a::Host for X {}
511 
512         impl foo::foo::a::HostR for X {
513             fn new(&mut self) -> wasmtime::Result<Resource<R>> {
514                 loop {}
515             }
516             fn foo(&mut self, _: Resource<R>) -> wasmtime::Result<()> {
517                 Ok(())
518             }
519             fn bar(&mut self) -> wasmtime::Result<()> {
520                 Ok(())
521             }
522             fn drop(&mut self, _: Resource<R>) -> wasmtime::Result<()> {
523                 Ok(())
524             }
525         }
526     }
527 }
528 
529 mod custom_derives {
530     use std::collections::{hash_map::RandomState, HashSet};
531 
532     wasmtime::component::bindgen!({
533         inline: "
534             package my:inline;
535 
536             interface blah {
537                 variant abc {
538                     a,
539                     b,
540                     c
541                 }
542 
543                 record foo {
544                     field1: string,
545                     field2: list<u32>,
546                     field3: abc
547                 }
548 
549                 bar: func(cool: foo);
550             }
551 
552             world baz {
553                 import blah;
554             }
555         ",
556         // Clone is included by default almost everywhere, so include it here to make sure it
557         // doesn't conflict
558         additional_derives: [serde::Serialize, serde::Deserialize, Hash, Clone, PartialEq, Eq],
559     });
560 
561     use my::inline::blah::{Abc, Foo, Host};
562 
563     struct X;
564 
565     impl Host for X {
566         fn bar(&mut self, cool: Foo) {
567             // Check that built in derives that I've added actually work by seeing that this hashes
568             let _blah: HashSet<Foo, RandomState> = HashSet::from_iter([Foo {
569                 field1: "hello".to_string(),
570                 field2: vec![1, 2, 3],
571                 field3: Abc::B,
572             }]);
573 
574             // Check that the attributes from an external crate actually work. If they don't work,
575             // compilation will fail here
576             let _ = serde_json::to_string(&cool);
577         }
578     }
579 }
580 
581 mod with_and_mixing_async {
582     mod with_async {
583         wasmtime::component::bindgen!({
584             inline: "
585                 package my:inline;
586                 interface foo {
587                     type t = u32;
588                     foo: func() -> t;
589                 }
590                 interface bar {
591                     use foo.{t};
592                     bar: func() -> t;
593                 }
594                 world x {
595                     import bar;
596                 }
597             ",
598             async: {
599                 only_imports: ["bar"],
600             },
601         });
602     }
603 
604     mod without_async {
605         wasmtime::component::bindgen!({
606             inline: "
607                 package my:inline;
608                 interface foo {
609                     type t = u32;
610                     foo: func() -> t;
611                 }
612                 interface bar {
613                     use foo.{t};
614                     bar: func() -> t;
615                 }
616                 world x {
617                     import bar;
618                 }
619             ",
620             with: {
621                 "my:inline/foo": super::with_async::my::inline::foo,
622             },
623             require_store_data_send: true,
624         });
625     }
626 
627     mod third {
628         wasmtime::component::bindgen!({
629             inline: "
630                 package my:inline;
631                 interface foo {
632                     type t = u32;
633                     foo: func() -> t;
634                 }
635                 interface bar {
636                     use foo.{t};
637                     bar: func() -> t;
638                 }
639                 interface baz {
640                     use bar.{t};
641                     baz: func() -> t;
642                 }
643                 world x {
644                     import baz;
645                 }
646             ",
647             with: {
648                 "my:inline/foo": super::with_async::my::inline::foo,
649                 "my:inline/bar": super::without_async::my::inline::bar,
650             },
651             require_store_data_send: true,
652         });
653     }
654 }
655 
656 mod trappable_error_type_and_versions {
657     struct MyError;
658 
659     mod package_no_version_path_no_version {
660         wasmtime::component::bindgen!({
661             inline: "
662                 package my:inline;
663                 interface i {
664                     enum e { a, b, c }
665                 }
666                 world foo {}
667             ",
668             trappable_error_type: {
669                 "my:inline/i/e" => super::MyError,
670             },
671         });
672     }
673     mod package_version_path_no_version {
674         wasmtime::component::bindgen!({
675             inline: "
676                 package my:[email protected];
677                 interface i {
678                     enum e { a, b, c }
679                 }
680                 world foo {}
681             ",
682             trappable_error_type: {
683                 "my:inline/i/e" => super::MyError,
684             },
685         });
686     }
687     mod package_version_path_version {
688         wasmtime::component::bindgen!({
689             inline: "
690                 package my:[email protected];
691                 interface i {
692                     enum e { a, b, c }
693                 }
694                 world foo {}
695             ",
696             trappable_error_type: {
697                 "my:inline/[email protected]/e" => super::MyError,
698             },
699         });
700     }
701 }
702 
703 mod paths {
704     mod multiple_paths {
705         wasmtime::component::bindgen!({
706             world: "test:paths/test",
707             inline: r#"
708             package test:paths;
709             world test {
710                 import paths:path1/test;
711                 export paths:path2/test;
712             }
713             "#,
714             path: ["tests/codegen/path1", "tests/codegen/path2"],
715         });
716     }
717 }
718