Skip to content

WeakValueMap: entries for recently garbage-collected values temporarily remain visible with undefined value #2

@mvduin

Description

@mvduin

After a value gets garbage collected but before the FinalizationRegistry callback has fired the table entry continues to exist according to has(), size, and iteration, but with undefined value. This is unlikely to be what any user wants, I would expect map entries to simply get deleted when values get garbage-collected.

It's easy enough to make the has() method and iteration methods deref the WeakRef to verify the entry is still valid and pretend it doesn't exist otherwise. It's a bit annoying though that a correct implementation for size would require iterating the entire map, although it would also be a rather ugly wart if it sometimes returns an erroneously high value. Perhaps if there's a use-case for a fast size estimate (upper bound) a separate accessor could be added for it.

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, {} );

await next_job();  // release strong ref on new/dereferenced weakrefs
gc();  // garbage-collect the now-unreferenced value

assert.strictEqual( map.get( 42 ), undefined );  // passes
assert( ! map.has( 42 ) );  // FAILS
assert.strictEqual( map.size, 0 );  // FAILS

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions