Skip to content

Commit

Permalink
fix: add stubs for GC tools (no-op on Node v12)
Browse files Browse the repository at this point in the history
The upcoming GC functionality will require `WeakRef` and
`FinalizationRegistry`. Node.js v14 provides these as globals, but v12 does
not (there might be a command-line flag to enable it, but I think it's marked
as experimental). Rather than require all users upgrade to v14, we elect to
disable GC when running on v12.

This adds a local `weakref.js` module which attempts to pull `WeakRef` and
`FinalizationRegistry` from the global, and exports either the real
constructors or no-op stubs.

refs #1872
refs #1925
  • Loading branch information
warner committed Oct 26, 2020
1 parent 54eea62 commit 7ecc184
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 0 deletions.
38 changes: 38 additions & 0 deletions packages/SwingSet/src/weakref.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/* global globalThis */

/*
* We retain a measure of compatibility with Node.js v12, which does not
* expose WeakRef or FinalizationRegistry (there is a --flag for it, but it's
* * not clear how stable it is). When running on a platform without these *
* tools, vats cannot do GC, and the tools they get will be no-ops. WeakRef
* instances will hold a strong reference, and the FinalizationRegistry will
* never invoke the callbacks.
*
* Modules should do:
*
* import { WeakRef, FinalizationRegistry } from '.../weakref';
*
*/

function FakeWeakRef(obj) {
const wr = Object.create({
deref: () => obj,
});
delete wr.constructor;
return wr;
}

function FakeFinalizationRegistry(_callback) {
const fr = Object.create({
register: (_obj, _handle) => undefined,
unregister: _handle => undefined,
});
delete fr.constructor;
return fr;
}

const WR = globalThis.WeakRef || FakeWeakRef;
const FR = globalThis.FinalizationRegistry || FakeFinalizationRegistry;

export const WeakRef = WR;
export const FinalizationRegistry = FR;
23 changes: 23 additions & 0 deletions packages/SwingSet/test/test-fake-weakref.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import '@agoric/install-ses';
import test from 'ava';
import { WeakRef, FinalizationRegistry } from '../src/weakref';

// We don't test that WeakRefs actually work, we only make sure we can
// interact with them without crashing. This exercises the fake no-op WeakRef
// and FinalizationRegistry that our `src/weakref.js` creates on Node.js v12.
// On v14 we get real constructors.

test('weakref is callable', async t => {
const obj = {};
const wr = new WeakRef(obj);
t.is(obj, wr.deref());

const callback = () => 0;
const fr = new FinalizationRegistry(callback);
fr.register(obj);

const obj2 = {};
const handle = {};
fr.register(obj2, handle);
fr.unregister(handle);
});

0 comments on commit 7ecc184

Please sign in to comment.