Skip to content

Instantly share code, notes, and snippets.

@Raynos
Forked from Gozala/weak-map.js
Last active September 18, 2019 07:49
Show Gist options
  • Star 15 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Raynos/1638059 to your computer and use it in GitHub Desktop.
Save Raynos/1638059 to your computer and use it in GitHub Desktop.
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)
}
}
}())
@FritsvanCampen
Copy link

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.

@Raynos
Copy link
Author

Raynos commented Mar 24, 2014

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