146 lines
4.4 KiB
JavaScript
Executable file
146 lines
4.4 KiB
JavaScript
Executable file
"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;
|