Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bytecodealliance
GitHub Repository: bytecodealliance/wasmtime
Path: blob/main/tests/all/funcref.rs
1692 views
1
use super::ref_types_module;
2
use std::sync::Arc;
3
use std::sync::atomic::{AtomicBool, Ordering::SeqCst};
4
use wasmtime::*;
5
6
#[test]
7
#[cfg_attr(miri, ignore)]
8
fn pass_funcref_in_and_out_of_wasm() -> anyhow::Result<()> {
9
let (mut store, module) = ref_types_module(
10
false,
11
r#"
12
(module
13
(func (export "func") (param funcref) (result funcref)
14
local.get 0
15
)
16
)
17
"#,
18
)?;
19
20
let instance = Instance::new(&mut store, &module, &[])?;
21
let func = instance.get_func(&mut store, "func").unwrap();
22
23
// Pass in a non-null funcref.
24
{
25
let mut results = [Val::I32(0)];
26
func.call(&mut store, &[Val::FuncRef(Some(func))], &mut results)?;
27
28
// Can't compare `Func` for equality, so this is the best we can do here.
29
let result_func = results[0].unwrap_funcref().unwrap();
30
assert!(FuncType::eq(&func.ty(&store), &result_func.ty(&store)));
31
}
32
33
// Pass in a null funcref.
34
{
35
let mut results = [Val::I32(0)];
36
func.call(&mut store, &[Val::FuncRef(None)], &mut results)?;
37
let result_func = results[0].unwrap_funcref();
38
assert!(result_func.is_none());
39
}
40
41
// Pass in a `funcref` from another instance.
42
{
43
let other_instance = Instance::new(&mut store, &module, &[])?;
44
let other_instance_func = other_instance.get_func(&mut store, "func").unwrap();
45
46
let mut results = [Val::I32(0)];
47
func.call(
48
&mut store,
49
&[Val::FuncRef(Some(other_instance_func))],
50
&mut results,
51
)?;
52
assert_eq!(results.len(), 1);
53
54
// Can't compare `Func` for equality, so this is the best we can do here.
55
let result_func = results[0].unwrap_funcref().unwrap();
56
assert!(FuncType::eq(
57
&other_instance_func.ty(&store),
58
&result_func.ty(&store),
59
));
60
}
61
62
// Passing in a `funcref` from another store fails.
63
{
64
let (mut other_store, other_module) =
65
ref_types_module(false, r#"(module (func (export "f")))"#)?;
66
let other_store_instance = Instance::new(&mut other_store, &other_module, &[])?;
67
let f = other_store_instance
68
.get_func(&mut other_store, "f")
69
.unwrap();
70
71
assert!(
72
func.call(&mut store, &[Val::FuncRef(Some(f))], &mut [Val::I32(0)])
73
.is_err()
74
);
75
}
76
77
Ok(())
78
}
79
80
#[test]
81
#[cfg_attr(miri, ignore)]
82
fn receive_null_funcref_from_wasm() -> anyhow::Result<()> {
83
let (mut store, module) = ref_types_module(
84
false,
85
r#"
86
(module
87
(func (export "get-null") (result funcref)
88
ref.null func
89
)
90
)
91
"#,
92
)?;
93
94
let instance = Instance::new(&mut store, &module, &[])?;
95
let get_null = instance.get_func(&mut store, "get-null").unwrap();
96
97
let mut results = [Val::I32(0)];
98
get_null.call(&mut store, &[], &mut results)?;
99
let result_func = results[0].unwrap_funcref();
100
assert!(result_func.is_none());
101
102
Ok(())
103
}
104
105
#[test]
106
fn wrong_store() -> anyhow::Result<()> {
107
let dropped = Arc::new(AtomicBool::new(false));
108
{
109
let mut store1 = Store::<()>::default();
110
let mut store2 = Store::<()>::default();
111
112
let set = SetOnDrop(dropped.clone());
113
let f1 = Func::wrap(&mut store1, move || {
114
let _ = &set;
115
});
116
let f2 = Func::wrap(&mut store2, move || Some(f1));
117
assert!(f2.call(&mut store2, &[], &mut []).is_err());
118
}
119
assert!(dropped.load(SeqCst));
120
121
return Ok(());
122
123
struct SetOnDrop(Arc<AtomicBool>);
124
125
impl Drop for SetOnDrop {
126
fn drop(&mut self) {
127
self.0.store(true, SeqCst);
128
}
129
}
130
}
131
132
#[test]
133
#[cfg_attr(miri, ignore)]
134
fn func_new_returns_wrong_store() -> anyhow::Result<()> {
135
let dropped = Arc::new(AtomicBool::new(false));
136
{
137
let mut store1 = Store::<()>::default();
138
let mut store2 = Store::<()>::default();
139
140
let set = SetOnDrop(dropped.clone());
141
let f1 = Func::wrap(&mut store1, move || {
142
let _ = &set;
143
});
144
let func_ty = FuncType::new(store2.engine(), None, Some(ValType::FUNCREF));
145
let f2 = Func::new(&mut store2, func_ty, move |_, _, results| {
146
results[0] = f1.into();
147
Ok(())
148
});
149
assert!(f2.call(&mut store2, &[], &mut [Val::I32(0)]).is_err());
150
}
151
assert!(dropped.load(SeqCst));
152
153
return Ok(());
154
155
struct SetOnDrop(Arc<AtomicBool>);
156
157
impl Drop for SetOnDrop {
158
fn drop(&mut self) {
159
self.0.store(true, SeqCst);
160
}
161
}
162
}
163
164