@endo/compartment-mapper 1.6.1 → 1.6.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +9 -8
- package/src/compartment-map.d.ts +0 -1
- package/src/compartment-map.d.ts.map +1 -1
- package/src/compartment-map.js +0 -49
- package/src/digest.d.ts.map +1 -1
- package/src/digest.js +2 -5
- package/src/generic-graph.d.ts +84 -0
- package/src/generic-graph.d.ts.map +1 -0
- package/src/generic-graph.js +351 -0
- package/src/import-hook.d.ts.map +1 -1
- package/src/import-hook.js +18 -2
- package/src/json.d.ts +1 -1
- package/src/json.d.ts.map +1 -1
- package/src/json.js +10 -3
- package/src/node-modules.d.ts +3 -2
- package/src/node-modules.d.ts.map +1 -1
- package/src/node-modules.js +200 -165
- package/src/node-powers.d.ts +6 -5
- package/src/node-powers.d.ts.map +1 -1
- package/src/node-powers.js +11 -8
- package/src/parse-cjs-shared-export-wrapper.d.ts.map +1 -1
- package/src/parse-cjs-shared-export-wrapper.js +20 -0
- package/src/types/external.d.ts +5 -1
- package/src/types/external.d.ts.map +1 -1
- package/src/types/external.ts +6 -1
- package/src/types/generic-graph.d.ts +17 -0
- package/src/types/generic-graph.d.ts.map +1 -0
- package/src/types/generic-graph.ts +17 -0
- package/src/types/internal.d.ts +1 -0
- package/src/types/internal.d.ts.map +1 -1
- package/src/types/internal.ts +1 -0
- package/src/types/node-modules.d.ts +36 -13
- package/src/types/node-modules.d.ts.map +1 -1
- package/src/types/node-modules.ts +40 -13
- package/src/types/powers.d.ts +38 -11
- package/src/types/powers.d.ts.map +1 -1
- package/src/types/powers.ts +50 -17
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@endo/compartment-mapper",
|
|
3
|
-
"version": "1.6.
|
|
3
|
+
"version": "1.6.3",
|
|
4
4
|
"description": "The compartment mapper assembles Node applications in a sandbox",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"node",
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
"scripts": {
|
|
51
51
|
"build": "exit 0",
|
|
52
52
|
"prepack": "tsc --build tsconfig.build.json",
|
|
53
|
-
"postpack": "git clean -
|
|
53
|
+
"postpack": "git clean -fX \"*.d.ts*\" \"*.d.cts*\" \"*.d.mts*\" \"*.tsbuildinfo\"",
|
|
54
54
|
"cover": "c8 ava",
|
|
55
55
|
"lint": "yarn lint:types && yarn lint:eslint",
|
|
56
56
|
"lint-fix": "eslint --fix .",
|
|
@@ -60,11 +60,12 @@
|
|
|
60
60
|
"test": "ava"
|
|
61
61
|
},
|
|
62
62
|
"dependencies": {
|
|
63
|
-
"@endo/cjs-module-analyzer": "^1.0.
|
|
64
|
-
"@endo/module-source": "^1.3.
|
|
65
|
-
"@endo/
|
|
66
|
-
"@endo/
|
|
67
|
-
"
|
|
63
|
+
"@endo/cjs-module-analyzer": "^1.0.11",
|
|
64
|
+
"@endo/module-source": "^1.3.3",
|
|
65
|
+
"@endo/path-compare": "^1.1.0",
|
|
66
|
+
"@endo/trampoline": "^1.0.5",
|
|
67
|
+
"@endo/zip": "^1.0.11",
|
|
68
|
+
"ses": "^1.14.0"
|
|
68
69
|
},
|
|
69
70
|
"devDependencies": {
|
|
70
71
|
"ava": "^6.1.3",
|
|
@@ -118,5 +119,5 @@
|
|
|
118
119
|
"typeCoverage": {
|
|
119
120
|
"atLeast": 86.14
|
|
120
121
|
},
|
|
121
|
-
"gitHead": "
|
|
122
|
+
"gitHead": "9815aea9541f241389d2135c6097a7442bdffa17"
|
|
122
123
|
}
|
package/src/compartment-map.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
/** @type {(a: string, b: string) => number} */
|
|
2
2
|
export const stringCompare: (a: string, b: string) => number;
|
|
3
|
-
export function pathCompare(a: Array<string> | undefined, b: Array<string> | undefined): number;
|
|
4
3
|
export function assertCompartmentMap(allegedCompartmentMap: unknown, url?: string): asserts allegedCompartmentMap is CompartmentMapDescriptor;
|
|
5
4
|
import type { CompartmentMapDescriptor } from './types.js';
|
|
6
5
|
//# sourceMappingURL=compartment-map.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compartment-map.d.ts","sourceRoot":"","sources":["compartment-map.js"],"names":[],"mappings":"AAYA,+CAA+C;AAE/C,4BAFW,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,KAAK,MAAM,CAE2B;
|
|
1
|
+
{"version":3,"file":"compartment-map.d.ts","sourceRoot":"","sources":["compartment-map.js"],"names":[],"mappings":"AAYA,+CAA+C;AAE/C,4BAFW,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,KAAK,MAAM,CAE2B;AA8Z/D,4DALI,OAAO,QACP,MAAM,GACJ,QAAQ,qBAAqB,IAAI,wBAAwB,CA+BrE;8CApc2C,YAAY"}
|
package/src/compartment-map.js
CHANGED
|
@@ -14,55 +14,6 @@ const q = JSON.stringify;
|
|
|
14
14
|
// eslint-disable-next-line no-nested-ternary
|
|
15
15
|
export const stringCompare = (a, b) => (a === b ? 0 : a < b ? -1 : 1);
|
|
16
16
|
|
|
17
|
-
/**
|
|
18
|
-
* @param {number} length
|
|
19
|
-
* @param {string} term
|
|
20
|
-
*/
|
|
21
|
-
const cumulativeLength = (length, term) => {
|
|
22
|
-
return length + term.length;
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* @param {Array<string> | undefined} a
|
|
27
|
-
* @param {Array<string> | undefined} b
|
|
28
|
-
*/
|
|
29
|
-
export const pathCompare = (a, b) => {
|
|
30
|
-
// Undefined is not preferred
|
|
31
|
-
if (a === undefined && b === undefined) {
|
|
32
|
-
return 0;
|
|
33
|
-
}
|
|
34
|
-
if (a === undefined) {
|
|
35
|
-
return 1;
|
|
36
|
-
}
|
|
37
|
-
if (b === undefined) {
|
|
38
|
-
return -1;
|
|
39
|
-
}
|
|
40
|
-
// Prefer the shortest dependency path.
|
|
41
|
-
if (a.length !== b.length) {
|
|
42
|
-
return a.length - b.length;
|
|
43
|
-
}
|
|
44
|
-
// Otherwise, favor the shortest cumulative length.
|
|
45
|
-
const aSum = a.reduce(cumulativeLength, 0);
|
|
46
|
-
const bSum = b.reduce(cumulativeLength, 0);
|
|
47
|
-
if (aSum !== bSum) {
|
|
48
|
-
return aSum - bSum;
|
|
49
|
-
}
|
|
50
|
-
// Otherwise, compare terms lexically.
|
|
51
|
-
assert(a.length === b.length); // Reminder
|
|
52
|
-
// This loop guarantees that if any pair of terms is different, including the
|
|
53
|
-
// case where one is a prefix of the other, we will return a non-zero value.
|
|
54
|
-
for (let i = 0; i < a.length; i += 1) {
|
|
55
|
-
const comparison = stringCompare(a[i], b[i]);
|
|
56
|
-
if (comparison !== 0) {
|
|
57
|
-
return comparison;
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
// If all pairs of terms are the same respective lengths, we are guaranteed
|
|
61
|
-
// that they are exactly the same or one of them is lexically distinct and would
|
|
62
|
-
// have already been caught.
|
|
63
|
-
return 0;
|
|
64
|
-
};
|
|
65
|
-
|
|
66
17
|
/**
|
|
67
18
|
* @template T
|
|
68
19
|
* @param {Iterable<T>} iterable
|
package/src/digest.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"digest.d.ts","sourceRoot":"","sources":["digest.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"digest.d.ts","sourceRoot":"","sources":["digest.js"],"names":[],"mappings":"AAqLO,qDAJI,wBAAwB,WACxB,OAAO,GACL,YAAY,CAoDxB;8CAxNS,YAAY;6BAAZ,YAAY;kCAAZ,YAAY"}
|
package/src/digest.js
CHANGED
|
@@ -16,11 +16,8 @@
|
|
|
16
16
|
* } from './types.js'
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
|
-
import {
|
|
20
|
-
|
|
21
|
-
pathCompare,
|
|
22
|
-
stringCompare,
|
|
23
|
-
} from './compartment-map.js';
|
|
19
|
+
import { pathCompare } from '@endo/path-compare';
|
|
20
|
+
import { assertCompartmentMap, stringCompare } from './compartment-map.js';
|
|
24
21
|
|
|
25
22
|
const { create, fromEntries, entries, keys } = Object;
|
|
26
23
|
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @template [T=string] The type of nodes in the graph
|
|
3
|
+
*
|
|
4
|
+
* A generic graph implementation with edge weights.
|
|
5
|
+
*
|
|
6
|
+
* Edge weights are assumed to be non-negative numbers (including `Infinity`)
|
|
7
|
+
*/
|
|
8
|
+
export class GenericGraph<T = string> {
|
|
9
|
+
/**
|
|
10
|
+
* Returns a shallow copy of the `Set` of nodes in the graph.
|
|
11
|
+
*/
|
|
12
|
+
get nodes(): Set<T>;
|
|
13
|
+
/**
|
|
14
|
+
* Adds a node to the graph.
|
|
15
|
+
* If node was already added, this function does nothing.
|
|
16
|
+
* If node was not already added, this function sets up an empty adjacency list.
|
|
17
|
+
* @param {T} node Node to add
|
|
18
|
+
* @returns {this} This graph instance
|
|
19
|
+
*/
|
|
20
|
+
addNode(node: T): this;
|
|
21
|
+
/**
|
|
22
|
+
* Removes a node from the graph.
|
|
23
|
+
* Also removes incoming and outgoing edges.
|
|
24
|
+
* @param {T} node
|
|
25
|
+
* @returns {this}
|
|
26
|
+
*/
|
|
27
|
+
removeNode(node: T): this;
|
|
28
|
+
/**
|
|
29
|
+
* Gets the adjacent nodes set for the given node.
|
|
30
|
+
* @param {T} node
|
|
31
|
+
* @returns {Set<T>|undefined}
|
|
32
|
+
*/
|
|
33
|
+
adjacent(node: T): Set<T> | undefined;
|
|
34
|
+
/**
|
|
35
|
+
* Sets the weight of the given edge between `source` and `target`.
|
|
36
|
+
*
|
|
37
|
+
* @param {T} source Source node
|
|
38
|
+
* @param {T} target Target node
|
|
39
|
+
* @param {number} weight New edge weight
|
|
40
|
+
* @returns {this}
|
|
41
|
+
*/
|
|
42
|
+
setEdgeWeight(source: T, target: T, weight: number): this;
|
|
43
|
+
/**
|
|
44
|
+
* Gets the weight of the given edge between `source` and `target`.
|
|
45
|
+
*
|
|
46
|
+
* @param {T} source Source node
|
|
47
|
+
* @param {T} target Target node
|
|
48
|
+
* @returns {number} Edge weight from source to target
|
|
49
|
+
*/
|
|
50
|
+
getEdgeWeight(source: T, target: T): number;
|
|
51
|
+
/**
|
|
52
|
+
* Adds an edge from the `source` node to `target` node.
|
|
53
|
+
*
|
|
54
|
+
* This method will create the `source` and `target` node(s) if they do not
|
|
55
|
+
* already exist.
|
|
56
|
+
*
|
|
57
|
+
* If {@link T `T`} is an object, the comparison is by-reference.
|
|
58
|
+
*
|
|
59
|
+
* @param {T} source Source node
|
|
60
|
+
* @param {T} target Target node
|
|
61
|
+
* @param {number} weight Edge weight from source to target
|
|
62
|
+
* @returns {this} This graph instance
|
|
63
|
+
*/
|
|
64
|
+
addEdge(source: T, target: T, weight: number): this;
|
|
65
|
+
/**
|
|
66
|
+
* Removes the edge from the `source` node to `target` node.
|
|
67
|
+
* Does not remove the nodes themselves.
|
|
68
|
+
* Does nothing if the edge does not exist.
|
|
69
|
+
* @param {T} source
|
|
70
|
+
* @param {T} target
|
|
71
|
+
* @returns {this}
|
|
72
|
+
*/
|
|
73
|
+
removeEdge(source: T, target: T): this;
|
|
74
|
+
/**
|
|
75
|
+
* Returns true if there is an edge from the `source` node to `target` node.
|
|
76
|
+
* @param {T} source
|
|
77
|
+
* @param {T} target
|
|
78
|
+
* @returns {boolean}
|
|
79
|
+
*/
|
|
80
|
+
hasEdge(source: T, target: T): boolean;
|
|
81
|
+
#private;
|
|
82
|
+
}
|
|
83
|
+
export function makeShortestPath<T = string>(graph: GenericGraph<T>): (source: NoInfer<T>, target: NoInfer<T>) => [T, T, ...T[]];
|
|
84
|
+
//# sourceMappingURL=generic-graph.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generic-graph.d.ts","sourceRoot":"","sources":["generic-graph.js"],"names":[],"mappings":"AAoHA;;;;;;GAMG;AACH,0BANc,CAAC;IA+Bb;;OAEG;IACH,oBAEC;IAED;;;;;;OAMG;IACH,cAHW,CAAC,GACC,IAAI,CAUhB;IAED;;;;;OAKG;IACH,iBAHW,CAAC,GACC,IAAI,CAShB;IAED;;;;OAIG;IACH,eAHW,CAAC,GACC,GAAG,CAAC,CAAC,CAAC,GAAC,SAAS,CAI5B;IAED;;;;;;;OAOG;IACH,sBALW,CAAC,UACD,CAAC,UACD,MAAM,GACJ,IAAI,CAWhB;IAED;;;;;;OAMG;IACH,sBAJW,CAAC,UACD,CAAC,GACC,MAAM,CAUlB;IAED;;;;;;;;;;;;OAYG;IACH,gBALW,CAAC,UACD,CAAC,UACD,MAAM,GACJ,IAAI,CAWhB;IAED;;;;;;;OAOG;IACH,mBAJW,CAAC,UACD,CAAC,GACC,IAAI,CAKhB;IAED;;;;;OAKG;IACH,gBAJW,CAAC,UACD,CAAC,GACC,OAAO,CAInB;;CACF;AA6DM,iCAHO,CAAC,kBACJ,YAAY,CAAC,CAAC,CAAC,YAIb,OAAO,CAAC,CAAC,CAAC,UACV,OAAO,CAAC,CAAC,CAAC,KACR,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAO5B"}
|
|
@@ -0,0 +1,351 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provides {@link GenericGraph} and {@link makeShortestPath}.
|
|
3
|
+
*
|
|
4
|
+
* Portions adapted from
|
|
5
|
+
* {@link https://github.com/datavis-tech/graph-data-structure graph-data-structure},
|
|
6
|
+
* which is Copyright (c) 2016 Curran Kelleher and licensed under the MIT
|
|
7
|
+
* License.
|
|
8
|
+
*
|
|
9
|
+
* @module
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* @import {TraversalContext} from './types/generic-graph.js';
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
const { stringify: q } = JSON;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Remove the node with the minimum weight from the priority queue.
|
|
20
|
+
*
|
|
21
|
+
* Performs linear search.
|
|
22
|
+
* @template [T=string]
|
|
23
|
+
* @param {TraversalContext<T>} tracks
|
|
24
|
+
* @returns {T|undefined}
|
|
25
|
+
*/
|
|
26
|
+
const extractMin = ({ distances, queue }) => {
|
|
27
|
+
let min = Infinity;
|
|
28
|
+
|
|
29
|
+
/** @type {T|undefined} */
|
|
30
|
+
let minNode;
|
|
31
|
+
|
|
32
|
+
queue.forEach(node => {
|
|
33
|
+
const nodeWeight = distances.get(node) ?? Infinity;
|
|
34
|
+
|
|
35
|
+
if (nodeWeight < min) {
|
|
36
|
+
min = nodeWeight;
|
|
37
|
+
minNode = node;
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
if (minNode === undefined) {
|
|
42
|
+
queue.clear();
|
|
43
|
+
return undefined;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
queue.delete(minNode);
|
|
47
|
+
return minNode;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Update context with the new distance to the target node if the distance
|
|
52
|
+
* through the source node is shorter than the current distance.
|
|
53
|
+
*
|
|
54
|
+
* @template [T=string]
|
|
55
|
+
* @param {GenericGraph<T>} graph
|
|
56
|
+
* @param {TraversalContext<NoInfer<T>>} context
|
|
57
|
+
* @param {NoInfer<T>} source
|
|
58
|
+
* @param {NoInfer<T>} target
|
|
59
|
+
*/
|
|
60
|
+
const relax = (graph, { distances, predecessors }, source, target) => {
|
|
61
|
+
const number = graph.getEdgeWeight(source, target);
|
|
62
|
+
|
|
63
|
+
const distanceSource = distances.get(source);
|
|
64
|
+
const distanceTarget = distances.get(target);
|
|
65
|
+
|
|
66
|
+
assert(
|
|
67
|
+
distanceSource !== undefined,
|
|
68
|
+
`Missing distance for source ${q(source)}`,
|
|
69
|
+
);
|
|
70
|
+
assert(
|
|
71
|
+
distanceTarget !== undefined,
|
|
72
|
+
`Missing distance for target ${q(target)} target`,
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
if (distanceTarget > distanceSource + number) {
|
|
76
|
+
distances.set(target, distanceSource + number);
|
|
77
|
+
predecessors.set(target, source);
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Assembles the shortest path by traversing the
|
|
83
|
+
* predecessor subgraph from destination to source.
|
|
84
|
+
*
|
|
85
|
+
* @template [T=string]
|
|
86
|
+
* @param {TraversalContext<NoInfer<T>>} context Traversal context object
|
|
87
|
+
* @param {NoInfer<T>} source Source node
|
|
88
|
+
* @param {NoInfer<T>} target Destination node
|
|
89
|
+
* @returns {[T, T, ...T[]]} Nodes from `source` to `target` inclusive
|
|
90
|
+
* @throws If no path is found
|
|
91
|
+
* @throws If the path has less than two nodes
|
|
92
|
+
*/
|
|
93
|
+
const getPath = ({ predecessors }, source, target) => {
|
|
94
|
+
/** @type {T[]} */
|
|
95
|
+
const nodeList = [];
|
|
96
|
+
|
|
97
|
+
let node = target;
|
|
98
|
+
|
|
99
|
+
while (predecessors.has(node)) {
|
|
100
|
+
const currentNode = /** @type {T} */ (predecessors.get(node));
|
|
101
|
+
nodeList.push(node);
|
|
102
|
+
node = currentNode;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
assert.equal(node, source, `No path found from ${q(source)} to ${q(target)}`);
|
|
106
|
+
|
|
107
|
+
nodeList.push(node);
|
|
108
|
+
|
|
109
|
+
assert(
|
|
110
|
+
nodeList.length >= 2,
|
|
111
|
+
`The path from ${source} to ${target} should have a least two nodes`,
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
return /** @type {[T, T, ...T[]]} */ (nodeList.reverse());
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* @template [T=string] The type of nodes in the graph
|
|
119
|
+
*
|
|
120
|
+
* A generic graph implementation with edge weights.
|
|
121
|
+
*
|
|
122
|
+
* Edge weights are assumed to be non-negative numbers (including `Infinity`)
|
|
123
|
+
*/
|
|
124
|
+
export class GenericGraph {
|
|
125
|
+
/**
|
|
126
|
+
* @type {Set<T>}
|
|
127
|
+
*/
|
|
128
|
+
#nodes;
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* @type {Map<T, Set<T>>}
|
|
132
|
+
*/
|
|
133
|
+
#edges;
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* @type {Map<T, Map<T, number>>}
|
|
137
|
+
*/
|
|
138
|
+
#edgeWeights;
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Initializes internal data structures.
|
|
142
|
+
*/
|
|
143
|
+
constructor() {
|
|
144
|
+
this.#edgeWeights = new Map();
|
|
145
|
+
this.#edges = new Map();
|
|
146
|
+
this.#nodes = new Set();
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Returns a shallow copy of the `Set` of nodes in the graph.
|
|
151
|
+
*/
|
|
152
|
+
get nodes() {
|
|
153
|
+
return new Set(this.#nodes);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Adds a node to the graph.
|
|
158
|
+
* If node was already added, this function does nothing.
|
|
159
|
+
* If node was not already added, this function sets up an empty adjacency list.
|
|
160
|
+
* @param {T} node Node to add
|
|
161
|
+
* @returns {this} This graph instance
|
|
162
|
+
*/
|
|
163
|
+
addNode(node) {
|
|
164
|
+
if (!this.#nodes.has(node)) {
|
|
165
|
+
this.#nodes.add(node);
|
|
166
|
+
}
|
|
167
|
+
if (!this.#edges.has(node)) {
|
|
168
|
+
this.#edges.set(node, new Set());
|
|
169
|
+
}
|
|
170
|
+
return this;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Removes a node from the graph.
|
|
175
|
+
* Also removes incoming and outgoing edges.
|
|
176
|
+
* @param {T} node
|
|
177
|
+
* @returns {this}
|
|
178
|
+
*/
|
|
179
|
+
removeNode(node) {
|
|
180
|
+
this.#edges.delete(node);
|
|
181
|
+
this.#nodes.delete(node);
|
|
182
|
+
for (const adjacentNodes of this.#edges.values()) {
|
|
183
|
+
adjacentNodes.delete(node);
|
|
184
|
+
}
|
|
185
|
+
return this;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Gets the adjacent nodes set for the given node.
|
|
190
|
+
* @param {T} node
|
|
191
|
+
* @returns {Set<T>|undefined}
|
|
192
|
+
*/
|
|
193
|
+
adjacent(node) {
|
|
194
|
+
return this.#edges.get(node);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Sets the weight of the given edge between `source` and `target`.
|
|
199
|
+
*
|
|
200
|
+
* @param {T} source Source node
|
|
201
|
+
* @param {T} target Target node
|
|
202
|
+
* @param {number} weight New edge weight
|
|
203
|
+
* @returns {this}
|
|
204
|
+
*/
|
|
205
|
+
setEdgeWeight(source, target, weight) {
|
|
206
|
+
if (!this.#edgeWeights.has(source)) {
|
|
207
|
+
this.#edgeWeights.set(source, new Map());
|
|
208
|
+
}
|
|
209
|
+
const weights = /** @type {Map<T, number>} */ (
|
|
210
|
+
this.#edgeWeights.get(source)
|
|
211
|
+
);
|
|
212
|
+
weights.set(target, weight);
|
|
213
|
+
return this;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Gets the weight of the given edge between `source` and `target`.
|
|
218
|
+
*
|
|
219
|
+
* @param {T} source Source node
|
|
220
|
+
* @param {T} target Target node
|
|
221
|
+
* @returns {number} Edge weight from source to target
|
|
222
|
+
*/
|
|
223
|
+
getEdgeWeight(source, target) {
|
|
224
|
+
const weight = this.#edgeWeights.get(source)?.get(target);
|
|
225
|
+
if (weight === undefined) {
|
|
226
|
+
throw new ReferenceError(
|
|
227
|
+
`Edge weight from ${q(source)} to ${q(target)} is not set`,
|
|
228
|
+
);
|
|
229
|
+
}
|
|
230
|
+
return weight;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Adds an edge from the `source` node to `target` node.
|
|
235
|
+
*
|
|
236
|
+
* This method will create the `source` and `target` node(s) if they do not
|
|
237
|
+
* already exist.
|
|
238
|
+
*
|
|
239
|
+
* If {@link T `T`} is an object, the comparison is by-reference.
|
|
240
|
+
*
|
|
241
|
+
* @param {T} source Source node
|
|
242
|
+
* @param {T} target Target node
|
|
243
|
+
* @param {number} weight Edge weight from source to target
|
|
244
|
+
* @returns {this} This graph instance
|
|
245
|
+
*/
|
|
246
|
+
addEdge(source, target, weight) {
|
|
247
|
+
this.addNode(source);
|
|
248
|
+
this.addNode(target);
|
|
249
|
+
const adjacentNodes = this.adjacent(source);
|
|
250
|
+
assert(adjacentNodes, `Source ${q(source)} should have adjacent nodes`);
|
|
251
|
+
|
|
252
|
+
adjacentNodes.add(target);
|
|
253
|
+
this.setEdgeWeight(source, target, weight);
|
|
254
|
+
return this;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* Removes the edge from the `source` node to `target` node.
|
|
259
|
+
* Does not remove the nodes themselves.
|
|
260
|
+
* Does nothing if the edge does not exist.
|
|
261
|
+
* @param {T} source
|
|
262
|
+
* @param {T} target
|
|
263
|
+
* @returns {this}
|
|
264
|
+
*/
|
|
265
|
+
removeEdge(source, target) {
|
|
266
|
+
this.#edges.get(source)?.delete(target);
|
|
267
|
+
return this;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Returns true if there is an edge from the `source` node to `target` node.
|
|
272
|
+
* @param {T} source
|
|
273
|
+
* @param {T} target
|
|
274
|
+
* @returns {boolean}
|
|
275
|
+
*/
|
|
276
|
+
hasEdge(source, target) {
|
|
277
|
+
return this.#edges.get(source)?.has(target) ?? false;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* Dijkstra's algorithm for shortest paths in a graph.
|
|
283
|
+
* @template [T=string] The type of nodes in the graph
|
|
284
|
+
* @param {GenericGraph<T>} graph
|
|
285
|
+
* @param {T} source
|
|
286
|
+
* @param {T} target
|
|
287
|
+
* @returns {TraversalContext<T>}
|
|
288
|
+
*/
|
|
289
|
+
const dijkstra = (graph, source, target) => {
|
|
290
|
+
const { nodes } = graph;
|
|
291
|
+
/** @type {TraversalContext<T>} */
|
|
292
|
+
const context = {
|
|
293
|
+
distances: new Map(),
|
|
294
|
+
predecessors: new Map(),
|
|
295
|
+
queue: new Set(),
|
|
296
|
+
};
|
|
297
|
+
const { queue, distances } = context;
|
|
298
|
+
|
|
299
|
+
for (const node of nodes) {
|
|
300
|
+
distances.set(node, Infinity);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
assert(
|
|
304
|
+
distances.get(source) === Infinity,
|
|
305
|
+
`Source ${q(source)} is not in the graph`,
|
|
306
|
+
);
|
|
307
|
+
assert(
|
|
308
|
+
distances.get(target) === Infinity,
|
|
309
|
+
`Target ${q(target)} is not in the graph`,
|
|
310
|
+
);
|
|
311
|
+
|
|
312
|
+
distances.set(source, 0);
|
|
313
|
+
|
|
314
|
+
for (const node of nodes) {
|
|
315
|
+
queue.add(node);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
while (queue.size !== 0) {
|
|
319
|
+
const node = extractMin(context);
|
|
320
|
+
if (node === undefined) {
|
|
321
|
+
return context;
|
|
322
|
+
}
|
|
323
|
+
const adjacent = graph.adjacent(node);
|
|
324
|
+
if (adjacent) {
|
|
325
|
+
for (const edge of adjacent) {
|
|
326
|
+
relax(graph, context, node, edge);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
return context;
|
|
331
|
+
};
|
|
332
|
+
|
|
333
|
+
/**
|
|
334
|
+
* Returns a function which uses Dijkstra's shortest path algorithm to compute
|
|
335
|
+
* the shortest path from `source` to `destination` in the given `graph`.
|
|
336
|
+
*
|
|
337
|
+
* @template [T=string]
|
|
338
|
+
* @param {GenericGraph<T>} graph Graph to use
|
|
339
|
+
*/
|
|
340
|
+
export const makeShortestPath = graph => {
|
|
341
|
+
/**
|
|
342
|
+
* @param {NoInfer<T>} source Source node
|
|
343
|
+
* @param {NoInfer<T>} target Target node
|
|
344
|
+
* @returns {[T, T, ...T[]]} Nodes from `source` to `target` inclusive (minimum of two nodes)
|
|
345
|
+
*/
|
|
346
|
+
const shortestPath = (source, target) => {
|
|
347
|
+
const context = dijkstra(graph, source, target);
|
|
348
|
+
return getPath(context, source, target);
|
|
349
|
+
};
|
|
350
|
+
return shortestPath;
|
|
351
|
+
};
|
package/src/import-hook.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"import-hook.d.ts","sourceRoot":"","sources":["import-hook.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"import-hook.d.ts","sourceRoot":"","sources":["import-hook.js"],"names":[],"mappings":"AAipBA;;;;;;;GAOG;AACH,mDALW,aAAa,gBACb,MAAM,2IACN,6BAA6B,GAC3B,kBAAkB,CAmN9B;AAlpBM,oGALJ;IAAqC,OAAO;IACN,oBAAoB;IACnC,oBAAoB,EAAnC,MAAM;CACd,GAAU,oBAAoB,GAAC,SAAS,CA8B1C;AA+PM,gDALI,MAAM,GAAC,UAAU,gBACjB,MAAM,iLACN,0BAA0B,GACxB,eAAe,CA8J3B;mCAxmBS,YAAY;mDAAZ,YAAY;wCAAZ,YAAY;0CAAZ,YAAY;4BAAZ,YAAY;gCAAZ,YAAY;gDAAZ,YAAY;qCAAZ,YAAY"}
|
package/src/import-hook.js
CHANGED
|
@@ -194,7 +194,8 @@ const findRedirect = ({
|
|
|
194
194
|
// go up a directory
|
|
195
195
|
const parentLocation = new URL('../', someLocation).href;
|
|
196
196
|
|
|
197
|
-
// afaict this behavior is consistent across both windows and posix
|
|
197
|
+
// afaict this behavior is consistent across both windows and posix:
|
|
198
|
+
// if this is true, we hit the filesystem root
|
|
198
199
|
if (parentLocation === someLocation) {
|
|
199
200
|
throw new Error(
|
|
200
201
|
`Could not import unknown module: ${q(absoluteModuleSpecifier)}`,
|
|
@@ -338,6 +339,20 @@ function* chooseModuleDescriptor(
|
|
|
338
339
|
// name, they are usable as URL's.
|
|
339
340
|
const moduleLocation = resolveLocation(candidateSpecifier, packageLocation);
|
|
340
341
|
|
|
342
|
+
// check if moduleLocation is within the compartment if it is not, then
|
|
343
|
+
// create a redirect record using absolute path which will be resolved by
|
|
344
|
+
// findRedirect
|
|
345
|
+
const { fileURLToPath } = unpackReadPowers(readPowers);
|
|
346
|
+
if (
|
|
347
|
+
typeof fileURLToPath === 'function' &&
|
|
348
|
+
!isLocationWithinCompartment(moduleLocation, packageLocation)
|
|
349
|
+
) {
|
|
350
|
+
return {
|
|
351
|
+
specifier: fileURLToPath(moduleLocation),
|
|
352
|
+
compartment: compartments[packageLocation],
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
|
|
341
356
|
// "next" values must have type assertions for narrowing because we have
|
|
342
357
|
// multiple yielded types
|
|
343
358
|
const moduleBytes = /** @type {Uint8Array|undefined} */ (
|
|
@@ -809,7 +824,8 @@ export function makeImportNowHookMaker(
|
|
|
809
824
|
}
|
|
810
825
|
} else if (
|
|
811
826
|
moduleSpecifier !== '.' &&
|
|
812
|
-
!moduleSpecifier.startsWith('./')
|
|
827
|
+
!moduleSpecifier.startsWith('./') &&
|
|
828
|
+
!moduleSpecifier.startsWith('../')
|
|
813
829
|
) {
|
|
814
830
|
// could be a builtin, which means we should not bother bouncing on the trampoline to find it.
|
|
815
831
|
return importExitModuleOrFail(moduleSpecifier, compartmentDescriptor);
|
package/src/json.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export function parseLocatedJson(source: string, location: string):
|
|
1
|
+
export function parseLocatedJson<T = any>(source: string, location: string): T;
|
|
2
2
|
//# sourceMappingURL=json.d.ts.map
|
package/src/json.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"json.d.ts","sourceRoot":"","sources":["json.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"json.d.ts","sourceRoot":"","sources":["json.js"],"names":[],"mappings":"AAgBO,iCANO,CAAC,gBAEJ,MAAM,YACN,MAAM,GACJ,CAAC,CAWb"}
|
package/src/json.js
CHANGED
|
@@ -1,11 +1,18 @@
|
|
|
1
|
-
/**
|
|
1
|
+
/**
|
|
2
|
+
* Annotates JSON parse exceptions with the location of the source.
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
2
6
|
|
|
3
7
|
/**
|
|
4
|
-
* Parses JSON and, if necessary, throws exceptions that include the location
|
|
5
|
-
*
|
|
8
|
+
* Parses JSON and, if necessary, throws exceptions that include the location of
|
|
9
|
+
* the offending file.
|
|
6
10
|
*
|
|
11
|
+
* @template [T=any] The desired type of the parsed JSON. `unknown` is
|
|
12
|
+
* recommended; using the default is unsafe.
|
|
7
13
|
* @param {string} source
|
|
8
14
|
* @param {string} location
|
|
15
|
+
* @returns {T}
|
|
9
16
|
*/
|
|
10
17
|
export const parseLocatedJson = (source, location) => {
|
|
11
18
|
try {
|
package/src/node-modules.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
export function basename(location: string): string;
|
|
2
|
-
export function compartmentMapForNodeModules(readPowers: ReadFn | ReadPowers | MaybeReadPowers
|
|
3
|
-
export function mapNodeModules(readPowers: ReadFn | ReadPowers | MaybeReadPowers
|
|
2
|
+
export function compartmentMapForNodeModules(readPowers: ReadFn | ReadPowers<FileUrlString> | MaybeReadPowers<FileUrlString>, packageLocation: FileUrlString, conditionsOption: Set<string>, packageDescriptor: PackageDescriptor, moduleSpecifier: string, options?: CompartmentMapForNodeModulesOptions): Promise<CompartmentMapDescriptor>;
|
|
3
|
+
export function mapNodeModules(readPowers: ReadFn | ReadPowers<FileUrlString> | MaybeReadPowers<FileUrlString>, moduleLocation: string, { tags, conditions, log, ...otherOptions }?: MapNodeModulesOptions): Promise<CompartmentMapDescriptor>;
|
|
4
4
|
import type { ReadFn } from './types.js';
|
|
5
|
+
import type { FileUrlString } from './types.js';
|
|
5
6
|
import type { ReadPowers } from './types.js';
|
|
6
7
|
import type { MaybeReadPowers } from './types.js';
|
|
7
8
|
import type { PackageDescriptor } from './types.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"node-modules.d.ts","sourceRoot":"","sources":["node-modules.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"node-modules.d.ts","sourceRoot":"","sources":["node-modules.js"],"names":[],"mappings":"AAyHO,mCAHI,MAAM,GACJ,MAAM,CAYlB;AAw1BM,yDATI,MAAM,GAAG,WAAW,aAAa,CAAC,GAAG,gBAAgB,aAAa,CAAC,mBACnE,aAAa,oBACb,GAAG,CAAC,MAAM,CAAC,qBACX,iBAAiB,mBACjB,MAAM,YACN,mCAAmC,GACjC,OAAO,CAAC,wBAAwB,CAAC,CAgG7C;AAaM,2CALI,MAAM,GAAG,WAAW,aAAa,CAAC,GAAG,gBAAgB,aAAa,CAAC,kBACnE,MAAM,+CACN,qBAAqB,GACnB,OAAO,CAAC,wBAAwB,CAAC,CA6B7C;4BAnjCS,YAAY;mCAAZ,YAAY;gCAAZ,YAAY;qCAAZ,YAAY;uCAAZ,YAAY;yDAAZ,YAAY;8CAAZ,YAAY;2CAAZ,YAAY"}
|