@atlaspack/graph 3.5.10 → 3.5.11-typescript-17c3d1dec.0
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/LICENSE +201 -0
- package/lib/AdjacencyList.d.ts +607 -0
- package/lib/AdjacencyList.js +26 -3
- package/lib/BitSet.d.ts +19 -0
- package/lib/BitSet.js +0 -1
- package/lib/ContentGraph.d.ts +23 -0
- package/lib/ContentGraph.js +1 -5
- package/lib/Graph.d.ts +91 -0
- package/lib/Graph.js +8 -3
- package/lib/index.d.ts +7 -0
- package/lib/shared-buffer.d.ts +2 -0
- package/lib/shared-buffer.js +5 -1
- package/lib/types.d.ts +9 -0
- package/lib/types.js +1 -0
- package/package.json +11 -8
- package/src/{AdjacencyList.js → AdjacencyList.ts} +127 -101
- package/src/{BitSet.js → BitSet.ts} +0 -3
- package/src/{ContentGraph.js → ContentGraph.ts} +21 -20
- package/src/{Graph.js → Graph.ts} +88 -65
- package/src/{index.js → index.ts} +0 -2
- package/src/{shared-buffer.js → shared-buffer.ts} +6 -3
- package/src/{types.js → types.ts} +5 -7
- package/test/{AdjacencyList.test.js → AdjacencyList.test.ts} +21 -29
- package/test/{BitSet.test.js → BitSet.test.ts} +3 -5
- package/test/{ContentGraph.test.js → ContentGraph.test.ts} +2 -4
- package/test/{Graph.test.js → Graph.test.ts} +22 -24
- package/tsconfig.json +4 -0
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
// @flow
|
|
2
1
|
import assert from 'assert';
|
|
3
2
|
import nullthrows from 'nullthrows';
|
|
4
3
|
import {SharedBuffer} from './shared-buffer';
|
|
@@ -6,49 +5,49 @@ import {fromNodeId, toNodeId} from './types';
|
|
|
6
5
|
import {
|
|
7
6
|
ALL_EDGE_TYPES,
|
|
8
7
|
NULL_EDGE_TYPE,
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
NullEdgeType,
|
|
9
|
+
AllEdgeTypes,
|
|
11
10
|
} from './Graph';
|
|
12
11
|
import type {NodeId} from './types';
|
|
13
12
|
|
|
14
13
|
/** The address of the node in the nodes map. */
|
|
15
|
-
|
|
14
|
+
type NodeAddress = number;
|
|
16
15
|
|
|
17
|
-
|
|
16
|
+
type EdgeHash = number;
|
|
18
17
|
|
|
19
18
|
/** The address of the edge in the edges map. */
|
|
20
|
-
|
|
19
|
+
type EdgeAddress = number;
|
|
21
20
|
|
|
22
21
|
// eslint-disable-next-line no-unused-vars
|
|
23
|
-
export type SerializedAdjacencyList<TEdgeType> = {
|
|
24
|
-
nodes: Uint32Array
|
|
25
|
-
edges: Uint32Array
|
|
26
|
-
|
|
22
|
+
export type SerializedAdjacencyList<TEdgeType> = {
|
|
23
|
+
nodes: Uint32Array;
|
|
24
|
+
edges: Uint32Array;
|
|
25
|
+
};
|
|
27
26
|
|
|
28
27
|
// eslint-disable-next-line no-unused-vars
|
|
29
|
-
export type AdjacencyListOptions<TEdgeType> = {
|
|
28
|
+
export type AdjacencyListOptions<TEdgeType> = {
|
|
30
29
|
/** The initial number of edges to accommodate. */
|
|
31
|
-
initialCapacity?: number
|
|
30
|
+
initialCapacity?: number;
|
|
32
31
|
/** The max amount by which to grow the capacity. */
|
|
33
|
-
maxGrowFactor?: number
|
|
32
|
+
maxGrowFactor?: number;
|
|
34
33
|
/** The min amount by which to grow the capacity. */
|
|
35
|
-
minGrowFactor?: number
|
|
34
|
+
minGrowFactor?: number;
|
|
36
35
|
/** The size after which to grow the capacity by the minimum factor. */
|
|
37
|
-
peakCapacity?: number
|
|
36
|
+
peakCapacity?: number;
|
|
38
37
|
/** The percentage of deleted edges above which the capacity should shrink. */
|
|
39
|
-
unloadFactor?: number
|
|
38
|
+
unloadFactor?: number;
|
|
40
39
|
/** The amount by which to shrink the capacity. */
|
|
41
|
-
shrinkFactor?: number
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
type AdjacencyListParams = {
|
|
45
|
-
initialCapacity: number
|
|
46
|
-
unloadFactor: number
|
|
47
|
-
maxGrowFactor: number
|
|
48
|
-
minGrowFactor: number
|
|
49
|
-
peakCapacity: number
|
|
50
|
-
shrinkFactor: number
|
|
51
|
-
|
|
40
|
+
shrinkFactor?: number;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
type AdjacencyListParams = {
|
|
44
|
+
initialCapacity: number;
|
|
45
|
+
unloadFactor: number;
|
|
46
|
+
maxGrowFactor: number;
|
|
47
|
+
minGrowFactor: number;
|
|
48
|
+
peakCapacity: number;
|
|
49
|
+
shrinkFactor: number;
|
|
50
|
+
};
|
|
52
51
|
|
|
53
52
|
const DEFAULT_PARAMS: AdjacencyListParams = {
|
|
54
53
|
initialCapacity: 2,
|
|
@@ -68,18 +67,18 @@ const DEFAULT_PARAMS: AdjacencyListParams = {
|
|
|
68
67
|
* `TooManyDeletes` = `3`: the edge map has too many deleted edges
|
|
69
68
|
* `NodesOverloaded` = `4`: the node map is overloaded
|
|
70
69
|
*/
|
|
71
|
-
const LinkResult: {
|
|
70
|
+
const LinkResult: {
|
|
72
71
|
/** The edge was successfully linked */
|
|
73
|
-
EdgeAdded: 0
|
|
72
|
+
EdgeAdded: 0;
|
|
74
73
|
/** The edge already exists */
|
|
75
|
-
EdgeExists: 1
|
|
74
|
+
EdgeExists: 1;
|
|
76
75
|
/** The edge map is overloaded */
|
|
77
|
-
EdgesOverloaded: 2
|
|
76
|
+
EdgesOverloaded: 2;
|
|
78
77
|
/** The edge map has too many deleted edges */
|
|
79
|
-
TooManyDeletes: 3
|
|
78
|
+
TooManyDeletes: 3;
|
|
80
79
|
/** The node map is overloaded */
|
|
81
|
-
NodesOverloaded: 4
|
|
82
|
-
|
|
80
|
+
NodesOverloaded: 4;
|
|
81
|
+
} = {
|
|
83
82
|
EdgeAdded: 0,
|
|
84
83
|
EdgeExists: 1,
|
|
85
84
|
EdgesOverloaded: 2,
|
|
@@ -121,7 +120,7 @@ const MAX_LINK_TRIES: 3 = 3;
|
|
|
121
120
|
* `getInboundEdgesByType` methods.
|
|
122
121
|
*
|
|
123
122
|
*/
|
|
124
|
-
export default class AdjacencyList<TEdgeType
|
|
123
|
+
export default class AdjacencyList<TEdgeType extends number = NullEdgeType> {
|
|
125
124
|
#nodes: NodeTypeMap<TEdgeType | NullEdgeType>;
|
|
126
125
|
#edges: EdgeTypeMap<TEdgeType | NullEdgeType>;
|
|
127
126
|
|
|
@@ -140,7 +139,9 @@ export default class AdjacencyList<TEdgeType: number = NullEdgeType> {
|
|
|
140
139
|
let nodes;
|
|
141
140
|
let edges;
|
|
142
141
|
|
|
142
|
+
// @ts-expect-error TS2339
|
|
143
143
|
if (opts?.nodes) {
|
|
144
|
+
// @ts-expect-error TS2339
|
|
144
145
|
({nodes, edges} = opts);
|
|
145
146
|
this.#nodes = new NodeTypeMap(nodes);
|
|
146
147
|
this.#edges = new EdgeTypeMap(edges);
|
|
@@ -167,7 +168,7 @@ export default class AdjacencyList<TEdgeType: number = NullEdgeType> {
|
|
|
167
168
|
* Create a new `AdjacencyList` with data serialized
|
|
168
169
|
* from another `AdjacencyList`.
|
|
169
170
|
*/
|
|
170
|
-
static deserialize(
|
|
171
|
+
static deserialize<TEdgeType extends number = NullEdgeType>(
|
|
171
172
|
opts: SerializedAdjacencyList<TEdgeType>,
|
|
172
173
|
): AdjacencyList<TEdgeType> {
|
|
173
174
|
return new AdjacencyList(opts);
|
|
@@ -184,35 +185,35 @@ export default class AdjacencyList<TEdgeType: number = NullEdgeType> {
|
|
|
184
185
|
}
|
|
185
186
|
|
|
186
187
|
/** Statistics about the current state of the `AdjacencyList`. */
|
|
187
|
-
get stats(): {
|
|
188
|
+
get stats(): {
|
|
188
189
|
/** The maximum number of edges the graph can contain. */
|
|
189
|
-
capacity: number
|
|
190
|
+
capacity: number;
|
|
190
191
|
/** The number of nodes in the graph. */
|
|
191
|
-
nodes: number
|
|
192
|
+
nodes: number;
|
|
192
193
|
/** The number of edge types associated with nodes in the graph. */
|
|
193
|
-
nodeEdgeTypes: number
|
|
194
|
+
nodeEdgeTypes: number;
|
|
194
195
|
/** The size of the raw nodes buffer, in mb. */
|
|
195
|
-
nodeBufferSize: string
|
|
196
|
+
nodeBufferSize: string;
|
|
196
197
|
/** The current load on the nodes array. */
|
|
197
|
-
nodeLoad: string
|
|
198
|
+
nodeLoad: string;
|
|
198
199
|
/** The number of edges in the graph. */
|
|
199
|
-
edges: number
|
|
200
|
+
edges: number;
|
|
200
201
|
/** The number of edges deleted from the graph. */
|
|
201
|
-
deleted: number
|
|
202
|
+
deleted: number;
|
|
202
203
|
/** The number of unique edge types in the graph. */
|
|
203
|
-
edgeTypes: number
|
|
204
|
+
edgeTypes: number;
|
|
204
205
|
/** The size of the raw edges buffer, in mb. */
|
|
205
|
-
edgeBufferSize: string
|
|
206
|
+
edgeBufferSize: string;
|
|
206
207
|
/** The current load on the edges array, including deletes. */
|
|
207
|
-
edgeLoadWithDeletes: string
|
|
208
|
+
edgeLoadWithDeletes: string;
|
|
208
209
|
/** The current load on the edges array. */
|
|
209
|
-
edgeLoad: string
|
|
210
|
+
edgeLoad: string;
|
|
210
211
|
/** The total number of edge hash collisions. */
|
|
211
|
-
collisions: number
|
|
212
|
+
collisions: number;
|
|
212
213
|
/** The number of collisions for the most common hash. */
|
|
213
|
-
maxCollisions: number
|
|
214
|
+
maxCollisions: number;
|
|
214
215
|
/** The average number of collisions per hash. */
|
|
215
|
-
avgCollisions: number
|
|
216
|
+
avgCollisions: number;
|
|
216
217
|
/**
|
|
217
218
|
* The actual distribution of hashes vs. the expected (uniform) distribution.
|
|
218
219
|
*
|
|
@@ -221,10 +222,11 @@ export default class AdjacencyList<TEdgeType: number = NullEdgeType> {
|
|
|
221
222
|
* > A ratio within one confidence interval (0.95 - 1.05) is indicative
|
|
222
223
|
* > that the hash function...has an expected uniform distribution.
|
|
223
224
|
*/
|
|
224
|
-
uniformity: number
|
|
225
|
-
|
|
225
|
+
uniformity: number;
|
|
226
|
+
} {
|
|
226
227
|
let edgeTypes = new Set();
|
|
227
228
|
let buckets = new Map();
|
|
229
|
+
// @ts-expect-error TS2488
|
|
228
230
|
for (let {from, to, type} of this.getAllEdges()) {
|
|
229
231
|
let hash = this.#edges.hash(from, to, type);
|
|
230
232
|
let bucket = buckets.get(hash) || new Set();
|
|
@@ -311,6 +313,7 @@ export default class AdjacencyList<TEdgeType: number = NullEdgeType> {
|
|
|
311
313
|
this.#edges.from(edge),
|
|
312
314
|
this.#edges.to(edge),
|
|
313
315
|
this.#edges.typeOf(edge),
|
|
316
|
+
// @ts-expect-error TS2345
|
|
314
317
|
edges,
|
|
315
318
|
nodes,
|
|
316
319
|
this.#params.unloadFactor,
|
|
@@ -324,7 +327,9 @@ export default class AdjacencyList<TEdgeType: number = NullEdgeType> {
|
|
|
324
327
|
);
|
|
325
328
|
|
|
326
329
|
// Finally, copy the new data arrays over to this graph.
|
|
330
|
+
// @ts-expect-error TS2322
|
|
327
331
|
this.#nodes = nodes;
|
|
332
|
+
// @ts-expect-error TS2322
|
|
328
333
|
this.#edges = edges;
|
|
329
334
|
}
|
|
330
335
|
|
|
@@ -418,11 +423,11 @@ export default class AdjacencyList<TEdgeType: number = NullEdgeType> {
|
|
|
418
423
|
/**
|
|
419
424
|
* Iterate over all edges in insertion order.
|
|
420
425
|
*/
|
|
421
|
-
*getAllEdges(): Iterator<{
|
|
422
|
-
type: TEdgeType | NullEdgeType
|
|
423
|
-
from: NodeId
|
|
424
|
-
to: NodeId
|
|
425
|
-
|
|
426
|
+
*getAllEdges(): Iterator<{
|
|
427
|
+
type: TEdgeType | NullEdgeType;
|
|
428
|
+
from: NodeId;
|
|
429
|
+
to: NodeId;
|
|
430
|
+
}> {
|
|
426
431
|
for (let edge of this.#edges) {
|
|
427
432
|
yield {
|
|
428
433
|
from: this.#edges.from(edge),
|
|
@@ -523,10 +528,14 @@ export default class AdjacencyList<TEdgeType: number = NullEdgeType> {
|
|
|
523
528
|
* Get a list of every node (labeled `from`) connecting _to_
|
|
524
529
|
* the given `to` node, along with the edge `type` connecting them.
|
|
525
530
|
*/
|
|
526
|
-
getInboundEdgesByType(
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
531
|
+
getInboundEdgesByType(to: NodeId): {
|
|
532
|
+
type: TEdgeType | NullEdgeType;
|
|
533
|
+
from: NodeId;
|
|
534
|
+
}[] {
|
|
535
|
+
let edges: Array<{
|
|
536
|
+
from: NodeId;
|
|
537
|
+
type: TEdgeType | NullEdgeType;
|
|
538
|
+
}> = [];
|
|
530
539
|
let node = this.#nodes.head(to);
|
|
531
540
|
while (node !== null) {
|
|
532
541
|
let type = this.#nodes.typeOf(node);
|
|
@@ -545,10 +554,14 @@ export default class AdjacencyList<TEdgeType: number = NullEdgeType> {
|
|
|
545
554
|
* Get a list of every node (labeled `to`) connected _from_
|
|
546
555
|
* the given `from` node, along with the edge `type` connecting them.
|
|
547
556
|
*/
|
|
548
|
-
getOutboundEdgesByType(
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
557
|
+
getOutboundEdgesByType(from: NodeId): {
|
|
558
|
+
type: TEdgeType | NullEdgeType;
|
|
559
|
+
to: NodeId;
|
|
560
|
+
}[] {
|
|
561
|
+
let edges: Array<{
|
|
562
|
+
to: NodeId;
|
|
563
|
+
type: TEdgeType | NullEdgeType;
|
|
564
|
+
}> = [];
|
|
552
565
|
let node = this.#nodes.head(from);
|
|
553
566
|
while (node !== null) {
|
|
554
567
|
let type = this.#nodes.typeOf(node);
|
|
@@ -578,12 +591,12 @@ export default class AdjacencyList<TEdgeType: number = NullEdgeType> {
|
|
|
578
591
|
| NullEdgeType
|
|
579
592
|
| Array<TEdgeType | NullEdgeType> = NULL_EDGE_TYPE,
|
|
580
593
|
): NodeId[] {
|
|
581
|
-
let matches = (node) =>
|
|
594
|
+
let matches = (node: number) =>
|
|
582
595
|
type === ALL_EDGE_TYPES ||
|
|
583
596
|
(Array.isArray(type)
|
|
584
597
|
? type.includes(this.#nodes.typeOf(node))
|
|
585
598
|
: type === this.#nodes.typeOf(node));
|
|
586
|
-
let nodes = [];
|
|
599
|
+
let nodes: Array<NodeId> = [];
|
|
587
600
|
let seen = new Set<NodeId>();
|
|
588
601
|
let node = this.#nodes.head(from);
|
|
589
602
|
while (node !== null) {
|
|
@@ -608,7 +621,7 @@ export default class AdjacencyList<TEdgeType: number = NullEdgeType> {
|
|
|
608
621
|
fn: (nodeId: NodeId) => boolean,
|
|
609
622
|
type: AllEdgeTypes | TEdgeType | NullEdgeType = ALL_EDGE_TYPES,
|
|
610
623
|
) {
|
|
611
|
-
const matches = (node) =>
|
|
624
|
+
const matches = (node: number) =>
|
|
612
625
|
type === ALL_EDGE_TYPES || type === this.#nodes.typeOf(node);
|
|
613
626
|
|
|
614
627
|
let node = this.#nodes.head(from);
|
|
@@ -629,10 +642,10 @@ export default class AdjacencyList<TEdgeType: number = NullEdgeType> {
|
|
|
629
642
|
|
|
630
643
|
forEachNodeIdConnectedTo(
|
|
631
644
|
to: NodeId,
|
|
632
|
-
fn: (nodeId: NodeId) => boolean |
|
|
645
|
+
fn: (nodeId: NodeId) => boolean | undefined,
|
|
633
646
|
type: AllEdgeTypes | TEdgeType | NullEdgeType = NULL_EDGE_TYPE,
|
|
634
647
|
) {
|
|
635
|
-
const matches = (node) =>
|
|
648
|
+
const matches = (node: number) =>
|
|
636
649
|
type === ALL_EDGE_TYPES || type === this.#nodes.typeOf(node);
|
|
637
650
|
|
|
638
651
|
let node = this.#nodes.head(to);
|
|
@@ -666,13 +679,13 @@ export default class AdjacencyList<TEdgeType: number = NullEdgeType> {
|
|
|
666
679
|
| NullEdgeType
|
|
667
680
|
| Array<TEdgeType | NullEdgeType> = NULL_EDGE_TYPE,
|
|
668
681
|
): NodeId[] {
|
|
669
|
-
let matches = (node) =>
|
|
682
|
+
let matches = (node: number) =>
|
|
670
683
|
type === ALL_EDGE_TYPES ||
|
|
671
684
|
(Array.isArray(type)
|
|
672
685
|
? type.includes(this.#nodes.typeOf(node))
|
|
673
686
|
: type === this.#nodes.typeOf(node));
|
|
674
687
|
|
|
675
|
-
let nodes = [];
|
|
688
|
+
let nodes: Array<NodeId> = [];
|
|
676
689
|
let seen = new Set<NodeId>();
|
|
677
690
|
let node = this.#nodes.head(to);
|
|
678
691
|
while (node !== null) {
|
|
@@ -739,7 +752,7 @@ export default class AdjacencyList<TEdgeType: number = NullEdgeType> {
|
|
|
739
752
|
* └────┼─────────┴─────────────────┘ │
|
|
740
753
|
* └─────────────────────────────────────────────┘
|
|
741
754
|
*/
|
|
742
|
-
export class SharedTypeMap<TItemType, THash, TAddress
|
|
755
|
+
export class SharedTypeMap<TItemType, THash, TAddress extends number>
|
|
743
756
|
implements Iterable<TAddress>
|
|
744
757
|
{
|
|
745
758
|
/**
|
|
@@ -779,7 +792,8 @@ export class SharedTypeMap<TItemType, THash, TAddress: number>
|
|
|
779
792
|
static #TYPE: 1 = 1;
|
|
780
793
|
|
|
781
794
|
/** The largest possible capacity. */
|
|
782
|
-
|
|
795
|
+
// @ts-expect-error TS1094
|
|
796
|
+
static get MAX_CAPACITY<TItemType, THash, TAddress extends number>(): number {
|
|
783
797
|
return Math.floor(
|
|
784
798
|
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Invalid_array_length#what_went_wrong
|
|
785
799
|
(2 ** 31 - 1 - this.HEADER_SIZE) / this.ITEM_SIZE,
|
|
@@ -787,7 +801,9 @@ export class SharedTypeMap<TItemType, THash, TAddress: number>
|
|
|
787
801
|
}
|
|
788
802
|
|
|
789
803
|
/** Assert that the given `capacity` does not exceed `MAX_CAPACITY`. */
|
|
790
|
-
static assertMaxCapacity
|
|
804
|
+
static assertMaxCapacity<TItemType, THash, TAddress extends number>(
|
|
805
|
+
capacity: number,
|
|
806
|
+
): void {
|
|
791
807
|
assert(capacity <= this.MAX_CAPACITY, `${this.name} capacity overflow!`);
|
|
792
808
|
}
|
|
793
809
|
|
|
@@ -815,6 +831,7 @@ export class SharedTypeMap<TItemType, THash, TAddress: number>
|
|
|
815
831
|
|
|
816
832
|
/** The address of the first item in the map. */
|
|
817
833
|
get addressableLimit(): number {
|
|
834
|
+
// @ts-expect-error TS2339
|
|
818
835
|
return this.constructor.HEADER_SIZE + this.capacity;
|
|
819
836
|
}
|
|
820
837
|
|
|
@@ -835,7 +852,6 @@ export class SharedTypeMap<TItemType, THash, TAddress: number>
|
|
|
835
852
|
if (typeof capacityOrData === 'number') {
|
|
836
853
|
let {BYTES_PER_ELEMENT} = Uint32Array;
|
|
837
854
|
let CAPACITY = SharedTypeMap.#CAPACITY;
|
|
838
|
-
// $FlowFixMe[incompatible-call]
|
|
839
855
|
this.data = new Uint32Array(
|
|
840
856
|
new SharedBuffer(this.getLength(capacityOrData) * BYTES_PER_ELEMENT),
|
|
841
857
|
);
|
|
@@ -854,6 +870,7 @@ export class SharedTypeMap<TItemType, THash, TAddress: number>
|
|
|
854
870
|
* and is expected to be of equal or smaller capacity to this map.
|
|
855
871
|
*/
|
|
856
872
|
set(data: Uint32Array): void {
|
|
873
|
+
// @ts-expect-error TS2339
|
|
857
874
|
let {HEADER_SIZE, ITEM_SIZE} = this.constructor;
|
|
858
875
|
let NEXT = SharedTypeMap.#NEXT;
|
|
859
876
|
let COUNT = SharedTypeMap.#COUNT;
|
|
@@ -902,31 +919,34 @@ export class SharedTypeMap<TItemType, THash, TAddress: number>
|
|
|
902
919
|
* get the length of the map, in bytes.
|
|
903
920
|
*/
|
|
904
921
|
getLength(capacity: number = this.capacity): number {
|
|
922
|
+
// @ts-expect-error TS2339
|
|
905
923
|
let {HEADER_SIZE, ITEM_SIZE} = this.constructor;
|
|
906
924
|
return capacity + HEADER_SIZE + ITEM_SIZE * capacity;
|
|
907
925
|
}
|
|
908
926
|
|
|
909
927
|
/** Get the next available address in the map. */
|
|
910
928
|
getNextAddress(): TAddress {
|
|
929
|
+
// @ts-expect-error TS2339
|
|
911
930
|
let {HEADER_SIZE, ITEM_SIZE} = this.constructor;
|
|
912
|
-
return (HEADER_SIZE + this.capacity + this.count * ITEM_SIZE
|
|
931
|
+
return (HEADER_SIZE + this.capacity + this.count * ITEM_SIZE) as any;
|
|
913
932
|
}
|
|
914
933
|
|
|
915
934
|
/** Get the address of the first item with the given hash. */
|
|
916
935
|
head(hash: THash): TAddress | null {
|
|
936
|
+
// @ts-expect-error TS2339
|
|
917
937
|
let {HEADER_SIZE} = this.constructor;
|
|
918
|
-
return (this.data[HEADER_SIZE + (hash
|
|
938
|
+
return (this.data[HEADER_SIZE + (hash as any)] as any) || null;
|
|
919
939
|
}
|
|
920
940
|
|
|
921
941
|
/** Get the address of the next item with the same hash as the given item. */
|
|
922
942
|
next(item: TAddress): TAddress | null {
|
|
923
943
|
let NEXT = SharedTypeMap.#NEXT;
|
|
924
|
-
return (this.data[(item
|
|
944
|
+
return (this.data[(item as any) + NEXT] as any) || null;
|
|
925
945
|
}
|
|
926
946
|
|
|
927
947
|
/** Get the type of the item at the given `item` address. */
|
|
928
948
|
typeOf(item: TAddress): TItemType {
|
|
929
|
-
return
|
|
949
|
+
return this.data[item + SharedTypeMap.#TYPE] as any;
|
|
930
950
|
}
|
|
931
951
|
|
|
932
952
|
/**
|
|
@@ -937,9 +957,10 @@ export class SharedTypeMap<TItemType, THash, TAddress: number>
|
|
|
937
957
|
let COUNT = SharedTypeMap.#COUNT;
|
|
938
958
|
let NEXT = SharedTypeMap.#NEXT;
|
|
939
959
|
let TYPE = SharedTypeMap.#TYPE;
|
|
960
|
+
// @ts-expect-error TS2339
|
|
940
961
|
let {HEADER_SIZE} = this.constructor;
|
|
941
962
|
|
|
942
|
-
this.data[item + TYPE] =
|
|
963
|
+
this.data[item + TYPE] = type as any;
|
|
943
964
|
|
|
944
965
|
let prev = this.head(hash);
|
|
945
966
|
if (prev !== null) {
|
|
@@ -951,7 +972,7 @@ export class SharedTypeMap<TItemType, THash, TAddress: number>
|
|
|
951
972
|
this.data[prev + NEXT] = item;
|
|
952
973
|
} else {
|
|
953
974
|
// This is the first item in the bucket!
|
|
954
|
-
this.data[HEADER_SIZE + (hash
|
|
975
|
+
this.data[HEADER_SIZE + (hash as any)] = item;
|
|
955
976
|
}
|
|
956
977
|
this.data[COUNT]++;
|
|
957
978
|
}
|
|
@@ -963,6 +984,7 @@ export class SharedTypeMap<TItemType, THash, TAddress: number>
|
|
|
963
984
|
let COUNT = SharedTypeMap.#COUNT;
|
|
964
985
|
let NEXT = SharedTypeMap.#NEXT;
|
|
965
986
|
let TYPE = SharedTypeMap.#TYPE;
|
|
987
|
+
// @ts-expect-error TS2339
|
|
966
988
|
let {HEADER_SIZE} = this.constructor;
|
|
967
989
|
|
|
968
990
|
this.data[item + TYPE] = 0;
|
|
@@ -976,6 +998,7 @@ export class SharedTypeMap<TItemType, THash, TAddress: number>
|
|
|
976
998
|
let candidate = head;
|
|
977
999
|
while (candidate !== null && candidate !== item) {
|
|
978
1000
|
prev = candidate;
|
|
1001
|
+
// @ts-expect-error TS2322
|
|
979
1002
|
candidate = this.next(candidate);
|
|
980
1003
|
}
|
|
981
1004
|
if (prev !== null && next !== null) {
|
|
@@ -983,9 +1006,9 @@ export class SharedTypeMap<TItemType, THash, TAddress: number>
|
|
|
983
1006
|
} else if (prev !== null) {
|
|
984
1007
|
this.data[prev + NEXT] = 0;
|
|
985
1008
|
} else if (next !== null) {
|
|
986
|
-
this.data[HEADER_SIZE + (hash
|
|
1009
|
+
this.data[HEADER_SIZE + (hash as any)] = next;
|
|
987
1010
|
} else {
|
|
988
|
-
this.data[HEADER_SIZE + (hash
|
|
1011
|
+
this.data[HEADER_SIZE + (hash as any)] = 0;
|
|
989
1012
|
}
|
|
990
1013
|
this.data[item + NEXT] = 0;
|
|
991
1014
|
this.data[COUNT]--;
|
|
@@ -994,6 +1017,7 @@ export class SharedTypeMap<TItemType, THash, TAddress: number>
|
|
|
994
1017
|
forEach(cb: (item: TAddress) => void): void {
|
|
995
1018
|
let max = this.count;
|
|
996
1019
|
let len = this.length;
|
|
1020
|
+
// @ts-expect-error TS2339
|
|
997
1021
|
let {ITEM_SIZE} = this.constructor;
|
|
998
1022
|
for (
|
|
999
1023
|
let i = this.addressableLimit, count = 0;
|
|
@@ -1001,8 +1025,8 @@ export class SharedTypeMap<TItemType, THash, TAddress: number>
|
|
|
1001
1025
|
i += ITEM_SIZE
|
|
1002
1026
|
) {
|
|
1003
1027
|
// Skip items that don't have a type.
|
|
1004
|
-
if (this.typeOf(
|
|
1005
|
-
cb(
|
|
1028
|
+
if (this.typeOf(i as any)) {
|
|
1029
|
+
cb(i as any);
|
|
1006
1030
|
count++;
|
|
1007
1031
|
}
|
|
1008
1032
|
}
|
|
@@ -1012,10 +1036,10 @@ export class SharedTypeMap<TItemType, THash, TAddress: number>
|
|
|
1012
1036
|
// See https://github.com/facebook/flow/issues/1163#issuecomment-353523840
|
|
1013
1037
|
/*:: @@iterator(): Iterator<TAddress> { return ({}: any); } */
|
|
1014
1038
|
|
|
1015
|
-
// $FlowFixMe[unsupported-syntax]
|
|
1016
1039
|
*[Symbol.iterator](): Iterator<TAddress> {
|
|
1017
1040
|
let max = this.count;
|
|
1018
1041
|
let len = this.length;
|
|
1042
|
+
// @ts-expect-error TS2339
|
|
1019
1043
|
let {ITEM_SIZE} = this.constructor;
|
|
1020
1044
|
for (
|
|
1021
1045
|
let i = this.addressableLimit, count = 0;
|
|
@@ -1023,17 +1047,18 @@ export class SharedTypeMap<TItemType, THash, TAddress: number>
|
|
|
1023
1047
|
i += ITEM_SIZE
|
|
1024
1048
|
) {
|
|
1025
1049
|
if (this.data.subarray(i, i + ITEM_SIZE).some(Boolean)) {
|
|
1026
|
-
yield
|
|
1050
|
+
yield i as any;
|
|
1027
1051
|
count++;
|
|
1028
1052
|
}
|
|
1029
1053
|
}
|
|
1030
1054
|
}
|
|
1031
1055
|
|
|
1032
|
-
inspect(): {
|
|
1033
|
-
header: Uint32Array
|
|
1034
|
-
table: Uint32Array
|
|
1035
|
-
data: Uint32Array
|
|
1036
|
-
|
|
1056
|
+
inspect(): {
|
|
1057
|
+
header: Uint32Array;
|
|
1058
|
+
table: Uint32Array;
|
|
1059
|
+
data: Uint32Array;
|
|
1060
|
+
} {
|
|
1061
|
+
// @ts-expect-error TS2339
|
|
1037
1062
|
const {HEADER_SIZE} = this.constructor;
|
|
1038
1063
|
let min = this.addressableLimit;
|
|
1039
1064
|
|
|
@@ -1063,7 +1088,7 @@ export class SharedTypeMap<TItemType, THash, TAddress: number>
|
|
|
1063
1088
|
export class NodeTypeMap<TEdgeType> extends SharedTypeMap<
|
|
1064
1089
|
TEdgeType,
|
|
1065
1090
|
NodeId,
|
|
1066
|
-
NodeAddress
|
|
1091
|
+
NodeAddress
|
|
1067
1092
|
> {
|
|
1068
1093
|
/**
|
|
1069
1094
|
* In addition to the header defined by `SharedTypeMap`, the header for
|
|
@@ -1305,7 +1330,7 @@ export class NodeTypeMap<TEdgeType> extends SharedTypeMap<
|
|
|
1305
1330
|
export class EdgeTypeMap<TEdgeType> extends SharedTypeMap<
|
|
1306
1331
|
TEdgeType,
|
|
1307
1332
|
EdgeHash,
|
|
1308
|
-
EdgeAddress
|
|
1333
|
+
EdgeAddress
|
|
1309
1334
|
> {
|
|
1310
1335
|
/**
|
|
1311
1336
|
* In addition to the header defined by `SharedTypeMap`, the header for
|
|
@@ -1376,6 +1401,7 @@ export class EdgeTypeMap<TEdgeType> extends SharedTypeMap<
|
|
|
1376
1401
|
|
|
1377
1402
|
/** Get the next available address in the map. */
|
|
1378
1403
|
getNextAddress(): EdgeAddress {
|
|
1404
|
+
// @ts-expect-error TS2339
|
|
1379
1405
|
let {ITEM_SIZE} = this.constructor;
|
|
1380
1406
|
return this.addressableLimit + (this.count + this.deletes) * ITEM_SIZE;
|
|
1381
1407
|
}
|
|
@@ -1535,9 +1561,9 @@ export class EdgeTypeMap<TEdgeType> extends SharedTypeMap<
|
|
|
1535
1561
|
// the output widely. Then we do a series of prime multiplications and
|
|
1536
1562
|
// additions to combine the hashes into one value.
|
|
1537
1563
|
let hash = 17;
|
|
1538
|
-
hash = hash * 37 + hash32shift(
|
|
1539
|
-
hash = hash * 37 + hash32shift(
|
|
1540
|
-
hash = hash * 37 + hash32shift(
|
|
1564
|
+
hash = hash * 37 + hash32shift(from as any);
|
|
1565
|
+
hash = hash * 37 + hash32shift(to as any);
|
|
1566
|
+
hash = hash * 37 + hash32shift(type as any);
|
|
1541
1567
|
// Finally, we map the hash to a value modulo the edge capacity.
|
|
1542
1568
|
hash %= this.capacity;
|
|
1543
1569
|
return hash;
|
|
@@ -1554,14 +1580,14 @@ export class EdgeTypeMap<TEdgeType> extends SharedTypeMap<
|
|
|
1554
1580
|
* - `3` TooManyDeletes: the edge map has too many deleted edges
|
|
1555
1581
|
* - `4` NodesOverloaded: the node map is overloaded
|
|
1556
1582
|
*/
|
|
1557
|
-
function link<TEdgeType
|
|
1583
|
+
function link<TEdgeType extends number>(
|
|
1558
1584
|
from: NodeId,
|
|
1559
1585
|
to: NodeId,
|
|
1560
1586
|
type: TEdgeType | NullEdgeType,
|
|
1561
1587
|
edges: EdgeTypeMap<TEdgeType | NullEdgeType>,
|
|
1562
1588
|
nodes: NodeTypeMap<TEdgeType | NullEdgeType>,
|
|
1563
1589
|
unloadFactor: number = DEFAULT_PARAMS.unloadFactor,
|
|
1564
|
-
):
|
|
1590
|
+
): (typeof LinkResult)[keyof typeof LinkResult] {
|
|
1565
1591
|
let hash = edges.hash(from, to, type);
|
|
1566
1592
|
let edge = edges.addressOf(hash, from, to, type);
|
|
1567
1593
|
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
// @flow strict-local
|
|
2
|
-
|
|
3
1
|
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/clz32#implementing_count_leading_ones_and_beyond
|
|
4
2
|
function ctz32(n: number): number {
|
|
5
3
|
if (n === 0) {
|
|
@@ -120,7 +118,6 @@ export class BitSet {
|
|
|
120
118
|
let v = bits[k];
|
|
121
119
|
while (v !== 0) {
|
|
122
120
|
let t = (v & -v) >>> 0;
|
|
123
|
-
// $FlowFixMe
|
|
124
121
|
fn((k << 5) + ctz32(v));
|
|
125
122
|
v ^= t;
|
|
126
123
|
}
|
|
@@ -1,27 +1,30 @@
|
|
|
1
|
-
// @flow strict-local
|
|
2
1
|
import type {ContentKey, NodeId} from './types';
|
|
3
2
|
|
|
4
|
-
import Graph, {
|
|
3
|
+
import Graph, {SerializedGraph, GraphOpts} from './Graph';
|
|
5
4
|
import nullthrows from 'nullthrows';
|
|
6
5
|
|
|
7
|
-
export type ContentGraphOpts<TNode, TEdgeType
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
6
|
+
export type ContentGraphOpts<TNode, TEdgeType extends number = 1> = GraphOpts<
|
|
7
|
+
TNode,
|
|
8
|
+
TEdgeType
|
|
9
|
+
> & {
|
|
10
|
+
_contentKeyToNodeId: Map<ContentKey, NodeId>;
|
|
11
|
+
_nodeIdToContentKey: Map<NodeId, ContentKey>;
|
|
12
|
+
};
|
|
13
|
+
export type SerializedContentGraph<
|
|
14
|
+
TNode,
|
|
15
|
+
TEdgeType extends number = 1,
|
|
16
|
+
> = SerializedGraph<TNode, TEdgeType> & {
|
|
17
|
+
_contentKeyToNodeId: Map<ContentKey, NodeId>;
|
|
18
|
+
};
|
|
16
19
|
|
|
17
|
-
export default class ContentGraph<
|
|
20
|
+
export default class ContentGraph<
|
|
18
21
|
TNode,
|
|
19
|
-
TEdgeType,
|
|
20
|
-
> {
|
|
22
|
+
TEdgeType extends number = 1,
|
|
23
|
+
> extends Graph<TNode, TEdgeType> {
|
|
21
24
|
_contentKeyToNodeId: Map<ContentKey, NodeId>;
|
|
22
25
|
_nodeIdToContentKey: Map<NodeId, ContentKey>;
|
|
23
26
|
|
|
24
|
-
constructor(opts
|
|
27
|
+
constructor(opts?: ContentGraphOpts<TNode, TEdgeType> | null) {
|
|
25
28
|
if (opts) {
|
|
26
29
|
let {_contentKeyToNodeId, _nodeIdToContentKey, ...rest} = opts;
|
|
27
30
|
super(rest);
|
|
@@ -34,19 +37,17 @@ export default class ContentGraph<TNode, TEdgeType: number = 1> extends Graph<
|
|
|
34
37
|
}
|
|
35
38
|
}
|
|
36
39
|
|
|
37
|
-
|
|
38
|
-
static deserialize(
|
|
40
|
+
static deserialize<TNode, TEdgeType extends number = 1>(
|
|
39
41
|
opts: ContentGraphOpts<TNode, TEdgeType>,
|
|
40
42
|
): ContentGraph<TNode, TEdgeType> {
|
|
41
43
|
return new ContentGraph(opts);
|
|
42
44
|
}
|
|
43
45
|
|
|
44
|
-
// $FlowFixMe[prop-missing]
|
|
45
46
|
serialize(): SerializedContentGraph<TNode, TEdgeType> {
|
|
46
|
-
// $FlowFixMe[prop-missing]
|
|
47
47
|
return {
|
|
48
48
|
...super.serialize(),
|
|
49
49
|
_contentKeyToNodeId: this._contentKeyToNodeId,
|
|
50
|
+
// @ts-expect-error TS2353
|
|
50
51
|
_nodeIdToContentKey: this._nodeIdToContentKey,
|
|
51
52
|
};
|
|
52
53
|
}
|
|
@@ -68,7 +69,7 @@ export default class ContentGraph<TNode, TEdgeType: number = 1> extends Graph<
|
|
|
68
69
|
: this.addNodeByContentKey(contentKey, node);
|
|
69
70
|
}
|
|
70
71
|
|
|
71
|
-
getNodeByContentKey(contentKey: ContentKey):
|
|
72
|
+
getNodeByContentKey(contentKey: ContentKey): TNode | null | undefined {
|
|
72
73
|
let nodeId = this._contentKeyToNodeId.get(contentKey);
|
|
73
74
|
if (nodeId != null) {
|
|
74
75
|
return super.getNode(nodeId);
|