Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bytecodealliance
GitHub Repository: bytecodealliance/wasmtime
Path: blob/main/tests/all/arrays.rs
1690 views
1
use super::gc_store;
2
use wasmtime::*;
3
4
#[test]
5
fn array_new_empty() -> Result<()> {
6
let mut store = gc_store()?;
7
let array_ty = ArrayType::new(
8
store.engine(),
9
FieldType::new(Mutability::Const, StorageType::I8),
10
);
11
let pre = ArrayRefPre::new(&mut store, array_ty);
12
let array = ArrayRef::new(&mut store, &pre, &Val::I32(0), 0)?;
13
assert_eq!(array.len(&store)?, 0);
14
Ok(())
15
}
16
17
#[test]
18
fn array_new_with_elems() -> Result<()> {
19
let mut store = gc_store()?;
20
let array_ty = ArrayType::new(
21
store.engine(),
22
FieldType::new(Mutability::Const, ValType::I32.into()),
23
);
24
let pre = ArrayRefPre::new(&mut store, array_ty);
25
let array = ArrayRef::new(&mut store, &pre, &Val::I32(99), 3)?;
26
assert_eq!(array.len(&store)?, 3);
27
for i in 0..3 {
28
assert_eq!(array.get(&mut store, i)?.unwrap_i32(), 99);
29
}
30
Ok(())
31
}
32
33
#[test]
34
fn array_new_unrooted_initial_elem() -> Result<()> {
35
let mut store = gc_store()?;
36
let array_ty = ArrayType::new(
37
store.engine(),
38
FieldType::new(Mutability::Var, StorageType::ValType(ValType::ANYREF)),
39
);
40
let pre = ArrayRefPre::new(&mut store, array_ty);
41
42
// Passing an unrooted `anyref` to `StructRef::new` results in an error.
43
let anyref = {
44
let mut scope = RootScope::new(&mut store);
45
AnyRef::from_i31(&mut scope, I31::new_i32(1234).unwrap())
46
};
47
48
assert!(ArrayRef::new(&mut store, &pre, &anyref.into(), 3).is_err());
49
Ok(())
50
}
51
52
#[test]
53
#[should_panic = "wrong store"]
54
fn array_new_cross_store_initial_elem() {
55
let mut store1 = gc_store().unwrap();
56
let mut store2 = gc_store().unwrap();
57
58
let array_ty = ArrayType::new(
59
store1.engine(),
60
FieldType::new(Mutability::Var, StorageType::ValType(ValType::ANYREF)),
61
);
62
let pre = ArrayRefPre::new(&mut store1, array_ty);
63
64
// Passing an `anyref` from a different store to `ArrayRef::new` results in
65
// a panic.
66
let anyref = AnyRef::from_i31(&mut store2, I31::new_i32(1234).unwrap());
67
ArrayRef::new(&mut store1, &pre, &anyref.into(), 3).unwrap();
68
}
69
70
#[test]
71
#[should_panic = "wrong store"]
72
fn array_new_cross_store_pre() {
73
let mut store1 = gc_store().unwrap();
74
let mut store2 = gc_store().unwrap();
75
76
let array_ty = ArrayType::new(
77
store1.engine(),
78
FieldType::new(Mutability::Var, StorageType::ValType(ValType::ANYREF)),
79
);
80
let pre = ArrayRefPre::new(&mut store2, array_ty);
81
82
ArrayRef::new(&mut store1, &pre, &Val::I32(0), 3).unwrap();
83
}
84
85
#[test]
86
fn array_new_fixed_empty() -> Result<()> {
87
let mut store = gc_store()?;
88
let array_ty = ArrayType::new(
89
store.engine(),
90
FieldType::new(Mutability::Const, ValType::I32.into()),
91
);
92
let pre = ArrayRefPre::new(&mut store, array_ty);
93
let array = ArrayRef::new_fixed(&mut store, &pre, &[])?;
94
assert_eq!(array.len(&store)?, 0);
95
Ok(())
96
}
97
98
#[test]
99
fn array_new_fixed_with_elems() -> Result<()> {
100
let mut store = gc_store()?;
101
let array_ty = ArrayType::new(
102
store.engine(),
103
FieldType::new(Mutability::Const, ValType::I32.into()),
104
);
105
let pre = ArrayRefPre::new(&mut store, array_ty);
106
let array = ArrayRef::new_fixed(
107
&mut store,
108
&pre,
109
&[Val::I32(11), Val::I32(22), Val::I32(33)],
110
)?;
111
assert_eq!(array.len(&store)?, 3);
112
for i in 0..3 {
113
assert_eq!(array.get(&mut store, i)?.unwrap_i32(), (i as i32 + 1) * 11);
114
}
115
Ok(())
116
}
117
118
#[test]
119
fn array_new_fixed_unrooted_initial_elem() -> Result<()> {
120
let mut store = gc_store()?;
121
let array_ty = ArrayType::new(
122
store.engine(),
123
FieldType::new(Mutability::Var, StorageType::ValType(ValType::ANYREF)),
124
);
125
let pre = ArrayRefPre::new(&mut store, array_ty);
126
127
// Passing an unrooted `anyref` to `StructRef::new` results in an error.
128
let anyref = {
129
let mut scope = RootScope::new(&mut store);
130
AnyRef::from_i31(&mut scope, I31::new_i32(1234).unwrap())
131
};
132
133
assert!(ArrayRef::new_fixed(&mut store, &pre, &[anyref.into()]).is_err());
134
Ok(())
135
}
136
137
#[test]
138
#[should_panic = "wrong store"]
139
fn array_new_fixed_cross_store_initial_elem() {
140
let mut store1 = gc_store().unwrap();
141
let mut store2 = gc_store().unwrap();
142
143
let array_ty = ArrayType::new(
144
store1.engine(),
145
FieldType::new(Mutability::Var, StorageType::ValType(ValType::ANYREF)),
146
);
147
let pre = ArrayRefPre::new(&mut store1, array_ty);
148
149
// Passing an `anyref` from a different store to `ArrayRef::new_fixed`
150
// results in a panic.
151
let anyref = AnyRef::from_i31(&mut store2, I31::new_i32(1234).unwrap());
152
ArrayRef::new_fixed(&mut store1, &pre, &[anyref.into()]).unwrap();
153
}
154
155
#[test]
156
#[should_panic = "wrong store"]
157
fn array_new_fixed_cross_store_pre() {
158
let mut store1 = gc_store().unwrap();
159
let mut store2 = gc_store().unwrap();
160
161
let array_ty = ArrayType::new(
162
store1.engine(),
163
FieldType::new(Mutability::Var, StorageType::ValType(ValType::ANYREF)),
164
);
165
let pre = ArrayRefPre::new(&mut store2, array_ty);
166
167
ArrayRef::new_fixed(&mut store1, &pre, &[Val::I32(0)]).unwrap();
168
}
169
170
#[test]
171
fn anyref_as_array() -> Result<()> {
172
let mut store = gc_store()?;
173
174
let array_ty = ArrayType::new(
175
store.engine(),
176
FieldType::new(Mutability::Const, StorageType::ValType(ValType::I32)),
177
);
178
let pre = ArrayRefPre::new(&mut store, array_ty);
179
let a0 = ArrayRef::new_fixed(&mut store, &pre, &[])?;
180
181
let anyref: Rooted<AnyRef> = a0.into();
182
assert!(anyref.is_array(&store)?);
183
let a1 = anyref.as_array(&store)?.unwrap();
184
assert!(Rooted::ref_eq(&store, &a0, &a1)?);
185
186
let anyref = AnyRef::from_i31(&mut store, I31::new_i32(42).unwrap());
187
assert!(!anyref.is_array(&store)?);
188
assert!(anyref.as_array(&store)?.is_none());
189
190
Ok(())
191
}
192
193
#[test]
194
fn array_len_empty() -> Result<()> {
195
let mut store = gc_store()?;
196
197
let array_ty = ArrayType::new(
198
store.engine(),
199
FieldType::new(Mutability::Const, ValType::I32.into()),
200
);
201
let pre = ArrayRefPre::new(&mut store, array_ty);
202
203
let array = ArrayRef::new_fixed(&mut store, &pre, &[])?;
204
assert_eq!(array.len(&store)?, 0);
205
206
Ok(())
207
}
208
209
#[test]
210
fn array_len_non_empty() -> Result<()> {
211
let mut store = gc_store()?;
212
213
let array_ty = ArrayType::new(
214
store.engine(),
215
FieldType::new(Mutability::Const, ValType::I32.into()),
216
);
217
let pre = ArrayRefPre::new(&mut store, array_ty);
218
219
let array = ArrayRef::new_fixed(
220
&mut store,
221
&pre,
222
&[Val::I32(11), Val::I32(22), Val::I32(33)],
223
)?;
224
assert_eq!(array.len(&store)?, 3);
225
226
Ok(())
227
}
228
229
#[test]
230
fn array_get_in_bounds() -> Result<()> {
231
let mut store = gc_store()?;
232
233
let array_ty = ArrayType::new(
234
store.engine(),
235
FieldType::new(Mutability::Const, ValType::I32.into()),
236
);
237
let pre = ArrayRefPre::new(&mut store, array_ty);
238
239
let array = ArrayRef::new_fixed(
240
&mut store,
241
&pre,
242
&[Val::I32(11), Val::I32(22), Val::I32(33)],
243
)?;
244
245
assert_eq!(array.get(&mut store, 0)?.unwrap_i32(), 11);
246
assert_eq!(array.get(&mut store, 1)?.unwrap_i32(), 22);
247
assert_eq!(array.get(&mut store, 2)?.unwrap_i32(), 33);
248
249
Ok(())
250
}
251
252
#[test]
253
fn array_get_out_of_bounds() -> Result<()> {
254
let mut store = gc_store()?;
255
256
let array_ty = ArrayType::new(
257
store.engine(),
258
FieldType::new(Mutability::Const, ValType::I32.into()),
259
);
260
let pre = ArrayRefPre::new(&mut store, array_ty);
261
262
let array = ArrayRef::new_fixed(
263
&mut store,
264
&pre,
265
&[Val::I32(11), Val::I32(22), Val::I32(33)],
266
)?;
267
268
assert!(array.get(&mut store, 3).is_err());
269
assert!(array.get(&mut store, 4).is_err());
270
271
Ok(())
272
}
273
274
#[test]
275
fn array_get_on_unrooted() -> Result<()> {
276
let mut store = gc_store()?;
277
278
let array_ty = ArrayType::new(
279
store.engine(),
280
FieldType::new(Mutability::Const, ValType::I32.into()),
281
);
282
let pre = ArrayRefPre::new(&mut store, array_ty);
283
284
let array = {
285
let mut scope = RootScope::new(&mut store);
286
ArrayRef::new_fixed(&mut scope, &pre, &[Val::I32(11)])?
287
};
288
289
assert!(array.get(&mut store, 0).is_err());
290
Ok(())
291
}
292
293
#[test]
294
#[should_panic = "wrong store"]
295
fn array_get_wrong_store() {
296
let mut store1 = gc_store().unwrap();
297
let mut store2 = gc_store().unwrap();
298
299
let array_ty = ArrayType::new(
300
store1.engine(),
301
FieldType::new(Mutability::Const, ValType::I32.into()),
302
);
303
let pre = ArrayRefPre::new(&mut store1, array_ty);
304
305
let array = ArrayRef::new_fixed(&mut store1, &pre, &[Val::I32(11)]).unwrap();
306
307
// Should panic.
308
let _ = array.get(&mut store2, 0);
309
}
310
311
#[test]
312
fn array_set_in_bounds() -> Result<()> {
313
let mut store = gc_store()?;
314
315
let array_ty = ArrayType::new(
316
store.engine(),
317
FieldType::new(Mutability::Var, ValType::I32.into()),
318
);
319
let pre = ArrayRefPre::new(&mut store, array_ty);
320
321
let array = ArrayRef::new_fixed(&mut store, &pre, &[Val::I32(11)])?;
322
323
assert_eq!(array.get(&mut store, 0)?.unwrap_i32(), 11);
324
array.set(&mut store, 0, Val::I32(22))?;
325
assert_eq!(array.get(&mut store, 0)?.unwrap_i32(), 22);
326
327
Ok(())
328
}
329
330
#[test]
331
fn array_set_out_of_bounds() -> Result<()> {
332
let mut store = gc_store()?;
333
334
let array_ty = ArrayType::new(
335
store.engine(),
336
FieldType::new(Mutability::Var, ValType::I32.into()),
337
);
338
let pre = ArrayRefPre::new(&mut store, array_ty);
339
340
let array = ArrayRef::new_fixed(&mut store, &pre, &[Val::I32(11)])?;
341
342
assert!(array.set(&mut store, 1, Val::I32(22)).is_err());
343
assert!(array.set(&mut store, 2, Val::I32(33)).is_err());
344
345
Ok(())
346
}
347
348
#[test]
349
fn array_set_on_unrooted() -> Result<()> {
350
let mut store = gc_store()?;
351
352
let array_ty = ArrayType::new(
353
store.engine(),
354
FieldType::new(Mutability::Var, ValType::I32.into()),
355
);
356
let pre = ArrayRefPre::new(&mut store, array_ty);
357
358
let array = {
359
let mut scope = RootScope::new(&mut store);
360
ArrayRef::new_fixed(&mut scope, &pre, &[Val::I32(11)])?
361
};
362
363
assert!(array.set(&mut store, 0, Val::I32(22)).is_err());
364
Ok(())
365
}
366
367
#[test]
368
fn array_set_given_unrooted() -> Result<()> {
369
let mut store = gc_store()?;
370
371
let array_ty = ArrayType::new(
372
store.engine(),
373
FieldType::new(Mutability::Var, ValType::ANYREF.into()),
374
);
375
let pre = ArrayRefPre::new(&mut store, array_ty);
376
377
let array = ArrayRef::new_fixed(&mut store, &pre, &[Val::AnyRef(None)])?;
378
379
let anyref = {
380
let mut scope = RootScope::new(&mut store);
381
AnyRef::from_i31(&mut scope, I31::new_i32(1234).unwrap())
382
};
383
384
assert!(array.set(&mut store, 0, anyref.into()).is_err());
385
Ok(())
386
}
387
388
#[test]
389
#[should_panic = "wrong store"]
390
fn array_set_cross_store_value() {
391
let mut store1 = gc_store().unwrap();
392
let mut store2 = gc_store().unwrap();
393
394
let array_ty = ArrayType::new(
395
store1.engine(),
396
FieldType::new(Mutability::Var, ValType::ANYREF.into()),
397
);
398
let pre = ArrayRefPre::new(&mut store1, array_ty);
399
400
let array = ArrayRef::new_fixed(&mut store1, &pre, &[Val::AnyRef(None)]).unwrap();
401
402
let anyref = AnyRef::from_i31(&mut store2, I31::new_i32(1234).unwrap());
403
404
// Should panic.
405
let _ = array.set(&mut store1, 0, anyref.into());
406
}
407
408
#[test]
409
fn array_set_immutable_elems() -> Result<()> {
410
let mut store = gc_store()?;
411
412
let array_ty = ArrayType::new(
413
store.engine(),
414
FieldType::new(Mutability::Const, ValType::I32.into()),
415
);
416
let pre = ArrayRefPre::new(&mut store, array_ty);
417
418
let array = ArrayRef::new_fixed(
419
&mut store,
420
&pre,
421
&[Val::I32(11), Val::I32(22), Val::I32(33)],
422
)?;
423
424
assert!(array.set(&mut store, 0, Val::I32(22)).is_err());
425
assert!(array.set(&mut store, 1, Val::I32(33)).is_err());
426
assert!(array.set(&mut store, 2, Val::I32(44)).is_err());
427
428
Ok(())
429
}
430
431
#[test]
432
fn array_set_wrong_field_type() -> Result<()> {
433
let mut store = gc_store()?;
434
435
let array_ty = ArrayType::new(
436
store.engine(),
437
FieldType::new(Mutability::Var, ValType::I32.into()),
438
);
439
let pre = ArrayRefPre::new(&mut store, array_ty);
440
441
let array = ArrayRef::new_fixed(&mut store, &pre, &[Val::I32(11)])?;
442
443
assert!(array.set(&mut store, 0, Val::I64(22)).is_err());
444
Ok(())
445
}
446
447
#[test]
448
fn array_ty() -> Result<()> {
449
let mut store = gc_store()?;
450
let array_ty = ArrayType::new(
451
store.engine(),
452
FieldType::new(Mutability::Const, ValType::I32.into()),
453
);
454
let pre = ArrayRefPre::new(&mut store, array_ty.clone());
455
let a = ArrayRef::new_fixed(&mut store, &pre, &[Val::I32(11)])?;
456
assert!(ArrayType::eq(&array_ty, &a.ty(&store)?));
457
Ok(())
458
}
459
460
#[test]
461
fn array_ty_unrooted() -> Result<()> {
462
let mut store = gc_store()?;
463
let array_ty = ArrayType::new(
464
store.engine(),
465
FieldType::new(Mutability::Const, ValType::I32.into()),
466
);
467
let pre = ArrayRefPre::new(&mut store, array_ty);
468
let a = {
469
let mut scope = RootScope::new(&mut store);
470
ArrayRef::new_fixed(&mut scope, &pre, &[Val::I32(11)])?
471
};
472
assert!(a.ty(&store).is_err());
473
Ok(())
474
}
475
476
#[test]
477
fn array_elems_empty() -> Result<()> {
478
let mut store = gc_store()?;
479
let array_ty = ArrayType::new(
480
store.engine(),
481
FieldType::new(Mutability::Const, ValType::I32.into()),
482
);
483
let pre = ArrayRefPre::new(&mut store, array_ty);
484
let array = ArrayRef::new_fixed(&mut store, &pre, &[])?;
485
let mut elems = array.elems(&mut store)?;
486
assert_eq!(elems.len(), 0);
487
assert!(elems.next().is_none());
488
Ok(())
489
}
490
491
#[test]
492
fn array_elems_non_empty() -> Result<()> {
493
let mut store = gc_store()?;
494
let array_ty = ArrayType::new(
495
store.engine(),
496
FieldType::new(Mutability::Const, ValType::I32.into()),
497
);
498
let pre = ArrayRefPre::new(&mut store, array_ty);
499
let array = ArrayRef::new_fixed(
500
&mut store,
501
&pre,
502
&[Val::I32(11), Val::I32(22), Val::I32(33)],
503
)?;
504
let mut elems = array.elems(&mut store)?;
505
assert_eq!(elems.len(), 3);
506
assert_eq!(elems.next().unwrap().unwrap_i32(), 11);
507
assert_eq!(elems.next().unwrap().unwrap_i32(), 22);
508
assert_eq!(elems.next().unwrap().unwrap_i32(), 33);
509
assert!(elems.next().is_none());
510
Ok(())
511
}
512
513
#[test]
514
fn array_elems_unrooted() -> Result<()> {
515
let mut store = gc_store()?;
516
let array_ty = ArrayType::new(
517
store.engine(),
518
FieldType::new(Mutability::Const, ValType::I32.into()),
519
);
520
let pre = ArrayRefPre::new(&mut store, array_ty);
521
let array = {
522
let mut scope = RootScope::new(&mut store);
523
ArrayRef::new_fixed(&mut scope, &pre, &[Val::I32(11)])?
524
};
525
assert!(array.elems(&mut store).is_err());
526
Ok(())
527
}
528
529
#[test]
530
#[cfg_attr(miri, ignore)]
531
fn passing_arrays_through_wasm_with_untyped_calls() -> Result<()> {
532
let mut store = gc_store()?;
533
534
let module = Module::new(
535
store.engine(),
536
r#"
537
(module
538
(type (array i8))
539
(import "" "" (func $f (param (ref 0)) (result (ref 0))))
540
(func (export "run") (param (ref 0)) (result (ref 0))
541
(call $f (local.get 0))
542
)
543
)
544
"#,
545
)?;
546
547
let array_ty = ArrayType::new(
548
store.engine(),
549
FieldType::new(Mutability::Const, StorageType::I8),
550
);
551
552
let ref_ty = RefType::new(false, HeapType::ConcreteArray(array_ty.clone()));
553
let func_ty = FuncType::new(store.engine(), [ref_ty.clone().into()], [ref_ty.into()]);
554
555
let func = Func::new(&mut store, func_ty, |mut caller, args, results| {
556
let a = args[0].unwrap_any_ref().unwrap();
557
let a = a.unwrap_array(&mut caller)?;
558
assert_eq!(a.len(&mut caller)?, 1);
559
assert_eq!(a.get(&mut caller, 0)?.unwrap_i32(), 42);
560
results[0] = args[0];
561
Ok(())
562
});
563
564
let instance = Instance::new(&mut store, &module, &[func.into()])?;
565
let run = instance.get_func(&mut store, "run").unwrap();
566
567
let pre = ArrayRefPre::new(&mut store, array_ty.clone());
568
let a = ArrayRef::new_fixed(&mut store, &pre, &[Val::I32(42)])?;
569
570
let mut results = vec![Val::null_any_ref()];
571
run.call(&mut store, &[a.into()], &mut results)?;
572
573
let a2 = results[0].unwrap_any_ref().unwrap();
574
let a2 = a2.unwrap_array(&mut store)?;
575
assert_eq!(a2.len(&mut store)?, 1);
576
assert_eq!(a2.get(&mut store, 0)?.unwrap_i32(), 42);
577
assert!(Rooted::ref_eq(&store, &a, &a2)?);
578
579
Ok(())
580
}
581
582
#[test]
583
#[cfg_attr(miri, ignore)]
584
fn passing_arrays_through_wasm_with_typed_calls() -> Result<()> {
585
let mut store = gc_store()?;
586
587
let module = Module::new(
588
store.engine(),
589
r#"
590
(module
591
(type (array i8))
592
(import "" "" (func $f (param (ref array)) (result (ref array))))
593
(func (export "run") (param (ref 0)) (result (ref array))
594
(call $f (local.get 0))
595
)
596
)
597
"#,
598
)?;
599
600
let array_ty = ArrayType::new(
601
store.engine(),
602
FieldType::new(Mutability::Const, StorageType::I8),
603
);
604
605
let func = Func::wrap(
606
&mut store,
607
|mut caller: Caller<()>, a: Rooted<ArrayRef>| -> Result<Rooted<ArrayRef>> {
608
assert_eq!(a.len(&caller)?, 1);
609
assert_eq!(a.get(&mut caller, 0)?.unwrap_i32(), 42);
610
Ok(a)
611
},
612
);
613
614
let instance = Instance::new(&mut store, &module, &[func.into()])?;
615
let run = instance.get_typed_func::<Rooted<ArrayRef>, Rooted<ArrayRef>>(&mut store, "run")?;
616
617
let pre = ArrayRefPre::new(&mut store, array_ty.clone());
618
let a = ArrayRef::new_fixed(&mut store, &pre, &[Val::I32(42)])?;
619
620
let a2 = run.call(&mut store, a)?;
621
622
assert_eq!(a2.len(&store)?, 1);
623
assert_eq!(a2.get(&mut store, 0)?.unwrap_i32(), 42);
624
assert!(Rooted::ref_eq(&store, &a, &a2)?);
625
626
Ok(())
627
}
628
629
#[test]
630
#[cfg_attr(miri, ignore)]
631
fn host_sets_array_global() -> Result<()> {
632
let mut store = gc_store()?;
633
634
let module = Module::new(
635
store.engine(),
636
r#"
637
(module
638
(type (array i8))
639
(global $g (export "g") (mut (ref null 0)) (ref.null 0))
640
(func (export "f") (result (ref null 0))
641
global.get $g
642
)
643
)
644
"#,
645
)?;
646
647
let instance = Instance::new(&mut store, &module, &[])?;
648
let g = instance.get_global(&mut store, "g").unwrap();
649
650
let array_ty = ArrayType::new(
651
store.engine(),
652
FieldType::new(Mutability::Const, StorageType::I8),
653
);
654
let pre = ArrayRefPre::new(&mut store, array_ty.clone());
655
let a0 = ArrayRef::new_fixed(&mut store, &pre, &[Val::I32(42)])?;
656
g.set(&mut store, a0.into())?;
657
658
// Get the global from the host.
659
let val = g.get(&mut store);
660
let anyref = val.unwrap_anyref().expect("non-null");
661
let a1 = anyref.unwrap_array(&store)?;
662
assert_eq!(a1.len(&store)?, 1);
663
assert_eq!(a1.get(&mut store, 0)?.unwrap_i32(), 42);
664
assert!(Rooted::ref_eq(&store, &a0, &a1)?);
665
666
// Get the global from the guest.
667
let f = instance.get_typed_func::<(), Option<Rooted<ArrayRef>>>(&mut store, "f")?;
668
let a2 = f.call(&mut store, ())?.expect("non-null");
669
assert_eq!(a2.len(&store)?, 1);
670
assert_eq!(a2.get(&mut store, 0)?.unwrap_i32(), 42);
671
assert!(Rooted::ref_eq(&store, &a0, &a2)?);
672
673
Ok(())
674
}
675
676
#[test]
677
#[cfg_attr(miri, ignore)]
678
fn wasm_sets_array_global() -> Result<()> {
679
let mut store = gc_store()?;
680
681
let module = Module::new(
682
store.engine(),
683
r#"
684
(module
685
(type (array i8))
686
(global $g (export "g") (mut (ref null 0)) (ref.null 0))
687
(func (export "get") (result (ref null 0))
688
global.get $g
689
)
690
(func (export "set") (param (ref null 0))
691
local.get 0
692
global.set $g
693
)
694
)
695
"#,
696
)?;
697
698
let array_ty = ArrayType::new(
699
store.engine(),
700
FieldType::new(Mutability::Const, StorageType::I8),
701
);
702
let pre = ArrayRefPre::new(&mut store, array_ty.clone());
703
let a0 = ArrayRef::new_fixed(&mut store, &pre, &[Val::I32(42)])?;
704
705
let instance = Instance::new(&mut store, &module, &[])?;
706
let set = instance.get_func(&mut store, "set").unwrap();
707
set.call(&mut store, &[a0.into()], &mut [])?;
708
709
// Get the global from the host.
710
let g = instance.get_global(&mut store, "g").unwrap();
711
let val = g.get(&mut store);
712
let anyref = val.unwrap_anyref().expect("non-null");
713
let a1 = anyref.unwrap_array(&store)?;
714
assert_eq!(a1.len(&store)?, 1);
715
assert_eq!(a1.get(&mut store, 0)?.unwrap_i32(), 42);
716
assert!(Rooted::ref_eq(&store, &a0, &a1)?);
717
718
// Get the global from the guest.
719
let f = instance.get_typed_func::<(), Option<Rooted<ArrayRef>>>(&mut store, "get")?;
720
let a2 = f.call(&mut store, ())?.expect("non-null");
721
assert_eq!(a2.len(&store)?, 1);
722
assert_eq!(a2.get(&mut store, 0)?.unwrap_i32(), 42);
723
assert!(Rooted::ref_eq(&store, &a0, &a2)?);
724
725
Ok(())
726
}
727
728
#[test]
729
#[cfg_attr(miri, ignore)]
730
fn host_sets_array_in_table() -> Result<()> {
731
let mut store = gc_store()?;
732
733
let module = Module::new(
734
store.engine(),
735
r#"
736
(module
737
(type (array i8))
738
(table $t (export "t") 1 1 (ref null 0) (ref.null 0))
739
(func (export "f") (result (ref null 0))
740
i32.const 0
741
table.get $t
742
)
743
)
744
"#,
745
)?;
746
747
let instance = Instance::new(&mut store, &module, &[])?;
748
let t = instance.get_table(&mut store, "t").unwrap();
749
750
let array_ty = ArrayType::new(
751
store.engine(),
752
FieldType::new(Mutability::Const, StorageType::I8),
753
);
754
let pre = ArrayRefPre::new(&mut store, array_ty.clone());
755
let a0 = ArrayRef::new_fixed(&mut store, &pre, &[Val::I32(42)])?;
756
t.set(&mut store, 0, a0.into())?;
757
758
// Get the global from the host.
759
let val = t.get(&mut store, 0).expect("in bounds");
760
let anyref = val.unwrap_any().expect("non-null");
761
let a1 = anyref.unwrap_array(&store)?;
762
assert_eq!(a1.len(&store)?, 1);
763
assert_eq!(a1.get(&mut store, 0)?.unwrap_i32(), 42);
764
assert!(Rooted::ref_eq(&store, &a0, &a1)?);
765
766
// Get the global from the guest.
767
let f = instance.get_typed_func::<(), Option<Rooted<ArrayRef>>>(&mut store, "f")?;
768
let a2 = f.call(&mut store, ())?.expect("non-null");
769
assert_eq!(a2.len(&store)?, 1);
770
assert_eq!(a2.get(&mut store, 0)?.unwrap_i32(), 42);
771
assert!(Rooted::ref_eq(&store, &a0, &a2)?);
772
773
Ok(())
774
}
775
776
#[test]
777
#[cfg_attr(miri, ignore)]
778
fn wasm_sets_array_in_table() -> Result<()> {
779
let mut store = gc_store()?;
780
781
let module = Module::new(
782
store.engine(),
783
r#"
784
(module
785
(type (array i8))
786
(table $t (export "t") 1 1 (ref null 0) (ref.null 0))
787
(func (export "get") (result (ref null 0))
788
i32.const 0
789
table.get $t
790
)
791
(func (export "set") (param (ref null 0))
792
i32.const 0
793
local.get 0
794
table.set $t
795
)
796
)
797
"#,
798
)?;
799
800
let array_ty = ArrayType::new(
801
store.engine(),
802
FieldType::new(Mutability::Const, StorageType::I8),
803
);
804
let pre = ArrayRefPre::new(&mut store, array_ty.clone());
805
let a0 = ArrayRef::new_fixed(&mut store, &pre, &[Val::I32(42)])?;
806
807
let instance = Instance::new(&mut store, &module, &[])?;
808
let set = instance.get_func(&mut store, "set").unwrap();
809
set.call(&mut store, &[a0.into()], &mut [])?;
810
811
// Get the global from the host.
812
let t = instance.get_table(&mut store, "t").unwrap();
813
let val = t.get(&mut store, 0).expect("in bounds");
814
let anyref = val.unwrap_any().expect("non-null");
815
let a1 = anyref.unwrap_array(&store)?;
816
assert_eq!(a1.len(&mut store)?, 1);
817
assert_eq!(a1.get(&mut store, 0)?.unwrap_i32(), 42);
818
assert!(Rooted::ref_eq(&store, &a0, &a1)?);
819
820
// Get the global from the guest.
821
let f = instance.get_typed_func::<(), Option<Rooted<ArrayRef>>>(&mut store, "get")?;
822
let a2 = f.call(&mut store, ())?.expect("non-null");
823
assert_eq!(a2.len(&mut store)?, 1);
824
assert_eq!(a2.get(&mut store, 0)?.unwrap_i32(), 42);
825
assert!(Rooted::ref_eq(&store, &a0, &a2)?);
826
827
Ok(())
828
}
829
830
#[test]
831
fn instantiate_with_array_global() -> Result<()> {
832
let mut store = gc_store()?;
833
834
let module = Module::new(
835
store.engine(),
836
r#"
837
(module
838
(type (array i8))
839
(import "" "" (global (ref null 0)))
840
(export "g" (global 0))
841
)
842
"#,
843
)?;
844
845
let array_ty = ArrayType::new(
846
store.engine(),
847
FieldType::new(Mutability::Const, StorageType::I8),
848
);
849
let global_ty = GlobalType::new(
850
ValType::Ref(RefType::new(
851
true,
852
HeapType::ConcreteArray(array_ty.clone()),
853
)),
854
Mutability::Const,
855
);
856
857
// Instantiate with a null-ref global.
858
let g = Global::new(&mut store, global_ty.clone(), Val::AnyRef(None))?;
859
let instance = Instance::new(&mut store, &module, &[g.into()])?;
860
let g = instance.get_global(&mut store, "g").expect("export exists");
861
let val = g.get(&mut store);
862
assert!(val.unwrap_anyref().is_none());
863
864
// Instantiate with a non-null-ref global.
865
let pre = ArrayRefPre::new(&mut store, array_ty);
866
let a0 = ArrayRef::new_fixed(&mut store, &pre, &[Val::I32(42)])?;
867
let g = Global::new(&mut store, global_ty, a0.into())?;
868
let instance = Instance::new(&mut store, &module, &[g.into()])?;
869
let g = instance.get_global(&mut store, "g").expect("export exists");
870
let val = g.get(&mut store);
871
let anyref = val.unwrap_anyref().expect("non-null");
872
let a1 = anyref.unwrap_array(&store)?;
873
assert_eq!(a1.len(&mut store)?, 1);
874
assert_eq!(a1.get(&mut store, 0)?.unwrap_i32(), 42);
875
assert!(Rooted::ref_eq(&store, &a0, &a1)?);
876
877
Ok(())
878
}
879
880