text: 'use strict';
  var $         = require('./$')
    , safe      = require('./$.uid').safe
    , assert    = require('./$.assert')
    , forOf     = require('./$.for-of')
    , _has      = $.has
    , isObject  = $.isObject
    , hide      = $.hide
    , isExtensible = Object.isExtensible || isObject
    , id        = 0
    , ID        = safe('id')
    , WEAK      = safe('weak')
    , LEAK      = safe('leak')
    , method    = require('./$.array-methods')
    , find      = method(5)
    , findIndex = method(6);
  function findFrozen(store, key){
    return find(store.array, function(it){
      return it[0] === key;
    });
  }
  // fallback for frozen keys
  function leakStore(that){
    return that[LEAK] || hide(that, LEAK, {
      array: [],
      get: function(key){
        var entry = findFrozen(this, key);
        if(entry)return entry[1];
      },
      has: function(key){
        return !!findFrozen(this, key);
      },
      set: function(key, value){
        var entry = findFrozen(this, key);
        if(entry)entry[1] = value;
        else this.array.push([key, value]);
      },
      'delete': function(key){
        var index = findIndex(this.array, function(it){
          return it[0] === key;
        });
        if(~index)this.array.splice(index, 1);
        return !!~index;
      }
    })[LEAK];
  }
  
  module.exports = {
    getConstructor: function(NAME, IS_MAP, ADDER){
      function C(){
        $.set(assert.inst(this, C, NAME), ID, id++);
        var iterable = arguments[0];
        if(iterable != undefined)forOf(iterable, IS_MAP, this[ADDER], this);
      }
      require('./$.mix')(C.prototype, {
        // 23.3.3.2 WeakMap.prototype.delete(key)
        // 23.4.3.3 WeakSet.prototype.delete(value)
        'delete': function(key){
          if(!isObject(key))return false;
          if(!isExtensible(key))return leakStore(this)['delete'](key);
          return _has(key, WEAK) && _has(key[WEAK], this[ID]) && delete key[WEAK][this[ID]];
        },
        // 23.3.3.4 WeakMap.prototype.has(key)
        // 23.4.3.4 WeakSet.prototype.has(value)
        has: function has(key){
          if(!isObject(key))return false;
          if(!isExtensible(key))return leakStore(this).has(key);
          return _has(key, WEAK) && _has(key[WEAK], this[ID]);
        }
      });
      return C;
    },
    def: function(that, key, value){
      if(!isExtensible(assert.obj(key))){
        leakStore(that).set(key, value);
      } else {
        _has(key, WEAK) || hide(key, WEAK, {});
        key[WEAK][that[ID]] = value;
      } return that;
    },
    leakStore: leakStore,
    WEAK: WEAK,
    ID: ID
  };