Skip to content

Instantly share code, notes, and snippets.

@corasaurus-hex
Last active August 15, 2022 04:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save corasaurus-hex/6d3dfec911d5a4adeaa3f59d77e518a5 to your computer and use it in GitHub Desktop.
Save corasaurus-hex/6d3dfec911d5a4adeaa3f59d77e518a5 to your computer and use it in GitHub Desktop.
class ProtocolMap {
constructor() {
this.impls = new Map();
this.cache = new Map();
}
get(object) {
let proto = Object.getPrototypeOf(object);
let impl = this.cache.get(proto);
if (impl) {
return impl;
}
while (proto !== null) {
impl = this.impls.get(proto);
if (impl) {
this.cache.set(Object.getPrototypeOf(object), impl);
return impl;
}
proto = Object.getPrototypeOf(proto);
}
return undefined;
}
set(prototype, impl) {
this.impls.set(prototype, impl);
this.cache = new Map([[prototype, impl]]);
}
call(object, ...args) {
return this.get(object)(object, ...args);
}
}
const protocols = new Map();
protocols.set(Symbol.for('IGet'), new ProtocolMap());
protocols.set(Symbol.for('ISet'), new ProtocolMap());
const IGet = protocols.get(Symbol.for('IGet'));
const ISet = protocols.get(Symbol.for('ISet'));
IGet.set(Map.prototype, (m, k) => m.get(k));
IGet.set(Object.prototype, (m, k) => m[k]);
ISet.set(Map.prototype, (m, k, v) => m.set(k, v));
ISet.set(Object.prototype, (m, k, v) => m[k] = v);
class FooMap extends Map {}
const a = new FooMap();
const b = {};
ISet.call(a, "foo", "bar")
ISet.call(b, "baz", "qux")
console.log(IGet.call(a, "foo"));
console.log(IGet.call(b, "baz"));
// ** OUTPUT **
// bar
// qux
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment