/* */ '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; }); } 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(wrapper, NAME, IS_MAP, ADDER) { var C = wrapper(function(that, iterable) { $.set(assert.inst(that, C, NAME), ID, id++); if (iterable != undefined) forOf(iterable, IS_MAP, that[ADDER], that); }); require("./$.mix")(C.prototype, { '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]]; }, 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 };