webpack-subresource-integrity
Version:
Webpack plugin for enabling Subresource Integrity
122 lines • 4.65 kB
JavaScript
"use strict";
/**
* Copyright (c) 2015-present, Waysact Pty Ltd
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.createDAGfromGraph = void 0;
const util_1 = require("./util");
class SccVerticesBuilder {
constructor({ vertices, edges }) {
this.vertexMetadata = new Map();
this.stack = [];
this.index = 0;
this.stronglyConnectedComponents = new Set();
this.vertices = vertices;
this.edges = edges;
for (const vertex of this.vertices) {
if (!this.vertexMetadata.has(vertex)) {
this.strongConnect(vertex);
}
}
}
build() {
return this.stronglyConnectedComponents;
}
strongConnectChildren(vertex, vertexData) {
var _a;
for (const child of (_a = this.edges.get(vertex)) !== null && _a !== void 0 ? _a : []) {
this.strongConnectChild(child, vertexData);
}
}
strongConnectChild(child, vertexData) {
const childData = this.vertexMetadata.get(child);
if ((childData === null || childData === void 0 ? void 0 : childData.onstack) === false) {
return;
}
vertexData.lowlink = Math.min(vertexData.lowlink, childData
? // Child is in stack and hence in the current SCC
// If child is not on stack, then (vertex, child) is an edge pointing to an SCC already found and must be ignored
// Note: The next line may look odd - but is correct.
// It says childData.index not childData.lowlink; that is deliberate and from the original paper
childData.index
: // Child has not yet been visited; recurse on it
this.strongConnect(child).lowlink);
}
strongConnect(vertex) {
// Set the depth index for v to the smallest unused index
const vertexData = {
index: this.index,
lowlink: this.index,
onstack: true,
};
this.vertexMetadata.set(vertex, vertexData);
this.index++;
this.stack.push(vertex);
this.strongConnectChildren(vertex, vertexData);
// If vertex is a root node, pop the stack and generate an SCC
if (vertexData.index === vertexData.lowlink) {
const newStronglyConnectedComponent = { nodes: new Set() };
let currentNode;
do {
currentNode = this.stack.pop();
(0, util_1.assert)(currentNode, "Working stack was empty");
const metadata = this.vertexMetadata.get(currentNode);
(0, util_1.assert)(metadata, "All nodes on stack should have metadata");
metadata.onstack = false;
newStronglyConnectedComponent.nodes.add(currentNode);
} while (currentNode !== vertex);
this.stronglyConnectedComponents.add(newStronglyConnectedComponent);
}
return vertexData;
}
}
class SccEdgesBuilder {
constructor(vertices, edges) {
this.vertexToSCCMap = new Map();
this.vertices = vertices;
this.edges = edges;
for (const scc of this.vertices) {
for (const vertex of scc.nodes) {
this.vertexToSCCMap.set(vertex, scc);
}
}
}
build() {
// Now that all SCCs have been identified, rebuild the graph
const sccEdges = new Map();
for (const scc of this.vertices) {
sccEdges.set(scc, this.getChildSCCNodes(scc));
}
return sccEdges;
}
getChildSCCNodes(scc) {
const childSCCNodes = new Set();
scc.nodes.forEach((vertex) => {
const edge = this.edges.get(vertex);
if (!edge) {
return;
}
edge.forEach((childVertex) => {
const childScc = this.vertexToSCCMap.get(childVertex);
if (childScc && childScc !== scc) {
childSCCNodes.add(childScc);
}
});
});
return childSCCNodes;
}
}
/**
* Tarjan's strongly connected components algorithm
* https://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm
*/
function createDAGfromGraph(graph) {
const vertices = new SccVerticesBuilder(graph).build();
const edges = new SccEdgesBuilder(vertices, graph.edges).build();
return { vertices, edges };
}
exports.createDAGfromGraph = createDAGfromGraph;
//# sourceMappingURL=scc.js.map