Skip to content

Instantly share code, notes, and snippets.



Forked from Gozala/weak-map.js
Last active Sep 18, 2019
What would you like to do?
Harmony WeakMap shim for ES5
// Original - @Gozola. This is a reimplemented version (with a few bug fixes).
window.WeakMap = window.WeakMap || (function () {
var privates = Name()
return {
get: function (key, fallback) {
var store = privates(key)
return store.hasOwnProperty("value") ?
store.value : fallback
set: function (key, value) {
privates(key).value = value
has: function(key) {
return "value" in privates(key)
"delete": function (key) {
return delete privates(key).value
function namespace(obj, key) {
var store = { identity: key },
valueOf = obj.valueOf
Object.defineProperty(obj, "valueOf", {
value: function (value) {
return value !== key ?
valueOf.apply(this, arguments) : store
writable: true
return store
function Name() {
var key = {}
return function (obj) {
var store = obj.valueOf(key)
return store && store.identity === key ?
store : namespace(obj, key)

This comment has been minimized.

Copy link

@Krinkle Krinkle commented Oct 10, 2012

        get: function (key, fallback) {
            return privates(key).value || fallback

This fails in case of false-y values. As documented values can be anything, including (but not limited to) objects, functionss, and undefined.

var foo = {};
wm.set(foo, false);
wm.set(foo, null);
wm.set(foo, undefined);
wm.set(foo, 0);
wm.set(foo, '');

// For all of these, the below returns the default value instead of the stored value:
wm.get(foo, 'default for unset properties');


        get: function (key, fallback) {
            var store = privates(key);
            return store.hasOwnProperty('value') ? store.value : fallback;

This comment has been minimized.

Copy link

@FritsvanCampen FritsvanCampen commented May 3, 2013

There is a (minor) bug in this implementation. It is possible to craft a value that will return a value for wm.get even though it's not in the WeakMap. A value that looks like this:

crafted_value = {
    "valueOf": function () {
        return { "value": "some value" };

wm.get(crafted_value, "some other value"); will return "some value" instead.

You can fix this in many different ways but they all boil down to the same thing: the value that you get from the store must be associated with the identity of the WeakMap.

My solution:

Construct your store like this: (line 21)

var store = {
    identity: key

And check like this: (line 38)

return store && store.identity === key ? store : namespace(obj, key)

You need the truethy check on store to avoid bugs with 'strange' implementations of valueOf that return undefined. store !== undefined also works and might be better.


This comment has been minimized.

Copy link
Owner Author

@Raynos Raynos commented Mar 24, 2014

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment