webpack
Version:
Packs CommonJs/AMD modules for the browser. Allows to split your codebase into multiple bundles, which can be loaded on demand. Support loaders to preprocess files, i.e. json, jsx, es7, css, less, ... and your custom stuff.
141 lines (128 loc) • 3.24 kB
JavaScript
"use strict";
/**
* A subset of Set that offers sorting functionality
* @template T item type in set
* @extends {Set<T>}
*/
class SortableSet extends Set {
/**
* Create a new sortable set
* @param {Iterable<T>=} initialIterable The initial iterable value
* @typedef {function(T, T): number} SortFunction
* @param {SortFunction=} defaultSort Default sorting function
*/
constructor(initialIterable, defaultSort) {
super(initialIterable);
/** @private @type {function(T, T): number}} */
this._sortFn = defaultSort;
/** @private @type {function(T, T): number} | null} */
this._lastActiveSortFn = null;
/** @private @type {Map<Function, T[]> | undefined} */
this._cache = undefined;
/** @private @type {Map<Function, T[]|string|number> | undefined} */
this._cacheOrderIndependent = undefined;
}
/**
* @param {T} value value to add to set
* @returns {this} returns itself
*/
add(value) {
this._lastActiveSortFn = null;
this._invalidateCache();
this._invalidateOrderedCache();
super.add(value);
return this;
}
/**
* @param {T} value value to delete
* @returns {boolean} true if value existed in set, false otherwise
*/
delete(value) {
this._invalidateCache();
this._invalidateOrderedCache();
return super.delete(value);
}
/**
* @returns {void}
*/
clear() {
this._invalidateCache();
this._invalidateOrderedCache();
return super.clear();
}
/**
* Sort with a comparer function
* @param {SortFunction} sortFn Sorting comparer function
* @returns {void}
*/
sortWith(sortFn) {
if (this.size <= 1 || sortFn === this._lastActiveSortFn) {
// already sorted - nothing to do
return;
}
const sortedArray = Array.from(this).sort(sortFn);
super.clear();
for (let i = 0; i < sortedArray.length; i += 1) {
super.add(sortedArray[i]);
}
this._lastActiveSortFn = sortFn;
this._invalidateCache();
}
sort() {
this.sortWith(this._sortFn);
}
/**
* Get data from cache
* @param {function(SortableSet<T>): T[]} fn function to calculate value
* @returns {T[]} returns result of fn(this), cached until set changes
*/
getFromCache(fn) {
if (this._cache === undefined) {
this._cache = new Map();
} else {
const data = this._cache.get(fn);
if (data !== undefined) {
return data;
}
}
const newData = fn(this);
this._cache.set(fn, newData);
return newData;
}
/**
* @param {function(SortableSet<T>): string|number|T[]} fn function to calculate value
* @returns {any} returns result of fn(this), cached until set changes
*/
getFromUnorderedCache(fn) {
if (this._cacheOrderIndependent === undefined) {
this._cacheOrderIndependent = new Map();
} else {
const data = this._cacheOrderIndependent.get(fn);
if (data !== undefined) {
return data;
}
}
const newData = fn(this);
this._cacheOrderIndependent.set(fn, newData);
return newData;
}
/**
* @private
* @returns {void}
*/
_invalidateCache() {
if (this._cache !== undefined) {
this._cache.clear();
}
}
/**
* @private
* @returns {void}
*/
_invalidateOrderedCache() {
if (this._cacheOrderIndependent !== undefined) {
this._cacheOrderIndependent.clear();
}
}
}
module.exports = SortableSet;