"use strict"; const util = require("util"); const errors = require("../errors"); const createWrapper = require("../util/function-wrapper"); const getValueType = require("../util/get-value-type"); let proto = { _source: null, set: null, size: 0, [Symbol.iterator]: createWrapper(Symbol.iterator), [util.inspect.custom]: function () { return this.valueOf(); }, clear: function () { this._source.clear(); this.size = 0; }, entries: createWrapper("entries"), forEach: createWrapper("forEach"), get: createWrapper("get"), has: createWrapper("has"), keys: createWrapper("keys"), values: createWrapper("values"), toString: createWrapper("toString"), valueOf: createWrapper("valueOf"), delete: function (key) { let deleted = this._source.delete(key); this.size = this._source.size; if (deleted === false) { throw new errors.ValidationError("Tried to delete non-existent key from guarded map", { key: key, nap: this._source }); } } }; module.exports = function createGuardedMap(map, valueGuard, keyGuard, parent) { function generateMapSignatureError() { let wantedSignature = { _guardedCollectionType: "map", _keyType: keyGuard._rule, _itemType: valueGuard._rule }; return new errors.ValidationError(`Expected a Map or ${getValueType(wantedSignature)}, got ${getValueType(map)} instead`); } if (map._guardedCollectionType === "map") { if (keyGuard === map._keyType && valueGuard === map._itemType) { return map; } else { throw generateMapSignatureError(); } } else if (map instanceof Map) { function check(key, value) { let keyGuardResult = keyGuard.call(parent, key); let valueGuardResult = valueGuard.call(parent, value); if (keyGuardResult === true && valueGuardResult === true) { return true; } else if (keyGuardResult !== true) { throw keyGuardResult; } else { throw valueGuardResult; } } for (let [key, value] of map.entries()) { check(key, value); } return Object.assign(Object.create(proto), { _source: map, _guardedCollectionType: "map", _itemType: valueGuard, _keyType: keyGuard, set: function (key, value) { if (check(key, value) === true) { this._source.set(key, value); this.size = this._source.size; } } }); } else { throw generateMapSignatureError(); } };