Last active
July 30, 2018 02:26
-
-
Save dead-claudia/a8494868c4b193dfbf7139589f472ad8 to your computer and use it in GitHub Desktop.
Weak maps and weak sets in terms of private symbols
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 _wmSymbol = Symbol.private("wmSymbol") | |
const _wsSymbol = Symbol.private("wsSymbol") | |
const call = Function.call.bind(Function.call) | |
const hasOwn = Function.call.bind({}.hasOwnProperty) | |
const getOwn = Object.getOwnPropertyDescriptor | |
const TE = TypeError | |
const checkMapThisKey = makeChecker("WeakMap", "weak map", _wmSymbol) | |
const checkSetThisKey = makeChecker("WeakSet", "weak set", _wsSymbol) | |
function makeChecker(name, human, symbol) { | |
return (inst, key, method) => { | |
if (!hasOwn(inst, _symbol)) { | |
throw new TE( | |
"`" + name + ".prototype." + method + | |
"` called on incompatible receiver" | |
) | |
} | |
if (typeof key !== "object") { | |
throw new TE("Invalid value used as " + human + " key") | |
} | |
} | |
} | |
class WeakMap { | |
constructor(iter) { | |
this[_wmSymbol] = Symbol.private() | |
const set = this.set | |
for (const [key, value] of iter) call(set, this, key, value) | |
} | |
delete(key) { | |
checkMapThisKey(this, key, "delete") | |
return delete key[this[_wmSymbol]] | |
} | |
get(key) { | |
checkMapThisKey(this, key, "get") | |
const desc = getOwn(key, this[_wmSymbol]) | |
return desc != null ? desc.value : void 0 | |
} | |
has(key) { | |
checkMapThisKey(this, key, "has") | |
return hasOwn(key, this[_wmSymbol]) | |
} | |
set(key, value) { | |
checkMapThisKey(this, key, "set") | |
key[this[_wmSymbol]] = value | |
return this | |
} | |
} | |
class WeakSet { | |
constructor(iter) { | |
this[_wsSymbol] = Symbol.private() | |
const set = this.set | |
for (const item of iter) call(set, this, item) | |
} | |
delete(key) { | |
checkSetThisKey(this, key, "delete") | |
return delete key[this[_wsSymbol]] | |
} | |
has(key) { | |
checkSetThisKey(this, key, "has") | |
return hasOwn(key, this[_wsSymbol]) | |
} | |
add(key) { | |
checkSetThisKey(this, key, "add") | |
key[this[_wsSymbol]] = true | |
return this | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment