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