Skip to content

Instantly share code, notes, and snippets.

@acutmore
Last active Nov 2, 2021
Embed
What would you like to do?
Proof-of-concept on how a userland library could provide record 'tagging'. Without direct support in the language.
/** Tag a record in an unforgeable way and without leaking memory */
class TaggedRecords {
#namespace;
/** @type {Map<Record, WeakRef<Record>>} */
#tagged = new Map();
#fr = new FinalizationRegistry(held => {
if (this.#tagged.get(held)?.deref() === void 0) {
this.#tagged.delete(held);
}
});
constructor(namespace = '') {
this.#namespace = Symbol(namespace);
}
create(obj) {
obj = #{...obj}; // do this only once
const key = {...obj, __tag__: this.#namespace };
let taggedR;
if (this.#tagged.has(key)) {
taggedR = this.#tagged.get(key).deref();
}
if (!taggedR) {
const fresh = Symbol();
taggedR = #{ ...obj, __tag__: fresh };
this.#fr.register(fresh, key); // Assumes symbols-as-weakmap keys - technique also applies for Box
this.#tagged.set(key, new WeakRef(taggedR));
}
return taggedR;
}
has(taggedRecord) {
const key = #{...taggedRecord, __tag__: this.#namespace };
return this.#tagged.has(key) && Object.is(this.#tagged.get(key).deref(), taggedRecord);
}
}
const tagA = new TaggedRecords('a');
const tagB = new TaggedRecords('b');
let r1 = tagA.create({ foo: 'bar' });
let r2 = tagA.create({ foo: 'bar' });
let r3 = tagB.create({ foo: 'bar' });
typeof r1; // 'record'
r1.foo; // 'bar'
r1 === r2; // true;
r1 === r3; // false
r1 === #{ foo: 'bar' }; // false
tagA.has(r1); // true
tagA.has(r2); // true
tagA.has(r3); // false
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment