2
0
Lutz Roeder 4 жил өмнө
parent
commit
a0a466a805
2 өөрчлөгдсөн 145 нэмэгдсэн , 162 устгасан
  1. 141 158
      source/dagre.js
  2. 4 4
      source/view-grapher.js

+ 141 - 158
source/dagre.js

@@ -27,7 +27,7 @@ dagre.layout = (graph, options) => {
     const buildLayoutGraph = (graph) => {
         const g = new dagre.Graph({ multigraph: true, compound: true });
         g.setGraph(Object.assign({}, { ranksep: 50, edgesep: 20, nodesep: 50, rankdir: 'tb' }, graph.graph()));
-        for (const v of graph.nodes()) {
+        for (const v of graph.nodes().keys()) {
             const node = graph.node(v);
             g.setNode(v, {
                 width: node.width || 0,
@@ -89,7 +89,7 @@ dagre.layout = (graph, options) => {
         const util_asNonCompoundGraph = (g) => {
             const graph = new dagre.Graph({ multigraph: g.isMultigraph() });
             graph.setGraph(g.graph());
-            for (const v of g.nodes()) {
+            for (const v of g.nodes().keys()) {
                 if (g.children(v).length === 0) {
                     graph.setNode(v, g.node(v));
                 }
@@ -102,8 +102,8 @@ dagre.layout = (graph, options) => {
 
         const maxRank = (g) => {
             let rank = Number.NEGATIVE_INFINITY;
-            for (const v of g.nodes()) {
-                const x = g.node(v).rank;
+            for (const node of g.nodes().values()) {
+                const x = node.rank;
                 if (x !== undefined && x > rank) {
                     rank = x;
                 }
@@ -116,7 +116,7 @@ dagre.layout = (graph, options) => {
             const rank = maxRank(g);
             const length = rank === undefined ? 0 : rank + 1;
             const layering = Array.from(new Array(length), () => []);
-            for (const v of g.nodes()) {
+            for (const v of g.nodes().keys()) {
                 const node = g.node(v);
                 const rank = node.rank;
                 if (rank !== undefined) {
@@ -223,7 +223,7 @@ dagre.layout = (graph, options) => {
                         stack.delete(v);
                     }
                 };
-                for (const v of g.nodes()) {
+                for (const v of g.nodes().keys()) {
                     dfs(v);
                 }
                 return fas;
@@ -303,7 +303,7 @@ dagre.layout = (graph, options) => {
             const feasibleTree = (g) => {
                 const t = new dagre.Graph({ directed: false });
                 // Choose arbitrary node from which to start our tree
-                const start = g.nodes()[0];
+                const start = g.nodes().keys().next().value;
                 const size = g.nodeCount();
                 t.setNode(start, {});
                 let edge;
@@ -325,7 +325,7 @@ dagre.layout = (graph, options) => {
                 };
                 // Finds a maximal tree of tight edges and returns the number of nodes in the tree.
                 const tightTree = (t, g) => {
-                    const stack = t.nodes().reverse();
+                    const stack = Array.from(t.nodes().keys()).reverse();
                     while (stack.length > 0) {
                         const v = stack.pop();
                         for (const e of g.nodeEdges(v)) {
@@ -343,7 +343,7 @@ dagre.layout = (graph, options) => {
                 while (tightTree(t, g) < size) {
                     edge = findMinSlackEdge(t, g);
                     delta = t.hasNode(edge.v) ? slack(g, edge) : -slack(g, edge);
-                    for (const v of t.nodes()) {
+                    for (const v of t.nodes().keys()) {
                         g.node(v).rank += delta;
                     }
                 }
@@ -437,7 +437,7 @@ dagre.layout = (graph, options) => {
                 const simplify = (g) => {
                     const graph = new dagre.Graph();
                     graph.setGraph(g.graph());
-                    for (const v of g.nodes()) {
+                    for (const v of g.nodes().keys()) {
                         graph.setNode(v, g.node(v));
                     }
                     for (const e of g.edges()) {
@@ -454,7 +454,7 @@ dagre.layout = (graph, options) => {
                 longestPath(g);
                 const tree = feasibleTree(g);
                 const initLowLimValues = (tree, root) => {
-                    root = tree.nodes()[0];
+                    root = tree.nodes().keys().next().value;
                     const dfsAssignLowLim = (tree, visited, nextLim, v, parent) => {
                         const low = nextLim;
                         const label = tree.node(v);
@@ -515,7 +515,7 @@ dagre.layout = (graph, options) => {
                         const parent = childLab.parent;
                         t.edge(child, parent).cutvalue = calcCutValue(t, g, child);
                     };
-                    let vs = postorder(t, t.nodes());
+                    let vs = postorder(t, Array.from(t.nodes().keys()));
                     vs = vs.slice(0, vs.length - 1);
                     for (const v of vs) {
                         assignCutValue(t, g, v);
@@ -523,7 +523,7 @@ dagre.layout = (graph, options) => {
                 };
                 initCutValues(tree, g);
                 const leaveEdge = (tree) => {
-                    return tree.edges().find((e) => tree.edge(e).cutvalue < 0);
+                    return Array.from(tree.edges()).find((e) => tree.edge(e).cutvalue < 0);
                 };
                 const enterEdge = (t, g, edge) => {
                     let v = edge.v;
@@ -550,7 +550,7 @@ dagre.layout = (graph, options) => {
                     const isDescendant = (tree, vLabel, rootLabel) => {
                         return rootLabel.low <= vLabel.lim && vLabel.lim <= rootLabel.lim;
                     };
-                    const candidates = g.edges().filter((edge) => flip === isDescendant(t, t.node(edge.v), tailLabel) && flip !== isDescendant(t, t.node(edge.w), tailLabel));
+                    const candidates = Array.from(g.edges()).filter((edge) => flip === isDescendant(t, t.node(edge.v), tailLabel) && flip !== isDescendant(t, t.node(edge.w), tailLabel));
                     let minKey = Number.POSITIVE_INFINITY;
                     let minValue = undefined;
                     for (const edge of candidates) {
@@ -570,7 +570,7 @@ dagre.layout = (graph, options) => {
                     initLowLimValues(t);
                     initCutValues(t, g);
                     const updateRanks = (t, g) => {
-                        const root = t.nodes().find((v) => !g.node(v).parent);
+                        const root = Array.from(t.nodes().keys()).find((v) => !g.node(v).parent);
                         let vs = preorder(t, root);
                         vs = vs.slice(1);
                         for (const v of vs) {
@@ -627,11 +627,10 @@ dagre.layout = (graph, options) => {
 
         const removeEmptyRanks = (g) => {
             // Ranks may not start at 0, so we need to offset them
-            if (g.nodes().length > 0) {
+            if (g.nodes().size > 0) {
                 let minRank = Number.POSITIVE_INFINITY;
                 let maxRank = Number.NEGATIVE_INFINITY;
-                for (const v of g.nodes()) {
-                    const node = g.node(v);
+                for (const node of g.nodes().values()) {
                     if (node.rank !== undefined) {
                         if (node.rank < minRank) {
                             minRank = node.rank;
@@ -644,7 +643,7 @@ dagre.layout = (graph, options) => {
                 const size = maxRank - minRank;
                 if (size > 0) {
                     const layers = new Array(size);
-                    for (const v of g.nodes()) {
+                    for (const v of g.nodes().keys()) {
                         const node = g.node(v);
                         if (node.rank !== undefined) {
                             const rank = node.rank - minRank;
@@ -759,7 +758,7 @@ dagre.layout = (graph, options) => {
             }
             // Calculate a weight that is sufficient to keep subgraphs vertically compact
             const sumWeights = (g) => {
-                return g.edges().reduce((acc, e) => acc + g.edge(e).weight, 0);
+                return Array.from(g.edges()).reduce((acc, e) => acc + g.edge(e).weight, 0);
             };
             const weight = sumWeights(g) + 1;
             // Create border nodes and link them up
@@ -784,14 +783,13 @@ dagre.layout = (graph, options) => {
         // Adjusts the ranks for all nodes in the graph such that all nodes v have rank(v) >= 0 and at least one node w has rank(w) = 0.
         const normalizeRanks = (g) => {
             let min = Number.POSITIVE_INFINITY;
-            for (const v of g.nodes()) {
-                const rank = g.node(v).rank;
+            for (const node of g.nodes().values()) {
+                const rank = node.rank;
                 if (rank !== undefined && rank < min) {
                     min = rank;
                 }
             }
-            for (const v of g.nodes()) {
-                const node = g.node(v);
+            for (const node of g.nodes().values()) {
                 if (node.rank !== undefined) {
                     node.rank -= min;
                 }
@@ -800,8 +798,7 @@ dagre.layout = (graph, options) => {
 
         const assignRankMinMax = (g) => {
             let maxRank = 0;
-            for (const v of g.nodes()) {
-                const node = g.node(v);
+            for (const node of g.nodes().values()) {
                 if (node.borderTop) {
                     node.minRank = g.node(node.borderTop).rank;
                     node.maxRank = g.node(node.borderBottom).rank;
@@ -891,7 +888,7 @@ dagre.layout = (graph, options) => {
         };
 
         const removeEdgeLabelProxies = (g) => {
-            for (const v of g.nodes()) {
+            for (const v of g.nodes().keys()) {
                 const node = g.node(v);
                 if (node.dummy === 'edge-proxy') {
                     g.edge(node.e).labelRank = node.rank;
@@ -1284,54 +1281,6 @@ dagre.layout = (graph, options) => {
                     addSubgraphConstraints(lg, cg, sorted.vs);
                 }
             };
-            const twoLayerCrossCount = (g, northLayer, southLayer) => {
-                // Sort all of the edges between the north and south layers by their position
-                // in the north layer and then the south. Map these edges to the position of
-                // their head in the south layer.
-                const southPos = {};
-                for (let i = 0; i < southLayer.length; i++) {
-                    southPos[southLayer[i]] = i;
-                }
-                const southEntries = [];
-                for (const v of northLayer) {
-                    const edges = g.outEdges(v);
-                    const entries = [];
-                    for (const e of edges) {
-                        entries.push({
-                            pos: southPos[e.w],
-                            weight: g.edge(e).weight
-                        });
-                    }
-                    entries.sort((a, b) => a.pos - b.pos);
-                    for (const entry of entries) {
-                        southEntries.push(entry);
-                    }
-                }
-                // Build the accumulator tree
-                let firstIndex = 1;
-                while (firstIndex < southLayer.length) {
-                    firstIndex <<= 1;
-                }
-                const treeSize = 2 * firstIndex - 1;
-                firstIndex -= 1;
-                const tree = Array.from(new Array(treeSize), () => 0);
-                // Calculate the weighted crossings
-                let cc = 0;
-                for (const entry of southEntries) {
-                    let index = entry.pos + firstIndex;
-                    tree[index] += entry.weight;
-                    let weightSum = 0;
-                    while (index > 0) {
-                        if (index % 2) {
-                            weightSum += tree[index + 1];
-                        }
-                        index = (index - 1) >> 1;
-                        tree[index] += entry.weight;
-                    }
-                    cc += entry.weight * weightSum;
-                }
-                return cc;
-            };
             /*
             * A function that takes a layering (an array of layers, each with an array of
             * ordererd nodes) and a graph and returns a weighted crossing count.
@@ -1351,7 +1300,52 @@ dagre.layout = (graph, options) => {
             const crossCount = (g, layering) => {
                 let count = 0;
                 for (let i = 1; i < layering.length; i++) {
-                    count += twoLayerCrossCount(g, layering[i - 1], layering[i]);
+                    const northLayer = layering[i - 1];
+                    const southLayer = layering[i];
+                    // Sort all of the edges between the north and south layers by their position
+                    // in the north layer and then the south. Map these edges to the position of
+                    // their head in the south layer.
+                    const southPos = {};
+                    for (let i = 0; i < southLayer.length; i++) {
+                        southPos[southLayer[i]] = i;
+                    }
+                    const southEntries = [];
+                    for (const v of northLayer) {
+                        const edges = g.outEdges(v);
+                        const entries = [];
+                        for (const e of edges) {
+                            entries.push({
+                                pos: southPos[e.w],
+                                weight: g.edge(e).weight
+                            });
+                        }
+                        entries.sort((a, b) => a.pos - b.pos);
+                        for (const entry of entries) {
+                            southEntries.push(entry);
+                        }
+                    }
+                    // Build the accumulator tree
+                    let firstIndex = 1;
+                    while (firstIndex < southLayer.length) {
+                        firstIndex <<= 1;
+                    }
+                    const treeSize = 2 * firstIndex - 1;
+                    firstIndex -= 1;
+                    const tree = Array.from(new Array(treeSize), () => 0);
+                    // Calculate the weighted crossings
+                    for (const entry of southEntries) {
+                        let index = entry.pos + firstIndex;
+                        tree[index] += entry.weight;
+                        let weightSum = 0;
+                        while (index > 0) {
+                            if (index % 2) {
+                                weightSum += tree[index + 1];
+                            }
+                            index = (index - 1) >> 1;
+                            tree[index] += entry.weight;
+                        }
+                        count += entry.weight * weightSum;
+                    }
                 }
                 return count;
             };
@@ -1368,7 +1362,7 @@ dagre.layout = (graph, options) => {
             */
             const initOrder = (g) => {
                 const visited = {};
-                const nodes = g.nodes().filter((v) => !g.children(v).length);
+                const nodes = Array.from(g.nodes().keys()).filter((v) => !g.children(v).length);
                 let maxRank = undefined;
                 for (const v of nodes) {
                     if (!g.children(v).length > 0) {
@@ -1432,18 +1426,22 @@ dagre.layout = (graph, options) => {
                 const graph = new dagre.Graph({ compound: true });
                 graph.setGraph({ root: root });
                 graph.setDefaultNodeLabel((v) => g.node(v));
-                for (const v of g.nodes()) {
+                for (const v of g.nodes().keys()) {
                     const node = g.node(v);
                     if (node.rank === rank || node.minRank <= rank && rank <= node.maxRank) {
                         graph.setNode(v);
                         const parent = g.parent(v);
                         graph.setParent(v, parent || root);
                         // This assumes we have only short edges!
-                        for (const e of g[relationship](v)) {
-                            const u = e.v === v ? e.w : e.v;
-                            const edge = graph.edge(u, v);
-                            const weight = edge !== undefined ? edge.weight : 0;
-                            graph.setEdge(u, v, { weight: g.edge(e).weight + weight });
+                        if (relationship) {
+                            for (const e of g.inEdges(v)) {
+                                graph.setEdge(e.v, v, { weight: g.edge(e).weight });
+                            }
+                        }
+                        else {
+                            for (const e of g.outEdges(v)) {
+                                graph.setEdge(e.w, v, { weight: g.edge(e).weight });
+                            }
                         }
                         if ('minRank' in node) {
                             graph.setNode(v, {
@@ -1455,13 +1453,6 @@ dagre.layout = (graph, options) => {
                 }
                 return graph;
             };
-            const rank = maxRank(g);
-            const downLayerGraphs = new Array(rank !== undefined ? rank : 0);
-            const upLayerGraphs = new Array(rank !== undefined ? rank : 0);
-            for (let i = 0; i < rank; i++) {
-                downLayerGraphs[i] = buildLayerGraph(g, i + 1, 'inEdges');
-                upLayerGraphs[i] = buildLayerGraph(g, rank - i - 1, 'outEdges');
-            }
             let layering = initOrder(g);
             const assignOrder = (g, layering) => {
                 for (const layer of layering) {
@@ -1471,6 +1462,14 @@ dagre.layout = (graph, options) => {
                 }
             };
             assignOrder(g, layering);
+
+            const rank = maxRank(g);
+            const downLayerGraphs = new Array(rank !== undefined ? rank : 0);
+            const upLayerGraphs = new Array(rank !== undefined ? rank : 0);
+            for (let i = 0; i < rank; i++) {
+                downLayerGraphs[i] = buildLayerGraph(g, i + 1, true);
+                upLayerGraphs[i] = buildLayerGraph(g, rank - i - 1, false);
+            }
             let bestCC = Number.POSITIVE_INFINITY;
             let best;
             for (let i = 0, lastBest = 0; lastBest < 4; ++i, ++lastBest) {
@@ -1528,8 +1527,8 @@ dagre.layout = (graph, options) => {
                     attrs.x = attrs.y;
                     attrs.y = x;
                 };
-                for (const v of g.nodes()) {
-                    swapXYOne(g.node(v));
+                for (const node of g.nodes().values()) {
+                    swapXYOne(node);
                 }
                 for (const e of g.edges()) {
                     const edge = g.edge(e);
@@ -1543,9 +1542,8 @@ dagre.layout = (graph, options) => {
             };
             const rankDir = g.graph().rankdir.toLowerCase();
             if (rankDir === 'bt' || rankDir === 'rl') {
-                for (const v of g.nodes()) {
-                    const attr = g.node(v);
-                    attr.y = -attr.y;
+                for (const node of g.nodes().values()) {
+                    node.y = -node.y;
                 }
                 for (const e of g.edges()) {
                     const edge = g.edge(e);
@@ -1563,16 +1561,16 @@ dagre.layout = (graph, options) => {
             }
         };
         const coordinateSystem_swapWidthHeight = (g) => {
-            const swapWidthHeightOne = (attrs) => {
-                const w = attrs.width;
-                attrs.width = attrs.height;
-                attrs.height = w;
-            };
-            for (const v of g.nodes()) {
-                swapWidthHeightOne(g.node(v));
+            for (const node of g.nodes().values()) {
+                const w = node.width;
+                node.width = node.height;
+                node.height = w;
             }
             for (const e of g.edges()) {
-                swapWidthHeightOne(g.edge(e));
+                const edge = g.edge(e);
+                const w = edge.width;
+                edge.width = edge.height;
+                edge.height = w;
             }
         };
 
@@ -1656,7 +1654,7 @@ dagre.layout = (graph, options) => {
                     const blockG = buildBlockGraph(g, layering, root, reverseSep);
                     const borderType = reverseSep ? 'borderLeft' : 'borderRight';
                     const iterate = (setXsFunc, nextNodesFunc) => {
-                        let stack = blockG.nodes();
+                        let stack = Array.from(blockG.nodes().keys());
                         let elem = stack.pop();
                         const visited = {};
                         while (elem) {
@@ -1956,7 +1954,7 @@ dagre.layout = (graph, options) => {
         };
 
         const positionSelfEdges = (g) => {
-            for (const v of g.nodes()) {
+            for (const v of g.nodes().keys()) {
                 const node = g.node(v);
                 if (node.dummy === 'selfedge') {
                     const selfNode = g.node(node.e.v);
@@ -1980,7 +1978,7 @@ dagre.layout = (graph, options) => {
         };
 
         const removeBorderNodes = (g) => {
-            for (const v of g.nodes()) {
+            for (const v of g.nodes().keys()) {
                 if (g.children(v).length) {
                     const node = g.node(v);
                     const t = g.node(node.borderTop);
@@ -1993,7 +1991,7 @@ dagre.layout = (graph, options) => {
                     node.y = t.y + node.height / 2;
                 }
             }
-            for (const v of g.nodes()) {
+            for (const v of g.nodes().keys()) {
                 if (g.node(v).dummy === 'border') {
                     g.removeNode(v);
                 }
@@ -2033,8 +2031,8 @@ dagre.layout = (graph, options) => {
                 minY = Math.min(minY, y - h / 2);
                 maxY = Math.max(maxY, y + h / 2);
             };
-            for (const v of g.nodes()) {
-                getExtremes(g.node(v));
+            for (const node of g.nodes().values()) {
+                getExtremes(node);
             }
             for (const e of g.edges()) {
                 const edge = g.edge(e);
@@ -2044,8 +2042,7 @@ dagre.layout = (graph, options) => {
             }
             minX -= marginX;
             minY -= marginY;
-            for (const v of g.nodes()) {
-                const node = g.node(v);
+            for (const node of g.nodes().values()) {
                 node.x -= minX;
                 node.y -= minY;
             }
@@ -2165,7 +2162,7 @@ dagre.layout = (graph, options) => {
     * attributes can influence layout.
     */
     const updateInputGraph = (inputGraph, layoutGraph) => {
-        for (const v of inputGraph.nodes()) {
+        for (const v of inputGraph.nodes().keys()) {
             const inputLabel = inputGraph.node(v);
             const layoutLabel = layoutGraph.node(v);
             if (inputLabel) {
@@ -2208,7 +2205,7 @@ dagre.Graph = class {
         this._label = undefined;
         this._defaultNodeLabelFn = () => undefined;
         this._defaultEdgeLabelFn = () => undefined;
-        this._nodes = {};
+        this._nodes = new Map();
         if (this._isCompound) {
             this._parent = {};
             this._children = {};
@@ -2218,8 +2215,8 @@ dagre.Graph = class {
         this._predecessors = {};
         this._out = {};
         this._successors = {};
-        this._edgeObjs = {};
-        this._edgeLabels = {};
+        this._edgeObjs = new Map();
+        this._edgeLabels = new Map();
         this._nodeCount = 0;
         this._edgeCount = 0;
     }
@@ -2254,24 +2251,24 @@ dagre.Graph = class {
     }
 
     nodes() {
-        return Object.keys(this._nodes);
+        return this._nodes;
     }
 
     sources() {
-        return this.nodes().filter((v) => {
+        return Array.from(this.nodes().keys()).filter((v) => {
             const value = this._in[v];
             return value && Object.keys(value).length === 0 && value.constructor === Object;
         });
     }
 
     setNode(v, value) {
-        if (v in this._nodes) {
+        if (this._nodes.has(v)) {
             if (arguments.length > 1) {
-                this._nodes[v] = value;
+                this._nodes.set(v, value);
             }
             return this;
         }
-        this._nodes[v] = arguments.length > 1 ? value : this._defaultNodeLabelFn(v);
+        this._nodes.set(v, arguments.length > 1 ? value : this._defaultNodeLabelFn(v));
         if (this._isCompound) {
             this._parent[v] = this.GRAPH_NODE;
             this._children[v] = {};
@@ -2286,16 +2283,16 @@ dagre.Graph = class {
     }
 
     node(v) {
-        return this._nodes[v];
+        return this._nodes.get(v);
     }
 
     hasNode(v) {
-        return v in this._nodes;
+        return this._nodes.has(v);
     }
 
     removeNode(v) {
-        if (v in this._nodes) {
-            delete this._nodes[v];
+        if (this._nodes.has(v)) {
+            delete this._nodes.delete(v);
             if (this._isCompound) {
                 delete this._children[this._parent[v]][v];
                 delete this._parent[v];
@@ -2305,12 +2302,12 @@ dagre.Graph = class {
                 delete this._children[v];
             }
             for (const e of Object.keys(this._in[v])) {
-                this.removeEdge(this._edgeObjs[e]);
+                this.removeEdge(this._edgeObjs.get(e));
             }
             delete this._in[v];
             delete this._predecessors[v];
             for (const e of Object.keys(this._out[v])) {
-                this.removeEdge(this._edgeObjs[e]);
+                this.removeEdge(this._edgeObjs.get(e));
             }
             delete this._out[v];
             delete this._successors[v];
@@ -2363,7 +2360,7 @@ dagre.Graph = class {
             }
         }
         else if (v === this.GRAPH_NODE) {
-            return this.nodes();
+            return this.nodes().keys();
         }
         else if (this.hasNode(v)) {
             return [];
@@ -2392,7 +2389,7 @@ dagre.Graph = class {
     }
 
     edges() {
-        return Object.values(this._edgeObjs);
+        return this._edgeObjs.values();
     }
 
     // setEdge(v, w, [value, [name]])
@@ -2428,9 +2425,9 @@ dagre.Graph = class {
             name = '' + name;
         }
         const e = this.edgeArgsToId(this._isDirected, v, w, name);
-        if (e in this._edgeLabels) {
+        if (this._edgeLabels.has(e)) {
             if (valueSpecified) {
-                this._edgeLabels[e] = value;
+                this._edgeLabels.set(e, value);
             }
             return this;
         }
@@ -2441,7 +2438,7 @@ dagre.Graph = class {
         // First ensure the nodes exist.
         this.setNode(v);
         this.setNode(w);
-        this._edgeLabels[e] = valueSpecified ? value : this._defaultEdgeLabelFn(v, w, name);
+        this._edgeLabels.set(e, valueSpecified ? value : this._defaultEdgeLabelFn(v, w, name));
         v = '' + v;
         w = '' + w;
         if (!this._isDirected && v > w) {
@@ -2451,7 +2448,7 @@ dagre.Graph = class {
         }
         const edgeObj = name ? { v: v, w: w, name: name } : { v: v, w: w };
         Object.freeze(edgeObj);
-        this._edgeObjs[e] = edgeObj;
+        this._edgeObjs.set(e, edgeObj);
         const incrementOrInitEntry = (map, k) => {
             if (map[k]) {
                 map[k]++;
@@ -2470,22 +2467,22 @@ dagre.Graph = class {
 
     edge(v, w, name) {
         const key = (arguments.length === 1 ? this.edgeObjToId(this._isDirected, arguments[0]) : this.edgeArgsToId(this._isDirected, v, w, name));
-        return this._edgeLabels[key];
+        return this._edgeLabels.get(key);
     }
 
     hasEdge(v, w, name) {
         const key = (arguments.length === 1 ? this.edgeObjToId(this._isDirected, arguments[0]) : this.edgeArgsToId(this._isDirected, v, w, name));
-        return key in this._edgeLabels;
+        return this._edgeLabels.has(key);
     }
 
     removeEdge(v, w, name) {
         const key = (arguments.length === 1 ? this.edgeObjToId(this._isDirected, arguments[0]) : this.edgeArgsToId(this._isDirected, v, w, name));
-        const edge = this._edgeObjs[key];
+        const edge = this._edgeObjs.get(key);
         if (edge) {
             v = edge.v;
             w = edge.w;
-            delete this._edgeLabels[key];
-            delete this._edgeObjs[key];
+            this._edgeLabels.delete(key);
+            this._edgeObjs.delete(key);
             const decrementOrRemoveEntry = (map, k) => {
                 if (!--map[k]) {
                     delete map[k];
@@ -2500,32 +2497,18 @@ dagre.Graph = class {
         return this;
     }
 
-    inEdges(v, u) {
-        const inV = this._in[v];
-        if (inV) {
-            const edges = Object.values(inV);
-            if (!u) {
-                return edges;
-            }
-            return edges.filter((edge) => edge.v === u);
-        }
+    inEdges(v) {
+        return Object.values(this._in[v]);
     }
 
-    outEdges(v, w) {
-        const outV = this._out[v];
-        if (outV) {
-            const edges = Object.values(outV);
-            if (!w) {
-                return edges;
-            }
-            return edges.filter((edge) => edge.w === w);
-        }
+    outEdges(v) {
+        return Object.values(this._out[v]);
     }
 
-    nodeEdges(v, w) {
-        const inEdges = this.inEdges(v, w);
+    nodeEdges(v) {
+        const inEdges = this.inEdges(v);
         if (inEdges) {
-            return inEdges.concat(this.outEdges(v, w));
+            return inEdges.concat(this.outEdges(v));
         }
     }
 

+ 4 - 4
source/view-grapher.js

@@ -59,7 +59,7 @@ grapher.Graph = class {
     }
 
     nodes() {
-        return Array.from(this._nodes.keys());
+        return this._nodes;
     }
 
     hasNode(key) {
@@ -96,7 +96,7 @@ grapher.Graph = class {
             }
         }
         else if (key === '\x00') {
-            return this.nodes();
+            return this.nodes().keys();
         }
         else if (this.hasNode(key)) {
             return [];
@@ -142,7 +142,7 @@ grapher.Graph = class {
         edgePathGroupDefs.appendChild(marker("arrowhead-vee"));
         edgePathGroupDefs.appendChild(marker("arrowhead-vee-select"));
 
-        for (const nodeId of this.nodes()) {
+        for (const nodeId of this.nodes().keys()) {
             const node = this.node(nodeId);
             if (this.children(nodeId).length == 0) {
                 // node
@@ -174,7 +174,7 @@ grapher.Graph = class {
 
         dagre.layout(this);
 
-        for (const nodeId of this.nodes()) {
+        for (const nodeId of this.nodes().keys()) {
             const node = this.node(nodeId);
             if (this.children(nodeId).length == 0) {
                 // node