-
Notifications
You must be signed in to change notification settings - Fork 215
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1924 from Agoric/1872-gctools
chore: provide GC tools (WeakRef/FinalizationRegistry) to makeLiveSlots
- Loading branch information
Showing
13 changed files
with
194 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
/* global globalThis */ | ||
|
||
import { assert, details as d } from '@agoric/assert'; | ||
|
||
const { defineProperties } = Object; | ||
|
||
/* | ||
* 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'; | ||
* | ||
*/ | ||
|
||
// TODO We need to migrate this into a ses-level tame-weakref.js, to happen | ||
// as part of `lockdown`. In anticipation, this uses some of the patterns | ||
// followed by the other tamings there. | ||
|
||
// Emulate the internal [[WeakRefTarget]] slot. Despite the term "Weak" in the | ||
// "WeakMap" used in the emulation, this map holds the target strongly. The only | ||
// weakness here is that the weakref,target pair can go away together if the | ||
// weakref is not reachable. | ||
const weakRefTarget = new WeakMap(); | ||
|
||
const FakeWeakRef = function WeakRef(target) { | ||
assert( | ||
new.target !== undefined, | ||
d`WeakRef Constructor requires 'new'`, | ||
TypeError, | ||
); | ||
assert.equal( | ||
Object(target), | ||
target, | ||
d`WeakRef target must be an object`, | ||
TypeError, | ||
); | ||
weakRefTarget.set(this, target); | ||
}; | ||
|
||
const InertWeakRef = function WeakRef(_target) { | ||
throw new TypeError('Not available'); | ||
}; | ||
|
||
const FakeWeakRefPrototype = { | ||
deref() { | ||
return weakRefTarget.get(this); | ||
}, | ||
[Symbol.toStringTag]: 'WeakRef', | ||
}; | ||
|
||
defineProperties(FakeWeakRef, { | ||
prototype: { value: FakeWeakRefPrototype }, | ||
}); | ||
|
||
const WeakRef = globalThis.WeakRef || FakeWeakRef; | ||
|
||
// If there is a real WeakRef constructor, we still make it safe before | ||
// exporting it. Unlike https://github.com/tc39/ecma262/issues/2214 | ||
// rather than deleting the `constructor` property, we follow the other | ||
// taming patterns and point it at a throw-only inert one. | ||
defineProperties(WeakRef.prototype, { | ||
constructor: { value: InertWeakRef }, | ||
}); | ||
|
||
harden(WeakRef); | ||
|
||
export { WeakRef }; | ||
|
||
// ///////////////////////////////////////////////////////////////////////////// | ||
|
||
const FakeFinalizationRegistry = function FinalizationRegistry( | ||
cleanupCallback, | ||
) { | ||
assert( | ||
new.target !== undefined, | ||
d`FinalizationRegistry Constructor requires 'new'`, | ||
TypeError, | ||
); | ||
assert.typeof( | ||
cleanupCallback, | ||
'function', | ||
d`cleanupCallback must be a function`, | ||
); | ||
// fall off the end with an empty instance | ||
}; | ||
|
||
const InertFinalizationRegistry = function FinalizationRegistry( | ||
_cleanupCallback, | ||
) { | ||
throw new TypeError('Not available'); | ||
}; | ||
|
||
const FakeFinalizationRegistryPrototype = { | ||
register() {}, | ||
unregister() {}, | ||
[Symbol.toStringTag]: 'FinalizationRegistry', | ||
}; | ||
|
||
defineProperties(FakeFinalizationRegistry, { | ||
prototype: { value: FakeFinalizationRegistryPrototype }, | ||
}); | ||
|
||
const FinalizationRegistry = | ||
globalThis.FinalizationRegistry || FakeFinalizationRegistry; | ||
|
||
// If there is a real FinalizationRegistry constructor, we still make it safe | ||
// before exporting it. Rather than deleting the `constructor` property, we | ||
// follow the other taming patterns and point it at a throw-only inert one. | ||
defineProperties(FinalizationRegistry.prototype, { | ||
constructor: { value: InertFinalizationRegistry }, | ||
}); | ||
|
||
harden(FinalizationRegistry); | ||
|
||
export { FinalizationRegistry }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.