“use strict”;
var originalObject = Object
; var originalDefProp = Object.defineProperty; var originalCreate = Object.create;
function defProp(obj, name, value) {
if (originalDefProp) try { originalDefProp.call(originalObject, obj, name, { value: value }); } catch (definePropertyIsBrokenInIE8) { obj[name] = value; } else { obj[name] = value; }
}
// For functions that will be invoked using .call or .apply, we need to // define those methods on the function objects themselves, rather than // inheriting them from Function.prototype, so that a malicious or clumsy // third party cannot interfere with the functionality of this module by // redefining Function.prototype.call or .apply. function makeSafeToCall(fun) {
if (fun) { defProp(fun, "call", fun.call); defProp(fun, "apply", fun.apply); } return fun;
}
makeSafeToCall(originalDefProp); makeSafeToCall(originalCreate);
var hasOwn = makeSafeToCall(Object.prototype.hasOwnProperty); var numToStr = makeSafeToCall(Number.prototype.toString); var strSlice = makeSafeToCall(String.prototype.slice);
var cloner = function(){}; function create(prototype) {
if (originalCreate) { return originalCreate.call(originalObject, prototype); } cloner.prototype = prototype || null; return new cloner;
}
var rand = Math.random; var uniqueKeys = create(null);
function makeUniqueKey() {
// Collisions are highly unlikely, but this module is in the business of // making guarantees rather than safe bets. do var uniqueKey = internString(strSlice.call(numToStr.call(rand(), 36), 2)); while (hasOwn.call(uniqueKeys, uniqueKey)); return uniqueKeys[uniqueKey] = uniqueKey;
}
function internString(str) {
var obj = {}; obj[str] = true; return Object.keys(obj)[0];
}
// External users might find this function useful, but it is not necessary // for the typical use of this module. exports.makeUniqueKey = makeUniqueKey;
// Object.getOwnPropertyNames is the only way to enumerate non-enumerable // properties, so if we wrap it to ignore our secret keys, there should be // no way (except guessing) to access those properties. var originalGetOPNs = Object.getOwnPropertyNames; Object.getOwnPropertyNames = function getOwnPropertyNames(object) {
for (var names = originalGetOPNs(object), src = 0, dst = 0, len = names.length; src < len; ++src) { if (!hasOwn.call(uniqueKeys, names[src])) { if (src > dst) { names[dst] = names[src]; } ++dst; } } names.length = dst; return names;
};
function defaultCreatorFn(object) {
return create(null);
}
function makeAccessor(secretCreatorFn) {
var brand = makeUniqueKey(); var passkey = create(null); secretCreatorFn = secretCreatorFn || defaultCreatorFn; function register(object) { var secret; // Created lazily. function vault(key, forget) { // Only code that has access to the passkey can retrieve (or forget) // the secret object. if (key === passkey) { return forget ? secret = null : secret || (secret = secretCreatorFn(object)); } } defProp(object, brand, vault); } function accessor(object) { if (!hasOwn.call(object, brand)) register(object); return object[brand](passkey); } accessor.forget = function(object) { if (hasOwn.call(object, brand)) object[brand](passkey, true); }; return accessor;
}
exports.makeAccessor = makeAccessor;