"use strict"; const generateValidator = require("./generate-validator"); const guardedSet = require("./guarded-collections/set"); const guardedMap = require("./guarded-collections/map"); const guardedArray = require("./guarded-collections/array"); module.exports = function generateDescriptor(rule, key, allowSlot = false) { if (rule._isTypeRule === true) { let validator = generateValidator(rule, key); if (rule._collectionType != null) { let guardedCollectionFactory; if (rule._collectionType === "set") { guardedCollectionFactory = guardedSet; } else if (rule._collectionType === "map") { guardedCollectionFactory = guardedMap; } else if (rule._collectionType === "array") { guardedCollectionFactory = guardedArray; } else { throw new Error(`Unknown collection type: ${rule._collectionType}`); } let valueGuard = generateValidator(rule._itemType); let keyGuard = (rule._keyType != null) ? generateValidator(rule._keyType) : null; return [key, { enumerable: true, get: function () { return this._data[key]; }, set: function (value) { if (allowSlot && value != null && value._isSlotRule === true) { this._data[key] = value; } else { let validationResult = validator.call(this, value); if (validationResult === true) { if (value == null) { this._data[key] = value; } else { this._data[key] = guardedCollectionFactory(value, valueGuard, keyGuard, this); } } else if (validationResult._default !== undefined) { this._data[key] = guardedCollectionFactory(validationResult._default, valueGuard, keyGuard, this); } else { throw validationResult; } } } }]; } else { return [key, { enumerable: true, get: function () { return this._data[key]; }, set: function (value) { if (allowSlot && value != null && value._isSlotRule === true) { this._data[key] = value; } else { let validationResult = validator.call(this, value); if (validationResult === true) { this._data[key] = value; } else if (validationResult._default !== undefined) { this._data[key] = validationResult._default; } else { throw validationResult; } } } }]; } } else { /* TODO: Does this cause a slowdown compared to merging in these props with Object.assign later? */ return [key, { value: rule }]; } };