New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@syntest/cfg

Package Overview
Dependencies
Maintainers
4
Versions
16
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@syntest/cfg - npm Package Compare versions

Comparing version 0.4.1-beta.3 to 0.5.0-beta.0

5

dist/lib/algorithms/edgeContraction.d.ts

@@ -0,1 +1,2 @@

import { Result } from "@syntest/diagnostics";
import { ControlFlowProgram } from "../ControlFlowProgram";

@@ -13,4 +14,4 @@ import { ContractedControlFlowGraph } from "../graph/ContractedControlFlowGraph";

*/
export declare function edgeContraction(controlFlowGraph: ControlFlowGraph): ContractedControlFlowGraph;
export declare function contractControlFlowProgram(program: ControlFlowProgram): ControlFlowProgram;
export declare function edgeContraction(controlFlowGraph: ControlFlowGraph): Result<ContractedControlFlowGraph>;
export declare function contractControlFlowProgram(program: ControlFlowProgram): Result<ControlFlowProgram>;
//# sourceMappingURL=edgeContraction.d.ts.map

101

dist/lib/algorithms/edgeContraction.js

@@ -21,4 +21,3 @@ "use strict";

*/
const logging_1 = require("@syntest/logging");
const diagnostics_1 = require("../diagnostics");
const diagnostics_1 = require("@syntest/diagnostics");
const ContractedControlFlowGraph_1 = require("../graph/ContractedControlFlowGraph");

@@ -41,6 +40,4 @@ const ControlFlowGraph_1 = require("../graph/ControlFlowGraph");

const nodeMapping = new Map();
let changed = false;
// Perform edge contraction until no more changes are made
do {
changed = false;
if (controlFlowGraph.nodes.size === 2) {

@@ -50,3 +47,3 @@ // Only entry and exit nodes left, so we can stop

}
bfs(controlFlowGraph, (edge) => {
const edge = bfs(controlFlowGraph, (edge) => {
return (controlFlowGraph.getOutgoingEdges(edge.source).length === 1 &&

@@ -60,13 +57,19 @@ controlFlowGraph.getIncomingEdges(edge.target).length === 1 &&

edge.target !== controlFlowGraph.errorExit.id);
}, (edge) => {
controlFlowGraph = mergeNodes(controlFlowGraph, edge.source, edge.target);
if (nodeMapping.has(edge.source)) {
nodeMapping.get(edge.source).push(edge.target);
}
else {
nodeMapping.set(edge.source, [edge.source, edge.target]);
}
changed = true;
});
} while (changed);
if (edge === undefined) {
// done
break;
}
const result = mergeNodes(controlFlowGraph, edge.source, edge.target);
if ((0, diagnostics_1.isFailure)(result))
return result;
controlFlowGraph = (0, diagnostics_1.unwrap)(result);
if (nodeMapping.has(edge.source)) {
nodeMapping.get(edge.source).push(edge.target);
}
else {
nodeMapping.set(edge.source, [edge.source, edge.target]);
}
// eslint-disable-next-line no-constant-condition
} while (true);
// safety check

@@ -77,7 +80,8 @@ for (const edge of controlFlowGraph.edges) {

if (outgoingFromSource.length > 1 && incomingToTarget.length > 1) {
(0, logging_1.getLogger)("edgeContration").warn((0, diagnostics_1.shouldNeverHappen)(`Missing placeholder node: \n${edge.source}\n${edge.target}`));
// throw new Error(shouldNeverHappen(`Missing placeholder node: \n${edge.source}\n${edge.target}`))
return (0, diagnostics_1.failure)(new diagnostics_1.IllegalStateError("Missing placeholder node between 2 nodes", {
context: { node1: edge.source, node2: edge.target },
}));
}
}
return new ContractedControlFlowGraph_1.ContractedControlFlowGraph(controlFlowGraph.entry, controlFlowGraph.successExit, controlFlowGraph.errorExit, controlFlowGraph.nodes, controlFlowGraph.edges, original, nodeMapping);
return (0, diagnostics_1.success)(new ContractedControlFlowGraph_1.ContractedControlFlowGraph(controlFlowGraph.entry, controlFlowGraph.successExit, controlFlowGraph.errorExit, controlFlowGraph.nodes, controlFlowGraph.edges, original, nodeMapping));
}

@@ -87,13 +91,22 @@ exports.edgeContraction = edgeContraction;

function contractControlFlowProgram(program) {
program.graph = edgeContraction(program.graph);
const result = edgeContraction(program.graph);
if ((0, diagnostics_1.isFailure)(result))
return result;
program.graph = (0, diagnostics_1.unwrap)(result);
for (const f of program.functions) {
f.graph = edgeContraction(f.graph);
const result = edgeContraction(f.graph);
if ((0, diagnostics_1.isFailure)(result))
return result;
f.graph = (0, diagnostics_1.unwrap)(result);
}
return program;
return (0, diagnostics_1.success)(program);
}
exports.contractControlFlowProgram = contractControlFlowProgram;
function bfs(controlFlowGraph, condition, callback) {
/**
* Perform BFS to find a node with only one incoming and one outgoing edge.
*/
/**
* BFS to find an edge in the graph that matches the provided condition
* @param controlFlowGraph the graph to search in
* @param condition the condition to match
* @returns the matching edge
*/
function bfs(controlFlowGraph, condition) {
const queue = [];

@@ -109,17 +122,17 @@ const visited = new Set();

if (condition(edge)) {
callback(edge);
break;
return edge;
}
queue.push(...controlFlowGraph.getOutgoingEdges(edge.target));
}
return undefined;
}
function beforeGuards(controlFlowGraph, source, target) {
if (controlFlowGraph.getOutgoingEdges(source).length !== 1) {
throw new Error((0, diagnostics_1.tooManyOutgoing)(source));
throw new diagnostics_1.IllegalStateError("Cannot merge nodes, node has more than one outgoing edge", { context: { node: source } });
}
if (controlFlowGraph.getIncomingEdges(target).length !== 1) {
throw new Error((0, diagnostics_1.tooManyIncoming)(target));
throw new diagnostics_1.IllegalStateError("Cannot merge nodes, node has more than one incoming edge", { context: { node: target } });
}
if (controlFlowGraph.getOutgoingEdges(source)[0].target !== target) {
throw new Error((0, diagnostics_1.notDirectlyConnected)(source, target));
throw new diagnostics_1.IllegalStateError("Cannot merge nodes, nodes are not directly connected", { context: { node1: source, node2: target } });
}

@@ -130,3 +143,3 @@ const isEntry = source === controlFlowGraph.entry.id;

if (isEntry && (isSuccessExit || isErrorExit)) {
throw new Error((0, diagnostics_1.cannotMergeEntryAndExit)());
throw new diagnostics_1.IllegalStateError("Cannot merge entry and exit nodes");
}

@@ -136,6 +149,18 @@ }

if (newNodes.size !== controlFlowGraph.nodes.size - 1) {
throw new Error((0, diagnostics_1.exactlyOneNodeShouldBeRemoved)(source, target, newNodes.size - controlFlowGraph.nodes.size));
throw new diagnostics_1.IllegalStateError("Exactly one node should be removed when merging nodes", {
context: {
mergeNode1: source,
mergeNode2: target,
removedAmount: newNodes.size - controlFlowGraph.nodes.size,
},
});
}
if (newEdges.length !== controlFlowGraph.edges.length - 1) {
throw new Error((0, diagnostics_1.exactlyOneEdgeShouldBeRemoved)(source, target, newNodes.size - controlFlowGraph.nodes.size));
throw new diagnostics_1.IllegalStateError("Exactly one edge should be removed when merging nodes", {
context: {
mergeNode1: source,
mergeNode2: target,
removedAmount: newEdges.length - controlFlowGraph.edges.length,
},
});
}

@@ -157,3 +182,9 @@ }

if (removedEdges.length !== 1) {
throw new Error((0, diagnostics_1.exactlyOneEdgeShouldBeRemoved)(source, target, removedEdges.length));
return (0, diagnostics_1.failure)(new diagnostics_1.IllegalStateError("Exactly one edge should be removed when merging nodes", {
context: {
mergeNode1: source,
mergeNode2: target,
removedAmount: removedEdges.length,
},
}));
}

@@ -174,4 +205,4 @@ const newEdges = controlFlowGraph.edges

afterGuards(newNodes, newEdges, controlFlowGraph, source, target);
return new ControlFlowGraph_1.ControlFlowGraph(controlFlowGraph.entry, controlFlowGraph.successExit, controlFlowGraph.errorExit, newNodes, newEdges);
return (0, diagnostics_1.success)(new ControlFlowGraph_1.ControlFlowGraph(controlFlowGraph.entry, controlFlowGraph.successExit, controlFlowGraph.errorExit, newNodes, newEdges));
}
//# sourceMappingURL=edgeContraction.js.map

@@ -21,3 +21,3 @@ "use strict";

exports.ContractedControlFlowGraph = void 0;
const diagnostics_1 = require("../diagnostics");
const diagnostics_1 = require("@syntest/diagnostics");
const ControlFlowGraph_1 = require("./ControlFlowGraph");

@@ -37,3 +37,5 @@ /**

if (this._reverseNodeMapping.has(node))
throw new Error((0, diagnostics_1.duplicateNodeInMappping)());
throw new diagnostics_1.IllegalArgumentError("Duplicate node found in mapping", {
context: { node: node },
});
this._reverseNodeMapping.set(node, key);

@@ -61,3 +63,3 @@ }

if (!this._reverseNodeMapping.has(node)) {
throw new Error((0, diagnostics_1.nodeNotFoundInMapping)(node));
return undefined;
}

@@ -68,3 +70,3 @@ return this._reverseNodeMapping.get(node);

if (!this._nodeMapping.has(node)) {
throw new Error((0, diagnostics_1.nodeNotFoundInMapping)(node));
return undefined;
}

@@ -71,0 +73,0 @@ return this._nodeMapping.get(node);

{
"name": "@syntest/cfg",
"version": "0.4.1-beta.3",
"version": "0.5.0-beta.0",
"description": "SynTest library for control flow graphs",

@@ -51,3 +51,4 @@ "keywords": [

"dependencies": {
"@syntest/logging": "^0.2.0-beta.1",
"@syntest/diagnostics": "^0.1.0-beta.0",
"@syntest/logging": "^0.2.0-beta.2",
"lodash.clonedeep": "^4.5.0"

@@ -64,3 +65,3 @@ },

},
"gitHead": "62fc32cd877d4f37e335e5e21027b0913d7bcb75"
"gitHead": "3f6b9612c030ffc79d5e79c5c1c126ca816a87a6"
}

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc