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
88 lines
2.1 KiB
JavaScript
6 years ago
|
"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();
|
||
|
}
|
||
|
};
|