| 1004 | #[test] |
| 1005 | #[cfg_attr(miri, ignore)] |
| 1006 | fn host_arrayref_has_trace_info_for_gc() -> Result<()> { |
| 1007 | for collector in [Collector::Copying, Collector::DeferredReferenceCounting] { |
| 1008 | println!("Using GC collector: {collector:?}"); |
| 1009 | |
| 1010 | let mut config = Config::new(); |
| 1011 | config.wasm_exceptions(true).wasm_gc(true); |
| 1012 | config.collector(collector); |
| 1013 | |
| 1014 | let engine = Engine::new(&config)?; |
| 1015 | |
| 1016 | // Create a store and allocate the GC store by instantiating a module |
| 1017 | let mut store = Store::new(&engine, ()); |
| 1018 | let module = Module::new( |
| 1019 | &engine, |
| 1020 | r#"(module |
| 1021 | (global (export "g") (mut arrayref) (ref.null array)) |
| 1022 | (table 1 anyref) |
| 1023 | )"#, |
| 1024 | )?; |
| 1025 | let instance = Instance::new(&mut store, &module, &[])?; |
| 1026 | let g = instance.get_global(&mut store, "g").unwrap(); |
| 1027 | |
| 1028 | // Allocate a host arrayref object in a nested scope and put it into the |
| 1029 | // module that was just allocated. |
| 1030 | let array_ty = ArrayType::new(&engine, FieldType::new(Mutability::Const, StorageType::I8)); |
| 1031 | let arraypre = ArrayRefPre::new(&mut store, array_ty.clone()); |
| 1032 | { |
| 1033 | let mut scope = RootScope::new(&mut store); |
| 1034 | let array = ArrayRef::new(&mut scope, &arraypre, &Val::I32(29), 1)?; |
| 1035 | g.set(&mut scope, Val::AnyRef(Some(array.into())))?; |
| 1036 | } |
| 1037 | |
| 1038 | // The arrayref should stay alive and be traced properly... |
| 1039 | store.gc(None)?; |
| 1040 | |
| 1041 | assert!(matches!(g.get(&mut store), Val::AnyRef(Some(_)))); |
| 1042 | } |
| 1043 | |
| 1044 | Ok(()) |
| 1045 | } |