1 use wasmtime::*;
2
3 #[test]
smoke() -> wasmtime::Result<()>4 fn smoke() -> wasmtime::Result<()> {
5 let mut store = Store::<()>::default();
6 let g = Global::new(
7 &mut store,
8 GlobalType::new(ValType::I32, Mutability::Const),
9 0.into(),
10 )?;
11 assert_eq!(g.get(&mut store).i32(), Some(0));
12 assert!(g.set(&mut store, 0.into()).is_err());
13
14 let g = Global::new(
15 &mut store,
16 GlobalType::new(ValType::I32, Mutability::Const),
17 1i32.into(),
18 )?;
19 assert_eq!(g.get(&mut store).i32(), Some(1));
20
21 let g = Global::new(
22 &mut store,
23 GlobalType::new(ValType::I64, Mutability::Const),
24 2i64.into(),
25 )?;
26 assert_eq!(g.get(&mut store).i64(), Some(2));
27
28 let g = Global::new(
29 &mut store,
30 GlobalType::new(ValType::F32, Mutability::Const),
31 3.0f32.into(),
32 )?;
33 assert_eq!(g.get(&mut store).f32(), Some(3.0));
34
35 let g = Global::new(
36 &mut store,
37 GlobalType::new(ValType::F64, Mutability::Const),
38 4.0f64.into(),
39 )?;
40 assert_eq!(g.get(&mut store).f64(), Some(4.0));
41 Ok(())
42 }
43
44 #[test]
mutability() -> wasmtime::Result<()>45 fn mutability() -> wasmtime::Result<()> {
46 let mut store = Store::<()>::default();
47 let g = Global::new(
48 &mut store,
49 GlobalType::new(ValType::I32, Mutability::Var),
50 0.into(),
51 )?;
52 assert_eq!(g.get(&mut store).i32(), Some(0));
53 g.set(&mut store, 1.into())?;
54 assert_eq!(g.get(&mut store).i32(), Some(1));
55 Ok(())
56 }
57
58 // Make sure that a global is still usable after its original instance is
59 // dropped. This is a bit of a weird test and really only fails depending on the
60 // implementation, but for now should hopefully be resilient enough to catch at
61 // least some cases of heap corruption.
62 #[test]
use_after_drop() -> wasmtime::Result<()>63 fn use_after_drop() -> wasmtime::Result<()> {
64 let mut store = Store::<()>::default();
65 let module = Module::new(
66 store.engine(),
67 r#"
68 (module
69 (global (export "foo") (mut i32) (i32.const 100)))
70 "#,
71 )?;
72 let instance = Instance::new(&mut store, &module, &[])?;
73 let g = instance.get_global(&mut store, "foo").unwrap();
74 assert_eq!(g.get(&mut store).i32(), Some(100));
75 g.set(&mut store, 101.into())?;
76 assert_eq!(g.get(&mut store).i32(), Some(101));
77 Instance::new(&mut store, &module, &[])?;
78 assert_eq!(g.get(&mut store).i32(), Some(101));
79 drop(module);
80 assert_eq!(g.get(&mut store).i32(), Some(101));
81
82 // spray some heap values
83 let mut x = Vec::new();
84 for _ in 0..100 {
85 x.push("xy".to_string());
86 }
87 drop(x);
88 assert_eq!(g.get(&mut store).i32(), Some(101));
89 Ok(())
90 }
91
92 #[test]
v128() -> wasmtime::Result<()>93 fn v128() -> wasmtime::Result<()> {
94 let mut store = Store::<()>::default();
95 let g = Global::new(
96 &mut store,
97 GlobalType::new(ValType::V128, Mutability::Var),
98 0u128.into(),
99 )?;
100 assert_eq!(g.get(&mut store).v128(), Some(V128::from(0)));
101 g.set(&mut store, 1u128.into())?;
102 assert_eq!(g.get(&mut store).v128(), Some(V128::from(1)));
103 Ok(())
104 }
105
106 #[test]
i31ref_global_new() -> Result<()>107 fn i31ref_global_new() -> Result<()> {
108 let mut config = Config::new();
109 config.wasm_function_references(true);
110 config.wasm_gc(true);
111
112 let engine = Engine::new(&config)?;
113 let mut store = Store::new(&engine, ());
114
115 for mutability in [Mutability::Const, Mutability::Var] {
116 for val in [
117 Some(AnyRef::from_i31(&mut store, I31::new_u32(42).unwrap())),
118 None,
119 ] {
120 Global::new(
121 &mut store,
122 GlobalType::new(ValType::I31REF, mutability),
123 val.into(),
124 )?;
125 }
126 }
127 Ok(())
128 }
129
130 #[test]
i31ref_global_get() -> Result<()>131 fn i31ref_global_get() -> Result<()> {
132 let mut config = Config::new();
133 config.wasm_function_references(true);
134 config.wasm_gc(true);
135
136 let engine = Engine::new(&config)?;
137 let mut store = Store::new(&engine, ());
138
139 for mutability in [Mutability::Const, Mutability::Var] {
140 for val in [
141 Some(AnyRef::from_i31(&mut store, I31::new_u32(42).unwrap())),
142 None,
143 ] {
144 let val = Val::from(val);
145 let global = Global::new(
146 &mut store,
147 GlobalType::new(ValType::I31REF, mutability),
148 val,
149 )?;
150
151 let got = global.get(&mut store);
152
153 let val = val
154 .anyref()
155 .and_then(|a| a.and_then(|a| a.as_i31(&store).unwrap()));
156 let got = got
157 .anyref()
158 .and_then(|a| a.and_then(|a| a.as_i31(&store).unwrap()));
159
160 assert_eq!(val, got);
161 }
162 }
163 Ok(())
164 }
165
166 #[test]
i31ref_global_set() -> Result<()>167 fn i31ref_global_set() -> Result<()> {
168 let mut config = Config::new();
169 config.wasm_function_references(true);
170 config.wasm_gc(true);
171
172 let engine = Engine::new(&config)?;
173 let mut store = Store::new(&engine, ());
174
175 for init in [
176 Some(AnyRef::from_i31(&mut store, I31::new_u32(42).unwrap())),
177 None,
178 ] {
179 for new_val in [
180 Some(AnyRef::from_i31(&mut store, I31::new_u32(36).unwrap())),
181 None,
182 ] {
183 let global = Global::new(
184 &mut store,
185 GlobalType::new(ValType::I31REF, Mutability::Var),
186 init.into(),
187 )?;
188
189 let new_val = Val::from(new_val);
190 global.set(&mut store, new_val)?;
191 let got = global.get(&mut store);
192
193 let new_val = new_val
194 .anyref()
195 .and_then(|a| a.and_then(|a| a.as_i31(&store).unwrap()));
196 let got = got
197 .anyref()
198 .and_then(|a| a.and_then(|a| a.as_i31(&store).unwrap()));
199
200 assert_eq!(new_val, got);
201 }
202 }
203 Ok(())
204 }
205
206 #[test]
i31ref_global_ty() -> Result<()>207 fn i31ref_global_ty() -> Result<()> {
208 let mut config = Config::new();
209 config.wasm_function_references(true);
210 config.wasm_gc(true);
211
212 let engine = Engine::new(&config)?;
213 let mut store = Store::new(&engine, ());
214
215 for mutability in [Mutability::Const, Mutability::Var] {
216 for val in [
217 Some(AnyRef::from_i31(&mut store, I31::new_u32(42).unwrap())),
218 None,
219 ] {
220 let expected_ty = GlobalType::new(ValType::I31REF, mutability);
221 let global = Global::new(&mut store, expected_ty.clone(), val.into())?;
222 let actual_ty = global.ty(&store);
223 assert_eq!(expected_ty.mutability(), actual_ty.mutability());
224 assert!(ValType::eq(expected_ty.content(), actual_ty.content()));
225 }
226 }
227 Ok(())
228 }
229
230 #[test]
i31ref_as_anyref_global_new() -> Result<()>231 fn i31ref_as_anyref_global_new() -> Result<()> {
232 let mut config = Config::new();
233 config.wasm_function_references(true);
234 config.wasm_gc(true);
235
236 let engine = Engine::new(&config)?;
237 let mut store = Store::new(&engine, ());
238
239 for mutability in [Mutability::Const, Mutability::Var] {
240 for val in [
241 Some(AnyRef::from_i31(&mut store, I31::new_u32(42).unwrap())),
242 None,
243 ] {
244 Global::new(
245 &mut store,
246 GlobalType::new(ValType::ANYREF, mutability),
247 val.into(),
248 )?;
249 }
250 }
251 Ok(())
252 }
253
254 #[test]
i31ref_as_anyref_global_get() -> Result<()>255 fn i31ref_as_anyref_global_get() -> Result<()> {
256 let mut config = Config::new();
257 config.wasm_function_references(true);
258 config.wasm_gc(true);
259
260 let engine = Engine::new(&config)?;
261 let mut store = Store::new(&engine, ());
262
263 for mutability in [Mutability::Const, Mutability::Var] {
264 for val in [
265 Some(AnyRef::from_i31(&mut store, I31::new_u32(42).unwrap())),
266 None,
267 ] {
268 let val = Val::from(val);
269 let global = Global::new(
270 &mut store,
271 GlobalType::new(ValType::ANYREF, mutability),
272 val,
273 )?;
274
275 let got = global.get(&mut store);
276
277 let val = val
278 .anyref()
279 .and_then(|a| a.and_then(|a| a.as_i31(&store).unwrap()));
280 let got = got
281 .anyref()
282 .and_then(|a| a.and_then(|a| a.as_i31(&store).unwrap()));
283
284 assert_eq!(val, got);
285 }
286 }
287 Ok(())
288 }
289
290 #[test]
i31ref_as_anyref_global_set() -> Result<()>291 fn i31ref_as_anyref_global_set() -> Result<()> {
292 let mut config = Config::new();
293 config.wasm_function_references(true);
294 config.wasm_gc(true);
295
296 let engine = Engine::new(&config)?;
297 let mut store = Store::new(&engine, ());
298
299 for init in [
300 Some(AnyRef::from_i31(&mut store, I31::new_u32(42).unwrap())),
301 None,
302 ] {
303 for new_val in [
304 Some(AnyRef::from_i31(&mut store, I31::new_u32(36).unwrap())),
305 None,
306 ] {
307 let global = Global::new(
308 &mut store,
309 GlobalType::new(ValType::ANYREF, Mutability::Var),
310 init.into(),
311 )?;
312
313 let new_val = Val::from(new_val);
314 global.set(&mut store, new_val)?;
315 let got = global.get(&mut store);
316
317 let new_val = new_val
318 .anyref()
319 .and_then(|a| a.and_then(|a| a.as_i31(&store).unwrap()));
320 let got = got
321 .anyref()
322 .and_then(|a| a.and_then(|a| a.as_i31(&store).unwrap()));
323
324 assert_eq!(new_val, got);
325 }
326 }
327 Ok(())
328 }
329
330 #[test]
i31ref_as_anyref_global_ty() -> Result<()>331 fn i31ref_as_anyref_global_ty() -> Result<()> {
332 let mut config = Config::new();
333 config.wasm_function_references(true);
334 config.wasm_gc(true);
335
336 let engine = Engine::new(&config)?;
337 let mut store = Store::new(&engine, ());
338
339 for mutability in [Mutability::Const, Mutability::Var] {
340 for val in [
341 Some(AnyRef::from_i31(&mut store, I31::new_u32(42).unwrap())),
342 None,
343 ] {
344 let expected_ty = GlobalType::new(ValType::ANYREF, mutability);
345 let global = Global::new(&mut store, expected_ty.clone(), val.into())?;
346 let actual_ty = global.ty(&store);
347 assert_eq!(expected_ty.mutability(), actual_ty.mutability());
348 assert!(ValType::eq(expected_ty.content(), actual_ty.content()));
349 }
350 }
351 Ok(())
352 }
353
354 #[test]
355 #[cfg_attr(miri, ignore)]
instantiate_global_with_subtype() -> Result<()>356 fn instantiate_global_with_subtype() -> Result<()> {
357 let mut config = Config::new();
358 config.wasm_function_references(true);
359 config.wasm_gc(true);
360
361 let engine = Engine::new(&config)?;
362 let module = Module::new(
363 &engine,
364 r#"
365 (module
366 (type $func_ty (sub (func)))
367 (import "" "" (global (ref null $func_ty)))
368 )
369 "#,
370 )?;
371
372 {
373 let func_ty =
374 FuncType::with_finality_and_supertype(&engine, Finality::NonFinal, None, [], [])?;
375 let sub_func_ty = FuncType::with_finality_and_supertype(
376 &engine,
377 Finality::NonFinal,
378 Some(&func_ty),
379 [],
380 [],
381 )?;
382 let global_ty = GlobalType::new(
383 RefType::new(true, HeapType::ConcreteFunc(sub_func_ty.clone())).into(),
384 Mutability::Const,
385 );
386 assert!(
387 global_ty.content().matches(
388 module
389 .imports()
390 .nth(0)
391 .unwrap()
392 .ty()
393 .unwrap_global()
394 .content()
395 )
396 );
397
398 let mut store = Store::new(&engine, ());
399 let func = Func::new(&mut store, sub_func_ty, |_caller, _args, _rets| Ok(()));
400 let global = Global::new(&mut store, global_ty, func.into())?;
401
402 // This instantiation should succeed: the given global's type is a subtype
403 // of the import's global type.
404 let _ = Instance::new(&mut store, &module, &[global.into()])?;
405 }
406
407 {
408 let func_ty = FuncType::new(&engine, [], []);
409 let global_ty = GlobalType::new(
410 RefType::new(true, HeapType::ConcreteFunc(func_ty.clone())).into(),
411 Mutability::Const,
412 );
413 assert!(
414 !global_ty.content().matches(
415 module
416 .imports()
417 .nth(0)
418 .unwrap()
419 .ty()
420 .unwrap_global()
421 .content()
422 )
423 );
424
425 let mut store = Store::new(&engine, ());
426 let func = Func::new(&mut store, func_ty, |_caller, _args, _rets| Ok(()));
427 let global = Global::new(&mut store, global_ty, func.into())?;
428
429 // This instantiation should fail: the given global's type is *not* a
430 // subtype of the import's global type.
431 assert!(Instance::new(&mut store, &module, &[global.into()]).is_err());
432 }
433
434 Ok(())
435 }
436
437 #[test]
host_globals_keep_type_registration() -> Result<()>438 fn host_globals_keep_type_registration() -> Result<()> {
439 let engine = Engine::default();
440 let mut store = Store::new(&engine, ());
441
442 let ty = FuncType::new(&engine, [], []);
443
444 let g = Global::new(
445 &mut store,
446 GlobalType::new(
447 RefType::new(true, HeapType::ConcreteFunc(ty)).into(),
448 Mutability::Const,
449 ),
450 Val::FuncRef(None),
451 )?;
452
453 {
454 let _ty2 = FuncType::new(&engine, [ValType::I32], [ValType::I32]);
455 let ty = g.ty(&store);
456 let fty = ty.content().unwrap_ref().heap_type().unwrap_concrete_func();
457 assert!(fty.params().len() == 0);
458 assert!(fty.results().len() == 0);
459 }
460
461 let ty = g.ty(&store);
462 let fty = ty.content().unwrap_ref().heap_type().unwrap_concrete_func();
463 assert!(fty.params().len() == 0);
464 assert!(fty.results().len() == 0);
465
466 Ok(())
467 }
468