// // Host GC integration library, see gc.h. // addToLibrary({ $gcMap: 'new Map()', $gcWeakRefMap: 'new Map()', $gcFinalizer: null, gc_alloc__deps: ['$gcMap', '$gcWeakRefMap', '$gcFinalizer'], gc_alloc: (self, onCollect) => { if (!gcFinalizer) { gcFinalizer = new FinalizationRegistry((held) => { const [self, onCollect] = held; {{{ makeDynCall('vii', 'onCollect') }}}(self); }); } const mirror = { self, onCollect, links: [], // Start at one root, until we are linked to. roots: 1, linkedTo: false, }; gcMap.set(self, mirror); gcWeakRefMap.set(self, new WeakRef(mirror)); gcFinalizer.register(mirror, [self, onCollect]); }, gc_set__deps: ['gc_unroot'], gc_set: (self, index, value) => { // The value written may be null. const valueMirror = gcWeakRefMap.get(value)?.deref(); gcWeakRefMap.get(self).deref().links[index] = valueMirror; if (valueMirror && !valueMirror.linkedTo) { valueMirror.linkedTo = true; _gc_unroot(value); } }, gc_root: (self) => { const mirror = gcWeakRefMap.get(self).deref(); mirror.roots++; if (mirror.roots == 1) { gcMap.set(self, mirror); } }, gc_unroot: (self) => { const mirror = gcWeakRefMap.get(self).deref(); mirror.roots--; if (mirror.roots == 0) { gcMap.delete(self); } if (mirror.roots < 0) { throw new Error('bad unroot'); } }, });