/* MIT License http://www.opensource.org/licenses/mit-license.php Author Tobias Koppers @sokra */ "use strict"; const util = require("util"); const TOMBSTONE = {}; const UNDEFINED_MARKER = {}; class StackedSetMap { constructor(parentStack) { this.stack = parentStack === undefined ? [] : parentStack.slice(); this.map = new Map(); this.stack.push(this.map); } add(item) { this.map.set(item, true); } set(item, value) { this.map.set(item, value === undefined ? UNDEFINED_MARKER : value); } delete(item) { if (this.stack.length > 1) { this.map.set(item, TOMBSTONE); } else { this.map.delete(item); } } has(item) { const topValue = this.map.get(item); if (topValue !== undefined) return topValue !== TOMBSTONE; if (this.stack.length > 1) { for (var i = this.stack.length - 2; i >= 0; i--) { const value = this.stack[i].get(item); if (value !== undefined) { this.map.set(item, value); return value !== TOMBSTONE; } } this.map.set(item, TOMBSTONE); } return false; } get(item) { const topValue = this.map.get(item); if (topValue !== undefined) { return topValue === TOMBSTONE || topValue === UNDEFINED_MARKER ? undefined : topValue; } if (this.stack.length > 1) { for (var i = this.stack.length - 2; i >= 0; i--) { const value = this.stack[i].get(item); if (value !== undefined) { this.map.set(item, value); return value === TOMBSTONE || value === UNDEFINED_MARKER ? undefined : value; } } this.map.set(item, TOMBSTONE); } return undefined; } _compress() { if (this.stack.length === 1) return; this.map = new Map(); for (const data of this.stack) { for (const pair of data) { if (pair[1] === TOMBSTONE) { this.map.delete(pair[0]); } else { this.map.set(pair[0], pair[1]); } } } this.stack = [this.map]; } asArray() { this._compress(); return Array.from(this.map.entries(), pair => pair[0]); } asSet() { return new Set(this.asArray()); } asPairArray() { this._compress(); return Array.from( this.map.entries(), pair => /** @type {[TODO, TODO]} */ (pair[1] === UNDEFINED_MARKER ? [pair[0], undefined] : pair) ); } asMap() { return new Map(this.asPairArray()); } get size() { this._compress(); return this.map.size; } createChild() { return new StackedSetMap(this.stack); } get length() { throw new Error("This is no longer an Array"); } set length(value) { throw new Error("This is no longer an Array"); } } // TODO remove in webpack 5 StackedSetMap.prototype.push = util.deprecate( /** * @deprecated * @this {StackedSetMap} * @param {any} item Item to add * @returns {void} */ function(item) { this.add(item); }, "This is no longer an Array: Use add instead." ); module.exports = StackedSetMap;