Skip to content

Instantly share code, notes, and snippets.

@acutmore
Last active January 13, 2022 14:17
Show Gist options
  • Save acutmore/8f16a8d4cf4b7b54c5956bd6eab05cfd to your computer and use it in GitHub Desktop.
Save acutmore/8f16a8d4cf4b7b54c5956bd6eab05cfd to your computer and use it in GitHub Desktop.
Pseudo implementation of supporting registered symbols in Weak{Ref, Set, Map} and FinalizationRegistry.
const wellKnownSymbols = Reflect.ownKeys(Symbol).map(k => Symbol[k]).filter(s => typeof s === 'symbol');
function eternalSymbol(s) {
return typeof s === 'symbol' && (Symbol.keyFor(s) !== undefined || wellKnownSymbols.includes(s));
}
/*
Assumes all symbol values are GC-allocated and can be stored in weak collections.
So to correcetly support registed-symbols (that might be otherwise unobservably collected as an optimisation)
implementations would need to ensure Weak{Map,Ref,Set} actually hold a strong ref to the registed symbol
while it is being held weakly to disable the now observable optimisation.
*/
class ModifiedWeakRef extends WeakRef {
#nativeStrongRef;
constructor(value) {
super(value);
if (eternalSymbol(value)) {
this.#nativeStrongRef = value;
}
}
}
class ModifiedFinalizationRegistry extends FinalizationRegistry {
register(target, heldValue, unregisterToken) {
if (eternalSymbol(target)) {
// still throw for the usual argument assertions that FinalizationRegistry::register has
super.__assertValidArguments(target, heldValue, unregisterToken);
// no need to actually register as the callback should never be called for this
return;
}
super.register(target, heldValue, unregisterToken);
}
}
class ModifiedWeakSet extends WeakSet {
#nativeStrongSet = new Set();
add(value) {
if (eternalSymbol(key)) {
this.#nativeStrongSet.add(key);
}
return super.add(key);
}
delete(value) {
this.#nativeStrongSet.delete(key);
return super.delete(key);
}
}
class ModifiedWeakMap extends WeakMap {
#nativeStrongSet = new Set();
set(key, value) {
if (eternalSymbol(key)) {
this.#nativeStrongSet.add(key);
}
return super.set(key, value);
}
delete(key) {
this.#nativeStrongSet.delete(key);
return super.delete(key);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment