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