You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

88 lines
2.1 KiB
JavaScript

"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,
description: null,
size: 0,
add: null,
[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"), /* FIXME: Prevent mutation from the third argument to forEach (which is the original set); maybe also needed for Map? */
has: createWrapper("has"),
keys: createWrapper("keys"),
values: createWrapper("values"),
toString: createWrapper("toString"),
valueOf: createWrapper("valueOf"),
delete: function (value) {
let deleted = this._source.delete(value);
this.size = this._source.size;
if (deleted === false) {
throw new errors.ValidationError("Tried to delete non-existent value from guarded set", {
value: value,
set: this._source
});
}
}
};
module.exports = function createGuardedSet(set, guard, _, parent) {
function generateSetSignatureError() {
let wantedSignature = {
_guardedCollectionType: "set",
_itemType: guard._rule
};
return new errors.ValidationError(`Expected a Set or ${getValueType(wantedSignature)}, got ${getValueType(set)} instead`);
}
if (set._guardedCollectionType === "set") {
if (guard === set._itemType) {
return set;
} else {
throw generateSetSignatureError();
}
} else if (set instanceof Set) {
function check(value) {
let guardResult = guard.call(parent, value);
if (guardResult === true) {
return true;
} else {
throw guardResult;
}
}
for (let value of set.values()) {
check(value);
}
return Object.assign(Object.create(proto), {
_source: set,
_guardedCollectionType: "set",
_itemType: guard,
add: function (value) {
if (check(value) === true) {
this._source.add(value);
this.size = this._source.size;
}
}
});
} else {
throw generateSetSignatureError();
}
};