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