| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191 | 
							- 'use strict';
 
- const Ref = require('./ref');
 
- const internals = {};
 
- internals.extendedCheckForValue = function (value, insensitive) {
 
-     const valueType = typeof value;
 
-     if (valueType === 'object') {
 
-         if (value instanceof Date) {
 
-             return (item) => {
 
-                 return item instanceof Date && value.getTime() === item.getTime();
 
-             };
 
-         }
 
-         if (Buffer.isBuffer(value)) {
 
-             return (item) => {
 
-                 return Buffer.isBuffer(item) && value.length === item.length && value.toString('binary') === item.toString('binary');
 
-             };
 
-         }
 
-     }
 
-     else if (insensitive && valueType === 'string') {
 
-         const lowercaseValue = value.toLowerCase();
 
-         return (item) => {
 
-             return typeof item === 'string' && lowercaseValue === item.toLowerCase();
 
-         };
 
-     }
 
-     return null;
 
- };
 
- module.exports = class InternalSet {
 
-     constructor(from) {
 
-         this._set = new Set(from);
 
-         this._hasRef = false;
 
-     }
 
-     add(value, refs) {
 
-         const isRef = Ref.isRef(value);
 
-         if (!isRef && this.has(value, null, null, false)) {
 
-             return this;
 
-         }
 
-         if (refs !== undefined) { // If it's a merge, we don't have any refs
 
-             Ref.push(refs, value);
 
-         }
 
-         this._set.add(value);
 
-         this._hasRef |= isRef;
 
-         return this;
 
-     }
 
-     merge(add, remove) {
 
-         for (const item of add._set) {
 
-             this.add(item);
 
-         }
 
-         for (const item of remove._set) {
 
-             this.remove(item);
 
-         }
 
-         return this;
 
-     }
 
-     remove(value) {
 
-         this._set.delete(value);
 
-         return this;
 
-     }
 
-     has(value, state, options, insensitive) {
 
-         return !!this.get(value, state, options, insensitive);
 
-     }
 
-     get(value, state, options, insensitive) {
 
-         if (!this._set.size) {
 
-             return false;
 
-         }
 
-         const hasValue = this._set.has(value);
 
-         if (hasValue) {
 
-             return { value };
 
-         }
 
-         const extendedCheck = internals.extendedCheckForValue(value, insensitive);
 
-         if (!extendedCheck) {
 
-             if (state && this._hasRef) {
 
-                 for (let item of this._set) {
 
-                     if (Ref.isRef(item)) {
 
-                         item = [].concat(item(state.reference || state.parent, options));
 
-                         const found = item.indexOf(value);
 
-                         if (found >= 0) {
 
-                             return { value: item[found] };
 
-                         }
 
-                     }
 
-                 }
 
-             }
 
-             return false;
 
-         }
 
-         return this._has(value, state, options, extendedCheck);
 
-     }
 
-     _has(value, state, options, check) {
 
-         const checkRef = !!(state && this._hasRef);
 
-         const isReallyEqual = function (item) {
 
-             if (value === item) {
 
-                 return true;
 
-             }
 
-             return check(item);
 
-         };
 
-         for (let item of this._set) {
 
-             if (checkRef && Ref.isRef(item)) { // Only resolve references if there is a state, otherwise it's a merge
 
-                 item = item(state.reference || state.parent, options);
 
-                 if (Array.isArray(item)) {
 
-                     const found = item.findIndex(isReallyEqual);
 
-                     if (found >= 0) {
 
-                         return {
 
-                             value: item[found]
 
-                         };
 
-                     }
 
-                     continue;
 
-                 }
 
-             }
 
-             if (isReallyEqual(item)) {
 
-                 return {
 
-                     value: item
 
-                 };
 
-             }
 
-         }
 
-         return false;
 
-     }
 
-     values(options) {
 
-         if (options && options.stripUndefined) {
 
-             const values = [];
 
-             for (const item of this._set) {
 
-                 if (item !== undefined) {
 
-                     values.push(item);
 
-                 }
 
-             }
 
-             return values;
 
-         }
 
-         return Array.from(this._set);
 
-     }
 
-     slice() {
 
-         const set = new InternalSet(this._set);
 
-         set._hasRef = this._hasRef;
 
-         return set;
 
-     }
 
-     concat(source) {
 
-         const set = new InternalSet([...this._set, ...source._set]);
 
-         set._hasRef = !!(this._hasRef | source._hasRef);
 
-         return set;
 
-     }
 
- };
 
 
  |