Last active
January 13, 2022 14:17
-
-
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.
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
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