|
|
|
"use strict";
|
|
|
|
|
|
|
|
const generateValidator = require("./generate-validator");
|
|
|
|
const guardedSet = require("./guarded-collections/set");
|
|
|
|
const guardedMap = require("./guarded-collections/map");
|
|
|
|
|
|
|
|
module.exports = function generateDescriptor(rule, key, allowSlot = false, registry) {
|
|
|
|
if (rule._isTypeRule === true) {
|
|
|
|
let validator = generateValidator(rule, key, registry);
|
|
|
|
|
|
|
|
if (rule._collectionType != null) {
|
|
|
|
let guardedCollectionFactory;
|
|
|
|
|
|
|
|
if (rule._collectionType === "set") {
|
|
|
|
guardedCollectionFactory = guardedSet;
|
|
|
|
} else if (rule._collectionType === "map") {
|
|
|
|
guardedCollectionFactory = guardedMap;
|
|
|
|
} else {
|
|
|
|
throw new Error(`Unknown collection type: ${rule._collectionType}`);
|
|
|
|
}
|
|
|
|
|
|
|
|
let valueGuard = generateValidator(rule._itemType, undefined, registry);
|
|
|
|
let keyGuard = (rule._keyType != null) ? generateValidator(rule._keyType, undefined, registry) : 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
|
|
|
|
}];
|
|
|
|
}
|
|
|
|
};
|