@atlaspack/graph 3.4.1-canary.52 → 3.4.1-canary.521

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