Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bytecodealliance
GitHub Repository: bytecodealliance/wasmtime
Path: blob/main/tests/all/component_model/bindgen.rs
3067 views
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]
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]
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]
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]
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]
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]
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 {
515
async fn x(&mut self) {}
516
517
async fn y(&mut self) {}
518
}
519
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 {
542
fn x(&mut self) {}
543
544
async fn y(&mut self) {}
545
}
546
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 {
566
async fn x(&mut self) {}
567
568
fn y(&mut self) {}
569
}
570
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 {
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 {
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
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]
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]
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
861
fn assert_success(link_options: &LinkOptions) {
862
run_with_options(link_options).unwrap();
863
}
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
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]
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
1005