“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. defProp(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;

}

defProp(exports, “makeAccessor”, makeAccessor);