Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bytecodealliance
GitHub Repository: bytecodealliance/wasmtime
Path: blob/main/tests/all/globals.rs
1691 views
1
use wasmtime::*;
2
3
#[test]
4
fn smoke() -> anyhow::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]
45
fn mutability() -> anyhow::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]
63
fn use_after_drop() -> anyhow::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]
93
fn v128() -> anyhow::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]
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]
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]
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]
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]
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]
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]
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]
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)]
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]
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
469