When replacing an existing entry of a WeakValueMap, the old value is not unregistered from the FinalizationRegistry so when it later get garbage-collected the corresponding entry gets erroneously deleted from the map.
Test case using node --expose-gc:
import { WeakValueMap } from 'weakref';
import assert from 'node:assert';
function next_job() {
return new Promise( resolve => setImmediate( resolve ) );
}
let map = new WeakValueMap;
map.set( 42, {} ); // create entry pointing to fresh garbage
let x = {};
map.set( 42, x ); // overwrite entry with a strongly retained value
await next_job(); // release strong ref on new/dereferenced weakrefs
gc(); // garbage-collect the now-unreferenced old value
await next_job(); // fire finalization callback
assert.strictEqual( map.get( 42 ), x ); // FAILS
assert.strictEqual( map.size, 1 ); // FAILS