"use strict"; /** * @license * Copyright Google LLC All Rights Reserved. * * Use of this source code is governed by an MIT-style license that can be * found in the LICENSE file at https://angular.io/license */ Object.defineProperty(exports, "__esModule", { value: true }); exports.PartiallyOrderedSet = exports.CircularDependencyFoundException = exports.DependencyNotFoundException = void 0; const exception_1 = require("../exception"); class DependencyNotFoundException extends exception_1.BaseException { constructor() { super('One of the dependencies is not part of the set.'); } } exports.DependencyNotFoundException = DependencyNotFoundException; class CircularDependencyFoundException extends exception_1.BaseException { constructor() { super('Circular dependencies found.'); } } exports.CircularDependencyFoundException = CircularDependencyFoundException; class PartiallyOrderedSet { constructor() { this._items = new Map(); } _checkCircularDependencies(item, deps) { if (deps.has(item)) { throw new CircularDependencyFoundException(); } deps.forEach((dep) => this._checkCircularDependencies(item, this._items.get(dep) || new Set())); } clear() { this._items.clear(); } has(item) { return this._items.has(item); } get size() { return this._items.size; } forEach(callbackfn, thisArg) { for (const x of this) { callbackfn.call(thisArg, x, x, this); } } /** * Returns an iterable of [v,v] pairs for every value `v` in the set. */ *entries() { for (const item of this) { yield [item, item]; } } /** * Despite its name, returns an iterable of the values in the set, */ keys() { return this.values(); } /** * Returns an iterable of values in the set. */ values() { return this[Symbol.iterator](); } add(item, deps = new Set()) { if (Array.isArray(deps)) { deps = new Set(deps); } // Verify item is not already in the set. if (this._items.has(item)) { const itemDeps = this._items.get(item) || new Set(); // If the dependency list is equal, just return, otherwise remove and keep going. let equal = true; for (const dep of deps) { if (!itemDeps.has(dep)) { equal = false; break; } } if (equal) { for (const dep of itemDeps) { if (!deps.has(dep)) { equal = false; break; } } } if (equal) { return this; } else { this._items.delete(item); } } // Verify all dependencies are part of the Set. for (const dep of deps) { if (!this._items.has(dep)) { throw new DependencyNotFoundException(); } } // Verify there's no dependency cycle. this._checkCircularDependencies(item, deps); this._items.set(item, new Set(deps)); return this; } delete(item) { if (!this._items.has(item)) { return false; } // Remove it from all dependencies if force == true. this._items.forEach((value) => value.delete(item)); return this._items.delete(item); } *[Symbol.iterator]() { const copy = new Map(this._items); for (const [key, value] of copy.entries()) { copy.set(key, new Set(value)); } while (copy.size > 0) { const run = []; // Take the first item without dependencies. for (const [item, deps] of copy.entries()) { if (deps.size == 0) { run.push(item); } } for (const item of run) { copy.forEach((s) => s.delete(item)); copy.delete(item); yield item; } if (run.length == 0) { // uh oh... throw new CircularDependencyFoundException(); } } } get [Symbol.toStringTag]() { return 'Set'; } } exports.PartiallyOrderedSet = PartiallyOrderedSet;